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, &notBefore, &notAfter);        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, &notBefore, &notAfter);        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 + -
显示快捷键?