certdb.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,329 行 · 第 1/4 页
C
2,329 行
} else { cert->nsCertType |= NS_CERT_TYPE_SSL_SERVER; } } if (findOIDinOIDSeqByTagNum(extKeyUsage, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH) == SECSuccess){ if (basicConstraintPresent == PR_TRUE && (basicConstraint.isCA)) { cert->nsCertType |= NS_CERT_TYPE_SSL_CA; } else { cert->nsCertType |= NS_CERT_TYPE_SSL_CLIENT; } } if (findOIDinOIDSeqByTagNum(extKeyUsage, SEC_OID_EXT_KEY_USAGE_CODE_SIGN) == SECSuccess) { if (basicConstraintPresent == PR_TRUE && (basicConstraint.isCA)) { cert->nsCertType |= NS_CERT_TYPE_OBJECT_SIGNING_CA; } else { cert->nsCertType |= NS_CERT_TYPE_OBJECT_SIGNING; } } if (findOIDinOIDSeqByTagNum(extKeyUsage, SEC_OID_EXT_KEY_USAGE_TIME_STAMP) == SECSuccess) { cert->nsCertType |= EXT_KEY_USAGE_TIME_STAMP; } if (findOIDinOIDSeqByTagNum(extKeyUsage, SEC_OID_OCSP_RESPONDER) == SECSuccess) { cert->nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER; } } else { /* if no extension, then allow any ssl or email (no ca or object * signing) */ cert->nsCertType = NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_SSL_SERVER | NS_CERT_TYPE_EMAIL; /* if the basic constraint extension says the cert is a CA, then allow SSL CA and EMAIL CA and Status Responder */ if ((basicConstraintPresent == PR_TRUE) && (basicConstraint.isCA)) { cert->nsCertType |= NS_CERT_TYPE_SSL_CA; cert->nsCertType |= NS_CERT_TYPE_EMAIL_CA; cert->nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER; } else if (CERT_IsCACert(cert, NULL) == PR_TRUE) { cert->nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER; } /* if the cert is a fortezza CA cert, then allow SSL CA and EMAIL CA */ if (fortezzaIsCA(cert)) { cert->nsCertType |= NS_CERT_TYPE_SSL_CA; cert->nsCertType |= NS_CERT_TYPE_EMAIL_CA; } } if (extKeyUsage != NULL) { PORT_Free(encodedExtKeyUsage.data); CERT_DestroyOidSequence(extKeyUsage); } return(SECSuccess);}/* * cert_GetKeyID() - extract or generate the subjectKeyID from a certificate */SECStatuscert_GetKeyID(CERTCertificate *cert){ SECItem tmpitem; SECStatus rv; SECKEYPublicKey *key; cert->subjectKeyID.len = 0; /* see of the cert has a key identifier extension */ rv = CERT_FindSubjectKeyIDExten(cert, &tmpitem); if ( rv == SECSuccess ) { cert->subjectKeyID.data = (unsigned char*) PORT_ArenaAlloc(cert->arena, tmpitem.len); if ( cert->subjectKeyID.data != NULL ) { PORT_Memcpy(cert->subjectKeyID.data, tmpitem.data, tmpitem.len); cert->subjectKeyID.len = tmpitem.len; cert->keyIDGenerated = PR_FALSE; } PORT_Free(tmpitem.data); } /* if the cert doesn't have a key identifier extension and the cert is * a V1 fortezza certificate, use the cert's 8 byte KMID as the * key identifier. */ key = CERT_KMIDPublicKey(cert); if (key != NULL) { if (key->keyType == fortezzaKey) { cert->subjectKeyID.data = (unsigned char *)PORT_ArenaAlloc(cert->arena, 8); if ( cert->subjectKeyID.data != NULL ) { PORT_Memcpy(cert->subjectKeyID.data, key->u.fortezza.KMID, 8); cert->subjectKeyID.len = 8; cert->keyIDGenerated = PR_FALSE; } } SECKEY_DestroyPublicKey(key); } /* if the cert doesn't have a key identifier extension, then generate one*/ if ( cert->subjectKeyID.len == 0 ) { /* * pkix says that if the subjectKeyID is not present, then we should * use the SHA-1 hash of the DER-encoded publicKeyInfo from the cert */ cert->subjectKeyID.data = (unsigned char *)PORT_ArenaAlloc(cert->arena, SHA1_LENGTH); if ( cert->subjectKeyID.data != NULL ) { rv = SHA1_HashBuf(cert->subjectKeyID.data, cert->derPublicKey.data, cert->derPublicKey.len); if ( rv == SECSuccess ) { cert->subjectKeyID.len = SHA1_LENGTH; } } } if ( cert->subjectKeyID.len == 0 ) { return(SECFailure); } return(SECSuccess);}/* * take a DER certificate and decode it into a certificate structure */CERTCertificate *CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, char *nickname){ CERTCertificate *cert; PRArenaPool *arena; void *data; int rv; int len; char *tmpname; /* make a new arena */ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( !arena ) { return 0; } /* allocate the certificate structure */ cert = (CERTCertificate *)PORT_ArenaZAlloc(arena, sizeof(CERTCertificate)); if ( !cert ) { goto loser; } cert->arena = arena; if ( copyDER ) { /* copy the DER data for the cert into this arena */ data = (void *)PORT_ArenaAlloc(arena, derSignedCert->len); if ( !data ) { goto loser; } cert->derCert.data = (unsigned char *)data; cert->derCert.len = derSignedCert->len; PORT_Memcpy(data, derSignedCert->data, derSignedCert->len); } else { /* point to passed in DER data */ cert->derCert = *derSignedCert; } /* decode the certificate info */ rv = SEC_ASN1DecodeItem(arena, cert, SEC_SignedCertificateTemplate, &cert->derCert); if ( rv ) { goto loser; } if (cert_HasUnknownCriticalExten (cert->extensions) == PR_TRUE) { PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION); goto loser; } /* generate and save the database key for the cert */ rv = CERT_KeyFromDERCert(arena, &cert->derCert, &cert->certKey); if ( rv ) { goto loser; } /* set the nickname */ if ( nickname == NULL ) { cert->nickname = NULL; } else { /* copy and install the nickname */ len = PORT_Strlen(nickname) + 1; cert->nickname = (char*)PORT_ArenaAlloc(arena, len); if ( cert->nickname == NULL ) { goto loser; } PORT_Memcpy(cert->nickname, nickname, len); } /* set the email address */ cert->emailAddr = CERT_GetCertificateEmailAddress(cert); /* initialize the subjectKeyID */ rv = cert_GetKeyID(cert); if ( rv != SECSuccess ) { goto loser; } /* initialize keyUsage */ rv = GetKeyUsage(cert); if ( rv != SECSuccess ) { goto loser; } /* initialize the certType */ rv = CERT_GetCertType(cert); if ( rv != SECSuccess ) { goto loser; } tmpname = CERT_NameToAscii(&cert->subject); if ( tmpname != NULL ) { cert->subjectName = PORT_ArenaStrdup(cert->arena, tmpname); PORT_Free(tmpname); } tmpname = CERT_NameToAscii(&cert->issuer); if ( tmpname != NULL ) { cert->issuerName = PORT_ArenaStrdup(cert->arena, tmpname); PORT_Free(tmpname); } cert->referenceCount = 1; cert->slot = NULL; cert->pkcs11ID = CK_INVALID_KEY; cert->dbnickname = NULL; return(cert); loser: if ( arena ) { PORT_FreeArena(arena, PR_FALSE); } return(0);}/*** Amount of time that a certifiate is allowed good before it is actually** good. This is used for pending certificates, ones that are about to be** valid. The slop is designed to allow for some variance in the clocks** of the machine checking the certificate.*/#define PENDING_SLOP (24L*60L*60L)SECStatusCERT_GetCertTimes(CERTCertificate *c, int64 *notBefore, int64 *notAfter){ int rv; /* convert DER not-before time */ rv = DER_UTCTimeToTime(notBefore, &c->validity.notBefore); if (rv) { return(SECFailure); } /* convert DER not-after time */ rv = DER_UTCTimeToTime(notAfter, &c->validity.notAfter); if (rv) { return(SECFailure); } return(SECSuccess);}/* * Check the validity times of a certificate */SECCertTimeValidityCERT_CheckCertValidTimes(CERTCertificate *c, int64 t, PRBool allowOverride){ int64 notBefore, notAfter, pendingSlop; SECStatus rv; /* if cert is already marked OK, then don't bother to check */ if ( allowOverride && c->timeOK ) { return(secCertTimeValid); } rv = CERT_GetCertTimes(c, ¬Before, ¬After); if (rv) { return(secCertTimeExpired); /*XXX is this the right thing to do here?*/ } LL_I2L(pendingSlop, PENDING_SLOP); LL_SUB(notBefore, notBefore, pendingSlop); if ( LL_CMP( t, <, notBefore ) ) { PORT_SetError(SEC_ERROR_EXPIRED_CERTIFICATE); return(secCertTimeNotValidYet); } if ( LL_CMP( t, >, notAfter) ) { PORT_SetError(SEC_ERROR_EXPIRED_CERTIFICATE); return(secCertTimeExpired); } return(secCertTimeValid);}SECStatusSEC_GetCrlTimes(CERTCrl *date, int64 *notBefore, int64 *notAfter){ int rv; /* convert DER not-before time */ rv = DER_UTCTimeToTime(notBefore, &date->lastUpdate); if (rv) { return(SECFailure); } /* convert DER not-after time */ if (date->nextUpdate.data) { rv = DER_UTCTimeToTime(notAfter, &date->nextUpdate); if (rv) { return(SECFailure); } } else { LL_I2L(*notAfter, 0L); } return(SECSuccess);}/* These routines should probably be combined with the cert * routines using an common extraction routine. */SECCertTimeValiditySEC_CheckCrlTimes(CERTCrl *crl, int64 t) { int64 notBefore, notAfter, pendingSlop; SECStatus rv; rv = SEC_GetCrlTimes(crl, ¬Before, ¬After); if (rv) { return(secCertTimeExpired); } LL_I2L(pendingSlop, PENDING_SLOP); LL_SUB(notBefore, notBefore, pendingSlop); if ( LL_CMP( t, <, notBefore ) ) { return(secCertTimeNotValidYet); } /* If next update is omitted and the test for notBefore passes, then we assume that the crl is up to date. */ if ( LL_IS_ZERO(notAfter) ) { return(secCertTimeValid); } if ( LL_CMP( t, >, notAfter) ) { return(secCertTimeExpired); } return(secCertTimeValid);}PRBoolSEC_CrlIsNewer(CERTCrl *inNew, CERTCrl *old) { int64 newNotBefore, newNotAfter; int64 oldNotBefore, oldNotAfter; SECStatus rv; /* problems with the new CRL? reject it */ rv = SEC_GetCrlTimes(inNew, &newNotBefore, &newNotAfter); if (rv) return PR_FALSE; /* problems with the old CRL? replace it */ rv = SEC_GetCrlTimes(old, &oldNotBefore, &oldNotAfter); if (rv) return PR_TRUE; /* Question: what about the notAfter's? */ return ((PRBool)LL_CMP(oldNotBefore, <, newNotBefore));} /* * return required key usage and cert type based on cert usage */SECStatusCERT_KeyUsageAndTypeForCertUsage(SECCertUsage usage, PRBool ca, unsigned int *retKeyUsage, unsigned int *retCertType){ unsigned int requiredKeyUsage = 0; unsigned int requiredCertType = 0; if ( ca ) { switch ( usage ) { case certUsageSSLServerWithStepUp: requiredKeyUsage = KU_NS_GOVT_APPROVED | KU_KEY_CERT_SIGN; requiredCertType = NS_CERT_TYPE_SSL_CA; break; case certUsageSSLClient: requiredKeyUsage = KU_KEY_CERT_SIGN; requiredCertType = NS_CERT_TYPE_SSL_CA; break; case certUsageSSLServer: requiredKeyUsage = KU_KEY_CERT_SIGN; requiredCertType = NS_CERT_TYPE_SSL_CA; break; case certUsageSSLCA: requiredKeyUsage = KU_KEY_CERT_SIGN; requiredCertType = NS_CERT_TYPE_SSL_CA; break; case certUsageEmailSigner: requiredKeyUsage = KU_KEY_CERT_SIGN; requiredCertType = NS_CERT_TYPE_EMAIL_CA; break; case certUsageEmailRecipient: requiredKeyUsage = KU_KEY_CERT_SIGN; requiredCertType = NS_CERT_TYPE_EMAIL_CA; break; case certUsageObjectSigner: requiredKeyUsage = KU_KEY_CERT_SIGN; requiredCertType = NS_CERT_TYPE_OBJECT_SIGNING_CA; break; case certUsageAnyCA: case certUsageStatusResponder: requiredKeyUsage = KU_KEY_CERT_SIGN; requiredCertType = NS_CERT_TYPE_OBJECT_SIGNING_CA | NS_CERT_TYPE_EMAIL_CA | NS_CERT_TYPE_SSL_CA; break; default: PORT_Assert(0); goto loser; } } else { switch ( usage ) { case certUsageSSLClient: requiredKeyUsage = KU_DIGITAL_SIGNATURE; requiredCertType = NS_CERT_TYPE_SSL_CLIENT; break; case certUsageSSLServer: requiredKeyUsage = KU_KEY_AGREEMENT_OR_ENCIPHERMENT; requiredCertType = NS_CERT_TYPE_SSL_SERVER; break; case certUsageSSLServerWithStepUp: requiredKeyUsage = KU_KEY_AGREEMENT_OR_ENCIPHERMENT | KU_NS_GOVT_APPROVED; requiredCertType = NS_CERT_TYPE_SSL_SERVER; break; case certUsageSSLCA: requiredKeyUsage = KU_KEY_CERT_SIGN; requiredCertType = NS_CERT_TYPE_SSL_CA; break; case certUsageEmailSigner: requiredKeyUsage = KU_DIGITAL_SIGNATURE; requiredCertType = NS_CERT_TYPE_EMAIL; break; case certUsageEmailRecipient: requiredKeyUsage = KU_KEY_AGREEMENT_OR_ENCIPHERMENT; requiredCertType = NS_CERT_TYPE_EMAIL; break; case certUsageObjectSigner: requiredKeyUsage = KU_DIGITAL_SIGNATURE; requiredCertType = NS_CERT_TYPE_OBJECT_SIGNING; break; case certUsageStatusResponder: requiredKeyUsage = KU_DIGITAL_SIGNATURE; requiredCertType = EXT_KEY_USAGE_STATUS_RESPONDER; break; default: PORT_Assert(0); goto loser; } } if ( retKeyUsage != NULL ) { *retKeyUsage = requiredKeyUsage; } if ( retCertType != NULL ) { *retCertType = requiredCertType; } return(SECSuccess);loser: return(SECFailure);}/* * check the key usage of a cert against a set of required values */SECStatusCERT_CheckKeyUsage(CERTCertificate *cert, unsigned int requiredUsage){ SECKEYPublicKey *key; /* choose between key agreement or key encipherment based on key * type in cert */ if ( requiredUsage & KU_KEY_AGREEMENT_OR_ENCIPHERMENT ) { key = CERT_ExtractPublicKey(cert); if ( ( key->keyType == keaKey ) || ( key->keyType == fortezzaKey ) || ( key->keyType == dhKey ) ) { requiredUsage |= KU_KEY_AGREEMENT; } else { requiredUsage |= KU_KEY_ENCIPHERMENT; } /* now turn off the special bit */ requiredUsage &= (~KU_KEY_AGREEMENT_OR_ENCIPHERMENT); SECKEY_DestroyPublicKey(key); } if ( ( cert->keyUsage & requiredUsage ) != requiredUsage ) { return(SECFailure); } return(SECSuccess);}CERTCertificate *CERT_DupCertificate(CERTCertificate *c){ if (c) { CERT_LockCertRefCount(c); ++c->referenceCount; CERT_UnlockCertRefCount(c); } return c;}/* * Allow use of default cert database, so that apps(such as mozilla) don't * have to pass the handle all over the place. */static CERTCertDBHandle *default_cert_db_handle = 0;voidCERT_SetDefaultCertDB(CERTCertDBHandle *handle){ default_cert_db_handle = handle; return;}CERTCertDBHandle *CERT_GetDefaultCertDB(void){ return(default_cert_db_handle);}/* * Open volatile certificate database and index databases. This is a * fallback if the real databases can't be opened or created. It is only * resident in memory, so it will not be persistent. We do this so that * we don't crash if the databases can't be created. */SECStatusCERT_OpenVolatileCertDB(CERTCertDBHandle *handle){ /* * Open the memory resident perm cert database. */ handle->permCertDB = dbopen( 0, O_RDWR | O_CREAT, 0600, DB_HASH, 0 ); if ( !handle->permCertDB ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?