diff options
author | ian.mcgreer%sun.com <devnull@localhost> | 2003-02-28 20:18:36 +0000 |
---|---|---|
committer | ian.mcgreer%sun.com <devnull@localhost> | 2003-02-28 20:18:36 +0000 |
commit | 66a2bc68e203a5e56e823fd02578cd586f495e5f (patch) | |
tree | 1a675b06bd160932a52c8b95f2b1425f05dedacb | |
parent | 64950c885de2409fea47c291bba2126330f15a0e (diff) | |
download | nss-hg-66a2bc68e203a5e56e823fd02578cd586f495e5f.tar.gz |
implement pki object table and above-PKCS#11 db
28 files changed, 2310 insertions, 2400 deletions
diff --git a/security/nss/cmd/pkiutil/pkiobject.c b/security/nss/cmd/pkiutil/pkiobject.c index b9e8f3016..b19d60c3f 100644 --- a/security/nss/cmd/pkiutil/pkiobject.c +++ b/security/nss/cmd/pkiutil/pkiobject.c @@ -723,21 +723,18 @@ ImportObject { PRStatus status; PKIObjectType objectKind; - NSSToken *token; - - /* XXX */ - token = tokenOpt ? tokenOpt : nss_GetDefaultDatabaseToken(); objectKind = get_object_class(objectTypeOpt); switch (objectKind) { case PKIAny: /* default to certificate */ case PKICert: - status = import_certificate(td, token, nickname, rtData); + status = import_certificate(td, tokenOpt, nickname, rtData); break; case PKIPublicKey: break; case PKIPrivateKey: - status = import_private_key(td, token, nickname, keyTypeOpt, + tokenOpt = tokenOpt ? tokenOpt : nss_GetDefaultDatabaseToken(); + status = import_private_key(td, tokenOpt, nickname, keyTypeOpt, keypass, rtData); break; case PKIUnknown: diff --git a/security/nss/cmd/selfserv/selfserv.c b/security/nss/cmd/selfserv/selfserv.c index d5034cd0b..34c128168 100644 --- a/security/nss/cmd/selfserv/selfserv.c +++ b/security/nss/cmd/selfserv/selfserv.c @@ -1674,6 +1674,8 @@ main(int argc, char **argv) fprintf(stderr, "selfserv: Can't find certificate %s\n", nickName); exit(10); } + /* XXX */ + NSSTrustDomain_Login(td, NULL); privKey[ssl_kea_rsa] = NSSCert_FindPrivateKey(cert[ssl_kea_rsa], NULL); if (privKey[ssl_kea_rsa] == NULL) { fprintf(stderr, "selfserv: Can't find Private Key for cert %s\n", diff --git a/security/nss/cmd/strsclnt/strsclnt.c b/security/nss/cmd/strsclnt/strsclnt.c index 014dbaafb..29de449db 100644 --- a/security/nss/cmd/strsclnt/strsclnt.c +++ b/security/nss/cmd/strsclnt/strsclnt.c @@ -1067,6 +1067,8 @@ main(int argc, char **argv) exit(1); } + /* XXX */ + NSSTrustDomain_Login(td, NULL); privKey[ssl_kea_rsa] = NSSCert_FindPrivateKey(cert[ssl_kea_rsa], NULL); if (privKey[ssl_kea_rsa] == NULL) { fprintf(stderr, "strsclnt: Can't find Private Key for cert %s\n", diff --git a/security/nss/lib/base/baset.h b/security/nss/lib/base/baset.h index 4fe186c0d..65a6988e9 100644 --- a/security/nss/lib/base/baset.h +++ b/security/nss/lib/base/baset.h @@ -106,25 +106,6 @@ typedef void (PR_CALLBACK *nssHashIterator)(const void *key, void *arg); /* - * nssPointerTracker - * - * This type is used in debug builds (both external and internal) to - * track our object pointers. Objects of this type must be statically - * allocated, which means the structure size must be available to the - * compiler. Therefore we must expose the contents of this structure. - * But please don't access elements directly; use the accessors. - */ - -#ifdef DEBUG -struct nssPointerTrackerStr { - PRCallOnceType once; - PZLock *lock; - PLHashTable *table; -}; -typedef struct nssPointerTrackerStr nssPointerTracker; -#endif /* DEBUG */ - -/* * nssStringType * * There are several types of strings in the real world. We try to diff --git a/security/nss/lib/ckfw/nsprstub.c b/security/nss/lib/ckfw/nsprstub.c index 24ecd507a..110c990d3 100644 --- a/security/nss/lib/ckfw/nsprstub.c +++ b/security/nss/lib/ckfw/nsprstub.c @@ -255,8 +255,6 @@ PR_GetCurrentThread(void) return (PRThread *)1; } - - PR_IMPLEMENT(void) PR_Assert(const char *expr, const char *file, int line) { return; diff --git a/security/nss/lib/dev/algparam.c b/security/nss/lib/dev/algparam.c index 50f9bb583..452f66a01 100644 --- a/security/nss/lib/dev/algparam.c +++ b/security/nss/lib/dev/algparam.c @@ -182,6 +182,7 @@ null_settor ( * Decoding IV parameters */ +/* XXX static PRStatus decode_iv(NSSAlgNParam *ap, const NSSItem *params) { @@ -196,6 +197,7 @@ decode_iv(NSSAlgNParam *ap, const NSSItem *params) } return status; } +*/ /* * RSA key generation @@ -303,6 +305,7 @@ set_dsa_mechanism ( */ /* set template parameters for Diffie-Hellman key generation */ +#if 0 static PRIntn dh_keygen_settor ( const NSSAlgNParam *ap, @@ -325,6 +328,7 @@ dh_keygen_settor ( } return attr - aTemplate; } +#endif /* * Diffie-Hellman key derivation @@ -428,6 +432,7 @@ set_des3_mechanism ( return PR_SUCCESS; } +#if 0 /* * AES */ @@ -464,6 +469,7 @@ set_aes_mechanism ( } return PR_SUCCESS; } +#endif /* * RC2 diff --git a/security/nss/lib/dev/ckhelper.c b/security/nss/lib/dev/ckhelper.c index 6288c2ea5..b14187dbc 100644 --- a/security/nss/lib/dev/ckhelper.c +++ b/security/nss/lib/dev/ckhelper.c @@ -386,8 +386,7 @@ nssCryptokiCert_GetAttributes ( NSSDER *encodingOpt, NSSDER *issuerOpt, NSSDER *serialOpt, - NSSDER *subjectOpt, - NSSASCII7 **emailOpt + NSSDER *subjectOpt ) { PRStatus status; @@ -417,9 +416,6 @@ nssCryptokiCert_GetAttributes ( if (subjectOpt) { NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT); } - if (emailOpt) { - NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_EMAIL); - } NSS_CK_TEMPLATE_FINISH(cert_template, attr, template_size); if (template_size == 0) { /* caller didn't want anything */ @@ -457,9 +453,6 @@ nssCryptokiCert_GetAttributes ( if (subjectOpt) { NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], subjectOpt); i++; } - if (emailOpt) { - NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[i], *emailOpt); i++; - } return PR_SUCCESS; } @@ -624,71 +617,6 @@ nssCryptokiPublicKey_GetAttributes ( return status; } -static nssTrustLevel -get_nss_trust ( - CK_TRUST ckt -) -{ - nssTrustLevel t; - switch (ckt) { - case CKT_NETSCAPE_UNTRUSTED: t = nssTrustLevel_NotTrusted; break; - case CKT_NETSCAPE_TRUSTED_DELEGATOR: t = nssTrustLevel_TrustedDelegator; - break; - case CKT_NETSCAPE_VALID_DELEGATOR: t = nssTrustLevel_ValidDelegator; break; - case CKT_NETSCAPE_TRUSTED: t = nssTrustLevel_Trusted; break; - case CKT_NETSCAPE_VALID: t = nssTrustLevel_Valid; break; - case CKT_NETSCAPE_MUST_VERIFY: - case CKT_NETSCAPE_TRUST_UNKNOWN: - default: - t = nssTrustLevel_Unknown; break; - } - return t; -} - -NSS_IMPLEMENT PRStatus -nssCryptokiTrust_GetAttributes ( - nssCryptokiObject *trustObject, - nssTrustLevel *serverAuth, - nssTrustLevel *clientAuth, - nssTrustLevel *codeSigning, - nssTrustLevel *emailProtection -) -{ - PRStatus status; - NSSSlot *slot; - CK_BBOOL isToken; - CK_TRUST saTrust, caTrust, epTrust, csTrust; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE trust_template[5]; - CK_ULONG trust_size; - - /* Use the trust object to find the trust settings */ - NSS_CK_TEMPLATE_START(trust_template, attr, trust_size); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, saTrust); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, caTrust); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, epTrust); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, csTrust); - NSS_CK_TEMPLATE_FINISH(trust_template, attr, trust_size); - - { - slot = nssToken_GetSlot(trustObject->token); - status = nssCKObject_GetAttributes(trustObject->handle, - trust_template, trust_size, - NULL, trustObject->session, slot); - nssSlot_Destroy(slot); - if (status != PR_SUCCESS) { - return status; - } - } - - *serverAuth = get_nss_trust(saTrust); - *clientAuth = get_nss_trust(caTrust); - *emailProtection = get_nss_trust(epTrust); - *codeSigning = get_nss_trust(csTrust); - return PR_SUCCESS; -} - NSS_IMPLEMENT PRStatus nssCryptokiCRL_GetAttributes ( nssCryptokiObject *crlObject, diff --git a/security/nss/lib/dev/dev.h b/security/nss/lib/dev/dev.h index b4888012b..7580f7718 100644 --- a/security/nss/lib/dev/dev.h +++ b/security/nss/lib/dev/dev.h @@ -302,19 +302,15 @@ nssSlot_CreateSession ( * nssToken_ImportCert * nssToken_FindCerts * - * ------ trust objects -------- - * nssToken_ImportTrust - * nssToken_FindTrustObjects - * nssToken_FindTrustForCert - * * ------ public/private key objects -------- * nssToken_GenerateKeyPair * nssToken_FindPrivateKeys - * nssToken_FindPrivateKeyByID - * nssToken_FindPublicKeyByID + * nssToken_FindPublicKeys * * ------ secret key objects -------- + * nssToken_ImportRawSymKey * nssToken_GenerateSymKey + * nssToken_FindSymKeys * * ------ generic key stuff ------- * nssToken_UnwrapPrivateKey @@ -420,44 +416,10 @@ NSS_EXTERN nssCryptokiObject ** nssToken_FindCerts ( NSSToken *token, nssSession *session, - nssTokenSearchType searchType, PRUint32 maximumOpt, PRStatus *statusOpt ); -NSS_EXTERN nssCryptokiObject * -nssToken_ImportTrust ( - NSSToken *tok, - nssSession *session, - NSSDER *certEncoding, - NSSDER *certIssuer, - NSSDER *certSerial, - nssTrustLevel serverAuth, - nssTrustLevel clientAuth, - nssTrustLevel codeSigning, - nssTrustLevel emailProtection, - PRBool asTokenObject -); - -NSS_EXTERN nssCryptokiObject ** -nssToken_FindTrustObjects ( - NSSToken *token, - nssSession *session, - nssTokenSearchType searchType, - PRUint32 maximumOpt, - PRStatus *statusOpt -); - -NSS_EXTERN nssCryptokiObject * -nssToken_FindTrustForCert ( - NSSToken *token, - nssSession *session, - NSSDER *certEncoding, - NSSDER *certIssuer, - NSSDER *certSerial, - nssTokenSearchType searchType -); - NSS_EXTERN PRStatus nssToken_GenerateKeyPair ( NSSToken *tok, @@ -480,26 +442,19 @@ nssToken_ImportPublicKey ( ); NSS_EXTERN nssCryptokiObject ** -nssToken_FindPrivateKeys ( +nssToken_FindPublicKeys ( NSSToken *token, nssSession *session, - nssTokenSearchType searchType, PRUint32 maximumOpt, PRStatus *statusOpt ); -NSS_EXTERN nssCryptokiObject * -nssToken_FindPrivateKeyByID ( - NSSToken *token, - nssSession *session, - NSSItem *keyID -); - -NSS_EXTERN nssCryptokiObject * -nssToken_FindPublicKeyByID ( +NSS_EXTERN nssCryptokiObject ** +nssToken_FindPrivateKeys ( NSSToken *token, nssSession *session, - NSSItem *keyID + PRUint32 maximumOpt, + PRStatus *statusOpt ); NSS_EXTERN nssCryptokiObject * @@ -514,6 +469,14 @@ nssToken_GenerateSymKey ( NSSProperties properties ); +NSS_EXTERN nssCryptokiObject ** +nssToken_FindSymKeys ( + NSSToken *token, + nssSession *session, + PRUint32 maximumOpt, + PRStatus *statusOpt +); + NSS_EXTERN nssCryptokiObject * nssToken_ImportRawSymKey ( NSSToken *token, @@ -934,7 +897,6 @@ nssSession_Clone ( * nssCryptokiCert_GetAttributes * nssCryptokiPrivateKey_GetAttributes * nssCryptokiPublicKey_GetAttributes - * nssCryptokiTrust_GetAttributes * nssCryptokiCRL_GetAttributes * nssCryptokiSymKey_GetAttributes */ @@ -989,8 +951,7 @@ nssCryptokiCert_GetAttributes ( NSSDER *encodingOpt, NSSDER *issuerOpt, NSSDER *serialOpt, - NSSDER *subjectOpt, - NSSASCII7 **emailOpt + NSSDER *subjectOpt ); NSS_EXTERN PRStatus @@ -1010,15 +971,6 @@ nssCryptokiPublicKey_GetAttributes ( ); NSS_EXTERN PRStatus -nssCryptokiTrust_GetAttributes ( - nssCryptokiObject *trustObject, - nssTrustLevel *serverAuth, - nssTrustLevel *clientAuth, - nssTrustLevel *codeSigning, - nssTrustLevel *emailProtection -); - -NSS_EXTERN PRStatus nssCryptokiCRL_GetAttributes ( nssCryptokiObject *crlObject, NSSArena *arenaOpt, @@ -1215,15 +1167,6 @@ nssSlotList_GetBestTokenForAlgorithm ( NSSOIDTag alg ); -NSS_EXTERN PRStatus -nssToken_TraverseCerts ( - NSSToken *token, - nssSession *session, - nssTokenSearchType searchType, - PRStatus (* callback)(nssCryptokiObject *instance, void *arg), - void *arg -); - PR_END_EXTERN_C #endif /* DEV_H */ diff --git a/security/nss/lib/dev/devt.h b/security/nss/lib/dev/devt.h index b8d23c574..73f27fde7 100644 --- a/security/nss/lib/dev/devt.h +++ b/security/nss/lib/dev/devt.h @@ -81,22 +81,6 @@ typedef struct nssSessionStr nssSession; typedef struct nssSlotListStr nssSlotList; -typedef enum { - nssTrustLevel_Unknown = 0, - nssTrustLevel_NotTrusted = 1, - nssTrustLevel_Trusted = 2, - nssTrustLevel_TrustedDelegator = 3, - nssTrustLevel_Valid = 4, - nssTrustLevel_ValidDelegator = 5 -} nssTrustLevel; - -typedef enum { - nssTokenSearchType_AllObjects = 0, - nssTokenSearchType_SessionOnly = 1, - nssTokenSearchType_TokenOnly = 2, - nssTokenSearchType_PrivateTokenOnly = 3 -} nssTokenSearchType; - struct nssCryptokiObjectStr { CK_OBJECT_HANDLE handle; diff --git a/security/nss/lib/dev/devtoken.c b/security/nss/lib/dev/devtoken.c index 9bc13519b..0ac665195 100644 --- a/security/nss/lib/dev/devtoken.c +++ b/security/nss/lib/dev/devtoken.c @@ -47,6 +47,10 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "ckhelper.h" #endif /* CKHELPER_H */ +#ifndef PKI1_H +#include "pki1.h" +#endif /* PKI1_H */ + /* The number of object handles to grab during each call to C_FindObjects */ #define OBJECT_STACK_SIZE 16 @@ -550,7 +554,6 @@ nssToken_ImportCert ( CK_ATTRIBUTE_PTR attr; CK_ATTRIBUTE cert_tmpl[10]; CK_ULONG ctsize; - nssTokenSearchType searchType; nssCryptokiObject *rvObject = NULL, **objs; if (certType == NSSCertType_PKIX) { @@ -561,10 +564,8 @@ nssToken_ImportCert ( 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; } /* required attributes */ NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); @@ -625,7 +626,6 @@ NSS_IMPLEMENT nssCryptokiObject ** nssToken_FindCerts ( NSSToken *token, nssSession *session, - nssTokenSearchType searchType, PRUint32 maximumOpt, PRStatus *statusOpt ) @@ -635,12 +635,7 @@ nssToken_FindCerts ( CK_ULONG ctsize; NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); - /* Set the search to token/session only if provided */ - if (searchType == nssTokenSearchType_SessionOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } else if (searchType == nssTokenSearchType_TokenOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); @@ -702,10 +697,9 @@ nssToken_ImportPublicKey ( } NSS_IMPLEMENT nssCryptokiObject ** -nssToken_FindPrivateKeys ( +nssToken_FindPublicKeys ( NSSToken *token, nssSession *session, - nssTokenSearchType searchType, PRUint32 maximumOpt, PRStatus *statusOpt ) @@ -716,12 +710,8 @@ nssToken_FindPrivateKeys ( nssCryptokiObject **objects; NSS_CK_TEMPLATE_START(key_template, attr, ktsize); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey); - if (searchType == nssTokenSearchType_SessionOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } else if (searchType == nssTokenSearchType_TokenOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_pubkey); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); objects = find_objects_by_template(token, session, @@ -730,216 +720,30 @@ nssToken_FindPrivateKeys ( return objects; } -/* XXX ?there are no session cert objects, so only search token objects */ -NSS_IMPLEMENT nssCryptokiObject * -nssToken_FindPrivateKeyByID ( +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindPrivateKeys ( NSSToken *token, nssSession *session, - NSSItem *keyID + PRUint32 maximumOpt, + PRStatus *statusOpt ) { CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE key_template[3]; + CK_ATTRIBUTE key_template[2]; CK_ULONG ktsize; nssCryptokiObject **objects; - nssCryptokiObject *rvKey = NULL; NSS_CK_TEMPLATE_START(key_template, attr, ktsize); NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey); NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID); NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); objects = find_objects_by_template(token, session, key_template, ktsize, - 1, NULL); - if (objects) { - rvKey = objects[0]; - nss_ZFreeIf(objects); - } - return rvKey; -} - -/* XXX ?there are no session cert objects, so only search token objects */ -NSS_IMPLEMENT nssCryptokiObject * -nssToken_FindPublicKeyByID ( - NSSToken *token, - nssSession *session, - NSSItem *keyID -) -{ - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE key_template[3]; - CK_ULONG ktsize; - nssCryptokiObject **objects; - nssCryptokiObject *rvKey = NULL; - - NSS_CK_TEMPLATE_START(key_template, attr, ktsize); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_pubkey); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID); - NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); - - objects = find_objects_by_template(token, session, - key_template, ktsize, - 1, NULL); - if (objects) { - rvKey = objects[0]; -#ifndef SOFTOKEN_RETURNS_PUBKEY_BUG - { - /* XXX the softoken will return a valid key handle when it - * only has the cert, not the pubkey - */ - PRStatus status; - NSSPublicKeyInfo keyInfo; - NSSArena *tmparena = nssArena_Create(); - if (tmparena) { - status = nssCryptokiPublicKey_GetAttributes(rvKey, tmparena, - &keyInfo, NULL); - nssArena_Destroy(tmparena); - } else { - status = PR_FAILURE; - } - if (status == PR_FAILURE) { - nssCryptokiObject_Destroy(rvKey); - rvKey = NULL; - } - } -#endif /* SOFTOKEN_RETURNS_PUBKEY_BUG */ - nss_ZFreeIf(objects); - } - return rvKey; -} - -static CK_TRUST -get_ck_trust ( - nssTrustLevel nssTrust -) -{ - CK_TRUST t; - switch (nssTrust) { - case nssTrustLevel_Unknown: t = CKT_NETSCAPE_TRUST_UNKNOWN; break; - case nssTrustLevel_NotTrusted: t = CKT_NETSCAPE_UNTRUSTED; break; - case nssTrustLevel_TrustedDelegator: t = CKT_NETSCAPE_TRUSTED_DELEGATOR; - break; - case nssTrustLevel_ValidDelegator: t = CKT_NETSCAPE_VALID_DELEGATOR; break; - case nssTrustLevel_Trusted: t = CKT_NETSCAPE_TRUSTED; break; - case nssTrustLevel_Valid: t = CKT_NETSCAPE_VALID; break; - } - return t; -} - -NSS_IMPLEMENT nssCryptokiObject * -nssToken_ImportTrust ( - NSSToken *tok, - nssSession *session, - NSSDER *certEncoding, - NSSDER *certIssuer, - NSSDER *certSerial, - nssTrustLevel serverAuth, - nssTrustLevel clientAuth, - nssTrustLevel codeSigning, - nssTrustLevel emailProtection, - PRBool asTokenObject -) -{ - nssCryptokiObject *object; - CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST; - CK_TRUST ckSA, ckCA, ckCS, ckEP; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE trust_tmpl[10]; - CK_ULONG tsize; - ckSA = get_ck_trust(serverAuth); - ckCA = get_ck_trust(clientAuth); - ckCS = get_ck_trust(codeSigning); - ckEP = get_ck_trust(emailProtection); - NSS_CK_TEMPLATE_START(trust_tmpl, attr, tsize); - if (asTokenObject) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } else { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } - NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, certSerial); - /* now set the trust values */ - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, ckSA); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, ckCA); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, ckCS); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, ckEP); - NSS_CK_TEMPLATE_FINISH(trust_tmpl, attr, tsize); - /* import the trust object onto the token */ - object = import_object(tok, session, trust_tmpl, tsize); - return object; -} - -NSS_IMPLEMENT nssCryptokiObject ** -nssToken_FindTrustObjects ( - NSSToken *token, - nssSession *session, - nssTokenSearchType searchType, - PRUint32 maximumOpt, - PRStatus *statusOpt -) -{ - CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE tobj_template[2]; - CK_ULONG tobj_size; - nssCryptokiObject **objects; - - NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size); - if (searchType == nssTokenSearchType_SessionOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } else if (searchType == nssTokenSearchType_TokenOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } - NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); - NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size); - - objects = find_objects_by_template(token, session, - tobj_template, tobj_size, maximumOpt, statusOpt); return objects; } -NSS_IMPLEMENT nssCryptokiObject * -nssToken_FindTrustForCert ( - NSSToken *token, - nssSession *session, - NSSDER *certEncoding, - NSSDER *certIssuer, - NSSDER *certSerial, - nssTokenSearchType searchType -) -{ - CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE tobj_template[5]; - CK_ULONG tobj_size; - nssCryptokiObject *object, **objects; - - NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size); - if (searchType == nssTokenSearchType_SessionOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } else if (searchType == nssTokenSearchType_TokenOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } - NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER , certSerial); - NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size); - object = NULL; - objects = find_objects_by_template(token, session, - tobj_template, tobj_size, - 1, NULL); - if (objects) { - object = objects[0]; - nss_ZFreeIf(objects); - } - return object; -} - NSS_IMPLEMENT PRStatus nssToken_SeedRandom ( NSSToken *token, @@ -1680,7 +1484,6 @@ nssToken_ContinueEncrypt ( ) { CK_RV ckrv; - CK_ULONG bufLen; PRBool freeit = PR_FALSE; void *epv = nssToken_GetCryptokiEPV(token); @@ -1850,7 +1653,6 @@ nssToken_ContinueDecrypt ( ) { CK_RV ckrv; - CK_ULONG bufLen; PRBool freeit = PR_FALSE; void *epv = nssToken_GetCryptokiEPV(token); diff --git a/security/nss/lib/nss/config.mk b/security/nss/lib/nss/config.mk index 771e5398a..2aabcf2c3 100644 --- a/security/nss/lib/nss/config.mk +++ b/security/nss/lib/nss/config.mk @@ -38,6 +38,10 @@ # are specifed as dependencies within rules.mk. # +EXTRA_LIBS += \ + $(DIST)/lib/$(LIB_PREFIX)dbm.$(LIB_SUFFIX) \ + $(NULL) + # can't do this in manifest.mn because OS_TARGET isn't defined there. ifeq (,$(filter-out WIN%,$(OS_TARGET))) diff --git a/security/nss/lib/nss/nssinit.c b/security/nss/lib/nss/nssinit.c index 22f6071ac..aa2ad46ae 100644 --- a/security/nss/lib/nss/nssinit.c +++ b/security/nss/lib/nss/nssinit.c @@ -455,7 +455,7 @@ loser: } } - g_default_trust_domain = NSSTrustDomain_Create(NULL, NULL, NULL, NULL); + g_default_trust_domain = nssTrustDomain_Create(configdir, NULL, NULL, NULL); modules = nss_GetLoadedModules(); if (!modules) { @@ -463,7 +463,7 @@ loser: } for (mp = modules; *mp; mp++) { - nssrv = NSSTrustDomain_AddModule(g_default_trust_domain, *mp); + nssrv = nssTrustDomain_AddModule(g_default_trust_domain, *mp); } nssModuleArray_Destroy(modules); @@ -554,7 +554,7 @@ NSS_Shutdown(void) PRStatus rv = PR_SUCCESS; nss_DumpModuleLog(); nss_FreeOIDTable(); - NSSTrustDomain_Destroy(g_default_trust_domain); + nssTrustDomain_Destroy(g_default_trust_domain); nss_DestroyGlobalModuleList(); nss_IsInitted = PR_FALSE; return rv; diff --git a/security/nss/lib/pki/asymmkey.c b/security/nss/lib/pki/asymmkey.c index b5ced552e..04a8c67c0 100644 --- a/security/nss/lib/pki/asymmkey.c +++ b/security/nss/lib/pki/asymmkey.c @@ -81,31 +81,6 @@ struct NSSPrivateKeyStr }; NSS_IMPLEMENT NSSPrivateKey * -nssPrivateKey_Create ( - nssPKIObject *object -) -{ - PRStatus status; - NSSPrivateKey *rvKey; - NSSArena *arena = object->arena; - PR_ASSERT(object->instances != NULL && object->numInstances > 0); - rvKey = nss_ZNEW(arena, NSSPrivateKey); - if (!rvKey) { - return (NSSPrivateKey *)NULL; - } - rvKey->object = *object; - /* XXX should choose instance based on some criteria */ - status = nssCryptokiPrivateKey_GetAttributes(object->instances[0], - arena, - &rvKey->kind, - &rvKey->id); - if (status != PR_SUCCESS) { - return (NSSPrivateKey *)NULL; - } - return rvKey; -} - -NSS_IMPLEMENT NSSPrivateKey * nssPrivateKey_CreateFromInstance ( nssCryptokiObject *instance, NSSTrustDomain *td, @@ -115,12 +90,29 @@ nssPrivateKey_CreateFromInstance ( PRStatus status; nssPKIObject *pkio; NSSPrivateKey *rvKey = NULL; + nssPKIObjectTable *objectTable = nssTrustDomain_GetObjectTable(td); - pkio = nssPKIObject_Create(NULL, instance, td, vdOpt); - if (!pkio) { - return (NSSPrivateKey *)NULL; + rvKey = nssPKIObject_CREATE(td, instance, NSSPrivateKey); + if (!rvKey) { + goto loser; + } + pkio = &rvKey->object; + status = nssCryptokiPrivateKey_GetAttributes(instance, pkio->arena, + &rvKey->kind, + &rvKey->id); + if (status != PR_SUCCESS) { + goto loser; + } + pkio->objectType = pkiObjectType_PrivateKey; + pkio->numIDs = 1; + pkio->uid[0] = &rvKey->id; + rvKey = (NSSPrivateKey *)nssPKIObjectTable_Add(objectTable, pkio); + if (!rvKey) { + rvKey = (NSSPrivateKey *)pkio; + goto loser; + } else if ((nssPKIObject *)rvKey != pkio) { + nssPrivateKey_Destroy((NSSPrivateKey *)pkio); } - rvKey = nssPrivateKey_Create(pkio); if (rvKey && vdOpt) { status = nssVolatileDomain_ImportPrivateKey(vdOpt, rvKey); if (status == PR_FAILURE) { @@ -129,6 +121,9 @@ nssPrivateKey_CreateFromInstance ( } } return rvKey; +loser: + nssPrivateKey_Destroy(rvKey); + return (NSSPrivateKey *)NULL; } NSS_IMPLEMENT NSSPrivateKey * @@ -188,12 +183,12 @@ nssPrivateKey_GetNickname ( } NSS_IMPLEMENT PRBool -nssPrivateKey_IsOnToken ( +nssPrivateKey_HasInstanceOnToken ( NSSPrivateKey *vk, NSSToken *token ) { - return nssPKIObject_IsOnToken(&vk->object, token); + return nssPKIObject_HasInstanceOnToken(&vk->object, token); } NSS_IMPLEMENT nssCryptokiObject * @@ -214,6 +209,23 @@ nssPrivateKey_FindInstanceForAlgorithm ( return nssPKIObject_FindInstanceForAlgorithm(&vk->object, ap); } +NSS_IMPLEMENT PRStatus +nssPrivateKey_RemoveInstanceForToken ( + NSSPrivateKey *vk, + NSSToken *token +) +{ + return nssPKIObject_RemoveInstanceForToken(&vk->object, token); +} + +NSS_IMPLEMENT PRIntn +nssPrivateKey_CountInstances ( + NSSPrivateKey *vk +) +{ + return nssPKIObject_CountInstances(&vk->object); +} + NSS_IMPLEMENT void nssPrivateKey_SetVolatileDomain ( NSSPrivateKey *vk, @@ -427,6 +439,7 @@ NSSPrivateKey_Encode ( rvOpt, arenaOpt); } +#if 0 /* XXX move to a lower layer to avoid extra translation? */ /* or keep data with oid? */ static NSSKeyPairType @@ -449,6 +462,7 @@ get_key_pair_type(NSSOID *kpAlg) return NSSKeyPairType_Unknown; } } +#endif NSS_IMPLEMENT NSSPrivateKey * nssPrivateKey_Decode ( @@ -642,7 +656,7 @@ nssPrivateKey_Decrypt ( NSSItem *rvIt = NULL; if (apOpt) { - ap = apOpt; + ap = (NSSAlgNParam *)apOpt; } else { NSSOIDTag alg; /* XXX are these defaults reasonable? */ @@ -823,56 +837,8 @@ nssPrivateKey_FindPublicKey ( NSSPrivateKey *vk ) { - PRStatus status; - NSSItem *id; - NSSPublicKey *rvPubKey = NULL; - nssPKIObjectCollection *collection = NULL; - id = nssPrivateKey_GetID(vk); - if (id) { - /* XXX - * This would ostensibly search the trust domain. However, that - * means searching every active token for the key, when it is - * almost assuredly only on the token with the private key. Even - * if not, the token that has the pair is the most desirable. - * In general, this is another place where multiple instances - * can be confusing/non-optimal, so needs to be handled correctly. - * For now, restricting the search to the private key's tokens. - */ - NSSToken **tokens, **tp; - nssCryptokiObject *instance; - NSSTrustDomain *td = nssPrivateKey_GetTrustDomain(vk, NULL); - tokens = nssPKIObject_GetTokens(&vk->object, NULL, 0, &status); - if (!tokens) { - return (NSSPublicKey *)NULL; /* defer to trust domain ??? */ - } - for (tp = tokens; *tp; tp++) { - /* XXX think of something better */ - nssCryptokiObject *vko; - vko = nssPKIObject_GetInstance(&vk->object, *tp); - if (!vko) { - continue; - } - instance = nssToken_FindPublicKeyByID(*tp, vko->session, id); - nssCryptokiObject_Destroy(vko); - if (instance) { - if (!collection) { - collection = nssPublicKeyCollection_Create(td, NULL); - if (!collection) { - nssCryptokiObject_Destroy(instance); - return (NSSPublicKey *)NULL; - } - } - status = nssPKIObjectCollection_AddInstances(collection, - &instance, 1); - } - } - } - if (collection) { - (void)nssPKIObjectCollection_GetPublicKeys(collection, - &rvPubKey, 1, NULL); - nssPKIObjectCollection_Destroy(collection); - } - return rvPubKey; + NSSTrustDomain *td = nssPrivateKey_GetTrustDomain(vk, NULL); + return nssTrustDomain_FindPublicKeyByID(td, &vk->id); } NSS_IMPLEMENT NSSPublicKey * @@ -955,48 +921,38 @@ struct NSSPublicKeyStr }; NSS_IMPLEMENT NSSPublicKey * -nssPublicKey_Create ( - nssPKIObject *object -) -{ - PRStatus status; - NSSPublicKey *rvKey; - NSSArena *arena = object->arena; - PR_ASSERT(object->instances != NULL && object->numInstances > 0); - rvKey = nss_ZNEW(arena, NSSPublicKey); - if (!rvKey) { - return (NSSPublicKey *)NULL; - } - rvKey->object = *object; - /* XXX should choose instance based on some criteria */ - status = nssCryptokiPublicKey_GetAttributes(object->instances[0], - arena, - &rvKey->info, - &rvKey->id); - if (status != PR_SUCCESS) { - nssPublicKey_Destroy(rvKey); - return (NSSPublicKey *)NULL; - } - return rvKey; -} - -NSS_IMPLEMENT NSSPublicKey * nssPublicKey_CreateFromInstance ( nssCryptokiObject *instance, NSSTrustDomain *td, - NSSVolatileDomain *vdOpt, - NSSArena *arenaOpt + NSSVolatileDomain *vdOpt ) { PRStatus status; nssPKIObject *pkio; NSSPublicKey *rvKey = NULL; + nssPKIObjectTable *objectTable = nssTrustDomain_GetObjectTable(td); - pkio = nssPKIObject_Create(arenaOpt, instance, td, vdOpt); - if (!pkio) { - return (NSSPublicKey *)NULL; + rvKey = nssPKIObject_CREATE(td, instance, NSSPublicKey); + if (!rvKey) { + goto loser; + } + pkio = &rvKey->object; + status = nssCryptokiPublicKey_GetAttributes(instance, pkio->arena, + &rvKey->info, + &rvKey->id); + if (status != PR_SUCCESS) { + goto loser; + } + pkio->objectType = pkiObjectType_PublicKey; + pkio->numIDs = 1; + pkio->uid[0] = &rvKey->id; + rvKey = (NSSPublicKey *)nssPKIObjectTable_Add(objectTable, pkio); + if (!rvKey) { + rvKey = (NSSPublicKey *)pkio; + goto loser; + } else if ((nssPKIObject *)rvKey != pkio) { + nssPublicKey_Destroy((NSSPublicKey *)pkio); } - rvKey = nssPublicKey_Create(pkio); if (rvKey && vdOpt) { status = nssVolatileDomain_ImportPublicKey(vdOpt, rvKey); if (status == PR_FAILURE) { @@ -1005,6 +961,9 @@ nssPublicKey_CreateFromInstance ( } } return rvKey; +loser: + nssPublicKey_Destroy(rvKey); + return (NSSPublicKey *)NULL; } /* XXX same here */ @@ -1068,12 +1027,13 @@ nssPublicKey_CreateFromInfo ( bko = nssToken_ImportPublicKey(token, session, &bki, PR_FALSE); if (bko) { - rvbk = nssPublicKey_CreateFromInstance(bko, td, vd, arena); + rvbk = nssPublicKey_CreateFromInstance(bko, td, vd); if (!rvbk) { nssCryptokiObject_Destroy(bko); } } + /* XXX leak arena */ nssSession_Destroy(session); nssToken_Destroy(token); return rvbk; @@ -1139,12 +1099,12 @@ nssPublicKey_GetID ( } NSS_IMPLEMENT PRBool -nssPublicKey_IsOnToken ( +nssPublicKey_HasInstanceOnToken ( NSSPublicKey *bk, NSSToken *token ) { - return nssPKIObject_IsOnToken(&bk->object, token); + return nssPKIObject_HasInstanceOnToken(&bk->object, token); } NSS_IMPLEMENT nssCryptokiObject * @@ -1165,6 +1125,23 @@ nssPublicKey_FindInstanceForAlgorithm ( return nssPKIObject_FindInstanceForAlgorithm(&bk->object, ap); } +NSS_IMPLEMENT PRStatus +nssPublicKey_RemoveInstanceForToken ( + NSSPublicKey *bk, + NSSToken *token +) +{ + return nssPKIObject_RemoveInstanceForToken(&bk->object, token); +} + +NSS_IMPLEMENT PRIntn +nssPublicKey_CountInstances ( + NSSPublicKey *bk +) +{ + return nssPKIObject_CountInstances(&bk->object); +} + NSS_IMPLEMENT void nssPublicKey_SetVolatileDomain ( NSSPublicKey *bk, @@ -1587,7 +1564,7 @@ nssPublicKey_FindCerts ( { NSSTrustDomain *td = nssPublicKey_GetTrustDomain(bk, NULL); return nssTrustDomain_FindCertsByID(td, &bk->id, - rvOpt, maximumOpt, arenaOpt); + rvOpt, maximumOpt, arenaOpt); } NSS_IMPLEMENT NSSCert ** diff --git a/security/nss/lib/pki/cert.c b/security/nss/lib/pki/cert.c index ce6fae498..f965b2f9b 100644 --- a/security/nss/lib/pki/cert.c +++ b/security/nss/lib/pki/cert.c @@ -73,6 +73,7 @@ struct NSSCertStr NSSDER serial; NSSASCII7 *email; NSSPublicKey *bk; /* for ephemeral decoded pubkeys */ + nssTrust trust; nssCertDecoding decoding; }; @@ -82,106 +83,91 @@ nss_GetMethodsForType ( NSSCertType certType ); -/* Creates a certificate from a base object */ NSS_IMPLEMENT NSSCert * -nssCert_Create ( - nssPKIObject *object +nssCert_CreateFromInstance ( + nssCryptokiObject *instance, + NSSTrustDomain *td, + NSSVolatileDomain *vdOpt ) { PRStatus status; - NSSCert *rvCert; - /* mark? */ - NSSArena *arena = object->arena; - PR_ASSERT(object->instances != NULL && object->numInstances > 0); - rvCert = nss_ZNEW(arena, NSSCert); + nssPKIObject *pkio; + NSSCert *rvCert = NULL; + nssPKIObjectTable *objectTable = nssTrustDomain_GetObjectTable(td); + + rvCert = nssPKIObject_CREATE(td, instance, NSSCert); if (!rvCert) { return (NSSCert *)NULL; } - rvCert->object = *object; - /* XXX should choose instance based on some criteria */ - status = nssCryptokiCert_GetAttributes(object->instances[0], - arena, + pkio = &rvCert->object; + status = nssCryptokiCert_GetAttributes(instance, pkio->arena, &rvCert->kind, &rvCert->id, &rvCert->encoding, &rvCert->issuer, &rvCert->serial, - &rvCert->subject, - &rvCert->email); + &rvCert->subject); if (status != PR_SUCCESS) { - return (NSSCert *)NULL; + goto loser; } - /* all certs need an encoding value */ - if (rvCert->encoding.data == NULL) { - return (NSSCert *)NULL; + pkio->objectType = pkiObjectType_Cert; + pkio->numIDs = 2; + pkio->uid[0] = &rvCert->issuer; + pkio->uid[1] = &rvCert->serial; + rvCert = (NSSCert *)nssPKIObjectTable_Add(objectTable, pkio); + if (!rvCert) { + rvCert = (NSSCert *)pkio; + goto loser; + } else if ((nssPKIObject *)rvCert != pkio) { + nssCert_Destroy((NSSCert *)pkio); } rvCert->decoding.methods = nss_GetMethodsForType(rvCert->kind); if (!rvCert->decoding.methods) { - return (NSSCert *)NULL; - } - return rvCert; -} - -NSS_IMPLEMENT NSSCert * -nssCert_CreateFromInstance ( - nssCryptokiObject *instance, - NSSTrustDomain *td, - NSSVolatileDomain *vdOpt, - NSSArena *arenaOpt -) -{ - PRStatus status; - nssPKIObject *pkio; - NSSCert *rvCert = NULL; - - pkio = nssPKIObject_Create(arenaOpt, instance, td, vdOpt); - if (!pkio) { - return (NSSCert *)NULL; + goto loser; } - rvCert = nssCert_Create(pkio); if (rvCert && vdOpt) { status = nssVolatileDomain_ImportCert(vdOpt, rvCert); if (status == PR_FAILURE) { - nssCert_Destroy(rvCert); - rvCert = NULL; + goto loser; } } + /* token certs trusted by default */ + rvCert->trust.trustedUsages.ca = rvCert->trust.trustedUsages.peer = ~0; + /* XXX or check trust here by looking at db? */ return rvCert; +loser: + nssCert_Destroy(rvCert); + return (NSSCert *)NULL; } NSS_IMPLEMENT NSSCert * nssCert_Decode ( - NSSBER *ber + NSSBER *ber, + NSSItem *nicknameOpt, + nssTrust *trustOpt, + NSSTrustDomain *td, + NSSVolatileDomain *vdOpt ) { - NSSArena *arena; + nssPKIObject *pkio; NSSCert *rvCert; NSSCertMethods *decoder; void *decoding; NSSItem *it; + nssPKIObjectTable *objectTable = nssTrustDomain_GetObjectTable(td); - /* create the PKIObject */ - arena = nssArena_Create(); - if (!arena) { - return (NSSCert *)NULL; - } - rvCert = nss_ZNEW(arena, NSSCert); + rvCert = nssPKIObject_CREATE(td, NULL, NSSCert); if (!rvCert) { - goto loser; - } - rvCert->object.arena = arena; - rvCert->object.refCount = 1; - rvCert->object.lock = PZ_NewLock(nssILockOther); - if (!rvCert->object.lock) { - goto loser; + return (NSSCert *)NULL; } + pkio = &rvCert->object; /* try to decode it */ decoder = nss_GetMethodsForType(NSSCertType_PKIX); if (!decoder) { /* nss_SetError(UNKNOWN_CERT_TYPE); */ goto loser; } - decoding = decoder->decode(arena, ber); + decoding = decoder->decode(pkio->arena, ber); if (decoding) { /* it's a PKIX cert */ rvCert->decoding.methods = decoder; @@ -191,7 +177,7 @@ nssCert_Decode ( goto loser; } /* copy the BER encoding */ - it = nssItem_Duplicate(ber, arena, &rvCert->encoding); + it = nssItem_Duplicate(ber, pkio->arena, &rvCert->encoding); if (!it) { goto loser; } @@ -215,9 +201,28 @@ nssCert_Decode ( rvCert->subject = *it; /* obtain the email address from the decoding */ rvCert->email = decoder->getEmailAddress(decoding); + /* set the nickname to the supplied one */ + if (nicknameOpt) { + pkio->nickname = nssUTF8_Create(pkio->arena, nssStringType_UTF8String, + nicknameOpt->data, nicknameOpt->size); + } + if (trustOpt) { + rvCert->trust = *trustOpt; + } + pkio->objectType = pkiObjectType_Cert; + pkio->numIDs = 2; + pkio->uid[0] = &rvCert->issuer; + pkio->uid[1] = &rvCert->serial; + rvCert = (NSSCert *)nssPKIObjectTable_Add(objectTable, pkio); + if (!rvCert) { + rvCert = (NSSCert *)pkio; + goto loser; + } else if ((nssPKIObject *)rvCert != pkio) { + nssCert_Destroy((NSSCert *)pkio); + } return rvCert; loser: - nssArena_Destroy(arena); + nssCert_Destroy(rvCert); return (NSSCert *)NULL; } @@ -809,47 +814,6 @@ nssCert_CopyToToken ( return PR_SUCCESS; } -static NSSUsage -get_trusted_usage ( - NSSCert *c, - PRBool asCA, - PRStatus *status -) -{ - nssTrust *trust; - nssTrustLevel checkLevel; - NSSUsage usage = 0; - - *status = PR_SUCCESS; - checkLevel = asCA ? nssTrustLevel_TrustedDelegator : - nssTrustLevel_Trusted; - /* XXX needs to be cached with cert */ - trust = nssTrustDomain_FindTrustForCert(c->object.td, c); - if (!trust) { - if (NSS_GetError() == NSS_ERROR_NO_ERROR) { - *status = PR_SUCCESS; - } else { - *status = PR_FAILURE; - } - return 0; - } - if (trust->clientAuth == checkLevel) { - usage |= NSSUsage_SSLClient; - } - if (trust->serverAuth == checkLevel) { - usage |= NSSUsage_SSLServer; - } - if (trust->emailProtection == checkLevel) { - usage |= NSSUsage_EmailSigner | NSSUsage_EmailRecipient; - } - if (trust->codeSigning == checkLevel) { - usage |= NSSUsage_CodeSigner; - } - nssTrust_Destroy(trust); - /* XXX should check user cert */ - return usage; -} - static PRStatus validate_and_discover_trust ( NSSCert *c, @@ -861,7 +825,6 @@ validate_and_discover_trust ( ) { PRStatus status; - NSSUsage trustedUsage; NSSUsages *certUsages; PRBool valid; @@ -877,8 +840,9 @@ validate_and_discover_trust ( } /* See if the cert is trusted, overrides cert's usage */ - trustedUsage = get_trusted_usage(c, asCA, &status); - if (trustedUsage && (trustedUsage & usage) == usage) { + if ((asCA && c->trust.trustedUsages.ca & usage) || + c->trust.trustedUsages.peer & usage) + { *trusted = PR_TRUE; return PR_SUCCESS; } @@ -1108,7 +1072,6 @@ nssCert_GetTrustedUsages ( NSSUsages *usagesOpt ) { - PRStatus status; PRBool freeIt = PR_FALSE; if (!usagesOpt) { usagesOpt = nss_ZNEW(NULL, NSSUsages); @@ -1117,16 +1080,7 @@ nssCert_GetTrustedUsages ( } freeIt = PR_TRUE; } - usagesOpt->ca = get_trusted_usage(c, PR_TRUE, &status); - if (status == PR_FAILURE) { - if (freeIt) nss_ZFreeIf(usagesOpt); - return (NSSUsages *)NULL; - } - usagesOpt->peer = get_trusted_usage(c, PR_FALSE, &status); - if (status == PR_FAILURE) { - if (freeIt) nss_ZFreeIf(usagesOpt); - return (NSSUsages *)NULL; - } + *usagesOpt = c->trust.trustedUsages; return usagesOpt; } @@ -1146,76 +1100,13 @@ nssCert_IsTrustedForUsages ( PRStatus *statusOpt ) { - NSSUsages certUsages; - if (nssCert_GetTrustedUsages(c, &certUsages) == NULL) { - if (statusOpt) *statusOpt = PR_FAILURE; + if (c->trust.trustedUsages.ca == usages->ca && + c->trust.trustedUsages.peer == usages->peer) + { + return PR_TRUE; + } else { return PR_FALSE; } - return nssUsages_Match(usages, &certUsages); -} - -static void -set_trust_for_usage ( - NSSUsage usage, - nssTrust *trust, - nssTrustLevel setLevel -) -{ - if (usage & NSSUsage_SSLClient) { - trust->clientAuth = setLevel; - } - if (usage & NSSUsage_SSLServer) { - trust->serverAuth = setLevel; - } - if (usage & (NSSUsage_EmailSigner | NSSUsage_EmailRecipient)) { - trust->emailProtection = setLevel; - } - if (usage & NSSUsage_CodeSigner) { - trust->codeSigning = setLevel; - } -} - -/* XXX move */ -NSS_IMPLEMENT NSSToken * -nssTrust_GetWriteToken ( - nssTrust *t, - nssSession **rvSessionOpt -) -{ - return nssPKIObject_GetWriteToken(&t->object, rvSessionOpt); -} - -/* XXX move */ -NSS_IMPLEMENT void -nssTrust_Clear ( - nssTrust *trust -) -{ - trust->clientAuth = nssTrustLevel_NotTrusted; - trust->serverAuth = nssTrustLevel_NotTrusted; - trust->emailProtection = nssTrustLevel_NotTrusted; - trust->codeSigning = nssTrustLevel_NotTrusted; -} - -/* XXX move */ -NSS_IMPLEMENT nssTrust * -nssTrust_CreateNull ( - NSSTrustDomain *td -) -{ - nssPKIObject *pkio; - nssTrust *trust = NULL; - pkio = nssPKIObject_Create(NULL, NULL, td, NULL); - if (pkio) { - trust = nss_ZNEW(pkio->arena, nssTrust); - if (trust) { - trust->object = *pkio; - nssTrust_Clear(trust); - } else { - nssPKIObject_Destroy(pkio); - } - } - return trust; } NSS_IMPLEMENT PRStatus @@ -1224,56 +1115,22 @@ nssCert_SetTrustedUsages ( NSSUsages *usages ) { - PRStatus status; - nssTrust *trust; - NSSToken *token; - nssSession *session; - nssCryptokiObject *instance; - - /* XXX needs to be cached with cert */ - trust = nssTrustDomain_FindTrustForCert(c->object.td, c); - if (trust) { - token = nssTrust_GetWriteToken(trust, &session); - nssTrust_Clear(trust); - } else { - if (NSS_GetError() != NSS_ERROR_NO_ERROR) { - return PR_FAILURE; - } - /* XXX something better */ - /* create a new trust object */ - trust = nssTrust_CreateNull(c->object.td); - if (!trust) { - return PR_FAILURE; - } - token = nssCert_GetWriteToken(c, &session); - if (!token) { - /* XXX should extract from trust domain */ - PR_ASSERT(0); - return PR_FAILURE; - } - } - /* set the new trust values */ - set_trust_for_usage(usages->ca, trust, nssTrustLevel_TrustedDelegator); - set_trust_for_usage(usages->peer, trust, nssTrustLevel_Trusted); - /* import (set) the trust values on the token */ - instance = nssToken_ImportTrust(token, session, &c->encoding, - &c->issuer, &c->serial, - trust->serverAuth, - trust->clientAuth, - trust->codeSigning, - trust->emailProtection, - PR_TRUE); - /* clean up */ - nssSession_Destroy(session); - nssToken_Destroy(token); - if (instance) { - nssCryptokiObject_Destroy(instance); - status = PR_SUCCESS; - } else { - status = PR_FAILURE; + NSSTrustDomain *td; + if (c->trust.trustedUsages.ca == usages->ca && + c->trust.trustedUsages.peer == usages->peer) + { + /* already set to desired value */ + return PR_SUCCESS; } - nssTrust_Destroy(trust); - return status; + /* XXX lock here? */ + /* set the new trusted usages */ + c->trust.trustedUsages = *usages; + /* clear the not trusted usages of all bits from the new trust */ + c->trust.notTrustedUsages.ca &= usages->ca; + c->trust.notTrustedUsages.peer &= usages->peer; + /* reflect the change in the db */ + td = nssCert_GetTrustDomain(c); + return nssTrustDomain_SetCertTrust(td, c, &c->trust); } NSS_IMPLEMENT PRStatus @@ -1383,24 +1240,26 @@ nssCert_BuildChain ( ) { PRStatus status; + PRUint32 i, size; NSSCert **rvChain; NSSTrustDomain *td; - nssPKIObjectCollection *collection; NSSUsages usages = { 0 }; td = NSSCert_GetTrustDomain(c); if (statusOpt) *statusOpt = PR_SUCCESS; - /* initialize the collection with the current cert */ - collection = nssCertCollection_Create(td, NULL); - if (!collection) { + if (rvLimit) { + size = rvLimit; + } else { + size = 4; + } + rvChain = nss_ZNEWARRAY(arenaOpt, NSSCert *, size + 1); + if (!rvChain) { if (statusOpt) *statusOpt = PR_FAILURE; return (NSSCert **)NULL; } - nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c); - if (rvLimit == 1) { - goto finish; - } + i = 0; /* begin the chain with the cert passed in */ + rvChain[i++] = nssCert_AddRef(c); /* going from peer to CA */ if (usagesOpt) { usages.ca = usagesOpt->peer; @@ -1410,25 +1269,29 @@ nssCert_BuildChain ( while (!nssItem_Equal(&c->subject, &c->issuer, &status)) { c = find_cert_issuer(c, time, usagesOpt, policiesOpt); if (c) { - nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c); - nssCert_Destroy(c); /* collection has it */ - if (rvLimit > 0 && - nssPKIObjectCollection_Count(collection) == rvLimit) - { + rvChain[i++] = c; + if (rvLimit > 0 && i == rvLimit) { + /* reached the limit of certs asked for */ break; } + if (i == size) { + /* unlimited search, but array is full */ + NSSCert **test; + size *= 2; + test = nss_ZREALLOCARRAY(rvChain, NSSCert *, size + 1); + if (!test) { + nssCertArray_Destroy(rvChain); + if (statusOpt) *statusOpt = PR_FAILURE; + return (NSSCert **)NULL; + } + rvChain = test; + } } else { nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND); if (statusOpt) *statusOpt = PR_FAILURE; break; } } -finish: - rvChain = nssPKIObjectCollection_GetCerts(collection, - rvOpt, - rvLimit, - arenaOpt); - nssPKIObjectCollection_Destroy(collection); return rvChain; } @@ -1565,44 +1428,17 @@ nssCert_GetPublicKey ( ) { PRStatus status; - NSSToken **tokens, **tp; - nssCryptokiObject *instance = NULL; NSSTrustDomain *td = nssCert_GetTrustDomain(c); NSSVolatileDomain *vd = nssCert_GetVolatileDomain(c, NULL); - /* first look for a persistent object in the trust domain */ - tokens = nssPKIObject_GetTokens(&c->object, NULL, 0, &status); - if (tokens) { - for (tp = tokens; *tp; tp++) { - /* XXX need to iterate over cert instances to have session */ - nssSession *session = nssToken_CreateSession(*tp, PR_FALSE); - if (!session) { - break; - } - instance = nssToken_FindPublicKeyByID(*tp, session, &c->id); - nssSession_Destroy(session); - if (instance) { - break; - } - } - /* also search on other tokens? */ - nssTokenArray_Destroy(tokens); - } - if (instance) { - NSSPublicKey *bk = NULL; - /* found a persistent instance of the pubkey, return it */ - bk = nssPublicKey_CreateFromInstance(instance, td, vd, NULL); - if (!bk) { - nssCryptokiObject_Destroy(instance); - nssVolatileDomain_Destroy(vd); - return (NSSPublicKey *)NULL; - } - return bk; - } else { + if (!c->bk && c->id.size > 0) { + /* first try looking for a persistent object */ + c->bk = nssTrustDomain_FindPublicKeyByID(td, &c->id); + } + if (!c->bk) { NSSOIDTag keyAlg; NSSBitString keyBits; nssCertDecoding *dc = nssCert_GetDecoding(c); - /* create an ephemeral pubkey object, either in the cert's * volatile domain (if it exists), or as a standalone object * that will be destroyed with the cert @@ -1610,11 +1446,12 @@ nssCert_GetPublicKey ( status = dc->methods->getPublicKeyInfo(dc->data, &keyAlg, &keyBits); if (status == PR_SUCCESS) { c->bk = nssPublicKey_CreateFromInfo(td, vd, keyAlg, &keyBits); - nssVolatileDomain_Destroy(vd); - return c->bk; } } nssVolatileDomain_Destroy(vd); + if (c->bk) { + return nssPublicKey_AddRef(c->bk); + } return (NSSPublicKey *)NULL; } @@ -1632,53 +1469,12 @@ nssCert_FindPrivateKey ( NSSCallback *uhh ) { - PRStatus status; - NSSToken **tokens, **tp; - nssCryptokiObject *instance; NSSTrustDomain *td = nssCert_GetTrustDomain(c); - - tokens = nssPKIObject_GetTokens(&c->object, NULL, 0, &status); - if (!tokens) { - return PR_FALSE; /* actually, should defer to crypto context */ - } - for (tp = tokens; *tp; tp++) { - NSSSlot *slot = nssToken_GetSlot(*tp); - NSSCallback *pwcb = uhh ? - uhh : - nssTrustDomain_GetDefaultCallback(td, NULL); - status = nssSlot_Login(slot, pwcb); - nssSlot_Destroy(slot); - if (status != PR_SUCCESS) { - break; - } - /* XXX need to iterate over cert instances to have session */ - { - nssSession *session = nssToken_CreateSession(*tp, PR_FALSE); - instance = nssToken_FindPrivateKeyByID(*tp, session, &c->id); - nssSession_Destroy(session); - if (instance) { - break; - } - } - } - /* also search on other tokens? */ - nssTokenArray_Destroy(tokens); - if (instance) { - nssPKIObject *pkio; - NSSPrivateKey *vk = NULL; - pkio = nssPKIObject_Create(NULL, instance, td, /* XXX cc */ NULL); - if (!pkio) { - nssCryptokiObject_Destroy(instance); - return (NSSPrivateKey *)NULL; - } - vk = nssPrivateKey_Create(pkio); - if (!vk) { - nssPKIObject_Destroy(pkio); - return (NSSPrivateKey *)NULL; - } - return vk; + if (c->id.size > 0) { + return nssTrustDomain_FindPrivateKeyByID(td, &c->id); + } else { + return (NSSPrivateKey *)NULL; } - return (NSSPrivateKey *)NULL; } NSS_IMPLEMENT NSSPrivateKey * @@ -1697,38 +1493,11 @@ nssCert_IsPrivateKeyAvailable ( PRStatus *statusOpt ) { - PRStatus status; - NSSToken **tokens, **tp; - nssCryptokiObject *instance = NULL; - NSSTrustDomain *td = nssCert_GetTrustDomain(c); - PRBool isLoggedIn; - tokens = nssPKIObject_GetTokens(&c->object, NULL, 0, &status); - if (!tokens) { - return PR_FALSE; /* can't have private key w/o a token instance */ - } - for (tp = tokens; *tp; tp++) { - NSSSlot *slot; - /* XXX need to iterate over cert instances to have session */ - nssSession *session = nssToken_CreateSession(*tp, PR_FALSE); - if (!session) { - break; - } - slot = nssToken_GetSlot(*tp); - isLoggedIn = nssSlot_IsLoggedIn(slot); - nssSlot_Destroy(slot); - if (isLoggedIn) { - instance = nssToken_FindPrivateKeyByID(*tp, session, &c->id); - } else { - instance = nssToken_FindPublicKeyByID(*tp, session, &c->id); - } - nssSession_Destroy(session); - if (instance) { - break; - } - } - nssTokenArray_Destroy(tokens); - if (instance) { - nssCryptokiObject_Destroy(instance); + NSSPrivateKey *vk; + /* XXX would be nice to "ping" the tokens w/o actually building the key */ + vk = nssCert_FindPrivateKey(c, uhh); + if (vk) { + nssPrivateKey_Destroy(vk); return PR_TRUE; } else { return PR_FALSE; @@ -1838,91 +1607,6 @@ NSSUserCert_DeriveSymKey ( return NULL; } -NSS_IMPLEMENT nssTrust * -nssTrust_Create ( - nssPKIObject *object -) -{ - PRStatus status; - PRUint32 i; - PRUint32 lastTrustOrder, myTrustOrder; - NSSModule *module; - nssTrust *rvt; - nssCryptokiObject *instance; - nssTrustLevel serverAuth, clientAuth, codeSigning, emailProtection; - lastTrustOrder = 1<<16; /* just make it big */ - PR_ASSERT(object->instances != NULL && object->numInstances > 0); - rvt = nss_ZNEW(object->arena, nssTrust); - if (!rvt) { - return (nssTrust *)NULL; - } - rvt->object = *object; - /* trust has to peek into the base object members */ - PZ_Lock(object->lock); - for (i=0; i<object->numInstances; i++) { - /* get the trust order from the token's module */ - instance = object->instances[i]; - module = nssToken_GetModule(instance->token); - myTrustOrder = nssModule_GetTrustOrder(module); - nssModule_Destroy(module); - /* get the trust values from this token */ - status = nssCryptokiTrust_GetAttributes(instance, - &serverAuth, - &clientAuth, - &codeSigning, - &emailProtection); - if (status != PR_SUCCESS) { - PZ_Unlock(object->lock); - return (nssTrust *)NULL; - } - if (rvt->serverAuth == nssTrustLevel_Unknown || - myTrustOrder < lastTrustOrder) - { - rvt->serverAuth = serverAuth; - } - if (rvt->clientAuth == nssTrustLevel_Unknown || - myTrustOrder < lastTrustOrder) - { - rvt->clientAuth = clientAuth; - } - if (rvt->emailProtection == nssTrustLevel_Unknown || - myTrustOrder < lastTrustOrder) - { - rvt->emailProtection = emailProtection; - } - if (rvt->codeSigning == nssTrustLevel_Unknown || - myTrustOrder < lastTrustOrder) - { - rvt->codeSigning = codeSigning; - } - lastTrustOrder = myTrustOrder; - } - PZ_Unlock(object->lock); - return rvt; -} - -NSS_IMPLEMENT nssTrust * -nssTrust_AddRef ( - nssTrust *trust -) -{ - if (trust) { - nssPKIObject_AddRef(&trust->object); - } - return trust; -} - -NSS_IMPLEMENT PRStatus -nssTrust_Destroy ( - nssTrust *trust -) -{ - if (trust) { - (void)nssPKIObject_Destroy(&trust->object); - } - return PR_SUCCESS; -} - struct nssSMIMEProfileStr { nssPKIObject object; diff --git a/security/nss/lib/pki/cryptocontext.c b/security/nss/lib/pki/cryptocontext.c index 7b11de350..7888b8957 100644 --- a/security/nss/lib/pki/cryptocontext.c +++ b/security/nss/lib/pki/cryptocontext.c @@ -775,10 +775,10 @@ nssCryptoContext_Sign ( } if (cc->which == a_symkey) { if (prepare_context_symmetric_key(cc, ap) == PR_FAILURE) - return PR_FAILURE; + return (NSSItem *)NULL; } else { if (prepare_context_private_key(cc, ap) == PR_FAILURE) - return PR_FAILURE; + return (NSSItem *)NULL; } return nssToken_Sign(cc->token, cc->session, ap, cc->key, data, rvOpt, arenaOpt); @@ -1468,7 +1468,7 @@ nssCryptoContext_Unmark ( NSSCryptoContextMark *mark ) { - nssArena_Destroy(mark->arena); + return nssArena_Destroy(mark->arena); } NSS_IMPLEMENT PRStatus diff --git a/security/nss/lib/pki/manifest.mn b/security/nss/lib/pki/manifest.mn index 2ba5eb790..a8b62aa56 100644 --- a/security/nss/lib/pki/manifest.mn +++ b/security/nss/lib/pki/manifest.mn @@ -34,7 +34,7 @@ MANIFEST_CVS_ID = "@(#) $RCSfile$ $Revision$ $Date$ $Name$" CORE_DEPTH = ../../.. -PRIVATE_EXPORTS = \ +PRIVATE_EXPORTS = \ pki.h \ pkit.h \ $(NULL) @@ -49,6 +49,7 @@ MODULE = nss CSRCS = \ pkibase.c \ pkistore.c \ + pkidb.c \ asymmkey.c \ cert.c \ cryptocontext.c \ @@ -58,6 +59,6 @@ CSRCS = \ volatiledomain.c \ $(NULL) -REQUIRES = security nspr +REQUIRES = security nspr dbm LIBRARY_NAME = nsspki diff --git a/security/nss/lib/pki/pki.h b/security/nss/lib/pki/pki.h index 47e1bc07a..54e35d6b8 100644 --- a/security/nss/lib/pki/pki.h +++ b/security/nss/lib/pki/pki.h @@ -117,15 +117,19 @@ nssTrustDomain_TraverseCerts ( void *arg ); -NSS_EXTERN nssTrust * -nssTrustDomain_FindTrustForCert ( +NSS_EXTERN NSSPublicKey * +nssTrustDomain_FindPublicKeyByID ( NSSTrustDomain *td, - NSSCert *c + NSSItem *keyID ); NSS_EXTERN NSSCert * nssCert_Decode ( - NSSBER *ber + NSSBER *ber, + NSSItem *nicknameOpt, + nssTrust *trustOpt, + NSSTrustDomain *td, + NSSVolatileDomain *vdOpt ); NSS_EXTERN NSSCert * @@ -271,6 +275,18 @@ nssPrivateKey_GetNickname ( NSSToken *tokenOpt ); +NSS_EXTERN NSSTrustDomain * +nssPrivateKey_GetTrustDomain ( + NSSPrivateKey *vk, + PRStatus *statusOpt +); + +NSS_EXTERN NSSVolatileDomain * +nssPrivateKey_GetVolatileDomain ( + NSSPrivateKey *vk, + PRStatus *statusOpt +); + NSS_EXTERN NSSPublicKey * nssPublicKey_AddRef ( NSSPublicKey *bk @@ -286,6 +302,11 @@ nssPublicKey_GetID ( NSSPublicKey *vk ); +NSS_EXTERN NSSKeyPairType +nssPublicKey_GetKeyType ( + NSSPublicKey *bk +); + NSS_EXTERN NSSItem * nssPublicKey_WrapSymKey ( NSSPublicKey *bk, @@ -302,11 +323,44 @@ nssSymKey_AddRef ( ); NSS_EXTERN NSSVolatileDomain * +nssSymKey_GetVolatileDomain ( + NSSSymKey *mk, + PRStatus *statusOpt +); + +NSS_EXTERN NSSVolatileDomain * nssVolatileDomain_Create ( NSSTrustDomain *td, NSSCallback *uhhOpt ); +NSS_EXTERN NSSVolatileDomain * +nssVolatileDomain_AddRef ( + NSSVolatileDomain *vd +); + +NSS_EXTERN PRStatus +nssVolatileDomain_Destroy ( + NSSVolatileDomain *vd +); + +NSS_EXTERN NSSTrustDomain * +nssVolatileDomain_GetTrustDomain ( + NSSVolatileDomain *vd +); + +NSS_EXTERN PRStatus +nssVolatileDomain_ImportCert ( + NSSVolatileDomain *vd, + NSSCert *c +); + +NSS_EXTERN PRStatus +nssVolatileDomain_ImportPrivateKey ( + NSSVolatileDomain *vd, + NSSPrivateKey *vk +); + NSS_EXTERN NSSCert ** nssVolatileDomain_FindCertsBySubject ( NSSVolatileDomain *vd, @@ -316,6 +370,30 @@ nssVolatileDomain_FindCertsBySubject ( NSSArena *arenaOpt ); +NSS_EXTERN PRStatus +nssVolatileDomain_ImportPublicKey ( + NSSVolatileDomain *vd, + NSSPublicKey *bk +); + +NSS_EXTERN PRStatus +nssVolatileDomain_ImportSymKey ( + NSSVolatileDomain *vd, + NSSSymKey *mk +); + +NSS_EXTERN NSSSymKey * +nssVolatileDomain_UnwrapSymKey ( + NSSVolatileDomain *vd, + const NSSAlgNParam *ap, + NSSPrivateKey *wrapKey, + NSSItem *wrappedKey, + NSSSymKeyType targetSymKeyType, + NSSCallback *uhhOpt, + NSSOperations operations, + NSSProperties properties +); + NSS_EXTERN void nssPublicKeyArray_Destroy ( NSSPublicKey **bkeys diff --git a/security/nss/lib/pki/pkibase.c b/security/nss/lib/pki/pkibase.c index 1a30da02c..e3e240547 100644 --- a/security/nss/lib/pki/pkibase.c +++ b/security/nss/lib/pki/pkibase.c @@ -45,25 +45,19 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; NSS_IMPLEMENT nssPKIObject * nssPKIObject_Create ( - NSSArena *arenaOpt, - nssCryptokiObject *instanceOpt, NSSTrustDomain *td, - NSSVolatileDomain *vdOpt /* XXX remove */ + nssCryptokiObject *instanceOpt, + PRUint32 size ) { NSSArena *arena; - nssArenaMark *mark = NULL; nssPKIObject *object; - if (arenaOpt) { - arena = arenaOpt; - mark = nssArena_Mark(arena); - } else { - arena = nssArena_Create(); - if (!arena) { - return (nssPKIObject *)NULL; - } + + arena = nssArena_Create(); + if (!arena) { + return (nssPKIObject *)NULL; } - object = nss_ZNEW(arena, nssPKIObject); + object = (nssPKIObject *)nss_ZAlloc(arena, size); if (!object) { goto loser; } @@ -77,18 +71,14 @@ nssPKIObject_Create ( if (nssPKIObject_AddInstance(object, instanceOpt) != PR_SUCCESS) { goto loser; } + if (instanceOpt->label) { + object->nickname = nssUTF8_Duplicate(instanceOpt->label, NULL); + } } PR_AtomicIncrement(&object->refCount); - if (mark) { - nssArena_Unmark(arena, mark); - } return object; loser: - if (mark) { - nssArena_Release(arena, mark); - } else { - nssArena_Destroy(arena); - } + nssArena_Destroy(arena); return (nssPKIObject *)NULL; } @@ -106,6 +96,7 @@ nssPKIObject_Destroy ( } /*nssVolatileDomain_Destroy(object->vd);*/ PZ_DestroyLock(object->lock); + nssUTF8_Destroy(object->nickname); nssArena_Destroy(object->arena); return PR_TRUE; } @@ -259,6 +250,26 @@ nssPKIObject_RemoveInstanceForToken ( return PR_SUCCESS; } +static nssPKIObject * +nssPKIObject_Merge ( + nssPKIObject *object1, + nssPKIObject *object2 +) +{ + PRUint32 i; + PZ_Lock(object2->lock); + for (i = 0; i < object2->numInstances; i++) { + if (!nssPKIObject_HasInstanceOnToken(object1, + object2->instances[i]->token)) + { + (void)nssPKIObject_AddInstance(object1, object2->instances[i]); + } + } + PZ_Unlock(object2->lock); + return object1; +} + + /* this needs more thought on what will happen when there are multiple * instances */ @@ -357,10 +368,7 @@ nssPKIObject_SetNickname ( PRUint32 i; PRStatus status; PZ_Lock(object->lock); - if (object->vd) { - object->tempName = nssUTF8_Duplicate(nickname, object->arena); - status = object->tempName ? PR_SUCCESS : PR_FAILURE; - } else { + if (tokenOpt) { nssCryptokiObject *instance = NULL; if (tokenOpt) { for (i=0; i<object->numInstances; i++) { @@ -378,6 +386,9 @@ nssPKIObject_SetNickname ( status = PR_FAILURE; } } + if (!object->nickname) { + object->nickname = nssUTF8_Duplicate(nickname, NULL); + } PZ_Unlock(object->lock); return status; } @@ -391,9 +402,7 @@ nssPKIObject_GetNickname ( PRUint32 i; NSSUTF8 *nickname = NULL; PZ_Lock(object->lock); - if (object->vd) { - return object->tempName; - } else { + if (tokenOpt) { for (i=0; i<object->numInstances; i++) { if ((!tokenOpt && object->instances[i]->label) || (object->instances[i]->token == tokenOpt)) @@ -403,6 +412,8 @@ nssPKIObject_GetNickname ( break; } } + } else { + nickname = object->nickname; } PZ_Unlock(object->lock); return nickname; @@ -468,25 +479,6 @@ nssPKIObject_FindInstanceForAlgorithm ( return instance; } -NSS_IMPLEMENT PRBool -nssPKIObject_IsOnToken ( - nssPKIObject *object, - NSSToken *token -) -{ - PRUint32 i; - PRBool foundIt = PR_FALSE; - PZ_Lock(object->lock); - for (i=0; i<object->numInstances; i++) { - if (object->instances[i]->token == token) { - foundIt = PR_TRUE; - break; - } - } - PZ_Unlock(object->lock); - return foundIt; -} - NSS_IMPLEMENT NSSTrustDomain * nssPKIObject_GetTrustDomain ( nssPKIObject *object, @@ -562,8 +554,7 @@ nssCertArray_CreateFromInstances ( return (NSSCert **)NULL; } for (i = 0; i < count; i++) { - rvCerts[i] = nssCert_CreateFromInstance(instances[i], td, - vdOpt, NULL); + rvCerts[i] = nssCert_CreateFromInstance(instances[i], td, vdOpt); if (!rvCerts[i]) { nssCertArray_Destroy(rvCerts); /* it's NULL-terminated */ return (NSSCert **)NULL; @@ -594,6 +585,17 @@ NSSCertArray_Destroy ( nssCertArray_Destroy(certs); } +NSS_IMPLEMENT PRIntn +nssObjectArray_Count ( + void **objects +) +{ + PRIntn n; + void **p; + for (p = objects, n = 0; p && *p; p++, n++); + return n; +} + NSS_IMPLEMENT NSSCert ** nssCertArray_Duplicate ( NSSCert **certs, @@ -668,7 +670,10 @@ nssCertArray_FindBestCert ( } if (!bestCert) { /* take the first cert with matching usage (if provided) */ - if (!usagesOpt || nssUsages_Match(usagesOpt, certUsages)) { + if (!usagesOpt || + ((usagesOpt->ca & certUsages->ca) == usagesOpt->ca && + (usagesOpt->peer & certUsages->peer) == usagesOpt->peer)) + { bestCert = nssCert_AddRef(c); } continue; @@ -677,7 +682,10 @@ nssCertArray_FindBestCert ( * the correct usage, continue * if ths cert does match usage, defer to time/policies */ - if (usagesOpt && !nssUsages_Match(usagesOpt, certUsages)) { + if (usagesOpt && + ((usagesOpt->ca & certUsages->ca) != usagesOpt->ca || + (usagesOpt->peer & certUsages->peer) != usagesOpt->peer)) + { continue; } } @@ -777,6 +785,33 @@ nssPrivateKeyArray_Destroy ( nss_ZFreeIf(vkeys); } +NSS_IMPLEMENT NSSPublicKey ** +nssPublicKeyArray_CreateFromInstances ( + nssCryptokiObject **instances, + NSSTrustDomain *td, + NSSVolatileDomain *vdOpt, + NSSArena *arenaOpt +) +{ + PRIntn i, count; + nssCryptokiObject **ip; + NSSPublicKey **rvBKeys; + + for (ip = instances, count = 0; *ip; ip++, count++); + rvBKeys = nss_ZNEWARRAY(arenaOpt, NSSPublicKey *, count + 1); + if (!rvBKeys) { + return (NSSPublicKey **)NULL; + } + for (i = 0; i < count; i++) { + rvBKeys[i] = nssPublicKey_CreateFromInstance(instances[i], td, vdOpt); + if (!rvBKeys[i]) { + nssPublicKeyArray_Destroy(rvBKeys); /* it's NULL-terminated */ + return (NSSPublicKey **)NULL; + } + } + return rvBKeys; +} + NSS_IMPLEMENT void nssPublicKeyArray_Destroy ( NSSPublicKey **bkeys @@ -791,809 +826,159 @@ nssPublicKeyArray_Destroy ( nss_ZFreeIf(bkeys); } -NSS_IMPLEMENT PRBool -nssUsages_Match ( - const NSSUsages *usages, - const NSSUsages *testUsages +NSS_IMPLEMENT NSSPrivateKey ** +nssPrivateKeyArray_CreateFromInstances ( + nssCryptokiObject **instances, + NSSTrustDomain *td, + NSSVolatileDomain *vdOpt, + NSSArena *arenaOpt ) { - return (((usages->ca & testUsages->ca) == usages->ca) && - ((usages->peer & testUsages->peer) == usages->peer)); -} - -/* - * Object collections - */ - -typedef enum -{ - pkiObjectType_Cert = 0, - pkiObjectType_CRL = 1, - pkiObjectType_PrivateKey = 2, - pkiObjectType_PublicKey = 3 -} pkiObjectType; - -/* Each object is defined by a set of items that uniquely identify it. - * Here are the uid sets: - * - * NSSCert ==> { issuer, serial } - * NSSPrivateKey - * (RSA) ==> { modulus, public exponent } - * - */ -#define MAX_ITEMS_FOR_UID 2 - -/* pkiObjectCollectionNode - * - * A node in the collection is the set of unique identifiers for a single - * object, along with either the actual object or a proto-object. - */ -typedef struct -{ - PRCList link; - PRBool haveObject; - nssPKIObject *object; - NSSItem uid[MAX_ITEMS_FOR_UID]; -} -pkiObjectCollectionNode; - -/* nssPKIObjectCollection - * - * The collection is the set of all objects, plus the interfaces needed - * to manage the objects. - * - */ -struct nssPKIObjectCollectionStr -{ - NSSArena *arena; - NSSTrustDomain *td; - PRCList head; /* list of pkiObjectCollectionNode's */ - PRUint32 size; - pkiObjectType objectType; - void (* destroyObject)(nssPKIObject *o); - PRStatus (* getUIDFromObject)(nssPKIObject *o, NSSItem *uid); - PRStatus (* getUIDFromInstance)(nssCryptokiObject *co, NSSItem *uid, - NSSArena *arena); - nssPKIObject * (* createObject)(nssPKIObject *o); -}; + PRIntn i, count; + nssCryptokiObject **ip; + NSSPrivateKey **rvVKeys; -static nssPKIObjectCollection * -nssPKIObjectCollection_Create ( - NSSTrustDomain *td -) -{ - NSSArena *arena; - nssPKIObjectCollection *rvCollection = NULL; - arena = nssArena_Create(); - if (!arena) { - return (nssPKIObjectCollection *)NULL; - } - rvCollection = nss_ZNEW(arena, nssPKIObjectCollection); - if (!rvCollection) { - goto loser; + for (ip = instances, count = 0; *ip; ip++, count++); + rvVKeys = nss_ZNEWARRAY(arenaOpt, NSSPrivateKey *, count + 1); + if (!rvVKeys) { + return (NSSPrivateKey **)NULL; } - PR_INIT_CLIST(&rvCollection->head); - rvCollection->arena = arena; - rvCollection->td = td; /* XXX */ - return rvCollection; -loser: - nssArena_Destroy(arena); - return (nssPKIObjectCollection *)NULL; -} - -NSS_IMPLEMENT void -nssPKIObjectCollection_Destroy ( - nssPKIObjectCollection *collection -) -{ - if (collection) { - PRCList *link; - pkiObjectCollectionNode *node; - /* first destroy any objects in the collection */ - link = PR_NEXT_LINK(&collection->head); - while (link != &collection->head) { - node = (pkiObjectCollectionNode *)link; - if (node->haveObject) { - (*collection->destroyObject)(node->object); - } else { - nssPKIObject_Destroy(node->object); - } - link = PR_NEXT_LINK(link); + for (i = 0; i < count; i++) { + rvVKeys[i] = nssPrivateKey_CreateFromInstance(instances[i], td, vdOpt); + if (!rvVKeys[i]) { + nssPrivateKeyArray_Destroy(rvVKeys); /* it's NULL-terminated */ + return (NSSPrivateKey **)NULL; } - /* then destroy it */ - nssArena_Destroy(collection->arena); - } -} - -NSS_IMPLEMENT PRUint32 -nssPKIObjectCollection_Count ( - nssPKIObjectCollection *collection -) -{ - return collection->size; -} - -NSS_IMPLEMENT PRStatus -nssPKIObjectCollection_AddObject ( - nssPKIObjectCollection *collection, - nssPKIObject *object -) -{ - pkiObjectCollectionNode *node; - node = nss_ZNEW(collection->arena, pkiObjectCollectionNode); - if (!node) { - return PR_FAILURE; } - node->haveObject = PR_TRUE; - node->object = nssPKIObject_AddRef(object); - (*collection->getUIDFromObject)(object, node->uid); - PR_INIT_CLIST(&node->link); - PR_INSERT_BEFORE(&node->link, &collection->head); - collection->size++; - return PR_SUCCESS; + return rvVKeys; } -static pkiObjectCollectionNode * -find_instance_in_collection ( - nssPKIObjectCollection *collection, - nssCryptokiObject *instance -) -{ - PRCList *link; - pkiObjectCollectionNode *node; - link = PR_NEXT_LINK(&collection->head); - while (link != &collection->head) { - node = (pkiObjectCollectionNode *)link; - if (nssPKIObject_HasInstance(node->object, instance)) { - return node; - } - link = PR_NEXT_LINK(link); - } - return (pkiObjectCollectionNode *)NULL; -} +/* + * Object table + */ -static pkiObjectCollectionNode * -find_object_in_collection ( - nssPKIObjectCollection *collection, - NSSItem *uid -) +struct nssPKIObjectTableStr { - PRUint32 i; - PRStatus status; - PRCList *link; - pkiObjectCollectionNode *node; - link = PR_NEXT_LINK(&collection->head); - while (link != &collection->head) { - node = (pkiObjectCollectionNode *)link; - for (i=0; i<MAX_ITEMS_FOR_UID; i++) { - if (!nssItem_Equal(&node->uid[i], &uid[i], &status)) { - break; - } - } - if (i == MAX_ITEMS_FOR_UID) { - return node; - } - link = PR_NEXT_LINK(link); - } - return (pkiObjectCollectionNode *)NULL; -} + PZLock *lock; + PLHashTable *hash; +}; -static pkiObjectCollectionNode * -add_object_instance ( - nssPKIObjectCollection *collection, - nssCryptokiObject *instance +static PLHashNumber +nss_pkiobject_hash ( + const void *key ) { - PRUint32 i; - PRStatus status; - pkiObjectCollectionNode *node; - nssArenaMark *mark = NULL; - NSSItem uid[MAX_ITEMS_FOR_UID]; - nsslibc_memset(uid, 0, sizeof uid); - /* The list is traversed twice, first (here) looking to match the - * { token, handle } tuple, and if that is not found, below a search - * for unique identifier is done. Here, a match means this exact object - * instance is already in the collection, and we have nothing to do. - */ - node = find_instance_in_collection(collection, instance); - if (node) { - /* The collection is assumed to take over the instance. Since we - * are not using it, it must be destroyed. - */ - nssCryptokiObject_Destroy(instance); - return node; - } - mark = nssArena_Mark(collection->arena); - if (!mark) { - goto loser; - } - status = (*collection->getUIDFromInstance)(instance, uid, - collection->arena); - if (status != PR_SUCCESS) { - goto loser; - } - /* Search for unique identifier. A match here means the object exists - * in the collection, but does not have this instance, so the instance - * needs to be added. - */ - node = find_object_in_collection(collection, uid); - if (node) { - /* This is a object with multiple instances */ - status = nssPKIObject_AddInstance(node->object, instance); - } else { - /* This is a completely new object. Create a node for it. */ - node = nss_ZNEW(collection->arena, pkiObjectCollectionNode); - if (!node) { - goto loser; + int i, j; + PLHashNumber h; + nssPKIObject *pkio = (nssPKIObject *)key; + h = 0; + for (i = 0; i < pkio->numIDs; i++) { + for (j=0; j < pkio->uid[i]->size; j++) { + h = (h >> 28) ^ (h << 4) ^ + ((unsigned char *)pkio->uid[i]->data)[i]; } - node->object = nssPKIObject_Create(NULL, instance, - collection->td, NULL); - if (!node->object) { - goto loser; - } - for (i=0; i<MAX_ITEMS_FOR_UID; i++) { - node->uid[i] = uid[i]; - } - node->haveObject = PR_FALSE; - PR_INIT_CLIST(&node->link); - PR_INSERT_BEFORE(&node->link, &collection->head); - collection->size++; - status = PR_SUCCESS; - } - nssArena_Unmark(collection->arena, mark); - return node; -loser: - if (mark) { - nssArena_Release(collection->arena, mark); } - nssCryptokiObject_Destroy(instance); - return (pkiObjectCollectionNode *)NULL; + return h; } -NSS_IMPLEMENT PRStatus -nssPKIObjectCollection_AddInstances ( - nssPKIObjectCollection *collection, - nssCryptokiObject **instances, - PRUint32 numInstances -) +static int +nss_compare_pkiobjects(const void *v1, const void *v2) { - PRStatus status = PR_SUCCESS; - PRUint32 i = 0; - pkiObjectCollectionNode *node; - if (instances) { - for (; *instances; instances++, i++) { - if (numInstances > 0 && i == numInstances) { - break; - } - node = add_object_instance(collection, *instances); - if (node == NULL) { - goto loser; - } - } + int i; + int rv = 0; + nssPKIObject *pkio1 = (nssPKIObject *)v1; + nssPKIObject *pkio2 = (nssPKIObject *)v2; + if (pkio1->objectType != pkio2->objectType) { + return 1; } - return status; -loser: - /* free the remaining instances */ - for (; *instances; instances++, i++) { - if (numInstances > 0 && i == numInstances) { + for (i = 0; i < pkio1->numIDs; i++) { + if (!nssItem_Equal(pkio1->uid[i], pkio1->uid[i], NULL)) { + rv = 1; break; } - nssCryptokiObject_Destroy(*instances); } - return PR_FAILURE; + return rv; } -static void -nssPKIObjectCollection_RemoveNode ( - nssPKIObjectCollection *collection, - pkiObjectCollectionNode *node +NSS_IMPLEMENT nssPKIObjectTable * +nssPKIObjectTable_Create ( + NSSArena *arena ) { - PR_REMOVE_LINK(&node->link); - collection->size--; -} + nssPKIObjectTable *rvTable; -static PRStatus -nssPKIObjectCollection_GetObjects ( - nssPKIObjectCollection *collection, - nssPKIObject **rvObjects, - PRUint32 rvSize -) -{ - PRUint32 i = 0; - PRCList *link = PR_NEXT_LINK(&collection->head); - pkiObjectCollectionNode *node; - while ((i < rvSize) && (link != &collection->head)) { - node = (pkiObjectCollectionNode *)link; - if (!node->haveObject) { - /* Convert the proto-object to an object */ - node->object = (*collection->createObject)(node->object); - if (!node->object) { - link = PR_NEXT_LINK(link); - /*remove bogus object from list*/ - nssPKIObjectCollection_RemoveNode(collection,node); - continue; - } - node->haveObject = PR_TRUE; - } - rvObjects[i++] = nssPKIObject_AddRef(node->object); - link = PR_NEXT_LINK(link); + rvTable = nss_ZNEW(arena, nssPKIObjectTable); + if (rvTable == NULL) { + return (nssPKIObjectTable *)NULL; } - return PR_SUCCESS; -} -NSS_IMPLEMENT PRStatus -nssPKIObjectCollection_Traverse ( - nssPKIObjectCollection *collection, - nssPKIObjectCallback *callback -) -{ - PRStatus status; - PRCList *link = PR_NEXT_LINK(&collection->head); - pkiObjectCollectionNode *node; - while (link != &collection->head) { - node = (pkiObjectCollectionNode *)link; - if (!node->haveObject) { - node->object = (*collection->createObject)(node->object); - if (!node->object) { - link = PR_NEXT_LINK(link); - /*remove bogus object from list*/ - nssPKIObjectCollection_RemoveNode(collection,node); - continue; - } - node->haveObject = PR_TRUE; - } - switch (collection->objectType) { - case pkiObjectType_Cert: - status = (*callback->func.cert)((NSSCert *)node->object, - callback->arg); - break; - case pkiObjectType_CRL: - status = (*callback->func.crl)((NSSCRL *)node->object, - callback->arg); - break; - case pkiObjectType_PrivateKey: - status = (*callback->func.pvkey)((NSSPrivateKey *)node->object, - callback->arg); - break; - case pkiObjectType_PublicKey: - status = (*callback->func.pbkey)((NSSPublicKey *)node->object, - callback->arg); - break; - } - link = PR_NEXT_LINK(link); + rvTable->lock = PZ_NewLock(nssILockOther); + if (rvTable->lock == NULL) { + return (nssPKIObjectTable *)NULL; } - return PR_SUCCESS; -} -NSS_IMPLEMENT PRStatus -nssPKIObjectCollection_AddInstanceAsObject ( - nssPKIObjectCollection *collection, - nssCryptokiObject *instance -) -{ - pkiObjectCollectionNode *node; - node = add_object_instance(collection, instance); - if (node == NULL) { - return PR_FAILURE; - } - if (!node->haveObject) { - node->object = (*collection->createObject)(node->object); - if (!node->object) { - /*remove bogus object from list*/ - nssPKIObjectCollection_RemoveNode(collection,node); - return PR_FAILURE; - } - node->haveObject = PR_TRUE; + rvTable->hash = PL_NewHashTable(0, + nss_pkiobject_hash, + nss_compare_pkiobjects, + PL_CompareValues, + NULL, NULL); + if (rvTable->hash == NULL) { + PZ_DestroyLock(rvTable->lock); + return (nssPKIObjectTable *)NULL; } - return PR_SUCCESS; -} - -/* - * Cert collections - */ - -static void -cert_destroyObject(nssPKIObject *o) -{ - NSSCert *c = (NSSCert *)o; - nssCert_Destroy(c); -} - -static PRStatus -cert_getUIDFromObject(nssPKIObject *o, NSSItem *uid) -{ - NSSCert *c = (NSSCert *)o; - NSSDER *issuer, *serial; - issuer = nssCert_GetIssuer(c); - serial = nssCert_GetSerialNumber(c); - uid[0] = *issuer; - uid[1] = *serial; - return PR_SUCCESS; -} - -static PRStatus -cert_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid, - NSSArena *arena) -{ - return nssCryptokiCert_GetAttributes(instance, - arena, /* arena */ - NULL, /* type */ - NULL, /* id */ - NULL, /* encoding */ - &uid[0], /* issuer */ - &uid[1], /* serial */ - NULL, /* subject */ - NULL); /* email */ -} - -static nssPKIObject * -cert_createObject(nssPKIObject *o) -{ - NSSCert *cert; - cert = nssCert_Create(o); - return (nssPKIObject *)cert; + return rvTable; } -NSS_IMPLEMENT nssPKIObjectCollection * -nssCertCollection_Create ( - NSSTrustDomain *td, - NSSCert **certsOpt -) -{ - PRStatus status; - nssPKIObjectCollection *collection; - collection = nssPKIObjectCollection_Create(td); - collection->objectType = pkiObjectType_Cert; - collection->destroyObject = cert_destroyObject; - collection->getUIDFromObject = cert_getUIDFromObject; - collection->getUIDFromInstance = cert_getUIDFromInstance; - collection->createObject = cert_createObject; - if (certsOpt) { - for (; *certsOpt; certsOpt++) { - nssPKIObject *object = (nssPKIObject *)(*certsOpt); - status = nssPKIObjectCollection_AddObject(collection, object); - } - } - return collection; -} - -NSS_IMPLEMENT NSSCert ** -nssPKIObjectCollection_GetCerts ( - nssPKIObjectCollection *collection, - NSSCert **rvOpt, - PRUint32 maximumOpt, - NSSArena *arenaOpt -) -{ - PRStatus status; - PRUint32 rvSize; - PRBool allocated = PR_FALSE; - if (collection->size == 0) { - return (NSSCert **)NULL; - } - if (maximumOpt == 0) { - rvSize = collection->size; - } else { - rvSize = PR_MIN(collection->size, maximumOpt); - } - if (!rvOpt) { - rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCert *, rvSize + 1); - if (!rvOpt) { - return (NSSCert **)NULL; - } - allocated = PR_TRUE; - } - status = nssPKIObjectCollection_GetObjects(collection, - (nssPKIObject **)rvOpt, - rvSize); - if (status != PR_SUCCESS) { - if (allocated) { - nss_ZFreeIf(rvOpt); - } - return (NSSCert **)NULL; - } - return rvOpt; -} - -/* - * CRL/KRL collections - */ - -static void -crl_destroyObject(nssPKIObject *o) -{ - NSSCRL *crl = (NSSCRL *)o; - nssCRL_Destroy(crl); -} - -static PRStatus -crl_getUIDFromObject(nssPKIObject *o, NSSItem *uid) -{ - NSSCRL *crl = (NSSCRL *)o; - NSSDER *encoding; - encoding = nssCRL_GetEncoding(crl); - uid[0] = *encoding; - uid[1].data = NULL; uid[1].size = 0; - return PR_SUCCESS; -} - -static PRStatus -crl_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid, - NSSArena *arena) -{ - return nssCryptokiCRL_GetAttributes(instance, - arena, /* arena */ - &uid[0], /* encoding */ - NULL, /* url */ - NULL); /* isKRL */ -} - -static nssPKIObject * -crl_createObject(nssPKIObject *o) -{ - return (nssPKIObject *)nssCRL_Create(o); -} - -NSS_IMPLEMENT nssPKIObjectCollection * -nssCRLCollection_Create ( - NSSTrustDomain *td, - NSSCRL **crlsOpt +NSS_IMPLEMENT void +nssPKIObjectTable_Destroy ( + nssPKIObjectTable *table ) { - PRStatus status; - nssPKIObjectCollection *collection; - collection = nssPKIObjectCollection_Create(td); - collection->objectType = pkiObjectType_CRL; - collection->destroyObject = crl_destroyObject; - collection->getUIDFromObject = crl_getUIDFromObject; - collection->getUIDFromInstance = crl_getUIDFromInstance; - collection->createObject = crl_createObject; - if (crlsOpt) { - for (; *crlsOpt; crlsOpt++) { - nssPKIObject *object = (nssPKIObject *)(*crlsOpt); - status = nssPKIObjectCollection_AddObject(collection, object); - } - } - return collection; + PZ_DestroyLock(table->lock); + PL_HashTableDestroy(table->hash); } -NSS_IMPLEMENT NSSCRL ** -nssPKIObjectCollection_GetCRLs ( - nssPKIObjectCollection *collection, - NSSCRL **rvOpt, - PRUint32 maximumOpt, - NSSArena *arenaOpt +NSS_IMPLEMENT nssPKIObject * +nssPKIObjectTable_Add ( + nssPKIObjectTable *table, + nssPKIObject *object ) { - PRStatus status; - PRUint32 rvSize; - PRBool allocated = PR_FALSE; - if (collection->size == 0) { - return (NSSCRL **)NULL; - } - if (maximumOpt == 0) { - rvSize = collection->size; - } else { - rvSize = PR_MIN(collection->size, maximumOpt); - } - if (!rvOpt) { - rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCRL *, rvSize + 1); - if (!rvOpt) { - return (NSSCRL **)NULL; - } - allocated = PR_TRUE; - } - status = nssPKIObjectCollection_GetObjects(collection, - (nssPKIObject **)rvOpt, - rvSize); - if (status != PR_SUCCESS) { - if (allocated) { - nss_ZFreeIf(rvOpt); - } - return (NSSCRL **)NULL; - } - return rvOpt; -} - -/* - * PrivateKey collections - */ - -static void -privkey_destroyObject(nssPKIObject *o) -{ - NSSPrivateKey *pvk = (NSSPrivateKey *)o; - nssPrivateKey_Destroy(pvk); -} - -static PRStatus -privkey_getUIDFromObject(nssPKIObject *o, NSSItem *uid) -{ - NSSPrivateKey *pvk = (NSSPrivateKey *)o; - NSSItem *id; - id = nssPrivateKey_GetID(pvk); - uid[0] = *id; - return PR_SUCCESS; -} - -static PRStatus -privkey_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid, - NSSArena *arena) -{ - return nssCryptokiPrivateKey_GetAttributes(instance, - arena, - NULL, /* type */ - &uid[0]); -} + PLHashEntry *he; + nssPKIObject *pkio; -static nssPKIObject * -privkey_createObject(nssPKIObject *o) -{ - NSSPrivateKey *pvk; - pvk = nssPrivateKey_Create(o); - return (nssPKIObject *)pvk; -} - -NSS_IMPLEMENT nssPKIObjectCollection * -nssPrivateKeyCollection_Create ( - NSSTrustDomain *td, - NSSPrivateKey **pvkOpt -) -{ - PRStatus status; - nssPKIObjectCollection *collection; - collection = nssPKIObjectCollection_Create(td); - collection->objectType = pkiObjectType_PrivateKey; - collection->destroyObject = privkey_destroyObject; - collection->getUIDFromObject = privkey_getUIDFromObject; - collection->getUIDFromInstance = privkey_getUIDFromInstance; - collection->createObject = privkey_createObject; - if (pvkOpt) { - for (; *pvkOpt; pvkOpt++) { - nssPKIObject *o = (nssPKIObject *)(*pvkOpt); - status = nssPKIObjectCollection_AddObject(collection, o); - } - } - return collection; -} + PZ_Lock(table->lock); -NSS_IMPLEMENT NSSPrivateKey ** -nssPKIObjectCollection_GetPrivateKeys ( - nssPKIObjectCollection *collection, - NSSPrivateKey **rvOpt, - PRUint32 maximumOpt, - NSSArena *arenaOpt -) -{ - PRStatus status; - PRUint32 rvSize; - PRBool allocated = PR_FALSE; - if (collection->size == 0) { - return (NSSPrivateKey **)NULL; - } - if (maximumOpt == 0) { - rvSize = collection->size; + pkio = (nssPKIObject *)PL_HashTableLookup(table->hash, object); + if (pkio) { + pkio = nssPKIObject_Merge(pkio, object); } else { - rvSize = PR_MIN(collection->size, maximumOpt); - } - if (!rvOpt) { - rvOpt = nss_ZNEWARRAY(arenaOpt, NSSPrivateKey *, rvSize + 1); - if (!rvOpt) { - return (NSSPrivateKey **)NULL; - } - allocated = PR_TRUE; - } - status = nssPKIObjectCollection_GetObjects(collection, - (nssPKIObject **)rvOpt, - rvSize); - if (status != PR_SUCCESS) { - if (allocated) { - nss_ZFreeIf(rvOpt); + he = PL_HashTableAdd(table->hash, object, object); + if( (PLHashEntry *)NULL == he ) { + nss_SetError(NSS_ERROR_NO_MEMORY); + pkio = NULL; + } else { + pkio = object; } - return (NSSPrivateKey **)NULL; } - return rvOpt; -} - -/* - * PublicKey collections - */ -static void -pubkey_destroyObject(nssPKIObject *o) -{ - NSSPublicKey *pubk = (NSSPublicKey *)o; - nssPublicKey_Destroy(pubk); -} - -static PRStatus -pubkey_getUIDFromObject(nssPKIObject *o, NSSItem *uid) -{ - NSSPublicKey *pubk = (NSSPublicKey *)o; - NSSItem *id; - id = nssPublicKey_GetID(pubk); - uid[0] = *id; - return PR_SUCCESS; -} + PZ_Unlock(table->lock); -static PRStatus -pubkey_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid, - NSSArena *arena) -{ - return nssCryptokiPublicKey_GetAttributes(instance, - arena, - NULL, /* type */ - &uid[0]); -} - -static nssPKIObject * -pubkey_createObject(nssPKIObject *o) -{ - NSSPublicKey *pubk; - pubk = nssPublicKey_Create(o); - return (nssPKIObject *)pubk; + return pkio; } -NSS_IMPLEMENT nssPKIObjectCollection * -nssPublicKeyCollection_Create ( - NSSTrustDomain *td, - NSSPublicKey **pubkOpt +NSS_IMPLEMENT PRStatus +nssPKIObjectTable_Remove ( + nssPKIObjectTable *table, + nssPKIObject *object ) { - PRStatus status; - nssPKIObjectCollection *collection; - collection = nssPKIObjectCollection_Create(td); - collection->objectType = pkiObjectType_PublicKey; - collection->destroyObject = pubkey_destroyObject; - collection->getUIDFromObject = pubkey_getUIDFromObject; - collection->getUIDFromInstance = pubkey_getUIDFromInstance; - collection->createObject = pubkey_createObject; - if (pubkOpt) { - for (; *pubkOpt; pubkOpt++) { - nssPKIObject *o = (nssPKIObject *)(*pubkOpt); - status = nssPKIObjectCollection_AddObject(collection, o); - } - } - return collection; -} -NSS_IMPLEMENT NSSPublicKey ** -nssPKIObjectCollection_GetPublicKeys ( - nssPKIObjectCollection *collection, - NSSPublicKey **rvOpt, - PRUint32 maximumOpt, - NSSArena *arenaOpt -) -{ PRStatus status; - PRUint32 rvSize; - PRBool allocated = PR_FALSE; - if (collection->size == 0) { - return (NSSPublicKey **)NULL; - } - if (maximumOpt == 0) { - rvSize = collection->size; - } else { - rvSize = PR_MIN(collection->size, maximumOpt); - } - if (!rvOpt) { - rvOpt = nss_ZNEWARRAY(arenaOpt, NSSPublicKey *, rvSize + 1); - if (!rvOpt) { - return (NSSPublicKey **)NULL; - } - allocated = PR_TRUE; - } - status = nssPKIObjectCollection_GetObjects(collection, - (nssPKIObject **)rvOpt, - rvSize); - if (status != PR_SUCCESS) { - if (allocated) { - nss_ZFreeIf(rvOpt); - } - return (NSSPublicKey **)NULL; - } - return rvOpt; + PZ_Lock(table->lock); + status = PL_HashTableRemove(table->hash, object); + PZ_Unlock(table->lock); + return status; } NSS_IMPLEMENT PRStatus @@ -1682,11 +1067,11 @@ nssPKIObjectCreator_GenerateKeyPair ( } #endif - *pbkOpt = nssPublicKey_CreateFromInstance(bkey, creator->td, NULL, NULL); + *pbkOpt = nssPublicKey_CreateFromInstance(bkey, creator->td, NULL); if (!*pbkOpt) { goto loser; } - *pvkOpt = nssPrivateKey_CreateFromInstance(vkey, creator->td, NULL, NULL); + *pvkOpt = nssPrivateKey_CreateFromInstance(vkey, creator->td, NULL); if (!*pvkOpt) { goto loser; } diff --git a/security/nss/lib/pki/pkidb.c b/security/nss/lib/pki/pkidb.c new file mode 100644 index 000000000..814c16a22 --- /dev/null +++ b/security/nss/lib/pki/pkidb.c @@ -0,0 +1,924 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License") +{ +} you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#ifdef DEBUG +static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; +#endif /* DEBUG */ + +#include "mcom_db.h" + +#ifndef BASE_H +#include "base.h" +#endif /* BASE_H */ + +#ifndef PKIM_H +#include "pkim.h" +#endif /* PKIM_H */ + +#define DBM_DEFAULT 0 +#define DBS_BLOCK_SIZE (16*1024) /* XXX not doing blobbing yet */ +#define DBS_CACHE_SIZE (DBS_BLOCK_SIZE * 8) + +static const HASHINFO s_db_hash_info = { + DBS_BLOCK_SIZE, /* bucket size, must be greater than = to + * or maximum record size (+ header) + * we allow before blobing + */ + DBM_DEFAULT, /* Fill Factor */ + DBM_DEFAULT, /* number of elements */ + DBS_CACHE_SIZE, /* cache size */ + DBM_DEFAULT, /* hash function */ + DBM_DEFAULT, /* byte order */ +}; + +struct nssPKIDatabaseStr +{ + NSSTrustDomain *td; + PZLock *lock; + DB *db; +}; + +#define PKIDB_VERSION 10 + +#define ROWID_CERT_HEADER 1 +#define ROWID_SUBJECT_HEADER 2 +#define ROWID_NICKNAME_HEADER 3 +#define ROWID_EMAIL_HEADER 4 + +#define PKIDB_IS_CERT_RECORD(rowID) \ + (((unsigned char *)(rowID)->data)[0] == ROWID_CERT_HEADER) + +#define PAYLOAD_HEADER_LENGTH 3 +#define PAYLOAD_CERT_HEADER 1 +#define PAYLOAD_SUBJECT_HEADER 2 +#define PAYLOAD_NICKNAME_HEADER 3 +#define PAYLOAD_EMAIL_HEADER 4 + +#define CERT_PAYLOAD_TRUST_OFFSET PAYLOAD_HEADER_LENGTH +#define TRUST_RECORD_LENGTH 16 + +#define SET_DBT_BYTE(dbt, index, val) \ + ((unsigned char *)(dbt)->data)[index] = val + +#define SET_DBT_INT(dbt, index, num) \ + nsslibc_memcpy(((unsigned char *)(dbt)->data) + index, &num, sizeof(num)) + +#define SET_DBT_BUF(dbt, index, buf, len) \ + nsslibc_memcpy(((unsigned char *)(dbt)->data) + index, buf, len) + +#define SET_DBT_ITEM(dbt, index, it) \ + nsslibc_memcpy(((unsigned char *)(dbt)->data) + index, \ + (it)->data, (it)->size) + +#define GET_DBT_INT(dbt, index, num) \ + num = *(PRUint32 *)(((unsigned char *)(dbt)->data) + index) + +#define GET_DBT_BUF(dbt, index, buf) \ + buf = ((unsigned char *)(dbt)->data) + index + +static PRStatus +write_record(nssPKIDatabase *pkidb, DBT *rowID, DBT *payload) +{ + int dberr; + PZ_Lock(pkidb->lock); + dberr = pkidb->db->put(pkidb->db, rowID, payload, 0); + PZ_Unlock(pkidb->lock); + return (dberr == 0) ? PR_SUCCESS : PR_FAILURE; +} + +static PRStatus +delete_record(nssPKIDatabase *pkidb, DBT *rowID) +{ + int dberr; + PZ_Lock(pkidb->lock); + dberr = pkidb->db->del(pkidb->db, rowID, 0); + PZ_Unlock(pkidb->lock); + return (dberr == 0) ? PR_SUCCESS : PR_FAILURE; +} + +static PRStatus +make_cert_rowid_from_issuer_serial(DBT *rowID, + NSSBER *issuer, NSSBER *serial, + NSSArena *arenaOpt) +{ + int i; + rowID->size = 1 + issuer->size + serial->size; + rowID->data = nss_ZAlloc(arenaOpt, rowID->size); + if (!rowID->data) { + return PR_FAILURE; + } + i = 0; + SET_DBT_BYTE(rowID, 0, ROWID_CERT_HEADER); i++; + SET_DBT_ITEM(rowID, i, issuer); i += issuer->size; + SET_DBT_ITEM(rowID, i, serial); i += serial->size; + return PR_SUCCESS; +} + +static PRStatus +make_cert_rowid(DBT *rowID, NSSCert *cert, NSSArena *arenaOpt) +{ + NSSBER *issuer, *serial; + issuer = nssCert_GetIssuer(cert); + serial = nssCert_GetSerialNumber(cert); + return make_cert_rowid_from_issuer_serial(rowID, issuer, serial, arenaOpt); +} + +static PRStatus +write_cert_record(nssPKIDatabase *pkidb, DBT *rowID, NSSCert *certOpt, + NSSUTF8 *nicknameOpt, nssTrust *trustOpt, + NSSArena *arena) +{ + DBT payload; + NSSBER *ber; + PRUint32 size; + PRUint32 berSize; + PRUint32 nicknameLen; + int i; + + if (certOpt) { + ber = nssCert_GetEncoding(certOpt); + berSize = ber->size; + } else { + berSize = 0; + } + nicknameLen = nicknameOpt ? nssUTF8_Length(nicknameOpt, NULL) : 0; + + payload.size = PAYLOAD_HEADER_LENGTH + + TRUST_RECORD_LENGTH + + 4 + berSize + + 4 + nicknameLen; + + payload.data = nss_ZAlloc(arena, payload.size); + if (!payload.data) { + return PR_FAILURE; + } + + /* HEADER */ + i = 0; + SET_DBT_BYTE(&payload, i, PKIDB_VERSION); i++; + SET_DBT_BYTE(&payload, i, PAYLOAD_CERT_HEADER); i++; + SET_DBT_BYTE(&payload, i, 0); i++; /* flags */ + /* TRUST */ + if (trustOpt) { + SET_DBT_INT(&payload, i, trustOpt->trustedUsages.ca); i += 4; + SET_DBT_INT(&payload, i, trustOpt->trustedUsages.peer); i += 4; + SET_DBT_INT(&payload, i, trustOpt->notTrustedUsages.ca); i += 4; + SET_DBT_INT(&payload, i, trustOpt->notTrustedUsages.peer); i += 4; + } else { + i += TRUST_RECORD_LENGTH; /* skip it */ + } + /* BER size */ + size = PR_htonl(berSize); + SET_DBT_INT(&payload, i, size); i += 4; + /* nickname length */ + size = PR_htonl(nicknameLen); + SET_DBT_INT(&payload, i, size); i += 4; + /* BER data */ + if (certOpt) { + SET_DBT_ITEM(&payload, i, ber); i += berSize; + } + /* nickname */ + if (nicknameOpt) { + SET_DBT_BUF(&payload, i, nicknameOpt, nicknameLen); i += nicknameLen; + } + /* always overwrite? */ + return write_record(pkidb, rowID, &payload); +} + +static PRStatus +decode_cert_payload(DBT *payload, NSSBER *ber, NSSItem *nick, + nssTrust *trustOpt) +{ + int i; + PRUint32 size; + + i = PAYLOAD_HEADER_LENGTH; /* skip the header */ + if (trustOpt) { + GET_DBT_INT(payload, i, trustOpt->trustedUsages.ca); i += 4; + GET_DBT_INT(payload, i, trustOpt->trustedUsages.peer); i += 4; + GET_DBT_INT(payload, i, trustOpt->notTrustedUsages.ca); i += 4; + GET_DBT_INT(payload, i, trustOpt->notTrustedUsages.peer); i += 4; + } else { + i += TRUST_RECORD_LENGTH; /* skip it */ + } + GET_DBT_INT(payload, i, size); i += 4; + ber->size = PR_ntohl(size); + GET_DBT_INT(payload, i, size); i += 4; + nick->size = PR_ntohl(size); + if (ber->size > 0) { + GET_DBT_BUF(payload, i, ber->data); i += ber->size; + } + if (nick->size > 0) { + GET_DBT_BUF(payload, i, nick->data); i += nick->size; + } + return PR_SUCCESS; +} + +static PRStatus +make_subject_rowid(DBT *rowID, NSSBER *subject, NSSArena *arenaOpt) +{ + int i; + rowID->size = 1 + subject->size; + rowID->data = nss_ZAlloc(arenaOpt, rowID->size); + if (!rowID->data) { + return PR_FAILURE; + } + i = 0; + SET_DBT_BYTE(rowID, 0, ROWID_SUBJECT_HEADER); i++; + SET_DBT_ITEM(rowID, i, subject); i += subject->size; + return PR_SUCCESS; +} + +static PRStatus +write_subject_record(nssPKIDatabase *pkidb, DBT *rowID, + NSSCert *cert, NSSArena *arena) +{ + DBT certRowID, payload, oldPayload; + int dberr; + PRUint32 size; + PRBool haveRecord; + int i, j, numCerts, numOldCerts; + + PZ_Lock(pkidb->lock); + dberr = pkidb->db->get(pkidb->db, rowID, &payload, 0); + PZ_Unlock(pkidb->lock); + if (dberr < 0) { + return PR_FAILURE; + } + haveRecord = (dberr == 0) ? PR_TRUE : PR_FALSE; + + /* XXX redundant */ + make_cert_rowid(&certRowID, cert, arena); + if (haveRecord) { + payload.size = 4 + certRowID.size + oldPayload.size; + } else { + payload.size = PAYLOAD_HEADER_LENGTH + + 4 + + 4 + certRowID.size; + } + + payload.data = nss_ZAlloc(arena, payload.size); + if (!payload.data) { + nss_ZFreeIf(certRowID.data); + return PR_FAILURE; + } + + /* HEADER */ + i = 0; + SET_DBT_BYTE(&payload, i, PKIDB_VERSION); i++; + SET_DBT_BYTE(&payload, i, PAYLOAD_SUBJECT_HEADER); i++; + SET_DBT_BYTE(&payload, i, 0); i++; /* flags */ + /* # of cert rowIDs */ + if (haveRecord) { + GET_DBT_INT(&payload, i, numOldCerts); j += 4; + } else { + numOldCerts = 0; + } + numCerts = PR_htonl(numOldCerts + 1); + SET_DBT_INT(&payload, i, numCerts); i += 4; + /* lengths of cert rowIDs */ + if (haveRecord) { + unsigned char *oldLengths; + GET_DBT_BUF(&oldPayload, i, oldLengths); + SET_DBT_BUF(&payload, i, oldLengths, 4 * numOldCerts); + i += 4 * numOldCerts; + } + size = PR_htonl(certRowID.size); + SET_DBT_INT(&payload, i, size); i += 4; + /* cert rowIDs */ + if (haveRecord) { + unsigned char *oldCertRowIDs; + int j = i - 4; /* -4 because we added one length */ + int remaining = oldPayload.size - j; + GET_DBT_BUF(&oldPayload, j, oldCertRowIDs); + SET_DBT_BUF(&payload, i, oldCertRowIDs, remaining); + i += remaining; + } + SET_DBT_ITEM(&payload, i, &certRowID); i += certRowID.size; + nss_ZFreeIf(certRowID.data); + return write_record(pkidb, rowID, &payload); +} + +static NSSCert * +get_cert_from_rowid(nssPKIDatabase *pkidb, DBT *rowID) +{ + DBT payload; + int dberr; + PRStatus status; + NSSBER ber, nick; + nssTrust trust; + NSSCert *cert = NULL; + + PZ_Lock(pkidb->lock); + dberr = pkidb->db->get(pkidb->db, rowID, &payload, 0); + PZ_Unlock(pkidb->lock); + + if (dberr == 0) { + status = decode_cert_payload(&payload, &ber, &nick, &trust); + if (status == PR_SUCCESS) { + cert = nssCert_Decode(&ber, &nick, &trust, pkidb->td, NULL); + } + } + return cert; +} + +static PRUint32 +get_num_certs_from_subject_payload(DBT *payload) +{ + PRUint32 numCerts; + GET_DBT_INT(payload, PAYLOAD_HEADER_LENGTH, numCerts); + numCerts = PR_ntohl(numCerts); + return numCerts; +} + +static PRStatus +get_cert_rowid_from_subject_payload(DBT *payload, int i, int *last, + int numCerts, DBT *rowID) +{ + int offset = PAYLOAD_HEADER_LENGTH + 4 + 4 * i; + GET_DBT_INT(payload, offset, rowID->size); + rowID->size = PR_ntohl(rowID->size); + if (*last == 0) { + offset = PAYLOAD_HEADER_LENGTH + 4 + 4 * numCerts; + } else { + offset = *last; + } + GET_DBT_BUF(payload, offset, rowID->data); + *last += rowID->size; + return PR_SUCCESS; +} + +static NSSCert ** +get_certs_from_subject_record(nssPKIDatabase *pkidb, DBT *subjectRowID, + NSSArena *arenaOpt) +{ + DBT payload, certRowID; + int dberr; + PRStatus status; + NSSCert **certs = NULL; + int i, last = 0; + int numCerts; + + PZ_Lock(pkidb->lock); + dberr = pkidb->db->get(pkidb->db, subjectRowID, &payload, 0); + PZ_Unlock(pkidb->lock); + + if (dberr == 0) { + numCerts = get_num_certs_from_subject_payload(&payload); + if (numCerts == 0) { + return (NSSCert **)NULL; + } + certs = nss_ZNEWARRAY(arenaOpt, NSSCert *, numCerts + 1); + if (!certs) { + return (NSSCert **)NULL; + } + for (i = 0; i < numCerts; i++) { + status = get_cert_rowid_from_subject_payload(&payload, i, + &last, numCerts, + &certRowID); + if (status == PR_SUCCESS) { + certs[i] = get_cert_from_rowid(pkidb, &certRowID); + if (!certs[i]) { + break; + } + } else { + break; + } + } + } + return certs; +} + +static PRStatus +make_nickname_rowid(DBT *rowID, NSSUTF8 *nickname, NSSArena *arenaOpt) +{ + int i; + PRUint32 nickLen = nssUTF8_Length(nickname, NULL); + rowID->size = 1 + nickLen; + rowID->data = nss_ZAlloc(arenaOpt, rowID->size); + if (!rowID->data) { + return PR_FAILURE; + } + i = 0; + SET_DBT_BYTE(rowID, 0, ROWID_NICKNAME_HEADER); i++; + SET_DBT_BUF( rowID, i, nickname, nickLen); i += nickLen; + return PR_SUCCESS; +} + +static PRStatus +write_nickname_record(nssPKIDatabase *pkidb, DBT *rowID, NSSCert *cert, + NSSArena *arena) +{ + DBT payload; + DBT subjectRowID; + PRStatus status; + NSSBER *berSubject; + PRUint32 size; + int i; + + berSubject = nssCert_GetSubject(cert); + status = make_subject_rowid(&subjectRowID, berSubject, arena); + if (status == PR_FAILURE) { + return status; + } + + payload.size = PAYLOAD_HEADER_LENGTH + 4 + 1 + berSubject->size; + + payload.data = nss_ZAlloc(arena, payload.size); + if (!payload.data) { + return PR_FAILURE; + } + + /* HEADER */ + i = 0; + SET_DBT_BYTE(&payload, i, PKIDB_VERSION); i++; + SET_DBT_BYTE(&payload, i, PAYLOAD_NICKNAME_HEADER); i++; + SET_DBT_BYTE(&payload, i, 0); i++; /* flags */ + /* BER subject size */ + size = PR_htonl(subjectRowID.size); + SET_DBT_INT(&payload, i, size); i += 4; + /* BER subject data */ + SET_DBT_ITEM(&payload, i, &subjectRowID); i += subjectRowID.size; + /* always overwrite? */ + return write_record(pkidb, rowID, &payload); +} + +static NSSCert ** +get_certs_from_nickname_record(nssPKIDatabase *pkidb, DBT *rowID, + NSSArena *arenaOpt) +{ + DBT payload; + DBT subjectRowID; + int dberr; + + PZ_Lock(pkidb->lock); + dberr = pkidb->db->get(pkidb->db, rowID, &payload, 0); + PZ_Unlock(pkidb->lock); + + if (dberr == 0) { + int i = 0; + i += PAYLOAD_HEADER_LENGTH; + GET_DBT_INT(&payload, i, subjectRowID.size); i += 4; + subjectRowID.size = PR_ntohl(subjectRowID.size); + GET_DBT_BUF(&payload, i, subjectRowID.data); i += subjectRowID.size; + return get_certs_from_subject_record(pkidb, &subjectRowID, arenaOpt); + } + return (NSSCert **)NULL; +} + +/* XXX needs nickname fixes above */ +static PRStatus +make_email_rowid(DBT *rowID, NSSASCII7 *email, NSSArena *arenaOpt) +{ + int i; + PRUint32 emailLen = nssUTF8_Length(email, NULL); + rowID->size = 1 + emailLen; + rowID->data = nss_ZAlloc(arenaOpt, rowID->size); + if (!rowID->data) { + return PR_FAILURE; + } + i = 0; + SET_DBT_BYTE(rowID, 0, ROWID_EMAIL_HEADER); i++; + SET_DBT_BUF( rowID, i, email, emailLen); i += emailLen; + return PR_SUCCESS; +} + +static NSSCert ** +get_certs_from_email_record(nssPKIDatabase *pkidb, DBT *rowID, + NSSArena *arenaOpt) +{ + DBT payload; + int dberr; + + PZ_Lock(pkidb->lock); + dberr = pkidb->db->get(pkidb->db, rowID, &payload, 0); + PZ_Unlock(pkidb->lock); + + if (dberr == 0) { + return get_certs_from_subject_record(pkidb, &payload, arenaOpt); + } + return (NSSCert **)NULL; +} + +#define DB_RDONLY O_RDONLY +#define DB_RDWR O_RDWR +#define DB_CREATE O_CREAT +#define PKIDB_FLAGS_READ_ONLY 1 + +NSS_IMPLEMENT nssPKIDatabase * +nssPKIDatabase_Open ( + NSSTrustDomain *td, + const NSSUTF8 *path, + PRUint32 flags +) +{ + nssPKIDatabase *rvDB; + PRIntn dbFlags; + const char *dbName = "certX.db"; /* XXX */ + char *filename; + PRUint32 pathLen, dbNameLen; + + pathLen = nssUTF8_Length(path, NULL); + dbNameLen = nssUTF8_Length(dbName, NULL); + filename = nss_ZAlloc(NULL, pathLen + dbNameLen + 2); + if (!filename) { + return (nssPKIDatabase *)NULL; + } + nsslibc_memcpy(filename, path, pathLen); + filename[pathLen] = '/'; + nsslibc_memcpy(filename + pathLen + 1, dbName, dbNameLen); + filename[pathLen + 1 + dbNameLen] = '\0'; + + rvDB = nss_ZNEW(NULL, nssPKIDatabase); + if (!rvDB) { + nssUTF8_Destroy(filename); + return (nssPKIDatabase *)NULL; + } + + rvDB->lock = PZ_NewLock(nssILockOther); + if (!rvDB) { + nssUTF8_Destroy(filename); + nss_ZFreeIf(rvDB); + return (nssPKIDatabase *)NULL; + } + + dbFlags = (flags & PKIDB_FLAGS_READ_ONLY) ? DB_RDONLY : DB_RDWR; + dbFlags |= DB_CREATE; /* always? */ + + rvDB->db = dbopen(filename, dbFlags, 0600, DB_HASH, &s_db_hash_info); + if (!rvDB->db) { + nssUTF8_Destroy(filename); + PZ_DestroyLock(rvDB->lock); + nss_ZFreeIf(rvDB); + return (nssPKIDatabase *)NULL; + } + rvDB->td = td; + return rvDB; +} + +NSS_IMPLEMENT PRStatus +nssPKIDatabase_Close ( + nssPKIDatabase *pkidb +) +{ + pkidb->db->close(pkidb->db); + PZ_DestroyLock(pkidb->lock); + nss_ZFreeIf(pkidb); + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssPKIDatabase_ImportCert ( + nssPKIDatabase *pkidb, + NSSCert *cert, + NSSUTF8 *nicknameOpt, + nssTrust *trustOpt +) +{ + DBT rowID; + PRStatus status; + NSSArena *tmparena; + NSSBER *subject; + NSSUTF8 *nickname; + + tmparena = nssArena_Create(); + if (!tmparena) { + return PR_FAILURE; + } + + status = make_cert_rowid(&rowID, cert, tmparena); + if (status == PR_FAILURE) { + goto cleanup; + } + status = write_cert_record(pkidb, &rowID, cert, + nicknameOpt, trustOpt, tmparena); + if (status == PR_FAILURE) { + goto cleanup; + } + + subject = nssCert_GetSubject(cert); + status = make_subject_rowid(&rowID, subject, tmparena); + if (status == PR_FAILURE) { + goto cleanup; + } + status = write_subject_record(pkidb, &rowID, cert, tmparena); + if (status == PR_FAILURE) { + goto cleanup; + } + + nickname = nicknameOpt ? nicknameOpt : nssCert_GetNickname(cert, NULL); + if (nickname) { + status = make_nickname_rowid(&rowID, nickname, tmparena); + if (status == PR_FAILURE) { + goto cleanup; + } + status = write_nickname_record(pkidb, &rowID, cert, tmparena); + if (status == PR_FAILURE) { + goto cleanup; + } + } + +cleanup: + nssArena_Destroy(tmparena); + return status; +} + +NSS_IMPLEMENT PRStatus +nssPKIDatabase_DeleteCert ( + nssPKIDatabase *pkidb, + NSSCert *cert +) +{ + DBT rowID; + PRStatus status; + + status = make_cert_rowid(&rowID, cert, NULL); + if (status == PR_FAILURE) { + return PR_FAILURE; + } + + status = delete_record(pkidb, &rowID); + + nss_ZFreeIf(rowID.data); + return status; +} + +NSS_IMPLEMENT PRStatus +nssPKIDatabase_SetCertTrust ( + nssPKIDatabase *pkidb, + NSSCert *cert, + nssTrust *trust +) +{ + DBT rowID, payload; + int dberr; + PRStatus status; + NSSArena *tmparena; + + tmparena = nssArena_Create(); + if (!tmparena) { + return PR_FAILURE; + } + + status = make_cert_rowid(&rowID, cert, tmparena); + if (status == PR_FAILURE) { + nssArena_Destroy(tmparena); + return PR_FAILURE; + } + + /* look up the cert record */ + PZ_Lock(pkidb->lock); + dberr = pkidb->db->get(pkidb->db, &rowID, &payload, 0); + PZ_Unlock(pkidb->lock); + + if (dberr == 0) { + /* cert already present, set the new trust value */ + PRUint32 i = CERT_PAYLOAD_TRUST_OFFSET; + DBT tmp; + /* XXX apparently, I must copy the dbt before writing. how lame. */ + tmp.data = nss_ZAlloc(NULL, payload.size); + nsslibc_memcpy(tmp.data, payload.data, payload.size); + tmp.size = payload.size; + payload = tmp; + SET_DBT_INT(&payload, i, trust->trustedUsages.ca); i += 4; + SET_DBT_INT(&payload, i, trust->trustedUsages.peer); i += 4; + SET_DBT_INT(&payload, i, trust->notTrustedUsages.ca); i += 4; + SET_DBT_INT(&payload, i, trust->notTrustedUsages.peer); i += 4; + status = write_record(pkidb, &rowID, &payload); + nss_ZFreeIf(tmp.data); + } else if (dberr == 1) { + /* cert is not present, create a new record */ + NSSUTF8 *nickname = nssCert_GetNickname(cert, NULL); + status = write_cert_record(pkidb, &rowID, cert, + nickname, trust, tmparena); + } else { + /* db failed */ + status = PR_FAILURE; + } + nssArena_Destroy(tmparena); + return status; +} + +/* +NSS_IMPLEMENT PRStatus +nssPKIDatabase_DeleteCertTrust ( + nssPKIDatabase *pkidb, + NSSCert *cert +) +{ +} +*/ + +NSS_IMPLEMENT NSSCert ** +nssPKIDatabase_FindCertsBySubject ( + nssPKIDatabase *pkidb, + NSSBER *subject, + NSSCert **rvOpt, + PRUint32 maximumOpt, + NSSArena *arenaOpt +) +{ + DBT rowID; + PRStatus status; + NSSCert **certs; + + status = make_subject_rowid(&rowID, subject, NULL); + if (status == PR_SUCCESS) { + certs = get_certs_from_subject_record(pkidb, &rowID, arenaOpt); + nss_ZFreeIf(rowID.data); + } + return certs; +} + +NSS_IMPLEMENT NSSCert ** +nssPKIDatabase_FindCertsByNickname ( + nssPKIDatabase *pkidb, + NSSUTF8 *nickname, + NSSCert **rvOpt, + PRUint32 maximumOpt, + NSSArena *arenaOpt +) +{ + DBT rowID; + PRStatus status; + NSSCert **certs; + + status = make_nickname_rowid(&rowID, nickname, NULL); + if (status == PR_SUCCESS) { + certs = get_certs_from_nickname_record(pkidb, &rowID, arenaOpt); + nss_ZFreeIf(rowID.data); + } + return certs; +} + +NSS_IMPLEMENT NSSCert ** +nssPKIDatabase_FindCertsByEmail ( + nssPKIDatabase *pkidb, + NSSASCII7 *email, + NSSCert **rvOpt, + PRUint32 maximumOpt, + NSSArena *arenaOpt +) +{ + DBT rowID; + PRStatus status; + NSSCert **certs; + + status = make_email_rowid(&rowID, email, NULL); + if (status == PR_SUCCESS) { + certs = get_certs_from_email_record(pkidb, &rowID, arenaOpt); + nss_ZFreeIf(rowID.data); + } + return certs; +} + +NSS_IMPLEMENT NSSCert * +nssPKIDatabase_FindCertByIssuerAndSerialNumber ( + nssPKIDatabase *pkidb, + NSSBER *issuer, + NSSBER *serial +) +{ + DBT rowID; + PRStatus status; + NSSCert *cert = NULL; + + status = make_cert_rowid_from_issuer_serial(&rowID, issuer, serial, NULL); + if (status == PR_SUCCESS) { + cert = get_cert_from_rowid(pkidb, &rowID); + nss_ZFreeIf(rowID.data); + } + return cert; +} + +/* d'oh! */ +struct match_encoded_cert_str { NSSCert *cert; NSSBER *ber; }; + +static PRStatus match_encoded_cert(NSSCert *cert, void *arg) +{ + struct match_encoded_cert_str *me = (struct match_encoded_cert_str *)arg; + NSSBER *certBER = nssCert_GetEncoding(cert); + if (nssItem_Equal(me->ber, certBER, NULL)) { + me->cert = nssCert_AddRef(cert); + } + return PR_SUCCESS; +} + +NSS_IMPLEMENT NSSCert * +nssPKIDatabase_FindCertByEncodedCert ( + nssPKIDatabase *pkidb, + NSSBER *ber +) +{ + struct match_encoded_cert_str me; + me.cert = NULL; + me.ber = ber; + nssPKIDatabase_TraverseCerts(pkidb, match_encoded_cert, &me); + return me.cert; +} + +NSS_IMPLEMENT PRStatus +nssPKIDatabase_FindTrustForCert ( + nssPKIDatabase *pkidb, + NSSCert *cert, + nssTrust *rvTrust +) +{ + DBT rowID, payload; + int dberr; + PRStatus status; + + status = make_cert_rowid(&rowID, cert, NULL); + if (status == PR_FAILURE) { + return PR_FAILURE; + } + + /* look up the cert record */ + PZ_Lock(pkidb->lock); + dberr = pkidb->db->get(pkidb->db, &rowID, &payload, 0); + PZ_Unlock(pkidb->lock); + + if (dberr == 0) { + /* cert already present, set the new trust value */ + PRUint32 i = CERT_PAYLOAD_TRUST_OFFSET; + GET_DBT_INT(&payload, i, rvTrust->trustedUsages.ca); i += 4; + GET_DBT_INT(&payload, i, rvTrust->trustedUsages.peer); i += 4; + GET_DBT_INT(&payload, i, rvTrust->notTrustedUsages.ca); i += 4; + GET_DBT_INT(&payload, i, rvTrust->notTrustedUsages.peer); i += 4; + status = PR_SUCCESS; + } else { + nsslibc_memset(rvTrust, 0, sizeof(*rvTrust)); + status = PR_FAILURE; + } + nss_ZFreeIf(rowID.data); + return status; +} + +NSS_IMPLEMENT PRStatus +nssPKIDatabase_TraverseCerts ( + nssPKIDatabase *pkidb, + PRStatus (*callback)(NSSCert *c, void *arg), + void *arg +) +{ + DBT rowID, payload; + int dberr; + PRStatus status = PR_SUCCESS; + NSSBER ber, nick; + nssTrust trust; + NSSCert *cert; + + PZ_Lock(pkidb->lock); + dberr = pkidb->db->seq(pkidb->db, &rowID, &payload, R_FIRST); + while (dberr == 0) { + if (PKIDB_IS_CERT_RECORD(&rowID)) { + status = decode_cert_payload(&payload, &ber, &nick, &trust); + if (status == PR_SUCCESS) { + cert = nssCert_Decode(&ber, &nick, &trust, pkidb->td, NULL); + if (cert) { + status = (*callback)(cert, arg); + if (status == PR_FAILURE) { + break; /* allow for early termination */ + } + } /* else ? */ + } /* else ? */ + } + dberr = pkidb->db->seq(pkidb->db, &rowID, &payload, R_NEXT); + } + PZ_Unlock(pkidb->lock); + + return status; +} + diff --git a/security/nss/lib/pki/pkim.h b/security/nss/lib/pki/pkim.h index a2248df6d..f3047db8d 100644 --- a/security/nss/lib/pki/pkim.h +++ b/security/nss/lib/pki/pkim.h @@ -64,7 +64,7 @@ PR_BEGIN_EXTERN_C * nssPKIObject_AddInstance * nssPKIObject_HasInstance * nssPKIObject_GetTokens - * nssPKIObject_IsOnToken + * nssPKIObject_HasInstanceOnToken * nssPKIObject_SetNickname * nssPKIObject_GetNickname * nssPKIObject_RemoveInstanceForToken @@ -78,12 +78,14 @@ PR_BEGIN_EXTERN_C */ NSS_EXTERN nssPKIObject * nssPKIObject_Create ( - NSSArena *arenaOpt, - nssCryptokiObject *instanceOpt, NSSTrustDomain *td, - NSSVolatileDomain *vdOpt + nssCryptokiObject *instanceOpt, + PRUint32 size ); +#define nssPKIObject_CREATE(td, instanceOpt, type) \ + (type *)nssPKIObject_Create(td, instanceOpt, sizeof(type)) + /* nssPKIObject_AddRef */ NSS_EXTERN nssPKIObject * @@ -139,7 +141,7 @@ nssPKIObject_GetTokens ( ); NSS_EXTERN PRBool -nssPKIObject_IsOnToken ( +nssPKIObject_HasInstanceOnToken ( nssPKIObject *object, NSSToken *token ); @@ -237,6 +239,26 @@ nssTrustDomain_FindSourceToken ( NSSToken *candidate ); +/* XXX */ +NSS_EXTERN nssSession * +nssTrustDomain_GetSessionForToken ( + NSSTrustDomain *td, + NSSToken *token, + PRBool readWrite +); + +/* XXX */ +NSS_EXTERN NSSSlot ** +nssTrustDomain_GetActiveSlots ( + NSSTrustDomain *td, + nssUpdateLevel *updateLevel +); + +NSS_EXTERN nssPKIObjectTable * +nssTrustDomain_GetObjectTable ( + NSSTrustDomain *td +); + NSS_EXTERN NSSCert ** nssTrustDomain_FindCertsByID ( NSSTrustDomain *td, @@ -246,12 +268,25 @@ nssTrustDomain_FindCertsByID ( NSSArena *arenaOpt ); +NSS_EXTERN NSSPrivateKey * +nssTrustDomain_FindPrivateKeyByID ( + NSSTrustDomain *td, + NSSItem *keyID +); + NSS_EXTERN NSSCRL ** nssTrustDomain_FindCRLsBySubject ( NSSTrustDomain *td, NSSDER *subject ); +NSS_EXTERN PRStatus +nssTrustDomain_SetCertTrust ( + NSSTrustDomain *td, + NSSCert *c, + nssTrust *trust +); + /* module-private nsspki methods */ NSS_EXTERN NSSCryptoContext * @@ -276,18 +311,11 @@ nssCryptoContext_CreateForPrivateKey ( NSSCallback *uhhOpt ); -/* XXX for the collection */ -NSS_EXTERN NSSCert * -nssCert_Create ( - nssPKIObject *object -); - NSS_EXTERN NSSCert * nssCert_CreateFromInstance ( nssCryptokiObject *instance, NSSTrustDomain *td, - NSSVolatileDomain *vdOpt, - NSSArena *arenaOpt + NSSVolatileDomain *vdOpt ); /* XXX XXX most of these belong in pki.h */ @@ -338,16 +366,6 @@ nssCert_HasCANameInChain ( NSSPolicies *policiesOpt ); -NSS_EXTERN nssTrust * -nssTrust_Create ( - nssPKIObject *object -); - -NSS_EXTERN NSSCRL * -nssCRL_Create ( - nssPKIObject *object -); - NSS_EXTERN NSSCRL * nssCRL_AddRef ( NSSCRL *crl @@ -365,11 +383,6 @@ nssCRL_DeleteStoredObject ( ); NSS_EXTERN NSSSymKey * -nssSymKey_Create ( - nssPKIObject *object -); - -NSS_EXTERN NSSSymKey * nssSymKey_CreateFromInstance ( nssCryptokiObject *instance, NSSTrustDomain *td, @@ -381,6 +394,12 @@ nssSymKey_Destroy ( NSSSymKey *mk ); +NSS_EXTERN void +nssSymKey_SetVolatileDomain ( + NSSSymKey *mk, + NSSVolatileDomain *vd +); + NSS_IMPLEMENT nssCryptokiObject * nssSymKey_CopyToToken ( NSSSymKey *mk, @@ -403,7 +422,7 @@ nssSymKey_GetTrustDomain ( ); NSS_EXTERN PRBool -nssSymKey_IsOnToken ( +nssSymKey_HasInstanceOnToken ( NSSSymKey *mk, NSSToken *token ); @@ -426,11 +445,6 @@ nssCRL_GetEncoding ( ); NSS_EXTERN NSSPublicKey * -nssPublicKey_Create ( - nssPKIObject *object -); - -NSS_EXTERN NSSPublicKey * nssPublicKey_CreateFromInfo ( NSSTrustDomain *td, NSSVolatileDomain *vdOpt, @@ -442,12 +456,17 @@ NSS_EXTERN NSSPublicKey * nssPublicKey_CreateFromInstance ( nssCryptokiObject *instance, NSSTrustDomain *td, - NSSVolatileDomain *vdOpt, - NSSArena *arenaOpt + NSSVolatileDomain *vdOpt +); + +NSS_EXTERN void +nssPublicKey_SetVolatileDomain ( + NSSPublicKey *bk, + NSSVolatileDomain *vd ); NSS_EXTERN PRBool -nssPublicKey_IsOnToken ( +nssPublicKey_HasInstanceOnToken ( NSSPublicKey *bk, NSSToken *token ); @@ -464,6 +483,17 @@ nssPublicKey_FindInstanceForAlgorithm ( const NSSAlgNParam *ap ); +NSS_EXTERN PRStatus +nssPublicKey_RemoveInstanceForToken ( + NSSPublicKey *bk, + NSSToken *token +); + +NSS_EXTERN PRIntn +nssPublicKey_CountInstances ( + NSSPublicKey *bk +); + NSS_EXTERN nssCryptokiObject * nssPublicKey_CopyToToken ( NSSPublicKey *bk, @@ -472,12 +502,20 @@ nssPublicKey_CopyToToken ( ); NSS_EXTERN NSSPrivateKey * -nssPrivateKey_Create ( - nssPKIObject *o +nssPrivateKey_CreateFromInstance ( + nssCryptokiObject *instance, + NSSTrustDomain *td, + NSSVolatileDomain *vdOpt +); + +NSS_EXTERN void +nssPrivateKey_SetVolatileDomain ( + NSSPrivateKey *vk, + NSSVolatileDomain *vd ); NSS_EXTERN PRBool -nssPrivateKey_IsOnToken ( +nssPrivateKey_HasInstanceOnToken ( NSSPrivateKey *vk, NSSToken *token ); @@ -494,16 +532,26 @@ nssPrivateKey_FindInstanceForAlgorithm ( const NSSAlgNParam *ap ); +NSS_EXTERN PRStatus +nssPrivateKey_RemoveInstanceForToken ( + NSSPrivateKey *vk, + NSSToken *token +); + +NSS_EXTERN PRIntn +nssPrivateKey_CountInstances ( + NSSPrivateKey *vk +); + NSS_EXTERN nssCryptokiObject * nssPrivateKey_CopyToToken ( NSSPrivateKey *vk, NSSToken *destination ); -NSS_EXTERN PRBool -nssUsages_Match ( - const NSSUsages *usages, - const NSSUsages *testUsages +NSS_EXTERN PRIntn +nssObjectArray_Count ( + void **objects ); /* nssCertArray @@ -586,173 +634,19 @@ nssCRLArray_Destroy ( NSSCRL **crls ); -/* nssPKIObjectCollection - * - * This is a handy way to group objects together and perform operations - * on them. It can also handle "proto-objects"-- references to - * objects instances on tokens, where the actual object hasn't - * been formed yet. - * - * nssCertCollection_Create - * nssPrivateKeyCollection_Create - * nssPublicKeyCollection_Create - * - * If this was a language that provided for inheritance, each type would - * inherit all of the following methods. Instead, there is only one - * type (nssPKIObjectCollection), shared among all. This may cause - * confusion; an alternative would be to define all of the methods - * for each subtype (nssCertCollection_Destroy, ...), but that doesn't - * seem worth the code bloat.. It is left up to the caller to remember - * what type of collection he/she is dealing with. - * - * nssPKIObjectCollection_Destroy - * nssPKIObjectCollection_Count - * nssPKIObjectCollection_AddObject - * nssPKIObjectCollection_AddInstances - * nssPKIObjectCollection_Traverse - * - * Back to type-specific methods. - * - * nssPKIObjectCollection_GetCerts - * nssPKIObjectCollection_GetCRLs - * nssPKIObjectCollection_GetPrivateKeys - * nssPKIObjectCollection_GetPublicKeys - */ - -/* nssCertCollection_Create - * - * Create a collection of certificates in the specified trust domain. - * Optionally provide a starting set of certs. - */ -NSS_EXTERN nssPKIObjectCollection * -nssCertCollection_Create ( - NSSTrustDomain *td, - NSSCert **certsOpt -); - -/* nssCRLCollection_Create - * - * Create a collection of CRLs/KRLs in the specified trust domain. - * Optionally provide a starting set of CRLs. - */ -NSS_EXTERN nssPKIObjectCollection * -nssCRLCollection_Create ( - NSSTrustDomain *td, - NSSCRL **crlsOpt -); - -/* nssPrivateKeyCollection_Create - * - * Create a collection of private keys in the specified trust domain. - * Optionally provide a starting set of keys. - */ -NSS_EXTERN nssPKIObjectCollection * -nssPrivateKeyCollection_Create ( - NSSTrustDomain *td, - NSSPrivateKey **pvkOpt -); - -/* nssPublicKeyCollection_Create - * - * Create a collection of public keys in the specified trust domain. - * Optionally provide a starting set of keys. - */ -NSS_EXTERN nssPKIObjectCollection * -nssPublicKeyCollection_Create ( - NSSTrustDomain *td, - NSSPublicKey **pvkOpt -); - -/* nssPKIObjectCollection_Destroy - */ -NSS_EXTERN void -nssPKIObjectCollection_Destroy ( - nssPKIObjectCollection *collection -); - -/* nssPKIObjectCollection_Count - */ -NSS_EXTERN PRUint32 -nssPKIObjectCollection_Count ( - nssPKIObjectCollection *collection -); - -NSS_EXTERN PRStatus -nssPKIObjectCollection_AddObject ( - nssPKIObjectCollection *collection, - nssPKIObject *object -); - -/* nssPKIObjectCollection_AddInstances - * - * Add a set of object instances to the collection. The instances - * will be sorted into any existing certs/proto-certs that may be in - * the collection. The instances will be absorbed by the collection, - * the array should not be used after this call (except to free it). - * - * Failure means the collection is in an invalid state. - * - * numInstances = 0 means the array is NULL-terminated - */ -NSS_EXTERN PRStatus -nssPKIObjectCollection_AddInstances ( - nssPKIObjectCollection *collection, +NSS_EXTERN NSSPublicKey ** +nssPublicKeyArray_CreateFromInstances ( nssCryptokiObject **instances, - PRUint32 numInstances -); - -/* nssPKIObjectCollection_Traverse - */ -NSS_EXTERN PRStatus -nssPKIObjectCollection_Traverse ( - nssPKIObjectCollection *collection, - nssPKIObjectCallback *callback -); - -/* This function is being added for NSS 3.5. It corresponds to the function - * nssToken_TraverseCerts. The idea is to use the collection during - * a traversal, creating certs each time a new instance is added for which - * a cert does not already exist. - */ -NSS_EXTERN PRStatus -nssPKIObjectCollection_AddInstanceAsObject ( - nssPKIObjectCollection *collection, - nssCryptokiObject *instance -); - -/* nssPKIObjectCollection_GetCerts - * - * Get all of the certificates in the collection. - */ -NSS_EXTERN NSSCert ** -nssPKIObjectCollection_GetCerts ( - nssPKIObjectCollection *collection, - NSSCert **rvOpt, - PRUint32 maximumOpt, - NSSArena *arenaOpt -); - -NSS_EXTERN NSSCRL ** -nssPKIObjectCollection_GetCRLs ( - nssPKIObjectCollection *collection, - NSSCRL **rvOpt, - PRUint32 maximumOpt, + NSSTrustDomain *td, + NSSVolatileDomain *vdOpt, NSSArena *arenaOpt ); NSS_EXTERN NSSPrivateKey ** -nssPKIObjectCollection_GetPrivateKeys ( - nssPKIObjectCollection *collection, - NSSPrivateKey **rvOpt, - PRUint32 maximumOpt, - NSSArena *arenaOpt -); - -NSS_EXTERN NSSPublicKey ** -nssPKIObjectCollection_GetPublicKeys ( - nssPKIObjectCollection *collection, - NSSPublicKey **rvOpt, - PRUint32 maximumOpt, +nssPrivateKeyArray_CreateFromInstances ( + nssCryptokiObject **instances, + NSSTrustDomain *td, + NSSVolatileDomain *vdOpt, NSSArena *arenaOpt ); @@ -793,7 +687,8 @@ nssTokenSessionHash_GetSession ( ); NSS_EXTERN nssTokenStore * -nssTokenObjectStore_Create ( +nssTokenStore_Create ( + NSSTrustDomain *td, NSSToken **tokens ); @@ -808,6 +703,12 @@ nssTokenStore_Refresh ( ); NSS_EXTERN PRStatus +nssTokenStore_AddToken ( + nssTokenStore *store, + NSSToken *token +); + +NSS_EXTERN PRStatus nssTokenStore_ImportCert ( nssTokenStore *store, NSSCert *cert, @@ -897,6 +798,135 @@ nssTokenStore_TraverseCerts ( void *arg ); +NSS_EXTERN NSSPublicKey * +nssTokenStore_FindPublicKeyByID ( + nssTokenStore *store, + NSSItem *id +); + +NSS_EXTERN NSSPrivateKey * +nssTokenStore_FindPrivateKeyByID ( + nssTokenStore *store, + NSSItem *id +); + +NSS_EXTERN PRStatus * +nssTokenStore_TraversePrivateKeys ( + nssTokenStore *store, + PRStatus (*callback)(NSSPrivateKey *vk, void *arg), + void *arg +); + +NSS_EXTERN nssPKIDatabase * +nssPKIDatabase_Open ( + NSSTrustDomain *td, + const char *path, + PRUint32 flags +); + +NSS_EXTERN PRStatus +nssPKIDatabase_Close ( + nssPKIDatabase *pkidb +); + +NSS_EXTERN PRStatus +nssPKIDatabase_ImportCert ( + nssPKIDatabase *pkidb, + NSSCert *cert, + NSSUTF8 *nicknameOpt, + nssTrust *trustOpt +); + +NSS_EXTERN PRStatus +nssPKIDatabase_ImportCertTrust ( + nssPKIDatabase *pkidb, + NSSCert *cert, + nssTrust *trust +); + +NSS_EXTERN PRStatus +nssPKIDatabase_DeleteCert ( + nssPKIDatabase *pkidb, + NSSCert *cert +); + +NSS_EXTERN PRStatus +nssPKIDatabase_SetCertTrust ( + nssPKIDatabase *pkidb, + NSSCert *cert, + nssTrust *trust +); + +NSS_EXTERN NSSCert ** +nssPKIDatabase_FindCertsByNickname ( + nssPKIDatabase *pkidb, + NSSUTF8 *nickname, + NSSCert **rvOpt, + PRUint32 maximumOpt, + NSSArena *arenaOpt +); + +NSS_EXTERN NSSCert ** +nssPKIDatabase_FindCertsBySubject ( + nssPKIDatabase *pkidb, + NSSBER *subject, + NSSCert **rvOpt, + PRUint32 maximumOpt, + NSSArena *arenaOpt +); + +NSS_EXTERN NSSCert ** +nssPKIDatabase_FindCertsByEmail ( + nssPKIDatabase *pkidb, + NSSASCII7 *email, + NSSCert **rvOpt, + PRUint32 maximumOpt, + NSSArena *arenaOpt +); + +NSS_EXTERN NSSCert * +nssPKIDatabase_FindCertByIssuerAndSerialNumber ( + nssPKIDatabase *pkidb, + NSSBER *issuer, + NSSBER *serial +); + +NSS_EXTERN NSSCert * +nssPKIDatabase_FindCertByEncodedCert ( + nssPKIDatabase *pkidb, + NSSBER *ber +); + +NSS_EXTERN PRStatus +nssPKIDatabase_FindTrustForCert ( + nssPKIDatabase *pkidb, + NSSCert *cert, + nssTrust *rvTrust +); + +NSS_EXTERN PRStatus +nssPKIDatabase_TraverseCerts ( + nssPKIDatabase *pkidb, + PRStatus (*callback)(NSSCert *c, void *arg), + void *arg +); + +NSS_EXTERN nssPKIObjectTable * +nssPKIObjectTable_Create ( + NSSArena *arena +); + +NSS_EXTERN void +nssPKIObjectTable_Destroy ( + nssPKIObjectTable *table +); + +NSS_EXTERN nssPKIObject * +nssPKIObjectTable_Add ( + nssPKIObjectTable *table, + nssPKIObject *object +); + PR_END_EXTERN_C #endif /* PKIM_H */ diff --git a/security/nss/lib/pki/pkistore.c b/security/nss/lib/pki/pkistore.c index a9a43870e..1550fedc5 100644 --- a/security/nss/lib/pki/pkistore.c +++ b/security/nss/lib/pki/pkistore.c @@ -700,6 +700,8 @@ struct nssTokenObjectStoreStr PRBool isFriendly; PZLock *lock; /* protects everything below */ NSSCert **certs; /* token certs */ + NSSPublicKey **bkeys; /* token public keys */ + NSSPrivateKey **vkeys; /* token private keys */ PRBool wasLoggedIn; /* token was authenticated last time * we accessed it */ @@ -715,12 +717,109 @@ struct nssTokenStoreStr { NSSTrustDomain *td; nssCertStore *certs; + NSSPublicKey **bkeys; + NSSPrivateKey **vkeys; + NSSSymKey **mkeys; PZLock *lock; /* protects the arena, array, and counter */ NSSArena *arena; nssTokenObjectStore **tokens; PRUint32 numTokens; }; +static PRStatus +add_pubkey_to_store(nssTokenStore *store, NSSPublicKey *bk) +{ + PRIntn count; + PZ_Lock(store->lock); + if (!store->bkeys) { + store->bkeys = nss_ZNEWARRAY(NULL, NSSPublicKey *, 5); + count = 0; + } else { + count = nssObjectArray_Count((void **)store->bkeys); + if (count > 0 && count % 4 == 0) { + NSSPublicKey **test; + test = nss_ZREALLOCARRAY(store->bkeys, NSSPublicKey *, count + 5); + if (!test) { + PZ_Unlock(store->lock); + return PR_FAILURE; + } + store->bkeys = test; + } + } + store->bkeys[count] = nssPublicKey_AddRef(bk); + PZ_Unlock(store->lock); + return PR_SUCCESS; +} + +static PRStatus +add_privkey_to_store(nssTokenStore *store, NSSPrivateKey *vk) +{ + PRIntn count; + PZ_Lock(store->lock); + if (!store->vkeys) { + store->vkeys = nss_ZNEWARRAY(NULL, NSSPrivateKey *, 5); + count = 0; + } else { + count = nssObjectArray_Count((void **)store->bkeys); + if (count > 0 && count % 4 == 0) { + NSSPrivateKey **test; + test = nss_ZREALLOCARRAY(store->vkeys, NSSPrivateKey *, count + 5); + if (!test) { + PZ_Unlock(store->lock); + return PR_FAILURE; + } + store->vkeys = test; + } + } + store->vkeys[count] = nssPrivateKey_AddRef(vk); + PZ_Unlock(store->lock); + return PR_SUCCESS; +} + +static void +remove_pubkey_from_store(nssTokenStore *store, NSSPublicKey *bk) +{ + PRBool foundIt = PR_FALSE; + NSSPublicKey **bkp; + PZ_Lock(store->lock); + for (bkp = store->bkeys; bkp && *bkp; bkp++) { + if (*bkp == bk) { + nssPublicKey_Destroy(*bkp); + foundIt = PR_TRUE; + break; + } + } + if (foundIt) { + NSSPublicKey **removed = bkp; + for (; bkp[1]; bkp++); + *removed = *bkp; + *bkp = NULL; + } + PZ_Unlock(store->lock); +} + +static void +remove_privkey_from_store(nssTokenStore *store, NSSPrivateKey *vk) +{ + PRBool foundIt = PR_FALSE; + NSSPrivateKey **vkp; + PZ_Lock(store->lock); + for (vkp = store->vkeys; vkp && *vkp; vkp++) { + if (*vkp == vk) { + nssPrivateKey_Destroy(*vkp); + foundIt = PR_TRUE; + break; + } + } + if (foundIt) { + NSSPrivateKey **removed = vkp; + for (; vkp[1]; vkp++); + *removed = *vkp; + *vkp = NULL; + } + PZ_Unlock(store->lock); +} + static void unload_token_certs(nssTokenObjectStore *objectStore, nssTokenStore *store) { @@ -758,7 +857,7 @@ load_token_certs(nssTokenObjectStore *objectStore, nssTokenStore *store) * on the token */ tokenCerts = nssToken_FindCerts(objectStore->token, objectStore->session, - nssTokenSearchType_TokenOnly, 0, &status); + 0, &status); if (status == PR_FAILURE) { return PR_FAILURE; } @@ -767,7 +866,7 @@ load_token_certs(nssTokenObjectStore *objectStore, nssTokenStore *store) store->td, NULL, NULL); if (!objectStore->certs) { - nssCryptokiObjectArray_Destroy(tokenCerts); + /* XXX nssCryptokiObjectArray_Destroy(tokenCerts); */ return PR_FAILURE; } nss_ZFreeIf(tokenCerts); @@ -781,6 +880,130 @@ load_token_certs(nssTokenObjectStore *objectStore, nssTokenStore *store) return PR_SUCCESS; } +static void +unload_token_bkeys(nssTokenObjectStore *objectStore, nssTokenStore *store) +{ + NSSPublicKey **bkp; + if (objectStore->bkeys) { + /* notify the objects that the token is removed */ + for (bkp = objectStore->bkeys; *bkp; bkp++) { + nssPublicKey_RemoveInstanceForToken(*bkp, objectStore->token); + if (nssPublicKey_CountInstances(*bkp) == 0) { + /* the key now has no token instances, remove it from + * the token store + */ + remove_pubkey_from_store(store, *bkp); + } + } + /* clear the array of token certs */ + nssPublicKeyArray_Destroy(objectStore->bkeys); + objectStore->bkeys = NULL; + } +} + +static PRStatus +load_token_bkeys(nssTokenObjectStore *objectStore, nssTokenStore *store) +{ + PRStatus status; + nssCryptokiObject **tokenBKeys; + NSSPublicKey **bkp; + + if (objectStore->bkeys) { + /* clear the existing array of token bkeys */ + nssPublicKeyArray_Destroy(objectStore->bkeys); + objectStore->bkeys = NULL; + } + /* find all peristent cert instances (PKCS #11 "token objects") + * on the token + */ + tokenBKeys = nssToken_FindPublicKeys(objectStore->token, + objectStore->session, + 0, &status); + if (status == PR_FAILURE) { + return PR_FAILURE; + } + if (tokenBKeys) { + objectStore->bkeys = nssPublicKeyArray_CreateFromInstances(tokenBKeys, + store->td, + NULL, NULL); + if (!objectStore->bkeys) { + /* XXX nssCryptokiObjectArray_Destroy(tokenBKeys); */ + return PR_FAILURE; + } + for (bkp = objectStore->bkeys; *bkp; bkp++) { + status = add_pubkey_to_store(store, *bkp); + if (status == PR_FAILURE) { + unload_token_bkeys(objectStore, store); + } + } + } + return PR_SUCCESS; +} + +static void +unload_token_vkeys(nssTokenObjectStore *objectStore, nssTokenStore *store) +{ + NSSPrivateKey **vkp; + if (objectStore->vkeys) { + /* notify the objects that the token is removed */ + for (vkp = objectStore->vkeys; *vkp; vkp++) { + nssPrivateKey_RemoveInstanceForToken(*vkp, objectStore->token); + if (nssPrivateKey_CountInstances(*vkp) == 0) { + /* the key now has no token instances, remove it from + * the token store + */ + remove_privkey_from_store(store, *vkp); + } + } + /* clear the array of token certs */ + nssPrivateKeyArray_Destroy(objectStore->vkeys); + objectStore->vkeys = NULL; + } +} + +static PRStatus +load_token_vkeys(nssTokenObjectStore *objectStore, nssTokenStore *store) +{ + PRStatus status; + nssCryptokiObject **tokenVKeys; + NSSPrivateKey **vkp; + + if (objectStore->vkeys) { + /* clear the existing array of token bkeys */ + nssPrivateKeyArray_Destroy(objectStore->vkeys); + objectStore->vkeys = NULL; + } + /* find all peristent cert instances (PKCS #11 "token objects") + * on the token + */ + tokenVKeys = nssToken_FindPrivateKeys(objectStore->token, + objectStore->session, + 0, &status); + if (status == PR_FAILURE) { + return PR_FAILURE; + } + if (tokenVKeys) { + objectStore->vkeys = nssPrivateKeyArray_CreateFromInstances(tokenVKeys, + store->td, + NULL, NULL); + if (!objectStore->vkeys) { + /* XXX nssCryptokiObjectArray_Destroy(tokenVKeys); */ + return PR_FAILURE; + } + for (vkp = objectStore->vkeys; *vkp; vkp++) { + status = add_privkey_to_store(store, *vkp); + if (status == PR_FAILURE) { + unload_token_vkeys(objectStore, store); + } + } + } + return PR_SUCCESS; +} + +static void +refresh_token_object_store(nssTokenObjectStore *objectStore, + nssTokenStore *store); + static nssTokenObjectStore * create_token_object_store(nssTokenStore *store, NSSToken *token) { @@ -803,18 +1026,9 @@ create_token_object_store(nssTokenStore *store, NSSToken *token) rvObjectStore->token = nssToken_AddRef(token); rvObjectStore->slot = nssToken_GetSlot(token); rvObjectStore->isFriendly = nssSlot_IsFriendly(rvObjectStore->slot); - if (load_token_certs(rvObjectStore, store) == PR_SUCCESS) { - rvObjectStore->wasPresent = PR_TRUE; - } else { - NSSError e = NSS_GetError(); - if (e == NSS_ERROR_DEVICE_REMOVED) { - rvObjectStore->wasPresent = PR_FALSE; - } else if (e == NSS_ERROR_LOGIN_REQUIRED) { - rvObjectStore->wasLoggedIn = PR_FALSE; - } else { - rvObjectStore->error = e; - } - } + rvObjectStore->wasPresent = PR_FALSE; + rvObjectStore->wasLoggedIn = PR_FALSE; + refresh_token_object_store(rvObjectStore, store); return rvObjectStore; } @@ -847,6 +1061,8 @@ refresh_token_object_store(nssTokenObjectStore *objectStore, if (objectStore->wasPresent) { /* token has been removed since the last search */ unload_token_certs(objectStore, store); + unload_token_bkeys(objectStore, store); + unload_token_vkeys(objectStore, store); } /* else it wasn't present before, so do nothing */ } else if (!objectStore->wasPresent) { /* token has been inserted since the last search */ @@ -855,18 +1071,30 @@ refresh_token_object_store(nssTokenObjectStore *objectStore, * be available */ status = load_token_certs(objectStore, store); + status = load_token_bkeys(objectStore, store); + if (isLoggedIn) { + status = load_token_vkeys(objectStore, store); + } } } else if (!isLoggedIn) { /* token is present but not authenticated */ - if (!objectStore->isFriendly && objectStore->wasLoggedIn) { - /* it is not friendly, and was previously authenticated, so + if (objectStore->wasLoggedIn) { + /* it was previously authenticated, so * we have private objects that need to be unloaded */ - unload_token_certs(objectStore, store); + unload_token_vkeys(objectStore, store); + if (!objectStore->isFriendly) { + unload_token_certs(objectStore, store); + unload_token_bkeys(objectStore, store); + } } /* else it wasn't authenticated before, so do nothing */ - } else if (!objectStore->isFriendly && !objectStore->wasLoggedIn) { - /* token is present and authenticated, load private objects */ - status = load_token_certs(objectStore, store); + } else if (!objectStore->wasLoggedIn) { + /* token is present and (now) authenticated, load private objects */ + status = load_token_vkeys(objectStore, store); + if (!objectStore->isFriendly) { + status = load_token_certs(objectStore, store); + status = load_token_bkeys(objectStore, store); + } } if (status == PR_FAILURE) { e = NSS_GetError(); @@ -876,6 +1104,8 @@ refresh_token_object_store(nssTokenObjectStore *objectStore, * move on. */ unload_token_certs(objectStore, store); + unload_token_bkeys(objectStore, store); + unload_token_vkeys(objectStore, store); e = NSS_ERROR_NO_ERROR; /* override the error */ } } @@ -919,38 +1149,6 @@ find_store_for_token(nssTokenStore *store, NSSToken *token) return objectStore; } -NSS_IMPLEMENT PRStatus -nssTokenStore_AddToken ( - nssTokenStore *store, - NSSToken *token -) -{ - PRStatus status = PR_SUCCESS; - PZ_Lock(store->lock); - if (store->numTokens == 0) { - store->tokens = nss_ZNEWARRAY(NULL, - nssTokenObjectStore *, - store->numTokens + 1); - } else { - store->tokens = nss_ZREALLOCARRAY(store->tokens, - nssTokenObjectStore *, - store->numTokens + 1); - } - if (store->tokens) { - store->tokens[store->numTokens] = create_token_object_store(store, - token); - if (!store->tokens[store->numTokens]) { - status = PR_FAILURE; - } else { - store->numTokens++; - } - } else { - status = PR_FAILURE; - } - PZ_Unlock(store->lock); - return status; -} - NSS_IMPLEMENT nssTokenStore * nssTokenStore_Create ( NSSTrustDomain *td, @@ -1024,6 +1222,38 @@ nssTokenStore_Destroy ( } NSS_IMPLEMENT PRStatus +nssTokenStore_AddToken ( + nssTokenStore *store, + NSSToken *token +) +{ + PRStatus status = PR_SUCCESS; + PZ_Lock(store->lock); + if (store->numTokens == 0) { + store->tokens = nss_ZNEWARRAY(NULL, + nssTokenObjectStore *, + store->numTokens + 1); + } else { + store->tokens = nss_ZREALLOCARRAY(store->tokens, + nssTokenObjectStore *, + store->numTokens + 1); + } + if (store->tokens) { + store->tokens[store->numTokens] = create_token_object_store(store, + token); + if (!store->tokens[store->numTokens]) { + status = PR_FAILURE; + } else { + store->numTokens++; + } + } else { + status = PR_FAILURE; + } + PZ_Unlock(store->lock); + return status; +} + +NSS_IMPLEMENT PRStatus nssTokenStore_EnableToken ( nssTokenStore *store, NSSToken *token @@ -1103,6 +1333,7 @@ nssTokenStore_ImportCert ( return PR_SUCCESS; } /* copy it onto the token and add it to the store */ + /* XXX use session */ status = nssCert_CopyToToken(cert, destination, nicknameOpt); if (status == PR_SUCCESS) { status = nssCertStore_AddCert(store->certs, cert); @@ -1130,6 +1361,7 @@ nssTokenStore_RemoveCert ( NSSCert *cert ) { + /* XXX destroy session objects */ (void)nssCertStore_RemoveCert(store->certs, cert); } @@ -1222,3 +1454,79 @@ nssTokenStore_TraverseCerts ( return nssCertStore_TraverseCerts(store->certs, callback, arg); } +NSS_IMPLEMENT NSSPublicKey * +nssTokenStore_FindPublicKeyByID ( + nssTokenStore *store, + NSSItem *id +) +{ + NSSPublicKey **bkp; + NSSPublicKey *rvBK = NULL; + NSSItem *bkID; + + nssTokenStore_Refresh(store); + PZ_Lock(store->lock); + for (bkp = store->bkeys; bkp && *bkp; bkp++) { + bkID = nssPublicKey_GetID(*bkp); + if (nssItem_Equal(bkID, id, NULL)) { + rvBK = nssPublicKey_AddRef(*bkp); + break; + } + } + PZ_Unlock(store->lock); + return rvBK; +} + +NSS_IMPLEMENT NSSPrivateKey * +nssTokenStore_FindPrivateKeyByID ( + nssTokenStore *store, + NSSItem *id +) +{ + NSSPrivateKey **vkp; + NSSPrivateKey *rvVK = NULL; + NSSItem *vkID; + + nssTokenStore_Refresh(store); + PZ_Lock(store->lock); + for (vkp = store->vkeys; vkp && *vkp; vkp++) { + vkID = nssPrivateKey_GetID(*vkp); + if (nssItem_Equal(vkID, id, NULL)) { + rvVK = nssPrivateKey_AddRef(*vkp); + break; + } + } + PZ_Unlock(store->lock); + return rvVK; +} + +NSS_IMPLEMENT PRStatus * +nssTokenStore_TraversePrivateKeys ( + nssTokenStore *store, + PRStatus (*callback)(NSSPrivateKey *vk, void *arg), + void *arg +) +{ + NSSPrivateKey **vkp; + NSSPrivateKey **vkeys; + PRUint32 count; + + nssTokenStore_Refresh(store); + /* XXX ugly */ + PZ_Lock(store->lock); + for (vkp = store->vkeys, count = 0; vkp && *vkp; vkp++, count++); + if (count > 0) { + vkeys = nss_ZNEWARRAY(NULL, NSSPrivateKey *, count + 1); + if (vkeys) { + for (vkp = store->vkeys, count = 0; *vkp; vkp++, count++) + vkeys[count++] = nssPrivateKey_AddRef(*vkp); + } + } + PZ_Unlock(store->lock); + for (vkp = vkeys; vkp && *vkp; vkp++) { + (*callback)(*vkp, arg); + } + nssPrivateKeyArray_Destroy(vkeys); + return NULL; +} + diff --git a/security/nss/lib/pki/pkit.h b/security/nss/lib/pki/pkit.h index d95ef3a67..182f16087 100644 --- a/security/nss/lib/pki/pkit.h +++ b/security/nss/lib/pki/pkit.h @@ -70,8 +70,6 @@ struct NSSSymKeyStr; struct NSSPoliciesStr; -struct NSSPKIXCertStr; - typedef struct nssTrustStr nssTrust; PR_END_EXTERN_C diff --git a/security/nss/lib/pki/pkitm.h b/security/nss/lib/pki/pkitm.h index b8618aad9..4c44c5f84 100644 --- a/security/nss/lib/pki/pkitm.h +++ b/security/nss/lib/pki/pkitm.h @@ -58,20 +58,16 @@ static const char PKITM_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; PR_BEGIN_EXTERN_C -/* - * A note on ephemeral certs - * - * The key objects defined here can only be created on tokens, and can only - * exist on tokens. Therefore, any instance of a key object must have - * a corresponding cryptoki instance. OTOH, certificates created in - * crypto contexts need not be stored as session objects on the token. - * There are good performance reasons for not doing so. The certificate - * and trust objects have been defined with a cryptoContext field to - * allow for ephemeral certs, which may have a single instance in a crypto - * context along with any number (including zero) of cryptoki instances. - * Since contexts may not share objects, there can be only one context - * for each object. - */ +typedef enum +{ + pkiObjectType_Cert = 0, + pkiObjectType_CRL = 1, + pkiObjectType_PrivateKey = 2, + pkiObjectType_PublicKey = 3, + pkiObjectType_SymKey = 4 +} pkiObjectType; + +#define MAX_ITEMS_FOR_UID 2 /* nssPKIObject * @@ -86,51 +82,27 @@ struct nssPKIObjectStr PRInt32 refCount; /* lock protects the array of nssCryptokiInstance's of the object */ PZLock *lock; - /* XXX with LRU cache, this cannot be guaranteed up-to-date. It cannot - * be compared against the update level of the trust domain, since it is - * also affected by import/export. Where is this array needed? - */ + /* the set of token instances (if any) for the object */ nssCryptokiObject **instances; PRUint32 numInstances; /* The object must live in a trust domain */ NSSTrustDomain *td; /* The object may live in a volatile domain */ NSSVolatileDomain *vd; - /* XXX added so temp certs can have nickname, think more ... */ - NSSUTF8 *tempName; + /* The "meta"-name of the object (token instance labels may differ) */ + NSSUTF8 *nickname; + /* The following data index the UID for the object. The UID is used + * in the table of active token objects, to ensure that the same object + * never appears as two different objects. + */ + pkiObjectType objectType; + NSSItem *uid[MAX_ITEMS_FOR_UID]; + PRUint32 numIDs; }; typedef struct nssPKIObjectStr nssPKIObject; -/* nssCertCollection - * - * You guessed it; a collection of certs. Each entry may be either an - * NSSCert or an nssProtoCert. - */ - -typedef struct nssPKIObjectCollectionStr nssPKIObjectCollection; - -typedef struct -{ - union { - PRStatus (* cert)(NSSCert *c, void *arg); - PRStatus (* crl)(NSSCRL *crl, void *arg); - PRStatus (* pvkey)(NSSPrivateKey *vk, void *arg); - PRStatus (* pbkey)(NSSPublicKey *bk, void *arg); - } func; - void *arg; -} nssPKIObjectCallback; - -/* XXX */ -struct nssTrustStr -{ - nssPKIObject object; - NSSCert *certificate; - nssTrustLevel serverAuth; - nssTrustLevel clientAuth; - nssTrustLevel emailProtection; - nssTrustLevel codeSigning; -}; +typedef struct nssPKIObjectTableStr nssPKIObjectTable; typedef struct nssPKIObjectCreatorStr { @@ -146,10 +118,18 @@ typedef struct nssPKIObjectCreatorStr NSSOperations operations; } nssPKIObjectCreator; +struct nssTrustStr +{ + NSSUsages trustedUsages; + NSSUsages notTrustedUsages; +}; + typedef struct nssTokenSessionHashStr nssTokenSessionHash; typedef struct nssTokenStoreStr nssTokenStore; +typedef struct nssPKIDatabaseStr nssPKIDatabase; + PR_END_EXTERN_C #endif /* PKITM_H */ diff --git a/security/nss/lib/pki/symkey.c b/security/nss/lib/pki/symkey.c index 9e0400e7d..cb67a6c2e 100644 --- a/security/nss/lib/pki/symkey.c +++ b/security/nss/lib/pki/symkey.c @@ -53,32 +53,6 @@ struct NSSSymKeyStr }; NSS_IMPLEMENT NSSSymKey * -nssSymKey_Create ( - nssPKIObject *object -) -{ - PRStatus status; - NSSSymKey *rvKey; - NSSArena *arena = object->arena; - PR_ASSERT(object->instances != NULL && object->numInstances > 0); - rvKey = nss_ZNEW(arena, NSSSymKey); - if (!rvKey) { - return (NSSSymKey *)NULL; - } - rvKey->object = *object; - /* XXX should choose instance based on some criteria */ - status = nssCryptokiSymKey_GetAttributes(object->instances[0], - arena, - &rvKey->kind, - &rvKey->length, - &rvKey->operations); - if (status != PR_SUCCESS) { - return (NSSSymKey *)NULL; - } - return rvKey; -} - -NSS_IMPLEMENT NSSSymKey * nssSymKey_CreateFromInstance ( nssCryptokiObject *instance, NSSTrustDomain *td, @@ -89,19 +63,31 @@ nssSymKey_CreateFromInstance ( nssPKIObject *pkio; NSSSymKey *rvKey = NULL; - pkio = nssPKIObject_Create(NULL, instance, td, vdOpt); - if (!pkio) { + rvKey = nssPKIObject_CREATE(td, instance, NSSSymKey); + if (!rvKey) { return (NSSSymKey *)NULL; } - rvKey = nssSymKey_Create(pkio); + pkio = &rvKey->object; + status = nssCryptokiSymKey_GetAttributes(instance, pkio->arena, + &rvKey->kind, + &rvKey->length, + &rvKey->operations); + if (status != PR_SUCCESS) { + goto loser; + } + pkio->objectType = pkiObjectType_SymKey; + pkio->numIDs = 0; /* XXX */ + /* XXX not adding to table w/o uid... */ if (rvKey && vdOpt) { status = nssVolatileDomain_ImportSymKey(vdOpt, rvKey); if (status == PR_FAILURE) { - nssSymKey_Destroy(rvKey); - rvKey = NULL; + goto loser; } } return rvKey; +loser: + nssSymKey_Destroy(rvKey); + return (NSSSymKey *)NULL; } NSS_IMPLEMENT NSSSymKey * @@ -184,12 +170,12 @@ nssSymKey_FindInstanceForAlgorithm ( } NSS_IMPLEMENT PRBool -nssSymKey_IsOnToken ( +nssSymKey_HasInstanceOnToken ( NSSSymKey *mk, NSSToken *token ) { - return nssPKIObject_IsOnToken(&mk->object, token); + return nssPKIObject_HasInstanceOnToken(&mk->object, token); } NSS_IMPLEMENT PRStatus diff --git a/security/nss/lib/pki/trustdomain.c b/security/nss/lib/pki/trustdomain.c index 298abd7cf..036b1eff7 100644 --- a/security/nss/lib/pki/trustdomain.c +++ b/security/nss/lib/pki/trustdomain.c @@ -47,12 +47,6 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "pki1.h" #endif /* PKI1_H */ -#ifdef CERT_CACHE -#ifndef CERTCACHE_H -#include "certcache.h" -#endif /* CERTCACHE_H */ -#endif /* CERT_CACHE */ - struct NSSTrustDomainStr { PRInt32 refCount; NSSArena *arena; @@ -62,16 +56,15 @@ struct NSSTrustDomainStr { nssSlotList *forCiphers; nssSlotList *forTrust; } slots; + nssPKIObjectTable *objectTable; nssTokenStore *tokenStore; -#ifdef CERT_CACHE - nssCertCache *cache; -#endif /* CERT_CACHE */ + nssPKIDatabase *pkidb; }; NSS_IMPLEMENT NSSTrustDomain * -NSSTrustDomain_Create ( - NSSUTF8 *moduleOpt, +nssTrustDomain_Create ( + NSSUTF8 *dbPath, NSSUTF8 *uriOpt, NSSUTF8 *opaqueOpt, void *reserved @@ -99,26 +92,48 @@ NSSTrustDomain_Create ( if (!rvTD->slots.forTrust) { goto loser; } + rvTD->objectTable = nssPKIObjectTable_Create(arena); + if (!rvTD->objectTable) { + goto loser; + } rvTD->tokenStore = nssTokenStore_Create(rvTD, NULL); if (!rvTD->tokenStore) { goto loser; } -#ifdef CERT_CACHE - rvTD->cache = nssCertCache_Create(); - if (!rvTD->cache) { + rvTD->pkidb = nssPKIDatabase_Open(rvTD, dbPath, 0); + if (!rvTD->pkidb) { goto loser; } -#endif /* CERT_CACHE */ rvTD->arena = arena; rvTD->refCount = 1; return rvTD; loser: + if (rvTD->objectTable) { + nssPKIObjectTable_Destroy(rvTD->objectTable); + } + if (rvTD->tokenStore) { + nssTokenStore_Destroy(rvTD->tokenStore); + } + if (rvTD->pkidb) { + nssPKIDatabase_Close(rvTD->pkidb); + } nssArena_Destroy(arena); return (NSSTrustDomain *)NULL; } +NSS_IMPLEMENT NSSTrustDomain * +NSSTrustDomain_Create ( + NSSUTF8 *dbPath, + NSSUTF8 *uriOpt, + NSSUTF8 *opaqueOpt, + void *reserved +) +{ + return nssTrustDomain_Create(dbPath, uriOpt, opaqueOpt, reserved); +} + NSS_IMPLEMENT PRStatus -NSSTrustDomain_Destroy ( +nssTrustDomain_Destroy ( NSSTrustDomain *td ) { @@ -126,16 +141,23 @@ NSSTrustDomain_Destroy ( nssSlotList_Destroy(td->slots.forCerts); nssSlotList_Destroy(td->slots.forCiphers); nssSlotList_Destroy(td->slots.forTrust); -#ifdef CERT_CACHE - nssCertCache_Destroy(td->cache); -#endif /* CERT_CACHE */ + nssPKIObjectTable_Destroy(td->objectTable); nssTokenStore_Destroy(td->tokenStore); + nssPKIDatabase_Close(td->pkidb); /* Destroy the trust domain */ nssArena_Destroy(td->arena); } return PR_SUCCESS; } +NSS_IMPLEMENT PRStatus +NSSTrustDomain_Destroy ( + NSSTrustDomain *td +) +{ + return nssTrustDomain_Destroy(td); +} + /* XXX */ NSS_IMPLEMENT NSSSlot ** nssTrustDomain_GetActiveSlots ( @@ -163,17 +185,13 @@ nssTrustDomain_GetSessionForToken ( return rvSession; } -/* XXX */ -#ifdef CERT_CACHE -static PRBool -nssTrustDomain_IsUpToDate ( - NSSTrustDomain *td, - nssUpdateLevel updateLevel +NSS_IMPLEMENT nssPKIObjectTable * +nssTrustDomain_GetObjectTable ( + NSSTrustDomain *td ) { - return (updateLevel > 0); + return td->objectTable; } -#endif /* CERT_CACHE */ NSS_IMPLEMENT PRStatus NSSTrustDomain_SetDefaultCallback ( @@ -223,7 +241,7 @@ NSSTrustDomain_LoadModule ( } NSS_IMPLEMENT PRStatus -NSSTrustDomain_AddModule ( +nssTrustDomain_AddModule ( NSSTrustDomain *td, NSSModule *module ) @@ -385,7 +403,7 @@ NSSTrustDomain_FindTokenForAlgNParam ( } NSS_IMPLEMENT PRStatus -NSSTrustDomain_Login ( +nssTrustDomain_Login ( NSSTrustDomain *td, NSSCallback *uhhOpt ) @@ -412,6 +430,15 @@ NSSTrustDomain_Login ( } NSS_IMPLEMENT PRStatus +NSSTrustDomain_Login ( + NSSTrustDomain *td, + NSSCallback *uhhOpt +) +{ + return nssTrustDomain_Login(td, uhhOpt); +} + +NSS_IMPLEMENT PRStatus NSSTrustDomain_Logout ( NSSTrustDomain *td ) @@ -442,13 +469,21 @@ nssTrustDomain_ImportEncodedCert ( PRStatus status; NSSCert *c = NULL; NSSToken *destination = destinationOpt; /* XXX */ + NSSItem nickIt; + + nickIt.data = nicknameOpt; + nickIt.size = nicknameOpt ? nssUTF8_Length(nicknameOpt, NULL) : 0; - c = nssCert_Decode(ber); + c = nssCert_Decode(ber, &nickIt, NULL, td, NULL); if (!c) { goto loser; } - status = nssTokenStore_ImportCert(td->tokenStore, c, - nicknameOpt, destination); + if (destinationOpt) { /* ja vohl? */ + status = nssTokenStore_ImportCert(td->tokenStore, c, + nicknameOpt, destination); + } else { + status = nssPKIDatabase_ImportCert(td->pkidb, c, nicknameOpt, NULL); + } if (status == PR_FAILURE) { goto loser; } @@ -529,6 +564,7 @@ NSSTrustDomain_ImportEncodedPublicKey ( return NULL; } +/* XXX do all token certs need to by synched with db certs first? */ NSS_IMPLEMENT NSSCert ** nssTrustDomain_FindCertsByNickname ( NSSTrustDomain *td, @@ -538,37 +574,21 @@ nssTrustDomain_FindCertsByNickname ( NSSArena *arenaOpt ) { - NSSCert **rvCerts = NULL; -#ifdef CERT_CACHE - PRStatus status; - nssUpdateLevel updateLevel; - /* see if this search is already cached */ - rvCerts = nssCertCache_FindCertsByNickname(td->cache, - name, - rvOpt, - maximumOpt, - arenaOpt, - &updateLevel); - if (nssTrustDomain_IsUpToDate(td, updateLevel)) { - /* The search was cached, and up-to-date with respect to token - * insertion/removal. Thus, it is complete, and we can return - * the cached search. - */ - return rvCerts; - } -#endif /* CERT_CACHE */ + NSSCert **rvCerts, **dbCerts; /* Locate all token certs */ rvCerts = nssTokenStore_FindCertsByNickname(td->tokenStore, name, rvOpt, maximumOpt, arenaOpt); -#ifdef CERT_CACHE - /* Cache this search. It is up-to-date w.r.t. the time when it grabbed - * the slots to search. - */ - status = nssCertCache_AddCertsForNickname(td->cache, - name, - rvCerts, - updateLevel); -#endif /* CERT_CACHE */ + if (rvOpt || maximumOpt > 0) { + PRIntn count = nssObjectArray_Count((void **)rvCerts); + maximumOpt -= count; + if (maximumOpt == 0) return rvCerts; + if (rvOpt) rvOpt += count; + } + dbCerts = nssPKIDatabase_FindCertsByNickname(td->pkidb, name, + rvOpt, maximumOpt, arenaOpt); + if (!rvOpt) { + rvCerts = nssCertArray_Join(rvCerts, dbCerts); + } return rvCerts; } @@ -630,29 +650,20 @@ nssTrustDomain_FindCertsBySubject ( NSSArena *arenaOpt ) { - NSSCert **rvCerts = NULL; -#ifdef CERT_CACHE - PRStatus status; - nssUpdateLevel updateLevel; - /* see if this search is already cached */ - rvCerts = nssCertCache_FindCertsBySubject(td->cache, - subject, - rvOpt, - maximumOpt, - arenaOpt, - &updateLevel); - if (nssTrustDomain_IsUpToDate(td, updateLevel)) { - return rvCerts; - } -#endif /* CERT_CACHE */ + NSSCert **rvCerts, **dbCerts; rvCerts = nssTokenStore_FindCertsBySubject(td->tokenStore, subject, rvOpt, maximumOpt, arenaOpt); -#ifdef CERT_CACHE - status = nssCertCache_AddCertsForSubject(td->cache, - subject, - rvCerts, - updateLevel); -#endif /* CERT_CACHE */ + if (rvOpt || maximumOpt > 0) { + PRIntn count = nssObjectArray_Count((void **)rvCerts); + maximumOpt -= count; + if (maximumOpt == 0) return rvCerts; + if (rvOpt) rvOpt += count; + } + dbCerts = nssPKIDatabase_FindCertsBySubject(td->pkidb, subject, + rvOpt, maximumOpt, arenaOpt); + if (!rvOpt) { + rvCerts = nssCertArray_Join(rvCerts, dbCerts); + } return rvCerts; } @@ -704,32 +715,6 @@ NSSTrustDomain_FindBestCertBySubject ( } NSS_IMPLEMENT NSSCert * -NSSTrustDomain_FindBestCertByNameComponents ( - NSSTrustDomain *td, - NSSUTF8 *nameComponents, - NSSTime time, - NSSUsages *usages, - NSSPolicies *policiesOpt -) -{ - nss_SetError(NSS_ERROR_NOT_FOUND); - return NULL; -} - -NSS_IMPLEMENT NSSCert ** -NSSTrustDomain_FindCertsByNameComponents ( - NSSTrustDomain *td, - NSSUTF8 *nameComponents, - NSSCert *rvOpt[], - PRUint32 maximumOpt, /* 0 for no max */ - NSSArena *arenaOpt -) -{ - nss_SetError(NSS_ERROR_NOT_FOUND); - return NULL; -} - -NSS_IMPLEMENT NSSCert * nssTrustDomain_FindCertByIssuerAndSerialNumber ( NSSTrustDomain *td, NSSDER *issuer, @@ -737,26 +722,14 @@ nssTrustDomain_FindCertByIssuerAndSerialNumber ( ) { NSSCert *rvCert = NULL; -#ifdef CERT_CACHE - PRStatus status; - nssUpdateLevel updateLevel; - /* see if this search is already cached */ - rvCert = nssCertCache_FindCertByIssuerAndSerialNumber( - td->cache, - issuer, - serial, - &updateLevel); - if (nssTrustDomain_IsUpToDate(td, updateLevel)) { - return rvCert; - } -#endif /* CERT_CACHE */ rvCert = nssTokenStore_FindCertByIssuerAndSerialNumber(td->tokenStore, issuer, serial); -#ifdef CERT_CACHE - status = nssCertCache_AddCert(td->cache, rvCert, - issuer, serial, updateLevel); -#endif /* CERT_CACHE */ + if (!rvCert) { + rvCert = nssPKIDatabase_FindCertByIssuerAndSerialNumber(td->pkidb, + issuer, + serial); + } return rvCert; } @@ -778,6 +751,9 @@ nssTrustDomain_FindCertByEncodedCert ( { NSSCert *rvCert = NULL; rvCert = nssTokenStore_FindCertByEncodedCert(td->tokenStore, ber); + if (!rvCert) { + rvCert = nssPKIDatabase_FindCertByEncodedCert(td->pkidb, ber); + } return rvCert; } @@ -802,6 +778,7 @@ nssTrustDomain_FindCertsByID ( NSSCert **rvCerts = NULL; rvCerts = nssTokenStore_FindCertsByID(td->tokenStore, id, rvOpt, maximumOpt, arenaOpt); + /* XXX bother with db? */ return rvCerts; } @@ -814,9 +791,20 @@ nssTrustDomain_FindCertsByEmail ( NSSArena *arenaOpt ) { - NSSCert **rvCerts = NULL; + NSSCert **rvCerts, **dbCerts; rvCerts = nssTokenStore_FindCertsByEmail(td->tokenStore, email, rvOpt, maximumOpt, arenaOpt); + if (rvOpt || maximumOpt > 0) { + PRIntn count = nssObjectArray_Count((void **)rvCerts); + maximumOpt -= count; + if (maximumOpt == 0) return rvCerts; + if (rvOpt) rvOpt += count; + } + dbCerts = nssPKIDatabase_FindCertsByEmail(td->pkidb, email, + rvOpt, maximumOpt, arenaOpt); + if (!rvOpt) { + rvCerts = nssCertArray_Join(rvCerts, dbCerts); + } return rvCerts; } @@ -854,16 +842,6 @@ NSSTrustDomain_FindBestCertByEmail ( return rvCert; } -NSS_IMPLEMENT NSSCert * -NSSTrustDomain_FindCertByOCSPHash ( - NSSTrustDomain *td, - NSSItem *hash -) -{ - nss_SetError(NSS_ERROR_NOT_FOUND); - return NULL; -} - /* XXX don't keep this */ struct stuff_str { NSSCert **rv; @@ -904,7 +882,7 @@ nssTrustDomain_FindUserCerts ( NSSArena *arenaOpt ) { - PRStatus *status; + PRStatus status; /* XXX need something more efficient */ struct stuff_str stuff; stuff.rv = rvOpt; @@ -912,8 +890,8 @@ nssTrustDomain_FindUserCerts ( stuff.rvSize = rvOpt ? rvLimit : 0; stuff.rvLimit = rvLimit; stuff.arenaOpt = arenaOpt; - status = nssTrustDomain_TraverseCerts(td, get_user, &stuff); - if (status && *status == PR_FAILURE) { + status = nssTokenStore_TraverseCerts(td->tokenStore, get_user, &stuff); + if (status == PR_FAILURE) { nssCertArray_Destroy(stuff.rv); stuff.rv = NULL; } @@ -1066,6 +1044,21 @@ NSSTrustDomain_FindUserCertsForEmailSigning ( return NULL; } +struct token_cert_filter_str { + PRStatus (*callback)(NSSCert *c, void *arg); + void *arg; +}; + +static PRStatus +filter_out_token_certs(NSSCert *c, void *arg) +{ + struct token_cert_filter_str *cbarg = (struct token_cert_filter_str *)arg; + if (nssCert_CountInstances(c) == 0) { + return cbarg->callback(c, cbarg->arg); + } + return PR_SUCCESS; +} + NSS_IMPLEMENT PRStatus * nssTrustDomain_TraverseCerts ( NSSTrustDomain *td, @@ -1074,7 +1067,12 @@ nssTrustDomain_TraverseCerts ( ) { PRStatus status; + /* XXX this is mighty ugly */ + struct token_cert_filter_str cbarg; + cbarg.callback = callback; + cbarg.arg = arg; status = nssTokenStore_TraverseCerts(td->tokenStore, callback, arg); + nssPKIDatabase_TraverseCerts(td->pkidb, filter_out_token_certs, &cbarg); return NULL; } @@ -1088,77 +1086,6 @@ NSSTrustDomain_TraverseCerts ( return nssTrustDomain_TraverseCerts(td, callback, arg); } -NSS_IMPLEMENT nssTrust * -nssTrustDomain_FindTrustForCert ( - NSSTrustDomain *td, - NSSCert *c -) -{ - PRStatus status; - NSSSlot **slots; - NSSSlot **slotp; - NSSToken *token; - NSSDER *encoding = nssCert_GetEncoding(c); - NSSDER *issuer = nssCert_GetIssuer(c); - NSSDER *serial = nssCert_GetSerialNumber(c); - nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; - nssCryptokiObject *to = NULL; - nssPKIObject *pkio = NULL; - nssTrust *rvt = NULL; - nssUpdateLevel updateLevel; - slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); - if (!slots) { - return (nssTrust *)NULL; - } - for (slotp = slots; *slotp; slotp++) { - token = nssSlot_GetToken(*slotp); - if (token) { - /* XXX */ - nssSession *session = nssToken_CreateSession(token, PR_FALSE); - if (!session) { - continue; - } - to = nssToken_FindTrustForCert(token, session, - encoding, - issuer, - serial, - tokenOnly); - nssSession_Destroy(session); - if (to) { - if (!pkio) { - pkio = nssPKIObject_Create(NULL, to, td, NULL); - if (!pkio) { - goto loser; - } - } else { - status = nssPKIObject_AddInstance(pkio, to); - if (status != PR_SUCCESS) { - goto loser; - } - } - } - nssToken_Destroy(token); - } - } - if (pkio) { - rvt = nssTrust_Create(pkio); - if (!rvt) { - goto loser; - } - } - nssSlotArray_Destroy(slots); - return rvt; -loser: - nssSlotArray_Destroy(slots); - if (to) { - nssCryptokiObject_Destroy(to); - } - if (pkio) { - nssPKIObject_Destroy(pkio); - } - return (nssTrust *)NULL; -} - NSS_IMPLEMENT NSSCRL ** nssTrustDomain_FindCRLsBySubject ( NSSTrustDomain *td, @@ -1270,7 +1197,7 @@ NSSTrustDomain_GenerateSymKey ( ) { return nssTrustDomain_GenerateSymKey(td, ap, keysize, - destination, uhhOpt); + destination, uhhOpt); } NSS_IMPLEMENT NSSSymKey * @@ -1298,6 +1225,34 @@ NSSTrustDomain_FindSymKeyByAlgorithmAndKeyID ( return NULL; } +NSS_IMPLEMENT NSSPublicKey * +nssTrustDomain_FindPublicKeyByID ( + NSSTrustDomain *td, + NSSItem *keyID +) +{ + return nssTokenStore_FindPublicKeyByID(td->tokenStore, keyID); +} + +NSS_IMPLEMENT NSSPrivateKey * +nssTrustDomain_FindPrivateKeyByID ( + NSSTrustDomain *td, + NSSItem *keyID +) +{ + return nssTokenStore_FindPrivateKeyByID(td->tokenStore, keyID); +} + +NSS_IMPLEMENT PRStatus * +nssTrustDomain_TraversePrivateKeys ( + NSSTrustDomain *td, + PRStatus (*callback)(NSSPrivateKey *vk, void *arg), + void *arg +) +{ + return nssTokenStore_TraversePrivateKeys(td->tokenStore, callback, arg); +} + NSS_IMPLEMENT PRStatus * NSSTrustDomain_TraversePrivateKeys ( NSSTrustDomain *td, @@ -1305,67 +1260,7 @@ NSSTrustDomain_TraversePrivateKeys ( void *arg ) { - PRStatus status; - NSSToken *token = NULL; - NSSSlot **slots = NULL; - NSSSlot **slotp; - nssPKIObjectCollection *collection = NULL; - nssPKIObjectCallback pkiCallback; - nssUpdateLevel updateLevel; - collection = nssPrivateKeyCollection_Create(td, NULL); - if (!collection) { - return (PRStatus *)NULL; - } - /* obtain the current set of active slots in the trust domain */ - slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); - if (!slots) { - goto loser; - } - /* iterate over the slots */ - for (slotp = slots; *slotp; slotp++) { - /* get the token for the slot, if present */ - token = nssSlot_GetToken(*slotp); - if (token) { - nssSession *session; - nssCryptokiObject **instances; - nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; - /* get a session for the token */ - session = nssTrustDomain_GetSessionForToken(td, token, PR_FALSE); - if (!session) { - nssToken_Destroy(token); - goto loser; - } - /* perform the traversal */ - instances = nssToken_FindPrivateKeys(token, - session, - tokenOnly, - 0, &status); - nssToken_Destroy(token); - status = nssPKIObjectCollection_AddInstances(collection, - instances, 0); - nss_ZFreeIf(instances); - if (status != PR_SUCCESS) { - goto loser; - } - } - slotp++; - } - /* Traverse the collection */ - pkiCallback.func.pvkey = callback; - pkiCallback.arg = arg; - status = nssPKIObjectCollection_Traverse(collection, &pkiCallback); - /* clean up */ - nssPKIObjectCollection_Destroy(collection); - NSSSlotArray_Destroy(slots); - return NULL; -loser: - if (collection) { - nssPKIObjectCollection_Destroy(collection); - } - if (slots) { - NSSSlotArray_Destroy(slots); - } - return NULL; + return nssTrustDomain_TraversePrivateKeys(td, callback, arg); } NSS_IMPLEMENT NSSVolatileDomain * @@ -1422,3 +1317,13 @@ NSSTrustDomain_CreateCryptoContextForAlgorithm ( return NULL; } +NSS_IMPLEMENT PRStatus +nssTrustDomain_SetCertTrust ( + NSSTrustDomain *td, + NSSCert *c, + nssTrust *trust +) +{ + return nssPKIDatabase_SetCertTrust(td->pkidb, c, trust); +} + diff --git a/security/nss/lib/pki/volatiledomain.c b/security/nss/lib/pki/volatiledomain.c index 7ddef1fc9..f07a52688 100644 --- a/security/nss/lib/pki/volatiledomain.c +++ b/security/nss/lib/pki/volatiledomain.c @@ -267,14 +267,19 @@ nssVolatileDomain_ImportEncodedCert ( ) { NSSCert *c; + NSSItem nickIt; + NSSItem *pNick = NULL; - c = nssCert_Decode(ber); + if (nickOpt) { + nickIt.data = nickOpt; + nickIt.size = nickOpt ? nssUTF8_Length(nickOpt, NULL) : 0; + pNick = &nickIt; + } + + c = nssCert_Decode(ber, pNick, NULL, vd->td, vd); if (!c) { return (NSSCert *)NULL; } - if (nickOpt) { - nssCert_SetNickname(c, NULL, nickOpt); - } if (nssVolatileDomain_ImportCert(vd, c) == PR_FAILURE) { nssCert_Destroy(c); return (NSSCert *)NULL; @@ -369,7 +374,7 @@ nssVolatileDomain_ImportPublicKeyByInfo ( bko = nssToken_ImportPublicKey(token, session, keyInfo, PR_FALSE); if (bko) { - rvbk = nssPublicKey_CreateFromInstance(bko, vd->td, vd, NULL); + rvbk = nssPublicKey_CreateFromInstance(bko, vd->td, vd); if (!rvbk) { nssCryptokiObject_Destroy(bko); } diff --git a/security/nss/lib/ssl/authcert.c b/security/nss/lib/ssl/authcert.c index 97681e737..249aa390b 100644 --- a/security/nss/lib/ssl/authcert.c +++ b/security/nss/lib/ssl/authcert.c @@ -73,6 +73,8 @@ SSL_GetClientAuthData(void * arg, NULL, NULL); } if (cert) { + /* XXX */ + NSSTrustDomain_Login(td, NULL); privkey = NSSCert_FindPrivateKey(cert, NULL /*XXX pinCallback*/); if (privkey) { *pRetCert = cert; diff --git a/security/nss/tests/stan/stan.sh b/security/nss/tests/stan/stan.sh index 5fc352bf4..7a9b52623 100644 --- a/security/nss/tests/stan/stan.sh +++ b/security/nss/tests/stan/stan.sh @@ -158,7 +158,7 @@ ciph() { echo "" echo ">>>>>>>>>>>>>> ${CIPHER_ACTION} <<<<<<<<<<<<<<" - echo "pkiutil $*" + echo "cipher $*" cipher $* RET=$? if [ "$RET" -ne 0 ]; then |