/* 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/. */ /* * X.509 v3 Subject Key Usage Extension * */ #include "prtypes.h" #include "seccomon.h" #include "secdert.h" #include "secoidt.h" #include "secasn1t.h" #include "secasn1.h" #include "secport.h" #include "certt.h" #include "genname.h" #include "secerr.h" SEC_ASN1_MKSUB(SEC_IntegerTemplate) SEC_ASN1_MKSUB(SEC_OctetStringTemplate) const SEC_ASN1Template CERTAuthKeyIDTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTAuthKeyID) }, { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, offsetof(CERTAuthKeyID, keyID), SEC_ASN1_SUB(SEC_OctetStringTemplate) }, { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, offsetof(CERTAuthKeyID, DERAuthCertIssuer), CERT_GeneralNamesTemplate }, { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2, offsetof(CERTAuthKeyID, authCertSerialNumber), SEC_ASN1_SUB(SEC_IntegerTemplate) }, { 0 } }; SECStatus CERT_EncodeAuthKeyID(PLArenaPool *arena, CERTAuthKeyID *value, SECItem *encodedValue) { SECStatus rv = SECFailure; PORT_Assert(value); PORT_Assert(arena); PORT_Assert(value->DERAuthCertIssuer == NULL); PORT_Assert(encodedValue); do { /* If both of the authCertIssuer and the serial number exist, encode the name first. Otherwise, it is an error if one exist and the other is not. */ if (value->authCertIssuer) { if (!value->authCertSerialNumber.data) { PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID); break; } value->DERAuthCertIssuer = cert_EncodeGeneralNames(arena, value->authCertIssuer); if (!value->DERAuthCertIssuer) { PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID); break; } } else if (value->authCertSerialNumber.data) { PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID); break; } if (SEC_ASN1EncodeItem(arena, encodedValue, value, CERTAuthKeyIDTemplate) == NULL) break; rv = SECSuccess; } while (0); return (rv); } CERTAuthKeyID * CERT_DecodeAuthKeyID(PLArenaPool *arena, const SECItem *encodedValue) { CERTAuthKeyID *value = NULL; SECStatus rv = SECFailure; void *mark; SECItem newEncodedValue; PORT_Assert(arena); do { mark = PORT_ArenaMark(arena); value = (CERTAuthKeyID *)PORT_ArenaZAlloc(arena, sizeof(*value)); if (value == NULL) break; value->DERAuthCertIssuer = NULL; /* copy the DER into the arena, since Quick DER returns data that points into the DER input, which may get freed by the caller */ rv = SECITEM_CopyItem(arena, &newEncodedValue, encodedValue); if (rv != SECSuccess) { break; } rv = SEC_QuickDERDecodeItem(arena, value, CERTAuthKeyIDTemplate, &newEncodedValue); if (rv != SECSuccess) break; value->authCertIssuer = cert_DecodeGeneralNames(arena, value->DERAuthCertIssuer); if (value->authCertIssuer == NULL) break; /* what if the general name contains other format but not URI ? hl */ if ((value->authCertSerialNumber.data && !value->authCertIssuer) || (!value->authCertSerialNumber.data && value->authCertIssuer)) { PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID); break; } } while (0); if (rv != SECSuccess) { PORT_ArenaRelease(arena, mark); return ((CERTAuthKeyID *)NULL); } PORT_ArenaUnmark(arena, mark); return (value); }