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 + -
显示快捷键?