/* searches both the baggage and the safe areas looking for * object of specified type matching either the nickname or the * thumbprint specified. * * safe and baggage store certs and keys * objType is the OID for the bag type to be searched: * SEC_OID_PKCS12_KEY_BAG_ID, or * SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID * nickname and thumbprint are the search criteria * * if no match found, NULL returned and error set */ void * sec_pkcs12_find_object(SEC_PKCS12SafeContents *safe, SEC_PKCS12Baggage *baggage, SECOidTag objType, SECItem *nickname, SGNDigestInfo *thumbprint) { int i, j; void *retItem; if(((safe == NULL) && (thumbprint == NULL)) || ((nickname == NULL) && (thumbprint == NULL))) { return NULL; } i = 0; if((safe != NULL) && (safe->contents != NULL)) { while(safe->contents[i] != NULL) { SECOidTag bagType = SECOID_FindOIDTag(&safe->contents[i]->safeBagType); retItem = sec_pkcs12_try_find(safe, NULL, objType, bagType, i, nickname, thumbprint); if(retItem != NULL) { return retItem; } i++; } } if((baggage != NULL) && (baggage->bags != NULL)) { i = 0; while(baggage->bags[i] != NULL) { SEC_PKCS12BaggageItem *xbag = baggage->bags[i]; j = 0; if(xbag->unencSecrets != NULL) { while(xbag->unencSecrets[j] != NULL) { SECOidTag bagType; bagType = SECOID_FindOIDTag(&xbag->unencSecrets[j]->safeBagType); retItem = sec_pkcs12_try_find(NULL, xbag, objType, bagType, j, nickname, thumbprint); if(retItem != NULL) { return retItem; } j++; } } i++; } } PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME); return NULL; }
// Find the first policy OID that is known to be an EV policy OID. SECStatus GetFirstEVPolicy(CERTCertificate* cert, /*out*/ mozilla::pkix::CertPolicyId& policy, /*out*/ SECOidTag& policyOidTag) { if (!cert) { PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return SECFailure; } if (cert->extensions) { for (int i=0; cert->extensions[i]; i++) { const SECItem* oid = &cert->extensions[i]->id; SECOidTag oidTag = SECOID_FindOIDTag(oid); if (oidTag != SEC_OID_X509_CERTIFICATE_POLICIES) continue; SECItem* value = &cert->extensions[i]->value; CERTCertificatePolicies* policies; CERTPolicyInfo** policyInfos; policies = CERT_DecodeCertificatePoliciesExtension(value); if (!policies) continue; policyInfos = policies->policyInfos; bool found = false; while (*policyInfos) { const CERTPolicyInfo* policyInfo = *policyInfos++; SECOidTag oid_tag = policyInfo->oid; if (oid_tag != SEC_OID_UNKNOWN && isEVPolicy(oid_tag)) { const SECOidData* oidData = SECOID_FindOIDByTag(oid_tag); PR_ASSERT(oidData); PR_ASSERT(oidData->oid.data); PR_ASSERT(oidData->oid.len > 0); PR_ASSERT(oidData->oid.len <= mozilla::pkix::CertPolicyId::MAX_BYTES); if (oidData && oidData->oid.data && oidData->oid.len > 0 && oidData->oid.len <= mozilla::pkix::CertPolicyId::MAX_BYTES) { policy.numBytes = static_cast<uint16_t>(oidData->oid.len); memcpy(policy.bytes, oidData->oid.data, policy.numBytes); policyOidTag = oid_tag; found = true; } break; } } CERT_DestroyCertificatePoliciesExtension(policies); if (found) { return SECSuccess; } } } PR_SetError(SEC_ERROR_POLICY_VALIDATION_FAILED, 0); return SECFailure; }
static unsigned long nss_SMIME_FindCipherForSMIMECap(NSSSMIMECapability *cap) { int i; SECOidTag capIDTag; /* we need the OIDTag here */ capIDTag = SECOID_FindOIDTag(&(cap->capabilityID)); /* go over all the SMIME ciphers we know and see if we find a match */ for (i = 0; i < smime_cipher_map_count; i++) { if (smime_cipher_map[i].algtag != capIDTag) continue; /* * XXX If SECITEM_CompareItem allowed NULLs as arguments (comparing * 2 NULLs as equal and NULL and non-NULL as not equal), we could * use that here instead of all of the following comparison code. */ if (cap->parameters.Data == NULL && smime_cipher_map[i].parms == NULL) break; /* both empty: bingo */ if (cap->parameters.Data != NULL && smime_cipher_map[i].parms != NULL && cap->parameters.Length == smime_cipher_map[i].parms->Length && PORT_Memcmp (cap->parameters.Data, smime_cipher_map[i].parms->Data, cap->parameters.Length) == 0) { break; /* both not empty, same length & equal content: bingo */ } } if (i == smime_cipher_map_count) return 0; /* no match found */ else return smime_cipher_map[i].cipher; /* match found, point to cipher */ }
const SECHashObject * NSS_CMSUtil_GetHashObjByAlgID(SECAlgorithmID *algid) { SECOidTag oidTag = SECOID_FindOIDTag(&(algid->algorithm)); const SECHashObject *digobj = HASH_GetHashObjectByOidTag(oidTag); return digobj; }
SECOidTag SECOID_GetAlgorithmTag(SECAlgorithmID *id) { if (id == NULL || id->algorithm.data == NULL) return SEC_OID_UNKNOWN; return SECOID_FindOIDTag (&(id->algorithm)); }
// Find the first policy OID that is known to be an EV policy OID. static SECStatus getFirstEVPolicy(CERTCertificate *cert, SECOidTag &outOidTag) { if (!cert) return SECFailure; if (cert->extensions) { for (int i=0; cert->extensions[i] != nsnull; i++) { const SECItem *oid = &cert->extensions[i]->id; SECOidTag oidTag = SECOID_FindOIDTag(oid); if (oidTag != SEC_OID_X509_CERTIFICATE_POLICIES) continue; SECItem *value = &cert->extensions[i]->value; CERTCertificatePolicies *policies; CERTPolicyInfo **policyInfos, *policyInfo; policies = CERT_DecodeCertificatePoliciesExtension(value); if (!policies) continue; policyInfos = policies->policyInfos; PRBool found = PR_FALSE; while (*policyInfos != NULL) { policyInfo = *policyInfos++; SECOidTag oid_tag = SECOID_FindOIDTag(&policyInfo->policyID); if (oid_tag != SEC_OID_UNKNOWN && isEVPolicy(oid_tag)) { // in our list of OIDs accepted for EV outOidTag = oid_tag; found = PR_TRUE; break; } } CERT_DestroyCertificatePoliciesExtension(policies); if (found) return SECSuccess; } } return SECFailure; }
PRBool CERT_GovtApprovedBitSet(CERTCertificate *cert) { SECStatus rv; SECItem extItem; CERTOidSequence *oidSeq = NULL; PRBool ret; SECItem **oids; SECItem *oid; SECOidTag oidTag; extItem.data = NULL; rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem); if ( rv != SECSuccess ) { goto loser; } oidSeq = CERT_DecodeOidSequence(&extItem); if ( oidSeq == NULL ) { goto loser; } oids = oidSeq->oids; while ( oids != NULL && *oids != NULL ) { oid = *oids; oidTag = SECOID_FindOIDTag(oid); if ( oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED ) { goto success; } oids++; } loser: ret = PR_FALSE; goto done; success: ret = PR_TRUE; done: if ( oidSeq != NULL ) { CERT_DestroyOidSequence(oidSeq); } if (extItem.data != NULL) { PORT_Free(extItem.data); } return(ret); }
CK_MECHANISM_TYPE crmf_get_mechanism_from_public_key(SECKEYPublicKey *inPubKey) { CERTSubjectPublicKeyInfo *spki = NULL; SECOidTag tag; spki = SECKEY_CreateSubjectPublicKeyInfo(inPubKey); if (spki == NULL) { return CKM_INVALID_MECHANISM; } tag = SECOID_FindOIDTag(&spki->algorithm.algorithm); SECKEY_DestroySubjectPublicKeyInfo(spki); spki = NULL; return PK11_AlgtagToMechanism(tag); }
int sv_PrintSubjectPublicKeyInfo(FILE *out, PLArenaPool *arena, CERTSubjectPublicKeyInfo *i, char *msg) { SECKEYPublicKey *pk; int rv; char mm[200]; sprintf(mm, "%s.publicKeyAlgorithm=", msg); sv_PrintAlgorithmID(out, &i->algorithm, mm); pk = (SECKEYPublicKey *)PORT_ZAlloc(sizeof(SECKEYPublicKey)); if (!pk) return PORT_GetError(); DER_ConvertBitString(&i->subjectPublicKey); switch (SECOID_FindOIDTag(&i->algorithm.algorithm)) { case SEC_OID_PKCS1_RSA_ENCRYPTION: rv = SEC_ASN1DecodeItem(arena, pk, SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate), &i->subjectPublicKey); if (rv) return rv; sprintf(mm, "%s.rsaPublicKey.", msg); sv_PrintRSAPublicKey(out, pk, mm); break; case SEC_OID_ANSIX9_DSA_SIGNATURE: rv = SEC_ASN1DecodeItem(arena, pk, SEC_ASN1_GET(SECKEY_DSAPublicKeyTemplate), &i->subjectPublicKey); if (rv) return rv; sprintf(mm, "%s.dsaPublicKey.", msg); sv_PrintDSAPublicKey(out, pk, mm); break; default: fprintf(out, "%s=bad SPKI algorithm type\n", msg); return 0; } return 0; }
static nsresult GetCertFingerprintByDottedOidString(CERTCertificate* nsscert, const nsCString &dottedOid, nsCString &fp) { SECItem oid; oid.data = nsnull; oid.len = 0; SECStatus srv = SEC_StringToOID(nsnull, &oid, dottedOid.get(), dottedOid.Length()); if (srv != SECSuccess) return NS_ERROR_FAILURE; SECOidTag oid_tag = SECOID_FindOIDTag(&oid); SECITEM_FreeItem(&oid, PR_FALSE); if (oid_tag == SEC_OID_UNKNOWN) return NS_ERROR_FAILURE; return GetCertFingerprintByOidTag(nsscert, oid_tag, fp); }
SECStatus NSS_CMSSignedData_Decode_BeforeData(NSSCMSSignedData *sigd) { SECStatus rv; if (!sigd) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } rv = NSS_CMSContentInfo_Private_Init(&sigd->contentInfo); if (rv != SECSuccess) { return SECFailure; } /* handle issue with Windows 2003 servers and kerberos */ if (sigd->digestAlgorithms != NULL) { int i; for (i=0; sigd->digestAlgorithms[i] != NULL; i++) { SECAlgorithmID *algid = sigd->digestAlgorithms[i]; SECOidTag senttag= SECOID_FindOIDTag(&algid->algorithm); SECOidTag maptag = NSS_CMSUtil_MapSignAlgs(senttag); if (maptag != senttag) { SECOidData *hashoid = SECOID_FindOIDByTag(maptag); rv = SECITEM_CopyItem(sigd->cmsg->poolp, &algid->algorithm ,&hashoid->oid); if (rv != SECSuccess) { return rv; } } } } /* set up the digests */ if (sigd->digestAlgorithms != NULL && sigd->digests == NULL) { /* if digests are already there, do nothing */ sigd->contentInfo.privateInfo->digcx = NSS_CMSDigestContext_StartMultiple(sigd->digestAlgorithms); if (sigd->contentInfo.privateInfo->digcx == NULL) return SECFailure; } return SECSuccess; }
static void smime_fill_capability(smime_capability *cap) { unsigned long cipher; SECOidTag algtag; int i; algtag = SECOID_FindOIDTag(&(cap->capabilityID)); for (i = 0; i < smime_symmetric_count; i++) { if (smime_cipher_maps[i].algtag != algtag) continue; /* * XXX If SECITEM_CompareItem allowed NULLs as arguments (comparing * 2 NULLs as equal and NULL and non-NULL as not equal), we could * use that here instead of all of the following comparison code. */ if (cap->parameters.data != NULL) { if (smime_cipher_maps[i].parms == NULL) continue; if (cap->parameters.len != smime_cipher_maps[i].parms->len) continue; if (PORT_Memcmp(cap->parameters.data, smime_cipher_maps[i].parms->data, cap->parameters.len) == 0) break; } else if (smime_cipher_maps[i].parms == NULL) { break; } } if (i == smime_symmetric_count) cipher = 0; else cipher = smime_cipher_maps[i].cipher; cap->cipher = cipher; cap->capIDTag = algtag; }
/* * smaller version of EC_FillParams. In this code, we only need * oid and DER data. */ SECStatus LGEC_FillParams(PLArenaPool *arena, const SECItem *encodedParams, ECParams *params) { SECOidTag tag; SECItem oid = { siBuffer, NULL, 0}; #if EC_DEBUG int i; printf("Encoded params in EC_DecodeParams: "); for (i = 0; i < encodedParams->len; i++) { printf("%02x:", encodedParams->data[i]); } printf("\n"); #endif oid.len = encodedParams->len - 2; oid.data = encodedParams->data + 2; if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) || ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; } params->arena = arena; /* For named curves, fill out curveOID */ params->curveOID.len = oid.len; params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len); if (params->curveOID.data == NULL) { return SECFailure; } memcpy(params->curveOID.data, oid.data, oid.len); return SECSuccess; }
int sv_PrintExtensions(FILE *out, CERTCertExtension **extensions, char *msg) { SECOidTag oidTag; if (extensions) { while (*extensions) { SECItem *tmpitem; fprintf(out, "%sname=", msg); tmpitem = &(*extensions)->id; sv_PrintObjectID(out, tmpitem, NULL); tmpitem = &(*extensions)->critical; if (tmpitem->len) fprintf(out, "%scritical=%s\n", msg, (tmpitem->data && tmpitem->data[0]) ? "True" : "False"); oidTag = SECOID_FindOIDTag(&((*extensions)->id)); fprintf(out, "%s", msg); tmpitem = &((*extensions)->value); if (oidTag == SEC_OID_X509_INVALID_DATE) sv_PrintInvalidDateExten(out, tmpitem, "invalidExt"); else sv_PrintAsHex(out, tmpitem, "data="); /*fprintf(out, "\n");*/ extensions++; } } return 0; }
SECStatus EC_FillParams(PLArenaPool *arena, const SECItem *encodedParams, ECParams *params) { SECStatus rv = SECFailure; SECOidTag tag; SECItem oid = { siBuffer, NULL, 0 }; #if EC_DEBUG int i; printf("Encoded params in EC_DecodeParams: "); for (i = 0; i < encodedParams->len; i++) { printf("%02x:", encodedParams->data[i]); } printf("\n"); #endif if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) && (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN) && (encodedParams->len != PKIX_NEWCURVES_OID_TOTAL_LEN)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; }; oid.len = encodedParams->len - 2; oid.data = encodedParams->data + 2; if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) || ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; } params->arena = arena; params->cofactor = 0; params->type = ec_params_named; params->name = ECCurve_noName; /* Fill out curveOID */ params->curveOID.len = oid.len; params->curveOID.data = (unsigned char *)PORT_ArenaAlloc(arena, oid.len); if (params->curveOID.data == NULL) goto cleanup; memcpy(params->curveOID.data, oid.data, oid.len); #if EC_DEBUG printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag)); #endif switch (tag) { case SEC_OID_ANSIX962_EC_PRIME256V1: /* Populate params for prime256v1 aka secp256r1 * (the NIST P-256 curve) */ CHECK_SEC_OK(gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp, params)); break; case SEC_OID_SECG_EC_SECP384R1: /* Populate params for secp384r1 * (the NIST P-384 curve) */ CHECK_SEC_OK(gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp, params)); break; case SEC_OID_SECG_EC_SECP521R1: /* Populate params for secp521r1 * (the NIST P-521 curve) */ CHECK_SEC_OK(gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp, params)); break; case SEC_OID_CURVE25519: /* Populate params for Curve25519 */ CHECK_SEC_OK(gf_populate_params(ECCurve25519, ec_field_plain, params)); break; default: break; }; cleanup: if (!params->cofactor) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); #if EC_DEBUG printf("Unrecognized curve, returning NULL params\n"); #endif } return rv; }
static CERTCertificatePolicies * secu_DecodeCertificatePoliciesExtension(SECItem *extnValue) { PRArenaPool *arena = NULL; SECStatus rv; CERTCertificatePolicies *policies; CERTPolicyInfo **policyInfos, *policyInfo; CERTPolicyQualifier **policyQualifiers, *policyQualifier; SECItem newExtnValue; /* make a new arena */ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( !arena ) { goto loser; } /* allocate the certifiate policies structure */ policies = PORT_ArenaZNew(arena, CERTCertificatePolicies); if ( policies == NULL ) { goto loser; } policies->arena = arena; /* 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, &newExtnValue, extnValue); if ( rv != SECSuccess ) { goto loser; } /* decode the policy info */ rv = SEC_QuickDERDecodeItem(arena, policies, secu_CertificatePoliciesTemplate, &newExtnValue); if ( rv != SECSuccess ) { goto loser; } /* initialize the oid tags */ policyInfos = policies->policyInfos; while (policyInfos != NULL && *policyInfos != NULL ) { policyInfo = *policyInfos; policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID); policyQualifiers = policyInfo->policyQualifiers; while ( policyQualifiers && *policyQualifiers != NULL ) { policyQualifier = *policyQualifiers; policyQualifier->oid = SECOID_FindOIDTag(&policyQualifier->qualifierID); policyQualifiers++; } policyInfos++; } return(policies); loser: if ( arena != NULL ) { PORT_FreeArena(arena, PR_FALSE); } return(NULL); }
// 4.2.1.12. Extended Key Usage (id-ce-extKeyUsage) // 4.2.1.12. Extended Key Usage (id-ce-extKeyUsage) Result CheckExtendedKeyUsage(EndEntityOrCA endEntityOrCA, const SECItem* encodedEKUs, SECOidTag requiredEKU) { // TODO: Either do not allow anyExtendedKeyUsage to be passed as requiredEKU, // or require that callers pass anyExtendedKeyUsage instead of // SEC_OID_UNKNWON and disallow SEC_OID_UNKNWON. // XXX: We're using SEC_ERROR_INADEQUATE_CERT_TYPE here so that callers can // distinguish EKU mismatch from KU mismatch from basic constraints mismatch. // We should probably add a new error code that is more clear for this type // of problem. bool foundOCSPSigning = false; if (encodedEKUs) { ScopedPtr<CERTOidSequence, CERT_DestroyOidSequence> seq(CERT_DecodeOidSequence(encodedEKUs)); if (!seq) { PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0); return RecoverableError; } bool found = false; // XXX: We allow duplicate entries. for (const SECItem* const* oids = seq->oids; oids && *oids; ++oids) { SECOidTag oidTag = SECOID_FindOIDTag(*oids); if (requiredEKU != SEC_OID_UNKNOWN && oidTag == requiredEKU) { found = true; } else { // Treat CA certs with step-up OID as also having SSL server type. // COMODO has issued certificates that require this behavior // that don't expire until June 2020! // TODO 982932: Limit this expection to old certificates if (endEntityOrCA == MustBeCA && requiredEKU == SEC_OID_EXT_KEY_USAGE_SERVER_AUTH && oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) { found = true; } } if (oidTag == SEC_OID_OCSP_RESPONDER) { foundOCSPSigning = true; } } // If the EKU extension was included, then the required EKU must be in the // list. if (!found) { PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0); return RecoverableError; } } // pkixocsp.cpp depends on the following additional checks. if (endEntityOrCA == MustBeEndEntity) { // When validating anything other than an delegated OCSP signing cert, // reject any cert that also claims to be an OCSP responder, because such // a cert does not make sense. For example, if an SSL certificate were to // assert id-kp-OCSPSigning then it could sign OCSP responses for itself, // if not for this check. // That said, we accept CA certificates with id-kp-OCSPSigning because // some CAs in Mozilla's CA program have issued such intermediate // certificates, and because some CAs have reported some Microsoft server // software wrongly requires CA certificates to have id-kp-OCSPSigning. // Allowing this exception does not cause any security issues because we // require delegated OCSP response signing certificates to be end-entity // certificates. if (foundOCSPSigning && requiredEKU != SEC_OID_OCSP_RESPONDER) { PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0); return RecoverableError; } // http://tools.ietf.org/html/rfc6960#section-4.2.2.2: // "OCSP signing delegation SHALL be designated by the inclusion of // id-kp-OCSPSigning in an extended key usage certificate extension // included in the OCSP response signer's certificate." // // id-kp-OCSPSigning is the only EKU that isn't implicitly assumed when the // EKU extension is missing from an end-entity certificate. However, any CA // certificate can issue a delegated OCSP response signing certificate, so // we can't require the EKU be explicitly included for CA certificates. if (!foundOCSPSigning && requiredEKU == SEC_OID_OCSP_RESPONDER) { PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0); return RecoverableError; } } return Success; }
// 4.2.1.12. Extended Key Usage (id-ce-extKeyUsage) // 4.2.1.12. Extended Key Usage (id-ce-extKeyUsage) Result CheckExtendedKeyUsage(EndEntityOrCA endEntityOrCA, const SECItem* encodedEKUs, SECOidTag requiredEKU) { // TODO: Either do not allow anyExtendedKeyUsage to be passed as requiredEKU, // or require that callers pass anyExtendedKeyUsage instead of // SEC_OID_UNKNWON and disallow SEC_OID_UNKNWON. // XXX: We're using SEC_ERROR_INADEQUATE_CERT_TYPE here so that callers can // distinguish EKU mismatch from KU mismatch from basic constraints mismatch. // We should probably add a new error code that is more clear for this type // of problem. bool foundOCSPSigning = false; if (encodedEKUs) { ScopedPtr<CERTOidSequence, CERT_DestroyOidSequence> seq(CERT_DecodeOidSequence(encodedEKUs)); if (!seq) { PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0); return RecoverableError; } bool found = false; // XXX: We allow duplicate entries. for (const SECItem* const* oids = seq->oids; oids && *oids; ++oids) { SECOidTag oidTag = SECOID_FindOIDTag(*oids); if (requiredEKU != SEC_OID_UNKNOWN && oidTag == requiredEKU) { found = true; } if (oidTag == SEC_OID_OCSP_RESPONDER) { foundOCSPSigning = true; } } // If the EKU extension was included, then the required EKU must be in the // list. if (!found) { PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0); return RecoverableError; } } // pkixocsp.cpp depends on the following additional checks. if (foundOCSPSigning) { // When validating anything other than an delegated OCSP signing cert, // reject any cert that also claims to be an OCSP responder, because such // a cert does not make sense. For example, if an SSL certificate were to // assert id-kp-OCSPSigning then it could sign OCSP responses for itself, // if not for this check. if (requiredEKU != SEC_OID_OCSP_RESPONDER) { PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0); return RecoverableError; } } else if (requiredEKU == SEC_OID_OCSP_RESPONDER && endEntityOrCA == MustBeEndEntity) { // http://tools.ietf.org/html/rfc6960#section-4.2.2.2: // "OCSP signing delegation SHALL be designated by the inclusion of // id-kp-OCSPSigning in an extended key usage certificate extension // included in the OCSP response signer's certificate." // // id-kp-OCSPSigning is the only EKU that isn't implicitly assumed when the // EKU extension is missing from an end-entity certificate. However, any CA // certificate can issue a delegated OCSP response signing certificate, so // we can't require the EKU be explicitly included for CA certificates. PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0); return RecoverableError; } return Success; }
/* search a certificate list for a nickname, a thumbprint, or both * within a certificate bag. if the certificate could not be * found or an error occurs, NULL is returned; */ static SEC_PKCS12CertAndCRL * sec_pkcs12_find_cert_in_certbag(SEC_PKCS12CertAndCRLBag *certbag, SECItem *nickname, SGNDigestInfo *thumbprint) { PRBool search_both = PR_FALSE, search_nickname = PR_FALSE; int i, j; if((certbag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) { return NULL; } if(thumbprint && nickname) { search_both = PR_TRUE; } if(nickname) { search_nickname = PR_TRUE; } search_again: i = 0; while(certbag->certAndCRLs[i] != NULL) { SEC_PKCS12CertAndCRL *cert = certbag->certAndCRLs[i]; if(SECOID_FindOIDTag(&cert->BagID) == SEC_OID_PKCS12_X509_CERT_CRL_BAG) { /* check nicknames */ if(search_nickname) { if(SECITEM_CompareItem(nickname, &cert->nickname) == SECEqual) { return cert; } } else { /* check thumbprints */ SECItem **derCertList; /* get pointer to certificate list, does not need to * be freed since it is within the arena which will * be freed later. */ derCertList = SEC_PKCS7GetCertificateList(&cert->value.x509->certOrCRL); j = 0; if(derCertList != NULL) { while(derCertList[j] != NULL) { SECComparison eq; SGNDigestInfo *di; di = sec_pkcs12_compute_thumbprint(derCertList[j]); if(di) { eq = SGN_CompareDigestInfo(thumbprint, di); SGN_DestroyDigestInfo(di); if(eq == SECEqual) { /* copy the derCert for later reference */ cert->value.x509->derLeafCert = derCertList[j]; return cert; } } else { /* an error occurred */ return NULL; } j++; } } } } i++; } if(search_both) { search_both = PR_FALSE; search_nickname = PR_FALSE; goto search_again; } return NULL; }
SECStatus EC_FillParams(PRArenaPool *arena, const SECItem *encodedParams, ECParams *params, int kmflag) { SECStatus rv = SECFailure; ECCurveName tag; SECItem oid = { siBuffer, NULL, 0}; #if EC_DEBUG int i; printf("Encoded params in EC_DecodeParams: "); for (i = 0; i < encodedParams->len; i++) { printf("%02x:", encodedParams->data[i]); } printf("\n"); #endif if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) && (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; }; oid.len = encodedParams->len - 2; oid.data = encodedParams->data + 2; if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) || ((tag = SECOID_FindOIDTag(&oid)) == ECCurve_noName)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; } params->arena = arena; params->cofactor = 0; params->type = ec_params_named; params->name = ECCurve_noName; /* For named curves, fill out curveOID */ params->curveOID.len = oid.len; params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(NULL, oid.len, kmflag); if (params->curveOID.data == NULL) goto cleanup; memcpy(params->curveOID.data, oid.data, oid.len); #if EC_DEBUG #ifndef SECOID_FindOIDTagDescription printf("Curve: %s\n", ecCurve_map[tag]->text); #else printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag)); #endif #endif switch (tag) { /* Binary curves */ case ECCurve_X9_62_CHAR2_PNB163V1: /* Populate params for c2pnb163v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB163V2: /* Populate params for c2pnb163v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB163V3: /* Populate params for c2pnb163v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V3, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB176V1: /* Populate params for c2pnb176v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB176V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB191V1: /* Populate params for c2tnb191v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB191V2: /* Populate params for c2tnb191v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB191V3: /* Populate params for c2tnb191v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V3, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB208W1: /* Populate params for c2pnb208w1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB208W1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB239V1: /* Populate params for c2tnb239v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB239V2: /* Populate params for c2tnb239v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB239V3: /* Populate params for c2tnb239v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V3, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB272W1: /* Populate params for c2pnb272w1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB272W1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB304W1: /* Populate params for c2pnb304w1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB304W1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB359V1: /* Populate params for c2tnb359v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB359V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB368W1: /* Populate params for c2pnb368w1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB368W1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB431R1: /* Populate params for c2tnb431r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB431R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_113R1: /* Populate params for sect113r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_113R2: /* Populate params for sect113r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_131R1: /* Populate params for sect131r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_131R2: /* Populate params for sect131r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_163K1: /* Populate params for sect163k1 * (the NIST K-163 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_163R1: /* Populate params for sect163r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_163R2: /* Populate params for sect163r2 * (the NIST B-163 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_193R1: /* Populate params for sect193r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_193R2: /* Populate params for sect193r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_233K1: /* Populate params for sect233k1 * (the NIST K-233 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_233R1: /* Populate params for sect233r1 * (the NIST B-233 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_239K1: /* Populate params for sect239k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_239K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_283K1: /* Populate params for sect283k1 * (the NIST K-283 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_283R1: /* Populate params for sect283r1 * (the NIST B-283 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_409K1: /* Populate params for sect409k1 * (the NIST K-409 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_409R1: /* Populate params for sect409r1 * (the NIST B-409 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_571K1: /* Populate params for sect571k1 * (the NIST K-571 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_571R1: /* Populate params for sect571r1 * (the NIST B-571 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571R1, ec_field_GF2m, params, kmflag) ); break; /* Prime curves */ case ECCurve_X9_62_PRIME_192V1: /* Populate params for prime192v1 aka secp192r1 * (the NIST P-192 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V1, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_192V2: /* Populate params for prime192v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V2, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_192V3: /* Populate params for prime192v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V3, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_239V1: /* Populate params for prime239v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V1, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_239V2: /* Populate params for prime239v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V2, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_239V3: /* Populate params for prime239v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V3, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_256V1: /* Populate params for prime256v1 aka secp256r1 * (the NIST P-256 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_112R1: /* Populate params for secp112r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_112R2: /* Populate params for secp112r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R2, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_128R1: /* Populate params for secp128r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_128R2: /* Populate params for secp128r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R2, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_160K1: /* Populate params for secp160k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160K1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_160R1: /* Populate params for secp160r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_160R2: /* Populate params for secp160r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R2, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_192K1: /* Populate params for secp192k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_192K1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_224K1: /* Populate params for secp224k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224K1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_224R1: /* Populate params for secp224r1 * (the NIST P-224 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_256K1: /* Populate params for secp256k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_256K1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_384R1: /* Populate params for secp384r1 * (the NIST P-384 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_521R1: /* Populate params for secp521r1 * (the NIST P-521 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp, params, kmflag) ); break; default: break; }; cleanup: if (!params->cofactor) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); #if EC_DEBUG printf("Unrecognized curve, returning NULL params\n"); #endif } return rv; }
bool ECKeyToJwk(const PK11ObjectType aKeyType, void* aKey, const SECItem* aEcParams, const SECItem* aPublicValue, JsonWebKey& aRetVal) { aRetVal.mX.Construct(); aRetVal.mY.Construct(); // Check that the given EC parameters are valid. if (!CheckEncodedECParameters(aEcParams)) { return false; } // Construct the OID tag. SECItem oid = { siBuffer, nullptr, 0 }; oid.len = aEcParams->data[1]; oid.data = aEcParams->data + 2; uint32_t flen; switch (SECOID_FindOIDTag(&oid)) { case SEC_OID_SECG_EC_SECP256R1: flen = 32; // bytes aRetVal.mCrv.Construct(NS_LITERAL_STRING(WEBCRYPTO_NAMED_CURVE_P256)); break; case SEC_OID_SECG_EC_SECP384R1: flen = 48; // bytes aRetVal.mCrv.Construct(NS_LITERAL_STRING(WEBCRYPTO_NAMED_CURVE_P384)); break; case SEC_OID_SECG_EC_SECP521R1: flen = 66; // bytes aRetVal.mCrv.Construct(NS_LITERAL_STRING(WEBCRYPTO_NAMED_CURVE_P521)); break; default: return false; } // No support for compressed points. if (aPublicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) { return false; } // Check length of uncompressed point coordinates. if (aPublicValue->len != (2 * flen + 1)) { return false; } ScopedSECItem ecPointX(::SECITEM_AllocItem(nullptr, nullptr, flen)); ScopedSECItem ecPointY(::SECITEM_AllocItem(nullptr, nullptr, flen)); if (!ecPointX || !ecPointY) { return false; } // Extract point data. memcpy(ecPointX->data, aPublicValue->data + 1, flen); memcpy(ecPointY->data, aPublicValue->data + 1 + flen, flen); CryptoBuffer x, y; if (!x.Assign(ecPointX) || NS_FAILED(x.ToJwkBase64(aRetVal.mX.Value())) || !y.Assign(ecPointY) || NS_FAILED(y.ToJwkBase64(aRetVal.mY.Value()))) { return false; } aRetVal.mKty = NS_LITERAL_STRING(JWK_TYPE_EC); return true; }
static SEC_PKCS7EncoderContext * sec_pkcs7_encoder_start_contexts (SEC_PKCS7ContentInfo *cinfo, PK11SymKey *bulkkey) { SEC_PKCS7EncoderContext *p7ecx; SECOidTag kind; PRBool encrypt; SECItem **digests; SECAlgorithmID *digestalg, **digestalgs; p7ecx = (SEC_PKCS7EncoderContext*)PORT_ZAlloc (sizeof(SEC_PKCS7EncoderContext)); if (p7ecx == NULL) return NULL; digests = NULL; digestalg = NULL; digestalgs = NULL; encrypt = PR_FALSE; kind = SEC_PKCS7ContentType (cinfo); switch (kind) { default: case SEC_OID_PKCS7_DATA: break; case SEC_OID_PKCS7_DIGESTED_DATA: digestalg = &(cinfo->content.digestedData->digestAlg); break; case SEC_OID_PKCS7_SIGNED_DATA: digests = cinfo->content.signedData->digests; digestalgs = cinfo->content.signedData->digestAlgorithms; break; case SEC_OID_PKCS7_ENCRYPTED_DATA: case SEC_OID_PKCS7_ENVELOPED_DATA: encrypt = PR_TRUE; break; case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: digests = cinfo->content.signedAndEnvelopedData->digests; digestalgs = cinfo->content.signedAndEnvelopedData->digestAlgorithms; encrypt = PR_TRUE; break; } if (encrypt) { p7ecx->encryptobj = sec_pkcs7_encoder_start_encrypt (cinfo, bulkkey); if (p7ecx->encryptobj == NULL) { PORT_Free (p7ecx); return NULL; } } if (digestalgs != NULL) { if (digests != NULL) { /* digests already created (probably for detached data) */ digestalg = NULL; } else { /* * XXX Some day we should handle multiple digests; for now, * assume only one will be done. */ PORT_Assert (digestalgs[0] != NULL && digestalgs[1] == NULL); digestalg = digestalgs[0]; } } if (digestalg != NULL) { SECOidTag oidTag = SECOID_FindOIDTag(&(digestalg->algorithm)); p7ecx->digestobj = HASH_GetHashObjectByOidTag(oidTag); if (p7ecx->digestobj != NULL) { p7ecx->digestcx = (* p7ecx->digestobj->create) (); if (p7ecx->digestcx == NULL) p7ecx->digestobj = NULL; else (* p7ecx->digestobj->begin) (p7ecx->digestcx); } if (p7ecx->digestobj == NULL) { if (p7ecx->encryptobj != NULL) sec_PKCS7DestroyEncryptObject (p7ecx->encryptobj); PORT_Free (p7ecx); return NULL; } } p7ecx->cinfo = cinfo; return p7ecx; }