123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /*
- * Code for dealing with X509.V3 extensions.
- */
- #include "cert.h"
- #include "secitem.h"
- #include "secoid.h"
- #include "secder.h"
- #include "secasn1.h"
- #include "certxutl.h"
- #include "secerr.h"
- SECStatus
- CERT_FindCertExtensionByOID(CERTCertificate *cert, SECItem *oid, SECItem *value)
- {
- return (cert_FindExtensionByOID(cert->extensions, oid, value));
- }
- SECStatus
- CERT_FindCertExtension(const CERTCertificate *cert, int tag, SECItem *value)
- {
- return (cert_FindExtension(cert->extensions, tag, value));
- }
- static void
- SetExts(void *object, CERTCertExtension **exts)
- {
- CERTCertificate *cert = (CERTCertificate *)object;
- cert->extensions = exts;
- DER_SetUInteger(cert->arena, &(cert->version), SEC_CERTIFICATE_VERSION_3);
- }
- void *
- CERT_StartCertExtensions(CERTCertificate *cert)
- {
- return (cert_StartExtensions((void *)cert, cert->arena, SetExts));
- }
- /*
- * get the value of the Netscape Certificate Type Extension
- */
- SECStatus
- CERT_FindNSCertTypeExtension(CERTCertificate *cert, SECItem *retItem)
- {
- return (CERT_FindBitStringExtension(
- cert->extensions, SEC_OID_NS_CERT_EXT_CERT_TYPE, retItem));
- }
- /*
- * get the value of a string type extension
- */
- char *
- CERT_FindNSStringExtension(CERTCertificate *cert, int oidtag)
- {
- SECItem wrapperItem, tmpItem = { siBuffer, 0 };
- SECStatus rv;
- PLArenaPool *arena = NULL;
- char *retstring = NULL;
- wrapperItem.data = NULL;
- tmpItem.data = NULL;
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (!arena) {
- goto loser;
- }
- rv = cert_FindExtension(cert->extensions, oidtag, &wrapperItem);
- if (rv != SECSuccess) {
- goto loser;
- }
- rv = SEC_QuickDERDecodeItem(
- arena, &tmpItem, SEC_ASN1_GET(SEC_IA5StringTemplate), &wrapperItem);
- if (rv != SECSuccess) {
- goto loser;
- }
- retstring = (char *)PORT_Alloc(tmpItem.len + 1);
- if (retstring == NULL) {
- goto loser;
- }
- PORT_Memcpy(retstring, tmpItem.data, tmpItem.len);
- retstring[tmpItem.len] = '\0';
- loser:
- if (arena) {
- PORT_FreeArena(arena, PR_FALSE);
- }
- if (wrapperItem.data) {
- PORT_Free(wrapperItem.data);
- }
- return (retstring);
- }
- /*
- * get the value of the X.509 v3 Key Usage Extension
- */
- SECStatus
- CERT_FindKeyUsageExtension(CERTCertificate *cert, SECItem *retItem)
- {
- return (CERT_FindBitStringExtension(cert->extensions,
- SEC_OID_X509_KEY_USAGE, retItem));
- }
- /*
- * get the value of the X.509 v3 Key Usage Extension
- */
- SECStatus
- CERT_FindSubjectKeyIDExtension(CERTCertificate *cert, SECItem *retItem)
- {
- SECStatus rv;
- SECItem encodedValue = { siBuffer, NULL, 0 };
- SECItem decodedValue = { siBuffer, NULL, 0 };
- rv = cert_FindExtension(cert->extensions, SEC_OID_X509_SUBJECT_KEY_ID,
- &encodedValue);
- if (rv == SECSuccess) {
- PORTCheapArenaPool tmpArena;
- PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
- rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &decodedValue,
- SEC_ASN1_GET(SEC_OctetStringTemplate),
- &encodedValue);
- if (rv == SECSuccess) {
- rv = SECITEM_CopyItem(NULL, retItem, &decodedValue);
- }
- PORT_DestroyCheapArena(&tmpArena);
- }
- SECITEM_FreeItem(&encodedValue, PR_FALSE);
- return rv;
- }
- SECStatus
- CERT_FindBasicConstraintExten(CERTCertificate *cert,
- CERTBasicConstraints *value)
- {
- SECItem encodedExtenValue;
- SECStatus rv;
- encodedExtenValue.data = NULL;
- encodedExtenValue.len = 0;
- rv = cert_FindExtension(cert->extensions, SEC_OID_X509_BASIC_CONSTRAINTS,
- &encodedExtenValue);
- if (rv != SECSuccess) {
- return (rv);
- }
- rv = CERT_DecodeBasicConstraintValue(value, &encodedExtenValue);
- /* free the raw extension data */
- PORT_Free(encodedExtenValue.data);
- encodedExtenValue.data = NULL;
- return (rv);
- }
- CERTAuthKeyID *
- CERT_FindAuthKeyIDExten(PLArenaPool *arena, CERTCertificate *cert)
- {
- SECItem encodedExtenValue;
- SECStatus rv;
- CERTAuthKeyID *ret;
- encodedExtenValue.data = NULL;
- encodedExtenValue.len = 0;
- rv = cert_FindExtension(cert->extensions, SEC_OID_X509_AUTH_KEY_ID,
- &encodedExtenValue);
- if (rv != SECSuccess) {
- return (NULL);
- }
- ret = CERT_DecodeAuthKeyID(arena, &encodedExtenValue);
- PORT_Free(encodedExtenValue.data);
- encodedExtenValue.data = NULL;
- return (ret);
- }
- SECStatus
- CERT_CheckCertUsage(CERTCertificate *cert, unsigned char usage)
- {
- SECItem keyUsage;
- SECStatus rv;
- /* There is no extension, v1 or v2 certificate */
- if (cert->extensions == NULL) {
- return (SECSuccess);
- }
- keyUsage.data = NULL;
- /* This code formerly ignored the Key Usage extension if it was
- ** marked non-critical. That was wrong. Since we do understand it,
- ** we are obligated to honor it, whether or not it is critical.
- */
- rv = CERT_FindKeyUsageExtension(cert, &keyUsage);
- if (rv == SECFailure) {
- rv = (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) ? SECSuccess
- : SECFailure;
- } else if (!keyUsage.data || !(keyUsage.data[0] & usage)) {
- PORT_SetError(SEC_ERROR_CERT_USAGES_INVALID);
- rv = SECFailure;
- }
- PORT_Free(keyUsage.data);
- return (rv);
- }
|