pk11cert.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,345 行 · 第 1/5 页

C
2,345
字号
  /* dataEncipherment = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_DATA_ENCIPHERMENT); */  /* keyAgreement     = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_KEY_AGREEMENT); */  /* keyCertSign      = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_KEY_CERT_SIGN); */  /* crlSign          = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CRL_SIGN); */  /* "Purpose" trust information */  serverAuth       = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_SERVER_AUTH);  /* clientAuth       = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CLIENT_AUTH); */  codeSigning      = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CODE_SIGNING);  emailProtection  = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_EMAIL_PROTECTION);  /* ipsecEndSystem   = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_IPSEC_END_SYSTEM); */  /* ipsecTunnel      = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_IPSEC_TUNNEL); */  /* ipsecUser        = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_IPSEC_USER); */  /* timeStamping     = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_TIME_STAMPING); */  /* Here's where the fun logic happens.  We have to map back from the key usage,   * extended key usage, purpose, and possibly other trust values into the old   * trust-flags bits.   */  /* First implementation: keep it simple for testing.  We can study what other   * mappings would be appropriate and add them later.. fgmr 20000724 */  if( serverAuth & CKT_NETSCAPE_TRUSTED ) {    trust->sslFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED;  }  if( serverAuth & CKT_NETSCAPE_TRUSTED_DELEGATOR ) {    trust->sslFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;  }  if( emailProtection & CKT_NETSCAPE_TRUSTED ) {    trust->emailFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED;  }  if( emailProtection & CKT_NETSCAPE_TRUSTED_DELEGATOR ) {    trust->emailFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;  }  if( codeSigning & CKT_NETSCAPE_TRUSTED ) {    trust->objectSigningFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED;  }  if( codeSigning & CKT_NETSCAPE_TRUSTED_DELEGATOR ) {    trust->objectSigningFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;  }  /* There's certainly a lot more logic that can go here.. */  return PR_TRUE;}/* * Build an CERTCertificate structure from a PKCS#11 object ID.... certID * Must be a CertObject. This code does not explicitly checks that. */CERTCertificate *PK11_MakeCertFromHandle(PK11SlotInfo *slot,CK_OBJECT_HANDLE certID,						CK_ATTRIBUTE *privateLabel){    char * nickname = NULL;    CERTCertificate *cert = NULL;    CERTCertTrust *trust;    PRBool isFortezzaRootCA = PR_FALSE;    PRBool swapNickname = PR_FALSE;    cert = pk11_fastCert(slot,certID,privateLabel, &nickname);    if (cert == NULL) goto loser;	    if (nickname) {	if (cert->nickname != NULL) {		cert->dbnickname = cert->nickname;	} 	cert->nickname = PORT_ArenaStrdup(cert->arena,nickname);	PORT_Free(nickname);	nickname = NULL;	swapNickname = PR_TRUE;    }    /* remember where this cert came from.... If we have just looked     * it up from the database and it already has a slot, don't add a new     * one. */    if (cert->slot == NULL) {	cert->slot = PK11_ReferenceSlot(slot);	cert->pkcs11ID = certID;	cert->ownSlot = PR_TRUE;    }    if (cert->trust == NULL) {	unsigned int type;	trust = 	  (CERTCertTrust*)PORT_ArenaAlloc(cert->arena, sizeof(CERTCertTrust));	if (trust == NULL) goto loser;	PORT_Memset(trust,0, sizeof(CERTCertTrust));	cert->trust = trust;	/* build some cert trust flags */    /* First, see if there's a trust object for this cert. */    /* For the first implementation, we'll just check this slot     * and worry about overriding trust info later. */    if( pk11_HandleTrustObject(slot, cert, trust) ) {      ;    } else	if (CERT_IsCACert(cert, &type)) {	    unsigned int trustflags = CERTDB_VALID_CA;	   	    /* Allow PKCS #11 modules to give us trusted CA's. We only accept	     * valid CA's which are self-signed here. They must have an object	     * ID of '0'.  */ 	    if (pk11_isID0(slot,certID) && 		SECITEM_CompareItem(&cert->derSubject,&cert->derIssuer)							   == SECEqual) {		trustflags |= CERTDB_TRUSTED_CA;		/* is the slot a fortezza card? allow the user or		 * admin to turn on objectSigning, but don't turn		 * full trust on explicitly */		if (PK11_DoesMechanism(slot,CKM_KEA_KEY_DERIVE)) {		    trust->objectSigningFlags |= CERTDB_VALID_CA;		    isFortezzaRootCA = PR_TRUE;		}	    }	    if ((type & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) {		trust->sslFlags |= trustflags;	    }	    if ((type & NS_CERT_TYPE_EMAIL_CA) == NS_CERT_TYPE_EMAIL_CA) {		trust->emailFlags |= trustflags;	    }	    if ((type & NS_CERT_TYPE_OBJECT_SIGNING_CA) 					== NS_CERT_TYPE_OBJECT_SIGNING_CA) {		trust->objectSigningFlags |= trustflags;	    }	}    } else  {	trust = cert->trust;    }    if (PK11_IsUserCert(slot,cert,certID)) {	trust->sslFlags |= CERTDB_USER;	trust->emailFlags |= CERTDB_USER;	/*    trust->objectSigningFlags |= CERTDB_USER; */    }    /* if fortezza, write the root cert to the DB */    if ((isFortezzaRootCA) && (!cert->isperm)) {	char *name = NULL;	if (swapNickname) {	    nickname = cert->nickname;	    cert->nickname = cert->dbnickname;	}	if (cert->nickname) {	     name = PORT_Strdup(cert->nickname);	}	if (name == NULL) name = CERT_MakeCANickname(cert);	CERT_AddTempCertToPerm(cert,name,cert->trust);	if (name) PORT_Free(name);	if (swapNickname) {	    if (cert->nickname != NULL) {		cert->dbnickname = cert->nickname;	    }	    cert->nickname = PORT_ArenaStrdup(cert->arena,nickname);	}    }    return cert;loser:    if (nickname) PORT_Free(nickname);    if (cert) CERT_DestroyCertificate(cert);    return NULL;}	/* * Build get a certificate from a private key */CERTCertificate *PK11_GetCertFromPrivateKey(SECKEYPrivateKey *privKey){    PK11SlotInfo *slot = privKey->pkcs11Slot;    CK_OBJECT_HANDLE certID = 		PK11_MatchItem(slot,privKey->pkcs11ID,CKO_CERTIFICATE);    SECStatus rv;    CERTCertificate *cert;    if (certID == CK_INVALID_KEY) {	/* couldn't find it on the card, look in our data base */	SECItem derSubject;	rv = PK11_ReadAttribute(slot, privKey->pkcs11ID, CKA_SUBJECT, NULL,					&derSubject);	if (rv != SECSuccess) {	    PORT_SetError(SSL_ERROR_NO_CERTIFICATE);	    return NULL;	}	cert = CERT_FindCertByName(CERT_GetDefaultCertDB(),&derSubject);	PORT_Free(derSubject.data);	return cert;    }    cert = PK11_MakeCertFromHandle(slot,certID,NULL);    return (cert);}/* * destroy a private key if there are no matching certs. * this function also frees the privKey structure. */SECStatusPK11_DeleteTokenPrivateKey(SECKEYPrivateKey *privKey){    CERTCertificate *cert=PK11_GetCertFromPrivateKey(privKey);    /* found a cert matching the private key?. */    if (cert != NULL) {	/* yes, don't delete the key */        CERT_DestroyCertificate(cert);	SECKEY_DestroyPrivateKey(privKey);	return SECWouldBlock;    }    /* now, then it's safe for the key to go away */    PK11_DestroyTokenObject(privKey->pkcs11Slot,privKey->pkcs11ID);    SECKEY_DestroyPrivateKey(privKey);    return SECSuccess;}/* * delete a cert and it's private key (if no other certs are pointing to the * private key. */SECStatusPK11_DeleteTokenCertAndKey(CERTCertificate *cert,void *wincx){    SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert,wincx);    CK_OBJECT_HANDLE pubKey;    PK11SlotInfo *slot = NULL;    pubKey = pk11_FindPubKeyByAnyCert(cert, &slot, wincx);    if (privKey) {    	PK11_DestroyTokenObject(cert->slot,cert->pkcs11ID);	PK11_DeleteTokenPrivateKey(privKey);    }    if ((pubKey != CK_INVALID_KEY) && (slot != NULL)) {     	PK11_DestroyTokenObject(slot,pubKey);        PK11_FreeSlot(slot);    }    return SECSuccess;}/* * count the number of objects that match the template. */intPK11_NumberObjectsFor(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate, 							int templateCount){    CK_OBJECT_HANDLE objID[PK11_SEARCH_CHUNKSIZE];    int object_count = 0;    CK_ULONG returned_count = 0;    CK_RV crv;    PK11_EnterSlotMonitor(slot);    crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session,					findTemplate, templateCount);    if (crv != CKR_OK) {        PK11_ExitSlotMonitor(slot);	PORT_SetError( PK11_MapError(crv) );	return 0;    }    /*     * collect all the Matching Objects     */    do {    	crv = PK11_GETTAB(slot)->C_FindObjects(slot->session,				objID,PK11_SEARCH_CHUNKSIZE,&returned_count);	if (crv != CKR_OK) {	    PORT_SetError( PK11_MapError(crv) );	    break;    	}	object_count += returned_count;    } while (returned_count == PK11_SEARCH_CHUNKSIZE);    PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);    PK11_ExitSlotMonitor(slot);    return object_count;}/* * cert callback structure */typedef struct pk11DoCertCallbackStr {	SECStatus(* callback)(PK11SlotInfo *slot, CERTCertificate*, void *);	SECStatus(* noslotcallback)(CERTCertificate*, void *);	void *callbackArg;} pk11DoCertCallback;/* * callback to map object handles to certificate structures. */SECStatuspk11_DoCerts(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, void *arg){    CERTCertificate *cert;    pk11DoCertCallback *certcb = (pk11DoCertCallback *) arg;    cert = PK11_MakeCertFromHandle(slot, certID, NULL);    if (cert == NULL) {	return SECFailure;    }    if (certcb ) {	if (certcb->callback) {	    (*certcb->callback)(slot, cert, certcb->callbackArg);	}	if (certcb->noslotcallback) {	    (*certcb->noslotcallback)(cert, certcb->callbackArg);	}    }    CERT_DestroyCertificate(cert);	        return SECSuccess;}/* * key call back structure. */typedef struct pk11KeyCallbackStr {	SECStatus (* callback)(SECKEYPrivateKey *,void *);	void *callbackArg;	void *wincx;} pk11KeyCallback;/* * callback to map Object Handles to Private Keys; */SECStatuspk11_DoKeys(PK11SlotInfo *slot, CK_OBJECT_HANDLE keyHandle, void *arg){    SECStatus rv = SECSuccess;    SECKEYPrivateKey *privKey;    pk11KeyCallback *keycb = (pk11KeyCallback *) arg;    privKey = PK11_MakePrivKey(slot,nullKey,PR_TRUE,keyHandle,keycb->wincx);    if (privKey == NULL) {	return SECFailure;    }    if (keycb && (keycb->callback)) {	rv = (*keycb->callback)(privKey,keycb->callbackArg);    }    SECKEY_DestroyPrivateKey(privKey);	        return rv;}/* Traverse slots callback */typedef struct pk11TraverseSlotStr {    SECStatus (*callback)(PK11SlotInfo *,CK_OBJECT_HANDLE, void *);    void *callbackArg;    CK_ATTRIBUTE *findTemplate;    int templateCount;} pk11TraverseSlotCert;/* * Extract all the certs on a card from a slot. */SECStatusPK11_TraverseSlot(PK11SlotInfo *slot, void *arg){    int i;    CK_OBJECT_HANDLE *objID = NULL;    int object_count = 0;    CK_ULONG returned_count = 0;    pk11TraverseSlotCert *slotcb = (pk11TraverseSlotCert *) arg;    objID = pk11_FindObjectsByTemplate(slot,slotcb->findTemplate,		slotcb->templateCount,&object_count);    /*Actually this isn't a failure... there just were no objs to be found*/    if (object_count == 0) {	return SECSuccess;    }    if (objID == NULL) {	return SECFailure;    }    for (i=0; i < object_count; i++) {	(*slotcb->callback)(slot,objID[i],slotcb->callbackArg);    }    PORT_Free(objID);    return SECSuccess;}typedef struct pk11CertCallbackStr {	SECStatus(* callback)(CERTCertificate*,SECItem *,void *);	void *callbackArg;} pk11CertCallback;static SECStatuspk11_SaveCert(PK11SlotInfo *slot, CERTCertificate *cert, void *arg){    pk11CertCallback *certcb = (pk11CertCallback *)arg;    SECStatus rv = SECSuccess;    if (slot->cert_count == slot->array_size) return CKR_OK;    slot->cert_array[slot->cert_count] = CERT_DupCertificate(cert);    if (slot->cert_array[slot->cert_count] == NULL) {	return SECFailure;    }    /* now the slot has a hold of the cert, free the slot's element in the     * cert.. */    if (cert->ownSlot && (slot == cert->slot)) {        PK11_FreeSlot(cert->slot);	cert->ownSlot = PR_FALSE;    }    slot->cert_count++;    if (certcb->callback) {	rv = (*certcb->callback)(cert, NULL, certcb->callbackArg);    }    return rv;}/* free the slots */voidPK11_FreeSlotCerts(PK11SlotInfo *slot){    int i;    if (slot->cert_array) {	for (i=0; i < slot->cert_count; i++) {	    /* if we point the cert on our array, the cert doesn't have a	     * reference to use (otherwise you would never be able to free	     * a slot :) */	    if ((slot->cert_array[i]->slot == slot) && 					(!slot->cert_array[i]->ownSlot)) {			 slot->cert_array[i]->slot = NULL;	    }	    CERT_DestroyCertificate(slot->cert_array[i]);	}	PORT_Free(slot->cert_array);	slot->cert_array = NULL;	slot->cert_count = 0;    }    return;}/* *  Update PQG parameters for all the certs on a slot. */static SECStatuspk11_UpdateSlotPQG(PK11SlotInfo *slot){    int i, tag;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?