SECStatus CERT_DecodePolicyConstraintsExtension (CERTCertificatePolicyConstraints *decodedValue, const SECItem *encodedValue) { CERTCertificatePolicyConstraints decodeContext; PLArenaPool *arena = NULL; SECStatus rv = SECSuccess; /* initialize so we can tell when an optional component is omitted */ PORT_Memset(&decodeContext, 0, sizeof(decodeContext)); /* make a new arena */ arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); if (!arena) { return SECFailure; } do { /* decode the policy constraints */ rv = SEC_QuickDERDecodeItem(arena, &decodeContext, CERT_PolicyConstraintsTemplate, encodedValue); if ( rv != SECSuccess ) { break; } if (decodeContext.explicitPolicySkipCerts.len == 0) { *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data = -1; } else { *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data = DER_GetInteger(&decodeContext.explicitPolicySkipCerts); } if (decodeContext.inhibitMappingSkipCerts.len == 0) { *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = -1; } else { *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = DER_GetInteger(&decodeContext.inhibitMappingSkipCerts); } if ((*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data == PR_INT32_MIN) || (*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data == PR_INT32_MAX) || (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data == PR_INT32_MIN) || (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data == PR_INT32_MAX)) { rv = SECFailure; } } while (0); PORT_FreeArena(arena, PR_FALSE); return(rv); }
SECStatus CERT_DecodeInhibitAnyExtension (CERTCertificateInhibitAny *decodedValue, SECItem *encodedValue) { CERTCertificateInhibitAny decodeContext; PLArenaPool *arena = NULL; SECStatus rv = SECSuccess; /* make a new arena */ arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); if ( !arena ) { return SECFailure; } do { /* decode the policy mappings */ decodeContext.inhibitAnySkipCerts.type = siUnsignedInteger; rv = SEC_QuickDERDecodeItem(arena, &decodeContext, CERT_InhibitAnyTemplate, encodedValue); if ( rv != SECSuccess ) { break; } *(PRInt32 *)decodedValue->inhibitAnySkipCerts.data = DER_GetInteger(&decodeContext.inhibitAnySkipCerts); } while (0); PORT_FreeArena(arena, PR_FALSE); return(rv); }
// BasicConstraints ::= SEQUENCE { // cA BOOLEAN DEFAULT FALSE, // pathLenConstraint INTEGER (0..MAX) OPTIONAL } der::Result DecodeBasicConstraints(const SECItem* encodedBasicConstraints, CERTBasicConstraints& basicConstraints) { PR_ASSERT(encodedBasicConstraints); if (!encodedBasicConstraints) { return der::Fail(SEC_ERROR_INVALID_ARGS); } basicConstraints.isCA = false; basicConstraints.pathLenConstraint = 0; der::Input input; if (input.Init(encodedBasicConstraints->data, encodedBasicConstraints->len) != der::Success) { return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID); } if (der::ExpectTagAndIgnoreLength(input, der::SEQUENCE) != der::Success) { return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID); } bool isCA = false; // TODO(bug 989518): cA is by default false. According to DER, default // values must not be explicitly encoded in a SEQUENCE. So, if this // value is present and false, it is an encoding error. However, Go Daddy // has issued many certificates with this improper encoding, so we can't // enforce this yet (hence passing true for allowInvalidExplicitEncoding // to der::OptionalBoolean). if (der::OptionalBoolean(input, true, isCA) != der::Success) { return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID); } basicConstraints.isCA = isCA; if (input.Peek(der::INTEGER)) { SECItem pathLenConstraintEncoded; if (der::Integer(input, pathLenConstraintEncoded) != der::Success) { return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID); } long pathLenConstraint = DER_GetInteger(&pathLenConstraintEncoded); if (pathLenConstraint >= std::numeric_limits<int>::max() || pathLenConstraint < 0) { return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID); } basicConstraints.pathLenConstraint = static_cast<int>(pathLenConstraint); // TODO(bug 985025): If isCA is false, pathLenConstraint MUST NOT // be included (as per RFC 5280 section 4.2.1.9), but for compatibility // reasons, we don't check this for now. } else if (basicConstraints.isCA) { // If this is a CA but the path length is omitted, it is unlimited. basicConstraints.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT; } if (der::End(input) != der::Success) { return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID); } return der::Success; }
SECStatus CERT_DecodeBasicConstraintValue (CERTBasicConstraints *value, SECItem *encodedValue) { EncodedContext decodeContext; PRArenaPool *our_pool; SECStatus rv = SECSuccess; do { PORT_Memset (&decodeContext, 0, sizeof (decodeContext)); /* initialize the value just in case we got "0x30 00", or when the pathLenConstraint is omitted. */ decodeContext.isCA.data =&hexFalse; decodeContext.isCA.len = 1; our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); if (our_pool == NULL) { PORT_SetError (SEC_ERROR_NO_MEMORY); GEN_BREAK (SECFailure); } rv = SEC_QuickDERDecodeItem (our_pool, &decodeContext, CERTBasicConstraintsTemplate, encodedValue); if (rv == SECFailure) break; value->isCA = decodeContext.isCA.data ? (PRBool)(decodeContext.isCA.data[0] != 0) : PR_FALSE; if (decodeContext.pathLenConstraint.data == NULL) { /* if the pathLenConstraint is not encoded, and the current setting is CA, then the pathLenConstraint should be set to a negative number for unlimited certificate path. */ if (value->isCA) value->pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT; } else if (value->isCA) { long len = DER_GetInteger (&decodeContext.pathLenConstraint); if (len < 0 || len == LONG_MAX) { PORT_SetError (SEC_ERROR_BAD_DER); GEN_BREAK (SECFailure); } value->pathLenConstraint = len; } else { /* here we get an error where the subject is not a CA, but the pathLenConstraint is set */ PORT_SetError (SEC_ERROR_BAD_DER); GEN_BREAK (SECFailure); break; } } while (0); PORT_FreeArena (our_pool, PR_FALSE); return (rv); }
CMMFPKIStatus cmmf_PKIStatusInfoGetStatus(CMMFPKIStatusInfo *inStatus) { long derVal; derVal = DER_GetInteger(&inStatus->status); if (derVal == -1 || derVal < cmmfGranted || derVal >= cmmfNumPKIStatus) { return cmmfNoPKIStatus; } return (CMMFPKIStatus)derVal; }
void sv_PrintInteger(FILE *out, SECItem *i, char *m) { int iv; if (i->len > 4) { sv_PrintAsHex(out, i, m); } else { iv = DER_GetInteger(i); fprintf(out, "%s%d (0x%x)\n", m, iv, iv); } }
/* I do have a formula, but it ain't pretty, and it only works because you * can always match three points to a parabola:) */ static unsigned char rc2_map(SECItem *version) { long x; x = DER_GetInteger(version); switch (x) { case 58: return 128; case 120: return 64; case 160: return 40; } return 128; }
int sv_PrintCertificate(FILE *out, SECItem *der, char *m, int level) { PLArenaPool *arena = NULL; CERTCertificate *c; int rv; int iv; char mm[200]; /* Decode certificate */ c = (CERTCertificate *)PORT_ZAlloc(sizeof(CERTCertificate)); if (!c) return PORT_GetError(); arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) return SEC_ERROR_NO_MEMORY; rv = SEC_ASN1DecodeItem(arena, c, SEC_ASN1_GET(CERT_CertificateTemplate), der); if (rv) { PORT_FreeArena(arena, PR_FALSE); return rv; } /* Pretty print it out */ iv = DER_GetInteger(&c->version); fprintf(out, "%sversion=%d (0x%x)\n", m, iv + 1, iv); sprintf(mm, "%sserialNumber=", m); sv_PrintInteger(out, &c->serialNumber, mm); sprintf(mm, "%ssignatureAlgorithm=", m); sv_PrintAlgorithmID(out, &c->signature, mm); sprintf(mm, "%sissuerName=", m); sv_PrintName(out, &c->issuer, mm); sprintf(mm, "%svalidity.", m); sv_PrintValidity(out, &c->validity, mm); sprintf(mm, "%ssubject=", m); sv_PrintName(out, &c->subject, mm); sprintf(mm, "%ssubjectPublicKeyInfo", m); rv = sv_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo, mm); if (rv) { PORT_FreeArena(arena, PR_FALSE); return rv; } sprintf(mm, "%ssignedExtensions.", m); sv_PrintExtensions(out, c->extensions, mm); PORT_FreeArena(arena, PR_FALSE); return 0; }
/* This expents i->data[0] to be the MSB of the integer. ** if you want to print a DER-encoded integer (with the tag and length) ** call SECU_PrintEncodedInteger(); */ void SECU_PrintInteger(FILE *out, const SECItem *i, const char *m, int level) { int iv; if (!i || !i->len || !i->data) { SECU_Indent(out, level); if (m) { fprintf(out, "%s: (null)\n", m); } else { fprintf(out, "(null)\n"); } } else if (i->len > 4) { SECU_PrintAsHex(out, i, m, level); } else { if (i->type == siUnsignedInteger && *i->data & 0x80) { /* Make sure i->data has zero in the highest bite * if i->data is an unsigned integer */ SECItem tmpI; char data[] = { 0, 0, 0, 0, 0 }; PORT_Memcpy(data + 1, i->data, i->len); tmpI.len = i->len + 1; tmpI.data = (void *)data; iv = DER_GetInteger(&tmpI); } else { iv = DER_GetInteger(i); } SECU_Indent(out, level); if (m) { fprintf(out, "%s: %d (0x%x)\n", m, iv, iv); } else { fprintf(out, "%d (0x%x)\n", iv, iv); } } }
SECStatus CERT_FindCRLEntryReasonExten (CERTCrlEntry *crlEntry, CERTCRLEntryReasonCode *value) { SECItem wrapperItem = {siBuffer,0}; SECItem tmpItem = {siBuffer,0}; SECStatus rv; PRArenaPool *arena = NULL; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( ! arena ) { return(SECFailure); } rv = cert_FindExtension(crlEntry->extensions, SEC_OID_X509_REASON_CODE, &wrapperItem); if ( rv != SECSuccess ) { goto loser; } rv = SEC_QuickDERDecodeItem(arena, &tmpItem, SEC_ASN1_GET(SEC_EnumeratedTemplate), &wrapperItem); if ( rv != SECSuccess ) { goto loser; } *value = (CERTCRLEntryReasonCode) DER_GetInteger(&tmpItem); loser: if ( arena ) { PORT_FreeArena(arena, PR_FALSE); } if ( wrapperItem.data ) { PORT_Free(wrapperItem.data); } return (rv); }
/* validates authenticates safe: * 1. checks that the version is supported * 2. checks that only password privacy mode is used (currently) * 3. further, makes sure safe has appropriate policies per above function * PR_FALSE indicates failure. */ static PRBool sec_pkcs12_validate_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe) { PRBool valid = PR_TRUE; SECOidTag safe_type; int version; if(asafe == NULL) { return PR_FALSE; } /* check version, since it is default it may not be present. * therefore, assume ok */ if((asafe->version.len > 0) && (asafe->old == PR_FALSE)) { version = DER_GetInteger(&asafe->version); if(version > SEC_PKCS12_PFX_VERSION) { PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION); return PR_FALSE; } } /* validate password mode is being used */ safe_type = SEC_PKCS7ContentType(asafe->safe); switch(safe_type) { case SEC_OID_PKCS7_ENCRYPTED_DATA: valid = sec_pkcs12_validate_encrypted_safe(asafe); break; case SEC_OID_PKCS7_ENVELOPED_DATA: default: PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE); valid = PR_FALSE; break; } return valid; }
/* Generate a mechaism param from a type, and iv. */ SECItem * PK11_ParamFromAlgid(SECAlgorithmID *algid) { CK_RC2_CBC_PARAMS * rc2_cbc_params = NULL; CK_RC2_PARAMS * rc2_ecb_params = NULL; CK_RC5_CBC_PARAMS * rc5_cbc_params = NULL; CK_RC5_PARAMS * rc5_ecb_params = NULL; PRArenaPool * arena = NULL; SECItem * mech = NULL; SECOidTag algtag; SECStatus rv; CK_MECHANISM_TYPE type; /* initialize these to prevent UMRs in the ASN1 decoder. */ SECItem iv = {siBuffer, NULL, 0}; sec_rc2cbcParameter rc2 = { {siBuffer, NULL, 0}, {siBuffer, NULL, 0} }; sec_rc5cbcParameter rc5 = { {siBuffer, NULL, 0}, {siBuffer, NULL, 0}, {siBuffer, NULL, 0}, {siBuffer, NULL, 0} }; algtag = SECOID_GetAlgorithmTag(algid); type = PK11_AlgtagToMechanism(algtag); mech = PORT_New(SECItem); if (mech == NULL) { return NULL; } mech->type = siBuffer; mech->data = NULL; mech->len = 0; arena = PORT_NewArena(1024); if (!arena) { goto loser; } /* handle the complicated cases */ switch (type) { case CKM_RC2_ECB: rv = SEC_ASN1DecodeItem(arena, &rc2 ,sec_rc2ecb_parameter_template, &(algid->parameters)); if (rv != SECSuccess) { goto loser; } rc2_ecb_params = PORT_New(CK_RC2_PARAMS); if (rc2_ecb_params == NULL) { goto loser; } *rc2_ecb_params = rc2_map(&rc2.rc2ParameterVersion); mech->data = (unsigned char *) rc2_ecb_params; mech->len = sizeof *rc2_ecb_params; break; case CKM_RC2_CBC: case CKM_RC2_CBC_PAD: rv = SEC_ASN1DecodeItem(arena, &rc2 ,sec_rc2cbc_parameter_template, &(algid->parameters)); if (rv != SECSuccess) { goto loser; } rc2_cbc_params = PORT_New(CK_RC2_CBC_PARAMS); if (rc2_cbc_params == NULL) { goto loser; } mech->data = (unsigned char *) rc2_cbc_params; mech->len = sizeof *rc2_cbc_params; rc2_cbc_params->ulEffectiveBits = rc2_map(&rc2.rc2ParameterVersion); if (rc2.iv.len != sizeof rc2_cbc_params->iv) { PORT_SetError(SEC_ERROR_INPUT_LEN); goto loser; } PORT_Memcpy(rc2_cbc_params->iv, rc2.iv.data, rc2.iv.len); break; case CKM_RC5_ECB: rv = SEC_ASN1DecodeItem(arena, &rc5 ,sec_rc5ecb_parameter_template, &(algid->parameters)); if (rv != SECSuccess) { goto loser; } rc5_ecb_params = PORT_New(CK_RC5_PARAMS); if (rc5_ecb_params == NULL) { goto loser; } rc5_ecb_params->ulRounds = DER_GetInteger(&rc5.rounds); rc5_ecb_params->ulWordsize = DER_GetInteger(&rc5.blockSizeInBits)/8; mech->data = (unsigned char *) rc5_ecb_params; mech->len = sizeof *rc5_ecb_params; break; case CKM_RC5_CBC: case CKM_RC5_CBC_PAD: rv = SEC_ASN1DecodeItem(arena, &rc5 ,sec_rc5cbc_parameter_template, &(algid->parameters)); if (rv != SECSuccess) { goto loser; } rc5_cbc_params = (CK_RC5_CBC_PARAMS *) PORT_Alloc(sizeof(CK_RC5_CBC_PARAMS) + rc5.iv.len); if (rc5_cbc_params == NULL) { goto loser; } mech->data = (unsigned char *) rc5_cbc_params; mech->len = sizeof *rc5_cbc_params; rc5_cbc_params->ulRounds = DER_GetInteger(&rc5.rounds); rc5_cbc_params->ulWordsize = DER_GetInteger(&rc5.blockSizeInBits)/8; rc5_cbc_params->pIv = ((CK_BYTE_PTR)rc5_cbc_params) + sizeof(CK_RC5_CBC_PARAMS); rc5_cbc_params->ulIvLen = rc5.iv.len; PORT_Memcpy(rc5_cbc_params->pIv, rc5.iv.data, rc5.iv.len); break; case CKM_PBE_MD2_DES_CBC: case CKM_PBE_MD5_DES_CBC: case CKM_NETSCAPE_PBE_SHA1_DES_CBC: case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: case CKM_PBE_SHA1_DES2_EDE_CBC: case CKM_PBE_SHA1_DES3_EDE_CBC: case CKM_PBE_SHA1_RC2_40_CBC: case CKM_PBE_SHA1_RC2_128_CBC: case CKM_PBE_SHA1_RC4_40: case CKM_PBE_SHA1_RC4_128: case CKM_PKCS5_PBKD2: rv = pbe_PK11AlgidToParam(algid,mech); if (rv != SECSuccess) { goto loser; } break; case CKM_RC4: case CKM_SEED_ECB: case CKM_CAMELLIA_ECB: case CKM_AES_ECB: case CKM_DES_ECB: case CKM_DES3_ECB: case CKM_IDEA_ECB: case CKM_CDMF_ECB: case CKM_CAST_ECB: case CKM_CAST3_ECB: case CKM_CAST5_ECB: break; default: if (pk11_lookup(type)->iv == 0) { break; } /* FALL THROUGH */ case CKM_SEED_CBC: case CKM_CAMELLIA_CBC: case CKM_AES_CBC: case CKM_DES_CBC: case CKM_DES3_CBC: case CKM_IDEA_CBC: case CKM_CDMF_CBC: case CKM_CAST_CBC: case CKM_CAST3_CBC: case CKM_CAST5_CBC: case CKM_SEED_CBC_PAD: case CKM_CAMELLIA_CBC_PAD: case CKM_AES_CBC_PAD: case CKM_DES_CBC_PAD: case CKM_DES3_CBC_PAD: case CKM_IDEA_CBC_PAD: case CKM_CDMF_CBC_PAD: case CKM_CAST_CBC_PAD: case CKM_CAST3_CBC_PAD: case CKM_CAST5_CBC_PAD: case CKM_SKIPJACK_CBC64: case CKM_SKIPJACK_ECB64: case CKM_SKIPJACK_OFB64: case CKM_SKIPJACK_CFB64: case CKM_SKIPJACK_CFB32: case CKM_SKIPJACK_CFB16: case CKM_SKIPJACK_CFB8: case CKM_BATON_ECB128: case CKM_BATON_ECB96: case CKM_BATON_CBC128: case CKM_BATON_COUNTER: case CKM_BATON_SHUFFLE: case CKM_JUNIPER_ECB128: case CKM_JUNIPER_CBC128: case CKM_JUNIPER_COUNTER: case CKM_JUNIPER_SHUFFLE: /* simple cases are simply octet string encoded IVs */ rv = SEC_ASN1DecodeItem(arena, &iv, SEC_ASN1_GET(SEC_OctetStringTemplate), &(algid->parameters)); if (rv != SECSuccess || iv.data == NULL) { goto loser; } /* XXX Should be some IV length sanity check here. */ mech->data = (unsigned char*)PORT_Alloc(iv.len); if (mech->data == NULL) { goto loser; } PORT_Memcpy(mech->data, iv.data, iv.len); mech->len = iv.len; break; } PORT_FreeArena(arena, PR_FALSE); return mech; loser: if (arena) PORT_FreeArena(arena, PR_FALSE); SECITEM_FreeItem(mech,PR_TRUE); return NULL; }
int main(int argc, char **argv) { int verbose=0, force=0; int ascii=0, issuerAscii=0; char *progName=0; PRFileDesc *inFile=0, *issuerCertFile=0; SECItem derCert, derIssuerCert; PLArenaPool *arena=0; CERTSignedData *signedData=0; CERTCertificate *cert=0, *issuerCert=0; SECKEYPublicKey *rsapubkey=0; SECAlgorithmID md5WithRSAEncryption, md2WithRSAEncryption; SECAlgorithmID sha1WithRSAEncryption, rsaEncryption; SECItem spk; int selfSigned=0; int invalid=0; char *inFileName = NULL, *issuerCertFileName = NULL; PLOptState *optstate; PLOptStatus status; SECStatus rv; PORT_Memset(&md5WithRSAEncryption, 0, sizeof(md5WithRSAEncryption)); PORT_Memset(&md2WithRSAEncryption, 0, sizeof(md2WithRSAEncryption)); PORT_Memset(&sha1WithRSAEncryption, 0, sizeof(sha1WithRSAEncryption)); PORT_Memset(&rsaEncryption, 0, sizeof(rsaEncryption)); progName = strrchr(argv[0], '/'); progName = progName ? progName+1 : argv[0]; optstate = PL_CreateOptState(argc, argv, "aAvf"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case 'v': verbose = 1; break; case 'f': force = 1; break; case 'a': ascii = 1; break; case 'A': issuerAscii = 1; break; case '\0': if (!inFileName) inFileName = PL_strdup(optstate->value); else if (!issuerCertFileName) issuerCertFileName = PL_strdup(optstate->value); else Usage(progName); break; } } if (!inFileName || !issuerCertFileName || status == PL_OPT_BAD) { /* insufficient or excess args */ Usage(progName); } inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile) { fprintf(stderr, "%s: unable to open \"%s\" for reading\n", progName, inFileName); exit(1); } issuerCertFile = PR_Open(issuerCertFileName, PR_RDONLY, 0); if (!issuerCertFile) { fprintf(stderr, "%s: unable to open \"%s\" for reading\n", progName, issuerCertFileName); exit(1); } if (SECU_ReadDERFromFile(&derCert, inFile, ascii, PR_FALSE) != SECSuccess) { printf("Couldn't read input certificate as DER binary or base64\n"); exit(1); } arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == 0) { fprintf(stderr,"%s: can't allocate scratch arena!", progName); exit(1); } if (issuerCertFile) { CERTSignedData *issuerCertSD=0; if (SECU_ReadDERFromFile(&derIssuerCert, issuerCertFile, issuerAscii, PR_FALSE) != SECSuccess) { printf("Couldn't read issuer certificate as DER binary or base64.\n"); exit(1); } issuerCertSD = PORT_ArenaZNew(arena, CERTSignedData); if (!issuerCertSD) { fprintf(stderr,"%s: can't allocate issuer signed data!", progName); exit(1); } rv = SEC_ASN1DecodeItem(arena, issuerCertSD, SEC_ASN1_GET(CERT_SignedDataTemplate), &derIssuerCert); if (rv) { fprintf(stderr, "%s: Issuer cert isn't X509 SIGNED Data?\n", progName); exit(1); } issuerCert = createEmptyCertificate(); if (!issuerCert) { printf("%s: can't allocate space for issuer cert.", progName); exit(1); } rv = SEC_ASN1DecodeItem(arena, issuerCert, SEC_ASN1_GET(CERT_CertificateTemplate), &issuerCertSD->data); if (rv) { printf("%s: Does not appear to be an X509 Certificate.\n", progName); exit(1); } } signedData = PORT_ArenaZNew(arena,CERTSignedData); if (!signedData) { fprintf(stderr,"%s: can't allocate signedData!", progName); exit(1); } rv = SEC_ASN1DecodeItem(arena, signedData, SEC_ASN1_GET(CERT_SignedDataTemplate), &derCert); if (rv) { fprintf(stderr, "%s: Does not appear to be X509 SIGNED Data.\n", progName); exit(1); } if (verbose) { printf("Decoded ok as X509 SIGNED data.\n"); } cert = createEmptyCertificate(); if (!cert) { fprintf(stderr, "%s: can't allocate cert", progName); exit(1); } rv = SEC_ASN1DecodeItem(arena, cert, SEC_ASN1_GET(CERT_CertificateTemplate), &signedData->data); if (rv) { fprintf(stderr, "%s: Does not appear to be an X509 Certificate.\n", progName); exit(1); } if (verbose) { printf("Decoded ok as an X509 certificate.\n"); } SECU_RegisterDynamicOids(); rv = SECU_PrintSignedData(stdout, &derCert, "Certificate", 0, (SECU_PPFunc)SECU_PrintCertificate); if (rv) { fprintf(stderr, "%s: Unable to pretty print cert. Error: %d\n", progName, PORT_GetError()); if (!force) { exit(1); } } /* Do various checks on the cert */ printf("\n"); /* Check algorithms */ rv = SECOID_SetAlgorithmID(arena, &md5WithRSAEncryption, SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, NULL); if (rv) { fprintf(stderr, "%s: failed to set algorithm ID for SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION.\n", progName); exit(1); } rv = SECOID_SetAlgorithmID(arena, &md2WithRSAEncryption, SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION, NULL); if (rv) { fprintf(stderr, "%s: failed to set algorithm ID for SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION.\n", progName); exit(1); } rv = SECOID_SetAlgorithmID(arena, &sha1WithRSAEncryption, SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, NULL); if (rv) { fprintf(stderr, "%s: failed to set algorithm ID for SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION.\n", progName); exit(1); } rv = SECOID_SetAlgorithmID(arena, &rsaEncryption, SEC_OID_PKCS1_RSA_ENCRYPTION, NULL); if (rv) { fprintf(stderr, "%s: failed to set algorithm ID for SEC_OID_PKCS1_RSA_ENCRYPTION.\n", progName); exit(1); } { int isMD5RSA = (SECOID_CompareAlgorithmID(&cert->signature, &md5WithRSAEncryption) == 0); int isMD2RSA = (SECOID_CompareAlgorithmID(&cert->signature, &md2WithRSAEncryption) == 0); int isSHA1RSA = (SECOID_CompareAlgorithmID(&cert->signature, &sha1WithRSAEncryption) == 0); if (verbose) { printf("\nDoing algorithm checks.\n"); } if (!(isMD5RSA || isMD2RSA || isSHA1RSA)) { printf("PROBLEM: Signature not PKCS1 MD5, MD2, or SHA1 + RSA.\n"); } else if (!isMD5RSA) { printf("WARNING: Signature not PKCS1 MD5 with RSA Encryption\n"); } if (SECOID_CompareAlgorithmID(&cert->signature, &signedData->signatureAlgorithm)) { printf("PROBLEM: Algorithm in sig and certInfo don't match.\n"); } } if (SECOID_CompareAlgorithmID(&cert->subjectPublicKeyInfo.algorithm, &rsaEncryption)) { printf("PROBLEM: Public key algorithm is not PKCS1 RSA Encryption.\n"); } /* Check further public key properties */ spk = cert->subjectPublicKeyInfo.subjectPublicKey; DER_ConvertBitString(&spk); if (verbose) { printf("\nsubjectPublicKey DER\n"); rv = DER_PrettyPrint(stdout, &spk, PR_FALSE); printf("\n"); } rsapubkey = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena,sizeof(SECKEYPublicKey)); if (!rsapubkey) { fprintf(stderr, "%s: rsapubkey allocation failed.\n", progName); exit(1); } rv = SEC_ASN1DecodeItem(arena, rsapubkey, SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate), &spk); if (rv) { printf("PROBLEM: subjectPublicKey is not a DER PKCS1 RSAPublicKey.\n"); } else { int mlen; int pubexp; if (verbose) { printf("Decoded RSA Public Key ok. Doing key checks.\n"); } PORT_Assert(rsapubkey->keyType == rsaKey); /* XXX RSA */ mlen = checkInteger(&rsapubkey->u.rsa.modulus, "Modulus", verbose); printf("INFO: Public Key modulus length in bits: %d\n", mlen); if (mlen > MAX_MODULUS) { printf("PROBLEM: Modulus length exceeds %d bits.\n", MAX_MODULUS); } if (mlen < 512) { printf("WARNING: Short modulus.\n"); } if (mlen != (1 << (ffs(mlen)-1))) { printf("WARNING: Unusual modulus length (not a power of two).\n"); } checkInteger(&rsapubkey->u.rsa.publicExponent, "Public Exponent", verbose); pubexp = DER_GetInteger(&rsapubkey->u.rsa.publicExponent); if (pubexp != 17 && pubexp != 3 && pubexp != 65537) { printf("WARNING: Public exponent not any of: 3, 17, 65537\n"); } } /* Name checks */ checkName(&cert->issuer, "Issuer Name", verbose); checkName(&cert->subject, "Subject Name", verbose); if (issuerCert) { SECComparison c = CERT_CompareName(&cert->issuer, &issuerCert->subject); if (c) { printf("PROBLEM: Issuer Name and Subject in Issuing Cert differ\n"); } } /* Check if self-signed */ selfSigned = (CERT_CompareName(&cert->issuer, &cert->subject) == 0); if (selfSigned) { printf("INFO: Certificate is self signed.\n"); } else { printf("INFO: Certificate is NOT self-signed.\n"); } /* Validity time check */ if (CERT_CertTimesValid(cert) == SECSuccess) { printf("INFO: Inside validity period of certificate.\n"); } else { printf("PROBLEM: Not in validity period of certificate.\n"); invalid = 1; } /* Signature check if self-signed */ if (selfSigned && !invalid) { if (rsapubkey->u.rsa.modulus.len) { SECStatus ver; if (verbose) { printf("Checking self signature.\n"); } ver = OurVerifySignedData(signedData, cert); if (ver != SECSuccess) { printf("PROBLEM: Verification of self-signature failed!\n"); } else { printf("INFO: Self-signature verifies ok.\n"); } } else { printf("INFO: Not checking signature due to key problems.\n"); } } else if (!selfSigned && !invalid && issuerCert) { SECStatus ver; ver = OurVerifySignedData(signedData, issuerCert); if (ver != SECSuccess) { printf("PROBLEM: Verification of issuer's signature failed!\n"); } else { printf("INFO: Issuer's signature verifies ok.\n"); } } else { printf("INFO: Not checking signature.\n"); } return 0; }
static SECStatus crmf_extract_long_from_item(SECItem *intItem, long *destLong) { *destLong = DER_GetInteger(intItem); return (*destLong == -1) ? SECFailure : SECSuccess; }