static der::Result MatchEKU(der::Input& value, KeyPurposeId requiredEKU, EndEntityOrCA endEntityOrCA, /*in/out*/ bool& found, /*in/out*/ bool& foundOCSPSigning) { // See Section 5.9 of "A Layman's Guide to a Subset of ASN.1, BER, and DER" // for a description of ASN.1 DER encoding of OIDs. // id-pkix OBJECT IDENTIFIER ::= // { iso(1) identified-organization(3) dod(6) internet(1) // security(5) mechanisms(5) pkix(7) } // id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } // id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } // id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } // id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } // id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } // id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } static const uint8_t server[] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 1 }; static const uint8_t client[] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 2 }; static const uint8_t code [] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 3 }; static const uint8_t email [] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 4 }; static const uint8_t ocsp [] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 9 }; // id-Netscape OBJECT IDENTIFIER ::= { 2 16 840 1 113730 } // id-Netscape-policy OBJECT IDENTIFIER ::= { id-Netscape 4 } // id-Netscape-stepUp OBJECT IDENTIFIER ::= { id-Netscape-policy 1 } static const uint8_t serverStepUp[] = { (40*2)+16, 128+6,72, 1, 128+6,128+120,66, 4, 1 }; bool match = false; if (!found) { switch (requiredEKU) { case KeyPurposeId::id_kp_serverAuth: // 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(bug 982932): Limit this exception to // old certificates. match = value.MatchRest(server) || (endEntityOrCA == EndEntityOrCA::MustBeCA && value.MatchRest(serverStepUp)); break; case KeyPurposeId::id_kp_clientAuth: match = value.MatchRest(client); break; case KeyPurposeId::id_kp_codeSigning: match = value.MatchRest(code); break; case KeyPurposeId::id_kp_emailProtection: match = value.MatchRest(email); break; case KeyPurposeId::id_kp_OCSPSigning: match = value.MatchRest(ocsp); break; case KeyPurposeId::anyExtendedKeyUsage: PR_NOT_REACHED("anyExtendedKeyUsage should start with found==true"); return der::Fail(SEC_ERROR_LIBRARY_FAILURE); default: PR_NOT_REACHED("unrecognized EKU"); return der::Fail(SEC_ERROR_LIBRARY_FAILURE); } } if (match) { found = true; if (requiredEKU == KeyPurposeId::id_kp_OCSPSigning) { foundOCSPSigning = true; } } else if (value.MatchRest(ocsp)) { foundOCSPSigning = true; } value.SkipToEnd(); // ignore unmatched OIDs. return der::Success; }