static int nss_compare_certs(const void *v1, const void *v2) { PRStatus ignore; NSSCertificate *c1 = (NSSCertificate *)v1; NSSCertificate *c2 = (NSSCertificate *)v2; return (int)(nssItem_Equal(&c1->issuer, &c2->issuer, &ignore) && nssItem_Equal(&c1->serial, &c2->serial, &ignore)); }
NSS_IMPLEMENT nssCryptokiObject * nssToken_ImportCertificate ( NSSToken *tok, nssSession *sessionOpt, NSSCertificateType certType, NSSItem *id, const NSSUTF8 *nickname, NSSDER *encoding, NSSDER *issuer, NSSDER *subject, NSSDER *serial, NSSASCII7 *email, PRBool asTokenObject ) { PRStatus status; CK_CERTIFICATE_TYPE cert_type; CK_ATTRIBUTE_PTR attr; CK_ATTRIBUTE cert_tmpl[10]; CK_ULONG ctsize; nssTokenSearchType searchType; nssCryptokiObject *rvObject = NULL; if (!tok) { PORT_SetError(SEC_ERROR_NO_TOKEN); return NULL; } if (certType == NSSCertificateType_PKIX) { cert_type = CKC_X_509; } else { return (nssCryptokiObject *)NULL; } NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); if (asTokenObject) { NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); searchType = nssTokenSearchType_TokenOnly; } else { NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); searchType = nssTokenSearchType_SessionOnly; } NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CERTIFICATE_TYPE, cert_type); NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encoding); NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer); NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial); if (email) { NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NSS_EMAIL, email); } NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); /* see if the cert is already there */ rvObject = nssToken_FindCertificateByIssuerAndSerialNumber(tok, sessionOpt, issuer, serial, searchType, NULL); if (rvObject) { NSSItem existingDER; NSSSlot *slot = nssToken_GetSlot(tok); nssSession *session = nssSlot_CreateSession(slot, NULL, PR_TRUE); if (!session) { nssCryptokiObject_Destroy(rvObject); nssSlot_Destroy(slot); return (nssCryptokiObject *)NULL; } /* Reject any attempt to import a new cert that has the same * issuer/serial as an existing cert, but does not have the * same encoding */ NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE); NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); status = nssCKObject_GetAttributes(rvObject->handle, cert_tmpl, ctsize, NULL, session, slot); NSS_CK_ATTRIBUTE_TO_ITEM(cert_tmpl, &existingDER); if (status == PR_SUCCESS) { if (!nssItem_Equal(encoding, &existingDER, NULL)) { nss_SetError(NSS_ERROR_INVALID_CERTIFICATE); status = PR_FAILURE; } nss_ZFreeIf(existingDER.data); } if (status == PR_FAILURE) { nssCryptokiObject_Destroy(rvObject); nssSession_Destroy(session); nssSlot_Destroy(slot); return (nssCryptokiObject *)NULL; } /* according to PKCS#11, label, ID, issuer, and serial number * may change after the object has been created. For PKIX, the * last two attributes can't change, so for now we'll only worry * about the first two. */ NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); /* reset the mutable attributes on the token */ nssCKObject_SetAttributes(rvObject->handle, cert_tmpl, ctsize, session, slot); if (!rvObject->label && nickname) { rvObject->label = nssUTF8_Duplicate(nickname, NULL); } nssSession_Destroy(session); nssSlot_Destroy(slot); } else { /* Import the certificate onto the token */ rvObject = import_object(tok, sessionOpt, cert_tmpl, ctsize); } if (rvObject && tok->cache) { /* The cache will overwrite the attributes if the object already * exists. */ nssTokenObjectCache_ImportObject(tok->cache, rvObject, CKO_CERTIFICATE, cert_tmpl, ctsize); } return rvObject; }
static int nss_compare_items(const void *v1, const void *v2) { PRStatus ignore; return (int)nssItem_Equal((NSSItem *)v1, (NSSItem *)v2, &ignore); }
CERTCertificate * CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, char *nickname, PRBool isperm, PRBool copyDER) { NSSCertificate *c; CERTCertificate *cc; NSSCertificate *tempCert = NULL; nssPKIObject *pkio; NSSCryptoContext *gCC = STAN_GetDefaultCryptoContext(); NSSTrustDomain *gTD = STAN_GetDefaultTrustDomain(); if (!isperm) { NSSDER encoding; NSSITEM_FROM_SECITEM(&encoding, derCert); /* First, see if it is already a temp cert */ c = NSSCryptoContext_FindCertificateByEncodedCertificate(gCC, &encoding); if (!c) { /* Then, see if it is already a perm cert */ c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, &encoding); } if (c) { /* actually, that search ends up going by issuer/serial, * so it is still possible to return a cert with the same * issuer/serial but a different encoding, and we're * going to reject that */ if (!nssItem_Equal(&c->encoding, &encoding, NULL)) { nssCertificate_Destroy(c); PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); cc = NULL; } else { cc = STAN_GetCERTCertificateOrRelease(c); if (cc == NULL) { CERT_MapStanError(); } } return cc; } } pkio = nssPKIObject_Create(NULL, NULL, gTD, gCC, nssPKIMonitor); if (!pkio) { CERT_MapStanError(); return NULL; } c = nss_ZNEW(pkio->arena, NSSCertificate); if (!c) { CERT_MapStanError(); nssPKIObject_Destroy(pkio); return NULL; } c->object = *pkio; if (copyDER) { nssItem_Create(c->object.arena, &c->encoding, derCert->len, derCert->data); } else { NSSITEM_FROM_SECITEM(&c->encoding, derCert); } /* Forces a decoding of the cert in order to obtain the parts used * below */ /* 'c' is not adopted here, if we fail loser frees what has been * allocated so far for 'c' */ cc = STAN_GetCERTCertificate(c); if (!cc) { CERT_MapStanError(); goto loser; } nssItem_Create(c->object.arena, &c->issuer, cc->derIssuer.len, cc->derIssuer.data); nssItem_Create(c->object.arena, &c->subject, cc->derSubject.len, cc->derSubject.data); if (PR_TRUE) { /* CERTCertificate stores serial numbers decoded. I need the DER * here. sigh. */ SECItem derSerial = { 0 }; CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial); if (!derSerial.data) goto loser; nssItem_Create(c->object.arena, &c->serial, derSerial.len, derSerial.data); PORT_Free(derSerial.data); } if (nickname) { c->object.tempName = nssUTF8_Create(c->object.arena, nssStringType_UTF8String, (NSSUTF8 *)nickname, PORT_Strlen(nickname)); } if (cc->emailAddr && cc->emailAddr[0]) { c->email = nssUTF8_Create( c->object.arena, nssStringType_PrintableString, (NSSUTF8 *)cc->emailAddr, PORT_Strlen(cc->emailAddr)); } tempCert = NSSCryptoContext_FindOrImportCertificate(gCC, c); if (!tempCert) { CERT_MapStanError(); goto loser; } /* destroy our copy */ NSSCertificate_Destroy(c); /* and use the stored entry */ c = tempCert; cc = STAN_GetCERTCertificateOrRelease(c); if (!cc) { /* STAN_GetCERTCertificateOrRelease destroys c on failure. */ CERT_MapStanError(); return NULL; } cc->istemp = PR_TRUE; cc->isperm = PR_FALSE; return cc; loser: /* Perhaps this should be nssCertificate_Destroy(c) */ nssPKIObject_Destroy(&c->object); return NULL; }