diff options
147 files changed, 14569 insertions, 19489 deletions
diff --git a/security/nss/cmd/certutil/certutil.c b/security/nss/cmd/certutil/certutil.c index b8cb13758..403332bd7 100644 --- a/security/nss/cmd/certutil/certutil.c +++ b/security/nss/cmd/certutil/certutil.c @@ -272,7 +272,7 @@ GetYesNo(char *prompt) static SECStatus AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts, - PRFileDesc *inFile, PRBool ascii, PRBool emailcert) + PRFileDesc *inFile, PRBool ascii, PRBool emailcert, void *pwdata) { CERTCertTrust *trust = NULL; CERTCertificate *cert = NULL, *tempCert = NULL; @@ -308,6 +308,7 @@ AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts, GEN_BREAK(SECFailure); } +#ifdef notdef /* CERT_ImportCert only collects certificates and returns the * first certficate. It does not insert these certificates into * the dbase. For now, just call CERT_NewTempCertificate. @@ -320,6 +321,7 @@ AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts, if (!PK11_IsInternal(slot)) { tempCert->trust = trust; + rv = PK11_ImportCertForKeyToSlot(slot, tempCert, name, PR_FALSE, NULL); } @@ -337,9 +339,36 @@ AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts, if ( emailcert ) CERT_SaveSMimeProfile(tempCert, NULL, NULL); +#else + cert->trust = trust; + rv = PK11_Authenticate(slot, PR_TRUE, pwdata); + if (rv != SECSuccess) { + SECU_PrintError(progName, "could authenticate to token or database"); + GEN_BREAK(SECFailure); + } + + rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE); + if (rv != SECSuccess) { + SECU_PrintError(progName, "could not add certificate to token or database"); + GEN_BREAK(SECFailure); + } + + rv = CERT_ChangeCertTrust(handle, cert, trust); + if (rv != SECSuccess) { + SECU_PrintError(progName, "could not change trust on certificate"); + GEN_BREAK(SECFailure); + } + + if ( emailcert ) { + CERT_SaveSMimeProfile(cert, NULL, pwdata); + } + +#endif } while (0); +#ifdef notdef CERT_DestroyCertificate (tempCert); +#endif CERT_DestroyCertificate (cert); PORT_Free(trust); PORT_Free(certDER.data); @@ -525,8 +554,8 @@ printCertCB(CERTCertificate *cert, void *arg) if (trust) { SECU_PrintTrustFlags(stdout, trust, "Certificate Trust Flags", 1); - } else { - SECU_PrintTrustFlags(stdout, &cert->dbEntry->trust, + } else if (cert->trust) { + SECU_PrintTrustFlags(stdout, cert->trust, "Certificate Trust Flags", 1); } @@ -544,6 +573,7 @@ listCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot, PRInt32 numBytes; SECStatus rv; +#ifdef nodef /* For now, split handling of slot to internal vs. other. slot should * probably be allowed to be NULL so that all slots can be listed. * In that case, need to add a call to PK11_TraverseSlotCerts(). @@ -584,8 +614,9 @@ listCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot, NULL); } } else { +#endif /* List certs on a non-internal slot. */ - if (PK11_NeedLogin(slot)) + if ( !PK11_IsFriendly(slot) && PK11_NeedLogin(slot)) PK11_Authenticate(slot, PR_TRUE, pwarg); if (name) { CERTCertificate *the_cert; @@ -594,7 +625,22 @@ listCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot, SECU_PrintError(progName, "Could not find: %s\n", name); return SECFailure; } - rv = printCertCB(the_cert, the_cert->trust); + data.data = the_cert->derCert.data; + data.len = the_cert->derCert.len; + if (ascii) { + PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER, + BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER); + rv = SECSuccess; + } else if (raw) { + numBytes = PR_Write(outfile, data.data, data.len); + if (numBytes != data.len) { + SECU_PrintSystemError(progName, "error writing raw cert"); + rv = SECFailure; + } + rv = SECSuccess; + } else { + rv = printCertCB(the_cert, the_cert->trust); + } } else { rv = PK11_TraverseCertsInSlot(slot, SECU_PrintCertNickname, stdout); } @@ -602,7 +648,9 @@ listCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot, SECU_PrintError(progName, "problem printing certificate nicknames"); return SECFailure; } +#ifdef notdef } +#endif return SECSuccess; /* not rv ?? */ } @@ -2690,7 +2738,7 @@ main(int argc, char **argv) certutil.options[opt_Trust].arg, inFile, certutil.options[opt_ASCIIForIO].activated, - certutil.commands[cmd_AddEmailCert].activated); + certutil.commands[cmd_AddEmailCert].activated,&pwdata); if (rv) return 255; } @@ -2701,9 +2749,13 @@ main(int argc, char **argv) PR_Delete(certreqfile); } +#ifdef notdef if ( certHandle ) { CERT_ClosePermCertDB(certHandle); } +#else + NSS_Shutdown(); +#endif return rv; } diff --git a/security/nss/cmd/crlutil/crlutil.c b/security/nss/cmd/crlutil/crlutil.c index b2633c40d..8d0dadc9d 100644 --- a/security/nss/cmd/crlutil/crlutil.c +++ b/security/nss/cmd/crlutil/crlutil.c @@ -64,7 +64,7 @@ static CERTSignedCrl *FindCRL return ((CERTSignedCrl *)NULL); } - crl = SEC_FindCrlByKey(certHandle, &cert->derSubject, type); + crl = SEC_FindCrlByName(certHandle, &cert->derSubject, type); if (crl ==NULL) SECU_PrintError (progName, "could not find %s's CRL", name); @@ -81,7 +81,7 @@ static void DisplayCRL (CERTCertDBHandle *certHandle, char *nickName, int crlTyp if (crl) { SECU_PrintCRLInfo (stdout, &crl->crl, "CRL Info:\n", 0); - CERT_DestroyCrl (crl); + SEC_DestroyCrl (crl); } } @@ -124,10 +124,8 @@ static void ListCRLNames (CERTCertDBHandle *certHandle, int crlType) fprintf (stdout, "\n"); fprintf (stdout, "\n%-40s %-5s\n\n", "CRL names", "CRL Type"); while (crlNode) { - mark = PORT_ArenaMark (arena); - rv = SEC_ASN1DecodeItem - (arena, name, CERT_NameTemplate, &(crlNode->crl->crl.derName)); - if (!name){ + name = &crlNode->crl->crl.name; + if (!name){ fprintf(stderr, "%s: fail to get the CRL issuer name\n", progName, SECU_Strerror(PORT_GetError())); break; @@ -135,7 +133,6 @@ static void ListCRLNames (CERTCertDBHandle *certHandle, int crlType) fprintf (stdout, "\n%-40s %-5s\n", CERT_NameToAscii(name), "CRL"); crlNode = crlNode->next; - PORT_ArenaRelease (arena, mark); } } while (0); @@ -172,14 +169,6 @@ static SECStatus DeleteCRL (CERTCertDBHandle *certHandle, char *name, int type) name, SECU_Strerror(PORT_GetError())); return SECFailure; } - - rv = SEC_DeleteTempCrl (crl); - if (rv != SECSuccess) { - SECU_PrintError - (progName, "fail to delete the issuer %s's CRL from the temp dbase (reason: %s)", - name, SECU_Strerror(PORT_GetError())); - return SECFailure; - } return (rv); } @@ -214,7 +203,7 @@ SECStatus ImportCRL (CERTCertDBHandle *certHandle, char *url, int type, (progName, "unable to import CRL"); } PORT_Free (crlDER.data); - CERT_DestroyCrl (crl); + SEC_DestroyCrl (crl); return (rv); } diff --git a/security/nss/cmd/crlutil/manifest.mn b/security/nss/cmd/crlutil/manifest.mn index e63d71c05..72fafb24a 100644 --- a/security/nss/cmd/crlutil/manifest.mn +++ b/security/nss/cmd/crlutil/manifest.mn @@ -50,4 +50,4 @@ CSRCS = crlutil.c # PROGRAM = ./$(OBJDIR)/crlutil.exe PROGRAM = crlutil -USE_STATIC_LIBS = 1 +#USE_STATIC_LIBS = 1 diff --git a/security/nss/cmd/lib/seccnames.c b/security/nss/cmd/lib/seccnames.c index b2acdfb37..833361e41 100644 --- a/security/nss/cmd/lib/seccnames.c +++ b/security/nss/cmd/lib/seccnames.c @@ -82,7 +82,7 @@ sec_CollectCertNamesAndTrust(CERTCertificate *cert, SECItem *unknown, void *arg) int i; i = pCertNames->numCerts; - name = cert->dbEntry->nickname ? cert->dbEntry->nickname : cert->emailAddr; + name = cert->nickname ? cert->nickname : cert->emailAddr; if (name) pCertNames->nameAndTrustEntries[i].name = PORT_Strdup(name); diff --git a/security/nss/cmd/lib/secutil.c b/security/nss/cmd/lib/secutil.c index f82a0e07a..b706ab7b7 100644 --- a/security/nss/cmd/lib/secutil.c +++ b/security/nss/cmd/lib/secutil.c @@ -1518,20 +1518,6 @@ SECU_PrintCertNickname(CERTCertificate *cert, void *data) PORT_Memset (trusts, 0, sizeof (trusts)); out = (FILE *)data; - if ( cert->dbEntry ) { - name = cert->dbEntry->nickname; - if ( name == NULL ) { - name = cert->emailAddr; - } - - trust = &cert->dbEntry->trust; - printflags(trusts, trust->sslFlags); - PORT_Strcat(trusts, ","); - printflags(trusts, trust->emailFlags); - PORT_Strcat(trusts, ","); - printflags(trusts, trust->objectSigningFlags); - fprintf(out, "%-60s %-5s\n", name, trusts); - } else { name = cert->nickname; if ( name == NULL ) { name = cert->emailAddr; @@ -1548,7 +1534,6 @@ SECU_PrintCertNickname(CERTCertificate *cert, void *data) PORT_Memcpy(trusts,",,",3); } fprintf(out, "%-60s %-5s\n", name, trusts); - } return (SECSuccess); } diff --git a/security/nss/cmd/modutil/manifest.mn b/security/nss/cmd/modutil/manifest.mn index fb0ac6ae3..a40aec6db 100644 --- a/security/nss/cmd/modutil/manifest.mn +++ b/security/nss/cmd/modutil/manifest.mn @@ -54,6 +54,7 @@ REQUIRES = seccmd security dbm DEFINES = -DNSPR20 -INCLUDES = +# sigh +INCLUDES += -I$(CORE_DEPTH)/nss/lib/pk11wrap -USE_STATIC_LIBS = 1 +USE_STATIC_LIBS = 1 diff --git a/security/nss/cmd/modutil/modutil.c b/security/nss/cmd/modutil/modutil.c index 522d070b4..b3505f7fc 100644 --- a/security/nss/cmd/modutil/modutil.c +++ b/security/nss/cmd/modutil/modutil.c @@ -57,6 +57,7 @@ typedef enum { JAR_COMMAND, LIST_COMMAND, RAW_LIST_COMMAND, + RAW_ADD_COMMAND, UNDEFAULT_COMMAND } Command; @@ -74,6 +75,7 @@ static char *commandNames[] = { "-jar", "-list", "-rawlist", + "-rawadd", "-undefault" }; @@ -81,6 +83,7 @@ static char *commandNames[] = { /* this enum must be kept in sync with the optionStrings list */ typedef enum { ADD_ARG=0, + RAW_ADD_ARG, CHANGEPW_ARG, CIPHERS_ARG, CREATE_ARG, @@ -112,6 +115,7 @@ typedef enum { /* This list must be kept in sync with the Arg enum */ static char *optionStrings[] = { "-add", + "-rawadd", "-changepw", "-ciphers", "-create", @@ -150,6 +154,7 @@ static Command command = NO_COMMAND; static char* pwFile = NULL; static char* newpwFile = NULL; static char* moduleName = NULL; +static char* moduleSpec = NULL; static char* slotName = NULL; static char* secmodName = NULL; static char* tokenName = NULL; @@ -398,6 +403,18 @@ parse_args(int argc, char *argv[]) moduleName = argv[++i]; } break; + case RAW_ADD_ARG: + if(command != NO_COMMAND) { + PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg); + return MULTIPLE_COMMAND_ERR; + } + command = RAW_ADD_COMMAND; + if(TRY_INC(i, argc)) { + PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg); + return OPTION_NEEDS_ARG_ERR; + } + moduleSpec = argv[i]; + break; case MECHANISMS_ARG: if(mechanisms != NULL) { PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg); @@ -500,6 +517,8 @@ verify_params() case LIST_COMMAND: case RAW_LIST_COMMAND: break; + case RAW_ADD_COMMAND: + break; case UNDEFAULT_COMMAND: case DEFAULT_COMMAND: if(mechanisms == NULL) { @@ -777,17 +796,26 @@ main(int argc, char *argv[]) goto loser; } - if (command == RAW_LIST_COMMAND) { + if ((command == RAW_LIST_COMMAND) || (command == RAW_ADD_COMMAND)) { if(!moduleName) { + char *readOnlyStr, *noCertDBStr, *sep; if (!secmodName) secmodName="secmod.db"; if (!dbprefix) dbprefix = ""; + sep = ((command == RAW_LIST_COMMAND) && nocertdb) ? "," : " "; + readOnlyStr = (command == RAW_LIST_COMMAND) ? "readOnly" : "" ; + noCertDBStr = nocertdb ? "noCertDB" : ""; SECU_ConfigDirectory(dbdir); - moduleName=PR_smprintf("name=\"NSS default Module DB\" parameters=\"configdir=%s certPrefix=%s keyPrefix=%s secmod=%s flags=readOnly%s\" NSS=\"flags=internal,moduleDB,moduleDBOnly,critical\"", - SECU_ConfigDirectory(NULL),dbprefix, - dbprefix,secmodName, nocertdb?",noCertDB":""); + moduleName=PR_smprintf("name=\"NSS default Module DB\" parameters=\"configdir=%s certPrefix=%s keyPrefix=%s secmod=%s flags=%s%s%s\" NSS=\"flags=internal,moduleDB,moduleDBOnly,critical\"", + SECU_ConfigDirectory(NULL),dbprefix, dbprefix, + secmodName, readOnlyStr,sep, noCertDBStr); + } + if (command == RAW_LIST_COMMAND) { + errcode = RawListModule(moduleName); + } else { + PORT_Assert(moduleSpec); + errcode = RawAddModule(moduleName,moduleSpec); } - errcode = RawListModule(moduleName); goto loser; } diff --git a/security/nss/cmd/modutil/pk11.c b/security/nss/cmd/modutil/pk11.c index 7f8433e8b..20838e6a0 100644 --- a/security/nss/cmd/modutil/pk11.c +++ b/security/nss/cmd/modutil/pk11.c @@ -303,6 +303,31 @@ RawListModule(char *modulespec) return SUCCESS; } +RawAddModule(char *dbmodulespec, char *modulespec) +{ + SECMODModule *module; + SECMODModule *dbmodule; + + + dbmodule = SECMOD_LoadModule(dbmodulespec,NULL,PR_TRUE); + if (dbmodule == NULL) { + /* handle error */ + return NO_SUCH_MODULE_ERR; + } + + module = SECMOD_LoadModule(modulespec,dbmodule,PR_FALSE); + if (module == NULL) { + /* handle error */ + return NO_SUCH_MODULE_ERR; + } + + if( SECMOD_UpdateModule(module) != SECSuccess ) { + PR_fprintf(PR_STDERR, errStrings[UPDATE_MOD_FAILED_ERR], modulespec); + return UPDATE_MOD_FAILED_ERR; + } + return SUCCESS; +} + /************************************************************************ * * L i s t M o d u l e s diff --git a/security/nss/cmd/ocspclnt/ocspclnt.c b/security/nss/cmd/ocspclnt/ocspclnt.c index c26633fbe..a5a1448c6 100644 --- a/security/nss/cmd/ocspclnt/ocspclnt.c +++ b/security/nss/cmd/ocspclnt/ocspclnt.c @@ -859,7 +859,7 @@ print_response (FILE *out_file, SECItem *data, CERTCertDBHandle *handle) } sigStatus = CERT_VerifyOCSPResponseSignature (response, handle, - NULL, &signerCert); + NULL, &signerCert, NULL); SECU_Indent (out_file, level); fprintf (out_file, "Signature verification "); if (sigStatus != SECSuccess) { @@ -1209,7 +1209,6 @@ nssdone: if (handle != NULL) { (void) CERT_DisableOCSPChecking (handle); - CERT_ClosePermCertDB (handle); } NSS_Shutdown (); diff --git a/security/nss/cmd/platlibs.mk b/security/nss/cmd/platlibs.mk index 8c0220c4e..2b82b4a7f 100644 --- a/security/nss/cmd/platlibs.mk +++ b/security/nss/cmd/platlibs.mk @@ -61,7 +61,7 @@ EXTRA_LIBS += \ $(DIST)/lib/cryptohi.lib \ $(DIST)/lib/pk11wrap.lib \ $(DIST)/lib/certdb.lib \ - $(DIST)/lib/softoken.lib \ + $(DIST)/lib/softokn.lib \ $(CRYPTOLIB) \ $(DIST)/lib/swfci.lib \ $(DIST)/lib/secutil.lib \ @@ -106,7 +106,7 @@ EXTRA_LIBS += \ $(DIST)/lib/libcerthi.$(LIB_SUFFIX) \ $(DIST)/lib/libnsspki.$(LIB_SUFFIX) \ $(DIST)/lib/libpk11wrap.$(LIB_SUFFIX) \ - $(DIST)/lib/libsoftoken.$(LIB_SUFFIX) \ + $(DIST)/lib/libsoftokn.$(LIB_SUFFIX) \ $(DIST)/lib/libcertdb.$(LIB_SUFFIX) \ $(DIST)/lib/libnsspki.$(LIB_SUFFIX) \ $(DIST)/lib/libnssdev.$(LIB_SUFFIX) \ diff --git a/security/nss/cmd/rsaperf/defkey.c b/security/nss/cmd/rsaperf/defkey.c index bcab2b683..fe4870d77 100644 --- a/security/nss/cmd/rsaperf/defkey.c +++ b/security/nss/cmd/rsaperf/defkey.c @@ -36,7 +36,7 @@ */ #include "seccomon.h" #include "secoidt.h" -#include "keytlow.h" +#include "lowkeyti.h" #define CONST @@ -100,16 +100,16 @@ static CONST unsigned char default_qInvModP[64] = { }; -static struct SECKEYLowPrivateKeyStr rsaPriv; +static struct NSSLOWKEYPrivateKeyStr rsaPriv; -SECKEYLowPrivateKey * +NSSLOWKEYPrivateKey * getDefaultRSAPrivateKey(void) { - if (rsaPriv.keyType != lowRSAKey) { + if (rsaPriv.keyType != NSSLOWKEYRSAKey) { /* leaving arena uninitialized. It isn't used in this test. */ - rsaPriv.keyType = lowRSAKey; + rsaPriv.keyType = NSSLOWKEYRSAKey; /* leaving arena uninitialized. It isn't used. */ /* leaving version uninitialized. It isn't used. */ @@ -134,14 +134,14 @@ getDefaultRSAPrivateKey(void) return &rsaPriv; } -static struct SECKEYLowPublicKeyStr rsaPub; +static struct NSSLOWKEYPublicKeyStr rsaPub; -SECKEYLowPublicKey * +NSSLOWKEYPublicKey * getDefaultRSAPublicKey(void) { - if (rsaPub.keyType != lowRSAKey) { + if (rsaPub.keyType != NSSLOWKEYRSAKey) { - rsaPub.keyType = lowRSAKey; + rsaPub.keyType = NSSLOWKEYRSAKey; rsaPub.u.rsa.modulus.data = default_n; rsaPub.u.rsa.modulus.len = sizeof default_n; diff --git a/security/nss/cmd/rsaperf/rsaperf.c b/security/nss/cmd/rsaperf/rsaperf.c index dbfc21d01..36a9ea383 100644 --- a/security/nss/cmd/rsaperf/rsaperf.c +++ b/security/nss/cmd/rsaperf/rsaperf.c @@ -38,14 +38,14 @@ #include "nss.h" #include "blapi.h" #include "plgetopt.h" -#include "keylow.h" +#include "lowkeyi.h" #define MAX_RSA_MODULUS_BYTES (1024/8) #define DEFAULT_ITERS 10 -extern SECKEYLowPrivateKey * getDefaultRSAPrivateKey(void); -extern SECKEYLowPublicKey * getDefaultRSAPublicKey(void); +extern NSSLOWKEYPrivateKey * getDefaultRSAPrivateKey(void); +extern NSSLOWKEYPublicKey * getDefaultRSAPublicKey(void); typedef struct TimingContextStr TimingContext; @@ -196,7 +196,7 @@ dumpItem( SECItem * item, const char * description) } void -printPrivKey(SECKEYLowPrivateKey * privKey) +printPrivKey(NSSLOWKEYPrivateKey * privKey) { RSAPrivateKey *rsa = &privKey->u.rsa; @@ -226,10 +226,9 @@ int main(int argc, char **argv) { TimingContext * timeCtx; - SECKEYKeyDBHandle * keydb; SECKEYPublicKey * pubHighKey; - SECKEYLowPrivateKey * privKey; - SECKEYLowPublicKey * pubKey; + NSSLOWKEYPrivateKey * privKey; + NSSLOWKEYPublicKey * pubKey; CERTCertificate * cert; char * progName; char * secDir = NULL; @@ -292,7 +291,6 @@ main(int argc, char **argv) exit(1); } certdb = CERT_GetDefaultCertDB(); - keydb = SECKEY_GetDefaultKeyDB(); } else { rv = NSS_NoDB_Init(secDir); if (rv != SECSuccess) { @@ -342,9 +340,6 @@ main(int argc, char **argv) exit(1); } -#if 0 - printPrivKey(privKey); -#endif fn = (RSAOp)RSA_PrivateKeyOp; rsaKey = (void *)(&privKey->u.rsa); } diff --git a/security/nss/cmd/signtool/certgen.c b/security/nss/cmd/signtool/certgen.c index 0709e5b44..dd7128eaa 100644 --- a/security/nss/cmd/signtool/certgen.c +++ b/security/nss/cmd/signtool/certgen.c @@ -498,8 +498,7 @@ install_cert(CERTCertDBHandle *db, PK11SlotInfo *slot, SECItem *derCert, CERTCertTrust trust; PK11SlotInfo *newSlot; - newcert = CERT_NewTempCertificate(db, derCert, NULL, - /*isperm*/ PR_FALSE, /*copyDER*/ PR_TRUE); + newcert = CERT_DecodeDERCertificate(derCert, PR_TRUE, NULL); if (newcert == NULL) { PR_fprintf(errorFD, "%s: can't create new certificate\n", PROGRAM_NAME); diff --git a/security/nss/cmd/signtool/list.c b/security/nss/cmd/signtool/list.c index 83ae4d6a3..2e2d1d1ac 100644 --- a/security/nss/cmd/signtool/list.c +++ b/security/nss/cmd/signtool/list.c @@ -91,14 +91,6 @@ ListCerts(char *key, int list_certs) return -1; } - /* Traverse Internal DB */ - rv = SEC_TraversePermCerts(db, cert_trav_callback, (void*)&list_certs); - - if (rv) { - PR_fprintf(outputFD, "**Traverse of internal DB failed**\n"); - return -1; - } - if (num_trav_certs == 0) { PR_fprintf(outputFD, "You don't appear to have any object signing certificates.\n"); diff --git a/security/nss/cmd/swfort/instinit/instinit.c b/security/nss/cmd/swfort/instinit/instinit.c index 5c840bab4..f6e5e5e2f 100644 --- a/security/nss/cmd/swfort/instinit/instinit.c +++ b/security/nss/cmd/swfort/instinit/instinit.c @@ -318,7 +318,8 @@ main(int argc, char ** argv) } continue; } - cert = CERT_NewTempCertificate(certhandle,derCert, NULL, + cert = (CERTCertificate *) + __CERT_NewTempCertificate(certhandle,derCert, NULL, PR_FALSE, PR_TRUE); if (cert == NULL) { if (verbose) { diff --git a/security/nss/cmd/swfort/newuser/newuser.c b/security/nss/cmd/swfort/newuser/newuser.c index f6862af31..94e6c21ab 100644 --- a/security/nss/cmd/swfort/newuser/newuser.c +++ b/security/nss/cmd/swfort/newuser/newuser.c @@ -40,7 +40,7 @@ #include "blapi.h" /* program calls low level functions directly!*/ #include "pk11func.h" #include "secmod.h" -#include "secmodi.h" +/*#include "secmodi.h"*/ #include "cert.h" #include "key.h" #include "swforti.h" @@ -791,7 +791,8 @@ main(int argc, char **argv) } derCert.data = origCert; derCert.len = Cert_length(origCert, sizeof(origCert)); - cert = CERT_NewTempCertificate(certhandle,&derCert, NULL, + cert = + (CERTCertificate *)CERT_NewTempCertificate(certhandle,&derCert, NULL, PR_FALSE, PR_TRUE); caCert.valid[i].cert = cert; if (cert == NULL) continue; diff --git a/security/nss/lib/asn1/asn1.c b/security/nss/lib/asn1/asn1.c index 3d5cfc8f7..9c584c770 100644 --- a/security/nss/lib/asn1/asn1.c +++ b/security/nss/lib/asn1/asn1.c @@ -316,7 +316,7 @@ nssASN1Decoder_Update PRUint32 amount ) { - PRStatus rv; + SECStatus rv; #ifdef DEBUG if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) { @@ -332,7 +332,7 @@ nssASN1Decoder_Update rv = SEC_ASN1DecoderUpdate((SEC_ASN1DecoderContext *)decoder, (const char *)data, (unsigned long)amount); - if( PR_SUCCESS != rv ) { + if( SECSuccess != rv ) { nss_SetError(PORT_GetError()); /* ugly */ return PR_FAILURE; } @@ -361,7 +361,8 @@ nssASN1Decoder_Finish nssASN1Decoder *decoder ) { - PRStatus rv; + PRStatus rv = PR_SUCCESS; + SECStatus srv; #ifdef DEBUG if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) { @@ -369,10 +370,11 @@ nssASN1Decoder_Finish } #endif /* DEBUG */ - rv = SEC_ASN1DecoderFinish((SEC_ASN1DecoderContext *)decoder); + srv = SEC_ASN1DecoderFinish((SEC_ASN1DecoderContext *)decoder); - if( PR_SUCCESS != rv ) { + if( SECSuccess != srv ) { nss_SetError(PORT_GetError()); /* ugly */ + rv = PR_FAILURE; } #ifdef DEBUG @@ -763,7 +765,7 @@ nssASN1Encoder_Update PRUint32 length ) { - PRStatus rv; + SECStatus rv; #ifdef DEBUG if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) { @@ -778,7 +780,7 @@ nssASN1Encoder_Update rv = SEC_ASN1EncoderUpdate((SEC_ASN1EncoderContext *)encoder, (const char *)data, (unsigned long)length); - if( PR_SUCCESS != rv ) { + if( SECSuccess != rv ) { nss_SetError(PORT_GetError()); /* ugly */ return PR_FAILURE; } @@ -1187,7 +1189,6 @@ nssASN1_EncodeItem NSSASN1EncodingType encoding ) { - PLArenaPool *hack = (PLArenaPool *)arenaOpt; NSSDER *rv; PRUint32 len = 0; PRStatus status; diff --git a/security/nss/lib/base/list.c b/security/nss/lib/base/list.c index 6bcde183c..7738633d4 100644 --- a/security/nss/lib/base/list.c +++ b/security/nss/lib/base/list.c @@ -91,7 +91,10 @@ nsslist_get_matching_element(nssList *list, void *data) break; } link = &node->link; - if (link == PR_LIST_TAIL(&list->head->link)) break; + if (link == PR_LIST_TAIL(&list->head->link)) { + node = NULL; + break; + } node = (nssListElement *)PR_NEXT_LINK(&node->link); } return node; diff --git a/security/nss/lib/base/nssbaset.h b/security/nss/lib/base/nssbaset.h index f5cea5fb0..c3e84c46e 100644 --- a/security/nss/lib/base/nssbaset.h +++ b/security/nss/lib/base/nssbaset.h @@ -138,7 +138,7 @@ typedef NSSItem NSSBitString; * Character strings encoded in UTF-8, as defined by RFC 2279. */ -typedef PRUint8 NSSUTF8; +typedef char NSSUTF8; /* * NSSASCII7 @@ -146,7 +146,7 @@ typedef PRUint8 NSSUTF8; * Character strings guaranteed to be 7-bit ASCII. */ -typedef PRUint8 NSSASCII7; +typedef char NSSASCII7; PR_END_EXTERN_C diff --git a/security/nss/lib/base/utf8.c b/security/nss/lib/base/utf8.c index 6be6912d7..3a8641f95 100644 --- a/security/nss/lib/base/utf8.c +++ b/security/nss/lib/base/utf8.c @@ -679,7 +679,7 @@ nssUTF8_CopyIntoFixedBuffer #endif /* NSSDEBUG */ if( (NSSUTF8 *)NULL == string ) { - string = (unsigned char*) ""; + string = (NSSUTF8 *) ""; } stringSize = nssUTF8_Size(string, (PRStatus *)NULL); @@ -699,7 +699,7 @@ nssUTF8_CopyIntoFixedBuffer } /* Too long. We have to trim the last character */ - for( bs; bs != 0; bs-- ) { + for( /*bs*/; bs != 0; bs-- ) { if( (buffer[bs-1] & 0xC0) != 0x80 ) { buffer[bs-1] = pad; break; diff --git a/security/nss/lib/certdb/cert.h b/security/nss/lib/certdb/cert.h index 5a70d7302..394d518f9 100644 --- a/security/nss/lib/certdb/cert.h +++ b/security/nss/lib/certdb/cert.h @@ -276,6 +276,10 @@ extern CERTCertDBHandle *CERT_GetDefaultCertDB(void); extern CERTCertList *CERT_GetCertChainFromCert(CERTCertificate *cert, int64 time, SECCertUsage usage); +extern CERTCertificate * +CERT_NewTempCertificate (CERTCertDBHandle *handle, SECItem *derCert, + char *nickname, PRBool isperm, PRBool copyDER); + /****************************************************************************** * @@ -397,26 +401,7 @@ extern void CERT_DestroyCrl (CERTSignedCrl *crl); ** Decode a certificate and put it into the temporary certificate database */ extern CERTCertificate * -CERT_NewTempCertificate (CERTCertDBHandle *handle, SECItem *derCert, - char *nickname, PRBool isperm, PRBool copyDER); - -/* -** Add a certificate to the temporary database. -** "dbCert" is the certificate from the perm database. -** "isperm" indicates if the cert is in the permanent database. -*/ -extern CERTCertificate * -CERT_AddTempCertificate (CERTCertDBHandle *handle, certDBEntryCert *entry, - PRBool isperm); - -/* -** Add a temporary certificate to the permanent database. -** "cert" is the temporary cert -** "nickname" is the permanent nickname to use -** "trust" is the certificate trust parameters to assign to the cert -*/ -extern SECStatus -CERT_AddTempCertToPerm (CERTCertificate *cert, char *nickname, CERTCertTrust *trust); +CERT_DecodeCertificate (SECItem *derCert, char *nickname,PRBool copyDER); /* ** Find a certificate in the database @@ -425,16 +410,6 @@ CERT_AddTempCertToPerm (CERTCertificate *cert, char *nickname, CERTCertTrust *tr extern CERTCertificate *CERT_FindCertByKey(CERTCertDBHandle *handle, SECItem *key); /* - * Lookup a certificate in the databases without locking - * "certKey" is the database key to look for - * - * XXX - this should be internal, but pkcs 11 needs to call it during a - * traversal. - */ -CERTCertificate * -CERT_FindCertByKeyNoLocking(CERTCertDBHandle *handle, SECItem *certKey); - -/* ** Find a certificate in the database by name ** "name" is the distinguished name to look up */ @@ -470,6 +445,7 @@ CERT_FindCertByIssuerAndSN (CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAnd */ extern CERTCertificate * CERT_FindCertByNickname (CERTCertDBHandle *handle, char *nickname); + /* ** Find a certificate in the database by a DER encoded certificate ** "derCert" is the DER encoded certificate @@ -505,17 +481,6 @@ CERTCertificate * CERT_FindCertIssuer(CERTCertificate *cert, int64 validTime, SECCertUsage usage); /* -** Delete a certificate from the temporary database -** "cert" is the certificate to be deleted -*/ -extern SECStatus CERT_DeleteTempCertificate(CERTCertificate *cert); - -/* -** Flush and close the permanent database. -*/ -extern void CERT_ClosePermCertDB(CERTCertDBHandle *handle); - -/* ** Check the validity times of a certificate vs. time 't', allowing ** some slop for broken clocks and stuff. ** "cert" is the certificate to be checked @@ -641,6 +606,14 @@ extern char *CERT_HTMLCertInfo(CERTCertificate *cert, PRBool showImages, */ extern SECItem *CERT_DecodeAVAValue(SECItem *derAVAValue); +/* + * take a DER certificate and decode it into a certificate structure + */ +CERTCertificate * +CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, + char *nickname); + + /* ** extract various element strings from a distinguished name. @@ -926,32 +899,6 @@ extern void CERT_DestroyCertificateList(CERTCertificateList *list); /* is cert a newer than cert b? */ PRBool CERT_IsNewer(CERTCertificate *certa, CERTCertificate *certb); -typedef SECStatus (* CERTCertCallback)(CERTCertificate *cert, void *arg); - -SECStatus -CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle, SECItem *derSubject, - CERTCertCallback cb, void *cbarg); -int -CERT_NumPermCertsForSubject(CERTCertDBHandle *handle, SECItem *derSubject); - -SECStatus -CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname, - CERTCertCallback cb, void *cbarg); - -int -CERT_NumPermCertsForNickname(CERTCertDBHandle *handle, char *nickname); - -int -CERT_NumCertsForCertSubject(CERTCertificate *cert); - -int -CERT_NumPermCertsForCertSubject(CERTCertificate *cert); - -SECStatus -CERT_TraverseCertsForSubject(CERTCertDBHandle *handle, - CERTSubjectList *subjectList, - CERTCertCallback cb, void *cbarg); - /* currently a stub for address book */ PRBool CERT_IsCertRevoked(CERTCertificate *cert); @@ -1009,12 +956,6 @@ CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile, SECItem * CERT_FindSMimeProfile(CERTCertificate *cert); -int -CERT_GetDBContentVersion(CERTCertDBHandle *handle); - -void -CERT_SetDBContentVersion(int version, CERTCertDBHandle *handle); - SECStatus CERT_AddNewCerts(CERTCertDBHandle *handle); @@ -1370,6 +1311,8 @@ CERT_GetStatusConfig(CERTCertDBHandle *handle); void CERT_SetStatusConfig(CERTCertDBHandle *handle, CERTStatusConfig *config); + + /* * Acquire the cert reference count lock * There is currently one global lock for all certs, but I'm putting a cert diff --git a/security/nss/lib/certdb/certdb.c b/security/nss/lib/certdb/certdb.c index 75413cc04..592418f5a 100644 --- a/security/nss/lib/certdb/certdb.c +++ b/security/nss/lib/certdb/certdb.c @@ -58,7 +58,7 @@ #include "secerr.h" #include "sslerr.h" #include "nsslocks.h" -#include "cdbhdl.h" +#include "pk11func.h" #ifndef NSS_3_4_CODE #define NSS_3_4_CODE @@ -462,7 +462,7 @@ fortezzaIsCA( CERTCertificate *cert) { unsigned char *end; int len; - rawkey = spki->subjectPublicKey; + rawkey = spki->subjectPublicKey; DER_ConvertBitString(&rawkey); rawptr = rawkey.data; end = rawkey.data + rawkey.len; @@ -489,7 +489,7 @@ fortezzaIsCA( CERTCertificate *cert) { /* DSSPrivilege (the string up to the first byte with the hi-bit on */ if (*rawptr & 0x30) isCA = PR_TRUE; - + } return isCA; } @@ -627,12 +627,12 @@ CERT_GetCertType(CERTCertificate *cert) cert->nsCertType = NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_SSL_SERVER | NS_CERT_TYPE_EMAIL; - /* if the basic constraint extension says the cert is a CA, then + /* if the basic constraint extension says the cert is a CA, then allow SSL CA and EMAIL CA and Status Responder */ if ((basicConstraintPresent == PR_TRUE) && (basicConstraint.isCA)) { - cert->nsCertType |= NS_CERT_TYPE_SSL_CA; - cert->nsCertType |= NS_CERT_TYPE_EMAIL_CA; + cert->nsCertType |= NS_CERT_TYPE_SSL_CA; + cert->nsCertType |= NS_CERT_TYPE_EMAIL_CA; cert->nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER; } else if (CERT_IsCACert(cert, NULL) == PR_TRUE) { cert->nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER; @@ -640,8 +640,8 @@ CERT_GetCertType(CERTCertificate *cert) /* if the cert is a fortezza CA cert, then allow SSL CA and EMAIL CA */ if (fortezzaIsCA(cert)) { - cert->nsCertType |= NS_CERT_TYPE_SSL_CA; - cert->nsCertType |= NS_CERT_TYPE_EMAIL_CA; + cert->nsCertType |= NS_CERT_TYPE_SSL_CA; + cert->nsCertType |= NS_CERT_TYPE_EMAIL_CA; } } @@ -688,9 +688,9 @@ cert_GetKeyID(CERTCertificate *cert) cert->subjectKeyID.data = (unsigned char *)PORT_ArenaAlloc(cert->arena, 8); if ( cert->subjectKeyID.data != NULL ) { - PORT_Memcpy(cert->subjectKeyID.data, key->u.fortezza.KMID, 8); - cert->subjectKeyID.len = 8; - cert->keyIDGenerated = PR_FALSE; + PORT_Memcpy(cert->subjectKeyID.data, key->u.fortezza.KMID, 8); + cert->subjectKeyID.len = 8; + cert->keyIDGenerated = PR_FALSE; } } @@ -705,7 +705,7 @@ cert_GetKeyID(CERTCertificate *cert) */ cert->subjectKeyID.data = (unsigned char *)PORT_ArenaAlloc(cert->arena, SHA1_LENGTH); if ( cert->subjectKeyID.data != NULL ) { - rv = SHA1_HashBuf(cert->subjectKeyID.data, + rv = PK11_HashBuf(SEC_OID_SHA1,cert->subjectKeyID.data, cert->derPublicKey.data, cert->derPublicKey.len); if ( rv == SECSuccess ) { @@ -725,7 +725,7 @@ cert_GetKeyID(CERTCertificate *cert) * take a DER certificate and decode it into a certificate structure */ CERTCertificate * -__CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, +CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, char *nickname) { CERTCertificate *cert; @@ -833,7 +833,7 @@ __CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, cert->referenceCount = 1; cert->slot = NULL; - cert->pkcs11ID = CK_INVALID_KEY; + cert->pkcs11ID = CK_INVALID_HANDLE; cert->dbnickname = NULL; return(cert); @@ -848,12 +848,13 @@ loser: } CERTCertificate * -CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, +__CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, char *nickname) { - return(__CERT_DecodeDERCertificate(derSignedCert, copyDER, nickname)); + return CERT_DecodeDERCertificate(derSignedCert, copyDER, nickname); } + /* ** Amount of time that a certifiate is allowed good before it is actually ** good. This is used for pending certificates, ones that are about to be @@ -909,7 +910,7 @@ CERT_CheckCertValidTimes(CERTCertificate *c, PRTime t, PRBool allowOverride) /* if cert is already marked OK, then don't bother to check */ if ( allowOverride && c->timeOK ) { - return(secCertTimeValid); + return(secCertTimeValid); } rv = CERT_GetCertTimes(c, ¬Before, ¬After); @@ -1184,70 +1185,6 @@ CERT_GetDefaultCertDB(void) return(default_cert_db_handle); } -/* - * Open volatile certificate database and index databases. This is a - * fallback if the real databases can't be opened or created. It is only - * resident in memory, so it will not be persistent. We do this so that - * we don't crash if the databases can't be created. - */ -SECStatus -CERT_OpenVolatileCertDB(CERTCertDBHandle *handle) -{ -#ifndef STAN_CERT_DB -#define DBM_DEFAULT 0 - static const HASHINFO hashInfo = { - DBM_DEFAULT, /* bucket size */ - DBM_DEFAULT, /* fill factor */ - DBM_DEFAULT, /* number of elements */ - 256 * 1024, /* bytes to cache */ - DBM_DEFAULT, /* hash function */ - DBM_DEFAULT /* byte order */ - }; - /* - * Open the memory resident perm cert database. - */ - handle->permCertDB = dbopen(0, O_RDWR | O_CREAT, 0600, DB_HASH, &hashInfo); - if ( !handle->permCertDB ) { - goto loser; - } - - /* - * Open the memory resident decoded cert database. - */ - handle->tempCertDB = dbopen(0, O_RDWR | O_CREAT, 0600, DB_HASH, &hashInfo); - if ( !handle->tempCertDB ) { - goto loser; - } - - handle->dbMon = PZ_NewMonitor(nssILockCertDB); - PORT_Assert(handle->dbMon != NULL); - - handle->spkDigestInfo = NULL; - handle->statusConfig = NULL; - - /* initialize the cert database */ - (void) CERT_InitCertDB(handle); - - return (SECSuccess); - -loser: - - PORT_SetError(SEC_ERROR_BAD_DATABASE); - - if ( handle->permCertDB ) { - (* handle->permCertDB->close)(handle->permCertDB); - handle->permCertDB = 0; - } - - if ( handle->tempCertDB ) { - (* handle->tempCertDB->close)(handle->tempCertDB); - handle->tempCertDB = 0; - } - -#endif - return(SECFailure); -} - /* XXX this would probably be okay/better as an xp routine? */ static void sec_lower_string(char *s) @@ -1272,14 +1209,14 @@ SECStatus CERT_AddOKDomainName(CERTCertificate *cert, const char *hn) { CERTOKDomainName *domainOK; - int newNameLen; + int newNameLen; if (!hn || !(newNameLen = strlen(hn))) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } domainOK = (CERTOKDomainName *)PORT_ArenaZAlloc(cert->arena, - (sizeof *domainOK) + newNameLen); + (sizeof *domainOK) + newNameLen); if (!domainOK) return SECFailure; /* error code is already set. */ @@ -1705,14 +1642,12 @@ CERT_IsCACert(CERTCertificate *cert, unsigned int *rettype) return(ret); } - PRBool CERT_IsCADERCert(SECItem *derCert, unsigned int *type) { CERTCertificate *cert; PRBool isCA; - cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert, NULL, - PR_FALSE, PR_TRUE); + cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if (cert == NULL) return PR_FALSE; isCA = CERT_IsCACert(cert,type); @@ -1961,8 +1896,8 @@ CERT_ImportCerts(CERTCertDBHandle *certdb, SECCertUsage usage, /* decode all of the certs into the temporary DB */ for ( i = 0, fcerts= 0; i < ncerts; i++) { - certs[fcerts] = CERT_NewTempCertificate(certdb, derCerts[i], NULL, - PR_FALSE, PR_TRUE); + certs[fcerts] = CERT_DecodeDERCertificate(derCerts[i], PR_FALSE, + NULL); if (certs[fcerts]) fcerts++; } @@ -1975,10 +1910,11 @@ CERT_ImportCerts(CERTCertDBHandle *certdb, SECCertUsage usage, * otherwise if there are more than one cert, we don't * know which cert it belongs to. */ - rv = CERT_SaveImportedCert(certs[i], usage, caOnly, NULL); + rv = PK11_ImportCert(PK11_GetInternalKeySlot(),certs[i], + CK_INVALID_HANDLE,NULL,PR_TRUE); } else { - rv = CERT_SaveImportedCert(certs[i], usage, caOnly, - nickname); + rv = PK11_ImportCert(PK11_GetInternalKeySlot(),certs[i], + CK_INVALID_HANDLE,nickname,PR_TRUE); } /* don't care if it fails - keep going */ } @@ -2321,40 +2257,6 @@ loser: return(SECFailure); } -/* - * Acquire the global lock on the cert database. - * This lock is currently used for the following operations: - * adding or deleting a cert to either the temp or perm databases - * converting a temp to perm or perm to temp - * changing(maybe just adding !?) the trust of a cert - * chaning the DB status checking Configuration - */ -void -CERT_LockDB(CERTCertDBHandle *handle) -{ -#ifndef STAN_CERT_DB - PZ_EnterMonitor(handle->dbMon); - return; -#endif -} - -/* - * Free the global cert database lock. - */ -void -CERT_UnlockDB(CERTCertDBHandle *handle) -{ -#ifndef STAN_CERT_DB - PRStatus prstat; - - prstat = PZ_ExitMonitor(handle->dbMon); - - PORT_Assert(prstat == PR_SUCCESS); - - return; -#endif -} - static PZLock *certRefCountLock = NULL; /* @@ -2436,7 +2338,12 @@ CERT_UnlockCertTrust(CERTCertificate *cert) CERTStatusConfig * CERT_GetStatusConfig(CERTCertDBHandle *handle) { +#ifdef notdef return handle->statusConfig; +#else + /*PORT_Assert(0); */ + return NULL; +#endif } /* @@ -2446,7 +2353,10 @@ CERT_GetStatusConfig(CERTCertDBHandle *handle) void CERT_SetStatusConfig(CERTCertDBHandle *handle, CERTStatusConfig *statusConfig) { +#ifdef notdef PORT_Assert(handle->statusConfig == NULL); - handle->statusConfig = statusConfig; +#else + PORT_Assert(0); +#endif } diff --git a/security/nss/lib/certdb/certdb.h b/security/nss/lib/certdb/certdb.h index 2d75ee8b5..736d5f097 100644 --- a/security/nss/lib/certdb/certdb.h +++ b/security/nss/lib/certdb/certdb.h @@ -34,247 +34,6 @@ #ifndef _CERTDB_H_ #define _CERTDB_H_ -#include "plarena.h" -#include "prlong.h" -/* - * Certificate Database related definitions and data structures - */ - -/* version number of certificate database */ -#define CERT_DB_FILE_VERSION 7 -#ifdef USE_NS_ROOTS -#define CERT_DB_CONTENT_VERSION 28 -#else -#define CERT_DB_CONTENT_VERSION 2 -#endif - -#define SEC_DB_ENTRY_HEADER_LEN 3 -#define SEC_DB_KEY_HEADER_LEN 1 - -/* All database entries have this form: - * - * byte offset field - * ----------- ----- - * 0 version - * 1 type - * 2 flags - */ - -/* database entry types */ -typedef enum { - certDBEntryTypeVersion = 0, - certDBEntryTypeCert = 1, - certDBEntryTypeNickname = 2, - certDBEntryTypeSubject = 3, - certDBEntryTypeRevocation = 4, - certDBEntryTypeKeyRevocation = 5, - certDBEntryTypeSMimeProfile = 6, - certDBEntryTypeContentVersion = 7 -} certDBEntryType; - -typedef struct { - certDBEntryType type; - unsigned int version; - unsigned int flags; - PRArenaPool *arena; -} certDBEntryCommon; - -/* - * Certificate entry: - * - * byte offset field - * ----------- ----- - * 0 sslFlags-msb - * 1 sslFlags-lsb - * 2 emailFlags-msb - * 3 emailFlags-lsb - * 4 objectSigningFlags-msb - * 5 objectSigningFlags-lsb - * 6 derCert-len-msb - * 7 derCert-len-lsb - * 8 nickname-len-msb - * 9 nickname-len-lsb - * ... derCert - * ... nickname - * - * NOTE: the nickname string as stored in the database is null terminated, - * in other words, the last byte of the db entry is always 0 - * if a nickname is present. - * NOTE: if nickname is not present, then nickname-len-msb and - * nickname-len-lsb will both be zero. - */ -struct _certDBEntryCert { - certDBEntryCommon common; - CERTCertTrust trust; - SECItem derCert; - char *nickname; -}; - -/* - * Certificate Nickname entry: - * - * byte offset field - * ----------- ----- - * 0 subjectname-len-msb - * 1 subjectname-len-lsb - * 2... subjectname - * - * The database key for this type of entry is a nickname string - * The "subjectname" value is the DER encoded DN of the identity - * that matches this nickname. - */ -typedef struct { - certDBEntryCommon common; - char *nickname; - SECItem subjectName; -} certDBEntryNickname; - -#define DB_NICKNAME_ENTRY_HEADER_LEN 2 - -/* - * Certificate Subject entry: - * - * byte offset field - * ----------- ----- - * 0 ncerts-msb - * 1 ncerts-lsb - * 2 nickname-msb - * 3 nickname-lsb - * 4 emailAddr-msb - * 5 emailAddr-lsb - * ... nickname - * ... emailAddr - * ...+2*i certkey-len-msb - * ...+1+2*i certkey-len-lsb - * ...+2*ncerts+2*i keyid-len-msb - * ...+1+2*ncerts+2*i keyid-len-lsb - * ... certkeys - * ... keyids - * - * The database key for this type of entry is the DER encoded subject name - * The "certkey" value is an array of certificate database lookup keys that - * points to the database entries for the certificates that matche - * this subject. - * - */ -typedef struct _certDBEntrySubject { - certDBEntryCommon common; - SECItem derSubject; - unsigned int ncerts; - char *nickname; - char *emailAddr; - SECItem *certKeys; - SECItem *keyIDs; -} certDBEntrySubject; - -#define DB_SUBJECT_ENTRY_HEADER_LEN 6 - -/* - * Certificate SMIME profile entry: - * - * byte offset field - * ----------- ----- - * 0 subjectname-len-msb - * 1 subjectname-len-lsb - * 2 smimeoptions-len-msb - * 3 smimeoptions-len-lsb - * 4 options-date-len-msb - * 5 options-date-len-lsb - * 6... subjectname - * ... smimeoptions - * ... options-date - * - * The database key for this type of entry is the email address string - * The "subjectname" value is the DER encoded DN of the identity - * that matches this nickname. - * The "smimeoptions" value is a string that represents the algorithm - * capabilities on the remote user. - * The "options-date" is the date that the smime options value was created. - * This is generally the signing time of the signed message that contained - * the options. It is a UTCTime value. - */ -typedef struct { - certDBEntryCommon common; - char *emailAddr; - SECItem subjectName; - SECItem smimeOptions; - SECItem optionsDate; -} certDBEntrySMime; - -#define DB_SMIME_ENTRY_HEADER_LEN 6 - -/* - * Crl/krl entry: - * - * byte offset field - * ----------- ----- - * 0 derCert-len-msb - * 1 derCert-len-lsb - * 2 url-len-msb - * 3 url-len-lsb - * ... derCert - * ... url - * - * NOTE: the url string as stored in the database is null terminated, - * in other words, the last byte of the db entry is always 0 - * if a nickname is present. - * NOTE: if url is not present, then url-len-msb and - * url-len-lsb will both be zero. - */ -#define DB_CRL_ENTRY_HEADER_LEN 4 -struct _certDBEntryRevocation { - certDBEntryCommon common; - SECItem derCrl; - char *url; /* where to load the crl from */ -}; - -/* - * Database Version Entry: - * - * byte offset field - * ----------- ----- - * only the low level header... - * - * The database key for this type of entry is the string "Version" - */ -typedef struct { - certDBEntryCommon common; -} certDBEntryVersion; - -#define SEC_DB_VERSION_KEY "Version" -#define SEC_DB_VERSION_KEY_LEN sizeof(SEC_DB_VERSION_KEY) - -/* - * Database Content Version Entry: - * - * byte offset field - * ----------- ----- - * 0 contentVersion - * - * The database key for this type of entry is the string "ContentVersion" - */ -typedef struct { - certDBEntryCommon common; - char contentVersion; -} certDBEntryContentVersion; - -#define SEC_DB_CONTENT_VERSION_KEY "ContentVersion" -#define SEC_DB_CONTENT_VERSION_KEY_LEN sizeof(SEC_DB_CONTENT_VERSION_KEY) - -typedef union { - certDBEntryCommon common; - certDBEntryVersion version; - certDBEntryCert cert; - certDBEntryNickname nickname; - certDBEntrySubject subject; - certDBEntryRevocation revocation; -} certDBEntry; - -/* length of the fixed part of a database entry */ -#define DBCERT_V4_HEADER_LEN 7 -#define DB_CERT_V5_ENTRY_HEADER_LEN 7 -#define DB_CERT_V6_ENTRY_HEADER_LEN 7 -#define DB_CERT_ENTRY_HEADER_LEN 10 /* common flags for all types of certificates */ #define CERTDB_VALID_PEER (1<<0) @@ -288,31 +47,58 @@ typedef union { #define CERTDB_INVISIBLE_CA (1<<8) /* don't show in UI */ #define CERTDB_GOVT_APPROVED_CA (1<<9) /* can do strong crypto in export ver */ + SEC_BEGIN_PROTOS +CERTSignedCrl * +SEC_FindCrlByKey(CERTCertDBHandle *handle, SECItem *crlKey, int type); + +CERTSignedCrl * +SEC_FindCrlByName(CERTCertDBHandle *handle, SECItem *crlKey, int type); + +CERTSignedCrl * +SEC_FindCrlByDERCert(CERTCertDBHandle *handle, SECItem *derCrl, int type); + +PRBool +SEC_CertNicknameConflict(char *nickname, SECItem *derSubject, + CERTCertDBHandle *handle); +CERTSignedCrl * +SEC_NewCrl(CERTCertDBHandle *handle, char *url, SECItem *derCrl, int type); + +SECStatus +SEC_DeletePermCRL(CERTSignedCrl *crl); + + +SECStatus +SEC_LookupCrls(CERTCertDBHandle *handle, CERTCrlHeadNode **nodes, int type); + +SECStatus +SEC_DestroyCrl(CERTSignedCrl *crl); + +#ifdef notdef /* ** Add a DER encoded certificate to the permanent database. ** "derCert" is the DER encoded certificate. ** "nickname" is the nickname to use for the cert ** "trust" is the trust parameters for the cert */ -SECStatus SEC_AddPermCertificate(CERTCertDBHandle *handle, SECItem *derCert, - char *nickname, CERTCertTrust *trust); +SECStatus SEC_AddPermCertificate(PCERTCertDBHandle *handle, SECItem *derCert, + char *nickname, PCERTCertTrust *trust); certDBEntryCert * -SEC_FindPermCertByKey(CERTCertDBHandle *handle, SECItem *certKey); +SEC_FindPermCertByKey(PCERTCertDBHandle *handle, SECItem *certKey); certDBEntryCert -*SEC_FindPermCertByName(CERTCertDBHandle *handle, SECItem *name); +*SEC_FindPermCertByName(PCERTCertDBHandle *handle, SECItem *name); -SECStatus SEC_OpenPermCertDB(CERTCertDBHandle *handle, +SECStatus SEC_OpenPermCertDB(PCERTCertDBHandle *handle, PRBool readOnly, - CERTDBNameFunc namecb, + PCERTDBNameFunc namecb, void *cbarg); -SECStatus SEC_DeletePermCertificate(CERTCertificate *cert); +SECStatus SEC_DeletePermCertificate(PCERTCertificate *cert); -typedef SECStatus (PR_CALLBACK * PermCertCallback)(CERTCertificate *cert, +typedef SECStatus (PR_CALLBACK * PermCertCallback)(PCERTCertificate *cert, SECItem *k, void *pdata); /* ** Traverse the entire permanent database, and pass the certs off to a @@ -321,75 +107,47 @@ typedef SECStatus (PR_CALLBACK * PermCertCallback)(CERTCertificate *cert, ** "udata" is the user's data, which is passed through to "certfunc" */ SECStatus -SEC_TraversePermCerts(CERTCertDBHandle *handle, +PCERT_TraversePermCerts(PCERTCertDBHandle *handle, PermCertCallback certfunc, void *udata ); SECStatus -SEC_AddTempNickname(CERTCertDBHandle *handle, char *nickname, SECItem *certKey); +SEC_AddTempNickname(PCERTCertDBHandle *handle, char *nickname, SECItem *certKey); SECStatus -SEC_DeleteTempNickname(CERTCertDBHandle *handle, char *nickname); +SEC_DeleteTempNickname(PCERTCertDBHandle *handle, char *nickname); -PRBool -SEC_CertNicknameConflict(char *nickname, SECItem *derSubject, - CERTCertDBHandle *handle); PRBool -SEC_CertDBKeyConflict(SECItem *derCert, CERTCertDBHandle *handle); +SEC_CertDBKeyConflict(SECItem *derCert, PCERTCertDBHandle *handle); SECStatus -SEC_GetCrlTimes(CERTCrl *dates, PRTime *notBefore, PRTime *notAfter); +SEC_GetCrlTimes(PCERTCrl *dates, PRTime *notBefore, PRTime *notAfter); SECCertTimeValidity -SEC_CheckCrlTimes(CERTCrl *crl, PRTime t); +SEC_CheckCrlTimes(PCERTCrl *crl, PRTime t); PRBool -SEC_CrlIsNewer(CERTCrl *inNew, CERTCrl *old); +SEC_CrlIsNewer(PCERTCrl *inNew, PCERTCrl *old); -CERTSignedCrl * -SEC_AddPermCrlToTemp(CERTCertDBHandle *handle, certDBEntryRevocation *entry); +PCERTSignedCrl * +SEC_AddPermCrlToTemp(PCERTCertDBHandle *handle, certDBEntryRevocation *entry); SECStatus -SEC_DeleteTempCrl(CERTSignedCrl *crl); +SEC_DeleteTempCrl(PCERTSignedCrl *crl); -CERTSignedCrl * -SEC_FindCrlByKey(CERTCertDBHandle *handle, SECItem *crlKey, int type); - -CERTSignedCrl * -SEC_FindCrlByName(CERTCertDBHandle *handle, SECItem *crlKey, int type); - -CERTSignedCrl * -SEC_FindCrlByDERCert(CERTCertDBHandle *handle, SECItem *derCrl, int type); - -SECStatus -SEC_DestroyCrl(CERTSignedCrl *crl); - -CERTSignedCrl * -SEC_NewCrl(CERTCertDBHandle *handle, char *url, SECItem *derCrl, int type); - -CERTSignedCrl * -cert_DBInsertCRL - (CERTCertDBHandle *handle, char *url, - CERTSignedCrl *newCrl, SECItem *derCrl, int type); - -SECStatus -SEC_CheckKRL(CERTCertDBHandle *handle,SECKEYPublicKey *key, - CERTCertificate *rootCert, int64 t, void *wincx); - -SECStatus -SEC_CheckCRL(CERTCertDBHandle *handle,CERTCertificate *cert, - CERTCertificate *caCert, int64 t, void *wincx); SECStatus -SEC_DeletePermCRL(CERTSignedCrl *crl); - +SEC_CheckKRL(PCERTCertDBHandle *handle,SECKEYLowPublicKey *key, + PCERTCertificate *rootCert, int64 t, void *wincx); SECStatus -SEC_LookupCrls(CERTCertDBHandle *handle, CERTCrlHeadNode **nodes, int type); +SEC_CheckCRL(PCERTCertDBHandle *handle,PCERTCertificate *cert, + PCERTCertificate *caCert, int64 t, void *wincx); SECStatus -SEC_CrlReplaceUrl(CERTSignedCrl *crl,char *url); +SEC_CrlReplaceUrl(PCERTSignedCrl *crl,char *url); +#endif SEC_END_PROTOS diff --git a/security/nss/lib/certdb/certinit.c b/security/nss/lib/certdb/certinit.c deleted file mode 100644 index d19b16cbf..000000000 --- a/security/nss/lib/certdb/certinit.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * 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. - */ - -#include "cert.h" -#include "base64.h" -#include "mcom_db.h" -#include "certdb.h" - -#ifdef STATIC_CERT_INIT -static char example_com_server_ca[] = -"MIICBTCCAW6gAwIBAgIBATANBgkqhkiG9w0BAQQFADA+MREwDwYICZIm9ZgeZAET" -"A2NvbTEVMBMGCAmSJvWYHmQBEwdFeGFtcGxlMRIwEAYDVQQDEwlTZXJ2ZXIgQ0Ew" -"HhcNMDAwMjAzMjIyMDA3WhcNMTAwNTAzMjIyMDA3WjA+MREwDwYICZIm9ZgeZAET" -"A2NvbTEVMBMGCAmSJvWYHmQBEwdFeGFtcGxlMRIwEAYDVQQDEwlTZXJ2ZXIgQ0Ew" -"gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALGiKEvTd2k4ZJbdAVWokfFlB6Hz" -"WJXveXm8+IgmFlgtAnicZI11z5wAutFRvDpun7WmRLgHxvEhU3tLoiACGYdGJXPw" -"+lI2pzHzFSd63B0qcA/NVAW3EOBJeaEFwy0jkUaCIki8qQV06g8RosNX/zv6a+OF" -"d5NMpS0fecK4fEvdAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN" -"AQEEBQADgYEAi5rFiG6afWS1PHigssk2LwAJws5cszPbVIeIMHCBbtu259V7uWts" -"gNxUPJRjeQBsK0ItAfinC0xxLeuMbRfIdZoRYv/OYDxCwGW7hUcNLi+fHlGnJNXH" -"TWaCRdOwkljnws4v8ABas2DYA/k7xUFAygkIJd9NtE29ZrdrWpfSavI="; - -static char example_com_individual_ca[] = -"MIICDTCCAXagAwIBAgIBAjANBgkqhkiG9w0BAQQFADBCMREwDwYICZIm9ZgeZAET" -"A2NvbTEVMBMGCAmSJvWYHmQBEwdFeGFtcGxlMRYwFAYDVQQDEw1JbmRpdmlkdWFs" -"IENBMB4XDTAwMDIwMzIyMjE1NFoXDTEwMDUwMzIyMjE1NFowQjERMA8GCAmSJvWY" -"HmQBEwNjb20xFTATBggJkib1mB5kARMHRXhhbXBsZTEWMBQGA1UEAxMNSW5kaXZp" -"ZHVhbCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu5syfboe93MOkGec" -"dOuJholyX42wcaH/RgnL3C/8NnZp9WWaTaguvn7KrbCj4TAMzu0pabUN8apB3J60" -"9C/FlixjXF7r73OzbyTCM5ja6/bPfmHMPmDl9l/9tKqhh+loFvRizXDaWSFRViDS" -"XvKNeQztwwAOpEAqnJwyTkn4FjECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN" -"BgkqhkiG9w0BAQQFAAOBgQB1XK+5pXdXYq3O3TC/ZY5LWlZ7zuoWUO75OpuMY7XF" -"iW/jeXbVT5IYZXoRGXJFGGaDmnAuK1/m6FTDhjSTG0XUmd5tg4aFieI+LY4rkYEv" -"mbJElxKabXl5hVD4mg2bwYlFY7XBmifTa1Ll3HDX3VZM0DC1bm4KCHBnY0qXjSYq" -"PA=="; - -static char example_com_objsign_ca[] = -"MIICETCCAXqgAwIBAgIBAzANBgkqhkiG9w0BAQQFADBEMREwDwYICZIm9ZgeZAET" -"A2NvbTEVMBMGCAmSJvWYHmQBEwdFeGFtcGxlMRgwFgYDVQQDEw9Db2RlIFNpZ25p" -"bmcgQ0EwHhcNMDAwMjAzMjIyMzEzWhcNMTAwNTAzMjIyMzEzWjBEMREwDwYICZIm" -"9ZgeZAETA2NvbTEVMBMGCAmSJvWYHmQBEwdFeGFtcGxlMRgwFgYDVQQDEw9Db2Rl" -"IFNpZ25pbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALcy76InmpM9" -"S9K2MlNSjusx6nkYWWbx7eDRTV+xhRPeDxW4t8jtKPqDF5LTusyM9WCI/nneqsIP" -"7iTSHpxlGx37J1VbqKX5fZsfJ3wKv6ZIylzeRuFY9MFypPA2UmVd1ACDOUB3YDvY" -"mrCVkOPEhjnZKbq4FfCpf8KNL2A5EBcZAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB" -"Af8wDQYJKoZIhvcNAQEEBQADgYEAI0IXzwgBRXvow3JQi8Y4YdG2wZc4BWRGW87x" -"2zOD7GOA0CWN149vb6rEchECykDsJj9LoBl6o1aRxk9WkIFnXmMOJSuJA+ilCe//" -"81a5OhKbe0p7ym6rh190BLwh2VePFeyabq6NipfZlN6qgWUzoepf+jVblufW/2EI" -"fbMSylc="; -#endif - -/* This is the cert->certKey (serial number and issuer name) of - * the cert that we want to revoke. - */ -static unsigned char revoked_system_principal_key[] = { -0x40, 0x18, 0xf2, 0x35, 0x86, 0x06, 0x78, 0xce, 0x87, 0x89, -0x0c, 0x5d, 0x68, 0x67, 0x33, 0x09, 0x30, 0x81, 0xc1, 0x31, -0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x16, -0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, -0x72, 0x75, 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, -0x72, 0x6b, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, -0x0b, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, -0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x3a, 0x30, -0x38, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x31, 0x56, 0x65, -0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x4f, 0x62, 0x6a, -0x65, 0x63, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, -0x67, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x43, 0x6c, 0x61, -0x73, 0x73, 0x20, 0x33, 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e, -0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x49, 0x30, -0x47, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x40, 0x77, 0x77, -0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, -0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x20, 0x49, -0x6e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x62, 0x79, 0x20, 0x52, -0x65, 0x66, 0x2e, 0x20, 0x4c, 0x49, 0x41, 0x42, 0x49, 0x4c, -0x49, 0x54, 0x59, 0x20, 0x4c, 0x54, 0x44, 0x2e, 0x28, 0x63, -0x29, 0x39, 0x37, 0x20, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, -0x67, 0x6e -}; - -SECStatus -CERT_CheckForEvilCert(CERTCertificate *cert) -{ - if ( cert->certKey.len == sizeof(revoked_system_principal_key) ) { - if ( PORT_Memcmp(cert->certKey.data, - revoked_system_principal_key, - sizeof(revoked_system_principal_key)) == 0 ) { - return(SECFailure); - } - } - - return(SECSuccess); -} - -#ifdef STATIC_CERT_INIT - -#define DEFAULT_TRUST_FLAGS (CERTDB_VALID_CA | \ - CERTDB_TRUSTED_CA | \ - CERTDB_NS_TRUSTED_CA) - -typedef enum { - certUpdateNone, - certUpdateAdd, - certUpdateDelete, - certUpdateAddTrust, - certUpdateRemoveTrust, - certUpdateSetTrust -} certUpdateOp; - -typedef struct { - char *cert; - char *nickname; - CERTCertTrust trust; - int updateVersion; - certUpdateOp op; - CERTCertTrust trustDelta; -} certInitEntry; - -static certInitEntry initialcerts[] = { - { - example_com_server_ca, - "Example.com Server CA", - { DEFAULT_TRUST_FLAGS | CERTDB_GOVT_APPROVED_CA, 0, 0 }, - 1, - certUpdateAdd, - { 0, 0, 0 } - }, - { - example_com_server_ca, - "Example.com Server CA", - { DEFAULT_TRUST_FLAGS | CERTDB_GOVT_APPROVED_CA, 0, 0 }, - 2, - certUpdateAddTrust, - { CERTDB_GOVT_APPROVED_CA, 0, 0 } - }, - - { - example_com_individual_ca, - "Example.com Individual CA", - { 0, DEFAULT_TRUST_FLAGS, 0 }, - 1, - certUpdateAdd, - { 0, 0, 0 } - }, - { - example_com_individual_ca, - "Example.com Individual CA", - { 0, DEFAULT_TRUST_FLAGS, 0 }, - 2, - certUpdateRemoveTrust, - { 0, 0, DEFAULT_TRUST_FLAGS } - }, - - { - example_com_objsign_ca, - "Example.com Code Signing CA", - { 0, 0, DEFAULT_TRUST_FLAGS }, - 2, - certUpdateAdd, - { 0, 0, 0 } - }, - - { - 0, 0 - } -}; - - -static SECStatus -ConvertAndCheckCertificate(CERTCertDBHandle *handle, char *asciicert, - char *nickname, CERTCertTrust *trust) -{ - SECItem sdder; - SECStatus rv; - CERTCertificate *cert; - PRBool conflict; - SECItem derSubject; - - /* First convert ascii to binary */ - rv = ATOB_ConvertAsciiToItem (&sdder, asciicert); - if (rv != SECSuccess) { - return(rv); - } - - /* - ** Inside the ascii is a Signed Certificate. - */ - - cert = NULL; - - /* make sure that no conflicts exist */ - conflict = SEC_CertDBKeyConflict(&sdder, handle); - if ( conflict ) { - goto done; - } - - rv = CERT_NameFromDERCert(&sdder, &derSubject); - if ( rv != SECSuccess ) { - goto loser; - } - - conflict = SEC_CertNicknameConflict(nickname, &derSubject, handle); - if ( conflict ) { - goto done; - } - - cert = CERT_NewTempCertificate(handle, &sdder, NULL, PR_FALSE, PR_TRUE); - if ( cert == NULL ) { - goto loser; - } - - rv = CERT_AddTempCertToPerm(cert, nickname, trust); - - CERT_DestroyCertificate(cert); - - if (rv == SECSuccess) { - /* - ** XXX should verify signatures too, if we have the certificate for - ** XXX its issuer... - */ - } - -done: - PORT_Free(sdder.data); - return(rv); - -loser: - return(SECFailure); -} - -#endif - -extern void certdb_InitDBLock(void); - -SECStatus -CERT_InitCertDB(CERTCertDBHandle *handle) -{ -#ifdef STATIC_CERT_INIT - SECStatus rv; - certInitEntry *entry; - certdb_InitDBLock(); - - entry = initialcerts; - - while ( entry->cert != NULL) { - if ( entry->op != certUpdateDelete ) { - rv = ConvertAndCheckCertificate(handle, entry->cert, - entry->nickname, &entry->trust); - /* keep going */ - } - - entry++; - } -done: - CERT_SetDBContentVersion(CERT_DB_CONTENT_VERSION, handle); - return(rv); -#else -#ifdef DO_ANYTHING_HERE_FOR_3_4 - certdb_InitDBLock(); - CERT_SetDBContentVersion(0, handle); -#endif - return(SECSuccess); -#endif -} - -#ifdef STATIC_CERT_INIT -static CERTCertificate * -CertFromEntry(CERTCertDBHandle *handle, char *asciicert) -{ - SECItem sdder; - SECStatus rv; - CERTCertificate *cert; - - /* First convert ascii to binary */ - rv = ATOB_ConvertAsciiToItem (&sdder, asciicert); - if (rv != SECSuccess) { - return(NULL); - } - - /* - ** Inside the ascii is a Signed Certificate. - */ - - cert = CERT_NewTempCertificate(handle, &sdder, NULL, PR_FALSE, PR_TRUE); - - return(cert); -} -#endif - -SECStatus -CERT_AddNewCerts(CERTCertDBHandle *handle) -{ -#ifdef STATIC_CERT_INIT - int oldversion; - int newversion; - certInitEntry *entry; - CERTCertTrust tmptrust; - SECStatus rv; - CERTCertificate *cert; - - newversion = CERT_DB_CONTENT_VERSION; - - oldversion = CERT_GetDBContentVersion(handle); - - if ( newversion > oldversion ) { - entry = initialcerts; - - while ( entry->cert != NULL ) { - if ( entry->updateVersion > oldversion ) { - switch ( entry->op ) { - default: - break; - case certUpdateAdd: - rv = ConvertAndCheckCertificate(handle, entry->cert, - entry->nickname, - &entry->trust); - break; - case certUpdateDelete: - cert = CertFromEntry(handle, entry->cert); - if ( cert != NULL ) { - if ( cert->isperm ) { - rv = SEC_DeletePermCertificate(cert); - } - CERT_DestroyCertificate(cert); - } - break; - case certUpdateAddTrust: - cert = CertFromEntry(handle, entry->cert); - if ( cert != NULL ) { - if ( cert->isperm ) { - tmptrust = *cert->trust; - tmptrust.sslFlags |= entry->trustDelta.sslFlags; - tmptrust.emailFlags |= - entry->trustDelta.emailFlags; - tmptrust.objectSigningFlags |= - entry->trustDelta.objectSigningFlags; - rv = CERT_ChangeCertTrust(handle, cert, -&tmptrust); - } - CERT_DestroyCertificate(cert); - } - break; - case certUpdateRemoveTrust: - cert = CertFromEntry(handle, entry->cert); - if ( cert != NULL ) { - if ( cert->isperm ) { - tmptrust = *cert->trust; - tmptrust.sslFlags &= - (~entry->trustDelta.sslFlags); - tmptrust.emailFlags &= - (~entry->trustDelta.emailFlags); - tmptrust.objectSigningFlags &= - (~entry->trustDelta.objectSigningFlags); - rv = CERT_ChangeCertTrust(handle, cert, -&tmptrust); - } - CERT_DestroyCertificate(cert); - } - break; - case certUpdateSetTrust: - cert = CertFromEntry(handle, entry->cert); - if ( cert != NULL ) { - if ( cert->isperm ) { - tmptrust = *cert->trust; - tmptrust.sslFlags = entry->trustDelta.sslFlags; - tmptrust.emailFlags = - entry->trustDelta.emailFlags; - tmptrust.objectSigningFlags = - entry->trustDelta.objectSigningFlags; - rv = CERT_ChangeCertTrust(handle, cert, -&tmptrust); - } - CERT_DestroyCertificate(cert); - } - break; - } - } - - entry++; - } - - CERT_SetDBContentVersion(newversion, handle); - } - -#endif - return(SECSuccess); -} diff --git a/security/nss/lib/certdb/certt.h b/security/nss/lib/certdb/certt.h index f186fd21f..5b208acd6 100644 --- a/security/nss/lib/certdb/certt.h +++ b/security/nss/lib/certdb/certt.h @@ -169,9 +169,6 @@ struct CERTPublicKeyAndChallengeStr { SECItem challenge; }; -typedef struct _certDBEntryCert certDBEntryCert; -typedef struct _certDBEntryRevocation certDBEntryRevocation; - struct CERTCertTrustStr { unsigned int sslFlags; unsigned int emailFlags; @@ -215,7 +212,7 @@ struct CERTSubjectListStr { char *emailAddr; CERTSubjectNode *head; CERTSubjectNode *tail; /* do we need tail? */ - struct _certDBEntrySubject *entry; + void *entry; }; /* @@ -275,7 +272,7 @@ struct CERTCertificateStr { PRBool istemp; char *nickname; char *dbnickname; - certDBEntryCert *dbEntry; /* database entry struct */ + void *dbEntry; /* database entry struct */ CERTCertTrust *trust; /* the reference count is modified whenever someone looks up, dups @@ -404,8 +401,10 @@ struct CERTCrlKeyStr { struct CERTSignedCrlStr { PRArenaPool *arena; CERTCrl crl; - certDBEntryRevocation *dbEntry; /* database entry struct */ - PRBool keep; /* keep this crl in the cache for the session*/ + /*certDBEntryRevocation *dbEntry; database entry struct */ + PK11SlotInfo *slot; + /* PRBool keep; keep this crl in the cache for the session*/ + CK_OBJECT_HANDLE pkcs11ID; PRBool isperm; PRBool istemp; int referenceCount; diff --git a/security/nss/lib/certdb/crl.c b/security/nss/lib/certdb/crl.c index 30a17a8fb..d6c232ec7 100644 --- a/security/nss/lib/certdb/crl.c +++ b/security/nss/lib/certdb/crl.c @@ -45,6 +45,7 @@ #include "certxutl.h" #include "prtime.h" #include "secerr.h" +#include "pk11func.h" const SEC_ASN1Template SEC_CERTExtensionTemplate[] = { { SEC_ASN1_SEQUENCE, @@ -389,6 +390,223 @@ loser: return(0); } +/* + * Lookup a CRL in the databases. We mirror the same fast caching data base + * caching stuff used by certificates....? + */ +CERTSignedCrl * +SEC_FindCrlByKeyOnSlot(PK11SlotInfo *slot, SECItem *crlKey, int type) +{ + CERTSignedCrl *crl = NULL; + SECItem *derCrl; + CK_OBJECT_HANDLE crlHandle; + + if (slot) { + PK11_ReferenceSlot(slot); + } + + derCrl = PK11_FindCrlByName(&slot, &crlHandle, crlKey,type); + if (derCrl == NULL) { + goto loser; + } + + crl = CERT_DecodeDERCrl(NULL, derCrl, type); + if (crl) { + crl->slot = slot; + slot = NULL; /* adopt it */ + } + +loser: + if (slot) { + PK11_FreeSlot(slot); + } + return(crl); +} + +SECStatus SEC_DestroyCrl(CERTSignedCrl *crl); + +CERTSignedCrl * +crl_storeCRL (PK11SlotInfo *slot,char *url, + CERTSignedCrl *newCrl, SECItem *derCrl, int type) +{ + CERTSignedCrl *oldCrl = NULL, *crl = NULL; + CK_OBJECT_HANDLE crlHandle; + + oldCrl = SEC_FindCrlByKeyOnSlot(slot, &newCrl->crl.derName, type); + + /* if there is an old crl, make sure the one we are installing + * is newer. If not, exit out, otherwise delete the old crl. + */ + if (oldCrl != NULL) { + if (!SEC_CrlIsNewer(&newCrl->crl,&oldCrl->crl)) { + + if (type == SEC_CRL_TYPE) { + PORT_SetError(SEC_ERROR_OLD_CRL); + } else { + PORT_SetError(SEC_ERROR_OLD_KRL); + } + + goto done; + } + + if ((SECITEM_CompareItem(&newCrl->crl.derName, + &oldCrl->crl.derName) != SECEqual) && + (type == SEC_KRL_TYPE) ) { + + PORT_SetError(SEC_ERROR_CKL_CONFLICT); + goto done; + } + + /* if we have a url in the database, use that one */ + if (oldCrl->url) { + url = oldCrl->url; + } + + + /* really destroy this crl */ + /* first drum it out of the permanment Data base */ + SEC_DeletePermCRL(oldCrl); + } + + /* Write the new entry into the data base */ + crlHandle = PK11_PutCrl(slot, derCrl, &newCrl->crl.derName, url, type); + if (crlHandle != CK_INVALID_HANDLE) { + crl = newCrl; + crl->slot = PK11_ReferenceSlot(slot); + crl->pkcs11ID = crlHandle; + } + +done: + if (oldCrl) SEC_DestroyCrl(oldCrl); + + return crl; +} + +CERTSignedCrl * +SEC_FindCrlByName(CERTCertDBHandle *handle, SECItem *crlKey, int type) +{ + return SEC_FindCrlByKeyOnSlot(NULL,crlKey,type); +} + +/* + * + * create a new CRL from DER material. + * + * The signature on this CRL must be checked before you + * load it. ??? + */ +CERTSignedCrl * +SEC_NewCrl(CERTCertDBHandle *handle, char *url, SECItem *derCrl, int type) +{ + CERTSignedCrl *newCrl = NULL, *crl = NULL; + PK11SlotInfo *slot; + + /* make this decode dates! */ + newCrl = CERT_DecodeDERCrl(NULL, derCrl, type); + if (newCrl == NULL) { + if (type == SEC_CRL_TYPE) { + PORT_SetError(SEC_ERROR_CRL_INVALID); + } else { + PORT_SetError(SEC_ERROR_KRL_INVALID); + } + goto done; + } + + slot = PK11_GetInternalKeySlot(); + crl = crl_storeCRL(slot, url, newCrl, derCrl, type); + PK11_FreeSlot(slot); + + +done: + if (crl == NULL) { + if (newCrl) { + PORT_FreeArena(newCrl->arena, PR_FALSE); + } + } + + return crl; +} + + +CERTSignedCrl * +SEC_FindCrlByDERCert(CERTCertDBHandle *handle, SECItem *derCrl, int type) +{ + PRArenaPool *arena; + SECItem crlKey; + SECStatus rv; + CERTSignedCrl *crl = NULL; + + /* create a scratch arena */ + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + return(NULL); + } + + /* extract the database key from the cert */ + rv = CERT_KeyFromDERCrl(arena, derCrl, &crlKey); + if ( rv != SECSuccess ) { + goto loser; + } + + /* find the crl */ + crl = SEC_FindCrlByName(handle, &crlKey, type); + +loser: + PORT_FreeArena(arena, PR_FALSE); + return(crl); +} + + +SECStatus +SEC_DestroyCrl(CERTSignedCrl *crl) +{ + if (crl) { + if (crl->referenceCount-- <= 1) { + if (crl->slot) { + PK11_FreeSlot(crl->slot); + } + PORT_FreeArena(crl->arena, PR_FALSE); + } + } + return SECSuccess; +} + +SECStatus +SEC_LookupCrls(CERTCertDBHandle *handle, CERTCrlHeadNode **nodes, int type) +{ + CERTCrlHeadNode *head; + PRArenaPool *arena = NULL; + SECStatus rv; + + *nodes = NULL; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + return SECFailure; + } + + /* build a head structure */ + head = (CERTCrlHeadNode *)PORT_ArenaAlloc(arena, sizeof(CERTCrlHeadNode)); + head->arena = arena; + head->first = NULL; + head->last = NULL; + head->dbhandle = handle; + + /* Look up the proper crl types */ + *nodes = head; + + rv = PK11_LookupCrls(nodes, type, NULL); + + if (rv != SECSuccess) { + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + *nodes = NULL; + } + } + + return rv; +} + /* These functions simply return the address of the above-declared templates. ** This is necessary for Windows DLLs. Sigh. */ diff --git a/security/nss/lib/certdb/manifest.mn b/security/nss/lib/certdb/manifest.mn index 37b08b85a..a9b5f3d8c 100644 --- a/security/nss/lib/certdb/manifest.mn +++ b/security/nss/lib/certdb/manifest.mn @@ -42,28 +42,20 @@ PRIVATE_EXPORTS = \ genname.h \ xconst.h \ certxutl.h \ - cdbhdl.h \ $(NULL) MODULE = security -CERTINIT=certinit.c -ifdef NSS_STAN_MODULE -PCERTDB=stanpcertdb.c DEFINES=-DSTAN_CERT_DB -else -PCERTDB=pcertdb.c -endif CSRCS = \ alg1485.c \ certdb.c \ certv3.c \ - $(CERTINIT) \ certxutl.c \ crl.c \ genname.c \ - $(PCERTDB) \ + stanpcertdb.c \ polcyxtn.c \ secname.c \ xauthkid.c \ diff --git a/security/nss/lib/certdb/pcertdb.c b/security/nss/lib/certdb/pcertdb.c deleted file mode 100644 index 48ea44c5a..000000000 --- a/security/nss/lib/certdb/pcertdb.c +++ /dev/null @@ -1,7490 +0,0 @@ -/* - * 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. - */ - -/* - * Permanent Certificate database handling code - * - * $Id$ - */ -#include "prtime.h" - -#include "cert.h" -#include "mcom_db.h" -#include "certdb.h" -#include "secitem.h" -#include "secder.h" - -/* Call to PK11_FreeSlot below */ - -#include "secasn1.h" -#include "secerr.h" -#include "nssilock.h" -#include "prmon.h" -#include "nsslocks.h" -#include "base64.h" -#include "sechash.h" -#include "plhash.h" -#include "pk11func.h" /* sigh */ - -#include "cdbhdl.h" - -/* forward declaration */ -CERTCertificate * -CERT_FindCertByDERCertNoLocking(CERTCertDBHandle *handle, SECItem *derCert); - -/* - * the following functions are wrappers for the db library that implement - * a global lock to make the database thread safe. - */ -static PZLock *dbLock = NULL; - -void -certdb_InitDBLock(void) -{ - if (dbLock == NULL) { - nss_InitLock(&dbLock, nssILockCertDB); - PORT_Assert(dbLock != NULL); - } - - return; -} - -static int -certdb_Get(DB *db, DBT *key, DBT *data, unsigned int flags) -{ - PRStatus prstat; - int ret; - - PORT_Assert(dbLock != NULL); - PZ_Lock(dbLock); - - ret = (* db->get)(db, key, data, flags); - - prstat = PZ_Unlock(dbLock); - - return(ret); -} - -static int -certdb_Put(DB *db, DBT *key, DBT *data, unsigned int flags) -{ - PRStatus prstat; - int ret; - - PORT_Assert(dbLock != NULL); - PZ_Lock(dbLock); - - ret = (* db->put)(db, key, data, flags); - - prstat = PZ_Unlock(dbLock); - - return(ret); -} - -static int -certdb_Sync(DB *db, unsigned int flags) -{ - PRStatus prstat; - int ret; - - PORT_Assert(dbLock != NULL); - PZ_Lock(dbLock); - - ret = (* db->sync)(db, flags); - - prstat = PZ_Unlock(dbLock); - - return(ret); -} - -static int -certdb_Del(DB *db, DBT *key, unsigned int flags) -{ - PRStatus prstat; - int ret; - - PORT_Assert(dbLock != NULL); - PZ_Lock(dbLock); - - ret = (* db->del)(db, key, flags); - - prstat = PZ_Unlock(dbLock); - - return(ret); -} - -static int -certdb_Seq(DB *db, DBT *key, DBT *data, unsigned int flags) -{ - PRStatus prstat; - int ret; - - PORT_Assert(dbLock != NULL); - PZ_Lock(dbLock); - - ret = (* db->seq)(db, key, data, flags); - - prstat = PZ_Unlock(dbLock); - - return(ret); -} - -static void -certdb_Close(DB *db) -{ - PRStatus prstat; - - PORT_Assert(dbLock != NULL); - PZ_Lock(dbLock); - - (* db->close)(db); - - prstat = PZ_Unlock(dbLock); - - return; -} - -/* forward references */ -static void CERT_DestroyCertificateNoLocking(CERTCertificate *cert); -static SECStatus AddCertToSPKDigestTable(CERTCertDBHandle *handle, - CERTCertificate *cert); -static SECStatus RemoveCertFromSPKDigestTable(CERTCertDBHandle *handle, - CERTCertificate *cert); - -static SECStatus -DeleteDBEntry(CERTCertDBHandle *handle, certDBEntryType type, SECItem *dbkey) -{ - DBT key; - int ret; - - /* init the database key */ - key.data = dbkey->data; - key.size = dbkey->len; - - dbkey->data[0] = (unsigned char)type; - - /* delete entry from database */ - ret = certdb_Del(handle->permCertDB, &key, 0 ); - if ( ret != 0 ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - ret = certdb_Sync(handle->permCertDB, 0); - if ( ret ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - return(SECSuccess); - -loser: - return(SECFailure); -} - -static SECStatus -ReadDBEntry(CERTCertDBHandle *handle, certDBEntryCommon *entry, - SECItem *dbkey, SECItem *dbentry, PRArenaPool *arena) -{ - DBT data, key; - int ret; - unsigned char *buf; - - /* init the database key */ - key.data = dbkey->data; - key.size = dbkey->len; - - dbkey->data[0] = (unsigned char)entry->type; - - /* read entry from database */ - ret = certdb_Get(handle->permCertDB, &key, &data, 0 ); - if ( ret != 0 ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - /* validate the entry */ - if ( data.size < SEC_DB_ENTRY_HEADER_LEN ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - buf = (unsigned char *)data.data; - if ( buf[0] != (unsigned char)CERT_DB_FILE_VERSION ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - if ( buf[1] != (unsigned char)entry->type ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - /* copy out header information */ - entry->version = (unsigned int)buf[0]; - entry->type = (certDBEntryType)buf[1]; - entry->flags = (unsigned int)buf[2]; - - /* format body of entry for return to caller */ - dbentry->len = data.size - SEC_DB_ENTRY_HEADER_LEN; - if ( dbentry->len ) { - dbentry->data = (unsigned char *)PORT_ArenaAlloc(arena, dbentry->len); - if ( dbentry->data == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - PORT_Memcpy(dbentry->data, &buf[SEC_DB_ENTRY_HEADER_LEN], - dbentry->len); - } else { - dbentry->data = NULL; - } - - return(SECSuccess); - -loser: - return(SECFailure); -} - -/** - ** Implement low level database access - **/ -static SECStatus -WriteDBEntry(CERTCertDBHandle *handle, certDBEntryCommon *entry, - SECItem *dbkey, SECItem *dbentry) -{ - int ret; - DBT data, key; - unsigned char *buf; - - data.data = dbentry->data; - data.size = dbentry->len; - - buf = (unsigned char*)data.data; - - buf[0] = (unsigned char)entry->version; - buf[1] = (unsigned char)entry->type; - buf[2] = (unsigned char)entry->flags; - - key.data = dbkey->data; - key.size = dbkey->len; - - dbkey->data[0] = (unsigned char)entry->type; - - /* put the record into the database now */ - ret = certdb_Put(handle->permCertDB, &key, &data, 0); - - if ( ret != 0 ) { - goto loser; - } - - ret = certdb_Sync( handle->permCertDB, 0 ); - - if ( ret ) { - goto loser; - } - - return(SECSuccess); - -loser: - return(SECFailure); -} - -/* - * encode a database cert record - */ -static SECStatus -EncodeDBCertEntry(certDBEntryCert *entry, PRArenaPool *arena, SECItem *dbitem) -{ - unsigned int nnlen; - unsigned char *buf; - char *nn; - char zbuf = 0; - - if ( entry->nickname ) { - nn = entry->nickname; - } else { - nn = &zbuf; - } - nnlen = PORT_Strlen(nn) + 1; - - /* allocate space for encoded database record, including space - * for low level header - */ - dbitem->len = entry->derCert.len + nnlen + DB_CERT_ENTRY_HEADER_LEN + - SEC_DB_ENTRY_HEADER_LEN; - - dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len); - if ( dbitem->data == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* fill in database record */ - buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN]; - - buf[0] = ( entry->trust.sslFlags >> 8 ) & 0xff; - buf[1] = entry->trust.sslFlags & 0xff; - buf[2] = ( entry->trust.emailFlags >> 8 ) & 0xff; - buf[3] = entry->trust.emailFlags & 0xff; - buf[4] = ( entry->trust.objectSigningFlags >> 8 ) & 0xff; - buf[5] = entry->trust.objectSigningFlags & 0xff; - buf[6] = ( entry->derCert.len >> 8 ) & 0xff; - buf[7] = entry->derCert.len & 0xff; - buf[8] = ( nnlen >> 8 ) & 0xff; - buf[9] = nnlen & 0xff; - - PORT_Memcpy(&buf[DB_CERT_ENTRY_HEADER_LEN], entry->derCert.data, - entry->derCert.len); - - PORT_Memcpy(&buf[DB_CERT_ENTRY_HEADER_LEN + entry->derCert.len], - nn, nnlen); - - return(SECSuccess); - -loser: - return(SECFailure); -} - -/* - * encode a database key for a cert record - */ -static SECStatus -EncodeDBCertKey(SECItem *certKey, PRArenaPool *arena, SECItem *dbkey) -{ - dbkey->len = certKey->len + SEC_DB_KEY_HEADER_LEN; - dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len); - if ( dbkey->data == NULL ) { - goto loser; - } - PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], - certKey->data, certKey->len); - dbkey->data[0] = certDBEntryTypeCert; - - return(SECSuccess); -loser: - return(SECFailure); -} - -static SECStatus -EncodeDBGenericKey(SECItem *certKey, PRArenaPool *arena, SECItem *dbkey, - certDBEntryType entryType) -{ - /* - * we only allow _one_ KRL key! - */ - if (entryType == certDBEntryTypeKeyRevocation) { - dbkey->len = SEC_DB_KEY_HEADER_LEN; - dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len); - if ( dbkey->data == NULL ) { - goto loser; - } - dbkey->data[0] = (unsigned char) entryType; - return(SECSuccess); - } - - - dbkey->len = certKey->len + SEC_DB_KEY_HEADER_LEN; - dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len); - if ( dbkey->data == NULL ) { - goto loser; - } - PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], - certKey->data, certKey->len); - dbkey->data[0] = (unsigned char) entryType; - - return(SECSuccess); -loser: - return(SECFailure); -} - -static SECStatus -DecodeDBCertEntry(certDBEntryCert *entry, SECItem *dbentry) -{ - unsigned int nnlen; - int headerlen; - int lenoff; - - /* allow updates of old versions of the database */ - switch ( entry->common.version ) { - case 5: - headerlen = DB_CERT_V5_ENTRY_HEADER_LEN; - lenoff = 3; - break; - case 6: - /* should not get here */ - PORT_Assert(0); - headerlen = DB_CERT_V6_ENTRY_HEADER_LEN; - lenoff = 3; - break; - case 7: - headerlen = DB_CERT_ENTRY_HEADER_LEN; - lenoff = 6; - break; - default: - /* better not get here */ - PORT_Assert(0); - headerlen = DB_CERT_V5_ENTRY_HEADER_LEN; - lenoff = 3; - break; - } - - /* is record long enough for header? */ - if ( dbentry->len < headerlen ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - /* is database entry correct length? */ - entry->derCert.len = ( ( dbentry->data[lenoff] << 8 ) | - dbentry->data[lenoff+1] ); - nnlen = ( ( dbentry->data[lenoff+2] << 8 ) | dbentry->data[lenoff+3] ); - if ( ( entry->derCert.len + nnlen + headerlen ) - != dbentry->len) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - /* copy the dercert */ - entry->derCert.data = (unsigned char *)PORT_ArenaAlloc(entry->common.arena, - entry->derCert.len); - if ( entry->derCert.data == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - PORT_Memcpy(entry->derCert.data, &dbentry->data[headerlen], - entry->derCert.len); - - /* copy the nickname */ - if ( nnlen > 1 ) { - entry->nickname = (char *)PORT_ArenaAlloc(entry->common.arena, nnlen); - if ( entry->nickname == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - PORT_Memcpy(entry->nickname, - &dbentry->data[headerlen + - entry->derCert.len], - nnlen); - } else { - entry->nickname = NULL; - } - - if ( entry->common.version < 7 ) { - /* allow updates of v5 db */ - entry->trust.sslFlags = dbentry->data[0]; - entry->trust.emailFlags = dbentry->data[1]; - entry->trust.objectSigningFlags = dbentry->data[2]; - } else { - entry->trust.sslFlags = ( dbentry->data[0] << 8 ) | dbentry->data[1]; - entry->trust.emailFlags = ( dbentry->data[2] << 8 ) | dbentry->data[3]; - entry->trust.objectSigningFlags = - ( dbentry->data[4] << 8 ) | dbentry->data[5]; - } - - return(SECSuccess); -loser: - return(SECFailure); -} - - -/* - * Create a new certDBEntryCert from existing data - */ -static certDBEntryCert * -NewDBCertEntry(SECItem *derCert, char *nickname, - CERTCertTrust *trust, int flags) -{ - certDBEntryCert *entry; - PRArenaPool *arena = NULL; - int nnlen; - - arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE ); - - if ( !arena ) { - goto loser; - } - - entry = (certDBEntryCert *)PORT_ArenaZAlloc(arena, sizeof(certDBEntryCert)); - - if ( entry == NULL ) { - goto loser; - } - - /* fill in the dbCert */ - entry->common.arena = arena; - entry->common.type = certDBEntryTypeCert; - entry->common.version = CERT_DB_FILE_VERSION; - entry->common.flags = flags; - - if ( trust ) { - entry->trust = *trust; - } - - entry->derCert.data = (unsigned char *)PORT_ArenaAlloc(arena, derCert->len); - if ( !entry->derCert.data ) { - goto loser; - } - entry->derCert.len = derCert->len; - PORT_Memcpy(entry->derCert.data, derCert->data, derCert->len); - - nnlen = ( nickname ? strlen(nickname) + 1 : 0 ); - - if ( nnlen ) { - entry->nickname = (char *)PORT_ArenaAlloc(arena, nnlen); - if ( !entry->nickname ) { - goto loser; - } - PORT_Memcpy(entry->nickname, nickname, nnlen); - - } else { - entry->nickname = 0; - } - - return(entry); - -loser: - - /* allocation error, free arena and return */ - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - PORT_SetError(SEC_ERROR_NO_MEMORY); - return(0); -} - -/* - * Decode a version 4 DBCert from the byte stream database format - * and construct a current database entry struct - */ -static certDBEntryCert * -DecodeV4DBCertEntry(unsigned char *buf, int len) -{ - certDBEntryCert *entry; - int certlen; - int nnlen; - PRArenaPool *arena; - - /* make sure length is at least long enough for the header */ - if ( len < DBCERT_V4_HEADER_LEN ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - return(0); - } - - /* get other lengths */ - certlen = buf[3] << 8 | buf[4]; - nnlen = buf[5] << 8 | buf[6]; - - /* make sure DB entry is the right size */ - if ( ( certlen + nnlen + DBCERT_V4_HEADER_LEN ) != len ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - return(0); - } - - /* allocate arena */ - arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE ); - - if ( !arena ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return(0); - } - - /* allocate structure and members */ - entry = (certDBEntryCert *) PORT_ArenaAlloc(arena, sizeof(certDBEntryCert)); - - if ( !entry ) { - goto loser; - } - - entry->derCert.data = (unsigned char *)PORT_ArenaAlloc(arena, certlen); - if ( !entry->derCert.data ) { - goto loser; - } - entry->derCert.len = certlen; - - if ( nnlen ) { - entry->nickname = (char *) PORT_ArenaAlloc(arena, nnlen); - if ( !entry->nickname ) { - goto loser; - } - } else { - entry->nickname = 0; - } - - entry->common.arena = arena; - entry->common.version = CERT_DB_FILE_VERSION; - entry->common.type = certDBEntryTypeCert; - entry->common.flags = 0; - entry->trust.sslFlags = buf[0]; - entry->trust.emailFlags = buf[1]; - entry->trust.objectSigningFlags = buf[2]; - - PORT_Memcpy(entry->derCert.data, &buf[DBCERT_V4_HEADER_LEN], certlen); - PORT_Memcpy(entry->nickname, &buf[DBCERT_V4_HEADER_LEN + certlen], nnlen); - - if (PORT_Strcmp(entry->nickname,"Server-Cert") == 0) { - entry->trust.sslFlags |= CERTDB_USER; - } - - return(entry); - -loser: - PORT_FreeArena(arena, PR_FALSE); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return(0); -} - -/* - * Encode a Certificate database entry into byte stream suitable for - * the database - */ -static SECStatus -WriteDBCertEntry(CERTCertDBHandle *handle, certDBEntryCert *entry) -{ - SECItem dbitem, dbkey; - PRArenaPool *tmparena = NULL; - SECItem tmpitem; - SECStatus rv; - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - goto loser; - } - - rv = EncodeDBCertEntry(entry, tmparena, &dbitem); - if ( rv != SECSuccess ) { - goto loser; - } - - /* get the database key and format it */ - rv = CERT_KeyFromDERCert(tmparena, &entry->derCert, &tmpitem); - if ( rv == SECFailure ) { - goto loser; - } - - rv = EncodeDBCertKey(&tmpitem, tmparena, &dbkey); - if ( rv == SECFailure ) { - goto loser; - } - - /* now write it to the database */ - rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem); - if ( rv != SECSuccess ) { - goto loser; - } - - PORT_FreeArena(tmparena, PR_FALSE); - return(SECSuccess); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - return(SECFailure); -} - - -/* - * delete a certificate entry - */ -static SECStatus -DeleteDBCertEntry(CERTCertDBHandle *handle, SECItem *certKey) -{ - SECItem dbkey; - PRArenaPool *arena = NULL; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - rv = EncodeDBCertKey(certKey, arena, &dbkey); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = DeleteDBEntry(handle, certDBEntryTypeCert, &dbkey); - if ( rv == SECFailure ) { - goto loser; - } - - PORT_FreeArena(arena, PR_FALSE); - return(SECSuccess); - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(SECFailure); -} - -/* - * Read a certificate entry - */ -static certDBEntryCert * -ReadDBCertEntry(CERTCertDBHandle *handle, SECItem *certKey) -{ - PRArenaPool *arena = NULL; - PRArenaPool *tmparena = NULL; - certDBEntryCert *entry; - SECItem dbkey; - SECItem dbentry; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - entry = (certDBEntryCert *)PORT_ArenaAlloc(arena, sizeof(certDBEntryCert)); - if ( entry == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - entry->common.arena = arena; - entry->common.type = certDBEntryTypeCert; - - rv = EncodeDBCertKey(certKey, tmparena, &dbkey); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); - if ( rv == SECFailure ) { - goto loser; - } - - rv = DecodeDBCertEntry(entry, &dbentry); - if ( rv != SECSuccess ) { - goto loser; - } - - PORT_FreeArena(tmparena, PR_FALSE); - return(entry); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -/* - * encode a database cert record - */ -static SECStatus -EncodeDBCrlEntry(certDBEntryRevocation *entry, PRArenaPool *arena, SECItem *dbitem) -{ - unsigned int nnlen = 0; - unsigned char *buf; - - if (entry->url) { - nnlen = PORT_Strlen(entry->url) + 1; - } - - /* allocate space for encoded database record, including space - * for low level header - */ - dbitem->len = entry->derCrl.len + nnlen - + SEC_DB_ENTRY_HEADER_LEN + DB_CRL_ENTRY_HEADER_LEN; - - dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len); - if ( dbitem->data == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* fill in database record */ - buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN]; - - buf[0] = ( entry->derCrl.len >> 8 ) & 0xff; - buf[1] = entry->derCrl.len & 0xff; - buf[2] = ( nnlen >> 8 ) & 0xff; - buf[3] = nnlen & 0xff; - - PORT_Memcpy(&buf[DB_CRL_ENTRY_HEADER_LEN], entry->derCrl.data, - entry->derCrl.len); - - if (nnlen != 0) { - PORT_Memcpy(&buf[DB_CRL_ENTRY_HEADER_LEN + entry->derCrl.len], - entry->url, nnlen); - } - - return(SECSuccess); - -loser: - return(SECFailure); -} - -static SECStatus -DecodeDBCrlEntry(certDBEntryRevocation *entry, SECItem *dbentry) -{ - unsigned int nnlen; - - /* is record long enough for header? */ - if ( dbentry->len < DB_CRL_ENTRY_HEADER_LEN ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - /* is database entry correct length? */ - entry->derCrl.len = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] ); - nnlen = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] ); - if ( ( entry->derCrl.len + nnlen + DB_CRL_ENTRY_HEADER_LEN ) - != dbentry->len) { - /* CRL entry is greater than 64 K. Hack to make this continue to work */ - if (dbentry->len >= (0xffff - DB_CRL_ENTRY_HEADER_LEN) - nnlen) { - entry->derCrl.len = - (dbentry->len - DB_CRL_ENTRY_HEADER_LEN) - nnlen; - } else { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - } - - /* copy the dercert */ - entry->derCrl.data = (unsigned char *)PORT_ArenaAlloc(entry->common.arena, - entry->derCrl.len); - if ( entry->derCrl.data == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - PORT_Memcpy(entry->derCrl.data, &dbentry->data[DB_CRL_ENTRY_HEADER_LEN], - entry->derCrl.len); - - /* copy the url */ - entry->url = NULL; - if (nnlen != 0) { - entry->url = (char *)PORT_ArenaAlloc(entry->common.arena, nnlen); - if ( entry->url == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - PORT_Memcpy(entry->url, - &dbentry->data[DB_CRL_ENTRY_HEADER_LEN + entry->derCrl.len], - nnlen); - } - - return(SECSuccess); -loser: - return(SECFailure); -} - -/* - * Create a new certDBEntryRevocation from existing data - */ -static certDBEntryRevocation * -NewDBCrlEntry(SECItem *derCrl, char * url, certDBEntryType crlType, int flags) -{ - certDBEntryRevocation *entry; - PRArenaPool *arena = NULL; - int nnlen; - - arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE ); - - if ( !arena ) { - goto loser; - } - - entry = (certDBEntryRevocation*) - PORT_ArenaZAlloc(arena, sizeof(certDBEntryRevocation)); - - if ( entry == NULL ) { - goto loser; - } - - /* fill in the dbRevolcation */ - entry->common.arena = arena; - entry->common.type = crlType; - entry->common.version = CERT_DB_FILE_VERSION; - entry->common.flags = flags; - - - entry->derCrl.data = (unsigned char *)PORT_ArenaAlloc(arena, derCrl->len); - if ( !entry->derCrl.data ) { - goto loser; - } - - if (url) { - nnlen = PORT_Strlen(url) + 1; - entry->url = (char *)PORT_ArenaAlloc(arena, nnlen); - if ( !entry->url ) { - goto loser; - } - PORT_Memcpy(entry->url, url, nnlen); - } else { - entry->url = NULL; - } - - - entry->derCrl.len = derCrl->len; - PORT_Memcpy(entry->derCrl.data, derCrl->data, derCrl->len); - - return(entry); - -loser: - - /* allocation error, free arena and return */ - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - PORT_SetError(SEC_ERROR_NO_MEMORY); - return(0); -} - - -static SECStatus -WriteDBCrlEntry(CERTCertDBHandle *handle, certDBEntryRevocation *entry ) -{ - SECItem dbkey; - PRArenaPool *tmparena = NULL; - SECItem tmpitem,encodedEntry; - SECStatus rv; - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - goto loser; - } - - /* get the database key and format it */ - rv = CERT_KeyFromDERCrl(tmparena, &entry->derCrl, &tmpitem); - if ( rv == SECFailure ) { - goto loser; - } - - rv = EncodeDBCrlEntry(entry, tmparena, &encodedEntry); - if ( rv == SECFailure ) { - goto loser; - } - - rv = EncodeDBGenericKey(&tmpitem, tmparena, &dbkey, entry->common.type); - if ( rv == SECFailure ) { - goto loser; - } - - /* now write it to the database */ - rv = WriteDBEntry(handle, &entry->common, &dbkey, &encodedEntry); - if ( rv != SECSuccess ) { - goto loser; - } - - PORT_FreeArena(tmparena, PR_FALSE); - return(SECSuccess); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - return(SECFailure); -} -/* - * delete a crl entry - */ -static SECStatus -DeleteDBCrlEntry(CERTCertDBHandle *handle, SECItem *crlKey, - certDBEntryType crlType) -{ - SECItem dbkey; - PRArenaPool *arena = NULL; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - rv = EncodeDBGenericKey(crlKey, arena, &dbkey, crlType); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = DeleteDBEntry(handle, crlType, &dbkey); - if ( rv == SECFailure ) { - goto loser; - } - - PORT_FreeArena(arena, PR_FALSE); - return(SECSuccess); - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(SECFailure); -} - -/* - * Read a certificate entry - */ -static certDBEntryRevocation * -ReadDBCrlEntry(CERTCertDBHandle *handle, SECItem *certKey, - certDBEntryType crlType) -{ - PRArenaPool *arena = NULL; - PRArenaPool *tmparena = NULL; - certDBEntryRevocation *entry; - SECItem dbkey; - SECItem dbentry; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - entry = (certDBEntryRevocation *) - PORT_ArenaAlloc(arena, sizeof(certDBEntryRevocation)); - if ( entry == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - entry->common.arena = arena; - entry->common.type = crlType; - - rv = EncodeDBGenericKey(certKey, tmparena, &dbkey, crlType); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); - if ( rv == SECFailure ) { - goto loser; - } - - rv = DecodeDBCrlEntry(entry, &dbentry); - if ( rv != SECSuccess ) { - goto loser; - } - - PORT_FreeArena(tmparena, PR_FALSE); - return(entry); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -/* - * destroy a database entry - */ -static void -DestroyDBEntry(certDBEntry *entry) -{ - PRArenaPool *arena = entry->common.arena; - - /* Zero out the entry struct, so that any further attempts to use it - * will cause an exception (e.g. null pointer reference). */ - PORT_Memset(&entry->common, 0, sizeof entry->common); - PORT_FreeArena(arena, PR_FALSE); - - return; -} - -/* - * Encode a database nickname record - */ -static SECStatus -EncodeDBNicknameEntry(certDBEntryNickname *entry, PRArenaPool *arena, - SECItem *dbitem) -{ - unsigned char *buf; - - /* allocate space for encoded database record, including space - * for low level header - */ - dbitem->len = entry->subjectName.len + DB_NICKNAME_ENTRY_HEADER_LEN + - SEC_DB_ENTRY_HEADER_LEN; - - dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len); - if ( dbitem->data == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* fill in database record */ - buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN]; - - buf[0] = ( entry->subjectName.len >> 8 ) & 0xff; - buf[1] = entry->subjectName.len & 0xff; - - PORT_Memcpy(&buf[DB_NICKNAME_ENTRY_HEADER_LEN], entry->subjectName.data, - entry->subjectName.len); - - return(SECSuccess); - -loser: - return(SECFailure); -} - -/* - * Encode a database key for a nickname record - */ -static SECStatus -EncodeDBNicknameKey(char *nickname, PRArenaPool *arena, - SECItem *dbkey) -{ - unsigned int nnlen; - - nnlen = PORT_Strlen(nickname) + 1; /* includes null */ - - /* now get the database key and format it */ - dbkey->len = nnlen + SEC_DB_KEY_HEADER_LEN; - dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len); - if ( dbkey->data == NULL ) { - goto loser; - } - PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], nickname, nnlen); - dbkey->data[0] = certDBEntryTypeNickname; - - return(SECSuccess); - -loser: - return(SECFailure); -} - -static SECStatus -DecodeDBNicknameEntry(certDBEntryNickname *entry, SECItem *dbentry, - char *nickname) -{ - /* is record long enough for header? */ - if ( dbentry->len < DB_NICKNAME_ENTRY_HEADER_LEN ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - /* is database entry correct length? */ - entry->subjectName.len = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] ); - if (( entry->subjectName.len + DB_NICKNAME_ENTRY_HEADER_LEN ) != - dbentry->len ){ - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - /* copy the certkey */ - entry->subjectName.data = - (unsigned char *)PORT_ArenaAlloc(entry->common.arena, - entry->subjectName.len); - if ( entry->subjectName.data == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - PORT_Memcpy(entry->subjectName.data, - &dbentry->data[DB_NICKNAME_ENTRY_HEADER_LEN], - entry->subjectName.len); - - entry->nickname = (char *)PORT_ArenaAlloc(entry->common.arena, - PORT_Strlen(nickname)+1); - if ( entry->nickname ) { - PORT_Strcpy(entry->nickname, nickname); - } - - return(SECSuccess); - -loser: - return(SECFailure); -} - -/* - * create a new nickname entry - */ -static certDBEntryNickname * -NewDBNicknameEntry(char *nickname, SECItem *subjectName, unsigned int flags) -{ - PRArenaPool *arena = NULL; - certDBEntryNickname *entry; - int nnlen; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - entry = (certDBEntryNickname *)PORT_ArenaAlloc(arena, - sizeof(certDBEntryNickname)); - if ( entry == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* init common fields */ - entry->common.arena = arena; - entry->common.type = certDBEntryTypeNickname; - entry->common.version = CERT_DB_FILE_VERSION; - entry->common.flags = flags; - - /* copy the nickname */ - nnlen = PORT_Strlen(nickname) + 1; - - entry->nickname = (char*)PORT_ArenaAlloc(arena, nnlen); - if ( entry->nickname == NULL ) { - goto loser; - } - - PORT_Memcpy(entry->nickname, nickname, nnlen); - - rv = SECITEM_CopyItem(arena, &entry->subjectName, subjectName); - if ( rv != SECSuccess ) { - goto loser; - } - - return(entry); -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -/* - * delete a nickname entry - */ -static SECStatus -DeleteDBNicknameEntry(CERTCertDBHandle *handle, char *nickname) -{ - PRArenaPool *arena = NULL; - SECStatus rv; - SECItem dbkey; - - if ( nickname == NULL ) { - return(SECSuccess); - } - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - rv = EncodeDBNicknameKey(nickname, arena, &dbkey); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = DeleteDBEntry(handle, certDBEntryTypeNickname, &dbkey); - if ( rv == SECFailure ) { - goto loser; - } - - PORT_FreeArena(arena, PR_FALSE); - return(SECSuccess); - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(SECFailure); -} - -/* - * Read a nickname entry - */ -static certDBEntryNickname * -ReadDBNicknameEntry(CERTCertDBHandle *handle, char *nickname) -{ - PRArenaPool *arena = NULL; - PRArenaPool *tmparena = NULL; - certDBEntryNickname *entry; - SECItem dbkey; - SECItem dbentry; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - entry = (certDBEntryNickname *)PORT_ArenaAlloc(arena, - sizeof(certDBEntryNickname)); - if ( entry == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - entry->common.arena = arena; - entry->common.type = certDBEntryTypeNickname; - - rv = EncodeDBNicknameKey(nickname, tmparena, &dbkey); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); - if ( rv == SECFailure ) { - goto loser; - } - - /* is record long enough for header? */ - if ( dbentry.len < DB_NICKNAME_ENTRY_HEADER_LEN ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - rv = DecodeDBNicknameEntry(entry, &dbentry, nickname); - if ( rv != SECSuccess ) { - goto loser; - } - - PORT_FreeArena(tmparena, PR_FALSE); - return(entry); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -/* - * Encode a nickname entry into byte stream suitable for - * the database - */ -static SECStatus -WriteDBNicknameEntry(CERTCertDBHandle *handle, certDBEntryNickname *entry) -{ - SECItem dbitem, dbkey; - PRArenaPool *tmparena = NULL; - SECStatus rv; - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - goto loser; - } - - rv = EncodeDBNicknameEntry(entry, tmparena, &dbitem); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = EncodeDBNicknameKey(entry->nickname, tmparena, &dbkey); - if ( rv != SECSuccess ) { - goto loser; - } - - /* now write it to the database */ - rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem); - if ( rv != SECSuccess ) { - goto loser; - } - - PORT_FreeArena(tmparena, PR_FALSE); - return(SECSuccess); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - return(SECFailure); - -} - -/* - * Encode a database smime record - */ -static SECStatus -EncodeDBSMimeEntry(certDBEntrySMime *entry, PRArenaPool *arena, - SECItem *dbitem) -{ - unsigned char *buf; - - /* allocate space for encoded database record, including space - * for low level header - */ - dbitem->len = entry->subjectName.len + entry->smimeOptions.len + - entry->optionsDate.len + - DB_SMIME_ENTRY_HEADER_LEN + SEC_DB_ENTRY_HEADER_LEN; - - dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len); - if ( dbitem->data == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* fill in database record */ - buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN]; - - buf[0] = ( entry->subjectName.len >> 8 ) & 0xff; - buf[1] = entry->subjectName.len & 0xff; - buf[2] = ( entry->smimeOptions.len >> 8 ) & 0xff; - buf[3] = entry->smimeOptions.len & 0xff; - buf[4] = ( entry->optionsDate.len >> 8 ) & 0xff; - buf[5] = entry->optionsDate.len & 0xff; - - /* if no smime options, then there should not be an options date either */ - PORT_Assert( ! ( ( entry->smimeOptions.len == 0 ) && - ( entry->optionsDate.len != 0 ) ) ); - - PORT_Memcpy(&buf[DB_SMIME_ENTRY_HEADER_LEN], entry->subjectName.data, - entry->subjectName.len); - if ( entry->smimeOptions.len ) { - PORT_Memcpy(&buf[DB_SMIME_ENTRY_HEADER_LEN+entry->subjectName.len], - entry->smimeOptions.data, - entry->smimeOptions.len); - PORT_Memcpy(&buf[DB_SMIME_ENTRY_HEADER_LEN + entry->subjectName.len + - entry->smimeOptions.len], - entry->optionsDate.data, - entry->optionsDate.len); - } - - return(SECSuccess); - -loser: - return(SECFailure); -} - -/* - * Encode a database key for a SMIME record - */ -static SECStatus -EncodeDBSMimeKey(char *emailAddr, PRArenaPool *arena, - SECItem *dbkey) -{ - unsigned int addrlen; - - addrlen = PORT_Strlen(emailAddr) + 1; /* includes null */ - - /* now get the database key and format it */ - dbkey->len = addrlen + SEC_DB_KEY_HEADER_LEN; - dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len); - if ( dbkey->data == NULL ) { - goto loser; - } - PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], emailAddr, addrlen); - dbkey->data[0] = certDBEntryTypeSMimeProfile; - - return(SECSuccess); - -loser: - return(SECFailure); -} - -/* - * Decode a database SMIME record - */ -static SECStatus -DecodeDBSMimeEntry(certDBEntrySMime *entry, SECItem *dbentry, char *emailAddr) -{ - /* is record long enough for header? */ - if ( dbentry->len < DB_SMIME_ENTRY_HEADER_LEN ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - /* is database entry correct length? */ - entry->subjectName.len = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] ); - entry->smimeOptions.len = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] ); - entry->optionsDate.len = ( ( dbentry->data[4] << 8 ) | dbentry->data[5] ); - if (( entry->subjectName.len + entry->smimeOptions.len + - entry->optionsDate.len + DB_SMIME_ENTRY_HEADER_LEN ) != dbentry->len){ - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - /* copy the subject name */ - entry->subjectName.data = - (unsigned char *)PORT_ArenaAlloc(entry->common.arena, - entry->subjectName.len); - if ( entry->subjectName.data == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - PORT_Memcpy(entry->subjectName.data, - &dbentry->data[DB_SMIME_ENTRY_HEADER_LEN], - entry->subjectName.len); - - /* copy the smime options */ - if ( entry->smimeOptions.len ) { - entry->smimeOptions.data = - (unsigned char *)PORT_ArenaAlloc(entry->common.arena, - entry->smimeOptions.len); - if ( entry->smimeOptions.data == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - PORT_Memcpy(entry->smimeOptions.data, - &dbentry->data[DB_SMIME_ENTRY_HEADER_LEN + - entry->subjectName.len], - entry->smimeOptions.len); - } - if ( entry->optionsDate.len ) { - entry->optionsDate.data = - (unsigned char *)PORT_ArenaAlloc(entry->common.arena, - entry->optionsDate.len); - if ( entry->optionsDate.data == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - PORT_Memcpy(entry->optionsDate.data, - &dbentry->data[DB_SMIME_ENTRY_HEADER_LEN + - entry->subjectName.len + - entry->smimeOptions.len], - entry->optionsDate.len); - } - - /* both options and options date must either exist or not exist */ - if ( ( ( entry->optionsDate.len == 0 ) || - ( entry->smimeOptions.len == 0 ) ) && - entry->smimeOptions.len != entry->optionsDate.len ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - entry->emailAddr = (char *)PORT_Alloc(PORT_Strlen(emailAddr)+1); - if ( entry->emailAddr ) { - PORT_Strcpy(entry->emailAddr, emailAddr); - } - - return(SECSuccess); - -loser: - return(SECFailure); -} - -/* - * create a new SMIME entry - */ -static certDBEntrySMime * -NewDBSMimeEntry(char *emailAddr, SECItem *subjectName, SECItem *smimeOptions, - SECItem *optionsDate, unsigned int flags) -{ - PRArenaPool *arena = NULL; - certDBEntrySMime *entry; - int addrlen; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - entry = (certDBEntrySMime *)PORT_ArenaAlloc(arena, - sizeof(certDBEntrySMime)); - if ( entry == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* init common fields */ - entry->common.arena = arena; - entry->common.type = certDBEntryTypeSMimeProfile; - entry->common.version = CERT_DB_FILE_VERSION; - entry->common.flags = flags; - - /* copy the email addr */ - addrlen = PORT_Strlen(emailAddr) + 1; - - entry->emailAddr = (char*)PORT_ArenaAlloc(arena, addrlen); - if ( entry->emailAddr == NULL ) { - goto loser; - } - - PORT_Memcpy(entry->emailAddr, emailAddr, addrlen); - - /* copy the subject name */ - rv = SECITEM_CopyItem(arena, &entry->subjectName, subjectName); - if ( rv != SECSuccess ) { - goto loser; - } - - /* copy the smime options */ - if ( smimeOptions ) { - rv = SECITEM_CopyItem(arena, &entry->smimeOptions, smimeOptions); - if ( rv != SECSuccess ) { - goto loser; - } - } else { - PORT_Assert(optionsDate == NULL); - entry->smimeOptions.data = NULL; - entry->smimeOptions.len = 0; - } - - /* copy the options date */ - if ( optionsDate ) { - rv = SECITEM_CopyItem(arena, &entry->optionsDate, optionsDate); - if ( rv != SECSuccess ) { - goto loser; - } - } else { - PORT_Assert(smimeOptions == NULL); - entry->optionsDate.data = NULL; - entry->optionsDate.len = 0; - } - - return(entry); -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -/* - * delete a SMIME entry - */ -static SECStatus -DeleteDBSMimeEntry(CERTCertDBHandle *handle, char *emailAddr) -{ - PRArenaPool *arena = NULL; - SECStatus rv; - SECItem dbkey; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - rv = EncodeDBSMimeKey(emailAddr, arena, &dbkey); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = DeleteDBEntry(handle, certDBEntryTypeSMimeProfile, &dbkey); - if ( rv == SECFailure ) { - goto loser; - } - - PORT_FreeArena(arena, PR_FALSE); - return(SECSuccess); - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(SECFailure); -} - -/* - * Read a SMIME entry - */ -static certDBEntrySMime * -ReadDBSMimeEntry(CERTCertDBHandle *handle, char *emailAddr) -{ - PRArenaPool *arena = NULL; - PRArenaPool *tmparena = NULL; - certDBEntrySMime *entry; - SECItem dbkey; - SECItem dbentry; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - entry = (certDBEntrySMime *)PORT_ArenaAlloc(arena, - sizeof(certDBEntrySMime)); - if ( entry == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - entry->common.arena = arena; - entry->common.type = certDBEntryTypeSMimeProfile; - - rv = EncodeDBSMimeKey(emailAddr, tmparena, &dbkey); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); - if ( rv == SECFailure ) { - goto loser; - } - - /* is record long enough for header? */ - if ( dbentry.len < DB_SMIME_ENTRY_HEADER_LEN ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - rv = DecodeDBSMimeEntry(entry, &dbentry, emailAddr); - if ( rv != SECSuccess ) { - goto loser; - } - - PORT_FreeArena(tmparena, PR_FALSE); - return(entry); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -/* - * Encode a SMIME entry into byte stream suitable for - * the database - */ -static SECStatus -WriteDBSMimeEntry(CERTCertDBHandle *handle, certDBEntrySMime *entry) -{ - SECItem dbitem, dbkey; - PRArenaPool *tmparena = NULL; - SECStatus rv; - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - goto loser; - } - - rv = EncodeDBSMimeEntry(entry, tmparena, &dbitem); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = EncodeDBSMimeKey(entry->emailAddr, tmparena, &dbkey); - if ( rv != SECSuccess ) { - goto loser; - } - - /* now write it to the database */ - rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem); - if ( rv != SECSuccess ) { - goto loser; - } - - PORT_FreeArena(tmparena, PR_FALSE); - return(SECSuccess); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - return(SECFailure); - -} - -/* - * Encode a database subject record - */ -static SECStatus -EncodeDBSubjectEntry(certDBEntrySubject *entry, PRArenaPool *arena, - SECItem *dbitem) -{ - unsigned char *buf; - int len; - unsigned int ncerts; - unsigned int i; - unsigned char *tmpbuf; - unsigned int nnlen = 0; - unsigned int eaddrlen = 0; - int keyidoff; - SECItem *certKeys; - SECItem *keyIDs; - - if ( entry->nickname ) { - nnlen = PORT_Strlen(entry->nickname) + 1; - } - if ( entry->emailAddr ) { - eaddrlen = PORT_Strlen(entry->emailAddr) + 1; - } - - ncerts = entry->ncerts; - - /* compute the length of the entry */ - keyidoff = DB_SUBJECT_ENTRY_HEADER_LEN + nnlen + eaddrlen; - len = keyidoff + 4 * ncerts; - for ( i = 0; i < ncerts; i++ ) { - len += entry->certKeys[i].len; - len += entry->keyIDs[i].len; - } - - /* allocate space for encoded database record, including space - * for low level header - */ - dbitem->len = len + SEC_DB_ENTRY_HEADER_LEN; - - dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len); - if ( dbitem->data == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* fill in database record */ - buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN]; - - buf[0] = ( ncerts >> 8 ) & 0xff; - buf[1] = ncerts & 0xff; - buf[2] = ( nnlen >> 8 ) & 0xff; - buf[3] = nnlen & 0xff; - buf[4] = ( eaddrlen >> 8 ) & 0xff; - buf[5] = eaddrlen & 0xff; - - PORT_Memcpy(&buf[DB_SUBJECT_ENTRY_HEADER_LEN], entry->nickname, nnlen); - PORT_Memcpy(&buf[DB_SUBJECT_ENTRY_HEADER_LEN+nnlen], entry->emailAddr, - eaddrlen); - - for ( i = 0; i < ncerts; i++ ) { - - certKeys = entry->certKeys; - keyIDs = entry->keyIDs; - - buf[keyidoff+i*2] = ( certKeys[i].len >> 8 ) & 0xff; - buf[keyidoff+1+i*2] = certKeys[i].len & 0xff; - buf[keyidoff+ncerts*2+i*2] = ( keyIDs[i].len >> 8 ) & 0xff; - buf[keyidoff+1+ncerts*2+i*2] = keyIDs[i].len & 0xff; - } - - /* temp pointer used to stuff certkeys and keyids into the buffer */ - tmpbuf = &buf[keyidoff+ncerts*4]; - - for ( i = 0; i < ncerts; i++ ) { - certKeys = entry->certKeys; - PORT_Memcpy(tmpbuf, certKeys[i].data, certKeys[i].len); - tmpbuf = tmpbuf + certKeys[i].len; - } - - for ( i = 0; i < ncerts; i++ ) { - keyIDs = entry->keyIDs; - PORT_Memcpy(tmpbuf, keyIDs[i].data, keyIDs[i].len); - tmpbuf = tmpbuf + keyIDs[i].len; - } - - PORT_Assert(tmpbuf == &buf[len]); - - return(SECSuccess); - -loser: - return(SECFailure); -} - -/* - * Encode a database key for a subject record - */ -static SECStatus -EncodeDBSubjectKey(SECItem *derSubject, PRArenaPool *arena, - SECItem *dbkey) -{ - dbkey->len = derSubject->len + SEC_DB_KEY_HEADER_LEN; - dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len); - if ( dbkey->data == NULL ) { - goto loser; - } - PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], derSubject->data, - derSubject->len); - dbkey->data[0] = certDBEntryTypeSubject; - - return(SECSuccess); - -loser: - return(SECFailure); -} - -static SECStatus -DecodeDBSubjectEntry(certDBEntrySubject *entry, SECItem *dbentry, - SECItem *derSubject) -{ - unsigned int ncerts; - PRArenaPool *arena; - unsigned int len, itemlen; - unsigned char *tmpbuf; - unsigned int i; - SECStatus rv; - unsigned int keyidoff; - unsigned int nnlen, eaddrlen; - - arena = entry->common.arena; - - rv = SECITEM_CopyItem(arena, &entry->derSubject, derSubject); - if ( rv != SECSuccess ) { - goto loser; - } - - /* is record long enough for header? */ - if ( dbentry->len < DB_SUBJECT_ENTRY_HEADER_LEN ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - entry->ncerts = ncerts = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] ); - nnlen = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] ); - eaddrlen = ( ( dbentry->data[4] << 8 ) | dbentry->data[5] ); - if ( dbentry->len < ( ncerts * 4 + DB_SUBJECT_ENTRY_HEADER_LEN + - nnlen + eaddrlen) ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - entry->certKeys = (SECItem *)PORT_ArenaAlloc(arena, - sizeof(SECItem) * ncerts); - entry->keyIDs = (SECItem *)PORT_ArenaAlloc(arena, - sizeof(SECItem) * ncerts); - - if ( ( entry->certKeys == NULL ) || ( entry->keyIDs == NULL ) ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - if ( nnlen > 1 ) { /* null terminator is stored */ - entry->nickname = (char *)PORT_ArenaAlloc(arena, nnlen); - if ( entry->nickname == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - PORT_Memcpy(entry->nickname, - &dbentry->data[DB_SUBJECT_ENTRY_HEADER_LEN], - nnlen); - } else { - entry->nickname = NULL; - } - - if ( eaddrlen > 1 ) { /* null terminator is stored */ - entry->emailAddr = (char *)PORT_ArenaAlloc(arena, eaddrlen); - if ( entry->emailAddr == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - PORT_Memcpy(entry->emailAddr, - &dbentry->data[DB_SUBJECT_ENTRY_HEADER_LEN+nnlen], - eaddrlen); - } else { - entry->emailAddr = NULL; - } - - /* collect the lengths of the certKeys and keyIDs, and total the - * overall length. - */ - keyidoff = DB_SUBJECT_ENTRY_HEADER_LEN + nnlen + eaddrlen; - len = keyidoff + 4 * ncerts; - - tmpbuf = &dbentry->data[0]; - - for ( i = 0; i < ncerts; i++ ) { - - itemlen = ( tmpbuf[keyidoff + 2*i] << 8 ) | tmpbuf[keyidoff + 1 + 2*i] ; - len += itemlen; - entry->certKeys[i].len = itemlen; - - itemlen = ( tmpbuf[keyidoff + 2*ncerts + 2*i] << 8 ) | - tmpbuf[keyidoff + 1 + 2*ncerts + 2*i] ; - len += itemlen; - entry->keyIDs[i].len = itemlen; - } - - /* is database entry correct length? */ - if ( len != dbentry->len ){ - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - tmpbuf = &tmpbuf[keyidoff + 4*ncerts]; - for ( i = 0; i < ncerts; i++ ) { - entry->certKeys[i].data = - (unsigned char *)PORT_ArenaAlloc(arena, entry->certKeys[i].len); - if ( entry->certKeys[i].data == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - PORT_Memcpy(entry->certKeys[i].data, tmpbuf, entry->certKeys[i].len); - tmpbuf = &tmpbuf[entry->certKeys[i].len]; - } - - for ( i = 0; i < ncerts; i++ ) { - entry->keyIDs[i].data = - (unsigned char *)PORT_ArenaAlloc(arena, entry->keyIDs[i].len); - if ( entry->keyIDs[i].data == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - PORT_Memcpy(entry->keyIDs[i].data, tmpbuf, entry->keyIDs[i].len); - tmpbuf = &tmpbuf[entry->keyIDs[i].len]; - } - - PORT_Assert(tmpbuf == &dbentry->data[dbentry->len]); - - return(SECSuccess); - -loser: - return(SECFailure); -} - -/* - * create a new subject entry with a single cert - */ -static certDBEntrySubject * -NewDBSubjectEntry(SECItem *derSubject, SECItem *certKey, - SECItem *keyID, char *nickname, char *emailAddr, - unsigned int flags) -{ - PRArenaPool *arena = NULL; - certDBEntrySubject *entry; - SECStatus rv; - unsigned int nnlen; - unsigned int eaddrlen; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - entry = (certDBEntrySubject *)PORT_ArenaAlloc(arena, - sizeof(certDBEntrySubject)); - if ( entry == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* init common fields */ - entry->common.arena = arena; - entry->common.type = certDBEntryTypeSubject; - entry->common.version = CERT_DB_FILE_VERSION; - entry->common.flags = flags; - - /* copy the subject */ - rv = SECITEM_CopyItem(arena, &entry->derSubject, derSubject); - if ( rv != SECSuccess ) { - goto loser; - } - - entry->ncerts = 1; - /* copy nickname */ - if ( nickname && ( *nickname != '\0' ) ) { - nnlen = PORT_Strlen(nickname) + 1; - entry->nickname = (char *)PORT_ArenaAlloc(arena, nnlen); - if ( entry->nickname == NULL ) { - goto loser; - } - - PORT_Memcpy(entry->nickname, nickname, nnlen); - } else { - entry->nickname = NULL; - } - - /* copy email addr */ - if ( emailAddr && ( *emailAddr != '\0' ) ) { - emailAddr = CERT_FixupEmailAddr(emailAddr); - if ( emailAddr == NULL ) { - entry->emailAddr = NULL; - goto loser; - } - - eaddrlen = PORT_Strlen(emailAddr) + 1; - entry->emailAddr = (char *)PORT_ArenaAlloc(arena, eaddrlen); - if ( entry->emailAddr == NULL ) { - PORT_Free(emailAddr); - goto loser; - } - - PORT_Memcpy(entry->emailAddr, emailAddr, eaddrlen); - PORT_Free(emailAddr); - } else { - entry->emailAddr = NULL; - } - - /* allocate space for certKeys and keyIDs */ - entry->certKeys = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem)); - entry->keyIDs = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem)); - if ( ( entry->certKeys == NULL ) || ( entry->keyIDs == NULL ) ) { - goto loser; - } - - /* copy the certKey and keyID */ - rv = SECITEM_CopyItem(arena, &entry->certKeys[0], certKey); - if ( rv != SECSuccess ) { - goto loser; - } - rv = SECITEM_CopyItem(arena, &entry->keyIDs[0], keyID); - if ( rv != SECSuccess ) { - goto loser; - } - - return(entry); -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -/* - * delete a subject entry - */ -static SECStatus -DeleteDBSubjectEntry(CERTCertDBHandle *handle, SECItem *derSubject) -{ - SECItem dbkey; - PRArenaPool *arena = NULL; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - rv = EncodeDBSubjectKey(derSubject, arena, &dbkey); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = DeleteDBEntry(handle, certDBEntryTypeSubject, &dbkey); - if ( rv == SECFailure ) { - goto loser; - } - - PORT_FreeArena(arena, PR_FALSE); - return(SECSuccess); - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(SECFailure); -} - -/* - * Read the subject entry - */ -static certDBEntrySubject * -ReadDBSubjectEntry(CERTCertDBHandle *handle, SECItem *derSubject) -{ - PRArenaPool *arena = NULL; - PRArenaPool *tmparena = NULL; - certDBEntrySubject *entry; - SECItem dbkey; - SECItem dbentry; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - entry = (certDBEntrySubject *)PORT_ArenaAlloc(arena, - sizeof(certDBEntrySubject)); - if ( entry == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - entry->common.arena = arena; - entry->common.type = certDBEntryTypeSubject; - - rv = EncodeDBSubjectKey(derSubject, tmparena, &dbkey); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); - if ( rv == SECFailure ) { - goto loser; - } - - rv = DecodeDBSubjectEntry(entry, &dbentry, derSubject); - if ( rv == SECFailure ) { - goto loser; - } - - PORT_FreeArena(tmparena, PR_FALSE); - return(entry); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -/* - * Encode a subject name entry into byte stream suitable for - * the database - */ -static SECStatus -WriteDBSubjectEntry(CERTCertDBHandle *handle, certDBEntrySubject *entry) -{ - SECItem dbitem, dbkey; - PRArenaPool *tmparena = NULL; - SECStatus rv; - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - goto loser; - } - - rv = EncodeDBSubjectEntry(entry, tmparena, &dbitem); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = EncodeDBSubjectKey(&entry->derSubject, tmparena, &dbkey); - if ( rv != SECSuccess ) { - goto loser; - } - - /* now write it to the database */ - rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem); - if ( rv != SECSuccess ) { - goto loser; - } - - PORT_FreeArena(tmparena, PR_FALSE); - return(SECSuccess); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - return(SECFailure); - -} - -static SECStatus -UpdateSubjectWithEmailAddr(CERTCertificate *cert, char *emailAddr) -{ - CERTSubjectList *subjectList; - PRBool save = PR_FALSE, delold = PR_FALSE; - certDBEntrySubject *entry; - SECStatus rv; - - emailAddr = CERT_FixupEmailAddr(emailAddr); - if ( emailAddr == NULL ) { - return(SECFailure); - } - - subjectList = cert->subjectList; - PORT_Assert(subjectList != NULL); - - if ( subjectList->emailAddr ) { - if ( PORT_Strcmp(subjectList->emailAddr, emailAddr) != 0 ) { - save = PR_TRUE; - delold = PR_TRUE; - } - } else { - save = PR_TRUE; - } - - if ( delold ) { - /* delete the old smime entry, because this cert now has a new - * smime entry pointing to it - */ - PORT_Assert(save); - PORT_Assert(subjectList->emailAddr != NULL); - DeleteDBSMimeEntry(cert->dbhandle, subjectList->emailAddr); - } - - if ( save ) { - unsigned int len; - - entry = subjectList->entry; - - PORT_Assert(entry != NULL); - len = PORT_Strlen(emailAddr) + 1; - entry->emailAddr = (char *)PORT_ArenaAlloc(entry->common.arena, len); - if ( entry->emailAddr == NULL ) { - goto loser; - } - PORT_Memcpy(entry->emailAddr, emailAddr, len); - - /* delete the subject entry */ - DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject); - - /* write the new one */ - rv = WriteDBSubjectEntry(cert->dbhandle, entry); - if ( rv != SECSuccess ) { - goto loser; - } - } - - PORT_Free(emailAddr); - return(SECSuccess); - -loser: - PORT_Free(emailAddr); - return(SECFailure); -} - -/* - * writes a nickname to an existing subject entry that does not currently - * have one - */ -static SECStatus -AddNicknameToSubject(CERTCertificate *cert, char *nickname) -{ - CERTSubjectList *subjectList; - certDBEntrySubject *entry; - SECStatus rv; - - if ( nickname == NULL ) { - return(SECFailure); - } - - subjectList = cert->subjectList; - PORT_Assert(subjectList != NULL); - if ( subjectList == NULL ) { - goto loser; - } - - entry = subjectList->entry; - PORT_Assert(entry != NULL); - if ( entry == NULL ) { - goto loser; - } - - PORT_Assert(entry->nickname == NULL); - if ( entry->nickname != NULL ) { - goto loser; - } - - entry->nickname = (nickname) ? PORT_ArenaStrdup(entry->common.arena, nickname) : NULL; - - if ( entry->nickname == NULL ) { - goto loser; - } - - /* delete the subject entry */ - DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject); - - /* write the new one */ - rv = WriteDBSubjectEntry(cert->dbhandle, entry); - if ( rv != SECSuccess ) { - goto loser; - } - - return(SECSuccess); - -loser: - return(SECFailure); -} - -/* - * create a new version entry - */ -static certDBEntryVersion * -NewDBVersionEntry(unsigned int flags) -{ - PRArenaPool *arena = NULL; - certDBEntryVersion *entry; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - entry = (certDBEntryVersion *)PORT_ArenaAlloc(arena, - sizeof(certDBEntryVersion)); - if ( entry == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - entry->common.arena = arena; - entry->common.type = certDBEntryTypeVersion; - entry->common.version = CERT_DB_FILE_VERSION; - entry->common.flags = flags; - - return(entry); -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -/* - * Read the version entry - */ -static certDBEntryVersion * -ReadDBVersionEntry(CERTCertDBHandle *handle) -{ - PRArenaPool *arena = NULL; - PRArenaPool *tmparena = NULL; - certDBEntryVersion *entry; - SECItem dbkey; - SECItem dbentry; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - entry = (certDBEntryVersion *)PORT_ArenaAlloc(arena, - sizeof(certDBEntryVersion)); - if ( entry == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - entry->common.arena = arena; - entry->common.type = certDBEntryTypeVersion; - - /* now get the database key and format it */ - dbkey.len = SEC_DB_VERSION_KEY_LEN + SEC_DB_KEY_HEADER_LEN; - dbkey.data = (unsigned char *)PORT_ArenaAlloc(tmparena, dbkey.len); - if ( dbkey.data == NULL ) { - goto loser; - } - PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], SEC_DB_VERSION_KEY, - SEC_DB_VERSION_KEY_LEN); - - ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); - - PORT_FreeArena(tmparena, PR_FALSE); - return(entry); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - - -/* - * Encode a version entry into byte stream suitable for - * the database - */ -static SECStatus -WriteDBVersionEntry(CERTCertDBHandle *handle, certDBEntryVersion *entry) -{ - SECItem dbitem, dbkey; - PRArenaPool *tmparena = NULL; - SECStatus rv; - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - goto loser; - } - - /* allocate space for encoded database record, including space - * for low level header - */ - dbitem.len = SEC_DB_ENTRY_HEADER_LEN; - - dbitem.data = (unsigned char *)PORT_ArenaAlloc(tmparena, dbitem.len); - if ( dbitem.data == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* now get the database key and format it */ - dbkey.len = SEC_DB_VERSION_KEY_LEN + SEC_DB_KEY_HEADER_LEN; - dbkey.data = (unsigned char *)PORT_ArenaAlloc(tmparena, dbkey.len); - if ( dbkey.data == NULL ) { - goto loser; - } - PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], SEC_DB_VERSION_KEY, - SEC_DB_VERSION_KEY_LEN); - - /* now write it to the database */ - rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem); - if ( rv != SECSuccess ) { - goto loser; - } - - PORT_FreeArena(tmparena, PR_FALSE); - return(SECSuccess); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - return(SECFailure); -} - -/* - * create a new version entry - */ -static certDBEntryContentVersion * -NewDBContentVersionEntry(unsigned int flags) -{ - PRArenaPool *arena = NULL; - certDBEntryContentVersion *entry; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - entry = (certDBEntryContentVersion *) - PORT_ArenaAlloc(arena, sizeof(certDBEntryContentVersion)); - if ( entry == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - entry->common.arena = arena; - entry->common.type = certDBEntryTypeContentVersion; - entry->common.version = CERT_DB_FILE_VERSION; - entry->common.flags = flags; - - entry->contentVersion = CERT_DB_CONTENT_VERSION; - - return(entry); -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -/* - * Read the version entry - */ -static certDBEntryContentVersion * -ReadDBContentVersionEntry(CERTCertDBHandle *handle) -{ - PRArenaPool *arena = NULL; - PRArenaPool *tmparena = NULL; - certDBEntryContentVersion *entry; - SECItem dbkey; - SECItem dbentry; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - entry = (certDBEntryContentVersion *) - PORT_ArenaAlloc(arena, sizeof(certDBEntryContentVersion)); - if ( entry == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - entry->common.arena = arena; - entry->common.type = certDBEntryTypeContentVersion; - - /* now get the database key and format it */ - dbkey.len = SEC_DB_CONTENT_VERSION_KEY_LEN + SEC_DB_KEY_HEADER_LEN; - dbkey.data = (unsigned char *)PORT_ArenaAlloc(tmparena, dbkey.len); - if ( dbkey.data == NULL ) { - goto loser; - } - PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], SEC_DB_CONTENT_VERSION_KEY, - SEC_DB_CONTENT_VERSION_KEY_LEN); - - dbentry.len = 0; - dbentry.data = NULL; - - ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); - - if ( dbentry.len != 1 ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - entry->contentVersion = dbentry.data[0]; - - PORT_FreeArena(tmparena, PR_FALSE); - return(entry); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -/* - * Encode a version entry into byte stream suitable for - * the database - */ -static SECStatus -WriteDBContentVersionEntry(CERTCertDBHandle *handle, - certDBEntryContentVersion *entry) -{ - SECItem dbitem, dbkey; - PRArenaPool *tmparena = NULL; - SECStatus rv; - - tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( tmparena == NULL ) { - goto loser; - } - - /* allocate space for encoded database record, including space - * for low level header - */ - dbitem.len = SEC_DB_ENTRY_HEADER_LEN + 1; - - dbitem.data = (unsigned char *)PORT_ArenaAlloc(tmparena, dbitem.len); - if ( dbitem.data == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - dbitem.data[SEC_DB_ENTRY_HEADER_LEN] = entry->contentVersion; - - /* now get the database key and format it */ - dbkey.len = SEC_DB_CONTENT_VERSION_KEY_LEN + SEC_DB_KEY_HEADER_LEN; - dbkey.data = (unsigned char *)PORT_ArenaAlloc(tmparena, dbkey.len); - if ( dbkey.data == NULL ) { - goto loser; - } - PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], SEC_DB_CONTENT_VERSION_KEY, - SEC_DB_CONTENT_VERSION_KEY_LEN); - - /* now write it to the database */ - rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem); - if ( rv != SECSuccess ) { - goto loser; - } - - PORT_FreeArena(tmparena, PR_FALSE); - return(SECSuccess); - -loser: - if ( tmparena ) { - PORT_FreeArena(tmparena, PR_FALSE); - } - return(SECFailure); -} - -/* - * delete a content version entry - */ -static SECStatus -DeleteDBContentVersionEntry(CERTCertDBHandle *handle) -{ - SECItem dbkey; - PRArenaPool *arena = NULL; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - /* now get the database key and format it */ - dbkey.len = SEC_DB_CONTENT_VERSION_KEY_LEN + SEC_DB_KEY_HEADER_LEN; - dbkey.data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey.len); - if ( dbkey.data == NULL ) { - goto loser; - } - PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], SEC_DB_CONTENT_VERSION_KEY, - SEC_DB_CONTENT_VERSION_KEY_LEN); - - rv = DeleteDBEntry(handle, certDBEntryTypeContentVersion, &dbkey); - if ( rv == SECFailure ) { - goto loser; - } - - PORT_FreeArena(arena, PR_FALSE); - return(SECSuccess); - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(SECFailure); -} - -/* - * Routines and datastructures to manage the list of certificates for a - * particular subject name. - */ - -/* - * Create a new certificate subject list. If entry exists, then populate - * the list with the entries from the permanent database. - */ -static CERTSubjectList * -NewSubjectList(certDBEntrySubject *entry) -{ - PRArenaPool *permarena; - unsigned int i; - CERTSubjectList *subjectList; - CERTSubjectNode *node; - SECStatus rv; - - permarena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( permarena == NULL ) { - goto loser; - } - subjectList = (CERTSubjectList *)PORT_ArenaAlloc(permarena, - sizeof(CERTSubjectList)); - if ( subjectList == NULL ) { - goto loser; - } - - subjectList->arena = permarena; - subjectList->ncerts = 0; - subjectList->head = NULL; - subjectList->tail = NULL; - subjectList->entry = entry; - subjectList->emailAddr = NULL; - if ( entry ) { - - /* initialize the list with certs from database entry */ - for ( i = 0; i < entry->ncerts; i++ ) { - /* Init the node */ - node = (CERTSubjectNode *)PORT_ArenaAlloc(permarena, - sizeof(CERTSubjectNode)); - if ( node == NULL ) { - goto loser; - } - - /* copy certKey and keyID to node */ - rv = SECITEM_CopyItem(permarena, &node->certKey, - &entry->certKeys[i]); - if ( rv != SECSuccess ) { - goto loser; - } - rv = SECITEM_CopyItem(permarena, &node->keyID, - &entry->keyIDs[i]); - if ( rv != SECSuccess ) { - goto loser; - } - - /* the certs are already in order, so just add them - * to the tail. - */ - node->next = NULL; - if ( subjectList->tail == NULL ) { - /* first in list */ - subjectList->head = node; - subjectList->tail = node; - node->prev = NULL; - } else { - /* add to end of list */ - node->prev = subjectList->tail; - subjectList->tail = node; - node->prev->next = node; - } - subjectList->ncerts++; - } - } - - return(subjectList); - -loser: - PORT_FreeArena(permarena, PR_FALSE); - return(NULL); -} - -/* - * Find the Subject entry in the temp database. It it is not in the - * temp database, then get it from the perm DB. It its not there either, - * then create a new one. - */ -static CERTSubjectList * -FindSubjectList(CERTCertDBHandle *handle, SECItem *subject, PRBool create) -{ - PRArenaPool *arena = NULL; - SECItem keyitem; - SECStatus rv; - DBT namekey; - DBT tmpdata; - int ret; - CERTSubjectList *subjectList = NULL; - certDBEntrySubject *entry; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - rv = EncodeDBSubjectKey(subject, arena, &keyitem); - if ( rv != SECSuccess ) { - goto loser; - } - - namekey.data = keyitem.data; - namekey.size = keyitem.len; - - /* lookup in the temporary database */ - ret = certdb_Get(handle->tempCertDB, &namekey, &tmpdata, 0); - - /* error accessing the database */ - if ( ret < 0 ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - if ( ret == 0 ) { /* found in temp database */ - if ( tmpdata.size != sizeof(CERTCertificate *) ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - /* copy pointer out of database */ - PORT_Memcpy(&subjectList, tmpdata.data, tmpdata.size); - } else { /* not found in temporary database */ - entry = ReadDBSubjectEntry(handle, subject); - if ( entry || create ) { - /* decode or create new subject list */ - subjectList = NewSubjectList(entry); - - /* put it in the temp database */ - if ( subjectList ) { - tmpdata.data = (unsigned char *)(&subjectList); - tmpdata.size = sizeof(subjectList); - ret = certdb_Put(handle->tempCertDB, &namekey, - &tmpdata, R_NOOVERWRITE); - if ( ret ) { - goto loser; - } - } - } else { - PORT_SetError(SEC_ERROR_UNKNOWN_CERT); - goto loser; - } - } - - goto done; - -loser: - subjectList = NULL; - -done: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(subjectList); -} - -/* - * Add a temp cert to the temp subject list - */ -static SECStatus -AddTempCertToSubjectList(CERTCertificate *cert) -{ - CERTSubjectList *subjectList; - CERTSubjectNode *node, *newnode; - CERTCertificate *cmpcert; - PRBool newer; - SECStatus rv; - - PORT_Assert(cert->isperm == PR_FALSE); - PORT_Assert(cert->subjectList == NULL); - - subjectList = FindSubjectList(cert->dbhandle, &cert->derSubject, PR_TRUE); - - if ( subjectList == NULL ) { - goto loser; - } - - newnode = (CERTSubjectNode*)PORT_ArenaAlloc(subjectList->arena, - sizeof(CERTSubjectNode)); - /* copy certKey and keyID to node */ - rv = SECITEM_CopyItem(subjectList->arena, &newnode->certKey, - &cert->certKey); - if ( rv != SECSuccess ) { - goto loser; - } - rv = SECITEM_CopyItem(subjectList->arena, &newnode->keyID, - &cert->subjectKeyID); - if ( rv != SECSuccess ) { - goto loser; - } - - node = subjectList->head; - - if ( node ) { - /* list is not empty */ - while ( node ) { - cmpcert = CERT_FindCertByKeyNoLocking(cert->dbhandle, - &node->certKey); - if ( cmpcert ) { - - newer = CERT_IsNewer(cert, cmpcert); - CERT_DestroyCertificateNoLocking(cmpcert); - if ( newer ) { - /* insert before this cert */ - newnode->next = node; - newnode->prev = node->prev; - if ( newnode->prev ) { - newnode->prev->next = newnode; - } else { - /* at the head of the list */ - subjectList->head = newnode; - } - node->prev = newnode; - goto done; - } - } - node = node->next; - } - /* if we get here, we add the node to the end of the list */ - newnode->prev = subjectList->tail; - newnode->next = NULL; - subjectList->tail->next = newnode; - subjectList->tail = newnode; - } else { - /* this is a new/empty list */ - newnode->next = NULL; - newnode->prev = NULL; - subjectList->head = newnode; - subjectList->tail = newnode; - } - -done: - subjectList->ncerts++; - cert->subjectList = subjectList; - return(SECSuccess); - -loser: - return(SECFailure); -} - -/* - * Find the node in a subjectList that belongs a cert - */ -static CERTSubjectNode * -FindCertSubjectNode(CERTCertificate *cert) -{ - CERTSubjectList *subjectList; - CERTSubjectNode *node = NULL; - - PORT_Assert(cert->subjectList); - - subjectList = cert->subjectList; - - if ( subjectList ) { - node = subjectList->head; - } - - while ( node ) { - if ( SECITEM_CompareItem(&node->certKey, &cert->certKey) == SECEqual ){ - return(node); - break; - } - - node = node->next; - } - - return(NULL); -} - -/* - * Remove a temp cert from the temp subject list - */ -static SECStatus -RemoveTempCertFromSubjectList(CERTCertificate *cert) -{ - CERTSubjectList *subjectList; - CERTSubjectNode *node; - SECItem keyitem; - DBT namekey; - SECStatus rv; - int ret; - CERTCertDBHandle *handle; - - PORT_Assert(cert->subjectList); - - /* don't remove perm certs */ - if ( cert->isperm ) { - return(SECSuccess); - } - - subjectList = cert->subjectList; - - node = FindCertSubjectNode(cert); - - if ( node ) { - /* found it, unlink it */ - if ( node->next ) { - node->next->prev = node->prev; - } else { - /* removing from tail of list */ - subjectList->tail = node->prev; - } - if ( node->prev ) { - node->prev->next = node->next; - } else { - /* removing from head of list */ - subjectList->head = node->next; - } - - subjectList->ncerts--; - - /* dont need to free the node, because it is from subjectList - * arena. - */ - - /* remove reference from cert */ - cert->subjectList = NULL; - - /* if the list is now empty, remove the list from the db and free it */ - if ( subjectList->head == NULL ) { - PORT_Assert(subjectList->ncerts == 0); - rv = EncodeDBSubjectKey(&cert->derSubject, subjectList->arena, - &keyitem); - if ( rv == SECSuccess ) { - namekey.data = keyitem.data; - namekey.size = keyitem.len; - - handle = cert->dbhandle; - - ret = certdb_Del(handle->tempCertDB, &namekey, 0); - /* keep going if it fails */ - - if ( cert->dbnickname ) { - rv = SEC_DeleteTempNickname(handle, cert->dbnickname); - } else if ( cert->nickname ) { - rv = SEC_DeleteTempNickname(handle, cert->nickname); - } - - /* keep going if it fails */ - } - - PORT_FreeArena(subjectList->arena, PR_FALSE); - } - } - - PORT_Assert(cert->subjectList == NULL); - - if ( cert->subjectList != NULL ) { - return(SECFailure); - } - - return(SECSuccess); -} - -/* - * cert is no longer a perm cert, but will remain a temp cert - */ -static SECStatus -RemovePermSubjectNode(CERTCertificate *cert) -{ - CERTSubjectList *subjectList; - certDBEntrySubject *entry; - unsigned int i; - SECStatus rv; - - PORT_Assert(cert->isperm); - if ( !cert->isperm ) { - return(SECFailure); - } - - subjectList = cert->subjectList; - PORT_Assert(subjectList); - if ( subjectList == NULL ) { - return(SECFailure); - } - entry = subjectList->entry; - PORT_Assert(entry); - if ( entry == NULL ) { - return(SECFailure); - } - - PORT_Assert(entry->ncerts); - rv = SECFailure; - - if ( entry->ncerts > 1 ) { - for ( i = 0; i < entry->ncerts; i++ ) { - if ( SECITEM_CompareItem(&entry->certKeys[i], &cert->certKey) == - SECEqual ) { - /* copy rest of list forward one entry */ - for ( i = i + 1; i < entry->ncerts; i++ ) { - entry->certKeys[i-1] = entry->certKeys[i]; - entry->keyIDs[i-1] = entry->keyIDs[i]; - } - entry->ncerts--; - DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject); - rv = WriteDBSubjectEntry(cert->dbhandle, entry); - break; - } - } - } else { - /* no entries left, delete the perm entry in the DB */ - if ( subjectList->entry->emailAddr ) { - /* if the subject had an email record, then delete it too */ - DeleteDBSMimeEntry(cert->dbhandle, subjectList->entry->emailAddr); - } - - DestroyDBEntry((certDBEntry *)subjectList->entry); - subjectList->entry = NULL; - DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject); - } - - return(rv); -} - -/* - * add a cert to the perm subject list - */ -static SECStatus -AddPermSubjectNode(CERTCertificate *cert, char *nickname) -{ - CERTSubjectList *subjectList; - certDBEntrySubject *entry; - SECItem *newCertKeys, *newKeyIDs; - int i; - SECStatus rv; - CERTCertificate *cmpcert; - unsigned int nnlen; - int ncerts; - - subjectList = cert->subjectList; - - PORT_Assert(subjectList); - if ( subjectList == NULL ) { - return(SECFailure); - } - - entry = subjectList->entry; - - if ( entry ) { - ncerts = entry->ncerts; - - if ( nickname && entry->nickname ) { - /* nicknames must be the same */ - PORT_Assert(PORT_Strcmp(nickname, entry->nickname) == 0); - } - - if ( ( entry->nickname == NULL ) && ( nickname != NULL ) ) { - /* copy nickname into the entry */ - nnlen = PORT_Strlen(nickname) + 1; - entry->nickname = (char *)PORT_ArenaAlloc(entry->common.arena, - nnlen); - if ( entry->nickname == NULL ) { - return(SECFailure); - } - PORT_Memcpy(entry->nickname, nickname, nnlen); - } - - /* a DB entry already exists, so add this cert */ - newCertKeys = (SECItem *)PORT_ArenaAlloc(entry->common.arena, - sizeof(SECItem) * - ( ncerts + 1 ) ); - newKeyIDs = (SECItem *)PORT_ArenaAlloc(entry->common.arena, - sizeof(SECItem) * - ( ncerts + 1 ) ); - - if ( ( newCertKeys == NULL ) || ( newKeyIDs == NULL ) ) { - return(SECFailure); - } - - for ( i = 0; i < ncerts; i++ ) { - cmpcert = CERT_FindCertByKeyNoLocking(cert->dbhandle, - &entry->certKeys[i]); - PORT_Assert(cmpcert); - - if ( CERT_IsNewer(cert, cmpcert) ) { - /* insert before cmpcert */ - rv = SECITEM_CopyItem(entry->common.arena, &newCertKeys[i], - &cert->certKey); - if ( rv != SECSuccess ) { - return(SECFailure); - } - rv = SECITEM_CopyItem(entry->common.arena, &newKeyIDs[i], - &cert->subjectKeyID); - if ( rv != SECSuccess ) { - return(SECFailure); - } - /* copy the rest of the entry */ - for ( ; i < ncerts; i++ ) { - newCertKeys[i+1] = entry->certKeys[i]; - newKeyIDs[i+1] = entry->keyIDs[i]; - } - - /* update certKeys and keyIDs */ - entry->certKeys = newCertKeys; - entry->keyIDs = newKeyIDs; - - /* increment count */ - entry->ncerts++; - break; - } - /* copy this cert entry */ - newCertKeys[i] = entry->certKeys[i]; - newKeyIDs[i] = entry->keyIDs[i]; - } - - if ( entry->ncerts == ncerts ) { - /* insert new one at end */ - rv = SECITEM_CopyItem(entry->common.arena, &newCertKeys[ncerts], - &cert->certKey); - if ( rv != SECSuccess ) { - return(SECFailure); - } - rv = SECITEM_CopyItem(entry->common.arena, &newKeyIDs[ncerts], - &cert->subjectKeyID); - if ( rv != SECSuccess ) { - return(SECFailure); - } - - /* update certKeys and keyIDs */ - entry->certKeys = newCertKeys; - entry->keyIDs = newKeyIDs; - - /* increment count */ - entry->ncerts++; - } - } else { - /* need to make a new DB entry */ - entry = NewDBSubjectEntry(&cert->derSubject, &cert->certKey, - &cert->subjectKeyID, nickname, - NULL, 0); - cert->subjectList->entry = entry; - } - if ( entry ) { - DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject); - rv = WriteDBSubjectEntry(cert->dbhandle, entry); - } else { - rv = SECFailure; - } - - return(rv); -} - - - -SECStatus -__CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle, - SECItem *derSubject, - CERTCertCallback cb, void *cbarg) -{ - certDBEntrySubject *entry; - int i; - CERTCertificate *cert; - SECStatus rv = SECSuccess; - - entry = ReadDBSubjectEntry(handle, derSubject); - - if ( entry == NULL ) { - return(SECFailure); - } - - for( i = 0; i < entry->ncerts; i++ ) { - cert = CERT_FindCertByKey(handle, &entry->certKeys[i]); - rv = (* cb)(cert, cbarg); - CERT_DestroyCertificate(cert); - if ( rv == SECFailure ) { - break; - } - } - - DestroyDBEntry((certDBEntry *)entry); - - return(rv); -} - -SECStatus -CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle, SECItem *derSubject, - CERTCertCallback cb, void *cbarg) -{ - return(__CERT_TraversePermCertsForSubject(handle, derSubject, cb, cbarg)); -} - -int -CERT_NumPermCertsForSubject(CERTCertDBHandle *handle, SECItem *derSubject) -{ - certDBEntrySubject *entry; - int ret; - - entry = ReadDBSubjectEntry(handle, derSubject); - - if ( entry == NULL ) { - return(SECFailure); - } - - ret = entry->ncerts; - - DestroyDBEntry((certDBEntry *)entry); - - return(ret); -} - -SECStatus -__CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname, - CERTCertCallback cb, void *cbarg) -{ - certDBEntryNickname *nnentry = NULL; - certDBEntrySMime *smentry = NULL; - SECStatus rv; - SECItem *derSubject = NULL; - - nnentry = ReadDBNicknameEntry(handle, nickname); - if ( nnentry ) { - derSubject = &nnentry->subjectName; - } else { - smentry = ReadDBSMimeEntry(handle, nickname); - if ( smentry ) { - derSubject = &smentry->subjectName; - } - } - - if ( derSubject ) { - rv = CERT_TraversePermCertsForSubject(handle, derSubject, - cb, cbarg); - } else { - rv = SECFailure; - } - - if ( nnentry ) { - DestroyDBEntry((certDBEntry *)nnentry); - } - if ( smentry ) { - DestroyDBEntry((certDBEntry *)smentry); - } - - return(rv); -} - -SECStatus -CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname, - CERTCertCallback cb, void *cbarg) -{ - return(__CERT_TraversePermCertsForNickname(handle, nickname, cb, cbarg)); -} - -int -CERT_NumPermCertsForNickname(CERTCertDBHandle *handle, char *nickname) -{ - certDBEntryNickname *entry; - int ret; - - entry = ReadDBNicknameEntry(handle, nickname); - - if ( entry ) { - ret = CERT_NumPermCertsForSubject(handle, &entry->subjectName); - DestroyDBEntry((certDBEntry *)entry); - } else { - ret = 0; - } - return(ret); -} - -int -CERT_NumCertsForCertSubject(CERTCertificate *cert) -{ - int ret = 0; - - if ( cert->subjectList ) { - ret = cert->subjectList->ncerts; - } - return(ret); -} - -int -CERT_NumPermCertsForCertSubject(CERTCertificate *cert) -{ - int ret = 0; - - if ( cert->subjectList ) { - if ( cert->subjectList->entry ) { - ret = cert->subjectList->entry->ncerts; - } - } - return(ret); -} - -SECStatus -CERT_TraverseCertsForSubject(CERTCertDBHandle *handle, - CERTSubjectList *subjectList, - CERTCertCallback cb, void *cbarg) -{ - CERTSubjectNode *node; - CERTCertificate *cert; - SECStatus rv = SECSuccess; - - CERT_LockDB(handle); - - node = subjectList->head; - while ( node ) { - - cert = CERT_FindCertByKeyNoLocking(handle, &node->certKey); - - PORT_Assert(cert != NULL); - - if ( cert != NULL ) { - rv = (* cb)(cert, cbarg); - CERT_DestroyCertificateNoLocking(cert); - if ( rv == SECFailure ) { - break; - } - } - - node = node->next; - } - - CERT_UnlockDB(handle); - - return(rv); -} - - -/* - * Given a cert, find the cert with the same subject name that - * has the given key usage. If the given cert has the correct keyUsage, then - * return it, otherwise search the list in order. - */ -CERTCertificate * -CERT_FindCertByUsage(CERTCertificate *basecert, unsigned int requiredKeyUsage) -{ - CERTSubjectNode *node; - CERTCertificate *cert; - CERTSubjectList *subjectList; - - if ( ( basecert->keyUsage & requiredKeyUsage ) == requiredKeyUsage ) { - return(CERT_DupCertificate(basecert)); - } - - CERT_LockDB(basecert->dbhandle); - - subjectList = basecert->subjectList; - - node = subjectList->head; - while ( node ) { - - cert = CERT_FindCertByKeyNoLocking(basecert->dbhandle, &node->certKey); - - PORT_Assert(cert != NULL); - - if ( cert != NULL ) { - if ( ( cert->keyUsage & requiredKeyUsage ) == - requiredKeyUsage ) { - CERT_UnlockDB(basecert->dbhandle); - return(cert); - } - - CERT_DestroyCertificateNoLocking(cert); - } - - node = node->next; - } - - CERT_UnlockDB(basecert->dbhandle); - - return(NULL); -} - - -/* - * add a nickname to a cert that doesn't have one - */ -static SECStatus -AddNicknameToPermCert(CERTCertificate *cert, char *nickname) -{ - certDBEntryCert *entry; - int rv; - - PORT_Assert(cert->isperm); - if ( !cert->isperm ) { - goto loser; - } - - entry = cert->dbEntry; - PORT_Assert(entry != NULL); - if ( entry == NULL ) { - goto loser; - } - - entry->nickname = PORT_ArenaStrdup(entry->common.arena, nickname); - - rv = WriteDBCertEntry(cert->dbhandle, entry); - if ( rv ) { - goto loser; - } - - cert->nickname = PORT_ArenaStrdup(cert->arena, nickname); - return(SECSuccess); - -loser: - return(SECFailure); -} - -/* - * add a nickname to a cert that is already in the perm database, but doesn't - * have one yet (it is probably an e-mail cert). - */ -SECStatus -CERT_AddPermNickname(CERTCertificate *cert, char *nickname) -{ - SECStatus rv; - - CERT_LockDB(cert->dbhandle); - - PORT_Assert(cert->nickname == NULL); - PORT_Assert(cert->isperm); - PORT_Assert(cert->subjectList != NULL); - PORT_Assert(cert->subjectList->entry != NULL); - - if ( cert->nickname != NULL ) { - goto done; - } - - if ( cert->subjectList == NULL ) { - goto loser; - } - - if ( cert->subjectList->entry == NULL ) { - goto loser; - } - - if ( cert->subjectList->entry->nickname == NULL ) { - /* no nickname for subject */ - rv = AddNicknameToSubject(cert, nickname); - if ( rv != SECSuccess ) { - goto loser; - } - rv = AddNicknameToPermCert(cert, nickname); - if ( rv != SECSuccess ) { - goto loser; - } - rv = SEC_AddTempNickname(cert->dbhandle, nickname, - &cert->derSubject); - if ( rv != SECSuccess ) { - goto loser; - } - - } else { - /* subject already has a nickname */ - rv = AddNicknameToPermCert(cert, cert->subjectList->entry->nickname); - if ( rv != SECSuccess ) { - goto loser; - } - } - -done: - CERT_UnlockDB(cert->dbhandle); - return(SECSuccess); -loser: - CERT_UnlockDB(cert->dbhandle); - return(SECFailure); -} - -static certDBEntryCert * -AddCertToPermDB(CERTCertDBHandle *handle, CERTCertificate *cert, - char *nickname, CERTCertTrust *trust) -{ - certDBEntryCert *certEntry = NULL; - certDBEntryNickname *nicknameEntry = NULL; - certDBEntrySubject *subjectEntry = NULL; - int state = 0; - SECStatus rv; - PRBool donnentry = PR_FALSE; - - if ( nickname ) { - donnentry = PR_TRUE; - } - - if ( cert->subjectList != NULL ) { - if ( cert->subjectList->entry != NULL ) { - if ( cert->subjectList->entry->ncerts > 0 ) { - /* of other certs with same subject exist, then they already - * have a nickname, so don't add a new one. - */ - donnentry = PR_FALSE; - nickname = cert->subjectList->entry->nickname; - } - } - } - - certEntry = NewDBCertEntry(&cert->derCert, nickname, trust, 0); - if ( certEntry == NULL ) { - goto loser; - } - - if ( donnentry ) { - nicknameEntry = NewDBNicknameEntry(nickname, &cert->derSubject, 0); - if ( nicknameEntry == NULL ) { - goto loser; - } - } - - rv = WriteDBCertEntry(handle, certEntry); - if ( rv != SECSuccess ) { - goto loser; - } - state = 1; - - if ( nicknameEntry ) { - rv = WriteDBNicknameEntry(handle, nicknameEntry); - if ( rv != SECSuccess ) { - goto loser; - } - } - - state = 2; - - /* add to or create new subject entry */ - if ( cert->subjectList ) { - rv = AddPermSubjectNode(cert, nickname); - if ( rv != SECSuccess ) { - goto loser; - } - } else { - /* make a new subject entry - this case is only used when updating - * an old version of the database. This is OK because the oldnickname - * db format didn't allow multiple certs with the same subject. - */ - subjectEntry = NewDBSubjectEntry(&cert->derSubject, &cert->certKey, - &cert->subjectKeyID, nickname, - NULL, 0); - if ( subjectEntry == NULL ) { - goto loser; - } - rv = WriteDBSubjectEntry(handle, subjectEntry); - if ( rv != SECSuccess ) { - goto loser; - } - } - - state = 3; - - if ( nicknameEntry ) { - DestroyDBEntry((certDBEntry *)nicknameEntry); - } - - if ( subjectEntry ) { - DestroyDBEntry((certDBEntry *)subjectEntry); - } - - return(certEntry); - -loser: - /* don't leave partial entry in the database */ - if ( state > 0 ) { - rv = DeleteDBCertEntry(handle, &cert->certKey); - } - if ( ( state > 1 ) && donnentry ) { - rv = DeleteDBNicknameEntry(handle, nickname); - } - if ( state > 2 ) { - rv = DeleteDBSubjectEntry(handle, &cert->derSubject); - } - if ( certEntry ) { - DestroyDBEntry((certDBEntry *)certEntry); - } - if ( nicknameEntry ) { - DestroyDBEntry((certDBEntry *)nicknameEntry); - } - if ( subjectEntry ) { - DestroyDBEntry((certDBEntry *)subjectEntry); - } - - return(NULL); -} - -/* - * NOTE - Version 6 DB did not go out to the real world in a release, - * so we can remove this function in a later release. - */ -static SECStatus -UpdateV6DB(CERTCertDBHandle *handle, DB *updatedb) -{ - int ret; - DBT key, data; - unsigned char *buf, *tmpbuf = NULL; - certDBEntryType type; - certDBEntryNickname *nnEntry = NULL; - certDBEntrySubject *subjectEntry = NULL; - certDBEntrySMime *emailEntry = NULL; - char *nickname; - char *emailAddr; - SECStatus rv; - - /* - * Sequence through the old database and copy all of the entries - * to the new database. Subject name entries will have the new - * fields inserted into them (with zero length). - */ - ret = (* updatedb->seq)(updatedb, &key, &data, R_FIRST); - if ( ret ) { - return(SECFailure); - } - - do { - buf = (unsigned char *)data.data; - - if ( data.size >= 3 ) { - if ( buf[0] == 6 ) { /* version number */ - type = (certDBEntryType)buf[1]; - if ( type == certDBEntryTypeSubject ) { - /* expando subjecto entrieo */ - tmpbuf = (unsigned char *)PORT_Alloc(data.size + 4); - if ( tmpbuf ) { - /* copy header stuff */ - PORT_Memcpy(tmpbuf, buf, SEC_DB_ENTRY_HEADER_LEN + 2); - /* insert 4 more bytes of zero'd header */ - PORT_Memset(&tmpbuf[SEC_DB_ENTRY_HEADER_LEN + 2], - 0, 4); - /* copy rest of the data */ - PORT_Memcpy(&tmpbuf[SEC_DB_ENTRY_HEADER_LEN + 6], - &buf[SEC_DB_ENTRY_HEADER_LEN + 2], - data.size - (SEC_DB_ENTRY_HEADER_LEN + 2)); - - data.data = (void *)tmpbuf; - data.size += 4; - buf = tmpbuf; - } - } else if ( type == certDBEntryTypeCert ) { - /* expando certo entrieo */ - tmpbuf = (unsigned char *)PORT_Alloc(data.size + 3); - if ( tmpbuf ) { - /* copy header stuff */ - PORT_Memcpy(tmpbuf, buf, SEC_DB_ENTRY_HEADER_LEN); - - /* copy trust flage, setting msb's to 0 */ - tmpbuf[SEC_DB_ENTRY_HEADER_LEN] = 0; - tmpbuf[SEC_DB_ENTRY_HEADER_LEN+1] = - buf[SEC_DB_ENTRY_HEADER_LEN]; - tmpbuf[SEC_DB_ENTRY_HEADER_LEN+2] = 0; - tmpbuf[SEC_DB_ENTRY_HEADER_LEN+3] = - buf[SEC_DB_ENTRY_HEADER_LEN+1]; - tmpbuf[SEC_DB_ENTRY_HEADER_LEN+4] = 0; - tmpbuf[SEC_DB_ENTRY_HEADER_LEN+5] = - buf[SEC_DB_ENTRY_HEADER_LEN+2]; - - /* copy rest of the data */ - PORT_Memcpy(&tmpbuf[SEC_DB_ENTRY_HEADER_LEN + 6], - &buf[SEC_DB_ENTRY_HEADER_LEN + 3], - data.size - (SEC_DB_ENTRY_HEADER_LEN + 3)); - - data.data = (void *)tmpbuf; - data.size += 3; - buf = tmpbuf; - } - - } - - /* update the record version number */ - buf[0] = CERT_DB_FILE_VERSION; - - /* copy to the new database */ - ret = certdb_Put(handle->permCertDB, &key, &data, 0); - if ( tmpbuf ) { - PORT_Free(tmpbuf); - tmpbuf = NULL; - } - } - } - } while ( (* updatedb->seq)(updatedb, &key, &data, R_NEXT) == 0 ); - - ret = certdb_Sync(handle->permCertDB, 0); - - ret = (* updatedb->seq)(updatedb, &key, &data, R_FIRST); - if ( ret ) { - return(SECFailure); - } - - do { - buf = (unsigned char *)data.data; - - if ( data.size >= 3 ) { - if ( buf[0] == CERT_DB_FILE_VERSION ) { /* version number */ - type = (certDBEntryType)buf[1]; - if ( type == certDBEntryTypeNickname ) { - nickname = &((char *)key.data)[1]; - - /* get the matching nickname entry in the new DB */ - nnEntry = ReadDBNicknameEntry(handle, nickname); - if ( nnEntry == NULL ) { - goto endloop; - } - - /* find the subject entry pointed to by nickname */ - subjectEntry = ReadDBSubjectEntry(handle, - &nnEntry->subjectName); - if ( subjectEntry == NULL ) { - goto endloop; - } - - subjectEntry->nickname = - (char *)PORT_ArenaAlloc(subjectEntry->common.arena, - key.size - 1); - if ( subjectEntry->nickname ) { - PORT_Memcpy(subjectEntry->nickname, nickname, - key.size - 1); - rv = WriteDBSubjectEntry(handle, subjectEntry); - } - } else if ( type == certDBEntryTypeSMimeProfile ) { - emailAddr = &((char *)key.data)[1]; - - /* get the matching smime entry in the new DB */ - emailEntry = ReadDBSMimeEntry(handle, emailAddr); - if ( emailEntry == NULL ) { - goto endloop; - } - - /* find the subject entry pointed to by nickname */ - subjectEntry = ReadDBSubjectEntry(handle, - &emailEntry->subjectName); - if ( subjectEntry == NULL ) { - goto endloop; - } - - subjectEntry->nickname = - (char *)PORT_ArenaAlloc(subjectEntry->common.arena, - key.size - 1); - if ( subjectEntry->emailAddr ) { - PORT_Memcpy(subjectEntry->emailAddr, emailAddr, - key.size - 1); - rv = WriteDBSubjectEntry(handle, subjectEntry); - } - } - -endloop: - if ( subjectEntry ) { - DestroyDBEntry((certDBEntry *)subjectEntry); - subjectEntry = NULL; - } - if ( nnEntry ) { - DestroyDBEntry((certDBEntry *)nnEntry); - nnEntry = NULL; - } - if ( emailEntry ) { - DestroyDBEntry((certDBEntry *)emailEntry); - emailEntry = NULL; - } - } - } - } while ( (* updatedb->seq)(updatedb, &key, &data, R_NEXT) == 0 ); - - ret = certdb_Sync(handle->permCertDB, 0); - - (* updatedb->close)(updatedb); - return(SECSuccess); -} - - -static SECStatus -updateV5Callback(CERTCertificate *cert, SECItem *k, void *pdata) -{ - CERTCertDBHandle *handle; - certDBEntryCert *entry; - CERTCertTrust *trust; - - handle = (CERTCertDBHandle *)pdata; - trust = &cert->dbEntry->trust; - - /* SSL user certs can be used for email if they have an email addr */ - if ( cert->emailAddr && ( trust->sslFlags & CERTDB_USER ) && - ( trust->emailFlags == 0 ) ) { - trust->emailFlags = CERTDB_USER; - } - /* servers didn't set the user flags on the server cert.. */ - if (PORT_Strcmp(cert->dbEntry->nickname,"Server-Cert") == 0) { - trust->sslFlags |= CERTDB_USER; - } - - entry = AddCertToPermDB(handle, cert, cert->dbEntry->nickname, - &cert->dbEntry->trust); - if ( entry ) { - DestroyDBEntry((certDBEntry *)entry); - } - - return(SECSuccess); -} - -static SECStatus -UpdateV5DB(CERTCertDBHandle *handle, DB *updatedb) -{ - CERTCertDBHandle updatehandle; - SECStatus rv; - - updatehandle.permCertDB = updatedb; - updatehandle.dbMon = PZ_NewMonitor(nssILockCertDB); - - rv = SEC_TraversePermCerts(&updatehandle, updateV5Callback, - (void *)handle); - - PZ_DestroyMonitor(updatehandle.dbMon); - - (* updatedb->close)(updatedb); - return(SECSuccess); -} - -static PRBool -isV4DB(DB *db) { - DBT key,data; - int ret; - - key.data = "Version"; - key.size = 7; - - ret = (*db->get)(db, &key, &data, 0); - if (ret) { - return PR_FALSE; - } - - if ((data.size == 1) && (*(unsigned char *)data.data <= 4)) { - return PR_TRUE; - } - - return PR_FALSE; -} - -static SECStatus -UpdateV4DB(CERTCertDBHandle *handle, DB *updatedb) -{ - DBT key, data; - certDBEntryCert *entry, *entry2; - SECItem derSubject; - int ret; - PRArenaPool *arena = NULL; - CERTCertificate *cert; - - ret = (* updatedb->seq)(updatedb, &key, &data, R_FIRST); - - if ( ret ) { - return(SECFailure); - } - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) { - return(SECFailure); - } - - do { - if ( data.size != 1 ) { /* skip version number */ - - /* decode the old DB entry */ - entry = (certDBEntryCert *)DecodeV4DBCertEntry((unsigned char*)data.data, data.size); - derSubject.data = NULL; - - if ( entry ) { - cert = CERT_DecodeDERCertificate(&entry->derCert, PR_TRUE, - entry->nickname); - - if ( cert != NULL ) { - /* add to new database */ - entry2 = AddCertToPermDB(handle, cert, entry->nickname, - &entry->trust); - - CERT_DestroyCertificate(cert); - if ( entry2 ) { - DestroyDBEntry((certDBEntry *)entry2); - } - } - DestroyDBEntry((certDBEntry *)entry); - } - } - } while ( (* updatedb->seq)(updatedb, &key, &data, R_NEXT) == 0 ); - - PORT_FreeArena(arena, PR_FALSE); - (* updatedb->close)(updatedb); - return(SECSuccess); -} - -/* - * return true if a database key conflict exists - */ -PRBool -SEC_CertDBKeyConflict(SECItem *derCert, CERTCertDBHandle *handle) -{ - SECStatus rv; - DBT tmpdata; - DBT namekey; - int ret; - SECItem keyitem; - PRArenaPool *arena = NULL; - SECItem derKey; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - /* get the db key of the cert */ - rv = CERT_KeyFromDERCert(arena, derCert, &derKey); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = EncodeDBCertKey(&derKey, arena, &keyitem); - if ( rv != SECSuccess ) { - goto loser; - } - - namekey.data = keyitem.data; - namekey.size = keyitem.len; - - /* lookup in the temporary database */ - ret = certdb_Get(handle->tempCertDB, &namekey, &tmpdata, 0); - - if ( ret == 0 ) { /* found in temp database */ - goto loser; - } else { /* not found in temporary database */ - ret = certdb_Get(handle->permCertDB, &namekey, &tmpdata, 0); - if ( ret == 0 ) { - goto loser; - } - } - - PORT_FreeArena(arena, PR_FALSE); - - return(PR_FALSE); -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(PR_TRUE); -} - -#ifdef NOTDEF -/* - * return true if a subject name conflict exists - * NOTE: caller must have already made sure that this exact cert - * doesn't exist in the DB - */ -PRBool -SEC_CertSubjectConflict(SECItem *derCert, CERTCertDBHandle *handle) -{ - SECStatus rv; - DBT tmpdata; - DBT namekey; - int ret; - SECItem keyitem; - PRArenaPool *arena = NULL; - SECItem derName; - - derName.data = NULL; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - /* get the subject name of the cert */ - rv = CERT_NameFromDERCert(derCert, &derName); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = EncodeDBSubjectKey(&derName, arena, &keyitem); - if ( rv != SECSuccess ) { - goto loser; - } - - namekey.data = keyitem.data; - namekey.size = keyitem.len; - - /* lookup in the temporary database */ - ret = certdb_Get(handle->tempCertDB, &namekey, &tmpdata, 0); - - if ( ret == 0 ) { /* found in temp database */ - return(PR_TRUE); - } else { /* not found in temporary database */ - ret = certdb_Get(handle->permCertDB, &namekey, &tmpdata, 0); - if ( ret == 0 ) { - return(PR_TRUE); - } - } - - PORT_FreeArena(arena, PR_FALSE); - PORT_Free(derName.data); - - return(PR_FALSE); -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - if ( derName.data ) { - PORT_Free(derName.data); - } - - return(PR_TRUE); -} -#endif - -/* - * return true if a nickname conflict exists - * NOTE: caller must have already made sure that this exact cert - * doesn't exist in the DB - */ -PRBool -SEC_CertNicknameConflict(char *nickname, SECItem *derSubject, - CERTCertDBHandle *handle) -{ - PRBool rv; - certDBEntryNickname *entry; - - if ( nickname == NULL ) { - return(PR_FALSE); - } - - entry = ReadDBNicknameEntry(handle, nickname); - - if ( entry == NULL ) { - /* no entry for this nickname, so no conflict */ - return(PR_FALSE); - } - - rv = PR_TRUE; - if ( SECITEM_CompareItem(derSubject, &entry->subjectName) == SECEqual ) { - /* if subject names are the same, then no conflict */ - rv = PR_FALSE; - } - - DestroyDBEntry((certDBEntry *)entry); - return(rv); -} - -/* - * Open the certificate database and index databases. Create them if - * they are not there or bad. - */ -SECStatus -SEC_OpenPermCertDB(CERTCertDBHandle *handle, PRBool readOnly, - CERTDBNameFunc namecb, void *cbarg) -{ - SECStatus rv; - int openflags; - certDBEntryVersion *versionEntry = NULL; - DB *updatedb = NULL; - char *tmpname; - char *certdbname; - PRBool updated = PR_FALSE; - PRBool forceUpdate = PR_FALSE; - - certdbname = (* namecb)(cbarg, CERT_DB_FILE_VERSION); - if ( certdbname == NULL ) { - return(SECFailure); - } - - if ( readOnly ) { - openflags = O_RDONLY; - } else { - openflags = O_RDWR; - } - - /* - * first open the permanent file based database. - */ - handle->permCertDB = dbopen( certdbname, openflags, 0600, DB_HASH, 0 ); - - /* check for correct version number */ - if ( handle->permCertDB ) { - versionEntry = ReadDBVersionEntry(handle); - - if ( versionEntry == NULL ) { - /* no version number */ - certdb_Close(handle->permCertDB); - handle->permCertDB = 0; - } else if ( versionEntry->common.version != CERT_DB_FILE_VERSION ) { - /* wrong version number, can't update in place */ - DestroyDBEntry((certDBEntry *)versionEntry); - PORT_Free(certdbname); - return(SECFailure); - } else { - DestroyDBEntry((certDBEntry *)versionEntry); - versionEntry = NULL; - } - } - - - /* if first open fails, try to create a new DB */ - if ( handle->permCertDB == NULL ) { - - /* don't create if readonly */ - if ( readOnly ) { - goto loser; - } - - handle->permCertDB = dbopen(certdbname, - O_RDWR | O_CREAT | O_TRUNC, - 0600, DB_HASH, 0); - - /* if create fails then we lose */ - if ( handle->permCertDB == 0 ) { - goto loser; - } - - versionEntry = NewDBVersionEntry(0); - if ( versionEntry == NULL ) { - goto loser; - } - - rv = WriteDBVersionEntry(handle, versionEntry); - - DestroyDBEntry((certDBEntry *)versionEntry); - - if ( rv != SECSuccess ) { - goto loser; - } - - /* try to upgrade old db here */ - tmpname = (* namecb)(cbarg, 6); /* get v6 db name */ - if ( tmpname ) { - updatedb = dbopen( tmpname, O_RDONLY, 0600, DB_HASH, 0 ); - PORT_Free(tmpname); - if ( updatedb ) { - rv = UpdateV6DB(handle, updatedb); - if ( rv != SECSuccess ) { - goto loser; - } - updated = PR_TRUE; - } else { /* no v6 db, so try v5 db */ - tmpname = (* namecb)(cbarg, 5); /* get v5 db name */ - if ( tmpname ) { - updatedb = dbopen( tmpname, O_RDONLY, 0600, DB_HASH, 0 ); - PORT_Free(tmpname); - if ( updatedb ) { - rv = UpdateV5DB(handle, updatedb); - if ( rv != SECSuccess ) { - goto loser; - } - updated = PR_TRUE; - } else { /* no v5 db, so try v4 db */ - /* try to upgrade v4 db */ - tmpname = (* namecb)(cbarg, 4); /* get v4 db name */ - if ( tmpname ) { - updatedb = dbopen( tmpname, O_RDONLY, 0600, - DB_HASH, 0 ); - PORT_Free(tmpname); - if ( updatedb ) { - /* NES has v5 db's with v4 db names! */ - if (isV4DB(updatedb)) { - rv = UpdateV4DB(handle, updatedb); - } else { - rv = UpdateV5DB(handle, updatedb); - } - if ( rv != SECSuccess ) { - goto loser; - } - forceUpdate = PR_TRUE; - updated = PR_TRUE; - } - } - } - } - } - } - - /* initialize the database with our well known certificates - * or in the case of update, just fall down to CERT_AddNewCerts() - * below. - * Note - if we are updating a really old database, then we try - * to push all of the certs into it. - */ - if ( ( !updated ) || forceUpdate ) { - rv = CERT_InitCertDB(handle); - if ( rv != SECSuccess ) { - goto loser; - } - } - } - - rv = CERT_AddNewCerts(handle); - - PORT_Free(certdbname); - - return (SECSuccess); - -loser: - - PORT_SetError(SEC_ERROR_BAD_DATABASE); - - if ( handle->permCertDB ) { - certdb_Close(handle->permCertDB); - handle->permCertDB = 0; - } - - PORT_Free(certdbname); - - return(SECFailure); -} - -/* - * delete all DB records associated with a particular certificate - */ -static SECStatus -DeletePermCert(CERTCertificate *cert) -{ - SECStatus rv; - SECStatus ret; - - ret = SECSuccess; - - rv = DeleteDBCertEntry(cert->dbhandle, &cert->certKey); - if ( rv != SECSuccess ) { - ret = SECFailure; - } - - if ( cert->nickname ) { - rv = DeleteDBNicknameEntry(cert->dbhandle, cert->nickname); - if ( rv != SECSuccess ) { - ret = SECFailure; - } - } - - rv = RemovePermSubjectNode(cert); - - return(ret); -} - -/* - * Delete a certificate from the permanent database. - */ -SECStatus -SEC_DeletePermCertificate(CERTCertificate *cert) -{ - SECStatus rv; - - if ( !cert->isperm ) { - return(SECSuccess); - } - CERT_LockDB(cert->dbhandle); - /* delete the records from the permanent database */ - rv = DeletePermCert(cert); - - /* no longer permanent */ - cert->isperm = PR_FALSE; - - /* get rid of dbcert and stuff pointing to it */ - DestroyDBEntry((certDBEntry *)cert->dbEntry); - cert->dbEntry = NULL; - cert->trust = NULL; - - /* delete it from the temporary database too. It will remain in - * memory until all references go away. - */ - if (cert->slot) { - /* If it's owned by a PKCS #11 slot, don't deleted if from the temp DB just - * yet... rv inherited from DeletePermCert (as if anyone checks the return - * code from this function anyway. */ - CERT_DestroyCertificateNoLocking(cert); - rv = SECSuccess; - } else { - rv = CERT_DeleteTempCertificate(cert); - } - - CERT_UnlockDB(cert->dbhandle); - return(rv); -} - -/* - * Lookup a certificate in the databases. - */ -certDBEntryCert * -SEC_FindPermCertByKey(CERTCertDBHandle *handle, SECItem *key) -{ - return(ReadDBCertEntry(handle, key)); -} - -/* - * Lookup a certificate in the database by name - */ -certDBEntryCert * -SEC_FindPermCertByName(CERTCertDBHandle *handle, SECItem *derSubject) -{ - certDBEntrySubject *subjectEntry; - certDBEntryCert *certEntry; - - subjectEntry = ReadDBSubjectEntry(handle, derSubject); - - if ( subjectEntry == NULL ) { - goto loser; - } - - certEntry = ReadDBCertEntry(handle, &subjectEntry->certKeys[0]); - DestroyDBEntry((certDBEntry *)subjectEntry); - - return(certEntry); - -loser: - return(NULL); -} - -/* - * Lookup a certificate in the database by nickname - */ -certDBEntryCert * -SEC_FindPermCertByNickname(CERTCertDBHandle *handle, char *nickname) -{ - certDBEntryNickname *nicknameEntry; - certDBEntryCert *certEntry; - - nicknameEntry = ReadDBNicknameEntry(handle, nickname); - - if ( nicknameEntry == NULL ) { - goto loser; - } - - certEntry = SEC_FindPermCertByName(handle, &nicknameEntry->subjectName); - DestroyDBEntry((certDBEntry *)nicknameEntry); - - return(certEntry); - -loser: - return(NULL); -} - -/* - * Traverse all of the entries in the database of a particular type - * call the given function for each one. - */ -SECStatus -SEC_TraverseDBEntries(CERTCertDBHandle *handle, - certDBEntryType type, - SECStatus (* callback)(SECItem *data, SECItem *key, - certDBEntryType type, void *pdata), - void *udata ) -{ - DBT data; - DBT key; - SECStatus rv; - int ret; - SECItem dataitem; - SECItem keyitem; - unsigned char *buf; - unsigned char *keybuf; - - ret = certdb_Seq(handle->permCertDB, &key, &data, R_FIRST); - - if ( ret ) { - return(SECFailure); - } - - do { - buf = (unsigned char *)data.data; - - if ( buf[1] == (unsigned char)type ) { - dataitem.len = data.size; - dataitem.data = buf; - dataitem.type = siBuffer; - keyitem.len = key.size - SEC_DB_KEY_HEADER_LEN; - keybuf = (unsigned char *)key.data; - keyitem.data = &keybuf[SEC_DB_KEY_HEADER_LEN]; - keyitem.type = siBuffer; - - rv = (* callback)(&dataitem, &keyitem, type, udata); - if ( rv != SECSuccess ) { - return(rv); - } - } - } while ( certdb_Seq(handle->permCertDB, &key, &data, R_NEXT) == 0 ); - - return(SECSuccess); -} - -typedef struct { - PermCertCallback certfunc; - CERTCertDBHandle *handle; - void *data; -} PermCertCallbackState; - -/* - * traversal callback to decode certs and call callers callback - */ -static SECStatus -certcallback(SECItem *dbdata, SECItem *dbkey, certDBEntryType type, void *data) -{ - PermCertCallbackState *mystate; - SECStatus rv; - certDBEntryCert entry; - SECItem entryitem; - CERTCertificate *cert; - PRArenaPool *arena = NULL; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - mystate = (PermCertCallbackState *)data; - entry.common.version = (unsigned int)dbdata->data[0]; - entry.common.type = (certDBEntryType)dbdata->data[1]; - entry.common.flags = (unsigned int)dbdata->data[2]; - entry.common.arena = arena; - - entryitem.len = dbdata->len - SEC_DB_ENTRY_HEADER_LEN; - entryitem.data = &dbdata->data[SEC_DB_ENTRY_HEADER_LEN]; - - rv = DecodeDBCertEntry(&entry, &entryitem); - if (rv != SECSuccess ) { - goto loser; - } - entry.derCert.type = siBuffer; - - cert = CERT_DecodeDERCertificate(&entry.derCert, PR_FALSE, - entry.nickname); - cert->dbEntry = &entry; - cert->trust = &entry.trust; - cert->dbhandle = mystate->handle; - - if ( CERT_IsCACert(cert, NULL) || - (( cert->trust->sslFlags & CERTDB_VALID_CA ) || - ( cert->trust->emailFlags & CERTDB_VALID_CA ) || - ( cert->trust->objectSigningFlags & CERTDB_VALID_CA)) ) { - cert->nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER; - } - - rv = (* mystate->certfunc)(cert, dbkey, mystate->data); - - /* arena destroyed by SEC_DestroyCert */ - CERT_DestroyCertificateNoLocking(cert); - - return(rv); - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - return(SECFailure); -} - -/* - * Traverse all of the certificates in the permanent database and - * call the given function for each one; expect the caller to have lock. - */ -static SECStatus -TraversePermCertsNoLocking(CERTCertDBHandle *handle, - SECStatus (* certfunc)(CERTCertificate *cert, - SECItem *k, - void *pdata), - void *udata ) -{ - SECStatus rv; - PermCertCallbackState mystate; - - mystate.certfunc = certfunc; - mystate.handle = handle; - mystate.data = udata; - rv = SEC_TraverseDBEntries(handle, certDBEntryTypeCert, certcallback, - (void *)&mystate); - - return(rv); -} - -/* - * Traverse all of the certificates in the permanent database and - * call the given function for each one. - */ -SECStatus -SEC_TraversePermCerts(CERTCertDBHandle *handle, - SECStatus (* certfunc)(CERTCertificate *cert, SECItem *k, - void *pdata), - void *udata ) -{ - SECStatus rv; - - CERT_LockDB(handle); - rv = TraversePermCertsNoLocking(handle, certfunc, udata); - CERT_UnlockDB(handle); - - return(rv); -} - - - -/* - * Close the database - */ -void -__CERT_ClosePermCertDB(CERTCertDBHandle *handle) -{ - if ( handle ) { - if ( handle->permCertDB ) { - if ( handle->statusConfig ) { - PORT_Assert(handle->statusConfig->statusDestroy != NULL); - (void) (* handle->statusConfig->statusDestroy)(handle->statusConfig); - handle->statusConfig = NULL; /* Destroy frees the structure */ - PORT_Assert(handle->statusConfig == NULL); - } - certdb_Close( handle->permCertDB ); - handle->permCertDB = 0; - } - } - return; -} - -void -CERT_ClosePermCertDB(CERTCertDBHandle *handle) -{ - __CERT_ClosePermCertDB(handle); -} - -/* - * Get the trust attributes from a certificate - */ -SECStatus -CERT_GetCertTrust(CERTCertificate *cert, CERTCertTrust *trust) -{ - SECStatus rv; - - CERT_LockCertTrust(cert); - - if ( cert->trust == NULL ) { - rv = SECFailure; - } else { - *trust = *cert->trust; - rv = SECSuccess; - } - - CERT_UnlockCertTrust(cert); - return(rv); -} - -static char * -cert_parseNickname(char *nickname) -{ - char *cp; - - for (cp=nickname; *cp && *cp != ':'; cp++); - - if (*cp == ':') return cp+1; - return nickname; -} - -/* - * Change the trust attributes of a certificate and make them permanent - * in the database. - */ -SECStatus -CERT_ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert, - CERTCertTrust *trust) -{ - certDBEntryCert *entry; - int rv; - SECStatus ret; - - CERT_LockDB(handle); - CERT_LockCertTrust(cert); - /* only set the trust on permanent certs */ - if ( cert->trust == NULL ) { - ret = SECFailure; - goto done; - } - - *cert->trust = *trust; - if ( cert->dbEntry == NULL ) { - ret = SECSuccess; /* not in permanent database */ - if ((cert->slot) && PK11_IsReadOnly(cert->slot)) { - char *nickname = cert_parseNickname(cert->nickname); - ret = CERT_AddTempCertToPerm(cert, nickname, trust); - } - goto done; - } - - entry = cert->dbEntry; - entry->trust = *trust; - - rv = WriteDBCertEntry(handle, entry); - if ( rv ) { - ret = SECFailure; - goto done; - } - - ret = SECSuccess; - -done: - CERT_UnlockCertTrust(cert); - CERT_UnlockDB(handle); - return(ret); -} - - -SECStatus -CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, - CERTCertTrust *trust) -{ - char *oldnn; - certDBEntryCert *entry; - SECStatus rv; - PRBool conflict; - SECStatus ret; - - PORT_Assert(cert->dbhandle); - - CERT_LockDB(cert->dbhandle); - - PORT_Assert(cert->istemp); - PORT_Assert(!cert->isperm); - PORT_Assert(!cert->dbEntry); - - /* don't add a conflicting nickname */ - conflict = SEC_CertNicknameConflict(nickname, &cert->derSubject, - cert->dbhandle); - if ( conflict ) { - ret = SECFailure; - goto done; - } - - /* save old nickname so that we can delete it */ - oldnn = cert->nickname; - - entry = AddCertToPermDB(cert->dbhandle, cert, nickname, trust); - - if ( entry == NULL ) { - ret = SECFailure; - goto done; - } - - cert->nickname = (entry->nickname) ? PORT_ArenaStrdup(cert->arena,entry->nickname) : NULL; - cert->trust = &entry->trust; - cert->isperm = PR_TRUE; - cert->dbEntry = entry; - - if ( nickname && oldnn && ( PORT_Strcmp(nickname, oldnn) != 0 ) ) { - /* only delete the old one if they are not the same */ - /* delete old nickname from temp database */ - rv = SEC_DeleteTempNickname(cert->dbhandle, oldnn); - if ( rv != SECSuccess ) { - /* do we care?? */ - } - } - /* add new nickname to temp database */ - if ( cert->nickname ) { - rv = SEC_AddTempNickname(cert->dbhandle, cert->nickname, - &cert->derSubject); - if ( rv != SECSuccess ) { - ret = SECFailure; - goto done; - } - } - - ret = SECSuccess; -done: - CERT_UnlockDB(cert->dbhandle); - return(ret); -} - -/* - * Open the certificate database and index databases. Create them if - * they are not there or bad. - */ -SECStatus -CERT_OpenCertDB(CERTCertDBHandle *handle, PRBool readOnly, - CERTDBNameFunc namecb, void *cbarg) -{ - int rv; -#define DBM_DEFAULT 0 - static const HASHINFO hashInfo = { - DBM_DEFAULT, /* bucket size */ - DBM_DEFAULT, /* fill factor */ - DBM_DEFAULT, /* number of elements */ - 256 * 1024, /* bytes to cache */ - DBM_DEFAULT, /* hash function */ - DBM_DEFAULT /* byte order */ - }; - - certdb_InitDBLock(); - - handle->dbMon = PZ_NewMonitor(nssILockCertDB); - PORT_Assert(handle->dbMon != NULL); - - handle->spkDigestInfo = NULL; - handle->statusConfig = NULL; - - /* - * Open the memory resident decoded cert database. - */ - handle->tempCertDB = dbopen(0, O_RDWR | O_CREAT, 0600, DB_HASH, &hashInfo); - if ( !handle->tempCertDB ) { - goto loser; - } - - rv = SEC_OpenPermCertDB(handle, readOnly, namecb, cbarg); - if ( rv ) { - goto loser; - } - - return (SECSuccess); - -loser: - - PORT_SetError(SEC_ERROR_BAD_DATABASE); - - if ( handle->tempCertDB ) { - certdb_Close(handle->tempCertDB); - handle->tempCertDB = 0; - } - - return(SECFailure); -} - -static char * -certDBFilenameCallback(void *arg, int dbVersion) -{ - return(PORT_Strdup((char *)arg)); -} - -SECStatus -CERT_OpenCertDBFilename(CERTCertDBHandle *handle, char *certdbname, - PRBool readOnly) -{ - return(CERT_OpenCertDB(handle, readOnly, certDBFilenameCallback, - (void *)certdbname)); -} - -/* - * Add a nickname to the temp database - */ -SECStatus -SEC_AddTempNickname(CERTCertDBHandle *handle, char *nickname, - SECItem *subjectName) -{ - DBT namekey; - int ret; - SECItem nameitem; - SECStatus rv; - DBT keydata; - PRArenaPool *arena = NULL; - SECItem tmpitem; - - PORT_Assert(nickname != NULL); - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - rv = EncodeDBNicknameKey(nickname, arena, &nameitem); - if ( rv != SECSuccess ) { - goto loser; - } - - namekey.data = nameitem.data; - namekey.size = nameitem.len; - - /* see if an entry already exists */ - ret = certdb_Get(handle->tempCertDB, &namekey, &keydata, 0); - - if ( ret == 0 ) { - /* found in temp database */ - tmpitem.data = (unsigned char*)keydata.data; - tmpitem.len = keydata.size; - - if ( SECITEM_CompareItem(subjectName, &tmpitem) == SECEqual ) { - /* same subject name */ - goto done; - } else { - /* different subject name is an error */ - goto loser; - } - } - - keydata.data = subjectName->data; - keydata.size = subjectName->len; - - /* put into temp byname index */ - ret = certdb_Put(handle->tempCertDB, &namekey, &keydata, R_NOOVERWRITE); - - if ( ret ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - -done: - PORT_FreeArena(arena, PR_FALSE); - return(SECSuccess); - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - return(SECFailure); -} - -SECStatus -SEC_DeleteTempNickname(CERTCertDBHandle *handle, char *nickname) -{ - DBT namekey; - SECStatus rv; - PRArenaPool *arena = NULL; - SECItem nameitem; - int ret; - - PORT_Assert(nickname != NULL); - if ( nickname == NULL ) { - return(SECSuccess); - } - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* format a database key based on the nickname */ - if ( nickname ) { - rv = EncodeDBNicknameKey(nickname, arena, &nameitem); - if ( rv != SECSuccess ) { - goto loser; - } - - namekey.data = nameitem.data; - namekey.size = nameitem.len; - - ret = certdb_Del(handle->tempCertDB, &namekey, 0); - if ( ret ) { - goto loser; - } - } - - PORT_FreeArena(arena, PR_FALSE); - - return(SECSuccess); - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - return(SECFailure); -} - -/* - * Decode a certificate and enter it into the temporary certificate database. - * Deal with nicknames correctly - * - * nickname is only used if isperm == PR_TRUE - * - * This is the private entry point, and locking is optional - */ -static CERTCertificate * -NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, char *nickname, - PRBool isperm, PRBool copyDER, PRBool lockdb) - -{ - DBT key; - DBT data; - int status; - CERTCertificate *cert = NULL; - PRBool promoteError = PR_TRUE; - PRArenaPool *arena = NULL; - SECItem keyitem; - SECStatus rv; - - if ( lockdb ) { - CERT_LockDB(handle); - } - - if ( isperm == PR_FALSE ) { - cert = CERT_FindCertByDERCertNoLocking(handle, derCert); - if ( cert ) { - goto winner; - } - - nickname = NULL; - } - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - cert = CERT_DecodeDERCertificate(derCert, copyDER, nickname ); - - if ( cert == NULL ) { - /* We want to save the decoding error here */ - promoteError = PR_FALSE; - goto loser; - } - - cert->dbhandle = handle; - - /* only save pointer to cert in database */ - data.data = &cert; - data.size = sizeof(cert); - - /* if this is a perm cert, then it is already in the subject db */ - if ( isperm == PR_FALSE ) { - /* enter into the subject index */ - rv = AddTempCertToSubjectList(cert); - if ( rv != SECSuccess ) { - goto loser; - } - /* - * Since it's not a perm cert, add it to the key hash lookup; if it - * is permanent it will either already be there or will get put there - * later along with the rest of the perm certs. A failure of the - * addition does not seem to warrant failing this whole function, - * so we intentionally ignore the returned status. - */ - (void) AddCertToSPKDigestTable(handle, cert); - } else { - cert->subjectList = FindSubjectList(cert->dbhandle, &cert->derSubject, - PR_FALSE); - } - - rv = EncodeDBCertKey(&cert->certKey, arena, &keyitem); - if ( rv != SECSuccess ) { - goto loser; - } - - key.data = keyitem.data; - key.size = keyitem.len; - - /* enter into main db */ - status = certdb_Put(handle->tempCertDB, &key, &data, R_NOOVERWRITE); - if ( status ) { - goto loser; - } - - if ( cert->nickname ) { - status = SEC_AddTempNickname(handle, cert->nickname, - &cert->derSubject); - if ( status ) { - promoteError = PR_FALSE; - goto loser; - } - } - - cert->isperm = isperm; - cert->istemp = PR_TRUE; - - PORT_FreeArena(arena, PR_FALSE); - -winner: - - if ( lockdb ) { - CERT_UnlockDB(handle); - } - - return(cert); - -loser: - if ( cert ) { - CERT_DestroyCertificateNoLocking(cert); - } - - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - if ( promoteError ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - } - - if ( lockdb ) { - CERT_UnlockDB(handle); - } - - return(0); -} - -/* - * Decode a certificate and enter it into the temporary certificate database. - * Deal with nicknames correctly - * - * nickname is only used if isperm == PR_TRUE - * - * This is the public entry point and does locking. - */ -CERTCertificate * -__CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, - char *nickname, PRBool isperm, PRBool copyDER) -{ - return( NewTempCertificate(handle, derCert, nickname, isperm, copyDER, - PR_TRUE) ); -} - -CERTCertificate * -CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, - char *nickname, PRBool isperm, PRBool copyDER) -{ - return( __CERT_NewTempCertificate(handle, derCert, nickname, - isperm, copyDER) ); -} - -/* - * Decode a permanent certificate and enter it into the temporary certificate - * database. - */ -static CERTCertificate * -SEC_AddPermCertToTemp(CERTCertDBHandle *handle, certDBEntryCert *entry) -{ - CERTCertificate *cert; - - /* we already hold the lock */ - cert = NewTempCertificate(handle, &entry->derCert, entry->nickname, - PR_TRUE, PR_TRUE, PR_FALSE); - if ( !cert ) { - return(0); - } - - cert->dbEntry = entry; - - cert->trust = &entry->trust; - - return(cert); -} - -SECStatus -CERT_DeleteTempCertificate(CERTCertificate *cert) -{ - SECStatus rv; - DBT nameKey; - CERTCertDBHandle *handle; - SECItem keyitem; - PRArenaPool *arena; - int ret; - - handle = cert->dbhandle; - - if ( !cert->istemp ) { - return(SECSuccess); - } - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - if (cert->slot) { - PK11_FreeSlot(cert->slot); - cert->slot = NULL; - cert->pkcs11ID = CK_INVALID_KEY; - } - - /* delete from subject list (also takes care of nickname) */ - rv = RemoveTempCertFromSubjectList(cert); - if ( rv != SECSuccess ) { - goto loser; - } - - if ( !cert->isperm ) { - /* - * Remove the cert from the subject public key digest table, - * though we do not care if the removal fails (perhaps meaning - * the cert wasn't even there). - */ - (void) RemoveCertFromSPKDigestTable(handle, cert); - } - - rv = EncodeDBCertKey(&cert->certKey, arena, &keyitem); - if ( rv != SECSuccess ) { - goto loser; - } - - nameKey.data = keyitem.data; - nameKey.size = keyitem.len; - /* delete the cert */ - ret = certdb_Del(handle->tempCertDB, &nameKey, 0); - if ( ret ) { - goto loser; - } - - cert->istemp = PR_FALSE; - - PORT_FreeArena(arena, PR_FALSE); - return(SECSuccess); - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(SECFailure); -} - -/* - * Lookup a certificate in the databases. - */ -static CERTCertificate * -FindCertByKey(CERTCertDBHandle *handle, SECItem *certKey, PRBool lockdb) -{ - DBT tmpdata; - int ret; - SECItem keyitem; - DBT key; - SECStatus rv; - CERTCertificate *cert = NULL; - PRArenaPool *arena = NULL; - certDBEntryCert *entry; - PRBool locked = PR_FALSE; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - rv = EncodeDBCertKey(certKey, arena, &keyitem); - if ( rv != SECSuccess ) { - goto loser; - } - - key.data = keyitem.data; - key.size = keyitem.len; - - if ( lockdb ) { - locked = PR_TRUE; - CERT_LockDB(handle); - } - - /* lookup in the temporary database */ - ret = certdb_Get( handle->tempCertDB, &key, &tmpdata, 0 ); - - /* error accessing the database */ - if ( ret < 0 ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - if ( ret == 0 ) { /* found in temp database */ - if ( tmpdata.size != sizeof(CERTCertificate *) ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - PORT_Memcpy(&cert, tmpdata.data, tmpdata.size); - CERT_LockCertRefCount(cert); - cert->referenceCount++; - CERT_UnlockCertRefCount(cert); - } - if ( ret != 0 ) { - /* not found in temporary database */ - - /* find in perm database */ - entry = SEC_FindPermCertByKey(handle, certKey); - - if ( entry == NULL ) { - goto loser; - } - - cert = SEC_AddPermCertToTemp(handle, entry); - } - -loser: - if ( locked ) { - CERT_UnlockDB(handle); - } - - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(cert); -} - -/* - * Lookup a certificate in the databases, with locking - */ -CERTCertificate * -CERT_FindCertByKey(CERTCertDBHandle *handle, SECItem *certKey) -{ - return(FindCertByKey(handle, certKey, PR_TRUE)); -} - -/* - * Lookup a certificate in the databases without locking - */ -CERTCertificate * -CERT_FindCertByKeyNoLocking(CERTCertDBHandle *handle, SECItem *certKey) -{ - return(FindCertByKey(handle, certKey, PR_FALSE)); -} - -/* - * Generate a key from an issuerAndSerialNumber, and find the - * associated cert in the database. - */ -CERTCertificate * -CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndSN) -{ - SECItem certKey; - CERTCertificate *cert; - - certKey.len = issuerAndSN->serialNumber.len + issuerAndSN->derIssuer.len; - certKey.data = (unsigned char*)PORT_Alloc(certKey.len); - - if ( certKey.data == NULL ) { - return(0); - } - - /* copy the serialNumber */ - PORT_Memcpy(certKey.data, issuerAndSN->serialNumber.data, - issuerAndSN->serialNumber.len); - - /* copy the issuer */ - PORT_Memcpy( &certKey.data[issuerAndSN->serialNumber.len], - issuerAndSN->derIssuer.data, issuerAndSN->derIssuer.len); - - cert = CERT_FindCertByKey(handle, &certKey); - - PORT_Free(certKey.data); - - return(cert); -} - -/* - * Lookup a certificate in the database by name - */ -CERTCertificate * -CERT_FindCertByName(CERTCertDBHandle *handle, SECItem *name) -{ - CERTCertificate *cert = NULL; - CERTSubjectList *subjectList; - - CERT_LockDB(handle); - - subjectList = FindSubjectList(handle, name, PR_FALSE); - - if ( subjectList ) { - PORT_Assert(subjectList->head); - cert = CERT_FindCertByKeyNoLocking(handle, - &subjectList->head->certKey); - } - - CERT_UnlockDB(handle); - - return(cert); -} - -/* - * Lookup a certificate in the database by name and key ID - */ -CERTCertificate * -CERT_FindCertByKeyID(CERTCertDBHandle *handle, SECItem *name, SECItem *keyID) -{ - CERTCertificate *cert = NULL; - CERTSubjectList *subjectList; - CERTSubjectNode *node; - - CERT_LockDB(handle); - - /* find the list of certs for the given subject */ - subjectList = FindSubjectList(handle, name, PR_FALSE); - - if ( subjectList ) { - PORT_Assert(subjectList->head); - node = subjectList->head; - - /* walk through the certs until we find one with a matching key ID */ - while ( node ) { - if ( SECITEM_CompareItem(keyID, &node->keyID) == SECEqual ) { - cert = CERT_FindCertByKeyNoLocking(handle, &node->certKey); - break; - } - node = node->next; - } - } - - CERT_UnlockDB(handle); - - return(cert); -} - -/* - * look up a cert by its nickname string - */ -CERTCertificate * -CERT_FindCertByNickname(CERTCertDBHandle *handle, char *nickname) -{ - DBT tmpdata; - DBT namekey; - CERTCertificate *cert; - SECStatus rv; - int ret; - SECItem keyitem; - PRArenaPool *arena = NULL; - certDBEntryCert *entry; - - PORT_Assert(nickname != NULL); - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - rv = EncodeDBNicknameKey(nickname, arena, &keyitem); - if ( rv != SECSuccess ) { - goto loser; - } - - namekey.data = keyitem.data; - namekey.size = keyitem.len; - - /* lookup in the temporary database */ - ret = certdb_Get(handle->tempCertDB, &namekey, &tmpdata, 0); - - /* error accessing the database */ - if ( ret < 0 ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - if ( ret == 0 ) { /* found in temp database */ - SECItem nameitem; - - nameitem.len = tmpdata.size; - nameitem.data = (unsigned char *)PORT_Alloc(tmpdata.size); - if ( nameitem.data == NULL ) { - goto loser; - } - PORT_Memcpy(nameitem.data, tmpdata.data, nameitem.len); - cert = CERT_FindCertByName(handle, &nameitem); - PORT_Free(nameitem.data); - } else { /* not found in temporary database */ - - CERT_LockDB(handle); - - entry = SEC_FindPermCertByNickname(handle, nickname); - - if ( entry == NULL ) { - CERT_UnlockDB(handle); - goto loser; - } - - cert = SEC_AddPermCertToTemp(handle, entry); - CERT_UnlockDB(handle); - } - - PORT_FreeArena(arena, PR_FALSE); - - return(cert); - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(0); -} - -/* - * look for the given DER certificate in the database - */ -CERTCertificate * -CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert) -{ - PRArenaPool *arena; - SECItem certKey; - SECStatus rv; - CERTCertificate *cert = NULL; - - /* create a scratch arena */ - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - return(NULL); - } - - /* extract the database key from the cert */ - rv = CERT_KeyFromDERCert(arena, derCert, &certKey); - if ( rv != SECSuccess ) { - goto loser; - } - - /* find the certificate */ - cert = CERT_FindCertByKey(handle, &certKey); - -loser: - PORT_FreeArena(arena, PR_FALSE); - return(cert); -} - -/* - * look for the given DER certificate in the database - */ -CERTCertificate * -CERT_FindCertByDERCertNoLocking(CERTCertDBHandle *handle, SECItem *derCert) -{ - PRArenaPool *arena; - SECItem certKey; - SECStatus rv; - CERTCertificate *cert = NULL; - - /* create a scratch arena */ - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - return(NULL); - } - - /* extract the database key from the cert */ - rv = CERT_KeyFromDERCert(arena, derCert, &certKey); - if ( rv != SECSuccess ) { - goto loser; - } - - /* find the certificate */ - cert = CERT_FindCertByKeyNoLocking(handle, &certKey); - -loser: - PORT_FreeArena(arena, PR_FALSE); - return(cert); -} - -/* - * The following is bunch of types and code to allow looking up a certificate - * by a hash of its subject public key. Because the words "hash" and "key" - * are overloaded and thus terribly confusing, I tried to disambiguate things. - * - Where I could, I used "digest" instead of "hash" when referring to - * hashing of the subject public key. The PLHashTable interfaces and - * our own HASH_Foo interfaces had to be left as is, obviously. The latter - * should be thought of as "digest" in this case. - * - There are three keys in use here -- the subject public key, the key - * used to do a lookup in the PLHashTable, and the key used to do a lookup - * in the cert database. As the latter is a fairly pervasive interface, - * I left it alone. The other two uses I changed to "spk" or "SPK" when - * referring to the subject public key, and "index" when referring to the - * key into the PLHashTable. - */ - -typedef struct SPKDigestInfoStr { - PLHashTable *table; - PRBool permPopulated; -} SPKDigestInfo; - -/* - * Since the key hash information is "hidden" (in a void pointer in the handle) - * these macros with the appropriate casts make it easy to get at the parts. - */ -#define SPK_DIGEST_TABLE(handle) \ - (((SPKDigestInfo *)(handle->spkDigestInfo))->table) - -/* -** Hash allocator ops for the SPKDigest hash table. The rules are: -** + The index and value fields are "owned" by the hash table, and are -** freed when the table entry is deleted. -** + Replacing a value in the table is not allowed, since the caller can't -** tell whether the index field was used or not, resulting in a memory -** leak. (This is a bug in the PL_Hash routines. -*/ -static void * PR_CALLBACK -spkAllocTable(void *pool, PRSize size) -{ -#if defined(XP_MAC) -#pragma unused (pool) -#endif - - return PR_MALLOC(size); -} - -static void PR_CALLBACK -spkFreeTable(void *pool, void *item) -{ -#if defined(XP_MAC) -#pragma unused (pool) -#endif - - PR_Free(item); -} - -/* NOTE: the key argument here appears to be useless, since the RawAdd - * routine in PL_Hash just uses the original anyway. - */ -static PLHashEntry * PR_CALLBACK -spkAllocEntry(void *pool, const void *key) -{ -#if defined(XP_MAC) -#pragma unused (pool,key) -#endif - - return PR_NEW(PLHashEntry); -} - -static void PR_CALLBACK -spkFreeEntry(void *pool, PLHashEntry *he, PRUintn flag) -{ -#if defined(XP_MAC) -#pragma unused (pool) -#endif - - SECItem *value = (SECItem *)he->value; - - /* The flag should always be to free the whole entry. Otherwise the - * index field gets leaked because the caller can't tell whether - * the "new" value (which is the same as the old) was used or not. - */ - PORT_Assert(flag == HT_FREE_ENTRY); - - /* We always free the value */ - SECITEM_FreeItem(value, PR_TRUE); - - if (flag == HT_FREE_ENTRY) - { - /* Comes from BTOA, is this the right free call? */ - PORT_Free((char *)he->key); - PR_Free(he); - } -} - -static PLHashAllocOps spkHashAllocOps = { - spkAllocTable, spkFreeTable, - spkAllocEntry, spkFreeEntry -}; - - -/* - * Create the key hash lookup table. Note that the table, and the - * structure which holds it and a little more information, is never freed. - * This is because the temporary database is never actually closed out, - * so there is no safe/obvious place to free the whole thing. - * - * The database must be locked already. - */ -static SECStatus -InitDBspkDigestInfo(CERTCertDBHandle *handle) -{ - SPKDigestInfo *spkDigestInfo; - PLHashTable *table; - - PORT_Assert(handle != NULL); - PORT_Assert(handle->spkDigestInfo == NULL); - - spkDigestInfo = PORT_ZAlloc(sizeof(SPKDigestInfo)); - if ( spkDigestInfo == NULL ) { - return(SECFailure); - } - - table = PL_NewHashTable(128, PL_HashString, PL_CompareStrings, - (PLHashComparator) SECITEM_ItemsAreEqual, - &spkHashAllocOps, NULL); - if ( table == NULL ) { - PORT_Free(spkDigestInfo); - return(SECFailure); - } - - spkDigestInfo->table = table; - handle->spkDigestInfo = spkDigestInfo; - return(SECSuccess); -} - -static const SECHashObject * -OidTagToRawDigestObject(SECOidTag digestAlg) -{ - const SECHashObject *rawDigestObject; - - switch (digestAlg) { - case SEC_OID_MD2: - rawDigestObject = &SECRawHashObjects[HASH_AlgMD2]; - break; - case SEC_OID_MD5: - rawDigestObject = &SECRawHashObjects[HASH_AlgMD5]; - break; - case SEC_OID_SHA1: - rawDigestObject = &SECRawHashObjects[HASH_AlgSHA1]; - break; - default: - PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); - rawDigestObject = NULL; - break; - } - return(rawDigestObject); -} - -/* - * Digest the cert's subject public key using the specified algorithm. - * The necessary storage for the digest data is allocated. If "fill" is - * non-null, the data is put there, otherwise a SECItem is allocated. - * Allocation from "arena" if it is non-null, heap otherwise. Any problem - * results in a NULL being returned (and an appropriate error set). - */ -SECItem * -CERT_SPKDigestValueForCert(PRArenaPool *arena, CERTCertificate *cert, - SECOidTag digestAlg, SECItem *fill) -{ - const SECHashObject *digestObject; - void *digestContext; - SECItem *result = NULL; - void *mark = NULL; - SECItem spk; - - if ( arena != NULL ) { - mark = PORT_ArenaMark(arena); - } - - /* - * This can end up being called before PKCS #11 is initialized, - * so we have to use the raw digest functions. - */ - digestObject = OidTagToRawDigestObject(digestAlg); - if ( digestObject == NULL ) { - goto loser; - } - - result = SECITEM_AllocItem(arena, fill, digestObject->length); - if ( result == NULL ) { - goto loser; - } - - /* - * Copy just the length and data pointer (nothing needs to be freed) - * of the subject public key so we can convert the length from bits - * to bytes, which is what the digest function expects. - */ - spk = cert->subjectPublicKeyInfo.subjectPublicKey; - DER_ConvertBitString(&spk); - - /* - * Now digest the value, using the specified algorithm. - */ - digestContext = digestObject->create(); - if ( digestContext == NULL ) { - goto loser; - } - digestObject->begin(digestContext); - digestObject->update(digestContext, spk.data, spk.len); - digestObject->end(digestContext, result->data, &(result->len), result->len); - digestObject->destroy(digestContext, PR_TRUE); - - if ( arena != NULL ) { - PORT_ArenaUnmark(arena, mark); - } - return(result); - -loser: - if ( arena != NULL ) { - PORT_ArenaRelease(arena, mark); - } else { - if ( result != NULL ) { - SECITEM_FreeItem(result, (fill == NULL) ? PR_TRUE : PR_FALSE); - } - } - return(NULL); -} - -/* - * Return the index for the spk digest lookup table for "spkDigest". - * - * Caller is responsible for freeing the returned string. - */ -static char * -spkDigestIndexFromDigest(SECItem *spkDigest) -{ - return BTOA_ConvertItemToAscii(spkDigest); -} - -/* - * Return the index for the spk digest lookup table for this certificate, - * based on the specified digest algorithm. - * - * Caller is responsible for freeing the returned string. - */ -static char * -spkDigestIndexFromCert(CERTCertificate *cert, SECOidTag digestAlg) -{ - SECItem *spkDigest; - char *index; - - spkDigest = CERT_SPKDigestValueForCert(NULL, cert, digestAlg, NULL); - if ( spkDigest == NULL ) - return(NULL); - - index = spkDigestIndexFromDigest(spkDigest); - - SECITEM_FreeItem(spkDigest, PR_TRUE); - - return(index); -} - -/* - * Remove the spk digest for the given cert from the spk digest table, - * based on the given digest algorithm. - * - * The database must be locked already. - */ -static SECStatus -RemoveCertFromSPKDigestTableForAlg(CERTCertDBHandle *handle, - CERTCertificate *cert, SECOidTag digestAlg) -{ - SECStatus rv = SECSuccess; - char *index = NULL; - PLHashTable *table; - - /* Expect to only be called if there is a table to work with. */ - PORT_Assert(handle->spkDigestInfo != NULL); - - table = SPK_DIGEST_TABLE(handle); - PORT_Assert(table != NULL); - - index = spkDigestIndexFromCert(cert, digestAlg); - if ( index == NULL ) { - rv = SECFailure; - goto done; - } - - if ( PL_HashTableRemove(table, index) != PR_TRUE ) { - /* not found means nothing to remove, which is fine */ - } - -done: - if ( index != NULL ) { - PORT_Free(index); - } - return(rv); -} - -/* - * Remove the spk digests for the given cert from the spk digest table, - * for all known digest algorithms. - * - * The database must be locked already. - */ -static SECStatus -RemoveCertFromSPKDigestTable(CERTCertDBHandle *handle, CERTCertificate *cert) -{ - /* - * If no certs have been added yet, then nothing to do. - */ - if ( handle->spkDigestInfo == NULL ) { - return(SECSuccess); - } - - (void) RemoveCertFromSPKDigestTableForAlg(handle, cert, SEC_OID_MD2); - (void) RemoveCertFromSPKDigestTableForAlg(handle, cert, SEC_OID_MD5); - return RemoveCertFromSPKDigestTableForAlg(handle, cert, SEC_OID_SHA1); -} - -/* - * Add the spk digest for the given cert to the spk digest table, - * based on the given digest algorithm. - * - * If a cert for the same spk digest is already in the table, choose whichever - * cert is "newer". (The other cert cannot be found via spk digest.) - * - * The database must be locked already. - * - * XXX Note that this implementation results in leaking the index value. - * Fixing that did not seem worth the trouble, given we will only leak - * once per cert. This whole thing should be done differently in the - * new rewrite (Stan), and then the problem will go away. - */ -static SECStatus -AddCertToSPKDigestTableForAlg(CERTCertDBHandle *handle, CERTCertificate *cert, - SECItem *certDBKey, SECOidTag digestAlg) -{ - SECStatus rv = SECFailure; - SECItem *oldCertDBKey; - PRBool addit = PR_TRUE; - CERTCertificate *oldCert = NULL; - char *index = NULL; - PLHashTable *table; - - /* - * After running some testing doing key hash lookups (like using OCSP), - * if these are never hit, they can probably be removed. - */ - PORT_Assert(handle != NULL); - PORT_Assert(handle == cert->dbhandle); - PORT_Assert(handle->spkDigestInfo != NULL); - PORT_Assert((certDBKey == &cert->certKey) - || (SECITEM_CompareItem(certDBKey, - &cert->certKey) == SECEqual)); - - table = SPK_DIGEST_TABLE(handle); - PORT_Assert(table != NULL); - - index = spkDigestIndexFromCert(cert, digestAlg); - if ( index == NULL ) { - goto loser; - } - - /* - * See if this cert's spk digest is already in the table. - */ - oldCertDBKey = PL_HashTableLookup(table, index); - if ( oldCertDBKey != NULL ) { - /* - * The spk digest *is* already in the table. We need to find that - * cert and see -- if it is the same, then we can just leave as is. - * Otherwise we have to choose which cert we want represented; - * in that case the best plan I can think of is to hang onto the - * most recent one. - */ - oldCert = CERT_FindCertByKey(handle, oldCertDBKey); - if ( oldCert != NULL ) { - if ( cert == oldCert ) { - /* They are the same cert, so we are done. */ - addit = PR_FALSE; - } else if ( CERT_IsNewer(cert, oldCert) ) { - if ( PL_HashTableRemove(table, index) != PR_TRUE ) { - goto loser; - } - } else { - /* oldCert is "newer", so we are done. */ - addit = PR_FALSE; - } - } - } - - if ( addit ) { - certDBKey = SECITEM_DupItem(certDBKey); - if ( certDBKey == NULL ) { - goto loser; - } - if ( PL_HashTableAdd(table, index, certDBKey) == NULL ) { - SECITEM_FreeItem(certDBKey, PR_TRUE); - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - index = NULL; /* don't want to free it */ - } - - rv = SECSuccess; - -loser: - if ( index != NULL ) { - PORT_Free(index); - } - if ( oldCert != NULL ) { - CERT_DestroyCertificate(oldCert); - } - return(rv); -} - -/* - * Add the spk digest for the given cert to the spk digest table, - * for all known digest algorithms. - * - * The database must be locked already, and the digest table already created. - */ -static SECStatus -AddCertToSPKDigestTableForAllAlgs(CERTCertDBHandle *handle, - CERTCertificate *cert, SECItem *certDBKey) -{ - (void) AddCertToSPKDigestTableForAlg(handle, cert, certDBKey, SEC_OID_MD2); - (void) AddCertToSPKDigestTableForAlg(handle, cert, certDBKey, SEC_OID_MD5); - return AddCertToSPKDigestTableForAlg(handle, cert, certDBKey, SEC_OID_SHA1); -} - -/* - * Add the spk digests for the given cert to the spk digest table, - * for all known digest algorithms. (This function is called when a - * new cert is added to the temporary database.) - * - * If the spk digest table does not yet exist, create it. - * - * In an ideal world, we would not hardwire the digest algorithms. - * But it is the case that we do not currently support any digest - * algorithms outside of these three. In the newer, cleaned-up world, - * this may be done differently. - * - * The database must be locked already. - */ -static SECStatus -AddCertToSPKDigestTable(CERTCertDBHandle *handle, CERTCertificate *cert) -{ - SECStatus rv; - - if ( handle->spkDigestInfo == NULL ) { - rv = InitDBspkDigestInfo(handle); - if ( rv != SECSuccess ) { - return(rv); - } - } - - return AddCertToSPKDigestTableForAllAlgs(handle, cert, &cert->certKey); -} - -/* - * Add the spk digest for the given cert to the spk digest table, - * for all known digest algorithms. This function is called while - * traversing all of the certs in the permanent database -- since - * that imposes some constraints on its arguments this routine is a - * simple cover for the "real" interface. - * - * The database must be locked already, and the digest table already created. - */ -static SECStatus -AddCertToSPKDigestTableInTraversal(CERTCertificate *cert, SECItem *certDBKey, - void *data) -{ - CERTCertDBHandle *handle = data; - - return AddCertToSPKDigestTableForAllAlgs(handle, cert, certDBKey); -} - -/* - * Add the spk digests for the all permanent certs to the spk digest table, - * for all known digest algorithms. - * - * This locks the database, and then checks to make sure that the work - * actually needs to get done. - * - * If the spk digest table does not yet exist, it is created. - */ -static SECStatus -PopulateSPKDigestTable(CERTCertDBHandle *handle) -{ - SPKDigestInfo *spkDigestInfo; - SECStatus rv = SECSuccess; - - CERT_LockDB(handle); - - spkDigestInfo = handle->spkDigestInfo; - if ( spkDigestInfo == NULL ) { - rv = InitDBspkDigestInfo(handle); - if ( rv != SECSuccess ) { - return(rv); - } - spkDigestInfo = handle->spkDigestInfo; - PORT_Assert(spkDigestInfo != NULL); - } else { - /* - * Check to see if someone already did it; it is important to do - * this after getting the lock. - */ - if ( spkDigestInfo->permPopulated == PR_TRUE ) { - goto done; - } - } - - rv = TraversePermCertsNoLocking(handle, AddCertToSPKDigestTableInTraversal, - handle); - - if ( rv != SECSuccess ) { - goto done; - } - - spkDigestInfo->permPopulated = PR_TRUE; - -done: - CERT_UnlockDB(handle); - - return(rv); -} - -/* - * Lookup a certificate by a digest of a subject public key. If it is - * found, it is returned (and must then be destroyed by the caller). - * NULL is returned otherwise -- if there was a problem performing the - * lookup, an appropriate error is set (e.g. SEC_ERROR_NO_MEMORY); - * if the cert simply was not found, the error is SEC_ERROR_UNKNOWN_CERT. - * - * If the lookup table has not yet been created or populated, do that first. - */ -CERTCertificate * -CERT_FindCertBySPKDigest(CERTCertDBHandle *handle, SECItem *spkDigest) -{ - SPKDigestInfo *spkDigestInfo; - char *index = NULL; - SECItem *certDBKey; - CERTCertificate *cert = NULL; - - PORT_Assert(handle != NULL); - spkDigestInfo = handle->spkDigestInfo; - - if ( spkDigestInfo == NULL || spkDigestInfo->permPopulated != PR_TRUE ) { - if ( PopulateSPKDigestTable(handle) != SECSuccess ) { - goto loser; - } - } - - index = spkDigestIndexFromDigest(spkDigest); - if ( index == NULL ) { - goto loser; - } - - certDBKey = PL_HashTableLookup(SPK_DIGEST_TABLE(handle), index); - if ( certDBKey != NULL ) { - cert = CERT_FindCertByKey(handle, certDBKey); - } - - if ( cert == NULL ) { - PORT_SetError(SEC_ERROR_UNKNOWN_CERT); - } - -loser: - if ( index != NULL ) { - PORT_Free(index); - } - return(cert); -} - -static void -DestroyCertificate(CERTCertificate *cert, PRBool lockdb) -{ - int refCount; - CERTCertDBHandle *handle; - - if ( cert ) { - - handle = cert->dbhandle; - - /* - * handle may be NULL, for example if the cert was created with - * CERT_DecodeDERCertificate. - */ - if ( lockdb && handle ) { - CERT_LockDB(handle); - } - - CERT_LockCertRefCount(cert); - PORT_Assert(cert->referenceCount > 0); - refCount = --cert->referenceCount; - CERT_UnlockCertRefCount(cert); - - if ( ( refCount == 0 ) && !cert->keepSession ) { - certDBEntryCert *entry = cert->dbEntry; - PRArenaPool * arena = cert->arena; - - if ( cert->istemp ) { - CERT_DeleteTempCertificate(cert); - } - - if ( entry ) { - DestroyDBEntry((certDBEntry *)entry); - } - - /* zero cert before freeing. Any stale references to this cert - * after this point will probably cause an exception. */ - PORT_Memset(cert, 0, sizeof *cert); - - cert = NULL; - - /* free the arena that contains the cert. */ - PORT_FreeArena(arena, PR_FALSE); - } - if ( lockdb && handle ) { - CERT_UnlockDB(handle); - } - } - - return; -} - -void -CERT_DestroyCertificate(CERTCertificate *cert) -{ - DestroyCertificate(cert, PR_TRUE); - return; -} - -void -CERT_DestroyCertificateNoLocking(CERTCertificate *cert) -{ - DestroyCertificate(cert, PR_FALSE); - return; -} - -/* - * cache a CRL from the permanent database into the temporary database - */ -CERTSignedCrl * -SEC_AddPermCrlToTemp(CERTCertDBHandle *handle, certDBEntryRevocation *entry) -{ - CERTSignedCrl *crl = NULL; - DBT key; - DBT data; - int status; - PRArenaPool *arena = NULL; - SECItem keyitem; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - crl = CERT_DecodeDERCrl(NULL, &entry->derCrl, - entry->common.type == certDBEntryTypeRevocation ? - SEC_CRL_TYPE : SEC_KRL_TYPE); - - if ( crl == NULL ) { - goto loser; - } - - /* only save pointer to cert in database */ - data.data = &crl; - data.size = sizeof(crl); - - - rv = EncodeDBGenericKey(&(crl->crl.derName), arena, - &keyitem, entry->common.type); - if ( rv != SECSuccess ) { - goto loser; - } - - if (entry->url) { - int nnlen = PORT_Strlen(entry->url) + 1; - crl->url = (char *)PORT_ArenaAlloc(crl->arena, nnlen); - if ( !crl->url ) { - goto loser; - } - PORT_Memcpy(crl->url, entry->url, nnlen); - } else { - crl->url = NULL; - } - - key.data = keyitem.data; - key.size = keyitem.len; - - /* enter into main db */ - status = certdb_Put(handle->tempCertDB, &key, &data, R_NOOVERWRITE); - if ( status ) { - goto loser; - } - - crl->istemp = PR_TRUE; - crl->isperm = PR_TRUE; - crl->dbhandle = handle; - crl->dbEntry = entry; - - - PORT_FreeArena(arena, PR_FALSE); - - crl->keep = PR_TRUE; - return(crl); - -loser: - if ( crl ) { - SEC_DestroyCrl(crl); - } - - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - PORT_SetError(SEC_ERROR_BAD_DATABASE); - return(0); -} - -SECStatus -SEC_DeleteTempCrl(CERTSignedCrl *crl) -{ - SECStatus rv; - DBT nameKey; - CERTCertDBHandle *handle; - SECItem keyitem; - PRArenaPool *arena; - int ret; - - handle = crl->dbhandle; - - if ( !crl->istemp ) { - return(SECSuccess); - } - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - rv = EncodeDBGenericKey - (&crl->crl.derName, arena, &keyitem, crl->dbEntry->common.type); - if ( rv != SECSuccess ) { - goto loser; - } - - nameKey.data = keyitem.data; - nameKey.size = keyitem.len; - - /* delete the cert */ - ret = certdb_Del(handle->tempCertDB, &nameKey, 0); - if ( ret ) { - goto loser; - } - - crl->istemp = PR_FALSE; - - PORT_FreeArena(arena, PR_FALSE); - return(SECSuccess); - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(SECFailure); -} - -/* - * Lookup a CRL in the databases. We mirror the same fast caching data base - * caching stuff used by certificates....? - */ -CERTSignedCrl * -SEC_FindCrlByKey(CERTCertDBHandle *handle, SECItem *crlKey, int type) -{ - DBT tmpdata; - int ret; - SECItem keyitem; - DBT key; - SECStatus rv; - CERTSignedCrl *crl = NULL; - PRArenaPool *arena = NULL; - certDBEntryRevocation *entry; - certDBEntryType crlType = (type == SEC_CRL_TYPE) ? - certDBEntryTypeRevocation : certDBEntryTypeKeyRevocation; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - rv = EncodeDBGenericKey(crlKey, arena, &keyitem, crlType); - if ( rv != SECSuccess ) { - goto loser; - } - - key.data = keyitem.data; - key.size = keyitem.len; - - /* lookup in the temporary database */ - ret = certdb_Get( handle->tempCertDB, &key, &tmpdata, 0 ); - - /* error accessing the database */ - if ( ret < 0 ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - if ( ret == 0 ) { /* found in temp database */ - if ( tmpdata.size != sizeof(CERTSignedCrl *) ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - PORT_Memcpy(&crl, tmpdata.data, tmpdata.size); - crl->referenceCount++; - } else { /* not found in temporary database */ - - /* find in perm database */ - entry = ReadDBCrlEntry(handle, crlKey, crlType); - - if ( entry == NULL ) { - goto loser; - } - - crl = SEC_AddPermCrlToTemp(handle, entry); - } - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(crl); -} - - -CERTSignedCrl * -SEC_FindCrlByName(CERTCertDBHandle *handle, SECItem *crlKey, int type) -{ - return SEC_FindCrlByKey(handle,crlKey,type); -} - -CERTSignedCrl * -SEC_FindCrlByDERCert(CERTCertDBHandle *handle, SECItem *derCrl, int type) -{ - PRArenaPool *arena; - SECItem crlKey; - SECStatus rv; - CERTSignedCrl *crl = NULL; - - /* create a scratch arena */ - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - return(NULL); - } - - /* extract the database key from the cert */ - rv = CERT_KeyFromDERCrl(arena, derCrl, &crlKey); - if ( rv != SECSuccess ) { - goto loser; - } - - /* find the crl */ - crl = SEC_FindCrlByKey(handle, &crlKey, type); - -loser: - PORT_FreeArena(arena, PR_FALSE); - return(crl); -} - - -SECStatus -SEC_DestroyCrl(CERTSignedCrl *crl) -{ - if (crl) { - if (crl->referenceCount-- <= 1) { - if (!crl->keep) { - SEC_DeleteTempCrl(crl); - if (crl->dbEntry) { - DestroyDBEntry((certDBEntry *)crl->dbEntry); - } - PORT_FreeArena(crl->arena, PR_FALSE); - } - } - } - return SECSuccess; -} - -CERTSignedCrl * -cert_DBInsertCRL (CERTCertDBHandle *handle, char *url, - CERTSignedCrl *newCrl, SECItem *derCrl, int type) -{ - CERTSignedCrl *oldCrl = NULL, *crl = NULL; - certDBEntryRevocation *entry = NULL; - PRArenaPool *arena = NULL; - SECCertTimeValidity validity; - certDBEntryType crlType = (type == SEC_CRL_TYPE) ? - certDBEntryTypeRevocation : certDBEntryTypeKeyRevocation; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) goto done; - - validity = SEC_CheckCrlTimes(&newCrl->crl,PR_Now()); - if ( validity == secCertTimeExpired) { - if (type == SEC_CRL_TYPE) { - PORT_SetError(SEC_ERROR_CRL_EXPIRED); - } else { - PORT_SetError(SEC_ERROR_KRL_EXPIRED); - } - goto done; - } else if (validity == secCertTimeNotValidYet) { - if (type == SEC_CRL_TYPE) { - PORT_SetError(SEC_ERROR_CRL_NOT_YET_VALID); - } else { - PORT_SetError(SEC_ERROR_KRL_NOT_YET_VALID); - } - goto done; - } - - oldCrl = SEC_FindCrlByKey(handle, &newCrl->crl.derName, type); - - /* if there is an old crl, make sure the one we are installing - * is newer. If not, exit out, otherwise delete the old crl. - */ - if (oldCrl != NULL) { - if (!SEC_CrlIsNewer(&newCrl->crl,&oldCrl->crl)) { - - if (type == SEC_CRL_TYPE) { - PORT_SetError(SEC_ERROR_OLD_CRL); - } else { - PORT_SetError(SEC_ERROR_OLD_KRL); - } - - goto done; - } - - if ((SECITEM_CompareItem(&newCrl->crl.derName, - &oldCrl->crl.derName) != SECEqual) && - (type == SEC_KRL_TYPE) ) { - - PORT_SetError(SEC_ERROR_CKL_CONFLICT); - goto done; - } - - /* if we have a url in the database, use that one */ - if (oldCrl->url) { - int nnlen = PORT_Strlen(oldCrl->url) + 1; - url = (char *)PORT_ArenaAlloc(arena, nnlen); - if ( url != NULL ) { - PORT_Memcpy(url, oldCrl->url, nnlen); - } - } - - - /* really destroy this crl */ - /* first drum it out of the permanment Data base */ - SEC_DeletePermCRL(oldCrl); - /* then get rid of our reference to it... */ - SEC_DestroyCrl(oldCrl); - oldCrl = NULL; - - } - - /* Write the new entry into the data base */ - entry = NewDBCrlEntry(derCrl, url, crlType, 0); - if (entry == NULL) goto done; - - rv = WriteDBCrlEntry(handle, entry); - if (rv != SECSuccess) goto done; - - crl = SEC_AddPermCrlToTemp(handle, entry); - if (crl) entry = NULL; /*crl->dbEntry now points to entry data */ - crl->isperm = PR_TRUE; - -done: - if (entry) DestroyDBEntry((certDBEntry *)entry); - if (arena) PORT_FreeArena(arena, PR_FALSE); - if (oldCrl) SEC_DestroyCrl(oldCrl); - - return crl; -} - - -/* - * create a new CRL from DER material. - * - * The signature on this CRL must be checked before you - * load it. ??? - */ -CERTSignedCrl * -SEC_NewCrl(CERTCertDBHandle *handle, char *url, SECItem *derCrl, int type) -{ - CERTSignedCrl *newCrl = NULL, *crl = NULL; - - /* make this decode dates! */ - newCrl = CERT_DecodeDERCrl(NULL, derCrl, type); - if (newCrl == NULL) { - if (type == SEC_CRL_TYPE) { - PORT_SetError(SEC_ERROR_CRL_INVALID); - } else { - PORT_SetError(SEC_ERROR_KRL_INVALID); - } - goto done; - } - - crl = cert_DBInsertCRL (handle, url, newCrl, derCrl, type); - - -done: - if (newCrl) PORT_FreeArena(newCrl->arena, PR_FALSE); - - return crl; -} - - -/* - * replace the existing URL in the data base with a new one - */ -SECStatus -SEC_CrlReplaceUrl(CERTSignedCrl *crl,char *url) { - SECStatus rv = SECFailure; - certDBEntryRevocation *entry = NULL; - int nnlen=0; - - SEC_DeletePermCRL(crl); - - /* Write the new entry into the data base */ - entry = NewDBCrlEntry(&crl->dbEntry->derCrl, url, crl->dbEntry->common.type, 0); - if (entry == NULL) goto done; - - rv = WriteDBCrlEntry(crl->dbhandle, entry); - if (rv != SECSuccess) goto done; - - if (url) { - nnlen = PORT_Strlen(url) + 1; - crl->url = (char *)PORT_ArenaAlloc(crl->arena, nnlen); - if ( !crl->url ) { - goto done; - } - PORT_Memcpy(crl->url, url, nnlen); - } else { - crl->url = NULL; - } -done: - return rv; -} - - -/* - * collect a linked list of CRL's - */ -static SECStatus CollectCrls(SECItem *dbdata, SECItem *dbkey, - certDBEntryType type, void *data) { - SECStatus rv; - certDBEntryRevocation entry; - SECItem entryitem; - PRArenaPool *arena = NULL; - CERTCrlHeadNode *head; - CERTCrlNode *new_node; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - head = (CERTCrlHeadNode *)data; - entry.common.version = (unsigned int)dbdata->data[0]; - entry.common.type = (certDBEntryType)dbdata->data[1]; - entry.common.flags = (unsigned int)dbdata->data[2]; - entry.common.arena = arena; - - entryitem.len = dbdata->len - SEC_DB_ENTRY_HEADER_LEN; - entryitem.data = &dbdata->data[SEC_DB_ENTRY_HEADER_LEN]; - - rv = DecodeDBCrlEntry(&entry, &entryitem); - if (rv != SECSuccess ) { - goto loser; - } - - new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, sizeof(CERTCrlNode)); - if (new_node == NULL) { - goto loser; - } - - new_node->type = (entry.common.type == certDBEntryTypeRevocation) ? - SEC_CRL_TYPE : SEC_KRL_TYPE; - new_node->crl=CERT_DecodeDERCrl(head->arena,&entry.derCrl,new_node->type); - - if (entry.url) { - int nnlen = PORT_Strlen(entry.url) + 1; - new_node->crl->url = (char *)PORT_ArenaAlloc(head->arena, nnlen); - if ( !new_node->crl->url ) { - goto loser; - } - PORT_Memcpy(new_node->crl->url, entry.url, nnlen); - } else { - new_node->crl->url = NULL; - } - - - new_node->next = NULL; - if (head->last) { - head->last->next = new_node; - head->last = new_node; - } else { - head->first = head->last = new_node; - } - return (SECSuccess); - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - return(SECFailure); -} - - -SECStatus -SEC_LookupCrls(CERTCertDBHandle *handle, CERTCrlHeadNode **nodes, int type) -{ - CERTCrlHeadNode *head; - PRArenaPool *arena = NULL; - SECStatus rv; - - *nodes = NULL; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - return SECFailure; - } - - /* build a head structure */ - head = (CERTCrlHeadNode *)PORT_ArenaAlloc(arena, sizeof(CERTCrlHeadNode)); - head->arena = arena; - head->first = NULL; - head->last = NULL; - head->dbhandle = handle; - - /* Look up the proper crl types */ - *nodes = head; - - CERT_LockDB(handle); - - switch (type) { - case SEC_CRL_TYPE: - rv = SEC_TraverseDBEntries(handle, certDBEntryTypeRevocation, - CollectCrls, (void *)head); - break; - case SEC_KRL_TYPE: - rv = SEC_TraverseDBEntries(handle, certDBEntryTypeKeyRevocation, - CollectCrls, (void *)head); - break; - case -1: - rv = SEC_TraverseDBEntries(handle, certDBEntryTypeKeyRevocation, - CollectCrls, (void *)head); - if (rv != SECSuccess) break; - rv = SEC_TraverseDBEntries(handle, certDBEntryTypeRevocation, - CollectCrls, (void *)head); - break; - default: - rv = SECFailure; - break; - } - - CERT_UnlockDB(handle); - - if (rv != SECSuccess) { - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - *nodes = NULL; - } - } - - return rv; -} - - -SECStatus -SEC_DeletePermCRL(CERTSignedCrl *crl) { - SECStatus rv; - - if (crl == NULL) { - return SECFailure; - } - - rv = DeleteDBCrlEntry(crl->dbhandle, &crl->crl.derName, - crl->dbEntry->common.type); - if (rv != SECSuccess) goto done; - - /* now force it to be freed when all the reference counts go */ - crl->keep = PR_FALSE; - /* force it out of the temporary data base */ - SEC_DeleteTempCrl(crl); - -done: - return rv; -} - -/* - * find a cert by email address - * - * pick one that is a valid recipient, meaning that it is an encryption - * cert. - * - */ -static CERTCertificate* -find_smime_recipient_cert(CERTCertDBHandle* handle, const char* email_addr) -{ - CERTCertificate* cert = NULL; - CERTCertList* certList = NULL; - SECStatus rv; - - certList = CERT_CreateEmailAddrCertList(NULL, handle, (char*)email_addr, - PR_Now(), PR_TRUE); - if (certList == NULL) { - return NULL; - } - - rv = CERT_FilterCertListByUsage(certList, certUsageEmailRecipient, - PR_FALSE); - - if (!CERT_LIST_END(CERT_LIST_HEAD(certList), certList)) { - cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert); - } - - CERT_DestroyCertList(certList); - - return cert; /* cert may point to a cert or may be NULL */ -} - -/* - * This function has the logic that decides if another person's cert and - * email profile from an S/MIME message should be saved. It can deal with - * the case when there is no profile. - */ -SECStatus -CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile, - SECItem *profileTime) -{ - certDBEntrySMime *entry = NULL, *oldentry = NULL; - int64 oldtime; - int64 newtime; - SECStatus rv; - CERTCertificate *oldcert = NULL; - PRBool saveit; - CERTCertTrust trust; - CERTCertTrust tmptrust; - char *emailAddr; - - emailAddr = cert->emailAddr; - - PORT_Assert(emailAddr); - if ( emailAddr == NULL ) { - goto loser; - } - - saveit = PR_FALSE; - - oldcert = find_smime_recipient_cert(cert->dbhandle, emailAddr); - if (oldcert) { - /* see if there is an entry already */ - oldentry = ReadDBSMimeEntry(cert->dbhandle, emailAddr); - } - - /* both profileTime and emailProfile have to exist or not exist */ - if ( emailProfile == NULL ) { - profileTime = NULL; - } else if ( profileTime == NULL ) { - emailProfile = NULL; - } - - if ( oldentry == NULL ) { - /* no old entry for this address */ - PORT_Assert(oldcert == NULL); - saveit = PR_TRUE; - } else { - /* there was already a profile for this email addr */ - if ( profileTime ) { - /* we have an old and new profile - save whichever is more recent*/ - if ( oldentry->optionsDate.len == 0 ) { - /* always replace if old entry doesn't have a time */ - oldtime = LL_MININT; - } else { - rv = DER_UTCTimeToTime(&oldtime, &oldentry->optionsDate); - if ( rv != SECSuccess ) { - goto loser; - } - } - - rv = DER_UTCTimeToTime(&newtime, profileTime); - if ( rv != SECSuccess ) { - goto loser; - } - - if ( LL_CMP(newtime, >, oldtime ) ) { - /* this is a newer profile, save it and cert */ - saveit = PR_TRUE; - } - } else { - /* we don't have a new profile or time */ - if ( oldentry->optionsDate.len == 0 ) { - /* the old entry doesn't have a time either, so compare certs*/ - if ( CERT_IsNewer(cert, oldcert) ) { - /* new cert is newer, use it instead */ - saveit = PR_TRUE; - } - } else { - if (oldcert) { - if (CERT_IsNewer(cert, oldcert)) { - saveit = PR_TRUE; - } - } else { - saveit = PR_TRUE; - } - } - } - } - - if ( saveit ) { - if ( oldcert && ( oldcert != cert ) ) { - /* old cert is different from new cert */ - if ( PORT_Memcmp(oldcert->trust, &trust, sizeof(trust)) == 0 ) { - /* old cert is only for e-mail, so delete it */ - SEC_DeletePermCertificate(oldcert); - } else { - /* old cert is for other things too, so just change trust */ - tmptrust = *oldcert->trust; - tmptrust.emailFlags &= ( ~CERTDB_VALID_PEER ); - rv = CERT_ChangeCertTrust(oldcert->dbhandle, oldcert, - &tmptrust); - if ( rv != SECSuccess ) { - goto loser; - } - } - } - -/* Subroutine */ - /* now save the entry */ - entry = NewDBSMimeEntry(emailAddr, &cert->derSubject, emailProfile, - profileTime, 0); - if ( entry == NULL ) { - goto loser; - } - - CERT_LockDB(cert->dbhandle); - - rv = DeleteDBSMimeEntry(cert->dbhandle, emailAddr); - /* if delete fails, try to write new entry anyway... */ - - rv = WriteDBSMimeEntry(cert->dbhandle, entry); - if ( rv != SECSuccess ) { - CERT_UnlockDB(cert->dbhandle); - goto loser; - } - - /* link subject entry back here */ - rv = UpdateSubjectWithEmailAddr(cert, emailAddr); - if ( rv != SECSuccess ) { - CERT_UnlockDB(cert->dbhandle); - goto loser; - } - - CERT_UnlockDB(cert->dbhandle); -/* End Subroutine */ - } - - rv = SECSuccess; - goto done; - -loser: - rv = SECFailure; - -done: - if ( oldcert ) { - CERT_DestroyCertificate(oldcert); - } - - if ( entry ) { - DestroyDBEntry((certDBEntry *)entry); - } - if ( oldentry ) { - DestroyDBEntry((certDBEntry *)oldentry); - } - - return(rv); -} - -CERTCertificate * -CERT_FindCertByEmailAddr(CERTCertDBHandle *handle, char *emailAddr) -{ - certDBEntrySMime *entry; - CERTCertificate *cert = NULL; - - emailAddr = CERT_FixupEmailAddr(emailAddr); - if ( emailAddr == NULL ) { - return(NULL); - } - - entry = ReadDBSMimeEntry(handle, emailAddr); - - /* XXX - this will have to change when multiple certs per subject - * are allowed - */ - if ( entry != NULL ) { - cert = CERT_FindCertByName(handle, &entry->subjectName); - } - - if ( entry ) { - DestroyDBEntry((certDBEntry *)entry); - } - - PORT_Free(emailAddr); - - return(cert); -} - -/* - * find the smime symmetric capabilities profile for a given cert - */ -SECItem * -CERT_FindSMimeProfile(CERTCertificate *cert) -{ - certDBEntrySMime *entry; - SECItem *retitem = NULL; - - PORT_Assert(cert->emailAddr != NULL); - - if ( cert->emailAddr == NULL ) { - return(NULL); - } - - entry = ReadDBSMimeEntry(cert->dbhandle, cert->emailAddr); - - if ( entry ) { - /* May not be for this cert... */ - if (SECITEM_ItemsAreEqual(&cert->derSubject, &entry->subjectName)) - retitem = SECITEM_DupItem(&entry->smimeOptions); - DestroyDBEntry((certDBEntry *)entry); - } - - return(retitem); -} - -CERTCertificate * -CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, char *name) -{ - CERTCertificate *cert; - cert = CERT_FindCertByNickname(handle, name); - if ( cert == NULL ) { - cert = CERT_FindCertByEmailAddr(handle, name); - } - - return(cert); -} - -PRBool -CERT_IsCertRevoked(CERTCertificate *cert) -{ - return(PR_FALSE); -} - -CERTCertificate * -CERT_NextSubjectCert(CERTCertificate *cert) -{ - CERTSubjectNode *node; - CERTCertificate *retcert = NULL; - - CERT_LockDB(cert->dbhandle); - - node = FindCertSubjectNode(cert); - PORT_Assert(node != NULL); - - if ( node->next != NULL ) { - retcert = CERT_FindCertByKeyNoLocking(cert->dbhandle, - &node->next->certKey); - } - - CERT_UnlockDB(cert->dbhandle); - - return(retcert); -} - -CERTCertificate * -CERT_PrevSubjectCert(CERTCertificate *cert) -{ - CERTSubjectNode *node; - CERTCertificate *retcert = NULL; - - CERT_LockDB(cert->dbhandle); - node = FindCertSubjectNode(cert); - PORT_Assert(node != NULL); - - if ( node->prev != NULL ) { - retcert = CERT_FindCertByKeyNoLocking(cert->dbhandle, - &node->prev->certKey); - } - CERT_UnlockDB(cert->dbhandle); - - return(retcert); -} - -SECStatus -CERT_SaveImportedCert(CERTCertificate *cert, SECCertUsage usage, - PRBool caOnly, char *nickname) -{ - SECStatus rv; - PRBool saveit; - CERTCertTrust trust; - CERTCertTrust tmptrust; - PRBool isCA; - unsigned int certtype; - PRBool freeNickname = PR_FALSE; - - isCA = CERT_IsCACert(cert, NULL); - if ( caOnly && ( !isCA ) ) { - return(SECSuccess); - } - - saveit = PR_TRUE; - - PORT_Memset((void *)&trust, 0, sizeof(trust)); - - certtype = cert->nsCertType; - - /* if no CA bits in cert type, then set all CA bits */ - if ( isCA && ( ! ( certtype & NS_CERT_TYPE_CA ) ) ) { - certtype |= NS_CERT_TYPE_CA; - } - - /* if no app bits in cert type, then set all app bits */ - if ( ( !isCA ) && ( ! ( certtype & NS_CERT_TYPE_APP ) ) ) { - certtype |= NS_CERT_TYPE_APP; - } - - if ( isCA && !nickname ) { - nickname = CERT_MakeCANickname(cert); - if ( nickname != NULL ) { - freeNickname = PR_TRUE; - } - } - - switch ( usage ) { - case certUsageEmailSigner: - case certUsageEmailRecipient: - if ( isCA ) { - if ( certtype & NS_CERT_TYPE_EMAIL_CA ) { - trust.emailFlags = CERTDB_VALID_CA; - } - } else { - PORT_Assert(nickname == NULL); - - if ( cert->emailAddr == NULL ) { - saveit = PR_FALSE; - } - - if ( certtype & NS_CERT_TYPE_EMAIL ) { - trust.emailFlags = CERTDB_VALID_PEER; - if ( ! ( cert->rawKeyUsage & KU_KEY_ENCIPHERMENT ) ) { - /* don't save it if KeyEncipherment is not allowed */ - saveit = PR_FALSE; - } - } - } - break; - case certUsageUserCertImport: - if ( isCA ) { - if ( certtype & NS_CERT_TYPE_SSL_CA ) { - trust.sslFlags = CERTDB_VALID_CA; - } - - if ( certtype & NS_CERT_TYPE_EMAIL_CA ) { - trust.emailFlags = CERTDB_VALID_CA; - } - - if ( certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA ) { - trust.objectSigningFlags = CERTDB_VALID_CA; - } - - } else { - if ( certtype & NS_CERT_TYPE_SSL_CLIENT ) { - trust.sslFlags = CERTDB_VALID_PEER; - } - - if ( certtype & NS_CERT_TYPE_EMAIL ) { - trust.emailFlags = CERTDB_VALID_PEER; - } - - if ( certtype & NS_CERT_TYPE_OBJECT_SIGNING ) { - trust.objectSigningFlags = CERTDB_VALID_PEER; - } - } - break; - case certUsageAnyCA: - trust.sslFlags = CERTDB_VALID_CA; - break; - case certUsageSSLCA: - trust.sslFlags = CERTDB_VALID_CA | - CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA; - break; - default: /* XXX added to quiet warnings; no other cases needed? */ - break; - } - - if ( saveit ) { - if ( cert->isperm ) { - /* Cert already in the DB. Just adjust flags */ - tmptrust = *cert->trust; - tmptrust.sslFlags |= trust.sslFlags; - tmptrust.emailFlags |= trust.emailFlags; - tmptrust.objectSigningFlags |= trust.objectSigningFlags; - - rv = CERT_ChangeCertTrust(cert->dbhandle, cert, - &tmptrust); - if ( rv != SECSuccess ) { - goto loser; - } - } else { - /* Cert not already in the DB. Add it */ - rv = CERT_AddTempCertToPerm(cert, nickname, &trust); - if ( rv != SECSuccess ) { - goto loser; - } - } - } - - rv = SECSuccess; - goto done; - -loser: - rv = SECFailure; -done: - - if ( freeNickname ) { - PORT_Free(nickname); - } - - return(rv); -} - -SECStatus -CERT_ChangeCertTrustByUsage(CERTCertDBHandle *certdb, - CERTCertificate *cert, SECCertUsage usage) -{ - SECStatus rv; - CERTCertTrust trust; - CERTCertTrust tmptrust; - unsigned int certtype; - PRBool saveit; - - saveit = PR_TRUE; - - PORT_Memset((void *)&trust, 0, sizeof(trust)); - - certtype = cert->nsCertType; - - /* if no app bits in cert type, then set all app bits */ - if ( ! ( certtype & NS_CERT_TYPE_APP ) ) { - certtype |= NS_CERT_TYPE_APP; - } - - switch ( usage ) { - case certUsageEmailSigner: - case certUsageEmailRecipient: - if ( certtype & NS_CERT_TYPE_EMAIL ) { - trust.emailFlags = CERTDB_VALID_PEER; - if ( ! ( cert->rawKeyUsage & KU_KEY_ENCIPHERMENT ) ) { - /* don't save it if KeyEncipherment is not allowed */ - saveit = PR_FALSE; - } - } - break; - case certUsageUserCertImport: - if ( certtype & NS_CERT_TYPE_EMAIL ) { - trust.emailFlags = CERTDB_VALID_PEER; - } - /* VALID_USER is already set if the cert was imported, - * in the case that the cert was already in the database - * through SMIME or other means, we should set the USER - * flags, if they are not already set. - */ - if( cert->isperm ) { - if ( certtype & NS_CERT_TYPE_SSL_CLIENT ) { - if( !(cert->trust->sslFlags & CERTDB_USER) ) { - trust.sslFlags |= CERTDB_USER; - } - } - - if ( certtype & NS_CERT_TYPE_EMAIL ) { - if( !(cert->trust->emailFlags & CERTDB_USER) ) { - trust.emailFlags |= CERTDB_USER; - } - } - - if ( certtype & NS_CERT_TYPE_OBJECT_SIGNING ) { - if( !(cert->trust->objectSigningFlags & CERTDB_USER) ) { - trust.objectSigningFlags |= CERTDB_USER; - } - } - } - break; - default: /* XXX added to quiet warnings; no other cases needed? */ - break; - } - - if ( (trust.sslFlags | trust.emailFlags | trust.objectSigningFlags) == 0 ){ - saveit = PR_FALSE; - } - - if ( saveit && cert->isperm ) { - /* Cert already in the DB. Just adjust flags */ - tmptrust = *cert->trust; - tmptrust.sslFlags |= trust.sslFlags; - tmptrust.emailFlags |= trust.emailFlags; - tmptrust.objectSigningFlags |= trust.objectSigningFlags; - - rv = CERT_ChangeCertTrust(cert->dbhandle, cert, - &tmptrust); - if ( rv != SECSuccess ) { - goto loser; - } - } - - rv = SECSuccess; - goto done; - -loser: - rv = SECFailure; -done: - - return(rv); -} - -int -CERT_GetDBContentVersion(CERTCertDBHandle *handle) -{ - certDBEntryContentVersion *entry; - int ret; - - entry = ReadDBContentVersionEntry(handle); - - if ( entry == NULL ) { - return(0); - } - - ret = entry->contentVersion; - - DestroyDBEntry((certDBEntry *)entry); - - return(ret); -} - -void -CERT_SetDBContentVersion(int version, CERTCertDBHandle *handle) -{ - SECStatus rv; - certDBEntryContentVersion *entry; - - entry = NewDBContentVersionEntry(0); - - if ( entry == NULL ) { - return; - } - - rv = DeleteDBContentVersionEntry(handle); - rv = WriteDBContentVersionEntry(handle, entry); - - DestroyDBEntry((certDBEntry *)entry); - - return; -} - -/* - * Creates or adds to a list of all certs with a give subject name, sorted by - * validity time, newest first. Invalid certs are considered older than - * valid certs. If validOnly is set, do not include invalid certs on list. - */ -CERTCertList * -CERT_CreateSubjectCertList(CERTCertList *certList, CERTCertDBHandle *handle, - SECItem *name, int64 sorttime, PRBool validOnly) -{ - CERTCertificate *cert = NULL; - CERTSubjectList *subjectList = NULL; - CERTSubjectNode *node; - SECStatus rv; - - if ( certList == NULL ) { - certList = CERT_NewCertList(); - } - - if ( certList == NULL ) { - goto loser; - } - - subjectList = FindSubjectList(handle, name, PR_FALSE); - - if ( subjectList != NULL ) { - node = subjectList->head; - PORT_Assert(node); - while (node) { - cert = CERT_FindCertByKey(handle, &node->certKey); - - /* if validOnly, then check validity period before adding to list*/ - if ( ( !validOnly ) || - ( CERT_CheckCertValidTimes(cert, sorttime, PR_FALSE) - == secCertTimeValid ) ) { - rv = CERT_AddCertToListSorted(certList, cert, - CERT_SortCBValidity, - (void *)&sorttime); - if ( rv != SECSuccess ) { - CERT_DestroyCertificate(cert); - goto loser; - } - } else { - CERT_DestroyCertificate(cert); - } - - node = node->next; - } - } - - return(certList); - -loser: - if ( certList != NULL ) { - CERT_DestroyCertList(certList); - } - - return(NULL); -} - -/* - * Creates or adds to a list of all certs with a give nickname, sorted by - * validity time, newest first. Invalid certs are considered older than valid - * certs. If validOnly is set, do not include invalid certs on list. - */ -CERTCertList * -CERT_CreateNicknameCertList(CERTCertList *certList, CERTCertDBHandle *handle, - char *nickname, int64 sorttime, PRBool validOnly) -{ - CERTCertificate *cert; - CERTCertList *ret; - - cert = CERT_FindCertByNickname(handle, nickname); - if ( cert == NULL ) { - return(NULL); - } - - ret = CERT_CreateSubjectCertList(certList, handle, &cert->derSubject, - sorttime, validOnly); - - CERT_DestroyCertificate(cert); - - return(ret); -} - -/* - * Creates or adds to a list of all certs with a give email addr, sorted by - * validity time, newest first. Invalid certs are considered older than valid - * certs. If validOnly is set, do not include invalid certs on list. - */ -CERTCertList * -CERT_CreateEmailAddrCertList(CERTCertList *certList, CERTCertDBHandle *handle, - char *emailAddr, int64 sorttime, PRBool validOnly) -{ - CERTCertificate *cert; - CERTCertList *ret; - - cert = CERT_FindCertByEmailAddr(handle, emailAddr); - if ( cert == NULL ) { - return(NULL); - } - - ret = CERT_CreateSubjectCertList(certList, handle, &cert->derSubject, - sorttime, validOnly); - - CERT_DestroyCertificate(cert); - - return(ret); -} diff --git a/security/nss/lib/certdb/stanpcertdb.c b/security/nss/lib/certdb/stanpcertdb.c index 115442853..fca67551f 100644 --- a/security/nss/lib/certdb/stanpcertdb.c +++ b/security/nss/lib/certdb/stanpcertdb.c @@ -51,109 +51,16 @@ #include "plhash.h" #include "pk11func.h" /* sigh */ -#include "cdbhdl.h" - #ifndef NSS_3_4_CODE #define NSS_3_4_CODE #endif /* NSS_3_4_CODE */ #include "nsspki.h" #include "pkit.h" #include "pkim.h" -#include "pkinss3hack.h" +#include "pki3hack.h" #include "ckhelper.h" #include "base.h" -struct stan_cert_callback_str { - CERTCertCallback callback; - void *arg; -}; - -/* Translate from NSSCertificate to CERTCertificate, then pass the latter - * to a callback. - */ -static PRStatus convert_cert(NSSCertificate *c, void *arg) -{ - CERTCertificate *nss3cert; - SECStatus secrv; - struct stan_cert_callback_str *scba = (struct stan_cert_callback_str *)arg; - nss3cert = STAN_GetCERTCertificate(c); - if (!nss3cert) return PR_FAILURE; - secrv = (*scba->callback)(nss3cert, scba->arg); - CERT_DestroyCertificate(nss3cert); - return (secrv) ? PR_FAILURE : PR_SUCCESS; -} - -struct stan_cert_der_callback_str { - SECStatus (* callback)(CERTCertificate *cert, SECItem *k, void *pdata); - void *arg; -}; - -/* Translate from NSSCertificate to CERTCertificate, then pass the latter - * to a callback. - */ -static PRStatus convert_cert_der(NSSCertificate *c, void *arg) -{ - CERTCertificate *nss3cert; - SECStatus secrv; - SECItem certKey; - struct stan_cert_der_callback_str *scdba = - (struct stan_cert_der_callback_str *)arg; - nss3cert = STAN_GetCERTCertificate(c); - if (!nss3cert) return PR_FAILURE; - SECITEM_FROM_NSSITEM(&certKey, &c->encoding); - secrv = (*scdba->callback)(nss3cert, &certKey, scdba->arg); - CERT_DestroyCertificate(nss3cert); - return (secrv) ? PR_FAILURE : PR_SUCCESS; -} - - -SECStatus -__CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle, - SECItem *derSubject, - CERTCertCallback cb, void *cbarg) -{ - struct stan_cert_callback_str scba; - PRStatus nssrv; - NSSDER subject; - scba.callback = cb; - scba.arg = cbarg; - NSSITEM_FROM_SECITEM(&subject, derSubject); - nssrv = nssTrustDomain_TraverseCertificatesBySubject(handle, - &subject, - convert_cert, - &scba); - return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; -} - -SECStatus -CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle, SECItem *derSubject, - CERTCertCallback cb, void *cbarg) -{ - return(__CERT_TraversePermCertsForSubject(handle, derSubject, cb, cbarg)); -} - -SECStatus -__CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname, - CERTCertCallback cb, void *cbarg) -{ - struct stan_cert_callback_str scba; - PRStatus nssrv; - scba.callback = cb; - scba.arg = cbarg; - nssrv = nssTrustDomain_TraverseCertificatesByNickname(handle, - (NSSUTF8 *)nickname, - convert_cert, - &scba); - return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; -} - -SECStatus -CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname, - CERTCertCallback cb, void *cbarg) -{ - return(__CERT_TraversePermCertsForNickname(handle, nickname, cb, cbarg)); -} - PRBool SEC_CertNicknameConflict(char *nickname, SECItem *derSubject, CERTCertDBHandle *handle) @@ -172,33 +79,6 @@ SEC_DeletePermCertificate(CERTCertificate *cert) } SECStatus -SEC_TraversePermCerts(CERTCertDBHandle *handle, - SECStatus (* certfunc)(CERTCertificate *cert, SECItem *k, - void *pdata), - void *udata ) -{ - struct stan_cert_der_callback_str scdba; - PRStatus nssrv; - scdba.callback = certfunc; - scdba.arg = udata; - nssrv = nssTrustDomain_TraverseCertificates(handle, - convert_cert_der, &scdba); - return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; -} - -void -__CERT_ClosePermCertDB(CERTCertDBHandle *handle) -{ - /* XXX do anything? */ -} - -void -CERT_ClosePermCertDB(CERTCertDBHandle *handle) -{ - __CERT_ClosePermCertDB(handle); -} - -SECStatus CERT_GetCertTrust(CERTCertificate *cert, CERTCertTrust *trust) { SECStatus rv; @@ -227,12 +107,12 @@ SECStatus CERT_ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert, CERTCertTrust *trust) { - SECStatus ret; - CERT_LockDB(handle); + SECStatus rv = SECFailure; + PRStatus ret; + CERT_LockCertTrust(cert); /* only set the trust on permanent certs */ if ( cert->trust == NULL ) { - ret = SECFailure; goto done; } if (PK11_IsReadOnly(cert->slot)) { @@ -240,13 +120,13 @@ CERT_ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert, /* XXX store it on a writeable token */ goto done; } else { - STAN_ChangeCertTrust(cert->nssCertificate, trust); + NSSCertificate *c = STAN_GetNSSCertificate(cert); + ret = STAN_ChangeCertTrust(c, trust); + rv = (ret == PR_SUCCESS) ? SECSuccess : SECFailure; } - ret = SECSuccess; done: CERT_UnlockCertTrust(cert); - CERT_UnlockDB(handle); - return(ret); + return rv; } SECStatus @@ -254,9 +134,12 @@ CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, CERTCertTrust *trust) { NSSCertificate *c = STAN_GetNSSCertificate(cert); +#ifdef notdef /* might as well keep these */ + /* actually we shouldn't keep these! rjr */ PORT_Assert(cert->istemp); PORT_Assert(!cert->isperm); +#endif if (SEC_CertNicknameConflict(nickname, &cert->derSubject, cert->dbhandle)){ return SECFailure; } @@ -277,20 +160,6 @@ CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, return SECFailure; } -SECStatus -CERT_OpenCertDBFilename(CERTCertDBHandle *handle, char *certdbname, - PRBool readOnly) -{ - /* XXX what to do here? */ -} - -/* only for jarver.c */ -SECStatus -SEC_AddTempNickname(CERTCertDBHandle *handle, char *nickname, - SECItem *subjectName) -{ -} - CERTCertificate * __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, char *nickname, PRBool isperm, PRBool copyDER) @@ -329,10 +198,11 @@ __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, PORT_Strlen(cc->emailAddr)); } c->trustDomain = handle; + cc->dbhandle = handle; nssTrustDomain_AddCertsToCache(handle, &c, 1); cc->istemp = 1; cc->isperm = 0; - /* XXX if !copyDER destroy it? */ + return cc; loser: nssArena_Destroy(arena); @@ -348,26 +218,18 @@ CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, } /* maybe all the wincx's should be some const for internal token login? */ - -CERTCertificate * -CERT_FindCertByKey(CERTCertDBHandle *handle, SECItem *certKey) -{ -} - -/* - * Lookup a certificate in the databases without locking - */ -CERTCertificate * -CERT_FindCertByKeyNoLocking(CERTCertDBHandle *handle, SECItem *certKey) -{ - return(CERT_FindCertByKey(handle, certKey)); -} - CERTCertificate * CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndSN) { PK11SlotInfo *slot; - return PK11_FindCertByIssuerAndSN(&slot, issuerAndSN, NULL); + CERTCertificate *cert; + + cert = PK11_FindCertByIssuerAndSN(&slot,issuerAndSN,NULL); + if (slot) { + PK11_FreeSlot(slot); + } + + return cert; } CERTCertificate * @@ -383,10 +245,23 @@ CERT_FindCertByName(CERTCertDBHandle *handle, SECItem *name) return STAN_GetCERTCertificate(c); } -/* this one is gonna be tough ... looks like traversal */ CERTCertificate * CERT_FindCertByKeyID(CERTCertDBHandle *handle, SECItem *name, SECItem *keyID) { + CERTCertList *list = + CERT_CreateSubjectCertList(NULL,handle,name,0,PR_FALSE); + CERTCertificate *cert = NULL; + CERTCertListNode *node = CERT_LIST_HEAD(list); + + if (list == NULL) return NULL; + + for (node = CERT_LIST_HEAD(list); node ; node = CERT_LIST_NEXT(node)) { + if (SECITEM_ItemsAreEqual(&cert->subjectKeyID, keyID) ) { + cert = CERT_DupCertificate(node->cert); + break; + } + } + return cert; } CERTCertificate * @@ -468,12 +343,6 @@ loser: return NULL; } -SECStatus -CERT_DeleteTempCertificate(CERTCertificate *cert) -{ - /* remove from cache */ -} - void CERT_DestroyCertificate(CERTCertificate *cert) { @@ -488,7 +357,7 @@ CERT_DestroyCertificate(CERTCertificate *cert) if ( ( refCount == 0 ) && !cert->keepSession ) { PRArenaPool *arena = cert->arena; if ( cert->istemp ) { - CERT_DeleteTempCertificate(cert); + /* uncache the cert ? */ } /* delete the NSSCertificate */ /* zero cert before freeing. Any stale references to this cert @@ -502,144 +371,7 @@ CERT_DestroyCertificate(CERTCertificate *cert) return; } -SECStatus -CERT_SaveImportedCert(CERTCertificate *cert, SECCertUsage usage, - PRBool caOnly, char *nickname) -{ - SECStatus rv; - PRBool saveit; - CERTCertTrust trust; - CERTCertTrust tmptrust; - PRBool isCA; - unsigned int certtype; - PRBool freeNickname = PR_FALSE; - - isCA = CERT_IsCACert(cert, NULL); - if ( caOnly && ( !isCA ) ) { - return(SECSuccess); - } - - saveit = PR_TRUE; - - PORT_Memset((void *)&trust, 0, sizeof(trust)); - - certtype = cert->nsCertType; - - /* if no CA bits in cert type, then set all CA bits */ - if ( isCA && ( ! ( certtype & NS_CERT_TYPE_CA ) ) ) { - certtype |= NS_CERT_TYPE_CA; - } - - /* if no app bits in cert type, then set all app bits */ - if ( ( !isCA ) && ( ! ( certtype & NS_CERT_TYPE_APP ) ) ) { - certtype |= NS_CERT_TYPE_APP; - } - - if ( isCA && !nickname ) { - nickname = CERT_MakeCANickname(cert); - if ( nickname != NULL ) { - freeNickname = PR_TRUE; - } - } - - switch ( usage ) { - case certUsageEmailSigner: - case certUsageEmailRecipient: - if ( isCA ) { - if ( certtype & NS_CERT_TYPE_EMAIL_CA ) { - trust.emailFlags = CERTDB_VALID_CA; - } - } else { - PORT_Assert(nickname == NULL); - - if ( cert->emailAddr == NULL ) { - saveit = PR_FALSE; - } - - if ( certtype & NS_CERT_TYPE_EMAIL ) { - trust.emailFlags = CERTDB_VALID_PEER; - if ( ! ( cert->rawKeyUsage & KU_KEY_ENCIPHERMENT ) ) { - /* don't save it if KeyEncipherment is not allowed */ - saveit = PR_FALSE; - } - } - } - break; - case certUsageUserCertImport: - if ( isCA ) { - if ( certtype & NS_CERT_TYPE_SSL_CA ) { - trust.sslFlags = CERTDB_VALID_CA; - } - - if ( certtype & NS_CERT_TYPE_EMAIL_CA ) { - trust.emailFlags = CERTDB_VALID_CA; - } - - if ( certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA ) { - trust.objectSigningFlags = CERTDB_VALID_CA; - } - - } else { - if ( certtype & NS_CERT_TYPE_SSL_CLIENT ) { - trust.sslFlags = CERTDB_VALID_PEER; - } - - if ( certtype & NS_CERT_TYPE_EMAIL ) { - trust.emailFlags = CERTDB_VALID_PEER; - } - - if ( certtype & NS_CERT_TYPE_OBJECT_SIGNING ) { - trust.objectSigningFlags = CERTDB_VALID_PEER; - } - } - break; - case certUsageAnyCA: - trust.sslFlags = CERTDB_VALID_CA; - break; - case certUsageSSLCA: - trust.sslFlags = CERTDB_VALID_CA | - CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA; - break; - default: /* XXX added to quiet warnings; no other cases needed? */ - break; - } - - if ( saveit ) { - if ( cert->isperm ) { - /* Cert already in the DB. Just adjust flags */ - tmptrust = *cert->trust; - tmptrust.sslFlags |= trust.sslFlags; - tmptrust.emailFlags |= trust.emailFlags; - tmptrust.objectSigningFlags |= trust.objectSigningFlags; - - rv = CERT_ChangeCertTrust(cert->dbhandle, cert, - &tmptrust); - if ( rv != SECSuccess ) { - goto loser; - } - } else { - /* Cert not already in the DB. Add it */ - rv = CERT_AddTempCertToPerm(cert, nickname, &trust); - if ( rv != SECSuccess ) { - goto loser; - } - } - } - - rv = SECSuccess; - goto done; - -loser: - rv = SECFailure; -done: - - if ( freeNickname ) { - PORT_Free(nickname); - } - - return(rv); -} - +#ifdef notdef SECStatus CERT_ChangeCertTrustByUsage(CERTCertDBHandle *certdb, CERTCertificate *cert, SECCertUsage usage) @@ -732,11 +464,13 @@ done: return(rv); } +#endif int CERT_GetDBContentVersion(CERTCertDBHandle *handle) { - /* do anything? */ + /* should read the DB content version from the pkcs #11 device */ + return 0; } /* @@ -749,649 +483,135 @@ SECStatus CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile, SECItem *profileTime) { -} - -SECItem * -CERT_FindSMimeProfile(CERTCertificate *cert) -{ -} - -/* - * - * Manage CRL's - * - */ - -/* only for crlutil.c */ -CERTSignedCrl * -SEC_FindCrlByKey(CERTCertDBHandle *handle, SECItem *crlKey, int type) -{ -} - -CERTSignedCrl * -SEC_FindCrlByName(CERTCertDBHandle *handle, SECItem *crlKey, int type) -{ -} - -SECStatus -SEC_DestroyCrl(CERTSignedCrl *crl) -{ -} - -CERTSignedCrl * -cert_DBInsertCRL (CERTCertDBHandle *handle, char *url, - CERTSignedCrl *newCrl, SECItem *derCrl, int type) -{ - CERTSignedCrl *oldCrl = NULL, *crl = NULL; - PRArenaPool *arena = NULL; - SECCertTimeValidity validity; - /* - certDBEntryType crlType = (type == SEC_CRL_TYPE) ? - certDBEntryTypeRevocation : certDBEntryTypeKeyRevocation; - */ - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) goto done; - - validity = SEC_CheckCrlTimes(&newCrl->crl,PR_Now()); - if ( validity == secCertTimeExpired) { - if (type == SEC_CRL_TYPE) { - PORT_SetError(SEC_ERROR_CRL_EXPIRED); - } else { - PORT_SetError(SEC_ERROR_KRL_EXPIRED); - } - goto done; - } else if (validity == secCertTimeNotValidYet) { - if (type == SEC_CRL_TYPE) { - PORT_SetError(SEC_ERROR_CRL_NOT_YET_VALID); - } else { - PORT_SetError(SEC_ERROR_KRL_NOT_YET_VALID); - } - goto done; + int64 oldtime; + int64 newtime; + SECStatus rv = SECFailure; + PRBool saveit; + char *emailAddr; + SECItem *oldProfile = NULL; + SECItem *oldProfileTime = NULL; + PK11SlotInfo *slot = NULL; + + emailAddr = cert->emailAddr; + + PORT_Assert(emailAddr); + if ( emailAddr == NULL ) { + goto loser; } - oldCrl = SEC_FindCrlByKey(handle, &newCrl->crl.derName, type); - - /* if there is an old crl, make sure the one we are installing - * is newer. If not, exit out, otherwise delete the old crl. - */ - if (oldCrl != NULL) { - if (!SEC_CrlIsNewer(&newCrl->crl,&oldCrl->crl)) { - - if (type == SEC_CRL_TYPE) { - PORT_SetError(SEC_ERROR_OLD_CRL); + saveit = PR_FALSE; + + oldProfile = PK11_FindSMimeProfile(&slot, emailAddr, &cert->derSubject, + &oldProfileTime); + + /* both profileTime and emailProfile have to exist or not exist */ + if ( emailProfile == NULL ) { + profileTime = NULL; + } else if ( profileTime == NULL ) { + emailProfile = NULL; + } + + if ( oldProfileTime == NULL ) { + saveit = PR_TRUE; + } else { + /* there was already a profile for this email addr */ + if ( profileTime ) { + /* we have an old and new profile - save whichever is more recent*/ + if ( oldProfileTime->len == 0 ) { + /* always replace if old entry doesn't have a time */ + oldtime = LL_MININT; } else { - PORT_SetError(SEC_ERROR_OLD_KRL); + rv = DER_UTCTimeToTime(&oldtime, oldProfileTime); + if ( rv != SECSuccess ) { + goto loser; + } } - - goto done; - } - - if ((SECITEM_CompareItem(&newCrl->crl.derName, - &oldCrl->crl.derName) != SECEqual) && - (type == SEC_KRL_TYPE) ) { - PORT_SetError(SEC_ERROR_CKL_CONFLICT); - goto done; - } - - /* if we have a url in the database, use that one */ - if (oldCrl->url) { - int nnlen = PORT_Strlen(oldCrl->url) + 1; - url = (char *)PORT_ArenaAlloc(arena, nnlen); - if ( url != NULL ) { - PORT_Memcpy(url, oldCrl->url, nnlen); + rv = DER_UTCTimeToTime(&newtime, profileTime); + if ( rv != SECSuccess ) { + goto loser; + } + + if ( LL_CMP(newtime, >, oldtime ) ) { + /* this is a newer profile, save it and cert */ + saveit = PR_TRUE; } - } - - - /* really destroy this crl */ - /* first drum it out of the permanment Data base */ - SEC_DeletePermCRL(oldCrl); - /* then get rid of our reference to it... */ - SEC_DestroyCrl(oldCrl); - oldCrl = NULL; - - } - - /* Write the new entry into the data base */ -#ifdef KNOW_HOW_TO_WRITE_CRL_TO_TOKEN - entry = NewDBCrlEntry(derCrl, url, crlType, 0); - if (entry == NULL) goto done; - - rv = WriteDBCrlEntry(handle, entry); - if (rv != SECSuccess) goto done; - - crl = SEC_AddPermCrlToTemp(handle, entry); - if (crl) entry = NULL; /*crl->dbEntry now points to entry data */ - crl->isperm = PR_TRUE; -#endif /* KNOW_HOW_TO_WRITE_CRL_TO_TOKEN */ - -done: - if (arena) PORT_FreeArena(arena, PR_FALSE); - if (oldCrl) SEC_DestroyCrl(oldCrl); - - return crl; -} - - -/* - * create a new CRL from DER material. - * - * The signature on this CRL must be checked before you - * load it. ??? - */ -CERTSignedCrl * -SEC_NewCrl(CERTCertDBHandle *handle, char *url, SECItem *derCrl, int type) -{ - CERTSignedCrl *newCrl = NULL, *crl = NULL; - - /* make this decode dates! */ - newCrl = CERT_DecodeDERCrl(NULL, derCrl, type); - if (newCrl == NULL) { - if (type == SEC_CRL_TYPE) { - PORT_SetError(SEC_ERROR_CRL_INVALID); } else { - PORT_SetError(SEC_ERROR_KRL_INVALID); + saveit = PR_TRUE; } - goto done; } - crl = cert_DBInsertCRL (handle, url, newCrl, derCrl, type); - - -done: - if (newCrl) PORT_FreeArena(newCrl->arena, PR_FALSE); - - return crl; -} - -SECStatus -SEC_LookupCrls(CERTCertDBHandle *handle, CERTCrlHeadNode **nodes, int type) -{ -} - -SECStatus -SEC_DeletePermCRL(CERTSignedCrl *crl) -{ -} -/* - * - * SPK Digest code, unmodified from pcertdb.c - * - */ - -/* - * The following is bunch of types and code to allow looking up a certificate - * by a hash of its subject public key. Because the words "hash" and "key" - * are overloaded and thus terribly confusing, I tried to disambiguate things. - * - Where I could, I used "digest" instead of "hash" when referring to - * hashing of the subject public key. The PLHashTable interfaces and - * our own HASH_Foo interfaces had to be left as is, obviously. The latter - * should be thought of as "digest" in this case. - * - There are three keys in use here -- the subject public key, the key - * used to do a lookup in the PLHashTable, and the key used to do a lookup - * in the cert database. As the latter is a fairly pervasive interface, - * I left it alone. The other two uses I changed to "spk" or "SPK" when - * referring to the subject public key, and "index" when referring to the - * key into the PLHashTable. - */ - -typedef struct SPKDigestInfoStr { - PLHashTable *table; - PRBool permPopulated; -} SPKDigestInfo; - -/* - * Since the key hash information is "hidden" (in a void pointer in the handle) - * these macros with the appropriate casts make it easy to get at the parts. - */ -#define SPK_DIGEST_TABLE(handle) \ - (((SPKDigestInfo *)(handle->spkDigestInfo))->table) - -/* -** Hash allocator ops for the SPKDigest hash table. The rules are: -** + The index and value fields are "owned" by the hash table, and are -** freed when the table entry is deleted. -** + Replacing a value in the table is not allowed, since the caller can't -** tell whether the index field was used or not, resulting in a memory -** leak. (This is a bug in the PL_Hash routines. -*/ -static void * PR_CALLBACK -spkAllocTable(void *pool, PRSize size) -{ -#if defined(XP_MAC) -#pragma unused (pool) -#endif - return PR_MALLOC(size); -} - -static void PR_CALLBACK -spkFreeTable(void *pool, void *item) -{ -#if defined(XP_MAC) -#pragma unused (pool) -#endif - PR_Free(item); -} - -/* NOTE: the key argument here appears to be useless, since the RawAdd - * routine in PL_Hash just uses the original anyway. - */ -static PLHashEntry * PR_CALLBACK -spkAllocEntry(void *pool, const void *key) -{ -#if defined(XP_MAC) -#pragma unused (pool,key) -#endif - return PR_NEW(PLHashEntry); -} - -static void PR_CALLBACK -spkFreeEntry(void *pool, PLHashEntry *he, PRUintn flag) -{ -#if defined(XP_MAC) -#pragma unused (pool) -#endif - SECItem *value = (SECItem *)he->value; - /* The flag should always be to free the whole entry. Otherwise the - * index field gets leaked because the caller can't tell whether - * the "new" value (which is the same as the old) was used or not. - */ - PORT_Assert(flag == HT_FREE_ENTRY); - /* We always free the value */ - SECITEM_FreeItem(value, PR_TRUE); - if (flag == HT_FREE_ENTRY) - { - /* Comes from BTOA, is this the right free call? */ - PORT_Free((char *)he->key); - PR_Free(he); + if (saveit) { + rv = PK11_SaveSMimeProfile(slot, emailAddr, &cert->derSubject, + emailProfile, profileTime); + } else { + rv = SECSuccess; } -} - -static PLHashAllocOps spkHashAllocOps = { - spkAllocTable, spkFreeTable, - spkAllocEntry, spkFreeEntry -}; -/* - * Create the key hash lookup table. Note that the table, and the - * structure which holds it and a little more information, is never freed. - * This is because the temporary database is never actually closed out, - * so there is no safe/obvious place to free the whole thing. - * - * The database must be locked already. - */ -static SECStatus -InitDBspkDigestInfo(CERTCertDBHandle *handle) -{ - SPKDigestInfo *spkDigestInfo; - PLHashTable *table; - PORT_Assert(handle != NULL); - PORT_Assert(handle->spkDigestInfo == NULL); - spkDigestInfo = PORT_ZAlloc(sizeof(SPKDigestInfo)); - if ( spkDigestInfo == NULL ) { - return(SECFailure); - } - table = PL_NewHashTable(128, PL_HashString, PL_CompareStrings, - (PLHashComparator) SECITEM_ItemsAreEqual, - &spkHashAllocOps, NULL); - if ( table == NULL ) { - PORT_Free(spkDigestInfo); - return(SECFailure); +loser: + if (oldProfile) { + SECITEM_FreeItem(oldProfile,PR_TRUE); } - spkDigestInfo->table = table; - handle->spkDigestInfo = spkDigestInfo; - return(SECSuccess); -} - -static const SECHashObject * -OidTagToRawDigestObject(SECOidTag digestAlg) -{ - const SECHashObject *rawDigestObject; - switch (digestAlg) { - case SEC_OID_MD2: - rawDigestObject = &SECRawHashObjects[HASH_AlgMD2]; - break; - case SEC_OID_MD5: - rawDigestObject = &SECRawHashObjects[HASH_AlgMD5]; - break; - case SEC_OID_SHA1: - rawDigestObject = &SECRawHashObjects[HASH_AlgSHA1]; - break; - default: - PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); - rawDigestObject = NULL; - break; + if (oldProfileTime) { + SECITEM_FreeItem(oldProfileTime,PR_TRUE); } - return(rawDigestObject); + + return(rv); } -/* - * Digest the cert's subject public key using the specified algorithm. - * The necessary storage for the digest data is allocated. If "fill" is - * non-null, the data is put there, otherwise a SECItem is allocated. - * Allocation from "arena" if it is non-null, heap otherwise. Any problem - * results in a NULL being returned (and an appropriate error set). - */ SECItem * -CERT_SPKDigestValueForCert(PRArenaPool *arena, CERTCertificate *cert, - SECOidTag digestAlg, SECItem *fill) -{ - const SECHashObject *digestObject; - void *digestContext; - SECItem *result = NULL; - void *mark = NULL; - SECItem spk; - if ( arena != NULL ) { - mark = PORT_ArenaMark(arena); - } - /* - * This can end up being called before PKCS #11 is initialized, - * so we have to use the raw digest functions. - */ - digestObject = OidTagToRawDigestObject(digestAlg); - if ( digestObject == NULL ) { - goto loser; - } - result = SECITEM_AllocItem(arena, fill, digestObject->length); - if ( result == NULL ) { - goto loser; - } - /* - * Copy just the length and data pointer (nothing needs to be freed) - * of the subject public key so we can convert the length from bits - * to bytes, which is what the digest function expects. - */ - spk = cert->subjectPublicKeyInfo.subjectPublicKey; - DER_ConvertBitString(&spk); - /* - * Now digest the value, using the specified algorithm. - */ - digestContext = digestObject->create(); - if ( digestContext == NULL ) { - goto loser; - } - digestObject->begin(digestContext); - digestObject->update(digestContext, spk.data, spk.len); - digestObject->end(digestContext, result->data, &(result->len), result->len); - digestObject->destroy(digestContext, PR_TRUE); - if ( arena != NULL ) { - PORT_ArenaUnmark(arena, mark); - } - return(result); -loser: - if ( arena != NULL ) { - PORT_ArenaRelease(arena, mark); - } else { - if ( result != NULL ) { - SECITEM_FreeItem(result, (fill == NULL) ? PR_TRUE : PR_FALSE); - } - } - return(NULL); -} - -/* - * Return the index for the spk digest lookup table for "spkDigest". - * - * Caller is responsible for freeing the returned string. - */ -static char * -spkDigestIndexFromDigest(SECItem *spkDigest) +CERT_FindSMimeProfile(CERTCertificate *cert) { - return BTOA_ConvertItemToAscii(spkDigest); + return + PK11_FindSMimeProfile(NULL, cert->emailAddr, &cert->derSubject, NULL); } /* - * Return the index for the spk digest lookup table for this certificate, - * based on the specified digest algorithm. - * - * Caller is responsible for freeing the returned string. + * depricated functions that are now just stubs. */ -static char * -spkDigestIndexFromCert(CERTCertificate *cert, SECOidTag digestAlg) -{ - SECItem *spkDigest; - char *index; - spkDigest = CERT_SPKDigestValueForCert(NULL, cert, digestAlg, NULL); - if ( spkDigest == NULL ) - return(NULL); - index = spkDigestIndexFromDigest(spkDigest); - SECITEM_FreeItem(spkDigest, PR_TRUE); - return(index); -} - /* - * Add the spk digest for the given cert to the spk digest table, - * based on the given digest algorithm. - * - * If a cert for the same spk digest is already in the table, choose whichever - * cert is "newer". (The other cert cannot be found via spk digest.) - * - * The database must be locked already. - * - * XXX Note that this implementation results in leaking the index value. - * Fixing that did not seem worth the trouble, given we will only leak - * once per cert. This whole thing should be done differently in the - * new rewrite (Stan), and then the problem will go away. + * Close the database */ -static SECStatus -AddCertToSPKDigestTableForAlg(CERTCertDBHandle *handle, CERTCertificate *cert, - SECItem *certDBKey, SECOidTag digestAlg) +void +__CERT_ClosePermCertDB(CERTCertDBHandle *handle) { - SECStatus rv = SECFailure; - SECItem *oldCertDBKey; - PRBool addit = PR_TRUE; - CERTCertificate *oldCert = NULL; - char *index = NULL; - PLHashTable *table; - /* - * After running some testing doing key hash lookups (like using OCSP), - * if these are never hit, they can probably be removed. - */ - PORT_Assert(handle != NULL); - PORT_Assert(handle == cert->dbhandle); - PORT_Assert(handle->spkDigestInfo != NULL); - PORT_Assert((certDBKey == &cert->certKey) - || (SECITEM_CompareItem(certDBKey, - &cert->certKey) == SECEqual)); - table = SPK_DIGEST_TABLE(handle); - PORT_Assert(table != NULL); - index = spkDigestIndexFromCert(cert, digestAlg); - if ( index == NULL ) { - goto loser; - } - /* - * See if this cert's spk digest is already in the table. - */ - oldCertDBKey = PL_HashTableLookup(table, index); - if ( oldCertDBKey != NULL ) { - /* - * The spk digest *is* already in the table. We need to find that - * cert and see -- if it is the same, then we can just leave as is. - * Otherwise we have to choose which cert we want represented; - * in that case the best plan I can think of is to hang onto the - * most recent one. - */ - oldCert = CERT_FindCertByKey(handle, oldCertDBKey); - if ( oldCert != NULL ) { - if ( cert == oldCert ) { - /* They are the same cert, so we are done. */ - addit = PR_FALSE; - } else if ( CERT_IsNewer(cert, oldCert) ) { - if ( PL_HashTableRemove(table, index) != PR_TRUE ) { - goto loser; - } - } else { - /* oldCert is "newer", so we are done. */ - addit = PR_FALSE; - } - } - } - if ( addit ) { - certDBKey = SECITEM_DupItem(certDBKey); - if ( certDBKey == NULL ) { - goto loser; - } - if ( PL_HashTableAdd(table, index, certDBKey) == NULL ) { - SECITEM_FreeItem(certDBKey, PR_TRUE); - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - index = NULL; /* don't want to free it */ - } - rv = SECSuccess; -loser: - if ( index != NULL ) { - PORT_Free(index); - } - if ( oldCert != NULL ) { - CERT_DestroyCertificate(oldCert); - } - return(rv); + PORT_Assert("CERT_ClosePermCertDB is Depricated" == NULL); + return; } -/* - * Add the spk digest for the given cert to the spk digest table, - * for all known digest algorithms. - * - * The database must be locked already, and the digest table already created. - */ -static SECStatus -AddCertToSPKDigestTableForAllAlgs(CERTCertDBHandle *handle, - CERTCertificate *cert, SECItem *certDBKey) +SECStatus +CERT_OpenCertDBFilename(CERTCertDBHandle *handle, char *certdbname, + PRBool readOnly) { - (void) AddCertToSPKDigestTableForAlg(handle, cert, certDBKey, SEC_OID_MD2); - (void) AddCertToSPKDigestTableForAlg(handle, cert, certDBKey, SEC_OID_MD5); - return AddCertToSPKDigestTableForAlg(handle, cert, certDBKey, SEC_OID_SHA1); + PORT_Assert("CERT_OpenCertDBFilename is Depricated" == NULL); + return SECFailure; } -/* - * Add the spk digest for the given cert to the spk digest table, - * for all known digest algorithms. This function is called while - * traversing all of the certs in the permanent database -- since - * that imposes some constraints on its arguments this routine is a - * simple cover for the "real" interface. - * - * The database must be locked already, and the digest table already created. - */ -static SECStatus -AddCertToSPKDigestTableInTraversal(CERTCertificate *cert, SECItem *certDBKey, - void *data) +SECItem * +SECKEY_HashPassword(char *pw, SECItem *salt) { - CERTCertDBHandle *handle = data; - return AddCertToSPKDigestTableForAllAlgs(handle, cert, certDBKey); + PORT_Assert("SECKEY_HashPassword is Depricated" == NULL); + return NULL; } -/* - * Add the spk digests for the all permanent certs to the spk digest table, - * for all known digest algorithms. - * - * This locks the database, and then checks to make sure that the work - * actually needs to get done. - * - * If the spk digest table does not yet exist, it is created. - */ -static SECStatus -PopulateSPKDigestTable(CERTCertDBHandle *handle) +SECStatus +__CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle, + SECItem *derSubject, + void *cb, void *cbarg) { - SPKDigestInfo *spkDigestInfo; - SECStatus rv = SECSuccess; - CERT_LockDB(handle); - spkDigestInfo = handle->spkDigestInfo; - if ( spkDigestInfo == NULL ) { - rv = InitDBspkDigestInfo(handle); - if ( rv != SECSuccess ) { - return(rv); - } - spkDigestInfo = handle->spkDigestInfo; - PORT_Assert(spkDigestInfo != NULL); - } else { - /* - * Check to see if someone already did it; it is important to do - * this after getting the lock. - */ - if ( spkDigestInfo->permPopulated == PR_TRUE ) { - goto done; - } - } - rv = SEC_TraversePermCerts(handle, AddCertToSPKDigestTableInTraversal, - handle); - if ( rv != SECSuccess ) { - goto done; - } - spkDigestInfo->permPopulated = PR_TRUE; -done: - CERT_UnlockDB(handle); - return(rv); + PORT_Assert("CERT_TraversePermCertsForSubject is Depricated" == NULL); + return SECFailure; } -/* - * Lookup a certificate by a digest of a subject public key. If it is - * found, it is returned (and must then be destroyed by the caller). - * NULL is returned otherwise -- if there was a problem performing the - * lookup, an appropriate error is set (e.g. SEC_ERROR_NO_MEMORY); - * if the cert simply was not found, the error is SEC_ERROR_UNKNOWN_CERT. - * - * If the lookup table has not yet been created or populated, do that first. - */ -CERTCertificate * -CERT_FindCertBySPKDigest(CERTCertDBHandle *handle, SECItem *spkDigest) -{ - SPKDigestInfo *spkDigestInfo; - char *index = NULL; - SECItem *certDBKey; - CERTCertificate *cert = NULL; - PORT_Assert(handle != NULL); - spkDigestInfo = handle->spkDigestInfo; - if ( spkDigestInfo == NULL || spkDigestInfo->permPopulated != PR_TRUE ) { - if ( PopulateSPKDigestTable(handle) != SECSuccess ) { - goto loser; - } - } - index = spkDigestIndexFromDigest(spkDigest); - if ( index == NULL ) { - goto loser; - } - certDBKey = PL_HashTableLookup(SPK_DIGEST_TABLE(handle), index); - if ( certDBKey != NULL ) { - cert = CERT_FindCertByKey(handle, certDBKey); - } - if ( cert == NULL ) { - PORT_SetError(SEC_ERROR_UNKNOWN_CERT); - } -loser: - if ( index != NULL ) { - PORT_Free(index); - } - return(cert); -} -/* XXX - * XXX - * - * These are included for now to allow this to build, but will not be needed - * once the softoken is below PKCS#11. - */ SECStatus -CERT_AddPermNickname(CERTCertificate *cert, char *nickname) +__CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname, + void *cb, void *cbarg) { + PORT_Assert("CERT_TraversePermCertsForNickname is Depricated" == NULL); + return SECFailure; } -int -CERT_NumPermCertsForSubject(CERTCertDBHandle *handle, SECItem *derSubject) -{ -} -int -CERT_NumPermCertsForNickname(CERTCertDBHandle *handle, char *nickname) -{ -} -SECStatus -CERT_OpenCertDB(CERTCertDBHandle *handle, PRBool readOnly, - CERTDBNameFunc namecb, void *cbarg) -{ - return SECSuccess; -} diff --git a/security/nss/lib/certhigh/certhigh.c b/security/nss/lib/certhigh/certhigh.c index 8a715fafb..62f2b1d88 100644 --- a/security/nss/lib/certhigh/certhigh.c +++ b/security/nss/lib/certhigh/certhigh.c @@ -44,7 +44,7 @@ #include "nsspki.h" #include "pkit.h" #include "pkitm.h" -#include "pkinss3hack.h" +#include "pki3hack.h" /* * Find all user certificates that match the given criteria. @@ -424,18 +424,11 @@ CERT_GetCertNicknames(CERTCertDBHandle *handle, int what, void *wincx) names->what = what; names->totallen = 0; - rv = SEC_TraversePermCerts(handle, CollectNicknames, (void *)names); + rv = PK11_TraverseSlotCerts(CollectNicknames, (void *)names, wincx); if ( rv ) { goto loser; } - if ( wincx != NULL ) { - rv = PK11_TraverseSlotCerts(CollectNicknames, (void *)names, wincx); - if ( rv ) { - goto loser; - } - } - if ( names->numnicknames ) { names->nicknames = (char**)PORT_ArenaAlloc(arena, names->numnicknames * sizeof(char *)); @@ -502,9 +495,7 @@ CollectDistNames( CERTCertificate *cert, SECItem *k, void *data) trust = cert->trust; /* only collect names of CAs trusted for issuing SSL clients */ - if ( ( trust->sslFlags & - ( CERTDB_VALID_CA | CERTDB_TRUSTED_CLIENT_CA ) ) == - ( CERTDB_VALID_CA | CERTDB_TRUSTED_CLIENT_CA ) ) { + if ( trust->sslFlags & CERTDB_TRUSTED_CLIENT_CA ) { saveit = PR_TRUE; } } @@ -568,7 +559,7 @@ CERT_GetSSLCACerts(CERTCertDBHandle *handle) names->names = NULL; /* collect the names from the database */ - rv = SEC_TraversePermCerts(handle, CollectDistNames, (void *)names); + rv = PK11_TraverseSlotCerts(CollectDistNames, (void *)names, NULL); if ( rv ) { goto loser; } @@ -746,10 +737,12 @@ CERTSignedCrl * CERT_ImportCRL break; } +#ifdef FIXME /* Do CRL validation and add to the dbase if this crl is more present then the one in the dbase, if one exists. */ crl = cert_DBInsertCRL (handle, url, newCrl, derCRL, type); +#endif } while (0); @@ -763,7 +756,6 @@ cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool { SECStatus rv; SECItem *derCert; - SECItem certKey; PRArenaPool *arena; CERTCertificate *cert = NULL; CERTCertificate *newcert = NULL; @@ -785,22 +777,6 @@ cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool while (numcerts--) { derCert = certs; certs++; - - /* get the key (issuer+cn) from the cert */ - rv = CERT_KeyFromDERCert(arena, derCert, &certKey); - if ( rv != SECSuccess ) { - goto loser; - } - - /* same cert already exists in the database, don't need to do - * anything more with it - */ - cert = CERT_FindCertByKey(handle, &certKey); - if ( cert ) { - CERT_DestroyCertificate(cert); - cert = NULL; - continue; - } /* decode my certificate */ newcert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); @@ -864,7 +840,7 @@ cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool } } - cert = CERT_NewTempCertificate(handle, derCert, NULL, PR_FALSE, PR_TRUE); + cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if ( cert == NULL ) { goto loser; } @@ -872,7 +848,10 @@ cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool /* get a default nickname for it */ nickname = CERT_MakeCANickname(cert); - rv = CERT_AddTempCertToPerm(cert, nickname, &trust); + cert->trust = &trust; + rv = PK11_ImportCert(PK11_GetInternalKeySlot(), cert, + CK_INVALID_HANDLE, nickname, PR_TRUE); + /* free the nickname */ if ( nickname ) { PORT_Free(nickname); diff --git a/security/nss/lib/certhigh/certvfy.c b/security/nss/lib/certhigh/certvfy.c index 580aac49f..c23adced7 100644 --- a/security/nss/lib/certhigh/certvfy.c +++ b/security/nss/lib/certhigh/certvfy.c @@ -48,7 +48,7 @@ #include "nsspki.h" #include "pkitm.h" #include "pkim.h" -#include "pkinss3hack.h" +#include "pki3hack.h" #include "base.h" #define PENDING_SLOP (24L*60L*60L) @@ -322,8 +322,6 @@ CERT_FindCertIssuer(CERTCertificate *cert, int64 validTime, SECCertUsage usage) CERTCertificate * issuerCert = NULL; SECItem * caName; PRArenaPool *tmpArena = NULL; - SECItem issuerCertKey; - SECStatus rv; tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); @@ -361,14 +359,16 @@ CERT_FindCertIssuer(CERTCertificate *cert, int64 validTime, SECCertUsage usage) */ if (caName != NULL) { - rv = CERT_KeyFromIssuerAndSN(tmpArena, caName, - &authorityKeyID->authCertSerialNumber, - &issuerCertKey); - if ( rv == SECSuccess ) { - issuerCert = CERT_FindCertByKey(cert->dbhandle, - &issuerCertKey); - } - + CERTIssuerAndSN issuerSN; + + issuerSN.derIssuer.data = caName->data; + issuerSN.derIssuer.len = caName->len; + issuerSN.serialNumber.data = + authorityKeyID->authCertSerialNumber.data; + issuerSN.serialNumber.len = + authorityKeyID->authCertSerialNumber.len; + issuerCert = CERT_FindCertByIssuerAndSN(cert->dbhandle, + &issuerSN); if ( issuerCert == NULL ) { PORT_SetError (SEC_ERROR_UNKNOWN_ISSUER); goto loser; @@ -994,13 +994,15 @@ CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool allowOverride; SECCertTimeValidity validity; CERTStatusConfig *statusConfig; - + +#ifdef notdef /* check if this cert is in the Evil list */ rv = CERT_CheckForEvilCert(cert); if ( rv != SECSuccess ) { PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); LOG_ERROR_OR_EXIT(log,cert,0,0); } +#endif /* make sure that the cert is valid at time t */ allowOverride = (PRBool)((certUsage == certUsageSSLServer) || diff --git a/security/nss/lib/certhigh/ocsp.c b/security/nss/lib/certhigh/ocsp.c index 150977149..2dc75e474 100644 --- a/security/nss/lib/certhigh/ocsp.c +++ b/security/nss/lib/certhigh/ocsp.c @@ -653,6 +653,28 @@ ocsp_CreateCertID(PRArenaPool *arena, CERTCertificate *cert, int64 time) if (rv != SECSuccess) { goto loser; } + certID->issuerSHA1NameHash.data = certID->issuerNameHash.data; + certID->issuerSHA1NameHash.len = certID->issuerNameHash.len; + /* cache the other two hash algorithms as well */ + if (SECITEM_AllocItem(arena, &(certID->issuerMD5NameHash), + MD5_LENGTH) == NULL) { + goto loser; + } + rv = PK11_HashBuf(SEC_OID_MD5, certID->issuerMD5NameHash.data, + tempItem->data, tempItem->len); + if (rv != SECSuccess) { + goto loser; + } + if (SECITEM_AllocItem(arena, &(certID->issuerMD2NameHash), + MD2_LENGTH) == NULL) { + goto loser; + } + rv = PK11_HashBuf(SEC_OID_MD2, certID->issuerMD2NameHash.data, + tempItem->data, tempItem->len); + if (rv != SECSuccess) { + goto loser; + } + SECITEM_FreeItem(tempItem, PR_TRUE); tempItem = NULL; @@ -660,6 +682,18 @@ ocsp_CreateCertID(PRArenaPool *arena, CERTCertificate *cert, int64 time) &(certID->issuerKeyHash)) == NULL) { goto loser; } + certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data; + certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len; + /* cache the other two hash algorithms as well */ + if (CERT_SPKDigestValueForCert(arena, issuerCert, SEC_OID_MD5, + &(certID->issuerMD5KeyHash)) == NULL) { + goto loser; + } + if (CERT_SPKDigestValueForCert(arena, issuerCert, SEC_OID_MD2, + &(certID->issuerMD2KeyHash)) == NULL) { + goto loser; + } + /* now we are done with issuerCert */ CERT_DestroyCertificate(issuerCert); @@ -2368,6 +2402,40 @@ ocsp_CertHasNoCheckExtension(CERTCertificate *cert) } #endif /* LATER */ +static PRBool +ocsp_matchcert(SECItem *certIndex,CERTCertificate *testCert) +{ + SECItem item; + unsigned char buf[SHA1_LENGTH]; /* MAX Hash Len */ + + item.data = buf; + item.len = SHA1_LENGTH; + + if (CERT_SPKDigestValueForCert(NULL,testCert,SEC_OID_SHA1, &item) == NULL) { + return PR_FALSE; + } + if (SECITEM_ItemsAreEqual(certIndex,&item)) { + return PR_TRUE; + } + if (CERT_SPKDigestValueForCert(NULL,testCert,SEC_OID_MD5, &item) == NULL) { + return PR_FALSE; + } + if (SECITEM_ItemsAreEqual(certIndex,&item)) { + return PR_TRUE; + } + if (CERT_SPKDigestValueForCert(NULL,testCert,SEC_OID_MD2, &item) == NULL) { + return PR_FALSE; + } + if (SECITEM_ItemsAreEqual(certIndex,&item)) { + return PR_TRUE; + } + + return PR_FALSE; +} + +static CERTCertificate * +ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle,CERTOCSPCertID *certID); + /* * Check the signature on some OCSP data. This is a helper function that * can be used to check either a request or a response. The result is @@ -2397,15 +2465,18 @@ ocsp_CheckSignature(ocspSignature *signature, void *tbs, const SEC_ASN1Template *encodeTemplate, CERTCertDBHandle *handle, SECCertUsage certUsage, int64 checkTime, PRBool lookupByName, void *certIndex, - void *pwArg, CERTCertificate **pSignerCert) + void *pwArg, CERTCertificate **pSignerCert, + CERTCertificate *issuer) { SECItem rawSignature; SECItem *encodedTBS = NULL; + CERTCertificate *responder = NULL; CERTCertificate *signerCert = NULL; SECKEYPublicKey *signerKey = NULL; CERTCertificate **certs = NULL; SECStatus rv = SECFailure; int certCount; + int i; /* * If this signature has already gone through verification, just @@ -2432,6 +2503,7 @@ ocsp_CheckSignature(ocspSignature *signature, void *tbs, if (signature->derCerts != NULL) { for (; signature->derCerts[certCount] != NULL; certCount++) { /* just counting */ + /*IMPORT CERT TO SPKI TABLE */ } } rv = CERT_ImportCerts(handle, certUsage, certCount, @@ -2455,7 +2527,22 @@ ocsp_CheckSignature(ocspSignature *signature, void *tbs, signerCert = CERT_FindCertByName(handle, encodedName); SECITEM_FreeItem(encodedName, PR_TRUE); } else { - signerCert = CERT_FindCertBySPKDigest(handle, certIndex); + /* + * The signer is either 1) a known issuer CA we passed in, + * 2) the default OCSP responder, or 3) and intermediate CA + * passed in the cert list to use. Figure out which it is. + */ + responder = ocsp_CertGetDefaultResponder(handle,NULL); + if (responder && ocsp_matchcert(certIndex,responder)) { + signerCert = CERT_DupCertificate(responder); + } else if (issuer && ocsp_matchcert(certIndex,issuer)) { + signerCert = CERT_DupCertificate(issuer); + } + for (i=0; (signerCert == NULL) && (i < certCount); i++) { + if (ocsp_matchcert(certIndex,certs[i])) { + signerCert = CERT_DupCertificate(certs[i]); + } + } } if (signerCert == NULL) { @@ -2546,6 +2633,7 @@ finish: if (certs != NULL) CERT_DestroyCertArray(certs, certCount); + /* Free CERTS from SPKDigest Table */ return rv; } @@ -2583,7 +2671,8 @@ finish: SECStatus CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response, CERTCertDBHandle *handle, void *pwArg, - CERTCertificate **pSignerCert) + CERTCertificate **pSignerCert, + CERTCertificate *issuer) { ocspResponseData *tbsData; /* this is what is signed */ PRBool byName; @@ -2623,7 +2712,7 @@ CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response, return ocsp_CheckSignature(ocsp_GetResponseSignature(response), tbsData, ocsp_ResponseDataTemplate, handle, certUsageStatusResponder, producedAt, - byName, certIndex, pwArg, pSignerCert); + byName, certIndex, pwArg, pSignerCert, issuer); } /* @@ -2635,12 +2724,10 @@ ocsp_CertIDsMatch(CERTCertDBHandle *handle, CERTOCSPCertID *certID1, CERTOCSPCertID *certID2) { PRBool match = PR_FALSE; - CERTCertificate *issuer1 = NULL; - CERTCertificate *issuer2 = NULL; SECItem *foundHash = NULL; - CERTCertificate *found; SECOidTag hashAlg; - SECItem *givenHash; + SECItem *keyHash; + SECItem *nameHash; /* * In order to match, they must have the same issuer and the same @@ -2668,63 +2755,34 @@ ocsp_CertIDsMatch(CERTCertDBHandle *handle, goto done; } - /* - * The hash algorithms are different; this is harder. We have - * to do a lookup of each one and compare them. - */ - issuer1 = CERT_FindCertBySPKDigest(handle, &certID1->issuerKeyHash); - issuer2 = CERT_FindCertBySPKDigest(handle, &certID2->issuerKeyHash); - - if (issuer1 == NULL && issuer2 == NULL) { - /* If we cannot find an issuer cert, we have no way to compare. */ - goto done; - } - - if (issuer1 != NULL && issuer2 != NULL) { - /* If we found a cert for each hash, we can just compare them. */ - if (issuer1 == issuer2) - match = PR_TRUE; - goto done; - } - - /* - * We found one issuer, but not both. So we have to use the other certID - * hash algorithm on the key in the found issuer cert to see if they match. - */ - - if (issuer1 != NULL) { - found = issuer1; - hashAlg = SECOID_FindOIDTag(&certID2->hashAlgorithm.algorithm); - givenHash = &certID2->issuerKeyHash; - } else { - found = issuer2; - hashAlg = SECOID_FindOIDTag(&certID1->hashAlgorithm.algorithm); - givenHash = &certID1->issuerKeyHash; + hashAlg = SECOID_FindOIDTag(&certID2->hashAlgorithm.algorithm); + switch (hashAlg) { + case SEC_OID_SHA1: + keyHash = &certID1->issuerSHA1KeyHash; + nameHash = &certID1->issuerSHA1NameHash; + break; + case SEC_OID_MD5: + keyHash = &certID1->issuerMD5KeyHash; + nameHash = &certID1->issuerMD5NameHash; + break; + case SEC_OID_MD2: + keyHash = &certID1->issuerMD2KeyHash; + nameHash = &certID1->issuerMD2NameHash; + break; + default: + foundHash == NULL; } - foundHash = CERT_SPKDigestValueForCert(NULL, found, hashAlg, NULL); if (foundHash == NULL) { goto done; } - if (SECITEM_CompareItem(foundHash, givenHash) == SECEqual) { - /* - * Strictly speaking, we should compare the issuerNameHash, too, - * but I think the added complexity doesn't actually buy anything. - */ + if ((SECITEM_CompareItem(nameHash, &certID2->issuerNameHash) == SECEqual) + && (SECITEM_CompareItem(keyHash, &certID2->issuerKeyHash) == SECEqual)) { match = PR_TRUE; } done: - if (issuer1 != NULL) { - CERT_DestroyCertificate(issuer1); - } - if (issuer2 != NULL) { - CERT_DestroyCertificate(issuer2); - } - if (foundHash != NULL) { - SECITEM_FreeItem(foundHash, PR_TRUE); - } return match; } @@ -2788,15 +2846,12 @@ ocsp_GetCheckingContext(CERTCertDBHandle *handle) return ocspcx; } - /* * Return true if the given signerCert is the default responder for * the given certID. If not, or if any error, return false. */ -static PRBool -ocsp_CertIsDefaultResponderForCertID(CERTCertDBHandle *handle, - CERTCertificate *signerCert, - CERTOCSPCertID *certID) +static CERTCertificate * +ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle,CERTOCSPCertID *certID) { ocspCheckingContext *ocspcx; @@ -2814,12 +2869,26 @@ ocsp_CertIsDefaultResponderForCertID(CERTCertDBHandle *handle, */ if (ocspcx->useDefaultResponder) { PORT_Assert(ocspcx->defaultResponderCert != NULL); - if (ocspcx->defaultResponderCert == signerCert) - return PR_TRUE; + return ocspcx->defaultResponderCert; } loser: - return PR_FALSE; + return NULL; +} + +/* + * Return true if the given signerCert is the default responder for + * the given certID. If not, or if any error, return false. + */ +static PRBool +ocsp_CertIsDefaultResponderForCertID(CERTCertDBHandle *handle, + CERTCertificate *signerCert, + CERTOCSPCertID *certID) +{ + CERTCertificate *defaultResponderCert; + + defaultResponderCert = ocsp_CertGetDefaultResponder(handle, certID); + return (PRBool) (defaultResponderCert == signerCert); } /* @@ -3300,6 +3369,7 @@ CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert, CERTOCSPRequest *request = NULL; CERTOCSPResponse *response = NULL; CERTCertificate *signerCert = NULL; + CERTCertificate *issuerCert = NULL; ocspResponseData *responseData; int64 producedAt; CERTOCSPCertID *certID; @@ -3413,7 +3483,9 @@ CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert, * If we've made it this far, we expect a response with a good signature. * So, check for that. */ - rv = CERT_VerifyOCSPResponseSignature(response, handle, pwArg, &signerCert); + issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA); + rv = CERT_VerifyOCSPResponseSignature(response, handle, pwArg, &signerCert, + issuerCert); if (rv != SECSuccess) goto loser; @@ -3471,6 +3543,8 @@ CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert, rv = ocsp_CertHasGoodStatus(single, time); loser: + if (issuerCert != NULL) + CERT_DestroyCertificate(issuerCert); if (signerCert != NULL) CERT_DestroyCertificate(signerCert); if (response != NULL) @@ -3905,3 +3979,97 @@ CERT_DisableOCSPDefaultResponder(CERTCertDBHandle *handle) statusContext->useDefaultResponder = PR_FALSE; return SECSuccess; } +static const SECHashObject * +OidTagToDigestObject(SECOidTag digestAlg) +{ + const SECHashObject *rawDigestObject; + + switch (digestAlg) { + case SEC_OID_MD2: + rawDigestObject = &SECHashObjects[HASH_AlgMD2]; + break; + case SEC_OID_MD5: + rawDigestObject = &SECHashObjects[HASH_AlgMD5]; + break; + case SEC_OID_SHA1: + rawDigestObject = &SECHashObjects[HASH_AlgSHA1]; + break; + default: + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + rawDigestObject = NULL; + break; + } + return(rawDigestObject); +} + +/* + * Digest the cert's subject public key using the specified algorithm. + * The necessary storage for the digest data is allocated. If "fill" is + * non-null, the data is put there, otherwise a SECItem is allocated. + * Allocation from "arena" if it is non-null, heap otherwise. Any problem + * results in a NULL being returned (and an appropriate error set). + */ +SECItem * +CERT_SPKDigestValueForCert(PRArenaPool *arena, CERTCertificate *cert, + SECOidTag digestAlg, SECItem *fill) +{ + const SECHashObject *digestObject; + void *digestContext; + SECItem *result = NULL; + void *mark = NULL; + SECItem spk; + + if ( arena != NULL ) { + mark = PORT_ArenaMark(arena); + } + + digestObject = OidTagToDigestObject(digestAlg); + if ( digestObject == NULL ) { + goto loser; + } + + if ((fill == NULL) || (fill->data == NULL)) { + result = SECITEM_AllocItem(arena, fill, digestObject->length); + if ( result == NULL ) { + goto loser; + } + fill = result; + } + + /* + * Copy just the length and data pointer (nothing needs to be freed) + * of the subject public key so we can convert the length from bits + * to bytes, which is what the digest function expects. + */ + spk = cert->subjectPublicKeyInfo.subjectPublicKey; + DER_ConvertBitString(&spk); + + /* + * Now digest the value, using the specified algorithm. + */ + digestContext = digestObject->create(); + if ( digestContext == NULL ) { + goto loser; + } + digestObject->begin(digestContext); + digestObject->update(digestContext, spk.data, spk.len); + digestObject->end(digestContext, fill->data, &(fill->len), fill->len); + digestObject->destroy(digestContext, PR_TRUE); + + if ( arena != NULL ) { + PORT_ArenaUnmark(arena, mark); + } + return(fill); + +loser: + if ( arena != NULL ) { + PORT_ArenaRelease(arena, mark); + } else { + if ( result != NULL ) { + SECITEM_FreeItem(result, (fill == NULL) ? PR_TRUE : PR_FALSE); + } + } + return(NULL); +} + + diff --git a/security/nss/lib/certhigh/ocsp.h b/security/nss/lib/certhigh/ocsp.h index 51f81e867..e4bd7dbdd 100644 --- a/security/nss/lib/certhigh/ocsp.h +++ b/security/nss/lib/certhigh/ocsp.h @@ -353,6 +353,8 @@ CERT_GetEncodedOCSPResponse(PRArenaPool *arena, CERTCertList *certList, * Pointer to CERTCertDBHandle for certificate DB to use for verification. * void *pwArg * Pointer to argument for password prompting, if needed. + * CERTCertificate *issuerCert + * Issuer of the certificate that generated the OCSP request. * OUTPUTS: * CERTCertificate **pSignerCert * Pointer in which to store signer's certificate; only filled-in if @@ -371,7 +373,8 @@ CERT_GetEncodedOCSPResponse(PRArenaPool *arena, CERTCertList *certList, extern SECStatus CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response, CERTCertDBHandle *handle, void *pwArg, - CERTCertificate **pSignerCert); + CERTCertificate **pSignerCert, + CERTCertificate *issuerCert); /* * FUNCTION: CERT_GetOCSPAuthorityInfoAccessLocation diff --git a/security/nss/lib/certhigh/ocspti.h b/security/nss/lib/certhigh/ocspti.h index 5f530c4bf..9c739bef4 100644 --- a/security/nss/lib/certhigh/ocspti.h +++ b/security/nss/lib/certhigh/ocspti.h @@ -194,6 +194,12 @@ struct CERTOCSPCertIDStr { SECItem issuerNameHash; /* an OCTET STRING */ SECItem issuerKeyHash; /* an OCTET STRING */ SECItem serialNumber; /* an INTEGER */ + SECItem issuerSHA1NameHash; /* keep other hashes around when */ + SECItem issuerMD5NameHash; /* we have them */ + SECItem issuerMD2NameHash; + SECItem issuerSHA1KeyHash; /* keep other hashes around when */ + SECItem issuerMD5KeyHash; /* we have them */ + SECItem issuerMD2KeyHash; }; /* diff --git a/security/nss/lib/ckfw/ckt.h b/security/nss/lib/ckfw/ckt.h index 762a70a0b..bf114dbc0 100644 --- a/security/nss/lib/ckfw/ckt.h +++ b/security/nss/lib/ckfw/ckt.h @@ -31,169 +31,7 @@ * GPL. */ -#ifndef CKT_H -#define CKT_H - -#ifdef DEBUG -static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; -#endif /* DEBUG */ - -/* - * ckt.h - * - * This file contains the NSS-specific type definitions for Cryptoki - * (PKCS#11). - */ - -#ifndef NSSCKT_H -#include "nssckt.h" -#endif /* NSSCKT_H */ - -/* - * NSSCK_VENDOR_NETSCAPE - * - * Cryptoki reserves the high half of all the number spaces for - * vendor-defined use. I'd like to keep all of our Netscape- - * specific values together, but not in the oh-so-obvious - * 0x80000001, 0x80000002, etc. area. So I've picked an offset, - * and constructed values for the beginnings of our spaces. - * - * Note that some "historical" Netscape values don't fall within - * this range. - */ -#define NSSCK_VENDOR_NETSCAPE 0x4E534350 /* NSCP */ - -/* - * Netscape-defined object classes - * - */ -#define CKO_NETSCAPE (CKO_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -#define CKO_NETSCAPE_CRL (CKO_NETSCAPE + 1) -#define CKO_NETSCAPE_SMIME (CKO_NETSCAPE + 2) -#define CKO_NETSCAPE_TRUST (CKO_NETSCAPE + 3) -#define CKO_NETSCAPE_BUILTIN_ROOT_LIST (CKO_NETSCAPE + 4) - -/* - * Netscape-defined key types - * - */ -#define CKK_NETSCAPE (CKK_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -#define CKK_NETSCAPE_PKCS8 (CKK_NETSCAPE + 1) -/* - * Netscape-defined certificate types - * - */ -#define CKC_NETSCAPE (CKC_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -/* - * Netscape-defined object attributes - * - */ -#define CKA_NETSCAPE (CKA_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -#define CKA_NETSCAPE_URL (CKA_NETSCAPE + 1) -#define CKA_NETSCAPE_EMAIL (CKA_NETSCAPE + 2) -#define CKA_NETSCAPE_SMIME_INFO (CKA_NETSCAPE + 3) -#define CKA_NETSCAPE_SMIME_TIMESTAMP (CKA_NETSCAPE + 4) -#define CKA_NETSCAPE_PKCS8_SALT (CKA_NETSCAPE + 5) -#define CKA_NETSCAPE_PASSWORD_CHECK (CKA_NETSCAPE + 6) -#define CKA_NETSCAPE_EXPIRES (CKA_NETSCAPE + 7) - -/* - * Trust attributes: - * - * If trust goes standard, these probably will too. So I'll - * put them all in one place. - */ - -#define CKA_TRUST (CKA_NETSCAPE + 0x2000) - -/* "Usage" key information */ -#define CKA_TRUST_DIGITAL_SIGNATURE (CKA_TRUST + 1) -#define CKA_TRUST_NON_REPUDIATION (CKA_TRUST + 2) -#define CKA_TRUST_KEY_ENCIPHERMENT (CKA_TRUST + 3) -#define CKA_TRUST_DATA_ENCIPHERMENT (CKA_TRUST + 4) -#define CKA_TRUST_KEY_AGREEMENT (CKA_TRUST + 5) -#define CKA_TRUST_KEY_CERT_SIGN (CKA_TRUST + 6) -#define CKA_TRUST_CRL_SIGN (CKA_TRUST + 7) - -/* "Purpose" trust information */ -#define CKA_TRUST_SERVER_AUTH (CKA_TRUST + 8) -#define CKA_TRUST_CLIENT_AUTH (CKA_TRUST + 9) -#define CKA_TRUST_CODE_SIGNING (CKA_TRUST + 10) -#define CKA_TRUST_EMAIL_PROTECTION (CKA_TRUST + 11) -#define CKA_TRUST_IPSEC_END_SYSTEM (CKA_TRUST + 12) -#define CKA_TRUST_IPSEC_TUNNEL (CKA_TRUST + 13) -#define CKA_TRUST_IPSEC_USER (CKA_TRUST + 14) -#define CKA_TRUST_TIME_STAMPING (CKA_TRUST + 15) -#define CKA_CERT_SHA1_HASH (CKA_TRUST + 100) -#define CKA_CERT_MD5_HASH (CKA_TRUST + 101) - -/* Netscape trust stuff */ -/* XXX fgmr new ones here-- step-up, etc. */ - -/* HISTORICAL: define used to pass in the database key for DSA private keys */ -#define CKA_NETSCAPE_DB 0xD5A0DB00L -#define CKA_NETSCAPE_TRUST 0x80000001L - -/* - * Netscape-defined crypto mechanisms - * - */ -#define CKM_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) -/* - * HISTORICAL: - * Do not attempt to use these. They are only used by NETSCAPE's internal - * PKCS #11 interface. Most of these are place holders for other mechanism - * and will change in the future. - */ -#define CKM_NETSCAPE_PBE_KEY_GEN 0x80000001L -#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002L -#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003L -#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004L -#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005L -#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006L -#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007L -#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008L -#define CKM_TLS_MASTER_KEY_DERIVE 0x80000371L -#define CKM_TLS_KEY_AND_MAC_DERIVE 0x80000372L - -/* - * Netscape-defined return values - * - */ -#define CKR_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -/* - * Trust info - * - * This isn't part of the Cryptoki standard (yet), so I'm putting - * all the definitions here. Some of this would move to nssckt.h - * if trust info were made part of the standard. In view of this - * possibility, I'm putting my (Netscape) values in the netscape - * vendor space, like everything else. - */ - -typedef CK_ULONG CK_TRUST; - -/* The following trust types are defined: */ -#define CKT_VENDOR_DEFINED 0x80000000 - -#define CKT_NETSCAPE (CKT_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -/* If trust goes standard, these'll probably drop out of vendor space. */ -#define CKT_NETSCAPE_TRUSTED (CKT_NETSCAPE + 1) -#define CKT_NETSCAPE_TRUSTED_DELEGATOR (CKT_NETSCAPE + 2) -#define CKT_NETSCAPE_UNTRUSTED (CKT_NETSCAPE + 3) - -/* - * These may well remain Netscape-specific; I'm only using them - * to cache resolution data. - */ -#define CKT_NETSCAPE_VALID (CKT_NETSCAPE + 4) -#define CKT_NETSCAPE_VALID_DELEGATOR (CKT_NETSCAPE + 5) - - -#endif /* CKT_H */ +/* get back to just one set of PKCS #11 headers. Use the onese that + * are easiest to maintain from the RSA website */ +/* this one is the one that defines NSS specific data */ +#include "pkcs11n.h" diff --git a/security/nss/lib/ckfw/manifest.mn b/security/nss/lib/ckfw/manifest.mn index d228e12ab..8a4f15086 100644 --- a/security/nss/lib/ckfw/manifest.mn +++ b/security/nss/lib/ckfw/manifest.mn @@ -54,9 +54,7 @@ EXPORTS = \ nssckfwt.h \ nssckg.h \ nssckmdt.h \ - nssckp.h \ nssckt.h \ - nsscku.h \ $(NULL) MODULE = security diff --git a/security/nss/lib/ckfw/nssckepv.h b/security/nss/lib/ckfw/nssckepv.h index 88ff9d773..bfa79ac78 100644 --- a/security/nss/lib/ckfw/nssckepv.h +++ b/security/nss/lib/ckfw/nssckepv.h @@ -31,102 +31,4 @@ * may use your version of this file under either the MPL or the * GPL. */ -#ifndef NSSCKEPV_H -#define NSSCKEPV_H - -#ifdef DEBUG -static const char NSSCKEPV_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$ ; @(#) $RCSfile$ $Revision$ $Date$ $Name$"; -#endif /* DEBUG */ - -/* - * nssckepv.h - * - * This automatically-generated header file defines the type - * CK_FUNCTION_LIST specified by PKCS#11. - */ - -#ifndef NSSCKT_H -#include "nssckt.h" -#endif /* NSSCKT_H */ - -#ifndef NSSCKFT_H -#include "nssckft.h" -#endif /* NSSCKFT_H */ - -#include "nssckp.h" - -struct CK_FUNCTION_LIST { - CK_VERSION version; - CK_C_Initialize C_Initialize; - CK_C_Finalize C_Finalize; - CK_C_GetInfo C_GetInfo; - CK_C_GetFunctionList C_GetFunctionList; - CK_C_GetSlotList C_GetSlotList; - CK_C_GetSlotInfo C_GetSlotInfo; - CK_C_GetTokenInfo C_GetTokenInfo; - CK_C_GetMechanismList C_GetMechanismList; - CK_C_GetMechanismInfo C_GetMechanismInfo; - CK_C_InitToken C_InitToken; - CK_C_InitPIN C_InitPIN; - CK_C_SetPIN C_SetPIN; - CK_C_OpenSession C_OpenSession; - CK_C_CloseSession C_CloseSession; - CK_C_CloseAllSessions C_CloseAllSessions; - CK_C_GetSessionInfo C_GetSessionInfo; - CK_C_GetOperationState C_GetOperationState; - CK_C_SetOperationState C_SetOperationState; - CK_C_Login C_Login; - CK_C_Logout C_Logout; - CK_C_CreateObject C_CreateObject; - CK_C_CopyObject C_CopyObject; - CK_C_DestroyObject C_DestroyObject; - CK_C_GetObjectSize C_GetObjectSize; - CK_C_GetAttributeValue C_GetAttributeValue; - CK_C_SetAttributeValue C_SetAttributeValue; - CK_C_FindObjectsInit C_FindObjectsInit; - CK_C_FindObjects C_FindObjects; - CK_C_FindObjectsFinal C_FindObjectsFinal; - CK_C_EncryptInit C_EncryptInit; - CK_C_Encrypt C_Encrypt; - CK_C_EncryptUpdate C_EncryptUpdate; - CK_C_EncryptFinal C_EncryptFinal; - CK_C_DecryptInit C_DecryptInit; - CK_C_Decrypt C_Decrypt; - CK_C_DecryptUpdate C_DecryptUpdate; - CK_C_DecryptFinal C_DecryptFinal; - CK_C_DigestInit C_DigestInit; - CK_C_Digest C_Digest; - CK_C_DigestUpdate C_DigestUpdate; - CK_C_DigestKey C_DigestKey; - CK_C_DigestFinal C_DigestFinal; - CK_C_SignInit C_SignInit; - CK_C_Sign C_Sign; - CK_C_SignUpdate C_SignUpdate; - CK_C_SignFinal C_SignFinal; - CK_C_SignRecoverInit C_SignRecoverInit; - CK_C_SignRecover C_SignRecover; - CK_C_VerifyInit C_VerifyInit; - CK_C_Verify C_Verify; - CK_C_VerifyUpdate C_VerifyUpdate; - CK_C_VerifyFinal C_VerifyFinal; - CK_C_VerifyRecoverInit C_VerifyRecoverInit; - CK_C_VerifyRecover C_VerifyRecover; - CK_C_DigestEncryptUpdate C_DigestEncryptUpdate; - CK_C_DecryptDigestUpdate C_DecryptDigestUpdate; - CK_C_SignEncryptUpdate C_SignEncryptUpdate; - CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate; - CK_C_GenerateKey C_GenerateKey; - CK_C_GenerateKeyPair C_GenerateKeyPair; - CK_C_WrapKey C_WrapKey; - CK_C_UnwrapKey C_UnwrapKey; - CK_C_DeriveKey C_DeriveKey; - CK_C_SeedRandom C_SeedRandom; - CK_C_GenerateRandom C_GenerateRandom; - CK_C_GetFunctionStatus C_GetFunctionStatus; - CK_C_CancelFunction C_CancelFunction; - CK_C_WaitForSlotEvent C_WaitForSlotEvent; -}; - -#include "nsscku.h" - -#endif /* NSSCKEPV_H */ +#include "pkcs11.h" diff --git a/security/nss/lib/ckfw/nssckft.h b/security/nss/lib/ckfw/nssckft.h index 287f91956..ef3e897ce 100644 --- a/security/nss/lib/ckfw/nssckft.h +++ b/security/nss/lib/ckfw/nssckft.h @@ -31,462 +31,5 @@ * may use your version of this file under either the MPL or the * GPL. */ -#ifndef NSSCKFT_H -#define NSSCKFT_H -#ifdef DEBUG -static const char NSSCKFT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$ ; @(#) $RCSfile$ $Revision$ $Date$ $Name$"; -#endif /* DEBUG */ - -/* - * nssckft.h - * - * The automatically-generated header file declares a typedef - * each of the Cryptoki functions specified by PKCS#11. - */ - -#ifndef NSSCKT_H -#include "nssckt.h" -#endif /* NSSCKT_H */ - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_Initialize)( - CK_VOID_PTR pInitArgs -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_Finalize)( - CK_VOID_PTR pReserved -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GetInfo)( - CK_INFO_PTR pInfo -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GetFunctionList)( - CK_FUNCTION_LIST_PTR_PTR ppFunctionList -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GetSlotList)( - CK_BBOOL tokenPresent, - CK_SLOT_ID_PTR pSlotList, - CK_ULONG_PTR pulCount -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GetSlotInfo)( - CK_SLOT_ID slotID, - CK_SLOT_INFO_PTR pInfo -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GetTokenInfo)( - CK_SLOT_ID slotID, - CK_TOKEN_INFO_PTR pInfo -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GetMechanismList)( - CK_SLOT_ID slotID, - CK_MECHANISM_TYPE_PTR pMechanismList, - CK_ULONG_PTR pulCount -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GetMechanismInfo)( - CK_SLOT_ID slotID, - CK_MECHANISM_TYPE type, - CK_MECHANISM_INFO_PTR pInfo -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_InitToken)( - CK_SLOT_ID slotID, - CK_CHAR_PTR pPin, - CK_ULONG ulPinLen, - CK_CHAR_PTR pLabel -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_InitPIN)( - CK_SESSION_HANDLE hSession, - CK_CHAR_PTR pPin, - CK_ULONG ulPinLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_SetPIN)( - CK_SESSION_HANDLE hSession, - CK_CHAR_PTR pOldPin, - CK_ULONG ulOldLen, - CK_CHAR_PTR pNewPin, - CK_ULONG ulNewLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_OpenSession)( - CK_SLOT_ID slotID, - CK_FLAGS flags, - CK_VOID_PTR pApplication, - CK_NOTIFY Notify, - CK_SESSION_HANDLE_PTR phSession -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_CloseSession)( - CK_SESSION_HANDLE hSession -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_CloseAllSessions)( - CK_SLOT_ID slotID -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GetSessionInfo)( - CK_SESSION_HANDLE hSession, - CK_SESSION_INFO_PTR pInfo -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GetOperationState)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pOperationState, - CK_ULONG_PTR pulOperationStateLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_SetOperationState)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pOperationState, - CK_ULONG ulOperationStateLen, - CK_OBJECT_HANDLE hEncryptionKey, - CK_OBJECT_HANDLE hAuthenticationKey -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_Login)( - CK_SESSION_HANDLE hSession, - CK_USER_TYPE userType, - CK_CHAR_PTR pPin, - CK_ULONG ulPinLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_Logout)( - CK_SESSION_HANDLE hSession -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_CreateObject)( - CK_SESSION_HANDLE hSession, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount, - CK_OBJECT_HANDLE_PTR phObject -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_CopyObject)( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount, - CK_OBJECT_HANDLE_PTR phNewObject -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_DestroyObject)( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GetObjectSize)( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject, - CK_ULONG_PTR pulSize -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GetAttributeValue)( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_SetAttributeValue)( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_FindObjectsInit)( - CK_SESSION_HANDLE hSession, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_FindObjects)( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE_PTR phObject, - CK_ULONG ulMaxObjectCount, - CK_ULONG_PTR pulObjectCount -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_FindObjectsFinal)( - CK_SESSION_HANDLE hSession -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_EncryptInit)( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_Encrypt)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pData, - CK_ULONG ulDataLen, - CK_BYTE_PTR pEncryptedData, - CK_ULONG_PTR pulEncryptedDataLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_EncryptUpdate)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pPart, - CK_ULONG ulPartLen, - CK_BYTE_PTR pEncryptedPart, - CK_ULONG_PTR pulEncryptedPartLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_EncryptFinal)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pLastEncryptedPart, - CK_ULONG_PTR pulLastEncryptedPartLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_DecryptInit)( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_Decrypt)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pEncryptedData, - CK_ULONG ulEncryptedDataLen, - CK_BYTE_PTR pData, - CK_ULONG_PTR pulDataLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_DecryptUpdate)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pEncryptedPart, - CK_ULONG ulEncryptedPartLen, - CK_BYTE_PTR pPart, - CK_ULONG_PTR pulPartLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_DecryptFinal)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pLastPart, - CK_ULONG_PTR pulLastPartLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_DigestInit)( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_Digest)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pData, - CK_ULONG ulDataLen, - CK_BYTE_PTR pDigest, - CK_ULONG_PTR pulDigestLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_DigestUpdate)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pPart, - CK_ULONG ulPartLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_DigestKey)( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hKey -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_DigestFinal)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pDigest, - CK_ULONG_PTR pulDigestLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_SignInit)( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_Sign)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pData, - CK_ULONG ulDataLen, - CK_BYTE_PTR pSignature, - CK_ULONG_PTR pulSignatureLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_SignUpdate)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pPart, - CK_ULONG ulPartLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_SignFinal)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pSignature, - CK_ULONG_PTR pulSignatureLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_SignRecoverInit)( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_SignRecover)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pData, - CK_ULONG ulDataLen, - CK_BYTE_PTR pSignature, - CK_ULONG_PTR pulSignatureLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_VerifyInit)( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_Verify)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pData, - CK_ULONG ulDataLen, - CK_BYTE_PTR pSignature, - CK_ULONG ulSignatureLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_VerifyUpdate)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pPart, - CK_ULONG ulPartLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_VerifyFinal)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pSignature, - CK_ULONG ulSignatureLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_VerifyRecoverInit)( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_VerifyRecover)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pSignature, - CK_ULONG ulSignatureLen, - CK_BYTE_PTR pData, - CK_ULONG_PTR pulDataLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_DigestEncryptUpdate)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pPart, - CK_ULONG ulPartLen, - CK_BYTE_PTR pEncryptedPart, - CK_ULONG_PTR pulEncryptedPartLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_DecryptDigestUpdate)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pEncryptedPart, - CK_ULONG ulEncryptedPartLen, - CK_BYTE_PTR pPart, - CK_ULONG_PTR pulPartLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_SignEncryptUpdate)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pPart, - CK_ULONG ulPartLen, - CK_BYTE_PTR pEncryptedPart, - CK_ULONG_PTR pulEncryptedPartLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_DecryptVerifyUpdate)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pEncryptedPart, - CK_ULONG ulEncryptedPartLen, - CK_BYTE_PTR pPart, - CK_ULONG_PTR pulPartLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GenerateKey)( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount, - CK_OBJECT_HANDLE_PTR phKey -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GenerateKeyPair)( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_ATTRIBUTE_PTR pPublicKeyTemplate, - CK_ULONG ulPublicKeyAttributeCount, - CK_ATTRIBUTE_PTR pPrivateKeyTemplate, - CK_ULONG ulPrivateKeyAttributeCount, - CK_OBJECT_HANDLE_PTR phPublicKey, - CK_OBJECT_HANDLE_PTR phPrivateKey -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_WrapKey)( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hWrappingKey, - CK_OBJECT_HANDLE hKey, - CK_BYTE_PTR pWrappedKey, - CK_ULONG_PTR pulWrappedKeyLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_UnwrapKey)( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hUnwrappingKey, - CK_BYTE_PTR pWrappedKey, - CK_ULONG ulWrappedKeyLen, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_OBJECT_HANDLE_PTR phKey -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_DeriveKey)( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hBaseKey, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_OBJECT_HANDLE_PTR phKey -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_SeedRandom)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pSeed, - CK_ULONG ulSeedLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GenerateRandom)( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR RandomData, - CK_ULONG ulRandomLen -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_GetFunctionStatus)( - CK_SESSION_HANDLE hSession -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_CancelFunction)( - CK_SESSION_HANDLE hSession -); - -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_C_WaitForSlotEvent)( - CK_FLAGS flags, - CK_SLOT_ID_PTR pSlot, - CK_VOID_PTR pRserved -); - -#endif /* NSSCKFT_H */ +#include "pkcs11t.h" diff --git a/security/nss/lib/ckfw/nssckg.h b/security/nss/lib/ckfw/nssckg.h index 3dc76622a..bfa79ac78 100644 --- a/security/nss/lib/ckfw/nssckg.h +++ b/security/nss/lib/ckfw/nssckg.h @@ -31,530 +31,4 @@ * may use your version of this file under either the MPL or the * GPL. */ -#ifndef NSSCKG_H -#define NSSCKG_H - -#ifdef DEBUG -static const char NSSCKG_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$ ; @(#) $RCSfile$ $Revision$ $Date$ $Name$"; -#endif /* DEBUG */ - -/* - * nssckg.h - * - * This automatically-generated header file prototypes the Cryptoki - * functions specified by PKCS#11. - */ - -#ifndef NSSCKT_H -#include "nssckt.h" -#endif /* NSSCKT_H */ - -CK_RV CK_ENTRY C_Initialize -( - CK_VOID_PTR pInitArgs -); - -CK_RV CK_ENTRY C_Finalize -( - CK_VOID_PTR pReserved -); - -CK_RV CK_ENTRY C_GetInfo -( - CK_INFO_PTR pInfo -); - -CK_RV CK_ENTRY C_GetFunctionList -( - CK_FUNCTION_LIST_PTR_PTR ppFunctionList -); - -CK_RV CK_ENTRY C_GetSlotList -( - CK_BBOOL tokenPresent, - CK_SLOT_ID_PTR pSlotList, - CK_ULONG_PTR pulCount -); - -CK_RV CK_ENTRY C_GetSlotInfo -( - CK_SLOT_ID slotID, - CK_SLOT_INFO_PTR pInfo -); - -CK_RV CK_ENTRY C_GetTokenInfo -( - CK_SLOT_ID slotID, - CK_TOKEN_INFO_PTR pInfo -); - -CK_RV CK_ENTRY C_GetMechanismList -( - CK_SLOT_ID slotID, - CK_MECHANISM_TYPE_PTR pMechanismList, - CK_ULONG_PTR pulCount -); - -CK_RV CK_ENTRY C_GetMechanismInfo -( - CK_SLOT_ID slotID, - CK_MECHANISM_TYPE type, - CK_MECHANISM_INFO_PTR pInfo -); - -CK_RV CK_ENTRY C_InitToken -( - CK_SLOT_ID slotID, - CK_CHAR_PTR pPin, - CK_ULONG ulPinLen, - CK_CHAR_PTR pLabel -); - -CK_RV CK_ENTRY C_InitPIN -( - CK_SESSION_HANDLE hSession, - CK_CHAR_PTR pPin, - CK_ULONG ulPinLen -); - -CK_RV CK_ENTRY C_SetPIN -( - CK_SESSION_HANDLE hSession, - CK_CHAR_PTR pOldPin, - CK_ULONG ulOldLen, - CK_CHAR_PTR pNewPin, - CK_ULONG ulNewLen -); - -CK_RV CK_ENTRY C_OpenSession -( - CK_SLOT_ID slotID, - CK_FLAGS flags, - CK_VOID_PTR pApplication, - CK_NOTIFY Notify, - CK_SESSION_HANDLE_PTR phSession -); - -CK_RV CK_ENTRY C_CloseSession -( - CK_SESSION_HANDLE hSession -); - -CK_RV CK_ENTRY C_CloseAllSessions -( - CK_SLOT_ID slotID -); - -CK_RV CK_ENTRY C_GetSessionInfo -( - CK_SESSION_HANDLE hSession, - CK_SESSION_INFO_PTR pInfo -); - -CK_RV CK_ENTRY C_GetOperationState -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pOperationState, - CK_ULONG_PTR pulOperationStateLen -); - -CK_RV CK_ENTRY C_SetOperationState -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pOperationState, - CK_ULONG ulOperationStateLen, - CK_OBJECT_HANDLE hEncryptionKey, - CK_OBJECT_HANDLE hAuthenticationKey -); - -CK_RV CK_ENTRY C_Login -( - CK_SESSION_HANDLE hSession, - CK_USER_TYPE userType, - CK_CHAR_PTR pPin, - CK_ULONG ulPinLen -); - -CK_RV CK_ENTRY C_Logout -( - CK_SESSION_HANDLE hSession -); - -CK_RV CK_ENTRY C_CreateObject -( - CK_SESSION_HANDLE hSession, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount, - CK_OBJECT_HANDLE_PTR phObject -); - -CK_RV CK_ENTRY C_CopyObject -( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount, - CK_OBJECT_HANDLE_PTR phNewObject -); - -CK_RV CK_ENTRY C_DestroyObject -( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject -); - -CK_RV CK_ENTRY C_GetObjectSize -( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject, - CK_ULONG_PTR pulSize -); - -CK_RV CK_ENTRY C_GetAttributeValue -( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount -); - -CK_RV CK_ENTRY C_SetAttributeValue -( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hObject, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount -); - -CK_RV CK_ENTRY C_FindObjectsInit -( - CK_SESSION_HANDLE hSession, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount -); - -CK_RV CK_ENTRY C_FindObjects -( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE_PTR phObject, - CK_ULONG ulMaxObjectCount, - CK_ULONG_PTR pulObjectCount -); - -CK_RV CK_ENTRY C_FindObjectsFinal -( - CK_SESSION_HANDLE hSession -); - -CK_RV CK_ENTRY C_EncryptInit -( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey -); - -CK_RV CK_ENTRY C_Encrypt -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pData, - CK_ULONG ulDataLen, - CK_BYTE_PTR pEncryptedData, - CK_ULONG_PTR pulEncryptedDataLen -); - -CK_RV CK_ENTRY C_EncryptUpdate -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pPart, - CK_ULONG ulPartLen, - CK_BYTE_PTR pEncryptedPart, - CK_ULONG_PTR pulEncryptedPartLen -); - -CK_RV CK_ENTRY C_EncryptFinal -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pLastEncryptedPart, - CK_ULONG_PTR pulLastEncryptedPartLen -); - -CK_RV CK_ENTRY C_DecryptInit -( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey -); - -CK_RV CK_ENTRY C_Decrypt -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pEncryptedData, - CK_ULONG ulEncryptedDataLen, - CK_BYTE_PTR pData, - CK_ULONG_PTR pulDataLen -); - -CK_RV CK_ENTRY C_DecryptUpdate -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pEncryptedPart, - CK_ULONG ulEncryptedPartLen, - CK_BYTE_PTR pPart, - CK_ULONG_PTR pulPartLen -); - -CK_RV CK_ENTRY C_DecryptFinal -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pLastPart, - CK_ULONG_PTR pulLastPartLen -); - -CK_RV CK_ENTRY C_DigestInit -( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism -); - -CK_RV CK_ENTRY C_Digest -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pData, - CK_ULONG ulDataLen, - CK_BYTE_PTR pDigest, - CK_ULONG_PTR pulDigestLen -); - -CK_RV CK_ENTRY C_DigestUpdate -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pPart, - CK_ULONG ulPartLen -); - -CK_RV CK_ENTRY C_DigestKey -( - CK_SESSION_HANDLE hSession, - CK_OBJECT_HANDLE hKey -); - -CK_RV CK_ENTRY C_DigestFinal -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pDigest, - CK_ULONG_PTR pulDigestLen -); - -CK_RV CK_ENTRY C_SignInit -( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey -); - -CK_RV CK_ENTRY C_Sign -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pData, - CK_ULONG ulDataLen, - CK_BYTE_PTR pSignature, - CK_ULONG_PTR pulSignatureLen -); - -CK_RV CK_ENTRY C_SignUpdate -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pPart, - CK_ULONG ulPartLen -); - -CK_RV CK_ENTRY C_SignFinal -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pSignature, - CK_ULONG_PTR pulSignatureLen -); - -CK_RV CK_ENTRY C_SignRecoverInit -( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey -); - -CK_RV CK_ENTRY C_SignRecover -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pData, - CK_ULONG ulDataLen, - CK_BYTE_PTR pSignature, - CK_ULONG_PTR pulSignatureLen -); - -CK_RV CK_ENTRY C_VerifyInit -( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey -); - -CK_RV CK_ENTRY C_Verify -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pData, - CK_ULONG ulDataLen, - CK_BYTE_PTR pSignature, - CK_ULONG ulSignatureLen -); - -CK_RV CK_ENTRY C_VerifyUpdate -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pPart, - CK_ULONG ulPartLen -); - -CK_RV CK_ENTRY C_VerifyFinal -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pSignature, - CK_ULONG ulSignatureLen -); - -CK_RV CK_ENTRY C_VerifyRecoverInit -( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey -); - -CK_RV CK_ENTRY C_VerifyRecover -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pSignature, - CK_ULONG ulSignatureLen, - CK_BYTE_PTR pData, - CK_ULONG_PTR pulDataLen -); - -CK_RV CK_ENTRY C_DigestEncryptUpdate -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pPart, - CK_ULONG ulPartLen, - CK_BYTE_PTR pEncryptedPart, - CK_ULONG_PTR pulEncryptedPartLen -); - -CK_RV CK_ENTRY C_DecryptDigestUpdate -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pEncryptedPart, - CK_ULONG ulEncryptedPartLen, - CK_BYTE_PTR pPart, - CK_ULONG_PTR pulPartLen -); - -CK_RV CK_ENTRY C_SignEncryptUpdate -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pPart, - CK_ULONG ulPartLen, - CK_BYTE_PTR pEncryptedPart, - CK_ULONG_PTR pulEncryptedPartLen -); - -CK_RV CK_ENTRY C_DecryptVerifyUpdate -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pEncryptedPart, - CK_ULONG ulEncryptedPartLen, - CK_BYTE_PTR pPart, - CK_ULONG_PTR pulPartLen -); - -CK_RV CK_ENTRY C_GenerateKey -( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount, - CK_OBJECT_HANDLE_PTR phKey -); - -CK_RV CK_ENTRY C_GenerateKeyPair -( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_ATTRIBUTE_PTR pPublicKeyTemplate, - CK_ULONG ulPublicKeyAttributeCount, - CK_ATTRIBUTE_PTR pPrivateKeyTemplate, - CK_ULONG ulPrivateKeyAttributeCount, - CK_OBJECT_HANDLE_PTR phPublicKey, - CK_OBJECT_HANDLE_PTR phPrivateKey -); - -CK_RV CK_ENTRY C_WrapKey -( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hWrappingKey, - CK_OBJECT_HANDLE hKey, - CK_BYTE_PTR pWrappedKey, - CK_ULONG_PTR pulWrappedKeyLen -); - -CK_RV CK_ENTRY C_UnwrapKey -( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hUnwrappingKey, - CK_BYTE_PTR pWrappedKey, - CK_ULONG ulWrappedKeyLen, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_OBJECT_HANDLE_PTR phKey -); - -CK_RV CK_ENTRY C_DeriveKey -( - CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hBaseKey, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_OBJECT_HANDLE_PTR phKey -); - -CK_RV CK_ENTRY C_SeedRandom -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pSeed, - CK_ULONG ulSeedLen -); - -CK_RV CK_ENTRY C_GenerateRandom -( - CK_SESSION_HANDLE hSession, - CK_BYTE_PTR RandomData, - CK_ULONG ulRandomLen -); - -CK_RV CK_ENTRY C_GetFunctionStatus -( - CK_SESSION_HANDLE hSession -); - -CK_RV CK_ENTRY C_CancelFunction -( - CK_SESSION_HANDLE hSession -); - -CK_RV CK_ENTRY C_WaitForSlotEvent -( - CK_FLAGS flags, - CK_SLOT_ID_PTR pSlot, - CK_VOID_PTR pRserved -); - -#endif /* NSSCKG_H */ +#include "pkcs11.h" diff --git a/security/nss/lib/ckfw/nssckp.h b/security/nss/lib/ckfw/nssckp.h deleted file mode 100644 index 502e18408..000000000 --- a/security/nss/lib/ckfw/nssckp.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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. - */ - -/* - * This file is in part derived from a file "pkcs11t.h" made available - * by RSA Security at ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/pkcs11t.h - */ - -#ifndef NSSCKP_H -#define NSSCKP_H - -#ifdef DEBUG -static const char NSSCKP_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; -#endif /* DEBUG */ - -#endif /* NSSCKP_H */ - -/* - * These platform-dependent packing rules are required by all PKCS#11 - * modules, to be binary compatible. These rules have been placed in - * separate header files (nssckp.h to enable the packing, nsscku.h to - * disable) for consistancy. These files can be included many times, - * so the bodies should *NOT* be in the multiple-inclusion-preventing - * #ifndef/#endif area above. - */ - -/* - * WIN32 is defined (when appropriate) in NSPR's prcpucfg.h. - */ - -#ifdef WIN32 -#pragma warning(disable:4103) -#pragma pack(push, cryptoki, 1) -#endif /* WIN32 */ - -/* End of nssckp.h */ diff --git a/security/nss/lib/ckfw/nssckt.h b/security/nss/lib/ckfw/nssckt.h index f2bf36f1d..f1b2ef1b5 100644 --- a/security/nss/lib/ckfw/nssckt.h +++ b/security/nss/lib/ckfw/nssckt.h @@ -30,1094 +30,13 @@ * may use your version of this file under either the MPL or the * GPL. */ +#ifndef _NSSCKT_H_ +#define _NSSCKT_H_ 1 -/* - * This file is in part derived from a file "pkcs11t.h" made available - * by RSA Security at ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/pkcs11t.h - * - * Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document - * is granted provided that it is identified as "RSA Security Inc Public-Key - * Cryptography Standards (PKCS)" in all material mentioning or referencing - * this document. - * - */ - -#ifndef NSSCKT_H -#define NSSCKT_H - -#ifdef DEBUG -static const char NSSCKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; -#endif /* DEBUG */ - -#include "nspr.h" - -/* - * nssckt.h - * - * This file contains the type definitions for Cryptoki (PKCS#11). - * These definitions are taken from the RSA Standard. - * - * NOTE: Unlike most things in NSS, there are public types and - * preprocessor definitions which do *NOT* begin with NSS-- rather, - * they begin with CK, as per the standard. - */ - -#ifndef CK_FALSE -#define CK_FALSE 0 -#endif - -#ifndef CK_TRUE -#define CK_TRUE (!CK_FALSE) -#endif - -#define CK_PTR * -#define CK_NULL_PTR 0 -#define CK_CALLBACK_FUNCTION(rv,func) rv (PR_CALLBACK * func) -#define CK_DECLARE_FUNCTION(rv,func) NSS_EXTERN rv func -#define CK_DECLARE_FUNCTION_POINTER(rv,func) rv (PR_CALLBACK * func) - -/* an unsigned 8-bit value */ -typedef unsigned char CK_BYTE; - -/* an unsigned 8-bit character */ -typedef CK_BYTE CK_CHAR; - -/* a BYTE-sized Boolean flag */ -typedef CK_BYTE CK_BBOOL; - -/* an unsigned value, at least 16 bits long */ -typedef unsigned short int CK_USHORT; - -/* a signed value, the same size as a CK_USHORT */ -typedef short int CK_SHORT; - -/* an unsigned value, at least 32 bits long */ -typedef unsigned long int CK_ULONG; - -/* a signed value, the same size as a CK_ULONG */ -/* CK_LONG is new for v2.0 */ -typedef long int CK_LONG; - -/* at least 32 bits; each bit is a Boolean flag */ -typedef CK_ULONG CK_FLAGS; - - -/* some special values for certain CK_ULONG variables */ -#define CK_UNAVAILABLE_INFORMATION (~0UL) -#define CK_EFFECTIVELY_INFINITE 0 - - -typedef CK_BYTE CK_PTR CK_BYTE_PTR; -typedef CK_CHAR CK_PTR CK_CHAR_PTR; -typedef CK_ULONG CK_PTR CK_ULONG_PTR; -typedef void CK_PTR CK_VOID_PTR; - -/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */ -typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR; - - -/* The following value is always invalid if used as a session */ -/* handle or object handle */ -#define CK_INVALID_HANDLE 0 - -#define CK_ENTRY - -/* pack */ -#include "nssckp.h" - -typedef struct CK_VERSION { - CK_BYTE major; /* integer portion of version number */ - CK_BYTE minor; /* 1/100ths portion of version number */ -} CK_VERSION; - -typedef CK_VERSION CK_PTR CK_VERSION_PTR; - - -typedef struct CK_INFO { - CK_VERSION cryptokiVersion; /* Cryptoki interface ver */ - CK_CHAR manufacturerID[32]; /* blank padded */ - CK_FLAGS flags; /* must be zero */ - - /* libraryDescription and libraryVersion are new for v2.0 */ - CK_CHAR libraryDescription[32]; /* blank padded */ - CK_VERSION libraryVersion; /* version of library */ -} CK_INFO; - -typedef CK_INFO CK_PTR CK_INFO_PTR; - - -/* CK_NOTIFICATION enumerates the types of notifications that - * Cryptoki provides to an application */ -/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG - * for v2.0 */ -typedef CK_ULONG CK_NOTIFICATION; -#define CKN_SURRENDER 0 - - -typedef CK_ULONG CK_SLOT_ID; - -typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR; - - -/* CK_SLOT_INFO provides information about a slot */ -typedef struct CK_SLOT_INFO { - CK_CHAR slotDescription[64]; /* blank padded */ - CK_CHAR manufacturerID[32]; /* blank padded */ - CK_FLAGS flags; - - /* hardwareVersion and firmwareVersion are new for v2.0 */ - CK_VERSION hardwareVersion; /* version of hardware */ - CK_VERSION firmwareVersion; /* version of firmware */ -} CK_SLOT_INFO; - -/* flags: bit flags that provide capabilities of the slot - * Bit Flag Mask Meaning - */ -#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */ -#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/ -#define CKF_HW_SLOT 0x00000004 /* hardware slot */ - -typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR; - - -/* CK_TOKEN_INFO provides information about a token */ -typedef struct CK_TOKEN_INFO { - CK_CHAR label[32]; /* blank padded */ - CK_CHAR manufacturerID[32]; /* blank padded */ - CK_CHAR model[16]; /* blank padded */ - CK_CHAR serialNumber[16]; /* blank padded */ - CK_FLAGS flags; /* see below */ - - /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount, - * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been - * changed from CK_USHORT to CK_ULONG for v2.0 */ - CK_ULONG ulMaxSessionCount; /* max open sessions */ - CK_ULONG ulSessionCount; /* sess. now open */ - CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */ - CK_ULONG ulRwSessionCount; /* R/W sess. now open */ - CK_ULONG ulMaxPinLen; /* in bytes */ - CK_ULONG ulMinPinLen; /* in bytes */ - CK_ULONG ulTotalPublicMemory; /* in bytes */ - CK_ULONG ulFreePublicMemory; /* in bytes */ - CK_ULONG ulTotalPrivateMemory; /* in bytes */ - CK_ULONG ulFreePrivateMemory; /* in bytes */ - - /* hardwareVersion, firmwareVersion, and time are new for - * v2.0 */ - CK_VERSION hardwareVersion; /* version of hardware */ - CK_VERSION firmwareVersion; /* version of firmware */ - CK_CHAR utcTime[16]; /* time */ -} CK_TOKEN_INFO; - -/* The flags parameter is defined as follows: - * Bit Flag Mask Meaning - */ -#define CKF_RNG 0x00000001 /* has random # - * generator */ -#define CKF_WRITE_PROTECTED 0x00000002 /* token is - * write- - * protected */ -#define CKF_LOGIN_REQUIRED 0x00000004 /* user must - * login */ -#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's - * PIN is set */ - -/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set, - * that means that *every* time the state of cryptographic - * operations of a session is successfully saved, all keys - * needed to continue those operations are stored in the state */ -#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020 - -/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means - * that the token has some sort of clock. The time on that - * clock is returned in the token info structure */ -#define CKF_CLOCK_ON_TOKEN 0x00000040 - -/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is - * set, that means that there is some way for the user to login - * without sending a PIN through the Cryptoki library itself */ -#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100 - -/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true, - * that means that a single session with the token can perform - * dual simultaneous cryptographic operations (digest and - * encrypt; decrypt and digest; sign and encrypt; and decrypt - * and sign) */ -#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200 - -typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; - - -/* CK_SESSION_HANDLE is a Cryptoki-assigned value that - * identifies a session */ -typedef CK_ULONG CK_SESSION_HANDLE; - -typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; - - -/* CK_USER_TYPE enumerates the types of Cryptoki users */ -/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for - * v2.0 */ -typedef CK_ULONG CK_USER_TYPE; -/* Security Officer */ -#define CKU_SO 0 -/* Normal user */ -#define CKU_USER 1 - - -/* CK_STATE enumerates the session states */ -/* CK_STATE has been changed from an enum to a CK_ULONG for - * v2.0 */ -typedef CK_ULONG CK_STATE; -#define CKS_RO_PUBLIC_SESSION 0 -#define CKS_RO_USER_FUNCTIONS 1 -#define CKS_RW_PUBLIC_SESSION 2 -#define CKS_RW_USER_FUNCTIONS 3 -#define CKS_RW_SO_FUNCTIONS 4 - - -/* CK_SESSION_INFO provides information about a session */ -typedef struct CK_SESSION_INFO { - CK_SLOT_ID slotID; - CK_STATE state; - CK_FLAGS flags; /* see below */ - - /* ulDeviceError was changed from CK_USHORT to CK_ULONG for - * v2.0 */ - CK_ULONG ulDeviceError; /* device-dependent error code */ -} CK_SESSION_INFO; - -/* The flags are defined in the following table: - * Bit Flag Mask Meaning - */ -#define CKF_RW_SESSION 0x00000002 /* session is r/w */ -#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */ - -typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR; - - -/* CK_OBJECT_HANDLE is a token-specific identifier for an - * object */ -typedef CK_ULONG CK_OBJECT_HANDLE; - -typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR; - - -/* CK_OBJECT_CLASS is a value that identifies the classes (or - * types) of objects that Cryptoki recognizes. It is defined - * as follows: */ -/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for - * v2.0 */ -typedef CK_ULONG CK_OBJECT_CLASS; - -/* The following classes of objects are defined: */ -#define CKO_DATA 0x00000000 -#define CKO_CERTIFICATE 0x00000001 -#define CKO_PUBLIC_KEY 0x00000002 -#define CKO_PRIVATE_KEY 0x00000003 -#define CKO_SECRET_KEY 0x00000004 -#define CKO_VENDOR_DEFINED 0x80000000 - -typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; - - -/* CK_KEY_TYPE is a value that identifies a key type */ -/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */ -typedef CK_ULONG CK_KEY_TYPE; - -/* the following key types are defined: */ -#define CKK_RSA 0x00000000 -#define CKK_DSA 0x00000001 -#define CKK_DH 0x00000002 - -/* CKK_ECDSA and CKK_KEA are new for v2.0 */ - -/* Cryptoki V2.01 probably won't actually have ECDSA in it */ -#define CKK_ECDSA 0x00000003 - -#define CKK_KEA 0x00000005 - -#define CKK_GENERIC_SECRET 0x00000010 -#define CKK_RC2 0x00000011 -#define CKK_RC4 0x00000012 -#define CKK_DES 0x00000013 -#define CKK_DES2 0x00000014 -#define CKK_DES3 0x00000015 - -/* all these key types are new for v2.0 */ -#define CKK_CAST 0x00000016 -#define CKK_CAST3 0x00000017 -#define CKK_CAST5 0x00000018 -#define CKK_CAST128 0x00000018 /* CAST128=CAST5 */ -#define CKK_RC5 0x00000019 -#define CKK_IDEA 0x0000001A -#define CKK_SKIPJACK 0x0000001B -#define CKK_BATON 0x0000001C -#define CKK_JUNIPER 0x0000001D -#define CKK_CDMF 0x0000001E - -#define CKK_VENDOR_DEFINED 0x80000000 - - -/* CK_CERTIFICATE_TYPE is a value that identifies a certificate - * type */ -/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG - * for v2.0 */ -typedef CK_ULONG CK_CERTIFICATE_TYPE; - -/* The following certificate types are defined: */ -#define CKC_X_509 0x00000000 -#define CKC_VENDOR_DEFINED 0x80000000 - -/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute - * type */ -/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for - * v2.0 */ -typedef CK_ULONG CK_ATTRIBUTE_TYPE; +#include "pkcs11t.h" typedef CK_ATTRIBUTE_TYPE CK_PTR CK_ATTRIBUTE_TYPE_PTR; +#define CK_ENTRY -/* The following attribute types are defined: */ -#define CKA_CLASS 0x00000000 -#define CKA_TOKEN 0x00000001 -#define CKA_PRIVATE 0x00000002 -#define CKA_LABEL 0x00000003 -#define CKA_APPLICATION 0x00000010 -#define CKA_VALUE 0x00000011 -#define CKA_CERTIFICATE_TYPE 0x00000080 -#define CKA_ISSUER 0x00000081 -#define CKA_SERIAL_NUMBER 0x00000082 -#define CKA_KEY_TYPE 0x00000100 -#define CKA_SUBJECT 0x00000101 -#define CKA_ID 0x00000102 -#define CKA_SENSITIVE 0x00000103 -#define CKA_ENCRYPT 0x00000104 -#define CKA_DECRYPT 0x00000105 -#define CKA_WRAP 0x00000106 -#define CKA_UNWRAP 0x00000107 -#define CKA_SIGN 0x00000108 -#define CKA_SIGN_RECOVER 0x00000109 -#define CKA_VERIFY 0x0000010A -#define CKA_VERIFY_RECOVER 0x0000010B -#define CKA_DERIVE 0x0000010C -#define CKA_START_DATE 0x00000110 -#define CKA_END_DATE 0x00000111 -#define CKA_MODULUS 0x00000120 -#define CKA_MODULUS_BITS 0x00000121 -#define CKA_PUBLIC_EXPONENT 0x00000122 -#define CKA_PRIVATE_EXPONENT 0x00000123 -#define CKA_PRIME_1 0x00000124 -#define CKA_PRIME_2 0x00000125 -#define CKA_EXPONENT_1 0x00000126 -#define CKA_EXPONENT_2 0x00000127 -#define CKA_COEFFICIENT 0x00000128 -#define CKA_PRIME 0x00000130 -#define CKA_SUBPRIME 0x00000131 -#define CKA_BASE 0x00000132 -#define CKA_VALUE_BITS 0x00000160 -#define CKA_VALUE_LEN 0x00000161 - -/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE, - * CKA_ALWAYS_SENSITIVE, and CKA_MODIFIABLE are new for v2.0 */ -#define CKA_EXTRACTABLE 0x00000162 -#define CKA_LOCAL 0x00000163 -#define CKA_NEVER_EXTRACTABLE 0x00000164 -#define CKA_ALWAYS_SENSITIVE 0x00000165 -#define CKA_MODIFIABLE 0x00000170 - -#define CKA_VENDOR_DEFINED 0x80000000 - - -/* CK_ATTRIBUTE is a structure that includes the type, length - * and value of an attribute */ -typedef struct CK_ATTRIBUTE { - CK_ATTRIBUTE_TYPE type; - CK_VOID_PTR pValue; - - /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */ - CK_ULONG ulValueLen; /* in bytes */ -} CK_ATTRIBUTE; - -typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR; - - -/* CK_DATE is a structure that defines a date */ -typedef struct CK_DATE{ - CK_CHAR year[4]; /* the year ("1900" - "9999") */ - CK_CHAR month[2]; /* the month ("01" - "12") */ - CK_CHAR day[2]; /* the day ("01" - "31") */ -} CK_DATE; - - -/* CK_MECHANISM_TYPE is a value that identifies a mechanism - * type */ -/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for - * v2.0 */ -typedef CK_ULONG CK_MECHANISM_TYPE; - -/* the following mechanism types are defined: */ -#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000 -#define CKM_RSA_PKCS 0x00000001 -#define CKM_RSA_9796 0x00000002 -#define CKM_RSA_X_509 0x00000003 - -/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS - * are new for v2.0. They are mechanisms which hash and sign */ -#define CKM_MD2_RSA_PKCS 0x00000004 -#define CKM_MD5_RSA_PKCS 0x00000005 -#define CKM_SHA1_RSA_PKCS 0x00000006 - -#define CKM_DSA_KEY_PAIR_GEN 0x00000010 -#define CKM_DSA 0x00000011 -#define CKM_DSA_SHA1 0x00000012 -#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 -#define CKM_DH_PKCS_DERIVE 0x00000021 -#define CKM_RC2_KEY_GEN 0x00000100 -#define CKM_RC2_ECB 0x00000101 -#define CKM_RC2_CBC 0x00000102 -#define CKM_RC2_MAC 0x00000103 - -/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */ -#define CKM_RC2_MAC_GENERAL 0x00000104 -#define CKM_RC2_CBC_PAD 0x00000105 - -#define CKM_RC4_KEY_GEN 0x00000110 -#define CKM_RC4 0x00000111 -#define CKM_DES_KEY_GEN 0x00000120 -#define CKM_DES_ECB 0x00000121 -#define CKM_DES_CBC 0x00000122 -#define CKM_DES_MAC 0x00000123 - -/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */ -#define CKM_DES_MAC_GENERAL 0x00000124 -#define CKM_DES_CBC_PAD 0x00000125 - -#define CKM_DES2_KEY_GEN 0x00000130 -#define CKM_DES3_KEY_GEN 0x00000131 -#define CKM_DES3_ECB 0x00000132 -#define CKM_DES3_CBC 0x00000133 -#define CKM_DES3_MAC 0x00000134 - -/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN, - * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC, - * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */ -#define CKM_DES3_MAC_GENERAL 0x00000135 -#define CKM_DES3_CBC_PAD 0x00000136 -#define CKM_CDMF_KEY_GEN 0x00000140 -#define CKM_CDMF_ECB 0x00000141 -#define CKM_CDMF_CBC 0x00000142 -#define CKM_CDMF_MAC 0x00000143 -#define CKM_CDMF_MAC_GENERAL 0x00000144 -#define CKM_CDMF_CBC_PAD 0x00000145 - -#define CKM_MD2 0x00000200 - -/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */ -#define CKM_MD2_HMAC 0x00000201 -#define CKM_MD2_HMAC_GENERAL 0x00000202 - -#define CKM_MD5 0x00000210 - -/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */ -#define CKM_MD5_HMAC 0x00000211 -#define CKM_MD5_HMAC_GENERAL 0x00000212 - -#define CKM_SHA_1 0x00000220 - -/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */ -#define CKM_SHA_1_HMAC 0x00000221 -#define CKM_SHA_1_HMAC_GENERAL 0x00000222 - -/* All of the following mechanisms are new for v2.0 */ -/* Note that CAST128 and CAST5 are the same algorithm */ -#define CKM_CAST_KEY_GEN 0x00000300 -#define CKM_CAST_ECB 0x00000301 -#define CKM_CAST_CBC 0x00000302 -#define CKM_CAST_MAC 0x00000303 -#define CKM_CAST_MAC_GENERAL 0x00000304 -#define CKM_CAST_CBC_PAD 0x00000305 -#define CKM_CAST3_KEY_GEN 0x00000310 -#define CKM_CAST3_ECB 0x00000311 -#define CKM_CAST3_CBC 0x00000312 -#define CKM_CAST3_MAC 0x00000313 -#define CKM_CAST3_MAC_GENERAL 0x00000314 -#define CKM_CAST3_CBC_PAD 0x00000315 -#define CKM_CAST5_KEY_GEN 0x00000320 -#define CKM_CAST128_KEY_GEN 0x00000320 -#define CKM_CAST5_ECB 0x00000321 -#define CKM_CAST128_ECB 0x00000321 -#define CKM_CAST5_CBC 0x00000322 -#define CKM_CAST128_CBC 0x00000322 -#define CKM_CAST5_MAC 0x00000323 -#define CKM_CAST128_MAC 0x00000323 -#define CKM_CAST5_MAC_GENERAL 0x00000324 -#define CKM_CAST128_MAC_GENERAL 0x00000324 -#define CKM_CAST5_CBC_PAD 0x00000325 -#define CKM_CAST128_CBC_PAD 0x00000325 -#define CKM_RC5_KEY_GEN 0x00000330 -#define CKM_RC5_ECB 0x00000331 -#define CKM_RC5_CBC 0x00000332 -#define CKM_RC5_MAC 0x00000333 -#define CKM_RC5_MAC_GENERAL 0x00000334 -#define CKM_RC5_CBC_PAD 0x00000335 -#define CKM_IDEA_KEY_GEN 0x00000340 -#define CKM_IDEA_ECB 0x00000341 -#define CKM_IDEA_CBC 0x00000342 -#define CKM_IDEA_MAC 0x00000343 -#define CKM_IDEA_MAC_GENERAL 0x00000344 -#define CKM_IDEA_CBC_PAD 0x00000345 -#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350 -#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360 -#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362 -#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363 -#define CKM_XOR_BASE_AND_DATA 0x00000364 -#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365 -#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370 -#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371 -#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372 -#define CKM_SSL3_MD5_MAC 0x00000380 -#define CKM_SSL3_SHA1_MAC 0x00000381 -#define CKM_MD5_KEY_DERIVATION 0x00000390 -#define CKM_MD2_KEY_DERIVATION 0x00000391 -#define CKM_SHA1_KEY_DERIVATION 0x00000392 -#define CKM_PBE_MD2_DES_CBC 0x000003A0 -#define CKM_PBE_MD5_DES_CBC 0x000003A1 -#define CKM_PBE_MD5_CAST_CBC 0x000003A2 -#define CKM_PBE_MD5_CAST3_CBC 0x000003A3 -#define CKM_PBE_MD5_CAST5_CBC 0x000003A4 -#define CKM_PBE_MD5_CAST128_CBC 0x000003A4 -#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5 -#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5 -#define CKM_PBE_SHA1_RC4_128 0x000003A6 -#define CKM_PBE_SHA1_RC4_40 0x000003A7 -#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8 -#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9 -#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA -#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB -#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 -#define CKM_KEY_WRAP_LYNKS 0x00000400 -#define CKM_KEY_WRAP_SET_OAEP 0x00000401 - -/* Fortezza mechanisms */ -#define CKM_SKIPJACK_KEY_GEN 0x00001000 -#define CKM_SKIPJACK_ECB64 0x00001001 -#define CKM_SKIPJACK_CBC64 0x00001002 -#define CKM_SKIPJACK_OFB64 0x00001003 -#define CKM_SKIPJACK_CFB64 0x00001004 -#define CKM_SKIPJACK_CFB32 0x00001005 -#define CKM_SKIPJACK_CFB16 0x00001006 -#define CKM_SKIPJACK_CFB8 0x00001007 -#define CKM_SKIPJACK_WRAP 0x00001008 -#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009 -#define CKM_SKIPJACK_RELAYX 0x0000100a -#define CKM_KEA_KEY_PAIR_GEN 0x00001010 -#define CKM_KEA_KEY_DERIVE 0x00001011 -#define CKM_FORTEZZA_TIMESTAMP 0x00001020 -#define CKM_BATON_KEY_GEN 0x00001030 -#define CKM_BATON_ECB128 0x00001031 -#define CKM_BATON_ECB96 0x00001032 -#define CKM_BATON_CBC128 0x00001033 -#define CKM_BATON_COUNTER 0x00001034 -#define CKM_BATON_SHUFFLE 0x00001035 -#define CKM_BATON_WRAP 0x00001036 - -/* Cryptoki V2.01 probably won't actually have ECDSA in it */ -#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 -#define CKM_ECDSA 0x00001041 -#define CKM_ECDSA_SHA1 0x00001042 - -#define CKM_JUNIPER_KEY_GEN 0x00001060 -#define CKM_JUNIPER_ECB128 0x00001061 -#define CKM_JUNIPER_CBC128 0x00001062 -#define CKM_JUNIPER_COUNTER 0x00001063 -#define CKM_JUNIPER_SHUFFLE 0x00001064 -#define CKM_JUNIPER_WRAP 0x00001065 -#define CKM_FASTHASH 0x00001070 - -#define CKM_VENDOR_DEFINED 0x80000000 - -typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR; - - -/* CK_MECHANISM is a structure that specifies a particular - * mechanism */ -typedef struct CK_MECHANISM { - CK_MECHANISM_TYPE mechanism; - CK_VOID_PTR pParameter; - - /* ulParameterLen was changed from CK_USHORT to CK_ULONG for - * v2.0 */ - CK_ULONG ulParameterLen; /* in bytes */ -} CK_MECHANISM; - -typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR; - - -/* CK_MECHANISM_INFO provides information about a particular - * mechanism */ -typedef struct CK_MECHANISM_INFO { - CK_ULONG ulMinKeySize; - CK_ULONG ulMaxKeySize; - CK_FLAGS flags; -} CK_MECHANISM_INFO; - -/* The flags are defined as follows: - * Bit Flag Mask Meaning */ -#define CKF_HW 0x00000001 /* performed by HW */ - -/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN, - * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER, - * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP, - * and CKF_DERIVE are new for v2.0. They specify whether or not - * a mechanism can be used for a particular task */ -#define CKF_ENCRYPT 0x00000100 -#define CKF_DECRYPT 0x00000200 -#define CKF_DIGEST 0x00000400 -#define CKF_SIGN 0x00000800 -#define CKF_SIGN_RECOVER 0x00001000 -#define CKF_VERIFY 0x00002000 -#define CKF_VERIFY_RECOVER 0x00004000 -#define CKF_GENERATE 0x00008000 -#define CKF_GENERATE_KEY_PAIR 0x00010000 -#define CKF_WRAP 0x00020000 -#define CKF_UNWRAP 0x00040000 -#define CKF_DERIVE 0x00080000 - -#define CKF_EXTENSION 0x80000000 /* FALSE for 2.01 */ - -typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR; - - -/* CK_RV is a value that identifies the return value of a - * Cryptoki function */ -/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */ -typedef CK_ULONG CK_RV; - -#define CKR_OK 0x00000000 -#define CKR_CANCEL 0x00000001 -#define CKR_HOST_MEMORY 0x00000002 -#define CKR_SLOT_ID_INVALID 0x00000003 - -/* CKR_FLAGS_INVALID was removed for v2.0 */ - -/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */ -#define CKR_GENERAL_ERROR 0x00000005 -#define CKR_FUNCTION_FAILED 0x00000006 - -/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS, - * and CKR_CANT_LOCK are new for v2.01 */ -#define CKR_ARGUMENTS_BAD 0x00000007 -#define CKR_NO_EVENT 0x00000008 -#define CKR_NEED_TO_CREATE_THREADS 0x00000009 -#define CKR_CANT_LOCK 0x0000000A - -#define CKR_ATTRIBUTE_READ_ONLY 0x00000010 -#define CKR_ATTRIBUTE_SENSITIVE 0x00000011 -#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012 -#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013 -#define CKR_DATA_INVALID 0x00000020 -#define CKR_DATA_LEN_RANGE 0x00000021 -#define CKR_DEVICE_ERROR 0x00000030 -#define CKR_DEVICE_MEMORY 0x00000031 -#define CKR_DEVICE_REMOVED 0x00000032 -#define CKR_ENCRYPTED_DATA_INVALID 0x00000040 -#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041 -#define CKR_FUNCTION_CANCELED 0x00000050 -#define CKR_FUNCTION_NOT_PARALLEL 0x00000051 - -/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */ -#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054 - -#define CKR_KEY_HANDLE_INVALID 0x00000060 - -/* CKR_KEY_SENSITIVE was removed for v2.0 */ - -#define CKR_KEY_SIZE_RANGE 0x00000062 -#define CKR_KEY_TYPE_INCONSISTENT 0x00000063 - -/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED, - * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED, - * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for - * v2.0 */ -#define CKR_KEY_NOT_NEEDED 0x00000064 -#define CKR_KEY_CHANGED 0x00000065 -#define CKR_KEY_NEEDED 0x00000066 -#define CKR_KEY_INDIGESTIBLE 0x00000067 -#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068 -#define CKR_KEY_NOT_WRAPPABLE 0x00000069 -#define CKR_KEY_UNEXTRACTABLE 0x0000006A - -#define CKR_MECHANISM_INVALID 0x00000070 -#define CKR_MECHANISM_PARAM_INVALID 0x00000071 - -/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID - * were removed for v2.0 */ -#define CKR_OBJECT_HANDLE_INVALID 0x00000082 -#define CKR_OPERATION_ACTIVE 0x00000090 -#define CKR_OPERATION_NOT_INITIALIZED 0x00000091 -#define CKR_PIN_INCORRECT 0x000000A0 -#define CKR_PIN_INVALID 0x000000A1 -#define CKR_PIN_LEN_RANGE 0x000000A2 - -/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */ -#define CKR_PIN_EXPIRED 0x000000A3 -#define CKR_PIN_LOCKED 0x000000A4 - -#define CKR_SESSION_CLOSED 0x000000B0 -#define CKR_SESSION_COUNT 0x000000B1 -#define CKR_SESSION_HANDLE_INVALID 0x000000B3 -#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4 -#define CKR_SESSION_READ_ONLY 0x000000B5 -#define CKR_SESSION_EXISTS 0x000000B6 - -/* CKR_SESSION_READ_ONLY_EXISTS and - * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */ -#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7 -#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8 - -#define CKR_SIGNATURE_INVALID 0x000000C0 -#define CKR_SIGNATURE_LEN_RANGE 0x000000C1 -#define CKR_TEMPLATE_INCOMPLETE 0x000000D0 -#define CKR_TEMPLATE_INCONSISTENT 0x000000D1 -#define CKR_TOKEN_NOT_PRESENT 0x000000E0 -#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1 -#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2 -#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0 -#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1 -#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2 -#define CKR_USER_ALREADY_LOGGED_IN 0x00000100 -#define CKR_USER_NOT_LOGGED_IN 0x00000101 -#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102 -#define CKR_USER_TYPE_INVALID 0x00000103 - -/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES - * are new to v2.01 */ -#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104 -#define CKR_USER_TOO_MANY_TYPES 0x00000105 - -#define CKR_WRAPPED_KEY_INVALID 0x00000110 -#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112 -#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113 -#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114 -#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115 -#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120 - -/* These are new to v2.0 */ -#define CKR_RANDOM_NO_RNG 0x00000121 -#define CKR_BUFFER_TOO_SMALL 0x00000150 -#define CKR_SAVED_STATE_INVALID 0x00000160 -#define CKR_INFORMATION_SENSITIVE 0x00000170 -#define CKR_STATE_UNSAVEABLE 0x00000180 - -/* These are new to v2.01 */ -#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190 -#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191 -#define CKR_MUTEX_BAD 0x000001A0 -#define CKR_MUTEX_NOT_LOCKED 0x000001A1 - -#define CKR_VENDOR_DEFINED 0x80000000 - - -/* CK_NOTIFY is an application callback that processes events */ -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)( - CK_SESSION_HANDLE hSession, /* the session's handle */ - CK_NOTIFICATION event, - CK_VOID_PTR pApplication /* passed to C_OpenSession */ -); - - -/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec - * version and pointers of appropriate types to all the - * Cryptoki functions */ -/* CK_FUNCTION_LIST is new for v2.0 */ -typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; - -typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR; - -typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR; - - -/* CK_CREATEMUTEX is an application callback for creating a - * mutex object */ -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)( - CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */ -); - - -/* CK_DESTROYMUTEX is an application callback for destroying a - * mutex object */ -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)( - CK_VOID_PTR pMutex /* pointer to mutex */ -); - - -/* CK_LOCKMUTEX is an application callback for locking a mutex */ -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)( - CK_VOID_PTR pMutex /* pointer to mutex */ -); - - -/* CK_UNLOCKMUTEX is an application callback for unlocking a - * mutex */ -typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)( - CK_VOID_PTR pMutex /* pointer to mutex */ -); - - -/* CK_C_INITIALIZE_ARGS provides the optional arguments to - * C_Initialize */ -typedef struct CK_C_INITIALIZE_ARGS { - CK_CREATEMUTEX CreateMutex; - CK_DESTROYMUTEX DestroyMutex; - CK_LOCKMUTEX LockMutex; - CK_UNLOCKMUTEX UnlockMutex; - CK_FLAGS flags; -#ifdef FGMR - CK_BYTE_PTR pConfig; - CK_ULONG ulConfigLen; -#endif /* FGMR */ - CK_VOID_PTR pReserved; -} CK_C_INITIALIZE_ARGS; - -/* flags: bit flags that provide capabilities of the slot - * Bit Flag Mask Meaning - */ -#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001 -#define CKF_OS_LOCKING_OK 0x00000002 - -typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR; - - -/* additional flags for parameters to functions */ - -/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */ -#define CKF_DONT_BLOCK 1 - - -/* CK_KEA_DERIVE_PARAMS provides the parameters to the - * CKM_KEA_DERIVE mechanism */ -/* CK_KEA_DERIVE_PARAMS is new for v2.0 */ -typedef struct CK_KEA_DERIVE_PARAMS { - CK_BBOOL isSender; - CK_ULONG ulRandomLen; - CK_BYTE_PTR pRandomA; - CK_BYTE_PTR pRandomB; - CK_ULONG ulPublicDataLen; - CK_BYTE_PTR pPublicData; -} CK_KEA_DERIVE_PARAMS; - -typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR; - - -/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and - * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just - * holds the effective keysize */ -typedef CK_ULONG CK_RC2_PARAMS; - -typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR; - - -/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC - * mechanism */ -typedef struct CK_RC2_CBC_PARAMS { - /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for - * v2.0 */ - CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ - - CK_BYTE iv[8]; /* IV for CBC mode */ -} CK_RC2_CBC_PARAMS; - -typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR; - - -/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the - * CKM_RC2_MAC_GENERAL mechanism */ -/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */ -typedef struct CK_RC2_MAC_GENERAL_PARAMS { - CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ - CK_ULONG ulMacLength; /* Length of MAC in bytes */ -} CK_RC2_MAC_GENERAL_PARAMS; - -typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \ - CK_RC2_MAC_GENERAL_PARAMS_PTR; - - -/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and - * CKM_RC5_MAC mechanisms */ -/* CK_RC5_PARAMS is new for v2.0 */ -typedef struct CK_RC5_PARAMS { - CK_ULONG ulWordsize; /* wordsize in bits */ - CK_ULONG ulRounds; /* number of rounds */ -} CK_RC5_PARAMS; - -typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR; - - -/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC - * mechanism */ -/* CK_RC5_CBC_PARAMS is new for v2.0 */ -typedef struct CK_RC5_CBC_PARAMS { - CK_ULONG ulWordsize; /* wordsize in bits */ - CK_ULONG ulRounds; /* number of rounds */ - CK_BYTE_PTR pIv; /* pointer to IV */ - CK_ULONG ulIvLen; /* length of IV in bytes */ -} CK_RC5_CBC_PARAMS; - -typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR; - - -/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the - * CKM_RC5_MAC_GENERAL mechanism */ -/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */ -typedef struct CK_RC5_MAC_GENERAL_PARAMS { - CK_ULONG ulWordsize; /* wordsize in bits */ - CK_ULONG ulRounds; /* number of rounds */ - CK_ULONG ulMacLength; /* Length of MAC in bytes */ -} CK_RC5_MAC_GENERAL_PARAMS; - -typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \ - CK_RC5_MAC_GENERAL_PARAMS_PTR; - - -/* CK_MAC_GENERAL_PARAMS provides the parameters to most block - * ciphers' MAC_GENERAL mechanisms. Its value is the length of - * the MAC */ -/* CK_MAC_GENERAL_PARAMS is new for v2.0 */ -typedef CK_ULONG CK_MAC_GENERAL_PARAMS; - -typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR; - - -/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the - * CKM_SKIPJACK_PRIVATE_WRAP mechanism */ -/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */ -typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS { - CK_ULONG ulPasswordLen; - CK_BYTE_PTR pPassword; - CK_ULONG ulPublicDataLen; - CK_BYTE_PTR pPublicData; - CK_ULONG ulPAndGLen; - CK_ULONG ulQLen; - CK_ULONG ulRandomLen; - CK_BYTE_PTR pRandomA; - CK_BYTE_PTR pPrimeP; - CK_BYTE_PTR pBaseG; - CK_BYTE_PTR pSubprimeQ; -} CK_SKIPJACK_PRIVATE_WRAP_PARAMS; - -typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \ - CK_SKIPJACK_PRIVATE_WRAP_PTR; - - -/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the - * CKM_SKIPJACK_RELAYX mechanism */ -/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */ -typedef struct CK_SKIPJACK_RELAYX_PARAMS { - CK_ULONG ulOldWrappedXLen; - CK_BYTE_PTR pOldWrappedX; - CK_ULONG ulOldPasswordLen; - CK_BYTE_PTR pOldPassword; - CK_ULONG ulOldPublicDataLen; - CK_BYTE_PTR pOldPublicData; - CK_ULONG ulOldRandomLen; - CK_BYTE_PTR pOldRandomA; - CK_ULONG ulNewPasswordLen; - CK_BYTE_PTR pNewPassword; - CK_ULONG ulNewPublicDataLen; - CK_BYTE_PTR pNewPublicData; - CK_ULONG ulNewRandomLen; - CK_BYTE_PTR pNewRandomA; -} CK_SKIPJACK_RELAYX_PARAMS; - -typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \ - CK_SKIPJACK_RELAYX_PARAMS_PTR; - - -typedef struct CK_PBE_PARAMS { - CK_CHAR_PTR pInitVector; - CK_CHAR_PTR pPassword; - CK_ULONG ulPasswordLen; - CK_CHAR_PTR pSalt; - CK_ULONG ulSaltLen; - CK_ULONG ulIteration; -} CK_PBE_PARAMS; - -typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR; - - -/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the - * CKM_KEY_WRAP_SET_OAEP mechanism */ -/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */ -typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS { - CK_BYTE bBC; /* block contents byte */ - CK_BYTE_PTR pX; /* extra data */ - CK_ULONG ulXLen; /* length of extra data in bytes */ -} CK_KEY_WRAP_SET_OAEP_PARAMS; - -typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \ - CK_KEY_WRAP_SET_OAEP_PARAMS_PTR; - - -typedef struct CK_SSL3_RANDOM_DATA { - CK_BYTE_PTR pClientRandom; - CK_ULONG ulClientRandomLen; - CK_BYTE_PTR pServerRandom; - CK_ULONG ulServerRandomLen; -} CK_SSL3_RANDOM_DATA; - - -typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS { - CK_SSL3_RANDOM_DATA RandomInfo; - CK_VERSION_PTR pVersion; -} CK_SSL3_MASTER_KEY_DERIVE_PARAMS; - -typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \ - CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR; - - -typedef struct CK_SSL3_KEY_MAT_OUT { - CK_OBJECT_HANDLE hClientMacSecret; - CK_OBJECT_HANDLE hServerMacSecret; - CK_OBJECT_HANDLE hClientKey; - CK_OBJECT_HANDLE hServerKey; - CK_BYTE_PTR pIVClient; - CK_BYTE_PTR pIVServer; -} CK_SSL3_KEY_MAT_OUT; - -typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR; - - -typedef struct CK_SSL3_KEY_MAT_PARAMS { - CK_ULONG ulMacSizeInBits; - CK_ULONG ulKeySizeInBits; - CK_ULONG ulIVSizeInBits; - CK_BBOOL bIsExport; - CK_SSL3_RANDOM_DATA RandomInfo; - CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial; -} CK_SSL3_KEY_MAT_PARAMS; - -typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR; - - -typedef struct CK_KEY_DERIVATION_STRING_DATA { - CK_BYTE_PTR pData; - CK_ULONG ulLen; -} CK_KEY_DERIVATION_STRING_DATA; - -typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \ - CK_KEY_DERIVATION_STRING_DATA_PTR; - - -/* The CK_EXTRACT_PARAMS is used for the - * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit - * of the base key should be used as the first bit of the - * derived key */ -/* CK_EXTRACT_PARAMS is new for v2.0 */ -typedef CK_ULONG CK_EXTRACT_PARAMS; - -typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; - -/* undo packing */ -#include "nsscku.h" +#endif /* _NSSCKT_H_ */ -#endif /* NSSCKT_H */ diff --git a/security/nss/lib/cryptohi/seckey.c b/security/nss/lib/cryptohi/seckey.c index 78ad26115..076dbc6a6 100644 --- a/security/nss/lib/cryptohi/seckey.c +++ b/security/nss/lib/cryptohi/seckey.c @@ -860,7 +860,7 @@ seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki) pubk->arena = arena; pubk->pkcs11Slot = 0; - pubk->pkcs11ID = CK_INVALID_KEY; + pubk->pkcs11ID = CK_INVALID_HANDLE; /* Convert bit string length from bits to bytes */ @@ -1037,7 +1037,7 @@ SECKEY_CopyPrivateKey(SECKEYPrivateKey *privk) if (privk->pkcs11IsTemp) { copyk->pkcs11ID = PK11_CopyKey(privk->pkcs11Slot,privk->pkcs11ID); - if (copyk->pkcs11ID == CK_INVALID_KEY) goto fail; + if (copyk->pkcs11ID == CK_INVALID_HANDLE) goto fail; } else { copyk->pkcs11ID = privk->pkcs11ID; } @@ -1072,7 +1072,7 @@ SECKEY_CopyPublicKey(SECKEYPublicKey *pubk) copyk->arena = arena; copyk->keyType = pubk->keyType; copyk->pkcs11Slot = NULL; /* go get own reference */ - copyk->pkcs11ID = CK_INVALID_KEY; + copyk->pkcs11ID = CK_INVALID_HANDLE; switch (pubk->keyType) { case rsaKey: rv = SECITEM_CopyItem(arena, ©k->u.rsa.modulus, @@ -1201,7 +1201,7 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk) } pubk->keyType = privk->keyType; pubk->pkcs11Slot = NULL; - pubk->pkcs11ID = CK_INVALID_KEY; + pubk->pkcs11ID = CK_INVALID_HANDLE; pubk->arena = arena; /* diff --git a/security/nss/lib/dev/ckhelper.h b/security/nss/lib/dev/ckhelper.h index 5088a3b7f..d1da20500 100644 --- a/security/nss/lib/dev/ckhelper.h +++ b/security/nss/lib/dev/ckhelper.h @@ -44,13 +44,9 @@ static const char CKHELPER_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #endif /* DEBUG */ -#ifdef NSS_3_4_CODE -#include "pkcs11t.h" -#else #ifndef NSSCKT_H #include "nssckt.h" #endif /* NSSCKT_H */ -#endif /* NSS_3_4_CODE */ PR_BEGIN_EXTERN_C diff --git a/security/nss/lib/dev/dev.h b/security/nss/lib/dev/dev.h index 7333cb69a..0bca3fc46 100644 --- a/security/nss/lib/dev/dev.h +++ b/security/nss/lib/dev/dev.h @@ -42,13 +42,9 @@ static const char DEV_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "devt.h" #endif /* DEVT_H */ -#ifdef NSS_3_4_CODE -#include "pkcs11t.h" -#else #ifndef NSSCKT_H #include "nssckt.h" #endif /* NSSCKT_H */ -#endif /* NSS_3_4_CODE */ #ifndef NSSPKIT_H #include "nsspkit.h" diff --git a/security/nss/lib/dev/devm.h b/security/nss/lib/dev/devm.h index 989198600..d226069c9 100644 --- a/security/nss/lib/dev/devm.h +++ b/security/nss/lib/dev/devm.h @@ -42,13 +42,9 @@ static const char DEVM_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "devt.h" #endif /* DEVT_H */ -#ifdef NSS_3_4_CODE -#include "pkcs11t.h" -#else #ifndef NSSCKT_H #include "nssckt.h" #endif /* NSSCKT_H */ -#endif /* NSS_3_4_CODE */ #ifndef BASE_H #include "base.h" diff --git a/security/nss/lib/dev/module.c b/security/nss/lib/dev/devmod.c index a3cb0b164..301799b77 100644 --- a/security/nss/lib/dev/module.c +++ b/security/nss/lib/dev/devmod.c @@ -35,6 +35,8 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #endif /* DEBUG */ +#include "nspr.h" + #ifndef DEV_H #include "dev.h" #endif /* DEV_H */ @@ -43,13 +45,9 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "devm.h" #endif /* DEVM_H */ -#ifdef NSS_3_4_CODE -#include "pkcs11.h" -#else #ifndef NSSCKEPV_H #include "nssckepv.h" #endif /* NSSCKEPV_H */ -#endif /* NSS_3_4_CODE */ #ifndef CKHELPER_H #include "ckhelper.h" @@ -252,7 +250,7 @@ nssModule_Load CK_C_GetFunctionList ep; CK_RV ckrv; /* Use NSPR to load the library */ - library = PR_LoadLibrary(mod->libraryPath); + library = PR_LoadLibrary((char *)mod->libraryPath); if (!library) { /* what's the error to set? */ return PR_FAILURE; diff --git a/security/nss/lib/dev/slot.c b/security/nss/lib/dev/devslot.c index 25e16d2c4..25e16d2c4 100644 --- a/security/nss/lib/dev/slot.c +++ b/security/nss/lib/dev/devslot.c diff --git a/security/nss/lib/dev/devt.h b/security/nss/lib/dev/devt.h index f2deaa130..cf8a6309a 100644 --- a/security/nss/lib/dev/devt.h +++ b/security/nss/lib/dev/devt.h @@ -56,13 +56,12 @@ static const char DEVT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "nssdevt.h" #endif /* NSSDEVT_H */ -#ifdef NSS_3_4_CODE -#include "pkcs11t.h" -#include "secmodt.h" -#else #ifndef NSSCKT_H #include "nssckt.h" #endif /* NSSCKT_H */ + +#ifdef NSS_3_4_CODE +#include "secmodt.h" #endif /* NSS_3_4_CODE */ PR_BEGIN_EXTERN_C diff --git a/security/nss/lib/dev/token.c b/security/nss/lib/dev/devtoken.c index 341583b8c..ceb7b2441 100644 --- a/security/nss/lib/dev/token.c +++ b/security/nss/lib/dev/devtoken.c @@ -48,13 +48,9 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "pki.h" #endif /* PKI_H */ -#ifdef NSS_3_4_CODE -#include "pkcs11.h" -#else #ifndef NSSCKEPV_H #include "nssckepv.h" #endif /* NSSCKEPV_H */ -#endif /* NSS_3_4_CODE */ #ifndef NSSPKI_H #include "nsspki.h" @@ -219,25 +215,30 @@ nssToken_DeleteStoredObject CK_OBJECT_HANDLE object ) { - nssSession *session; + nssSession *session = NULL; CK_RV ckrv; PRStatus nssrv; PRBool createdSession; if (nssCKObject_IsAttributeTrue(object, CKA_TOKEN, tok->defaultSession, - tok->slot, &nssrv)) { - if (sessionOpt) { - if (!nssSession_IsReadWrite(sessionOpt)) { - return PR_FAILURE;; - } else { - session = sessionOpt; - } - } else if (nssSession_IsReadWrite(tok->defaultSession)) { - session = tok->defaultSession; - } else { - session = nssSlot_CreateSession(tok->slot, NULL, PR_TRUE); - createdSession = PR_TRUE; - } + tok->slot, &nssrv)) { + if (sessionOpt) { + if (!nssSession_IsReadWrite(sessionOpt)) { + return PR_FAILURE;; + } else { + session = sessionOpt; + } + } else if (nssSession_IsReadWrite(tok->defaultSession)) { + session = tok->defaultSession; + } else { + session = nssSlot_CreateSession(tok->slot, NULL, PR_TRUE); + createdSession = PR_TRUE; + } } + + if (session == NULL) { + return PR_FAILURE; + } + nssSession_EnterMonitor(session); ckrv = CKAPI(tok->slot)->C_DestroyObject(session->handle, object); nssSession_ExitMonitor(session); @@ -259,10 +260,11 @@ nssToken_ImportObject CK_ULONG otsize ) { - nssSession *session; + nssSession *session = NULL; PRBool createdSession = PR_FALSE; CK_OBJECT_HANDLE object; CK_RV ckrv; + if (nssCKObject_IsTokenObjectTemplate(objectTemplate, otsize)) { if (sessionOpt) { if (!nssSession_IsReadWrite(sessionOpt)) { @@ -277,6 +279,9 @@ nssToken_ImportObject createdSession = PR_TRUE; } } + if (session == NULL) { + return PR_FAILURE; + } nssSession_EnterMonitor(session); ckrv = CKAPI(tok->slot)->C_CreateObject(session->handle, objectTemplate, otsize, @@ -311,17 +316,17 @@ nssToken_FindObjectByTemplate ckrv = CKAPI(tok)->C_FindObjectsInit(hSession, cktemplate, ctsize); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } ckrv = CKAPI(tok)->C_FindObjects(hSession, &rvObject, 1, &count); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } ckrv = CKAPI(tok)->C_FindObjectsFinal(hSession); nssSession_ExitMonitor(session); if (ckrv != CKR_OK) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } return rvObject; } diff --git a/security/nss/lib/dev/util.c b/security/nss/lib/dev/devutil.c index 02db7831b..02db7831b 100644 --- a/security/nss/lib/dev/util.c +++ b/security/nss/lib/dev/devutil.c diff --git a/security/nss/lib/dev/manifest.mn b/security/nss/lib/dev/manifest.mn index 570eeae73..279bfe0b2 100644 --- a/security/nss/lib/dev/manifest.mn +++ b/security/nss/lib/dev/manifest.mn @@ -47,17 +47,15 @@ EXPORTS = \ MODULE = security CSRCS = \ - module.c \ - slot.c \ - token.c \ - util.c \ + devmod.c \ + devslot.c \ + devtoken.c \ + devutil.c \ ckhelper.c \ $(NULL) # here is where the 3.4 glue code is added ifndef PURE_STAN_BUILD -CSRCS += nss3hack.c -PRIVATE_EXPORTS += devnss3hack.h DEFINES = -DNSS_3_4_CODE endif diff --git a/security/nss/lib/dev/nssdevt.h b/security/nss/lib/dev/nssdevt.h index 61f9d1a50..a402ddddd 100644 --- a/security/nss/lib/dev/nssdevt.h +++ b/security/nss/lib/dev/nssdevt.h @@ -52,15 +52,6 @@ static const char NSSDEVT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "nsspkit.h" #endif /* NSSPKIT_H */ -#ifdef NSS_3_4_CODE -#include "pkcs11t.h" -#include "secmodt.h" -#else -#ifndef NSSCKT_H -#include "nssckt.h" -#endif /* NSSCKT_H */ -#endif /* NSS_3_4_CODE */ - PR_BEGIN_EXTERN_C /* diff --git a/security/nss/lib/fortcrypt/swfort/pkcs11/Makefile b/security/nss/lib/fortcrypt/swfort/pkcs11/Makefile index 00c911bc6..495e70ae3 100644 --- a/security/nss/lib/fortcrypt/swfort/pkcs11/Makefile +++ b/security/nss/lib/fortcrypt/swfort/pkcs11/Makefile @@ -55,7 +55,7 @@ endif # $(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.lib EXTRA_LIBS = \ $(DIST)/lib/swfci.lib \ - $(DIST)/lib/softoken.lib \ + $(DIST)/lib/softokn.lib \ $(CRYPTO_LIB) \ $(DIST)/lib/secutil.lib \ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4_s.lib \ @@ -89,7 +89,7 @@ endif EXTRA_LIBS += \ $(DIST)/lib/libswfci.$(LIB_SUFFIX) \ - $(DIST)/lib/libsoftoken.$(LIB_SUFFIX) \ + $(DIST)/lib/libsoftokn.$(LIB_SUFFIX) \ $(CRYPTO_LIB) \ $(DIST)/lib/libsecutil.$(LIB_SUFFIX) \ $(PLC_STATIC_LIB) \ diff --git a/security/nss/lib/jar/jarevil.c b/security/nss/lib/jar/jarevil.c index 8ceba9d3c..56dc5dbc3 100644 --- a/security/nss/lib/jar/jarevil.c +++ b/security/nss/lib/jar/jarevil.c @@ -394,7 +394,7 @@ struct EVIL_certkey int error; CERTCertificate *cert; CERTCertDBHandle *certdb; - SECItem *seckey; + CERTIssuerAndSN *seckey; }; @@ -407,7 +407,7 @@ PR_STATIC_CALLBACK(void) jar_moz_certkey_fn (void *data) PORT_SetError (certkey_data->error); - cert = CERT_FindCertByKey (certkey_data->certdb, certkey_data->seckey); + cert=CERT_FindCertByIssuerAndSN(certkey_data->certdb, certkey_data->seckey); certkey_data->cert = cert; certkey_data->error = PORT_GetError(); @@ -416,7 +416,8 @@ PR_STATIC_CALLBACK(void) jar_moz_certkey_fn (void *data) /* Wrapper for the ET_MOZ call */ -CERTCertificate *jar_moz_certkey (CERTCertDBHandle *certdb, SECItem *seckey) +CERTCertificate *jar_moz_certkey (CERTCertDBHandle *certdb, + CERTIssuerAndSN *seckey) { CERTCertificate *cert; ALLOC_OR_DEFINE(struct EVIL_certkey, certkey_data, NULL); diff --git a/security/nss/lib/jar/jarevil.h b/security/nss/lib/jar/jarevil.h index a7c835e6c..95b4f6883 100644 --- a/security/nss/lib/jar/jarevil.h +++ b/security/nss/lib/jar/jarevil.h @@ -68,7 +68,7 @@ extern SECStatus jar_moz_perm (CERTCertificate *cert, char *nickname, CERTCertTrust *trust); extern CERTCertificate *jar_moz_certkey - (CERTCertDBHandle *certdb, SECItem *seckey); + (CERTCertDBHandle *certdb, CERTIssuerAndSN *seckey); extern CERTCertificate *jar_moz_issuer (CERTCertificate *cert); diff --git a/security/nss/lib/jar/jarint.h b/security/nss/lib/jar/jarint.h index a107f8c2b..7baa4f3f1 100644 --- a/security/nss/lib/jar/jarint.h +++ b/security/nss/lib/jar/jarint.h @@ -36,7 +36,7 @@ #include "nspr.h" /* definitely required */ -#include "certdb.h" +/*#include "certdb.h" */ #include "key.h" #include "base64.h" diff --git a/security/nss/lib/jar/jarver.c b/security/nss/lib/jar/jarver.c index a7f5bdb77..af1a28328 100644 --- a/security/nss/lib/jar/jarver.c +++ b/security/nss/lib/jar/jarver.c @@ -45,7 +45,7 @@ #ifdef USE_MOZ_THREAD #include "jarevil.h" #endif -#include "cdbhdl.h" +/*#include "cdbhdl.h" */ #include "secder.h" /* to use huge pointers in win16 */ @@ -74,11 +74,12 @@ extern SECStatus SEC_AddTempNickname (CERTCertDBHandle *handle, char *nickname, SECItem *certKey); /* from certdb.h */ typedef SECStatus (* PermCertCallback)(CERTCertificate *cert, SECItem *k, void *pdata); -#endif /* from certdb.h */ SECStatus SEC_TraversePermCerts (CERTCertDBHandle *handle, PermCertCallback certfunc, void *udata); +#endif + #define SZ 512 @@ -856,6 +857,7 @@ static int jar_add_cert (JAR *jar, JAR_Signer *signer, int type, CERTCertificate *cert) { JAR_Cert *fing; + unsigned char *keyData; if (cert == NULL) return JAR_ERR_ORDER; @@ -873,14 +875,18 @@ static int jar_add_cert /* get the certkey */ - fing->length = cert->certKey.len; + fing->length = cert->derIssuer.len + 2 + cert->serialNumber.len; - fing->key = (char *) PORT_ZAlloc (fing->length); + keyData = (unsigned char *) PORT_ZAlloc (fing->length); + fing->key = keyData; if (fing->key == NULL) goto loser; - - PORT_Memcpy (fing->key, cert->certKey.data, fing->length); + keyData[0] = ((cert->derIssuer.len) >> 8) & 0xff; + keyData[1] = ((cert->derIssuer.len) & 0xff); + PORT_Memcpy (&keyData[2], cert->derIssuer.data, cert->derIssuer.len); + PORT_Memcpy (&keyData[2+cert->derIssuer.len], cert->serialNumber.data, + cert->serialNumber.len); ADDITEM (signer->certs, type, /* pathname */ NULL, fing, sizeof (JAR_Cert)); @@ -1518,7 +1524,7 @@ extern int PR_CALLBACK JAR_stash_cert void *JAR_fetch_cert (long length, void *key) { - SECItem seckey; + CERTIssuerAndSN issuerSN; CERTCertificate *cert = NULL; CERTCertDBHandle *certdb; @@ -1527,13 +1533,16 @@ void *JAR_fetch_cert (long length, void *key) if (certdb) { - seckey.len = length; - seckey.data = (unsigned char*)key; + unsigned char *keyData = (unsigned char *)key; + issuerSN.derIssuer.len = (keyData[0] << 8) + keyData[0]; + issuerSN.derIssuer.data = &keyData[2]; + issuerSN.serialNumber.len = length - (2 + issuerSN.derIssuer.len); + issuerSN.serialNumber.data = &keyData[2+issuerSN.derIssuer.len]; #ifdef USE_MOZ_THREAD - cert = jar_moz_certkey (certdb, &seckey); + cert = jar_moz_certkey (certdb, &issuerSN); #else - cert = CERT_FindCertByKey (certdb, &seckey); + cert = CERT_FindCertByIssuerAndSN (certdb, &issuerSN); #endif JAR_close_database (certdb); @@ -1816,21 +1825,8 @@ CERTCertDBHandle *JAR_open_database (void) int keepcerts = 0; CERTCertDBHandle *certdb; - /* local_certdb will only be used if calling from a command line tool */ - static CERTCertDBHandle local_certdb; - certdb = CERT_GetDefaultCertDB(); - if (certdb == NULL) - { - if (CERT_OpenCertDBFilename (&local_certdb, NULL, (PRBool)!keepcerts) != - SECSuccess) - { - return NULL; - } - certdb = &local_certdb; - } - return certdb; } @@ -1844,6 +1840,7 @@ CERTCertDBHandle *JAR_open_database (void) int JAR_close_database (CERTCertDBHandle *certdb) { +#ifdef notdef CERTCertDBHandle *defaultdb; /* This really just retrieves the handle, nothing more */ @@ -1854,6 +1851,7 @@ int JAR_close_database (CERTCertDBHandle *certdb) if (defaultdb == NULL && certdb != NULL) CERT_ClosePermCertDB (certdb); +#endif return 0; } diff --git a/security/nss/lib/manifest.mn b/security/nss/lib/manifest.mn index 1e3274293..2738cf722 100644 --- a/security/nss/lib/manifest.mn +++ b/security/nss/lib/manifest.mn @@ -33,29 +33,25 @@ CORE_DEPTH = ../.. DEPTH = ../.. -DIRS = \ - base \ - asn1 \ - dev \ - pki \ - pki1 \ - crmf \ - jar \ - certhigh \ - pk11wrap \ - cryptohi \ - softoken \ - certdb \ - crypto \ - util \ - freebl \ - nss \ - pkcs12 \ - fortcrypt \ - pkcs7 \ - smime \ - ssl \ +# +# organized by DLL +# +# softoken and prereqs. +# stan (not a separate dll yet) +# nss base (traditional) +# ssl +# smime +# ckfw (builtins module) +# crmf jar (not dll's) +# fortcrypt +DIRS = util freebl softoken \ + base asn1 dev pki pki1 \ + certdb certhigh pk11wrap cryptohi crypto nss \ + ssl \ + pkcs12 pkcs7 smime \ + crmf jar \ ckfw \ + fortcrypt \ $(NULL) # NSS 4.0 build - pure stan libraries diff --git a/security/nss/lib/nss/config.mk b/security/nss/lib/nss/config.mk index c33cdd3ab..dec348831 100644 --- a/security/nss/lib/nss/config.mk +++ b/security/nss/lib/nss/config.mk @@ -48,25 +48,15 @@ ifeq ($(OS_ARCH), WINNT) SHARED_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).dll IMPORT_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).lib -DLLFLAGS += -DEF:nss.def -RES = $(OBJDIR)/nss.res -RESNAME = nss.rc +RES = $(OBJDIR)/$(LIBRARY_NAME).res +RESNAME = $(LIBRARY_NAME).rc # $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS) -CRYPTOLIB=$(DIST)/lib/freebl.lib -CRYPTODIR=../freebl -ifdef MOZILLA_SECURITY_BUILD - CRYPTOLIB=$(DIST)/lib/crypto.lib - CRYPTODIR=../crypto -endif - SHARED_LIBRARY_LIBS = \ $(DIST)/lib/certhi.lib \ $(DIST)/lib/cryptohi.lib \ $(DIST)/lib/pk11wrap.lib \ $(DIST)/lib/certdb.lib \ - $(DIST)/lib/softoken.lib \ - $(CRYPTOLIB) \ $(DIST)/lib/secutil.lib \ $(DIST)/lib/nsspki.lib \ $(DIST)/lib/nssdev.lib \ @@ -78,67 +68,37 @@ SHARED_LIBRARY_DIRS = \ ../cryptohi \ ../pk11wrap \ ../certdb \ - ../softoken \ - $(CRYPTODIR) \ ../util \ ../pki \ ../dev \ ../base \ $(NULL) -EXTRA_LIBS += \ - $(DIST)/lib/dbm.lib \ - $(NULL) - -ifdef MOZILLA_BSAFE_BUILD - EXTRA_LIBS+=$(DIST)/lib/bsafe$(BSAFEVER).lib -endif - EXTRA_SHARED_LIBS += \ + $(DIST)/lib/softokn3.lib \ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4.lib \ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4.lib \ $(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.lib \ $(NULL) - -# $(PROGRAM) has NO explicit dependencies on $(OS_LIBS) -#OS_LIBS += \ -# wsock32.lib \ -# winmm.lib \ -# $(NULL) else # $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS) -CRYPTOLIB=$(DIST)/lib/libfreebl.$(LIB_SUFFIX) -CRYPTODIR=../freebl -ifdef MOZILLA_SECURITY_BUILD - CRYPTOLIB=$(DIST)/lib/libcrypto.$(LIB_SUFFIX) - CRYPTODIR=../crypto -endif SHARED_LIBRARY_LIBS = \ $(DIST)/lib/libcerthi.$(LIB_SUFFIX) \ $(DIST)/lib/libpk11wrap.$(LIB_SUFFIX) \ $(DIST)/lib/libcryptohi.$(LIB_SUFFIX) \ - $(DIST)/lib/libsoftoken.$(LIB_SUFFIX) \ $(DIST)/lib/libcertdb.$(LIB_SUFFIX) \ - $(CRYPTOLIB) \ $(DIST)/lib/libsecutil.$(LIB_SUFFIX) \ $(DIST)/lib/libnsspki.$(LIB_SUFFIX) \ $(DIST)/lib/libnssdev.$(LIB_SUFFIX) \ $(DIST)/lib/libnssb.$(LIB_SUFFIX) \ $(NULL) -EXTRA_LIBS += \ - $(DIST)/lib/libdbm.$(LIB_SUFFIX) \ - $(NULL) -ifdef MOZILLA_BSAFE_BUILD - EXTRA_LIBS+=$(DIST)/lib/libbsafe.$(LIB_SUFFIX) -endif + SHARED_LIBRARY_DIRS = \ ../certhigh \ ../pk11wrap \ ../cryptohi \ - ../softoken \ ../certdb \ - $(CRYPTODIR) \ ../util \ ../pki \ ../dev \ @@ -149,49 +109,10 @@ SHARED_LIBRARY_DIRS = \ # $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX. EXTRA_SHARED_LIBS += \ -L$(DIST)/lib/ \ + -lsoftokn3 \ -lplc4 \ -lplds4 \ -lnspr4 \ $(NULL) endif -ifeq ($(OS_ARCH),SunOS) -MAPFILE = $(OBJDIR)/nssmap.sun -ALL_TRASH += $(MAPFILE) -MKSHLIB += -M $(MAPFILE) -ifndef USE_64 -ifeq ($(CPU_ARCH),sparc) -# The -R '$ORIGIN' linker option instructs libnss3.so to search for its -# dependencies (libfreebl_*.so) in the same directory where it resides. -MKSHLIB += -R '$$ORIGIN' -endif -endif -endif - -ifeq ($(OS_ARCH),AIX) -MAPFILE = $(OBJDIR)/nssmap.aix -ALL_TRASH += $(MAPFILE) -EXPORT_RULES = -bexport:$(MAPFILE) -endif - -ifeq ($(OS_ARCH),HP-UX) -MAPFILE = $(OBJDIR)/nssmap.hp -ALL_TRASH += $(MAPFILE) -MKSHLIB += -c $(MAPFILE) -endif - -ifeq ($(OS_ARCH), OSF1) -MAPFILE = $(OBJDIR)/nssmap.osf -ALL_TRASH += $(MAPFILE) -MKSHLIB += -hidden -input $(MAPFILE) -endif - -ifeq ($(OS_ARCH),Linux) -MAPFILE = $(OBJDIR)/nssmap.linux -ALL_TRASH += $(MAPFILE) -MKSHLIB += -Wl,--version-script,$(MAPFILE) -endif - - - - diff --git a/security/nss/lib/nss/manifest.mn b/security/nss/lib/nss/manifest.mn index 5d822c170..1fbdc045d 100644 --- a/security/nss/lib/nss/manifest.mn +++ b/security/nss/lib/nss/manifest.mn @@ -49,5 +49,7 @@ CSRCS = \ REQUIRES = security dbm +MAPFILE = $(OBJDIR)/nss.def + LIBRARY_NAME = nss LIBRARY_VERSION = 3 diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index fc1424372..75650ff24 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -564,6 +564,7 @@ SECMOD_LoadModule; SECMOD_GetModuleSpecList; SECMOD_FreeModuleSpecList; SECMOD_UpdateModule; +PK11_RawPBEKeyGen; ;+ local: ;+ *; ;+}; diff --git a/security/nss/lib/nss/nssinit.c b/security/nss/lib/nss/nssinit.c index e63c569f4..fac40d786 100644 --- a/security/nss/lib/nss/nssinit.c +++ b/security/nss/lib/nss/nssinit.c @@ -50,7 +50,7 @@ #include "secrng.h" #include "pk11func.h" -#include "pkinss3hack.h" +#include "pki3hack.h" #define NSS_MAX_FLAG_SIZE sizeof("readOnly")+sizeof("noCertDB")+ \ sizeof("noModDB")+sizeof("forceOpen")+sizeof("passwordRequired") @@ -241,6 +241,8 @@ nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix, } STAN_LoadDefaultNSS3TrustDomain(); + CERT_SetDefaultCertDB((CERTCertDBHandle *) + STAN_GetDefaultTrustDomain()); return rv; } diff --git a/security/nss/lib/nss/nsssym.c b/security/nss/lib/nss/nsssym.c deleted file mode 100644 index e0c53c993..000000000 --- a/security/nss/lib/nss/nsssym.c +++ /dev/null @@ -1,429 +0,0 @@ - -#define INC_SSL 1 -#define INC_SMIME 1 - - -#ifdef INC_SSL -extern int nss_InitLock; - -extern void ATOB_AsciiToData(); -extern void BTOA_DataToAscii(); -extern void CERT_CertChainFromCert(); -extern void CERT_CheckCertValidTimes(); -extern void CERT_DestroyCertificate(); -extern void CERT_DestroyCertificateList(); -extern void CERT_DupCertList(); -extern void CERT_DupCertificate(); -extern void CERT_ExtractPublicKey(); -extern void CERT_FindCertByName(); -extern void CERT_FreeNicknames(); -extern void CERT_GetCertNicknames(); -extern void CERT_GetDefaultCertDB(); -extern void CERT_GetSSLCACerts(); -extern void CERT_NameToAscii(); -extern void CERT_NewTempCertificate(); -extern void CERT_VerifyCertName(); -extern void CERT_VerifyCertNow(); -extern void DER_Lengths(); -extern void DSAU_DecodeDerSig(); -extern void DSAU_EncodeDerSig(); -extern void NSSRWLock_Destroy(); -extern void NSSRWLock_HaveWriteLock(); -extern void NSSRWLock_LockRead(); -extern void NSSRWLock_LockWrite(); -extern void NSSRWLock_New(); -extern void NSSRWLock_UnlockRead(); -extern void NSSRWLock_UnlockWrite(); -extern void NSS_PutEnv(); -extern void PK11_CipherOp(); -extern void PK11_CloneContext(); -extern void PK11_CreateContextByRawKey(); -extern void PK11_CreateContextBySymKey(); -extern void PK11_CreateDigestContext(); -extern void PK11_Derive(); -extern void PK11_DeriveWithFlags(); -extern void PK11_DestroyContext(); -extern void PK11_DigestBegin(); -extern void PK11_DigestFinal(); -extern void PK11_DigestKey(); -extern void PK11_DigestOp(); -extern void PK11_FindBestKEAMatch(); -extern void PK11_FindCertFromNickname(); -extern void PK11_FindFixedKey(); -extern void PK11_FindKeyByAnyCert(); -extern void PK11_FreeSlot(); -extern void PK11_FreeSymKey(); -extern void PK11_GenerateFortezzaIV(); -extern void PK11_GenerateRandom(); -extern void PK11_GetBestKeyLength(); -extern void PK11_GetBestSlot(); -extern void PK11_GetBestSlotMultiple(); -extern void PK11_GetBestWrapMechanism(); -extern void PK11_GetCurrentWrapIndex(); -extern void PK11_GetInternalSlot(); -extern void PK11_GetKeyData(); -extern void PK11_GetMechanism(); -extern void PK11_GetModuleID(); -extern void PK11_GetPrivateModulusLen(); -extern void PK11_GetSlotFromKey(); -extern void PK11_GetSlotFromPrivateKey(); -extern void PK11_GetSlotID(); -extern void PK11_GetSlotSeries(); -extern void PK11_GetTokenInfo(); -extern void PK11_GetWindow(); -extern void PK11_GetWrapKey(); -extern void PK11_IVFromParam(); -extern void PK11_IsPresent(); -extern void PK11_KeyGen(); -extern void PK11_MakeKEAPubKey(); -extern void PK11_ParamFromIV(); -extern void PK11_PubDecryptRaw(); -extern void PK11_PubDerive(); -extern void PK11_PubEncryptRaw(); -extern void PK11_PubUnwrapSymKey(); -extern void PK11_PubWrapSymKey(); -extern void PK11_ReferenceSymKey(); -extern void PK11_RestoreContext(); -extern void PK11_SaveContext(); -extern void PK11_SetFortezzaHack(); -extern void PK11_SetWrapKey(); -extern void PK11_Sign(); -extern void PK11_SignatureLen(); -extern void PK11_SymKeyFromHandle(); -extern void PK11_TokenExists(); -extern void PK11_UnwrapSymKey(); -extern void PK11_UnwrapSymKeyWithFlags(); -extern void PK11_Verify(); -extern void PK11_VerifyKeyOK(); -extern void PK11_WrapSymKey(); -extern void PORT_Alloc(); -extern void PORT_ArenaAlloc(); -extern void PORT_ArenaZAlloc(); -extern void PORT_Free(); -extern void PORT_FreeArena(); -extern void PORT_GetError(); -extern void PORT_NewArena(); -extern void PORT_Realloc(); -extern void PORT_SetError(); -extern void PORT_ZAlloc(); -extern void PORT_ZFree(); -extern void RSA_FormatBlock(); -extern void SECITEM_CompareItem(); -extern void SECITEM_CopyItem(); -extern void SECITEM_FreeItem(); -extern void SECITEM_ZfreeItem(); -extern void SECKEY_CopyPrivateKey(); -extern void SECKEY_CreateRSAPrivateKey(); -extern void SECKEY_DestroyPrivateKey(); -extern void SECKEY_DestroyPublicKey(); -extern void SECKEY_PublicKeyStrength(); -extern void SECKEY_UpdateCertPQG(); -extern void SECMOD_LookupSlot(); -extern void SECOID_GetAlgorithmTag(); -extern void SGN_Begin(); -extern void SGN_DestroyContext(); -extern void SGN_End(); -extern void SGN_NewContext(); -extern void SGN_Update(); -extern void VFY_Begin(); -extern void VFY_CreateContext(); -extern void VFY_DestroyContext(); -extern void VFY_End(); -extern void VFY_Update(); - -void -nss_referenceNSSFunctionsForSSL() { - int tmp2 = nss_InitLock; - - ATOB_AsciiToData(); - BTOA_DataToAscii(); - CERT_CertChainFromCert(); - CERT_CheckCertValidTimes(); - CERT_DestroyCertificate(); - CERT_DestroyCertificateList(); - CERT_DupCertList(); - CERT_DupCertificate(); - CERT_ExtractPublicKey(); - CERT_FindCertByName(); - CERT_FreeNicknames(); - CERT_GetCertNicknames(); - CERT_GetDefaultCertDB(); - CERT_GetSSLCACerts(); - CERT_NameToAscii(); - CERT_NewTempCertificate(); - CERT_VerifyCertName(); - CERT_VerifyCertNow(); - DER_Lengths(); - DSAU_DecodeDerSig(); - DSAU_EncodeDerSig(); - NSSRWLock_Destroy(); - NSSRWLock_HaveWriteLock(); - NSSRWLock_LockRead(); - NSSRWLock_LockWrite(); - NSSRWLock_New(); - NSSRWLock_UnlockRead(); - NSSRWLock_UnlockWrite(); - NSS_PutEnv(); - PK11_CipherOp(); - PK11_CloneContext(); - PK11_CreateContextByRawKey(); - PK11_CreateContextBySymKey(); - PK11_CreateDigestContext(); - PK11_Derive(); - PK11_DeriveWithFlags(); - PK11_DestroyContext(); - PK11_DigestBegin(); - PK11_DigestFinal(); - PK11_DigestKey(); - PK11_DigestOp(); - PK11_FindBestKEAMatch(); - PK11_FindCertFromNickname(); - PK11_FindFixedKey(); - PK11_FindKeyByAnyCert(); - PK11_FreeSlot(); - PK11_FreeSymKey(); - PK11_GenerateFortezzaIV(); - PK11_GenerateRandom(); - PK11_GetBestKeyLength(); - PK11_GetBestSlot(); - PK11_GetBestSlotMultiple(); - PK11_GetBestWrapMechanism(); - PK11_GetCurrentWrapIndex(); - PK11_GetInternalSlot(); - PK11_GetKeyData(); - PK11_GetMechanism(); - PK11_GetModuleID(); - PK11_GetPrivateModulusLen(); - PK11_GetSlotFromKey(); - PK11_GetSlotFromPrivateKey(); - PK11_GetSlotID(); - PK11_GetSlotSeries(); - PK11_GetTokenInfo(); - PK11_GetWindow(); - PK11_GetWrapKey(); - PK11_IVFromParam(); - PK11_IsPresent(); - PK11_KeyGen(); - PK11_MakeKEAPubKey(); - PK11_ParamFromIV(); - PK11_PubDecryptRaw(); - PK11_PubDerive(); - PK11_PubEncryptRaw(); - PK11_PubUnwrapSymKey(); - PK11_PubWrapSymKey(); - PK11_ReferenceSymKey(); - PK11_RestoreContext(); - PK11_SaveContext(); - PK11_SetFortezzaHack(); - PK11_SetWrapKey(); - PK11_Sign(); - PK11_SignatureLen(); - PK11_SymKeyFromHandle(); - PK11_TokenExists(); - PK11_UnwrapSymKey(); - PK11_UnwrapSymKeyWithFlags(); - PK11_Verify(); - PK11_VerifyKeyOK(); - PK11_WrapSymKey(); - PORT_Alloc(); - PORT_ArenaAlloc(); - PORT_ArenaZAlloc(); - PORT_Free(); - PORT_FreeArena(); - PORT_GetError(); - PORT_NewArena(); - PORT_Realloc(); - PORT_SetError(); - PORT_ZAlloc(); - PORT_ZFree(); - RSA_FormatBlock(); - SECITEM_CompareItem(); - SECITEM_CopyItem(); - SECITEM_FreeItem(); - SECITEM_ZfreeItem(); - SECKEY_CopyPrivateKey(); - SECKEY_CreateRSAPrivateKey(); - SECKEY_DestroyPrivateKey(); - SECKEY_DestroyPublicKey(); - SECKEY_PublicKeyStrength(); - SECKEY_UpdateCertPQG(); - SECMOD_LookupSlot(); - SECOID_GetAlgorithmTag(); - SGN_Begin(); - SGN_DestroyContext(); - SGN_End(); - SGN_NewContext(); - SGN_Update(); - VFY_Begin(); - VFY_CreateContext(); - VFY_DestroyContext(); - VFY_End(); - VFY_Update(); -} - -#endif - -#ifdef INC_SMIME -extern int CERT_IssuerAndSNTemplate; -extern int CERT_SetOfSignedCrlTemplate; -extern int SEC_PointerToAnyTemplate; -extern int SEC_PointerToOctetStringTemplate; -extern int SEC_SetOfAnyTemplate; - -extern void CERT_CertListFromCert(); -extern void CERT_DestroyCertArray(); -extern void CERT_FindSMimeProfile(); -extern void CERT_GetCertIssuerAndSN(); -extern void CERT_ImportCerts(); -extern void CERT_OpenCertDBFilename(); -extern void CERT_SaveSMimeProfile(); -extern void CERT_VerifyCert(); -extern void DER_TimeToUTCTime(); -extern void PK11_CreatePBEAlgorithmID(); -extern void PK11_FindCertAndKeyByRecipientList(); -extern void PK11_FindCertAndKeyByRecipientListNew(); -extern void PK11_FortezzaHasKEA(); -extern void PK11_FortezzaMapSig(); -extern void PK11_GenerateNewParam(); -extern void PK11_GetKeyStrength(); -extern void PK11_IsHW(); -extern void PK11_PBEKeyGen(); -extern void PK11_ParamToAlgid(); -extern void PK11_SetPasswordFunc(); -extern void SEC_ASN1DecodeInteger(); -extern void SEC_ASN1DecoderClearFilterProc(); -extern void SEC_ASN1DecoderClearNotifyProc(); -extern void SEC_ASN1DecoderFinish(); -extern void SEC_ASN1DecoderSetFilterProc(); -extern void SEC_ASN1DecoderSetNotifyProc(); -extern void SEC_ASN1DecoderStart(); -extern void SEC_ASN1DecoderUpdate(); -extern void SEC_ASN1EncoderClearNotifyProc(); -extern void SEC_ASN1EncoderClearStreaming(); -extern void SEC_ASN1EncoderClearTakeFromBuf(); -extern void SEC_ASN1EncoderFinish(); -extern void SEC_ASN1EncoderSetNotifyProc(); -extern void SEC_ASN1EncoderSetStreaming(); -extern void SEC_ASN1EncoderSetTakeFromBuf(); -extern void SEC_ASN1EncoderStart(); -extern void SEC_ASN1EncoderUpdate(); -extern void SEC_PKCS5IsAlgorithmPBEAlg(); -extern void SEC_SignData(); -extern void SGN_Digest(); -extern void VFY_VerifyDigest(); - -nss_referenceNSSFunctionsForSMIME() { - int tmp1=CERT_IssuerAndSNTemplate; - int tmp2=CERT_SetOfSignedCrlTemplate; - int tmp3=SEC_PointerToAnyTemplate; - int tmp4=SEC_PointerToOctetStringTemplate; - int tmp5=SEC_SetOfAnyTemplate; - - CERT_CertListFromCert(); - CERT_FindSMimeProfile(); - CERT_GetCertIssuerAndSN(); - CERT_ImportCerts(); - CERT_SaveSMimeProfile(); - CERT_VerifyCert(); - DER_TimeToUTCTime(); - PK11_CreatePBEAlgorithmID(); - PK11_FindCertAndKeyByRecipientListNew(); - PK11_FortezzaHasKEA(); - PK11_FortezzaMapSig(); - PK11_GenerateNewParam(); - PK11_GetKeyStrength(); - PK11_IsHW(); - PK11_ParamToAlgid(); - PK11_SetPasswordFunc(); - SEC_ASN1DecodeInteger(); - SEC_ASN1DecoderClearFilterProc(); - SEC_ASN1DecoderFinish(); - SEC_ASN1DecoderSetFilterProc(); - SEC_ASN1DecoderSetNotifyProc(); - SEC_ASN1DecoderStart(); - SEC_ASN1DecoderUpdate(); - SEC_ASN1EncoderClearNotifyProc(); - SEC_ASN1EncoderClearStreaming(); - SEC_ASN1EncoderClearTakeFromBuf(); - SEC_ASN1EncoderFinish(); - SEC_ASN1EncoderSetNotifyProc(); - SEC_ASN1EncoderSetStreaming(); - SEC_ASN1EncoderSetTakeFromBuf(); - SEC_ASN1EncoderStart(); - SEC_ASN1EncoderUpdate(); - SEC_PKCS5IsAlgorithmPBEAlg(); - SEC_SignData(); - SGN_Digest(); - VFY_VerifyDigest(); - CERT_OpenCertDBFilename(); - CERT_DestroyCertArray(); - PK11_PBEKeyGen(); - PK11_FindCertAndKeyByRecipientList(); - SEC_ASN1DecoderClearNotifyProc(); -} -#endif - -extern int CERT_CertificateRequestTemplate; - -extern void CERT_DecodeCertificatePoliciesExtension(); -extern void CERT_DecodeUserNotice(); -extern void CERT_DestroyCertificatePoliciesExtension(); -extern void CERT_GenTime2FormattedAscii(); -extern void CERT_Hexify(); -extern void DER_GeneralizedTimeToTime(); -extern void HASH_GetHashObject(); -extern void MD2_Flatten(); -extern void MD2_Resurrect(); -extern void MD5_Flatten(); -extern void MD5_Resurrect(); -extern void NSSBase64Decoder_Create(); -extern void NSSBase64Decoder_Destroy(); -extern void NSSBase64Decoder_Update(); -extern void NSSBase64Encoder_Create(); -extern void NSSBase64Encoder_Destroy(); -extern void NSSBase64Encoder_Update(); -extern void PK11_ChangePW(); -extern void PK11_CheckUserPassword(); -extern void PK11_DoPassword(); -extern void PK11_FindKeyByKeyID(); -extern void PK11_InitPin(); -extern void PK11_NeedUserInit(); -extern void PQG_ParamGen(); -extern void PQG_VerifyParams(); -extern void SECITEM_ReallocItem(); -extern void SECKEY_DeriveKeyDBPassword(); -extern void SECKEY_GetKeyDBVersion(); - -nss_CMDExports() { - int tmp1 = CERT_CertificateRequestTemplate; - - CERT_DecodeCertificatePoliciesExtension(); - CERT_DecodeUserNotice(); - CERT_DestroyCertificatePoliciesExtension(); - CERT_GenTime2FormattedAscii(); - CERT_Hexify(); - DER_GeneralizedTimeToTime(); - HASH_GetHashObject(); - MD2_Flatten(); - MD2_Resurrect(); - MD5_Flatten(); - MD5_Resurrect(); - NSSBase64Decoder_Create(); - NSSBase64Decoder_Destroy(); - NSSBase64Decoder_Update(); - NSSBase64Encoder_Create(); - NSSBase64Encoder_Destroy(); - NSSBase64Encoder_Update(); - PK11_ChangePW(); - PK11_CheckUserPassword(); - PK11_DoPassword(); - PK11_FindKeyByKeyID(); - PK11_InitPin(); - PK11_NeedUserInit(); - PQG_ParamGen(); - PQG_VerifyParams(); - SECITEM_ReallocItem(); - SECKEY_DeriveKeyDBPassword(); - SECKEY_GetKeyDBVersion(); -} - diff --git a/security/nss/lib/dev/nss3hack.c b/security/nss/lib/pk11wrap/dev3hack.c index f77085028..5c40608f3 100644 --- a/security/nss/lib/dev/nss3hack.c +++ b/security/nss/lib/pk11wrap/dev3hack.c @@ -35,6 +35,10 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #endif /* DEBUG */ +#ifndef NSS_3_4_CODE +#define NSS_3_4_CODE +#endif /* NSS_3_4_CODE */ + #ifndef PKIT_H #include "pkit.h" #endif /* PKIT_H */ @@ -43,9 +47,7 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "devt.h" #endif /* DEVT_H */ -#ifndef DEVM_H -#include "devm.h" -#endif /* DEVM_H */ +#include "dev3hack.h" #ifndef BASE_H #include "base.h" @@ -160,6 +162,13 @@ nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) return rvToken; } + +NSSTrustDomain * +nssToken_GetTrustDomain(NSSToken *token) +{ + return token->trustDomain; +} + typedef enum { nssPK11Event_DefaultSessionRO = 0, nssPK11Event_DefaultSessionRW = 1 diff --git a/security/nss/lib/dev/devnss3hack.h b/security/nss/lib/pk11wrap/dev3hack.h index a9d28e2e2..2ae362a15 100644 --- a/security/nss/lib/dev/devnss3hack.h +++ b/security/nss/lib/pk11wrap/dev3hack.h @@ -45,6 +45,14 @@ PR_BEGIN_EXTERN_C NSS_EXTERN NSSToken * nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot); +NSSTrustDomain * +nssToken_GetTrustDomain(NSSToken *token); + +void PK11Slot_SetNSSToken(PK11SlotInfo *sl, NSSToken *nsst); + +NSSToken * PK11Slot_GetNSSToken(PK11SlotInfo *sl); + + PR_END_EXTERN_C #endif /* DEVNSS3HACK_H */ diff --git a/security/nss/lib/pk11wrap/manifest.mn b/security/nss/lib/pk11wrap/manifest.mn index c043af789..1c525506d 100644 --- a/security/nss/lib/pk11wrap/manifest.mn +++ b/security/nss/lib/pk11wrap/manifest.mn @@ -41,13 +41,14 @@ EXPORTS = \ $(NULL) PRIVATE_EXPORTS = \ - secmodi.h \ - secmodti.h \ + pk11init.h \ + dev3hack.h \ $(NULL) MODULE = security CSRCS = \ + dev3hack.c \ pk11cert.c \ pk11err.c \ pk11load.c \ @@ -60,6 +61,7 @@ CSRCS = \ pk11sdr.c \ pk11pqg.c \ pk11pk12.c \ + pk11pbe.c \ $(NULL) REQUIRES = security dbm diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c index ab4289bdb..47bf56b12 100644 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ b/security/nss/lib/pk11wrap/pk11cert.c @@ -52,14 +52,13 @@ #include "secerr.h" #include "sslerr.h" -#define NSSCKT_H /* we included pkcs11t.h, so block ckt.h from including nssckt.h */ -#include "ckt.h" - #ifndef NSS_3_4_CODE #define NSS_3_4_CODE #endif /* NSS_3_4_CODE */ -#include "pkinss3hack.h" -#include "dev.h" +#include "pki3hack.h" +#include "dev3hack.h" + +/*#include "dev.h" */ #include "nsspki.h" #include "pkitm.h" @@ -120,10 +119,6 @@ pk11_buildNickname(PK11SlotInfo *slot,CK_ATTRIBUTE *cert_label, char buildNew[sizeof(DEFAULT_STRING)+MAX_CERT_ID*2]; char *next,*nickname; - if (slot->isInternal) { - return NULL; - } - if ((cert_label) && (cert_label->pValue)) { suffixLen = cert_label->ulValueLen; suffix = (char*)cert_label->pValue; @@ -150,6 +145,7 @@ pk11_buildNickname(PK11SlotInfo *slot,CK_ATTRIBUTE *cert_label, return NULL; } + /* if is internal key slot, add code to skip the prefix!! */ next = nickname = (char *)PORT_Alloc(prefixLen+1+suffixLen+1); if (nickname == NULL) return NULL; @@ -180,7 +176,7 @@ pk11_FindObjectByTemplate(PK11SlotInfo *slot,CK_ATTRIBUTE *theTemplate,int tsize if (crv != CKR_OK) { PK11_ExitSlotMonitor(slot); PORT_SetError( PK11_MapError(crv) ); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } crv=PK11_GETTAB(slot)->C_FindObjects(slot->session,&object,1,&objectCount); @@ -190,11 +186,11 @@ pk11_FindObjectByTemplate(PK11SlotInfo *slot,CK_ATTRIBUTE *theTemplate,int tsize /* shouldn't use SSL_ERROR... here */ PORT_SetError( crv != CKR_OK ? PK11_MapError(crv) : SSL_ERROR_NO_CERTIFICATE); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } /* blow up if the PKCS #11 module returns us and invalid object handle */ - PORT_Assert(object != CK_INVALID_KEY); + PORT_Assert(object != CK_INVALID_HANDLE); return object; } @@ -282,13 +278,13 @@ PK11_MatchItem(PK11SlotInfo *slot, CK_OBJECT_HANDLE searchID, /* now we need to create space for the public key */ arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) return CK_INVALID_KEY; + if (arena == NULL) return CK_INVALID_HANDLE; crv = PK11_GetAttributes(arena,slot,searchID,theTemplate,tsize); if (crv != CKR_OK) { PORT_FreeArena(arena,PR_FALSE); PORT_SetError( PK11_MapError(crv) ); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } /* @@ -316,7 +312,7 @@ PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert, if (!PK11_IsLoggedIn(slot,NULL) && PK11_NeedLogin(slot)) { theClass = CKO_PUBLIC_KEY; } - if (PK11_MatchItem(slot, certID , theClass) != CK_INVALID_KEY) { + if (PK11_MatchItem(slot, certID , theClass) != CK_INVALID_HANDLE) { return PR_TRUE; } @@ -353,7 +349,7 @@ PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert, return PR_FALSE; } pk11_SignedToUnsigned(&theTemplate); - if (pk11_FindObjectByTemplate(slot,&theTemplate,1) != CK_INVALID_KEY) { + if (pk11_FindObjectByTemplate(slot,&theTemplate,1) != CK_INVALID_HANDLE) { SECKEY_DestroyPublicKey(pubKey); return PR_TRUE; } @@ -436,8 +432,12 @@ CERTCertificate /* figure out the nickname.... */ nickname = pk11_buildNickname(slot,label,privateLabel,id); - cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert, nickname, - PR_FALSE, PR_TRUE); + cert = CERT_DecodeDERCertificate(&derCert, PR_TRUE, nickname); + if (cert) { + cert->dbhandle = (CERTCertDBHandle *) + nssToken_GetTrustDomain(slot->nssToken); + } + if (nickptr) { *nickptr = nickname; } else { @@ -481,11 +481,7 @@ pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust CK_OBJECT_HANDLE tobjID; unsigned char sha1_hash[SHA1_LENGTH]; - CK_TRUST serverAuth, codeSigning, emailProtection; -/* - CK_TRUST digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, - keyAgreement, keyCertSign, crlSign, serverAuth, clientAuth, codeSigning, - emailProtection, ipsecEndSystem, ipsecTunnel, ipsecUser, timeStamping; */ + CK_TRUST serverAuth, codeSigning, emailProtection, clientAuth; PK11_HashBuf(SEC_OID_SHA1, sha1_hash, cert->derCert.data, cert->derCert.len); @@ -495,7 +491,7 @@ pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust tobjID = pk11_FindObjectByTemplate(slot, tobjTemplate, sizeof(tobjTemplate)/sizeof(tobjTemplate[0])); - if( CK_INVALID_KEY == tobjID ) { + if( CK_INVALID_HANDLE == tobjID ) { return PR_FALSE; } @@ -511,46 +507,37 @@ pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust /* We could verify CKA_EXPIRES here */ - /* "Usage" trust information */ - /* digitalSignature = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_DIGITAL_SIGNATURE); */ - /* nonRepudiation = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_NON_REPUDIATION); */ - /* keyEncipherment = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_KEY_ENCIPHERMENT); */ - /* dataEncipherment = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_DATA_ENCIPHERMENT); */ - /* keyAgreement = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_KEY_AGREEMENT); */ - /* keyCertSign = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_KEY_CERT_SIGN); */ - /* crlSign = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CRL_SIGN); */ /* "Purpose" trust information */ - serverAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_SERVER_AUTH); - /* clientAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CLIENT_AUTH); */ - codeSigning = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CODE_SIGNING); - emailProtection = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_EMAIL_PROTECTION); - /* ipsecEndSystem = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_IPSEC_END_SYSTEM); */ - /* ipsecTunnel = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_IPSEC_TUNNEL); */ - /* ipsecUser = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_IPSEC_USER); */ - /* timeStamping = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_TIME_STAMPING); */ - - /* Here's where the fun logic happens. We have to map back from the key usage, - * extended key usage, purpose, and possibly other trust values into the old - * trust-flags bits. - */ + serverAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_SERVER_AUTH); + clientAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CLIENT_AUTH); + codeSigning = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CODE_SIGNING); + emailProtection = pk11_GetTrustField(slot, arena, tobjID, + CKA_TRUST_EMAIL_PROTECTION); + /* Here's where the fun logic happens. We have to map back from the + * key usage, extended key usage, purpose, and possibly other trust values + * into the old trust-flags bits. */ /* First implementation: keep it simple for testing. We can study what other * mappings would be appropriate and add them later.. fgmr 20000724 */ - if( serverAuth == CKT_NETSCAPE_TRUSTED ) { + if ( serverAuth == CKT_NETSCAPE_TRUSTED ) { trust->sslFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED; } - if( serverAuth == CKT_NETSCAPE_TRUSTED_DELEGATOR ) { - trust->sslFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA; + if ( serverAuth == CKT_NETSCAPE_TRUSTED_DELEGATOR ) { + trust->sslFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | + CERTDB_NS_TRUSTED_CA; + } + if ( clientAuth == CKT_NETSCAPE_TRUSTED_DELEGATOR ) { + trust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA ; } - if( emailProtection == CKT_NETSCAPE_TRUSTED ) { + if ( emailProtection == CKT_NETSCAPE_TRUSTED ) { trust->emailFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED; } - if( emailProtection == CKT_NETSCAPE_TRUSTED_DELEGATOR ) { + if ( emailProtection == CKT_NETSCAPE_TRUSTED_DELEGATOR ) { trust->emailFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA; } @@ -605,24 +592,17 @@ PK11_MakeCertFromHandle(PK11SlotInfo *slot,CK_OBJECT_HANDLE certID, cert->ownSlot = PR_TRUE; } - if (cert->trust == NULL) { - unsigned int type; - - trust = - (CERTCertTrust*)PORT_ArenaAlloc(cert->arena, sizeof(CERTCertTrust)); - if (trust == NULL) goto loser; + trust = (CERTCertTrust*)PORT_ArenaAlloc(cert->arena, sizeof(CERTCertTrust)); + if (trust == NULL) goto loser; + PORT_Memset(trust,0, sizeof(CERTCertTrust)); + cert->trust = trust; - PORT_Memset(trust,0, sizeof(CERTCertTrust)); - cert->trust = trust; - /* build some cert trust flags */ + - /* First, see if there's a trust object for this cert. */ - /* For the first implementation, we'll just check this slot - * and worry about overriding trust info later. */ - if( pk11_HandleTrustObject(slot, cert, trust) ) { - ; - } else + if(! pk11_HandleTrustObject(slot, cert, trust) ) { + unsigned int type; + /* build some cert trust flags */ if (CERT_IsCACert(cert, &type)) { unsigned int trustflags = CERTDB_VALID_CA; @@ -652,8 +632,6 @@ PK11_MakeCertFromHandle(PK11SlotInfo *slot,CK_OBJECT_HANDLE certID, trust->objectSigningFlags |= trustflags; } } - } else { - trust = cert->trust; } if (PK11_IsUserCert(slot,cert,certID)) { @@ -662,29 +640,6 @@ PK11_MakeCertFromHandle(PK11SlotInfo *slot,CK_OBJECT_HANDLE certID, /* trust->objectSigningFlags |= CERTDB_USER; */ } - - /* if fortezza, write the root cert to the DB */ - if ((isFortezzaRootCA) && (!cert->isperm)) { - char *name = NULL; - if (swapNickname) { - nickname = cert->nickname; - cert->nickname = cert->dbnickname; - } - if (cert->nickname) { - name = PORT_Strdup(cert->nickname); - } - if (name == NULL) name = CERT_MakeCANickname(cert); - CERT_AddTempCertToPerm(cert,name,cert->trust); - if (name) PORT_Free(name); - if (swapNickname) { - if (cert->nickname != NULL) { - cert->dbnickname = cert->nickname; - } - cert->nickname = PORT_ArenaStrdup(cert->arena,nickname); - } - - } - return cert; loser: @@ -706,7 +661,7 @@ PK11_GetCertFromPrivateKey(SECKEYPrivateKey *privKey) SECStatus rv; CERTCertificate *cert; - if (certID == CK_INVALID_KEY) { + if (certID == CK_INVALID_HANDLE) { /* couldn't find it on the card, look in our data base */ SECItem derSubject; @@ -765,7 +720,7 @@ PK11_DeleteTokenCertAndKey(CERTCertificate *cert,void *wincx) PK11_DestroyTokenObject(cert->slot,cert->pkcs11ID); PK11_DeleteTokenPrivateKey(privKey); } - if ((pubKey != CK_INVALID_KEY) && (slot != NULL)) { + if ((pubKey != CK_INVALID_HANDLE) && (slot != NULL)) { PK11_DestroyTokenObject(slot,pubKey); PK11_FreeSlot(slot); } @@ -817,13 +772,14 @@ PK11_NumberObjectsFor(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate, typedef struct pk11DoCertCallbackStr { SECStatus(* callback)(PK11SlotInfo *slot, CERTCertificate*, void *); SECStatus(* noslotcallback)(CERTCertificate*, void *); + SECStatus(* itemcallback)(CERTCertificate*, SECItem *, void *); void *callbackArg; } pk11DoCertCallback; /* * callback to map object handles to certificate structures. */ -SECStatus +static SECStatus pk11_DoCerts(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, void *arg) { CERTCertificate *cert; @@ -842,6 +798,9 @@ pk11_DoCerts(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, void *arg) if (certcb->noslotcallback) { (*certcb->noslotcallback)(cert, certcb->callbackArg); } + if (certcb->itemcallback) { + (*certcb->itemcallback)(cert, NULL, certcb->callbackArg); + } } CERT_DestroyCertificate(cert); @@ -849,6 +808,63 @@ pk11_DoCerts(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, void *arg) return SECSuccess; } +static SECStatus +pk11_CollectCrls(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID, void *arg) +{ + SECItem derCrl; + CERTCrlHeadNode *head = (CERTCrlHeadNode *) arg; + CERTCrlNode *new_node = NULL; + CK_ATTRIBUTE fetchCrl[3] = { + { CKA_VALUE, NULL, 0}, + { CKA_NETSCAPE_KRL, NULL, 0}, + { CKA_NETSCAPE_URL, NULL, 0}, + }; + const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]); + SECStatus rv; + + rv = PK11_GetAttributes(head->arena,slot,crlID,fetchCrl,fetchCrlSize); + if (rv == SECFailure) { + goto loser; + } + rv = SECFailure; + + new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, sizeof(CERTCrlNode)); + if (new_node == NULL) { + goto loser; + } + + new_node->type = *((CK_BBOOL *)fetchCrl[1].pValue) ? + SEC_KRL_TYPE : SEC_CRL_TYPE; + derCrl.data = (unsigned char *)fetchCrl[0].pValue; + derCrl.len = fetchCrl[0].ulValueLen; + new_node->crl=CERT_DecodeDERCrl(head->arena,&derCrl,new_node->type); + + if (fetchCrl[2].pValue) { + int nnlen = fetchCrl[2].ulValueLen; + new_node->crl->url = (char *)PORT_ArenaAlloc(head->arena, nnlen+1); + if ( !new_node->crl->url ) { + goto loser; + } + PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen); + new_node->crl->url[nnlen] = 0; + } else { + new_node->crl->url = NULL; + } + + + new_node->next = NULL; + if (head->last) { + head->last->next = new_node; + head->last = new_node; + } else { + head->first = head->last = new_node; + } + rv = SECSuccess; + +loser: + return(rv); +} + /* * key call back structure. @@ -927,191 +943,24 @@ typedef struct pk11CertCallbackStr { void *callbackArg; } pk11CertCallback; -static SECStatus -pk11_SaveCert(PK11SlotInfo *slot, CERTCertificate *cert, void *arg) -{ - pk11CertCallback *certcb = (pk11CertCallback *)arg; - SECStatus rv = SECSuccess; - - if (slot->cert_count == slot->array_size) return CKR_OK; - - slot->cert_array[slot->cert_count] = CERT_DupCertificate(cert); - if (slot->cert_array[slot->cert_count] == NULL) { - return SECFailure; - } - /* now the slot has a hold of the cert, free the slot's element in the - * cert.. */ - if (cert->ownSlot && (slot == cert->slot)) { - PK11_FreeSlot(cert->slot); - cert->ownSlot = PR_FALSE; - } - slot->cert_count++; - - if (certcb->callback) { - rv = (*certcb->callback)(cert, NULL, certcb->callbackArg); - } - return rv; -} - - -/* free the slots */ -void -PK11_FreeSlotCerts(PK11SlotInfo *slot) -{ - int i; - - if (slot->cert_array) { - for (i=0; i < slot->cert_count; i++) { - /* if we point the cert on our array, the cert doesn't have a - * reference to use (otherwise you would never be able to free - * a slot :) */ - if ((slot->cert_array[i]->slot == slot) && - (!slot->cert_array[i]->ownSlot)) { - slot->cert_array[i]->slot = NULL; - } - CERT_DestroyCertificate(slot->cert_array[i]); - } - PORT_Free(slot->cert_array); - slot->cert_array = NULL; - slot->cert_count = 0; - } - return; -} - -/* - * Update PQG parameters for all the certs on a slot. - */ -static SECStatus -pk11_UpdateSlotPQG(PK11SlotInfo *slot) -{ - int i, tag; - CERTCertificate * cert; - SECOidData *oid; - SECStatus rv1 = SECSuccess; - SECStatus rv2 = SECSuccess; - - if (slot->cert_array) { - for (i=0; i < slot->cert_count; i++) { - - cert = slot->cert_array[i]; - - oid = SECOID_FindOID(&cert->subjectPublicKeyInfo.algorithm.algorithm); - - if (oid != NULL) { - tag = oid->offset; - - /* Check if cert has a DSA or Fortezza public key */ - if ( (tag == SEC_OID_MISSI_KEA_DSS_OLD) || - (tag == SEC_OID_MISSI_DSS_OLD) || - (tag == SEC_OID_MISSI_KEA_DSS) || - (tag == SEC_OID_MISSI_DSS) || - (tag == SEC_OID_ANSIX9_DSA_SIGNATURE) || - (tag == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) || - (tag == SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) ) { - - /* update PQG parameters */ - - rv1 = SECKEY_UpdateCertPQG(cert); - if (rv1 == SECFailure) { - rv2 = rv1; - } - } - } /* end of if oid != NULL */ - } /* end of for loop */ - } - return rv2; -} - - /* * Extract all the certs on a card from a slot. */ static SECStatus -pk11_ExtractCertsFromSlot(PK11SlotInfo *slot, void *arg) -{ - pk11TraverseSlot *slotcb = (pk11TraverseSlot*) arg; - int object_count; - SECStatus rv; - - rv = SECSuccess; - - PK11_FreeSlotCerts(slot); - - object_count = PK11_NumberObjectsFor(slot,slotcb->findTemplate, - slotcb->templateCount); - - /*Actually this isn't a failure... there just were no certs to be found*/ - if (object_count == 0) { - return SECSuccess; - } - - slot->cert_array = (CERTCertificate **) - PORT_Alloc(sizeof(CERTCertificate *)*object_count); - if (slot->cert_array == NULL) { - return SECFailure; - } - slot->cert_count = 0; - slot->array_size = object_count; - PK11_TraverseSlot(slot,arg); - - /* Update the PQG parameters for the extracted certs. */ - rv = pk11_UpdateSlotPQG(slot); - - return rv; -} - -/* - * read all the certs from a slot - */ -SECStatus -PK11_ReadSlotCerts(PK11SlotInfo *slot) -{ - - /* build slot list */ - pk11CertCallback caller; - pk11DoCertCallback saver; - pk11TraverseSlot creater; - CK_ATTRIBUTE theTemplate; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - - PK11_SETATTRS(&theTemplate, CKA_CLASS, &certClass, sizeof(certClass)); - - caller.callback = NULL; - caller.callbackArg = NULL; - saver.callback = pk11_SaveCert; - saver.noslotcallback = NULL; - saver.callbackArg = (void *) & caller; - creater.callback = pk11_DoCerts; - creater.callbackArg = (void *) & saver; - creater.findTemplate = &theTemplate; - creater.templateCount = 1; - - return pk11_ExtractCertsFromSlot(slot, &creater); -} - -/* - * Extract all the certs on a card from a slot. - */ -static SECStatus -pk11_TraverseAllSlots(PRBool loadCerts, - SECStatus (*callback)(PK11SlotInfo *,void *),void *arg,void *wincx) { - +pk11_TraverseAllSlots( SECStatus (*callback)(PK11SlotInfo *,void *), + void *arg,void *wincx) { PK11SlotList *list; PK11SlotListElement *le; SECStatus rv; /* get them all! */ - list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,loadCerts,wincx); + list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,wincx); if (list == NULL) return SECFailure; /* look at each slot and authenticate as necessary */ for (le = list->head ; le; le = le->next) { - /* don't nab internal slots */ - if ((!loadCerts) && le->slot->isInternal == PR_TRUE) { - continue; - } - if (loadCerts || !PK11_IsFriendly(le->slot)) { - rv = PK11_Authenticate(le->slot, loadCerts, wincx); + if (!PK11_IsFriendly(le->slot)) { + rv = PK11_Authenticate(le->slot, PR_FALSE, wincx); if (rv != SECSuccess) continue; } (*callback)(le->slot,arg); @@ -1128,26 +977,48 @@ pk11_TraverseAllSlots(PRBool loadCerts, SECStatus PK11_TraverseSlotCerts(SECStatus(* callback)(CERTCertificate*,SECItem *,void *), void *arg, void *wincx) { - pk11CertCallback caller; - pk11DoCertCallback saver; + pk11DoCertCallback caller; pk11TraverseSlot creater; CK_ATTRIBUTE theTemplate; CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; PK11_SETATTRS(&theTemplate, CKA_CLASS, &certClass, sizeof(certClass)); - caller.callback = callback; + caller.callback = NULL; + caller.noslotcallback = NULL; + caller.itemcallback = callback; caller.callbackArg = arg; - saver.callback = pk11_SaveCert; - saver.noslotcallback = NULL; - saver.callbackArg = (void *) & caller; creater.callback = pk11_DoCerts; - creater.callbackArg = (void *) & saver; + creater.callbackArg = (void *) & caller; creater.findTemplate = &theTemplate; creater.templateCount = 1; - return pk11_TraverseAllSlots(PR_FALSE, pk11_ExtractCertsFromSlot, - &creater, wincx); + return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, wincx); +} + +/* + * Extract all the certs on a card from a slot. + */ +SECStatus +PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx) { + pk11TraverseSlot creater; + CK_ATTRIBUTE theTemplate[2]; + CK_ATTRIBUTE *attrs; + CK_OBJECT_CLASS certClass = CKO_NETSCAPE_CRL; + + attrs = theTemplate; + PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); attrs++; + if (type != -1) { + CK_BBOOL isKrl = (CK_BBOOL) (type == SEC_KRL_TYPE); + PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, &isKrl, sizeof(isKrl)); attrs++; + } + + creater.callback = pk11_CollectCrls; + creater.callbackArg = (void *) nodes; + creater.findTemplate = theTemplate; + creater.templateCount = (attrs - theTemplate); + + return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, wincx); } /*********************************************************************** @@ -1194,7 +1065,8 @@ PK11_TraversePrivateKeysInSlot( PK11SlotInfo *slot, CK_OBJECT_HANDLE * PK11_FindObjectsFromNickname(char *nickname,PK11SlotInfo **slotptr, - CK_OBJECT_CLASS objclass, int *returnCount, void *wincx) { + CK_OBJECT_CLASS objclass, int *returnCount, void *wincx) +{ char *tokenName; char *delimit; PK11SlotInfo *slot; @@ -1229,7 +1101,7 @@ PK11_FindObjectsFromNickname(char *nickname,PK11SlotInfo **slotptr, *slotptr = slot = PK11_GetInternalKeySlot(); } if (slot == NULL) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } if (!PK11_IsFriendly(slot)) { @@ -1237,7 +1109,7 @@ PK11_FindObjectsFromNickname(char *nickname,PK11SlotInfo **slotptr, if (rv != SECSuccess) { PK11_FreeSlot(slot); *slotptr = NULL; - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } } @@ -1273,7 +1145,7 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) { CKO_CERTIFICATE, &count, wincx); CERTCertificate *cert; - if (certID == CK_INVALID_KEY) return NULL; + if (certID == CK_INVALID_HANDLE) return NULL; cert = PK11_MakeCertFromHandle(slot,certID[0],NULL); PK11_FreeSlot(slot); PORT_Free(certID); @@ -1579,11 +1451,13 @@ PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, } rwsession = PK11_GetRWSession(slot); - crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession,key,keyAttrs, + if (key != CK_INVALID_HANDLE) { + crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession,key,keyAttrs, keyCount); - if (crv != CKR_OK) { - PORT_SetError( PK11_MapError(crv) ); - goto done; + if (crv != CKR_OK) { + PORT_SetError( PK11_MapError(crv) ); + goto done; + } } crv = PK11_GETTAB(slot)-> @@ -1594,8 +1468,11 @@ PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, PORT_SetError( PK11_MapError(crv) ); } - if (cert->nssCertificate) { - cert->nssCertificate->token = slot->nssToken; + if (cert->slot == NULL) { + cert->slot = PK11_ReferenceSlot(slot); + if (cert->nssCertificate) { + cert->nssCertificate->token = slot->nssToken; + } } done: @@ -1619,7 +1496,7 @@ pk11_getcerthandle(PK11SlotInfo *slot, CERTCertificate *cert, if (cert->slot == slot) { certh = cert->pkcs11ID; - if (certh == CK_INVALID_KEY) { + if (certh == CK_INVALID_HANDLE) { certh = pk11_FindObjectByTemplate(slot,theTemplate,tsize); cert->pkcs11ID = certh; } @@ -1660,11 +1537,11 @@ PK11_FindPrivateKeyFromCert(PK11SlotInfo *slot, CERTCertificate *cert, } certh = pk11_getcerthandle(slot,cert,theTemplate,tsize); - if (certh == CK_INVALID_KEY) { + if (certh == CK_INVALID_HANDLE) { return NULL; } keyh = PK11_MatchItem(slot,certh,CKO_PRIVATE_KEY); - if (keyh == CK_INVALID_KEY) { return NULL; } + if (keyh == CK_INVALID_HANDLE) { return NULL; } return PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyh, wincx); } @@ -1718,7 +1595,7 @@ PK11_KeyForCertExists(CERTCertificate *cert, CK_OBJECT_HANDLE *keyPtr, if (rv != SECSuccess) continue; key = pk11_FindPrivateKeyFromCertID(le->slot,keyID); - if (key != CK_INVALID_KEY) { + if (key != CK_INVALID_HANDLE) { slot = PK11_ReferenceSlot(le->slot); if (keyPtr) *keyPtr = key; break; @@ -1740,8 +1617,7 @@ PK11_KeyForDERCertExists(SECItem *derCert, CK_OBJECT_HANDLE *keyPtr, CERTCertificate *cert; PK11SlotInfo *slot = NULL; - cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert, NULL, - PR_FALSE, PR_TRUE); + cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if (cert == NULL) return NULL; slot = PK11_KeyForCertExists(cert, keyPtr, wincx); @@ -1773,8 +1649,7 @@ PK11_ImportDERCertForKey(SECItem *derCert, char *nickname,void *wincx) { CERTCertificate *cert; PK11SlotInfo *slot = NULL; - cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert, NULL, - PR_FALSE, PR_TRUE); + cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if (cert == NULL) return NULL; slot = PK11_ImportCertForKey(cert, nickname, wincx); @@ -1787,7 +1662,7 @@ pk11_FindCertObjectByTemplate(PK11SlotInfo **slotPtr, CK_ATTRIBUTE *searchTemplate, int count, void *wincx) { PK11SlotList *list; PK11SlotListElement *le; - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; + CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE; PK11SlotInfo *slot = NULL; SECStatus rv; @@ -1797,7 +1672,7 @@ pk11_FindCertObjectByTemplate(PK11SlotInfo **slotPtr, list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); if (list == NULL) { if (list) PK11_FreeSlotList(list); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } @@ -1809,7 +1684,7 @@ pk11_FindCertObjectByTemplate(PK11SlotInfo **slotPtr, } certHandle = pk11_FindObjectByTemplate(le->slot,searchTemplate,count); - if (certHandle != CK_INVALID_KEY) { + if (certHandle != CK_INVALID_HANDLE) { slot = PK11_ReferenceSlot(le->slot); break; } @@ -1818,7 +1693,7 @@ pk11_FindCertObjectByTemplate(PK11SlotInfo **slotPtr, PK11_FreeSlotList(list); if (slot == NULL) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } *slotPtr = slot; return certHandle; @@ -1867,7 +1742,7 @@ pk11_FindCertObjectByRecipientNew(PK11SlotInfo *slot, NSSCMSRecipient **recipien ri->id.issuerAndSN->serialNumber.data,ri->id.issuerAndSN->serialNumber.len); certHandle = pk11_FindObjectByTemplate(slot,searchTemplate,count); - if (certHandle != CK_INVALID_KEY) { + if (certHandle != CK_INVALID_HANDLE) { CERTCertificate *cert = pk11_fastCert(slot,certHandle,NULL,NULL); if (PK11_IsUserCert(slot,cert,certHandle)) { /* we've found a cert handle, now let's see if there is a key @@ -1882,7 +1757,7 @@ pk11_FindCertObjectByRecipientNew(PK11SlotInfo *slot, NSSCMSRecipient **recipien } } *rlIndex = -1; - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } /* @@ -1896,14 +1771,14 @@ pk11_AllFindCertObjectByRecipientNew(NSSCMSRecipient **recipientlist, void *winc { PK11SlotList *list; PK11SlotListElement *le; - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; + CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE; SECStatus rv; /* get them all! */ list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); if (list == NULL) { if (list) PK11_FreeSlotList(list); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } /* Look for the slot that holds the Key */ @@ -1914,13 +1789,13 @@ pk11_AllFindCertObjectByRecipientNew(NSSCMSRecipient **recipientlist, void *winc } certHandle = pk11_FindCertObjectByRecipientNew(le->slot, recipientlist, rlIndex); - if (certHandle != CK_INVALID_KEY) + if (certHandle != CK_INVALID_HANDLE) break; } PK11_FreeSlotList(list); - return (le == NULL) ? CK_INVALID_KEY : certHandle; + return (le == NULL) ? CK_INVALID_HANDLE : certHandle; } /* @@ -1960,7 +1835,7 @@ pk11_FindCertObjectByRecipient(PK11SlotInfo *slot, ri->issuerAndSN->serialNumber.data,ri->issuerAndSN->serialNumber.len); certHandle = pk11_FindObjectByTemplate(slot,searchTemplate,count); - if (certHandle != CK_INVALID_KEY) { + if (certHandle != CK_INVALID_HANDLE) { CERTCertificate *cert = pk11_fastCert(slot,certHandle,NULL,NULL); if (PK11_IsUserCert(slot,cert,certHandle)) { /* we've found a cert handle, now let's see if there is a key @@ -1974,7 +1849,7 @@ pk11_FindCertObjectByRecipient(PK11SlotInfo *slot, } } *rip = NULL; - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } /* @@ -1986,7 +1861,7 @@ pk11_AllFindCertObjectByRecipient(PK11SlotInfo **slotPtr, void *wincx) { PK11SlotList *list; PK11SlotListElement *le; - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; + CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE; PK11SlotInfo *slot = NULL; SECStatus rv; @@ -1996,7 +1871,7 @@ pk11_AllFindCertObjectByRecipient(PK11SlotInfo **slotPtr, list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); if (list == NULL) { if (list) PK11_FreeSlotList(list); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } *rip = NULL; @@ -2010,7 +1885,7 @@ pk11_AllFindCertObjectByRecipient(PK11SlotInfo **slotPtr, certHandle = pk11_FindCertObjectByRecipient(le->slot, recipientArray,rip); - if (certHandle != CK_INVALID_KEY) { + if (certHandle != CK_INVALID_HANDLE) { slot = PK11_ReferenceSlot(le->slot); break; } @@ -2019,7 +1894,7 @@ pk11_AllFindCertObjectByRecipient(PK11SlotInfo **slotPtr, PK11_FreeSlotList(list); if (slot == NULL) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } *slotPtr = slot; return certHandle; @@ -2037,14 +1912,14 @@ PK11_FindCertAndKeyByRecipientList(PK11SlotInfo **slotPtr, SEC_PKCS7RecipientInfo **array, SEC_PKCS7RecipientInfo **rip, SECKEYPrivateKey**privKey, void *wincx) { - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; - CK_OBJECT_HANDLE keyHandle = CK_INVALID_KEY; + CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE keyHandle = CK_INVALID_HANDLE; CERTCertificate *cert = NULL; SECStatus rv; *privKey = NULL; certHandle = pk11_AllFindCertObjectByRecipient(slotPtr,array,rip,wincx); - if (certHandle == CK_INVALID_KEY) { + if (certHandle == CK_INVALID_HANDLE) { return NULL; } @@ -2056,7 +1931,7 @@ PK11_FindCertAndKeyByRecipientList(PK11SlotInfo **slotPtr, } keyHandle = PK11_MatchItem(*slotPtr,certHandle,CKO_PRIVATE_KEY); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { PK11_FreeSlot(*slotPtr); *slotPtr = NULL; return NULL; @@ -2087,13 +1962,13 @@ PK11_FindCertAndKeyByRecipientList(PK11SlotInfo **slotPtr, int PK11_FindCertAndKeyByRecipientListNew(NSSCMSRecipient **recipientlist, void *wincx) { - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; - CK_OBJECT_HANDLE keyHandle = CK_INVALID_KEY; + CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE keyHandle = CK_INVALID_HANDLE; NSSCMSRecipient *rl; int rlIndex; certHandle = pk11_AllFindCertObjectByRecipientNew(recipientlist, wincx, &rlIndex); - if (certHandle == CK_INVALID_KEY) { + if (certHandle == CK_INVALID_HANDLE) { return -1; } @@ -2110,7 +1985,7 @@ PK11_FindCertAndKeyByRecipientListNew(NSSCMSRecipient **recipientlist, void *win /* try to get a private key handle for the cert we found */ keyHandle = PK11_MatchItem(rl->slot, certHandle, CKO_PRIVATE_KEY); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { PK11_FreeSlot(rl->slot); rl->slot = NULL; return -1; @@ -2142,13 +2017,16 @@ PK11_FindCertByIssuerAndSN(PK11SlotInfo **slotPtr, CERTIssuerAndSN *issuerSN, #ifndef NSS_SOFTOKEN_MODULE CK_OBJECT_HANDLE certHandle; CERTCertificate *cert = NULL; + CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; CK_ATTRIBUTE searchTemplate[] = { + { CKA_CLASS, NULL, 0 }, { CKA_ISSUER, NULL, 0 }, { CKA_SERIAL_NUMBER, NULL, 0} }; int count = sizeof(searchTemplate)/sizeof(CK_ATTRIBUTE); CK_ATTRIBUTE *attrs = searchTemplate; + PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); attrs++; PK11_SETATTRS(attrs, CKA_ISSUER, issuerSN->derIssuer.data, issuerSN->derIssuer.len); attrs++; PK11_SETATTRS(attrs, CKA_SERIAL_NUMBER, issuerSN->serialNumber.data, @@ -2156,7 +2034,7 @@ PK11_FindCertByIssuerAndSN(PK11SlotInfo **slotPtr, CERTIssuerAndSN *issuerSN, certHandle = pk11_FindCertObjectByTemplate (slotPtr,searchTemplate,count,wincx); - if (certHandle == CK_INVALID_KEY) { + if (certHandle == CK_INVALID_HANDLE) { return NULL; } cert = PK11_MakeCertFromHandle(*slotPtr,certHandle,NULL); @@ -2197,14 +2075,14 @@ PK11_FindObjectForCert(CERTCertificate *cert, void *wincx, PK11SlotInfo **pSlot) if (cert->slot) { certHandle = pk11_getcerthandle(cert->slot,cert,&searchTemplate,1); - if (certHandle != CK_INVALID_KEY) { + if (certHandle != CK_INVALID_HANDLE) { *pSlot = PK11_ReferenceSlot(cert->slot); return certHandle; } } certHandle = pk11_FindCertObjectByTemplate(pSlot,&searchTemplate,1,wincx); - if (certHandle != CK_INVALID_KEY) { + if (certHandle != CK_INVALID_HANDLE) { if (cert->slot == NULL) { cert->slot = PK11_ReferenceSlot(*pSlot); cert->pkcs11ID = certHandle; @@ -2225,7 +2103,7 @@ PK11_FindKeyByAnyCert(CERTCertificate *cert, void *wincx) SECStatus rv; certHandle = PK11_FindObjectForCert(cert, wincx, &slot); - if (certHandle == CK_INVALID_KEY) { + if (certHandle == CK_INVALID_HANDLE) { return NULL; } rv = PK11_Authenticate(slot, PR_TRUE, wincx); @@ -2234,7 +2112,7 @@ PK11_FindKeyByAnyCert(CERTCertificate *cert, void *wincx) return NULL; } keyHandle = PK11_MatchItem(slot,certHandle,CKO_PRIVATE_KEY); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { PK11_FreeSlot(slot); return NULL; } @@ -2250,13 +2128,13 @@ pk11_FindPubKeyByAnyCert(CERTCertificate *cert, PK11SlotInfo **slot, void *wincx CK_OBJECT_HANDLE keyHandle; certHandle = PK11_FindObjectForCert(cert, wincx, slot); - if (certHandle == CK_INVALID_KEY) { - return CK_INVALID_KEY; + if (certHandle == CK_INVALID_HANDLE) { + return CK_INVALID_HANDLE; } keyHandle = PK11_MatchItem(*slot,certHandle,CKO_PUBLIC_KEY); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { PK11_FreeSlot(*slot); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } return keyHandle; } @@ -2268,7 +2146,7 @@ PK11_FindKeyByKeyID(PK11SlotInfo *slot, SECItem *keyID, void *wincx) SECKEYPrivateKey *privKey; keyHandle = pk11_FindPrivateKeyFromCertID(slot, keyID); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { return NULL; } privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx); @@ -2292,8 +2170,18 @@ PK11_NumberCertsForCertSubject(CERTCertificate *cert) PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; PK11_SETATTRS(attr,CKA_SUBJECT,cert->derSubject.data,cert->derSubject.len); - if ((cert->slot == NULL) || (cert->slot->isInternal)) { - return 0; + if (cert->slot == NULL) { + PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, + PR_FALSE,PR_TRUE,NULL); + PK11SlotListElement *le; + int count = 0; + + /* loop through all the fortezza tokens */ + for (le = list->head; le; le = le->next) { + count += PK11_NumberObjectsFor(le->slot,theTemplate,templateSize); + } + PK11_FreeSlotList(list); + return count; } return PK11_NumberObjectsFor(cert->slot,theTemplate,templateSize); @@ -2309,6 +2197,19 @@ PK11_TraverseCertsForSubject(CERTCertificate *cert, if(!cert) { return SECFailure; } + if (cert->slot == NULL) { + PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, + PR_FALSE,PR_TRUE,NULL); + PK11SlotListElement *le; + + /* loop through all the fortezza tokens */ + for (le = list->head; le; le = le->next) { + PK11_TraverseCertsForSubjectInSlot(cert,le->slot,callback,arg); + } + PK11_FreeSlotList(list); + return SECSuccess; + + } return PK11_TraverseCertsForSubjectInSlot(cert, cert->slot, callback, arg); } @@ -2331,11 +2232,12 @@ PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot, PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; PK11_SETATTRS(attr,CKA_SUBJECT,cert->derSubject.data,cert->derSubject.len); - if ((slot == NULL) || (slot->isInternal)) { + if (slot == NULL) { return SECSuccess; } caller.noslotcallback = callback; caller.callback = NULL; + caller.itemcallback = NULL; caller.callbackArg = arg; callarg.callback = pk11_DoCerts; callarg.callbackArg = (void *) & caller; @@ -2395,12 +2297,13 @@ PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot, PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; PK11_SETATTRS(attr,CKA_LABEL,nickname->data,nickname->len); - if ((slot == NULL) || (slot->isInternal)) { + if (slot == NULL) { return SECSuccess; } caller.noslotcallback = callback; caller.callback = NULL; + caller.itemcallback = NULL; caller.callbackArg = arg; callarg.callback = pk11_DoCerts; callarg.callbackArg = (void *) & caller; @@ -2460,6 +2363,7 @@ PK11_TraverseCertsInSlot(PK11SlotInfo *slot, caller.noslotcallback = callback; caller.callback = NULL; + caller.itemcallback = NULL; caller.callbackArg = arg; callarg.callback = pk11_DoCerts; callarg.callbackArg = (void *) & caller; @@ -2513,7 +2417,7 @@ PK11_FindCertFromDERCert(PK11SlotInfo *slot, CERTCertificate *cert, } certh = pk11_getcerthandle(slot,cert,theTemplate,tsize); - if (certh == CK_INVALID_KEY) { + if (certh == CK_INVALID_HANDLE) { return NULL; } return PK11_MakeCertFromHandle(slot, certh, NULL); @@ -2569,7 +2473,7 @@ PK11_FindCertFromDERSubjectAndNickname(PK11SlotInfo *slot, } certh = pk11_getcerthandle(slot,cert,theTemplate,tsize); - if (certh == CK_INVALID_KEY) { + if (certh == CK_INVALID_HANDLE) { return NULL; } @@ -2589,15 +2493,15 @@ pk11_findKeyObjectByDERCert(PK11SlotInfo *slot, CERTCertificate *cert, SECStatus rv; if((slot == NULL) || (cert == NULL)) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } keyID = pk11_mkcertKeyID(cert); if(keyID == NULL) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } - key = CK_INVALID_KEY; + key = CK_INVALID_HANDLE; rv = PK11_Authenticate(slot, PR_TRUE, wincx); if (rv != SECSuccess) goto loser; @@ -2620,7 +2524,7 @@ PK11_FindKeyByDERCert(PK11SlotInfo *slot, CERTCertificate *cert, } keyHandle = pk11_findKeyObjectByDERCert(slot, cert, wincx); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { return NULL; } @@ -2639,7 +2543,7 @@ PK11_ImportCertForKeyToSlot(PK11SlotInfo *slot, CERTCertificate *cert, } keyHandle = pk11_findKeyObjectByDERCert(slot, cert, wincx); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { return SECFailure; } @@ -2794,7 +2698,7 @@ PK11_FindCertInSlot(PK11SlotInfo *slot, CERTCertificate *cert, void *wincx) */ rv = PK11_Authenticate(slot, PR_TRUE, wincx); if (rv != SECSuccess) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } return pk11_getcerthandle(slot,cert,theTemplate,tsize); @@ -2813,7 +2717,7 @@ PK11_GetKeyIDFromCert(CERTCertificate *cert, void *wincx) CK_RV crv; handle = PK11_FindObjectForCert(cert,wincx,&slot); - if (handle == CK_INVALID_KEY) { + if (handle == CK_INVALID_HANDLE) { goto loser; } @@ -2963,9 +2867,6 @@ PK11_ListCerts(PK11CertListType type, void *pwarg) listCerts.type = type; listCerts.certList = certList; - SEC_TraversePermCerts(CERT_GetDefaultCertDB(),pk11ListCertCallback, - &listCerts); - PK11_TraverseSlotCerts(pk11ListCertCallback,&listCerts,pwarg); if (CERT_LIST_HEAD(certList) == NULL) { @@ -3044,13 +2945,13 @@ PK11_GetLowLevelKeyIDForCert(PK11SlotInfo *slot, certHandle = pk11_getcerthandle(slot,cert,theTemplate,tsize); } else { certHandle = PK11_FindObjectForCert(cert, wincx, &slotRef); - if (certHandle == CK_INVALID_KEY) { + if (certHandle == CK_INVALID_HANDLE) { return pk11_mkcertKeyID(cert); } slot = slotRef; } - if (certHandle == CK_INVALID_KEY) { + if (certHandle == CK_INVALID_HANDLE) { return NULL; } @@ -3121,3 +3022,306 @@ PK11_ListPrivateKeysInSlot(PK11SlotInfo *slot) return keys; } +/* + * return the certificate associated with a derCert + */ +SECItem * +PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle, + SECItem *name, int type) +{ + CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL; + CK_ATTRIBUTE theTemplate[] = { + { CKA_SUBJECT, NULL, 0 }, + { CKA_CLASS, NULL, 0 }, + { CKA_NETSCAPE_KRL, NULL, 0 }, + }; + CK_ATTRIBUTE crlData = { CKA_VALUE, NULL, 0 }; + /* if you change the array, change the variable below as well */ + int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); + CK_BBOOL ck_true = CK_TRUE; + CK_BBOOL ck_false = CK_FALSE; + CK_OBJECT_HANDLE crlh = CK_INVALID_HANDLE; + CK_ATTRIBUTE *attrs = theTemplate; + CK_RV crv; + SECStatus rv; + SECItem *derCrl = NULL; + + PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); attrs++; + PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass)); attrs++; + PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, (type == SEC_CRL_TYPE) ? + &ck_false : &ck_true, sizeof (CK_BBOOL)); attrs++; + + if (*slot) { + crlh = pk11_FindObjectByTemplate(*slot,theTemplate,tsize); + } else { + PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, + PR_FALSE,PR_TRUE,NULL); + PK11SlotListElement *le; + + /* loop through all the fortezza tokens */ + for (le = list->head; le; le = le->next) { + crlh = pk11_FindObjectByTemplate(le->slot,theTemplate,tsize); + if (crlh != CK_INVALID_HANDLE) { + *slot = PK11_ReferenceSlot(le->slot); + break; + } + } + PK11_FreeSlotList(list); + } + + if (crlh == CK_INVALID_HANDLE) { + PORT_SetError(SEC_ERROR_NO_KRL); + return NULL; + } + crv = PK11_GetAttributes(NULL,*slot,crlh,&crlData,1); + if (crv != CKR_OK) { + PORT_SetError(PK11_MapError (crv)); + goto loser; + } + + derCrl = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + if (derCrl == NULL) { + goto loser; + } + + derCrl->data = crlData.pValue; + derCrl->len = crlData.ulValueLen; + + if (crlHandle) { + *crlHandle = crlh; + } + +loser: + if (!derCrl) { + if (crlData.pValue) PORT_Free(crlData.pValue); + } + return derCrl; +} + +CK_OBJECT_HANDLE +PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, + char *url, int type) +{ + CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL; + CK_ATTRIBUTE theTemplate[] = { + { CKA_SUBJECT, NULL, 0 }, + { CKA_CLASS, NULL, 0 }, + { CKA_NETSCAPE_KRL, NULL, 0 }, + { CKA_NETSCAPE_URL, NULL, 0 }, + { CKA_VALUE, NULL, 0 } + }; + /* if you change the array, change the variable below as well */ + int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); + CK_BBOOL ck_true = CK_TRUE; + CK_BBOOL ck_false = CK_FALSE; + CK_OBJECT_HANDLE crlh = CK_INVALID_HANDLE; + CK_ATTRIBUTE *attrs = theTemplate; + CK_SESSION_HANDLE rwsession; + CK_RV crv; + + PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); attrs++; + PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass)); attrs++; + PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, (type == SEC_CRL_TYPE) ? + &ck_false : &ck_true, sizeof (CK_BBOOL)); attrs++; + PK11_SETATTRS(attrs, CKA_NETSCAPE_URL, url, PORT_Strlen(url)+1); attrs++; + PK11_SETATTRS(attrs, CKA_VALUE,crl->data,crl->len); attrs++; + + rwsession = PK11_GetRWSession(slot); + if (rwsession == CK_INVALID_SESSION) { + PORT_SetError(SEC_ERROR_READ_ONLY); + return crlh; + } + + crv = PK11_GETTAB(slot)-> + C_CreateObject(rwsession,attrs,tsize,&crlh); + if (crv != CKR_OK) { + PORT_SetError( PK11_MapError(crv) ); + } + + PK11_RestoreROSession(slot,rwsession); + return crlh; +} + + + +/* + * delete a crl. + */ +SECStatus +SEC_DeletePermCRL(CERTSignedCrl *crl) +{ + PK11SlotInfo *slot = crl->slot; + CK_RV crv; + + if (slot == NULL) { + /* shouldn't happen */ + PORT_SetError( SEC_ERROR_CRL_INVALID); + return SECFailure; + } + + crv = PK11_DestroyTokenObject(slot,crl->pkcs11ID); + if (crv != CKR_OK) { + PORT_SetError( PK11_MapError(crv) ); + goto loser; + } + crl->slot = NULL; + PK11_FreeSlot(slot); +loser: + return SECSuccess; +} + +/* + * return the certificate associated with a derCert + */ +SECItem * +PK11_FindSMimeProfile(PK11SlotInfo **slot, char *emailAddr, + SECItem *name, SECItem **profileTime) +{ + CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME; + CK_ATTRIBUTE theTemplate[] = { + { CKA_SUBJECT, NULL, 0 }, + { CKA_CLASS, NULL, 0 }, + { CKA_NETSCAPE_EMAIL, NULL, 0 }, + }; + CK_ATTRIBUTE smimeData[] = { + { CKA_SUBJECT, NULL, 0 }, + { CKA_VALUE, NULL, 0 }, + }; + /* if you change the array, change the variable below as well */ + int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); + CK_BBOOL ck_true = CK_TRUE; + CK_BBOOL ck_false = CK_FALSE; + CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE; + CK_ATTRIBUTE *attrs = theTemplate; + CK_RV crv; + SECStatus rv; + SECItem *emailProfile = NULL; + + PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); attrs++; + PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++; + PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, emailAddr, strlen(emailAddr)); + attrs++; + + if (*slot) { + smimeh = pk11_FindObjectByTemplate(*slot,theTemplate,tsize); + } else { + PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, + PR_FALSE,PR_TRUE,NULL); + PK11SlotListElement *le; + + /* loop through all the fortezza tokens */ + for (le = list->head; le; le = le->next) { + smimeh = pk11_FindObjectByTemplate(le->slot,theTemplate,tsize); + if (smimeh != CK_INVALID_HANDLE) { + *slot = PK11_ReferenceSlot(le->slot); + break; + } + } + PK11_FreeSlotList(list); + } + + if (smimeh == CK_INVALID_HANDLE) { + PORT_SetError(SEC_ERROR_NO_KRL); + return NULL; + } + + if (profileTime) { + PK11_SETATTRS(smimeData, CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0); + } + + crv = PK11_GetAttributes(NULL,*slot,smimeh,smimeData,2); + if (crv != CKR_OK) { + PORT_SetError(PK11_MapError (crv)); + goto loser; + } + + if (!profileTime) { + SECItem profileSubject; + + profileSubject.data = smimeData[0].pValue; + profileSubject.len = smimeData[0].ulValueLen; + if (!SECITEM_ItemsAreEqual(&profileSubject,name)) { + goto loser; + } + } + + emailProfile = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + if (emailProfile == NULL) { + goto loser; + } + + emailProfile->data = smimeData[1].pValue; + emailProfile->len = smimeData[1].ulValueLen; + + if (profileTime) { + *profileTime = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + if (*profileTime) { + (*profileTime)->data = smimeData[0].pValue; + (*profileTime)->len = smimeData[0].ulValueLen; + } + } + +loser: + if (emailProfile == NULL) { + if (smimeData[1].pValue) { + PORT_Free(smimeData[1].pValue); + } + } + if (profileTime == NULL || *profileTime == NULL) { + if (smimeData[0].pValue) { + PORT_Free(smimeData[0].pValue); + } + } + return emailProfile; +} + + +SECStatus +PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj, + SECItem *emailProfile, SECItem *profileTime) +{ + CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_CRL; + CK_ATTRIBUTE theTemplate[] = { + { CKA_SUBJECT, NULL, 0 }, + { CKA_CLASS, NULL, 0 }, + { CKA_NETSCAPE_EMAIL, NULL, 0 }, + { CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0 }, + { CKA_VALUE, NULL, 0 } + }; + /* if you change the array, change the variable below as well */ + int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); + CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE; + CK_ATTRIBUTE *attrs = theTemplate; + CK_SESSION_HANDLE rwsession; + CK_RV crv; + + PK11_SETATTRS(attrs, CKA_SUBJECT, derSubj->data, derSubj->len); attrs++; + PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++; + PK11_SETATTRS(attrs, CKA_NETSCAPE_SMIME_TIMESTAMP, profileTime->data, + profileTime->len); attrs++; + PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, + emailAddr, PORT_Strlen(emailAddr)+1); attrs++; + PK11_SETATTRS(attrs, CKA_VALUE,emailProfile->data,emailProfile->len); attrs++; + + if (slot == NULL) { + slot = PK11_GetInternalKeySlot(); + /* we need to free the key slot in the end!!! */ + } + + rwsession = PK11_GetRWSession(slot); + if (rwsession == CK_INVALID_SESSION) { + PORT_SetError(SEC_ERROR_READ_ONLY); + return SECFailure; + } + + crv = PK11_GETTAB(slot)-> + C_CreateObject(rwsession,attrs,tsize,&smimeh); + if (crv != CKR_OK) { + PORT_SetError( PK11_MapError(crv) ); + } + + PK11_RestoreROSession(slot,rwsession); + return SECSuccess; +} + + diff --git a/security/nss/lib/pk11wrap/pk11func.h b/security/nss/lib/pk11wrap/pk11func.h index 3679a0add..51252f0fc 100644 --- a/security/nss/lib/pk11wrap/pk11func.h +++ b/security/nss/lib/pk11wrap/pk11func.h @@ -477,6 +477,9 @@ PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt); PK11SymKey * PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES, void *wincx); +PK11SymKey * +PK11_RawPBEKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *params, + SECItem *pwitem, PRBool faulty3DES, void *wincx); SECItem * PK11_GetPBEIV(SECAlgorithmID *algid, SECItem *pwitem); @@ -489,6 +492,21 @@ PK11_GetLowLevelKeyIDForCert(PK11SlotInfo *slot, SECItem * PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey *key); +SECItem * +PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *handle, + SECItem *derName, int type); + +CK_OBJECT_HANDLE +PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, + SECItem *name, char *url, int type); + +SECItem * +PK11_FindSMimeProfile(PK11SlotInfo **slotp, char *emailAddr, SECItem *derSubj, + SECItem **profileTime); +SECStatus +PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj, + SECItem *emailProfile, SECItem *profileTime); + SEC_END_PROTOS #endif diff --git a/security/nss/lib/ckfw/nsscku.h b/security/nss/lib/pk11wrap/pk11init.h index 46f4d1f59..b5fa0b4ec 100644 --- a/security/nss/lib/ckfw/nsscku.h +++ b/security/nss/lib/pk11wrap/pk11init.h @@ -1,4 +1,4 @@ -/* +/* * 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 @@ -30,42 +30,34 @@ * may use your version of this file under either the MPL or the * GPL. */ - /* - * This file is in part derived from a file "pkcs11t.h" made available - * by RSA Security at ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/pkcs11t.h - * - * Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document - * is granted provided that it is identified as "RSA Security Inc. Public-Key - * Cryptography Standards (PKCS)" in all material mentioning or referencing - * this document. + * Internal header file included in pk11wrap dir, or in softoken */ - -#ifndef NSSCKU_H -#define NSSCKU_H - -#ifdef DEBUG -static const char NSSCKU_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; -#endif /* DEBUG */ - -#endif /* NSSCKU_H */ - -/* - * These platform-dependent packing rules are required by all PKCS#11 - * modules, to be binary compatible. These rules have been placed in - * separate header files (nssckp.h to enable the packing, nsscku.h to - * disable) for consistancy. These files can be included many times, - * so the bodies should *NOT* be in the multiple-inclusion-preventing - * #ifndef/#endif area above. - */ - -/* - * WIN32 is defined (when appropriate) in NSPR's prcpucfg.h. - */ - -#ifdef WIN32 -#pragma warning(disable:4103) -#pragma pack(pop, cryptoki) -#endif /* WIN32 */ - -/* End of nsscku.h */ +#ifndef _PK11_INIT_H_ +#define _PK11_INIT_H_ 1 + +/* hold slot default flags until we initialize a slot. This structure is only + * useful between the time we define a module (either by hand or from the + * database) and the time the module is loaded. Not reference counted */ +struct PK11PreSlotInfoStr { + CK_SLOT_ID slotID; /* slot these flags are for */ + unsigned long defaultFlags; /* bit mask of default implementation this slot + * provides */ + int askpw; /* slot specific password bits */ + long timeout; /* slot specific timeout value */ + char hasRootCerts; /* is this the root cert PKCS #11 module? */ + char hasRootTrust; /* is this the root cert PKCS #11 module? */ +}; + +#define SECMOD_SLOT_FLAGS "slotFlags=[RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES]" + +#define SECMOD_MAKE_NSS_FLAGS(fips,slot) \ +"Flags=internal,critical"fips" slotparams=("#slot"={"SECMOD_SLOT_FLAGS"})" + +#define SECMOD_INT_NAME "NSS Internal PKCS #11 Module" +#define SECMOD_INT_FLAGS SECMOD_MAKE_NSS_FLAGS("",1) +#define SECMOD_FIPS_NAME "NSS Internal FIPS PKCS #11 Module" +#define SECMOD_FIPS_FLAGS SECMOD_MAKE_NSS_FLAGS(",fips",3) + + +#endif /* _PK11_INIT_H_ 1 */ diff --git a/security/nss/lib/pk11wrap/pk11kea.c b/security/nss/lib/pk11wrap/pk11kea.c index c50b9d8b6..b5b810d0b 100644 --- a/security/nss/lib/pk11wrap/pk11kea.c +++ b/security/nss/lib/pk11wrap/pk11kea.c @@ -85,8 +85,8 @@ pk11_KeyExchange(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, /* RSA */ if (PK11_DoesMechanism(symKey->slot, CKM_RSA_PKCS) && PK11_DoesMechanism(slot,CKM_RSA_PKCS)) { - CK_OBJECT_HANDLE pubKeyHandle = CK_INVALID_KEY; - CK_OBJECT_HANDLE privKeyHandle = CK_INVALID_KEY; + CK_OBJECT_HANDLE pubKeyHandle = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE privKeyHandle = CK_INVALID_HANDLE; SECKEYPublicKey *pubKey = NULL; SECKEYPrivateKey *privKey = NULL; SECItem wrapData; @@ -95,12 +95,12 @@ pk11_KeyExchange(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, /* find RSA Public Key on target */ pubKeyHandle = pk11_FindRSAPubKey(slot); - if (pubKeyHandle != CK_INVALID_KEY) { + if (pubKeyHandle != CK_INVALID_HANDLE) { privKeyHandle = PK11_MatchItem(slot,pubKeyHandle,CKO_PRIVATE_KEY); } /* if no key exists, generate a key pair */ - if (privKeyHandle == CK_INVALID_KEY) { + if (privKeyHandle == CK_INVALID_HANDLE) { unsigned int symKeyLength = PK11_GetKeyLength(symKey); PK11RSAGenParams rsaParams; @@ -125,7 +125,7 @@ pk11_KeyExchange(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, if (pubKey && pubKey->pkcs11Slot) { PK11_FreeSlot(pubKey->pkcs11Slot); pubKey->pkcs11Slot = NULL; - pubKey->pkcs11ID = CK_INVALID_KEY; + pubKey->pkcs11ID = CK_INVALID_HANDLE; } } } diff --git a/security/nss/lib/pk11wrap/pk11pbe.c b/security/nss/lib/pk11wrap/pk11pbe.c new file mode 100644 index 000000000..45ee01a84 --- /dev/null +++ b/security/nss/lib/pk11wrap/pk11pbe.c @@ -0,0 +1,689 @@ +/* + * 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. + */ + +#include "plarena.h" + +#include "seccomon.h" +#include "secitem.h" +#include "secport.h" +#include "hasht.h" +#include "pkcs11t.h" +/*#include "blapi.h" */ +#include "sechash.h" +#include "secasn1.h" +#include "secder.h" +#include "secoid.h" +#include "alghmac.h" +#include "secerr.h" +#include "secmod.h" +#include "pk11func.h" + +/* stuff for the new secpkcs5.h */ +/* used for V2 PKCS 12 Draft Spec */ +typedef enum { + pbeBitGenIDNull = 0, + pbeBitGenCipherKey = 0x01, + pbeBitGenCipherIV = 0x02, + pbeBitGenIntegrityKey = 0x03 +} PBEBitGenID; + +typedef struct PBEBitGenContextStr PBEBitGenContext; + +/* end new secpkcs5.h */ + +typedef struct SEC_PKCS5PBEParameterStr SEC_PKCS5PBEParameter; +struct SEC_PKCS5PBEParameterStr { + PRArenaPool *poolp; + SECItem salt; /* octet string */ + SECItem iteration; /* integer */ +}; + + +/* template for PKCS 5 PBE Parameter. This template has been expanded + * based upon the additions in PKCS 12. This should eventually be moved + * if RSA updates PKCS 5. + */ +const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] = +{ + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, + { SEC_ASN1_OCTET_STRING, + offsetof(SEC_PKCS5PBEParameter, salt) }, + { SEC_ASN1_INTEGER, + offsetof(SEC_PKCS5PBEParameter, iteration) }, + { 0 } +}; + +const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] = +{ + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, + { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) }, + { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) }, + { 0 } +}; + +/* maps crypto algorithm from PBE algorithm. + */ +SECOidTag +SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid) +{ + + SECOidTag algorithm; + + if(algid == NULL) + return SEC_OID_UNKNOWN; + + algorithm = SECOID_GetAlgorithmTag(algid); + switch(algorithm) + { + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: + return SEC_OID_DES_EDE3_CBC; + case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: + case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: + case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: + return SEC_OID_DES_CBC; + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: + return SEC_OID_RC2_CBC; + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: + return SEC_OID_RC4; + default: + break; + } + + return SEC_OID_UNKNOWN; +} + +/* check to see if an oid is a pbe algorithm + */ +PRBool +SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid) +{ + return (PRBool)(SEC_PKCS5GetCryptoAlgorithm(algid) != SEC_OID_UNKNOWN); +} + +/* maps PBE algorithm from crypto algorithm, assumes SHA1 hashing. + */ +SECOidTag +SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen) +{ + switch(algTag) + { + case SEC_OID_DES_EDE3_CBC: + switch(keyLen) { + case 168: + case 192: + return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC; + case 128: + case 92: + return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC; + default: + break; + } + break; + case SEC_OID_DES_CBC: + return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC; + case SEC_OID_RC2_CBC: + switch(keyLen) { + case 40: + return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; + case 128: + return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC; + default: + break; + } + break; + case SEC_OID_RC4: + switch(keyLen) { + case 40: + return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4; + case 128: + return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4; + default: + break; + } + break; + default: + break; + } + + return SEC_OID_UNKNOWN; +} + + +/* get the key length needed for the PBE algorithm + */ + +int +SEC_PKCS5GetKeyLength(SECAlgorithmID *algid) +{ + + SECOidTag algorithm; + + if(algid == NULL) + return SEC_OID_UNKNOWN; + + algorithm = SECOID_GetAlgorithmTag(algid); + + switch(algorithm) + { + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: + return 24; + case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: + case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: + case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: + return 8; + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: + return 5; + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: + return 16; + default: + break; + } + return -1; +} + + +/* the V2 algorithms only encode the salt, there is no iteration + * count so we need a check for V2 algorithm parameters. + */ +static PRBool +sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm) +{ + switch(algorithm) + { + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: + return PR_TRUE; + default: + break; + } + + return PR_FALSE; +} +/* destroy a pbe parameter. it assumes that the parameter was + * generated using the appropriate create function and therefor + * contains an arena pool. + */ +static void +sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param) +{ + if(pbe_param != NULL) + PORT_FreeArena(pbe_param->poolp, PR_TRUE); +} + +/* creates a PBE parameter based on the PBE algorithm. the only required + * parameters are algorithm and interation. the return is a PBE parameter + * which conforms to PKCS 5 parameter unless an extended parameter is needed. + * this is primarily if keyLen and a variable key length algorithm are + * specified. + * salt - if null, a salt will be generated from random bytes. + * iteration - number of iterations to perform hashing. + * keyLen - only used in variable key length algorithms + * iv - if null, the IV will be generated based on PKCS 5 when needed. + * params - optional, currently unsupported additional parameters. + * once a parameter is allocated, it should be destroyed calling + * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter. + */ +static SEC_PKCS5PBEParameter * +sec_pkcs5_create_pbe_parameter(SECOidTag algorithm, + SECItem *salt, + int iteration) +{ + PRArenaPool *poolp = NULL; + SEC_PKCS5PBEParameter *pbe_param = NULL; + SECStatus rv; + void *dummy = NULL; + + if(iteration < 0) { + return NULL; + } + if(!salt || !salt->data) { + return NULL; + } + + poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); + if(poolp == NULL) + return NULL; + + pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp, + sizeof(SEC_PKCS5PBEParameter)); + if(!pbe_param) { + PORT_FreeArena(poolp, PR_TRUE); + return NULL; + } + + pbe_param->poolp = poolp; + + rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt); + + if(rv != SECSuccess) { + PORT_FreeArena(poolp, PR_TRUE); + return NULL; + } + + /* encode the integer */ + dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration, + iteration); + rv = (dummy) ? SECSuccess : SECFailure; + + if(rv != SECSuccess) { + PORT_FreeArena(poolp, PR_FALSE); + return NULL; + } + + return pbe_param; +} + +/* creates a algorithm ID containing the PBE algorithm and appropriate + * parameters. the required parameter is the algorithm. if salt is + * not specified, it is generated randomly. if IV is specified, it overrides + * the PKCS 5 generation of the IV. + * + * the returned SECAlgorithmID should be destroyed using + * SECOID_DestroyAlgorithmID + */ +SECAlgorithmID * +SEC_PKCS5CreateAlgorithmID(SECOidTag algorithm, + SECItem *salt, + int iteration) +{ + PRArenaPool *poolp = NULL; + SECAlgorithmID *algid, *ret_algid; + SECItem der_param; + SECStatus rv = SECFailure; + SEC_PKCS5PBEParameter *pbe_param; + +#ifdef nodef + if(sec_pkcs5_hash_algorithm(algorithm) == SEC_OID_UNKNOWN) + return NULL; +#endif + + if(iteration <= 0) { + return NULL; + } + + der_param.data = NULL; + der_param.len = 0; + + /* generate the parameter */ + pbe_param = sec_pkcs5_create_pbe_parameter(algorithm, salt, iteration); + if(!pbe_param) { + return NULL; + } + + poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); + if(!poolp) { + sec_pkcs5_destroy_pbe_param(pbe_param); + return NULL; + } + + /* generate the algorithm id */ + algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID)); + if(algid != NULL) { + void *dummy; + if(!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { + dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, + SEC_PKCS5PBEParameterTemplate); + } else { + dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, + SEC_V2PKCS12PBEParameterTemplate); + } + + if(dummy) { + rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param); + } + } + + ret_algid = NULL; + if(algid != NULL) { + ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID)); + if(ret_algid != NULL) { + rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid); + if(rv != SECSuccess) { + SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE); + ret_algid = NULL; + } + } + } + + if(poolp != NULL) { + PORT_FreeArena(poolp, PR_TRUE); + algid = NULL; + } + + sec_pkcs5_destroy_pbe_param(pbe_param); + + return ret_algid; +} + +SECStatus +pbe_PK11AlgidToParam(SECAlgorithmID *algid,SECItem *mech) +{ + CK_PBE_PARAMS *pbe_params = NULL; + SEC_PKCS5PBEParameter p5_param; + SECItem *salt = NULL; + SECOidTag algorithm = SECOID_GetAlgorithmTag(algid); + PRArenaPool *arena = NULL; + SECStatus rv = SECFailure; + int iv_len; + + + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); + if (arena == NULL) { + goto loser; + } + iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm)); + if (iv_len < 0) { + goto loser; + } + + if (sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { + rv = SEC_ASN1DecodeItem(arena, &p5_param, + SEC_V2PKCS12PBEParameterTemplate, &algid->parameters); + } else { + rv = SEC_ASN1DecodeItem(arena,&p5_param,SEC_PKCS5PBEParameterTemplate, + &algid->parameters); + } + + if (rv != SECSuccess) { + goto loser; + } + + salt = &p5_param.salt; + + pbe_params = (CK_PBE_PARAMS *)PORT_ZAlloc(sizeof(CK_PBE_PARAMS)+ + salt->len+iv_len); + if (pbe_params == NULL) { + goto loser; + } + + /* get salt */ + pbe_params->pSalt = ((CK_CHAR_PTR) pbe_params)+sizeof(CK_PBE_PARAMS); + if (iv_len) { + pbe_params->pInitVector = ((CK_CHAR_PTR) pbe_params)+ + sizeof(CK_PBE_PARAMS)+salt->len; + } + PORT_Memcpy(pbe_params->pSalt, salt->data, salt->len); + pbe_params->ulSaltLen = (CK_ULONG) salt->len; + + /* get iteration count */ + pbe_params->ulIteration = (CK_ULONG) DER_GetInteger(&p5_param.iteration); + + /* copy into the mechanism sec item */ + mech->data = (unsigned char *)pbe_params; + mech->len = sizeof(*pbe_params); + if (arena) { + PORT_FreeArena(arena,PR_TRUE); + } + return SECSuccess; + +loser: + if (pbe_params) { + PORT_Free(pbe_params); + } + if (arena) { + PORT_FreeArena(arena,PR_TRUE); + } + return SECFailure; +} + +SECStatus +PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PRArenaPool *arena, + SECAlgorithmID *algId) +{ + CK_PBE_PARAMS *pbe_param; + SECItem pbeSalt; + SECAlgorithmID *pbeAlgID = NULL; + SECStatus rv; + + if(!param || !algId) { + return SECFailure; + } + + pbe_param = (CK_PBE_PARAMS *)param->data; + pbeSalt.data = (unsigned char *)pbe_param->pSalt; + pbeSalt.len = pbe_param->ulSaltLen; + pbeAlgID = SEC_PKCS5CreateAlgorithmID(algTag, &pbeSalt, + (int)pbe_param->ulIteration); + if(!pbeAlgID) { + return SECFailure; + } + + rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID); + SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE); + return rv; +} + +PBEBitGenContext * +PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, + SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, + unsigned int iterations) +{ + SECItem *context = NULL; + SECItem mechItem; + CK_PBE_PARAMS pbe_params; + CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; + PK11SymKey *symKey = NULL; + unsigned char ivData[8]; + + + /* use the purpose to select the low level keygen algorithm */ + switch (bitGenPurpose) { + case pbeBitGenIntegrityKey: + switch (hashAlgorithm) { + case SEC_OID_SHA1: + mechanism = CKM_PBA_SHA1_WITH_SHA1_HMAC; + break; + case SEC_OID_MD2: + mechanism = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN; + break; + case SEC_OID_MD5: + mechanism = CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN; + break; + default: + break; + } + break; + case pbeBitGenCipherIV: + if (bitsNeeded > 64) { + break; + } + if (hashAlgorithm != SEC_OID_SHA1) { + break; + } + mechanism = CKM_PBE_SHA1_DES3_EDE_CBC; + case pbeBitGenCipherKey: + if (hashAlgorithm != SEC_OID_SHA1) { + break; + } + switch (bitsNeeded) { + case 40: + mechanism = CKM_PBE_SHA1_RC4_40; + break; + case 128: + mechanism = CKM_PBE_SHA1_RC4_128; + break; + default: + break; + } + case pbeBitGenIDNull: + break; + } + + if (mechanism == CKM_INVALID_MECHANISM) { + /* we should set an error, but this is a depricated function, and + * we are keeping bug for bug compatibility;)... */ + return NULL; + } + + pbe_params.pInitVector = ivData; + pbe_params.pPassword = pwitem->data; + pbe_params.ulPasswordLen = pwitem->len; + pbe_params.pSalt = salt->data; + pbe_params.ulSaltLen = salt->len; + pbe_params.ulIteration = iterations; + mechItem.data = (unsigned char *) &pbe_params; + mechItem.len = sizeof(pbe_params); + + + symKey = PK11_RawPBEKeyGen(PK11_GetInternalSlot(),mechanism, + &mechItem, pwitem, PR_FALSE, NULL); + if (symKey == NULL) { + if (bitGenPurpose == pbeBitGenCipherIV) { + /* NOTE: this assumes that bitsNeeded is a multiple of 8! */ + SECItem ivItem; + + ivItem.data = ivData; + ivItem.len = bitsNeeded/8; + context = SECITEM_DupItem(&ivItem); + } else { + SECItem *keyData; + PK11_ExtractKeyValue(symKey); + keyData = PK11_GetKeyData(symKey); + + /* assert bitsNeeded with length? */ + if (keyData) { + context = SECITEM_DupItem(keyData); + } + } + PK11_FreeSymKey(symKey); + } + + return (PBEBitGenContext *)context; +} + +SECItem * +PBE_GenerateBits(PBEBitGenContext *context) +{ + return (SECItem *)context; +} + +void +PBE_DestroyContext(PBEBitGenContext *context) +{ + SECITEM_FreeItem((SECItem *)context,PR_TRUE); +} + +SECItem * +SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES) +{ + SECItem mechItem; + SECOidTag algorithm = SECOID_GetAlgorithmTag(algid); + CK_PBE_PARAMS *pbe_params; + CK_MECHANISM_TYPE mechanism; + SECItem *iv = NULL; + SECStatus rv; + int iv_len; + PK11SymKey *symKey; + + rv = pbe_PK11AlgidToParam(algid,&mechItem); + if (rv != SECSuccess) { + return NULL; + } + + mechanism = PK11_AlgtagToMechanism(algorithm); + iv_len = PK11_GetIVLength(mechanism); + pbe_params = (CK_PBE_PARAMS_PTR)mechItem.data; + + symKey = PK11_RawPBEKeyGen(PK11_GetInternalSlot(),mechanism, + &mechItem, pwitem, faulty3DES,NULL); + + if (symKey) { + SECItem tmp; + + tmp.data = pbe_params->pInitVector; + tmp.len = iv_len; + iv = SECITEM_DupItem(&tmp); + PK11_FreeSymKey(symKey); + } + + if (mechItem.data) { + PORT_ZFree(mechItem.data,mechItem.len); + } + + return iv; +} + +/* + * Subs from nss 3.x that are depricated + */ +PBEBitGenContext * +__PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, + SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, + unsigned int iterations) +{ + PORT_Assert("__PBE_CreateContext is Depricated" == NULL); + return NULL; +} + +SECItem * +__PBE_GenerateBits(PBEBitGenContext *context) +{ + PORT_Assert("__PBE_GenerateBits is Depricated" == NULL); + return NULL; +} + +void +__PBE_DestroyContext(PBEBitGenContext *context) +{ + PORT_Assert("__PBE_DestroyContext is Depricated" == NULL); +} + +SECStatus +RSA_FormatBlock(SECItem *result, unsigned modulusLen, + int blockType, SECItem *data) +{ + PORT_Assert("RSA_FormatBlock is Depricated" == NULL); + return SECFailure; +} + diff --git a/security/nss/lib/pk11wrap/pk11pk12.c b/security/nss/lib/pk11wrap/pk11pk12.c index df6646e04..aea0ea8df 100644 --- a/security/nss/lib/pk11wrap/pk11pk12.c +++ b/security/nss/lib/pk11wrap/pk11pk12.c @@ -106,9 +106,41 @@ struct SECKEYRawPrivateKeyStr { } u; }; typedef struct SECKEYRawPrivateKeyStr SECKEYRawPrivateKey; -/*const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[];*/ +/* ASN1 Templates for new decoder/encoder */ +/* + * Attribute value for PKCS8 entries (static?) + */ +const SEC_ASN1Template SECKEY_AttributeTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SECKEYAttribute) }, + { SEC_ASN1_OBJECT_ID, offsetof(SECKEYAttribute, attrType) }, + { SEC_ASN1_SET_OF, offsetof(SECKEYAttribute, attrValue), + SEC_AnyTemplate }, + { 0 } +}; + +const SEC_ASN1Template SECKEY_SetOfAttributeTemplate[] = { + { SEC_ASN1_SET_OF, 0, SECKEY_AttributeTemplate }, +}; + +const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPrivateKeyInfo) }, + { SEC_ASN1_INTEGER, offsetof(SECKEYPrivateKeyInfo,version) }, + { SEC_ASN1_INLINE, offsetof(SECKEYPrivateKeyInfo,algorithm), + SECOID_AlgorithmIDTemplate }, + { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPrivateKeyInfo,privateKey) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(SECKEYPrivateKeyInfo,attributes), + SECKEY_SetOfAttributeTemplate }, + { 0 } +}; + +const SEC_ASN1Template SECKEY_PointerToPrivateKeyInfoTemplate[] = { + { SEC_ASN1_POINTER, 0, SECKEY_PrivateKeyInfoTemplate } +}; + const SEC_ASN1Template SECKEY_RSAPrivateKeyExportTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRawPrivateKey) }, { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.version) }, @@ -133,6 +165,25 @@ const SEC_ASN1Template SECKEY_DHPrivateKeyExportTemplate[] = { { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dh.prime) }, }; +const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SECKEYEncryptedPrivateKeyInfo) }, + { SEC_ASN1_INLINE, + offsetof(SECKEYEncryptedPrivateKeyInfo,algorithm), + SECOID_AlgorithmIDTemplate }, + { SEC_ASN1_OCTET_STRING, + offsetof(SECKEYEncryptedPrivateKeyInfo,encryptedData) }, + { 0 } +}; + +const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[] = { + { SEC_ASN1_POINTER, 0, SECKEY_EncryptedPrivateKeyInfoTemplate } +}; + +SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_EncryptedPrivateKeyInfoTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PrivateKeyInfoTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToPrivateKeyInfoTemplate) SECStatus diff --git a/security/nss/lib/pk11wrap/pk11pqg.c b/security/nss/lib/pk11wrap/pk11pqg.c index ef741198b..530548c36 100644 --- a/security/nss/lib/pk11wrap/pk11pqg.c +++ b/security/nss/lib/pk11wrap/pk11pqg.c @@ -42,7 +42,11 @@ */ extern SECStatus PK11_PQG_ParamGen(unsigned int j, PQGParams **pParams, PQGVerify **pVfy) { +#ifdef notdef return PQG_ParamGen(j, pParams, pVfy); +#else + return SECFailure; +#endif } /* Generate PQGParams and PQGVerify structs. @@ -53,7 +57,11 @@ PK11_PQG_ParamGen(unsigned int j, PQGParams **pParams, PQGVerify **pVfy) { extern SECStatus PK11_PQG_ParamGenSeedLen( unsigned int j, unsigned int seedBytes, PQGParams **pParams, PQGVerify **pVfy) { +#ifdef notdef return PQG_ParamGenSeedLen(j, seedBytes, pParams, pVfy); +#else + return SECFailure; +#endif } /* Test PQGParams for validity as DSS PQG values. @@ -85,7 +93,11 @@ PK11_PQG_ParamGenSeedLen( unsigned int j, unsigned int seedBytes, extern SECStatus PK11_PQG_VerifyParams(const PQGParams *params, const PQGVerify *vfy, SECStatus *result) { +#ifdef notdef return PQG_VerifyParams(params, vfy, result); +#else + return SECFailure; +#endif } diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index c036e46a0..430bd2cf7 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -49,7 +49,7 @@ #include "sechash.h" #include "cert.h" #include "secerr.h" -#include "secpkcs5.h" +/*#include "secpkcs5.h" */ #define PAIRWISE_SECITEM_TYPE siBuffer #define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */ @@ -225,7 +225,7 @@ PK11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, void *wincx) symKey->data.data = NULL; symKey->data.len = 0; symKey->owner = PR_TRUE; - symKey->objectID = CK_INVALID_KEY; + symKey->objectID = CK_INVALID_HANDLE; symKey->slot = slot; symKey->series = slot->series; symKey->cx = wincx; @@ -253,7 +253,7 @@ PK11_FreeSymKey(PK11SymKey *symKey) } PK11_USE_THREADS(PZ_Unlock(symKey->refLock);) if (destroy) { - if ((symKey->owner) && symKey->objectID != CK_INVALID_KEY) { + if ((symKey->owner) && symKey->objectID != CK_INVALID_HANDLE) { pk11_EnterKeyMonitor(symKey); (void) PK11_GETTAB(symKey->slot)-> C_DestroyObject(symKey->session, symKey->objectID); @@ -301,7 +301,7 @@ PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin, { PK11SymKey *symKey; - if (keyID == CK_INVALID_KEY) { + if (keyID == CK_INVALID_HANDLE) { return NULL; } @@ -338,7 +338,7 @@ PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type, PK11SymKey *symKey = NULL; if (slot->series != series) return NULL; - if (slot->refKeys[wrap] == CK_INVALID_KEY) return NULL; + if (slot->refKeys[wrap] == CK_INVALID_HANDLE) return NULL; if (type == CKM_INVALID_MECHANISM) type = slot->wrapMechanism; symKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, @@ -535,7 +535,7 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, /* what about fortezza??? */ default: PORT_SetError( SEC_ERROR_BAD_KEY ); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } templateCount = attrs - theTemplate; @@ -547,7 +547,7 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, theTemplate, templateCount, isToken, &objectID); if ( rv != SECSuccess) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } } @@ -588,7 +588,7 @@ PK11_FindFixedKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *keyID, PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE)); key_id = pk11_FindObjectByTemplate(slot,findTemp,tsize); - if (key_id == CK_INVALID_KEY) { + if (key_id == CK_INVALID_HANDLE) { return NULL; } return PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, type, key_id, @@ -1140,7 +1140,7 @@ PK11_CopyKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE srcObject) PK11_ExitSlotMonitor(slot); if (crv == CKR_OK) return destObject; PORT_SetError( PK11_MapError(crv) ); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } @@ -1374,7 +1374,7 @@ pk11_PairwiseConsistencyCheck(SECKEYPublicKey *pubKey, } id = PK11_ImportPublicKey(slot,pubKey,PR_FALSE); - if (id == CK_INVALID_KEY) { + if (id == CK_INVALID_HANDLE) { PK11_FreeSlot(slot); return SECFailure; } @@ -1702,7 +1702,7 @@ pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, if (pubKey->pkcs11Slot) { PK11_FreeSlot(pubKey->pkcs11Slot); pubKey->pkcs11Slot = NULL; - pubKey->pkcs11ID = CK_INVALID_KEY; + pubKey->pkcs11ID = CK_INVALID_HANDLE; } } @@ -2491,7 +2491,7 @@ PK11_MakeKEAPubKey(unsigned char *keyData,int length) pubk->arena = arena; pubk->pkcs11Slot = 0; - pubk->pkcs11ID = CK_INVALID_KEY; + pubk->pkcs11ID = CK_INVALID_HANDLE; pubk->keyType = fortezzaKey; rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.KEAKey, &pkData); if (rv != SECSuccess) { @@ -3226,7 +3226,7 @@ pk11_restoreContext(PK11Context *context,void *space, unsigned long savedLength) { CK_RV crv; CK_OBJECT_HANDLE objectID = (context->key) ? context->key->objectID: - CK_INVALID_KEY; + CK_INVALID_HANDLE; PORT_Assert(space != NULL); if (space == NULL) { @@ -4096,24 +4096,21 @@ PK11_DestroyPBEParams(SECItem *params) SECAlgorithmID * PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt) { - SECAlgorithmID *algid; - + SECAlgorithmID *algid = NULL; +#ifdef notdef algid = SEC_PKCS5CreateAlgorithmID(algorithm, salt, iteration); +#endif return algid; } PK11SymKey * -PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem, - PRBool faulty3DES, void *wincx) +PK11_RawPBEKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *mech, + SECItem *pwitem, PRBool faulty3DES, void *wincx) { /* pbe stuff */ CK_PBE_PARAMS *pbe_params; - CK_MECHANISM_TYPE type; - SECItem *mech; PK11SymKey *symKey; - mech = PK11_ParamFromAlgid(algid); - type = PK11_AlgtagToMechanism(SECOID_FindOIDTag(&algid->algorithm)); if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) { type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC; } @@ -4134,6 +4131,30 @@ PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem, symKey = PK11_KeyGen(slot, type, mech, 0, wincx); PORT_ZFree(pbe_params->pPassword, pwitem->len); + pbe_params->pPassword = NULL; + pbe_params->ulPasswordLen = 0; + return symKey; +} + +PK11SymKey * +PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem, + PRBool faulty3DES, void *wincx) +{ + /* pbe stuff */ + CK_MECHANISM_TYPE type; + SECItem *mech; + PK11SymKey *symKey; + + mech = PK11_ParamFromAlgid(algid); + type = PK11_AlgtagToMechanism(SECOID_FindOIDTag(&algid->algorithm)); + if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) { + type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC; + } + if(mech == NULL) { + return NULL; + } + symKey = PK11_RawPBEKeyGen(slot, type, mech, pwitem, faulty3DES, wincx); + SECITEM_ZfreeItem(mech, PR_TRUE); return symKey; } @@ -4205,7 +4226,8 @@ PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot, try_faulty_3des: pbe_param = PK11_ParamFromAlgid(&epki->algorithm); - key = PK11_PBEKeyGen(slot, &epki->algorithm, pwitem, faulty3DES, wincx); + key = PK11_RawPBEKeyGen(slot, mechanism, pbe_param, pwitem, + faulty3DES, wincx); if((key == NULL) || (pbe_param == NULL)) { rv = SECFailure; goto done; @@ -4372,7 +4394,9 @@ PK11_ExportEncryptedPrivateKeyInfo(PK11SlotInfo *slot, SECOidTag algTag, goto loser; } epki->arena = arena; +#ifdef notdef algid = SEC_PKCS5CreateAlgorithmID(algTag, NULL, iteration); +#endif if(algid == NULL) { rv = SECFailure; goto loser; @@ -4383,7 +4407,8 @@ PK11_ExportEncryptedPrivateKeyInfo(PK11SlotInfo *slot, SECOidTag algTag, pbeMech.mechanism = mechanism; pbeMech.pParameter = pbe_param->data; pbeMech.ulParameterLen = pbe_param->len; - key = PK11_PBEKeyGen(slot, algid, pwitem, PR_FALSE, wincx); + key = PK11_RawPBEKeyGen(slot, mechanism, pbe_param, pwitem, + PR_FALSE, wincx); if((key == NULL) || (pbe_param == NULL)) { rv = SECFailure; diff --git a/security/nss/lib/pk11wrap/pk11slot.c b/security/nss/lib/pk11wrap/pk11slot.c index f468c217b..b42607f57 100644 --- a/security/nss/lib/pk11wrap/pk11slot.c +++ b/security/nss/lib/pk11wrap/pk11slot.c @@ -49,9 +49,7 @@ #include "prtime.h" #include "prlong.h" #include "secerr.h" -#include "secpkcs5.h" -#define NSSCKT_H /* we included pkcs11t.h, so block ckt.h from including nssckt.h */ -#include "ckt.h" +/*#include "secpkcs5.h" */ /************************************************************* @@ -419,7 +417,7 @@ PK11_NewSlotInfo(void) slot->series = 0; slot->wrapKey = 0; slot->wrapMechanism = CKM_INVALID_MECHANISM; - slot->refKeys[0] = CK_INVALID_KEY; + slot->refKeys[0] = CK_INVALID_HANDLE; slot->reason = PK11_DIS_NONE; slot->readOnly = PR_TRUE; slot->needLogin = PR_FALSE; @@ -467,9 +465,6 @@ PK11_DestroySlot(PK11SlotInfo *slot) PK11_GETTAB(slot)->C_CloseAllSessions(slot->slotID); } - /* now free up all the certificates we grabbed on this slot */ - PK11_FreeSlotCerts(slot); - /* free up the cached keys and sessions */ PK11_CleanKeyList(slot); @@ -1082,9 +1077,6 @@ PK11_DoPassword(PK11SlotInfo *slot, PRBool loadCerts, void *wincx) if (rv != SECWouldBlock) break; } if (rv == SECSuccess) { - if ((loadCerts) && (!slot->isInternal) && (slot->cert_count == 0)) { - PK11_ReadSlotCerts(slot); - } rv = pk11_CheckVerifyTest(slot); } else if (!attempt) PORT_SetError(SEC_ERROR_BAD_PASSWORD); return rv; @@ -1715,14 +1707,6 @@ PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts) if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); } - /*if we have cached slotcerts, free them they are almost certainly stale*/ - PK11_FreeSlotCerts(slot); - - if (loadCerts && (!slot->isInternal) && - ((!slot->needLogin) || (slot->defaultFlags & SECMOD_FRIENDLY_FLAG))) { - PK11_ReadSlotCerts(slot); - } - if (!(slot->needLogin)) { return pk11_CheckVerifyTest(slot); } @@ -1783,7 +1767,7 @@ pk11_isRootSlot(PK11SlotInfo *slot) PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE)); handle = pk11_FindObjectByTemplate(slot,findTemp,tsize); - if (handle == CK_INVALID_KEY) { + if (handle == CK_INVALID_HANDLE) { return PR_FALSE; } return PR_TRUE; @@ -1891,7 +1875,6 @@ pk11_IsPresentCertLoad(PK11SlotInfo *slot, PRBool loadCerts) PK11_GETTAB(slot)->C_CloseSession(slot->session); slot->session = CK_INVALID_SESSION; /* force certs to be freed */ - PK11_FreeSlotCerts(slot); } if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); return PR_FALSE; @@ -1904,7 +1887,6 @@ pk11_IsPresentCertLoad(PK11SlotInfo *slot, PRBool loadCerts) if (crv != CKR_OK) { PK11_GETTAB(slot)->C_CloseSession(slot->session); slot->session = CK_INVALID_SESSION; - PK11_FreeSlotCerts(slot); } } if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); @@ -3334,59 +3316,6 @@ static unsigned long rc2_unmap(unsigned long x) } -/* - * Helper function to decode a PKCS5 DER encode paramter block into a PKCS #11 - * PBE_Parameter structure. - */ -SECStatus -pk11_pbe_decode(SECAlgorithmID *algid, SECItem *mech) -{ - CK_PBE_PARAMS *pbe_params = NULL; - SEC_PKCS5PBEParameter *p5_param; - SECItem *p5_misc = NULL; - int paramSize = 0; - - p5_param = SEC_PKCS5GetPBEParameter(algid); - if(p5_param == NULL) { - return SECFailure; - } - - - p5_misc = &p5_param->salt; - paramSize = sizeof(CK_PBE_PARAMS); - - pbe_params = (CK_PBE_PARAMS *)PORT_ZAlloc(paramSize); - if (pbe_params == NULL) { - SEC_PKCS5DestroyPBEParameter(p5_param); - return SECFailure; - } - - /* get salt */ - pbe_params->pSalt = (CK_CHAR_PTR)PORT_ZAlloc(p5_misc->len); - if (pbe_params->pSalt == CK_NULL_PTR) { - goto loser; - } - PORT_Memcpy(pbe_params->pSalt, p5_misc->data, p5_misc->len); - pbe_params->ulSaltLen = (CK_ULONG) p5_misc->len; - - /* get iteration count */ - p5_misc = &p5_param->iteration; - pbe_params->ulIteration = (CK_ULONG) DER_GetInteger(p5_misc); - - /* copy into the mechanism sec item */ - mech->data = (unsigned char *)pbe_params; - mech->len = paramSize; - SEC_PKCS5DestroyPBEParameter(p5_param); - return SECSuccess; - -loser: - if (pbe_params->pSalt != CK_NULL_PTR) { - PORT_Free(pbe_params->pSalt); - } - PORT_Free(pbe_params); - SEC_PKCS5DestroyPBEParameter(p5_param); - return SECFailure; -} /* Generate a mechaism param from a type, and iv. */ SECItem * @@ -3520,7 +3449,7 @@ PK11_ParamFromAlgid(SECAlgorithmID *algid) case CKM_PBE_SHA1_RC2_128_CBC: case CKM_PBE_SHA1_RC4_40: case CKM_PBE_SHA1_RC4_128: - rv = pk11_pbe_decode(algid,mech); + rv = pbe_PK11AlgidToParam(algid,mech); if (rv != SECSuccess) { PORT_Free(mech); return NULL; @@ -4285,7 +4214,6 @@ PK11_ResetToken(PK11SlotInfo *slot, char *sso_pwd) /* first shutdown the token. Existing sessions will get closed here */ PK11_GETTAB(slot)->C_CloseAllSessions(slot->slotID); slot->session = CK_INVALID_SESSION; - PK11_FreeSlotCerts(slot); /* now re-init the token */ crv = PK11_GETTAB(slot)->C_InitToken(slot->slotID, @@ -4301,47 +4229,14 @@ PK11_ResetToken(PK11SlotInfo *slot, char *sso_pwd) return SECSuccess; } - - - -static SECOidTag -pk11_MapPBEMechanismTypeToAlgtag(CK_MECHANISM_TYPE mech) -{ - switch(mech) { - case CKM_PBE_MD2_DES_CBC: - return SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC; - case CKM_PBE_MD5_DES_CBC: - return SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC; - case CKM_NETSCAPE_PBE_SHA1_DES_CBC: - return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC; - case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: - return SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC; - case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: - return SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC; - case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: - return SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4; - case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: - return SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4; - case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: - return SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; - case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: - return SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC; - case CKM_PBE_SHA1_RC2_128_CBC: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC; - case CKM_PBE_SHA1_RC2_40_CBC: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; - case CKM_PBE_SHA1_RC4_40: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4; - case CKM_PBE_SHA1_RC4_128: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4; - case CKM_PBE_SHA1_DES3_EDE_CBC: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC; - case CKM_PBE_SHA1_DES2_EDE_CBC: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC; - default: - break; +static PRBool +pk11_isAllZero(unsigned char *data,int len) { + while (len--) { + if (*data++) { + return PR_FALSE; + } } - return SEC_OID_UNKNOWN; + return PR_TRUE; } CK_RV @@ -4353,9 +4248,6 @@ PK11_MapPBEMechanismToCryptoMechanism(CK_MECHANISM_PTR pPBEMechanism, CK_PBE_PARAMS_PTR pPBEparams; CK_RC2_CBC_PARAMS_PTR rc2_params; CK_ULONG rc2_key_len; - SECStatus rv = SECFailure; - SECAlgorithmID temp_algid; - SECItem param, *iv; if((pPBEMechanism == CK_NULL_PTR) || (pCryptoMechanism == CK_NULL_PTR)) { return CKR_HOST_MEMORY; @@ -4364,32 +4256,20 @@ PK11_MapPBEMechanismToCryptoMechanism(CK_MECHANISM_PTR pPBEMechanism, pPBEparams = (CK_PBE_PARAMS_PTR)pPBEMechanism->pParameter; iv_len = PK11_GetIVLength(pPBEMechanism->mechanism); - if(pPBEparams->pInitVector == CK_NULL_PTR) { - pPBEparams->pInitVector = (CK_CHAR_PTR)PORT_ZAlloc(iv_len); - if(pPBEparams->pInitVector == NULL) { - return CKR_HOST_MEMORY; - } - param.data = (unsigned char*)pPBEMechanism->pParameter; - param.len = pPBEMechanism->ulParameterLen; - rv = PK11_ParamToAlgid(pk11_MapPBEMechanismTypeToAlgtag( - pPBEMechanism->mechanism), - ¶m, NULL, &temp_algid); - if(rv != SECSuccess) { - SECOID_DestroyAlgorithmID(&temp_algid, PR_FALSE); - return CKR_HOST_MEMORY; - } else { - iv = SEC_PKCS5GetIV(&temp_algid, pbe_pwd, faulty3DES); - if((iv == NULL) && (iv_len != 0)) { - SECOID_DestroyAlgorithmID(&temp_algid, PR_FALSE); - return CKR_HOST_MEMORY; - } - SECOID_DestroyAlgorithmID(&temp_algid, PR_FALSE); - if(iv != NULL) { - PORT_Memcpy((char *)pPBEparams->pInitVector, - (char *)iv->data, - iv->len); - SECITEM_ZfreeItem(iv, PR_TRUE); + if (iv_len) { + if (pk11_isAllZero(pPBEparams->pInitVector,iv_len)) { + SECItem param; + PK11SymKey *symKey; + + param.data = pPBEMechanism->pParameter; + param.len = pPBEMechanism->ulParameterLen; + + symKey = PK11_RawPBEKeyGen(PK11_GetInternalSlot(), + pPBEMechanism->mechanism, ¶m, pbe_pwd, faulty3DES, NULL); + if (symKey== NULL) { + return CKR_DEVICE_ERROR; /* sigh */ } + PK11_FreeSymKey(symKey); } } @@ -4430,9 +4310,10 @@ have_crypto_mechanism: rc2_key_len = 128; have_key_len: pCryptoMechanism->mechanism = CKM_RC2_CBC; - pCryptoMechanism->ulParameterLen = (CK_ULONG)sizeof(CK_RC2_CBC_PARAMS); - pCryptoMechanism->pParameter = - (CK_RC2_CBC_PARAMS_PTR)PORT_ZAlloc(sizeof(CK_RC2_CBC_PARAMS)); + pCryptoMechanism->ulParameterLen = (CK_ULONG) + sizeof(CK_RC2_CBC_PARAMS); + pCryptoMechanism->pParameter = (CK_RC2_CBC_PARAMS_PTR) + PORT_ZAlloc(sizeof(CK_RC2_CBC_PARAMS)); if(pCryptoMechanism->pParameter == NULL) { return CKR_HOST_MEMORY; } diff --git a/security/nss/lib/pk11wrap/pk11util.c b/security/nss/lib/pk11wrap/pk11util.c index adf16cb43..a8326a404 100644 --- a/security/nss/lib/pk11wrap/pk11util.c +++ b/security/nss/lib/pk11wrap/pk11util.c @@ -460,8 +460,8 @@ SECStatus SECMOD_UpdateModule(SECMODModule *module) result = SECMOD_DeletePermDB(module); if (result == SECSuccess) { - result = SECMOD_AddPermDB(module); } + result = SECMOD_AddPermDB(module); return result; } diff --git a/security/nss/lib/pk11wrap/secmodt.h b/security/nss/lib/pk11wrap/secmodt.h index b36350ae6..de2ae10f3 100644 --- a/security/nss/lib/pk11wrap/secmodt.h +++ b/security/nss/lib/pk11wrap/secmodt.h @@ -162,8 +162,6 @@ struct PK11DefaultArrayEntryStr { #define CKM_FAKE_RANDOM 0x80000efeL #define CKM_INVALID_MECHANISM 0xffffffffL #define CKA_DIGEST 0x81000000L -#define CK_INVALID_KEY 0 -#define CK_INVALID_SESSION 0 /* Cryptographic module types */ #define SECMOD_EXTERNAL 0 /* external module */ @@ -206,11 +204,11 @@ typedef PRBool (*PK11IsLoggedInFunc)(PK11SlotInfo *slot, void *arg); /* ** Attributes */ -struct SECKEYPrivAttributeStr { +struct SECKEYAttributeStr { SECItem attrType; SECItem **attrValue; }; -typedef struct SECKEYPrivAttributeStr SECKEYPrivAttribute; +typedef struct SECKEYAttributeStr SECKEYAttribute; /* ** A PKCS#8 private key info object @@ -220,10 +218,9 @@ struct SECKEYPrivateKeyInfoStr { SECItem version; SECAlgorithmID algorithm; SECItem privateKey; - SECKEYPrivAttribute **attributes; + SECKEYAttribute **attributes; }; typedef struct SECKEYPrivateKeyInfoStr SECKEYPrivateKeyInfo; -#define SEC_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */ /* ** A PKCS#8 private key info object diff --git a/security/nss/lib/pk11wrap/secmodti.h b/security/nss/lib/pk11wrap/secmodti.h index b25c257c5..30f431f90 100644 --- a/security/nss/lib/pk11wrap/secmodti.h +++ b/security/nss/lib/pk11wrap/secmodti.h @@ -35,8 +35,12 @@ * pkcs11 specific client and server files. */ +#ifndef _SECMODTI_H_ +#define _SECMODTI_H_ 1 #include "prmon.h" #include "prtypes.h" +#include "nssilckt.h" +#include "pk11init.h" #ifndef NSS_3_4_CODE #define NSS_3_4_CODE @@ -129,19 +133,6 @@ struct PK11SlotInfoStr { NSSToken *nssToken; }; -/* hold slot default flags until we initialize a slot. This structure is only - * useful between the time we define a module (either by hand or from the - * database) and the time the module is loaded. Not reference counted */ -struct PK11PreSlotInfoStr { - CK_SLOT_ID slotID; /* slot these flags are for */ - unsigned long defaultFlags; /* bit mask of default implementation this slot - * provides */ - int askpw; /* slot specific password bits */ - long timeout; /* slot specific timeout value */ - char hasRootCerts; /* is this the root cert PKCS #11 module? */ - char hasRootTrust; /* is this the root cert PKCS #11 module? */ -}; - #define SECMOD_SLOT_FLAGS "slotFlags=[RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES]" #define SECMOD_MAKE_NSS_FLAGS(fips,slot) \ @@ -203,3 +194,4 @@ struct PK11ContextStr { * non-standard semantics*/ }; +#endif /* _SECMODTI_H_ */ diff --git a/security/nss/lib/pkcs12/p12d.c b/security/nss/lib/pkcs12/p12d.c index 60edeae0d..051428575 100644 --- a/security/nss/lib/pkcs12/p12d.c +++ b/security/nss/lib/pkcs12/p12d.c @@ -1976,8 +1976,7 @@ sec_pkcs12_get_existing_nick_for_dn(sec_PKCS12SafeBag *cert, void *wincx) return NULL; } - tempCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert, NULL, - PR_FALSE, PR_TRUE); + tempCert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if(!tempCert) { returnDn = NULL; goto loser; @@ -2002,15 +2001,6 @@ sec_pkcs12_get_existing_nick_for_dn(sec_PKCS12SafeBag *cert, void *wincx) /* if the token is local, first traverse the cert database * then traverse the token. */ - if(PK11_IsInternal(cert->slot)) { - if(CERT_TraversePermCertsForSubject(CERT_GetDefaultCertDB(), - &tempCert->derSubject, gatherNicknames, - nickArg) != SECSuccess) { - returnDn = NULL; - goto loser; - } - } - if(PK11_TraverseCertsForSubjectInSlot(tempCert, cert->slot, gatherNicknames, (void *)nickArg) != SECSuccess) { returnDn = NULL; @@ -2071,12 +2061,6 @@ sec_pkcs12_certs_for_nickname_exist(SECItem *nickname, PK11SlotInfo *slot) } /* we want to check the local database first if we are importing to it */ - if(PK11_IsInternal(slot)) { - CERT_TraversePermCertsForNickname(CERT_GetDefaultCertDB(), - (char *)nickname->data, - countCertificate, (void *)&nCerts); - } - PK11_TraverseCertsForNicknameInSlot(nickname, slot, countCertificate, (void *)&nCerts); if(nCerts) return PR_TRUE; @@ -2243,9 +2227,8 @@ sec_pkcs12_validate_cert(sec_PKCS12SafeBag *cert, cert->problem = PR_FALSE; cert->error = 0; - leafCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), - &cert->safeBagContent.certBag->value.x509Cert, - NULL, PR_FALSE, PR_TRUE); + leafCert = CERT_DecodeDERCertificate( + &cert->safeBagContent.certBag->value.x509Cert, PR_FALSE, NULL); if(!leafCert) { cert->noInstall = PR_TRUE; cert->problem = PR_TRUE; @@ -2297,9 +2280,8 @@ sec_pkcs12_validate_key_by_cert(sec_PKCS12SafeBag *cert, sec_PKCS12SafeBag *key, return; } - leafCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), - &(cert->safeBagContent.certBag->value.x509Cert), - NULL, PR_FALSE, PR_TRUE); + leafCert = CERT_DecodeDERCertificate( + &(cert->safeBagContent.certBag->value.x509Cert), PR_FALSE, NULL); if(!leafCert) { key->problem = PR_TRUE; key->noInstall = PR_TRUE; @@ -2337,8 +2319,7 @@ sec_pkcs12_remove_existing_cert(sec_PKCS12SafeBag *cert, cert->removeExisting = PR_FALSE; derCert = &cert->safeBagContent.certBag->value.x509Cert; - tempCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert, - NULL, PR_FALSE, PR_TRUE); + tempCert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if(!tempCert) { return SECFailure; } @@ -2347,7 +2328,7 @@ sec_pkcs12_remove_existing_cert(sec_PKCS12SafeBag *cert, CERT_DestroyCertificate(tempCert); tempCert = NULL; - if(certObj != CK_INVALID_KEY) { + if(certObj != CK_INVALID_HANDLE) { PK11_DestroyObject(cert->slot, certObj); removed = PR_TRUE; } else if(PK11_IsInternal(cert->slot)) { @@ -2408,8 +2389,7 @@ sec_pkcs12_add_cert(sec_PKCS12SafeBag *cert, PRBool keyExists, void *wincx) if(keyExists) { CERTCertificate *newCert; - newCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), - derCert, NULL, PR_FALSE, PR_TRUE); + newCert = CERT_DecodeDERCertificate( derCert, PR_FALSE, NULL); if(!newCert) { if(nickName) SECITEM_ZfreeItem(nickName, PR_TRUE); cert->error = SEC_ERROR_NO_MEMORY; @@ -2591,8 +2571,7 @@ SEC_PKCS12DecoderGetCerts(SEC_PKCS12DecoderContext *p12dcx) CERTCertificate *tempCert = NULL; if (derCert == NULL) continue; - tempCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), - derCert, NULL, PR_FALSE, PR_TRUE); + tempCert=CERT_DecodeDERCertificate(derCert, PR_TRUE, NULL); if (tempCert) { CERT_AddCertToListTail(certList,tempCert); @@ -2777,9 +2756,8 @@ sec_pkcs12_get_public_value_and_type(sec_PKCS12SafeBag *certBag, return NULL; } - cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), - &certBag->safeBagContent.certBag->value.x509Cert, - NULL, PR_FALSE, PR_FALSE); + cert = CERT_DecodeDERCertificate( + &certBag->safeBagContent.certBag->value.x509Cert, PR_FALSE, NULL); if(!cert) { return NULL; } diff --git a/security/nss/lib/pkcs12/p12dec.c b/security/nss/lib/pkcs12/p12dec.c index bae2bd736..f1f9fe464 100644 --- a/security/nss/lib/pkcs12/p12dec.c +++ b/security/nss/lib/pkcs12/p12dec.c @@ -44,8 +44,8 @@ #include "cert.h" #include "certdb.h" #include "p12plcy.h" -#include "p12.h" -#include "secpkcs5.h" +#include "p12.h" +/*#include "secpkcs5.h" */ /* PFX extraction and validation routines */ diff --git a/security/nss/lib/pkcs12/p12e.c b/security/nss/lib/pkcs12/p12e.c index 22ff31104..1a7248e70 100644 --- a/security/nss/lib/pkcs12/p12e.c +++ b/security/nss/lib/pkcs12/p12e.c @@ -1029,17 +1029,17 @@ SEC_PKCS12AddCert(SEC_PKCS12ExportContext *p12ctxt, SEC_PKCS12SafeInfo *safe, CERTCertificate *tempCert; /* decode the certificate */ - tempCert = CERT_NewTempCertificate(certDb, - &certList->certs[count], NULL, - PR_FALSE, PR_TRUE); + tempCert = + CERT_DecodeDERCertificate( &certList->certs[count], + PR_FALSE, NULL); if(!tempCert) { CERT_DestroyCertificateList(certList); goto loser; } /* add the certificate */ - if(SEC_PKCS12AddCert(p12ctxt, safe, nestedDest, tempCert, certDb, - NULL, PR_FALSE) != SECSuccess) { + if(SEC_PKCS12AddCert(p12ctxt, safe, nestedDest, tempCert, + certDb, NULL, PR_FALSE) != SECSuccess) { CERT_DestroyCertificate(tempCert); CERT_DestroyCertificateList(certList); goto loser; @@ -1400,8 +1400,7 @@ SEC_PKCS12AddDERCertAndEncryptedKey(SEC_PKCS12ExportContext *p12ctxt, mark = PORT_ArenaMark(p12ctxt->arena); - cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert, - NULL, PR_FALSE, PR_TRUE); + cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if(!cert) { PORT_ArenaRelease(p12ctxt->arena, mark); PORT_SetError(SEC_ERROR_NO_MEMORY); diff --git a/security/nss/lib/pkcs12/p12plcy.c b/security/nss/lib/pkcs12/p12plcy.c index e9616ade0..26edd16ba 100644 --- a/security/nss/lib/pkcs12/p12plcy.c +++ b/security/nss/lib/pkcs12/p12plcy.c @@ -35,7 +35,7 @@ #include "p12plcy.h" #include "secoid.h" #include "secport.h" -#include "secpkcs5.h" /* LOTS of PKCS5 calls below. XXX EVIL. */ +/*#include "secpkcs5.h" LOTS of PKCS5 calls below. XXX EVIL. */ #define PKCS12_NULL 0x0000 diff --git a/security/nss/lib/pkcs7/p7common.c b/security/nss/lib/pkcs7/p7common.c index 8bab3685f..329b078ed 100644 --- a/security/nss/lib/pkcs7/p7common.c +++ b/security/nss/lib/pkcs7/p7common.c @@ -485,16 +485,22 @@ SEC_PKCS7EncryptContents(PRArenaPool *poolp, rv = SECFailure; goto loser; } - eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx); - if(eKey == NULL) { + pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); + result = PK11_ParamFromAlgid(algid); + if (result == NULL) { rv = SECFailure; goto loser; } - - pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); - result = PK11_ParamFromAlgid(algid); pbeMech.pParameter = result->data; pbeMech.ulParameterLen = result->len; + + eKey = PK11_RawPBEKeyGen(slot, pbeMech.mechanism, result, key, PR_FALSE, + wincx); + if(eKey == NULL) { + rv = SECFailure; + goto loser; + } + if(PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, key, PR_FALSE) != CKR_OK) { rv = SECFailure; @@ -646,16 +652,20 @@ SEC_PKCS7DecryptContents(PRArenaPool *poolp, rv = SECFailure; goto loser; } - eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx); - if(eKey == NULL) { + pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); + result = PK11_ParamFromAlgid(algid); + if (result == NULL) { rv = SECFailure; goto loser; } - - pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); - result = PK11_ParamFromAlgid(algid); pbeMech.pParameter = result->data; pbeMech.ulParameterLen = result->len; + eKey = PK11_RawPBEKeyGen(slot,pbeMech.mechanism,result,key,PR_FALSE,wincx); + if(eKey == NULL) { + rv = SECFailure; + goto loser; + } + if(PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, key, PR_FALSE) != CKR_OK) { rv = SECFailure; diff --git a/security/nss/lib/pkcs7/p7decode.c b/security/nss/lib/pkcs7/p7decode.c index a6c47bbc1..0df147a3f 100644 --- a/security/nss/lib/pkcs7/p7decode.c +++ b/security/nss/lib/pkcs7/p7decode.c @@ -47,7 +47,7 @@ /* the add certificate code needs to get */ /* rewritten/abstracted and then this */ /* include should be removed! */ -#include "cdbhdl.h" +/*#include "cdbhdl.h" */ #include "cryptohi.h" #include "key.h" #include "secasn1.h" @@ -58,7 +58,7 @@ #include "secerr.h" #include "sechash.h" /* for HASH_GetHashObject() */ #include "secder.h" -#include "secpkcs5.h" +/*#include "secpkcs5.h" */ struct sec_pkcs7_decoder_worker { int depth; @@ -1449,7 +1449,7 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo, SEC_PKCS7SignerInfo **signerinfos, *signerinfo; CERTCertificate *cert, **certs; PRBool goodsig; - CERTCertDBHandle local_certdb, *certdb, *defaultdb; + CERTCertDBHandle *certdb, *defaultdb; SECOidData *algiddata; int i, certcount; SECKEYPublicKey *publickey; @@ -1541,10 +1541,7 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo, */ certdb = defaultdb; if (certdb == NULL) { - if (CERT_OpenCertDBFilename (&local_certdb, NULL, - (PRBool)!keepcerts) != SECSuccess) - goto done; - certdb = &local_certdb; + goto done; } certcount = 0; @@ -1915,9 +1912,6 @@ done: if (certs != NULL) CERT_DestroyCertArray (certs, certcount); - if (defaultdb == NULL && certdb != NULL) - CERT_ClosePermCertDB (certdb); - if (publickey != NULL) SECKEY_DestroyPublicKey (publickey); diff --git a/security/nss/lib/pkcs7/p7encode.c b/security/nss/lib/pkcs7/p7encode.c index c38026a56..879a1b286 100644 --- a/security/nss/lib/pkcs7/p7encode.c +++ b/security/nss/lib/pkcs7/p7encode.c @@ -96,7 +96,6 @@ sec_pkcs7_encoder_start_encrypt (SEC_PKCS7ContentInfo *cinfo, void *mark, *wincx; int i; PRArenaPool *arena = NULL; - unsigned char zero = 0; /* Get the context in case we need it below. */ wincx = cinfo->pwfn_arg; diff --git a/security/nss/lib/pkcs7/p7local.c b/security/nss/lib/pkcs7/p7local.c index 68376cec0..114bf73eb 100644 --- a/security/nss/lib/pkcs7/p7local.c +++ b/security/nss/lib/pkcs7/p7local.c @@ -47,7 +47,7 @@ #include "secoid.h" #include "secitem.h" #include "pk11func.h" -#include "secpkcs5.h" +/*#include "secpkcs5.h" */ #include "secerr.h" /* diff --git a/security/nss/lib/pki/certdecode.c b/security/nss/lib/pki/certdecode.c index d815275e4..deccb57ce 100644 --- a/security/nss/lib/pki/certdecode.c +++ b/security/nss/lib/pki/certdecode.c @@ -114,7 +114,7 @@ nssDecodedCert_Destroy #if 0 nss_SetError(NSS_ERROR_INVALID_ARGUMENT); #endif - return PR_FAILURE; + break; } return PR_FAILURE; } diff --git a/security/nss/lib/pki/certificate.c b/security/nss/lib/pki/certificate.c index ff41de22d..16f9291e3 100644 --- a/security/nss/lib/pki/certificate.c +++ b/security/nss/lib/pki/certificate.c @@ -135,7 +135,7 @@ NSSCertificate_Create if (!arenaOpt) { rvCert->arena = arena; } - rvCert->handle = CK_INVALID_KEY; + rvCert->handle = CK_INVALID_HANDLE; return rvCert; loser: if (!arenaOpt && arena) { @@ -191,27 +191,30 @@ nssCertificate_GetCertTrust ) { PRStatus nssrv; - CK_TRUST saTrust, epTrust, csTrust; + CK_TRUST saTrust, caTrust, epTrust, csTrust; CK_OBJECT_HANDLE tobjID; CK_ULONG trust_size; CK_ATTRIBUTE trust_template[] = { { CKA_TRUST_SERVER_AUTH, NULL, 0 }, + { CKA_TRUST_CLIENT_AUTH, NULL, 0 }, { CKA_TRUST_EMAIL_PROTECTION, NULL, 0 }, { CKA_TRUST_CODE_SIGNING, NULL, 0 } }; trust_size = sizeof(trust_template) / sizeof(trust_template[0]); tobjID = get_cert_trust_handle(c, session); - if (tobjID == CK_INVALID_KEY) { + if (tobjID == CK_INVALID_HANDLE) { return PR_FAILURE; } /* Then use the trust object to find the trust settings */ NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 0, saTrust); - NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 1, epTrust); - NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 2, csTrust); + NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 1, caTrust); + NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 2, epTrust); + NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 3, csTrust); nssrv = nssCKObject_GetAttributes(tobjID, trust_template, trust_size, NULL, session, c->slot); c->trust.serverAuth = saTrust; + c->trust.clientAuth = caTrust; c->trust.emailProtection = epTrust; c->trust.codeSigning = csTrust; return PR_SUCCESS; @@ -371,9 +374,17 @@ nssCertificate_SetCertTrust } session = c->token->defaultSession; tobjID = get_cert_trust_handle(c, session); - if (tobjID == CK_INVALID_KEY) { + if (tobjID == CK_INVALID_HANDLE) { /* trust object doesn't exist yet, create one */ - return create_cert_trust_object(c, trust); + tobjID = create_cert_trust_object(c, trust); + if (tobjID == CK_INVALID_HANDLE) { + return PR_FAILURE; + } + c->trust.serverAuth = trust->serverAuth; + c->trust.clientAuth = trust->clientAuth; + c->trust.emailProtection = trust->emailProtection; + c->trust.codeSigning = trust->codeSigning; + return PR_SUCCESS; } NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 0, trust->serverAuth); NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 1, trust->clientAuth); @@ -754,13 +765,15 @@ NSSCertificate_GetPublicKey NSSCertificate *c ) { - PRStatus nssrv; CK_ATTRIBUTE pubktemplate[] = { { CKA_CLASS, NULL, 0 }, { CKA_ID, NULL, 0 }, { CKA_SUBJECT, NULL, 0 } }; +#if 0 + PRStatus nssrv; CK_ULONG count = sizeof(pubktemplate) / sizeof(pubktemplate[0]); +#endif NSS_CK_SET_ATTRIBUTE_ITEM(pubktemplate, 0, &g_ck_class_pubkey); if (c->id.size > 0) { /* CKA_ID */ diff --git a/security/nss/lib/pki/manifest.mn b/security/nss/lib/pki/manifest.mn index 80713dba5..e52c8d146 100644 --- a/security/nss/lib/pki/manifest.mn +++ b/security/nss/lib/pki/manifest.mn @@ -57,8 +57,8 @@ CSRCS = \ $(NULL) ifndef PURE_STAN_BUILD -CSRCS += nss3hack.c -PRIVATE_EXPORTS += pkinss3hack.h pkitm.h pkim.h +CSRCS += pki3hack.c +PRIVATE_EXPORTS += pki3hack.h pkitm.h pkim.h DEFINES = -DNSS_3_4_CODE endif diff --git a/security/nss/lib/pki/nss3hack.c b/security/nss/lib/pki/pki3hack.c index 5968ac571..db6a4e2b0 100644 --- a/security/nss/lib/pki/nss3hack.c +++ b/security/nss/lib/pki/pki3hack.c @@ -56,11 +56,11 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #endif /* CKHELPER_H */ #ifndef DEVNSS3HACK_H -#include "devnss3hack.h" +#include "dev3hack.h" #endif /* DEVNSS3HACK_H */ #ifndef PKINSS3HACK_H -#include "pkinss3hack.h" +#include "pki3hack.h" #endif /* PKINSS3HACK_H */ #include "secitem.h" @@ -95,13 +95,10 @@ STAN_LoadDefaultNSS3TrustDomain td->tokenList = nssList_Create(td->arena, PR_TRUE); list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL); if (list) { - /* XXX this doesn't work until softoken is a true PKCS#11 mod */ for (le = list->head; le; le = le->next) { - if (!PK11_IsInternal(le->slot)) { - token = nssToken_CreateFromPK11SlotInfo(td, le->slot); - PK11Slot_SetNSSToken(le->slot, token); - nssList_Add(td->tokenList, token); - } + token = nssToken_CreateFromPK11SlotInfo(td, le->slot); + PK11Slot_SetNSSToken(le->slot, token); + nssList_Add(td->tokenList, token); } } td->tokens = nssList_CreateIterator(td->tokenList); @@ -322,7 +319,14 @@ static CERTCertTrust * nssTrust_GetCERTCertTrust(NSSTrust *t, CERTCertificate *cc) { CERTCertTrust *rvTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust)); + unsigned int client; rvTrust->sslFlags = get_nss3trust_from_cktrust(t->serverAuth); + client = get_nss3trust_from_cktrust(t->clientAuth); + if (client & (CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA)) { + client &= ~(CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA); + rvTrust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA; + } + rvTrust->sslFlags |= client; rvTrust->emailFlags = get_nss3trust_from_cktrust(t->emailProtection); rvTrust->objectSigningFlags = get_nss3trust_from_cktrust(t->codeSigning); if (PK11_IsUserCert(cc->slot, cc, cc->pkcs11ID)) { @@ -347,7 +351,7 @@ fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc) } /* trust */ cc->trust = nssTrust_GetCERTCertTrust(&c->trust, cc); - /* referenceCount addref? */ + cc->referenceCount++; /* subjectList ? */ /* pkcs11ID */ cc->pkcs11ID = c->handle; @@ -378,14 +382,55 @@ NSS_EXTERN NSSCertificate * STAN_GetNSSCertificate(CERTCertificate *cc) { NSSCertificate *c; + NSSArena *arena; + c = cc->nssCertificate; - if (!c) { - /* i don't think this should happen. but if it can, need to create - * NSSCertificate from CERTCertificate values here. - */ + if (c) { + return c; + } + + /* i don't think this should happen. but if it can, need to create + * NSSCertificate from CERTCertificate values here. */ + /* Yup, it can happen. */ + arena = NSSArena_Create(); + if (!arena) { return NULL; } + c = NSSCertificate_Create(arena); + if (!c) { + goto loser; + } + NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert); + c->type = NSSCertificateType_PKIX; + c->arena = arena; + nssItem_Create(arena, + &c->issuer, cc->derIssuer.len, cc->derIssuer.data); + nssItem_Create(arena, + &c->subject, cc->derSubject.len, cc->derSubject.data); + nssItem_Create(arena, + &c->serial, cc->serialNumber.len, cc->serialNumber.data); + if (cc->nickname) { + c->nickname = nssUTF8_Create(arena, + nssStringType_UTF8String, + (NSSUTF8 *)cc->nickname, + PORT_Strlen(cc->nickname)); + } + if (cc->emailAddr) { + c->email = nssUTF8_Create(arena, + nssStringType_PrintableString, + (NSSUTF8 *)cc->emailAddr, + PORT_Strlen(cc->emailAddr)); + } + c->trustDomain = (NSSTrustDomain *)cc->dbhandle; + if (cc->slot) { + c->token = PK11Slot_GetNSSToken(cc->slot); + c->slot = c->token->slot; + } + cc->nssCertificate = c; return c; +loser: + nssArena_Destroy(arena); + return NULL; } static CK_TRUST @@ -545,7 +590,8 @@ get_cert_type(NSSCertificateType nssType) case NSSCertificateType_PKIX: return CKC_X_509; default: - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; /* Not really! CK_INVALID_HANDLE is not a + * type CK_CERTIFICATE_TYPE */ } } @@ -591,7 +637,7 @@ nssTrustDomain_AddTempCertToPerm /* This is a hack, ignoring the 4.0 token ordering scheme */ token = STAN_GetInternalToken(); c->handle = nssToken_ImportObject(token, NULL, cert_template, ctsize); - if (c->handle == CK_INVALID_KEY) { + if (c->handle == CK_INVALID_HANDLE) { return PR_FAILURE; } c->token = token; diff --git a/security/nss/lib/pki/pkinss3hack.h b/security/nss/lib/pki/pki3hack.h index c9c58e283..c9c58e283 100644 --- a/security/nss/lib/pki/pkinss3hack.h +++ b/security/nss/lib/pki/pki3hack.h diff --git a/security/nss/lib/pki/tdcache.c b/security/nss/lib/pki/tdcache.c index f164bd609..6c01694dc 100644 --- a/security/nss/lib/pki/tdcache.c +++ b/security/nss/lib/pki/tdcache.c @@ -398,7 +398,7 @@ collect_subject_certs ) { NSSCertificate *c; - NSSCertificate **rvArray; + NSSCertificate **rvArray = NULL; PRUint32 count; if (rvCertListOpt) { nssListIterator *iter = nssList_CreateIterator(subjectList); @@ -409,15 +409,13 @@ collect_subject_certs } nssListIterator_Finish(iter); nssListIterator_Destroy(iter); - return (NSSCertificate **)NULL; } else { count = nssList_Count(subjectList); rvArray = nss_ZNEWARRAY(NULL, NSSCertificate *, count); if (!rvArray) return (NSSCertificate **)NULL; nssList_GetArray(subjectList, (void **)rvArray, count); - return rvArray; } - return (NSSCertificate **)NULL; + return rvArray; } /* diff --git a/security/nss/lib/pki/trustdomain.c b/security/nss/lib/pki/trustdomain.c index 6f3a23dd9..91eeb24de 100644 --- a/security/nss/lib/pki/trustdomain.c +++ b/security/nss/lib/pki/trustdomain.c @@ -393,11 +393,8 @@ get_best_cert(NSSCertificate *c, void *arg) } /* either they are both valid at time, or neither valid; take the newer */ /* XXX later -- defer to policies */ - if (bestdc->isNewerThan(bestdc, dc)) { - return PR_SUCCESS; - } else { + if (!bestdc->isNewerThan(bestdc, dc)) { best->cert = c; - return PR_SUCCESS; } /* policies */ return PR_SUCCESS; @@ -721,7 +718,7 @@ NSSTrustDomain_FindCertificateByIssuerAndSerialNumber { object = nssToken_FindObjectByTemplate(tok, NULL, cert_template, ctsize); - if (object != CK_INVALID_KEY) { + if (object != CK_INVALID_HANDLE) { /* Could not find cert, so create it */ rvCert = nssCertificate_CreateFromHandle(NULL, object, NULL, tok->slot); @@ -864,7 +861,7 @@ NSSTrustDomain_FindCertificateByEncodedCertificate { object = nssToken_FindObjectByTemplate(tok, NULL, cert_template, ctsize); - if (object != CK_INVALID_KEY) { + if (object != CK_INVALID_HANDLE) { /* Could not find cert, so create it */ rvCert = nssCertificate_CreateFromHandle(NULL, object, NULL, tok->slot); diff --git a/security/nss/lib/pki1/Makefile b/security/nss/lib/pki1/Makefile index 72e97c17c..3207c6bbf 100644 --- a/security/nss/lib/pki1/Makefile +++ b/security/nss/lib/pki1/Makefile @@ -38,8 +38,10 @@ include config.mk include $(CORE_DEPTH)/coreconf/rules.mk # Generate oiddata.h and oiddata.c. -generate: - perl oidgen.perl < oids.txt +$(OBJDIR)/oiddata.c $(OBJDIR)/oiddata.h: oidgen.perl oids.txt + @$(MAKE_OBJDIR) + rm -f $(OBJDIR)/oiddata.c $(OBJDIR)/oiddata.h + perl oidgen.perl $(OBJDIR)/oiddata.c $(OBJDIR)/oiddata.h oids.txt -export:: generate private_export +export:: private_export diff --git a/security/nss/lib/pki1/atav.c b/security/nss/lib/pki1/atav.c index 1f8d056a3..5d87efaf6 100644 --- a/security/nss/lib/pki1/atav.c +++ b/security/nss/lib/pki1/atav.c @@ -961,13 +961,13 @@ nss_atav_utf8_string_is_hex return PR_TRUE; } -static PRUint8 +static NSSUTF8 nss_atav_fromhex ( - PRUint8 *d + NSSUTF8 *d ) { - PRUint8 rv; + NSSUTF8 rv; if( d[0] <= '9' ) { rv = (d[0] - '0') * 16; @@ -1105,8 +1105,8 @@ nssATAV_CreateFromUTF8 if( '#' == *value ) { /* XXX fgmr.. was it '#'? or backslash? */ PRUint32 size; PRUint32 len; - PRUint8 *c; - PRUint8 *d; + NSSUTF8 *c; + NSSUTF8 *d; PRStatus status; /* It's in hex */ @@ -1717,6 +1717,9 @@ nssATAV_Compare break; case nssStringType_BMPString: break; + case nssStringType_GeneralString: + /* what to do here? */ + break; case nssStringType_UTF8String: break; case nssStringType_PHGString: diff --git a/security/nss/lib/pki1/manifest.mn b/security/nss/lib/pki1/manifest.mn index e99df9a11..a5b4ef80f 100644 --- a/security/nss/lib/pki1/manifest.mn +++ b/security/nss/lib/pki1/manifest.mn @@ -35,7 +35,7 @@ MANIFEST_CVS_ID = "@(#) $RCSfile$ $Revision$ $Date$ $Name$" CORE_DEPTH = ../../.. PRIVATE_EXPORTS = \ - oiddata.h \ + $(OBJDIR)/oiddata.h \ pki1.h \ pki1t.h \ $(NULL) @@ -47,6 +47,9 @@ EXPORTS = \ MODULE = security +BUILT_CSRCS = oiddata.c \ + $(NULL) + CSRCS = \ atav.c \ genname.c \ diff --git a/security/nss/lib/pki1/oidgen.perl b/security/nss/lib/pki1/oidgen.perl index 959e3cbaf..2d644481e 100755 --- a/security/nss/lib/pki1/oidgen.perl +++ b/security/nss/lib/pki1/oidgen.perl @@ -32,7 +32,8 @@ # GPL. # $cvs_id = '@(#) $RCSfile$ $Revision$ $Date$ $Name$'; - +$cfile = shift; +$hfile = shift; $count = -1; while(<>) { s/^((?:[^"#]+|"[^"]*")*)(\s*#.*$)/$1/; @@ -60,7 +61,8 @@ while(<>) { } # dodump(); -doprint(); + +doprint($cfile,$hfile); sub dodump { for( $i = 0; $i <= $count; $i++ ) { @@ -73,8 +75,8 @@ for( $i = 0; $i <= $count; $i++ ) { } sub doprint { -open(CFILE, ">oiddata.c") || die "Can't open oiddata.c: $!"; -open(HFILE, ">oiddata.h") || die "Can't open oiddata.h: $!"; +open(CFILE, "> $cfile") || die "Can't open $cfile: $!"; +open(HFILE, "> $hfile") || die "Can't open $hfile: $!"; print CFILE <<EOD /* THIS IS A GENERATED FILE */ diff --git a/security/nss/lib/smime/cmscipher.c b/security/nss/lib/smime/cmscipher.c index 27e5668aa..8ad4efcc5 100644 --- a/security/nss/lib/smime/cmscipher.c +++ b/security/nss/lib/smime/cmscipher.c @@ -43,7 +43,7 @@ #include "secitem.h" #include "pk11func.h" #include "secerr.h" -#include "secpkcs5.h" +/*#include "secpkcs5.h" */ /* * ------------------------------------------------------------------- diff --git a/security/nss/lib/smime/cmsenvdata.c b/security/nss/lib/smime/cmsenvdata.c index e64c829a6..fdd3d821a 100644 --- a/security/nss/lib/smime/cmsenvdata.c +++ b/security/nss/lib/smime/cmsenvdata.c @@ -46,7 +46,7 @@ #include "secoid.h" #include "pk11func.h" #include "secerr.h" -#include "secpkcs5.h" +/*#include "secpkcs5.h" */ /* * NSS_CMSEnvelopedData_Create - create an enveloped data message diff --git a/security/nss/lib/smime/cmssigdata.c b/security/nss/lib/smime/cmssigdata.c index 34c36284f..1af54fc9b 100644 --- a/security/nss/lib/smime/cmssigdata.c +++ b/security/nss/lib/smime/cmssigdata.c @@ -40,7 +40,7 @@ #include "cmslocal.h" #include "cert.h" -#include "cdbhdl.h" +/*#include "cdbhdl.h"*/ #include "secasn1.h" #include "secitem.h" #include "secoid.h" diff --git a/security/nss/lib/softoken/alghmac.c b/security/nss/lib/softoken/alghmac.c index aef81a76b..60abd73d0 100644 --- a/security/nss/lib/softoken/alghmac.c +++ b/security/nss/lib/softoken/alghmac.c @@ -31,10 +31,10 @@ * GPL. */ -#include "alghmac.h" #include "sechash.h" -#include "secoid.h" #include "secport.h" +#include "alghmac.h" +/*#include "secoid.h"*/ #define HMAC_PAD_SIZE 64 @@ -57,8 +57,7 @@ HMAC_Destroy(HMACContext *cx) } HMACContext * -HMAC_Create(SECOidTag hash_alg, - const unsigned char *secret, +HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret, unsigned int secret_len) { HMACContext *cx; @@ -68,20 +67,7 @@ HMAC_Create(SECOidTag hash_alg, cx = (HMACContext*)PORT_ZAlloc(sizeof(HMACContext)); if (cx == NULL) return NULL; - - switch (hash_alg) { - case SEC_OID_MD5: - cx->hashobj = &SECRawHashObjects[HASH_AlgMD5]; - break; - case SEC_OID_MD2: - cx->hashobj = &SECRawHashObjects[HASH_AlgMD2]; - break; - case SEC_OID_SHA1: - cx->hashobj = &SECRawHashObjects[HASH_AlgSHA1]; - break; - default: - goto loser; - } + cx->hashobj = hash_obj; cx->hash = cx->hashobj->create(); if (cx->hash == NULL) diff --git a/security/nss/lib/softoken/alghmac.h b/security/nss/lib/softoken/alghmac.h index 10d598267..3cb1a74dc 100644 --- a/security/nss/lib/softoken/alghmac.h +++ b/security/nss/lib/softoken/alghmac.h @@ -34,8 +34,6 @@ #ifndef _ALGHMAC_H_ #define _ALGHMAC_H_ -#include "secoid.h" - typedef struct HMACContextStr HMACContext; SEC_BEGIN_PROTOS @@ -53,7 +51,7 @@ HMAC_Destroy(HMACContext *cx); * NULL is returned if an error occurs or the secret is > 64 bytes. */ extern HMACContext * -HMAC_Create(SECOidTag hash_alg, const unsigned char *secret, +HMAC_Create(const SECHashObject *hashObj, const unsigned char *secret, unsigned int secret_len); /* reset HMAC for a fresh round */ diff --git a/security/nss/lib/certdb/cdbhdl.h b/security/nss/lib/softoken/cdbhdl.h index c195eb308..b606e9876 100644 --- a/security/nss/lib/certdb/cdbhdl.h +++ b/security/nss/lib/softoken/cdbhdl.h @@ -41,16 +41,13 @@ #include "nspr.h" #include "mcom_db.h" -#include "certt.h" +#include "pcertt.h" /* * Handle structure for open certificate databases */ -struct CERTCertDBHandleStr { +struct NSSLOWCERTCertDBHandleStr { DB *permCertDB; - DB *tempCertDB; - void *spkDigestInfo; - CERTStatusConfig *statusConfig; PZMonitor *dbMon; }; diff --git a/security/nss/lib/softoken/config.mk b/security/nss/lib/softoken/config.mk index 0a00dc61e..702802b8c 100644 --- a/security/nss/lib/softoken/config.mk +++ b/security/nss/lib/softoken/config.mk @@ -36,8 +36,81 @@ # are specifed as dependencies within rules.mk. # -TARGETS = $(LIBRARY) -SHARED_LIBRARY = -IMPORT_LIBRARY = -PROGRAM = +#TARGETS = $(LIBRARY) +#SHARED_LIBRARY = +#IMPORT_LIBRARY = +#PROGRAM = +# can't do this in manifest.mn because OS_ARCH isn't defined there. +ifeq ($(OS_ARCH), WINNT) + +# don't want the 32 in the shared library name +SHARED_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).dll +IMPORT_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).lib + +RES = $(OBJDIR)/$(LIBRARY_NAME).res +RESNAME = $(LIBRARY_NAME).rc + +# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS) +CRYPTOLIB=$(DIST)/lib/freebl.lib +CRYPTODIR=../freebl +ifdef MOZILLA_SECURITY_BUILD + CRYPTOLIB=$(DIST)/lib/crypto.lib + CRYPTODIR=../crypto +endif + +EXTRA_SHARED_LIBRARY_LIBS += \ + $(CRYPTOLIB) \ + $(DIST)/lib/secutil.lib \ + $(NULL) + +EXTRA_LIBS += \ + $(DIST)/lib/dbm.lib \ + $(NULL) + +ifdef MOZILLA_BSAFE_BUILD + EXTRA_LIBS+=$(DIST)/lib/bsafe$(BSAFEVER).lib +endif + +EXTRA_SHARED_LIBS += \ + $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4.lib \ + $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4.lib \ + $(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.lib \ + $(NULL) +else + +# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS) +CRYPTOLIB=$(DIST)/lib/libfreebl.$(LIB_SUFFIX) +CRYPTODIR=../freebl +ifdef MOZILLA_SECURITY_BUILD + CRYPTOLIB=$(DIST)/lib/libcrypto.$(LIB_SUFFIX) + CRYPTODIR=../crypto +endif +EXTRA_LIBS += \ + $(CRYPTOLIB) \ + $(DIST)/lib/libsecutil.$(LIB_SUFFIX) \ + $(DIST)/lib/libdbm.$(LIB_SUFFIX) \ + $(NULL) +ifdef MOZILLA_BSAFE_BUILD + EXTRA_LIBS+=$(DIST)/lib/libbsafe.$(LIB_SUFFIX) +endif + +# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS) +# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX. +EXTRA_SHARED_LIBS += \ + -L$(DIST)/lib/ \ + -lplc4 \ + -lplds4 \ + -lnspr4 \ + $(NULL) +endif + +ifeq ($(OS_ARCH),SunOS) +ifndef USE_64 +ifeq ($(CPU_ARCH),sparc) +# The -R '$ORIGIN' linker option instructs libnss3.so to search for its +# dependencies (libfreebl_*.so) in the same directory where it resides. +MKSHLIB += -R '$$ORIGIN' +endif +endif +endif diff --git a/security/nss/lib/softoken/dbinit.c b/security/nss/lib/softoken/dbinit.c index f31eb514b..bae037a4a 100644 --- a/security/nss/lib/softoken/dbinit.c +++ b/security/nss/lib/softoken/dbinit.c @@ -40,22 +40,15 @@ #include "prinit.h" #include "prprf.h" #include "prmem.h" -#include "cert.h" -#include "keylow.h" -#include "keydbt.h" -#include "ssl.h" -#include "sslproto.h" -#include "secmod.h" -#include "secmodi.h" -#include "secoid.h" -#include "nss.h" +#include "pcertt.h" +#include "lowkeyi.h" +#include "pcert.h" +/*#include "secmodi.h" */ #include "secrng.h" #include "cdbhdl.h" -#include "pk11func.h" +/*#include "pk11func.h" */ #include "pkcs11i.h" -static char *secmodname = NULL; - static char * pk11_certdb_name_cb(void *arg, int dbVersion) { @@ -109,77 +102,61 @@ pk11_keydb_name_cb(void *arg, int dbVersion) #define CKR_KEYDB_FAILED CKR_DEVICE_ERROR static CK_RV -pk11_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly) +pk11_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly, + NSSLOWCERTCertDBHandle **certdbPtr) { - CERTCertDBHandle *certdb; - CK_RV crv = CKR_OK; + NSSLOWCERTCertDBHandle *certdb; + CK_RV crv = CKR_CERTDB_FAILED; SECStatus rv; char * name = NULL; - certdb = CERT_GetDefaultCertDB(); - if (certdb) - return CKR_OK; /* idempotency */ + if (prefix == NULL) { + prefix = ""; + } name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix); if (name == NULL) goto loser; - certdb = (CERTCertDBHandle*)PORT_ZAlloc(sizeof(CERTCertDBHandle)); + certdb = (NSSLOWCERTCertDBHandle*)PORT_ZAlloc(sizeof(NSSLOWCERTCertDBHandle)); if (certdb == NULL) goto loser; /* fix when we get the DB in */ - rv = CERT_OpenCertDB(certdb, readOnly, pk11_certdb_name_cb, (void *)name); - if (rv == SECSuccess) - CERT_SetDefaultCertDB(certdb); - else { - PR_Free(certdb); -loser: - crv = CKR_CERTDB_FAILED; + rv = nsslowcert_OpenCertDB(certdb, readOnly, + pk11_certdb_name_cb, (void *)name, PR_FALSE); + if (rv == SECSuccess) { + crv = CKR_OK; + *certdbPtr = certdb; + certdb = NULL; } +loser: + if (certdb) PR_Free(certdb); if (name) PORT_Free(name); return crv; } static CK_RV -pk11_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly) +pk11_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly, + NSSLOWKEYDBHandle **keydbPtr) { - SECKEYKeyDBHandle *keydb; + NSSLOWKEYDBHandle *keydb; char * name = NULL; - keydb = SECKEY_GetDefaultKeyDB(); - if (keydb) - return SECSuccess; + if (prefix == NULL) { + prefix = ""; + } name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix); if (name == NULL) return SECFailure; - keydb = SECKEY_OpenKeyDB(readOnly, pk11_keydb_name_cb, (void *)name); + keydb = nsslowkey_OpenKeyDB(readOnly, pk11_keydb_name_cb, (void *)name); + PORT_Free(name); if (keydb == NULL) return CKR_KEYDB_FAILED; - SECKEY_SetDefaultKeyDB(keydb); - PORT_Free(name); + *keydbPtr = keydb; return CKR_OK; } -static CERTCertDBHandle certhandle = { 0 }; - -static PRBool isInitialized = PR_FALSE; - -static CK_RV -pk11_OpenVolatileCertDB() { - SECStatus rv = SECSuccess; - /* now we want to verify the signature */ - /* Initialize the cert code */ - rv = CERT_OpenVolatileCertDB(&certhandle); - if (rv != SECSuccess) { - return CKR_DEVICE_ERROR; - } - CERT_SetDefaultCertDB(&certhandle); - return CKR_OK; -} - -/* forward declare so that a failure in the init case can shutdown */ -void pk11_Shutdown(void); /* * OK there are now lots of options here, lets go through them all: @@ -200,71 +177,53 @@ void pk11_Shutdown(void); */ CK_RV pk11_DBInit(const char *configdir, const char *certPrefix, - const char *keyPrefix, - const char *secmodName, PRBool readOnly, PRBool noCertDB, - PRBool noModDB, PRBool forceOpen) + const char *keyPrefix, PRBool readOnly, + PRBool noCertDB, PRBool noKeyDB, PRBool forceOpen, + NSSLOWCERTCertDBHandle **certdbPtr, NSSLOWKEYDBHandle **keydbPtr) { - SECStatus rv = SECFailure; CK_RV crv = CKR_OK; - if( isInitialized ) { - return CKR_OK; - } - - rv = RNG_RNGInit(); /* initialize random number generator */ - if (rv != SECSuccess) { - crv = CKR_DEVICE_ERROR; - goto loser; - } - RNG_SystemInfoForRNG(); - if (noCertDB) { - crv = pk11_OpenVolatileCertDB(); - if (crv != CKR_OK) { - goto loser; - } - } else { - crv = pk11_OpenCertDB(configdir, certPrefix, readOnly); + if (!noCertDB) { + crv = pk11_OpenCertDB(configdir, certPrefix, readOnly, certdbPtr); if (crv != CKR_OK) { if (!forceOpen) goto loser; - crv = pk11_OpenVolatileCertDB(); - if (crv != CKR_OK) { - goto loser; - } + crv = CKR_OK; } + } + if (!noKeyDB) { - crv = pk11_OpenKeyDB(configdir, keyPrefix, readOnly); + crv = pk11_OpenKeyDB(configdir, keyPrefix, readOnly, keydbPtr); if (crv != CKR_OK) { if (!forceOpen) goto loser; + crv = CKR_OK; } } - isInitialized = PR_TRUE; loser: - if (crv != CKR_OK) { - pk11_Shutdown(); - } return crv; } +#ifdef notdef void pk11_Shutdown(void) { - CERTCertDBHandle *certHandle; - SECKEYKeyDBHandle *keyHandle; + NSSLOWCERTCertDBHandle *certHandle; + NSSLOWKEYDBHandle *keyHandle; PR_FREEIF(secmodname); - certHandle = CERT_GetDefaultCertDB(); + certHandle = nsslowcert_GetDefaultCertDB(); if (certHandle) - CERT_ClosePermCertDB(certHandle); - CERT_SetDefaultCertDB(NULL); + nsslowcert_ClosePermCertDB(certHandle); + nsslowcert_SetDefaultCertDB(NULL); - keyHandle = SECKEY_GetDefaultKeyDB(); + keyHandle = nsslowkey_GetDefaultKeyDB(); if (keyHandle) - SECKEY_CloseKeyDB(keyHandle); - SECKEY_SetDefaultKeyDB(NULL); + nsslowkey_CloseKeyDB(keyHandle); + nsslowkey_SetDefaultKeyDB(NULL); isInitialized = PR_FALSE; } +#endif diff --git a/security/nss/lib/softoken/fipstest.c b/security/nss/lib/softoken/fipstest.c index f11448356..15e490090 100644 --- a/security/nss/lib/softoken/fipstest.c +++ b/security/nss/lib/softoken/fipstest.c @@ -39,7 +39,7 @@ /* DES-CBC, DES3-ECB, DES3-CBC, RSA */ /* and DSA. */ #include "seccomon.h" /* Required for RSA and DSA. */ -#include "keylow.h" /* Required for RSA and DSA. */ +#include "lowkeyi.h" /* Required for RSA and DSA. */ #include "pkcs11.h" /* Required for PKCS #11. */ #include "secerr.h" @@ -792,13 +792,13 @@ pk11_fips_RSA_PowerUpSelfTest( void ) PLArenaPool * rsa_public_arena; PLArenaPool * rsa_private_arena; #endif - SECKEYLowPublicKey * rsa_public_key; - SECKEYLowPrivateKey * rsa_private_key; + NSSLOWKEYPublicKey * rsa_public_key; + NSSLOWKEYPrivateKey * rsa_private_key; unsigned int rsa_bytes_signed; SECStatus rsa_status; - SECKEYLowPublicKey low_public_key = { NULL, lowRSAKey, }; - SECKEYLowPrivateKey low_private_key = { NULL, lowRSAKey, }; + NSSLOWKEYPublicKey low_public_key = { NULL, NSSLOWKEYRSAKey, }; + NSSLOWKEYPrivateKey low_private_key = { NULL, NSSLOWKEYRSAKey, }; PRUint8 rsa_computed_ciphertext[FIPS_RSA_ENCRYPT_LENGTH]; PRUint8 rsa_computed_plaintext[FIPS_RSA_DECRYPT_LENGTH]; PRUint8 rsa_computed_signature[FIPS_RSA_SIGNATURE_LENGTH]; @@ -894,16 +894,16 @@ pk11_fips_RSA_PowerUpSelfTest( void ) goto rsa_loser; /* Dispose of all RSA key material. */ - SECKEY_LowDestroyPublicKey( rsa_public_key ); - SECKEY_LowDestroyPrivateKey( rsa_private_key ); + nsslowkey_DestroyPublicKey( rsa_public_key ); + nsslowkey_DestroyPrivateKey( rsa_private_key ); return( CKR_OK ); rsa_loser: - SECKEY_LowDestroyPublicKey( rsa_public_key ); - SECKEY_LowDestroyPrivateKey( rsa_private_key ); + nsslowkey_DestroyPublicKey( rsa_public_key ); + nsslowkey_DestroyPrivateKey( rsa_private_key ); return( CKR_DEVICE_ERROR ); } diff --git a/security/nss/lib/softoken/fipstokn.c b/security/nss/lib/softoken/fipstokn.c index e72a9965a..b547a93e4 100644 --- a/security/nss/lib/softoken/fipstokn.c +++ b/security/nss/lib/softoken/fipstokn.c @@ -48,32 +48,11 @@ */ #include "seccomon.h" #include "softoken.h" -#include "key.h" +#include "lowkeyi.h" +#include "pcert.h" #include "pkcs11.h" #include "pkcs11i.h" -/* The next two strings must be exactly 64 characters long, with the - first 32 characters meaningful */ -static char *slotDescription = - "Netscape Internal FIPS-140-1 Cryptographic Services "; -static char *privSlotDescription = - "Netscape FIPS-140-1 User Private Key Services "; - - -/* - * Configuration utils - */ -void -PK11_ConfigureFIPS(char *slotdes, char *pslotdes) -{ - if (slotdes && (PORT_Strlen(slotdes) == 65)) { - slotDescription = slotdes; - } - if (pslotdes && (PORT_Strlen(pslotdes) == 65)) { - privSlotDescription = pslotdes; - } - return; -} /* * ******************** Password Utilities ******************************* @@ -170,30 +149,22 @@ CK_RV FC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) { /* FC_Initialize initializes the PKCS #11 library. */ CK_RV FC_Initialize(CK_VOID_PTR pReserved) { - CK_RV rv; - static PRBool init= PR_FALSE; - - - rv = PK11_LowInitialize(pReserved); + CK_RV crv; - if (rv == CKR_OK && !init) { - init = PR_TRUE; - rv = PK11_SlotInit(FIPS_SLOT_ID,PR_TRUE); - /* fall through to check below */ - } + crv = nsc_CommonInitialize(pReserved, PR_TRUE); /* not an 'else' rv can be set by either PK11_LowInit or PK11_SlotInit*/ - if (rv != CKR_OK) { + if (crv != CKR_OK) { fatalError = PR_TRUE; - return rv; + return crv; } fatalError = PR_FALSE; /* any error has been reset */ - rv = pk11_fipsPowerUpSelfTest(); - if (rv != CKR_OK) { + crv = pk11_fipsPowerUpSelfTest(); + if (crv != CKR_OK) { fatalError = PR_TRUE; - return rv; + return crv; } return CKR_OK; @@ -214,11 +185,7 @@ CK_RV FC_GetInfo(CK_INFO_PTR pInfo) { /* FC_GetSlotList obtains a list of slots in the system. */ CK_RV FC_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) { - *pulCount = 1; - if (pSlotList != NULL) { - pSlotList[0] = FIPS_SLOT_ID; - } - return CKR_OK; + return NSC_GetSlotList(tokenPresent,pSlotList,pulCount); } /* FC_GetSlotInfo obtains information about a particular slot in the system. */ @@ -226,16 +193,11 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV crv; - if (slotID != FIPS_SLOT_ID) return CKR_SLOT_ID_INVALID; - - /* Use NETSCAPE_SLOT_ID as a basis so that we get Library version number, - * not key_DB version number */ - crv = NSC_GetSlotInfo(NETSCAPE_SLOT_ID,pInfo); + crv = NSC_GetSlotInfo(slotID,pInfo); if (crv != CKR_OK) { return crv; } - PORT_Memcpy(pInfo->slotDescription,slotDescription,64); return CKR_OK; } @@ -244,13 +206,8 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) { CK_RV crv; - if (slotID != FIPS_SLOT_ID) return CKR_SLOT_ID_INVALID; - - /* use PRIVATE_KEY_SLOT_ID so we get the correct - Authentication information */ - crv = NSC_GetTokenInfo(PRIVATE_KEY_SLOT_ID,pInfo); + crv = NSC_GetTokenInfo(slotID,pInfo); pInfo->flags |= CKF_RNG | CKF_LOGIN_REQUIRED; - /* yes virginia, FIPS can do random number generation:) */ return crv; } @@ -261,9 +218,9 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pusCount) { PK11_FIPSFATALCHECK(); - if (slotID != FIPS_SLOT_ID) return CKR_SLOT_ID_INVALID; + if (slotID == FIPS_SLOT_ID) slotID = NETSCAPE_SLOT_ID; /* FIPS Slot supports all functions */ - return NSC_GetMechanismList(NETSCAPE_SLOT_ID,pMechanismList,pusCount); + return NSC_GetMechanismList(slotID,pMechanismList,pusCount); } @@ -272,9 +229,9 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { PK11_FIPSFATALCHECK(); - if (slotID != FIPS_SLOT_ID) return CKR_SLOT_ID_INVALID; + if (slotID == FIPS_SLOT_ID) slotID = NETSCAPE_SLOT_ID; /* FIPS Slot supports all functions */ - return NSC_GetMechanismInfo(NETSCAPE_SLOT_ID,type,pInfo); + return NSC_GetMechanismInfo(slotID,type,pInfo); } diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c index f13ca5374..cc00014f7 100644 --- a/security/nss/lib/softoken/keydb.c +++ b/security/nss/lib/softoken/keydb.c @@ -35,9 +35,7 @@ * $Id$ */ -#include "keylow.h" -#include "keydbt.h" -#include "keytboth.h" +#include "lowkeyi.h" #include "seccomon.h" #include "sechash.h" #include "secder.h" @@ -45,12 +43,12 @@ #include "secoid.h" #include "blapi.h" #include "secitem.h" -#include "cert.h" +#include "pcert.h" #include "mcom_db.h" -#include "secpkcs5.h" +#include "lowpbe.h" #include "secerr.h" -#include "private.h" +#include "keydbi.h" /* * Record keys for keydb @@ -66,55 +64,36 @@ #define SALT_LENGTH 16 /* ASN1 Templates for new decoder/encoder */ -/* - * Attribute value for PKCS8 entries (static?) - */ -const SEC_ASN1Template SECKEY_AttributeTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(SECKEYAttribute) }, - { SEC_ASN1_OBJECT_ID, offsetof(SECKEYAttribute, attrType) }, - { SEC_ASN1_SET_OF, offsetof(SECKEYAttribute, attrValue), - SEC_AnyTemplate }, - { 0 } -}; - -const SEC_ASN1Template SECKEY_SetOfAttributeTemplate[] = { - { SEC_ASN1_SET_OF, 0, SECKEY_AttributeTemplate }, -}; - -const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[] = { +const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = { { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(PrivateKeyInfo) }, + 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) }, { SEC_ASN1_INTEGER, - offsetof(PrivateKeyInfo,version) }, + offsetof(NSSLOWKEYPrivateKeyInfo,version) }, { SEC_ASN1_INLINE, - offsetof(PrivateKeyInfo,algorithm), + offsetof(NSSLOWKEYPrivateKeyInfo,algorithm), SECOID_AlgorithmIDTemplate }, { SEC_ASN1_OCTET_STRING, - offsetof(PrivateKeyInfo,privateKey) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(PrivateKeyInfo,attributes), - SECKEY_SetOfAttributeTemplate }, + offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) }, { 0 } }; -const SEC_ASN1Template SECKEY_PointerToPrivateKeyInfoTemplate[] = { - { SEC_ASN1_POINTER, 0, SECKEY_PrivateKeyInfoTemplate } +const SEC_ASN1Template nsslowkey_PointerToPrivateKeyInfoTemplate[] = { + { SEC_ASN1_POINTER, 0, nsslowkey_PrivateKeyInfoTemplate } }; -const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = { +const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[] = { { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(EncryptedPrivateKeyInfo) }, + 0, NULL, sizeof(NSSLOWKEYEncryptedPrivateKeyInfo) }, { SEC_ASN1_INLINE, - offsetof(EncryptedPrivateKeyInfo,algorithm), + offsetof(NSSLOWKEYEncryptedPrivateKeyInfo,algorithm), SECOID_AlgorithmIDTemplate }, { SEC_ASN1_OCTET_STRING, - offsetof(EncryptedPrivateKeyInfo,encryptedData) }, + offsetof(NSSLOWKEYEncryptedPrivateKeyInfo,encryptedData) }, { 0 } }; -const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[] = { - { SEC_ASN1_POINTER, 0, SECKEY_EncryptedPrivateKeyInfoTemplate } +const SEC_ASN1Template nsslowkey_PointerToEncryptedPrivateKeyInfoTemplate[] = { + { SEC_ASN1_POINTER, 0, nsslowkey_EncryptedPrivateKeyInfoTemplate } }; @@ -126,13 +105,13 @@ static SECOidTag defaultKeyDBAlg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_C * Default algorithm for encrypting data in the key database */ SECOidTag -SECKEY_GetDefaultKeyDBAlg(void) +nsslowkey_GetDefaultKeyDBAlg(void) { return(defaultKeyDBAlg); } void -SECKEY_SetDefaultKeyDBAlg(SECOidTag alg) +nsslowkey_SetDefaultKeyDBAlg(SECOidTag alg) { defaultKeyDBAlg = alg; @@ -140,7 +119,7 @@ SECKEY_SetDefaultKeyDBAlg(SECOidTag alg) } static void -sec_destroy_dbkey(SECKEYDBKey *dbkey) +sec_destroy_dbkey(NSSLOWKEYDBKey *dbkey) { if ( dbkey && dbkey->arena ) { PORT_FreeArena(dbkey->arena, PR_FALSE); @@ -170,7 +149,7 @@ free_dbt(DBT *dbt) * ... encrypted-key-data */ static DBT * -encode_dbkey(SECKEYDBKey *dbkey) +encode_dbkey(NSSLOWKEYDBKey *dbkey) { DBT *bufitem = NULL; unsigned char *buf; @@ -202,7 +181,7 @@ encode_dbkey(SECKEYDBKey *dbkey) buf = (unsigned char *)bufitem->data; /* set version number */ - buf[0] = PRIVATE_KEY_DB_FILE_VERSION; + buf[0] = NSSLOWKEY_DB_FILE_VERSION; /* set length of salt */ PORT_Assert(dbkey->salt.len < 256); @@ -232,10 +211,10 @@ loser: return(NULL); } -static SECKEYDBKey * +static NSSLOWKEYDBKey * decode_dbkey(DBT *bufitem, int expectedVersion) { - SECKEYDBKey *dbkey; + NSSLOWKEYDBKey *dbkey; PLArenaPool *arena = NULL; unsigned char *buf; int version; @@ -256,7 +235,7 @@ decode_dbkey(DBT *bufitem, int expectedVersion) goto loser; } - dbkey = (SECKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYDBKey)); + dbkey = (NSSLOWKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYDBKey)); if ( dbkey == NULL ) { goto loser; } @@ -274,7 +253,7 @@ decode_dbkey(DBT *bufitem, int expectedVersion) saltoff = 2; keyoff = 2 + dbkey->salt.len; - if ( expectedVersion == PRIVATE_KEY_DB_FILE_VERSION ) { + if ( expectedVersion == NSSLOWKEY_DB_FILE_VERSION ) { nnlen = buf[2]; if ( nnlen ) { dbkey->nickname = (char *)PORT_ArenaZAlloc(arena, nnlen + 1); @@ -307,10 +286,10 @@ loser: return(NULL); } -static SECKEYDBKey * -get_dbkey(SECKEYKeyDBHandle *handle, DBT *index) +static NSSLOWKEYDBKey * +get_dbkey(NSSLOWKEYDBHandle *handle, DBT *index) { - SECKEYDBKey *dbkey; + NSSLOWKEYDBKey *dbkey; DBT entry; int ret; @@ -323,13 +302,13 @@ get_dbkey(SECKEYKeyDBHandle *handle, DBT *index) /* set up dbkey struct */ - dbkey = decode_dbkey(&entry, PRIVATE_KEY_DB_FILE_VERSION); + dbkey = decode_dbkey(&entry, NSSLOWKEY_DB_FILE_VERSION); return(dbkey); } static SECStatus -put_dbkey(SECKEYKeyDBHandle *handle, DBT *index, SECKEYDBKey *dbkey, PRBool update) +put_dbkey(NSSLOWKEYDBHandle *handle, DBT *index, NSSLOWKEYDBKey *dbkey, PRBool update) { DBT *keydata = NULL; int status; @@ -369,7 +348,7 @@ loser: } SECStatus -SECKEY_TraverseKeys(SECKEYKeyDBHandle *handle, +nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle, SECStatus (* keyfunc)(DBT *k, DBT *d, void *pdata), void *udata ) { @@ -480,7 +459,7 @@ decodeKeyDBGlobalSalt(DBT *saltData) } static SECItem * -GetKeyDBGlobalSalt(SECKEYKeyDBHandle *handle) +GetKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle) { DBT saltKey; DBT saltData; @@ -498,14 +477,14 @@ GetKeyDBGlobalSalt(SECKEYKeyDBHandle *handle) } static SECStatus -makeGlobalVersion(SECKEYKeyDBHandle *handle) +makeGlobalVersion(NSSLOWKEYDBHandle *handle) { unsigned char version; DBT versionData; DBT versionKey; int status; - version = PRIVATE_KEY_DB_FILE_VERSION; + version = NSSLOWKEY_DB_FILE_VERSION; versionData.data = &version; versionData.size = 1; versionKey.data = VERSION_STRING; @@ -522,7 +501,7 @@ makeGlobalVersion(SECKEYKeyDBHandle *handle) static SECStatus -makeGlobalSalt(SECKEYKeyDBHandle *handle) +makeGlobalSalt(NSSLOWKEYDBHandle *handle) { DBT saltKey; DBT saltData; @@ -551,17 +530,241 @@ keyDBFilenameCallback(void *arg, int dbVersion) return(PORT_Strdup((char *)arg)); } -SECKEYKeyDBHandle * -SECKEY_OpenKeyDBFilename(char *dbname, PRBool readOnly) +NSSLOWKEYDBHandle * +nsslowkey_OpenKeyDBFilename(char *dbname, PRBool readOnly) { - return(SECKEY_OpenKeyDB(readOnly, keyDBFilenameCallback, + return(nsslowkey_OpenKeyDB(readOnly, keyDBFilenameCallback, (void *)dbname)); } -SECKEYKeyDBHandle * -SECKEY_OpenKeyDB(PRBool readOnly, SECKEYDBNameFunc namecb, void *cbarg) +static SECStatus +ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, + SECItem *oldpwitem, SECItem *newpwitem, + SECOidTag new_algorithm); +/* + * Second pass of updating the key db. This time we have a password. + */ +static SECStatus +nsslowkey_UpdateKeyDBPass2(NSSLOWKEYDBHandle *handle, SECItem *pwitem) +{ + SECStatus rv; + + rv = ChangeKeyDBPasswordAlg(handle, pwitem, pwitem, + nsslowkey_GetDefaultKeyDBAlg()); + + return(rv); +} + +static SECStatus +encodePWCheckEntry(PLArenaPool *arena, SECItem *entry, SECOidTag alg, + SECItem *encCheck); +/* + * currently updates key database from v2 to v3 + */ +static SECStatus +nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) +{ + SECStatus rv; + DBT versionKey; + DBT versionData; + DBT checkKey; + DBT checkData; + DBT saltKey; + DBT saltData; + DBT key; + DBT data; + SECItem *rc4key = NULL; + NSSLOWKEYDBKey *dbkey = NULL; + SECItem *oldSalt = NULL; + int ret; + SECItem checkitem; + + if ( handle->updatedb == NULL ) { + return(SECSuccess); + } + + /* + * check the version record + */ + versionKey.data = VERSION_STRING; + versionKey.size = sizeof(VERSION_STRING)-1; + + ret = (* handle->updatedb->get)(handle->updatedb, &versionKey, + &versionData, 0 ); + + if (ret) { + /* no version record, so old db never used */ + goto done; + } + + if ( ( versionData.size != 1 ) || + ( *((unsigned char *)versionData.data) != 2 ) ) { + /* corrupt or wrong version number so don't update */ + goto done; + } + + saltKey.data = SALT_STRING; + saltKey.size = sizeof(SALT_STRING) - 1; + + ret = (* handle->updatedb->get)(handle->updatedb, &saltKey, &saltData, 0); + if ( ret ) { + /* no salt in old db, so it is corrupted */ + goto done; + } + + oldSalt = decodeKeyDBGlobalSalt(&saltData); + if ( oldSalt == NULL ) { + /* bad salt in old db, so it is corrupted */ + goto done; + } + + /* + * look for a pw check entry + */ + checkKey.data = KEYDB_PW_CHECK_STRING; + checkKey.size = KEYDB_PW_CHECK_LEN; + + ret = (* handle->updatedb->get)(handle->updatedb, &checkKey, + &checkData, 0 ); + if (ret) { + /* + * if we have a key, but no KEYDB_PW_CHECK_STRING, then this must + * be an old server database, and it does have a password associated + * with it. Put a fake entry in so we can identify this db when we do + * get the password for it. + */ + if (seckey_HasAServerKey(handle->updatedb)) { + DBT fcheckKey; + DBT fcheckData; + + /* + * include a fake string + */ + fcheckKey.data = KEYDB_FAKE_PW_CHECK_STRING; + fcheckKey.size = KEYDB_FAKE_PW_CHECK_LEN; + fcheckData.data = "1"; + fcheckData.size = 1; + /* put global salt into the new database now */ + ret = (* handle->db->put)( handle->db, &saltKey, &saltData, 0); + if ( ret ) { + goto done; + } + ret = (* handle->db->put)( handle->db, &fcheckKey, &fcheckData, 0); + if ( ret ) { + goto done; + } + } else { + goto done; + } + } else { + /* put global salt into the new database now */ + ret = (* handle->db->put)( handle->db, &saltKey, &saltData, 0); + if ( ret ) { + goto done; + } + + dbkey = decode_dbkey(&checkData, 2); + if ( dbkey == NULL ) { + goto done; + } + checkitem = dbkey->derPK; + dbkey->derPK.data = NULL; + + /* format the new pw check entry */ + rv = encodePWCheckEntry(NULL, &dbkey->derPK, SEC_OID_RC4, &checkitem); + if ( rv != SECSuccess ) { + goto done; + } + + rv = put_dbkey(handle, &checkKey, dbkey, PR_TRUE); + if ( rv != SECSuccess ) { + goto done; + } + + /* free the dbkey */ + sec_destroy_dbkey(dbkey); + dbkey = NULL; + } + + + /* now traverse the database */ + ret = (* handle->updatedb->seq)(handle->updatedb, &key, &data, R_FIRST); + if ( ret ) { + goto done; + } + + do { + /* skip version record */ + if ( data.size > 1 ) { + /* skip salt */ + if ( key.size == ( sizeof(SALT_STRING) - 1 ) ) { + if ( PORT_Memcmp(key.data, SALT_STRING, key.size) == 0 ) { + continue; + } + } + /* skip pw check entry */ + if ( key.size == checkKey.size ) { + if ( PORT_Memcmp(key.data, checkKey.data, key.size) == 0 ) { + continue; + } + } + + /* keys stored by nickname will have 0 as the last byte of the + * db key. Other keys must be stored by modulus. We will not + * update those because they are left over from a keygen that + * never resulted in a cert. + */ + if ( ((unsigned char *)key.data)[key.size-1] != 0 ) { + continue; + } + + dbkey = decode_dbkey(&data, 2); + if ( dbkey == NULL ) { + continue; + } + + /* This puts the key into the new database with the same + * index (nickname) that it had before. The second pass + * of the update will have the password. It will decrypt + * and re-encrypt the entries using a new algorithm. + */ + dbkey->nickname = (char *)key.data; + rv = put_dbkey(handle, &key, dbkey, PR_FALSE); + dbkey->nickname = NULL; + + sec_destroy_dbkey(dbkey); + } + } while ( (* handle->updatedb->seq)(handle->updatedb, &key, &data, + R_NEXT) == 0 ); + + dbkey = NULL; + +done: + /* sync the database */ + ret = (* handle->db->sync)(handle->db, 0); + + (* handle->updatedb->close)(handle->updatedb); + handle->updatedb = NULL; + + if ( rc4key ) { + SECITEM_FreeItem(rc4key, PR_TRUE); + } + + if ( oldSalt ) { + SECITEM_FreeItem(oldSalt, PR_TRUE); + } + + if ( dbkey ) { + sec_destroy_dbkey(dbkey); + } + + return(SECSuccess); +} + +NSSLOWKEYDBHandle * +nsslowkey_OpenKeyDB(PRBool readOnly, NSSLOWKEYDBNameFunc namecb, void *cbarg) { - SECKEYKeyDBHandle *handle; + NSSLOWKEYDBHandle *handle; DBT versionKey; DBT versionData; int ret; @@ -570,7 +773,7 @@ SECKEY_OpenKeyDB(PRBool readOnly, SECKEYDBNameFunc namecb, void *cbarg) char *dbname = NULL; PRBool updated = PR_FALSE; - handle = (SECKEYKeyDBHandle *)PORT_ZAlloc (sizeof(SECKEYKeyDBHandle)); + handle = (NSSLOWKEYDBHandle *)PORT_ZAlloc (sizeof(NSSLOWKEYDBHandle)); if (handle == NULL) { PORT_SetError (SEC_ERROR_NO_MEMORY); return NULL; @@ -585,7 +788,7 @@ SECKEY_OpenKeyDB(PRBool readOnly, SECKEYDBNameFunc namecb, void *cbarg) openflags = O_RDWR; } - dbname = (*namecb)(cbarg, PRIVATE_KEY_DB_FILE_VERSION); + dbname = (*namecb)(cbarg, NSSLOWKEY_DB_FILE_VERSION); if ( dbname == NULL ) { goto loser; } @@ -616,7 +819,7 @@ SECKEY_OpenKeyDB(PRBool readOnly, SECKEYDBNameFunc namecb, void *cbarg) handle->version = *( (unsigned char *)versionData.data); - if (handle->version != PRIVATE_KEY_DB_FILE_VERSION ) { + if (handle->version != NSSLOWKEY_DB_FILE_VERSION ) { /* bogus version number record, reset the database */ (* handle->db->close)( handle->db ); handle->db = NULL; @@ -666,7 +869,7 @@ newdb: * have a password, then this will fail and we will do the * update later */ - rv = SECKEY_UpdateKeyDBPass1(handle); + rv = nsslowkey_UpdateKeyDBPass1(handle); if ( rv == SECSuccess ) { updated = PR_TRUE; } @@ -716,11 +919,11 @@ loser: * Close the database */ void -SECKEY_CloseKeyDB(SECKEYKeyDBHandle *handle) +nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle) { if (handle != NULL) { - if (handle == SECKEY_GetDefaultKeyDB()) { - SECKEY_SetDefaultKeyDB(NULL); + if (handle == nsslowkey_GetDefaultKeyDB()) { + nsslowkey_SetDefaultKeyDB(NULL); } if (handle->db != NULL) { (* handle->db->close)(handle->db); @@ -732,7 +935,7 @@ SECKEY_CloseKeyDB(SECKEYKeyDBHandle *handle) /* Get the key database version */ int -SECKEY_GetKeyDBVersion(SECKEYKeyDBHandle *handle) +nsslowkey_GetKeyDBVersion(NSSLOWKEYDBHandle *handle) { PORT_Assert(handle != NULL); @@ -744,16 +947,16 @@ SECKEY_GetKeyDBVersion(SECKEYKeyDBHandle *handle) * not have to pass the handle all over the place. */ -static SECKEYKeyDBHandle *sec_default_key_db = NULL; +static NSSLOWKEYDBHandle *sec_default_key_db = NULL; void -SECKEY_SetDefaultKeyDB(SECKEYKeyDBHandle *handle) +nsslowkey_SetDefaultKeyDB(NSSLOWKEYDBHandle *handle) { sec_default_key_db = handle; } -SECKEYKeyDBHandle * -SECKEY_GetDefaultKeyDB(void) +NSSLOWKEYDBHandle * +nsslowkey_GetDefaultKeyDB(void) { return sec_default_key_db; } @@ -762,7 +965,7 @@ SECKEY_GetDefaultKeyDB(void) * Delete a private key that was stored in the database */ SECStatus -SECKEY_DeleteKey(SECKEYKeyDBHandle *handle, SECItem *pubkey) +nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle, SECItem *pubkey) { DBT namekey; int ret; @@ -797,112 +1000,66 @@ SECKEY_DeleteKey(SECKEYKeyDBHandle *handle, SECItem *pubkey) * Store a key in the database, indexed by its public key modulus.(value!) */ SECStatus -SECKEY_StoreKeyByPublicKey(SECKEYKeyDBHandle *handle, - SECKEYLowPrivateKey *privkey, +nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle, + NSSLOWKEYPrivateKey *privkey, SECItem *pubKeyData, char *nickname, - SECKEYLowGetPasswordKey f, void *arg) + SECItem *arg) { - return SECKEY_StoreKeyByPublicKeyAlg(handle, privkey, pubKeyData, nickname, - f, arg, SECKEY_GetDefaultKeyDBAlg()); + return nsslowkey_StoreKeyByPublicKeyAlg(handle, privkey, pubKeyData, + nickname, arg, nsslowkey_GetDefaultKeyDBAlg()); } /* see if the public key for this cert is in the database filed * by modulus */ -SECStatus -SECKEY_KeyForCertExists(SECKEYKeyDBHandle *handle, CERTCertificate *cert) +PRBool +nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cert) { - SECKEYPublicKey *pubkey = NULL; + NSSLOWKEYPublicKey *pubkey = NULL; DBT namekey; DBT dummy; int status; /* get cert's public key */ - pubkey = CERT_ExtractPublicKey(cert); + pubkey = nsslowcert_ExtractPublicKey(cert); if ( pubkey == NULL ) { - return SECFailure; + return PR_FALSE; } - /* TNH - make key from SECKEYPublicKey */ + /* TNH - make key from NSSLOWKEYPublicKey */ switch (pubkey->keyType) { - case rsaKey: + case NSSLOWKEYRSAKey: namekey.data = pubkey->u.rsa.modulus.data; namekey.size = pubkey->u.rsa.modulus.len; break; - case dsaKey: + case NSSLOWKEYDSAKey: namekey.data = pubkey->u.dsa.publicValue.data; namekey.size = pubkey->u.dsa.publicValue.len; break; - case dhKey: + case NSSLOWKEYDHKey: namekey.data = pubkey->u.dh.publicValue.data; namekey.size = pubkey->u.dh.publicValue.len; break; default: /* XXX We don't do Fortezza or DH yet. */ - return SECFailure; + return PR_FALSE; } status = (* handle->db->get)(handle->db, &namekey, &dummy, 0); - SECKEY_DestroyPublicKey(pubkey); + nsslowkey_DestroyPublicKey(pubkey); if ( status ) { - /* TNH - should this really set an error? */ - PORT_SetError(SEC_ERROR_BAD_DATABASE); - return SECFailure; + return PR_FALSE; } - return SECSuccess; -} - -/* - * find the private key for a cert - */ -SECKEYLowPrivateKey * -SECKEY_FindKeyByCert(SECKEYKeyDBHandle *handle, CERTCertificate *cert, - SECKEYLowGetPasswordKey f, void *arg) -{ - SECKEYPublicKey *pubkey = NULL; - SECItem *keyItem = NULL; - SECKEYLowPrivateKey *privKey = NULL; - - /* get cert's public key */ - pubkey = CERT_ExtractPublicKey(cert); - if ( !pubkey ) { - goto loser; - } - - /* TNH - make record key from SECKEYPublicKey (again) */ - switch (pubkey->keyType) { - case rsaKey: - keyItem = &pubkey->u.rsa.modulus; - break; - case dsaKey: - keyItem = &pubkey->u.dsa.publicValue; - break; - case dhKey: - keyItem = &pubkey->u.dh.publicValue; - break; - /* fortezza an NULL keys are not stored in the data base */ - case keaKey: - case fortezzaKey: - case nullKey: - goto loser; - } - PORT_Assert( keyItem != NULL ); - - privKey = SECKEY_FindKeyByPublicKey(handle, keyItem, f, arg); - - /* success falls through */ -loser: - SECKEY_DestroyPublicKey(pubkey); - return(privKey); + return PR_TRUE; } /* * check to see if the user has a password */ SECStatus -SECKEY_HasKeyDBPassword(SECKEYKeyDBHandle *handle) +nsslowkey_HasKeyDBPassword(NSSLOWKEYDBHandle *handle) { DBT checkkey, checkdata; int ret; @@ -933,23 +1090,10 @@ SECKEY_HasKeyDBPassword(SECKEYKeyDBHandle *handle) * This is done by encrypting a known plaintext with the user's key. */ SECStatus -SECKEY_SetKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem) -{ - return SECKEY_SetKeyDBPasswordAlg(handle, pwitem, - SECKEY_GetDefaultKeyDBAlg()); -} - -/* - * Re-encrypt the entire key database with a new password. - * NOTE: This really should create a new database rather than doing it - * in place in the original - */ -SECStatus -SECKEY_ChangeKeyDBPassword(SECKEYKeyDBHandle *handle, - SECItem *oldpwitem, SECItem *newpwitem) +nsslowkey_SetKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem) { - return SECKEY_ChangeKeyDBPasswordAlg(handle, oldpwitem, newpwitem, - SECKEY_GetDefaultKeyDBAlg()); + return nsslowkey_SetKeyDBPasswordAlg(handle, pwitem, + nsslowkey_GetDefaultKeyDBAlg()); } static SECStatus @@ -976,7 +1120,7 @@ HashPassword(unsigned char *hashresult, char *pw, SECItem *salt) } SECItem * -SECKEY_HashPassword(char *pw, SECItem *salt) +nsslowkey_HashPassword(char *pw, SECItem *salt) { SECItem *pwitem; SECStatus rv; @@ -1004,13 +1148,13 @@ SECKEY_HashPassword(char *pw, SECItem *salt) /* Derive the actual password value for the database from a pw string */ SECItem * -SECKEY_DeriveKeyDBPassword(SECKEYKeyDBHandle *keydb, char *pw) +nsslowkey_DeriveKeyDBPassword(NSSLOWKEYDBHandle *keydb, char *pw) { PORT_Assert(keydb != NULL); PORT_Assert(pw != NULL); if (keydb == NULL || pw == NULL) return(NULL); - return SECKEY_HashPassword(pw, keydb->global_salt); + return nsslowkey_HashPassword(pw, keydb->global_salt); } #if 0 @@ -1019,11 +1163,11 @@ SECKEY_DeriveKeyDBPassword(SECKEYKeyDBHandle *keydb, char *pw) * is encrypted. */ SECOidTag -seckey_get_private_key_algorithm(SECKEYKeyDBHandle *keydb, DBT *index) +seckey_get_private_key_algorithm(NSSLOWKEYDBHandle *keydb, DBT *index) { - SECKEYDBKey *dbkey = NULL; + NSSLOWKEYDBKey *dbkey = NULL; SECOidTag algorithm = SEC_OID_UNKNOWN; - EncryptedPrivateKeyInfo *epki = NULL; + NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL; PLArenaPool *poolp = NULL; SECStatus rv; @@ -1035,12 +1179,12 @@ seckey_get_private_key_algorithm(SECKEYKeyDBHandle *keydb, DBT *index) if(dbkey == NULL) return (SECOidTag)SECFailure; - epki = (EncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(poolp, - sizeof(EncryptedPrivateKeyInfo)); + epki = (NSSLOWKEYEncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(poolp, + sizeof(NSSLOWKEYEncryptedPrivateKeyInfo)); if(epki == NULL) goto loser; rv = SEC_ASN1DecodeItem(poolp, epki, - SECKEY_EncryptedPrivateKeyInfoTemplate, &dbkey->derPK); + nsslowkey_EncryptedPrivateKeyInfoTemplate, &dbkey->derPK); if(rv == SECFailure) goto loser; @@ -1129,7 +1273,7 @@ seckey_create_rc4_salt(void) } SECItem * -seckey_rc4_cipher(SECItem *key, SECItem *src, PRBool encrypt) +seckey_rc4_decode(SECItem *key, SECItem *src) { SECItem *dest = NULL; RC4Context *ctxt = NULL; @@ -1149,11 +1293,7 @@ seckey_rc4_cipher(SECItem *key, SECItem *src, PRBool encrypt) ctxt = RC4_CreateContext(key->data, key->len); if(ctxt != NULL) { - if(encrypt == PR_TRUE) - rv = RC4_Encrypt(ctxt, dest->data, &dest->len, - src->len + 64, src->data, src->len); - else - rv = RC4_Decrypt(ctxt, dest->data, &dest->len, + rv = RC4_Decrypt(ctxt, dest->data, &dest->len, src->len + 64, src->data, src->len); RC4_DestroyContext(ctxt, PR_TRUE); } @@ -1171,19 +1311,21 @@ seckey_rc4_cipher(SECItem *key, SECItem *src, PRBool encrypt) /* TNH - keydb is unused */ /* TNH - the pwitem should be the derived key for RC4 */ -EncryptedPrivateKeyInfo * +NSSLOWKEYEncryptedPrivateKeyInfo * seckey_encrypt_private_key( - SECKEYLowPrivateKey *pk, SECItem *pwitem, SECKEYKeyDBHandle *keydb, - SECOidTag algorithm) + NSSLOWKEYPrivateKey *pk, SECItem *pwitem, NSSLOWKEYDBHandle *keydb, + SECOidTag algorithm, SECItem **salt) { - EncryptedPrivateKeyInfo *epki = NULL; - PrivateKeyInfo *pki = NULL; + NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL; + NSSLOWKEYPrivateKeyInfo *pki = NULL; SECStatus rv = SECFailure; - SECAlgorithmID *algid = NULL; PLArenaPool *temparena = NULL, *permarena = NULL; - SECItem *key = NULL, *salt = NULL, *der_item = NULL; + SECItem *der_item = NULL; + NSSPKCS5PBEParameter *param; SECItem *dummy = NULL, *dest = NULL; + SECAlgorithmID *algid; + *salt = NULL; permarena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); if(permarena == NULL) return NULL; @@ -1193,10 +1335,10 @@ seckey_encrypt_private_key( goto loser; /* allocate structures */ - epki = (EncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(permarena, - sizeof(EncryptedPrivateKeyInfo)); - pki = (PrivateKeyInfo *)PORT_ArenaZAlloc(temparena, - sizeof(PrivateKeyInfo)); + epki = (NSSLOWKEYEncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(permarena, + sizeof(NSSLOWKEYEncryptedPrivateKeyInfo)); + pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(temparena, + sizeof(NSSLOWKEYPrivateKeyInfo)); der_item = (SECItem *)PORT_ArenaZAlloc(temparena, sizeof(SECItem)); if((epki == NULL) || (pki == NULL) || (der_item == NULL)) goto loser; @@ -1205,15 +1347,15 @@ seckey_encrypt_private_key( /* setup private key info */ dummy = SEC_ASN1EncodeInteger(temparena, &(pki->version), - SEC_PRIVATE_KEY_INFO_VERSION); + NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); if(dummy == NULL) goto loser; /* Encode the key, and set the algorithm (with params) */ switch (pk->keyType) { - case lowRSAKey: + case NSSLOWKEYRSAKey: dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk, - SECKEY_LowRSAPrivateKeyTemplate); + nsslowkey_RSAPrivateKeyTemplate); if (dummy == NULL) { rv = SECFailure; goto loser; @@ -1226,16 +1368,16 @@ seckey_encrypt_private_key( } break; - case lowDSAKey: + case NSSLOWKEYDSAKey: dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk, - SECKEY_LowDSAPrivateKeyTemplate); + nsslowkey_DSAPrivateKeyTemplate); if (dummy == NULL) { rv = SECFailure; goto loser; } dummy = SEC_ASN1EncodeItem(temparena, NULL, &pk->u.dsa.params, - SECKEY_LowPQGParamsTemplate); + nsslowkey_PQGParamsTemplate); if (dummy == NULL) { rv = SECFailure; goto loser; @@ -1248,9 +1390,9 @@ seckey_encrypt_private_key( } break; - case lowDHKey: + case NSSLOWKEYDHKey: dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk, - SECKEY_LowDHPrivateKeyTemplate); + nsslowkey_DHPrivateKeyTemplate); if (dummy == NULL) { rv = SECFailure; goto loser; @@ -1270,85 +1412,72 @@ seckey_encrypt_private_key( /* setup encrypted private key info */ dummy = SEC_ASN1EncodeItem(temparena, der_item, pki, - SECKEY_PrivateKeyInfoTemplate); + nsslowkey_PrivateKeyInfoTemplate); if(dummy == NULL) { rv = SECFailure; goto loser; } rv = SECFailure; /* assume failure */ - switch(algorithm) - { - case SEC_OID_RC4: - salt = seckey_create_rc4_salt(); - if(salt != NULL) - { - key = seckey_create_rc4_key(pwitem, salt); - if(key != NULL) - { - dest = seckey_rc4_cipher(key, der_item, PR_TRUE); - if(dest != NULL) - { - rv = SECITEM_CopyItem(permarena, &epki->encryptedData, - dest); - if(rv == SECSuccess) - rv = SECOID_SetAlgorithmID(permarena, - &epki->algorithm, SEC_OID_RC4, salt); - } - } - } - if(dest != NULL) - SECITEM_FreeItem(dest, PR_TRUE); - if(key != NULL) - SECITEM_ZfreeItem(key, PR_TRUE); - break; - default: - algid = SEC_PKCS5CreateAlgorithmID(algorithm, NULL, 1); - if(algid != NULL) - { - dest = SEC_PKCS5CipherData(algid, pwitem, - der_item, PR_TRUE, NULL); - if(dest != NULL) - { - rv = SECITEM_CopyItem(permarena, &epki->encryptedData, - dest); - if(rv == SECSuccess) - rv = SECOID_CopyAlgorithmID(permarena, - &epki->algorithm, algid); - } - } - if(dest != NULL) - SECITEM_FreeItem(dest, PR_TRUE); - if(algid != NULL) - SECOID_DestroyAlgorithmID(algid, PR_TRUE); - break; + *salt = seckey_create_rc4_salt(); + if (*salt == NULL) { + goto loser; } - /* let success fall through */ + param = nsspkcs5_NewParam(algorithm,*salt,1); + if (param == NULL) { + goto loser; + } + + dest = nsspkcs5_CipherData(param, pwitem, der_item, PR_TRUE, NULL); + if (dest == NULL) { + goto loser; + } + + rv = SECITEM_CopyItem(permarena, &epki->encryptedData, dest); + if (rv != SECSuccess) { + goto loser; + } + + algid = nsspkcs5_CreateAlgorithmID(permarena, algorithm, param); + if (algid == NULL) { + rv = SECFailure; + goto loser; + } + + rv = SECOID_CopyAlgorithmID(permarena, &epki->algorithm, algid); + SECOID_DestroyAlgorithmID(algid, PR_TRUE); + loser: + if(dest != NULL) + SECITEM_FreeItem(dest, PR_TRUE); + + if(param != NULL) + nsspkcs5_DestroyPBEParameter(param); + + /* let success fall through */ if(rv == SECFailure) { PORT_FreeArena(permarena, PR_TRUE); - epki = NULL; + epki = NULL; + if(*salt != NULL) + SECITEM_FreeItem(*salt, PR_TRUE); } if(temparena != NULL) PORT_FreeArena(temparena, PR_TRUE); - - if(salt != NULL) - SECITEM_FreeItem(salt, PR_TRUE); return epki; } -SECStatus -seckey_put_private_key(SECKEYKeyDBHandle *keydb, DBT *index, SECItem *pwitem, - SECKEYLowPrivateKey *pk, char *nickname, PRBool update, +static SECStatus +seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem, + NSSLOWKEYPrivateKey *pk, char *nickname, PRBool update, SECOidTag algorithm) { - SECKEYDBKey *dbkey = NULL; - EncryptedPrivateKeyInfo *epki = NULL; + NSSLOWKEYDBKey *dbkey = NULL; + NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL; PLArenaPool *temparena = NULL, *permarena = NULL; SECItem *dummy = NULL; SECItem *salt = NULL; @@ -1362,7 +1491,7 @@ seckey_put_private_key(SECKEYKeyDBHandle *keydb, DBT *index, SECItem *pwitem, if(permarena == NULL) return SECFailure; - dbkey = (SECKEYDBKey *)PORT_ArenaZAlloc(permarena, sizeof(SECKEYDBKey)); + dbkey = (NSSLOWKEYDBKey *)PORT_ArenaZAlloc(permarena, sizeof(NSSLOWKEYDBKey)); if(dbkey == NULL) goto loser; dbkey->arena = permarena; @@ -1370,33 +1499,19 @@ seckey_put_private_key(SECKEYKeyDBHandle *keydb, DBT *index, SECItem *pwitem, /* TNH - for RC4, the salt should be created here */ - epki = seckey_encrypt_private_key(pk, pwitem, keydb, algorithm); + epki = seckey_encrypt_private_key(pk, pwitem, keydb, algorithm, &salt); if(epki == NULL) goto loser; temparena = epki->arena; - /* extract salt for db key */ - switch(algorithm) + if(salt != NULL) { - case SEC_OID_RC4: - rv = SECITEM_CopyItem(permarena, &(dbkey->salt), - &(epki->algorithm.parameters)); - epki->algorithm.parameters.len = 0; - epki->algorithm.parameters.data = NULL; - break; - default: - /* TNH - this should not be necessary */ - salt = SEC_PKCS5GetSalt(&epki->algorithm); - if(salt != NULL) - { - rv = SECITEM_CopyItem(permarena, &(dbkey->salt), salt); - SECITEM_ZfreeItem(salt, PR_TRUE); - } - break; + rv = SECITEM_CopyItem(permarena, &(dbkey->salt), salt); + SECITEM_ZfreeItem(salt, PR_TRUE); } dummy = SEC_ASN1EncodeItem(permarena, &(dbkey->derPK), epki, - SECKEY_EncryptedPrivateKeyInfoTemplate); + nsslowkey_EncryptedPrivateKeyInfoTemplate); if(dummy == NULL) rv = SECFailure; else @@ -1418,15 +1533,14 @@ loser: * Note that the nickname is optional. It was only used by keyutil. */ SECStatus -SECKEY_StoreKeyByPublicKeyAlg(SECKEYKeyDBHandle *handle, - SECKEYLowPrivateKey *privkey, +nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle, + NSSLOWKEYPrivateKey *privkey, SECItem *pubKeyData, char *nickname, - SECKEYLowGetPasswordKey f, void *arg, + SECItem *pwitem, SECOidTag algorithm) { DBT namekey; - SECItem *pwitem = NULL; SECStatus rv; if (handle == NULL) { @@ -1438,29 +1552,24 @@ SECKEY_StoreKeyByPublicKeyAlg(SECKEYKeyDBHandle *handle, namekey.data = pubKeyData->data; namekey.size = pubKeyData->len; - pwitem = (*f )(arg, handle); - if ( pwitem == NULL ) { - return(SECFailure); - } - /* encrypt the private key */ rv = seckey_put_private_key(handle, &namekey, pwitem, privkey, nickname, PR_FALSE, algorithm); - SECITEM_ZfreeItem(pwitem, PR_TRUE); return(rv); } -SECKEYLowPrivateKey * -seckey_decrypt_private_key(EncryptedPrivateKeyInfo *epki, +NSSLOWKEYPrivateKey * +seckey_decrypt_private_key(NSSLOWKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem) { - SECKEYLowPrivateKey *pk = NULL; - PrivateKeyInfo *pki = NULL; + NSSLOWKEYPrivateKey *pk = NULL; + NSSLOWKEYPrivateKeyInfo *pki = NULL; SECStatus rv = SECFailure; SECOidTag algorithm; PLArenaPool *temparena = NULL, *permarena = NULL; SECItem *salt = NULL, *dest = NULL, *key = NULL; + NSSPKCS5PBEParameter *param; if((epki == NULL) || (pwitem == NULL)) goto loser; @@ -1471,12 +1580,12 @@ seckey_decrypt_private_key(EncryptedPrivateKeyInfo *epki, goto loser; /* allocate temporary items */ - pki = (PrivateKeyInfo *)PORT_ArenaZAlloc(temparena, - sizeof(PrivateKeyInfo)); + pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(temparena, + sizeof(NSSLOWKEYPrivateKeyInfo)); /* allocate permanent arena items */ - pk = (SECKEYLowPrivateKey *)PORT_ArenaZAlloc(permarena, - sizeof(SECKEYLowPrivateKey)); + pk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(permarena, + sizeof(NSSLOWKEYPrivateKey)); if((pk == NULL) || (pki == NULL)) goto loser; @@ -1493,8 +1602,7 @@ seckey_decrypt_private_key(EncryptedPrivateKeyInfo *epki, key = seckey_create_rc4_key(pwitem, salt); if(key != NULL) { - dest = seckey_rc4_cipher(key, &epki->encryptedData, - PR_FALSE); + dest = seckey_rc4_decode(key, &epki->encryptedData); } } if(salt != NULL) @@ -1506,40 +1614,45 @@ seckey_decrypt_private_key(EncryptedPrivateKeyInfo *epki, /* we depend on the fact that if this key was encoded with * DES, that the pw was also encoded with DES, so we don't have * to do the update here, the password code will handle it. */ - dest = SEC_PKCS5CipherData(&epki->algorithm, pwitem, - &epki->encryptedData, PR_FALSE, NULL); + param = nsspkcs5_AlgidToParam(&epki->algorithm); + if (param == NULL) { + break; + } + dest = nsspkcs5_CipherData(param, pwitem, &epki->encryptedData, + PR_FALSE, NULL); + nsspkcs5_DestroyPBEParameter(param); break; } if(dest != NULL) { rv = SEC_ASN1DecodeItem(temparena, pki, - SECKEY_PrivateKeyInfoTemplate, dest); + nsslowkey_PrivateKeyInfoTemplate, dest); if(rv == SECSuccess) { switch(SECOID_GetAlgorithmTag(&pki->algorithm)) { case SEC_OID_X500_RSA_ENCRYPTION: case SEC_OID_PKCS1_RSA_ENCRYPTION: - pk->keyType = lowRSAKey; + pk->keyType = NSSLOWKEYRSAKey; rv = SEC_ASN1DecodeItem(permarena, pk, - SECKEY_LowRSAPrivateKeyTemplate, + nsslowkey_RSAPrivateKeyTemplate, &pki->privateKey); break; case SEC_OID_ANSIX9_DSA_SIGNATURE: - pk->keyType = lowDSAKey; + pk->keyType = NSSLOWKEYDSAKey; rv = SEC_ASN1DecodeItem(permarena, pk, - SECKEY_LowDSAPrivateKeyTemplate, + nsslowkey_DSAPrivateKeyTemplate, &pki->privateKey); if (rv != SECSuccess) goto loser; rv = SEC_ASN1DecodeItem(permarena, &pk->u.dsa.params, - SECKEY_LowPQGParamsTemplate, + nsslowkey_PQGParamsTemplate, &pki->algorithm.parameters); break; case SEC_OID_X942_DIFFIE_HELMAN_KEY: - pk->keyType = lowDHKey; + pk->keyType = NSSLOWKEYDHKey; rv = SEC_ASN1DecodeItem(permarena, pk, - SECKEY_LowDHPrivateKeyTemplate, + nsslowkey_DHPrivateKeyTemplate, &pki->privateKey); break; default: @@ -1571,11 +1684,11 @@ loser: return pk; } -static SECKEYLowPrivateKey * -seckey_decode_encrypted_private_key(SECKEYDBKey *dbkey, SECItem *pwitem) +static NSSLOWKEYPrivateKey * +seckey_decode_encrypted_private_key(NSSLOWKEYDBKey *dbkey, SECItem *pwitem) { - SECKEYLowPrivateKey *pk = NULL; - EncryptedPrivateKeyInfo *epki; + NSSLOWKEYPrivateKey *pk = NULL; + NSSLOWKEYEncryptedPrivateKeyInfo *epki; PLArenaPool *temparena = NULL; SECStatus rv; SECOidTag algorithm; @@ -1589,15 +1702,15 @@ seckey_decode_encrypted_private_key(SECKEYDBKey *dbkey, SECItem *pwitem) return NULL; } - epki = (EncryptedPrivateKeyInfo *) - PORT_ArenaZAlloc(temparena, sizeof(EncryptedPrivateKeyInfo)); + epki = (NSSLOWKEYEncryptedPrivateKeyInfo *) + PORT_ArenaZAlloc(temparena, sizeof(NSSLOWKEYEncryptedPrivateKeyInfo)); if(epki == NULL) { goto loser; } rv = SEC_ASN1DecodeItem(temparena, epki, - SECKEY_EncryptedPrivateKeyInfoTemplate, + nsslowkey_EncryptedPrivateKeyInfoTemplate, &(dbkey->derPK)); if(rv != SECSuccess) { goto loser; @@ -1625,12 +1738,12 @@ loser: return pk; } -SECKEYLowPrivateKey * -seckey_get_private_key(SECKEYKeyDBHandle *keydb, DBT *index, char **nickname, +NSSLOWKEYPrivateKey * +seckey_get_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, char **nickname, SECItem *pwitem) { - SECKEYDBKey *dbkey = NULL; - SECKEYLowPrivateKey *pk = NULL; + NSSLOWKEYDBKey *dbkey = NULL; + NSSLOWKEYPrivateKey *pk = NULL; if( ( keydb == NULL ) || ( index == NULL ) || ( pwitem == NULL ) ) { return NULL; @@ -1665,9 +1778,9 @@ loser: * used by pkcs11 to import keys into it's object format... In the future * we really need a better way to tie in... */ -SECKEYLowPrivateKey * -SECKEY_DecryptKey(DBT *key, SECItem *pwitem, - SECKEYKeyDBHandle *handle) { +NSSLOWKEYPrivateKey * +nsslowkey_DecryptKey(DBT *key, SECItem *pwitem, + NSSLOWKEYDBHandle *handle) { return seckey_get_private_key(handle,key,NULL,pwitem); } @@ -1678,13 +1791,12 @@ SECKEY_DecryptKey(DBT *key, SECItem *pwitem, * is looked up by the public modulus in the certificate, and the * re-stored by its nickname. */ -SECKEYLowPrivateKey * -SECKEY_FindKeyByPublicKey(SECKEYKeyDBHandle *handle, SECItem *modulus, - SECKEYLowGetPasswordKey f, void *arg) +NSSLOWKEYPrivateKey * +nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus, + SECItem *pwitem) { DBT namekey; - SECKEYLowPrivateKey *pk = NULL; - SECItem *pwitem = NULL; + NSSLOWKEYPrivateKey *pk = NULL; if (handle == NULL) { PORT_SetError(SEC_ERROR_BAD_DATABASE); @@ -1695,13 +1807,7 @@ SECKEY_FindKeyByPublicKey(SECKEYKeyDBHandle *handle, SECItem *modulus, namekey.data = modulus->data; namekey.size = modulus->len; - pwitem = (*f )(arg, handle); - if ( pwitem == NULL ) { - return(NULL); - } - pk = seckey_get_private_key(handle, &namekey, NULL, pwitem); - SECITEM_ZfreeItem(pwitem, PR_TRUE); /* no need to free dbkey, since its on the stack, and the data it * points to is owned by the database @@ -1754,15 +1860,15 @@ loser: * This is done by encrypting a known plaintext with the user's key. */ SECStatus -SECKEY_SetKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, +nsslowkey_SetKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, SECItem *pwitem, SECOidTag algorithm) { DBT checkkey; - SECAlgorithmID *algid = NULL; + NSSPKCS5PBEParameter *param = NULL; SECStatus rv = SECFailure; - SECKEYDBKey *dbkey = NULL; + NSSLOWKEYDBKey *dbkey = NULL; PLArenaPool *arena; - SECItem *key = NULL, *salt = NULL; + SECItem *salt = NULL; SECItem *dest = NULL, test_key; if (handle == NULL) { @@ -1775,7 +1881,7 @@ SECKEY_SetKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, goto loser; } - dbkey = (SECKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYDBKey)); + dbkey = (NSSLOWKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYDBKey)); if ( dbkey == NULL ) { rv = SECFailure; goto loser; @@ -1793,40 +1899,31 @@ SECKEY_SetKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, goto loser; } - switch(algorithm) - { - case SEC_OID_RC4: - key = seckey_create_rc4_key(pwitem, salt); - if(key != NULL) - { - dest = seckey_rc4_cipher(key, &test_key, PR_TRUE); - SECITEM_FreeItem(key, PR_TRUE); - } - break; - default: - algid = SEC_PKCS5CreateAlgorithmID(algorithm, salt, 1); - if(algid != NULL) - dest = SEC_PKCS5CipherData(algid, pwitem, &test_key, - PR_TRUE, NULL); - break; + param = nsspkcs5_NewParam(algorithm, salt, 1); + if (param == NULL) { + rv = SECFailure; + goto loser; } - if(dest != NULL) + dest = nsspkcs5_CipherData(param, pwitem, &test_key, PR_TRUE, NULL); + if (dest == NULL) { - rv = SECITEM_CopyItem(arena, &dbkey->salt, salt); - if(rv == SECFailure) - goto loser; + rv = SECFailure; + goto loser; + } + + rv = SECITEM_CopyItem(arena, &dbkey->salt, salt); + if (rv == SECFailure) { + goto loser; + } - rv = encodePWCheckEntry(arena, &dbkey->derPK, algorithm, dest); - - if ( rv != SECSuccess ) { - goto loser; - } + rv = encodePWCheckEntry(arena, &dbkey->derPK, algorithm, dest); - rv = put_dbkey(handle, &checkkey, dbkey, PR_TRUE); - } else { - rv = SECFailure; + if ( rv != SECSuccess ) { + goto loser; } + + rv = put_dbkey(handle, &checkkey, dbkey, PR_TRUE); /* let success fall through */ loser: @@ -1841,6 +1938,10 @@ loser: if ( salt != NULL ) { SECITEM_ZfreeItem(salt, PR_TRUE); } + + if (param != NULL) { + nsspkcs5_DestroyPBEParameter(param); + } return(rv); } @@ -1896,12 +1997,12 @@ seckey_HasAServerKey(DB *db) } static SECStatus -seckey_CheckKeyDB1Password(SECKEYKeyDBHandle *handle, SECItem *pwitem) +seckey_CheckKeyDB1Password(NSSLOWKEYDBHandle *handle, SECItem *pwitem) { SECStatus rv = SECFailure; keyList keylist; keyNode *node = NULL; - SECKEYLowPrivateKey *privkey = NULL; + NSSLOWKEYPrivateKey *privkey = NULL; /* @@ -1919,7 +2020,7 @@ seckey_CheckKeyDB1Password(SECKEYKeyDBHandle *handle, SECItem *pwitem) /* TNH - TraverseKeys should not be public, since it exposes the underlying DBT data type. */ - rv = SECKEY_TraverseKeys(handle, sec_add_key_to_list, (void *)&keylist); + rv = nsslowkey_TraverseKeys(handle, sec_add_key_to_list, (void *)&keylist); if ( rv != SECSuccess ) goto done; @@ -1939,7 +2040,7 @@ seckey_CheckKeyDB1Password(SECKEYKeyDBHandle *handle, SECItem *pwitem) /* if we can decrypt the private key, then we had the correct password */ rv = SECSuccess; - SECKEY_LowDestroyPrivateKey(privkey); + nsslowkey_DestroyPrivateKey(privkey); done: @@ -1955,13 +2056,13 @@ done: * check to see if the user has typed the right password */ SECStatus -SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem) +nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem) { DBT checkkey; DBT checkdata; - SECAlgorithmID *algid = NULL; + NSSPKCS5PBEParameter *param = NULL; SECStatus rv = SECFailure; - SECKEYDBKey *dbkey = NULL; + NSSLOWKEYDBKey *dbkey = NULL; SECItem *key = NULL; SECItem *dest = NULL; SECOidTag algorithm; @@ -1993,7 +2094,7 @@ SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem) rv = seckey_CheckKeyDB1Password(handle,pwitem); if (rv == SECSuccess) { /* OK we have enough to complete our conversion */ - SECKEY_UpdateKeyDBPass2(handle,pwitem); + nsslowkey_UpdateKeyDBPass2(handle,pwitem); } return rv; } @@ -2022,14 +2123,13 @@ SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem) case SEC_OID_RC4: key = seckey_create_rc4_key(pwitem, &dbkey->salt); if(key != NULL) { - dest = seckey_rc4_cipher(key, &encstring, PR_FALSE); + dest = seckey_rc4_decode(key, &encstring); SECITEM_FreeItem(key, PR_TRUE); } break; default: - algid = SEC_PKCS5CreateAlgorithmID(algorithm, - &dbkey->salt, 1); - if(algid != NULL) { + param = nsspkcs5_NewParam(algorithm, &dbkey->salt, 1); + if (param != NULL) { /* Decrypt - this function implements a workaround for * a previous coding error. It will decrypt values using * DES rather than 3DES, if the initial try at 3DES @@ -2037,9 +2137,9 @@ SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem) * set to TRUE. This indication is used later to force * an update of the database to "real" 3DES encryption. */ - dest = SEC_PKCS5CipherData(algid, pwitem, + dest = nsspkcs5_CipherData(param, pwitem, &encstring, PR_FALSE, &update); - SECOID_DestroyAlgorithmID(algid, PR_TRUE); + nsspkcs5_DestroyPBEParameter(param); } break; } @@ -2055,7 +2155,7 @@ SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem) /* we succeeded */ if ( algorithm == SEC_OID_RC4 ) { /* partially updated database */ - SECKEY_UpdateKeyDBPass2(handle, pwitem); + nsslowkey_UpdateKeyDBPass2(handle, pwitem); } /* Force an update of the password to remove the incorrect DES * encryption (see the note above) @@ -2063,7 +2163,7 @@ SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem) if (update && (algorithm == SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC)) { /* data base was encoded with DES not triple des, fix it */ - SECKEY_UpdateKeyDBPass2(handle,pwitem); + nsslowkey_UpdateKeyDBPass2(handle,pwitem); } } @@ -2082,14 +2182,14 @@ loser: * the caller. */ static SECStatus -ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, +ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, SECItem *oldpwitem, SECItem *newpwitem, SECOidTag new_algorithm) { SECStatus rv; keyList keylist; keyNode *node = NULL; - SECKEYLowPrivateKey *privkey = NULL; + NSSLOWKEYPrivateKey *privkey = NULL; char *nickname; DBT newkey; int ret; @@ -2105,7 +2205,7 @@ ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, /* TNH - TraverseKeys should not be public, since it exposes the underlying DBT data type. */ - rv = SECKEY_TraverseKeys(handle, sec_add_key_to_list, (void *)&keylist); + rv = nsslowkey_TraverseKeys(handle, sec_add_key_to_list, (void *)&keylist); if ( rv != SECSuccess ) goto loser; @@ -2133,20 +2233,19 @@ ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, /* get the public key, which we use as the database index */ switch (privkey->keyType) { - case lowRSAKey: + case NSSLOWKEYRSAKey: newkey.data = privkey->u.rsa.modulus.data; newkey.size = privkey->u.rsa.modulus.len; break; - case lowDSAKey: + case NSSLOWKEYDSAKey: newkey.data = privkey->u.dsa.publicValue.data; newkey.size = privkey->u.dsa.publicValue.len; break; - case lowDHKey: + case NSSLOWKEYDHKey: newkey.data = privkey->u.dh.publicValue.data; newkey.size = privkey->u.dh.publicValue.len; break; default: - /* XXX We don't do Fortezza. */ return SECFailure; } @@ -2164,7 +2263,7 @@ ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, node = node->next; } - rv = SECKEY_SetKeyDBPasswordAlg(handle, newpwitem, new_algorithm); + rv = nsslowkey_SetKeyDBPasswordAlg(handle, newpwitem, new_algorithm); loser: @@ -2182,9 +2281,8 @@ loser: * in place in the original */ SECStatus -SECKEY_ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, - SECItem *oldpwitem, SECItem *newpwitem, - SECOidTag new_algorithm) +nsslowkey_ChangeKeyDBPassword(NSSLOWKEYDBHandle *handle, + SECItem *oldpwitem, SECItem *newpwitem) { SECStatus rv; @@ -2194,240 +2292,25 @@ SECKEY_ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, goto loser; } - rv = SECKEY_CheckKeyDBPassword(handle, oldpwitem); + rv = nsslowkey_CheckKeyDBPassword(handle, oldpwitem); if ( rv != SECSuccess ) { return(SECFailure); /* return rv? */ } - rv = ChangeKeyDBPasswordAlg(handle, oldpwitem, newpwitem, new_algorithm); + rv = ChangeKeyDBPasswordAlg(handle, oldpwitem, newpwitem, + nsslowkey_GetDefaultKeyDBAlg()); loser: return(rv); } -/* - * Second pass of updating the key db. This time we have a password. - */ -SECStatus -SECKEY_UpdateKeyDBPass2(SECKEYKeyDBHandle *handle, SECItem *pwitem) -{ - SECStatus rv; - - rv = ChangeKeyDBPasswordAlg(handle, pwitem, pwitem, - SECKEY_GetDefaultKeyDBAlg()); - - return(rv); -} - -/* - * currently updates key database from v2 to v3 - */ -SECStatus -SECKEY_UpdateKeyDBPass1(SECKEYKeyDBHandle *handle) -{ - SECStatus rv; - DBT versionKey; - DBT versionData; - DBT checkKey; - DBT checkData; - DBT saltKey; - DBT saltData; - DBT key; - DBT data; - SECItem *rc4key = NULL; - SECKEYDBKey *dbkey = NULL; - SECItem *oldSalt = NULL; - int ret; - SECItem checkitem; - - if ( handle->updatedb == NULL ) { - return(SECSuccess); - } - - /* - * check the version record - */ - versionKey.data = VERSION_STRING; - versionKey.size = sizeof(VERSION_STRING)-1; - - ret = (* handle->updatedb->get)(handle->updatedb, &versionKey, - &versionData, 0 ); - - if (ret) { - /* no version record, so old db never used */ - goto done; - } - - if ( ( versionData.size != 1 ) || - ( *((unsigned char *)versionData.data) != 2 ) ) { - /* corrupt or wrong version number so don't update */ - goto done; - } - - saltKey.data = SALT_STRING; - saltKey.size = sizeof(SALT_STRING) - 1; - - ret = (* handle->updatedb->get)(handle->updatedb, &saltKey, &saltData, 0); - if ( ret ) { - /* no salt in old db, so it is corrupted */ - goto done; - } - - oldSalt = decodeKeyDBGlobalSalt(&saltData); - if ( oldSalt == NULL ) { - /* bad salt in old db, so it is corrupted */ - goto done; - } - - /* - * look for a pw check entry - */ - checkKey.data = KEYDB_PW_CHECK_STRING; - checkKey.size = KEYDB_PW_CHECK_LEN; - - ret = (* handle->updatedb->get)(handle->updatedb, &checkKey, - &checkData, 0 ); - if (ret) { - /* - * if we have a key, but no KEYDB_PW_CHECK_STRING, then this must - * be an old server database, and it does have a password associated - * with it. Put a fake entry in so we can identify this db when we do - * get the password for it. - */ - if (seckey_HasAServerKey(handle->updatedb)) { - DBT fcheckKey; - DBT fcheckData; - - /* - * include a fake string - */ - fcheckKey.data = KEYDB_FAKE_PW_CHECK_STRING; - fcheckKey.size = KEYDB_FAKE_PW_CHECK_LEN; - fcheckData.data = "1"; - fcheckData.size = 1; - /* put global salt into the new database now */ - ret = (* handle->db->put)( handle->db, &saltKey, &saltData, 0); - if ( ret ) { - goto done; - } - ret = (* handle->db->put)( handle->db, &fcheckKey, &fcheckData, 0); - if ( ret ) { - goto done; - } - } else { - goto done; - } - } else { - /* put global salt into the new database now */ - ret = (* handle->db->put)( handle->db, &saltKey, &saltData, 0); - if ( ret ) { - goto done; - } - - dbkey = decode_dbkey(&checkData, 2); - if ( dbkey == NULL ) { - goto done; - } - checkitem = dbkey->derPK; - dbkey->derPK.data = NULL; - - /* format the new pw check entry */ - rv = encodePWCheckEntry(NULL, &dbkey->derPK, SEC_OID_RC4, &checkitem); - if ( rv != SECSuccess ) { - goto done; - } - - rv = put_dbkey(handle, &checkKey, dbkey, PR_TRUE); - if ( rv != SECSuccess ) { - goto done; - } - - /* free the dbkey */ - sec_destroy_dbkey(dbkey); - dbkey = NULL; - } - - - /* now traverse the database */ - ret = (* handle->updatedb->seq)(handle->updatedb, &key, &data, R_FIRST); - if ( ret ) { - goto done; - } - - do { - /* skip version record */ - if ( data.size > 1 ) { - /* skip salt */ - if ( key.size == ( sizeof(SALT_STRING) - 1 ) ) { - if ( PORT_Memcmp(key.data, SALT_STRING, key.size) == 0 ) { - continue; - } - } - /* skip pw check entry */ - if ( key.size == checkKey.size ) { - if ( PORT_Memcmp(key.data, checkKey.data, key.size) == 0 ) { - continue; - } - } - - /* keys stored by nickname will have 0 as the last byte of the - * db key. Other keys must be stored by modulus. We will not - * update those because they are left over from a keygen that - * never resulted in a cert. - */ - if ( ((unsigned char *)key.data)[key.size-1] != 0 ) { - continue; - } - - dbkey = decode_dbkey(&data, 2); - if ( dbkey == NULL ) { - continue; - } - - /* This puts the key into the new database with the same - * index (nickname) that it had before. The second pass - * of the update will have the password. It will decrypt - * and re-encrypt the entries using a new algorithm. - */ - dbkey->nickname = (char *)key.data; - rv = put_dbkey(handle, &key, dbkey, PR_FALSE); - dbkey->nickname = NULL; - - sec_destroy_dbkey(dbkey); - } - } while ( (* handle->updatedb->seq)(handle->updatedb, &key, &data, - R_NEXT) == 0 ); - - dbkey = NULL; - -done: - /* sync the database */ - ret = (* handle->db->sync)(handle->db, 0); - - (* handle->updatedb->close)(handle->updatedb); - handle->updatedb = NULL; - - if ( rc4key ) { - SECITEM_FreeItem(rc4key, PR_TRUE); - } - - if ( oldSalt ) { - SECITEM_FreeItem(oldSalt, PR_TRUE); - } - - if ( dbkey ) { - sec_destroy_dbkey(dbkey); - } - - return(SECSuccess); -} #define MAX_DB_SIZE 0xffff /* * Clear out all the keys in the existing database */ SECStatus -SECKEY_ResetKeyDB(SECKEYKeyDBHandle *handle) +nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle) { SECStatus rv; int ret; @@ -2478,12 +2361,3 @@ done: return (errors == 0 ? SECSuccess : SECFailure); } - -/* These functions simply return the address of the above-declared templates. -** This is necessary for Windows DLLs. Sigh. -*/ -SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PrivateKeyInfoTemplate) -SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToPrivateKeyInfoTemplate) -SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_EncryptedPrivateKeyInfoTemplate) -SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate) - diff --git a/security/nss/lib/softoken/private.h b/security/nss/lib/softoken/keydbi.h index 0125c7e7b..28eb962ad 100644 --- a/security/nss/lib/softoken/private.h +++ b/security/nss/lib/softoken/keydbi.h @@ -35,8 +35,8 @@ * $Id$ */ -#ifndef _PRIVATE_H_ -#define _PRIVATE_H_ +#ifndef _KEYDBI_H_ +#define _KEYDBI_H_ #include "nspr.h" #include "seccomon.h" @@ -45,7 +45,7 @@ /* * Handle structure for open key databases */ -struct SECKEYKeyDBHandleStr { +struct NSSLOWKEYDBHandleStr { DB *db; DB *updatedb; /* used when updating an old version */ SECItem *global_salt; /* password hashing salt for this db */ @@ -60,7 +60,7 @@ struct SECKEYKeyDBHandleStr { ** "data" is the key data ** "pdata" is the user's data */ -typedef SECStatus (* SECKEYTraverseKeysFunc)(DBT *key, DBT *data, void *pdata); +typedef SECStatus (* NSSLOWKEYTraverseKeysFunc)(DBT *key, DBT *data, void *pdata); SEC_BEGIN_PROTOS @@ -71,10 +71,10 @@ SEC_BEGIN_PROTOS ** "f" is the user function to call for each key ** "udata" is the user's data, which is passed through to "f" */ -extern SECStatus SECKEY_TraverseKeys(SECKEYKeyDBHandle *handle, - SECKEYTraverseKeysFunc f, +extern SECStatus NSSLOWKEY_TraverseKeys(NSSLOWKEYDBHandle *handle, + NSSLOWKEYTraverseKeysFunc f, void *udata); SEC_END_PROTOS -#endif /* _PRIVATE_H_ */ +#endif /* _KEYDBI_H_ */ diff --git a/security/nss/lib/softoken/keydbt.h b/security/nss/lib/softoken/keydbt.h deleted file mode 100644 index 5cb574b47..000000000 --- a/security/nss/lib/softoken/keydbt.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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. - * - * keydbt.h - private data structures for the private key library - * - * $Id$ - */ - -#ifndef _KEYDBT_H_ -#define _KEYDBT_H_ - -#include "prtypes.h" -#include "plarena.h" -#include "secitem.h" -#include "secasn1t.h" -#include "secmodt.h" -#include "pkcs11t.h" - - -/* - * a key in/for the data base - */ -struct SECKEYDBKeyStr { - PLArenaPool *arena; - int version; - char *nickname; - SECItem salt; - SECItem derPK; -}; -typedef struct SECKEYDBKeyStr SECKEYDBKey; - -typedef struct SECKEYKeyDBHandleStr SECKEYKeyDBHandle; - -#define PRIVATE_KEY_DB_FILE_VERSION 3 - -#define SEC_PRIVATE_KEY_VERSION 0 /* what we *create* */ - -/* -** Typedef for callback to get a password "key". -*/ -typedef SECItem * (* SECKEYLowGetPasswordKey)(void *arg, - SECKEYKeyDBHandle *handle); - -extern const SEC_ASN1Template SECKEY_LowPQGParamsTemplate[]; -extern const SEC_ASN1Template SECKEY_LowRSAPrivateKeyTemplate[]; -extern const SEC_ASN1Template SECKEY_LowDSAPrivateKeyTemplate[]; -extern const SEC_ASN1Template SECKEY_LowDSAPrivateKeyExportTemplate[]; -extern const SEC_ASN1Template SECKEY_LowDHPrivateKeyTemplate[]; -extern const SEC_ASN1Template SECKEY_LowDHPrivateKeyExportTemplate[]; - -extern const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[]; -extern const SEC_ASN1Template SECKEY_AttributeTemplate[]; - -/* These functions simply return the address of the above-declared templates. -** This is necessary for Windows DLLs. Sigh. -*/ -extern SEC_ASN1TemplateChooser NSS_Get_SECKEY_EncryptedPrivateKeyInfoTemplate; - -#endif /* _KEYDBT_H_ */ diff --git a/security/nss/lib/softoken/keytboth.h b/security/nss/lib/softoken/keytboth.h deleted file mode 100644 index 0e4816cb6..000000000 --- a/security/nss/lib/softoken/keytboth.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ -#ifndef _KEYTBOTH_H_ -#define _KEYTBOTH_H_ 1 - -#include "blapit.h" -#include "secoidt.h" - -/* -** Attributes -*/ -struct SECKEYAttributeStr { - SECItem attrType; - SECItem **attrValue; -}; -typedef struct SECKEYAttributeStr SECKEYAttribute; - -/* -** A PKCS#8 private key info object -*/ -struct PrivateKeyInfoStr { - PLArenaPool *arena; - SECItem version; - SECAlgorithmID algorithm; - SECItem privateKey; - SECKEYAttribute **attributes; -}; -typedef struct PrivateKeyInfoStr PrivateKeyInfo; -#define SEC_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */ - -/* -** A PKCS#8 private key info object -*/ -struct EncryptedPrivateKeyInfoStr { - PLArenaPool *arena; - SECAlgorithmID algorithm; - SECItem encryptedData; -}; -typedef struct EncryptedPrivateKeyInfoStr EncryptedPrivateKeyInfo; - -#endif /* _KEYT_H_ */ diff --git a/security/nss/lib/softoken/keytlow.h b/security/nss/lib/softoken/keytlow.h deleted file mode 100644 index 3c0c55ab0..000000000 --- a/security/nss/lib/softoken/keytlow.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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. - */ -#ifndef _KEYTLOW_H_ -#define _KEYTLOW_H_ 1 - -#include "blapit.h" - -typedef enum { - lowNullKey = 0, - lowRSAKey = 1, - lowDSAKey = 2, - lowDHKey = 4 -} LowKeyType; - -/* -** An RSA public key object. -*/ -struct SECKEYLowPublicKeyStr { - PLArenaPool *arena; - LowKeyType keyType ; - union { - RSAPublicKey rsa; - DSAPublicKey dsa; - DHPublicKey dh; - } u; -}; -typedef struct SECKEYLowPublicKeyStr SECKEYLowPublicKey; - -/* -** Low Level private key object -** This is only used by the raw Crypto engines (crypto), keydb (keydb), -** and PKCS #11. Everyone else uses the high level key structure. -*/ -struct SECKEYLowPrivateKeyStr { - PLArenaPool *arena; - LowKeyType keyType; - union { - RSAPrivateKey rsa; - DSAPrivateKey dsa; - DHPrivateKey dh; - } u; -}; -typedef struct SECKEYLowPrivateKeyStr SECKEYLowPrivateKey; - -#endif /* _KEYTLOW_H_ */ diff --git a/security/nss/lib/softoken/lowcert.c b/security/nss/lib/softoken/lowcert.c new file mode 100644 index 000000000..0cea4e396 --- /dev/null +++ b/security/nss/lib/softoken/lowcert.c @@ -0,0 +1,525 @@ +/* + * 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. + */ + +/* + * Certificate handling code + * + * $Id$ + */ + +#include "seccomon.h" +#include "secder.h" +#include "nssilock.h" +#include "prmon.h" +#include "prtime.h" +#include "lowkeyi.h" +#include "pcert.h" +#include "secasn1.h" +#include "secoid.h" + +/* should have been in a 'util' header */ +extern const SEC_ASN1Template CERT_ValidityTemplate[]; + +static const SEC_ASN1Template nsslowcert_CertKeyTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSSLOWCERTCertKey) }, + { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_CONTEXT_SPECIFIC | 0, 0, SEC_SkipTemplate }, /* version */ + { SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertKey,serialNumber) }, + { SEC_ASN1_SKIP }, /* signature algorithm */ + { SEC_ASN1_ANY, offsetof(NSSLOWCERTCertKey,derIssuer) }, + { SEC_ASN1_SKIP_REST }, + { 0 } +}; + +const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSubjectPublicKeyInfo) }, + { SEC_ASN1_INLINE, offsetof(NSSLOWCERTSubjectPublicKeyInfo,algorithm), + SECOID_AlgorithmIDTemplate }, + { SEC_ASN1_BIT_STRING, + offsetof(NSSLOWCERTSubjectPublicKeyInfo,subjectPublicKey), }, + { 0, } +}; + +const SEC_ASN1Template nsslowcert_CertificateTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSSLOWCERTCertificate) }, + { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_CONTEXT_SPECIFIC | 0, 0, SEC_SkipTemplate }, /* version */ + { SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertificate,serialNumber) }, + { SEC_ASN1_SKIP }, /* Signature algorithm */ + { SEC_ASN1_ANY, offsetof(NSSLOWCERTCertificate,derIssuer) }, + { SEC_ASN1_INLINE, + offsetof(NSSLOWCERTCertificate,validity), + CERT_ValidityTemplate }, + { SEC_ASN1_ANY, offsetof(NSSLOWCERTCertificate,derSubject) }, + { SEC_ASN1_INLINE, + offsetof(NSSLOWCERTCertificate,subjectPublicKeyInfo), + nsslowcert_SubjectPublicKeyInfoTemplate }, + { SEC_ASN1_SKIP_REST }, + { 0 } +}; +const SEC_ASN1Template nsslowcert_SignedCertificateTemplate[] = +{ + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTCertificate) }, + { SEC_ASN1_INLINE, 0, nsslowcert_CertificateTemplate }, + { SEC_ASN1_SKIP_REST }, + { 0 } +}; +const SEC_ASN1Template nsslowcert_SignedDataTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSignedData) }, + { SEC_ASN1_ANY, offsetof(NSSLOWCERTSignedData,data), }, + { SEC_ASN1_SKIP_REST }, + { 0, } +}; +const SEC_ASN1Template nsslowcert_RSAPublicKeyTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.modulus), }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.publicExponent), }, + { 0, } +}; +const SEC_ASN1Template nsslowcert_DSAPublicKeyTemplate[] = { + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dsa.publicValue), }, + { 0, } +}; +const SEC_ASN1Template nsslowcert_DHPublicKeyTemplate[] = { + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dh.publicValue), }, + { 0, } +}; + + +static PZLock *pcertRefCountLock = NULL; + +/* + * Acquire the cert reference count lock + * There is currently one global lock for all certs, but I'm putting a cert + * arg here so that it will be easy to make it per-cert in the future if + * that turns out to be necessary. + */ +void +nsslowcert_LockCertRefCount(NSSLOWCERTCertificate *cert) +{ + if ( pcertRefCountLock == NULL ) { + nss_InitLock(&pcertRefCountLock, nssILockRefLock); + PORT_Assert(pcertRefCountLock != NULL); + } + + PZ_Lock(pcertRefCountLock); + return; +} + +/* + * Free the cert reference count lock + */ +void +nsslowcert_UnlockCertRefCount(NSSLOWCERTCertificate *cert) +{ + PRStatus prstat; + + PORT_Assert(pcertRefCountLock != NULL); + + prstat = PZ_Unlock(pcertRefCountLock); + + PORT_Assert(prstat == PR_SUCCESS); + + return; +} + + +NSSLOWCERTCertificate * +nsslowcert_DupCertificate(NSSLOWCERTCertificate *c) +{ + if (c) { + nsslowcert_LockCertRefCount(c); + ++c->referenceCount; + nsslowcert_UnlockCertRefCount(c); + } + return c; +} + +/* + * Allow use of default cert database, so that apps(such as mozilla) don't + * have to pass the handle all over the place. + */ +static NSSLOWCERTCertDBHandle *default_pcert_db_handle = 0; + +void +nsslowcert_SetDefaultCertDB(NSSLOWCERTCertDBHandle *handle) +{ + default_pcert_db_handle = handle; + + return; +} + +NSSLOWCERTCertDBHandle * +nsslowcert_GetDefaultCertDB(void) +{ + return(default_pcert_db_handle); +} + + +SECStatus +nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter) +{ + int rv; + + /* convert DER not-before time */ + rv = DER_UTCTimeToTime(notBefore, &c->validity.notBefore); + if (rv) { + return(SECFailure); + } + + /* convert DER not-after time */ + rv = DER_UTCTimeToTime(notAfter, &c->validity.notAfter); + if (rv) { + return(SECFailure); + } + + return(SECSuccess); +} + +/* + * is certa newer than certb? If one is expired, pick the other one. + */ +PRBool +nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb) +{ + PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now; + SECStatus rv; + PRBool newerbefore, newerafter; + + rv = nsslowcert_GetCertTimes(certa, ¬BeforeA, ¬AfterA); + if ( rv != SECSuccess ) { + return(PR_FALSE); + } + + rv = nsslowcert_GetCertTimes(certb, ¬BeforeB, ¬AfterB); + if ( rv != SECSuccess ) { + return(PR_TRUE); + } + + newerbefore = PR_FALSE; + if ( LL_CMP(notBeforeA, >, notBeforeB) ) { + newerbefore = PR_TRUE; + } + + newerafter = PR_FALSE; + if ( LL_CMP(notAfterA, >, notAfterB) ) { + newerafter = PR_TRUE; + } + + if ( newerbefore && newerafter ) { + return(PR_TRUE); + } + + if ( ( !newerbefore ) && ( !newerafter ) ) { + return(PR_FALSE); + } + + /* get current UTC time */ + now = PR_Now(); + + if ( newerbefore ) { + /* cert A was issued after cert B, but expires sooner */ + /* if A is expired, then pick B */ + if ( LL_CMP(notAfterA, <, now ) ) { + return(PR_FALSE); + } + return(PR_TRUE); + } else { + /* cert B was issued after cert A, but expires sooner */ + /* if B is expired, then pick A */ + if ( LL_CMP(notAfterB, <, now ) ) { + return(PR_TRUE); + } + return(PR_FALSE); + } +} + +#define SOFT_DEFAULT_CHUNKSIZE 2048 + +/* + * take a DER certificate and decode it into a certificate structure + */ +NSSLOWCERTCertificate * +nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, + char *nickname) +{ + NSSLOWCERTCertificate *cert; + PRArenaPool *arena; + void *data; + int rv; + int len; + + /* make a new arena */ + arena = PORT_NewArena(SOFT_DEFAULT_CHUNKSIZE); + + if ( !arena ) { + return 0; + } + + /* allocate the certificate structure */ + cert = (NSSLOWCERTCertificate *)PORT_ArenaZAlloc(arena, sizeof(NSSLOWCERTCertificate)); + + if ( !cert ) { + goto loser; + } + + cert->arena = arena; + + if ( copyDER ) { + /* copy the DER data for the cert into this arena */ + data = (void *)PORT_ArenaAlloc(arena, derSignedCert->len); + if ( !data ) { + goto loser; + } + cert->derCert.data = (unsigned char *)data; + cert->derCert.len = derSignedCert->len; + PORT_Memcpy(data, derSignedCert->data, derSignedCert->len); + } else { + /* point to passed in DER data */ + cert->derCert = *derSignedCert; + } + + /* decode the certificate info */ + rv = SEC_ASN1DecodeItem(arena, cert, nsslowcert_SignedCertificateTemplate, + &cert->derCert); + + /* cert->subjectKeyID; x509v3 subject key identifier */ + cert->dbEntry = NULL; + cert ->trust = NULL; + +#ifdef notdef + /* these fields are used by client GUI code to keep track of ssl sockets + * that are blocked waiting on GUI feedback related to this cert. + * XXX - these should be moved into some sort of application specific + * data structure. They are only used by the browser right now. + */ + struct SECSocketNode *socketlist; + int socketcount; + struct SECSocketNode *authsocketlist; + int authsocketcount; + + /* This is PKCS #11 stuff. */ + PK11SlotInfo *slot; /*if this cert came of a token, which is it*/ + CK_OBJECT_HANDLE pkcs11ID; /*and which object on that token is it */ + PRBool ownSlot; /*true if the cert owns the slot reference */ +#endif + + /* generate and save the database key for the cert */ + rv = nsslowcert_KeyFromDERCert(arena, &cert->derCert, &cert->certKey); + if ( rv ) { + goto loser; + } + + /* set the nickname */ + if ( nickname == NULL ) { + cert->nickname = NULL; + } else { + /* copy and install the nickname */ + len = PORT_Strlen(nickname) + 1; + cert->nickname = (char*)PORT_ArenaAlloc(arena, len); + if ( cert->nickname == NULL ) { + goto loser; + } + + PORT_Memcpy(cert->nickname, nickname, len); + } + +#ifdef FIXME + /* initialize the subjectKeyID */ + rv = cert_GetKeyID(cert); + if ( rv != SECSuccess ) { + goto loser; + } + + /* set the email address */ + cert->emailAddr = CERT_GetCertificateEmailAddress(cert); + +#endif + + cert->referenceCount = 1; + + return(cert); + +loser: + + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(0); +} + +char * +nsslowcert_FixupEmailAddr(char *emailAddr) +{ + char *retaddr; + char *str; + + if ( emailAddr == NULL ) { + return(NULL); + } + + /* copy the string */ + str = retaddr = PORT_Strdup(emailAddr); + if ( str == NULL ) { + return(NULL); + } + + /* make it lower case */ + while ( *str ) { + *str = tolower( *str ); + str++; + } + + return(retaddr); +} + +static SECStatus +nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena, SECItem *issuer, SECItem *sn, + SECItem *key) +{ + key->len = sn->len + issuer->len; + + key->data = (unsigned char*)PORT_ArenaAlloc(arena, key->len); + if ( !key->data ) { + goto loser; + } + + /* copy the serialNumber */ + PORT_Memcpy(key->data, sn->data, sn->len); + + /* copy the issuer */ + PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len); + + return(SECSuccess); + +loser: + return(SECFailure); +} + + + +/* + * Generate a database key, based on serial number and issuer, from a + * DER certificate. + */ +SECStatus +nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key) +{ + int rv; + NSSLOWCERTSignedData sd; + NSSLOWCERTCertKey certkey; + + PORT_Memset(&sd, 0, sizeof(NSSLOWCERTSignedData)); + PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey)); + + rv = SEC_ASN1DecodeItem(arena, &sd, nsslowcert_SignedDataTemplate, derCert); + + if ( rv ) { + goto loser; + } + + PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey)); + rv = SEC_ASN1DecodeItem(arena, &certkey, + nsslowcert_CertKeyTemplate, &sd.data); + + if ( rv ) { + goto loser; + } + + return(nsslowcert_KeyFromIssuerAndSN(arena, &certkey.derIssuer, + &certkey.serialNumber, key)); +loser: + return(SECFailure); +} + +NSSLOWKEYPublicKey * +nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert) +{ + NSSLOWCERTSubjectPublicKeyInfo *spki = &cert->subjectPublicKeyInfo; + NSSLOWKEYPublicKey *pubk; + SECItem os; + SECStatus rv; + PRArenaPool *arena; + SECOidTag tag; + + arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) + return NULL; + + pubk = (NSSLOWKEYPublicKey *) + PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYPublicKey)); + if (pubk == NULL) { + PORT_FreeArena (arena, PR_FALSE); + return NULL; + } + + pubk->arena = arena; + + /* Convert bit string length from bits to bytes */ + os = spki->subjectPublicKey; + DER_ConvertBitString (&os); + + tag = SECOID_GetAlgorithmTag(&spki->algorithm); + switch ( tag ) { + case SEC_OID_X500_RSA_ENCRYPTION: + case SEC_OID_PKCS1_RSA_ENCRYPTION: + pubk->keyType = NSSLOWKEYRSAKey; + rv = SEC_ASN1DecodeItem(arena, pubk, + nsslowcert_RSAPublicKeyTemplate, &os); + if (rv == SECSuccess) + return pubk; + break; + case SEC_OID_ANSIX9_DSA_SIGNATURE: + pubk->keyType = NSSLOWKEYDSAKey; + rv = SEC_ASN1DecodeItem(arena, pubk, + nsslowcert_DSAPublicKeyTemplate, &os); + if (rv == SECSuccess) return pubk; + break; + case SEC_OID_X942_DIFFIE_HELMAN_KEY: + pubk->keyType = NSSLOWKEYDHKey; + rv = SEC_ASN1DecodeItem(arena, pubk, + nsslowcert_DHPublicKeyTemplate, &os); + if (rv == SECSuccess) return pubk; + break; + default: + rv = SECFailure; + break; + } + + nsslowkey_DestroyPublicKey (pubk); + return NULL; +} + diff --git a/security/nss/lib/softoken/lowkey.c b/security/nss/lib/softoken/lowkey.c index fafbf361e..3d7cfa94a 100644 --- a/security/nss/lib/softoken/lowkey.c +++ b/security/nss/lib/softoken/lowkey.c @@ -30,17 +30,17 @@ * may use your version of this file under either the MPL or the * GPL. */ -#include "keylow.h" +#include "lowkeyi.h" #include "secoid.h" #include "secitem.h" #include "secder.h" #include "base64.h" #include "secasn1.h" -#include "cert.h" +#include "pcert.h" #include "secerr.h" -const SEC_ASN1Template SECKEY_LowPQGParamsTemplate[] = { +const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) }, { SEC_ASN1_INTEGER, offsetof(PQGParams,prime) }, { SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) }, @@ -48,43 +48,43 @@ const SEC_ASN1Template SECKEY_LowPQGParamsTemplate[] = { { 0, } }; -const SEC_ASN1Template SECKEY_LowRSAPrivateKeyTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPrivateKey) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.version) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.modulus) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.publicExponent) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.privateExponent) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.prime1) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.prime2) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.exponent1) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.exponent2) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.coefficient) }, +const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) }, { 0 } }; -const SEC_ASN1Template SECKEY_LowDSAPrivateKeyTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYLowPrivateKey) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dsa.publicValue) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dsa.privateValue) }, +const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.publicValue) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) }, { 0, } }; -const SEC_ASN1Template SECKEY_LowDSAPrivateKeyExportTemplate[] = { - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dsa.privateValue) }, +const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = { + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) }, }; -const SEC_ASN1Template SECKEY_LowDHPrivateKeyTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYLowPrivateKey) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dh.publicValue) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dh.privateValue) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dh.base) }, - { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dh.prime) }, +const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.publicValue) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.privateValue) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.base) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.prime) }, { 0, } }; void -SECKEY_LowDestroyPrivateKey(SECKEYLowPrivateKey *privk) +nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk) { if (privk && privk->arena) { PORT_FreeArena(privk->arena, PR_TRUE); @@ -92,14 +92,14 @@ SECKEY_LowDestroyPrivateKey(SECKEYLowPrivateKey *privk) } void -SECKEY_LowDestroyPublicKey(SECKEYLowPublicKey *pubk) +nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk) { if (pubk && pubk->arena) { PORT_FreeArena(pubk->arena, PR_FALSE); } } unsigned -SECKEY_LowPublicModulusLen(SECKEYLowPublicKey *pubk) +nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk) { unsigned char b0; @@ -107,7 +107,7 @@ SECKEY_LowPublicModulusLen(SECKEYLowPublicKey *pubk) * fortezza that's the public key length */ switch (pubk->keyType) { - case lowRSAKey: + case NSSLOWKEYRSAKey: b0 = pubk->u.rsa.modulus.data[0]; return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1; default: @@ -117,13 +117,13 @@ SECKEY_LowPublicModulusLen(SECKEYLowPublicKey *pubk) } unsigned -SECKEY_LowPrivateModulusLen(SECKEYLowPrivateKey *privk) +nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk) { unsigned char b0; switch (privk->keyType) { - case lowRSAKey: + case NSSLOWKEYRSAKey: b0 = privk->u.rsa.modulus.data[0]; return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len - 1; default: @@ -132,10 +132,10 @@ SECKEY_LowPrivateModulusLen(SECKEYLowPrivateKey *privk) return 0; } -SECKEYLowPublicKey * -SECKEY_LowConvertToPublicKey(SECKEYLowPrivateKey *privk) +NSSLOWKEYPublicKey * +nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk) { - SECKEYLowPublicKey *pubk; + NSSLOWKEYPublicKey *pubk; PLArenaPool *arena; @@ -146,16 +146,16 @@ SECKEY_LowConvertToPublicKey(SECKEYLowPrivateKey *privk) } switch(privk->keyType) { - case lowRSAKey: - case nullKey: - pubk = (SECKEYLowPublicKey *)PORT_ArenaZAlloc(arena, - sizeof (SECKEYLowPublicKey)); + case NSSLOWKEYRSAKey: + case NSSLOWKEYNullKey: + pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, + sizeof (NSSLOWKEYPublicKey)); if (pubk != NULL) { SECStatus rv; pubk->arena = arena; pubk->keyType = privk->keyType; - if (privk->keyType == nullKey) return pubk; + if (privk->keyType == NSSLOWKEYNullKey) return pubk; rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus, &privk->u.rsa.modulus); if (rv == SECSuccess) { @@ -164,14 +164,14 @@ SECKEY_LowConvertToPublicKey(SECKEYLowPrivateKey *privk) if (rv == SECSuccess) return pubk; } - SECKEY_LowDestroyPublicKey (pubk); + nsslowkey_DestroyPublicKey (pubk); } else { PORT_SetError (SEC_ERROR_NO_MEMORY); } break; - case lowDSAKey: - pubk = (SECKEYLowPublicKey *)PORT_ArenaZAlloc(arena, - sizeof(SECKEYLowPublicKey)); + case NSSLOWKEYDSAKey: + pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, + sizeof(NSSLOWKEYPublicKey)); if (pubk != NULL) { SECStatus rv; @@ -191,9 +191,9 @@ SECKEY_LowConvertToPublicKey(SECKEYLowPrivateKey *privk) if (rv == SECSuccess) return pubk; } break; - case lowDHKey: - pubk = (SECKEYLowPublicKey *)PORT_ArenaZAlloc(arena, - sizeof(SECKEYLowPublicKey)); + case NSSLOWKEYDHKey: + pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, + sizeof(NSSLOWKEYPublicKey)); if (pubk != NULL) { SECStatus rv; @@ -220,10 +220,10 @@ SECKEY_LowConvertToPublicKey(SECKEYLowPrivateKey *privk) return NULL; } -SECKEYLowPrivateKey * -SECKEY_CopyLowPrivateKey(SECKEYLowPrivateKey *privKey) +NSSLOWKEYPrivateKey * +nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey) { - SECKEYLowPrivateKey *returnKey = NULL; + NSSLOWKEYPrivateKey *returnKey = NULL; SECStatus rv = SECFailure; PLArenaPool *poolp; @@ -236,7 +236,7 @@ SECKEY_CopyLowPrivateKey(SECKEYLowPrivateKey *privKey) return NULL; } - returnKey = (SECKEYLowPrivateKey*)PORT_ArenaZAlloc(poolp, sizeof(SECKEYLowPrivateKey)); + returnKey = (NSSLOWKEYPrivateKey*)PORT_ArenaZAlloc(poolp, sizeof(NSSLOWKEYPrivateKey)); if(!returnKey) { rv = SECFailure; goto loser; @@ -246,7 +246,7 @@ SECKEY_CopyLowPrivateKey(SECKEYLowPrivateKey *privKey) returnKey->arena = poolp; switch(privKey->keyType) { - case lowRSAKey: + case NSSLOWKEYRSAKey: rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.modulus), &(privKey->u.rsa.modulus)); if(rv != SECSuccess) break; @@ -275,7 +275,7 @@ SECKEY_CopyLowPrivateKey(SECKEYLowPrivateKey *privKey) &(privKey->u.rsa.coefficient)); if(rv != SECSuccess) break; break; - case lowDSAKey: + case NSSLOWKEYDSAKey: rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.publicValue), &(privKey->u.dsa.publicValue)); if(rv != SECSuccess) break; @@ -293,7 +293,7 @@ SECKEY_CopyLowPrivateKey(SECKEYLowPrivateKey *privKey) &(privKey->u.dsa.params.base)); if(rv != SECSuccess) break; break; - case lowDHKey: + case NSSLOWKEYDHKey: rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.publicValue), &(privKey->u.dh.publicValue)); if(rv != SECSuccess) break; diff --git a/security/nss/lib/softoken/keylow.h b/security/nss/lib/softoken/lowkeyi.h index 3c7679b3a..0a58b1fa3 100644 --- a/security/nss/lib/softoken/keylow.h +++ b/security/nss/lib/softoken/lowkeyi.h @@ -35,65 +35,64 @@ * $Id$ */ -#ifndef _KEYLOW_H_ -#define _KEYLOW_H_ +#ifndef _LOWKEYI_H_ +#define _LOWKEYI_H_ #include "prtypes.h" #include "seccomon.h" -#include "keydbt.h" #include "secoidt.h" -#include "certt.h" -#include "keytlow.h" +#include "pcertt.h" +#include "lowkeyti.h" SEC_BEGIN_PROTOS -typedef char * (* SECKEYDBNameFunc)(void *arg, int dbVersion); +typedef char * (* NSSLOWKEYDBNameFunc)(void *arg, int dbVersion); /* ** Open a key database. */ -extern SECKEYKeyDBHandle *SECKEY_OpenKeyDB(PRBool readOnly, - SECKEYDBNameFunc namecb, +extern NSSLOWKEYDBHandle *nsslowkey_OpenKeyDB(PRBool readOnly, + NSSLOWKEYDBNameFunc namecb, void *cbarg); -extern SECKEYKeyDBHandle *SECKEY_OpenKeyDBFilename(char *filename, +extern NSSLOWKEYDBHandle *nsslowkey_OpenKeyDBFilename(char *filename, PRBool readOnly); /* ** Update the database */ -extern SECStatus SECKEY_UpdateKeyDBPass1(SECKEYKeyDBHandle *handle); -extern SECStatus SECKEY_UpdateKeyDBPass2(SECKEYKeyDBHandle *handle, +extern SECStatus nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle); +extern SECStatus nsslowkey_UpdateKeyDBPass2(NSSLOWKEYDBHandle *handle, SECItem *pwitem); /* * Clear out all the keys in the existing database */ -extern SECStatus SECKEY_ResetKeyDB(SECKEYKeyDBHandle *handle); +extern SECStatus nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle); /* ** Close the specified key database. */ -extern void SECKEY_CloseKeyDB(SECKEYKeyDBHandle *handle); +extern void nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle); /* * Get the version number of the database */ -extern int SECKEY_GetKeyDBVersion(SECKEYKeyDBHandle *handle); +extern int nsslowkey_GetKeyDBVersion(NSSLOWKEYDBHandle *handle); /* ** Support a default key database. */ -extern void SECKEY_SetDefaultKeyDB(SECKEYKeyDBHandle *handle); -extern SECKEYKeyDBHandle *SECKEY_GetDefaultKeyDB(void); +extern void nsslowkey_SetDefaultKeyDB(NSSLOWKEYDBHandle *handle); +extern NSSLOWKEYDBHandle *nsslowkey_GetDefaultKeyDB(void); /* set the alg id of the key encryption algorithm */ -extern void SECKEY_SetDefaultKeyDBAlg(SECOidTag alg); +extern void nsslowkey_SetDefaultKeyDBAlg(SECOidTag alg); /* * given a password and salt, produce a hash of the password */ -extern SECItem *SECKEY_HashPassword(char *pw, SECItem *salt); +extern SECItem *nsslowkey_HashPassword(char *pw, SECItem *salt); /* * Derive the actual password value for a key database from the @@ -101,12 +100,12 @@ extern SECItem *SECKEY_HashPassword(char *pw, SECItem *salt); * stored in the key database. */ extern SECItem * -SECKEY_DeriveKeyDBPassword(SECKEYKeyDBHandle *handle, char *pw); +nsslowkey_DeriveKeyDBPassword(NSSLOWKEYDBHandle *handle, char *pw); /* ** Delete a key from the database */ -extern SECStatus SECKEY_DeleteKey(SECKEYKeyDBHandle *handle, +extern SECStatus nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle, SECItem *pubkey); /* @@ -115,27 +114,22 @@ extern SECStatus SECKEY_DeleteKey(SECKEYKeyDBHandle *handle, ** "f" is a the callback function for getting the password ** "arg" is the argument for the callback */ -extern SECStatus SECKEY_StoreKeyByPublicKey(SECKEYKeyDBHandle *handle, - SECKEYLowPrivateKey *pk, +extern SECStatus nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle, + NSSLOWKEYPrivateKey *pk, SECItem *pubKeyData, char *nickname, - SECKEYLowGetPasswordKey f, - void *arg); + SECItem *arg); /* does the key for this cert exist in the database filed by modulus */ -extern SECStatus SECKEY_KeyForCertExists(SECKEYKeyDBHandle *handle, - CERTCertificate *cert); +extern PRBool nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, + NSSLOWCERTCertificate *cert); -SECKEYLowPrivateKey * -SECKEY_FindKeyByCert(SECKEYKeyDBHandle *handle, CERTCertificate *cert, - SECKEYLowGetPasswordKey f, void *arg); - -extern SECStatus SECKEY_HasKeyDBPassword(SECKEYKeyDBHandle *handle); -extern SECStatus SECKEY_SetKeyDBPassword(SECKEYKeyDBHandle *handle, +extern SECStatus nsslowkey_HasKeyDBPassword(NSSLOWKEYDBHandle *handle); +extern SECStatus nsslowkey_SetKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem); -extern SECStatus SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, +extern SECStatus nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem); -extern SECStatus SECKEY_ChangeKeyDBPassword(SECKEYKeyDBHandle *handle, +extern SECStatus nsslowkey_ChangeKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *oldpwitem, SECItem *newpwitem); @@ -144,32 +138,32 @@ extern SECStatus SECKEY_ChangeKeyDBPassword(SECKEYKeyDBHandle *handle, ** "key" the object ** "freeit" if PR_TRUE then free the object as well as its sub-objects */ -extern void SECKEY_LowDestroyPrivateKey(SECKEYLowPrivateKey *key); +extern void nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *key); /* ** Destroy a public key object. ** "key" the object ** "freeit" if PR_TRUE then free the object as well as its sub-objects */ -extern void SECKEY_LowDestroyPublicKey(SECKEYLowPublicKey *key); +extern void nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *key); /* ** Return the modulus length of "pubKey". */ -extern unsigned int SECKEY_LowPublicModulusLen(SECKEYLowPublicKey *pubKey); +extern unsigned int nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubKey); /* ** Return the modulus length of "privKey". */ -extern unsigned int SECKEY_LowPrivateModulusLen(SECKEYLowPrivateKey *privKey); +extern unsigned int nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privKey); /* ** Convert a low private key "privateKey" into a public low key */ -extern SECKEYLowPublicKey - *SECKEY_LowConvertToPublicKey(SECKEYLowPrivateKey *privateKey); +extern NSSLOWKEYPublicKey + *nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privateKey); /* * Set the Key Database password. @@ -181,7 +175,7 @@ extern SECKEYLowPublicKey * returned. */ extern SECStatus -SECKEY_SetKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, +nsslowkey_SetKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, SECItem *pwitem, SECOidTag algorithm); @@ -194,7 +188,7 @@ SECKEY_SetKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, * actual password. If it is not, SECFailure is returned. */ extern SECStatus -SECKEY_CheckKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, +nsslowkey_CheckKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, SECItem *pwitem, SECOidTag algorithm); @@ -210,7 +204,7 @@ SECKEY_CheckKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, * A return of anything but SECSuccess indicates failure. */ extern SECStatus -SECKEY_ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, +nsslowkey_ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, SECItem *oldpwitem, SECItem *newpwitem, SECOidTag old_algorithm); @@ -223,11 +217,11 @@ SECKEY_ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle, * A return of anything but SECSuccess indicates failure. */ extern SECStatus -SECKEY_StoreKeyByPublicKeyAlg(SECKEYKeyDBHandle *handle, - SECKEYLowPrivateKey *privkey, +nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle, + NSSLOWKEYPrivateKey *privkey, SECItem *pubKeyData, char *nickname, - SECKEYLowGetPasswordKey f, void *arg, + SECItem *arg, SECOidTag algorithm); /* Find key by modulus. This function is the inverse of store key @@ -236,17 +230,17 @@ SECKEY_StoreKeyByPublicKeyAlg(SECKEYKeyDBHandle *handle, * else NULL is returned. * modulus is the modulus to locate */ -extern SECKEYLowPrivateKey * -SECKEY_FindKeyByPublicKey(SECKEYKeyDBHandle *handle, SECItem *modulus, - SECKEYLowGetPasswordKey f, void *arg); +extern NSSLOWKEYPrivateKey * +nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus, + SECItem *arg); /* Make a copy of a low private key in it's own arena. * a return of NULL indicates an error. */ -extern SECKEYLowPrivateKey * -SECKEY_CopyLowPrivateKey(SECKEYLowPrivateKey *privKey); +extern NSSLOWKEYPrivateKey * +nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey); SEC_END_PROTOS -#endif /* _KEYLOW_H_ */ +#endif /* _LOWKEYI_H_ */ diff --git a/security/nss/lib/softoken/lowkeyti.h b/security/nss/lib/softoken/lowkeyti.h new file mode 100644 index 000000000..b8941bb0d --- /dev/null +++ b/security/nss/lib/softoken/lowkeyti.h @@ -0,0 +1,138 @@ +/* + * 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. + */ +#ifndef _LOWKEYTI_H_ +#define _LOWKEYTI_H_ 1 + +#include "blapit.h" +#include "prtypes.h" +#include "plarena.h" +#include "secitem.h" +#include "secasn1t.h" +#include "secoidt.h" +/*#include "secmodt.h" +#include "pkcs11t.h" */ + + +/* + * a key in/for the data base + */ +struct NSSLOWKEYDBKeyStr { + PLArenaPool *arena; + int version; + char *nickname; + SECItem salt; + SECItem derPK; +}; +typedef struct NSSLOWKEYDBKeyStr NSSLOWKEYDBKey; + +typedef struct NSSLOWKEYDBHandleStr NSSLOWKEYDBHandle; + +#define NSSLOWKEY_DB_FILE_VERSION 3 + +#define NSSLOWKEY_VERSION 0 /* what we *create* */ + +/* +** Typedef for callback to get a password "key". +*/ +extern const SEC_ASN1Template nsslowkey_PQGParamsTemplate[]; +extern const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[]; +extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[]; +extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[]; +extern const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[]; +extern const SEC_ASN1Template nsslowkey_DHPrivateKeyExportTemplate[]; + +extern const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[]; +extern const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[]; + + +/* +** A PKCS#8 private key info object +*/ +struct NSSLOWKEYPrivateKeyInfoStr { + PLArenaPool *arena; + SECItem version; + SECAlgorithmID algorithm; + SECItem privateKey; +}; +typedef struct NSSLOWKEYPrivateKeyInfoStr NSSLOWKEYPrivateKeyInfo; +#define NSSLOWKEY_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */ + +/* +** A PKCS#8 private key info object +*/ +struct NSSLOWKEYEncryptedPrivateKeyInfoStr { + PLArenaPool *arena; + SECAlgorithmID algorithm; + SECItem encryptedData; +}; +typedef struct NSSLOWKEYEncryptedPrivateKeyInfoStr NSSLOWKEYEncryptedPrivateKeyInfo; + + +typedef enum { + NSSLOWKEYNullKey = 0, + NSSLOWKEYRSAKey = 1, + NSSLOWKEYDSAKey = 2, + NSSLOWKEYDHKey = 4 +} NSSLOWKEYType; + +/* +** An RSA public key object. +*/ +struct NSSLOWKEYPublicKeyStr { + PLArenaPool *arena; + NSSLOWKEYType keyType ; + union { + RSAPublicKey rsa; + DSAPublicKey dsa; + DHPublicKey dh; + } u; +}; +typedef struct NSSLOWKEYPublicKeyStr NSSLOWKEYPublicKey; + +/* +** Low Level private key object +** This is only used by the raw Crypto engines (crypto), keydb (keydb), +** and PKCS #11. Everyone else uses the high level key structure. +*/ +struct NSSLOWKEYPrivateKeyStr { + PLArenaPool *arena; + NSSLOWKEYType keyType; + union { + RSAPrivateKey rsa; + DSAPrivateKey dsa; + DHPrivateKey dh; + } u; +}; +typedef struct NSSLOWKEYPrivateKeyStr NSSLOWKEYPrivateKey; + +#endif /* _LOWKEYTI_H_ */ diff --git a/security/nss/lib/softoken/lowpbe.c b/security/nss/lib/softoken/lowpbe.c new file mode 100644 index 000000000..cac83b90c --- /dev/null +++ b/security/nss/lib/softoken/lowpbe.c @@ -0,0 +1,1184 @@ +/* + * 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. + */ + +#include "plarena.h" + +#include "seccomon.h" +#include "secitem.h" +#include "secport.h" +#include "hasht.h" +#include "pkcs11t.h" +#include "blapi.h" +#include "hasht.h" +#include "secasn1.h" +#include "secder.h" +#include "lowpbe.h" +#include "secoid.h" +#include "alghmac.h" +#include "softoken.h" +#include "secerr.h" + +/* template for PKCS 5 PBE Parameter. This template has been expanded + * based upon the additions in PKCS 12. This should eventually be moved + * if RSA updates PKCS 5. + */ +static const SEC_ASN1Template NSSPKCS5PBEParameterTemplate[] = +{ + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSSPKCS5PBEParameter) }, + { SEC_ASN1_OCTET_STRING, + offsetof(NSSPKCS5PBEParameter, salt) }, + { SEC_ASN1_INTEGER, + offsetof(NSSPKCS5PBEParameter, iteration) }, + { 0 } +}; + +static const SEC_ASN1Template NSSPKCS5PKCS12V2PBEParameterTemplate[] = +{ + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSPKCS5PBEParameter) }, + { SEC_ASN1_OCTET_STRING, offsetof(NSSPKCS5PBEParameter, salt) }, + { SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, iteration) }, + { 0 } +}; + +SECStatus +nsspkcs5_HashBuf(const SECHashObject *hashObj, unsigned char *dest, + unsigned char *src, int len) +{ + void *ctx; + unsigned int retLen; + + ctx = hashObj->create(); + if(ctx == NULL) { + return SECFailure; + } + hashObj->begin(ctx); + hashObj->update(ctx, src, len); + hashObj->end(ctx, dest, &retLen, hashObj->length); + hashObj->destroy(ctx, PR_TRUE); + return SECSuccess; +} + +/* generate bits using any hash + */ +static SECItem * +nsspkcs5_PBKDF1(const SECHashObject *hashObj, SECItem *salt, SECItem *pwd, + int iter, PRBool faulty3DES) +{ + SECItem *hash = NULL, *pre_hash = NULL; + SECStatus rv = SECFailure; + + if((salt == NULL) || (pwd == NULL) || (iter < 0)) { + return NULL; + } + + hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + + if((hash != NULL) && (pre_hash != NULL)) { + int i, ph_len; + + ph_len = hashObj->length; + if((salt->len + pwd->len) > hashObj->length) { + ph_len = salt->len + pwd->len; + } + + rv = SECFailure; + + /* allocate buffers */ + hash->data = (unsigned char *)PORT_ZAlloc(SHA1_LENGTH); + hash->len = hashObj->length; + pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len); + + /* in pbeSHA1TripleDESCBC there was an allocation error that made + * it into the caller. We do not want to propagate those errors + * further, so we are doing it correctly, but reading the old method. + */ + if (faulty3DES) { + pre_hash->len = ph_len; + } else { + pre_hash->len = salt->len + pwd->len; + } + + /* preform hash */ + if ((hash->data != NULL) && (pre_hash->data != NULL)) { + rv = SECSuccess; + /* check for 0 length password */ + if(pwd->len > 0) { + PORT_Memcpy(pre_hash->data, pwd->data, pwd->len); + } + if(salt->len > 0) { + PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len); + } + for(i = 0; ((i < iter) && (rv == SECSuccess)); i++) { + rv = nsspkcs5_HashBuf(hashObj, hash->data, + pre_hash->data, pre_hash->len); + if(rv != SECFailure) { + pre_hash->len = hashObj->length; + PORT_Memcpy(pre_hash->data, hash->data, hashObj->length); + } + } + } + } + + if(pre_hash != NULL) { + SECITEM_FreeItem(pre_hash, PR_TRUE); + } + + if((rv != SECSuccess) && (hash != NULL)) { + SECITEM_FreeItem(hash, PR_TRUE); + hash = NULL; + } + + return hash; +} + +/* this bit generation routine is described in PKCS 12 and the proposed + * extensions to PKCS 5. an initial hash is generated following the + * instructions laid out in PKCS 5. If the number of bits generated is + * insufficient, then the method discussed in the proposed extensions to + * PKCS 5 in PKCS 12 are used. This extension makes use of the HMAC + * function. And the P_Hash function from the TLS standard. + */ +static SECItem * +nsspkcs5_PFXPBE(const SECHashObject *hashObj, NSSPKCS5PBEParameter *pbe_param, + SECItem *init_hash, unsigned int bytes_needed) +{ + SECItem *ret_bits = NULL; + int hash_size = 0; + unsigned int i; + unsigned int hash_iter; + unsigned int dig_len; + SECStatus rv = SECFailure; + unsigned char *state = NULL; + unsigned int state_len; + HMACContext *cx = NULL; + + hash_size = hashObj->length; + hash_iter = (bytes_needed + (unsigned int)hash_size - 1) / hash_size; + + /* allocate return buffer */ + ret_bits = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + if(ret_bits == NULL) + return NULL; + ret_bits->data = (unsigned char *)PORT_ZAlloc((hash_iter * hash_size) + 1); + ret_bits->len = (hash_iter * hash_size); + if(ret_bits->data == NULL) { + PORT_Free(ret_bits); + return NULL; + } + + /* allocate intermediate hash buffer. 8 is for the 8 bytes of + * data which are added based on iteration number + */ + + if ((unsigned int)hash_size > pbe_param->salt.len) { + state_len = hash_size; + } else { + state_len = pbe_param->salt.len; + } + state = (unsigned char *)PORT_ZAlloc(state_len); + if(state == NULL) { + rv = SECFailure; + goto loser; + } + if(pbe_param->salt.len > 0) { + PORT_Memcpy(state, pbe_param->salt.data, pbe_param->salt.len); + } + + cx = HMAC_Create(hashObj, init_hash->data, init_hash->len); + if (cx == NULL) { + rv = SECFailure; + goto loser; + } + + for(i = 0; i < hash_iter; i++) { + + /* generate output bits */ + HMAC_Begin(cx); + HMAC_Update(cx, state, state_len); + HMAC_Update(cx, pbe_param->salt.data, pbe_param->salt.len); + rv = HMAC_Finish(cx, ret_bits->data + (i * hash_size), + &dig_len, hash_size); + if (rv != SECSuccess) + goto loser; + PORT_Assert((unsigned int)hash_size == dig_len); + + /* generate new state */ + HMAC_Begin(cx); + HMAC_Update(cx, state, state_len); + rv = HMAC_Finish(cx, state, &state_len, state_len); + if (rv != SECSuccess) + goto loser; + PORT_Assert(state_len == dig_len); + } + +loser: + if (state != NULL) + PORT_ZFree(state, state_len); + HMAC_Destroy(cx); + + if(rv != SECSuccess) { + SECITEM_ZfreeItem(ret_bits, PR_TRUE); + ret_bits = NULL; + } + + return ret_bits; +} + +/* generate bits for the key and iv determination. if enough bits + * are not generated using PKCS 5, then we need to generate more bits + * based on the extension proposed in PKCS 12 + */ +static SECItem * +nsspkcs5_PBKDF1Extended(const SECHashObject *hashObj, + NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, PRBool faulty3DES) +{ + SECItem * hash = NULL; + SECItem * newHash = NULL; + int bytes_needed; + int bytes_available; + + bytes_needed = pbe_param->ivLen + pbe_param->keyLen; + bytes_available = hashObj->length; + + hash = nsspkcs5_PBKDF1(hashObj, &pbe_param->salt, pwitem, + pbe_param->iter, faulty3DES); + + if(hash == NULL) { + return NULL; + } + + if(bytes_needed <= bytes_available) { + return hash; + } + + newHash = nsspkcs5_PFXPBE(hashObj, pbe_param, hash, bytes_needed); + if (hash != newHash) + SECITEM_FreeItem(hash, PR_TRUE); + return newHash; +} + +#ifdef PBKDF2 + +/* + * PBDKDF2 is PKCS #5 v2.0 it's currently not used by NSS + */ +/* + * We This is safe because hLen for all our + * HMAC algorithms are multiples of 4. + */ +static void +xorbytes(unsigned char *dest, unsigned char *src, int len) +{ +#ifdef PARANOIA + while (len--) { + *dest = *dest ^ *src; + dest++; + src++; + } +#else + PRUInt32 dest32 = (PRUInt32 *)dest; + PRUInt32 src32 = (PRUInt32 *)dest; + while (len -= sizeof(PRUInt32)) { + *dest32 = *dest32 ^ *src32; + dest++; + src++; + } +#endif +} + +static SECStatus +nsspkcs5_PBKFD2_F(const SECHashObject *hashobj, SECItem *pwitem, SECItem *salt, + int iterations, unsigned int i, unsigned char *T) +{ + int j; + HMACContext *cx = NULL; + unsigned int hLen = hashObject->length + SECStatus rv = SECFailure; + unsigned char *last = NULL; + int lastLength = salt->len + 4; + + cx=HMAC_Create(hashobj,pwitem->data,pwitem->len); + if (cx == NULL) { + goto loser; + } + PORT_Memset(T,0,hLen); + realLastLength= MAX(lastLength,hLen); + last = PORT_Alloc(realLastLength); + if (last == NULL) { + goto loser; + } + PORT_Memcpy(last,salt.data,salt.len); + last[salt->len ] = (i >> 24) & 0xff; + last[salt->len+1] = (i >> 16) & 0xff; + last[salt->len+2] = (i >> 8) & 0xff; + last[salt->len+3] = i & 0xff; + + /* NOTE: we need at least one iteration to return success! */ + for (j=0; j < interations; j++) { + rv =HMAC_Begin(cx); + if (rv !=SECSuccess) { + break; + } + HMAC_Update(cx,last,lastLength); + rv =HMAC_Finish(cx,last,&lastLength,hLen); + if (rv !=SECSuccess) { + break; + } + do_xor(T,last,hLen); + } +loser: + if (cx) { + HMAC_DestroyContext(cx); + } + if (last) { + PORT_ZFree(last,reaLastLength); + } + return rv; +} + +static SECItem * +nsspkcs5_PBKFD2(const SECHashObject *hashObj, NSSPKCS5PBEParameter *pbe_param, + SECItem *pwitem) +{ + unsigned int dkLen = bytesNeeded; + unsigned int hLen = hashObject->length + unsigned int l = (dkLen+hLen-1) / hLen; + unsigned char *rp; + SECItem *result; + SECItem *salt = pbe_param->salt; + int interations = pbe_param->iter; + int bytesNeeded = pbe_param->keyLen; + + result = SECITEM_AllocItem(NULL,NULL,l*hLen); + if (result == NULL) { + return NULL; + } + + T = PORT_Alloc(hLen); + if (T == NULL) { + goto loser; + } + + for (i=0,rp=results->data; i < l ; i++, rp +=hLen) { + rv = nsspkcs5_PBKFD2_F(hashobj,pwitem,salt,iterations,i,T); + if (rv != SECSuccess) { + break; + } + PORT_Memcpy(rp,T,hLen); + } + +loser: + if (T) { + PORT_ZFree(T); + } + if (rv != SECSuccess) { + SECITEM_FreeITEM(result,PR_TRUE); + result = NULL; + } else { + result->len = dkLen; + } + + return result; +} +#endif + +#define HMAC_BUFFER 64 +#define ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y)) +/* + * This is the extended PBE function defined by the final PKCS #12 spec. + */ +static SECItem * +nsspkcs5_PKCS12PBE(const SECHashObject *hashObject, + NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, + PBEBitGenID bitGenPurpose, unsigned int bytesNeeded) +{ + PRArenaPool *arena = NULL; + unsigned int SLen,PLen; + unsigned int hashLength = hashObject->length; + unsigned char *S, *P; + SECItem *A = NULL, B, D, I; + SECItem *salt = &pbe_param->salt; + unsigned int c,i = 0; + unsigned int hashLen, iter; + unsigned char *iterBuf; + void *hash = NULL; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if(!arena) { + return NULL; + } + + /* how many hash object lengths are needed */ + c = (bytesNeeded + (hashLength-1))/hashLength; + + /* initialize our buffers */ + D.len = HMAC_BUFFER; + /* B and D are the same length, use one alloc go get both */ + D.data = (unsigned char*)PORT_ArenaZAlloc(arena, D.len*2); + B.len = D.len; + B.data = D.data + D.len; + + /* if all goes well, A will be returned, so don't use our temp arena */ + A = SECITEM_AllocItem(NULL,NULL,c*hashLength); + if (A == NULL) { + goto loser; + } + + SLen = ROUNDUP(salt->len,HMAC_BUFFER); + PLen = ROUNDUP(pwitem->len,HMAC_BUFFER); + I.len = SLen+PLen; + I.data = (unsigned char*)PORT_ArenaZAlloc(arena, I.len); + if (I.data == NULL) { + goto loser; + } + + /* S & P are only used to initialize I */ + S = I.data; + P = S + SLen; + + PORT_Memset(D.data, (char)bitGenPurpose, D.len); + if (SLen) { + PORT_Memcpy(S, salt->data, salt->len); + if (salt->len != SLen) { + PORT_Memcpy(S+salt->len, salt->data, SLen-(salt->len)); + } + } + if (PLen) { + PORT_Memcpy(P, salt->data, salt->len); + if (salt->len != PLen) { + PORT_Memcpy(P+salt->len, salt->data, PLen-salt->len); + } + } + + iterBuf = (unsigned char*)PORT_ArenaZAlloc(arena,hashLength); + if (iterBuf == NULL) { + goto loser; + } + + hash = hashObject->create(); + if(!hash) { + goto loser; + } + /* calculate the PBE now */ + for(i = 0; i < c; i++) { + int Bidx; /* must be signed or the for loop won't terminate */ + unsigned int k, j; + unsigned char *Ai = A->data+i*hashLength; + + + for(iter = 0; iter < pbe_param->iter; iter++) { + hashObject->begin(hash); + + if (iter) { + hashObject->update(hash, iterBuf, hashLen); + } else { + hashObject->update(hash, D.data, D.len); + hashObject->update(hash, I.data, I.len); + } + + hashObject->end(hash, iterBuf, &hashLen, hashObject->length); + if(hashLen != hashObject->length) { + break; + } + } + + PORT_Memcpy(Ai, iterBuf, hashLength); + for (Bidx = 0; Bidx < B.len; B.len += hashLength) { + PORT_Memcpy(B.data +Bidx, iterBuf, + (((Bidx + hashLength) > B.len) ? (B.len - Bidx) : + hashLength)); + } + + k = I.len/B.len; + for(j = 0; j < k; j++) { + unsigned int q, carryBit; + unsigned char *Ij = I.data + j*B.len; + + /* (Ij = Ij+B+1) */ + for (Bidx = (B.len-1), q=1, carryBit=0; Bidx >= 0; Bidx--,q=0) { + q += (unsigned int)Ij[Bidx]; + q += (unsigned int)B.data[Bidx]; + q += carryBit; + + carryBit = (q > 0xff); + Ij[Bidx] = (unsigned char)(q & 0xff); + } + } + } +loser: + if (hash) { + hashObject->destroy(hash, PR_TRUE); + } + if(arena) { + PORT_FreeArena(arena, PR_TRUE); + } + + /* if i != c, then we didn't complete the loop above and must of failed + * somwhere along the way */ + if (i != c) { + SECITEM_ZfreeItem(A,PR_TRUE); + A = NULL; + } else { + A->len = bytesNeeded; + } + + return A; +} + +/* + * generate key as per PKCS 5 + */ +SECItem * +nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, + SECItem *iv, PRBool faulty3DES) +{ + SECItem *hash = NULL, *key = NULL; + const SECHashObject *hashObj; + PRBool getIV = PR_FALSE; + + if((pbe_param == NULL) || (pwitem == NULL)) { + return NULL; + } + + key = SECITEM_AllocItem(NULL,NULL,pbe_param->keyLen); + if (key == NULL) { + return NULL; + } + + if ((pbe_param->ivLen) && (iv->data == NULL)) { + getIV = PR_TRUE; + iv->data = (unsigned char *)PORT_Alloc(pbe_param->ivLen); + if (iv->data == NULL) { + goto loser; + } + iv->len = pbe_param->ivLen; + } + + hashObj = &SECRawHashObjects[pbe_param->hashType]; + switch (pbe_param->pbeType) { + case NSSPKCS5_PBKDF1: + hash = nsspkcs5_PBKDF1Extended(hashObj,pbe_param,pwitem,faulty3DES); + if (hash == NULL) { + goto loser; + } + PORT_Assert(hash->len >= key->len+iv->len); + if (getIV) { + PORT_Memcpy(iv->data, hash->data+(hash->len - iv->len),iv->len); + } + break; +#ifdef PBKDF2 + case NSSPKCS5_PBKDF2: + hash = nsspkcs5_PBKDF2(hashObj,pbe_param,pwitem); + PORT_Assert(!getIV); + break; +#endif + case NSSPKCS5_PKCS12_V2: + if (getIV) { + hash = nsspkcs5_PKCS12PBE(hashObj,pbe_param,pwitem, + pbeBitGenCipherIV,iv->len); + if (hash == NULL) { + goto loser; + } + PORT_Memcpy(iv->data,hash->data,iv->len); + SECITEM_ZfreeItem(hash,PR_TRUE); + hash = NULL; + } + hash = nsspkcs5_PKCS12PBE(hashObj,pbe_param,pwitem, + pbe_param->keyID,key->len); + default: + break; + } + + if (hash == NULL) { + goto loser; + } + + if (pbe_param->is2KeyDES) { + PORT_Memcpy(key->data, hash->data, (key->len * 2) / 3); + PORT_Memcpy(&(key->data[(key->len * 2) / 3]), key->data, + key->len / 3); + } else { + PORT_Memcpy(key->data, hash->data, key->len); + } + + SECITEM_FreeItem(hash, PR_TRUE); + return key; + +loser: + if (getIV && iv->data) { + PORT_ZFree(iv->data,iv->len); + iv->data = NULL; + } + + SECITEM_ZfreeItem(key, PR_TRUE); + return NULL; +} + +static SECStatus +nsspkcs5_FillInParam(SECOidTag algorithm, NSSPKCS5PBEParameter *pbe_param) +{ + PRBool skipType = PR_FALSE; + + pbe_param->keyLen = 5; + pbe_param->ivLen = 8; + pbe_param->hashType = HASH_AlgSHA1; + pbe_param->pbeType = NSSPKCS5_PBKDF1; + pbe_param->encAlg = SEC_OID_RC2_CBC; + pbe_param->is2KeyDES = PR_FALSE; + switch(algorithm) { + /* DES3 Algorithms */ + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: + pbe_param->is2KeyDES = PR_TRUE; + /* fall through */ + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: + pbe_param->pbeType = NSSPKCS5_PKCS12_V2; + /* fall through */ + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: + pbe_param->keyLen = 24; + pbe_param->encAlg = SEC_OID_DES_EDE3_CBC; + break; + + /* DES Algorithms */ + case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: + pbe_param->hashType = HASH_AlgMD2; + goto finish_des; + case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: + pbe_param->hashType = HASH_AlgMD5; + /* fall through */ + case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: +finish_des: + pbe_param->keyLen = 8; + pbe_param->encAlg = SEC_OID_DES_CBC; + break; + + /* RC2 Algorithms */ + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: + pbe_param->keyLen = 16; + /* fall through */ + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: + pbe_param->pbeType = NSSPKCS5_PKCS12_V2; + break; + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: + pbe_param->keyLen = 16; + /* fall through */ + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: + break; + + /* RC4 algorithms */ + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: + skipType = PR_TRUE; + /* fall through */ + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: + pbe_param->keyLen = 16; + /* fall through */ + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: + if (!skipType) { + pbe_param->pbeType = NSSPKCS5_PKCS12_V2; + } + /* fall through */ + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: + pbe_param->ivLen = 0; + pbe_param->encAlg = SEC_OID_RC4; + break; + default: + return SECFailure; + } + + return SECSuccess; +} + +/* decode the algid and generate a PKCS 5 parameter from it + */ +NSSPKCS5PBEParameter * +nsspkcs5_NewParam(SECOidTag alg, SECItem *salt, int iterator) +{ + PRArenaPool *arena = NULL; + NSSPKCS5PBEParameter *pbe_param = NULL; + SECStatus rv = SECFailure; + + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); + if (arena == NULL) + return NULL; + + /* allocate memory for the parameter */ + pbe_param = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena, + sizeof(NSSPKCS5PBEParameter)); + + if (pbe_param == NULL) { + goto loser; + } + + pbe_param->poolp = arena; + + rv = nsspkcs5_FillInParam(alg, pbe_param); + if (rv != SECSuccess) { + goto loser; + } + + pbe_param->iter = iterator; + if (salt) { + rv = SECITEM_CopyItem(arena,&pbe_param->salt,salt); + } + + /* default key gen */ + pbe_param->keyID = pbeBitGenCipherKey; + +loser: + if (rv != SECSuccess) { + PORT_FreeArena(arena, PR_TRUE); + pbe_param = NULL; + } + + return pbe_param; +} + +/* decode the algid and generate a PKCS 5 parameter from it + */ +NSSPKCS5PBEParameter * +nsspkcs5_AlgidToParam(SECAlgorithmID *algid) +{ + NSSPKCS5PBEParameter *pbe_param = NULL; + SECOidTag algorithm; + SECStatus rv = SECFailure; + + if (algid == NULL) { + return NULL; + } + + algorithm = SECOID_GetAlgorithmTag(algid); + if (algorithm == SEC_OID_UNKNOWN) { + goto loser; + } + + pbe_param = nsspkcs5_NewParam(algorithm, NULL, 1); + if (pbe_param == NULL) { + goto loser; + } + + /* decode parameter */ + rv = SECFailure; + switch (pbe_param->pbeType) { + case NSSPKCS5_PBKDF1: + rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param, + NSSPKCS5PBEParameterTemplate, &algid->parameters); + break; + case NSSPKCS5_PKCS12_V2: + rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param, + NSSPKCS5PKCS12V2PBEParameterTemplate, &algid->parameters); + break; + case NSSPKCS5_PBKDF2: + break; + } + +loser: + if (rv == SECSuccess) { + pbe_param->iter = DER_GetInteger(&pbe_param->iteration); + } else { + nsspkcs5_DestroyPBEParameter(pbe_param); + pbe_param = NULL; + } + + return pbe_param; +} + +/* destroy a pbe parameter. it assumes that the parameter was + * generated using the appropriate create function and therefor + * contains an arena pool. + */ +void +nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *pbe_param) +{ + if (pbe_param != NULL) { + PORT_FreeArena(pbe_param->poolp, PR_TRUE); + } +} + + +/* crypto routines */ +/* perform DES encryption and decryption. these routines are called + * by nsspkcs5_CipherData. In the case of an error, NULL is returned. + */ +static SECItem * +sec_pkcs5_des(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des, + PRBool encrypt) +{ + SECItem *dest; + SECItem *dup_src; + SECStatus rv = SECFailure; + int pad; + + if((src == NULL) || (key == NULL) || (iv == NULL)) + return NULL; + + dup_src = SECITEM_DupItem(src); + if(dup_src == NULL) { + return NULL; + } + + if(encrypt != PR_FALSE) { + void *dummy; + + dummy = DES_PadBuffer(NULL, dup_src->data, + dup_src->len, &dup_src->len); + if(dummy == NULL) { + SECITEM_FreeItem(dup_src, PR_TRUE); + return NULL; + } + dup_src->data = (unsigned char*)dummy; + } + + dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + if(dest != NULL) { + /* allocate with over flow */ + dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64); + if(dest->data != NULL) { + DESContext *ctxt; + ctxt = DES_CreateContext(key->data, iv->data, + (triple_des ? NSS_DES_EDE3_CBC : NSS_DES_CBC), + encrypt); + + if(ctxt != NULL) { + rv = ((encrypt != PR_TRUE) ? DES_Decrypt : DES_Encrypt)( + ctxt, dest->data, &dest->len, + dup_src->len + 64, dup_src->data, dup_src->len); + + /* remove padding -- assumes 64 bit blocks */ + if((encrypt == PR_FALSE) && (rv == SECSuccess)) { + pad = dest->data[dest->len-1]; + if((pad > 0) && (pad <= 8)) { + if(dest->data[dest->len-pad] != pad) { + rv = SECFailure; + PORT_SetError(SEC_ERROR_BAD_PASSWORD); + } else { + dest->len -= pad; + } + } else { + rv = SECFailure; + PORT_SetError(SEC_ERROR_BAD_PASSWORD); + } + } + DES_DestroyContext(ctxt, PR_TRUE); + } + } + } + + if(rv == SECFailure) { + if(dest != NULL) { + SECITEM_FreeItem(dest, PR_TRUE); + } + dest = NULL; + } + + if(dup_src != NULL) { + SECITEM_FreeItem(dup_src, PR_TRUE); + } + + return dest; +} + +/* perform rc2 encryption/decryption if an error occurs, NULL is returned + */ +static SECItem * +sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy, + PRBool encrypt) +{ + SECItem *dest; + SECItem *dup_src; + SECStatus rv = SECFailure; + int pad; + + if((src == NULL) || (key == NULL) || (iv == NULL)) { + return NULL; + } + + dup_src = SECITEM_DupItem(src); + if(dup_src == NULL) { + return NULL; + } + + if(encrypt != PR_FALSE) { + void *dummy; + + dummy = DES_PadBuffer(NULL, dup_src->data, + dup_src->len, &dup_src->len); + if(dummy == NULL) { + SECITEM_FreeItem(dup_src, PR_TRUE); + return NULL; + } + dup_src->data = (unsigned char*)dummy; + } + + dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + if(dest != NULL) { + dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64); + if(dest->data != NULL) { + RC2Context *ctxt; + + ctxt = RC2_CreateContext(key->data, key->len, iv->data, + NSS_RC2_CBC, key->len); + + if(ctxt != NULL) { + rv = ((encrypt != PR_TRUE) ? RC2_Decrypt : RC2_Encrypt)( + ctxt, dest->data, &dest->len, + dup_src->len + 64, dup_src->data, dup_src->len); + + /* assumes 8 byte blocks -- remove padding */ + if((rv == SECSuccess) && (encrypt != PR_TRUE)) { + pad = dest->data[dest->len-1]; + if((pad > 0) && (pad <= 8)) { + if(dest->data[dest->len-pad] != pad) { + PORT_SetError(SEC_ERROR_BAD_PASSWORD); + rv = SECFailure; + } else { + dest->len -= pad; + } + } else { + PORT_SetError(SEC_ERROR_BAD_PASSWORD); + rv = SECFailure; + } + } + + } + } + } + + if((rv != SECSuccess) && (dest != NULL)) { + SECITEM_FreeItem(dest, PR_TRUE); + dest = NULL; + } + + if(dup_src != NULL) { + SECITEM_FreeItem(dup_src, PR_TRUE); + } + + return dest; +} + +/* perform rc4 encryption and decryption */ +static SECItem * +sec_pkcs5_rc4(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy_op, + PRBool encrypt) +{ + SECItem *dest; + SECStatus rv = SECFailure; + + if((src == NULL) || (key == NULL) || (iv == NULL)) { + return NULL; + } + + dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + if(dest != NULL) { + dest->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * + (src->len + 64)); + if(dest->data != NULL) { + RC4Context *ctxt; + + ctxt = RC4_CreateContext(key->data, key->len); + if(ctxt) { + rv = ((encrypt != PR_FALSE) ? RC4_Decrypt : RC4_Encrypt)( + ctxt, dest->data, &dest->len, + src->len + 64, src->data, src->len); + RC4_DestroyContext(ctxt, PR_TRUE); + } + } + } + + if((rv != SECSuccess) && (dest)) { + SECITEM_FreeItem(dest, PR_TRUE); + dest = NULL; + } + + return dest; +} +/* function pointer template for crypto functions */ +typedef SECItem *(* pkcs5_crypto_func)(SECItem *key, SECItem *iv, + SECItem *src, PRBool op1, PRBool op2); + +/* performs the cipher operation on the src and returns the result. + * if an error occurs, NULL is returned. + * + * a null length password is allowed. this corresponds to encrypting + * the data with ust the salt. + */ +/* change this to use PKCS 11? */ +SECItem * +nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, + SECItem *src, PRBool encrypt, PRBool *update) +{ + SECItem *key = NULL, iv; + SECItem *dest = NULL; + PRBool tripleDES = PR_TRUE; + pkcs5_crypto_func cryptof; + + iv.data = NULL; + + if (update) { + *update = PR_FALSE; + } + + if ((pwitem == NULL) || (src == NULL)) { + return NULL; + } + + /* get key, and iv */ + key = nsspkcs5_ComputeKeyAndIV(pbe_param, pwitem, &iv, PR_FALSE); + if(key == NULL) { + return NULL; + } + + switch(pbe_param->encAlg) { + case SEC_OID_DES_EDE3_CBC: + cryptof = sec_pkcs5_des; + tripleDES = PR_TRUE; + break; + case SEC_OID_DES_CBC: + cryptof = sec_pkcs5_des; + tripleDES = PR_FALSE; + break; + case SEC_OID_RC2_CBC: + cryptof = sec_pkcs5_rc2; + break; + case SEC_OID_RC4: + cryptof = sec_pkcs5_rc4; + break; + default: + cryptof = NULL; + break; + } + + if (cryptof == NULL) { + goto loser; + } + + dest = (*cryptof)(key, &iv, src, tripleDES, encrypt); + /* + * it's possible for some keys and keydb's to claim to + * be triple des when they're really des. In this case + * we simply try des. If des works we set the update flag + * so the key db knows it needs to update all it's entries. + * The case can only happen on decrypted of a + * SEC_OID_DES_EDE3_CBD. + */ + if ((dest == NULL) && (encrypt == PR_FALSE) && + (pbe_param->encAlg == SEC_OID_DES_EDE3_CBC)) { + dest = (*cryptof)(key, &iv, src, PR_FALSE, encrypt); + if (update && (dest != NULL)) *update = PR_TRUE; + } + +loser: + if (key != NULL) { + SECITEM_ZfreeItem(key, PR_TRUE); + } + if (iv.data != NULL) { + SECITEM_ZfreeItem(&iv, PR_FALSE); + } + + return dest; +} + +/* creates a algorithm ID containing the PBE algorithm and appropriate + * parameters. the required parameter is the algorithm. if salt is + * not specified, it is generated randomly. if IV is specified, it overrides + * the PKCS 5 generation of the IV. + * + * the returned SECAlgorithmID should be destroyed using + * SECOID_DestroyAlgorithmID + */ +SECAlgorithmID * +nsspkcs5_CreateAlgorithmID(PRArenaPool *arena, SECOidTag algorithm, + NSSPKCS5PBEParameter *pbe_param) +{ + SECAlgorithmID *algid, *ret_algid; + SECItem der_param; + SECStatus rv = SECFailure; + void *dummy = NULL; + + if (arena == NULL) { + return NULL; + } + + der_param.data = NULL; + der_param.len = 0; + + /* generate the algorithm id */ + algid = (SECAlgorithmID *)PORT_ArenaZAlloc(arena, sizeof(SECAlgorithmID)); + if (algid == NULL) { + goto loser; + } + + if (pbe_param->iteration.data == NULL) { + dummy = SEC_ASN1EncodeInteger(pbe_param->poolp,&pbe_param->iteration, + pbe_param->iter); + if (dummy == NULL) { + goto loser; + } + } + switch (pbe_param->pbeType) { + case NSSPKCS5_PBKDF1: + dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param, + NSSPKCS5PBEParameterTemplate); + break; + case NSSPKCS5_PKCS12_V2: + dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param, + NSSPKCS5PKCS12V2PBEParameterTemplate); + break; + default: + break; + } + + if (dummy == NULL) { + goto loser; + } + + rv = SECOID_SetAlgorithmID(arena, algid, algorithm, &der_param); + if (rv != SECSuccess) { + goto loser; + } + + ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID)); + if (ret_algid == NULL) { + goto loser; + } + + rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid); + if (rv != SECSuccess) { + SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE); + ret_algid = NULL; + } + +loser: + + return ret_algid; +} diff --git a/security/nss/lib/softoken/lowpbe.h b/security/nss/lib/softoken/lowpbe.h new file mode 100644 index 000000000..8ddee11a6 --- /dev/null +++ b/security/nss/lib/softoken/lowpbe.h @@ -0,0 +1,132 @@ +/* + * 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. + */ + +#ifndef _SECPKCS5_H_ +#define _SECPKCS5_H_ + +#include "plarena.h" +#include "secitem.h" +#include "seccomon.h" +#include "secoidt.h" +#include "hasht.h" + +typedef SECItem * (* SEC_PKCS5GetPBEPassword)(void *arg); + +/* used for V2 PKCS 12 Draft Spec */ +typedef enum { + pbeBitGenIDNull = 0, + pbeBitGenCipherKey = 0x01, + pbeBitGenCipherIV = 0x02, + pbeBitGenIntegrityKey = 0x03 +} PBEBitGenID; + +typedef enum { + NSSPKCS5_PBKDF1 = 0, + NSSPKCS5_PBKDF2 = 1, + NSSPKCS5_PKCS12_V2 = 2 +} NSSPKCS5PBEType; + +typedef struct NSSPKCS5PBEParameterStr NSSPKCS5PBEParameter; + +struct NSSPKCS5PBEParameterStr { + PRArenaPool *poolp; + SECItem salt; /* octet string */ + SECItem iteration; /* integer */ + + /* used locally */ + int iter; + int keyLen; + int ivLen; + HASH_HashType hashType; + NSSPKCS5PBEType pbeType; + PBEBitGenID keyID; + SECOidTag encAlg; + PRBool is2KeyDES; +}; + + +SEC_BEGIN_PROTOS +/* Create a PKCS5 Algorithm ID + * The algorithm ID is set up using the PKCS #5 parameter structure + * algorithm is the PBE algorithm ID for the desired algorithm + * pbe is a pbe param block with all the info needed to create the + * algorithm id. + * If an error occurs or the algorithm specified is not supported + * or is not a password based encryption algorithm, NULL is returned. + * Otherwise, a pointer to the algorithm id is returned. + */ +extern SECAlgorithmID * +nsspkcs5_CreateAlgorithmID(PRArenaPool *arena, SECOidTag algorithm, + NSSPKCS5PBEParameter *pbe); + +/* + * Convert an Algorithm ID to a PBE Param. + * NOTE: this does not suppport PKCS 5 v2 because it's only used for the + * keyDB which only support PKCS 5 v1, PFX, and PKCS 12. + */ +NSSPKCS5PBEParameter * +nsspkcs5_AlgidToParam(SECAlgorithmID *algid); + +/* + * Convert an Algorithm ID to a PBE Param. + * NOTE: this does not suppport PKCS 5 v2 because it's only used for the + * keyDB which only support PKCS 5 v1, PFX, and PKCS 12. + */ +NSSPKCS5PBEParameter * +nsspkcs5_NewParam(SECOidTag alg, SECItem *salt, int iterator); + + +/* Encrypt/Decrypt data using password based encryption. + * algid is the PBE algorithm identifier, + * pwitem is the password, + * src is the source for encryption/decryption, + * encrypt is PR_TRUE for encryption, PR_FALSE for decryption. + * The key and iv are generated based upon PKCS #5 then the src + * is either encrypted or decrypted. If an error occurs, NULL + * is returned, otherwise the ciphered contents is returned. + */ +extern SECItem * +nsspkcs5_CipherData(NSSPKCS5PBEParameter *, SECItem *pwitem, + SECItem *src, PRBool encrypt, PRBool *update); + +extern SECItem * +nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *, SECItem *pwitem, + SECItem *iv, PRBool faulty3DES); + +/* Destroys PBE parameter */ +extern void +nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *param); + +SEC_END_PROTOS + +#endif diff --git a/security/nss/lib/util/mac_rand.c b/security/nss/lib/softoken/mac_rand.c index 6198f3407..6198f3407 100644 --- a/security/nss/lib/util/mac_rand.c +++ b/security/nss/lib/softoken/mac_rand.c diff --git a/security/nss/lib/softoken/manifest.mn b/security/nss/lib/softoken/manifest.mn index c889a90c4..9d06365bb 100644 --- a/security/nss/lib/softoken/manifest.mn +++ b/security/nss/lib/softoken/manifest.mn @@ -36,39 +36,42 @@ MODULE = security REQUIRES = dbm -LIBRARY_NAME = softoken +LIBRARY_NAME = softokn +LIBRARY_VERSION = 3 +MAPFILE = $(OBJDIR)/softokn.def EXPORTS = \ - secpkcs5.h \ pkcs11.h \ pkcs11f.h \ pkcs11p.h \ pkcs11t.h \ + pkcs11n.h \ pkcs11u.h \ $(NULL) PRIVATE_EXPORTS = \ alghmac.h \ - pkcs11i.h \ pk11pars.h \ + pkcs11i.h \ $(NULL) CSRCS = \ alghmac.c \ - rsawrapr.c \ - pkcs11.c \ - pkcs11c.c \ - pkcs11u.c \ - secpkcs5.c \ + dbinit.c \ + fipstest.c \ + fipstokn.c \ keydb.c \ + lowcert.c \ lowkey.c \ + lowpbe.c \ padbuf.c \ - fipstest.c \ - fipstokn.c \ - rawhash.c \ - dbinit.c \ + pcertdb.c \ pk11db.c \ + pkcs11.c \ + pkcs11c.c \ + pkcs11u.c \ + rawhash.c \ + rsawrapr.c \ + sysrand.c \ $(NULL) - - diff --git a/security/nss/lib/util/os2_rand.c b/security/nss/lib/softoken/os2_rand.c index b1dbba805..b1dbba805 100644 --- a/security/nss/lib/util/os2_rand.c +++ b/security/nss/lib/softoken/os2_rand.c diff --git a/security/nss/lib/softoken/pcert.h b/security/nss/lib/softoken/pcert.h new file mode 100644 index 000000000..51a969f1a --- /dev/null +++ b/security/nss/lib/softoken/pcert.h @@ -0,0 +1,147 @@ +/* + * 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. + */ + +#ifndef _PCERTDB_H_ +#define _PCERTDB_H_ + +#include "plarena.h" +#include "prlong.h" +#include "pcertt.h" + +SEC_BEGIN_PROTOS + +/* +** Add a DER encoded certificate to the permanent database. +** "derCert" is the DER encoded certificate. +** "nickname" is the nickname to use for the cert +** "trust" is the trust parameters for the cert +*/ +SECStatus nsslowcert_AddPermCert(NSSLOWCERTCertDBHandle *handle, + NSSLOWCERTCertificate *cert, + char *nickname, NSSLOWCERTCertTrust *trust); + +SECStatus nsslowcert_DeletePermCertificate(NSSLOWCERTCertificate *cert); + +typedef SECStatus (PR_CALLBACK * PermCertCallback)(NSSLOWCERTCertificate *cert, + SECItem *k, void *pdata); +/* +** Traverse the entire permanent database, and pass the certs off to a +** user supplied function. +** "certfunc" is the user function to call for each certificate +** "udata" is the user's data, which is passed through to "certfunc" +*/ +SECStatus +nsslowcert_TraversePermCerts(NSSLOWCERTCertDBHandle *handle, + PermCertCallback certfunc, + void *udata ); + +PRBool +nsslowcert_CertDBKeyConflict(SECItem *derCert, NSSLOWCERTCertDBHandle *handle); + +SECItem * +nsslowcert_FindCrlByKey(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey, + char **urlp, PRBool isKRL); + +SECStatus +nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle,SECItem *derName, + PRBool isKRL); +SECStatus +nsslowcert_AddCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl , + SECItem *derKey, char *url, PRBool isKRL); + +NSSLOWCERTCertDBHandle *nsslowcert_GetDefaultCertDB(); +NSSLOWKEYPublicKey *nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *); + +NSSLOWCERTCertificate * +nsslowcert_NewTempCertificate(NSSLOWCERTCertDBHandle *handle, SECItem *derCert, + char *nickname, PRBool isperm, PRBool copyDER); +NSSLOWCERTCertificate * +nsslowcert_DupCertificate(NSSLOWCERTCertificate *cert); +void nsslowcert_DestroyCertificate(NSSLOWCERTCertificate *cert); + +/* + * Lookup a certificate in the databases without locking + * "certKey" is the database key to look for + * + * XXX - this should be internal, but pkcs 11 needs to call it during a + * traversal. + */ +NSSLOWCERTCertificate * +nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey); + +/* +** Generate a certificate key from the issuer and serialnumber, then look it +** up in the database. Return the cert if found. +** "issuerAndSN" is the issuer and serial number to look for +*/ +extern NSSLOWCERTCertificate * +nsslowcert_FindCertByIssuerAndSN (NSSLOWCERTCertDBHandle *handle, NSSLOWCERTIssuerAndSN *issuerAndSN); + +/* +** Find a certificate in the database by a DER encoded certificate +** "derCert" is the DER encoded certificate +*/ +extern NSSLOWCERTCertificate * +nsslowcert_FindCertByDERCert(NSSLOWCERTCertDBHandle *handle, SECItem *derCert); + +/* convert an email address to lower case */ +char *nsslowcert_FixupEmailAddr(char *emailAddr); + +/* +** Decode a DER encoded certificate into an NSSLOWCERTCertificate structure +** "derSignedCert" is the DER encoded signed certificate +** "copyDER" is true if the DER should be copied, false if the +** existing copy should be referenced +** "nickname" is the nickname to use in the database. If it is NULL +** then a temporary nickname is generated. +*/ +extern NSSLOWCERTCertificate * +nsslowcert_DecodeDERCertificate (SECItem *derSignedCert, PRBool copyDER, char *nickname); + +SECStatus +nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key); + +certDBEntrySMime * +nsslowcert_ReadDBSMimeEntry(NSSLOWCERTCertDBHandle *certHandle, + char *emailAddr); +void +nsslowcert_DestroyDBEntry(certDBEntry *entry); + +SECStatus +nsslowcert_OpenCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, + NSSLOWCERTDBNameFunc namecb, void *cbarg, PRBool openVolatile); + + +SEC_END_PROTOS + + #endif /* _PCERTDB_H_ */ diff --git a/security/nss/lib/softoken/pcertdb.c b/security/nss/lib/softoken/pcertdb.c new file mode 100644 index 000000000..e23752990 --- /dev/null +++ b/security/nss/lib/softoken/pcertdb.c @@ -0,0 +1,4410 @@ +/* + * 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. + */ + +/* + * Permanent Certificate database handling code + * + * $Id$ + */ +#include "prtime.h" + +#include "lowkeyti.h" +#include "pcert.h" +#include "mcom_db.h" +#include "pcert.h" +#include "secitem.h" +#include "secder.h" + +/* Call to PK11_FreeSlot below */ + +#include "secasn1.h" +#include "secerr.h" +#include "nssilock.h" +#include "prmon.h" +#include "nsslocks.h" +#include "base64.h" +#include "sechash.h" +#include "plhash.h" + +#include "cdbhdl.h" + +/* forward declaration */ +NSSLOWCERTCertificate * +nsslowcert_FindCertByDERCertNoLocking(NSSLOWCERTCertDBHandle *handle, SECItem *derCert); + +/* + * the following functions are wrappers for the db library that implement + * a global lock to make the database thread safe. + */ +static PZLock *dbLock = NULL; + +void +certdb_InitDBLock(NSSLOWCERTCertDBHandle *handle) +{ + if (dbLock == NULL) { + nss_InitLock(&dbLock, nssILockCertDB); + PORT_Assert(dbLock != NULL); + } + + return; +} + +/* + * Acquire the global lock on the cert database. + * This lock is currently used for the following operations: + * adding or deleting a cert to either the temp or perm databases + * converting a temp to perm or perm to temp + * changing(maybe just adding????) the trust of a cert + * chaning the DB status checking Configuration + */ +static void +nsslowcert_LockDB(NSSLOWCERTCertDBHandle *handle) +{ + PZ_EnterMonitor(handle->dbMon); + return; +} + +/* + * Free the global cert database lock. + */ +static void +nsslowcert_UnlockDB(NSSLOWCERTCertDBHandle *handle) +{ + PRStatus prstat; + + prstat = PZ_ExitMonitor(handle->dbMon); + + PORT_Assert(prstat == PR_SUCCESS); + + return; +} + +static PZLock *certRefCountLock = NULL; + +/* + * Acquire the cert reference count lock + * There is currently one global lock for all certs, but I'm putting a cert + * arg here so that it will be easy to make it per-cert in the future if + * that turns out to be necessary. + */ +static void +nsslowcert_LockCertRefCount(NSSLOWCERTCertificate *cert) +{ + if ( certRefCountLock == NULL ) { + nss_InitLock(&certRefCountLock, nssILockRefLock); + PORT_Assert(certRefCountLock != NULL); + } + + PZ_Lock(certRefCountLock); + return; +} + +/* + * Free the cert reference count lock + */ +static void +nsslowcert_UnlockCertRefCount(NSSLOWCERTCertificate *cert) +{ + PRStatus prstat; + + PORT_Assert(certRefCountLock != NULL); + + prstat = PZ_Unlock(certRefCountLock); + + PORT_Assert(prstat == PR_SUCCESS); + + return; +} + +static PZLock *certTrustLock = NULL; + +/* + * Acquire the cert trust lock + * There is currently one global lock for all certs, but I'm putting a cert + * arg here so that it will be easy to make it per-cert in the future if + * that turns out to be necessary. + */ +void +nsslowcert_LockCertTrust(NSSLOWCERTCertificate *cert) +{ + if ( certTrustLock == NULL ) { + nss_InitLock(&certTrustLock, nssILockCertDB); + PORT_Assert(certTrustLock != NULL); + } + + PZ_Lock(certTrustLock); + return; +} + +/* + * Free the cert trust lock + */ +void +nsslowcert_UnlockCertTrust(NSSLOWCERTCertificate *cert) +{ + PRStatus prstat; + + PORT_Assert(certTrustLock != NULL); + + prstat = PZ_Unlock(certTrustLock); + + PORT_Assert(prstat == PR_SUCCESS); + + return; +} + + +static int +certdb_Get(DB *db, DBT *key, DBT *data, unsigned int flags) +{ + PRStatus prstat; + int ret; + + PORT_Assert(dbLock != NULL); + PZ_Lock(dbLock); + + ret = (* db->get)(db, key, data, flags); + + prstat = PZ_Unlock(dbLock); + + return(ret); +} + +static int +certdb_Put(DB *db, DBT *key, DBT *data, unsigned int flags) +{ + PRStatus prstat; + int ret; + + PORT_Assert(dbLock != NULL); + PZ_Lock(dbLock); + + ret = (* db->put)(db, key, data, flags); + + prstat = PZ_Unlock(dbLock); + + return(ret); +} + +static int +certdb_Sync(DB *db, unsigned int flags) +{ + PRStatus prstat; + int ret; + + PORT_Assert(dbLock != NULL); + PZ_Lock(dbLock); + + ret = (* db->sync)(db, flags); + + prstat = PZ_Unlock(dbLock); + + return(ret); +} + +static int +certdb_Del(DB *db, DBT *key, unsigned int flags) +{ + PRStatus prstat; + int ret; + + PORT_Assert(dbLock != NULL); + PZ_Lock(dbLock); + + ret = (* db->del)(db, key, flags); + + prstat = PZ_Unlock(dbLock); + + return(ret); +} + +static int +certdb_Seq(DB *db, DBT *key, DBT *data, unsigned int flags) +{ + PRStatus prstat; + int ret; + + PORT_Assert(dbLock != NULL); + PZ_Lock(dbLock); + + ret = (* db->seq)(db, key, data, flags); + + prstat = PZ_Unlock(dbLock); + + return(ret); +} + +static void +certdb_Close(DB *db) +{ + PRStatus prstat; + + PORT_Assert(dbLock != NULL); + PZ_Lock(dbLock); + + (* db->close)(db); + + prstat = PZ_Unlock(dbLock); + + return; +} + +/* forward references */ +static void nsslowcert_DestroyCertificateNoLocking(NSSLOWCERTCertificate *cert); + +static SECStatus +DeleteDBEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryType type, SECItem *dbkey) +{ + DBT key; + int ret; + + /* init the database key */ + key.data = dbkey->data; + key.size = dbkey->len; + + dbkey->data[0] = (unsigned char)type; + + /* delete entry from database */ + ret = certdb_Del(handle->permCertDB, &key, 0 ); + if ( ret != 0 ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + ret = certdb_Sync(handle->permCertDB, 0); + if ( ret ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + return(SECSuccess); + +loser: + return(SECFailure); +} + +static SECStatus +ReadDBEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryCommon *entry, + SECItem *dbkey, SECItem *dbentry, PRArenaPool *arena) +{ + DBT data, key; + int ret; + unsigned char *buf; + + /* init the database key */ + key.data = dbkey->data; + key.size = dbkey->len; + + dbkey->data[0] = (unsigned char)entry->type; + + /* read entry from database */ + ret = certdb_Get(handle->permCertDB, &key, &data, 0 ); + if ( ret != 0 ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + /* validate the entry */ + if ( data.size < SEC_DB_ENTRY_HEADER_LEN ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + buf = (unsigned char *)data.data; + if ( buf[0] != (unsigned char)CERT_DB_FILE_VERSION ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + if ( buf[1] != (unsigned char)entry->type ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + /* copy out header information */ + entry->version = (unsigned int)buf[0]; + entry->type = (certDBEntryType)buf[1]; + entry->flags = (unsigned int)buf[2]; + + /* format body of entry for return to caller */ + dbentry->len = data.size - SEC_DB_ENTRY_HEADER_LEN; + if ( dbentry->len ) { + dbentry->data = (unsigned char *)PORT_ArenaAlloc(arena, dbentry->len); + if ( dbentry->data == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + PORT_Memcpy(dbentry->data, &buf[SEC_DB_ENTRY_HEADER_LEN], + dbentry->len); + } else { + dbentry->data = NULL; + } + + return(SECSuccess); + +loser: + return(SECFailure); +} + +/** + ** Implement low level database access + **/ +static SECStatus +WriteDBEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryCommon *entry, + SECItem *dbkey, SECItem *dbentry) +{ + int ret; + DBT data, key; + unsigned char *buf; + + data.data = dbentry->data; + data.size = dbentry->len; + + buf = (unsigned char*)data.data; + + buf[0] = (unsigned char)entry->version; + buf[1] = (unsigned char)entry->type; + buf[2] = (unsigned char)entry->flags; + + key.data = dbkey->data; + key.size = dbkey->len; + + dbkey->data[0] = (unsigned char)entry->type; + + /* put the record into the database now */ + ret = certdb_Put(handle->permCertDB, &key, &data, 0); + + if ( ret != 0 ) { + goto loser; + } + + ret = certdb_Sync( handle->permCertDB, 0 ); + + if ( ret ) { + goto loser; + } + + return(SECSuccess); + +loser: + return(SECFailure); +} + +/* + * encode a database cert record + */ +static SECStatus +EncodeDBCertEntry(certDBEntryCert *entry, PRArenaPool *arena, SECItem *dbitem) +{ + unsigned int nnlen; + unsigned char *buf; + char *nn; + char zbuf = 0; + + if ( entry->nickname ) { + nn = entry->nickname; + } else { + nn = &zbuf; + } + nnlen = PORT_Strlen(nn) + 1; + + /* allocate space for encoded database record, including space + * for low level header + */ + dbitem->len = entry->derCert.len + nnlen + DB_CERT_ENTRY_HEADER_LEN + + SEC_DB_ENTRY_HEADER_LEN; + + dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len); + if ( dbitem->data == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + /* fill in database record */ + buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN]; + + buf[0] = ( entry->trust.sslFlags >> 8 ) & 0xff; + buf[1] = entry->trust.sslFlags & 0xff; + buf[2] = ( entry->trust.emailFlags >> 8 ) & 0xff; + buf[3] = entry->trust.emailFlags & 0xff; + buf[4] = ( entry->trust.objectSigningFlags >> 8 ) & 0xff; + buf[5] = entry->trust.objectSigningFlags & 0xff; + buf[6] = ( entry->derCert.len >> 8 ) & 0xff; + buf[7] = entry->derCert.len & 0xff; + buf[8] = ( nnlen >> 8 ) & 0xff; + buf[9] = nnlen & 0xff; + + PORT_Memcpy(&buf[DB_CERT_ENTRY_HEADER_LEN], entry->derCert.data, + entry->derCert.len); + + PORT_Memcpy(&buf[DB_CERT_ENTRY_HEADER_LEN + entry->derCert.len], + nn, nnlen); + + return(SECSuccess); + +loser: + return(SECFailure); +} + +/* + * encode a database key for a cert record + */ +static SECStatus +EncodeDBCertKey(SECItem *certKey, PRArenaPool *arena, SECItem *dbkey) +{ + dbkey->len = certKey->len + SEC_DB_KEY_HEADER_LEN; + dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len); + if ( dbkey->data == NULL ) { + goto loser; + } + PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], + certKey->data, certKey->len); + dbkey->data[0] = certDBEntryTypeCert; + + return(SECSuccess); +loser: + return(SECFailure); +} + +static SECStatus +EncodeDBGenericKey(SECItem *certKey, PRArenaPool *arena, SECItem *dbkey, + certDBEntryType entryType) +{ + /* + * we only allow _one_ KRL key! + */ + if (entryType == certDBEntryTypeKeyRevocation) { + dbkey->len = SEC_DB_KEY_HEADER_LEN; + dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len); + if ( dbkey->data == NULL ) { + goto loser; + } + dbkey->data[0] = (unsigned char) entryType; + return(SECSuccess); + } + + + dbkey->len = certKey->len + SEC_DB_KEY_HEADER_LEN; + dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len); + if ( dbkey->data == NULL ) { + goto loser; + } + PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], + certKey->data, certKey->len); + dbkey->data[0] = (unsigned char) entryType; + + return(SECSuccess); +loser: + return(SECFailure); +} + +static SECStatus +DecodeDBCertEntry(certDBEntryCert *entry, SECItem *dbentry) +{ + unsigned int nnlen; + int headerlen; + int lenoff; + + /* allow updates of old versions of the database */ + switch ( entry->common.version ) { + case 5: + headerlen = DB_CERT_V5_ENTRY_HEADER_LEN; + lenoff = 3; + break; + case 6: + /* should not get here */ + PORT_Assert(0); + headerlen = DB_CERT_V6_ENTRY_HEADER_LEN; + lenoff = 3; + break; + case 7: + headerlen = DB_CERT_ENTRY_HEADER_LEN; + lenoff = 6; + break; + default: + /* better not get here */ + PORT_Assert(0); + headerlen = DB_CERT_V5_ENTRY_HEADER_LEN; + lenoff = 3; + break; + } + + /* is record long enough for header? */ + if ( dbentry->len < headerlen ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + /* is database entry correct length? */ + entry->derCert.len = ( ( dbentry->data[lenoff] << 8 ) | + dbentry->data[lenoff+1] ); + nnlen = ( ( dbentry->data[lenoff+2] << 8 ) | dbentry->data[lenoff+3] ); + if ( ( entry->derCert.len + nnlen + headerlen ) + != dbentry->len) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + /* copy the dercert */ + entry->derCert.data = (unsigned char *)PORT_ArenaAlloc(entry->common.arena, + entry->derCert.len); + if ( entry->derCert.data == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + PORT_Memcpy(entry->derCert.data, &dbentry->data[headerlen], + entry->derCert.len); + + /* copy the nickname */ + if ( nnlen > 1 ) { + entry->nickname = (char *)PORT_ArenaAlloc(entry->common.arena, nnlen); + if ( entry->nickname == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + PORT_Memcpy(entry->nickname, + &dbentry->data[headerlen + + entry->derCert.len], + nnlen); + } else { + entry->nickname = NULL; + } + + if ( entry->common.version < 7 ) { + /* allow updates of v5 db */ + entry->trust.sslFlags = dbentry->data[0]; + entry->trust.emailFlags = dbentry->data[1]; + entry->trust.objectSigningFlags = dbentry->data[2]; + } else { + entry->trust.sslFlags = ( dbentry->data[0] << 8 ) | dbentry->data[1]; + entry->trust.emailFlags = ( dbentry->data[2] << 8 ) | dbentry->data[3]; + entry->trust.objectSigningFlags = + ( dbentry->data[4] << 8 ) | dbentry->data[5]; + } + + return(SECSuccess); +loser: + return(SECFailure); +} + + +/* + * Create a new certDBEntryCert from existing data + */ +static certDBEntryCert * +NewDBCertEntry(SECItem *derCert, char *nickname, + NSSLOWCERTCertTrust *trust, int flags) +{ + certDBEntryCert *entry; + PRArenaPool *arena = NULL; + int nnlen; + + arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE ); + + if ( !arena ) { + goto loser; + } + + entry = (certDBEntryCert *)PORT_ArenaZAlloc(arena, sizeof(certDBEntryCert)); + + if ( entry == NULL ) { + goto loser; + } + + /* fill in the dbCert */ + entry->common.arena = arena; + entry->common.type = certDBEntryTypeCert; + entry->common.version = CERT_DB_FILE_VERSION; + entry->common.flags = flags; + + if ( trust ) { + entry->trust = *trust; + } + + entry->derCert.data = (unsigned char *)PORT_ArenaAlloc(arena, derCert->len); + if ( !entry->derCert.data ) { + goto loser; + } + entry->derCert.len = derCert->len; + PORT_Memcpy(entry->derCert.data, derCert->data, derCert->len); + + nnlen = ( nickname ? strlen(nickname) + 1 : 0 ); + + if ( nnlen ) { + entry->nickname = (char *)PORT_ArenaAlloc(arena, nnlen); + if ( !entry->nickname ) { + goto loser; + } + PORT_Memcpy(entry->nickname, nickname, nnlen); + + } else { + entry->nickname = 0; + } + + return(entry); + +loser: + + /* allocation error, free arena and return */ + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + PORT_SetError(SEC_ERROR_NO_MEMORY); + return(0); +} + +/* + * Decode a version 4 DBCert from the byte stream database format + * and construct a current database entry struct + */ +static certDBEntryCert * +DecodeV4DBCertEntry(unsigned char *buf, int len) +{ + certDBEntryCert *entry; + int certlen; + int nnlen; + PRArenaPool *arena; + + /* make sure length is at least long enough for the header */ + if ( len < DBCERT_V4_HEADER_LEN ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + return(0); + } + + /* get other lengths */ + certlen = buf[3] << 8 | buf[4]; + nnlen = buf[5] << 8 | buf[6]; + + /* make sure DB entry is the right size */ + if ( ( certlen + nnlen + DBCERT_V4_HEADER_LEN ) != len ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + return(0); + } + + /* allocate arena */ + arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE ); + + if ( !arena ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return(0); + } + + /* allocate structure and members */ + entry = (certDBEntryCert *) PORT_ArenaAlloc(arena, sizeof(certDBEntryCert)); + + if ( !entry ) { + goto loser; + } + + entry->derCert.data = (unsigned char *)PORT_ArenaAlloc(arena, certlen); + if ( !entry->derCert.data ) { + goto loser; + } + entry->derCert.len = certlen; + + if ( nnlen ) { + entry->nickname = (char *) PORT_ArenaAlloc(arena, nnlen); + if ( !entry->nickname ) { + goto loser; + } + } else { + entry->nickname = 0; + } + + entry->common.arena = arena; + entry->common.version = CERT_DB_FILE_VERSION; + entry->common.type = certDBEntryTypeCert; + entry->common.flags = 0; + entry->trust.sslFlags = buf[0]; + entry->trust.emailFlags = buf[1]; + entry->trust.objectSigningFlags = buf[2]; + + PORT_Memcpy(entry->derCert.data, &buf[DBCERT_V4_HEADER_LEN], certlen); + PORT_Memcpy(entry->nickname, &buf[DBCERT_V4_HEADER_LEN + certlen], nnlen); + + if (PORT_Strcmp(entry->nickname,"Server-Cert") == 0) { + entry->trust.sslFlags |= CERTDB_USER; + } + + return(entry); + +loser: + PORT_FreeArena(arena, PR_FALSE); + PORT_SetError(SEC_ERROR_NO_MEMORY); + return(0); +} + +/* + * Encode a Certificate database entry into byte stream suitable for + * the database + */ +static SECStatus +WriteDBCertEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryCert *entry) +{ + SECItem dbitem, dbkey; + PRArenaPool *tmparena = NULL; + SECItem tmpitem; + SECStatus rv; + + tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( tmparena == NULL ) { + goto loser; + } + + rv = EncodeDBCertEntry(entry, tmparena, &dbitem); + if ( rv != SECSuccess ) { + goto loser; + } + + /* get the database key and format it */ + rv = nsslowcert_KeyFromDERCert(tmparena, &entry->derCert, &tmpitem); + if ( rv == SECFailure ) { + goto loser; + } + + rv = EncodeDBCertKey(&tmpitem, tmparena, &dbkey); + if ( rv == SECFailure ) { + goto loser; + } + + /* now write it to the database */ + rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem); + if ( rv != SECSuccess ) { + goto loser; + } + + PORT_FreeArena(tmparena, PR_FALSE); + return(SECSuccess); + +loser: + if ( tmparena ) { + PORT_FreeArena(tmparena, PR_FALSE); + } + return(SECFailure); +} + + +/* + * delete a certificate entry + */ +static SECStatus +DeleteDBCertEntry(NSSLOWCERTCertDBHandle *handle, SECItem *certKey) +{ + SECItem dbkey; + PRArenaPool *arena = NULL; + SECStatus rv; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + goto loser; + } + + rv = EncodeDBCertKey(certKey, arena, &dbkey); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = DeleteDBEntry(handle, certDBEntryTypeCert, &dbkey); + if ( rv == SECFailure ) { + goto loser; + } + + PORT_FreeArena(arena, PR_FALSE); + return(SECSuccess); + +loser: + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(SECFailure); +} + +/* + * Read a certificate entry + */ +static certDBEntryCert * +ReadDBCertEntry(NSSLOWCERTCertDBHandle *handle, SECItem *certKey) +{ + PRArenaPool *arena = NULL; + PRArenaPool *tmparena = NULL; + certDBEntryCert *entry; + SECItem dbkey; + SECItem dbentry; + SECStatus rv; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( tmparena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + entry = (certDBEntryCert *)PORT_ArenaAlloc(arena, sizeof(certDBEntryCert)); + if ( entry == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + entry->common.arena = arena; + entry->common.type = certDBEntryTypeCert; + + rv = EncodeDBCertKey(certKey, tmparena, &dbkey); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); + if ( rv == SECFailure ) { + goto loser; + } + + rv = DecodeDBCertEntry(entry, &dbentry); + if ( rv != SECSuccess ) { + goto loser; + } + + PORT_FreeArena(tmparena, PR_FALSE); + return(entry); + +loser: + if ( tmparena ) { + PORT_FreeArena(tmparena, PR_FALSE); + } + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(NULL); +} + +/* + * encode a database cert record + */ +static SECStatus +EncodeDBCrlEntry(certDBEntryRevocation *entry, PRArenaPool *arena, SECItem *dbitem) +{ + unsigned int nnlen = 0; + unsigned char *buf; + + if (entry->url) { + nnlen = PORT_Strlen(entry->url) + 1; + } + + /* allocate space for encoded database record, including space + * for low level header + */ + dbitem->len = entry->derCrl.len + nnlen + + SEC_DB_ENTRY_HEADER_LEN + DB_CRL_ENTRY_HEADER_LEN; + + dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len); + if ( dbitem->data == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + /* fill in database record */ + buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN]; + + buf[0] = ( entry->derCrl.len >> 8 ) & 0xff; + buf[1] = entry->derCrl.len & 0xff; + buf[2] = ( nnlen >> 8 ) & 0xff; + buf[3] = nnlen & 0xff; + + PORT_Memcpy(&buf[DB_CRL_ENTRY_HEADER_LEN], entry->derCrl.data, + entry->derCrl.len); + + if (nnlen != 0) { + PORT_Memcpy(&buf[DB_CRL_ENTRY_HEADER_LEN + entry->derCrl.len], + entry->url, nnlen); + } + + return(SECSuccess); + +loser: + return(SECFailure); +} + +static SECStatus +DecodeDBCrlEntry(certDBEntryRevocation *entry, SECItem *dbentry) +{ + unsigned int nnlen; + + /* is record long enough for header? */ + if ( dbentry->len < DB_CRL_ENTRY_HEADER_LEN ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + /* is database entry correct length? */ + entry->derCrl.len = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] ); + nnlen = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] ); + if ( ( entry->derCrl.len + nnlen + DB_CRL_ENTRY_HEADER_LEN ) + != dbentry->len) { + /* CRL entry is greater than 64 K. Hack to make this continue to work */ + if (dbentry->len >= (0xffff - DB_CRL_ENTRY_HEADER_LEN) - nnlen) { + entry->derCrl.len = + (dbentry->len - DB_CRL_ENTRY_HEADER_LEN) - nnlen; + } else { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + } + + /* copy the dercert */ + entry->derCrl.data = (unsigned char *)PORT_ArenaAlloc(entry->common.arena, + entry->derCrl.len); + if ( entry->derCrl.data == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + PORT_Memcpy(entry->derCrl.data, &dbentry->data[DB_CRL_ENTRY_HEADER_LEN], + entry->derCrl.len); + + /* copy the url */ + entry->url = NULL; + if (nnlen != 0) { + entry->url = (char *)PORT_ArenaAlloc(entry->common.arena, nnlen); + if ( entry->url == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + PORT_Memcpy(entry->url, + &dbentry->data[DB_CRL_ENTRY_HEADER_LEN + entry->derCrl.len], + nnlen); + } + + return(SECSuccess); +loser: + return(SECFailure); +} + +/* + * Create a new certDBEntryRevocation from existing data + */ +static certDBEntryRevocation * +NewDBCrlEntry(SECItem *derCrl, char * url, certDBEntryType crlType, int flags) +{ + certDBEntryRevocation *entry; + PRArenaPool *arena = NULL; + int nnlen; + + arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE ); + + if ( !arena ) { + goto loser; + } + + entry = (certDBEntryRevocation*) + PORT_ArenaZAlloc(arena, sizeof(certDBEntryRevocation)); + + if ( entry == NULL ) { + goto loser; + } + + /* fill in the dbRevolcation */ + entry->common.arena = arena; + entry->common.type = crlType; + entry->common.version = CERT_DB_FILE_VERSION; + entry->common.flags = flags; + + + entry->derCrl.data = (unsigned char *)PORT_ArenaAlloc(arena, derCrl->len); + if ( !entry->derCrl.data ) { + goto loser; + } + + if (url) { + nnlen = PORT_Strlen(url) + 1; + entry->url = (char *)PORT_ArenaAlloc(arena, nnlen); + if ( !entry->url ) { + goto loser; + } + PORT_Memcpy(entry->url, url, nnlen); + } else { + entry->url = NULL; + } + + + entry->derCrl.len = derCrl->len; + PORT_Memcpy(entry->derCrl.data, derCrl->data, derCrl->len); + + return(entry); + +loser: + + /* allocation error, free arena and return */ + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + PORT_SetError(SEC_ERROR_NO_MEMORY); + return(0); +} + + +static SECStatus +WriteDBCrlEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryRevocation *entry, + SECItem *crlKey ) +{ + SECItem dbkey; + PRArenaPool *tmparena = NULL; + SECItem encodedEntry; + SECStatus rv; + + tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( tmparena == NULL ) { + goto loser; + } + + rv = EncodeDBCrlEntry(entry, tmparena, &encodedEntry); + if ( rv == SECFailure ) { + goto loser; + } + + rv = EncodeDBGenericKey(crlKey, tmparena, &dbkey, entry->common.type); + if ( rv == SECFailure ) { + goto loser; + } + + /* now write it to the database */ + rv = WriteDBEntry(handle, &entry->common, &dbkey, &encodedEntry); + if ( rv != SECSuccess ) { + goto loser; + } + + PORT_FreeArena(tmparena, PR_FALSE); + return(SECSuccess); + +loser: + if ( tmparena ) { + PORT_FreeArena(tmparena, PR_FALSE); + } + return(SECFailure); +} +/* + * delete a crl entry + */ +static SECStatus +DeleteDBCrlEntry(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey, + certDBEntryType crlType) +{ + SECItem dbkey; + PRArenaPool *arena = NULL; + SECStatus rv; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + goto loser; + } + + rv = EncodeDBGenericKey(crlKey, arena, &dbkey, crlType); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = DeleteDBEntry(handle, crlType, &dbkey); + if ( rv == SECFailure ) { + goto loser; + } + + PORT_FreeArena(arena, PR_FALSE); + return(SECSuccess); + +loser: + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(SECFailure); +} + +/* + * Read a certificate entry + */ +static certDBEntryRevocation * +ReadDBCrlEntry(NSSLOWCERTCertDBHandle *handle, SECItem *certKey, + certDBEntryType crlType) +{ + PRArenaPool *arena = NULL; + PRArenaPool *tmparena = NULL; + certDBEntryRevocation *entry; + SECItem dbkey; + SECItem dbentry; + SECStatus rv; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( tmparena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + entry = (certDBEntryRevocation *) + PORT_ArenaAlloc(arena, sizeof(certDBEntryRevocation)); + if ( entry == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + entry->common.arena = arena; + entry->common.type = crlType; + + rv = EncodeDBGenericKey(certKey, tmparena, &dbkey, crlType); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); + if ( rv == SECFailure ) { + goto loser; + } + + rv = DecodeDBCrlEntry(entry, &dbentry); + if ( rv != SECSuccess ) { + goto loser; + } + + PORT_FreeArena(tmparena, PR_FALSE); + return(entry); + +loser: + if ( tmparena ) { + PORT_FreeArena(tmparena, PR_FALSE); + } + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(NULL); +} + +/* + * destroy a database entry + */ +static void +DestroyDBEntry(certDBEntry *entry) +{ + PRArenaPool *arena = entry->common.arena; + + /* Zero out the entry struct, so that any further attempts to use it + * will cause an exception (e.g. null pointer reference). */ + PORT_Memset(&entry->common, 0, sizeof entry->common); + PORT_FreeArena(arena, PR_FALSE); + + return; +} + +void +nsslowcert_DestroyDBEntry(certDBEntry *entry) +{ + DestroyDBEntry(entry); + return; +} + +/* + * Encode a database nickname record + */ +static SECStatus +EncodeDBNicknameEntry(certDBEntryNickname *entry, PRArenaPool *arena, + SECItem *dbitem) +{ + unsigned char *buf; + + /* allocate space for encoded database record, including space + * for low level header + */ + dbitem->len = entry->subjectName.len + DB_NICKNAME_ENTRY_HEADER_LEN + + SEC_DB_ENTRY_HEADER_LEN; + + dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len); + if ( dbitem->data == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + /* fill in database record */ + buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN]; + + buf[0] = ( entry->subjectName.len >> 8 ) & 0xff; + buf[1] = entry->subjectName.len & 0xff; + + PORT_Memcpy(&buf[DB_NICKNAME_ENTRY_HEADER_LEN], entry->subjectName.data, + entry->subjectName.len); + + return(SECSuccess); + +loser: + return(SECFailure); +} + +/* + * Encode a database key for a nickname record + */ +static SECStatus +EncodeDBNicknameKey(char *nickname, PRArenaPool *arena, + SECItem *dbkey) +{ + unsigned int nnlen; + + nnlen = PORT_Strlen(nickname) + 1; /* includes null */ + + /* now get the database key and format it */ + dbkey->len = nnlen + SEC_DB_KEY_HEADER_LEN; + dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len); + if ( dbkey->data == NULL ) { + goto loser; + } + PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], nickname, nnlen); + dbkey->data[0] = certDBEntryTypeNickname; + + return(SECSuccess); + +loser: + return(SECFailure); +} + +static SECStatus +DecodeDBNicknameEntry(certDBEntryNickname *entry, SECItem *dbentry, + char *nickname) +{ + /* is record long enough for header? */ + if ( dbentry->len < DB_NICKNAME_ENTRY_HEADER_LEN ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + /* is database entry correct length? */ + entry->subjectName.len = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] ); + if (( entry->subjectName.len + DB_NICKNAME_ENTRY_HEADER_LEN ) != + dbentry->len ){ + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + /* copy the certkey */ + entry->subjectName.data = + (unsigned char *)PORT_ArenaAlloc(entry->common.arena, + entry->subjectName.len); + if ( entry->subjectName.data == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + PORT_Memcpy(entry->subjectName.data, + &dbentry->data[DB_NICKNAME_ENTRY_HEADER_LEN], + entry->subjectName.len); + + entry->nickname = (char *)PORT_ArenaAlloc(entry->common.arena, + PORT_Strlen(nickname)+1); + if ( entry->nickname ) { + PORT_Strcpy(entry->nickname, nickname); + } + + return(SECSuccess); + +loser: + return(SECFailure); +} + +/* + * create a new nickname entry + */ +static certDBEntryNickname * +NewDBNicknameEntry(char *nickname, SECItem *subjectName, unsigned int flags) +{ + PRArenaPool *arena = NULL; + certDBEntryNickname *entry; + int nnlen; + SECStatus rv; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + entry = (certDBEntryNickname *)PORT_ArenaAlloc(arena, + sizeof(certDBEntryNickname)); + if ( entry == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + /* init common fields */ + entry->common.arena = arena; + entry->common.type = certDBEntryTypeNickname; + entry->common.version = CERT_DB_FILE_VERSION; + entry->common.flags = flags; + + /* copy the nickname */ + nnlen = PORT_Strlen(nickname) + 1; + + entry->nickname = (char*)PORT_ArenaAlloc(arena, nnlen); + if ( entry->nickname == NULL ) { + goto loser; + } + + PORT_Memcpy(entry->nickname, nickname, nnlen); + + rv = SECITEM_CopyItem(arena, &entry->subjectName, subjectName); + if ( rv != SECSuccess ) { + goto loser; + } + + return(entry); +loser: + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(NULL); +} + +/* + * delete a nickname entry + */ +static SECStatus +DeleteDBNicknameEntry(NSSLOWCERTCertDBHandle *handle, char *nickname) +{ + PRArenaPool *arena = NULL; + SECStatus rv; + SECItem dbkey; + + if ( nickname == NULL ) { + return(SECSuccess); + } + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + goto loser; + } + + rv = EncodeDBNicknameKey(nickname, arena, &dbkey); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = DeleteDBEntry(handle, certDBEntryTypeNickname, &dbkey); + if ( rv == SECFailure ) { + goto loser; + } + + PORT_FreeArena(arena, PR_FALSE); + return(SECSuccess); + +loser: + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(SECFailure); +} + +/* + * Read a nickname entry + */ +static certDBEntryNickname * +ReadDBNicknameEntry(NSSLOWCERTCertDBHandle *handle, char *nickname) +{ + PRArenaPool *arena = NULL; + PRArenaPool *tmparena = NULL; + certDBEntryNickname *entry; + SECItem dbkey; + SECItem dbentry; + SECStatus rv; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( tmparena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + entry = (certDBEntryNickname *)PORT_ArenaAlloc(arena, + sizeof(certDBEntryNickname)); + if ( entry == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + entry->common.arena = arena; + entry->common.type = certDBEntryTypeNickname; + + rv = EncodeDBNicknameKey(nickname, tmparena, &dbkey); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); + if ( rv == SECFailure ) { + goto loser; + } + + /* is record long enough for header? */ + if ( dbentry.len < DB_NICKNAME_ENTRY_HEADER_LEN ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + rv = DecodeDBNicknameEntry(entry, &dbentry, nickname); + if ( rv != SECSuccess ) { + goto loser; + } + + PORT_FreeArena(tmparena, PR_FALSE); + return(entry); + +loser: + if ( tmparena ) { + PORT_FreeArena(tmparena, PR_FALSE); + } + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(NULL); +} + +/* + * Encode a nickname entry into byte stream suitable for + * the database + */ +static SECStatus +WriteDBNicknameEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryNickname *entry) +{ + SECItem dbitem, dbkey; + PRArenaPool *tmparena = NULL; + SECStatus rv; + + tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( tmparena == NULL ) { + goto loser; + } + + rv = EncodeDBNicknameEntry(entry, tmparena, &dbitem); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = EncodeDBNicknameKey(entry->nickname, tmparena, &dbkey); + if ( rv != SECSuccess ) { + goto loser; + } + + /* now write it to the database */ + rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem); + if ( rv != SECSuccess ) { + goto loser; + } + + PORT_FreeArena(tmparena, PR_FALSE); + return(SECSuccess); + +loser: + if ( tmparena ) { + PORT_FreeArena(tmparena, PR_FALSE); + } + return(SECFailure); + +} + +SECStatus +EncodeDBSMimeEntry(certDBEntrySMime *entry, PRArenaPool *arena, + SECItem *dbitem) +{ + unsigned char *buf; + + /* allocate space for encoded database record, including space + * for low level header + */ + dbitem->len = entry->subjectName.len + entry->smimeOptions.len + + entry->optionsDate.len + + DB_SMIME_ENTRY_HEADER_LEN + SEC_DB_ENTRY_HEADER_LEN; + + dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len); + if ( dbitem->data == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + /* fill in database record */ + buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN]; + + buf[0] = ( entry->subjectName.len >> 8 ) & 0xff; + buf[1] = entry->subjectName.len & 0xff; + buf[2] = ( entry->smimeOptions.len >> 8 ) & 0xff; + buf[3] = entry->smimeOptions.len & 0xff; + buf[4] = ( entry->optionsDate.len >> 8 ) & 0xff; + buf[5] = entry->optionsDate.len & 0xff; + + /* if no smime options, then there should not be an options date either */ + PORT_Assert( ! ( ( entry->smimeOptions.len == 0 ) && + ( entry->optionsDate.len != 0 ) ) ); + + PORT_Memcpy(&buf[DB_SMIME_ENTRY_HEADER_LEN], entry->subjectName.data, + entry->subjectName.len); + if ( entry->smimeOptions.len ) { + PORT_Memcpy(&buf[DB_SMIME_ENTRY_HEADER_LEN+entry->subjectName.len], + entry->smimeOptions.data, + entry->smimeOptions.len); + PORT_Memcpy(&buf[DB_SMIME_ENTRY_HEADER_LEN + entry->subjectName.len + + entry->smimeOptions.len], + entry->optionsDate.data, + entry->optionsDate.len); + } + + return(SECSuccess); + +loser: + return(SECFailure); +} + +/* + * Encode a database key for a SMIME record + */ +static SECStatus +EncodeDBSMimeKey(char *emailAddr, PRArenaPool *arena, + SECItem *dbkey) +{ + unsigned int addrlen; + + addrlen = PORT_Strlen(emailAddr) + 1; /* includes null */ + + /* now get the database key and format it */ + dbkey->len = addrlen + SEC_DB_KEY_HEADER_LEN; + dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len); + if ( dbkey->data == NULL ) { + goto loser; + } + PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], emailAddr, addrlen); + dbkey->data[0] = certDBEntryTypeSMimeProfile; + + return(SECSuccess); + +loser: + return(SECFailure); +} + +/* + * Decode a database SMIME record + */ +static SECStatus +DecodeDBSMimeEntry(certDBEntrySMime *entry, SECItem *dbentry, char *emailAddr) +{ + /* is record long enough for header? */ + if ( dbentry->len < DB_SMIME_ENTRY_HEADER_LEN ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + /* is database entry correct length? */ + entry->subjectName.len = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] ); + entry->smimeOptions.len = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] ); + entry->optionsDate.len = ( ( dbentry->data[4] << 8 ) | dbentry->data[5] ); + if (( entry->subjectName.len + entry->smimeOptions.len + + entry->optionsDate.len + DB_SMIME_ENTRY_HEADER_LEN ) != dbentry->len){ + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + /* copy the subject name */ + entry->subjectName.data = + (unsigned char *)PORT_ArenaAlloc(entry->common.arena, + entry->subjectName.len); + if ( entry->subjectName.data == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + PORT_Memcpy(entry->subjectName.data, + &dbentry->data[DB_SMIME_ENTRY_HEADER_LEN], + entry->subjectName.len); + + /* copy the smime options */ + if ( entry->smimeOptions.len ) { + entry->smimeOptions.data = + (unsigned char *)PORT_ArenaAlloc(entry->common.arena, + entry->smimeOptions.len); + if ( entry->smimeOptions.data == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + PORT_Memcpy(entry->smimeOptions.data, + &dbentry->data[DB_SMIME_ENTRY_HEADER_LEN + + entry->subjectName.len], + entry->smimeOptions.len); + } + if ( entry->optionsDate.len ) { + entry->optionsDate.data = + (unsigned char *)PORT_ArenaAlloc(entry->common.arena, + entry->optionsDate.len); + if ( entry->optionsDate.data == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + PORT_Memcpy(entry->optionsDate.data, + &dbentry->data[DB_SMIME_ENTRY_HEADER_LEN + + entry->subjectName.len + + entry->smimeOptions.len], + entry->optionsDate.len); + } + + /* both options and options date must either exist or not exist */ + if ( ( ( entry->optionsDate.len == 0 ) || + ( entry->smimeOptions.len == 0 ) ) && + entry->smimeOptions.len != entry->optionsDate.len ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + entry->emailAddr = (char *)PORT_Alloc(PORT_Strlen(emailAddr)+1); + if ( entry->emailAddr ) { + PORT_Strcpy(entry->emailAddr, emailAddr); + } + + return(SECSuccess); + +loser: + return(SECFailure); +} + +/* + * create a new SMIME entry + */ +static certDBEntrySMime * +NewDBSMimeEntry(char *emailAddr, SECItem *subjectName, SECItem *smimeOptions, + SECItem *optionsDate, unsigned int flags) +{ + PRArenaPool *arena = NULL; + certDBEntrySMime *entry; + int addrlen; + SECStatus rv; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + entry = (certDBEntrySMime *)PORT_ArenaAlloc(arena, + sizeof(certDBEntrySMime)); + if ( entry == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + /* init common fields */ + entry->common.arena = arena; + entry->common.type = certDBEntryTypeSMimeProfile; + entry->common.version = CERT_DB_FILE_VERSION; + entry->common.flags = flags; + + /* copy the email addr */ + addrlen = PORT_Strlen(emailAddr) + 1; + + entry->emailAddr = (char*)PORT_ArenaAlloc(arena, addrlen); + if ( entry->emailAddr == NULL ) { + goto loser; + } + + PORT_Memcpy(entry->emailAddr, emailAddr, addrlen); + + /* copy the subject name */ + rv = SECITEM_CopyItem(arena, &entry->subjectName, subjectName); + if ( rv != SECSuccess ) { + goto loser; + } + + /* copy the smime options */ + if ( smimeOptions ) { + rv = SECITEM_CopyItem(arena, &entry->smimeOptions, smimeOptions); + if ( rv != SECSuccess ) { + goto loser; + } + } else { + PORT_Assert(optionsDate == NULL); + entry->smimeOptions.data = NULL; + entry->smimeOptions.len = 0; + } + + /* copy the options date */ + if ( optionsDate ) { + rv = SECITEM_CopyItem(arena, &entry->optionsDate, optionsDate); + if ( rv != SECSuccess ) { + goto loser; + } + } else { + PORT_Assert(smimeOptions == NULL); + entry->optionsDate.data = NULL; + entry->optionsDate.len = 0; + } + + return(entry); +loser: + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(NULL); +} + +/* + * delete a SMIME entry + */ +static SECStatus +DeleteDBSMimeEntry(NSSLOWCERTCertDBHandle *handle, char *emailAddr) +{ + PRArenaPool *arena = NULL; + SECStatus rv; + SECItem dbkey; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + goto loser; + } + + rv = EncodeDBSMimeKey(emailAddr, arena, &dbkey); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = DeleteDBEntry(handle, certDBEntryTypeSMimeProfile, &dbkey); + if ( rv == SECFailure ) { + goto loser; + } + + PORT_FreeArena(arena, PR_FALSE); + return(SECSuccess); + +loser: + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(SECFailure); +} + +/* + * Read a SMIME entry + */ +certDBEntrySMime * +nsslowcert_ReadDBSMimeEntry(NSSLOWCERTCertDBHandle *handle, char *emailAddr) +{ + PRArenaPool *arena = NULL; + PRArenaPool *tmparena = NULL; + certDBEntrySMime *entry; + SECItem dbkey; + SECItem dbentry; + SECStatus rv; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( tmparena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + entry = (certDBEntrySMime *)PORT_ArenaAlloc(arena, + sizeof(certDBEntrySMime)); + if ( entry == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + entry->common.arena = arena; + entry->common.type = certDBEntryTypeSMimeProfile; + + rv = EncodeDBSMimeKey(emailAddr, tmparena, &dbkey); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); + if ( rv == SECFailure ) { + goto loser; + } + + /* is record long enough for header? */ + if ( dbentry.len < DB_SMIME_ENTRY_HEADER_LEN ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + rv = DecodeDBSMimeEntry(entry, &dbentry, emailAddr); + if ( rv != SECSuccess ) { + goto loser; + } + + PORT_FreeArena(tmparena, PR_FALSE); + return(entry); + +loser: + if ( tmparena ) { + PORT_FreeArena(tmparena, PR_FALSE); + } + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(NULL); +} + +/* + * Encode a SMIME entry into byte stream suitable for + * the database + */ +static SECStatus +WriteDBSMimeEntry(NSSLOWCERTCertDBHandle *handle, certDBEntrySMime *entry) +{ + SECItem dbitem, dbkey; + PRArenaPool *tmparena = NULL; + SECStatus rv; + + tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( tmparena == NULL ) { + goto loser; + } + + rv = EncodeDBSMimeEntry(entry, tmparena, &dbitem); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = EncodeDBSMimeKey(entry->emailAddr, tmparena, &dbkey); + if ( rv != SECSuccess ) { + goto loser; + } + + /* now write it to the database */ + rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem); + if ( rv != SECSuccess ) { + goto loser; + } + + PORT_FreeArena(tmparena, PR_FALSE); + return(SECSuccess); + +loser: + if ( tmparena ) { + PORT_FreeArena(tmparena, PR_FALSE); + } + return(SECFailure); + +} + +/* + * Encode a database subject record + */ +static SECStatus +EncodeDBSubjectEntry(certDBEntrySubject *entry, PRArenaPool *arena, + SECItem *dbitem) +{ + unsigned char *buf; + int len; + unsigned int ncerts; + unsigned int i; + unsigned char *tmpbuf; + unsigned int nnlen = 0; + unsigned int eaddrlen = 0; + int keyidoff; + SECItem *certKeys; + SECItem *keyIDs; + + if ( entry->nickname ) { + nnlen = PORT_Strlen(entry->nickname) + 1; + } + if ( entry->emailAddr ) { + eaddrlen = PORT_Strlen(entry->emailAddr) + 1; + } + + ncerts = entry->ncerts; + + /* compute the length of the entry */ + keyidoff = DB_SUBJECT_ENTRY_HEADER_LEN + nnlen + eaddrlen; + len = keyidoff + 4 * ncerts; + for ( i = 0; i < ncerts; i++ ) { + len += entry->certKeys[i].len; + len += entry->keyIDs[i].len; + } + + /* allocate space for encoded database record, including space + * for low level header + */ + dbitem->len = len + SEC_DB_ENTRY_HEADER_LEN; + + dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len); + if ( dbitem->data == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + /* fill in database record */ + buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN]; + + buf[0] = ( ncerts >> 8 ) & 0xff; + buf[1] = ncerts & 0xff; + buf[2] = ( nnlen >> 8 ) & 0xff; + buf[3] = nnlen & 0xff; + buf[4] = ( eaddrlen >> 8 ) & 0xff; + buf[5] = eaddrlen & 0xff; + + PORT_Memcpy(&buf[DB_SUBJECT_ENTRY_HEADER_LEN], entry->nickname, nnlen); + PORT_Memcpy(&buf[DB_SUBJECT_ENTRY_HEADER_LEN+nnlen], entry->emailAddr, + eaddrlen); + + for ( i = 0; i < ncerts; i++ ) { + + certKeys = entry->certKeys; + keyIDs = entry->keyIDs; + + buf[keyidoff+i*2] = ( certKeys[i].len >> 8 ) & 0xff; + buf[keyidoff+1+i*2] = certKeys[i].len & 0xff; + buf[keyidoff+ncerts*2+i*2] = ( keyIDs[i].len >> 8 ) & 0xff; + buf[keyidoff+1+ncerts*2+i*2] = keyIDs[i].len & 0xff; + } + + /* temp pointer used to stuff certkeys and keyids into the buffer */ + tmpbuf = &buf[keyidoff+ncerts*4]; + + for ( i = 0; i < ncerts; i++ ) { + certKeys = entry->certKeys; + PORT_Memcpy(tmpbuf, certKeys[i].data, certKeys[i].len); + tmpbuf = tmpbuf + certKeys[i].len; + } + + for ( i = 0; i < ncerts; i++ ) { + keyIDs = entry->keyIDs; + PORT_Memcpy(tmpbuf, keyIDs[i].data, keyIDs[i].len); + tmpbuf = tmpbuf + keyIDs[i].len; + } + + PORT_Assert(tmpbuf == &buf[len]); + + return(SECSuccess); + +loser: + return(SECFailure); +} + +/* + * Encode a database key for a subject record + */ +static SECStatus +EncodeDBSubjectKey(SECItem *derSubject, PRArenaPool *arena, + SECItem *dbkey) +{ + dbkey->len = derSubject->len + SEC_DB_KEY_HEADER_LEN; + dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len); + if ( dbkey->data == NULL ) { + goto loser; + } + PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], derSubject->data, + derSubject->len); + dbkey->data[0] = certDBEntryTypeSubject; + + return(SECSuccess); + +loser: + return(SECFailure); +} + +static SECStatus +DecodeDBSubjectEntry(certDBEntrySubject *entry, SECItem *dbentry, + SECItem *derSubject) +{ + unsigned int ncerts; + PRArenaPool *arena; + unsigned int len, itemlen; + unsigned char *tmpbuf; + unsigned int i; + SECStatus rv; + unsigned int keyidoff; + unsigned int nnlen, eaddrlen; + + arena = entry->common.arena; + + rv = SECITEM_CopyItem(arena, &entry->derSubject, derSubject); + if ( rv != SECSuccess ) { + goto loser; + } + + /* is record long enough for header? */ + if ( dbentry->len < DB_SUBJECT_ENTRY_HEADER_LEN ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + entry->ncerts = ncerts = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] ); + nnlen = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] ); + eaddrlen = ( ( dbentry->data[4] << 8 ) | dbentry->data[5] ); + if ( dbentry->len < ( ncerts * 4 + DB_SUBJECT_ENTRY_HEADER_LEN + + nnlen + eaddrlen) ) { + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + entry->certKeys = (SECItem *)PORT_ArenaAlloc(arena, + sizeof(SECItem) * ncerts); + entry->keyIDs = (SECItem *)PORT_ArenaAlloc(arena, + sizeof(SECItem) * ncerts); + + if ( ( entry->certKeys == NULL ) || ( entry->keyIDs == NULL ) ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + if ( nnlen > 1 ) { /* null terminator is stored */ + entry->nickname = (char *)PORT_ArenaAlloc(arena, nnlen); + if ( entry->nickname == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + PORT_Memcpy(entry->nickname, + &dbentry->data[DB_SUBJECT_ENTRY_HEADER_LEN], + nnlen); + } else { + entry->nickname = NULL; + } + + if ( eaddrlen > 1 ) { /* null terminator is stored */ + entry->emailAddr = (char *)PORT_ArenaAlloc(arena, eaddrlen); + if ( entry->emailAddr == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + PORT_Memcpy(entry->emailAddr, + &dbentry->data[DB_SUBJECT_ENTRY_HEADER_LEN+nnlen], + eaddrlen); + } else { + entry->emailAddr = NULL; + } + + /* collect the lengths of the certKeys and keyIDs, and total the + * overall length. + */ + keyidoff = DB_SUBJECT_ENTRY_HEADER_LEN + nnlen + eaddrlen; + len = keyidoff + 4 * ncerts; + + tmpbuf = &dbentry->data[0]; + + for ( i = 0; i < ncerts; i++ ) { + + itemlen = ( tmpbuf[keyidoff + 2*i] << 8 ) | tmpbuf[keyidoff + 1 + 2*i] ; + len += itemlen; + entry->certKeys[i].len = itemlen; + + itemlen = ( tmpbuf[keyidoff + 2*ncerts + 2*i] << 8 ) | + tmpbuf[keyidoff + 1 + 2*ncerts + 2*i] ; + len += itemlen; + entry->keyIDs[i].len = itemlen; + } + + /* is database entry correct length? */ + if ( len != dbentry->len ){ + PORT_SetError(SEC_ERROR_BAD_DATABASE); + goto loser; + } + + tmpbuf = &tmpbuf[keyidoff + 4*ncerts]; + for ( i = 0; i < ncerts; i++ ) { + entry->certKeys[i].data = + (unsigned char *)PORT_ArenaAlloc(arena, entry->certKeys[i].len); + if ( entry->certKeys[i].data == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + PORT_Memcpy(entry->certKeys[i].data, tmpbuf, entry->certKeys[i].len); + tmpbuf = &tmpbuf[entry->certKeys[i].len]; + } + + for ( i = 0; i < ncerts; i++ ) { + entry->keyIDs[i].data = + (unsigned char *)PORT_ArenaAlloc(arena, entry->keyIDs[i].len); + if ( entry->keyIDs[i].data == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + PORT_Memcpy(entry->keyIDs[i].data, tmpbuf, entry->keyIDs[i].len); + tmpbuf = &tmpbuf[entry->keyIDs[i].len]; + } + + PORT_Assert(tmpbuf == &dbentry->data[dbentry->len]); + + return(SECSuccess); + +loser: + return(SECFailure); +} + +/* + * create a new subject entry with a single cert + */ +static certDBEntrySubject * +NewDBSubjectEntry(SECItem *derSubject, SECItem *certKey, + SECItem *keyID, char *nickname, char *emailAddr, + unsigned int flags) +{ + PRArenaPool *arena = NULL; + certDBEntrySubject *entry; + SECStatus rv; + unsigned int nnlen; + unsigned int eaddrlen; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + entry = (certDBEntrySubject *)PORT_ArenaAlloc(arena, + sizeof(certDBEntrySubject)); + if ( entry == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + /* init common fields */ + entry->common.arena = arena; + entry->common.type = certDBEntryTypeSubject; + entry->common.version = CERT_DB_FILE_VERSION; + entry->common.flags = flags; + + /* copy the subject */ + rv = SECITEM_CopyItem(arena, &entry->derSubject, derSubject); + if ( rv != SECSuccess ) { + goto loser; + } + + entry->ncerts = 1; + /* copy nickname */ + if ( nickname && ( *nickname != '\0' ) ) { + nnlen = PORT_Strlen(nickname) + 1; + entry->nickname = (char *)PORT_ArenaAlloc(arena, nnlen); + if ( entry->nickname == NULL ) { + goto loser; + } + + PORT_Memcpy(entry->nickname, nickname, nnlen); + } else { + entry->nickname = NULL; + } + + /* copy email addr */ + if ( emailAddr && ( *emailAddr != '\0' ) ) { + emailAddr = nsslowcert_FixupEmailAddr(emailAddr); + if ( emailAddr == NULL ) { + entry->emailAddr = NULL; + goto loser; + } + + eaddrlen = PORT_Strlen(emailAddr) + 1; + entry->emailAddr = (char *)PORT_ArenaAlloc(arena, eaddrlen); + if ( entry->emailAddr == NULL ) { + PORT_Free(emailAddr); + goto loser; + } + + PORT_Memcpy(entry->emailAddr, emailAddr, eaddrlen); + PORT_Free(emailAddr); + } else { + entry->emailAddr = NULL; + } + + /* allocate space for certKeys and keyIDs */ + entry->certKeys = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem)); + entry->keyIDs = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem)); + if ( ( entry->certKeys == NULL ) || ( entry->keyIDs == NULL ) ) { + goto loser; + } + + /* copy the certKey and keyID */ + rv = SECITEM_CopyItem(arena, &entry->certKeys[0], certKey); + if ( rv != SECSuccess ) { + goto loser; + } + rv = SECITEM_CopyItem(arena, &entry->keyIDs[0], keyID); + if ( rv != SECSuccess ) { + goto loser; + } + + return(entry); +loser: + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(NULL); +} + +/* + * delete a subject entry + */ +static SECStatus +DeleteDBSubjectEntry(NSSLOWCERTCertDBHandle *handle, SECItem *derSubject) +{ + SECItem dbkey; + PRArenaPool *arena = NULL; + SECStatus rv; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + goto loser; + } + + rv = EncodeDBSubjectKey(derSubject, arena, &dbkey); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = DeleteDBEntry(handle, certDBEntryTypeSubject, &dbkey); + if ( rv == SECFailure ) { + goto loser; + } + + PORT_FreeArena(arena, PR_FALSE); + return(SECSuccess); + +loser: + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(SECFailure); +} + +/* + * Read the subject entry + */ +static certDBEntrySubject * +ReadDBSubjectEntry(NSSLOWCERTCertDBHandle *handle, SECItem *derSubject) +{ + PRArenaPool *arena = NULL; + PRArenaPool *tmparena = NULL; + certDBEntrySubject *entry; + SECItem dbkey; + SECItem dbentry; + SECStatus rv; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( tmparena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + entry = (certDBEntrySubject *)PORT_ArenaAlloc(arena, + sizeof(certDBEntrySubject)); + if ( entry == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + entry->common.arena = arena; + entry->common.type = certDBEntryTypeSubject; + + rv = EncodeDBSubjectKey(derSubject, tmparena, &dbkey); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); + if ( rv == SECFailure ) { + goto loser; + } + + rv = DecodeDBSubjectEntry(entry, &dbentry, derSubject); + if ( rv == SECFailure ) { + goto loser; + } + + PORT_FreeArena(tmparena, PR_FALSE); + return(entry); + +loser: + if ( tmparena ) { + PORT_FreeArena(tmparena, PR_FALSE); + } + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(NULL); +} + +/* + * Encode a subject name entry into byte stream suitable for + * the database + */ +static SECStatus +WriteDBSubjectEntry(NSSLOWCERTCertDBHandle *handle, certDBEntrySubject *entry) +{ + SECItem dbitem, dbkey; + PRArenaPool *tmparena = NULL; + SECStatus rv; + + tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( tmparena == NULL ) { + goto loser; + } + + rv = EncodeDBSubjectEntry(entry, tmparena, &dbitem); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = EncodeDBSubjectKey(&entry->derSubject, tmparena, &dbkey); + if ( rv != SECSuccess ) { + goto loser; + } + + /* now write it to the database */ + rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem); + if ( rv != SECSuccess ) { + goto loser; + } + + PORT_FreeArena(tmparena, PR_FALSE); + return(SECSuccess); + +loser: + if ( tmparena ) { + PORT_FreeArena(tmparena, PR_FALSE); + } + return(SECFailure); + +} + +static SECStatus +UpdateSubjectWithEmailAddr(NSSLOWCERTCertDBHandle *dbhandle, + SECItem *derSubject, char *emailAddr) +{ + PRBool save = PR_FALSE, delold = PR_FALSE; + certDBEntrySubject *entry; + SECStatus rv; + + if (emailAddr) { + emailAddr = nsslowcert_FixupEmailAddr(emailAddr); + if (emailAddr == NULL) { + return SECFailure; + } + } + + entry = ReadDBSubjectEntry(dbhandle,derSubject); + + if ( entry->emailAddr ) { + if ( (emailAddr == NULL) || + (PORT_Strcmp(entry->emailAddr, emailAddr) != 0) ) { + save = PR_TRUE; + delold = PR_TRUE; + } + } else if (emailAddr) { + save = PR_TRUE; + } + + if ( delold ) { + /* delete the old smime entry, because this cert now has a new + * smime entry pointing to it + */ + PORT_Assert(save); + PORT_Assert(entry->emailAddr != NULL); + DeleteDBSMimeEntry(dbhandle, entry->emailAddr); + } + + if ( save ) { + unsigned int len; + + PORT_Assert(entry != NULL); + if (emailAddr) { + len = PORT_Strlen(emailAddr) + 1; + entry->emailAddr = (char *)PORT_ArenaAlloc(entry->common.arena, len); + if ( entry->emailAddr == NULL ) { + goto loser; + } + PORT_Memcpy(entry->emailAddr, emailAddr, len); + } else { + entry->emailAddr = NULL; + } + + /* delete the subject entry */ + DeleteDBSubjectEntry(dbhandle, derSubject); + + /* write the new one */ + rv = WriteDBSubjectEntry(dbhandle, entry); + if ( rv != SECSuccess ) { + goto loser; + } + } + + if (emailAddr) PORT_Free(emailAddr); + return(SECSuccess); + +loser: + if (emailAddr) PORT_Free(emailAddr); + return(SECFailure); +} + +/* + * writes a nickname to an existing subject entry that does not currently + * have one + */ +static SECStatus +AddNicknameToSubject(NSSLOWCERTCertDBHandle *dbhandle, + NSSLOWCERTCertificate *cert, char *nickname) +{ + certDBEntrySubject *entry; + SECStatus rv; + + if ( nickname == NULL ) { + return(SECFailure); + } + + entry = ReadDBSubjectEntry(dbhandle,&cert->derSubject); + PORT_Assert(entry != NULL); + if ( entry == NULL ) { + goto loser; + } + + PORT_Assert(entry->nickname == NULL); + if ( entry->nickname != NULL ) { + goto loser; + } + + entry->nickname = (nickname) ? + PORT_ArenaStrdup(entry->common.arena, nickname) : NULL; + + if ( entry->nickname == NULL ) { + goto loser; + } + + /* delete the subject entry */ + DeleteDBSubjectEntry(dbhandle, &cert->derSubject); + + /* write the new one */ + rv = WriteDBSubjectEntry(dbhandle, entry); + if ( rv != SECSuccess ) { + goto loser; + } + + return(SECSuccess); + +loser: + return(SECFailure); +} + +/* + * create a new version entry + */ +static certDBEntryVersion * +NewDBVersionEntry(unsigned int flags) +{ + PRArenaPool *arena = NULL; + certDBEntryVersion *entry; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + entry = (certDBEntryVersion *)PORT_ArenaAlloc(arena, + sizeof(certDBEntryVersion)); + if ( entry == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + entry->common.arena = arena; + entry->common.type = certDBEntryTypeVersion; + entry->common.version = CERT_DB_FILE_VERSION; + entry->common.flags = flags; + + return(entry); +loser: + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(NULL); +} + +/* + * Read the version entry + */ +static certDBEntryVersion * +ReadDBVersionEntry(NSSLOWCERTCertDBHandle *handle) +{ + PRArenaPool *arena = NULL; + PRArenaPool *tmparena = NULL; + certDBEntryVersion *entry; + SECItem dbkey; + SECItem dbentry; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( tmparena == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + entry = (certDBEntryVersion *)PORT_ArenaAlloc(arena, + sizeof(certDBEntryVersion)); + if ( entry == NULL ) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + entry->common.arena = arena; + entry->common.type = certDBEntryTypeVersion; + + /* now get the database key and format it */ + dbkey.len = SEC_DB_VERSION_KEY_LEN + SEC_DB_KEY_HEADER_LEN; + dbkey.data = (unsigned char *)PORT_ArenaAlloc(tmparena, dbkey.len); + if ( dbkey.data == NULL ) { + goto loser; + } + PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], SEC_DB_VERSION_KEY, + SEC_DB_VERSION_KEY_LEN); + + ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); + + PORT_FreeArena(tmparena, PR_FALSE); + return(entry); + +loser: + if ( tmparena ) { + PORT_FreeArena(tmparena, PR_FALSE); + } + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(NULL); +} + + +/* + * Encode a version entry into byte stream suitable for + * the database + */ +static SECStatus +WriteDBVersionEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryVersion *entry) +{ + SECItem dbitem, dbkey; + PRArenaPool *tmparena = NULL; + SECStatus rv; + + tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( tmparena == NULL ) { + goto loser; + } + + /* allocate space for encoded database record, including space + * for low level header + */ + dbitem.len = SEC_DB_ENTRY_HEADER_LEN; + + dbitem.data = (unsigned char *)PORT_ArenaAlloc(tmparena, dbitem.len); + if ( dbitem.data == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + /* now get the database key and format it */ + dbkey.len = SEC_DB_VERSION_KEY_LEN + SEC_DB_KEY_HEADER_LEN; + dbkey.data = (unsigned char *)PORT_ArenaAlloc(tmparena, dbkey.len); + if ( dbkey.data == NULL ) { + goto loser; + } + PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], SEC_DB_VERSION_KEY, + SEC_DB_VERSION_KEY_LEN); + + /* now write it to the database */ + rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem); + if ( rv != SECSuccess ) { + goto loser; + } + + PORT_FreeArena(tmparena, PR_FALSE); + return(SECSuccess); + +loser: + if ( tmparena ) { + PORT_FreeArena(tmparena, PR_FALSE); + } + return(SECFailure); +} + +/* + * cert is no longer a perm cert, but will remain a temp cert + */ +static SECStatus +RemovePermSubjectNode(NSSLOWCERTCertificate *cert) +{ + certDBEntrySubject *entry; + unsigned int i; + SECStatus rv; + + entry = ReadDBSubjectEntry(cert->dbhandle,&cert->derSubject); + PORT_Assert(entry); + if ( entry == NULL ) { + return(SECFailure); + } + + PORT_Assert(entry->ncerts); + rv = SECFailure; + + if ( entry->ncerts > 1 ) { + for ( i = 0; i < entry->ncerts; i++ ) { + if ( SECITEM_CompareItem(&entry->certKeys[i], &cert->certKey) == + SECEqual ) { + /* copy rest of list forward one entry */ + for ( i = i + 1; i < entry->ncerts; i++ ) { + entry->certKeys[i-1] = entry->certKeys[i]; + entry->keyIDs[i-1] = entry->keyIDs[i]; + } + entry->ncerts--; + DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject); + rv = WriteDBSubjectEntry(cert->dbhandle, entry); + break; + } + } + } else { + /* no entries left, delete the perm entry in the DB */ + if ( entry->emailAddr ) { + /* if the subject had an email record, then delete it too */ + DeleteDBSMimeEntry(cert->dbhandle, entry->emailAddr); + } + + DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject); + } + DestroyDBEntry((certDBEntry *)entry); + + return(rv); +} + +/* + * add a cert to the perm subject list + */ +static SECStatus +AddPermSubjectNode(certDBEntrySubject *entry, NSSLOWCERTCertificate *cert, + char *nickname) +{ + SECItem *newCertKeys, *newKeyIDs; + int i; + SECStatus rv; + NSSLOWCERTCertificate *cmpcert; + unsigned int nnlen; + int ncerts; + + + PORT_Assert(entry); + ncerts = entry->ncerts; + + if ( nickname && entry->nickname ) { + /* nicknames must be the same */ + PORT_Assert(PORT_Strcmp(nickname, entry->nickname) == 0); + } + + if ( ( entry->nickname == NULL ) && ( nickname != NULL ) ) { + /* copy nickname into the entry */ + nnlen = PORT_Strlen(nickname) + 1; + entry->nickname = (char *)PORT_ArenaAlloc(entry->common.arena,nnlen); + if ( entry->nickname == NULL ) { + return(SECFailure); + } + PORT_Memcpy(entry->nickname, nickname, nnlen); + } + + /* a DB entry already exists, so add this cert */ + newCertKeys = (SECItem *)PORT_ArenaAlloc(entry->common.arena, + sizeof(SECItem) * ( ncerts + 1 ) ); + newKeyIDs = (SECItem *)PORT_ArenaAlloc(entry->common.arena, + sizeof(SECItem) * ( ncerts + 1 ) ); + + if ( ( newCertKeys == NULL ) || ( newKeyIDs == NULL ) ) { + return(SECFailure); + } + + for ( i = 0; i < ncerts; i++ ) { + cmpcert = nsslowcert_FindCertByKey(cert->dbhandle, + &entry->certKeys[i]); + PORT_Assert(cmpcert); + if ( nsslowcert_IsNewer(cert, cmpcert) ) { + /* insert before cmpcert */ + rv = SECITEM_CopyItem(entry->common.arena, &newCertKeys[i], + &cert->certKey); + if ( rv != SECSuccess ) { + return(SECFailure); + } + rv = SECITEM_CopyItem(entry->common.arena, &newKeyIDs[i], + &cert->subjectKeyID); + if ( rv != SECSuccess ) { + return(SECFailure); + } + /* copy the rest of the entry */ + for ( ; i < ncerts; i++ ) { + newCertKeys[i+1] = entry->certKeys[i]; + newKeyIDs[i+1] = entry->keyIDs[i]; + } + + /* update certKeys and keyIDs */ + entry->certKeys = newCertKeys; + entry->keyIDs = newKeyIDs; + + /* increment count */ + entry->ncerts++; + break; + } + /* copy this cert entry */ + newCertKeys[i] = entry->certKeys[i]; + newKeyIDs[i] = entry->keyIDs[i]; + } + + if ( entry->ncerts == ncerts ) { + /* insert new one at end */ + rv = SECITEM_CopyItem(entry->common.arena, &newCertKeys[ncerts], + &cert->certKey); + if ( rv != SECSuccess ) { + return(SECFailure); + } + rv = SECITEM_CopyItem(entry->common.arena, &newKeyIDs[ncerts], + &cert->subjectKeyID); + if ( rv != SECSuccess ) { + return(SECFailure); + } + + /* update certKeys and keyIDs */ + entry->certKeys = newCertKeys; + entry->keyIDs = newKeyIDs; + + /* increment count */ + entry->ncerts++; + } + DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject); + rv = WriteDBSubjectEntry(cert->dbhandle, entry); + return(rv); +} + + +SECStatus +nsslowcert_TraversePermCertsForSubject(NSSLOWCERTCertDBHandle *handle, + SECItem *derSubject, + NSSLOWCERTCertCallback cb, void *cbarg) +{ + certDBEntrySubject *entry; + int i; + NSSLOWCERTCertificate *cert; + SECStatus rv = SECSuccess; + + entry = ReadDBSubjectEntry(handle, derSubject); + + if ( entry == NULL ) { + return(SECFailure); + } + + for( i = 0; i < entry->ncerts; i++ ) { + cert = nsslowcert_FindCertByKey(handle, &entry->certKeys[i]); + rv = (* cb)(cert, cbarg); + nsslowcert_DestroyCertificate(cert); + if ( rv == SECFailure ) { + break; + } + } + + DestroyDBEntry((certDBEntry *)entry); + + return(rv); +} + +int +nsslowcert_NumPermCertsForSubject(NSSLOWCERTCertDBHandle *handle, SECItem *derSubject) +{ + certDBEntrySubject *entry; + int ret; + + entry = ReadDBSubjectEntry(handle, derSubject); + + if ( entry == NULL ) { + return(SECFailure); + } + + ret = entry->ncerts; + + DestroyDBEntry((certDBEntry *)entry); + + return(ret); +} + +SECStatus +nsslowcert_TraversePermCertsForNickname(NSSLOWCERTCertDBHandle *handle, char *nickname, + NSSLOWCERTCertCallback cb, void *cbarg) +{ + certDBEntryNickname *nnentry = NULL; + certDBEntrySMime *smentry = NULL; + SECStatus rv; + SECItem *derSubject = NULL; + + nnentry = ReadDBNicknameEntry(handle, nickname); + if ( nnentry ) { + derSubject = &nnentry->subjectName; + } else { + smentry = nsslowcert_ReadDBSMimeEntry(handle, nickname); + if ( smentry ) { + derSubject = &smentry->subjectName; + } + } + + if ( derSubject ) { + rv = nsslowcert_TraversePermCertsForSubject(handle, derSubject, + cb, cbarg); + } else { + rv = SECFailure; + } + + if ( nnentry ) { + DestroyDBEntry((certDBEntry *)nnentry); + } + if ( smentry ) { + DestroyDBEntry((certDBEntry *)smentry); + } + + return(rv); +} + + +int +nsslowcert_NumPermCertsForNickname(NSSLOWCERTCertDBHandle *handle, char *nickname) +{ + certDBEntryNickname *entry; + int ret; + + entry = ReadDBNicknameEntry(handle, nickname); + + if ( entry ) { + ret = nsslowcert_NumPermCertsForSubject(handle, &entry->subjectName); + DestroyDBEntry((certDBEntry *)entry); + } else { + ret = 0; + } + return(ret); +} + +/* + * add a nickname to a cert that doesn't have one + */ +static SECStatus +AddNicknameToPermCert(NSSLOWCERTCertDBHandle *dbhandle, + NSSLOWCERTCertificate *cert, char *nickname) +{ + certDBEntryCert *entry; + int rv; + + entry = cert->dbEntry; + PORT_Assert(entry != NULL); + if ( entry == NULL ) { + goto loser; + } + + entry->nickname = PORT_ArenaStrdup(entry->common.arena, nickname); + + rv = WriteDBCertEntry(dbhandle, entry); + if ( rv ) { + goto loser; + } + + cert->nickname = PORT_ArenaStrdup(cert->arena, nickname); + return(SECSuccess); + +loser: + return(SECFailure); +} + +/* + * add a nickname to a cert that is already in the perm database, but doesn't + * have one yet (it is probably an e-mail cert). + */ +SECStatus +nsslowcert_AddPermNickname(NSSLOWCERTCertDBHandle *dbhandle, + NSSLOWCERTCertificate *cert, char *nickname) +{ + SECStatus rv = SECFailure; + certDBEntrySubject *entry = NULL; + + nsslowcert_LockDB(dbhandle); + + PORT_Assert(cert->nickname == NULL); + + if ( cert->nickname != NULL ) { + rv = SECSuccess; + goto loser; + } + + entry = ReadDBSubjectEntry(dbhandle, &cert->derSubject); + if (entry == NULL) goto loser; + + if ( entry->nickname == NULL ) { + /* no nickname for subject */ + rv = AddNicknameToSubject(dbhandle, cert, nickname); + if ( rv != SECSuccess ) { + goto loser; + } + rv = AddNicknameToPermCert(dbhandle, cert, nickname); + if ( rv != SECSuccess ) { + goto loser; + } + } else { + /* subject already has a nickname */ + rv = AddNicknameToPermCert(dbhandle, cert, entry->nickname); + if ( rv != SECSuccess ) { + goto loser; + } + } + rv = SECSuccess; + +loser: + if (entry) { + DestroyDBEntry((certDBEntry *)entry); + } + nsslowcert_UnlockDB(dbhandle); + return(rv); +} + +static certDBEntryCert * +AddCertToPermDB(NSSLOWCERTCertDBHandle *handle, NSSLOWCERTCertificate *cert, + char *nickname, NSSLOWCERTCertTrust *trust) +{ + certDBEntryCert *certEntry = NULL; + certDBEntryNickname *nicknameEntry = NULL; + certDBEntrySubject *subjectEntry = NULL; + int state = 0; + SECStatus rv; + PRBool donnentry = PR_FALSE; + + if ( nickname ) { + donnentry = PR_TRUE; + } + + subjectEntry = ReadDBSubjectEntry(handle, &cert->derSubject); + + if ( subjectEntry ) { + donnentry = PR_FALSE; + nickname = subjectEntry->nickname; + } + + certEntry = NewDBCertEntry(&cert->derCert, nickname, trust, 0); + if ( certEntry == NULL ) { + goto loser; + } + + if ( donnentry ) { + nicknameEntry = NewDBNicknameEntry(nickname, &cert->derSubject, 0); + if ( nicknameEntry == NULL ) { + goto loser; + } + } + + rv = WriteDBCertEntry(handle, certEntry); + if ( rv != SECSuccess ) { + goto loser; + } + state = 1; + + if ( nicknameEntry ) { + rv = WriteDBNicknameEntry(handle, nicknameEntry); + if ( rv != SECSuccess ) { + goto loser; + } + } + + state = 2; + + /* add to or create new subject entry */ + if ( subjectEntry ) { + /* REWRITE BASED ON SUBJECT ENTRY */ + rv = AddPermSubjectNode(subjectEntry, cert, nickname); + if ( rv != SECSuccess ) { + goto loser; + } + } else { + /* make a new subject entry - this case is only used when updating + * an old version of the database. This is OK because the oldnickname + * db format didn't allow multiple certs with the same subject. + */ + /* where does subjectKeyID and certKey come from? */ + subjectEntry = NewDBSubjectEntry(&cert->derSubject, &cert->certKey, + &cert->subjectKeyID, nickname, + NULL, 0); + if ( subjectEntry == NULL ) { + goto loser; + } + rv = WriteDBSubjectEntry(handle, subjectEntry); + if ( rv != SECSuccess ) { + goto loser; + } + } + + state = 3; + + if ( nicknameEntry ) { + DestroyDBEntry((certDBEntry *)nicknameEntry); + } + + if ( subjectEntry ) { + DestroyDBEntry((certDBEntry *)subjectEntry); + } + + return(certEntry); + +loser: + /* don't leave partial entry in the database */ + if ( state > 0 ) { + rv = DeleteDBCertEntry(handle, &cert->certKey); + } + if ( ( state > 1 ) && donnentry ) { + rv = DeleteDBNicknameEntry(handle, nickname); + } + if ( state > 2 ) { + rv = DeleteDBSubjectEntry(handle, &cert->derSubject); + } + if ( certEntry ) { + DestroyDBEntry((certDBEntry *)certEntry); + } + if ( nicknameEntry ) { + DestroyDBEntry((certDBEntry *)nicknameEntry); + } + if ( subjectEntry ) { + DestroyDBEntry((certDBEntry *)subjectEntry); + } + + return(NULL); +} + +/* + * NOTE - Version 6 DB did not go out to the real world in a release, + * so we can remove this function in a later release. + */ +static SECStatus +UpdateV6DB(NSSLOWCERTCertDBHandle *handle, DB *updatedb) +{ + int ret; + DBT key, data; + unsigned char *buf, *tmpbuf = NULL; + certDBEntryType type; + certDBEntryNickname *nnEntry = NULL; + certDBEntrySubject *subjectEntry = NULL; + certDBEntrySMime *emailEntry = NULL; + char *nickname; + char *emailAddr; + SECStatus rv; + + /* + * Sequence through the old database and copy all of the entries + * to the new database. Subject name entries will have the new + * fields inserted into them (with zero length). + */ + ret = (* updatedb->seq)(updatedb, &key, &data, R_FIRST); + if ( ret ) { + return(SECFailure); + } + + do { + buf = (unsigned char *)data.data; + + if ( data.size >= 3 ) { + if ( buf[0] == 6 ) { /* version number */ + type = (certDBEntryType)buf[1]; + if ( type == certDBEntryTypeSubject ) { + /* expando subjecto entrieo */ + tmpbuf = (unsigned char *)PORT_Alloc(data.size + 4); + if ( tmpbuf ) { + /* copy header stuff */ + PORT_Memcpy(tmpbuf, buf, SEC_DB_ENTRY_HEADER_LEN + 2); + /* insert 4 more bytes of zero'd header */ + PORT_Memset(&tmpbuf[SEC_DB_ENTRY_HEADER_LEN + 2], + 0, 4); + /* copy rest of the data */ + PORT_Memcpy(&tmpbuf[SEC_DB_ENTRY_HEADER_LEN + 6], + &buf[SEC_DB_ENTRY_HEADER_LEN + 2], + data.size - (SEC_DB_ENTRY_HEADER_LEN + 2)); + + data.data = (void *)tmpbuf; + data.size += 4; + buf = tmpbuf; + } + } else if ( type == certDBEntryTypeCert ) { + /* expando certo entrieo */ + tmpbuf = (unsigned char *)PORT_Alloc(data.size + 3); + if ( tmpbuf ) { + /* copy header stuff */ + PORT_Memcpy(tmpbuf, buf, SEC_DB_ENTRY_HEADER_LEN); + + /* copy trust flage, setting msb's to 0 */ + tmpbuf[SEC_DB_ENTRY_HEADER_LEN] = 0; + tmpbuf[SEC_DB_ENTRY_HEADER_LEN+1] = + buf[SEC_DB_ENTRY_HEADER_LEN]; + tmpbuf[SEC_DB_ENTRY_HEADER_LEN+2] = 0; + tmpbuf[SEC_DB_ENTRY_HEADER_LEN+3] = + buf[SEC_DB_ENTRY_HEADER_LEN+1]; + tmpbuf[SEC_DB_ENTRY_HEADER_LEN+4] = 0; + tmpbuf[SEC_DB_ENTRY_HEADER_LEN+5] = + buf[SEC_DB_ENTRY_HEADER_LEN+2]; + + /* copy rest of the data */ + PORT_Memcpy(&tmpbuf[SEC_DB_ENTRY_HEADER_LEN + 6], + &buf[SEC_DB_ENTRY_HEADER_LEN + 3], + data.size - (SEC_DB_ENTRY_HEADER_LEN + 3)); + + data.data = (void *)tmpbuf; + data.size += 3; + buf = tmpbuf; + } + + } + + /* update the record version number */ + buf[0] = CERT_DB_FILE_VERSION; + + /* copy to the new database */ + ret = certdb_Put(handle->permCertDB, &key, &data, 0); + if ( tmpbuf ) { + PORT_Free(tmpbuf); + tmpbuf = NULL; + } + } + } + } while ( (* updatedb->seq)(updatedb, &key, &data, R_NEXT) == 0 ); + + ret = certdb_Sync(handle->permCertDB, 0); + + ret = (* updatedb->seq)(updatedb, &key, &data, R_FIRST); + if ( ret ) { + return(SECFailure); + } + + do { + buf = (unsigned char *)data.data; + + if ( data.size >= 3 ) { + if ( buf[0] == CERT_DB_FILE_VERSION ) { /* version number */ + type = (certDBEntryType)buf[1]; + if ( type == certDBEntryTypeNickname ) { + nickname = &((char *)key.data)[1]; + + /* get the matching nickname entry in the new DB */ + nnEntry = ReadDBNicknameEntry(handle, nickname); + if ( nnEntry == NULL ) { + goto endloop; + } + + /* find the subject entry pointed to by nickname */ + subjectEntry = ReadDBSubjectEntry(handle, + &nnEntry->subjectName); + if ( subjectEntry == NULL ) { + goto endloop; + } + + subjectEntry->nickname = + (char *)PORT_ArenaAlloc(subjectEntry->common.arena, + key.size - 1); + if ( subjectEntry->nickname ) { + PORT_Memcpy(subjectEntry->nickname, nickname, + key.size - 1); + rv = WriteDBSubjectEntry(handle, subjectEntry); + } + } else if ( type == certDBEntryTypeSMimeProfile ) { + emailAddr = &((char *)key.data)[1]; + + /* get the matching smime entry in the new DB */ + emailEntry = nsslowcert_ReadDBSMimeEntry(handle, emailAddr); + if ( emailEntry == NULL ) { + goto endloop; + } + + /* find the subject entry pointed to by nickname */ + subjectEntry = ReadDBSubjectEntry(handle, + &emailEntry->subjectName); + if ( subjectEntry == NULL ) { + goto endloop; + } + + subjectEntry->nickname = + (char *)PORT_ArenaAlloc(subjectEntry->common.arena, + key.size - 1); + if ( subjectEntry->emailAddr ) { + PORT_Memcpy(subjectEntry->emailAddr, emailAddr, + key.size - 1); + rv = WriteDBSubjectEntry(handle, subjectEntry); + } + } + +endloop: + if ( subjectEntry ) { + DestroyDBEntry((certDBEntry *)subjectEntry); + subjectEntry = NULL; + } + if ( nnEntry ) { + DestroyDBEntry((certDBEntry *)nnEntry); + nnEntry = NULL; + } + if ( emailEntry ) { + DestroyDBEntry((certDBEntry *)emailEntry); + emailEntry = NULL; + } + } + } + } while ( (* updatedb->seq)(updatedb, &key, &data, R_NEXT) == 0 ); + + ret = certdb_Sync(handle->permCertDB, 0); + + (* updatedb->close)(updatedb); + return(SECSuccess); +} + + +static SECStatus +updateV5Callback(NSSLOWCERTCertificate *cert, SECItem *k, void *pdata) +{ + NSSLOWCERTCertDBHandle *handle; + certDBEntryCert *entry; + NSSLOWCERTCertTrust *trust; + + handle = (NSSLOWCERTCertDBHandle *)pdata; + trust = &cert->dbEntry->trust; + + /* SSL user certs can be used for email if they have an email addr */ + if ( cert->emailAddr && ( trust->sslFlags & CERTDB_USER ) && + ( trust->emailFlags == 0 ) ) { + trust->emailFlags = CERTDB_USER; + } + /* servers didn't set the user flags on the server cert.. */ + if (PORT_Strcmp(cert->dbEntry->nickname,"Server-Cert") == 0) { + trust->sslFlags |= CERTDB_USER; + } + + entry = AddCertToPermDB(handle, cert, cert->dbEntry->nickname, + &cert->dbEntry->trust); + if ( entry ) { + DestroyDBEntry((certDBEntry *)entry); + } + + return(SECSuccess); +} + +static SECStatus +UpdateV5DB(NSSLOWCERTCertDBHandle *handle, DB *updatedb) +{ + NSSLOWCERTCertDBHandle updatehandle; + SECStatus rv; + + updatehandle.permCertDB = updatedb; + updatehandle.dbMon = PZ_NewMonitor(nssILockCertDB); + + rv = nsslowcert_TraversePermCerts(&updatehandle, updateV5Callback, + (void *)handle); + + PZ_DestroyMonitor(updatehandle.dbMon); + + (* updatedb->close)(updatedb); + return(SECSuccess); +} + +static PRBool +isV4DB(DB *db) { + DBT key,data; + int ret; + + key.data = "Version"; + key.size = 7; + + ret = (*db->get)(db, &key, &data, 0); + if (ret) { + return PR_FALSE; + } + + if ((data.size == 1) && (*(unsigned char *)data.data <= 4)) { + return PR_TRUE; + } + + return PR_FALSE; +} + +static SECStatus +UpdateV4DB(NSSLOWCERTCertDBHandle *handle, DB *updatedb) +{ + DBT key, data; + certDBEntryCert *entry, *entry2; + SECItem derSubject; + int ret; + PRArenaPool *arena = NULL; + NSSLOWCERTCertificate *cert; + + ret = (* updatedb->seq)(updatedb, &key, &data, R_FIRST); + + if ( ret ) { + return(SECFailure); + } + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + return(SECFailure); + } + + do { + if ( data.size != 1 ) { /* skip version number */ + + /* decode the old DB entry */ + entry = (certDBEntryCert *)DecodeV4DBCertEntry((unsigned char*)data.data, data.size); + derSubject.data = NULL; + + if ( entry ) { + cert = nsslowcert_DecodeDERCertificate(&entry->derCert, PR_TRUE, + entry->nickname); + + if ( cert != NULL ) { + /* add to new database */ + entry2 = AddCertToPermDB(handle, cert, entry->nickname, + &entry->trust); + + nsslowcert_DestroyCertificate(cert); + if ( entry2 ) { + DestroyDBEntry((certDBEntry *)entry2); + } + } + DestroyDBEntry((certDBEntry *)entry); + } + } + } while ( (* updatedb->seq)(updatedb, &key, &data, R_NEXT) == 0 ); + + PORT_FreeArena(arena, PR_FALSE); + (* updatedb->close)(updatedb); + return(SECSuccess); +} + + +/* + * return true if a database key conflict exists + */ +PRBool +nsslowcert_CertDBKeyConflict(SECItem *derCert, NSSLOWCERTCertDBHandle *handle) +{ + SECStatus rv; + DBT tmpdata; + DBT namekey; + int ret; + SECItem keyitem; + PRArenaPool *arena = NULL; + SECItem derKey; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + goto loser; + } + + /* get the db key of the cert */ + rv = nsslowcert_KeyFromDERCert(arena, derCert, &derKey); + if ( rv != SECSuccess ) { + goto loser; + } + + rv = EncodeDBCertKey(&derKey, arena, &keyitem); + if ( rv != SECSuccess ) { + goto loser; + } + + namekey.data = keyitem.data; + namekey.size = keyitem.len; + + ret = certdb_Get(handle->permCertDB, &namekey, &tmpdata, 0); + if ( ret == 0 ) { + goto loser; + } + + PORT_FreeArena(arena, PR_FALSE); + + return(PR_FALSE); +loser: + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(PR_TRUE); +} + +/* + * return true if a nickname conflict exists + * NOTE: caller must have already made sure that this exact cert + * doesn't exist in the DB + */ +static PRBool +nsslowcert_CertNicknameConflict(char *nickname, SECItem *derSubject, + NSSLOWCERTCertDBHandle *handle) +{ + PRBool rv; + certDBEntryNickname *entry; + + if ( nickname == NULL ) { + return(PR_FALSE); + } + + entry = ReadDBNicknameEntry(handle, nickname); + + if ( entry == NULL ) { + /* no entry for this nickname, so no conflict */ + return(PR_FALSE); + } + + rv = PR_TRUE; + if ( SECITEM_CompareItem(derSubject, &entry->subjectName) == SECEqual ) { + /* if subject names are the same, then no conflict */ + rv = PR_FALSE; + } + + DestroyDBEntry((certDBEntry *)entry); + return(rv); +} + +/* + * Open the certificate database and index databases. Create them if + * they are not there or bad. + */ +static SECStatus +nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, + NSSLOWCERTDBNameFunc namecb, void *cbarg) +{ + SECStatus rv; + int openflags; + certDBEntryVersion *versionEntry = NULL; + DB *updatedb = NULL; + char *tmpname; + char *certdbname; + PRBool updated = PR_FALSE; + PRBool forceUpdate = PR_FALSE; + + certdbname = (* namecb)(cbarg, CERT_DB_FILE_VERSION); + if ( certdbname == NULL ) { + return(SECFailure); + } + + if ( readOnly ) { + openflags = O_RDONLY; + } else { + openflags = O_RDWR; + } + + /* + * first open the permanent file based database. + */ + handle->permCertDB = dbopen( certdbname, openflags, 0600, DB_HASH, 0 ); + + /* check for correct version number */ + if ( handle->permCertDB ) { + versionEntry = ReadDBVersionEntry(handle); + + if ( versionEntry == NULL ) { + /* no version number */ + certdb_Close(handle->permCertDB); + handle->permCertDB = 0; + } else if ( versionEntry->common.version != CERT_DB_FILE_VERSION ) { + /* wrong version number, can't update in place */ + DestroyDBEntry((certDBEntry *)versionEntry); + PORT_Free(certdbname); + return(SECFailure); + } else { + DestroyDBEntry((certDBEntry *)versionEntry); + versionEntry = NULL; + } + } + + + /* if first open fails, try to create a new DB */ + if ( handle->permCertDB == NULL ) { + + /* don't create if readonly */ + if ( readOnly ) { + goto loser; + } + + handle->permCertDB = dbopen(certdbname, + O_RDWR | O_CREAT | O_TRUNC, + 0600, DB_HASH, 0); + + /* if create fails then we lose */ + if ( handle->permCertDB == 0 ) { + goto loser; + } + + versionEntry = NewDBVersionEntry(0); + if ( versionEntry == NULL ) { + goto loser; + } + + rv = WriteDBVersionEntry(handle, versionEntry); + + DestroyDBEntry((certDBEntry *)versionEntry); + + if ( rv != SECSuccess ) { + goto loser; + } + + /* try to upgrade old db here */ + tmpname = (* namecb)(cbarg, 6); /* get v6 db name */ + if ( tmpname ) { + updatedb = dbopen( tmpname, O_RDONLY, 0600, DB_HASH, 0 ); + PORT_Free(tmpname); + if ( updatedb ) { + rv = UpdateV6DB(handle, updatedb); + if ( rv != SECSuccess ) { + goto loser; + } + updated = PR_TRUE; + } else { /* no v6 db, so try v5 db */ + tmpname = (* namecb)(cbarg, 5); /* get v5 db name */ + if ( tmpname ) { + updatedb = dbopen( tmpname, O_RDONLY, 0600, DB_HASH, 0 ); + PORT_Free(tmpname); + if ( updatedb ) { + rv = UpdateV5DB(handle, updatedb); + if ( rv != SECSuccess ) { + goto loser; + } + updated = PR_TRUE; + } else { /* no v5 db, so try v4 db */ + /* try to upgrade v4 db */ + tmpname = (* namecb)(cbarg, 4); /* get v4 db name */ + if ( tmpname ) { + updatedb = dbopen( tmpname, O_RDONLY, 0600, + DB_HASH, 0 ); + PORT_Free(tmpname); + if ( updatedb ) { + /* NES has v5 db's with v4 db names! */ + if (isV4DB(updatedb)) { + rv = UpdateV4DB(handle, updatedb); + } else { + rv = UpdateV5DB(handle, updatedb); + } + if ( rv != SECSuccess ) { + goto loser; + } + forceUpdate = PR_TRUE; + updated = PR_TRUE; + } + } + } + } + } + } + + /* Root certs are no longer automatically added to the DB. They + * come from and external PKCS #11 file. + */ + } + + PORT_Free(certdbname); + + return (SECSuccess); + +loser: + + PORT_SetError(SEC_ERROR_BAD_DATABASE); + + if ( handle->permCertDB ) { + certdb_Close(handle->permCertDB); + handle->permCertDB = 0; + } + + PORT_Free(certdbname); + + return(SECFailure); +} + +/* + * delete all DB records associated with a particular certificate + */ +static SECStatus +DeletePermCert(NSSLOWCERTCertificate *cert) +{ + SECStatus rv; + SECStatus ret; + + ret = SECSuccess; + + rv = DeleteDBCertEntry(cert->dbhandle, &cert->certKey); + if ( rv != SECSuccess ) { + ret = SECFailure; + } + + if ( cert->nickname ) { + rv = DeleteDBNicknameEntry(cert->dbhandle, cert->nickname); + if ( rv != SECSuccess ) { + ret = SECFailure; + } + } + + rv = RemovePermSubjectNode(cert); + + return(ret); +} + +/* + * Delete a certificate from the permanent database. + */ +SECStatus +nsslowcert_DeletePermCertificate(NSSLOWCERTCertificate *cert) +{ + SECStatus rv; + + nsslowcert_LockDB(cert->dbhandle); + /* delete the records from the permanent database */ + rv = DeletePermCert(cert); + + /* get rid of dbcert and stuff pointing to it */ + DestroyDBEntry((certDBEntry *)cert->dbEntry); + cert->dbEntry = NULL; + cert->trust = NULL; + + nsslowcert_UnlockDB(cert->dbhandle); + return(rv); +} + +/* + * Traverse all of the entries in the database of a particular type + * call the given function for each one. + */ +SECStatus +nsslowcert_TraverseDBEntries(NSSLOWCERTCertDBHandle *handle, + certDBEntryType type, + SECStatus (* callback)(SECItem *data, SECItem *key, + certDBEntryType type, void *pdata), + void *udata ) +{ + DBT data; + DBT key; + SECStatus rv; + int ret; + SECItem dataitem; + SECItem keyitem; + unsigned char *buf; + unsigned char *keybuf; + + ret = certdb_Seq(handle->permCertDB, &key, &data, R_FIRST); + + if ( ret ) { + return(SECFailure); + } + + do { + buf = (unsigned char *)data.data; + + if ( buf[1] == (unsigned char)type ) { + dataitem.len = data.size; + dataitem.data = buf; + dataitem.type = siBuffer; + keyitem.len = key.size - SEC_DB_KEY_HEADER_LEN; + keybuf = (unsigned char *)key.data; + keyitem.data = &keybuf[SEC_DB_KEY_HEADER_LEN]; + keyitem.type = siBuffer; + + rv = (* callback)(&dataitem, &keyitem, type, udata); + if ( rv != SECSuccess ) { + return(rv); + } + } + } while ( certdb_Seq(handle->permCertDB, &key, &data, R_NEXT) == 0 ); + + return(SECSuccess); +} +/* + * Decode a certificate and enter it into the temporary certificate database. + * Deal with nicknames correctly + * + * This is the private entry point. + */ +static NSSLOWCERTCertificate * +DecodeACert(NSSLOWCERTCertDBHandle *handle, certDBEntryCert *entry) +{ + NSSLOWCERTCertificate *cert = NULL; + + cert = nsslowcert_DecodeDERCertificate(&entry->derCert, PR_TRUE, + entry->nickname ); + + if ( cert == NULL ) { + goto loser; + } + + cert->dbhandle = handle; + cert->dbEntry = entry; + cert->trust = &entry->trust; + + return(cert); + +loser: + return(0); +} + +typedef struct { + PermCertCallback certfunc; + NSSLOWCERTCertDBHandle *handle; + void *data; +} PermCertCallbackState; + +/* + * traversal callback to decode certs and call callers callback + */ +static SECStatus +certcallback(SECItem *dbdata, SECItem *dbkey, certDBEntryType type, void *data) +{ + PermCertCallbackState *mystate; + SECStatus rv; + certDBEntryCert *entry; + SECItem entryitem; + NSSLOWCERTCertificate *cert; + PRArenaPool *arena = NULL; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + goto loser; + } + + entry = (certDBEntryCert *)PORT_ArenaAlloc(arena, sizeof(certDBEntryCert)); + mystate = (PermCertCallbackState *)data; + entry->common.version = (unsigned int)dbdata->data[0]; + entry->common.type = (certDBEntryType)dbdata->data[1]; + entry->common.flags = (unsigned int)dbdata->data[2]; + entry->common.arena = arena; + + entryitem.len = dbdata->len - SEC_DB_ENTRY_HEADER_LEN; + entryitem.data = &dbdata->data[SEC_DB_ENTRY_HEADER_LEN]; + + rv = DecodeDBCertEntry(entry, &entryitem); + if (rv != SECSuccess ) { + goto loser; + } + entry->derCert.type = siBuffer; + + /* note: Entry is 'inheritted'. */ + cert = DecodeACert(mystate->handle, entry); + + rv = (* mystate->certfunc)(cert, dbkey, mystate->data); + + /* arena stored in entry destroyed by nsslowcert_DestroyCertificate */ + nsslowcert_DestroyCertificateNoLocking(cert); + + return(rv); + +loser: + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + return(SECFailure); +} + +/* + * Traverse all of the certificates in the permanent database and + * call the given function for each one; expect the caller to have lock. + */ +static SECStatus +TraversePermCertsNoLocking(NSSLOWCERTCertDBHandle *handle, + SECStatus (* certfunc)(NSSLOWCERTCertificate *cert, + SECItem *k, + void *pdata), + void *udata ) +{ + SECStatus rv; + PermCertCallbackState mystate; + + mystate.certfunc = certfunc; + mystate.handle = handle; + mystate.data = udata; + rv = nsslowcert_TraverseDBEntries(handle, certDBEntryTypeCert, certcallback, + (void *)&mystate); + + return(rv); +} + +/* + * Traverse all of the certificates in the permanent database and + * call the given function for each one. + */ +SECStatus +nsslowcert_TraversePermCerts(NSSLOWCERTCertDBHandle *handle, + SECStatus (* certfunc)(NSSLOWCERTCertificate *cert, SECItem *k, + void *pdata), + void *udata ) +{ + SECStatus rv; + + nsslowcert_LockDB(handle); + rv = TraversePermCertsNoLocking(handle, certfunc, udata); + nsslowcert_UnlockDB(handle); + + return(rv); +} + + + +/* + * Close the database + */ +void +__nsslowcert_ClosePermCertDB(NSSLOWCERTCertDBHandle *handle) +{ + if ( handle ) { + if ( handle->permCertDB ) { + certdb_Close( handle->permCertDB ); + handle->permCertDB = 0; + } + } + return; +} + +void +nsslowcert_ClosePermCertDB(NSSLOWCERTCertDBHandle *handle) +{ + __nsslowcert_ClosePermCertDB(handle); +} + +/* + * Get the trust attributes from a certificate + */ +SECStatus +nsslowcert_GetCertTrust(NSSLOWCERTCertificate *cert, NSSLOWCERTCertTrust *trust) +{ + SECStatus rv; + + nsslowcert_LockCertTrust(cert); + + if ( cert->trust == NULL ) { + rv = SECFailure; + } else { + *trust = *cert->trust; + rv = SECSuccess; + } + + nsslowcert_UnlockCertTrust(cert); + return(rv); +} + +/* + * Change the trust attributes of a certificate and make them permanent + * in the database. + */ +SECStatus +nsslowcert_ChangeCertTrust(NSSLOWCERTCertDBHandle *handle, NSSLOWCERTCertificate *cert, + NSSLOWCERTCertTrust *trust) +{ + certDBEntryCert *entry; + int rv; + SECStatus ret; + + nsslowcert_LockDB(handle); + nsslowcert_LockCertTrust(cert); + /* only set the trust on permanent certs */ + if ( cert->trust == NULL ) { + ret = SECFailure; + goto done; + } + + *cert->trust = *trust; + if ( cert->dbEntry == NULL ) { + ret = SECSuccess; /* not in permanent database */ + goto done; + } + + entry = cert->dbEntry; + entry->trust = *trust; + + rv = WriteDBCertEntry(handle, entry); + if ( rv ) { + ret = SECFailure; + goto done; + } + + ret = SECSuccess; + +done: + nsslowcert_UnlockCertTrust(cert); + nsslowcert_UnlockDB(handle); + return(ret); +} + + +SECStatus +nsslowcert_AddPermCert(NSSLOWCERTCertDBHandle *dbhandle, + NSSLOWCERTCertificate *cert, char *nickname, NSSLOWCERTCertTrust *trust) +{ + char *oldnn; + certDBEntryCert *entry; + PRBool conflict; + SECStatus ret; + + nsslowcert_LockDB(dbhandle); + + PORT_Assert(!cert->dbEntry); + + /* don't add a conflicting nickname */ + conflict = nsslowcert_CertNicknameConflict(nickname, &cert->derSubject, + dbhandle); + if ( conflict ) { + ret = SECFailure; + goto done; + } + + /* save old nickname so that we can delete it */ + oldnn = cert->nickname; + + entry = AddCertToPermDB(dbhandle, cert, nickname, trust); + + if ( entry == NULL ) { + ret = SECFailure; + goto done; + } + + cert->nickname = (entry->nickname) ? PORT_ArenaStrdup(cert->arena,entry->nickname) : NULL; + cert->trust = &entry->trust; + cert->dbEntry = entry; + + ret = SECSuccess; +done: + nsslowcert_UnlockDB(dbhandle); + return(ret); +} + +/* + * Open the certificate database and index databases. Create them if + * they are not there or bad. + */ +SECStatus +nsslowcert_OpenCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, + NSSLOWCERTDBNameFunc namecb, void *cbarg, PRBool openVolatile) +{ + int rv; + + certdb_InitDBLock(handle); + + handle->dbMon = PZ_NewMonitor(nssILockCertDB); + PORT_Assert(handle->dbMon != NULL); + + rv = nsslowcert_OpenPermCertDB(handle, readOnly, namecb, cbarg); + if ( rv ) { + goto loser; + } + + return (SECSuccess); + +loser: + + PORT_SetError(SEC_ERROR_BAD_DATABASE); + return(SECFailure); +} + + +/* + * Lookup a certificate in the databases. + */ +static NSSLOWCERTCertificate * +FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey, PRBool lockdb) +{ + SECItem keyitem; + DBT key; + SECStatus rv; + NSSLOWCERTCertificate *cert = NULL; + PRArenaPool *arena = NULL; + certDBEntryCert *entry; + PRBool locked = PR_FALSE; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + goto loser; + } + + rv = EncodeDBCertKey(certKey, arena, &keyitem); + if ( rv != SECSuccess ) { + goto loser; + } + + key.data = keyitem.data; + key.size = keyitem.len; + + if ( lockdb ) { + locked = PR_TRUE; + nsslowcert_LockDB(handle); + } + + /* find in perm database */ + entry = ReadDBCertEntry(handle, certKey); + + if ( entry == NULL ) { + goto loser; + } + + /* inherit entry */ + cert = DecodeACert(handle, entry); + +loser: + if ( locked ) { + nsslowcert_UnlockDB(handle); + } + + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(cert); +} + +/* + * Lookup a certificate in the databases without locking + */ +NSSLOWCERTCertificate * +nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey) +{ + return(FindCertByKey(handle, certKey, PR_FALSE)); +} + +/* + * Generate a key from an issuerAndSerialNumber, and find the + * associated cert in the database. + */ +NSSLOWCERTCertificate * +nsslowcert_FindCertByIssuerAndSN(NSSLOWCERTCertDBHandle *handle, NSSLOWCERTIssuerAndSN *issuerAndSN) +{ + SECItem certKey; + NSSLOWCERTCertificate *cert; + + certKey.len = issuerAndSN->serialNumber.len + issuerAndSN->derIssuer.len; + certKey.data = (unsigned char*)PORT_Alloc(certKey.len); + + if ( certKey.data == NULL ) { + return(0); + } + + /* copy the serialNumber */ + PORT_Memcpy(certKey.data, issuerAndSN->serialNumber.data, + issuerAndSN->serialNumber.len); + + /* copy the issuer */ + PORT_Memcpy( &certKey.data[issuerAndSN->serialNumber.len], + issuerAndSN->derIssuer.data, issuerAndSN->derIssuer.len); + + cert = nsslowcert_FindCertByKey(handle, &certKey); + + PORT_Free(certKey.data); + + return(cert); +} + +/* + * look for the given DER certificate in the database + */ +NSSLOWCERTCertificate * +nsslowcert_FindCertByDERCert(NSSLOWCERTCertDBHandle *handle, SECItem *derCert) +{ + PRArenaPool *arena; + SECItem certKey; + SECStatus rv; + NSSLOWCERTCertificate *cert = NULL; + + /* create a scratch arena */ + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + return(NULL); + } + + /* extract the database key from the cert */ + rv = nsslowcert_KeyFromDERCert(arena, derCert, &certKey); + if ( rv != SECSuccess ) { + goto loser; + } + + /* find the certificate */ + cert = nsslowcert_FindCertByKey(handle, &certKey); + +loser: + PORT_FreeArena(arena, PR_FALSE); + return(cert); +} + +static void +DestroyCertificate(NSSLOWCERTCertificate *cert, PRBool lockdb) +{ + int refCount; + NSSLOWCERTCertDBHandle *handle; + + if ( cert ) { + + handle = cert->dbhandle; + + /* + * handle may be NULL, for example if the cert was created with + * nsslowcert_DecodeDERCertificate. + */ + if ( lockdb && handle ) { + nsslowcert_LockDB(handle); + } + + nsslowcert_LockCertRefCount(cert); + PORT_Assert(cert->referenceCount > 0); + refCount = --cert->referenceCount; + nsslowcert_UnlockCertRefCount(cert); + + if ( ( refCount == 0 ) ) { + certDBEntryCert *entry = cert->dbEntry; + PRArenaPool * arena = cert->arena; + + if ( entry ) { + DestroyDBEntry((certDBEntry *)entry); + } + + /* zero cert before freeing. Any stale references to this cert + * after this point will probably cause an exception. */ + PORT_Memset(cert, 0, sizeof *cert); + + cert = NULL; + + /* free the arena that contains the cert. */ + PORT_FreeArena(arena, PR_FALSE); + } + if ( lockdb && handle ) { + nsslowcert_UnlockDB(handle); + } + } + + return; +} + +void +nsslowcert_DestroyCertificate(NSSLOWCERTCertificate *cert) +{ + DestroyCertificate(cert, PR_TRUE); + return; +} + +static void +nsslowcert_DestroyCertificateNoLocking(NSSLOWCERTCertificate *cert) +{ + DestroyCertificate(cert, PR_FALSE); + return; +} + +/* + * Lookup a CRL in the databases. We mirror the same fast caching data base + * caching stuff used by certificates....? + */ +SECItem * +nsslowcert_FindCrlByKey(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey, + char **url, PRBool isKRL) +{ + SECItem keyitem; + DBT key; + SECStatus rv; + SECItem *crl = NULL; + PRArenaPool *arena = NULL; + certDBEntryRevocation *entry; + certDBEntryType crlType = isKRL ? certDBEntryTypeKeyRevocation + : certDBEntryTypeRevocation; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + goto loser; + } + + rv = EncodeDBGenericKey(crlKey, arena, &keyitem, crlType); + if ( rv != SECSuccess ) { + goto loser; + } + + key.data = keyitem.data; + key.size = keyitem.len; + + /* find in perm database */ + entry = ReadDBCrlEntry(handle, crlKey, crlType); + + if ( entry == NULL ) { + goto loser; + } + + if (entry->url) { + *url = PORT_Strdup(entry->url); + } + crl = SECITEM_DupItem(&entry->derCrl); + +loser: + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + if (entry) { + DestroyDBEntry((certDBEntry *)entry); + } + + return(crl); +} + +/* + * replace the existing URL in the data base with a new one + */ +SECStatus +nsslowcert_AddCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl, + SECItem *crlKey, char *url, PRBool isKRL) +{ + SECStatus rv = SECFailure; + certDBEntryRevocation *entry = NULL; + certDBEntryType crlType = isKRL ? certDBEntryTypeKeyRevocation + : certDBEntryTypeRevocation; + DeleteDBCrlEntry(handle, crlKey, crlType); + + /* Write the new entry into the data base */ + entry = NewDBCrlEntry(derCrl, url, crlType, 0); + if (entry == NULL) goto done; + + rv = WriteDBCrlEntry(handle, entry, crlKey); + if (rv != SECSuccess) goto done; + +done: + if (entry) { + DestroyDBEntry((certDBEntry *)entry); + } + return rv; +} + +SECStatus +nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle, SECItem *derName, + PRBool isKRL) +{ + SECStatus rv; + certDBEntryType crlType = isKRL ? certDBEntryTypeKeyRevocation + : certDBEntryTypeRevocation; + + rv = DeleteDBCrlEntry(handle, derName, crlType); + if (rv != SECSuccess) goto done; + +done: + return rv; +} + + +PRBool +nsslowcert_hasTrust(NSSLOWCERTCertificate *cert) +{ + NSSLOWCERTCertTrust *trust; + + if (cert->trust == NULL) { + return PR_FALSE; + } + trust = cert->trust; + return !((trust->sslFlags & CERTDB_TRUSTED_UNKNOWN) && + (trust->emailFlags & CERTDB_TRUSTED_UNKNOWN) && + (trust->objectSigningFlags & CERTDB_TRUSTED_UNKNOWN)); +} + +/* + * This function has the logic that decides if another person's cert and + * email profile from an S/MIME message should be saved. It can deal with + * the case when there is no profile. + */ +SECStatus +nsslowcert_SaveSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, char *emailAddr, + SECItem *derSubject, SECItem *emailProfile, SECItem *profileTime) +{ + certDBEntrySMime *entry = NULL; + SECStatus rv = SECFailure;; + + /* find our existing entry */ + entry = nsslowcert_ReadDBSMimeEntry(dbhandle, emailAddr); + + if ( entry ) { + /* keep our old db entry consistant for old applications. */ + if (!SECITEM_ItemsAreEqual(derSubject, &entry->subjectName)) { + UpdateSubjectWithEmailAddr(dbhandle, &entry->subjectName, NULL); + } + DestroyDBEntry((certDBEntry *)entry); + entry = NULL; + } + + /* now save the entry */ + entry = NewDBSMimeEntry(emailAddr, derSubject, emailProfile, + profileTime, 0); + if ( entry == NULL ) { + rv = SECFailure; + goto loser; + } + + nsslowcert_LockDB(dbhandle); + + rv = DeleteDBSMimeEntry(dbhandle, emailAddr); + /* if delete fails, try to write new entry anyway... */ + + /* link subject entry back here */ + rv = UpdateSubjectWithEmailAddr(dbhandle, derSubject, emailAddr); + if ( rv != SECSuccess ) { + nsslowcert_UnlockDB(dbhandle); + goto loser; + } + + rv = WriteDBSMimeEntry(dbhandle, entry); + if ( rv != SECSuccess ) { + nsslowcert_UnlockDB(dbhandle); + goto loser; + } + + nsslowcert_UnlockDB(dbhandle); + + rv = SECSuccess; + +loser: + if ( entry ) { + DestroyDBEntry((certDBEntry *)entry); + } + return(rv); +} diff --git a/security/nss/lib/softoken/pcertt.h b/security/nss/lib/softoken/pcertt.h new file mode 100644 index 000000000..808f95fe1 --- /dev/null +++ b/security/nss/lib/softoken/pcertt.h @@ -0,0 +1,433 @@ +/* + * 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. + */ +/* + * certt.h - public data structures for the certificate library + * + * $Id$ + */ +#ifndef _PCERTT_H_ +#define _PCERTT_H_ + +#include "prclist.h" +#include "pkcs11t.h" +#include "seccomon.h" +#include "secoidt.h" +#include "plarena.h" +#include "prcvar.h" +#include "nssilock.h" +#include "prio.h" +#include "prmon.h" + + +/* Non-opaque objects */ +typedef struct NSSLOWCERTCertDBHandleStr NSSLOWCERTCertDBHandle; +typedef struct NSSLOWCERTCertKeyStr NSSLOWCERTCertKey; + +typedef struct NSSLOWCERTCertTrustStr NSSLOWCERTCertTrust; +typedef struct NSSLOWCERTCertificateStr NSSLOWCERTCertificate; +typedef struct NSSLOWCERTCertificateListStr NSSLOWCERTCertificateList; +typedef struct NSSLOWCERTIssuerAndSNStr NSSLOWCERTIssuerAndSN; +typedef struct NSSLOWCERTSignedDataStr NSSLOWCERTSignedData; +typedef struct NSSLOWCERTSubjectPublicKeyInfoStr NSSLOWCERTSubjectPublicKeyInfo; +typedef struct NSSLOWCERTValidityStr NSSLOWCERTValidity; + +/* +** An X.509 validity object +*/ +struct NSSLOWCERTValidityStr { + PRArenaPool *arena; + SECItem notBefore; + SECItem notAfter; +}; + +/* + * A serial number and issuer name, which is used as a database key + */ +struct NSSLOWCERTCertKeyStr { + SECItem serialNumber; + SECItem derIssuer; +}; + +/* +** A signed data object. Used to implement the "signed" macro used +** in the X.500 specs. +*/ +struct NSSLOWCERTSignedDataStr { + SECItem data; + SECAlgorithmID signatureAlgorithm; + SECItem signature; +}; + +/* +** An X.509 subject-public-key-info object +*/ +struct NSSLOWCERTSubjectPublicKeyInfoStr { + PRArenaPool *arena; + SECAlgorithmID algorithm; + SECItem subjectPublicKey; +}; + +typedef struct _certDBEntryCert certDBEntryCert; +typedef struct _certDBEntryRevocation certDBEntryRevocation; + +struct NSSLOWCERTCertTrustStr { + unsigned int sslFlags; + unsigned int emailFlags; + unsigned int objectSigningFlags; +}; + +/* +** An X.509 certificate object (the unsigned form) +*/ +struct NSSLOWCERTCertificateStr { + /* the arena is used to allocate any data structures that have the same + * lifetime as the cert. This is all stuff that hangs off of the cert + * structure, and is all freed at the same time. I is used when the + * cert is decoded, destroyed, and at some times when it changes + * state + */ + PRArenaPool *arena; + NSSLOWCERTCertDBHandle *dbhandle; + + SECItem derCert; /* original DER for the cert */ + SECItem derIssuer; /* DER for issuer name */ + SECItem serialNumber; + SECItem derSubject; /* DER for subject name */ + NSSLOWCERTSubjectPublicKeyInfo subjectPublicKeyInfo; + SECItem certKey; /* database key for this cert */ + NSSLOWCERTValidity validity; + certDBEntryCert *dbEntry; /* database entry struct */ + SECItem subjectKeyID; /* x509v3 subject key identifier */ + char *nickname; + char *emailAddr; + NSSLOWCERTCertTrust *trust; + + /* the reference count is modified whenever someone looks up, dups + * or destroys a certificate + */ + int referenceCount; +}; +#define SEC_CERTIFICATE_VERSION_1 0 /* default created */ +#define SEC_CERTIFICATE_VERSION_2 1 /* v2 */ +#define SEC_CERTIFICATE_VERSION_3 2 /* v3 extensions */ + +#define SEC_CRL_VERSION_1 0 /* default */ +#define SEC_CRL_VERSION_2 1 /* v2 extensions */ + +struct NSSLOWCERTIssuerAndSNStr { + SECItem derIssuer; + SECItem serialNumber; +}; + +typedef SECStatus (* NSSLOWCERTCertCallback)(NSSLOWCERTCertificate *cert, void *arg); + +/* This is the typedef for the callback passed to nsslowcert_OpenCertDB() */ +/* callback to return database name based on version number */ +typedef char * (*NSSLOWCERTDBNameFunc)(void *arg, int dbVersion); + +/* XXX Lisa thinks the template declarations belong in cert.h, not here? */ + +#include "secasn1t.h" /* way down here because I expect template stuff to + * move out of here anyway */ + +SEC_BEGIN_PROTOS + +extern const SEC_ASN1Template nsslowcert_CertificateTemplate[]; +extern const SEC_ASN1Template SEC_SignedCertificateTemplate[]; +extern const SEC_ASN1Template nsslowcert_SignedDataTemplate[]; +extern const SEC_ASN1Template NSSLOWKEY_PublicKeyTemplate[]; +extern const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[]; +extern const SEC_ASN1Template nsslowcert_ValidityTemplate[]; + +SEC_END_PROTOS + +/* + * Certificate Database related definitions and data structures + */ + +/* version number of certificate database */ +#define CERT_DB_FILE_VERSION 7 +#ifdef USE_NS_ROOTS +#define CERT_DB_CONTENT_VERSION 28 +#else +#define CERT_DB_CONTENT_VERSION 2 +#endif + +#define SEC_DB_ENTRY_HEADER_LEN 3 +#define SEC_DB_KEY_HEADER_LEN 1 + +/* All database entries have this form: + * + * byte offset field + * ----------- ----- + * 0 version + * 1 type + * 2 flags + */ + +/* database entry types */ +typedef enum { + certDBEntryTypeVersion = 0, + certDBEntryTypeCert = 1, + certDBEntryTypeNickname = 2, + certDBEntryTypeSubject = 3, + certDBEntryTypeRevocation = 4, + certDBEntryTypeKeyRevocation = 5, + certDBEntryTypeSMimeProfile = 6, + certDBEntryTypeContentVersion = 7 +} certDBEntryType; + +typedef struct { + certDBEntryType type; + unsigned int version; + unsigned int flags; + PRArenaPool *arena; +} certDBEntryCommon; + +/* + * Certificate entry: + * + * byte offset field + * ----------- ----- + * 0 sslFlags-msb + * 1 sslFlags-lsb + * 2 emailFlags-msb + * 3 emailFlags-lsb + * 4 objectSigningFlags-msb + * 5 objectSigningFlags-lsb + * 6 derCert-len-msb + * 7 derCert-len-lsb + * 8 nickname-len-msb + * 9 nickname-len-lsb + * ... derCert + * ... nickname + * + * NOTE: the nickname string as stored in the database is null terminated, + * in other words, the last byte of the db entry is always 0 + * if a nickname is present. + * NOTE: if nickname is not present, then nickname-len-msb and + * nickname-len-lsb will both be zero. + */ +struct _certDBEntryCert { + certDBEntryCommon common; + NSSLOWCERTCertTrust trust; + SECItem derCert; + char *nickname; +}; + +/* + * Certificate Nickname entry: + * + * byte offset field + * ----------- ----- + * 0 subjectname-len-msb + * 1 subjectname-len-lsb + * 2... subjectname + * + * The database key for this type of entry is a nickname string + * The "subjectname" value is the DER encoded DN of the identity + * that matches this nickname. + */ +typedef struct { + certDBEntryCommon common; + char *nickname; + SECItem subjectName; +} certDBEntryNickname; + +#define DB_NICKNAME_ENTRY_HEADER_LEN 2 + +/* + * Certificate Subject entry: + * + * byte offset field + * ----------- ----- + * 0 ncerts-msb + * 1 ncerts-lsb + * 2 nickname-msb + * 3 nickname-lsb + * 4 emailAddr-msb + * 5 emailAddr-lsb + * ... nickname + * ... emailAddr + * ...+2*i certkey-len-msb + * ...+1+2*i certkey-len-lsb + * ...+2*ncerts+2*i keyid-len-msb + * ...+1+2*ncerts+2*i keyid-len-lsb + * ... certkeys + * ... keyids + * + * The database key for this type of entry is the DER encoded subject name + * The "certkey" value is an array of certificate database lookup keys that + * points to the database entries for the certificates that matche + * this subject. + * + */ +typedef struct _certDBEntrySubject { + certDBEntryCommon common; + SECItem derSubject; + unsigned int ncerts; + char *nickname; + char *emailAddr; + SECItem *certKeys; + SECItem *keyIDs; +} certDBEntrySubject; + +#define DB_SUBJECT_ENTRY_HEADER_LEN 6 + +/* + * Certificate SMIME profile entry: + * + * byte offset field + * ----------- ----- + * 0 subjectname-len-msb + * 1 subjectname-len-lsb + * 2 smimeoptions-len-msb + * 3 smimeoptions-len-lsb + * 4 options-date-len-msb + * 5 options-date-len-lsb + * 6... subjectname + * ... smimeoptions + * ... options-date + * + * The database key for this type of entry is the email address string + * The "subjectname" value is the DER encoded DN of the identity + * that matches this nickname. + * The "smimeoptions" value is a string that represents the algorithm + * capabilities on the remote user. + * The "options-date" is the date that the smime options value was created. + * This is generally the signing time of the signed message that contained + * the options. It is a UTCTime value. + */ +typedef struct { + certDBEntryCommon common; + char *emailAddr; + SECItem subjectName; + SECItem smimeOptions; + SECItem optionsDate; +} certDBEntrySMime; + +#define DB_SMIME_ENTRY_HEADER_LEN 6 + +/* + * Crl/krl entry: + * + * byte offset field + * ----------- ----- + * 0 derCert-len-msb + * 1 derCert-len-lsb + * 2 url-len-msb + * 3 url-len-lsb + * ... derCert + * ... url + * + * NOTE: the url string as stored in the database is null terminated, + * in other words, the last byte of the db entry is always 0 + * if a nickname is present. + * NOTE: if url is not present, then url-len-msb and + * url-len-lsb will both be zero. + */ +#define DB_CRL_ENTRY_HEADER_LEN 4 +struct _certDBEntryRevocation { + certDBEntryCommon common; + SECItem derCrl; + char *url; /* where to load the crl from */ +}; + +/* + * Database Version Entry: + * + * byte offset field + * ----------- ----- + * only the low level header... + * + * The database key for this type of entry is the string "Version" + */ +typedef struct { + certDBEntryCommon common; +} certDBEntryVersion; + +#define SEC_DB_VERSION_KEY "Version" +#define SEC_DB_VERSION_KEY_LEN sizeof(SEC_DB_VERSION_KEY) + +/* + * Database Content Version Entry: + * + * byte offset field + * ----------- ----- + * 0 contentVersion + * + * The database key for this type of entry is the string "ContentVersion" + */ +typedef struct { + certDBEntryCommon common; + char contentVersion; +} certDBEntryContentVersion; + +#define SEC_DB_CONTENT_VERSION_KEY "ContentVersion" +#define SEC_DB_CONTENT_VERSION_KEY_LEN sizeof(SEC_DB_CONTENT_VERSION_KEY) + +typedef union { + certDBEntryCommon common; + certDBEntryVersion version; + certDBEntryCert cert; + certDBEntryNickname nickname; + certDBEntrySubject subject; + certDBEntryRevocation revocation; +} certDBEntry; + +/* length of the fixed part of a database entry */ +#define DBCERT_V4_HEADER_LEN 7 +#define DB_CERT_V5_ENTRY_HEADER_LEN 7 +#define DB_CERT_V6_ENTRY_HEADER_LEN 7 +#define DB_CERT_ENTRY_HEADER_LEN 10 + +/* common flags for all types of certificates */ +#define CERTDB_VALID_PEER (1<<0) +#define CERTDB_TRUSTED (1<<1) +#define CERTDB_SEND_WARN (1<<2) +#define CERTDB_VALID_CA (1<<3) +#define CERTDB_TRUSTED_CA (1<<4) /* trusted for issuing server certs */ +#define CERTDB_NS_TRUSTED_CA (1<<5) +#define CERTDB_USER (1<<6) +#define CERTDB_TRUSTED_CLIENT_CA (1<<7) /* trusted for issuing client certs */ +#define CERTDB_INVISIBLE_CA (1<<8) /* don't show in UI */ +#define CERTDB_GOVT_APPROVED_CA (1<<9) /* can do strong crypto in export ver */ +#define CERTDB_NOT_TRUSTED (1<<10) /* explicitly don't trust this cert */ +#define CERTDB_TRUSTED_UNKNOWN (1<<11) /* accept trust from another source */ + +/* bits not affected by the CKO_NETSCAPE_TRUST object */ +#define CERTDB_PRESERVE_TRUST_BITS (CERTDB_USER | CERTDB_VALID_PEER | \ + CERTDB_NS_TRUSTED_CA | CERTDB_VALID_CA | CERTDB_INVISIBLE_CA | \ + CERTDB_GOVT_APPROVED_CA) + +#endif /* _PCERTT_H_ */ diff --git a/security/nss/lib/softoken/pk11db.c b/security/nss/lib/softoken/pk11db.c index ee0e94d0e..162d53714 100644 --- a/security/nss/lib/softoken/pk11db.c +++ b/security/nss/lib/softoken/pk11db.c @@ -38,68 +38,210 @@ #include "pk11pars.h" #include "pkcs11i.h" +#include "mcom_db.h" #define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; } static void -secmod_parseFlags(char *tmp, pk11_parameters *parsed) { +secmod_parseTokenFlags(char *tmp, pk11_token_parameters *parsed) { parsed->readOnly = pk11_argHasFlag("flags","readOnly",tmp); parsed->noCertDB = pk11_argHasFlag("flags","noCertDB",tmp); + parsed->noKeyDB = pk11_argHasFlag("flags","noKeyDB",tmp); + parsed->forceOpen = pk11_argHasFlag("flags","forceOpen",tmp); + parsed->pwRequired = pk11_argHasFlag("flags","passwordRequired",tmp); + return; +} + +static void +secmod_parseFlags(char *tmp, pk11_parameters *parsed) { parsed->noModDB = pk11_argHasFlag("flags","noModDB",tmp); + parsed->readOnly = pk11_argHasFlag("flags","readOnly",tmp); + /* keep legacy interface working */ + parsed->noCertDB = pk11_argHasFlag("flags","noCertDB",tmp); parsed->forceOpen = pk11_argHasFlag("flags","forceOpen",tmp); parsed->pwRequired = pk11_argHasFlag("flags","passwordRequired",tmp); return; } +CK_RV +secmod_parseTokenParameters(char *param, pk11_token_parameters *parsed) +{ + int next; + char *tmp; + char *index; + index = pk11_argStrip(param); + + while (*index) { + PK11_HANDLE_STRING_ARG(index,parsed->configdir,"configdir=",;) + PK11_HANDLE_STRING_ARG(index,parsed->certPrefix,"certprefix=",;) + PK11_HANDLE_STRING_ARG(index,parsed->keyPrefix,"keyprefix=",;) + PK11_HANDLE_STRING_ARG(index,parsed->tokdes,"tokenDescription=",;) + PK11_HANDLE_STRING_ARG(index,parsed->slotdes,"slotDescription=",;) + PK11_HANDLE_STRING_ARG(index,tmp,"minPWLen=", + if(tmp) { parsed->minPW=atoi(tmp); PORT_Free(tmp); }) + PK11_HANDLE_STRING_ARG(index,tmp,"flags=", + if(tmp) { secmod_parseTokenFlags(param,parsed); PORT_Free(tmp); }) + PK11_HANDLE_FINAL_ARG(index) + } + return CKR_OK; +} + +static void +secmod_parseTokens(char *tokenParams, pk11_parameters *parsed) +{ + char *tokenIndex; + pk11_token_parameters *tokens = NULL; + int i=0,count = 0,next; + + if ((tokenParams == NULL) || (*tokenParams == 0)) return; + /* first count the number of slots */ + for (tokenIndex = pk11_argStrip(tokenParams); *tokenIndex; + tokenIndex = pk11_argStrip(pk11_argSkipParameter(tokenIndex))) { + count++; + } + + /* get the data structures */ + tokens = (pk11_token_parameters *) + PORT_ZAlloc(count*sizeof(pk11_token_parameters)); + if (tokens == NULL) return; + + for (tokenIndex = pk11_argStrip(tokenParams), i = 0; + *tokenIndex && i < count ; i++ ) { + char *name; + name = pk11_argGetName(tokenIndex,&next); + tokenIndex += next; + + tokens[i].slotID = pk11_argDecodeNumber(name); + tokens[i].readOnly = PR_TRUE; + tokens[i].noCertDB = PR_TRUE; + tokens[i].noKeyDB = PR_TRUE; + if (!pk11_argIsBlank(*tokenIndex)) { + char *args = pk11_argFetchValue(tokenIndex,&next); + tokenIndex += next; + if (args) { + secmod_parseTokenParameters(args,&tokens[i]); + PORT_Free(args); + } + } + if (name) PORT_Free(name); + tokenIndex = pk11_argStrip(tokenIndex); + } + parsed->token_count = i; + parsed->tokens = tokens; + return; +} CK_RV -secmod_parseParameters(char *param, pk11_parameters *parsed) +secmod_parseParameters(char *param, pk11_parameters *parsed, PRBool isFIPS) { int next; char *tmp; char *index; + char *certPrefix = NULL, *keyPrefix = NULL; + char *tokdes = NULL, *ptokdes = NULL; + char *slotdes = NULL, *pslotdes = NULL; + char *fslotdes = NULL, *fpslotdes = NULL; + char *minPW = NULL; index = pk11_argStrip(param); PORT_Memset(parsed, 0, sizeof(pk11_parameters)); while (*index) { PK11_HANDLE_STRING_ARG(index,parsed->configdir,"configdir=",;) - PK11_HANDLE_STRING_ARG(index,parsed->certPrefix,"certprefix=",;) - PK11_HANDLE_STRING_ARG(index,parsed->keyPrefix,"keyprefix=",;) PK11_HANDLE_STRING_ARG(index,parsed->secmodName,"secmod=",;) PK11_HANDLE_STRING_ARG(index,parsed->man,"manufactureID=",;) PK11_HANDLE_STRING_ARG(index,parsed->libdes,"libraryDescription=",;) - PK11_HANDLE_STRING_ARG(index,parsed->tokdes,"cryptoTokenDescription=",;) - PK11_HANDLE_STRING_ARG(index,parsed->ptokdes,"dbTokenDescription=",;) - PK11_HANDLE_STRING_ARG(index,parsed->slotdes,"cryptoSlotDescription=",;) - PK11_HANDLE_STRING_ARG(index,parsed->pslotdes,"dbSlotDescription=",;) - PK11_HANDLE_STRING_ARG(index,parsed->fslotdes,"FIPSSlotDescription=",;) - PK11_HANDLE_STRING_ARG(index,parsed->fpslotdes,"FIPSTokenDescription=",;) - PK11_HANDLE_STRING_ARG(index,tmp,"minPWLen=", - if(tmp) { parsed->minPW=atoi(tmp); PORT_Free(tmp); }) + /* constructed values, used so legacy interfaces still work */ + PK11_HANDLE_STRING_ARG(index,certPrefix,"certprefix=",;) + PK11_HANDLE_STRING_ARG(index,keyPrefix,"keyprefix=",;) + PK11_HANDLE_STRING_ARG(index,tokdes,"cryptoTokenDescription=",;) + PK11_HANDLE_STRING_ARG(index,ptokdes,"dbTokenDescription=",;) + PK11_HANDLE_STRING_ARG(index,slotdes,"cryptoSlotDescription=",;) + PK11_HANDLE_STRING_ARG(index,pslotdes,"dbSlotDescription=",;) + PK11_HANDLE_STRING_ARG(index,fslotdes,"FIPSSlotDescription=",;) + PK11_HANDLE_STRING_ARG(index,minPW,"FIPSTokenDescription=",;) + PK11_HANDLE_STRING_ARG(index,tmp,"minPWLen=",;) + PK11_HANDLE_STRING_ARG(index,tmp,"flags=", if(tmp) { secmod_parseFlags(param,parsed); PORT_Free(tmp); }) + PK11_HANDLE_STRING_ARG(index,tmp,"tokens=", + if(tmp) { secmod_parseTokens(tmp,parsed); PORT_Free(tmp); }) PK11_HANDLE_FINAL_ARG(index) - } - return CKR_OK; + } + if (parsed->tokens == NULL) { + int count = isFIPS ? 1 : 2; + int index = count-1; + pk11_token_parameters *tokens = NULL; + + tokens = (pk11_token_parameters *) + PORT_ZAlloc(count*sizeof(pk11_token_parameters)); + if (tokens == NULL) { + goto loser; + } + parsed->tokens = tokens; + parsed->token_count = count; + tokens[index].slotID = isFIPS ? FIPS_SLOT_ID : PRIVATE_KEY_SLOT_ID; + tokens[index].certPrefix = certPrefix; + tokens[index].keyPrefix = keyPrefix; + tokens[index].minPW = minPW ? atoi(minPW) : 0; + tokens[index].readOnly = parsed->readOnly; + tokens[index].noCertDB = parsed->noCertDB; + tokens[index].forceOpen = parsed->forceOpen; + tokens[index].pwRequired = parsed->pwRequired; + certPrefix = NULL; + keyPrefix = NULL; + if (isFIPS) { + tokens[index].tokdes = fslotdes; + tokens[index].slotdes = fpslotdes; + fslotdes = NULL; + fpslotdes = NULL; + } else { + tokens[index].tokdes = ptokdes; + tokens[index].slotdes = pslotdes; + tokens[0].slotID = NETSCAPE_SLOT_ID; + tokens[0].tokdes = tokdes; + tokens[0].slotdes = slotdes; + tokens[0].noCertDB = PR_TRUE; + tokens[0].noKeyDB = PR_TRUE; + ptokdes = NULL; + pslotdes = NULL; + tokdes = NULL; + slotdes = NULL; + } + } + +loser: + FREE_CLEAR(certPrefix); + FREE_CLEAR(keyPrefix); + FREE_CLEAR(tokdes); + FREE_CLEAR(ptokdes); + FREE_CLEAR(slotdes); + FREE_CLEAR(pslotdes); + FREE_CLEAR(fslotdes); + FREE_CLEAR(fpslotdes); + FREE_CLEAR(minPW); + return CKR_OK; } void secmod_freeParams(pk11_parameters *params) { + int i; + + for (i=0; i < params->token_count; i++) { + FREE_CLEAR(params->tokens[i].configdir); + FREE_CLEAR(params->tokens[i].certPrefix); + FREE_CLEAR(params->tokens[i].keyPrefix); + FREE_CLEAR(params->tokens[i].tokdes); + FREE_CLEAR(params->tokens[i].slotdes); + } + FREE_CLEAR(params->configdir); - FREE_CLEAR(params->certPrefix); - FREE_CLEAR(params->keyPrefix); FREE_CLEAR(params->secmodName); FREE_CLEAR(params->man); FREE_CLEAR(params->libdes); - FREE_CLEAR(params->tokdes); - FREE_CLEAR(params->ptokdes); - FREE_CLEAR(params->slotdes); - FREE_CLEAR(params->pslotdes); - FREE_CLEAR(params->fslotdes); - FREE_CLEAR(params->fpslotdes); + FREE_CLEAR(params->tokens); } @@ -462,7 +604,7 @@ secmod_DecodeData(char *defParams, DBT *data, PRBool *retInternal) trustOrder = 20; } - slotStrings[i] = pk11_mkSlotString(slotID,defaultFlags, + slotStrings[i] = pk11_mkSlotString(slotID,defaultFlags, timeout,slots[i].askpw,hasRootCerts,hasRootTrust); } @@ -488,7 +630,7 @@ static DB *secmod_OpenDB(char *dbName, PRBool readOnly) { if (readOnly) return NULL; pkcs11db = dbopen( dbName, - O_RDWR | O_CREAT | O_TRUNC, 0600, DB_HASH, 0 ); + O_RDWR | O_CREAT | O_TRUNC, 0600, DB_HASH, 0 ); if (pkcs11db) (* pkcs11db->sync)(pkcs11db, 0); } return pkcs11db; diff --git a/security/nss/lib/softoken/pk11pars.h b/security/nss/lib/softoken/pk11pars.h index 7710820ab..9e273f104 100644 --- a/security/nss/lib/softoken/pk11pars.h +++ b/security/nss/lib/softoken/pk11pars.h @@ -45,8 +45,8 @@ #include "pkcs11.h" #include "seccomon.h" #include "prprf.h" -#include "secmod.h" -#include "secmodi.h" +#include "secmodt.h" +#include "pk11init.h" #define PK11_ARG_LIBRARY_PARAMETER "library=" #define PK11_ARG_NAME_PARAMETER "name=" diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index 78a26cebf..e6eaf1f1e 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -52,14 +52,13 @@ #include "pkcs11.h" #include "pkcs11i.h" #include "softoken.h" -#include "cert.h" -#include "keylow.h" +#include "lowkeyi.h" #include "blapi.h" #include "secder.h" #include "secport.h" -#include "certdb.h" +#include "pcert.h" -#include "private.h" +#include "keydbi.h" /* @@ -71,6 +70,7 @@ static char *manufacturerID = "mozilla.org "; static char manufacturerID_space[33]; static char *libraryDescription = "NSS Internal Crypto Services "; static char libraryDescription_space[33]; +#ifdef notdef static char *tokDescription = "NSS Generic Crypto Services "; static char tokDescription_space[33]; static char *privTokDescription = "NSS Certificate DB "; @@ -83,7 +83,13 @@ static char slotDescription_space[65]; static char *privSlotDescription = "NSS User Private Key and Certificate Services "; static char privSlotDescription_space[65]; -static int minimumPinLen = 0; +/* The next two strings must be exactly 64 characters long, with the + first 32 characters meaningful */ +static char *slotDescription = + "Netscape Internal FIPS-140-1 Cryptographic Services "; +static char *privSlotDescription = + "Netscape FIPS-140-1 User Private Key Services "; +#endif #define __PASTE(x,y) x##y @@ -104,7 +110,7 @@ static int minimumPinLen = 0; /* build the crypto module table */ -static CK_FUNCTION_LIST pk11_funcList = { +static const CK_FUNCTION_LIST pk11_funcList = { { 1, 10 }, #undef CK_PKCS11_FUNCTION_INFO @@ -124,7 +130,7 @@ static CK_FUNCTION_LIST pk11_funcList = { /* List of DES Weak Keys */ typedef unsigned char desKey[8]; -static desKey pk11_desWeakTable[] = { +static const desKey pk11_desWeakTable[] = { #ifdef noParity /* weak */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -178,12 +184,12 @@ static desKey pk11_desWeakTable[] = { }; -static int pk11_desWeakTableSize = sizeof(pk11_desWeakTable)/ +static const int pk11_desWeakTableSize = sizeof(pk11_desWeakTable)/ sizeof(pk11_desWeakTable[0]); /* DES KEY Parity conversion table. Takes each byte/2 as an index, returns * that byte with the proper parity bit set */ -static unsigned char parityTable[256] = { +static const unsigned char parityTable[256] = { /* Even...0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e */ /* E */ 0x01,0x02,0x04,0x07,0x08,0x0b,0x0d,0x0e, /* Odd....0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e */ @@ -239,7 +245,9 @@ struct mechanismList { #define CKF_SN_VR_RE CKF_SN_VR | CKF_SN_RE #define CKF_DUZ_IT_ALL CKF_EN_DE_WR_UN | CKF_SN_VR_RE -static struct mechanismList mechanisms[] = { +#define CK_MAX 0xffffffff + +static const struct mechanismList mechanisms[] = { /* * PKCS #11 Mechanism List. @@ -262,16 +270,16 @@ static struct mechanismList mechanisms[] = { */ /* ------------------------- RSA Operations ---------------------------*/ - {CKM_RSA_PKCS_KEY_PAIR_GEN,{128,0xffffffff,CKF_GENERATE_KEY_PAIR},PR_TRUE}, - {CKM_RSA_PKCS, {128,0xffffffff, CKF_DUZ_IT_ALL},PR_TRUE}, + {CKM_RSA_PKCS_KEY_PAIR_GEN,{128,CK_MAX,CKF_GENERATE_KEY_PAIR},PR_TRUE}, + {CKM_RSA_PKCS, {128,CK_MAX,CKF_DUZ_IT_ALL}, PR_TRUE}, #ifdef PK11_RSA9796_SUPPORTED - {CKM_RSA_9796, {128,0xffffffff, CKF_DUZ_IT_ALL},PR_TRUE}, + {CKM_RSA_9796, {128,CK_MAX,CKF_DUZ_IT_ALL}, PR_TRUE}, #endif - {CKM_RSA_X_509, {128,0xffffffff, CKF_DUZ_IT_ALL},PR_TRUE}, + {CKM_RSA_X_509, {128,CK_MAX,CKF_DUZ_IT_ALL}, PR_TRUE}, /* -------------- RSA Multipart Signing Operations -------------------- */ - {CKM_MD2_RSA_PKCS, {128,0xffffffff, CKF_SN_VR}, PR_TRUE}, - {CKM_MD5_RSA_PKCS, {128,0xffffffff, CKF_SN_VR}, PR_TRUE}, - {CKM_SHA1_RSA_PKCS, {128,0xffffffff, CKF_SN_VR}, PR_TRUE}, + {CKM_MD2_RSA_PKCS, {128,CK_MAX,CKF_SN_VR}, PR_TRUE}, + {CKM_MD5_RSA_PKCS, {128,CK_MAX,CKF_SN_VR}, PR_TRUE}, + {CKM_SHA1_RSA_PKCS, {128,CK_MAX,CKF_SN_VR}, PR_TRUE}, /* ------------------------- DSA Operations --------------------------- */ {CKM_DSA_KEY_PAIR_GEN, {512, 1024, CKF_GENERATE_KEY_PAIR}, PR_TRUE}, {CKM_DSA, {512, 1024, CKF_SN_VR}, PR_TRUE}, @@ -330,7 +338,7 @@ static struct mechanismList mechanisms[] = { {CKM_SHA_1_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_FALSE}, {CKM_TLS_PRF_GENERAL, {0, 512, CKF_SN_VR}, PR_FALSE}, /* ------------------------- CAST Operations --------------------------- */ -#ifdef PK11_CAST_SUPPORTED +#ifdef NSS_SOFTOKEN_DOES_CAST /* Cast operations are not supported ( yet? ) */ {CKM_CAST_KEY_GEN, {1, 8, CKF_GENERATE}, PR_FALSE}, {CKM_CAST_ECB, {1, 8, CKF_EN_DE_WR_UN}, PR_FALSE}, @@ -354,13 +362,13 @@ static struct mechanismList mechanisms[] = { #if NSS_SOFTOKEN_DOES_RC5 /* ------------------------- RC5 Operations --------------------------- */ {CKM_RC5_KEY_GEN, {1, 32, CKF_GENERATE}, PR_FALSE}, - {CKM_RC5_ECB, {1, 32, CKF_EN_DE_WR_UN}, PR_FALSE}, + {CKM_RC5_ECB, {1, 32, CKF_EN_DE_WR_UN}, PR_FALSE}, {CKM_RC5_CBC, {1, 32, CKF_EN_DE_WR_UN}, PR_FALSE}, {CKM_RC5_MAC, {1, 32, CKF_SN_VR}, PR_FALSE}, {CKM_RC5_MAC_GENERAL, {1, 32, CKF_SN_VR}, PR_FALSE}, {CKM_RC5_CBC_PAD, {1, 32, CKF_EN_DE_WR_UN}, PR_FALSE}, #endif -#ifdef PK11_IDEA_SUPPORTED +#ifdef NSS_SOFTOKEN_DOES_IDEA /* ------------------------- IDEA Operations -------------------------- */ {CKM_IDEA_KEY_GEN, {16, 16, CKF_GENERATE}, PR_FALSE}, {CKM_IDEA_ECB, {16, 16, CKF_EN_DE_WR_UN}, PR_FALSE}, @@ -394,26 +402,19 @@ static struct mechanismList mechanisms[] = { {CKM_PBE_MD5_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE}, /* ------------------ NETSCAPE PBE Key Derivations ------------------- */ {CKM_NETSCAPE_PBE_SHA1_DES_CBC, { 8, 8, CKF_GENERATE}, PR_TRUE}, - {CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, {CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, - {CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC, {40,40, CKF_GENERATE}, PR_TRUE}, - {CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC, {40,40, CKF_GENERATE}, PR_TRUE}, - {CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4, {40,40, CKF_GENERATE}, PR_TRUE}, - {CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4, {128,128, CKF_GENERATE}, PR_TRUE}, {CKM_PBE_SHA1_DES3_EDE_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, {CKM_PBE_SHA1_DES2_EDE_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, {CKM_PBE_SHA1_RC2_40_CBC, {40,40, CKF_GENERATE}, PR_TRUE}, {CKM_PBE_SHA1_RC2_128_CBC, {128,128, CKF_GENERATE}, PR_TRUE}, {CKM_PBE_SHA1_RC4_40, {40,40, CKF_GENERATE}, PR_TRUE}, {CKM_PBE_SHA1_RC4_128, {128,128, CKF_GENERATE}, PR_TRUE}, - {CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN, {1,32, CKF_GENERATE}, PR_TRUE}, - {CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN, {1,32, CKF_GENERATE}, PR_TRUE}, - {CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN, {1,32, CKF_GENERATE}, PR_TRUE}, + {CKM_PBA_SHA1_WITH_SHA1_HMAC, {20,20, CKF_GENERATE}, PR_TRUE}, + {CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN, {20,20, CKF_GENERATE}, PR_TRUE}, + {CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN, {16,16, CKF_GENERATE}, PR_TRUE}, + {CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN, {16,16, CKF_GENERATE}, PR_TRUE}, }; static CK_ULONG mechanismCount = sizeof(mechanisms)/sizeof(mechanisms[0]); -/* load up our token database */ -static CK_RV pk11_importKeyDB(PK11Slot *slot); - static char * pk11_setStringName(char *inString, char *buffer, int buffer_length) { @@ -431,9 +432,7 @@ pk11_setStringName(char *inString, char *buffer, int buffer_length) { * Configuration utils */ static CK_RV -pk11_configure(char *man, char *libdes, char *tokdes, char *ptokdes, - char *slotdes, char *pslotdes, char *fslotdes, char *fpslotdes, - int minPwd, int pwRequired) +pk11_configure(char *man, char *libdes) { /* make sure the internationalization was done correctly... */ @@ -445,32 +444,6 @@ pk11_configure(char *man, char *libdes, char *tokdes, char *ptokdes, libraryDescription = pk11_setStringName(libdes, libraryDescription_space, sizeof(libraryDescription_space)); } - if (tokdes) { - tokDescription = pk11_setStringName(tokdes,tokDescription_space, - sizeof(tokDescription_space)); - } - if (ptokdes) { - privTokDescription = pk11_setStringName(ptokdes, - privTokDescription_space, sizeof(privTokDescription_space)); - } - if (slotdes) { - slotDescription = pk11_setStringName(slotdes,slotDescription_space, - sizeof(slotDescription_space)); - } - if (pslotdes) { - privSlotDescription = pk11_setStringName(pslotdes, - privSlotDescription_space, sizeof(privSlotDescription_space)); - } - - if (minimumPinLen <= PK11_MAX_PIN) { - minimumPinLen = minPwd; - } - if ((minimumPinLen == 0) && (pwRequired) && - (minimumPinLen <= PK11_MAX_PIN)) { - minimumPinLen = 1; - } - - PK11_ConfigureFIPS(fslotdes,fpslotdes); return CKR_OK; } @@ -479,33 +452,20 @@ pk11_configure(char *man, char *libdes, char *tokdes, char *ptokdes, * ******************** Password Utilities ******************************* */ -/* Handle to give the password to the database. user arg should be a pointer - * to the slot. */ -static SECItem *pk11_givePass(void *sp,SECKEYKeyDBHandle *handle) -{ - PK11Slot *slot = (PK11Slot *)sp; - - if (slot->password == NULL) return NULL; - - return SECITEM_DupItem(slot->password); -} - /* * see if the key DB password is enabled */ PRBool -pk11_hasNullPassword(SECItem **pwitem) +pk11_hasNullPassword(NSSLOWKEYDBHandle *keydb,SECItem **pwitem) { PRBool pwenabled; - SECKEYKeyDBHandle *keydb; - keydb = SECKEY_GetDefaultKeyDB(); pwenabled = PR_FALSE; *pwitem = NULL; - if (SECKEY_HasKeyDBPassword (keydb) == SECSuccess) { - *pwitem = SECKEY_HashPassword("", keydb->global_salt); + if (nsslowkey_HasKeyDBPassword (keydb) == SECSuccess) { + *pwitem = nsslowkey_HashPassword("", keydb->global_salt); if ( *pwitem ) { - if (SECKEY_CheckKeyDBPassword (keydb, *pwitem) == SECSuccess) { + if (nsslowkey_CheckKeyDBPassword (keydb, *pwitem) == SECSuccess) { pwenabled = PR_TRUE; } else { SECITEM_ZfreeItem(*pwitem, PR_TRUE); @@ -563,13 +523,12 @@ pk11_handleDataObject(PK11Session *session,PK11Object *object) static CK_RV pk11_handleCertObject(PK11Session *session,PK11Object *object) { - PK11Attribute *attribute; CK_CERTIFICATE_TYPE type; - SECItem derCert; - char *label; - CERTCertDBHandle *handle; - CERTCertificate *cert; + PK11Attribute *attribute; CK_RV crv; + PK11SessionObject *sessObject = pk11_narrowToSessionObject(object); + + PORT_Assert(sessObject); /* certificates must have a type */ if ( !pk11_hasAttribute(object,CKA_CERTIFICATE_TYPE) ) { @@ -603,99 +562,393 @@ pk11_handleCertObject(PK11Session *session,PK11Object *object) return CKR_TEMPLATE_INCOMPLETE; } - /* - * now parse the certificate - */ - handle = CERT_GetDefaultCertDB(); - - /* get the nickname */ - label = pk11_getString(object,CKA_LABEL); - object->label = label; - if (label == NULL) { - return CKR_HOST_MEMORY; + /* in PKCS #11, Issuer is a required field */ + if ( !pk11_hasAttribute(object,CKA_ISSUER) ) { + return CKR_TEMPLATE_INCOMPLETE; } - - /* get the der cert */ - attribute = pk11_FindAttribute(object,CKA_VALUE); - derCert.data = (unsigned char *)attribute->attrib.pValue; - derCert.len = attribute->attrib.ulValueLen ; - - cert = CERT_NewTempCertificate(handle, &derCert, label, PR_FALSE, PR_TRUE); - pk11_FreeAttribute(attribute); - if (cert == NULL) { - return CKR_ATTRIBUTE_VALUE_INVALID; + + /* in PKCS #11, Serial is a required field */ + if ( !pk11_hasAttribute(object,CKA_SERIAL_NUMBER) ) { + return CKR_TEMPLATE_INCOMPLETE; } /* add it to the object */ - object->objectInfo = cert; - object->infoFree = (PK11Free) CERT_DestroyCertificate; + object->objectInfo = NULL; + object->infoFree = (PK11Free) NULL; /* now just verify the required date fields */ crv = pk11_defaultAttribute(object, CKA_ID, NULL, 0); if (crv != CKR_OK) { return crv; } - crv = pk11_defaultAttribute(object,CKA_ISSUER, - pk11_item_expand(&cert->derIssuer)); - if (crv != CKR_OK) { return crv; } - crv = pk11_defaultAttribute(object,CKA_SERIAL_NUMBER, - pk11_item_expand(&cert->serialNumber)); - if (crv != CKR_OK) { return crv; } - if (pk11_isTrue(object,CKA_TOKEN)) { - SECCertUsage *certUsage = NULL; - CERTCertTrust trust = { CERTDB_USER, CERTDB_USER, CERTDB_USER }; + PK11Slot *slot = session->slot; + SECItem derCert; + NSSLOWCERTCertificate *cert; + NSSLOWCERTCertTrust *trust = NULL; + NSSLOWCERTCertTrust userTrust = + { CERTDB_USER, CERTDB_USER, CERTDB_USER }; + NSSLOWCERTCertTrust defTrust = + { CERTDB_TRUSTED_UNKNOWN, + CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN }; + char *label; + SECStatus rv; + PRBool inDB = PR_TRUE; + + if (slot->certDB == NULL) { + return CKR_TOKEN_WRITE_PROTECTED; + } + + /* get the der cert */ + attribute = pk11_FindAttribute(object,CKA_VALUE); + PORT_Assert(attribute); - attribute = pk11_FindAttribute(object,CKA_NETSCAPE_TRUST); - if(attribute) { - certUsage = (SECCertUsage*)attribute->attrib.pValue; - pk11_FreeAttribute(attribute); + derCert.data = (unsigned char *)attribute->attrib.pValue; + derCert.len = attribute->attrib.ulValueLen ; + + label = pk11_getString(object,CKA_LABEL); + + cert = nsslowcert_FindCertByDERCert(slot->certDB, &derCert); + if (cert == NULL) { + cert = nsslowcert_DecodeDERCertificate(&derCert,PR_FALSE,label); + inDB = PR_FALSE; + } + if (cert == NULL) { + if (label) PORT_Free(label); + pk11_FreeAttribute(attribute); + return CKR_ATTRIBUTE_VALUE_INVALID; } - /* Temporary for PKCS 12 */ - if(cert->nickname == NULL) { - /* use the arena so we at least don't leak memory */ - cert->nickname = PORT_ArenaStrdup(cert->arena, label); + if (slot->keyDB && nsslowkey_KeyForCertExists(slot->keyDB,cert)) { + trust = &userTrust; + } + if (!inDB) { + if (!trust) trust = &defTrust; + rv = nsslowcert_AddPermCert(slot->certDB, cert, label, trust); + } else { + rv = trust ? nsslowcert_ChangeCertTrust(slot->certDB,cert,trust) : + SECSuccess; } - /* only add certs that have a private key */ - if (SECKEY_KeyForCertExists(SECKEY_GetDefaultKeyDB(),cert) - != SECSuccess) { + if (label) PORT_Free(label); + pk11_FreeAttribute(attribute); + if (rv != SECSuccess) { + nsslowcert_DestroyCertificate(cert); + return CKR_DEVICE_ERROR; + } + object->handle=pk11_mkHandle(slot,&cert->certKey,PK11_TOKEN_TYPE_CERT); + nsslowcert_DestroyCertificate(cert); + } + + return CKR_OK; +} +unsigned int +pk11_MapTrust(CK_TRUST trust, PRBool clientAuth) +{ + unsigned int trustCA = clientAuth ? CERTDB_TRUSTED_CLIENT_CA : + CERTDB_TRUSTED_CA; + switch (trust) { + case CKT_NETSCAPE_TRUSTED: + return CERTDB_VALID_PEER|CERTDB_TRUSTED; + case CKT_NETSCAPE_TRUSTED_DELEGATOR: + return CERTDB_VALID_CA|trustCA; + case CKT_NETSCAPE_UNTRUSTED: + return CERTDB_NOT_TRUSTED; + case CKT_NETSCAPE_MUST_VERIFY: + return 0; + case CKT_NETSCAPE_VALID: /* implies must verify */ + return CERTDB_VALID_PEER; + case CKT_NETSCAPE_VALID_DELEGATOR: /* implies must verify */ + return CERTDB_VALID_CA; + default: + break; + } + return CERTDB_TRUSTED_UNKNOWN; +} + + +/* + * check the consistancy and initialize a Trust Object + */ +static CK_RV +pk11_handleTrustObject(PK11Session *session,PK11Object *object) +{ + NSSLOWCERTIssuerAndSN issuerSN; + + /* we can't store any certs private */ + if (pk11_isTrue(object,CKA_PRIVATE)) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + + /* certificates must have a type */ + if ( !pk11_hasAttribute(object,CKA_ISSUER) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + if ( !pk11_hasAttribute(object,CKA_SERIAL_NUMBER) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + if ( !pk11_hasAttribute(object,CKA_CERT_SHA1_HASH) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + if ( !pk11_hasAttribute(object,CKA_CERT_MD5_HASH) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + + if (pk11_isTrue(object,CKA_TOKEN)) { + PK11Slot *slot = session->slot; + PK11Attribute *issuer = NULL; + PK11Attribute *serial = NULL; + NSSLOWCERTCertificate *cert = NULL; + PK11Attribute *trust; + CK_TRUST sslTrust = CKT_NETSCAPE_TRUST_UNKNOWN; + CK_TRUST clientTrust = CKT_NETSCAPE_TRUST_UNKNOWN; + CK_TRUST emailTrust = CKT_NETSCAPE_TRUST_UNKNOWN; + CK_TRUST signTrust = CKT_NETSCAPE_TRUST_UNKNOWN; + NSSLOWCERTCertTrust dbTrust; + SECStatus rv; + + + if (slot->certDB == NULL) { + return CKR_TOKEN_WRITE_PROTECTED; + } + issuer = pk11_FindAttribute(object,CKA_ISSUER); + PORT_Assert(issuer); + issuerSN.derIssuer.data = (unsigned char *)issuer->attrib.pValue; + issuerSN.derIssuer.len = issuer->attrib.ulValueLen ; + + serial = pk11_FindAttribute(object,CKA_SERIAL_NUMBER); + PORT_Assert(serial); + issuerSN.serialNumber.data = (unsigned char *)serial->attrib.pValue; + issuerSN.serialNumber.len = serial->attrib.ulValueLen ; + + cert = nsslowcert_FindCertByIssuerAndSN(slot->certDB,&issuerSN); + pk11_FreeAttribute(serial); + pk11_FreeAttribute(issuer); + + if (cert == NULL) { return CKR_ATTRIBUTE_VALUE_INVALID; } - if (!cert->isperm) { - if (CERT_AddTempCertToPerm(cert, label, &trust) != SECSuccess) { - return CKR_HOST_MEMORY; + + trust = pk11_FindAttribute(object,CKA_TRUST_SERVER_AUTH); + if (trust) { + if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) { + PORT_Memcpy(&sslTrust,trust->attrib.pValue, sizeof(sslTrust)); + } + pk11_FreeAttribute(trust); + } + trust = pk11_FindAttribute(object,CKA_TRUST_CLIENT_AUTH); + if (trust) { + if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) { + PORT_Memcpy(&clientTrust,trust->attrib.pValue, + sizeof(clientTrust)); + } + pk11_FreeAttribute(trust); + } + trust = pk11_FindAttribute(object,CKA_TRUST_EMAIL_PROTECTION); + if (trust) { + if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) { + PORT_Memcpy(&emailTrust,trust->attrib.pValue, + sizeof(emailTrust)); } - } else { - CERT_ChangeCertTrust(cert->dbhandle,cert,&trust); + pk11_FreeAttribute(trust); } - if(certUsage) { - if(CERT_ChangeCertTrustByUsage(CERT_GetDefaultCertDB(), - cert, *certUsage) != SECSuccess) { - return CKR_HOST_MEMORY; + trust = pk11_FindAttribute(object,CKA_TRUST_CODE_SIGNING); + if (trust) { + if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) { + PORT_Memcpy(&signTrust,trust->attrib.pValue, + sizeof(signTrust)); } + pk11_FreeAttribute(trust); + } + + /* preserve certain old fields */ + if (cert->trust) { + dbTrust.sslFlags = + cert->trust->sslFlags & CERTDB_PRESERVE_TRUST_BITS; + dbTrust.emailFlags= + cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS; + dbTrust.objectSigningFlags = + cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS; + } + + dbTrust.sslFlags = pk11_MapTrust(sslTrust,PR_FALSE); + dbTrust.sslFlags |= pk11_MapTrust(clientTrust,PR_TRUE); + dbTrust.emailFlags = pk11_MapTrust(emailTrust,PR_FALSE); + dbTrust.objectSigningFlags = pk11_MapTrust(signTrust,PR_FALSE); + + rv = nsslowcert_ChangeCertTrust(slot->certDB,cert,&dbTrust); + object->handle=pk11_mkHandle(slot,&cert->certKey,PK11_TOKEN_TYPE_TRUST); + nsslowcert_DestroyCertificate(cert); + if (rv != SECSuccess) { + return CKR_DEVICE_ERROR; + } + } + + return CKR_OK; +} + +/* + * check the consistancy and initialize a Trust Object + */ +static CK_RV +pk11_handleSMimeObject(PK11Session *session,PK11Object *object) +{ + + /* we can't store any certs private */ + if (pk11_isTrue(object,CKA_PRIVATE)) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + + /* certificates must have a type */ + if ( !pk11_hasAttribute(object,CKA_SUBJECT) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + if ( !pk11_hasAttribute(object,CKA_NETSCAPE_SMIME_TIMESTAMP) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + if ( !pk11_hasAttribute(object,CKA_NETSCAPE_EMAIL) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + if ( !pk11_hasAttribute(object,CKA_VALUE) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + + if (pk11_isTrue(object,CKA_TOKEN)) { + PK11Slot *slot = session->slot; + SECItem derSubj,rawProfile,rawTime,emailKey; + char *email = NULL; + PK11Attribute *subject,*profile,*time; + SECStatus rv; + + PORT_Assert(slot); + if (slot->certDB == NULL) { + return CKR_TOKEN_WRITE_PROTECTED; + } + + /* lookup SUBJECT */ + subject = pk11_FindAttribute(object,CKA_SUBJECT); + PORT_Assert(subject); + derSubj.data = (unsigned char *)subject->attrib.pValue; + derSubj.len = subject->attrib.ulValueLen ; + + /* lookup VALUE */ + profile = pk11_FindAttribute(object,CKA_VALUE); + PORT_Assert(profile); + rawProfile.data = (unsigned char *)profile->attrib.pValue; + rawProfile.len = profile->attrib.ulValueLen ; + + /* lookup Time */ + time = pk11_FindAttribute(object,CKA_NETSCAPE_SMIME_TIMESTAMP); + PORT_Assert(time); + rawTime.data = (unsigned char *)time->attrib.pValue; + rawTime.len = time->attrib.ulValueLen ; + + + email = pk11_getString(object,CKA_NETSCAPE_EMAIL); + + /* Store CRL by SUBJECT */ + rv = nsslowcert_SaveSMimeProfile(slot->certDB, email, &derSubj, + &rawProfile,&rawTime); + + pk11_FreeAttribute(profile); + pk11_FreeAttribute(subject); + pk11_FreeAttribute(time); + if (rv != SECSuccess) { + PORT_Free(email); + return CKR_DEVICE_ERROR; } - object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_CERT); - object->inDB = PR_TRUE; + emailKey.data = (unsigned char *)email; + emailKey.len = PORT_Strlen(email)+1; + + object->handle = pk11_mkHandle(slot, &emailKey, PK11_TOKEN_TYPE_SMIME); + PORT_Free(email); + } + + return CKR_OK; +} + +/* + * check the consistancy and initialize a Trust Object + */ +static CK_RV +pk11_handleCrlObject(PK11Session *session,PK11Object *object) +{ + + /* we can't store any certs private */ + if (pk11_isTrue(object,CKA_PRIVATE)) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + + /* certificates must have a type */ + if ( !pk11_hasAttribute(object,CKA_SUBJECT) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + if ( !pk11_hasAttribute(object,CKA_VALUE) ) { + return CKR_TEMPLATE_INCOMPLETE; } - /* label has been adopted by object->label */ - /*PORT_Free(label); */ + if (pk11_isTrue(object,CKA_TOKEN)) { + PK11Slot *slot = session->slot; + PRBool isKRL = PR_FALSE; + SECItem derSubj,derCrl; + char *url = NULL; + PK11Attribute *subject,*crl; + SECStatus rv; + + PORT_Assert(slot); + if (slot->certDB == NULL) { + return CKR_TOKEN_WRITE_PROTECTED; + } + + /* lookup SUBJECT */ + subject = pk11_FindAttribute(object,CKA_SUBJECT); + PORT_Assert(subject); + derSubj.data = (unsigned char *)subject->attrib.pValue; + derSubj.len = subject->attrib.ulValueLen ; + + /* lookup VALUE */ + crl = pk11_FindAttribute(object,CKA_VALUE); + PORT_Assert(crl); + derCrl.data = (unsigned char *)crl->attrib.pValue; + derCrl.len = crl->attrib.ulValueLen ; + + + url = pk11_getString(object,CKA_NETSCAPE_URL); + isKRL = pk11_isTrue(object,CKA_NETSCAPE_KRL); + + /* Store CRL by SUBJECT */ + rv = nsslowcert_AddCrl(slot->certDB, &derCrl, &derSubj, url, isKRL); + + if (url) { + PORT_Free(url); + } + pk11_FreeAttribute(crl); + if (rv != SECSuccess) { + pk11_FreeAttribute(subject); + return CKR_DEVICE_ERROR; + } + + object->handle = pk11_mkHandle(slot,&derSubj, + isKRL ? PK11_TOKEN_KRL_HANDLE : PK11_TOKEN_TYPE_CRL); + pk11_FreeAttribute(subject); + } return CKR_OK; } -SECKEYLowPublicKey * pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key); +NSSLOWKEYPublicKey * pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key); /* * check the consistancy and initialize a Public Key Object */ static CK_RV -pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type) +pk11_handlePublicKeyObject(PK11Session *session, PK11Object *object, + CK_KEY_TYPE key_type) { - CK_BBOOL cktrue = CK_TRUE; CK_BBOOL encrypt = CK_TRUE; CK_BBOOL recover = CK_TRUE; CK_BBOOL wrap = CK_TRUE; + CK_BBOOL derive = CK_FALSE; + CK_BBOOL verify = CK_TRUE; + CK_ATTRIBUTE_TYPE pubKeyAttr = CKA_VALUE; CK_RV crv; switch (key_type) { @@ -706,6 +959,7 @@ pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type) if ( !pk11_hasAttribute(object, CKA_PUBLIC_EXPONENT)) { return CKR_TEMPLATE_INCOMPLETE; } + pubKeyAttr = CKA_MODULUS; break; case CKK_DSA: if ( !pk11_hasAttribute(object, CKA_SUBPRIME)) { @@ -721,6 +975,10 @@ pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type) if ( !pk11_hasAttribute(object, CKA_VALUE)) { return CKR_TEMPLATE_INCOMPLETE; } + if (key_type == CKK_DH) { + verify = CK_FALSE; + derive = CK_TRUE; + } encrypt = CK_FALSE; recover = CK_FALSE; wrap = CK_FALSE; @@ -734,176 +992,55 @@ pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type) if (crv != CKR_OK) return crv; crv = pk11_defaultAttribute(object,CKA_ENCRYPT,&encrypt,sizeof(CK_BBOOL)); if (crv != CKR_OK) return crv; - crv = pk11_defaultAttribute(object,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL)); + crv = pk11_defaultAttribute(object,CKA_VERIFY,&verify,sizeof(CK_BBOOL)); if (crv != CKR_OK) return crv; crv = pk11_defaultAttribute(object,CKA_VERIFY_RECOVER, &recover,sizeof(CK_BBOOL)); if (crv != CKR_OK) return crv; crv = pk11_defaultAttribute(object,CKA_WRAP,&wrap,sizeof(CK_BBOOL)); if (crv != CKR_OK) return crv; + crv = pk11_defaultAttribute(object,CKA_DERIVE,&derive,sizeof(CK_BBOOL)); + if (crv != CKR_OK) return crv; object->objectInfo = pk11_GetPubKey(object,key_type); - object->infoFree = (PK11Free) SECKEY_LowDestroyPublicKey; + object->infoFree = (PK11Free) nsslowkey_DestroyPublicKey; if (pk11_isTrue(object,CKA_TOKEN)) { - object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PUB); - } - - return CKR_OK; -} -/* pk11_GetPubItem returns data associated with the public key. - * one only needs to free the public key. This comment is here - * because this sematic would be non-obvious otherwise. All callers - * should include this comment. - */ -static SECItem * -pk11_GetPubItem(SECKEYPublicKey *pubKey) { - SECItem *pubItem = NULL; - /* get value to compare from the cert's public key */ - switch ( pubKey->keyType ) { - case rsaKey: - pubItem = &pubKey->u.rsa.modulus; - break; - case dsaKey: - pubItem = &pubKey->u.dsa.publicValue; - break; - default: - break; - } - return pubItem; -} - -/* convert a high key type to a low key type. This will go away when - * the last SECKEYPublicKey structs go away. - */ -LowKeyType -seckeyLow_KeyType(KeyType keyType) -{ - switch (keyType) { - case rsaKey: - return lowRSAKey; - case dsaKey: - return lowDSAKey; - case dhKey: - return lowDHKey; - default: - break; - } - return lowNullKey; -} - -typedef struct { - CERTCertificate *cert; - SECItem *pubKey; -} find_cert_callback_arg; - -static SECStatus -find_cert_by_pub_key(CERTCertificate *cert, SECItem *k, void *arg) -{ - find_cert_callback_arg *cbarg; - SECKEYPublicKey *pubKey = NULL; - SECItem *pubItem; - - if((cert == NULL) || (arg == NULL)) { - return SECFailure; - } - - /* if this cert doesn't look like a user cert, we aren't interested */ - if (!((cert->isperm) && (cert->trust) && - (( cert->trust->sslFlags & CERTDB_USER ) || - ( cert->trust->emailFlags & CERTDB_USER ) || - ( cert->trust->objectSigningFlags & CERTDB_USER )) && - ( cert->nickname != NULL ) ) ) { - goto done; - } - - /* get cert's public key */ - pubKey = CERT_ExtractPublicKey(cert); - if ( pubKey == NULL ) { - goto done; - } - /* pk11_GetPubItem returns data associated with the public key. - * one only needs to free the public key. This comment is here - * because this sematic would be non-obvious otherwise. All callers - * should include this comment. - */ - pubItem = pk11_GetPubItem(pubKey); - if (pubItem == NULL) goto done; - - cbarg = (find_cert_callback_arg *)arg; - - if(SECITEM_CompareItem(pubItem, cbarg->pubKey) == SECEqual) { - cbarg->cert = CERT_DupCertificate(cert); - return SECFailure; - } - -done: - if ( pubKey ) { - SECKEY_DestroyPublicKey(pubKey); - } + PK11Slot *slot = session->slot; + NSSLOWKEYPrivateKey *priv; + SECItem pubKey; - return (SECSuccess); -} + crv = pk11_Attribute2SSecItem(NULL,&pubKey,object,pubKeyAttr); + if (crv != CKR_OK) return crv; -static PK11Object *pk11_importCertificate(PK11Slot *slot,CERTCertificate *cert, - unsigned char *data, unsigned int size, PRBool needCert); -/* - * find a cert associated with the key and load it. - */ -static SECStatus -reload_existing_certificate(PK11Object *privKeyObject,SECItem *pubKey) -{ - find_cert_callback_arg cbarg; - SECItem nickName; - CERTCertificate *cert = NULL; - CK_RV crv; - SECStatus rv; - - cbarg.pubKey = pubKey; - cbarg.cert = NULL; - SEC_TraversePermCerts(CERT_GetDefaultCertDB(), - find_cert_by_pub_key, (void *)&cbarg); - if (cbarg.cert != NULL) { - CERTCertificate *cert = NULL; - /* can anyone tell me why this is call is necessary? rjr */ - cert = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), - &cbarg.cert->derCert); - - /* does the certificate in the database have a - * nickname? if not, it probably was inserted - * through SMIME and a nickname needs to be - * set. - */ - if (cert && !cert->nickname) { - crv=pk11_Attribute2SecItem(NULL,&nickName,privKeyObject,CKA_LABEL); - if (crv != CKR_OK) { - goto loser; - } - rv = CERT_AddPermNickname(cert, (char *)nickName.data); - SECITEM_ZfreeItem(&nickName, PR_FALSE); - if (rv != SECSuccess) { - goto loser; - } + PORT_Assert(pubKey.data); + if (slot->keyDB == NULL) { + PORT_Free(pubKey.data); + return CKR_TOKEN_WRITE_PROTECTED; + } + /* make sure the associated private key already exists */ + /* only works if we are logged in */ + priv = nsslowkey_FindKeyByPublicKey(slot->keyDB, &pubKey, + slot->password); + if (priv == NULL) { + PORT_Free(pubKey.data); + return CKR_ATTRIBUTE_VALUE_INVALID; } + nsslowkey_DestroyPrivateKey(priv); - /* associate the certificate with the key */ - pk11_importCertificate(privKeyObject->slot, cert, pubKey->data, - pubKey->len, PR_FALSE); + object->handle = pk11_mkHandle(slot, &pubKey, PK11_TOKEN_TYPE_PUB); + PORT_Free(pubKey.data); } - return SECSuccess; -loser: - if (cert) CERT_DestroyCertificate(cert); - if (cbarg.cert) CERT_DestroyCertificate(cbarg.cert); - return SECFailure; + return CKR_OK; } -static SECKEYLowPrivateKey * pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key); +static NSSLOWKEYPrivateKey * pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key); /* * check the consistancy and initialize a Private Key Object */ static CK_RV -pk11_handlePrivateKeyObject(PK11Object *object,CK_KEY_TYPE key_type) +pk11_handlePrivateKeyObject(PK11Session *session,PK11Object *object,CK_KEY_TYPE key_type) { CK_BBOOL cktrue = CK_TRUE; CK_BBOOL encrypt = CK_TRUE; @@ -996,60 +1133,59 @@ pk11_handlePrivateKeyObject(PK11Object *object,CK_KEY_TYPE key_type) if (crv != CKR_OK) return crv; if (pk11_isTrue(object,CKA_TOKEN)) { - SECKEYLowPrivateKey *privKey; + PK11Slot *slot = session->slot; + NSSLOWKEYPrivateKey *privKey; char *label; SECStatus rv = SECSuccess; SECItem pubKey; + if (slot->keyDB == NULL) { + return CKR_TOKEN_WRITE_PROTECTED; + } + privKey=pk11_mkPrivKey(object,key_type); if (privKey == NULL) return CKR_HOST_MEMORY; - label = object->label = pk11_getString(object,CKA_LABEL); + label = pk11_getString(object,CKA_LABEL); crv = pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB); - if (crv == CKR_OK) { - rv = SECKEY_StoreKeyByPublicKey(SECKEY_GetDefaultKeyDB(), - privKey, &pubKey, label, - (SECKEYLowGetPasswordKey) pk11_givePass, object->slot); - - /* check for the existance of an existing certificate and activate - * it if necessary */ - if (rv == SECSuccess) { - reload_existing_certificate(object,&pubKey); - } - - if (pubKey.data) PORT_Free(pubKey.data); - } else { - rv = SECFailure; + if (crv != CKR_OK) { + if (label) PORT_Free(label); + nsslowkey_DestroyPrivateKey(privKey); + return CKR_TEMPLATE_INCOMPLETE; } + rv = nsslowkey_StoreKeyByPublicKey(object->slot->keyDB, + privKey, &pubKey, label, object->slot->password); - SECKEY_LowDestroyPrivateKey(privKey); + if (label) PORT_Free(label); + object->handle = pk11_mkHandle(slot,&pubKey,PK11_TOKEN_TYPE_PRIV); + if (pubKey.data) PORT_Free(pubKey.data); + nsslowkey_DestroyPrivateKey(privKey); if (rv != SECSuccess) return CKR_DEVICE_ERROR; - object->inDB = PR_TRUE; - object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV); } else { object->objectInfo = pk11_mkPrivKey(object,key_type); if (object->objectInfo == NULL) return CKR_HOST_MEMORY; - object->infoFree = (PK11Free) SECKEY_LowDestroyPrivateKey; - } - /* now NULL out the sensitive attributes */ - if (pk11_isTrue(object,CKA_SENSITIVE)) { - pk11_nullAttribute(object,CKA_PRIVATE_EXPONENT); - pk11_nullAttribute(object,CKA_PRIME_1); - pk11_nullAttribute(object,CKA_PRIME_2); - pk11_nullAttribute(object,CKA_EXPONENT_1); - pk11_nullAttribute(object,CKA_EXPONENT_2); - pk11_nullAttribute(object,CKA_COEFFICIENT); + object->infoFree = (PK11Free) nsslowkey_DestroyPrivateKey; + /* now NULL out the sensitive attributes */ + if (pk11_isTrue(object,CKA_SENSITIVE)) { + pk11_nullAttribute(object,CKA_PRIVATE_EXPONENT); + pk11_nullAttribute(object,CKA_PRIME_1); + pk11_nullAttribute(object,CKA_PRIME_2); + pk11_nullAttribute(object,CKA_EXPONENT_1); + pk11_nullAttribute(object,CKA_EXPONENT_2); + pk11_nullAttribute(object,CKA_COEFFICIENT); + } } return CKR_OK; } /* forward delcare the DES formating function for handleSecretKey */ void pk11_FormatDESKey(unsigned char *key, int length); -static SECKEYLowPrivateKey *pk11_mkSecretKeyRep(PK11Object *object); +static NSSLOWKEYPrivateKey *pk11_mkSecretKeyRep(PK11Object *object); /* Validate secret key data, and set defaults */ static CK_RV -validateSecretKey(PK11Object *object, CK_KEY_TYPE key_type, PRBool isFIPS) +validateSecretKey(PK11Session *session, PK11Object *object, + CK_KEY_TYPE key_type, PRBool isFIPS) { CK_RV crv; CK_BBOOL cktrue = CK_TRUE; @@ -1095,9 +1231,14 @@ validateSecretKey(PK11Object *object, CK_KEY_TYPE key_type, PRBool isFIPS) #if NSS_SOFTOKEN_DOES_RC5 case CKK_RC5: #endif +#ifdef NSS_SOFTOKEN_DOES_CAST case CKK_CAST: case CKK_CAST3: case CKK_CAST5: +#endif +#if NSS_SOFTOKEN_DOES_IDEA + case CKK_IDEA: +#endif attribute = pk11_FindAttribute(object,CKA_VALUE); /* shouldn't happen */ if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; @@ -1127,45 +1268,51 @@ validateSecretKey(PK11Object *object, CK_KEY_TYPE key_type, PRBool isFIPS) * check the consistancy and initialize a Secret Key Object */ static CK_RV -pk11_handleSecretKeyObject(PK11Object *object,CK_KEY_TYPE key_type, - PRBool isFIPS) +pk11_handleSecretKeyObject(PK11Session *session,PK11Object *object, + CK_KEY_TYPE key_type, PRBool isFIPS) { CK_RV crv; - SECKEYLowPrivateKey *privKey = NULL; + NSSLOWKEYPrivateKey *privKey = NULL; SECItem pubKey; + char *label = NULL; pubKey.data = 0; /* First validate and set defaults */ - crv = validateSecretKey(object, key_type, isFIPS); + crv = validateSecretKey(session, object, key_type, isFIPS); if (crv != CKR_OK) goto loser; /* If the object is a TOKEN object, store in the database */ if (pk11_isTrue(object,CKA_TOKEN)) { - char *label; + PK11Slot *slot = session->slot; SECStatus rv = SECSuccess; + if (slot->keyDB == NULL) { + return CKR_TOKEN_WRITE_PROTECTED; + } privKey=pk11_mkSecretKeyRep(object); if (privKey == NULL) return CKR_HOST_MEMORY; - label = object->label = pk11_getString(object,CKA_LABEL); + label = pk11_getString(object,CKA_LABEL); - crv = pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_ID); /* Should this be ID? */ + crv = pk11_Attribute2SecItem(NULL, &pubKey, object, CKA_ID); + /* Should this be ID? */ if (crv != CKR_OK) goto loser; - rv = SECKEY_StoreKeyByPublicKey(SECKEY_GetDefaultKeyDB(), - privKey, &pubKey, label, - (SECKEYLowGetPasswordKey) pk11_givePass, object->slot); + PORT_Assert(slot->keyDB); + rv = nsslowkey_StoreKeyByPublicKey(slot->keyDB, + privKey, &pubKey, label, slot->password); if (rv != SECSuccess) { crv = CKR_DEVICE_ERROR; + goto loser; } - object->inDB = PR_TRUE; - object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV); + object->handle = pk11_mkHandle(slot,&pubKey,PK11_TOKEN_TYPE_KEY); } loser: - if (privKey) SECKEY_LowDestroyPrivateKey(privKey); + if (label) PORT_Free(label); + if (privKey) nsslowkey_DestroyPrivateKey(privKey); if (pubKey.data) PORT_Free(pubKey.data); return crv; @@ -1207,12 +1354,12 @@ pk11_handleKeyObject(PK11Session *session, PK11Object *object) switch (object->objclass) { case CKO_PUBLIC_KEY: - return pk11_handlePublicKeyObject(object,key_type); + return pk11_handlePublicKeyObject(session,object,key_type); case CKO_PRIVATE_KEY: - return pk11_handlePrivateKeyObject(object,key_type); + return pk11_handlePrivateKeyObject(session,object,key_type); case CKO_SECRET_KEY: /* make sure the required fields exist */ - return pk11_handleSecretKeyObject(object,key_type, + return pk11_handleSecretKeyObject(session,object,key_type, (PRBool)(session->slot->slotID == FIPS_SLOT_ID)); default: break; @@ -1223,8 +1370,8 @@ pk11_handleKeyObject(PK11Session *session, PK11Object *object) /* * Handle Object does all the object consistancy checks, automatic attribute * generation, attribute defaulting, etc. If handleObject succeeds, the object - * will be assigned an object handle, and the object pointer will be adopted - * by the session. (that is don't free object). + * will be assigned an object handle, and the object installed in the session + * or stored in the DB. */ CK_RV pk11_handleObject(PK11Object *object, PK11Session *session) @@ -1257,17 +1404,6 @@ pk11_handleObject(PK11Object *object, PK11Session *session) (pk11_isTrue(object,CKA_TOKEN))) { return CKR_SESSION_READ_ONLY; } - - if (pk11_isTrue(object, CKA_TOKEN)) { - if (slot->DB_loaded == PR_FALSE) { - /* we are creating a token object, make sure we load the database - * first so we don't get duplicates.... - * ... NOTE: This assumes we are logged in as well! - */ - pk11_importKeyDB(slot); - slot->DB_loaded = PR_TRUE; - } - } /* PKCS #11 object ID's are unique for all objects on a * token */ @@ -1288,9 +1424,19 @@ pk11_handleObject(PK11Object *object, PK11Session *session) switch (object->objclass) { case CKO_DATA: crv = pk11_handleDataObject(session,object); + break; case CKO_CERTIFICATE: crv = pk11_handleCertObject(session,object); break; + case CKO_NETSCAPE_TRUST: + crv = pk11_handleTrustObject(session,object); + break; + case CKO_NETSCAPE_CRL: + crv = pk11_handleCrlObject(session,object); + break; + case CKO_NETSCAPE_SMIME: + crv = pk11_handleSMimeObject(session,object); + break; case CKO_PRIVATE_KEY: case CKO_PUBLIC_KEY: case CKO_SECRET_KEY: @@ -1308,632 +1454,23 @@ pk11_handleObject(PK11Object *object, PK11Session *session) } /* now link the object into the slot and session structures */ - object->slot = slot; - pk11_AddObject(session,object); - - return CKR_OK; -} - -/* import a private key as an object. We don't call handle object. - * because we the private key came from the key DB and we don't want to - * write back out again */ -static PK11Object * -pk11_importPrivateKey(PK11Slot *slot,SECKEYLowPrivateKey *lowPriv, - SECItem *dbKey) -{ - PK11Object *privateKey; - CK_KEY_TYPE key_type; - CK_BBOOL cktrue = CK_TRUE; - CK_BBOOL ckfalse = CK_FALSE; - CK_BBOOL sign = CK_TRUE; - CK_BBOOL recover = CK_TRUE; - CK_BBOOL decrypt = CK_TRUE; - CK_BBOOL derive = CK_FALSE; - CK_RV crv = CKR_OK; - CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; - unsigned char cka_id[SHA1_LENGTH]; - - /* - * now lets create an object to hang the attributes off of - */ - privateKey = pk11_NewObject(slot); /* fill in the handle later */ - if (privateKey == NULL) { - pk11_FreeObject(privateKey); - return NULL; - } - - /* Netscape Private Attribute for dealing with database storeage */ - if (pk11_AddAttributeType(privateKey, CKA_NETSCAPE_DB, - pk11_item_expand(dbKey)) ) { - pk11_FreeObject(privateKey); - return NULL; - } - - /* now force the CKA_ID */ - SHA1_HashBuf(cka_id, (unsigned char *)dbKey->data, (uint32)dbKey->len); - if (pk11_AddAttributeType(privateKey, CKA_ID, cka_id, sizeof(cka_id))) { - pk11_FreeObject(privateKey); - return NULL; - } - - - /* Fill in the common Default values */ - if (pk11_AddAttributeType(privateKey,CKA_CLASS, &privClass, - sizeof(CK_OBJECT_CLASS)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_TOKEN, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_PRIVATE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_MODIFIABLE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_LABEL, NULL, 0) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_START_DATE, NULL, 0) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_END_DATE, NULL, 0) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_DERIVE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - /* local: well we really don't know for sure... it could have been an - * imported key, but it's not a useful attribute anyway. */ - if (pk11_AddAttributeType(privateKey,CKA_LOCAL, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_SUBJECT, NULL, 0) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_SENSITIVE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_EXTRACTABLE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - /* is this really true? Maybe we should just say false here? */ - if (pk11_AddAttributeType(privateKey,CKA_ALWAYS_SENSITIVE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_NEVER_EXTRACTABLE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - - /* Now Set up the parameters to generate the key (based on mechanism) */ - /* NOTE: for safety sake we *DO NOT* remember critical attributes. PKCS #11 - * will look them up again from the database when it needs them. - */ - switch (lowPriv->keyType) { - case lowRSAKey: - /* format the keys */ - key_type = CKK_RSA; - sign = CK_TRUE; - recover = CK_TRUE; - decrypt = CK_TRUE; - derive = CK_FALSE; - /* now fill in the RSA dependent parameters in the public key */ - crv = pk11_AddAttributeType(privateKey,CKA_MODULUS, - pk11_item_expand(&lowPriv->u.rsa.modulus)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_PRIVATE_EXPONENT,NULL,0); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT, - pk11_item_expand(&lowPriv->u.rsa.publicExponent)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_PRIME_1,NULL,0); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_PRIME_2,NULL,0); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_1,NULL,0); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_2,NULL,0); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_COEFFICIENT,NULL,0); - break; - case lowDSAKey: - key_type = CKK_DSA; - sign = CK_TRUE; - recover = CK_FALSE; - decrypt = CK_FALSE; - derive = CK_FALSE; - crv = pk11_AddAttributeType(privateKey,CKA_PRIME, - pk11_item_expand(&lowPriv->u.dsa.params.prime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_SUBPRIME, - pk11_item_expand(&lowPriv->u.dsa.params.subPrime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_BASE, - pk11_item_expand(&lowPriv->u.dsa.params.base)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_VALUE,NULL,0); - if (crv != CKR_OK) break; - break; - case lowDHKey: - key_type = CKK_DH; - sign = CK_FALSE; - decrypt = CK_FALSE; - recover = CK_FALSE; - derive = CK_TRUE; - crv = CKR_MECHANISM_INVALID; - break; - default: - crv = CKR_MECHANISM_INVALID; - } - - if (crv != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - - - if (pk11_AddAttributeType(privateKey,CKA_SIGN, &sign, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_SIGN_RECOVER, &recover, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_DECRYPT, &decrypt, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_UNWRAP, &decrypt, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_DERIVE, &derive, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_KEY_TYPE,&key_type, - sizeof(CK_KEY_TYPE)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - privateKey->handle = slot->tokenIDCount++; - privateKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV); - PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) - privateKey->objclass = privClass; - privateKey->slot = slot; - privateKey->inDB = PR_TRUE; - - return privateKey; -} - -/* import a private key or cert as a public key object.*/ -static PK11Object * -pk11_importPublicKey(PK11Slot *slot, - SECKEYLowPrivateKey *lowPriv, CERTCertificate *cert, SECItem *dbKey) -{ - PK11Object *publicKey = NULL; - CK_KEY_TYPE key_type; - CK_BBOOL cktrue = CK_TRUE; - CK_BBOOL ckfalse = CK_FALSE; - CK_BBOOL verify = CK_TRUE; - CK_BBOOL recover = CK_TRUE; - CK_BBOOL encrypt = CK_TRUE; - CK_BBOOL derive = CK_FALSE; - CK_RV crv = CKR_OK; - CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; - unsigned char cka_id[SHA1_LENGTH]; - LowKeyType keyType = nullKey; - SECKEYPublicKey *pubKey = NULL; - CK_ATTRIBUTE theTemplate[2]; - PK11ObjectListElement *objectList = NULL; - - if (lowPriv == NULL) { - pubKey = CERT_ExtractPublicKey(cert); - if (pubKey == NULL) { - goto failed; - } - /* pk11_GetPubItem returns data associated with the public key. - * one only needs to free the public key. This comment is here - * because this sematic would be non-obvious otherwise. All callers - * should include this comment. - */ - dbKey = pk11_GetPubItem(pubKey); - if (dbKey == NULL) { - goto failed; - } - } - SHA1_HashBuf(cka_id, (unsigned char *)dbKey->data, (uint32)dbKey->len); - theTemplate[0].type = CKA_ID; - theTemplate[0].pValue = cka_id; - theTemplate[0].ulValueLen = sizeof(cka_id); - theTemplate[1].type = CKA_CLASS; - theTemplate[1].pValue = &pubClass; - theTemplate[1].ulValueLen = sizeof(CK_OBJECT_CLASS); - crv = pk11_searchObjectList(&objectList,slot->tokObjects, - slot->objectLock, theTemplate, 2, slot->isLoggedIn); - if ((crv == CKR_OK) && (objectList != NULL)) { - goto failed; - } - /* - * now lets create an object to hang the attributes off of - */ - publicKey = pk11_NewObject(slot); /* fill in the handle later */ - if (publicKey == NULL) { - goto failed; - } - - /* now force the CKA_ID */ - if (pk11_AddAttributeType(publicKey, CKA_ID, cka_id, sizeof(cka_id))) { - goto failed; - } - - /* Fill in the common Default values */ - if (pk11_AddAttributeType(publicKey,CKA_CLASS,&pubClass, - sizeof(CK_OBJECT_CLASS)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_TOKEN, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_PRIVATE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_MODIFIABLE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_LABEL, NULL, 0) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_START_DATE, NULL, 0) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_END_DATE, NULL, 0) != CKR_OK) { - goto failed; - } - /* local: well we really don't know for sure... it could have been an - * imported key, but it's not a useful attribute anyway. */ - if (pk11_AddAttributeType(publicKey,CKA_LOCAL, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_SUBJECT, NULL, 0) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_SENSITIVE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_EXTRACTABLE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_ALWAYS_SENSITIVE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_NEVER_EXTRACTABLE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - - /* Now Set up the parameters to generate the key (based on mechanism) */ - if (lowPriv == NULL) { - - keyType = seckeyLow_KeyType(pubKey->keyType); - } else { - keyType = lowPriv->keyType; - } - - - switch (keyType) { - case lowRSAKey: - /* format the keys */ - key_type = CKK_RSA; - verify = CK_TRUE; - recover = CK_TRUE; - encrypt = CK_TRUE; - derive = CK_FALSE; - /* now fill in the RSA dependent parameters in the public key */ - if (lowPriv) { - crv = pk11_AddAttributeType(publicKey,CKA_MODULUS, - pk11_item_expand(&lowPriv->u.rsa.modulus)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_PUBLIC_EXPONENT, - pk11_item_expand(&lowPriv->u.rsa.publicExponent)); - if (crv != CKR_OK) break; - } else { - crv = pk11_AddAttributeType(publicKey,CKA_MODULUS, - pk11_item_expand(&pubKey->u.rsa.modulus)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_PUBLIC_EXPONENT, - pk11_item_expand(&pubKey->u.rsa.publicExponent)); - if (crv != CKR_OK) break; - } - break; - case lowDSAKey: - key_type = CKK_DSA; - verify = CK_TRUE; - recover = CK_FALSE; - encrypt = CK_FALSE; - derive = CK_FALSE; - if (lowPriv) { - crv = pk11_AddAttributeType(publicKey,CKA_PRIME, - pk11_item_expand(&lowPriv->u.dsa.params.prime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_SUBPRIME, - pk11_item_expand(&lowPriv->u.dsa.params.subPrime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_BASE, - pk11_item_expand(&lowPriv->u.dsa.params.base)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_VALUE, - pk11_item_expand(&lowPriv->u.dsa.publicValue)); - if (crv != CKR_OK) break; - } else { - crv = pk11_AddAttributeType(publicKey,CKA_PRIME, - pk11_item_expand(&pubKey->u.dsa.params.prime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_SUBPRIME, - pk11_item_expand(&pubKey->u.dsa.params.subPrime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_BASE, - pk11_item_expand(&pubKey->u.dsa.params.base)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_VALUE, - pk11_item_expand(&pubKey->u.dsa.publicValue)); - if (crv != CKR_OK) break; - } - break; - case lowDHKey: - key_type = CKK_DH; - verify = CK_FALSE; - encrypt = CK_FALSE; - recover = CK_FALSE; - derive = CK_TRUE; - crv = CKR_MECHANISM_INVALID; - break; - default: - crv = CKR_MECHANISM_INVALID; - } - - if (pubKey) { - SECKEY_DestroyPublicKey(pubKey); - pubKey = NULL; - } - - if (crv != CKR_OK) { - goto failed; - } - - if (pk11_AddAttributeType(publicKey,CKA_VERIFY, &verify, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_VERIFY_RECOVER, &recover, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_ENCRYPT, &encrypt, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_WRAP, &encrypt, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_DERIVE, &derive, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_KEY_TYPE,&key_type, - sizeof(CK_KEY_TYPE)) != CKR_OK) { - goto failed; - } - PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - publicKey->handle = slot->tokenIDCount++; - publicKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PUB); - PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) - publicKey->objclass = pubClass; - publicKey->slot = slot; - publicKey->inDB = PR_FALSE; /* not really in the Database */ - - return publicKey; -failed: - if (pubKey) SECKEY_DestroyPublicKey(pubKey); - if (publicKey) pk11_FreeObject(publicKey); - return NULL; -} - -/* - * Question.. Why doesn't import Cert call pk11_handleObject, or - * pk11 handleCertObject? Answer: because they will try to write - * this cert back out to the Database, even though it is already in - * the database. - */ -static PK11Object * -pk11_importCertificate(PK11Slot *slot, CERTCertificate *cert, - unsigned char *data, unsigned int size, PRBool needObject) -{ - PK11Object *certObject = NULL; - CK_BBOOL cktrue = CK_TRUE; - CK_BBOOL ckfalse = CK_FALSE; - CK_CERTIFICATE_TYPE certType = CKC_X_509; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - unsigned char cka_id[SHA1_LENGTH]; - CK_ATTRIBUTE theTemplate; - PK11ObjectListElement *objectList = NULL; - CK_RV crv; - - - /* - * first make sure that no object for this cert already exists. - */ - theTemplate.type = CKA_VALUE; - theTemplate.pValue = cert->derCert.data; - theTemplate.ulValueLen = cert->derCert.len; - crv = pk11_searchObjectList(&objectList,slot->tokObjects, - slot->objectLock, &theTemplate, 1, slot->isLoggedIn); - if ((crv == CKR_OK) && (objectList != NULL)) { - if (needObject) { - pk11_ReferenceObject(objectList->object); - certObject = objectList->object; - } - pk11_FreeObjectList(objectList); - return certObject; - } - - /* - * now lets create an object to hang the attributes off of - */ - certObject = pk11_NewObject(slot); /* fill in the handle later */ - if (certObject == NULL) { - return NULL; - } - - /* First set the CKA_ID */ - if (data == NULL) { - SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(cert); - SECItem *pubItem; - if (pubKey == NULL) { - pk11_FreeObject(certObject); - return NULL; - } - /* pk11_GetPubItem returns data associated with the public key. - * one only needs to free the public key. This comment is here - * because this sematic would be non-obvious otherwise. - */ - pubItem =pk11_GetPubItem(pubKey); - if (pubItem == NULL) { - SECKEY_DestroyPublicKey(pubKey); - pk11_FreeObject(certObject); - return NULL; - } - SHA1_HashBuf(cka_id, (unsigned char *)pubItem->data, - (uint32)pubItem->len); - SECKEY_DestroyPublicKey(pubKey); - } else { - SHA1_HashBuf(cka_id, (unsigned char *)data, (uint32)size); - } - if (pk11_AddAttributeType(certObject, CKA_ID, cka_id, sizeof(cka_id))) { - pk11_FreeObject(certObject); - return NULL; - } - - /* initalize the certificate attributes */ - if (pk11_AddAttributeType(certObject, CKA_CLASS, &certClass, - sizeof(CK_OBJECT_CLASS)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_TOKEN, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_PRIVATE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_LABEL, cert->nickname, - PORT_Strlen(cert->nickname)) - != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_MODIFIABLE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_CERTIFICATE_TYPE, &certType, - sizeof(CK_CERTIFICATE_TYPE))!=CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_VALUE, - pk11_item_expand(&cert->derCert)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_ISSUER, - pk11_item_expand(&cert->derIssuer)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_SUBJECT, - pk11_item_expand(&cert->derSubject)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_SERIAL_NUMBER, - pk11_item_expand(&cert->serialNumber)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - - - certObject->objectInfo = CERT_DupCertificate(cert); - certObject->infoFree = (PK11Free) CERT_DestroyCertificate; - - /* now just verify the required date fields */ - PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - certObject->handle = slot->tokenIDCount++; - certObject->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_CERT); - PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) - certObject->objclass = certClass; - certObject->slot = slot; - certObject->inDB = PR_TRUE; - pk11_AddSlotObject(slot, certObject); - if (needObject) { - pk11_ReferenceObject(certObject); + if (pk11_isToken(object->handle)) { + pk11_convertSessionToToken(object); } else { - certObject = NULL; + object->slot = slot; + pk11_AddObject(session,object); } - return certObject; + return CKR_OK; } /* * ******************** Public Key Utilities *************************** */ /* Generate a low public key structure from an object */ -SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type) +NSSLOWKEYPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type) { - SECKEYLowPublicKey *pubKey; + NSSLOWKEYPublicKey *pubKey; PLArenaPool *arena; CK_RV crv; @@ -1941,17 +1478,21 @@ SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type) return NULL; } + if (pk11_isToken(object->handle)) { +/* ferret out the token object handle */ + } + /* If we already have a key, use it */ if (object->objectInfo) { - return (SECKEYLowPublicKey *)object->objectInfo; + return (NSSLOWKEYPublicKey *)object->objectInfo; } /* allocate the structure */ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) return NULL; - pubKey = (SECKEYLowPublicKey *) - PORT_ArenaAlloc(arena,sizeof(SECKEYLowPublicKey)); + pubKey = (NSSLOWKEYPublicKey *) + PORT_ArenaAlloc(arena,sizeof(NSSLOWKEYPublicKey)); if (pubKey == NULL) { PORT_FreeArena(arena,PR_FALSE); return NULL; @@ -1961,7 +1502,7 @@ SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type) pubKey->arena = arena; switch (key_type) { case CKK_RSA: - pubKey->keyType = lowRSAKey; + pubKey->keyType = NSSLOWKEYRSAKey; crv = pk11_Attribute2SSecItem(arena,&pubKey->u.rsa.modulus, object,CKA_MODULUS); if (crv != CKR_OK) break; @@ -1969,7 +1510,7 @@ SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type) object,CKA_PUBLIC_EXPONENT); break; case CKK_DSA: - pubKey->keyType = lowDSAKey; + pubKey->keyType = NSSLOWKEYDSAKey; crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dsa.params.prime, object,CKA_PRIME); if (crv != CKR_OK) break; @@ -1983,7 +1524,7 @@ SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type) object,CKA_VALUE); break; case CKK_DH: - pubKey->keyType = lowDHKey; + pubKey->keyType = NSSLOWKEYDHKey; crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dh.prime, object,CKA_PRIME); if (crv != CKR_OK) break; @@ -2003,24 +1544,25 @@ SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type) } object->objectInfo = pubKey; - object->infoFree = (PK11Free) SECKEY_LowDestroyPublicKey; + object->infoFree = (PK11Free) nsslowkey_DestroyPublicKey; return pubKey; } /* make a private key from a verified object */ -static SECKEYLowPrivateKey * +static NSSLOWKEYPrivateKey * pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type) { - SECKEYLowPrivateKey *privKey; + NSSLOWKEYPrivateKey *privKey; PLArenaPool *arena; CK_RV crv = CKR_OK; SECStatus rv; + PORT_Assert(!pk11_isToken(object->handle)); arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) return NULL; - privKey = (SECKEYLowPrivateKey *) - PORT_ArenaAlloc(arena,sizeof(SECKEYLowPrivateKey)); + privKey = (NSSLOWKEYPrivateKey *) + PORT_ArenaAlloc(arena,sizeof(NSSLOWKEYPrivateKey)); if (privKey == NULL) { PORT_FreeArena(arena,PR_FALSE); return NULL; @@ -2030,7 +1572,7 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type) privKey->arena = arena; switch (key_type) { case CKK_RSA: - privKey->keyType = lowRSAKey; + privKey->keyType = NSSLOWKEYRSAKey; crv=pk11_Attribute2SSecItem(arena,&privKey->u.rsa.modulus, object,CKA_MODULUS); if (crv != CKR_OK) break; @@ -2056,12 +1598,12 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type) CKA_COEFFICIENT); if (crv != CKR_OK) break; rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version, - SEC_PRIVATE_KEY_VERSION); + NSSLOWKEY_VERSION); if (rv != SECSuccess) crv = CKR_HOST_MEMORY; break; case CKK_DSA: - privKey->keyType = lowDSAKey; + privKey->keyType = NSSLOWKEYDSAKey; crv = pk11_Attribute2SSecItem(arena,&privKey->u.dsa.params.prime, object,CKA_PRIME); if (crv != CKR_OK) break; @@ -2080,7 +1622,7 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type) break; case CKK_DH: - privKey->keyType = lowDHKey; + privKey->keyType = NSSLOWKEYDHKey; crv = pk11_Attribute2SSecItem(arena,&privKey->u.dh.prime, object,CKA_PRIME); if (crv != CKR_OK) break; @@ -2089,6 +1631,9 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type) if (crv != CKR_OK) break; crv = pk11_Attribute2SSecItem(arena,&privKey->u.dh.privateValue, object,CKA_VALUE); + if (crv != CKR_OK) break; + crv = pk11_Attribute2SSecItem(arena,&privKey->u.dh.publicValue, + object,CKA_NETSCAPE_DB); break; default: crv = CKR_KEY_TYPE_INCONSISTENT; @@ -2103,52 +1648,31 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type) /* Generate a low private key structure from an object */ -SECKEYLowPrivateKey * +NSSLOWKEYPrivateKey * pk11_GetPrivKey(PK11Object *object,CK_KEY_TYPE key_type) { - SECKEYLowPrivateKey *priv = NULL; + NSSLOWKEYPrivateKey *priv = NULL; if (object->objclass != CKO_PRIVATE_KEY) { return NULL; } if (object->objectInfo) { - return (SECKEYLowPrivateKey *)object->objectInfo; + return (NSSLOWKEYPrivateKey *)object->objectInfo; } - if (pk11_isTrue(object,CKA_TOKEN)) { + if (pk11_isToken(object->handle)) { /* grab it from the data base */ - SECItem pubKey; - CK_RV crv; + PK11TokenObject *to = pk11_narrowToTokenObject(object); - /* KEYID is the public KEY for DSA and DH, and the MODULUS for - * RSA */ - crv=pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB); - if (crv != CKR_OK) return NULL; - - priv=SECKEY_FindKeyByPublicKey(SECKEY_GetDefaultKeyDB(),&pubKey, - (SECKEYLowGetPasswordKey) pk11_givePass, - object->slot); - if (!priv && pubKey.data[0] == 0) { - /* Because of legacy code issues, sometimes the public key has - * a '0' prepended to it, forcing it to be unsigned. The database - * may not store that '0', so remove it and try again. - */ - SECItem tmpPubKey; - tmpPubKey.data = pubKey.data + 1; - tmpPubKey.len = pubKey.len - 1; - priv=SECKEY_FindKeyByPublicKey(SECKEY_GetDefaultKeyDB(),&tmpPubKey, - (SECKEYLowGetPasswordKey) pk11_givePass, - object->slot); - } - if (pubKey.data) PORT_Free(pubKey.data); - - /* don't 'cache' DB private keys */ - return priv; - } - - priv = pk11_mkPrivKey(object, key_type); + PORT_Assert(to); + PORT_Assert(object->slot->keyDB); + priv = nsslowkey_FindKeyByPublicKey(object->slot->keyDB, &to->dbKey, + object->slot->password); + } else { + priv = pk11_mkPrivKey(object, key_type); + } object->objectInfo = priv; - object->infoFree = (PK11Free) SECKEY_LowDestroyPrivateKey; + object->infoFree = (PK11Free) nsslowkey_DestroyPrivateKey; return priv; } @@ -2213,10 +1737,10 @@ pk11_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type) /* make a fake private key representing a symmetric key */ -static SECKEYLowPrivateKey * +static NSSLOWKEYPrivateKey * pk11_mkSecretKeyRep(PK11Object *object) { - SECKEYLowPrivateKey *privKey; + NSSLOWKEYPrivateKey *privKey; PLArenaPool *arena = 0; CK_RV crv; SECStatus rv; @@ -2225,8 +1749,8 @@ pk11_mkSecretKeyRep(PK11Object *object) arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { crv = CKR_HOST_MEMORY; goto loser; } - privKey = (SECKEYLowPrivateKey *) - PORT_ArenaAlloc(arena,sizeof(SECKEYLowPrivateKey)); + privKey = (NSSLOWKEYPrivateKey *) + PORT_ArenaAlloc(arena,sizeof(NSSLOWKEYPrivateKey)); if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; } privKey->arena = arena; @@ -2240,7 +1764,7 @@ pk11_mkSecretKeyRep(PK11Object *object) * is used for the key. * all others - set to integer 0 */ - privKey->keyType = lowRSAKey; + privKey->keyType = NSSLOWKEYRSAKey; /* The modulus is set to the key id of the symmetric key */ crv=pk11_Attribute2SecItem(arena,&privKey->u.rsa.modulus,object,CKA_ID); @@ -2272,7 +1796,8 @@ pk11_mkSecretKeyRep(PK11Object *object) if (crv != CKR_OK) goto loser; /* Private key version field set normally for compatibility */ - rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version,SEC_PRIVATE_KEY_VERSION); + rv = DER_SetUInteger(privKey->arena, + &privKey->u.rsa.version, NSSLOWKEY_VERSION); if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; goto loser; } loser: @@ -2285,117 +1810,178 @@ loser: } static PRBool -isSecretKey(SECKEYLowPrivateKey *privKey) +isSecretKey(NSSLOWKEYPrivateKey *privKey) { - if (privKey->keyType == lowRSAKey && privKey->u.rsa.publicExponent.len == 1 && - privKey->u.rsa.publicExponent.data[0] == 0) + if (privKey->keyType == NSSLOWKEYRSAKey && + privKey->u.rsa.publicExponent.len == 1 && + privKey->u.rsa.publicExponent.data[0] == 0) return PR_TRUE; return PR_FALSE; } -/* Import a Secret Key */ -static PRBool -importSecretKey(PK11Slot *slot, SECKEYLowPrivateKey *priv) -{ - PK11Object *object; - CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY; - CK_BBOOL cktrue = CK_TRUE; - CK_BBOOL ckfalse = CK_FALSE; - CK_KEY_TYPE key_type; +/********************************************************************** + * + * Start of PKCS 11 functions + * + **********************************************************************/ - /* Check for secret key representation, return if it isn't one */ - if (!isSecretKey(priv)) - return PR_FALSE; - /* - * now lets create an object to hang the attributes off of - */ - object = pk11_NewObject(slot); /* fill in the handle later */ - if (object == NULL) { - goto loser; - } +/* return the function list */ +CK_RV NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) +{ + *pFunctionList = (CK_FUNCTION_LIST_PTR) &pk11_funcList; + return CKR_OK; +} - /* Set the ID value */ - if (pk11_AddAttributeType(object, CKA_ID, - priv->u.rsa.modulus.data, priv->u.rsa.modulus.len)) { - pk11_FreeObject(object); - goto loser; - } +/* return the function list */ +CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) +{ + return NSC_GetFunctionList(pFunctionList); +} - /* initalize the object attributes */ - if (pk11_AddAttributeType(object, CKA_CLASS, &secretClass, - sizeof(secretClass)) != CKR_OK) { - pk11_FreeObject(object); - goto loser; - } +static PLHashNumber +pk11_HashNumber(const void *key) +{ + return (PLHashNumber) key; +} - if (pk11_AddAttributeType(object, CKA_TOKEN, &cktrue, - sizeof(cktrue)) != CKR_OK) { - pk11_FreeObject(object); - goto loser; - } +/* + * eventually I'd like to expunge all occurances of XXX_SLOT_ID and + * just go with the info in the slot. This is one place, however, + * where it might be a little difficult. + */ +char * +pk11_getDefTokName(CK_SLOT_ID slotID) +{ + static char buf[33]; - if (pk11_AddAttributeType(object, CKA_PRIVATE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(object); - goto loser; + switch (slotID) { + case NETSCAPE_SLOT_ID: + return "NSS Generic Crypto Services "; + case PRIVATE_KEY_SLOT_ID: + return "NSS Certificate DB "; + case FIPS_SLOT_ID: + return "NSS FIPS-140-1 Cerificate DB "; + default: + break; } + sprintf(buf,"NSS Application Token %08x ",(unsigned int) slotID); + return buf; +} - if (pk11_AddAttributeType(object, CKA_VALUE, - pk11_item_expand(&priv->u.rsa.privateExponent)) != CKR_OK) { - pk11_FreeObject(object); - goto loser; - } +char * +pk11_getDefSlotName(CK_SLOT_ID slotID) +{ + static char buf[65]; - if (pk11_AddAttributeType(object, CKA_KEY_TYPE, - pk11_item_expand(&priv->u.rsa.coefficient)) != CKR_OK) { - pk11_FreeObject(object); - goto loser; + switch (slotID) { + case NETSCAPE_SLOT_ID: + return + "NSS Internal Cryptographic Services Version 3.4 "; + case PRIVATE_KEY_SLOT_ID: + return + "NSS User Private Key and Certificate Services "; + case FIPS_SLOT_ID: + return + "Netscape FIPS-140-1 User Private Key Services "; + default: + break; } - key_type = *(CK_KEY_TYPE*)priv->u.rsa.coefficient.data; + sprintf(buf, + "NSS Application Slot %08x ", + (unsigned int) slotID); + return buf; +} - /* Validate and add default attributes */ - validateSecretKey(object, key_type, (PRBool)(slot->slotID == FIPS_SLOT_ID)); +static CK_ULONG nscSlotCount = 0; +static CK_SLOT_ID_PTR nscSlotList = NULL; +static CK_ULONG nscSlotListSize = 0; +static PLHashTable *nscSlotHashTable = NULL; - /* now just verify the required date fields */ - PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - object->handle = slot->tokenIDCount++; - object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV); - PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) +/* look up a slot structure from the ID (used to be a macro when we only + * had two slots) */ +PK11Slot * +pk11_SlotFromID(CK_SLOT_ID slotID) +{ + return (PK11Slot *)PL_HashTableLookupConst(nscSlotHashTable, + (void *)slotID); +} + +PK11Slot * +pk11_SlotFromSessionHandle(CK_SESSION_HANDLE handle) +{ + int slotIDIndex = (handle >> 24) & 0xff; - object->objclass = secretClass; - object->slot = slot; - object->inDB = PR_TRUE; - pk11_AddSlotObject(slot, object); + if (slotIDIndex >= nscSlotCount) { + return NULL; + } -loser: - return PR_TRUE; + return pk11_SlotFromID(nscSlotList[slotIDIndex]); } + +PK11Slot * pk11_NewSlotFromID(CK_SLOT_ID slotID) +{ + PK11Slot *slot = NULL; + PLHashEntry *entry; + + if (nscSlotList == NULL) { + nscSlotListSize = NSC_SLOT_LIST_BLOCK_SIZE; + nscSlotList = (CK_SLOT_ID *) + PORT_ZAlloc(nscSlotListSize*sizeof(CK_SLOT_ID)); + if (nscSlotList == NULL) { + return NULL; + } + } + if (nscSlotCount >= nscSlotListSize) { + nscSlotListSize += NSC_SLOT_LIST_BLOCK_SIZE; + nscSlotList = (CK_SLOT_ID *) PORT_Realloc(nscSlotList, + nscSlotListSize*sizeof(CK_SLOT_ID)); + if (nscSlotList == NULL) { + return NULL; + } + } + if (nscSlotHashTable == NULL) { + nscSlotHashTable = PL_NewHashTable(64,pk11_HashNumber,PL_CompareValues, + PL_CompareValues, NULL, 0); + if (nscSlotHashTable == NULL) { + return NULL; + } + } -/********************************************************************** - * - * Start of PKCS 11 functions - * - **********************************************************************/ + slot = (PK11Slot *) PORT_ZAlloc(sizeof(PK11Slot)); + if (slot == NULL) { + return NULL; + } + entry = PL_HashTableAdd(nscSlotHashTable,(void *)slotID,slot); + if (entry == NULL) { + PORT_Free(slot); + return NULL; + } + slot->index = nscSlotCount; + nscSlotList[nscSlotCount++] = slotID; -/* return the function list */ -CK_RV NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) -{ - *pFunctionList = &pk11_funcList; - return CKR_OK; + return slot; } /* * initialize one of the slot structures. figure out which by the ID */ CK_RV -PK11_SlotInit(CK_SLOT_ID slotID, PRBool needLogin) +PK11_SlotInit(char *configdir,pk11_token_parameters *params) { int i; - PK11Slot *slot = pk11_SlotFromID(slotID); + CK_SLOT_ID slotID = params->slotID; + PK11Slot *slot = pk11_NewSlotFromID(slotID); + PRBool needLogin = !params->noKeyDB; + CK_RV crv; + + if (slot == NULL) { + return CKR_HOST_MEMORY; + } + #ifdef PKCS11_USE_THREADS slot->sessionLock = PZ_NewLock(nssILockSession); if (slot->sessionLock == NULL) return CKR_HOST_MEMORY; @@ -2411,6 +1997,11 @@ PK11_SlotInit(CK_SLOT_ID slotID, PRBool needLogin) for(i=0; i < TOKEN_OBJECT_HASH_SIZE; i++) { slot->tokObjects[i] = NULL; } + slot->tokenHashTable = PL_NewHashTable(64,pk11_HashNumber,PL_CompareValues, + SECITEM_HashCompare, NULL, 0); + if (slot->tokenHashTable == NULL) { + return CKR_HOST_MEMORY; + } slot->password = NULL; slot->hasTokens = PR_FALSE; slot->sessionIDCount = 1; @@ -2422,61 +2013,39 @@ PK11_SlotInit(CK_SLOT_ID slotID, PRBool needLogin) slot->ssoLoggedIn = PR_FALSE; slot->DB_loaded = PR_FALSE; slot->slotID = slotID; - if (needLogin) { - /* if the data base is initialized with a null password,remember that */ - slot->needLogin = (PRBool)!pk11_hasNullPassword(&slot->password); - } - return CKR_OK; -} - - -/* - * common initialization routines between PKCS #11 and FIPS - */ -CK_RV PK11_LowInitialize(CK_VOID_PTR pReserved) -{ - CK_RV crv = CKR_OK; - CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *) pReserved; - - /* NOTE: - * we should be getting out mutexes from this list, not statically binding - * them from NSPR. This should happen before we allow the internal to split - * off from the rest on NSS. - */ - - /* initialize the key and cert db's */ - SECKEY_SetDefaultKeyDBAlg(SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC); - - if ((init_args && init_args->LibraryParameters)) { - pk11_parameters paramStrings; - - crv = secmod_parseParameters - ((char *)init_args->LibraryParameters,¶mStrings); + slot->certDB = NULL; + slot->keyDB = NULL; + slot->minimumPinLen = 0; + slot->readOnly = params->readOnly; + pk11_setStringName(params->tokdes ? params->tokdes : + pk11_getDefTokName(slotID), slot->tokDescription, + sizeof(slot->tokDescription)); + pk11_setStringName(params->slotdes ? params->slotdes : + pk11_getDefSlotName(slotID), slot->slotDescription, + sizeof(slot->slotDescription)); + + if ((!params->noCertDB) || (!params->noKeyDB)) { + crv = pk11_DBInit(params->configdir ? params->configdir : configdir, + params->certPrefix, params->keyPrefix, params->readOnly, + params->noCertDB, params->noKeyDB, params->forceOpen, + &slot->certDB, &slot->keyDB); if (crv != CKR_OK) { + /* shoutdown slot? */ return crv; } - - crv = pk11_DBInit(paramStrings.configdir,paramStrings.certPrefix, - paramStrings.keyPrefix,paramStrings.secmodName, paramStrings.readOnly,paramStrings.noCertDB, - paramStrings.noModDB, paramStrings.forceOpen); - if (crv != CKR_OK) { - secmod_freeParams(¶mStrings); - return crv; + } + if (needLogin) { + /* if the data base is initialized with a null password,remember that */ + slot->needLogin = + (PRBool)!pk11_hasNullPassword(slot->keyDB,&slot->password); + if (params->minPW <= PK11_MAX_PIN) { + slot->minimumPinLen = params->minPW; } - crv = pk11_configure(paramStrings.man, paramStrings.libdes, - paramStrings.tokdes,paramStrings.ptokdes,paramStrings.slotdes, - paramStrings.pslotdes,paramStrings.fslotdes, - paramStrings.fpslotdes, paramStrings.minPW, - paramStrings.pwRequired); - secmod_freeParams(¶mStrings); - if (crv != CKR_OK) { - return crv; + if ((slot->minimumPinLen == 0) && (params->pwRequired) && + (slot->minimumPinLen <= PK11_MAX_PIN)) { + slot->minimumPinLen = 1; } - } else { - return CKR_ARGUMENTS_BAD; } - - return CKR_OK; } @@ -2507,25 +2076,67 @@ NSC_ModuleDBFunc(unsigned long function,char *parameters, char *args) /* NSC_Initialize initializes the Cryptoki library. */ -CK_RV NSC_Initialize(CK_VOID_PTR pReserved) +CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) { static PRBool init = PR_FALSE; CK_RV crv = CKR_OK; + SECStatus rv; + CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *) pReserved; + int i; - crv = PK11_LowInitialize(pReserved); - if (crv != CKR_OK) return crv; + if (init) { + return crv; + } - /* intialize all the slots */ - if (!init) { - crv = PK11_SlotInit(NETSCAPE_SLOT_ID,PR_FALSE); - if (crv != CKR_OK) return crv; - crv = PK11_SlotInit(PRIVATE_KEY_SLOT_ID,PR_TRUE); - init = PR_TRUE; + rv = RNG_RNGInit(); /* initialize random number generator */ + if (rv != SECSuccess) { + crv = CKR_DEVICE_ERROR; + goto loser; } + RNG_SystemInfoForRNG(); + + + /* NOTE: + * we should be getting out mutexes from this list, not statically binding + * them from NSPR. This should happen before we allow the internal to split + * off from the rest on NSS. + */ + + /* initialize the key and cert db's */ + nsslowkey_SetDefaultKeyDBAlg + (SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC); + crv = CKR_ARGUMENTS_BAD; + if ((init_args && init_args->LibraryParameters)) { + pk11_parameters paramStrings; + + crv = secmod_parseParameters + ((char *)init_args->LibraryParameters,¶mStrings, isFIPS); + if (crv != CKR_OK) { + return crv; + } + crv = pk11_configure(paramStrings.man, paramStrings.libdes); + if (crv != CKR_OK) { + goto loser; + } + + for (i=0; i < paramStrings.token_count; i++) { + crv = + PK11_SlotInit(paramStrings.configdir,¶mStrings.tokens[i]); + if (crv != CKR_OK) break; + } +loser: + secmod_freeParams(¶mStrings); + } + init = (PRBool) (crv == CKR_OK); return crv; } +CK_RV NSC_Initialize(CK_VOID_PTR pReserved) +{ + return nsc_CommonInitialize(pReserved,PR_FALSE); +} + /* NSC_Finalize indicates that an application is done with the * Cryptoki library.*/ CK_RV NSC_Finalize (CK_VOID_PTR pReserved) @@ -2538,7 +2149,7 @@ CK_RV NSC_Finalize (CK_VOID_PTR pReserved) CK_RV NSC_GetInfo(CK_INFO_PTR pInfo) { pInfo->cryptokiVersion.major = 2; - pInfo->cryptokiVersion.minor = 1; + pInfo->cryptokiVersion.minor = 11; PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); pInfo->libraryVersion.major = 3; pInfo->libraryVersion.minor = 2; @@ -2551,10 +2162,9 @@ CK_RV NSC_GetInfo(CK_INFO_PTR pInfo) CK_RV NSC_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) { - *pulCount = 2; + *pulCount = nscSlotCount; if (pSlotList != NULL) { - pSlotList[0] = NETSCAPE_SLOT_ID; - pSlotList[1] = PRIVATE_KEY_SLOT_ID; + PORT_Memcpy(pSlotList,nscSlotList,nscSlotCount*sizeof(CK_SLOT_ID)); } return CKR_OK; } @@ -2562,28 +2172,19 @@ CK_RV NSC_GetSlotList(CK_BBOOL tokenPresent, /* NSC_GetSlotInfo obtains information about a particular slot in the system. */ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { + PK11Slot *slot = pk11_SlotFromID(slotID); + if (slot == NULL) return CKR_SLOT_ID_INVALID; + pInfo->firmwareVersion.major = 0; pInfo->firmwareVersion.minor = 0; - switch (slotID) { - case NETSCAPE_SLOT_ID: - PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); - PORT_Memcpy(pInfo->slotDescription,slotDescription,64); - pInfo->flags = CKF_TOKEN_PRESENT; - pInfo->hardwareVersion.major = 3; - pInfo->hardwareVersion.minor = 2; - return CKR_OK; - case PRIVATE_KEY_SLOT_ID: - PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); - PORT_Memcpy(pInfo->slotDescription,privSlotDescription,64); - pInfo->flags = CKF_TOKEN_PRESENT; - /* ok we really should read it out of the keydb file. */ - pInfo->hardwareVersion.major = PRIVATE_KEY_DB_FILE_VERSION; - pInfo->hardwareVersion.minor = 0; - return CKR_OK; - default: - break; - } - return CKR_SLOT_ID_INVALID; + PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); + PORT_Memcpy(pInfo->slotDescription,slot->slotDescription,64); + pInfo->flags = CKF_TOKEN_PRESENT; + /* ok we really should read it out of the keydb file. */ + /* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */ + pInfo->hardwareVersion.major = 3; + pInfo->hardwareVersion.minor = 2; + return CKR_OK; } #define CKF_THREAD_SAFE 0x8000 /* for now */ @@ -2593,12 +2194,12 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) { PK11Slot *slot = pk11_SlotFromID(slotID); - SECKEYKeyDBHandle *handle; + NSSLOWKEYDBHandle *handle; if (slot == NULL) return CKR_SLOT_ID_INVALID; PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); - PORT_Memcpy(pInfo->model,"Libsec 4.0 ",16); + PORT_Memcpy(pInfo->model,"NSS 3 ",16); PORT_Memcpy(pInfo->serialNumber,"0000000000000000",16); pInfo->ulMaxSessionCount = 0; /* arbitrarily large */ pInfo->ulSessionCount = slot->sessionCount; @@ -2606,9 +2207,9 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) pInfo->ulRwSessionCount = slot->rwSessionCount; pInfo->firmwareVersion.major = 0; pInfo->firmwareVersion.minor = 0; - switch (slotID) { - case NETSCAPE_SLOT_ID: - PORT_Memcpy(pInfo->label,tokDescription,32); + PORT_Memcpy(pInfo->label,slot->tokDescription,32); + handle = slot->keyDB; + if (handle == NULL) { pInfo->flags= CKF_RNG | CKF_WRITE_PROTECTED | CKF_THREAD_SAFE; pInfo->ulMaxPinLen = 0; pInfo->ulMinPinLen = 0; @@ -2618,10 +2219,7 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) pInfo->ulFreePrivateMemory = 0; pInfo->hardwareVersion.major = 4; pInfo->hardwareVersion.minor = 0; - return CKR_OK; - case PRIVATE_KEY_SLOT_ID: - PORT_Memcpy(pInfo->label,privTokDescription,32); - handle = SECKEY_GetDefaultKeyDB(); + } else { /* * we have three possible states which we may be in: * (1) No DB password has been initialized. This also means we @@ -2631,7 +2229,7 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) * (3) Finally we have an initialized password whicn is not NULL, and * we will need to prompt for it. */ - if (SECKEY_HasKeyDBPassword(handle) == SECFailure) { + if (nsslowkey_HasKeyDBPassword(handle) == SECFailure) { pInfo->flags = CKF_THREAD_SAFE | CKF_LOGIN_REQUIRED; } else if (!slot->needLogin) { pInfo->flags = CKF_THREAD_SAFE | CKF_USER_PIN_INITIALIZED; @@ -2641,8 +2239,8 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) } pInfo->ulMaxPinLen = PK11_MAX_PIN; pInfo->ulMinPinLen = 0; - if (minimumPinLen > 0) { - pInfo->ulMinPinLen = (CK_ULONG)minimumPinLen; + if (slot->minimumPinLen > 0) { + pInfo->ulMinPinLen = (CK_ULONG)slot->minimumPinLen; } pInfo->ulTotalPublicMemory = 1; pInfo->ulFreePublicMemory = 1; @@ -2650,11 +2248,8 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) pInfo->ulFreePrivateMemory = 1; pInfo->hardwareVersion.major = CERT_DB_FILE_VERSION; pInfo->hardwareVersion.minor = 0; - return CKR_OK; - default: - break; } - return CKR_SLOT_ID_INVALID; + return CKR_OK; } @@ -2674,8 +2269,8 @@ CK_RV NSC_GetMechanismList(CK_SLOT_ID slotID, pMechanismList[i] = mechanisms[i].type; } } - return CKR_OK; - case PRIVATE_KEY_SLOT_ID: + break; + default: *pulCount = 0; for (i=0; i < (int) mechanismCount; i++) { if (mechanisms[i].privkey) { @@ -2685,11 +2280,9 @@ CK_RV NSC_GetMechanismList(CK_SLOT_ID slotID, } } } - return CKR_OK; - default: break; } - return CKR_SLOT_ID_INVALID; + return CKR_OK; } @@ -2705,11 +2298,9 @@ CK_RV NSC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, case NETSCAPE_SLOT_ID: isPrivateKey = PR_FALSE; break; - case PRIVATE_KEY_SLOT_ID: + default: isPrivateKey = PR_TRUE; break; - default: - return CKR_SLOT_ID_INVALID; } for (i=0; i < (int) mechanismCount; i++) { if (type == mechanisms[i].type) { @@ -2725,19 +2316,19 @@ CK_RV NSC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, } static SECStatus -pk11_TurnOffUser(CERTCertificate *cert, SECItem *k, void *arg) +pk11_TurnOffUser(NSSLOWCERTCertificate *cert, SECItem *k, void *arg) { - CERTCertTrust trust; + NSSLOWCERTCertTrust trust; SECStatus rv; - rv = CERT_GetCertTrust(cert,&trust); + rv = nsslowcert_GetCertTrust(cert,&trust); if (rv == SECSuccess && ((trust.emailFlags & CERTDB_USER) || (trust.sslFlags & CERTDB_USER) || (trust.objectSigningFlags & CERTDB_USER))) { trust.emailFlags &= ~CERTDB_USER; trust.sslFlags &= ~CERTDB_USER; trust.objectSigningFlags &= ~CERTDB_USER; - CERT_ChangeCertTrust(cert->dbhandle,cert,&trust); + nsslowcert_ChangeCertTrust(cert->dbhandle,cert,&trust); } return SECSuccess; } @@ -2746,8 +2337,8 @@ pk11_TurnOffUser(CERTCertificate *cert, SECItem *k, void *arg) CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin, CK_ULONG ulPinLen,CK_CHAR_PTR pLabel) { PK11Slot *slot = pk11_SlotFromID(slotID); - SECKEYKeyDBHandle *handle; - CERTCertDBHandle *certHandle; + NSSLOWKEYDBHandle *handle; + NSSLOWCERTCertDBHandle *certHandle; SECStatus rv; int i; PK11Object *object; @@ -2784,19 +2375,19 @@ CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin, PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) /* then clear out the key database */ - handle = SECKEY_GetDefaultKeyDB(); + handle = slot->keyDB; if (handle == NULL) { return CKR_TOKEN_WRITE_PROTECTED; } /* what to do on an error here? */ - rv = SECKEY_ResetKeyDB(handle); + rv = nsslowkey_ResetKeyDB(handle); /* finally mark all the user certs as non-user certs */ - certHandle = CERT_GetDefaultCertDB(); + certHandle = slot->certDB; if (certHandle == NULL) return CKR_OK; - SEC_TraversePermCerts(certHandle,pk11_TurnOffUser, NULL); + nsslowcert_TraversePermCerts(certHandle,pk11_TurnOffUser, NULL); return CKR_OK; /*is this the right function for not implemented*/ } @@ -2808,9 +2399,9 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession, { PK11Session *sp; PK11Slot *slot; - SECKEYKeyDBHandle *handle; + NSSLOWKEYDBHandle *handle; SECItem *newPin; - char newPinStr[256]; + char newPinStr[PK11_MAX_PIN+1]; SECStatus rv; @@ -2819,36 +2410,35 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession, return CKR_SESSION_HANDLE_INVALID; } - if (sp->info.slotID == NETSCAPE_SLOT_ID) { + slot = pk11_SlotFromSession(sp); + if (slot == NULL) { pk11_FreeSession(sp); - return CKR_PIN_LEN_RANGE; + return CKR_SESSION_HANDLE_INVALID;; } - /* should be an assert */ - if (!((sp->info.slotID == PRIVATE_KEY_SLOT_ID) || - (sp->info.slotID == FIPS_SLOT_ID)) ) { + handle = slot->keyDB; + if (handle == NULL) { pk11_FreeSession(sp); - return CKR_SESSION_HANDLE_INVALID;; + return CKR_PIN_LEN_RANGE; } + if (sp->info.state != CKS_RW_SO_FUNCTIONS) { pk11_FreeSession(sp); return CKR_USER_NOT_LOGGED_IN; } - slot = pk11_SlotFromSession(sp); pk11_FreeSession(sp); /* make sure the pins aren't too long */ - if (ulPinLen > 255) { + if (ulPinLen > PK11_MAX_PIN) { return CKR_PIN_LEN_RANGE; } - - handle = SECKEY_GetDefaultKeyDB(); - if (handle == NULL) { - return CKR_TOKEN_WRITE_PROTECTED; + if (ulPinLen < slot->minimumPinLen) { + return CKR_PIN_LEN_RANGE; } - if (SECKEY_HasKeyDBPassword(handle) != SECFailure) { + + if (nsslowkey_HasKeyDBPassword(handle) != SECFailure) { return CKR_DEVICE_ERROR; } @@ -2857,11 +2447,11 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession, newPinStr[ulPinLen] = 0; /* build the hashed pins which we pass around */ - newPin = SECKEY_HashPassword(newPinStr,handle->global_salt); + newPin = nsslowkey_HashPassword(newPinStr,handle->global_salt); PORT_Memset(newPinStr,0,sizeof(newPinStr)); /* change the data base */ - rv = SECKEY_SetKeyDBPassword(handle,newPin); + rv = nsslowkey_SetKeyDBPassword(handle,newPin); /* Now update our local copy of the pin */ if (rv == SECSuccess) { @@ -2884,10 +2474,10 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, { PK11Session *sp; PK11Slot *slot; - SECKEYKeyDBHandle *handle; + NSSLOWKEYDBHandle *handle; SECItem *newPin; SECItem *oldPin; - char newPinStr[256],oldPinStr[256]; + char newPinStr[PK11_MAX_PIN+1],oldPinStr[PK11_MAX_PIN+1]; SECStatus rv; @@ -2896,20 +2486,18 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, return CKR_SESSION_HANDLE_INVALID; } - if (sp->info.slotID == NETSCAPE_SLOT_ID) { + slot = pk11_SlotFromSession(sp); + if (!slot) { pk11_FreeSession(sp); - return CKR_PIN_LEN_RANGE; + return CKR_SESSION_HANDLE_INVALID;; } - /* should be an assert */ - /* should be an assert */ - if (!((sp->info.slotID == PRIVATE_KEY_SLOT_ID) || - (sp->info.slotID == FIPS_SLOT_ID)) ) { + handle = slot->keyDB; + if (handle == NULL) { pk11_FreeSession(sp); - return CKR_SESSION_HANDLE_INVALID;; + return CKR_PIN_LEN_RANGE; } - slot = pk11_SlotFromSession(sp); if (slot->needLogin && sp->info.state != CKS_RW_USER_FUNCTIONS) { pk11_FreeSession(sp); return CKR_USER_NOT_LOGGED_IN; @@ -2918,16 +2506,14 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, pk11_FreeSession(sp); /* make sure the pins aren't too long */ - if ((ulNewLen > 255) || (ulOldLen > 255)) { + if ((ulNewLen > PK11_MAX_PIN) || (ulOldLen > PK11_MAX_PIN)) { return CKR_PIN_LEN_RANGE; } - - - handle = SECKEY_GetDefaultKeyDB(); - if (handle == NULL) { - return CKR_TOKEN_WRITE_PROTECTED; + if (ulNewLen < slot->minimumPinLen) { + return CKR_PIN_LEN_RANGE; } + /* convert to null terminated string */ PORT_Memcpy(newPinStr,pNewPin,ulNewLen); newPinStr[ulNewLen] = 0; @@ -2935,13 +2521,13 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, oldPinStr[ulOldLen] = 0; /* build the hashed pins which we pass around */ - newPin = SECKEY_HashPassword(newPinStr,handle->global_salt); - oldPin = SECKEY_HashPassword(oldPinStr,handle->global_salt); + newPin = nsslowkey_HashPassword(newPinStr,handle->global_salt); + oldPin = nsslowkey_HashPassword(oldPinStr,handle->global_salt); PORT_Memset(newPinStr,0,sizeof(newPinStr)); PORT_Memset(oldPinStr,0,sizeof(oldPinStr)); /* change the data base */ - rv = SECKEY_ChangeKeyDBPassword(handle,oldPin,newPin); + rv = nsslowkey_ChangeKeyDBPassword(handle,oldPin,newPin); /* Now update our local copy of the pin */ SECITEM_ZfreeItem(oldPin, PR_TRUE); @@ -2974,12 +2560,8 @@ CK_RV NSC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, if (session == NULL) return CKR_HOST_MEMORY; PK11_USE_THREADS(PZ_Lock(slot->sessionLock);) - sessionID = slot->sessionIDCount++; - if (slotID == PRIVATE_KEY_SLOT_ID) { - sessionID |= PK11_PRIVATE_KEY_FLAG; - } else if (slotID == FIPS_SLOT_ID) { - sessionID |= PK11_FIPS_FLAG; - } else if (flags & CKF_RW_SESSION) { + sessionID = slot->sessionIDCount++ | (slot->index << 24); + if (slot->readOnly && (flags & CKF_RW_SESSION)) { /* NETSCAPE_SLOT_ID is Read ONLY */ session->info.flags &= ~CKF_RW_SESSION; } @@ -3101,9 +2683,9 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, { PK11Slot *slot; PK11Session *session; - SECKEYKeyDBHandle *handle; + NSSLOWKEYDBHandle *handle; SECItem *pin; - char pinStr[256]; + char pinStr[PK11_MAX_PIN+1]; /* get the slot */ @@ -3123,20 +2705,23 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, if (slot->isLoggedIn) return CKR_USER_ALREADY_LOGGED_IN; slot->ssoLoggedIn = PR_FALSE; - if (ulPinLen > 255) return CKR_PIN_LEN_RANGE; + if (ulPinLen > PK11_MAX_PIN) return CKR_PIN_LEN_RANGE; /* convert to null terminated string */ PORT_Memcpy(pinStr,pPin,ulPinLen); pinStr[ulPinLen] = 0; - handle = SECKEY_GetDefaultKeyDB(); + handle = slot->keyDB; + if (handle == NULL) { + return CKR_USER_TYPE_INVALID; + } /* * Deal with bootstrap. We allow the SSO to login in with a NULL * password if and only if we haven't initialized the KEY DB yet. * We only allow this on a RW session. */ - if (SECKEY_HasKeyDBPassword(handle) == SECFailure) { + if (nsslowkey_HasKeyDBPassword(handle) == SECFailure) { /* allow SSO's to log in only if there is not password on the * key database */ if (((userType == CKU_SO) && (session->info.flags & CKF_RW_SESSION)) @@ -3165,10 +2750,10 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, /* build the hashed pins which we pass around */ - pin = SECKEY_HashPassword(pinStr,handle->global_salt); + pin = nsslowkey_HashPassword(pinStr,handle->global_salt); if (pin == NULL) return CKR_HOST_MEMORY; - if (SECKEY_CheckKeyDBPassword(handle,pin) == SECSuccess) { + if (nsslowkey_CheckKeyDBPassword(handle,pin) == SECSuccess) { SECItem *tmp; PK11_USE_THREADS(PZ_Lock(slot->sessionLock);) tmp = slot->password; @@ -3255,14 +2840,11 @@ CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession, * handle the base object stuff */ crv = pk11_handleObject(object,session); + *phObject = object->handle; pk11_FreeSession(session); - if (crv != CKR_OK) { - pk11_FreeObject(object); - return crv; - } + pk11_FreeObject(object); - *phObject = object->handle; - return CKR_OK; + return crv; } @@ -3343,12 +2925,9 @@ CK_RV NSC_CopyObject(CK_SESSION_HANDLE hSession, crv = pk11_handleObject(destObject,session); *phNewObject = destObject->handle; pk11_FreeSession(session); - if (crv != CKR_OK) { - pk11_FreeObject(destObject); - return crv; - } + pk11_FreeObject(destObject); - return CKR_OK; + return crv; } @@ -3497,568 +3076,641 @@ CK_RV NSC_SetAttributeValue (CK_SESSION_HANDLE hSession, } pk11_FreeObject(object); - return CKR_OK; + return crv; } -/* stolen from keydb.c */ -#define KEYDB_PW_CHECK_STRING "password-check" -#define KEYDB_PW_CHECK_LEN 14 - -SECKEYLowPrivateKey * SECKEY_DecryptKey(DBT *key, SECItem *pwitem, - SECKEYKeyDBHandle *handle); -typedef struct pk11keyNodeStr { - struct pk11keyNodeStr *next; - SECKEYLowPrivateKey *privKey; - CERTCertificate *cert; - SECItem *pubItem; -} pk11keyNode; +/* + * find any certs that may match the template and load them. + */ +#define NSC_CERT 0x00000001 +#define NSC_TRUST 0x00000002 +#define NSC_CRL 0x00000004 +#define NSC_SMIME 0x00000008 +#define NSC_PRIVATE 0x00000010 +#define NSC_PUBLIC 0x00000020 +#define NSC_KEY 0x00000040 -typedef struct { - PLArenaPool *arena; - pk11keyNode *head; +/* + * structure to collect key handles. + */ +typedef struct pk11CrlDataStr { PK11Slot *slot; -} keyList; + PK11SearchResults *searchHandles; + CK_ATTRIBUTE *template; + CK_ULONG templ_count; +} pk11CrlData; + static SECStatus -add_key_to_list(DBT *key, DBT *data, void *arg) +pk11_crl_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg) { - keyList *keylist; - pk11keyNode *node; - void *keydata; - SECKEYLowPrivateKey *privKey = NULL; + pk11CrlData *crlData; + CK_OBJECT_HANDLE class_handle; + PK11Slot *slot; - keylist = (keyList *)arg; + crlData = (pk11CrlData *)arg; + slot = crlData->slot; - privKey = SECKEY_DecryptKey(key, keylist->slot->password, - SECKEY_GetDefaultKeyDB()); - if ( privKey == NULL ) { - goto loser; + class_handle = (type == certDBEntryTypeRevocation) ? PK11_TOKEN_TYPE_CRL : + PK11_TOKEN_KRL_HANDLE; + if (pk11_tokenMatch(slot, key, class_handle, + crlData->template, crlData->templ_count)) { + pk11_addHandle(crlData->searchHandles, + pk11_mkHandle(slot,key,class_handle)); } + return(SECSuccess); +} - /* allocate the node struct */ - node = (pk11keyNode*)PORT_ArenaZAlloc(keylist->arena, sizeof(pk11keyNode)); - if ( node == NULL ) { - goto loser; - } - - /* allocate room for key data */ - keydata = PORT_ArenaZAlloc(keylist->arena, key->size); - if ( keydata == NULL ) { - goto loser; - } +static void +pk11_searchCrls(PK11Slot *slot, SECItem *derSubject, PRBool isKrl, + unsigned long classFlags, PK11SearchResults *search, + CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) +{ + NSSLOWCERTCertDBHandle *certHandle = NULL; - /* link node into list */ - node->next = keylist->head; - keylist->head = node; - - node->privKey = privKey; - switch (privKey->keyType) { - case lowRSAKey: - node->pubItem = &privKey->u.rsa.modulus; - break; - case lowDSAKey: - node->pubItem = &privKey->u.dsa.publicValue; - break; - default: - break; - } - - return(SECSuccess); -loser: - if ( privKey ) { - SECKEY_LowDestroyPrivateKey(privKey); + certHandle = slot->certDB; + if (certHandle == NULL) { + return; } - return(SECSuccess); + if (derSubject->data != NULL) { + SECItem *crl = + nsslowcert_FindCrlByKey(certHandle,derSubject,NULL,isKrl); + + if (crl != NULL) { + pk11_addHandle(search, pk11_mkHandle(slot,derSubject, + isKrl ? PK11_TOKEN_KRL_HANDLE : PK11_TOKEN_TYPE_CRL)); + } + } else { + pk11CrlData crlData; + + /* traverse */ + crlData.slot = slot; + crlData.searchHandles = search; + crlData.template = pTemplate; + crlData.templ_count = ulCount; + nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeRevocation, + pk11_crl_collect, (void *)&crlData); + nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeKeyRevocation, + pk11_crl_collect, (void *)&crlData); + } } /* - * If the cert is a user cert, then try to match it to a key on the - * linked list of private keys built earlier. - * If the cert matches one on the list, then save it. + * structure to collect key handles. */ +typedef struct pk11KeyDataStr { + PK11Slot *slot; + PK11SearchResults *searchHandles; + SECItem *id; + CK_ATTRIBUTE *template; + CK_ULONG templ_count; + unsigned long classFlags; + PRBool isLoggedIn; + PRBool strict; +} pk11KeyData; + + static SECStatus -add_cert_to_list(CERTCertificate *cert, SECItem *k, void *pdata) +pk11_key_collect(DBT *key, DBT *data, void *arg) { - keyList *keylist; - pk11keyNode *node; - SECKEYPublicKey *pubKey = NULL; - SECItem *pubItem; - CERTCertificate *oldcert; - - keylist = (keyList *)pdata; + pk11KeyData *keyData; + NSSLOWKEYPrivateKey *privKey = NULL; + SECItem tmpDBKey; + PK11Slot *slot; - /* only if it is a user cert and has a nickname!! */ - if ( ( ( cert->trust->sslFlags & CERTDB_USER ) || - ( cert->trust->emailFlags & CERTDB_USER ) || - ( cert->trust->objectSigningFlags & CERTDB_USER ) ) && - ( cert->nickname != NULL ) ) { - - /* get cert's public key */ - pubKey = CERT_ExtractPublicKey(cert); - if ( pubKey == NULL ) { - goto done; - } - - /* pk11_GetPubItem returns data associated with the public key. - * one only needs to free the public key. This comment is here - * because this sematic would be non-obvious otherwise. - */ - pubItem = pk11_GetPubItem(pubKey); - if (pubItem == NULL) goto done; - - node = keylist->head; - while ( node ) { - /* if key type is different, then there is no match */ - if (node->privKey->keyType == seckeyLow_KeyType(pubKey->keyType)) { - - /* compare public value from cert with public value from - * the key - */ - if ( SECITEM_CompareItem(pubItem, node->pubItem) == SECEqual ){ - /* this is a match */ - - /* if no cert has yet been found for this key, or this - * cert is newer, then save this cert - */ - if ( ( node->cert == NULL ) || - CERT_IsNewer(cert, node->cert ) ) { - - oldcert = node->cert; - - /* get a real DB copy of the cert, since the one - * passed in here is not properly recorded in the - * temp database - */ - - /* We need a better way to deal with this */ - node->cert = - CERT_FindCertByKeyNoLocking(CERT_GetDefaultCertDB(), - &cert->certKey); - - /* free the old cert if there was one */ - if ( oldcert ) { - CERT_DestroyCertificate(oldcert); - } - } - } + keyData = (pk11KeyData *)arg; + slot = keyData->slot; + + tmpDBKey.data = key->data; + tmpDBKey.len = key->size; + + PORT_Assert(slot->keyDB); + if (!keyData->strict && keyData->id) { + SECItem result; + unsigned char hashKey[SHA1_LENGTH]; + result.data = hashKey; + result.len = sizeof(hashKey); + + SHA1_HashBuf( hashKey, key->data, key->size ); + if (SECITEM_ItemsAreEqual(keyData->id,&result)) { + if (keyData->classFlags & NSC_PRIVATE) { + pk11_addHandle(keyData->searchHandles, + pk11_mkHandle(slot,&tmpDBKey,PK11_TOKEN_TYPE_PRIV)); } - - node = node->next; + if (keyData->classFlags & NSC_PUBLIC) { + pk11_addHandle(keyData->searchHandles, + pk11_mkHandle(slot,&tmpDBKey,PK11_TOKEN_TYPE_PUB)); + } + /* NSC_KEY Already handled */ } + return SECSuccess; } -done: - if ( pubKey ) { - SECKEY_DestroyPublicKey(pubKey); + + privKey = nsslowkey_FindKeyByPublicKey(keyData->slot->keyDB, &tmpDBKey, + keyData->slot->password); + if ( privKey == NULL ) { + goto loser; + } + + if (isSecretKey(privKey)) { + if ((keyData->classFlags & NSC_KEY) && + pk11_tokenMatch(keyData->slot, &tmpDBKey, PK11_TOKEN_TYPE_KEY, + keyData->template, keyData->templ_count)) { + pk11_addHandle(keyData->searchHandles, + pk11_mkHandle(keyData->slot, &tmpDBKey, PK11_TOKEN_TYPE_KEY)); + } + } else { + if ((keyData->classFlags & NSC_PRIVATE) && + pk11_tokenMatch(keyData->slot, &tmpDBKey, PK11_TOKEN_TYPE_PRIV, + keyData->template, keyData->templ_count)) { + pk11_addHandle(keyData->searchHandles, + pk11_mkHandle(keyData->slot,&tmpDBKey,PK11_TOKEN_TYPE_PRIV)); + } + if ((keyData->classFlags & NSC_PUBLIC) && + pk11_tokenMatch(keyData->slot, &tmpDBKey, PK11_TOKEN_TYPE_PUB, + keyData->template, keyData->templ_count)) { + pk11_addHandle(keyData->searchHandles, + pk11_mkHandle(keyData->slot, &tmpDBKey,PK11_TOKEN_TYPE_PUB)); + } } +loser: + if ( privKey ) { + nsslowkey_DestroyPrivateKey(privKey); + } return(SECSuccess); } -#if 0 -/* This appears to be obsolete - TNH */ -static SECItem * -decodeKeyDBGlobalSalt(DBT *saltData) +static void +pk11_searchKeys(PK11Slot *slot, SECItem *key_id, PRBool isLoggedIn, + unsigned long classFlags, PK11SearchResults *search, + CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) { - SECItem *saltitem; - - saltitem = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if ( saltitem == NULL ) { - return(NULL); + NSSLOWKEYDBHandle *keyHandle = NULL; + NSSLOWKEYPrivateKey *privKey; + pk11KeyData keyData; + + keyHandle = slot->keyDB; + if (keyHandle == NULL) { + return; } - - saltitem->data = (unsigned char *)PORT_ZAlloc(saltData->size); - if ( saltitem->data == NULL ) { - PORT_Free(saltitem); - return(NULL); + + if (key_id->data && (classFlags & NSC_KEY)) { + privKey = nsslowkey_FindKeyByPublicKey(keyHandle,key_id, slot->password); + if (privKey) { + pk11_addHandle(search,pk11_mkHandle(slot,key_id,PK11_TOKEN_TYPE_KEY)); + nsslowkey_DestroyPrivateKey(privKey); + } + if ( !(classFlags & (NSC_PRIVATE|NSC_PUBLIC)) ) { + /* skip the traverse, nothing new to find */ + return; + } } - - saltitem->len = saltData->size; - PORT_Memcpy(saltitem->data, saltData->data, saltitem->len); - - return(saltitem); + keyData.slot = slot; + keyData.searchHandles = search; + keyData.id = key_id; + keyData.template = pTemplate; + keyData.templ_count = ulCount; + keyData.isLoggedIn = isLoggedIn; + keyData.classFlags = classFlags; + keyData.strict = NSC_STRICT; + + nsslowkey_TraverseKeys(keyHandle, pk11_key_collect, &keyData); } -#endif -#if 0 /* - * Create a (fixed) DES3 key [ testing ] + * structure to collect certs into */ -static unsigned char keyValue[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 -}; - -static SECItem keyItem = { - 0, - keyValue, - sizeof keyValue -}; - -static unsigned char keyID[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; +typedef struct pk11CertDataStr { + PK11Slot *slot; + int cert_count; + int max_cert_count; + NSSLOWCERTCertificate **certs; + CK_ATTRIBUTE *template; + CK_ULONG templ_count; + unsigned long classFlags; + PRBool strict; +} pk11CertData; -static SECItem keyIDItem = { - 0, - keyID, - sizeof keyID -}; -/* +AAA */ -static CK_RV -pk11_createFixedDES3Key(PK11Slot *slot) +/* + * collect all the certs from the traverse call. + */ +static SECStatus +pk11_cert_collect(NSSLOWCERTCertificate *cert,void *arg) { - CK_RV rv = CKR_OK; - PK11Object *keyObject; - CK_BBOOL true = CK_TRUE; - CK_OBJECT_CLASS class = CKO_SECRET_KEY; - CK_KEY_TYPE keyType = CKK_DES3; + pk11CertData *cd = (pk11CertData *)arg; - /* - * Create the object - */ - keyObject = pk11_NewObject(slot); /* fill in the handle later */ - if (keyObject == NULL) { - return CKR_HOST_MEMORY; + if (cd->certs == NULL) { + return SECFailure; } - /* Add attributes to the object */ - rv = pk11_AddAttributeType(keyObject, CKA_ID, keyID, sizeof keyID); - if (rv != CKR_OK) { - pk11_FreeObject(keyObject); - return rv; + if (cd->strict) { + if ((cd->classFlags & NSC_CERT) && !pk11_tokenMatch(cd->slot, + &cert->certKey, PK11_TOKEN_TYPE_CERT, cd->template,cd->templ_count)) { + return SECSuccess; + } + if ((cd->classFlags & NSC_TRUST) && !pk11_tokenMatch(cd->slot, + &cert->certKey, PK11_TOKEN_TYPE_TRUST, + cd->template, cd->templ_count)) { + return SECSuccess; + } } - rv = pk11_AddAttributeType(keyObject, CKA_VALUE, keyValue, sizeof keyValue); - if (rv != CKR_OK) { - pk11_FreeObject(keyObject); - return rv; + /* allocate more space if we need it. This should only happen in + * the general traversal case */ + if (cd->cert_count >= cd->max_cert_count) { + int size; + cd->max_cert_count += NSC_CERT_BLOCK_SIZE; + size = cd->max_cert_count * sizeof (NSSLOWCERTCertificate *); + cd->certs = (NSSLOWCERTCertificate **)PORT_Realloc(cd->certs,size); + if (cd->certs == NULL) { + return SECFailure; + } } - rv = pk11_AddAttributeType(keyObject, CKA_TOKEN, &true, sizeof true); - if (rv != CKR_OK) { - pk11_FreeObject(keyObject); - return rv; - } + cd->certs[cd->cert_count++] = nsslowcert_DupCertificate(cert); + return SECSuccess; +} - rv = pk11_AddAttributeType(keyObject, CKA_CLASS, &class, sizeof class); - if (rv != CKR_OK) { - pk11_FreeObject(keyObject); - return rv; - } +/* provide impedence matching ... */ +static SECStatus +pk11_cert_collect2(NSSLOWCERTCertificate *cert, SECItem *dymmy, void *arg) +{ + return pk11_cert_collect(cert, arg); +} - rv = pk11_AddAttributeType(keyObject, CKA_KEY_TYPE, &keyType, sizeof keyType); - if (rv != CKR_OK) { - pk11_FreeObject(keyObject); - return rv; +static void +pk11_searchSingleCert(pk11CertData *certData,NSSLOWCERTCertificate *cert) +{ + if (cert == NULL) { + return; } + if (certData->strict && + !pk11_tokenMatch(certData->slot, &cert->certKey, PK11_TOKEN_TYPE_CERT, + certData->template,certData->templ_count)) { + nsslowcert_DestroyCertificate(cert); + return; + } + certData->certs = (NSSLOWCERTCertificate **) + PORT_Alloc(sizeof (NSSLOWCERTCertificate *)); + if (certData->certs == NULL) { + nsslowcert_DestroyCertificate(cert); + return; + } + certData->certs[0] = cert; + certData->cert_count = 1; +} - pk11_handleSecretKeyObject(keyObject, keyType, PR_TRUE); - - PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - keyObject->handle = slot->tokenIDCount++; - PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) - keyObject->slot = slot; - keyObject->objclass = CKO_SECRET_KEY; - pk11_AddSlotObject(slot, keyObject); +static void +pk11_CertSetupData(pk11CertData *certData,int count) +{ + certData->max_cert_count = count; - return rv; + if (certData->max_cert_count <= 0) { + return; + } + certData->certs = (NSSLOWCERTCertificate **) + PORT_Alloc( count * sizeof(NSSLOWCERTCertificate *)); + return; } -#endif /* Fixed DES key */ -/* - * load up our token database - */ -static CK_RV -pk11_importKeyDB(PK11Slot *slot) +static void +pk11_searchCertsAndTrust(PK11Slot *slot, SECItem *derCert, SECItem *name, + SECItem *derSubject, NSSLOWCERTIssuerAndSN *issuerSN, + unsigned long classFlags, PK11SearchResults *handles, + CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) { - keyList keylist; - pk11keyNode *node; - CK_RV crv; - SECStatus rv; - PK11Object *privateKeyObject; - PK11Object *publicKeyObject; - PK11Object *certObject; + NSSLOWCERTCertDBHandle *certHandle = NULL; + pk11CertData certData; + int i; - /* traverse the database, collecting the index keys of all - * records into a linked list - */ - keylist.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( keylist.arena == NULL ) { - return CKR_HOST_MEMORY; - } - keylist.head = NULL; - keylist.slot = slot; - - /* collect all of the keys */ - rv = SECKEY_TraverseKeys(SECKEY_GetDefaultKeyDB(), - add_key_to_list, (void *)&keylist); - if (rv != SECSuccess) { - PORT_FreeArena(keylist.arena, PR_FALSE); - return CKR_HOST_MEMORY; - } + certHandle = slot->certDB; + if (certHandle == NULL) return; - /* find certs that match any of the keys */ - crv = SEC_TraversePermCerts(CERT_GetDefaultCertDB(), - add_cert_to_list, (void *)&keylist); - if ( crv != SECSuccess ) { - PORT_FreeArena(keylist.arena, PR_FALSE); - return CKR_HOST_MEMORY; - } + certData.slot = slot; + certData.max_cert_count = 0; + certData.certs = NULL; + certData.cert_count = 0; + certData.template = pTemplate; + certData.templ_count = ulCount; + certData.classFlags = classFlags; + certData.strict = NSC_STRICT; - /* now traverse the list and entry certs/keys into the - * pkcs11 world + + /* + * Find the Cert. */ - for (node = keylist.head; node != NULL; node=node->next ) { - /* Check for "special" private key that wraps a symmetric key */ - if (isSecretKey(node->privKey)) { - importSecretKey(slot, node->privKey); - goto end_loop; - } - - /* create the private key object */ - privateKeyObject = pk11_importPrivateKey(slot, node->privKey, - node->pubItem); - if ( privateKeyObject == NULL ) { - goto end_loop; - } + if (derCert->data != NULL) { + NSSLOWCERTCertificate *cert = + nsslowcert_FindCertByDERCert(certHandle,derCert); + pk11_searchSingleCert(&certData,cert); + } else if (name->data != NULL) { + char *tmp_name = (char*)PORT_Alloc(name->len+1); + int count; - publicKeyObject = pk11_importPublicKey(slot, node->privKey, NULL, - node->pubItem); - if ( node->cert ) { - /* Now import the Cert */ - certObject = pk11_importCertificate(slot, node->cert, - node->pubItem->data, - node->pubItem->len, PR_TRUE); - - /* Copy the subject */ - if ( certObject ) { - /* NOTE: cert has been adopted */ - PK11Attribute *attribute; - - /* Copy the Subject */ - attribute = pk11_FindAttribute(certObject,CKA_SUBJECT); - if (attribute) { - pk11_forceAttribute(privateKeyObject, - pk11_attr_expand(&attribute->attrib)); - if (publicKeyObject) { - pk11_forceAttribute(publicKeyObject, - pk11_attr_expand(&attribute->attrib)); - } - pk11_FreeAttribute(attribute); - } - pk11_FreeObject(certObject); - } + if (tmp_name == NULL) { + return; } + PORT_Memcpy(tmp_name,name->data,name->len); + tmp_name[name->len] = 0; - if ( publicKeyObject != NULL ) { - pk11_AddSlotObject(slot, publicKeyObject); - } + count= nsslowcert_NumPermCertsForNickname(certHandle,tmp_name); + pk11_CertSetupData(&certData,count); + nsslowcert_TraversePermCertsForNickname(certHandle,tmp_name, + pk11_cert_collect, &certData); + PORT_Free(tmp_name); + } else if (derSubject->data != NULL) { + int count; + + count = nsslowcert_NumPermCertsForSubject(certHandle,derSubject); + pk11_CertSetupData(&certData,count); + nsslowcert_TraversePermCertsForSubject(certHandle,derSubject, + pk11_cert_collect, &certData); + } else if ((issuerSN->derIssuer.data != NULL) && + (issuerSN->serialNumber.data != NULL)) { + NSSLOWCERTCertificate *cert = + nsslowcert_FindCertByIssuerAndSN(certHandle,issuerSN); + + pk11_searchSingleCert(&certData,cert); + } else { + /* we aren't filtering the certs, we are working on all, so turn + * on the strict filters. */ + certData.strict = PR_TRUE; + pk11_CertSetupData(&certData,NSC_CERT_BLOCK_SIZE); + nsslowcert_TraversePermCerts(certHandle, pk11_cert_collect2, &certData); + } - pk11_AddSlotObject(slot, privateKeyObject); + /* + * build the handles + */ + for (i=0 ; i < certData.cert_count ; i++) { + NSSLOWCERTCertificate *cert = certData.certs[i]; -end_loop: - SECKEY_LowDestroyPrivateKey(node->privKey); - if ( node->cert ) { - CERT_DestroyCertificate(node->cert); + /* if we filtered it would have been on the stuff above */ + if (classFlags & NSC_CERT) { + pk11_addHandle(handles, + pk11_mkHandle(slot,&cert->certKey,PK11_TOKEN_TYPE_CERT)); } - + if ((classFlags & NSC_TRUST) && nsslowcert_hasTrust(cert)) { + pk11_addHandle(handles, + pk11_mkHandle(slot,&cert->certKey,PK11_TOKEN_TYPE_TRUST)); + } + nsslowcert_DestroyCertificate(cert); } - PORT_FreeArena(keylist.arena, PR_FALSE); - return CKR_OK; + if (certData.certs) PORT_Free(certData.certs); + return; } -/* - * structure to collect certs into - */ -typedef struct pk11CertDataStr { - int cert_count; - int max_cert_count; - CERTCertificate **certs; -} pk11CertData; +static void +pk11_searchSMime(PK11Slot *slot, SECItem *email, PK11SearchResults *handles, + CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) +{ + NSSLOWCERTCertDBHandle *certHandle = NULL; + certDBEntrySMime *entry; -/* - * collect all the certs from the traverse call. - */ -static SECStatus -pk11_cert_collect(CERTCertificate *cert,void *arg) { - pk11CertData *cd = (pk11CertData *)arg; + certHandle = slot->certDB; + if (certHandle == NULL) return; - /* shouldn't happen, but don't crash if it does */ - if (cd->cert_count >= cd->max_cert_count) { - PORT_Assert(0); - return SECFailure; - } + if (email->data != NULL) { + char *tmp_name = (char*)PORT_Alloc(email->len+1); - cd->certs[cd->cert_count++] = CERT_DupCertificate(cert); - return SECSuccess; + if (tmp_name == NULL) { + return; + } + PORT_Memcpy(tmp_name,email->data,email->len); + tmp_name[email->len] = 0; + + entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name); + if (entry) { + SECItem emailKey; + + emailKey.data = (unsigned char *)tmp_name; + emailKey.len = PORT_Strlen(tmp_name)+1; + pk11_addHandle(handles, + pk11_mkHandle(slot,&emailKey,PK11_TOKEN_TYPE_SMIME)); + nsslowcert_DestroyDBEntry((certDBEntry *)entry); + } + PORT_Free(tmp_name); + } + return; } -/* - * find any certs that may match the template and load them. - */ -static void -pk11_searchCerts(PK11Slot *slot, CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) { + +static CK_RV +pk11_searchTokenList(PK11Slot *slot, PK11SearchResults *search, + CK_ATTRIBUTE *pTemplate, CK_LONG ulCount, + PRBool *tokenOnly, PRBool isLoggedIn) +{ int i; + PRBool isKrl = PR_FALSE; SECItem derCert = { siBuffer, NULL, 0 }; SECItem derSubject = { siBuffer, NULL, 0 }; SECItem name = { siBuffer, NULL, 0 }; - CERTIssuerAndSN issuerSN = { + SECItem email = { siBuffer, NULL, 0 }; + SECItem key_id = { siBuffer, NULL, 0 }; + SECItem cert_sha1_hash = { siBuffer, NULL, 0 }; + SECItem cert_md5_hash = { siBuffer, NULL, 0 }; + NSSLOWCERTIssuerAndSN issuerSN = { { siBuffer, NULL, 0 }, - { NULL, NULL }, { siBuffer, NULL, 0 } }; SECItem *copy = NULL; - CERTCertDBHandle *handle = NULL; - SECKEYKeyDBHandle *keyHandle = NULL; - pk11CertData certData; + unsigned long classFlags = + NSC_CERT|NSC_TRUST|NSC_PRIVATE|NSC_PUBLIC|NSC_KEY|NSC_SMIME ; + /* if we aren't logged in, don't look for private or secret keys */ + if (!isLoggedIn) { + classFlags &= ~(NSC_PRIVATE|NSC_KEY); + } /* - * These should be stored in the slot some day in the future - */ - handle = CERT_GetDefaultCertDB(); - if (handle == NULL) return; - keyHandle = SECKEY_GetDefaultKeyDB(); - if (keyHandle == NULL) return; - - /* - * look for things to search on certs for. We only need one of these - * items. If we find all the certs that match that item, import them - * (as long as they are user certs). We'll let find objects filter out - * the ones that don't apply. + * look for things to search on token objects for. If the right options + * are specified, we can use them as direct indeces into the database + * (rather than using linear searches. We can also use the attributes to + * limit the kinds of objects we are searching for. Later we can use this + * array to filter the remaining objects more finely. */ - for (i=0 ;i < (int)ulCount; i++) { + for (i=0 ;classFlags && i < (int)ulCount; i++) { switch (pTemplate[i].type) { - case CKA_SUBJECT: copy = &derSubject; break; - case CKA_ISSUER: copy = &issuerSN.derIssuer; break; - case CKA_SERIAL_NUMBER: copy = &issuerSN.serialNumber; break; - case CKA_VALUE: copy = &derCert; break; - case CKA_LABEL: copy = &name; break; + case CKA_SUBJECT: + copy = &derSubject; + classFlags &= (NSC_CERT|NSC_PRIVATE|NSC_PUBLIC|NSC_SMIME); + break; + case CKA_ISSUER: + copy = &issuerSN.derIssuer; + classFlags &= (NSC_CERT|NSC_CRL|NSC_TRUST); + break; + case CKA_SERIAL_NUMBER: + copy = &issuerSN.serialNumber; + classFlags &= (NSC_CERT|NSC_TRUST); + break; + case CKA_VALUE: + copy = &derCert; + classFlags &= (NSC_CERT|NSC_CRL|NSC_SMIME); + break; + case CKA_LABEL: + copy = &name; + break; + case CKA_NETSCAPE_EMAIL: + copy = &email; + classFlags &= NSC_SMIME; + break; + case CKA_NETSCAPE_SMIME_TIMESTAMP: + classFlags &= NSC_SMIME; + break; case CKA_CLASS: if (pTemplate[i].ulValueLen != sizeof(CK_OBJECT_CLASS)) { - return; + classFlags = 0; + break;; } - if (*((CK_OBJECT_CLASS *)pTemplate[i].pValue) != CKO_CERTIFICATE) { - return; + switch (*((CK_OBJECT_CLASS *)pTemplate[i].pValue)) { + case CKO_CERTIFICATE: + classFlags &= NSC_CERT; + break; + case CKO_NETSCAPE_TRUST: + classFlags &= NSC_TRUST; + break; + case CKO_NETSCAPE_CRL: + classFlags &= NSC_CRL; + break; + case CKO_NETSCAPE_SMIME: + classFlags &= NSC_SMIME; + break; + case CKO_PRIVATE_KEY: + classFlags &= NSC_PRIVATE; + break; + case CKO_PUBLIC_KEY: + classFlags &= NSC_PUBLIC; + break; + case CKO_SECRET_KEY: + classFlags &= NSC_KEY; + break; + default: + classFlags = 0; + break; } - copy = NULL; break; + break; case CKA_PRIVATE: if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) { - return; + classFlags = 0; + } + if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) { + classFlags &= (NSC_PRIVATE|NSC_KEY); + } else { + classFlags &= ~(NSC_PRIVATE|NSC_KEY); + } + break; + case CKA_SENSITIVE: + if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) { + classFlags = 0; } - if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_FALSE) { - return; + if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) { + classFlags &= (NSC_PRIVATE|NSC_KEY); + } else { + classFlags = 0; } - copy = NULL; break; + break; case CKA_TOKEN: if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) { - return; + classFlags = 0; } - if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_TRUE) { - return; + if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) { + *tokenOnly = PR_TRUE; + } else { + classFlags = 0; } - copy = NULL; break; + break; + case CKA_CERT_SHA1_HASH: + classFlags &= NSC_TRUST; + copy = &cert_sha1_hash; break; + case CKA_CERT_MD5_HASH: + classFlags &= NSC_TRUST; + copy = &cert_md5_hash; break; case CKA_CERTIFICATE_TYPE: + if (pTemplate[i].ulValueLen != sizeof(CK_CERTIFICATE_TYPE)) { + classFlags = 0; + } + classFlags &= NSC_CERT; + if (*((CK_CERTIFICATE_TYPE *)pTemplate[i].pValue) != CKC_X_509) { + classFlags = 0; + } + break; case CKA_ID: + copy = &key_id; + classFlags &= (NSC_CERT|NSC_PRIVATE|NSC_KEY|NSC_PUBLIC); + break; + case CKA_NETSCAPE_KRL: + if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) { + classFlags = 0; + } + classFlags &= NSC_CRL; + isKrl = (PRBool)(*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE); + break; case CKA_MODIFIABLE: - copy = NULL; break; + break; + case CKA_KEY_TYPE: + case CKA_DERIVE: + classFlags &= NSC_PUBLIC|NSC_PRIVATE|NSC_KEY; + break; + case CKA_VERIFY_RECOVER: + classFlags &= NSC_PUBLIC; + break; + case CKA_SIGN_RECOVER: + classFlags &= NSC_PRIVATE; + break; + case CKA_ENCRYPT: + case CKA_VERIFY: + case CKA_WRAP: + classFlags &= NSC_PUBLIC|NSC_KEY; + break; + case CKA_DECRYPT: + case CKA_SIGN: + case CKA_UNWRAP: + case CKA_ALWAYS_SENSITIVE: + case CKA_EXTRACTABLE: + case CKA_NEVER_EXTRACTABLE: + classFlags &= NSC_PRIVATE|NSC_KEY; + break; /* can't be a certificate if it doesn't match one of the above * attributes */ - default: return; + default: + classFlags = 0; + break; } if (copy) { copy->data = (unsigned char*)pTemplate[i].pValue; copy->len = pTemplate[i].ulValueLen; } + copy = NULL; } - certData.max_cert_count = 0; - certData.certs = NULL; - certData.cert_count = 0; - - if (derCert.data != NULL) { - CERTCertificate *cert = CERT_FindCertByDERCert(handle,&derCert); - if (cert != NULL) { - certData.certs = - (CERTCertificate **) PORT_Alloc(sizeof (CERTCertificate *)); - if (certData.certs) { - certData.certs[0] = cert; - certData.cert_count = 1; - } else CERT_DestroyCertificate(cert); - } - } else if (name.data != NULL) { - char *tmp_name = (char*)PORT_Alloc(name.len+1); - - if (tmp_name == NULL) { - return; - } - PORT_Memcpy(tmp_name,name.data,name.len); - tmp_name[name.len] = 0; - - certData.max_cert_count=CERT_NumPermCertsForNickname(handle,tmp_name); - if (certData.max_cert_count > 0) { - certData.certs = (CERTCertificate **) - PORT_Alloc(certData.max_cert_count *sizeof(CERTCertificate *)); - if (certData.certs) { - CERT_TraversePermCertsForNickname(handle,tmp_name, - pk11_cert_collect, &certData); - } - - } - PORT_Free(tmp_name); - } else if (derSubject.data != NULL) { - certData.max_cert_count=CERT_NumPermCertsForSubject(handle,&derSubject); - if (certData.max_cert_count > 0) { - certData.certs = (CERTCertificate **) - PORT_Alloc(certData.max_cert_count *sizeof(CERTCertificate *)); - if (certData.certs) { - CERT_TraversePermCertsForSubject(handle,&derSubject, - pk11_cert_collect, &certData); - } - } - } else if ((issuerSN.derIssuer.data != NULL) && - (issuerSN.serialNumber.data != NULL)) { - CERTCertificate *cert = CERT_FindCertByIssuerAndSN(handle,&issuerSN); - - if (cert != NULL) { - certData.certs = - (CERTCertificate **) PORT_Alloc(sizeof (CERTCertificate *)); - if (certData.certs) { - certData.certs[0] = cert; - certData.cert_count = 1; - } else CERT_DestroyCertificate(cert); - } - } else { - /* PORT_Assert(0); may get called when not looking for certs */ - /* look up all the certs sometime, and get rid of the assert */; + /* certs */ + if (classFlags & (NSC_CERT|NSC_TRUST)) { + pk11_searchCertsAndTrust(slot,&derCert,&name,&derSubject, + &issuerSN,classFlags,search, + pTemplate, ulCount); } + /* keys */ + if (classFlags & (NSC_PRIVATE|NSC_PUBLIC|NSC_KEY)) { + pk11_searchKeys(slot, &key_id, isLoggedIn, classFlags, search, + pTemplate, ulCount); + } - for (i=0 ; i < certData.cert_count ; i++) { - CERTCertificate *cert = certData.certs[i]; - - /* we are only interested in permanment user certs here */ - if ((cert->isperm) && (cert->trust) && - (( cert->trust->sslFlags & CERTDB_USER ) || - ( cert->trust->emailFlags & CERTDB_USER ) || - ( cert->trust->objectSigningFlags & CERTDB_USER )) && - ( cert->nickname != NULL ) && - (SECKEY_KeyForCertExists(keyHandle, cert) == SECSuccess)) { - PK11Object *obj; - pk11_importCertificate(slot, cert, NULL, 0, PR_FALSE); - obj = pk11_importPublicKey(slot, NULL, cert, NULL); - if (obj) pk11_AddSlotObject(slot, obj); - } - CERT_DestroyCertificate(cert); + /* crl's */ + if (classFlags & NSC_CRL) { + pk11_searchCrls(slot, &derSubject, isKrl, classFlags, search, + pTemplate, ulCount); + } + /* Add S/MIME entry stuff */ + if (classFlags & NSC_SMIME) { + pk11_searchSMime(slot, &email, search, pTemplate, ulCount); } - if (certData.certs) PORT_Free(certData.certs); - return; + return CKR_OK; } @@ -4067,74 +3719,50 @@ pk11_searchCerts(PK11Slot *slot, CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) { CK_RV NSC_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount) { - PK11ObjectListElement *objectList = NULL; - PK11ObjectListElement *olp; PK11SearchResults *search,*freeSearch; - PK11Session *session; + PK11Session *session = NULL; PK11Slot *slot = pk11_SlotFromSessionHandle(hSession); - int count, i; - CK_RV crv; + PRBool tokenOnly = PR_FALSE; + CK_RV crv = CKR_OK; + PRBool isLoggedIn; session = pk11_SessionFromHandle(hSession); if (session == NULL) { - return CKR_SESSION_HANDLE_INVALID; - } - - /* resync token objects with the data base */ - if ((session->info.slotID == PRIVATE_KEY_SLOT_ID) || - (session->info.slotID == FIPS_SLOT_ID)) { - if (slot->DB_loaded == PR_FALSE) { - /* if we aren't logged in, we can't unload all key keys - * and certs. Just unload those certs we need for this search - */ - if ((!slot->isLoggedIn) && (slot->needLogin)) { - pk11_searchCerts(slot,pTemplate,ulCount); - } else { - pk11_importKeyDB(slot); - slot->DB_loaded = PR_TRUE; - } - } - } - - - /* build list of found objects in the session */ - crv = pk11_searchObjectList(&objectList,slot->tokObjects, - slot->objectLock, pTemplate, ulCount, (PRBool)((!slot->needLogin) || - slot->isLoggedIn)); - if (crv != CKR_OK) { - pk11_FreeObjectList(objectList); - pk11_FreeSession(session); - return crv; - } - - - /* copy list to session */ - count = 0; - for (olp = objectList; olp != NULL; olp = olp->next) { - count++; + crv = CKR_SESSION_HANDLE_INVALID; + goto loser; } + search = (PK11SearchResults *)PORT_Alloc(sizeof(PK11SearchResults)); if (search == NULL) { - pk11_FreeObjectList(objectList); - pk11_FreeSession(session); - return CKR_HOST_MEMORY; + crv = CKR_HOST_MEMORY; + goto loser; } search->handles = (CK_OBJECT_HANDLE *) - PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * count); + PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * NSC_SEARCH_BLOCK_SIZE); if (search->handles == NULL) { - PORT_Free(search); - pk11_FreeObjectList(objectList); - pk11_FreeSession(session); - return CKR_HOST_MEMORY; + crv = CKR_HOST_MEMORY; + goto loser; } - for (i=0; i < count; i++) { - search->handles[i] = objectList->object->handle; - objectList = pk11_FreeObjectListElement(objectList); + search->index = 0; + search->size = 0; + search->array_size = NSC_SEARCH_BLOCK_SIZE; + isLoggedIn = (PRBool)((!slot->needLogin) || slot->isLoggedIn); + + crv = pk11_searchTokenList(slot, search, pTemplate, ulCount, &tokenOnly, + isLoggedIn); + if (crv != CKR_OK) { + goto loser; + } + + /* build list of found objects in the session */ + if (!tokenOnly) { + crv = pk11_searchObjectList(search, slot->tokObjects, + slot->objectLock, pTemplate, ulCount, isLoggedIn); + } + if (crv != CKR_OK) { + goto loser; } - /* store the search info */ - search->index = 0; - search->size = count; if ((freeSearch = session->search) != NULL) { session->search = NULL; pk11_FreeSearch(freeSearch); @@ -4142,6 +3770,15 @@ CK_RV NSC_FindObjectsInit(CK_SESSION_HANDLE hSession, session->search = search; pk11_FreeSession(session); return CKR_OK; + +loser: + if (freeSearch) { + pk11_FreeSearch(freeSearch); + } + if (session) { + pk11_FreeSession(session); + } + return crv; } @@ -4166,8 +3803,13 @@ CK_RV NSC_FindObjects(CK_SESSION_HANDLE hSession, search = session->search; left = session->search->size - session->search->index; transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount; - PORT_Memcpy(phObject,&search->handles[search->index], - transfer*sizeof(CK_OBJECT_HANDLE_PTR)); + if (transfer > 0) { + PORT_Memcpy(phObject,&search->handles[search->index], + transfer*sizeof(CK_OBJECT_HANDLE_PTR)); + } else { + *phObject = CK_INVALID_HANDLE; + } + search->index += transfer; if (search->index == search->size) { session->search = NULL; diff --git a/security/nss/lib/softoken/pkcs11.h b/security/nss/lib/softoken/pkcs11.h index 9ada2625e..9b54421e7 100644 --- a/security/nss/lib/softoken/pkcs11.h +++ b/security/nss/lib/softoken/pkcs11.h @@ -16,7 +16,7 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): RSA Labs * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -35,6 +35,9 @@ * is granted provided that it is identified as "RSA Security In.c Public-Key * Cryptography Standards (PKCS)" in all material mentioning or referencing * this document. + * + * The latest version of this header can be found at: + * http://www.rsalabs.com/pkcs/pkcs-11/index.html */ #ifndef _PKCS11_H_ #define _PKCS11_H_ 1 @@ -313,12 +316,4 @@ struct CK_FUNCTION_LIST { } #endif -/* -** Functions called directly by applications to configure the FIPS token. -*/ -extern void PK11_ConfigurePKCS11(char *man, char *libdes, char *tokdes, - char *ptokdes, char *slotdes, char *pslotdes, char *fslotdes, - char *fpslotdes, int minPwd, int pwdRequired); -extern void PK11_ConfigureFIPS(char *slotdes, char *pslotdes); - #endif diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c index 32eef81ca..cde08a599 100644 --- a/security/nss/lib/softoken/pkcs11c.c +++ b/security/nss/lib/softoken/pkcs11c.c @@ -53,20 +53,20 @@ #include "blapi.h" #include "pkcs11.h" #include "pkcs11i.h" -#include "keylow.h" -#include "cert.h" +#include "lowkeyi.h" +#include "pcert.h" #include "sechash.h" #include "secder.h" #include "secdig.h" -#include "secpkcs5.h" /* We do PBE below */ +#include "lowpbe.h" /* We do PBE below */ #include "pkcs11t.h" #include "secoid.h" #include "alghmac.h" #include "softoken.h" #include "secasn1.h" -#include "secmodi.h" +/*#include "secmodi.h" */ -#include "certdb.h" +#include "pcert.h" #include "ssl3prot.h" /* for SSL3_RANDOM_LENGTH */ #define __PASTE(x,y) x##y @@ -102,9 +102,9 @@ static void pk11_Null(void *data, PRBool freeit) * other free routines to the destroy signature. */ static void -pk11_FreePrivKey(SECKEYLowPrivateKey *key, PRBool freeit) +pk11_FreePrivKey(NSSLOWKEYPrivateKey *key, PRBool freeit) { - SECKEY_LowDestroyPrivateKey(key); + nsslowkey_DestroyPrivateKey(key); } static void @@ -119,11 +119,6 @@ pk11_Space(void *data, PRBool freeit) PORT_Free(data); } -static void pk11_FreeSignInfo(PK11HashSignInfo *data, PRBool freeit) -{ - SECKEY_LowDestroyPrivateKey(data->key); - PORT_Free(data); -} /* * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by @@ -176,9 +171,9 @@ pk11_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey) static CK_RV -pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, +pk11_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE etype, - PK11ContextType contextType); + PK11ContextType contextType, PRBool isEncrypt); /* * Calculate a Lynx checksum for CKM_LYNX_WRAP mechanism. */ @@ -206,7 +201,8 @@ pk11_calcLynxChecksum(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hWrapKey, /* encrypt with key 1 */ - crv = pk11_EncryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT); + crv = pk11_CryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT, + PR_TRUE); if (crv != CKR_OK) return crv; crv = NSC_Encrypt(hSession,key,len,E,&Elen); @@ -215,7 +211,8 @@ pk11_calcLynxChecksum(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hWrapKey, E[8] = (sum2 >> 8) & 0xff; E[9] = sum2 & 0xff; - crv = pk11_EncryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT); + crv = pk11_CryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT, + PR_TRUE); if (crv != CKR_OK) return crv; crv = NSC_Encrypt(hSession,&E[2],len,C,&Clen); @@ -422,18 +419,19 @@ pk11_InitGeneric(PK11Session *session,PK11SessionContext **contextPtr, context->hashInfo = NULL; context->doPad = PR_FALSE; context->padDataLength = 0; + context->key = key; *contextPtr = context; return CKR_OK; } -/* NSC_EncryptInit initializes an encryption operation. */ +/* NSC_CryptInit initializes an encryption/Decryption operation. */ /* This function is used by NSC_EncryptInit and NSC_WrapKey. The only difference * in their uses if whether or not etype is CKA_ENCRYPT or CKA_WRAP */ static CK_RV -pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, +pk11_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE etype, - PK11ContextType contextType) + PK11ContextType contextType, PRBool isEncrypt) { PK11Session *session; PK11Object *key; @@ -446,7 +444,6 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, #endif CK_KEY_TYPE key_type; CK_RV crv = CKR_OK; - SECKEYLowPublicKey *pubKey; unsigned effectiveKeyLength; unsigned char newdeskey[8]; PRBool useNewKey=PR_FALSE; @@ -456,7 +453,7 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, if (session == NULL) return CKR_SESSION_HANDLE_INVALID; crv = pk11_InitGeneric(session,&context,contextType,&key,hKey,&key_type, - CKO_PUBLIC_KEY, etype); + isEncrypt ?CKO_PUBLIC_KEY:CKO_PRIVATE_KEY, etype); if (crv != CKR_OK) { pk11_FreeSession(session); @@ -472,14 +469,22 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, break; } context->multi = PR_FALSE; - pubKey = pk11_GetPubKey(key,CKK_RSA); - if (pubKey == NULL) { + context->cipherInfo = isEncrypt ? + (void *)pk11_GetPubKey(key,CKK_RSA) : + (void *)pk11_GetPrivKey(key,CKK_RSA); + if (context->cipherInfo == NULL) { crv = CKR_HOST_MEMORY; break; } - context->cipherInfo = pubKey; - context->update = (PK11Cipher) (pMechanism->mechanism == CKM_RSA_X_509 - ? RSA_EncryptRaw : RSA_EncryptBlock); + if (isEncrypt) { + context->update = (PK11Cipher) + (pMechanism->mechanism == CKM_RSA_X_509 + ? RSA_EncryptRaw : RSA_EncryptBlock); + } else { + context->update = (PK11Cipher) + (pMechanism->mechanism == CKM_RSA_X_509 + ? RSA_DecryptRaw : RSA_DecryptBlock); + } context->destroy = pk11_Null; break; case CKM_RC2_CBC_PAD: @@ -509,7 +514,7 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, crv = CKR_HOST_MEMORY; break; } - context->update = (PK11Cipher) RC2_Encrypt; + context->update = (PK11Cipher) (isEncrypt ? RC2_Encrypt : RC2_Decrypt); context->destroy = (PK11Destroy) RC2_DestroyContext; break; #if NSS_SOFTOKEN_DOES_RC5 @@ -541,7 +546,7 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, crv = CKR_HOST_MEMORY; break; } - context->update = (PK11Cipher) RC5_Encrypt; + context->update = (PK11Cipher) (isEncrypt ? RC5_Encrypt : RC5_Decrypt); context->destroy = (PK11Destroy) RC5_DestroyContext; break; #endif @@ -563,7 +568,7 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, crv = CKR_HOST_MEMORY; /* WRONG !!! */ break; } - context->update = (PK11Cipher) RC4_Encrypt; + context->update = (PK11Cipher) (isEncrypt ? RC4_Encrypt : RC4_Decrypt); context->destroy = (PK11Destroy) RC4_DestroyContext; break; case CKM_CDMF_CBC_PAD: @@ -630,13 +635,13 @@ finish_des: } context->cipherInfo = DES_CreateContext( useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue, - (unsigned char*)pMechanism->pParameter,t, PR_TRUE); + (unsigned char*)pMechanism->pParameter,t, isEncrypt); pk11_FreeAttribute(att); if (context->cipherInfo == NULL) { crv = CKR_HOST_MEMORY; break; } - context->update = (PK11Cipher) DES_Encrypt; + context->update = (PK11Cipher) (isEncrypt ? DES_Encrypt : DES_Decrypt); context->destroy = (PK11Destroy) DES_DestroyContext; break; @@ -659,13 +664,13 @@ finish_des: (unsigned char*)att->attrib.pValue, (unsigned char*)pMechanism->pParameter, pMechanism->mechanism == CKM_AES_ECB ? NSS_AES : NSS_AES_CBC, - PR_TRUE, att->attrib.ulValueLen, 16); + isEncrypt, att->attrib.ulValueLen, 16); pk11_FreeAttribute(att); if (context->cipherInfo == NULL) { crv = CKR_HOST_MEMORY; break; } - context->update = (PK11Cipher) AES_Encrypt; + context->update = (PK11Cipher) (isEncrypt ? AES_Encrypt : AES_Decrypt); context->destroy = (PK11Destroy) AES_DestroyContext; break; @@ -674,7 +679,6 @@ finish_des: break; } - pk11_FreeObject(key); if (crv != CKR_OK) { pk11_FreeContext(context); pk11_FreeSession(session); @@ -689,8 +693,8 @@ finish_des: CK_RV NSC_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { - return pk11_EncryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, - PK11_ENCRYPT); + return pk11_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, + PK11_ENCRYPT, PR_TRUE); } /* NSC_EncryptUpdate continues a multiple-part encryption operation. */ @@ -846,258 +850,11 @@ CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, */ /* NSC_DecryptInit initializes a decryption operation. */ -static CK_RV pk11_DecryptInit( CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE dtype, - PK11ContextType contextType) -{ - PK11Session *session; - PK11Object *key; - PK11Attribute *att; - PK11SessionContext *context; - CK_RC2_CBC_PARAMS *rc2_param; -#if NSS_SOFTOKEN_DOES_RC5 - CK_RC5_CBC_PARAMS *rc5_param; - SECItem rc5Key; -#endif - CK_KEY_TYPE key_type; - CK_RV crv = CKR_OK; - unsigned effectiveKeyLength; - SECKEYLowPrivateKey *privKey; - unsigned char newdeskey[8]; - PRBool useNewKey=PR_FALSE; - int t; - - session = pk11_SessionFromHandle(hSession); - if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - - crv = pk11_InitGeneric(session,&context,contextType,&key,hKey,&key_type, - CKO_PRIVATE_KEY,dtype); - if (crv != CKR_OK) { - pk11_FreeSession(session); - return crv; - } - - /* - * now handle each mechanism - */ - switch(pMechanism->mechanism) { - case CKM_RSA_PKCS: - case CKM_RSA_X_509: - if (key_type != CKK_RSA) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - context->multi = PR_FALSE; - privKey = pk11_GetPrivKey(key,CKK_RSA); - if (privKey == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->cipherInfo = privKey; - context->update = (PK11Cipher) (pMechanism->mechanism == CKM_RSA_X_509 - ? RSA_DecryptRaw : RSA_DecryptBlock); - context->destroy = (context->cipherInfo == key->objectInfo) ? - (PK11Destroy) pk11_Null : (PK11Destroy) pk11_FreePrivKey; - break; - case CKM_RC2_CBC_PAD: - context->doPad = PR_TRUE; - context->blockSize = 8; - /* fall thru */ - case CKM_RC2_ECB: - case CKM_RC2_CBC: - if (key_type != CKK_RC2) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = pk11_FindAttribute(key,CKA_VALUE); - rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter; - effectiveKeyLength = (rc2_param->ulEffectiveBits+7)/8; - context->cipherInfo = RC2_CreateContext((unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen, rc2_param->iv, - pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : - NSS_RC2_CBC, effectiveKeyLength); - pk11_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (PK11Cipher) RC2_Decrypt; - context->destroy = (PK11Destroy) RC2_DestroyContext; - break; -#if NSS_SOFTOKEN_DOES_RC5 - case CKM_RC5_CBC_PAD: - context->doPad = PR_TRUE; - /* fall thru */ - case CKM_RC5_ECB: - case CKM_RC5_CBC: - if (key_type != CKK_RC5) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = pk11_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter; - if (context->doPad) { - context->blockSize = rc5_param->ulWordsize*2; - } - rc5Key.data = (unsigned char*)att->attrib.pValue; - rc5Key.len = att->attrib.ulValueLen; - context->cipherInfo = RC5_CreateContext(&rc5Key,rc5_param->ulRounds, - rc5_param->ulWordsize,rc5_param->pIv, - pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC); - pk11_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (PK11Cipher) RC5_Decrypt; - context->destroy = (PK11Destroy) RC5_DestroyContext; - break; -#endif - case CKM_RC4: - if (key_type != CKK_RC4) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = pk11_FindAttribute(key,CKA_VALUE); - context->cipherInfo = - RC4_CreateContext((unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - pk11_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (PK11Cipher) RC4_Decrypt; - context->destroy = (PK11Destroy) RC4_DestroyContext; - break; - case CKM_CDMF_CBC_PAD: - context->doPad = PR_TRUE; - context->blockSize = 8; - /* fall thru */ - case CKM_CDMF_ECB: - case CKM_CDMF_CBC: - if (key_type != CKK_CDMF) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC; - useNewKey = PR_TRUE; - if (crv != CKR_OK) break; - goto finish_des; - case CKM_DES_ECB: - if (key_type != CKK_DES) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = NSS_DES; - goto finish_des; - case CKM_DES_CBC_PAD: - context->doPad = PR_TRUE; - context->blockSize = 8; - /* fall thru */ - case CKM_DES_CBC: - if (key_type != CKK_DES) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = NSS_DES_CBC; - goto finish_des; - case CKM_DES3_ECB: - if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = NSS_DES_EDE3; - goto finish_des; - case CKM_DES3_CBC_PAD: - context->doPad = PR_TRUE; - context->blockSize = 8; - /* fall thru */ - case CKM_DES3_CBC: - if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = NSS_DES_EDE3_CBC; -finish_des: - att = pk11_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - if (useNewKey) { - crv = pk11_cdmf2des((unsigned char*)att->attrib.pValue,newdeskey); - if (crv != CKR_OK) { - pk11_FreeAttribute(att); - break; - } - } - context->cipherInfo = DES_CreateContext( - useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue, - (unsigned char*)pMechanism->pParameter,t, PR_FALSE); - pk11_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (PK11Cipher) DES_Decrypt; - context->destroy = (PK11Destroy) DES_DestroyContext; - - break; - case CKM_AES_CBC_PAD: - context->doPad = PR_TRUE; - context->blockSize = 16; - /* fall thru */ - case CKM_AES_ECB: - case CKM_AES_CBC: - if (key_type != CKK_AES) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = pk11_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - context->cipherInfo = AES_CreateContext( - (unsigned char*)att->attrib.pValue, - (unsigned char*)pMechanism->pParameter, - pMechanism->mechanism == CKM_AES_ECB ? NSS_AES : NSS_AES_CBC, - PR_FALSE, att->attrib.ulValueLen,16); - pk11_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (PK11Cipher) AES_Decrypt; - context->destroy = (PK11Destroy) AES_DestroyContext; - - break; - default: - crv = CKR_MECHANISM_INVALID; - break; - } - - pk11_FreeObject(key); - if (crv != CKR_OK) { - pk11_FreeContext(context); - pk11_FreeSession(session); - return crv; - } - pk11_SetContextByType(session, contextType, context); - pk11_FreeSession(session); - return CKR_OK; -} - -/* NSC_DecryptInit initializes a decryption operation. */ CK_RV NSC_DecryptInit( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { - return pk11_DecryptInit(hSession,pMechanism,hKey,CKA_DECRYPT,PK11_DECRYPT); + return pk11_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, + PK11_DECRYPT, PR_FALSE); } /* NSC_DecryptUpdate continues a multiple-part decryption operation. */ @@ -1448,17 +1205,19 @@ pk11_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen, * common HMAC initalization routine */ static CK_RV -pk11_doHMACInit(PK11SessionContext *context,SECOidTag oid, +pk11_doHMACInit(PK11SessionContext *context,HASH_HashType hash, PK11Object *key, CK_ULONG mac_size) { PK11Attribute *keyval; HMACContext *HMACcontext; CK_ULONG *intpointer; + const SECHashObject *hashObj = &SECRawHashObjects[hash]; keyval = pk11_FindAttribute(key,CKA_VALUE); if (keyval == NULL) return CKR_KEY_SIZE_RANGE; - HMACcontext = HMAC_Create(oid, (const unsigned char*)keyval->attrib.pValue, + HMACcontext = HMAC_Create(hashObj, + (const unsigned char*)keyval->attrib.pValue, keyval->attrib.ulValueLen); context->hashInfo = HMACcontext; context->multi = PR_TRUE; @@ -1865,8 +1624,8 @@ pk11_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, return CKR_FUNCTION_NOT_SUPPORTED; } - crv = pk11_EncryptInit(hSession, &cbc_mechanism, hKey, keyUsage, - contextType); + crv = pk11_CryptInit(hSession, &cbc_mechanism, hKey, keyUsage, + contextType, PR_TRUE); if (crv != CKR_OK) return crv; crv = pk11_GetContext(hSession,&context,contextType,PR_TRUE,NULL); @@ -1926,7 +1685,7 @@ nsc_DSA_Verify_Stub(void *ctx, void *sigBuf, unsigned int sigLen, void *dataBuf, unsigned int dataLen) { SECItem signature, digest; - SECKEYLowPublicKey *key = (SECKEYLowPublicKey *)ctx; + NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx; signature.data = (unsigned char *)sigBuf; signature.len = sigLen; @@ -1942,7 +1701,7 @@ nsc_DSA_Sign_Stub(void *ctx, void *sigBuf, { SECItem signature = { 0 }, digest; SECStatus rv; - SECKEYLowPrivateKey *key = (SECKEYLowPrivateKey *)ctx; + NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx; (void)SECITEM_AllocItem(NULL, &signature, maxSigLen); digest.data = (unsigned char *)dataBuf; @@ -1984,7 +1743,7 @@ CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession, PK11SessionContext *context; CK_KEY_TYPE key_type; CK_RV crv = CKR_OK; - SECKEYLowPrivateKey *privKey; + NSSLOWKEYPrivateKey *privKey; PK11HashSignInfo *info = NULL; /* Block Cipher MACing Algorithms use a different Context init method..*/ @@ -2061,23 +1820,14 @@ finish_rsa: /* OK, info is allocated only if we're doing hash and sign mechanism. * It's necessary to be able to set the correct OID in the final * signature. - * Second, what's special about privKey == key->objectInfo? - * Well we don't 'cache' token versions - * of private keys because (1) it's sensitive data, and (2) it never - * gets destroyed. Instead we grab the key out of the database as - * necessary, but now the key is our context, and we need to free - * it when we are done. Non-token private keys will get freed when - * the user destroys the session object (or the session the session - * object lives in) */ + */ if (info) { info->key = privKey; context->cipherInfo = info; - context->destroy = (privKey == key->objectInfo) ? - (PK11Destroy)pk11_Space:(PK11Destroy)pk11_FreeSignInfo; + context->destroy = (PK11Destroy)pk11_Space; } else { context->cipherInfo = privKey; - context->destroy = (privKey == key->objectInfo) ? - (PK11Destroy)pk11_Null:(PK11Destroy)pk11_FreePrivKey; + context->destroy = (PK11Destroy)pk11_Null; } break; @@ -2103,25 +1853,25 @@ finish_rsa: break; case CKM_MD2_HMAC_GENERAL: - crv = pk11_doHMACInit(context,SEC_OID_MD2,key, + crv = pk11_doHMACInit(context,HASH_AlgMD2,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_MD2_HMAC: - crv = pk11_doHMACInit(context,SEC_OID_MD2,key,MD2_LENGTH); + crv = pk11_doHMACInit(context,HASH_AlgMD2,key,MD2_LENGTH); break; case CKM_MD5_HMAC_GENERAL: - crv = pk11_doHMACInit(context,SEC_OID_MD5,key, + crv = pk11_doHMACInit(context,HASH_AlgMD5,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_MD5_HMAC: - crv = pk11_doHMACInit(context,SEC_OID_MD5,key,MD5_LENGTH); + crv = pk11_doHMACInit(context,HASH_AlgMD5,key,MD5_LENGTH); break; case CKM_SHA_1_HMAC_GENERAL: - crv = pk11_doHMACInit(context,SEC_OID_SHA1,key, + crv = pk11_doHMACInit(context,HASH_AlgSHA1,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_SHA_1_HMAC: - crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,SHA1_LENGTH); + crv = pk11_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH); break; case CKM_SSL3_MD5_MAC: crv = pk11_doSSLMACInit(context,SEC_OID_MD5,key, @@ -2139,9 +1889,8 @@ finish_rsa: break; } - pk11_FreeObject(key); if (crv != CKR_OK) { - PORT_Free(context); + pk11_FreeContext(context); pk11_FreeSession(session); return crv; } @@ -2363,7 +2112,7 @@ pk11_hashCheckSign(PK11HashVerifyInfo *info, unsigned char *sig, if (info->key == NULL) goto loser; - it.len = SECKEY_LowPublicModulusLen(info->key); + it.len = nsslowkey_PublicModulusLen(info->key); if (!it.len) goto loser; it.data = (unsigned char *) PORT_Alloc(it.len); @@ -2407,7 +2156,7 @@ CK_RV NSC_VerifyInit(CK_SESSION_HANDLE hSession, PK11SessionContext *context; CK_KEY_TYPE key_type; CK_RV crv = CKR_OK; - SECKEYLowPublicKey *pubKey; + NSSLOWKEYPublicKey *pubKey; PK11HashVerifyInfo *info = NULL; /* Block Cipher MACing Algorithms use a different Context init method..*/ @@ -2508,25 +2257,25 @@ finish_rsa: break; case CKM_MD2_HMAC_GENERAL: - crv = pk11_doHMACInit(context,SEC_OID_MD2,key, + crv = pk11_doHMACInit(context,HASH_AlgMD2,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_MD2_HMAC: - crv = pk11_doHMACInit(context,SEC_OID_MD2,key,MD2_LENGTH); + crv = pk11_doHMACInit(context,HASH_AlgMD2,key,MD2_LENGTH); break; case CKM_MD5_HMAC_GENERAL: - crv = pk11_doHMACInit(context,SEC_OID_MD5,key, + crv = pk11_doHMACInit(context,HASH_AlgMD5,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_MD5_HMAC: - crv = pk11_doHMACInit(context,SEC_OID_MD5,key,MD5_LENGTH); + crv = pk11_doHMACInit(context,HASH_AlgMD5,key,MD5_LENGTH); break; case CKM_SHA_1_HMAC_GENERAL: - crv = pk11_doHMACInit(context,SEC_OID_SHA1,key, + crv = pk11_doHMACInit(context,HASH_AlgSHA1,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_SHA_1_HMAC: - crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,SHA1_LENGTH); + crv = pk11_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH); break; case CKM_SSL3_MD5_MAC: crv = pk11_doSSLMACInit(context,SEC_OID_MD5,key, @@ -2544,7 +2293,6 @@ finish_rsa: break; } - pk11_FreeObject(key); if (crv != CKR_OK) { PORT_Free(context); pk11_FreeSession(session); @@ -2650,7 +2398,7 @@ CK_RV NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, PK11SessionContext *context; CK_KEY_TYPE key_type; CK_RV crv = CKR_OK; - SECKEYLowPublicKey *pubKey; + NSSLOWKEYPublicKey *pubKey; session = pk11_SessionFromHandle(hSession); if (session == NULL) return CKR_SESSION_HANDLE_INVALID; @@ -2686,7 +2434,6 @@ CK_RV NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, break; } - pk11_FreeObject(key); if (crv != CKR_OK) { PORT_Free(context); pk11_FreeSession(session); @@ -2755,105 +2502,50 @@ CK_RV NSC_GenerateRandom(CK_SESSION_HANDLE hSession, **************************** Key Functions: ************************ */ -CK_RV -pk11_pbe_hmac_key_gen(CK_MECHANISM_PTR pMechanism, char *buf, - unsigned long *len, PRBool faultyPBE3DES) -{ - PBEBitGenContext *pbeCx; - SECItem pwd, salt, *key; - SECOidTag hashAlg; - unsigned long keylenbits; - CK_PBE_PARAMS *pbe_params = NULL; - pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; - pwd.data = (unsigned char *)pbe_params->pPassword; - pwd.len = (unsigned int)pbe_params->ulPasswordLen; - salt.data = (unsigned char *)pbe_params->pSalt; - salt.len = (unsigned int)pbe_params->ulSaltLen; - switch (pMechanism->mechanism) { - case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: - hashAlg = SEC_OID_SHA1; keylenbits = 160; break; - case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: - hashAlg = SEC_OID_MD5; keylenbits = 128; break; - case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: - hashAlg = SEC_OID_MD2; keylenbits = 128; break; - default: - return CKR_MECHANISM_INVALID; - } - pbeCx = PBE_CreateContext(hashAlg, pbeBitGenIntegrityKey, &pwd, - &salt, keylenbits, pbe_params->ulIteration); - key = PBE_GenerateBits(pbeCx); - PORT_Memcpy(buf, key->data, key->len); - *len = key->len; - PBE_DestroyContext(pbeCx); - SECITEM_ZfreeItem(key, PR_TRUE); - return CKR_OK; -} /* * generate a password based encryption key. This code uses - * PKCS5 to do the work. Note that it calls PBE_PK11ParamToAlgid, which is - * a utility function in secpkcs5.c. This function is used in here - * and in PK11_ParamToAlgid. + * PKCS5 to do the work. */ -CK_RV -pk11_pbe_key_gen(SECOidTag algtag,CK_MECHANISM_PTR pMechanism, - char *buf,CK_ULONG *key_length, PRBool faulty3DES) +static CK_RV +nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism, + char *buf, CK_ULONG *key_length, PRBool faulty3DES) { - SECAlgorithmID algid; - SECItem *pbe_key = NULL, mech; + SECItem *pbe_key = NULL, iv, pwitem; CK_PBE_PARAMS *pbe_params = NULL; - SECStatus pbe_rv; *key_length = 0; + iv.data = NULL; iv.len = 0; - mech.data = (unsigned char *)pMechanism->pParameter; - mech.len = (unsigned int)pMechanism->ulParameterLen; - - /* A common routine to map from Params to AlgIDs for PBE - * algorithms was created in secpkcs5.c. This function is - * called both by PK11_ParamToAlgid and this function. - */ - pbe_rv = PBE_PK11ParamToAlgid(algtag, &mech, NULL, &algid); - if (pbe_rv != SECSuccess) { - return CKR_DATA_INVALID; - } pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; - mech.data = (unsigned char *)pbe_params->pPassword; - mech.len = (unsigned int)pbe_params->ulPasswordLen; - pbe_key = SEC_PKCS5GetKey(&algid, &mech, faulty3DES); + + pwitem.data = (unsigned char *)pbe_params->pPassword; + pwitem.len = (unsigned int)pbe_params->ulPasswordLen; + pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES); if (pbe_key == NULL) { - SECOID_DestroyAlgorithmID(&algid, PR_FALSE); return CKR_HOST_MEMORY; } + PORT_Memcpy(buf, pbe_key->data, pbe_key->len); *key_length = pbe_key->len; SECITEM_ZfreeItem(pbe_key, PR_TRUE); pbe_key = NULL; - if (pbe_params->pInitVector == NULL) { - pbe_key = SEC_PKCS5GetIV(&algid, &mech, faulty3DES); - if (pbe_key == NULL) { - SECOID_DestroyAlgorithmID(&algid, PR_FALSE); - SECITEM_ZfreeItem(pbe_key, PR_TRUE); - return CKR_HOST_MEMORY; - } + if (iv.data && pbe_params->pInitVector == NULL) { pbe_params->pInitVector = (CK_CHAR_PTR)PORT_ZAlloc(pbe_key->len); if (pbe_params->pInitVector == NULL) { - SECOID_DestroyAlgorithmID(&algid, PR_FALSE); - SECITEM_ZfreeItem(pbe_key, PR_TRUE); return CKR_HOST_MEMORY; } - PORT_Memcpy(pbe_params->pInitVector, pbe_key->data, pbe_key->len); + PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len); } - SECITEM_ZfreeItem(pbe_key, PR_TRUE); - SECOID_DestroyAlgorithmID(&algid, PR_FALSE); return CKR_OK; } static CK_RV -nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, - CK_KEY_TYPE *key_type,CK_ULONG *key_length) { +nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type, + CK_ULONG *key_length) +{ CK_RV crv = CKR_OK; switch (mechanism) { @@ -2904,81 +2596,111 @@ nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, return crv; } +CK_RV +nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe) +{ + SECItem salt; + CK_PBE_PARAMS *pbe_params = NULL; + NSSPKCS5PBEParameter *params; + PRArenaPool *arena = NULL; + SECStatus rv; + + *pbe = NULL; + + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); + if (arena == NULL) { + return CKR_HOST_MEMORY; + } + + params = (NSSPKCS5PBEParameter *) PORT_ArenaZAlloc(arena, + sizeof(NSSPKCS5PBEParameter)); + if (params == NULL) { + PORT_FreeArena(arena,PR_TRUE); + return CKR_HOST_MEMORY; + } + + params->ivLen = 0; + params->pbeType = NSSPKCS5_PKCS12_V2; + params->hashType = HASH_AlgSHA1; + params->encAlg = SEC_OID_SHA1; /* any invalid value */ + params->is2KeyDES = PR_FALSE; + params->keyID = pbeBitGenIntegrityKey; + params->iter = pbe_params->ulIteration; + + pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; + salt.data = (unsigned char *)pbe_params->pSalt; + salt.len = (unsigned int)pbe_params->ulSaltLen; + rv = SECITEM_CopyItem(arena,¶ms->salt,&salt); + if (rv != SECSuccess) { + PORT_FreeArena(arena,PR_TRUE); + return CKR_HOST_MEMORY; + } + switch (pMechanism->mechanism) { + case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: + case CKM_PBA_SHA1_WITH_SHA1_HMAC: + params->hashType = HASH_AlgSHA1; + params->keyLen = 20; + break; + case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: + params->hashType = HASH_AlgMD5; + params->keyLen = 16; + break; + case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: + params->hashType = HASH_AlgMD2; + params->keyLen = 16; + break; + default: + PORT_FreeArena(arena,PR_TRUE); + return CKR_MECHANISM_INVALID; + } + *pbe = params; + return CKR_OK; +} +/* maybe this should be table driven? */ static CK_RV -nsc_SetupPBEKeyGen(CK_MECHANISM_TYPE mechanism,SECOidTag *algtag, - CK_KEY_TYPE *key_type,CK_ULONG *key_length) { +nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe, + CK_KEY_TYPE *key_type) +{ CK_RV crv = CKR_OK; + SECOidData *oid; + CK_PBE_PARAMS *pbe_params; + NSSPKCS5PBEParameter *params; + SECItem salt; - switch (mechanism) { - case CKM_PBE_MD2_DES_CBC: - *algtag = SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC; + oid = SECOID_FindOIDByMechanism(pMechanism->mechanism); + if (oid == NULL) { + return CKR_MECHANISM_INVALID; + } + + pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; + salt.data = (unsigned char *)pbe_params->pSalt; + salt.len = (unsigned int)pbe_params->ulSaltLen; + + params=nsspkcs5_NewParam(oid->offset, &salt, pbe_params->ulIteration); + if (params == NULL) { + return CKR_MECHANISM_INVALID; + } + + + switch (params->encAlg) { + case SEC_OID_DES_CBC: *key_type = CKK_DES; break; + case SEC_OID_DES_EDE3_CBC: + *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3; case CKM_PBE_MD5_DES_CBC: - *algtag = SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC; - *key_type = CKK_DES; - break; - case CKM_PBE_SHA1_RC4_40: - *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4; - *key_length = 5; - *key_type = CKK_RC4; - break; - case CKM_PBE_SHA1_RC4_128: - *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4; - *key_length = 16; - *key_type = CKK_RC4; - break; - case CKM_PBE_SHA1_RC2_40_CBC: - *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; - *key_length = 5; - *key_type = CKK_RC2; - break; - case CKM_PBE_SHA1_RC2_128_CBC: - *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC; - *key_length = 16; - *key_type = CKK_RC2; - break; - case CKM_PBE_SHA1_DES3_EDE_CBC: - *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC; - *key_length = 24; - *key_type = CKK_DES3; - break; - case CKM_PBE_SHA1_DES2_EDE_CBC: - *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC; - *key_length = 16; - *key_type = CKK_DES2; - break; - case CKM_NETSCAPE_PBE_SHA1_DES_CBC: - *algtag = SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC; *key_type = CKK_DES; break; - case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: - case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: - *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC; - *key_type = CKK_DES3; - break; - case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: - *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; - *key_type = CKK_RC2; - break; - case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: - *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC; - *key_type = CKK_RC2; - break; - case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: - *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4; + case SEC_OID_RC2_CBC: *key_type = CKK_RC4; break; - case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: - *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4; + case SEC_OID_RC4: *key_type = CKK_RC4; break; default: - PORT_Assert(0); crv = CKR_MECHANISM_INVALID; break; } - return crv; } @@ -2998,8 +2720,8 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, int i; PK11Slot *slot = pk11_SlotFromSessionHandle(hSession); char buf[MAX_KEY_LEN]; - enum {pk11_pbe, pk11_pbe_hmac, pk11_ssl, pk11_bulk} key_gen_type; - SECOidTag algtag = SEC_OID_UNKNOWN; + enum {nsc_pbe, nsc_ssl, nsc_bulk} key_gen_type; + NSSPKCS5PBEParameter *pbe_param; SSL3RSAPreMasterSecret *rsa_pms; CK_VERSION *version; /* in very old versions of NSS, there were implementation errors with key @@ -3040,7 +2762,7 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, pk11_DeleteAttributeType(key,CKA_VALUE); /* Now Set up the parameters to generate the key (based on mechanism) */ - key_gen_type = pk11_bulk; /* bulk key by default */ + key_gen_type = nsc_bulk; /* bulk key by default */ switch (pMechanism->mechanism) { case CKM_CDMF_KEY_GEN: case CKM_DES_KEY_GEN: @@ -3059,16 +2781,18 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, case CKM_SSL3_PRE_MASTER_KEY_GEN: key_type = CKK_GENERIC_SECRET; key_length = 48; - key_gen_type = pk11_ssl; + key_gen_type = nsc_ssl; break; - case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: - faultyPBE3DES = PR_TRUE; + case CKM_PBA_SHA1_WITH_SHA1_HMAC: case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: - key_gen_type = pk11_pbe_hmac; + key_gen_type = nsc_pbe; key_type = CKK_GENERIC_SECRET; + crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param); break; + case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: + faultyPBE3DES = PR_TRUE; case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: case CKM_NETSCAPE_PBE_SHA1_DES_CBC: @@ -3083,9 +2807,8 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, case CKM_PBE_SHA1_RC4_40: case CKM_PBE_MD5_DES_CBC: case CKM_PBE_MD2_DES_CBC: - key_gen_type = pk11_pbe; - crv = nsc_SetupPBEKeyGen(pMechanism->mechanism,&algtag, - &key_type,&key_length); + key_gen_type = nsc_pbe; + crv = nsc_SetupPBEKeyGen(pMechanism,&pbe_param, &key_type); break; default: crv = CKR_MECHANISM_INVALID; @@ -3109,15 +2832,11 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, * now to the actual key gen. */ switch (key_gen_type) { - case pk11_pbe_hmac: - crv = pk11_pbe_hmac_key_gen(pMechanism, buf, &key_length, - faultyPBE3DES); - break; - case pk11_pbe: - crv = pk11_pbe_key_gen(algtag, pMechanism, buf, &key_length, + case nsc_pbe: + crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length, faultyPBE3DES); break; - case pk11_ssl: + case nsc_ssl: rsa_pms = (SSL3RSAPreMasterSecret *)buf; version = (CK_VERSION *)pMechanism->pParameter; rsa_pms->client_version[0] = version->major; @@ -3125,7 +2844,7 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, crv = NSC_GenerateRandom(0,&rsa_pms->random[0], sizeof(rsa_pms->random)); break; - case pk11_bulk: + case nsc_bulk: /* get the key, check for weak keys and repeat if found */ do { crv = NSC_GenerateRandom(0, (unsigned char *)buf, key_length); @@ -3158,10 +2877,6 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, */ crv = pk11_handleObject(key,session); pk11_FreeSession(session); - if (crv != CKR_OK) { - pk11_FreeObject(key); - return crv; - } if (pk11_isTrue(key,CKA_SENSITIVE)) { pk11_forceAttribute(key,CKA_ALWAYS_SENSITIVE,&cktrue,sizeof(CK_BBOOL)); } @@ -3170,7 +2885,8 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, } *phKey = key->handle; - return CKR_OK; + pk11_FreeObject(key); + return crv; } @@ -3495,7 +3211,7 @@ dhgn_done: /* * handle the base object cleanup for the public Key */ - crv = pk11_handleObject(publicKey,session); + crv = pk11_handleObject(privateKey,session); if (crv != CKR_OK) { pk11_FreeSession(session); pk11_FreeObject(privateKey); @@ -3508,11 +3224,12 @@ dhgn_done: * If we have any problems, we destroy the public Key we've * created and linked. */ - crv = pk11_handleObject(privateKey,session); + crv = pk11_handleObject(publicKey,session); pk11_FreeSession(session); if (crv != CKR_OK) { + pk11_FreeObject(publicKey); + NSC_DestroyObject(hSession,privateKey->handle); pk11_FreeObject(privateKey); - NSC_DestroyObject(hSession,publicKey->handle); return crv; } if (pk11_isTrue(privateKey,CKA_SENSITIVE)) { @@ -3533,14 +3250,16 @@ dhgn_done: } *phPrivateKey = privateKey->handle; *phPublicKey = publicKey->handle; + pk11_FreeObject(publicKey); + pk11_FreeObject(privateKey); return CKR_OK; } static SECItem *pk11_PackagePrivateKey(PK11Object *key) { - SECKEYLowPrivateKey *lk = NULL; - PrivateKeyInfo *pki = NULL; + NSSLOWKEYPrivateKey *lk = NULL; + NSSLOWKEYPrivateKeyInfo *pki = NULL; PK11Attribute *attribute = NULL; PLArenaPool *arena = NULL; SECOidTag algorithm = SEC_OID_UNKNOWN; @@ -3569,8 +3288,8 @@ static SECItem *pk11_PackagePrivateKey(PK11Object *key) goto loser; } - pki = (PrivateKeyInfo*)PORT_ArenaZAlloc(arena, - sizeof(PrivateKeyInfo)); + pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena, + sizeof(NSSLOWKEYPrivateKeyInfo)); if(!pki) { rv = SECFailure; goto loser; @@ -3579,25 +3298,25 @@ static SECItem *pk11_PackagePrivateKey(PK11Object *key) param = NULL; switch(lk->keyType) { - case lowRSAKey: + case NSSLOWKEYRSAKey: dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, - SECKEY_LowRSAPrivateKeyTemplate); + nsslowkey_RSAPrivateKeyTemplate); algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; break; - case lowDSAKey: + case NSSLOWKEYDSAKey: dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, - SECKEY_LowDSAPrivateKeyExportTemplate); + nsslowkey_DSAPrivateKeyExportTemplate); param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params), - SECKEY_LowPQGParamsTemplate); + nsslowkey_PQGParamsTemplate); algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE; break; - case lowDHKey: + case NSSLOWKEYDHKey: default: dummy = NULL; break; } - if(!dummy || ((lk->keyType == lowDSAKey) && !param)) { + if(!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) { goto loser; } @@ -3609,14 +3328,14 @@ static SECItem *pk11_PackagePrivateKey(PK11Object *key) } dummy = SEC_ASN1EncodeInteger(arena, &pki->version, - SEC_PRIVATE_KEY_INFO_VERSION); + NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); if(!dummy) { rv = SECFailure; goto loser; } encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki, - SECKEY_PrivateKeyInfoTemplate); + nsslowkey_PrivateKeyInfoTemplate); loser: if(arena) { @@ -3624,7 +3343,7 @@ loser: } if(lk && (lk != key->objectInfo)) { - SECKEY_LowDestroyPrivateKey(lk); + nsslowkey_DestroyPrivateKey(lk); } if(param) { @@ -3680,8 +3399,8 @@ CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession, len = *pulWrappedKeyLen; } - crv = pk11_EncryptInit(hSession, pMechanism, hWrappingKey, - CKA_WRAP, PK11_ENCRYPT); + crv = pk11_CryptInit(hSession, pMechanism, hWrappingKey, + CKA_WRAP, PK11_ENCRYPT, PR_TRUE); if (crv != CKR_OK) { pk11_FreeAttribute(attribute); break; @@ -3712,8 +3431,8 @@ CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession, break; } - crv = pk11_EncryptInit(hSession, pMechanism, hWrappingKey, - CKA_WRAP, PK11_ENCRYPT); + crv = pk11_CryptInit(hSession, pMechanism, hWrappingKey, + CKA_WRAP, PK11_ENCRYPT, PR_TRUE); if(crv != CKR_OK) { SECITEM_ZfreeItem(bpki, PR_TRUE); crv = CKR_KEY_TYPE_INCONSISTENT; @@ -3747,8 +3466,8 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki) const SEC_ASN1Template *keyTemplate, *paramTemplate; void *paramDest = NULL; PLArenaPool *arena; - SECKEYLowPrivateKey *lpk = NULL; - PrivateKeyInfo *pki = NULL; + NSSLOWKEYPrivateKey *lpk = NULL; + NSSLOWKEYPrivateKeyInfo *pki = NULL; SECItem *ck_id = NULL; CK_RV crv = CKR_KEY_TYPE_INCONSISTENT; @@ -3757,21 +3476,21 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki) return SECFailure; } - pki = (PrivateKeyInfo*)PORT_ArenaZAlloc(arena, - sizeof(PrivateKeyInfo)); + pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena, + sizeof(NSSLOWKEYPrivateKeyInfo)); if(!pki) { PORT_FreeArena(arena, PR_TRUE); return SECFailure; } - if(SEC_ASN1DecodeItem(arena, pki, SECKEY_PrivateKeyInfoTemplate, bpki) + if(SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) != SECSuccess) { PORT_FreeArena(arena, PR_FALSE); return SECFailure; } - lpk = (SECKEYLowPrivateKey *)PORT_ArenaZAlloc(arena, - sizeof(SECKEYLowPrivateKey)); + lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena, + sizeof(NSSLOWKEYPrivateKey)); if(lpk == NULL) { goto loser; } @@ -3779,18 +3498,18 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki) switch(SECOID_GetAlgorithmTag(&pki->algorithm)) { case SEC_OID_PKCS1_RSA_ENCRYPTION: - keyTemplate = SECKEY_LowRSAPrivateKeyTemplate; + keyTemplate = nsslowkey_RSAPrivateKeyTemplate; paramTemplate = NULL; paramDest = NULL; - lpk->keyType = lowRSAKey; + lpk->keyType = NSSLOWKEYRSAKey; break; case SEC_OID_ANSIX9_DSA_SIGNATURE: - keyTemplate = SECKEY_LowDSAPrivateKeyExportTemplate; - paramTemplate = SECKEY_LowPQGParamsTemplate; + keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate; + paramTemplate = nsslowkey_PQGParamsTemplate; paramDest = &(lpk->u.dsa.params); - lpk->keyType = lowDSAKey; + lpk->keyType = NSSLOWKEYDSAKey; break; - /* case lowDHKey: */ + /* case NSSLOWKEYDHKey: */ default: keyTemplate = NULL; paramTemplate = NULL; @@ -3818,7 +3537,7 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki) rv = SECFailure; switch (lpk->keyType) { - case lowRSAKey: + case NSSLOWKEYRSAKey: keyType = CKK_RSA; if(pk11_hasAttribute(key, CKA_NETSCAPE_DB)) { pk11_DeleteAttributeType(key, CKA_NETSCAPE_DB); @@ -3862,7 +3581,7 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki) crv = pk11_AddAttributeType(key, CKA_COEFFICIENT, pk11_item_expand(&lpk->u.rsa.coefficient)); break; - case lowDSAKey: + case NSSLOWKEYDSAKey: keyType = CKK_DSA; crv = (pk11_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT; @@ -3890,7 +3609,7 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki) if(crv != CKR_OK) break; break; #ifdef notdef - case lowDHKey: + case NSSLOWKEYDHKey: template = dhTemplate; templateCount = sizeof(dhTemplate)/sizeof(CK_ATTRIBUTE); keyType = CKK_DH; @@ -3908,7 +3627,7 @@ loser: } if(lpk) { - SECKEY_LowDestroyPrivateKey(lpk); + nsslowkey_DestroyPrivateKey(lpk); } if(crv != CKR_OK) { @@ -3972,8 +3691,8 @@ CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession, ulWrappedKeyLen -= 2; /* don't decrypt the checksum */ } - crv = pk11_DecryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP, - PK11_DECRYPT); + crv = pk11_CryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP, + PK11_DECRYPT, PR_FALSE); if (crv != CKR_OK) { pk11_FreeObject(key); return pk11_mapWrap(crv); @@ -4050,14 +3769,11 @@ CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession, * handle the base object stuff */ crv = pk11_handleObject(key,session); + *phKey = key->handle; pk11_FreeSession(session); - if (crv != CKR_OK) { - pk11_FreeObject(key); - return crv; - } + pk11_FreeObject(key); - *phKey = key->handle; - return CKR_OK; + return crv; } @@ -4080,10 +3796,10 @@ pk11_buildSSLKey(CK_SESSION_HANDLE hSession, PK11Object *baseKey, /* * now lets create an object to hang the attributes off of */ - *keyHandle = CK_INVALID_KEY; + *keyHandle = CK_INVALID_HANDLE; key = pk11_NewObject(baseKey->slot); if (key == NULL) return CKR_HOST_MEMORY; - key->wasDerived = PR_TRUE; + pk11_narrowToSessionObject(key)->wasDerived = PR_TRUE; crv = pk11_CopyObject(key,baseKey); if (crv != CKR_OK) goto loser; @@ -4115,10 +3831,7 @@ pk11_buildSSLKey(CK_SESSION_HANDLE hSession, PK11Object *baseKey, crv = pk11_handleObject(key,session); pk11_FreeSession(session); - if (crv == CKR_OK) { - *keyHandle = key->handle; - return crv; - } + *keyHandle = key->handle; loser: if (key) pk11_FreeObject(key); return crv; @@ -4131,16 +3844,16 @@ loser: static void pk11_freeSSLKeys(CK_SESSION_HANDLE session, CK_SSL3_KEY_MAT_OUT *returnedMaterial ) { - if (returnedMaterial->hClientMacSecret != CK_INVALID_KEY) { + if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) { NSC_DestroyObject(session,returnedMaterial->hClientMacSecret); } - if (returnedMaterial->hServerMacSecret != CK_INVALID_KEY) { + if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) { NSC_DestroyObject(session, returnedMaterial->hServerMacSecret); } - if (returnedMaterial->hClientKey != CK_INVALID_KEY) { + if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) { NSC_DestroyObject(session, returnedMaterial->hClientKey); } - if (returnedMaterial->hServerKey != CK_INVALID_KEY) { + if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) { NSC_DestroyObject(session, returnedMaterial->hServerKey); } } @@ -4233,7 +3946,7 @@ pk11_MapKeySize(CK_KEY_TYPE keyType) { /* TLS P_hash function */ static SECStatus -pk11_P_hash(SECOidTag alg, const SECItem *secret, const char *label, +pk11_P_hash(HASH_HashType hashType, const SECItem *secret, const char *label, SECItem *seed, SECItem *result) { unsigned char state[PHASH_STATE_MAX_LEN]; @@ -4244,6 +3957,7 @@ pk11_P_hash(SECOidTag alg, const SECItem *secret, const char *label, SECStatus status; HMACContext *cx; SECStatus rv = SECFailure; + const SECHashObject *hashObj = &SECRawHashObjects[hashType]; PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len)); PORT_Assert((seed != NULL) && (seed->data != NULL)); @@ -4255,7 +3969,7 @@ pk11_P_hash(SECOidTag alg, const SECItem *secret, const char *label, if (label != NULL) label_len = PORT_Strlen(label); - cx = HMAC_Create(alg, secret->data, secret->len); + cx = HMAC_Create(hashObj, secret->data, secret->len); if (cx == NULL) goto loser; @@ -4330,11 +4044,11 @@ pk11_PRF(const SECItem *secret, const char *label, SECItem *seed, goto loser; tmp.len = result->len; - status = pk11_P_hash(SEC_OID_MD5, &S1, label, seed, result); + status = pk11_P_hash(HASH_AlgMD5, &S1, label, seed, result); if (status != SECSuccess) goto loser; - status = pk11_P_hash(SEC_OID_SHA1, &S2, label, seed, &tmp); + status = pk11_P_hash(HASH_AlgSHA1, &S2, label, seed, &tmp); if (status != SECSuccess) goto loser; @@ -4404,7 +4118,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, /* * now lets create an object to hang the attributes off of */ - if (phKey) *phKey = CK_INVALID_KEY; + if (phKey) *phKey = CK_INVALID_HANDLE; key = pk11_NewObject(slot); /* fill in the handle later */ if (key == NULL) { @@ -4513,9 +4227,10 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *) pMechanism->pParameter; if (ssl3_master->pVersion) { + PK11SessionObject *sessKey = pk11_narrowToSessionObject(key); rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue; /* don't leak more key material then necessary for SSL to work */ - if (key->wasDerived) { + if ((sessKey == NULL) || sessKey->wasDerived) { ssl3_master->pVersion->major = 0xff; ssl3_master->pVersion->minor = 0xff; } else { @@ -4652,10 +4367,10 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, * clear out our returned keys so we can recover on failure */ ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial; - ssl3_keys_out->hClientMacSecret = CK_INVALID_KEY; - ssl3_keys_out->hServerMacSecret = CK_INVALID_KEY; - ssl3_keys_out->hClientKey = CK_INVALID_KEY; - ssl3_keys_out->hServerKey = CK_INVALID_KEY; + ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE; + ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE; + ssl3_keys_out->hClientKey = CK_INVALID_HANDLE; + ssl3_keys_out->hServerKey = CK_INVALID_HANDLE; /* * generate the key material: This looks amazingly similar to the @@ -5222,8 +4937,10 @@ key_and_mac_derive_fail: /* link the key object into the list */ if (key) { + PK11SessionObject *sessKey = pk11_narrowToSessionObject(key); + PORT_Assert(sessKey); /* get the session */ - key->wasDerived = PR_TRUE; + sessKey->wasDerived = PR_TRUE; session = pk11_SessionFromHandle(hSession); if (session == NULL) { pk11_FreeObject(key); @@ -5232,10 +4949,7 @@ key_and_mac_derive_fail: crv = pk11_handleObject(key,session); pk11_FreeSession(session); - if (crv == CKR_OK) { - *phKey = key->handle; - return crv; - } + *phKey = key->handle; pk11_FreeObject(key); } return crv; diff --git a/security/nss/lib/softoken/pkcs11f.h b/security/nss/lib/softoken/pkcs11f.h index 71ee2676a..70d34da5e 100644 --- a/security/nss/lib/softoken/pkcs11f.h +++ b/security/nss/lib/softoken/pkcs11f.h @@ -150,10 +150,11 @@ CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo) CK_PKCS11_FUNCTION_INFO(C_InitToken) #ifdef CK_NEED_ARG_LIST ( - CK_SLOT_ID slotID, /* ID of the token's slot */ - CK_CHAR_PTR pPin, /* the SO's initial PIN */ - CK_ULONG ulPinLen, /* length in bytes of the PIN */ - CK_CHAR_PTR pLabel /* 32-byte token label (blank padded) */ +/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */ + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_CHAR_PTR pPin, /* the SO's initial PIN */ + CK_ULONG ulPinLen, /* length in bytes of the PIN */ + CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */ ); #endif diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h index 2e924a4ef..c09b2635e 100644 --- a/security/nss/lib/softoken/pkcs11i.h +++ b/security/nss/lib/softoken/pkcs11i.h @@ -39,14 +39,67 @@ #include "nssilock.h" #include "seccomon.h" #include "secoidt.h" -#include "keytlow.h" +#include "lowkeyti.h" #include "pkcs11t.h" +#include "pcertt.h" -#define PKCS11_USE_THREADS -#define NO_ARENA -#define MAX_OBJS_ATTRS 45 -#define ATTR_SPACE 50 /* hold up to a SSL premaster secret */ +/* + * Configuration Defines + * + * The following defines affect the space verse speed trade offs of + * the PKCS #11 module. For the most part the current settings are optimized + * for web servers, where we want faster speed and lower lock contention at + * the expense of space. + */ + +#define PKCS11_USE_THREADS /* set to true of you are need threads */ +/* + * Attribute Allocation strategy: + * + * 1) static allocation (PKCS11_STATIC_ATTRIBUTES set + * PKCS11_REF_COUNT_ATTRIBUTES not set) + * Attributes are pre-allocated as part of the session object and used from + * the object array. + * + * 2) heap allocation with ref counting (PKCS11_STATIC_ATTRIBUTES not set + * PKCS11_REF_COUNT_ATTRIBUTES set) + * Attributes are allocated from the heap when needed and freed when their + * reference count goes to zero. + * + * 3) arena allocation (PKCS11_STATIC_ATTRIBUTES not set + * PKCS11_REF_COUNT_ATTRIBUTE not set) + * Attributes are allocated from the arena when needed and freed only when + * the object goes away. + */ +#define PKCS11_STATIC_ATTRIBUTES +/*#define PKCS11_REF_COUNT_ATTRIBUTES */ +/* the next two are only active if PKCS11_STATIC_ATTRIBUTES is set */ +#define MAX_OBJS_ATTRS 45 /* number of attributes to preallocate in + * the object (must me the absolute max) */ +#define ATTR_SPACE 50 /* Maximum size of attribute data before extra + * data needs to be allocated. This is set to + * enough space to hold an SSL MASTER secret */ + +#define NSC_STRICT PR_FALSE /* forces the code to do strict template + * matching when doing C_FindObject on token + * objects. This will slow down search in + * NSS. */ +/* default search block allocations and increments */ +#define NSC_CERT_BLOCK_SIZE 50 +#define NSC_SEARCH_BLOCK_SIZE 5 +#define NSC_SLOT_LIST_BLOCK_SIZE 10 + +/* these are data base storage hashes, not cryptographic hashes.. The define + * the effective size of the various object hash tables */ +#define ATTRIBUTE_HASH_SIZE 32 +#define SESSION_OBJECT_HASH_SIZE 32 +#define TOKEN_OBJECT_HASH_SIZE 1024 +#define SESSION_HASH_SIZE 512 +#define MAX_OBJECT_LIST_SIZE 800 /* how many objects to keep on the free list + * before we start freeing them */ +#define MAX_KEY_LEN 256 + #ifdef PKCS11_USE_THREADS @@ -60,6 +113,8 @@ typedef struct PK11AttributeStr PK11Attribute; typedef struct PK11ObjectListStr PK11ObjectList; typedef struct PK11ObjectListElementStr PK11ObjectListElement; typedef struct PK11ObjectStr PK11Object; +typedef struct PK11SessionObjectStr PK11SessionObject; +typedef struct PK11TokenObjectStr PK11TokenObject; typedef struct PK11SessionStr PK11Session; typedef struct PK11SlotStr PK11Slot; typedef struct PK11SessionContextStr PK11SessionContext; @@ -78,17 +133,6 @@ typedef void (*PK11Hash)(void *,void *,unsigned int); typedef void (*PK11End)(void *,void *,unsigned int *,unsigned int); typedef void (*PK11Free)(void *); -/* - * these are data base storage hashes, not cryptographic hashes.. The define - * the effective size of the various object hash tables - */ -#define ATTRIBUTE_HASH_SIZE 32 -#define SESSION_OBJECT_HASH_SIZE 32 -#define TOKEN_OBJECT_HASH_SIZE 1024 -#define SESSION_HASH_SIZE 512 -#define MAX_KEY_LEN 256 -#define MAX_OBJECT_LIST_SIZE 800 - /* Value to tell if an attribute is modifiable or not. * NEVER: attribute is only set on creation. * ONCOPY: attribute is set on creation and can only be changed on copy. @@ -118,14 +162,16 @@ typedef enum { struct PK11AttributeStr { PK11Attribute *next; PK11Attribute *prev; -#ifdef REF_COUNT_ATTRIBUTE + PRBool freeAttr; + PRBool freeData; +#ifdef PKCS11_REF_COUNT_ATTRIBUTES int refCount; PZLock *refLock; #endif /*must be called handle to make pk11queue_find work */ CK_ATTRIBUTE_TYPE handle; CK_ATTRIBUTE attrib; -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES unsigned char space[ATTR_SPACE]; #endif }; @@ -145,27 +191,33 @@ struct PK11ObjectListStr { */ struct PK11ObjectStr { PK11Object *next; - PK11Object *prev; - PK11ObjectList sessionList; - CK_OBJECT_HANDLE handle; -#ifdef NO_ARENA - int nextAttr; -#else - PLArenaPool *arena; -#endif - int refCount; + PK11Object *prev; + CK_OBJECT_CLASS objclass; + CK_OBJECT_HANDLE handle; + int refCount; PZLock *refLock; - PZLock *attributeLock; - PK11Session *session; PK11Slot *slot; - CK_OBJECT_CLASS objclass; void *objectInfo; PK11Free infoFree; - char *label; - PRBool inDB; +#ifndef PKCS11_STATIC_ATTRIBUTES + PLArenaPool *arena; +#endif +}; + +struct PK11TokenObjectStr { + PK11Object obj; + SECItem dbKey; +}; + +struct PK11SessionObjectStr { + PK11Object obj; + PK11ObjectList sessionList; + PZLock *attributeLock; + PK11Session *session; PRBool wasDerived; PK11Attribute *head[ATTRIBUTE_HASH_SIZE]; -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES + int nextAttr; PK11Attribute attrList[MAX_OBJS_ATTRS]; #endif }; @@ -185,6 +237,7 @@ struct PK11SearchResultsStr { CK_OBJECT_HANDLE *handles; int size; int index; + int array_size; }; @@ -227,6 +280,7 @@ struct PK11SessionContextStr { PK11Destroy hashdestroy; PK11Verify verify; unsigned int maxLen; + PK11Object *key; }; /* @@ -264,12 +318,20 @@ struct PK11SlotStr { PRBool ssoLoggedIn; PRBool needLogin; PRBool DB_loaded; + PRBool readOnly; + NSSLOWCERTCertDBHandle *certDB; + NSSLOWKEYDBHandle *keyDB; + int minimumPinLen; int sessionIDCount; int sessionCount; int rwSessionCount; int tokenIDCount; + int index; + PLHashTable *tokenHashTable; PK11Object *tokObjects[TOKEN_OBJECT_HASH_SIZE]; PK11Session *head[SESSION_HASH_SIZE]; + char tokDescription[33]; + char slotDescription[64]; }; /* @@ -277,12 +339,12 @@ struct PK11SlotStr { */ struct PK11HashVerifyInfoStr { SECOidTag hashOid; - SECKEYLowPublicKey *key; + NSSLOWKEYPublicKey *key; }; struct PK11HashSignInfoStr { SECOidTag hashOid; - SECKEYLowPrivateKey *key; + NSSLOWKEYPrivateKey *key; }; /* context for the Final SSLMAC message */ @@ -300,8 +362,7 @@ struct PK11SSLMACInfoStr { /* * session handle modifiers */ -#define PK11_PRIVATE_KEY_FLAG 0x80000000L -#define PK11_FIPS_FLAG 0x40000000L +#define PK11_SESSION_SLOT_MASK 0xff000000L /* * object handle modifiers @@ -309,10 +370,17 @@ struct PK11SSLMACInfoStr { #define PK11_TOKEN_MASK 0x80000000L #define PK11_TOKEN_MAGIC 0x80000000L #define PK11_TOKEN_TYPE_MASK 0x70000000L -#define PK11_TOKEN_TYPE_CERT 0x00000000L +/* keydb (high bit == 0) */ #define PK11_TOKEN_TYPE_PRIV 0x10000000L #define PK11_TOKEN_TYPE_PUB 0x20000000L - +#define PK11_TOKEN_TYPE_KEY 0x30000000L +/* certdb (high bit == 1) */ +#define PK11_TOKEN_TYPE_TRUST 0x40000000L +#define PK11_TOKEN_TYPE_CRL 0x50000000L +#define PK11_TOKEN_TYPE_SMIME 0x60000000L +#define PK11_TOKEN_TYPE_CERT 0x70000000L + +#define PK11_TOKEN_KRL_HANDLE (PK11_TOKEN_MAGIC|PK11_TOKEN_TYPE_CRL|0) /* how big a password/pin we can deal with */ #define PK11_MAX_PIN 255 @@ -351,27 +419,36 @@ struct PK11SSLMACInfoStr { #define pk11_attr_expand(ap) (ap)->type,(ap)->pValue,(ap)->ulValueLen #define pk11_item_expand(ip) (ip)->data,(ip)->len -typedef struct pk11_parametersStr { +typedef struct pk11_token_parametersStr { + CK_SLOT_ID slotID; char *configdir; char *certPrefix; char *keyPrefix; - char *secmodName; - char *man; - char *libdes; char *tokdes; - char *ptokdes; char *slotdes; - char *pslotdes; - char *fslotdes; - char *fpslotdes; int minPW; PRBool readOnly; PRBool noCertDB; + PRBool noKeyDB; + PRBool forceOpen; + PRBool pwRequired; +} pk11_token_parameters; + +typedef struct pk11_parametersStr { + char *configdir; + char *secmodName; + char *man; + char *libdes; + PRBool readOnly; PRBool noModDB; + PRBool noCertDB; PRBool forceOpen; PRBool pwRequired; + pk11_token_parameters *tokens; + int token_count; } pk11_parameters; + /* machine dependent path stuff used by dbinit.c and pk11db.c */ #ifdef macintosh #define PATH_SEPARATOR ":" @@ -387,9 +464,9 @@ typedef struct pk11_parametersStr { SEC_BEGIN_PROTOS +extern CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS); /* shared functions between PKCS11.c and PK11FIPS.c */ -extern CK_RV PK11_LowInitialize(CK_VOID_PTR pReserved); -extern CK_RV PK11_SlotInit(CK_SLOT_ID slotID, PRBool needLogin); +extern CK_RV PK11_SlotInit(char *configdir,pk11_token_parameters *params); /* internal utility functions used by pkcs11.c */ extern PK11Attribute *pk11_FindAttribute(PK11Object *object, @@ -422,14 +499,14 @@ extern CK_RV pk11_defaultAttribute(PK11Object *object, CK_ATTRIBUTE_TYPE type, extern PK11Object *pk11_NewObject(PK11Slot *slot); extern CK_RV pk11_CopyObject(PK11Object *destObject, PK11Object *srcObject); extern PK11FreeStatus pk11_FreeObject(PK11Object *object); -extern void pk11_DeleteObject(PK11Session *session, PK11Object *object); +extern CK_RV pk11_DeleteObject(PK11Session *session, PK11Object *object); extern void pk11_ReferenceObject(PK11Object *object); extern PK11Object *pk11_ObjectFromHandle(CK_OBJECT_HANDLE handle, PK11Session *session); extern void pk11_AddSlotObject(PK11Slot *slot, PK11Object *object); extern void pk11_AddObject(PK11Session *session, PK11Object *object); -extern CK_RV pk11_searchObjectList(PK11ObjectListElement **objectList, +extern CK_RV pk11_searchObjectList(PK11SearchResults *search, PK11Object **head, PZLock *lock, CK_ATTRIBUTE_PTR inTemplate, int count, PRBool isLoggedIn); @@ -449,15 +526,16 @@ extern void pk11_update_state(PK11Slot *slot,PK11Session *session); extern void pk11_update_all_states(PK11Slot *slot); extern void pk11_FreeContext(PK11SessionContext *context); -extern SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object, +extern NSSLOWKEYPublicKey *pk11_GetPubKey(PK11Object *object, CK_KEY_TYPE key_type); -extern SECKEYLowPrivateKey *pk11_GetPrivKey(PK11Object *object, +extern NSSLOWKEYPrivateKey *pk11_GetPrivKey(PK11Object *object, CK_KEY_TYPE key_type); extern void pk11_FormatDESKey(unsigned char *key, int length); extern PRBool pk11_CheckDESKey(unsigned char *key); extern PRBool pk11_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type); -extern CK_RV secmod_parseParameters(char *param, pk11_parameters *parsed); +extern CK_RV secmod_parseParameters(char *param, pk11_parameters *parsed, + PRBool isFIPS); extern void secmod_freeParams(pk11_parameters *params); extern char *secmod_getSecmodName(char *params, PRBool *rw); extern char ** secmod_ReadPermDB(char *dbname, char *params, PRBool rw); @@ -481,10 +559,26 @@ extern SECStatus secmod_AddPermDB(char *dbname, char *module, PRBool rw); * be opened. */ CK_RV pk11_DBInit(const char *configdir, const char *certPrefix, - const char *keyPrefix, const char *secmodName, PRBool readOnly, - PRBool noCertDB, PRBool noModDB, PRBool forceOpen); + const char *keyPrefix, PRBool readOnly, PRBool noCertDB, + PRBool noKeyDB, PRBool forceOpen, + NSSLOWCERTCertDBHandle **certDB, NSSLOWKEYDBHandle **keyDB); +/* + * narrow objects + */ +PK11SessionObject * pk11_narrowToSessionObject(PK11Object *); +PK11TokenObject * pk11_narrowToTokenObject(PK11Object *); +/* + * token object utilities + */ +void pk11_addHandle(PK11SearchResults *search, CK_OBJECT_HANDLE handle); +PRBool pk11_tokenMatch(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class, + CK_ATTRIBUTE_PTR theTemplate,int count); +CK_OBJECT_HANDLE pk11_mkHandle(PK11Slot *slot, + SECItem *dbKey, CK_OBJECT_HANDLE class); +PK11Object * pk11_NewTokenObject(PK11Slot *slot, SECItem *dbKey, + CK_OBJECT_HANDLE handle); SEC_END_PROTOS #endif /* _PKCS11I_H_ */ diff --git a/security/nss/lib/softoken/pkcs11t.h b/security/nss/lib/softoken/pkcs11t.h index aa3d70496..124a1bb27 100644 --- a/security/nss/lib/softoken/pkcs11t.h +++ b/security/nss/lib/softoken/pkcs11t.h @@ -17,7 +17,6 @@ * Rights Reserved. * * Contributor(s): - * Dr Stephen Henson <stephen.henson@gemplus.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -61,12 +60,17 @@ #define CK_DECLARE_FUNCTION(rv,func) PR_EXTERN(rv) func #define CK_DECLARE_FUNCTION_POINTER(rv,func) rv (PR_CALLBACK * func) +#define CK_INVALID_SESSION 0 + /* an unsigned 8-bit value */ typedef unsigned char CK_BYTE; /* an unsigned 8-bit character */ typedef CK_BYTE CK_CHAR; +/* an unsigned 8-bit character */ +typedef CK_BYTE CK_UTF8CHAR; + /* a BYTE-sized Boolean flag */ typedef CK_BYTE CK_BBOOL; @@ -88,6 +92,7 @@ typedef CK_ULONG CK_FLAGS; typedef CK_BYTE CK_PTR CK_BYTE_PTR; typedef CK_CHAR CK_PTR CK_CHAR_PTR; +typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR; typedef CK_ULONG CK_PTR CK_ULONG_PTR; typedef void CK_PTR CK_VOID_PTR; @@ -112,12 +117,14 @@ typedef CK_VERSION CK_PTR CK_VERSION_PTR; typedef struct CK_INFO { + /* manufacturerID and libraryDecription have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ CK_VERSION cryptokiVersion; /* PKCS #11 interface ver */ - CK_CHAR manufacturerID[32]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ CK_FLAGS flags; /* must be zero */ /* libraryDescription and libraryVersion are new for v2.0 */ - CK_CHAR libraryDescription[32]; /* blank padded */ + CK_UTF8CHAR libraryDescription[32]; /* blank padded */ CK_VERSION libraryVersion; /* version of library */ } CK_INFO; @@ -139,8 +146,10 @@ typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR; /* CK_SLOT_INFO provides information about a slot */ typedef struct CK_SLOT_INFO { - CK_CHAR slotDescription[64]; /* blank padded */ - CK_CHAR manufacturerID[32]; /* blank padded */ + /* slotDescription and manufacturerID have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_UTF8CHAR slotDescription[64]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ CK_FLAGS flags; /* hardwareVersion and firmwareVersion are new for v2.0 */ @@ -160,9 +169,11 @@ typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR; /* CK_TOKEN_INFO provides information about a token */ typedef struct CK_TOKEN_INFO { - CK_CHAR label[32]; /* blank padded */ - CK_CHAR manufacturerID[32]; /* blank padded */ - CK_CHAR model[16]; /* blank padded */ + /* label, manufacturerID, and model have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_UTF8CHAR label[32]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_UTF8CHAR model[16]; /* blank padded */ CK_CHAR serialNumber[16]; /* blank padded */ CK_FLAGS flags; /* see below */ @@ -223,6 +234,57 @@ typedef struct CK_TOKEN_INFO { * and sign) */ #define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200 +/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the + * token has been initialized using C_InitializeToken or an + * equivalent mechanism outside the scope of PKCS #11. + * Calling C_InitializeToken when this flag is set will cause + * the token to be reinitialized. */ +#define CKF_TOKEN_INITIALIZED 0x00000400 + +/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is + * true, the token supports secondary authentication for + * private key objects. */ +/* DEPRICATED in v2.11 */ +#define CKF_SECONDARY_AUTHENTICATION 0x00000800 + +/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect user login PIN has been entered at least once + * since the last successful authentication. */ +#define CKF_USER_PIN_COUNT_LOW 0x00010000 + +/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true, + * supplying an incorrect user PIN will it to become locked. */ +#define CKF_USER_PIN_FINAL_TRY 0x00020000 + +/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the + * user PIN has been locked. User login to the token is not + * possible. */ +#define CKF_USER_PIN_LOCKED 0x00040000 + +/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the user PIN value is the default value set by token + * initialization or manufacturing. */ +#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000 + +/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect SO login PIN has been entered at least once since + * the last successful authentication. */ +#define CKF_SO_PIN_COUNT_LOW 0x00100000 + +/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true, + * supplying an incorrect SO PIN will it to become locked. */ +#define CKF_SO_PIN_FINAL_TRY 0x00200000 + +/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO + * PIN has been locked. SO login to the token is not possible. + */ +#define CKF_SO_PIN_LOCKED 0x00400000 + +/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the SO PIN value is the default value set by token + * initialization or manufacturing. */ +#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000 + typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; @@ -289,15 +351,28 @@ typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR; typedef CK_ULONG CK_OBJECT_CLASS; /* The following classes of objects are defined: */ -#define CKO_DATA 0x00000000 -#define CKO_CERTIFICATE 0x00000001 -#define CKO_PUBLIC_KEY 0x00000002 -#define CKO_PRIVATE_KEY 0x00000003 -#define CKO_SECRET_KEY 0x00000004 -#define CKO_VENDOR_DEFINED 0x80000000 +/* CKO_HW_FEATURE is new for v2.10 */ +/* CKO_DOMAIN_PARAMETERS is new for v2.11 */ +#define CKO_DATA 0x00000000 +#define CKO_CERTIFICATE 0x00000001 +#define CKO_PUBLIC_KEY 0x00000002 +#define CKO_PRIVATE_KEY 0x00000003 +#define CKO_SECRET_KEY 0x00000004 +#define CKO_HW_FEATURE 0x00000005 +#define CKO_DOMAIN_PARAMETERS 0x00000006 +#define CKO_VENDOR_DEFINED 0x80000000 typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; +/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a + * value that identifies the hardware feature type of an object + * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */ +typedef CK_ULONG CK_HW_FEATURE_TYPE; + +/* The following hardware feature types are defined */ +#define CKH_MONOTONIC_COUNTER 0x00000001 +#define CKH_CLOCK 0x00000002 +#define CKH_VENDOR_DEFINED 0x80000000 /* CK_KEY_TYPE is a value that identifies a key type */ /* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */ @@ -309,10 +384,10 @@ typedef CK_ULONG CK_KEY_TYPE; #define CKK_DH 0x00000002 /* CKK_ECDSA and CKK_KEA are new for v2.0 */ - -/* PKCS #11 V2.01 probably won't actually have ECDSA in it */ -#define CKK_ECDSA 0x00000003 - +/* CKK_X9_42_DH is new for v2.11 */ +#define CKK_ECDSA 0x00000003 /* deprecated in v2.11 */ +#define CKK_EC 0x00000003 +#define CKK_X9_42_DH 0x00000004 #define CKK_KEA 0x00000005 #define CKK_GENERIC_SECRET 0x00000010 @@ -325,8 +400,8 @@ typedef CK_ULONG CK_KEY_TYPE; /* all these key types are new for v2.0 */ #define CKK_CAST 0x00000016 #define CKK_CAST3 0x00000017 -#define CKK_CAST5 0x00000018 -#define CKK_CAST128 0x00000018 /* CAST128=CAST5 */ +#define CKK_CAST5 0x00000018 /* deprecated in v2.11 */ +#define CKK_CAST128 0x00000018 #define CKK_RC5 0x00000019 #define CKK_IDEA 0x0000001A #define CKK_SKIPJACK 0x0000001B @@ -348,7 +423,9 @@ typedef CK_ULONG CK_KEY_TYPE; typedef CK_ULONG CK_CERTIFICATE_TYPE; /* The following certificate types are defined: */ +/* CKC_X_509_ATTR_CERT is new for v2.10 */ #define CKC_X_509 0x00000000 +#define CKC_X_509_ATTR_CERT 0x00000001 #define CKC_VENDOR_DEFINED 0x80000000 @@ -365,9 +442,22 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; #define CKA_LABEL 0x00000003 #define CKA_APPLICATION 0x00000010 #define CKA_VALUE 0x00000011 + +/* CKA_OBJECT_ID is new for v2.10 */ +#define CKA_OBJECT_ID 0x00000012 + #define CKA_CERTIFICATE_TYPE 0x00000080 #define CKA_ISSUER 0x00000081 #define CKA_SERIAL_NUMBER 0x00000082 + +/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new + * for v2.10 */ +#define CKA_AC_ISSUER 0x00000083 +#define CKA_OWNER 0x00000084 +#define CKA_ATTR_TYPES 0x00000085 +/* CKA_TRUSTED is new for v2.11 */ +#define CKA_TRUSTED 0x00000086 + #define CKA_KEY_TYPE 0x00000100 #define CKA_SUBJECT 0x00000101 #define CKA_ID 0x00000102 @@ -395,16 +485,34 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; #define CKA_PRIME 0x00000130 #define CKA_SUBPRIME 0x00000131 #define CKA_BASE 0x00000132 +/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */ +#define CKA_PRIME_BITS 0x00000133 +#define CKA_SUB_PRIME_BITS 0x00000134 #define CKA_VALUE_BITS 0x00000160 #define CKA_VALUE_LEN 0x00000161 /* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE, - * CKA_ALWAYS_SENSITIVE, and CKA_MODIFIABLE are new for v2.0 */ + * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS, + * and CKA_EC_POINT are new for v2.0 */ #define CKA_EXTRACTABLE 0x00000162 #define CKA_LOCAL 0x00000163 #define CKA_NEVER_EXTRACTABLE 0x00000164 #define CKA_ALWAYS_SENSITIVE 0x00000165 +/* CKA_KEY_GEN_MECHANISM is new for v2.11 */ +#define CKA_KEY_GEN_MECHANISM 0x00000166 #define CKA_MODIFIABLE 0x00000170 +#define CKA_ECDSA_PARAMS 0x00000180 /* depricated v2.11 */ +#define CKA_EC_PARAMS 0x00000180 +#define CKA_EC_POINT 0x00000181 + +/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, + * CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET + * are new for v2.10 */ +#define CKA_SECONDARY_AUTH 0x00000200 /* depricated v2.11 */ +#define CKA_AUTH_PIN_FLAGS 0x00000201 /* depricated v2.11 */ +#define CKA_HW_FEATURE_TYPE 0x00000300 +#define CKA_RESET_ON_INIT 0x00000301 +#define CKA_HAS_RESET 0x00000302 #define CKA_VENDOR_DEFINED 0x80000000 @@ -448,11 +556,32 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_MD5_RSA_PKCS 0x00000005 #define CKM_SHA1_RSA_PKCS 0x00000006 +/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS & CKM_RSA_OAEP + * are new for 2.10 */ +#define CKM_RIPEMD128_RSA_PKCS 0x00000007 +#define CKM_RIPEMD160_RSA_PKCS 0x00000008 +#define CKM_RSA_PKCS_OAEP 0x00000009 + +/* CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31 & CKM_RSA_X9_31_KEY_PAIR_GEN + * are new for 2.11 */ +#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A +#define CKM_RSA_X9_31 0x0000000B +#define CKM_SHA1_RSA_X9_31 0x0000000C + #define CKM_DSA_KEY_PAIR_GEN 0x00000010 #define CKM_DSA 0x00000011 #define CKM_DSA_SHA1 0x00000012 #define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 #define CKM_DH_PKCS_DERIVE 0x00000021 + +/* CKM_X9_42_DH_PKCS_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE, + * CKM_X9_42_DH_HYBRID_DERIVE, & CKM_X9_42_MQV_DERIVE + * are new for v2.11 */ +#define CKM_X9_42_DH_PKCS_KEY_PAIR_GEN 0x00000030 +#define CKM_X9_42_DH_DERIVE 0x00000031 +#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032 +#define CKM_X9_42_MQV_DERIVE 0x00000033 + #define CKM_RC2_KEY_GEN 0x00000100 #define CKM_RC2_ECB 0x00000101 #define CKM_RC2_CBC 0x00000102 @@ -509,6 +638,16 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_SHA_1_HMAC 0x00000221 #define CKM_SHA_1_HMAC_GENERAL 0x00000222 +/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC, + * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC, + * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */ +#define CKM_RIPEMD128 0x00000230 +#define CKM_RIPEMD128_HMAC 0x00000231 +#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232 +#define CKM_RIPEMD160 0x00000240 +#define CKM_RIPEMD160_HMAC 0x00000241 +#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242 + /* All of the following mechanisms are new for v2.0 */ /* Note that CAST128 and CAST5 are the same algorithm */ #define CKM_CAST_KEY_GEN 0x00000300 @@ -556,6 +695,17 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370 #define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371 #define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372 + +/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN, + * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, + * CKM_TLS_MASTER_KEY_DERIVE_DH, & CKM_SSL3_MASTER_KEY_DERIVE_DH + * are new for v2.11. */ +#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373 +#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374 +#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375 +#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376 +#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377 + #define CKM_SSL3_MD5_MAC 0x00000380 #define CKM_SSL3_SHA1_MAC 0x00000381 #define CKM_MD5_KEY_DERIVATION 0x00000390 @@ -575,6 +725,10 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9 #define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA #define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB + +/* CKM_PKCS5_PBKD2 is new for v2.10 */ +#define CKM_PKCS5_PBKD2 0x000003B0 + #define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 #define CKM_KEY_WRAP_LYNKS 0x00000400 #define CKM_KEY_WRAP_SET_OAEP 0x00000401 @@ -601,12 +755,16 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_BATON_COUNTER 0x00001034 #define CKM_BATON_SHUFFLE 0x00001035 #define CKM_BATON_WRAP 0x00001036 - -/* PKCS #11 V2.01 probably won't actually have ECDSA in it */ -#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 +#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 /* depricated in v2.11 */ +#define CKM_EC_KEY_PAIR_GEN 0x00001040 #define CKM_ECDSA 0x00001041 #define CKM_ECDSA_SHA1 0x00001042 +/* ECDH1 is new for 2.11 */ +#define CKM_ECDH1_DERIVE 0x00001043 +#define CKM_ECDH1_COFACTOR_DERIVE 0x00001044 +#define CKM_ECMQV_DERIVE 0x00001045 + #define CKM_JUNIPER_KEY_GEN 0x00001060 #define CKM_JUNIPER_ECB128 0x00001061 #define CKM_JUNIPER_CBC128 0x00001062 @@ -615,6 +773,7 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_JUNIPER_WRAP 0x00001065 #define CKM_FASTHASH 0x00001070 +/* AES is new for 2.11 */ #define CKM_AES_KEY_GEN 0x00001080 #define CKM_AES_ECB 0x00001081 #define CKM_AES_CBC 0x00001082 @@ -622,6 +781,12 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_AES_MAC_GENERAL 0x00001084 #define CKM_AES_CBC_PAD 0x00001085 +/* CKM_DSA_PARAMETER_GEN, CKM_DH_PKCS_PARAMETER_GEN, + * and CKM_DH_X9_42_PARAMETER_GEN are new for 2.11 */ +#define CKM_DSA_PARAMETER_GEN 0x00002000 +#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001 +#define CKM_DH_X9_42_PARAMETER_GEN 0x00002002 + #define CKM_VENDOR_DEFINED 0x80000000 typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR; @@ -658,6 +823,8 @@ typedef struct CK_MECHANISM_INFO { * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP, * and CKF_DERIVE are new for v2.0. They specify whether or not * a mechanism can be used for a particular task */ +/* The flags CKF_EC_FP, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE, + * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11 */ #define CKF_ENCRYPT 0x00000100 #define CKF_DECRYPT 0x00000200 #define CKF_DIGEST 0x00000400 @@ -670,6 +837,12 @@ typedef struct CK_MECHANISM_INFO { #define CKF_WRAP 0x00020000 #define CKF_UNWRAP 0x00040000 #define CKF_DERIVE 0x00080000 +#define CKF_EC_FP 0x00100000 +#define CKF_EC_F_2M 0x00200000 +#define CKF_EC_ECPARAMETERS 0x00400000 +#define CKF_EC_NAMEDCURVE 0x00800000 +#define CKF_EC_UNCOMPRESS 0x01000000 +#define CKF_EC_COMPRESS 0x02000000 #define CKF_EXTENSION 0x80000000 /* FALSE for 2.01 */ @@ -735,6 +908,9 @@ typedef CK_ULONG CK_RV; #define CKR_KEY_NOT_WRAPPABLE 0x00000069 #define CKR_KEY_UNEXTRACTABLE 0x0000006A +/* CKR_KEY_PARAMS_INVALID is new for v2.11 */ +#define CKR_KEY_PARAMS_INVALID 0x0000006B + #define CKR_MECHANISM_INVALID 0x00000070 #define CKR_MECHANISM_PARAM_INVALID 0x00000071 @@ -790,8 +966,13 @@ typedef CK_ULONG CK_RV; #define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115 #define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120 -/* These are new to v2.0 */ +/* New for v2.0 */ #define CKR_RANDOM_NO_RNG 0x00000121 + +/* New for v2.11 */ +#define CKR_DOMAIN_PARAMS_INVALID 0x00000130 + +/* These are new to v2.0 */ #define CKR_BUFFER_TOO_SMALL 0x00000150 #define CKR_SAVED_STATE_INVALID 0x00000160 #define CKR_INFORMATION_SENSITIVE 0x00000170 @@ -878,6 +1059,41 @@ typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR; /* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */ #define CKF_DONT_BLOCK 1 +/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10. + * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message + * Generation Function (MGF) applied to a message block when + * formatting a message block for the PKCS #1 OAEP encryption + * scheme. */ +typedef CK_ULONG CK_RSA_PKCS_OAEP_MGF_TYPE; + +typedef CK_RSA_PKCS_OAEP_MGF_TYPE CK_PTR CK_RSA_PKCS_OAEP_MGF_TYPE_PTR; + +/* The following MGFs are defined */ +#define CKG_MGF1_SHA1 0x00000001 + +/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10. + * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source + * of the encoding parameter when formatting a message block + * for the PKCS #1 OAEP encryption scheme. */ +typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE; + +typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR; + +/* The following encoding parameter sources are defined */ +#define CKZ_DATA_SPECIFIED 0x00000001 + +/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10. + * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the + * CKM_RSA_PKCS_OAEP mechanism. */ +typedef struct CK_RSA_PKCS_OAEP_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_OAEP_MGF_TYPE mgf; + CK_RSA_PKCS_OAEP_SOURCE_TYPE source; + CK_VOID_PTR pSourceData; + CK_ULONG ulSourceDataLen; +} CK_RSA_PKCS_OAEP_PARAMS; + +typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR; /* CK_KEA_DERIVE_PARAMS provides the parameters to the * CKM_KEA_DERIVE mechanism */ @@ -1102,36 +1318,46 @@ typedef CK_ULONG CK_EXTRACT_PARAMS; typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; -/* Do not attempt to use these. They are only used by NETSCAPE's internal - * PKCS #11 interface. Most of these are place holders for other mechanism - * and will change in the future. - */ -#define CKM_NETSCAPE_PBE_KEY_GEN 0x80000001L -#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002L -#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003L -#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004L -#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005L -#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006L -#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007L -#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008L -#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009L -#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aL -#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bL -#define CKM_TLS_MASTER_KEY_DERIVE 0x80000371L -#define CKM_TLS_KEY_AND_MAC_DERIVE 0x80000372L -#define CKM_TLS_PRF_GENERAL 0x80000373L -#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x80000374L -#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x80000375L - -/* define used to pass in the database key for DSA private keys */ -#define CKA_NETSCAPE_DB 0xD5A0DB00L -#define CKA_NETSCAPE_TRUST 0x80000001L - -#define SECMOD_MODULE_DB_FUNCTION_FIND 0 -#define SECMOD_MODULE_DB_FUNCTION_ADD 1 -#define SECMOD_MODULE_DB_FUNCTION_DEL 2 -typedef char ** (PR_CALLBACK *SECMODModuleDBFunc)(unsigned long function, - char *parameters, char *moduleSpec); +/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10. + * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to + * indicate the Pseudo-Random Function (PRF) used to generate + * key bits using PKCS #5 PBKDF2. */ +typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE; + +typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR; + +/* The following PRFs are defined in PKCS #5 v2.0. */ +#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001 + + +/* CK_PKCS5_PBKD2_SALT_SOURCE_TYPE is new for v2.10. + * CK_PKCS5_PBKD2_SALT_SOURCE_TYPE is used to indicate the + * source of the salt value when deriving a key using PKCS #5 + * PBKDF2. */ +typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE; + +typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR; + +/* The following salt value sources are defined in PKCS #5 v2.0. */ +#define CKZ_SALT_SPECIFIED 0x00000001 + +/* CK_PKCS5_PBKD2_PARAMS is new for v2.10. + * CK_PKCS5_PBKD2_PARAMS is a structure that provides the + * parameters to the CKM_PKCS5_PBKD2 mechanism. */ +typedef struct CK_PKCS5_PBKD2_PARAMS { + CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; + CK_VOID_PTR pSaltSourceData; + CK_ULONG ulSaltSourceDataLen; + CK_ULONG iterations; + CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; + CK_VOID_PTR pPrfData; + CK_ULONG ulPrfDataLen; +} CK_PKCS5_PBKD2_PARAMS; + +typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR; + +/* Netscape Specific defines */ +#include "pkcs11n.h" /* undo packing */ #include "pkcs11u.h" diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c index 0aa42823a..1c8cd821a 100644 --- a/security/nss/lib/softoken/pkcs11u.c +++ b/security/nss/lib/softoken/pkcs11u.c @@ -35,18 +35,10 @@ */ #include "pkcs11.h" #include "pkcs11i.h" -#include "key.h" -#include "keylow.h" -#include "certdb.h" - - -/* declare the internal pkcs11 slot structures: - * There are threee: - * slot 0 is the generic crypto service token. - * slot 1 is the Database service token. - * slot 2 is the FIPS token (both generic and database). - */ -static PK11Slot pk11_slot[3]; +#include "pcertt.h" +#include "lowkeyi.h" +#include "pcert.h" +#include "secasn1.h" /* * ******************** Attribute Utilities ******************************* @@ -62,27 +54,36 @@ pk11_NewAttribute(PK11Object *object, { PK11Attribute *attribute; -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES + PK11SessionObject *so = pk11_narrowToSessionObject(object); int index; + + if (so == NULL) { + /* allocate new attribute in a buffer */ + PORT_Assert(0); + } /* - * NO_ARENA attempts to keep down contention on Malloc and Arena locks + * PKCS11_STATIC_ATTRIBUTES attempts to keep down contention on Malloc and Arena locks * by limiting the number of these calls on high traversed paths. this * is done for attributes by 'allocating' them from a pool already allocated * by the parent object. */ - PK11_USE_THREADS(PZ_Lock(object->attributeLock);) - index = object->nextAttr++; - PK11_USE_THREADS(PZ_Unlock(object->attributeLock);) + PK11_USE_THREADS(PZ_Lock(so->attributeLock);) + index = so->nextAttr++; + PK11_USE_THREADS(PZ_Unlock(so->attributeLock);) PORT_Assert(index < MAX_OBJS_ATTRS); if (index >= MAX_OBJS_ATTRS) return NULL; - attribute = &object->attrList[index]; + attribute = &so->attrList[index]; attribute->attrib.type = type; + attribute->freeAttr = PR_FALSE; + attribute->freeData = PR_FALSE; if (value) { if (len <= ATTR_SPACE) { attribute->attrib.pValue = attribute->space; } else { attribute->attrib.pValue = PORT_Alloc(len); + attribute->freeData = PR_TRUE; } if (attribute->attrib.pValue == NULL) { return NULL; @@ -94,23 +95,27 @@ pk11_NewAttribute(PK11Object *object, attribute->attrib.ulValueLen = 0; } #else -#ifdef REF_COUNT_ATTRIBUTE +#ifdef PKCS11_REF_COUNT_ATTRIBUTES attribute = (PK11Attribute*)PORT_Alloc(sizeof(PK11Attribute)); + attribute->freeAttr = PR_TRUE; #else attribute = (PK11Attribute*)PORT_ArenaAlloc(object->arena,sizeof(PK11Attribute)); -#endif /* REF_COUNT_ATTRIBUTE */ + attribute->freeAttr = PR_FALSE; +#endif /* PKCS11_REF_COUNT_ATTRIBUTES */ if (attribute == NULL) return NULL; + attribute->freeData = PR_FALSE; if (value) { -#ifdef REF_COUNT_ATTRIBUTE +#ifdef PKCS11_REF_COUNT_ATTRIBUTES attribute->attrib.pValue = PORT_Alloc(len); + attribute->freeData = PR_TRUE; #else attribute->attrib.pValue = PORT_ArenaAlloc(object->arena,len); -#endif /* REF_COUNT_ATTRIBUTE */ +#endif /* PKCS11_REF_COUNT_ATTRIBUTES */ if (attribute->attrib.pValue == NULL) { -#ifdef REF_COUNT_ATTRIBUTE +#ifdef PKCS11_REF_COUNT_ATTRIBUTES PORT_Free(attribute); -#endif /* REF_COUNT_ATTRIBUTE */ +#endif /* PKCS11_REF_COUNT_ATTRIBUTES */ return NULL; } PORT_Memcpy(attribute->attrib.pValue,value,len); @@ -119,11 +124,11 @@ pk11_NewAttribute(PK11Object *object, attribute->attrib.pValue = NULL; attribute->attrib.ulValueLen = 0; } -#endif /* NO_ARENA */ +#endif /* PKCS11_STATIC_ATTRIBUTES */ attribute->attrib.type = type; attribute->handle = type; attribute->next = attribute->prev = NULL; -#ifdef REF_COUNT_ATTRIBUTE +#ifdef PKCS11_REF_COUNT_ATTRIBUTES attribute->refCount = 1; #ifdef PKCS11_USE_THREADS attribute->refLock = PZ_NewLock(nssILockRefLock); @@ -135,31 +140,893 @@ pk11_NewAttribute(PK11Object *object, #else attribute->refLock = NULL; #endif -#endif /* REF_COUNT_ATTRIBUTE */ +#endif /* PKCS11_REF_COUNT_ATTRIBUTES */ + return attribute; +} + +static PK11Attribute * +pk11_NewTokenAttribute(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value, + CK_ULONG len, PRBool copy) +{ + PK11Attribute *attribute; + + attribute = (PK11Attribute*)PORT_Alloc(sizeof(PK11Attribute)); + + if (attribute == NULL) return NULL; + attribute->attrib.type = type; + attribute->handle = type; + attribute->next = attribute->prev = NULL; + attribute->freeAttr = PR_TRUE; + attribute->freeData = PR_FALSE; +#ifdef PKCS11_REF_COUNT_ATTRIBUTES + attribute->refCount = 1; +#ifdef PKCS11_USE_THREADS + attribute->refLock = PZ_NewLock(nssILockRefLock); + if (attribute->refLock == NULL) { + PORT_Free(attribute); + return NULL; + } +#else + attribute->refLock = NULL; +#endif +#endif /* PKCS11_REF_COUNT_ATTRIBUTES */ + attribute->attrib.type = type; + if (!copy) { + attribute->attrib.pValue = value; + attribute->attrib.ulValueLen = len; + return attribute; + } + + if (value) { +#ifdef PKCS11_STATIC_ATTRIBUTES + if (len <= ATTR_SPACE) { + attribute->attrib.pValue = attribute->space; + } else { + attribute->attrib.pValue = PORT_Alloc(len); + attribute->freeData = PR_TRUE; + } +#else + attribute->attrib.pValue = PORT_Alloc(len); + attribute->freeData = PR_TRUE; +#endif + if (attribute->attrib.pValue == NULL) { +#ifdef PKCS11_REF_COUNT_ATTRIBUTES + if (attribute->refLock) { + PK11_USE_THREADS(PZ_DestroyLock(attribute->refLock);) + } +#endif + PORT_Free(attribute); + return NULL; + } + PORT_Memcpy(attribute->attrib.pValue,value,len); + attribute->attrib.ulValueLen = len; + } else { + attribute->attrib.pValue = NULL; + attribute->attrib.ulValueLen = 0; + } return attribute; } +static PK11Attribute * +pk11_NewTokenAttributeSigned(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value, + CK_ULONG len, PRBool copy) +{ + unsigned char * dval = (unsigned char *)value; + if (*dval == 0) { + dval++; + len--; + } + return pk11_NewTokenAttribute(type,dval,len,copy); +} + /* * Free up all the memory associated with an attribute. Reference count * must be zero to call this. */ -#ifdef REF_COUNT_ATTRIBUTE static void pk11_DestroyAttribute(PK11Attribute *attribute) { +#ifdef PKCS11_REF_COUNT_ATTRIBUTES PORT_Assert(attribute->refCount == 0); PK11_USE_THREADS(PZ_DestroyLock(attribute->refLock);) - if (attribute->attrib.pValue) { - /* clear out the data in the attribute value... it may have been - * sensitive data */ - PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen); - PORT_Free(attribute->attrib.pValue); +#endif + if (attribute->freeData) { + if (attribute->attrib.pValue) { + /* clear out the data in the attribute value... it may have been + * sensitive data */ + PORT_Memset(attribute->attrib.pValue, 0, + attribute->attrib.ulValueLen); + } + PORT_Free(attribute->attrib.pValue); } PORT_Free(attribute); } + +/* + * release a reference to an attribute structure + */ +void +pk11_FreeAttribute(PK11Attribute *attribute) +{ +#ifdef PKCS11_REF_COUNT_ATTRIBUTES + PRBool destroy = PR_FALSE; #endif + + if (attribute->freeAttr) { + pk11_DestroyAttribute(attribute); + return; + } + +#ifdef PKCS11_REF_COUNT_ATTRIBUTES + PK11_USE_THREADS(PZ_Lock(attribute->refLock);) + if (attribute->refCount == 1) destroy = PR_TRUE; + attribute->refCount--; + PK11_USE_THREADS(PZ_Unlock(attribute->refLock);) + + if (destroy) pk11_DestroyAttribute(attribute); +#endif +} + +#ifdef PKCS11_REF_COUNT_ATTRIBUTES +#define PK11_DEF_ATTRIBUTE(value,len) \ + { NULL, NULL, PR_FALSE, PR_FALSE, 1, NULL, 0, { 0, value, len } } + +#else +#define PK11_DEF_ATTRIBUTE(value,len) \ + { NULL, NULL, PR_FALSE, PR_FALSE, 0, { 0, value, len } } +#endif + +CK_BBOOL pk11_staticTrueValue = CK_TRUE; +CK_BBOOL pk11_staticFalseValue = CK_FALSE; +static const PK11Attribute pk11_StaticTrueAttr = + PK11_DEF_ATTRIBUTE(&pk11_staticTrueValue,sizeof(pk11_staticTrueValue)); +static const PK11Attribute pk11_StaticFalseAttr = + PK11_DEF_ATTRIBUTE(&pk11_staticFalseValue,sizeof(pk11_staticFalseValue)); +static const PK11Attribute pk11_StaticNullAttr = PK11_DEF_ATTRIBUTE(NULL,0); + +CK_CERTIFICATE_TYPE pk11_staticX509Value = CKC_X_509; +static const PK11Attribute pk11_StaticX509Attr = + PK11_DEF_ATTRIBUTE(&pk11_staticX509Value, sizeof(pk11_staticX509Value)); +CK_TRUST pk11_staticTrustedValue = CKT_NETSCAPE_TRUSTED; +CK_TRUST pk11_staticTrustedDelegatorValue = CKT_NETSCAPE_TRUSTED_DELEGATOR; +CK_TRUST pk11_staticUnTrustedValue = CKT_NETSCAPE_UNTRUSTED; +CK_TRUST pk11_staticTrustUnknownValue = CKT_NETSCAPE_TRUST_UNKNOWN; +CK_TRUST pk11_staticMustVerifyValue = CKT_NETSCAPE_MUST_VERIFY; +static const PK11Attribute pk11_StaticTrustedAttr = + PK11_DEF_ATTRIBUTE(&pk11_staticTrustedValue, + sizeof(pk11_staticTrustedValue)); +static const PK11Attribute pk11_StaticTrustedDelegatorAttr = + PK11_DEF_ATTRIBUTE(&pk11_staticTrustedDelegatorValue, + sizeof(pk11_staticTrustedDelegatorValue)); +static const PK11Attribute pk11_StaticUnTrustedAttr = + PK11_DEF_ATTRIBUTE(&pk11_staticUnTrustedValue, + sizeof(pk11_staticUnTrustedValue)); +static const PK11Attribute pk11_StaticTrustUnknownAttr = + PK11_DEF_ATTRIBUTE(&pk11_staticTrustUnknownValue, + sizeof(pk11_staticTrustUnknownValue)); +static const PK11Attribute pk11_StaticMustVerifyAttr = + PK11_DEF_ATTRIBUTE(&pk11_staticMustVerifyValue, + sizeof(pk11_staticMustVerifyValue)); + +static void pk11_FreeItem(SECItem *item) +{ + SECITEM_FreeItem(item, PR_TRUE); +} + +static certDBEntrySMime * +pk11_getSMime(PK11TokenObject *object) +{ + certDBEntrySMime *entry; + + if (object->obj.objclass != CKO_NETSCAPE_SMIME) { + return NULL; + } + if (object->obj.objectInfo) { + return (certDBEntrySMime *)object->obj.objectInfo; + } + + entry = nsslowcert_ReadDBSMimeEntry(object->obj.slot->certDB, + (char *)object->dbKey.data); + object->obj.objectInfo = (void *)entry; + object->obj.infoFree = (PK11Free) nsslowcert_DestroyDBEntry; + return entry; +} + +static SECItem * +pk11_getCrl(PK11TokenObject *object) +{ + SECItem *crl; + PRBool isKrl; + + if (object->obj.objclass != CKO_NETSCAPE_CRL) { + return NULL; + } + if (object->obj.objectInfo) { + return (SECItem *)object->obj.objectInfo; + } + + isKrl = (PRBool) object->obj.handle == PK11_TOKEN_KRL_HANDLE; + crl = nsslowcert_FindCrlByKey(object->obj.slot->certDB,&object->dbKey, + NULL,isKrl); + object->obj.objectInfo = (void *)crl; + object->obj.infoFree = (PK11Free) pk11_FreeItem; + return crl; +} + +static char * +pk11_getUrl(PK11TokenObject *object) +{ + SECItem *crl; + PRBool isKrl; + char *url = NULL; + + if (object->obj.objclass != CKO_NETSCAPE_CRL) { + return NULL; + } + + isKrl = (PRBool) object->obj.handle == PK11_TOKEN_KRL_HANDLE; + crl = nsslowcert_FindCrlByKey(object->obj.slot->certDB,&object->dbKey, + &url,isKrl); + if (object->obj.objectInfo == NULL) { + object->obj.objectInfo = (void *)crl; + object->obj.infoFree = (PK11Free) pk11_FreeItem; + } else { + if (crl) SECITEM_FreeItem(crl,PR_TRUE); + } + return url; +} + +static NSSLOWCERTCertificate * +pk11_getCert(PK11TokenObject *object) +{ + NSSLOWCERTCertificate *cert; + + if ((object->obj.objclass != CKO_CERTIFICATE) && + (object->obj.objclass != CKO_NETSCAPE_TRUST)) { + return NULL; + } + if (object->obj.objectInfo) { + return (NSSLOWCERTCertificate *)object->obj.objectInfo; + } + cert = nsslowcert_FindCertByKey(object->obj.slot->certDB,&object->dbKey); + object->obj.objectInfo = (void *)cert; + object->obj.infoFree = (PK11Free) nsslowcert_DestroyCertificate ; + return cert; +} + +static NSSLOWKEYPublicKey * +pk11_GetPublicKey(PK11TokenObject *object) +{ + NSSLOWKEYPublicKey *pubKey; + NSSLOWKEYPrivateKey *privKey; + + if (object->obj.objclass != CKO_PUBLIC_KEY) { + return NULL; + } + if (object->obj.objectInfo) { + return (NSSLOWKEYPublicKey *)object->obj.objectInfo; + } + privKey = nsslowkey_FindKeyByPublicKey(object->obj.slot->keyDB, + &object->dbKey, object->obj.slot->password); + pubKey = nsslowkey_ConvertToPublicKey(privKey); + nsslowkey_DestroyPrivateKey(privKey); + object->obj.objectInfo = (void *) pubKey; + object->obj.infoFree = (PK11Free) nsslowkey_DestroyPublicKey ; + return pubKey; +} + +static NSSLOWKEYPrivateKey * +pk11_GetPrivateKey(PK11TokenObject *object) +{ + NSSLOWKEYPrivateKey *privKey; + + if ((object->obj.objclass != CKO_PRIVATE_KEY) && + (object->obj.objclass != CKO_SECRET_KEY)) { + return NULL; + } + if (object->obj.objectInfo) { + return (NSSLOWKEYPrivateKey *)object->obj.objectInfo; + } + privKey = nsslowkey_FindKeyByPublicKey(object->obj.slot->keyDB, + &object->dbKey, object->obj.slot->password); + object->obj.objectInfo = (void *) privKey; + object->obj.infoFree = (PK11Free) nsslowkey_DestroyPrivateKey ; + return privKey; +} + +/* pk11_GetPubItem returns data associated with the public key. + * one only needs to free the public key. This comment is here + * because this sematic would be non-obvious otherwise. All callers + * should include this comment. + */ +static SECItem * +pk11_GetPubItem(NSSLOWKEYPublicKey *pubKey) { + SECItem *pubItem = NULL; + /* get value to compare from the cert's public key */ + switch ( pubKey->keyType ) { + case NSSLOWKEYRSAKey: + pubItem = &pubKey->u.rsa.modulus; + break; + case NSSLOWKEYDSAKey: + pubItem = &pubKey->u.dsa.publicValue; + break; + case NSSLOWKEYDHKey: + pubItem = &pubKey->u.dh.publicValue; + break; + default: + break; + } + return pubItem; +} + +static const SEC_ASN1Template pk11_SerialTemplate[] = { + { SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertificate,serialNumber) }, + { 0 } +}; + +static PK11Attribute * +pk11_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_RSA; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_ENCRYPT: + case CKA_VERIFY: + case CKA_VERIFY_RECOVER: + case CKA_WRAP: + return (PK11Attribute *) &pk11_StaticTrueAttr; + default: + case CKA_MODULUS: + return pk11_NewTokenAttributeSigned(type,key->u.rsa.modulus.data, + key->u.rsa.modulus.len, PR_FALSE); + case CKA_PUBLIC_EXPONENT: + return pk11_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data, + key->u.rsa.publicExponent.len, PR_FALSE); + break; + } + return NULL; +} + +static PK11Attribute * +pk11_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_DSA; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash,key->u.dsa.publicValue.data, + key->u.dsa.publicValue.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + case CKA_ENCRYPT: + case CKA_VERIFY_RECOVER: + case CKA_WRAP: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_VERIFY: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_VALUE: + return pk11_NewTokenAttributeSigned(type,key->u.dsa.publicValue.data, + key->u.dsa.publicValue.len, PR_FALSE); + case CKA_PRIME: + return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data, + key->u.dsa.params.prime.len, PR_FALSE); + case CKA_SUBPRIME: + return pk11_NewTokenAttributeSigned(type, + key->u.dsa.params.subPrime.data, + key->u.dsa.params.subPrime.len, PR_FALSE); + case CKA_BASE: + return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.base.data, + key->u.dsa.params.base.len, PR_FALSE); + default: + break; + } + return NULL; +} + +static PK11Attribute * +pk11_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_DH; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_ENCRYPT: + case CKA_VERIFY: + case CKA_VERIFY_RECOVER: + case CKA_WRAP: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_VALUE: + return pk11_NewTokenAttributeSigned(type,key->u.dh.publicValue.data, + key->u.dh.publicValue.len, PR_FALSE); + case CKA_PRIME: + return pk11_NewTokenAttributeSigned(type,key->u.dh.prime.data, + key->u.dh.prime.len, PR_FALSE); + case CKA_BASE: + return pk11_NewTokenAttributeSigned(type,key->u.dh.base.data, + key->u.dh.base.len, PR_FALSE); + default: + break; + } + return NULL; +} + +static PK11Attribute * +pk11_FindPublicKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + NSSLOWKEYPublicKey *key; + + switch (type) { + case CKA_PRIVATE: + case CKA_SENSITIVE: + case CKA_ALWAYS_SENSITIVE: + case CKA_NEVER_EXTRACTABLE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_MODIFIABLE: + case CKA_EXTRACTABLE: + return (PK11Attribute *) &pk11_StaticTrueAttr; + default: + break; + } + + key = pk11_GetPublicKey(object); + if (key == NULL) { + return NULL; + } + switch (key->keyType) { + case NSSLOWKEYRSAKey: + return pk11_FindRSAPublicKeyAttribute(key,type); + case NSSLOWKEYDSAKey: + return pk11_FindDSAPublicKeyAttribute(key,type); + case NSSLOWKEYDHKey: + return pk11_FindDHPublicKeyAttribute(key,type); + default: + break; + } + + return NULL; +} + +static PK11Attribute * +pk11_FindSecretKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + NSSLOWKEYPrivateKey *key; + switch (type) { + case CKA_PRIVATE: + case CKA_SENSITIVE: + case CKA_ALWAYS_SENSITIVE: + case CKA_EXTRACTABLE: + case CKA_DERIVE: + case CKA_ENCRYPT: + case CKA_DECRYPT: + case CKA_SIGN: + case CKA_VERIFY: + case CKA_WRAP: + case CKA_UNWRAP: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_NEVER_EXTRACTABLE: + case CKA_MODIFIABLE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_VALUE: + return (PK11Attribute *) &pk11_StaticNullAttr; + default: + break; + } + + key = pk11_GetPrivateKey(object); + if (key == NULL) { + return NULL; + } + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,key->u.rsa.coefficient.data, + key->u.rsa.coefficient.len, PR_FALSE); + case CKA_VALUE: + return pk11_NewTokenAttribute(type,key->u.rsa.privateExponent.data, + key->u.rsa.privateExponent.len, PR_FALSE); + } + + return NULL; +} + +static PK11Attribute * +pk11_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, + CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_RSA; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_DECRYPT: + case CKA_SIGN: + case CKA_SIGN_RECOVER: + case CKA_UNWRAP: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_MODULUS: + return pk11_NewTokenAttributeSigned(type,key->u.rsa.modulus.data, + key->u.rsa.modulus.len, PR_FALSE); + case CKA_PUBLIC_EXPONENT: + return pk11_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data, + key->u.rsa.publicExponent.len, PR_FALSE); + case CKA_PRIVATE_EXPONENT: + case CKA_PRIME_1: + case CKA_PRIME_2: + case CKA_EXPONENT_1: + case CKA_EXPONENT_2: + case CKA_COEFFICIENT: + return (PK11Attribute *) &pk11_StaticNullAttr; + default: + break; + } + return NULL; +} + +static PK11Attribute * +pk11_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, + CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_DSA; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash,key->u.dsa.publicValue.data, + key->u.dsa.publicValue.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + case CKA_DECRYPT: + case CKA_SIGN_RECOVER: + case CKA_UNWRAP: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_SIGN: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_VALUE: + return (PK11Attribute *) &pk11_StaticNullAttr; + case CKA_PRIME: + return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data, + key->u.dsa.params.prime.len, PR_FALSE); + case CKA_SUBPRIME: + return pk11_NewTokenAttributeSigned(type, + key->u.dsa.params.subPrime.data, + key->u.dsa.params.subPrime.len, PR_FALSE); + case CKA_BASE: + return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.base.data, + key->u.dsa.params.base.len, PR_FALSE); + default: + break; + } + return NULL; +} + +static PK11Attribute * +pk11_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_DH; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_DECRYPT: + case CKA_SIGN: + case CKA_SIGN_RECOVER: + case CKA_UNWRAP: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_VALUE: + return (PK11Attribute *) &pk11_StaticNullAttr; + case CKA_PRIME: + return pk11_NewTokenAttributeSigned(type,key->u.dh.prime.data, + key->u.dh.prime.len, PR_FALSE); + case CKA_BASE: + return pk11_NewTokenAttributeSigned(type,key->u.dh.base.data, + key->u.dh.base.len, PR_FALSE); + default: + break; + } + return NULL; +} + +static PK11Attribute * +pk11_FindPrivateKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + NSSLOWKEYPrivateKey *key; + switch (type) { + case CKA_PRIVATE: + case CKA_SENSITIVE: + case CKA_ALWAYS_SENSITIVE: + case CKA_EXTRACTABLE: + case CKA_MODIFIABLE: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_NEVER_EXTRACTABLE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + default: + break; + } + key = pk11_GetPrivateKey(object); + if (key == NULL) { + return NULL; + } + switch (key->keyType) { + case NSSLOWKEYRSAKey: + return pk11_FindRSAPrivateKeyAttribute(key,type); + case NSSLOWKEYDSAKey: + return pk11_FindDSAPrivateKeyAttribute(key,type); + case NSSLOWKEYDHKey: + return pk11_FindDHPrivateKeyAttribute(key,type); + default: + break; + } + + return NULL; +} + +static PK11Attribute * +pk11_FindSMIMEAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + certDBEntrySMime *entry; + switch (type) { + case CKA_PRIVATE: + case CKA_MODIFIABLE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_NETSCAPE_EMAIL: + return pk11_NewTokenAttribute(type,object->dbKey.data, + object->dbKey.len, PR_FALSE); + default: + break; + } + entry = pk11_getSMime(object); + if (entry == NULL) { + return NULL; + } + switch (type) { + case CKA_NETSCAPE_SMIME_TIMESTAMP: + return pk11_NewTokenAttribute(type,entry->optionsDate.data, + entry->optionsDate.len, PR_FALSE); + case CKA_SUBJECT: + return pk11_NewTokenAttribute(type,entry->subjectName.data, + entry->subjectName.len, PR_FALSE); + case CKA_VALUE: + return pk11_NewTokenAttribute(type,entry->smimeOptions.data, + entry->smimeOptions.len, PR_FALSE); + default: + break; + } + return NULL; +} + +static PK11Attribute * +pk11_FindTrustAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + NSSLOWCERTCertificate *cert; + unsigned char hash[SHA1_LENGTH]; + SECItem *item; + PK11Attribute *attr; + unsigned int trustFlags; + + switch (type) { + case CKA_PRIVATE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_MODIFIABLE: + return (PK11Attribute *) &pk11_StaticTrueAttr; + default: + break; + } + cert = pk11_getCert(object); + if (cert == NULL) { + return NULL; + } + switch (type) { + case CKA_CERT_SHA1_HASH: + SHA1_HashBuf(hash,cert->derCert.data,cert->derCert.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_CERT_MD5_HASH: + MD5_HashBuf(hash,cert->derCert.data,cert->derCert.len); + return pk11_NewTokenAttribute(type,hash,MD5_LENGTH, PR_TRUE); + case CKA_ISSUER: + return pk11_NewTokenAttribute(type,cert->derIssuer.data, + cert->derIssuer.len, PR_FALSE); + case CKA_SERIAL_NUMBER: + item = SEC_ASN1EncodeItem(NULL,NULL,cert,pk11_SerialTemplate); + if (item == NULL) break; + attr = pk11_NewTokenAttribute(type, item->data, item->len, PR_TRUE); + SECITEM_FreeItem(item,PR_TRUE); + return attr; + case CKA_TRUST_CLIENT_AUTH: + trustFlags = cert->trust->sslFlags & CERTDB_TRUSTED_CLIENT_CA ? + cert->trust->sslFlags | CERTDB_TRUSTED_CA : 0 ; + goto trust; + case CKA_TRUST_SERVER_AUTH: + trustFlags = cert->trust->sslFlags; + goto trust; + case CKA_TRUST_EMAIL_PROTECTION: + trustFlags = cert->trust->emailFlags; + goto trust; + case CKA_TRUST_CODE_SIGNING: + trustFlags = cert->trust->objectSigningFlags; +trust: + if (trustFlags & CERTDB_TRUSTED_CA ) { + return (PK11Attribute *)&pk11_StaticTrustedDelegatorAttr; + } + if (trustFlags & CERTDB_TRUSTED) { + return (PK11Attribute *)&pk11_StaticTrustedAttr; + } + if (trustFlags & CERTDB_NOT_TRUSTED) { + return (PK11Attribute *)&pk11_StaticUnTrustedAttr; + } + if (trustFlags & CERTDB_TRUSTED_UNKNOWN) { + return (PK11Attribute *)&pk11_StaticTrustUnknownAttr; + } + return (PK11Attribute *)&pk11_StaticMustVerifyAttr; + default: + break; + } + return NULL; +} + +static PK11Attribute * +pk11_FindCrlAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + SECItem *crl; + char *url; + + switch (type) { + case CKA_PRIVATE: + case CKA_MODIFIABLE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_NETSCAPE_KRL: + return (PK11Attribute *) ((object->obj.handle == PK11_TOKEN_KRL_HANDLE) + ? &pk11_StaticTrueAttr : &pk11_StaticFalseAttr); + case CKA_NETSCAPE_URL: + url = pk11_getUrl(object); + if (url == NULL) { + return (PK11Attribute *) &pk11_StaticNullAttr; + } + return pk11_NewTokenAttribute(type, url, PORT_Strlen(url)+1, PR_TRUE); + case CKA_VALUE: + crl = pk11_getCrl(object); + if (crl == NULL) break; + return pk11_NewTokenAttribute(type, crl->data, crl->len, PR_FALSE); + case CKA_SUBJECT: + return pk11_NewTokenAttribute(type,object->dbKey.data, + object->dbKey.len, PR_FALSE); + default: + break; + } + return NULL; +} + +static PK11Attribute * +pk11_FindCertAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + NSSLOWCERTCertificate *cert; + NSSLOWKEYPublicKey *pubKey; + unsigned char hash[SHA1_LENGTH]; + SECItem *item; + PK11Attribute *attr; + + switch (type) { + case CKA_PRIVATE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_MODIFIABLE: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_CERTIFICATE_TYPE: + /* hardcoding X.509 into here */ + return (PK11Attribute *)&pk11_StaticX509Attr; + default: + break; + } + cert = pk11_getCert(object); + if (cert == NULL) { + return NULL; + } + switch (type) { + case CKA_VALUE: + return pk11_NewTokenAttribute(type,cert->derCert.data, + cert->derCert.len,PR_FALSE); + case CKA_ID: + pubKey = nsslowcert_ExtractPublicKey(cert); + if (pubKey == NULL) break; + item = pk11_GetPubItem(pubKey); + if (item == NULL) { + nsslowkey_DestroyPublicKey(pubKey); + break; + } + SHA1_HashBuf(hash,item->data,item->len); + /* item is imbedded in pubKey, just free the key */ + nsslowkey_DestroyPublicKey(pubKey); + return pk11_NewTokenAttribute(type, hash, SHA1_LENGTH, PR_TRUE); + case CKA_LABEL: + return cert->nickname ? pk11_NewTokenAttribute(type, cert->nickname, + PORT_Strlen(cert->nickname)+1, PR_FALSE) : + (PK11Attribute *) &pk11_StaticNullAttr; + case CKA_SUBJECT: + return pk11_NewTokenAttribute(type,cert->derSubject.data, + cert->derSubject.len, PR_FALSE); + case CKA_ISSUER: + return pk11_NewTokenAttribute(type,cert->derIssuer.data, + cert->derIssuer.len, PR_FALSE); + case CKA_SERIAL_NUMBER: + item = SEC_ASN1EncodeItem(NULL,NULL,cert,pk11_SerialTemplate); + if (item == NULL) break; + attr = pk11_NewTokenAttribute(type, item->data, item->len, PR_TRUE); + SECITEM_FreeItem(item,PR_TRUE); + return attr; + default: + break; + } + return NULL; +} - +static PK11Attribute * +pk11_FindTokenAttribute(PK11TokenObject *object,CK_ATTRIBUTE_TYPE type) +{ + /* handle the common ones */ + switch (type) { + case CKA_CLASS: + return pk11_NewTokenAttribute(type,&object->obj.objclass, + sizeof(object->obj.objclass),PR_FALSE); + case CKA_TOKEN: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_LABEL: + return (object->obj.objclass != CKO_CERTIFICATE) ? + (PK11Attribute *) &pk11_StaticNullAttr : + pk11_FindCertAttribute(object,type); + default: + break; + } + switch (object->obj.objclass) { + case CKO_CERTIFICATE: + return pk11_FindCertAttribute(object,type); + case CKO_NETSCAPE_CRL: + return pk11_FindCrlAttribute(object,type); + case CKO_NETSCAPE_TRUST: + return pk11_FindTrustAttribute(object,type); + case CKO_NETSCAPE_SMIME: + return pk11_FindSMIMEAttribute(object,type); + case CKO_PUBLIC_KEY: + return pk11_FindPublicKeyAttribute(object,type); + case CKO_PRIVATE_KEY: + return pk11_FindPrivateKeyAttribute(object,type); + case CKO_SECRET_KEY: + return pk11_FindSecretKeyAttribute(object,type); + default: + break; + } + PORT_Assert(0); + return NULL; +} + /* * look up and attribute structure from a type and Object structure. * The returned attribute is referenced and needs to be freed when @@ -169,10 +1036,15 @@ PK11Attribute * pk11_FindAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) { PK11Attribute *attribute; + PK11SessionObject *sessObject = pk11_narrowToSessionObject(object); + + if (sessObject == NULL) { + return pk11_FindTokenAttribute(pk11_narrowToTokenObject(object),type); + } - PK11_USE_THREADS(PZ_Lock(object->attributeLock);) - pk11queue_find(attribute,type,object->head,ATTRIBUTE_HASH_SIZE); -#ifdef REF_COUNT_ATTRIBUTE + PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);) + pk11queue_find(attribute,type,sessObject->head,ATTRIBUTE_HASH_SIZE); +#ifdef PKCS11_REF_COUNT_ATTRIBUTES if (attribute) { /* atomic increment would be nice here */ PK11_USE_THREADS(PZ_Lock(attribute->refLock);) @@ -180,31 +1052,19 @@ pk11_FindAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) PK11_USE_THREADS(PZ_Unlock(attribute->refLock);) } #endif - PK11_USE_THREADS(PZ_Unlock(object->attributeLock);) + PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);) return(attribute); } -/* - * release a reference to an attribute structure - */ -void -pk11_FreeAttribute(PK11Attribute *attribute) -{ -#ifdef REF_COUNT_ATTRIBUTE - PRBool destroy = PR_FALSE; - - PK11_USE_THREADS(PZ_Lock(attribute->refLock);) - if (attribute->refCount == 1) destroy = PR_TRUE; - attribute->refCount--; - PK11_USE_THREADS(PZ_Unlock(attribute->refLock);) - if (destroy) pk11_DestroyAttribute(attribute); -#endif +PRBool +pk11_hasAttributeToken(PK11TokenObject *object) +{ + return PR_FALSE; } - /* * return true if object has attribute */ @@ -212,10 +1072,15 @@ PRBool pk11_hasAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) { PK11Attribute *attribute; + PK11SessionObject *sessObject = pk11_narrowToSessionObject(object); - PK11_USE_THREADS(PZ_Lock(object->attributeLock);) - pk11queue_find(attribute,type,object->head,ATTRIBUTE_HASH_SIZE); - PK11_USE_THREADS(PZ_Unlock(object->attributeLock);) + if (sessObject == NULL) { + return pk11_hasAttributeToken(pk11_narrowToTokenObject(object)); + } + + PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);) + pk11queue_find(attribute,type,sessObject->head,ATTRIBUTE_HASH_SIZE); + PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);) return (PRBool)(attribute != NULL); } @@ -223,12 +1088,16 @@ pk11_hasAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) /* * add an attribute to an object */ -static -void pk11_AddAttribute(PK11Object *object,PK11Attribute *attribute) +static void +pk11_AddAttribute(PK11Object *object,PK11Attribute *attribute) { - PK11_USE_THREADS(PZ_Lock(object->attributeLock);) - pk11queue_add(attribute,attribute->handle,object->head,ATTRIBUTE_HASH_SIZE); - PK11_USE_THREADS(PZ_Unlock(object->attributeLock);) + PK11SessionObject *sessObject = pk11_narrowToSessionObject(object); + + if (sessObject == NULL) return; + PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);) + pk11queue_add(attribute,attribute->handle, + sessObject->head,ATTRIBUTE_HASH_SIZE); + PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);) } /* @@ -277,13 +1146,18 @@ pk11_Attribute2SSecItem(PLArenaPool *arena,SECItem *item,PK11Object *object, static void pk11_DeleteAttribute(PK11Object *object, PK11Attribute *attribute) { - PK11_USE_THREADS(PZ_Lock(object->attributeLock);) + PK11SessionObject *sessObject = pk11_narrowToSessionObject(object); + + if (sessObject == NULL) { + return ; + } + PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);) if (pk11queue_is_queued(attribute,attribute->handle, - object->head,ATTRIBUTE_HASH_SIZE)) { + sessObject->head,ATTRIBUTE_HASH_SIZE)) { pk11queue_delete(attribute,attribute->handle, - object->head,ATTRIBUTE_HASH_SIZE); + sessObject->head,ATTRIBUTE_HASH_SIZE); } - PK11_USE_THREADS(PZ_Unlock(object->attributeLock);) + PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);) pk11_FreeAttribute(attribute); } @@ -320,20 +1194,106 @@ pk11_nullAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) if (attribute->attrib.pValue != NULL) { PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen); -#ifdef REF_COUNT_ATTRIBUTE - PORT_Free(attribute->attrib.pValue); -#endif /* REF_COUNT_ATTRIBUTE */ -#ifdef NO_ARENA - if (attribute->attrib.pValue != attribute->space) { + if (attribute->freeData) { PORT_Free(attribute->attrib.pValue); } -#endif /* NO_ARENA */ + attribute->freeData = PR_FALSE; attribute->attrib.pValue = NULL; attribute->attrib.ulValueLen = 0; } pk11_FreeAttribute(attribute); } +static CK_RV +pk11_SetTrustAttribute(PK11TokenObject *to, CK_ATTRIBUTE_TYPE type, + void *value, unsigned int len) +{ + unsigned int flags; + CK_TRUST trust; + NSSLOWCERTCertificate *cert; + NSSLOWCERTCertTrust dbTrust; + SECStatus rv; + + if (to->obj.slot->certDB == NULL) { + return CKR_TOKEN_WRITE_PROTECTED; + } + if (len != sizeof (CK_TRUST)) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + trust = *(CK_TRUST *)value; + flags = pk11_MapTrust(trust, (PRBool) (type == CKA_TRUST_SERVER_AUTH)); + + cert = pk11_getCert(to); + if (cert == NULL) { + return CKR_OBJECT_HANDLE_INVALID; + } + dbTrust = *cert->trust; + + switch (type) { + case CKA_TRUST_EMAIL_PROTECTION: + dbTrust.emailFlags = flags | + (cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS); + break; + case CKA_TRUST_CODE_SIGNING: + dbTrust.objectSigningFlags = flags | + (cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS); + break; + case CKA_TRUST_CLIENT_AUTH: + dbTrust.sslFlags = flags | (cert->trust->sslFlags & + CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CA); + break; + case CKA_TRUST_SERVER_AUTH: + dbTrust.sslFlags = flags | (cert->trust->sslFlags & + CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CLIENT_CA); + break; + default: + return CKR_ATTRIBUTE_READ_ONLY; + } + + rv = nsslowcert_ChangeCertTrust(to->obj.slot->certDB,cert,&dbTrust); + if (rv != SECSuccess) { + return CKR_DEVICE_ERROR; + } + return CKR_OK; +} + +static CK_RV +pk11_forceTokenAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, + void *value, unsigned int len) +{ + PK11Attribute *attribute; + PK11TokenObject *to = pk11_narrowToTokenObject(object); + CK_RV crv = CKR_ATTRIBUTE_READ_ONLY; + + PORT_Assert(to); + if (to == NULL) { + return CKR_DEVICE_ERROR; + } + + /* if we are just setting it to the value we already have, + * allow it to happen. */ + attribute=pk11_FindAttribute(object,type); + if ((attribute->attrib.ulValueLen == len) && + PORT_Memcmp(attribute->attrib.pValue,value,len) == 0) { + pk11_FreeAttribute(attribute); + return CKR_OK; + } + + switch (object->objclass) { + case CKO_CERTIFICATE: + /* change NICKNAME, EMAIL, */ + break; + case CKO_NETSCAPE_CRL: + /* change URL */ + break; + case CKO_NETSCAPE_TRUST: + crv = pk11_SetTrustAttribute(to,type,value,len); + break; + } + pk11_FreeAttribute(attribute); + return crv; +} + /* * force an attribute to a spaecif value. */ @@ -343,25 +1303,31 @@ pk11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, void *value, { PK11Attribute *attribute; void *att_val = NULL; + PRBool freeData = PR_FALSE; + if (pk11_isToken(object->handle)) { + return pk11_forceTokenAttribute(object,type,value,len); + } attribute=pk11_FindAttribute(object,type); if (attribute == NULL) return pk11_AddAttributeType(object,type,value,len); if (value) { -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES if (len <= ATTR_SPACE) { att_val = attribute->space; } else { att_val = PORT_Alloc(len); + freeData = PR_TRUE; } #else -#ifdef REF_COUNT_ATTRIBUTE +#ifdef PKCS11_REF_COUNT_ATTRIBUTES att_val = PORT_Alloc(len); + freeData = PR_TRUE; #else att_val = PORT_ArenaAlloc(object->arena,len); -#endif /* REF_COUNT_ATTRIBUTE */ -#endif /* NO_ARENA */ +#endif /* PKCS11_REF_COUNT_ATTRIBUTES */ +#endif /* PKCS11_STATIC_ATTRIBUTES */ if (att_val == NULL) { return CKR_HOST_MEMORY; } @@ -376,21 +1342,19 @@ pk11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, void *value, PORT_Memset(attribute->attrib.pValue,0, attribute->attrib.ulValueLen); } -#ifdef REF_COUNT_ATTRIBUTE - PORT_Free(attribute->attrib.pValue); -#endif /* REF_COUNT_ATTRIBUTE */ -#ifdef NO_ARENA - if (attribute->attrib.pValue != attribute->space) { + if (attribute->freeData) { PORT_Free(attribute->attrib.pValue); } -#endif /* NO_ARENA */ + attribute->freeData = PR_FALSE; attribute->attrib.pValue = NULL; attribute->attrib.ulValueLen = 0; } if (att_val) { attribute->attrib.pValue = att_val; attribute->attrib.ulValueLen = len; + attribute->freeData = freeData; } + pk11_FreeAttribute(attribute); return CKR_OK; } @@ -591,6 +1555,62 @@ pk11_AddAttributeType(PK11Object *object,CK_ATTRIBUTE_TYPE type,void *valPtr, * ******************** Object Utilities ******************************* */ +static SECStatus +pk11_deleteTokenKeyByHandle(PK11Slot *slot, CK_OBJECT_HANDLE handle) +{ + SECItem *item; + PRBool rem; + + item = (SECItem *)PL_HashTableLookupConst(slot->tokenHashTable, + (void *)handle); + if (item) { + SECITEM_FreeItem(item,PR_TRUE); + } + rem = PL_HashTableRemove(slot->tokenHashTable,(void *)handle) ; + return rem ? SECSuccess : SECFailure; +} + +static SECStatus +pk11_addTokenKeyByHandle(PK11Slot *slot, CK_OBJECT_HANDLE handle, SECItem *key) +{ + PLHashEntry *entry; + SECItem *item; + + item = SECITEM_DupItem(key); + if (item == NULL) { + return SECFailure; + } + entry = PL_HashTableAdd(slot->tokenHashTable,(void *)handle,item); + if (entry == NULL) { + SECITEM_FreeItem(item,PR_TRUE); + return SECFailure; + } + return SECSuccess; +} + +static SECItem * +pk11_lookupTokenKeyByHandle(PK11Slot *slot, CK_OBJECT_HANDLE handle) +{ + return (SECItem *)PL_HashTableLookupConst(slot->tokenHashTable, + (void *)handle); +} + +/* + * use the refLock. This operations should be very rare, so the added + * contention on the ref lock should be lower than the overhead of adding + * a new lock. We use separate functions for this just in case I'm wrong. + */ +static void +pk11_tokenKeyLock(PK11Slot *slot) { + PK11_USE_THREADS(PZ_Lock(slot->objectLock);) +} + +static void +pk11_tokenKeyUnlock(PK11Slot *slot) { + PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) +} + + /* allocation hooks that allow us to recycle old object structures */ #ifdef MAX_OBJECT_LIST_SIZE static PK11Object * objectFreeList = NULL; @@ -620,26 +1640,26 @@ pk11_GetObjectFromList(PRBool *hasLocks) { } #endif - object = (PK11Object*)PORT_ZAlloc(sizeof(PK11Object)); + object = (PK11Object*)PORT_ZAlloc(sizeof(PK11SessionObject)); *hasLocks = PR_FALSE; return object; } static void -pk11_PutObjectToList(PK11Object *object) { +pk11_PutObjectToList(PK11SessionObject *object) { #ifdef MAX_OBJECT_LIST_SIZE if (object_count < MAX_OBJECT_LIST_SIZE) { PK11_USE_THREADS(PZ_Lock(objectLock)); - object->next = objectFreeList; - objectFreeList = object; + object->obj.next = objectFreeList; + objectFreeList = &object->obj; object_count++; PK11_USE_THREADS(PZ_Unlock(objectLock)); return; } #endif PK11_USE_THREADS(PZ_DestroyLock(object->attributeLock);) - PK11_USE_THREADS(PZ_DestroyLock(object->refLock);) - object->attributeLock = object->refLock = NULL; + PK11_USE_THREADS(PZ_DestroyLock(object->obj.refLock);) + object->attributeLock = object->obj.refLock = NULL; PORT_Free(object); } @@ -651,58 +1671,63 @@ PK11Object * pk11_NewObject(PK11Slot *slot) { PK11Object *object; + PK11SessionObject *sessObject; PRBool hasLocks = PR_FALSE; int i; -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES object = pk11_GetObjectFromList(&hasLocks); if (object == NULL) { return NULL; } - object->nextAttr = 0; + sessObject = (PK11SessionObject *)object; + sessObject->nextAttr = 0; + + for (i=0; i < MAX_OBJS_ATTRS; i++) { + sessObject->attrList[i].attrib.pValue = NULL; + sessObject->attrList[i].freeData = PR_FALSE; + } #else + PRArenaPool *arena; + arena = PORT_NewArena(2048); if (arena == NULL) return NULL; - object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11Object)); + object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11SessionObject)); if (object == NULL) { PORT_FreeArena(arena,PR_FALSE); return NULL; } object->arena = arena; - for (i=0; i < MAX_OBJS_ATTRS; i++) { - object->attrList[i].attrib.pValue = NULL; - } + sessObject = (PK11SessionObject *)object; #endif object->handle = 0; object->next = object->prev = NULL; - object->sessionList.next = NULL; - object->sessionList.prev = NULL; - object->sessionList.parent = object; - object->inDB = PR_FALSE; - object->label = NULL; - object->refCount = 1; - object->session = NULL; object->slot = slot; object->objclass = 0xffff; - object->wasDerived = PR_FALSE; + object->refCount = 1; + sessObject->sessionList.next = NULL; + sessObject->sessionList.prev = NULL; + sessObject->sessionList.parent = object; + sessObject->session = NULL; + sessObject->wasDerived = PR_FALSE; #ifdef PKCS11_USE_THREADS if (!hasLocks) object->refLock = PZ_NewLock(nssILockRefLock); if (object->refLock == NULL) { -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES PORT_Free(object); #else PORT_FreeArena(arena,PR_FALSE); #endif return NULL; } - if (!hasLocks) object->attributeLock = PZ_NewLock(nssILockAttribute); - if (object->attributeLock == NULL) { + if (!hasLocks) sessObject->attributeLock = PZ_NewLock(nssILockAttribute); + if (sessObject->attributeLock == NULL) { PK11_USE_THREADS(PZ_DestroyLock(object->refLock);) -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES PORT_Free(object); #else PORT_FreeArena(arena,PR_FALSE); @@ -710,17 +1735,55 @@ pk11_NewObject(PK11Slot *slot) return NULL; } #else - object->attributeLock = NULL; + sessObject->attributeLock = NULL; object->refLock = NULL; #endif for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) { - object->head[i] = NULL; + sessObject->head[i] = NULL; } object->objectInfo = NULL; object->infoFree = NULL; return object; } +static CK_RV +pk11_DestroySessionObjectData(PK11SessionObject *so) +{ + int i; + +#ifdef PKCS11_STATIC_ATTRIBUTES + for (i=0; i < MAX_OBJS_ATTRS; i++) { + unsigned char *value = so->attrList[i].attrib.pValue; + if (value) { + PORT_Memset(value,0,so->attrList[i].attrib.ulValueLen); + if (so->attrList[i].freeData) { + PORT_Free(value); + } + so->attrList[i].attrib.pValue = NULL; + so->attrList[i].freeData = PR_FALSE; + } + } +#endif + +#ifdef PKCS11_REF_COUNT_ATTRIBUTES + /* clean out the attributes */ + /* since no one is referencing us, it's safe to walk the chain + * without a lock */ + for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) { + PK11Attribute *ap,*next; + for (ap = so->head[i]; ap != NULL; ap = next) { + next = ap->next; + /* paranoia */ + ap->next = ap->prev = NULL; + pk11_FreeAttribute(ap); + } + so->head[i] = NULL; + } +#endif +/* PK11_USE_THREADS(PZ_DestroyLock(so->attributeLock));*/ + return CKR_OK; +} + /* * free all the data associated with an object. Object reference count must * be 'zero'. @@ -728,86 +1791,33 @@ pk11_NewObject(PK11Slot *slot) static CK_RV pk11_DestroyObject(PK11Object *object) { -#if defined(REF_COUNT_ATTRIBUTE) || defined(NO_ARENA) - int i; -#endif - SECItem pubKey; CK_RV crv = CKR_OK; - SECStatus rv; + PK11SessionObject *so = pk11_narrowToSessionObject(object); + PK11TokenObject *to = pk11_narrowToTokenObject(object); PORT_Assert(object->refCount == 0); /* delete the database value */ - if (object->inDB) { - if (pk11_isToken(object->handle)) { - /* remove the objects from the real data base */ - switch (object->handle & PK11_TOKEN_TYPE_MASK) { - case PK11_TOKEN_TYPE_PRIV: - /* KEYID is the public KEY for DSA and DH, and the MODULUS for - * RSA */ - crv=pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB); - if (crv != CKR_OK) break; - rv = SECKEY_DeleteKey(SECKEY_GetDefaultKeyDB(), &pubKey); - if (rv != SECSuccess && pubKey.data[0] == 0) { - /* Because of legacy code issues, sometimes the public key - * has a '0' prepended to it, forcing it to be unsigned. - * The database may not store that '0', so remove it and - * try again. - */ - SECItem tmpPubKey; - tmpPubKey.data = pubKey.data + 1; - tmpPubKey.len = pubKey.len - 1; - rv = SECKEY_DeleteKey(SECKEY_GetDefaultKeyDB(), &tmpPubKey); - } - if (rv != SECSuccess) crv= CKR_DEVICE_ERROR; - break; - case PK11_TOKEN_TYPE_CERT: - rv = SEC_DeletePermCertificate((CERTCertificate *)object->objectInfo); - if (rv != SECSuccess) crv = CKR_DEVICE_ERROR; - break; - } + if (to) { + if (to->dbKey.data) { + PORT_Free(to->dbKey.data); + to->dbKey.data = NULL; } } - if (object->label) PORT_Free(object->label); - - object->inDB = PR_FALSE; - object->label = NULL; - -#ifdef NO_ARENA - for (i=0; i < MAX_OBJS_ATTRS; i++) { - unsigned char *value = object->attrList[i].attrib.pValue; - if (value) { - PORT_Memset(value,0,object->attrList[i].attrib.ulValueLen); - if (value != object->attrList[i].space) { - PORT_Free(value); - } - object->attrList[i].attrib.pValue = NULL; - } + if (so) { + pk11_DestroySessionObjectData(so); } -#endif - -#ifdef REF_COUNT_ATTRIBUTE - /* clean out the attributes */ - /* since no one is referencing us, it's safe to walk the chain - * without a lock */ - for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) { - PK11Attribute *ap,*next; - for (ap = object->head[i]; ap != NULL; ap = next) { - next = ap->next; - /* paranoia */ - ap->next = ap->prev = NULL; - pk11_FreeAttribute(ap); - } - object->head[i] = NULL; - } -#endif if (object->objectInfo) { (*object->infoFree)(object->objectInfo); } -#ifdef NO_ARENA - pk11_PutObjectToList(object); +#ifdef PKCS11_STATIC_ATTRIBUTES + if (so) { + pk11_PutObjectToList(so); + } else { + PK11_USE_THREADS(PZ_DestroyLock(object->refLock);) + PORT_Free(to);; + } #else - PK11_USE_THREADS(PZ_DestroyLock(object->attributeLock);) PK11_USE_THREADS(PZ_DestroyLock(object->refLock);) arena = object->arena; PORT_FreeArena(arena,PR_FALSE); @@ -830,6 +1840,10 @@ pk11_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, PK11Slot *slot) PZLock *lock; PK11Object *object; + if (pk11_isToken(handle)) { + return pk11_NewTokenObject(slot, NULL, handle); + } + head = slot->tokObjects; lock = slot->objectLock; @@ -888,7 +1902,8 @@ void pk11_AddSlotObject(PK11Slot *slot, PK11Object *object) { PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - pk11queue_add(object,object->handle,slot->tokObjects,TOKEN_OBJECT_HASH_SIZE); + pk11queue_add(object,object->handle,slot->tokObjects, + TOKEN_OBJECT_HASH_SIZE); PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) } @@ -896,35 +1911,98 @@ void pk11_AddObject(PK11Session *session, PK11Object *object) { PK11Slot *slot = pk11_SlotFromSession(session); + PK11SessionObject *so = pk11_narrowToSessionObject(object); - if (!pk11_isToken(object->handle)) { + if (so) { PK11_USE_THREADS(PZ_Lock(session->objectLock);) - pk11queue_add(&object->sessionList,0,session->objects,0); - object->session = session; + pk11queue_add(&so->sessionList,0,session->objects,0); + so->session = session; PK11_USE_THREADS(PZ_Unlock(session->objectLock);) } pk11_AddSlotObject(slot,object); + pk11_ReferenceObject(object); } /* * add an object to a slot andsession queue */ -void +CK_RV pk11_DeleteObject(PK11Session *session, PK11Object *object) { PK11Slot *slot = pk11_SlotFromSession(session); + PK11SessionObject *so = pk11_narrowToSessionObject(object); + PK11TokenObject *to = pk11_narrowToTokenObject(object); + CK_RV crv = CKR_OK; + SECStatus rv; + NSSLOWCERTCertificate *cert; + NSSLOWCERTCertTrust tmptrust; + PRBool isKrl; - if (object->session) { - PK11Session *session = object->session; + /* Handle Token case */ + if (so && so->session) { + PK11Session *session = so->session; PK11_USE_THREADS(PZ_Lock(session->objectLock);) - pk11queue_delete(&object->sessionList,0,session->objects,0); + pk11queue_delete(&so->sessionList,0,session->objects,0); PK11_USE_THREADS(PZ_Unlock(session->objectLock);) - } - PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - pk11queue_delete(object,object->handle,slot->tokObjects, + PK11_USE_THREADS(PZ_Lock(slot->objectLock);) + pk11queue_delete(object,object->handle,slot->tokObjects, TOKEN_OBJECT_HASH_SIZE); - PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) - pk11_FreeObject(object); + PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) + pk11_FreeObject(object); /* reduce it's reference count */ + } else { + PORT_Assert(to); + /* remove the objects from the real data base */ + switch (object->handle & PK11_TOKEN_TYPE_MASK) { + case PK11_TOKEN_TYPE_PRIV: + case PK11_TOKEN_TYPE_KEY: + /* KEYID is the public KEY for DSA and DH, and the MODULUS for + * RSA */ + PORT_Assert(slot->keyDB); + rv = nsslowkey_DeleteKey(slot->keyDB, &to->dbKey); + if (rv != SECSuccess) crv= CKR_DEVICE_ERROR; + break; + case PK11_TOKEN_TYPE_PUB: + break; /* public keys only exist at the behest of the priv key */ + case PK11_TOKEN_TYPE_CERT: + cert = nsslowcert_FindCertByKey(slot->certDB,&to->dbKey); + if (cert == NULL) { + crv = CKR_DEVICE_ERROR; + break; + } + rv = nsslowcert_DeletePermCertificate(cert); + if (rv != SECSuccess) crv = CKR_DEVICE_ERROR; + nsslowcert_DestroyCertificate(cert); + break; + case PK11_TOKEN_TYPE_CRL: + isKrl = (PRBool) (object->handle == PK11_TOKEN_KRL_HANDLE); + rv = nsslowcert_DeletePermCRL(slot->certDB,&to->dbKey,isKrl); + if (rv == SECFailure) crv = CKR_DEVICE_ERROR; + break; + case PK11_TOKEN_TYPE_TRUST: + cert = nsslowcert_FindCertByKey(slot->certDB,&to->dbKey); + if (cert == NULL) { + crv = CKR_DEVICE_ERROR; + break; + } + tmptrust = *cert->trust; + tmptrust.sslFlags &= CERTDB_PRESERVE_TRUST_BITS; + tmptrust.emailFlags &= CERTDB_PRESERVE_TRUST_BITS; + tmptrust.objectSigningFlags &= CERTDB_PRESERVE_TRUST_BITS; + tmptrust.sslFlags |= CERTDB_TRUSTED_UNKNOWN; + tmptrust.emailFlags |= CERTDB_TRUSTED_UNKNOWN; + tmptrust.objectSigningFlags |= CERTDB_TRUSTED_UNKNOWN; + rv = nsslowcert_ChangeCertTrust(slot->certDB,cert,&tmptrust); + if (rv != SECSuccess) crv = CKR_DEVICE_ERROR; + nsslowcert_DestroyCertificate(cert); + break; + default: + break; + } + pk11_tokenKeyLock(object->slot); + pk11_deleteTokenKeyByHandle(object->slot,object->handle); + pk11_tokenKeyUnlock(object->slot); + } + return crv; } /* @@ -936,11 +2014,16 @@ CK_RV pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject) { PK11Attribute *attribute; + PK11SessionObject *src_so = pk11_narrowToSessionObject(srcObject); int i; - PK11_USE_THREADS(PZ_Lock(srcObject->attributeLock);) + if (src_so == NULL) { + return CKR_DEVICE_ERROR; /* can't copy token objects yet */ + } + + PK11_USE_THREADS(PZ_Lock(src_so->attributeLock);) for(i=0; i < ATTRIBUTE_HASH_SIZE; i++) { - attribute = srcObject->head[i]; + attribute = src_so->head[i]; do { if (attribute) { if (!pk11_hasAttribute(destObject,attribute->handle)) { @@ -949,7 +2032,7 @@ pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject) PK11Attribute *newAttribute = pk11_NewAttribute( destObject,pk11_attr_expand(&attribute->attrib)); if (newAttribute == NULL) { - PK11_USE_THREADS(PZ_Unlock(srcObject->attributeLock);) + PK11_USE_THREADS(PZ_Unlock(src_so->attributeLock);) return CKR_HOST_MEMORY; } pk11_AddAttribute(destObject,newAttribute); @@ -958,7 +2041,7 @@ pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject) } } while (attribute != NULL); } - PK11_USE_THREADS(PZ_Unlock(srcObject->attributeLock);) + PK11_USE_THREADS(PZ_Unlock(src_so->attributeLock);) return CKR_OK; } @@ -1012,7 +2095,7 @@ pk11_objectMatch(PK11Object *object,CK_ATTRIBUTE_PTR theTemplate,int count) * in the object list. */ CK_RV -pk11_searchObjectList(PK11ObjectListElement **objectList,PK11Object **head, +pk11_searchObjectList(PK11SearchResults *search,PK11Object **head, PZLock *lock, CK_ATTRIBUTE_PTR theTemplate, int count, PRBool isLoggedIn) { int i; @@ -1027,10 +2110,7 @@ pk11_searchObjectList(PK11ObjectListElement **objectList,PK11Object **head, if (pk11_objectMatch(object,theTemplate,count)) { /* don't return objects that aren't yet visible */ if ((!isLoggedIn) && pk11_isTrue(object,CKA_PRIVATE)) continue; - crv = AddToList(objectList,object); - if (crv != CKR_OK) { - break; - } + pk11_addHandle(search,object->handle); } } PK11_USE_THREADS(PZ_Unlock(lock);) @@ -1126,37 +2206,11 @@ pk11_FreeContext(PK11SessionContext *context) if (context->hashInfo) { (*context->hashdestroy)(context->hashInfo,PR_TRUE); } - PORT_Free(context); -} - -/* look up a slot structure from the ID (used to be a macro when we only - * had two slots) */ -PK11Slot * -pk11_SlotFromID(CK_SLOT_ID slotID) -{ - switch (slotID) { - case NETSCAPE_SLOT_ID: - return &pk11_slot[0]; - case PRIVATE_KEY_SLOT_ID: - return &pk11_slot[1]; - case FIPS_SLOT_ID: - return &pk11_slot[2]; - default: - break; /* fall through to NULL */ + if (context->key) { + pk11_FreeObject(context->key); + context->key = NULL; } - return NULL; -} - -PK11Slot * -pk11_SlotFromSessionHandle(CK_SESSION_HANDLE handle) -{ - if (handle & PK11_PRIVATE_KEY_FLAG) { - return &pk11_slot[1]; - } - if (handle & PK11_FIPS_FLAG) { - return &pk11_slot[2]; - } - return &pk11_slot[0]; + PORT_Free(context); } /* @@ -1278,3 +2332,190 @@ pk11_FreeSession(PK11Session *session) if (destroy) pk11_DestroySession(session); } +/* + * handle Token Object stuff + */ + +/* Make a token handle for an object and record it so we can find it again */ +CK_OBJECT_HANDLE +pk11_mkHandle(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class) +{ + unsigned char hashBuf[SHA1_LENGTH]; + CK_OBJECT_HANDLE handle; + SECItem *key; + + handle = class; + /* there is only one KRL, use a fixed handle for it */ + if (handle != PK11_TOKEN_KRL_HANDLE) { + SHA1_HashBuf(hashBuf,dbKey->data,dbKey->len); + handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) | + (hashBuf[2] << 8) | hashBuf[3]; + handle = PK11_TOKEN_MAGIC | class | + (handle & ~(PK11_TOKEN_TYPE_MASK|PK11_TOKEN_MASK)); + /* we have a CRL who's handle has randomly matched the reserved KRL + * handle, increment it */ + if (handle == PK11_TOKEN_KRL_HANDLE) { + handle++; + } + } + + pk11_tokenKeyLock(slot); + while ((key = pk11_lookupTokenKeyByHandle(slot,handle)) != NULL) { + if (SECITEM_ItemsAreEqual(key,dbKey)) { + pk11_tokenKeyUnlock(slot); + return handle; + } + handle++; + } + pk11_addTokenKeyByHandle(slot,handle,dbKey); + pk11_tokenKeyUnlock(slot); + return handle; +} + +void +pk11_addHandle(PK11SearchResults *search, CK_OBJECT_HANDLE handle) +{ + if (search->handles == NULL) { + return; + } + if (search->size >= search->array_size) { + search->array_size += NSC_SEARCH_BLOCK_SIZE; + search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles, + sizeof(CK_OBJECT_HANDLE)* search->array_size); + if (search->handles == NULL) { + return; + } + } + search->handles[search->size] = handle; + search->size++; +} + +static const CK_OBJECT_HANDLE pk11_classArray[] = { + 0, CKO_PRIVATE_KEY, CKO_PUBLIC_KEY, CKO_SECRET_KEY, + CKO_NETSCAPE_TRUST, CKO_NETSCAPE_CRL, CKO_NETSCAPE_SMIME, + CKO_CERTIFICATE }; + +#define handleToClass(handle) \ + pk11_classArray[((handle & PK11_TOKEN_TYPE_MASK))>>28] + +PK11Object * +pk11_NewTokenObject(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle) +{ + PK11Object *object = NULL; + PK11TokenObject *tokObject = NULL; + SECStatus rv; + +#ifdef PKCS11_STATIC_ATTRIBUTES + object = (PK11Object *) PORT_ZAlloc(sizeof(PK11TokenObject)); + if (object == NULL) { + return NULL; + } +#else + PRArenaPool *arena; + + arena = PORT_NewArena(2048); + if (arena == NULL) return NULL; + + object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11TokenObject)); + if (object == NULL) { + PORT_FreeArena(arena,PR_FALSE); + return NULL; + } + object->arena = arena; +#endif + tokObject = (PK11TokenObject *) object; + + object->objclass = handleToClass(handle); + object->handle = handle; + object->refCount = 1; + object->slot = slot; + object->objectInfo = NULL; + object->infoFree = NULL; + if (dbKey == NULL) { + pk11_tokenKeyLock(slot); + dbKey = pk11_lookupTokenKeyByHandle(slot,handle); + if (dbKey == NULL) { + pk11_tokenKeyUnlock(slot); + goto loser; + } + rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey); + pk11_tokenKeyUnlock(slot); + } else { + rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey); + } + if (rv != SECSuccess) { + goto loser; + } +#ifdef PKCS11_USE_THREADS + object->refLock = PZ_NewLock(nssILockRefLock); + if (object->refLock == NULL) { + goto loser; + } +#endif + + return object; +loser: + if (object) { + pk11_FreeObject(object); + } + return NULL; + +} + +PRBool +pk11_tokenMatch(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class, + CK_ATTRIBUTE_PTR theTemplate,int count) +{ + PK11Object *object; + PRBool ret; + + object = pk11_NewTokenObject(slot,dbKey,PK11_TOKEN_MASK|class); + if (object == NULL) { + return PR_FALSE; + } + + ret = pk11_objectMatch(object,theTemplate,count); + pk11_FreeObject(object); + return ret; +} + +PK11TokenObject * +pk11_convertSessionToToken(PK11SessionObject *so) +{ + SECItem *key; + PK11TokenObject *to = pk11_narrowToTokenObject(&so->obj); + SECStatus rv; + + pk11_DestroySessionObjectData(so); + PK11_USE_THREADS(PZ_DestroyLock(so->attributeLock)); + if (to == NULL) { + return NULL; + } + pk11_tokenKeyLock(so->obj.slot); + key = pk11_lookupTokenKeyByHandle(so->obj.slot,so->obj.handle); + if (key == NULL) { + pk11_tokenKeyUnlock(so->obj.slot); + return NULL; + } + rv = SECITEM_CopyItem(NULL,&to->dbKey,key); + pk11_tokenKeyUnlock(so->obj.slot); + if (rv == SECFailure) { + return NULL; + } + + return to; + +} + +PK11SessionObject * +pk11_narrowToSessionObject(PK11Object *obj) +{ + return !pk11_isToken(obj->handle) ? (PK11SessionObject *)obj : NULL; +} + +PK11TokenObject * +pk11_narrowToTokenObject(PK11Object *obj) +{ + return pk11_isToken(obj->handle) ? (PK11TokenObject *)obj : NULL; +} + diff --git a/security/nss/lib/softoken/rsawrapr.c b/security/nss/lib/softoken/rsawrapr.c index 7ada1e28c..b1e499016 100644 --- a/security/nss/lib/softoken/rsawrapr.c +++ b/security/nss/lib/softoken/rsawrapr.c @@ -40,7 +40,7 @@ #include "softoken.h" #include "sechash.h" -#include "keylow.h" +#include "lowkeyi.h" #include "secerr.h" #define RSA_BLOCK_MIN_PAD_LEN 8 @@ -182,8 +182,8 @@ oaep_xor_with_h2(unsigned char *salt, unsigned int saltlen, * Format one block of data for public/private key encryption using * the rules defined in PKCS #1. */ -unsigned char * -RSA_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType, +static unsigned char * +rsa_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType, SECItem *data) { unsigned char *block; @@ -341,8 +341,8 @@ RSA_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType, return block; } -SECStatus -RSA_FormatBlock(SECItem *result, unsigned modulusLen, +static SECStatus +rsa_FormatBlock(SECItem *result, unsigned modulusLen, RSA_BlockType blockType, SECItem *data) { /* @@ -370,7 +370,7 @@ RSA_FormatBlock(SECItem *result, unsigned modulusLen, */ PORT_Assert (data->len <= (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN))); - result->data = RSA_FormatOneBlock(modulusLen, blockType, data); + result->data = rsa_FormatOneBlock(modulusLen, blockType, data); if (result->data == NULL) { result->len = 0; return SECFailure; @@ -390,7 +390,7 @@ RSA_FormatBlock(SECItem *result, unsigned modulusLen, PORT_Assert (data->len <= (modulusLen - (2 + OAEP_SALT_LEN + OAEP_PAD_LEN))); - result->data = RSA_FormatOneBlock(modulusLen, blockType, data); + result->data = rsa_FormatOneBlock(modulusLen, blockType, data); if (result->data == NULL) { result->len = 0; return SECFailure; @@ -420,193 +420,9 @@ RSA_FormatBlock(SECItem *result, unsigned modulusLen, return SECSuccess; } -/* - * Takes a formatted block and returns the data part. - * (This is the inverse of RSA_FormatOneBlock().) - * In some formats the start of the data is ambiguous; - * if it is non-zero, expectedLen will disambiguate. - * - * NOTE: this routine is not yet used/tested! (XXX please - * remove this comment once that is no longer the case ;-) - */ -unsigned char * -RSA_DecodeOneBlock(unsigned char *data, - unsigned int modulusLen, - unsigned int expectedLen, - RSA_BlockType *pResultType, - unsigned int *pResultLen) -{ - RSA_BlockType blockType; - unsigned char *dp, *res; - unsigned int i, len, padLen; - - dp = data; - if (*dp++ != RSA_BLOCK_FIRST_OCTET) { - PORT_SetError (SEC_ERROR_BAD_DATA); - return NULL; - } - - blockType = (RSA_BlockType)*dp++; - switch (blockType) { - case RSA_BlockPrivate0: - if (expectedLen) { - padLen = modulusLen - expectedLen - 3; - PORT_Assert (padLen >= RSA_BLOCK_MIN_PAD_LEN); - for (i = 0; i < padLen; i++) { - if (*dp++ != RSA_BLOCK_PRIVATE0_PAD_OCTET) - break; - } - if ((i != padLen) || (*dp != RSA_BLOCK_AFTER_PAD_OCTET)) { - PORT_SetError (SEC_ERROR_BAD_DATA); - return NULL; - } - dp++; - len = expectedLen; - } else { - for (i = 0; i < modulusLen; i++) { - if (*dp++ != RSA_BLOCK_PRIVATE0_PAD_OCTET) - break; - } - if (i == modulusLen) { - PORT_SetError (SEC_ERROR_BAD_DATA); - return NULL; - } - if (RSA_BLOCK_PRIVATE0_PAD_OCTET == RSA_BLOCK_AFTER_PAD_OCTET) - dp--; - padLen = dp - data - 2; - if ((padLen < RSA_BLOCK_MIN_PAD_LEN) - || (*dp != RSA_BLOCK_AFTER_PAD_OCTET)) { - PORT_SetError (SEC_ERROR_BAD_DATA); - return NULL; - } - dp++; - len = modulusLen - (dp - data); - } - res = (unsigned char *) PORT_Alloc(len); - if (res == NULL) { - return NULL; - } - PORT_Memcpy (res, dp, len); - break; - - case RSA_BlockPrivate: - for (i = 0; i < modulusLen; i++) { - if (*dp++ != RSA_BLOCK_PRIVATE_PAD_OCTET) - break; - } - if ((i == modulusLen) || (*dp != RSA_BLOCK_AFTER_PAD_OCTET)) { - PORT_SetError (SEC_ERROR_BAD_DATA); - return NULL; - } - padLen = dp - data - 2; - dp++; - len = modulusLen - (dp - data); - if ((padLen < RSA_BLOCK_MIN_PAD_LEN) || (expectedLen - && (expectedLen != len))) { - PORT_SetError (SEC_ERROR_BAD_DATA); - return NULL; - } - res = (unsigned char *) PORT_Alloc(len); - if (res == NULL) { - return NULL; - } - PORT_Memcpy (res, dp, len); - break; - - case RSA_BlockPublic: - for (i = 0; i < modulusLen; i++) { - if (*dp++ == RSA_BLOCK_AFTER_PAD_OCTET) - break; - } - if (i == modulusLen) { - PORT_SetError (SEC_ERROR_BAD_DATA); - return NULL; - } - padLen = dp - data - 2; - dp++; - len = modulusLen - (dp - data); - if ((padLen < RSA_BLOCK_MIN_PAD_LEN) || (expectedLen - && (expectedLen != len))) { - PORT_SetError (SEC_ERROR_BAD_DATA); - return NULL; - } - res = (unsigned char *) PORT_Alloc(len); - if (res == NULL) { - return NULL; - } - PORT_Memcpy (res, dp, len); - break; - - case RSA_BlockOAEP: - { - unsigned char *salt, *tmp_res; - SECStatus rv; - - len = modulusLen - 2 - OAEP_SALT_LEN; - /* - * dp points to: - * Modified2(Salt) || Modified1(PaddedData) - * To recover Salt we need to XOR it with the low-order hash - * of Modified1. - */ - salt = (unsigned char *) PORT_Alloc(OAEP_SALT_LEN); - if (salt == NULL) { - return NULL; - } - PORT_Memcpy (salt, dp, OAEP_SALT_LEN); - dp += OAEP_SALT_LEN; - rv = oaep_xor_with_h2 (salt, OAEP_SALT_LEN, dp, len); - if (rv != SECSuccess) { - PORT_Free (salt); - return NULL; - } - if (expectedLen) { - PORT_Assert (expectedLen <= len); - len = expectedLen; - } - tmp_res = (unsigned char *) PORT_Alloc(len); - if (tmp_res == NULL) { - PORT_Free (salt); - return NULL; - } - PORT_Memcpy (tmp_res, dp, len); - rv = oaep_xor_with_h1 (tmp_res, len, salt, OAEP_SALT_LEN); - PORT_Free (salt); - if (rv != SECSuccess) { - return NULL; - } - for (i = 0; i < OAEP_PAD_LEN; i++) { - if (tmp_res[i] != OAEP_PAD_OCTET) { - PORT_SetError (SEC_ERROR_BAD_DATA); - PORT_Free (tmp_res); - return NULL; - } - } - len -= OAEP_PAD_LEN; - res = (unsigned char *) PORT_Alloc(len); - if (res == NULL) { - PORT_Free (tmp_res); - return NULL; - } - PORT_Memcpy (res, tmp_res + OAEP_PAD_LEN, len); - PORT_Free (tmp_res); - } - break; - - default: - PORT_SetError (SEC_ERROR_BAD_DATA); - return NULL; - } - - PORT_Assert (res != NULL); - *pResultLen = len; - *pResultType = blockType; - return res; -} - /* XXX Doesn't set error code */ SECStatus -RSA_Sign(SECKEYLowPrivateKey *key, +RSA_Sign(NSSLOWKEYPrivateKey *key, unsigned char * output, unsigned int * output_len, unsigned int maxOutputLen, @@ -614,20 +430,20 @@ RSA_Sign(SECKEYLowPrivateKey *key, unsigned int input_len) { SECStatus rv = SECSuccess; - unsigned int modulus_len = SECKEY_LowPrivateModulusLen(key); + unsigned int modulus_len = nsslowkey_PrivateModulusLen(key); SECItem formatted; SECItem unformatted; if (maxOutputLen < modulus_len) return SECFailure; - PORT_Assert(key->keyType == lowRSAKey); - if (key->keyType != lowRSAKey) + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); + if (key->keyType != NSSLOWKEYRSAKey) return SECFailure; unformatted.len = input_len; unformatted.data = input; formatted.data = NULL; - rv = RSA_FormatBlock(&formatted, modulus_len, RSA_BlockPrivate, + rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockPrivate, &unformatted); if (rv != SECSuccess) goto done; @@ -645,24 +461,24 @@ done: /* XXX Doesn't set error code */ SECStatus -RSA_CheckSign(SECKEYLowPublicKey *key, +RSA_CheckSign(NSSLOWKEYPublicKey *key, unsigned char * sign, unsigned int sign_len, unsigned char * hash, unsigned int hash_len) { SECStatus rv; - unsigned int modulus_len = SECKEY_LowPublicModulusLen(key); + unsigned int modulus_len = nsslowkey_PublicModulusLen(key); unsigned int i; unsigned char * buffer; - modulus_len = SECKEY_LowPublicModulusLen(key); + modulus_len = nsslowkey_PublicModulusLen(key); if (sign_len != modulus_len) goto failure; if (hash_len > modulus_len - 8) goto failure; - PORT_Assert(key->keyType == lowRSAKey); - if (key->keyType != lowRSAKey) + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); + if (key->keyType != NSSLOWKEYRSAKey) goto failure; buffer = (unsigned char *)PORT_Alloc(modulus_len + 1); @@ -702,7 +518,7 @@ failure: /* XXX Doesn't set error code */ SECStatus -RSA_CheckSignRecover(SECKEYLowPublicKey *key, +RSA_CheckSignRecover(NSSLOWKEYPublicKey *key, unsigned char * data, unsigned int * data_len, unsigned int max_output_len, @@ -710,14 +526,14 @@ RSA_CheckSignRecover(SECKEYLowPublicKey *key, unsigned int sign_len) { SECStatus rv; - unsigned int modulus_len = SECKEY_LowPublicModulusLen(key); + unsigned int modulus_len = nsslowkey_PublicModulusLen(key); unsigned int i; unsigned char * buffer; if (sign_len != modulus_len) goto failure; - PORT_Assert(key->keyType == lowRSAKey); - if (key->keyType != lowRSAKey) + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); + if (key->keyType != NSSLOWKEYRSAKey) goto failure; buffer = (unsigned char *)PORT_Alloc(modulus_len + 1); @@ -763,7 +579,7 @@ failure: /* XXX Doesn't set error code */ SECStatus -RSA_EncryptBlock(SECKEYLowPublicKey *key, +RSA_EncryptBlock(NSSLOWKEYPublicKey *key, unsigned char * output, unsigned int * output_len, unsigned int max_output_len, @@ -771,21 +587,21 @@ RSA_EncryptBlock(SECKEYLowPublicKey *key, unsigned int input_len) { SECStatus rv; - unsigned int modulus_len = SECKEY_LowPublicModulusLen(key); + unsigned int modulus_len = nsslowkey_PublicModulusLen(key); SECItem formatted; SECItem unformatted; formatted.data = NULL; if (max_output_len < modulus_len) goto failure; - PORT_Assert(key->keyType == lowRSAKey); - if (key->keyType != lowRSAKey) + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); + if (key->keyType != NSSLOWKEYRSAKey) goto failure; unformatted.len = input_len; unformatted.data = input; formatted.data = NULL; - rv = RSA_FormatBlock(&formatted, modulus_len, RSA_BlockPublic, + rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockPublic, &unformatted); if (rv != SECSuccess) goto failure; @@ -806,7 +622,7 @@ failure: /* XXX Doesn't set error code */ SECStatus -RSA_DecryptBlock(SECKEYLowPrivateKey *key, +RSA_DecryptBlock(NSSLOWKEYPrivateKey *key, unsigned char * output, unsigned int * output_len, unsigned int max_output_len, @@ -814,12 +630,12 @@ RSA_DecryptBlock(SECKEYLowPrivateKey *key, unsigned int input_len) { SECStatus rv; - unsigned int modulus_len = SECKEY_LowPrivateModulusLen(key); + unsigned int modulus_len = nsslowkey_PrivateModulusLen(key); unsigned int i; unsigned char * buffer; - PORT_Assert(key->keyType == lowRSAKey); - if (key->keyType != lowRSAKey) + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); + if (key->keyType != NSSLOWKEYRSAKey) goto failure; if (input_len != modulus_len) goto failure; @@ -863,7 +679,7 @@ failure: * RAW is RSA_X_509 */ SECStatus -RSA_SignRaw(SECKEYLowPrivateKey *key, +RSA_SignRaw(NSSLOWKEYPrivateKey *key, unsigned char * output, unsigned int * output_len, unsigned int maxOutputLen, @@ -871,20 +687,20 @@ RSA_SignRaw(SECKEYLowPrivateKey *key, unsigned int input_len) { SECStatus rv = SECSuccess; - unsigned int modulus_len = SECKEY_LowPrivateModulusLen(key); + unsigned int modulus_len = nsslowkey_PrivateModulusLen(key); SECItem formatted; SECItem unformatted; if (maxOutputLen < modulus_len) return SECFailure; - PORT_Assert(key->keyType == lowRSAKey); - if (key->keyType != lowRSAKey) + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); + if (key->keyType != NSSLOWKEYRSAKey) return SECFailure; unformatted.len = input_len; unformatted.data = input; formatted.data = NULL; - rv = RSA_FormatBlock(&formatted, modulus_len, RSA_BlockRaw, &unformatted); + rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockRaw, &unformatted); if (rv != SECSuccess) goto done; @@ -899,22 +715,22 @@ done: /* XXX Doesn't set error code */ SECStatus -RSA_CheckSignRaw(SECKEYLowPublicKey *key, +RSA_CheckSignRaw(NSSLOWKEYPublicKey *key, unsigned char * sign, unsigned int sign_len, unsigned char * hash, unsigned int hash_len) { SECStatus rv; - unsigned int modulus_len = SECKEY_LowPublicModulusLen(key); + unsigned int modulus_len = nsslowkey_PublicModulusLen(key); unsigned char * buffer; if (sign_len != modulus_len) goto failure; if (hash_len > modulus_len) goto failure; - PORT_Assert(key->keyType == lowRSAKey); - if (key->keyType != lowRSAKey) + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); + if (key->keyType != NSSLOWKEYRSAKey) goto failure; buffer = (unsigned char *)PORT_Alloc(modulus_len + 1); @@ -943,7 +759,7 @@ failure: /* XXX Doesn't set error code */ SECStatus -RSA_CheckSignRecoverRaw(SECKEYLowPublicKey *key, +RSA_CheckSignRecoverRaw(NSSLOWKEYPublicKey *key, unsigned char * data, unsigned int * data_len, unsigned int max_output_len, @@ -951,14 +767,14 @@ RSA_CheckSignRecoverRaw(SECKEYLowPublicKey *key, unsigned int sign_len) { SECStatus rv; - unsigned int modulus_len = SECKEY_LowPublicModulusLen(key); + unsigned int modulus_len = nsslowkey_PublicModulusLen(key); if (sign_len != modulus_len) goto failure; if (max_output_len < modulus_len) goto failure; - PORT_Assert(key->keyType == lowRSAKey); - if (key->keyType != lowRSAKey) + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); + if (key->keyType != NSSLOWKEYRSAKey) goto failure; rv = RSA_PublicKeyOp(&key->u.rsa, data, sign); @@ -975,7 +791,7 @@ failure: /* XXX Doesn't set error code */ SECStatus -RSA_EncryptRaw(SECKEYLowPublicKey *key, +RSA_EncryptRaw(NSSLOWKEYPublicKey *key, unsigned char * output, unsigned int * output_len, unsigned int max_output_len, @@ -983,21 +799,21 @@ RSA_EncryptRaw(SECKEYLowPublicKey *key, unsigned int input_len) { SECStatus rv; - unsigned int modulus_len = SECKEY_LowPublicModulusLen(key); + unsigned int modulus_len = nsslowkey_PublicModulusLen(key); SECItem formatted; SECItem unformatted; formatted.data = NULL; if (max_output_len < modulus_len) goto failure; - PORT_Assert(key->keyType == lowRSAKey); - if (key->keyType != lowRSAKey) + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); + if (key->keyType != NSSLOWKEYRSAKey) goto failure; unformatted.len = input_len; unformatted.data = input; formatted.data = NULL; - rv = RSA_FormatBlock(&formatted, modulus_len, RSA_BlockRaw, &unformatted); + rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockRaw, &unformatted); if (rv != SECSuccess) goto failure; @@ -1017,7 +833,7 @@ failure: /* XXX Doesn't set error code */ SECStatus -RSA_DecryptRaw(SECKEYLowPrivateKey *key, +RSA_DecryptRaw(NSSLOWKEYPrivateKey *key, unsigned char * output, unsigned int * output_len, unsigned int max_output_len, @@ -1025,14 +841,14 @@ RSA_DecryptRaw(SECKEYLowPrivateKey *key, unsigned int input_len) { SECStatus rv; - unsigned int modulus_len = SECKEY_LowPrivateModulusLen(key); + unsigned int modulus_len = nsslowkey_PrivateModulusLen(key); if (modulus_len <= 0) goto failure; if (modulus_len > max_output_len) goto failure; - PORT_Assert(key->keyType == lowRSAKey); - if (key->keyType != lowRSAKey) + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); + if (key->keyType != NSSLOWKEYRSAKey) goto failure; if (input_len != modulus_len) goto failure; diff --git a/security/nss/lib/softoken/secpkcs5.c b/security/nss/lib/softoken/secpkcs5.c deleted file mode 100644 index 1cfa37206..000000000 --- a/security/nss/lib/softoken/secpkcs5.c +++ /dev/null @@ -1,1849 +0,0 @@ -/* - * 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. - */ - -#include "plarena.h" - -#include "seccomon.h" -#include "secitem.h" -#include "secport.h" -#include "hasht.h" -#include "pkcs11t.h" -#include "blapi.h" -#include "sechash.h" -#include "secasn1.h" -#include "secder.h" -#include "secpkcs5.h" -#include "secoid.h" -#include "alghmac.h" -#include "softoken.h" -#include "secerr.h" - -#define DES_IV_LENGTH 8 -#define RC2_IV_LENGTH 8 -#define MD2_LENGTH 16 -#define MD5_LENGTH 16 -#define SHA1_LENGTH 20 -#define SEED_LENGTH 16 -#define SALT_LENGTH 8 -#define PBE_SALT_LENGTH 16 - -/* template for PKCS 5 PBE Parameter. This template has been expanded - * based upon the additions in PKCS 12. This should eventually be moved - * if RSA updates PKCS 5. - */ -const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] = -{ - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, - { SEC_ASN1_OCTET_STRING, - offsetof(SEC_PKCS5PBEParameter, salt) }, - { SEC_ASN1_INTEGER, - offsetof(SEC_PKCS5PBEParameter, iteration) }, - { 0 } -}; - -const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, - { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) }, - { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) }, - { 0 } -}; - -pbeBitGenParameters pbeHashAlgorithmParams[] = { - { 0, 0, SEC_OID_UNKNOWN }, - { 128, 512, SEC_OID_MD2 }, - { 128, 512, SEC_OID_MD5 }, - { 160, 512, SEC_OID_SHA1 }, -}; - -/* generate some random bytes. this is used to generate the - * salt if it is not specified. - */ -static SECStatus -sec_pkcs5_generate_random_bytes(PRArenaPool *poolp, - SECItem *dest, int len) -{ - SECStatus rv = SECFailure; - - if(dest != NULL) - { - void *mark = PORT_ArenaMark(poolp); - dest->data = (unsigned char *)PORT_ArenaZAlloc(poolp, len); - if(dest->data != NULL) - { - dest->len = len; - RNG_GenerateGlobalRandomBytes(dest->data, dest->len); - PORT_ArenaUnmark(poolp, mark); - rv = SECSuccess; - } else - PORT_ArenaRelease(poolp, mark); - } - - return rv; -} - -/* maps hash algorithm from PBE algorithm. - */ -static SECOidTag -sec_pkcs5_hash_algorithm(SECOidTag algorithm) -{ - switch(algorithm) - { - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - return SEC_OID_SHA1; - case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: - return SEC_OID_MD5; - case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: - return SEC_OID_MD2; - default: - break; - } - return SEC_OID_UNKNOWN; -} - -/* get the iv length needed for the PBE algorithm - */ -static int -sec_pkcs5_iv_length(SECOidTag algorithm) -{ - switch(algorithm) - { - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: - return DES_IV_LENGTH; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - return RC2_IV_LENGTH; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: - return 0; - default: - break; - } - return -1; -} - -/* get the key length needed for the PBE algorithm - */ -static int -sec_pkcs5_key_length(SECOidTag algorithm) -{ - switch(algorithm) - { - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: - return 24; - case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: - return 8; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - return 5; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: - return 16; - default: - break; - } - return -1; -} - -/* the V2 algorithms only encode the salt, there is no iteration - * count so we need a check for V2 algorithm parameters. - */ -static PRBool -sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm) -{ - switch(algorithm) - { - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - return PR_TRUE; - default: - break; - } - - return PR_FALSE; -} - -/* creates a PBE parameter based on the PBE algorithm. the only required - * parameters are algorithm and interation. the return is a PBE parameter - * which conforms to PKCS 5 parameter unless an extended parameter is needed. - * this is primarily if keyLen and a variable key length algorithm are - * specified. - * salt - if null, a salt will be generated from random bytes. - * iteration - number of iterations to perform hashing. - * keyLen - only used in variable key length algorithms - * iv - if null, the IV will be generated based on PKCS 5 when needed. - * params - optional, currently unsupported additional parameters. - * once a parameter is allocated, it should be destroyed calling - * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter. - */ -static SEC_PKCS5PBEParameter * -sec_pkcs5_create_pbe_parameter(SECOidTag algorithm, - SECItem *salt, - int iteration) -{ - PRArenaPool *poolp = NULL; - SEC_PKCS5PBEParameter *pbe_param = NULL; - SECStatus rv; - void *dummy = NULL; - - if(iteration < 0) { - return NULL; - } - - poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if(poolp == NULL) - return NULL; - - pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp, - sizeof(SEC_PKCS5PBEParameter)); - if(!pbe_param) { - PORT_FreeArena(poolp, PR_TRUE); - return NULL; - } - - pbe_param->poolp = poolp; - pbe_param->algorithm = algorithm; - - /* should we generate the salt? */ - if(!salt || !salt->data) { - rv = sec_pkcs5_generate_random_bytes(poolp, &pbe_param->salt, - SALT_LENGTH); - } else { - rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt); - } - - if(rv != SECSuccess) { - PORT_FreeArena(poolp, PR_TRUE); - return NULL; - } - - /* encode the integer */ - dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration, - iteration); - rv = (dummy) ? SECSuccess : SECFailure; - - if(rv != SECSuccess) { - PORT_FreeArena(poolp, PR_FALSE); - return NULL; - } - - return pbe_param; -} - -/* generate bits for key and iv using MD5 hashing - */ -static SECItem * -sec_pkcs5_compute_md5_hash(SECItem *salt, SECItem *pwd, int iter, - PRBool dummy) -{ - SECItem *hash = NULL, *pre_hash = NULL; - SECStatus rv = SECFailure; - - if((salt == NULL) || (pwd == NULL) || (iter < 0)) { - return NULL; - } - - hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if((hash != NULL) && (pre_hash != NULL)) { - unsigned int i, ph_len; - - ph_len = MD5_LENGTH; - if(ph_len < (salt->len + pwd->len)) { - ph_len = salt->len + pwd->len; - } - - rv = SECFailure; - hash->data = (unsigned char *)PORT_ZAlloc(MD5_LENGTH); - hash->len = MD5_LENGTH; - pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len); - pre_hash->len = salt->len + pwd->len; - - if((hash->data != NULL) && (pre_hash->data != NULL)) { - rv = SECSuccess; - /* handle 0 length password */ - if(pwd->len > 0) { - PORT_Memcpy(pre_hash->data, pwd->data, pwd->len); - } - if(salt->len > 0) { - PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len); - } - for(i = 0; ((i < (unsigned int)iter) && (rv == SECSuccess)); i++) { - rv = MD5_HashBuf(hash->data, pre_hash->data, pre_hash->len); - if(rv != SECFailure) { - PORT_Memcpy(pre_hash->data, hash->data, MD5_LENGTH); - pre_hash->len = MD5_LENGTH; - } - } - } - } - - if(pre_hash != NULL) - SECITEM_FreeItem(pre_hash, PR_TRUE); - - if((rv == SECFailure) && (hash)) { - SECITEM_FreeItem(hash, PR_TRUE); - hash = NULL; - } - - return hash; -} - -/* generate bits for key and iv using MD2 hashing - */ -static SECItem * -sec_pkcs5_compute_md2_hash(SECItem *salt, SECItem *pwd, int iter, - PRBool dummy) -{ - SECItem *hash = NULL, *pre_hash = NULL; - SECStatus rv = SECFailure; - - if((salt == NULL) || (pwd == NULL) || (iter < 0)) - return NULL; - - hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if((hash != NULL) && (pre_hash != NULL)) - { - int i, ph_len; - - ph_len = MD2_LENGTH; - if((salt->len + pwd->len) > MD2_LENGTH) - ph_len = salt->len+pwd->len; - - rv = SECFailure; - hash->data = (unsigned char *)PORT_ZAlloc(MD2_LENGTH); - hash->len = MD2_LENGTH; - pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len); - pre_hash->len = salt->len + pwd->len; - - if((hash->data != NULL) && (pre_hash->data != NULL)) - { - MD2Context *ctxt; - - rv = SECSuccess; - if(pwd->len > 0) { - PORT_Memcpy(pre_hash->data, pwd->data, pwd->len); - } - if(salt->len > 0) { - PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len); - } - - for(i = 0; ((i < iter) && (rv == SECSuccess)); i++) - { - ctxt = MD2_NewContext(); - if(ctxt == NULL) - rv = SECFailure; - else - { - MD2_Update(ctxt, pre_hash->data, pre_hash->len); - MD2_End(ctxt, hash->data, &hash->len, hash->len); - PORT_Memcpy(pre_hash->data, hash->data, MD2_LENGTH); - pre_hash->len = MD2_LENGTH; - MD2_DestroyContext(ctxt, PR_TRUE); - } - } - } - } - - if(pre_hash != NULL) - SECITEM_FreeItem(pre_hash, PR_TRUE); - - if(rv != SECSuccess) - if(hash != NULL) - { - SECITEM_FreeItem(hash, PR_TRUE); - hash = NULL; - } - - return hash; -} - -/* generate bits using SHA1 hash - */ -static SECItem * -sec_pkcs5_compute_sha1_hash(SECItem *salt, SECItem *pwd, int iter, - PRBool faulty3DES) -{ - SECItem *hash = NULL, *pre_hash = NULL; - SECStatus rv = SECFailure; - - if((salt == NULL) || (pwd == NULL) || (iter < 0)) { - return NULL; - } - - hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - - if((hash != NULL) && (pre_hash != NULL)) { - int i, ph_len; - - ph_len = SHA1_LENGTH; - if((salt->len + pwd->len) > SHA1_LENGTH) { - ph_len = salt->len + pwd->len; - } - - rv = SECFailure; - - /* allocate buffers */ - hash->data = (unsigned char *)PORT_ZAlloc(SHA1_LENGTH); - hash->len = SHA1_LENGTH; - pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len); - - /* in pbeSHA1TripleDESCBC there was an allocation error that made - * it into the caller. We do not want to propagate those errors - * further, so we are doing it correctly, but reading the old method. - */ - if(faulty3DES) { - pre_hash->len = ph_len; - } else { - pre_hash->len = salt->len + pwd->len; - } - - /* preform hash */ - if((hash->data != NULL) && (pre_hash->data != NULL)) { - rv = SECSuccess; - /* check for 0 length password */ - if(pwd->len > 0) { - PORT_Memcpy(pre_hash->data, pwd->data, pwd->len); - } - if(salt->len > 0) { - PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len); - } - for(i = 0; ((i < iter) && (rv == SECSuccess)); i++) { - rv = SHA1_HashBuf(hash->data, pre_hash->data, pre_hash->len); - if(rv != SECFailure) { - pre_hash->len = SHA1_LENGTH; - PORT_Memcpy(pre_hash->data, hash->data, SHA1_LENGTH); - } - } - } - } - - if(pre_hash != NULL) { - SECITEM_FreeItem(pre_hash, PR_TRUE); - } - - if((rv != SECSuccess) && (hash != NULL)) { - SECITEM_FreeItem(hash, PR_TRUE); - hash = NULL; - } - - return hash; -} - -/* bit generation/key and iv generation routines. */ -typedef SECItem *(* sec_pkcs5_hash_func)(SECItem *s, SECItem *p, - int iter, PRBool faulty3DES); - -/* generates bits needed for the key and iv based on PKCS 5, - * be concatenating the password and salt and using the appropriate - * hash algorithm. This function serves as a front end to the - * specific hash functions above. a return of NULL indicates an - * error. - */ -static SECItem * -sec_pkcs5_compute_hash(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem, - PRBool faulty3DES) -{ - sec_pkcs5_hash_func hash_func; - SECOidTag hash_alg; - SECItem *hash = NULL; - SECItem *salt = NULL; - - hash_alg = sec_pkcs5_hash_algorithm(pbe_param->algorithm); - salt = &(pbe_param->salt); - switch(hash_alg) - { - case SEC_OID_SHA1: - hash_func = sec_pkcs5_compute_sha1_hash; - break; - case SEC_OID_MD2: - hash_func = sec_pkcs5_compute_md2_hash; - break; - case SEC_OID_MD5: - hash_func = sec_pkcs5_compute_md5_hash; - break; - default: - hash_func = NULL; - } - - if(hash_func) { - hash = (* hash_func)(salt, pwitem, pbe_param->iter, faulty3DES); - } - - return hash; -} - -/* determines the number of bits needed for key and iv generation - * based upon the algorithm identifier. if a number of - * bits greater than the hash algorithm can produce are needed, - * the bits will be generated based upon the extended PKCS 5 - * described in PKCS 12. - * - * a return of -1 indicates an error. - */ -static int -sec_pkcs5_bits_needed(SEC_PKCS5PBEParameter *pbe_param) -{ - int iv_bits; - int key_bits; - - if(pbe_param == NULL) { - return -1; - } - - iv_bits = sec_pkcs5_iv_length(pbe_param->algorithm) * 8; - key_bits = sec_pkcs5_key_length(pbe_param->algorithm) * 8; - - if(key_bits != 0) { - return iv_bits + key_bits; - } - - return -1; -} - -/* determines the number of bits generated by each hash algorithm. - * in case of an error, -1 is returned. - */ -static int -sec_pkcs5_hash_bits_generated(SEC_PKCS5PBEParameter *pbe_param) -{ - if(pbe_param == NULL) { - return -1; - } - - switch(sec_pkcs5_hash_algorithm(pbe_param->algorithm)) { - case SEC_OID_SHA1: - return SHA1_LENGTH * 8; - case SEC_OID_MD2: - return MD2_LENGTH * 8; - case SEC_OID_MD5: - return MD5_LENGTH * 8; - default: - break; - } - - return -1; -} - -/* this bit generation routine is described in PKCS 12 and the proposed - * extensions to PKCS 5. an initial hash is generated following the - * instructions laid out in PKCS 5. If the number of bits generated is - * insufficient, then the method discussed in the proposed extensions to - * PKCS 5 in PKCS 12 are used. This extension makes use of the HMAC - * function. And the P_Hash function from the TLS standard. - */ -static SECItem * -sec_pkcs5_bit_generator(SEC_PKCS5PBEParameter *pbe_param, - SECItem *init_hash, - unsigned int bits_needed) -{ - SECItem *ret_bits = NULL; - int hash_size = 0; - unsigned int i; - unsigned int hash_iter; - unsigned int dig_len; - SECStatus rv = SECFailure; - unsigned char *state = NULL; - unsigned int state_len; - HMACContext *cx = NULL; - - hash_size = sec_pkcs5_hash_bits_generated(pbe_param); - if(hash_size == -1) - return NULL; - - hash_iter = (bits_needed + (unsigned int)hash_size - 1) / hash_size; - hash_size /= 8; - - /* allocate return buffer */ - ret_bits = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(ret_bits == NULL) - return NULL; - ret_bits->data = (unsigned char *)PORT_ZAlloc((hash_iter * hash_size) + 1); - ret_bits->len = (hash_iter * hash_size); - if(ret_bits->data == NULL) { - PORT_Free(ret_bits); - return NULL; - } - - /* allocate intermediate hash buffer. 8 is for the 8 bytes of - * data which are added based on iteration number - */ - - if ((unsigned int)hash_size > pbe_param->salt.len) { - state_len = hash_size; - } else { - state_len = pbe_param->salt.len; - } - state = (unsigned char *)PORT_ZAlloc(state_len); - if(state == NULL) { - rv = SECFailure; - goto loser; - } - if(pbe_param->salt.len > 0) { - PORT_Memcpy(state, pbe_param->salt.data, pbe_param->salt.len); - } - - cx = HMAC_Create(sec_pkcs5_hash_algorithm(pbe_param->algorithm), - init_hash->data, init_hash->len); - if (cx == NULL) { - rv = SECFailure; - goto loser; - } - - for(i = 0; i < hash_iter; i++) { - - /* generate output bits */ - HMAC_Begin(cx); - HMAC_Update(cx, state, state_len); - HMAC_Update(cx, pbe_param->salt.data, pbe_param->salt.len); - rv = HMAC_Finish(cx, ret_bits->data + (i * hash_size), - &dig_len, hash_size); - if (rv != SECSuccess) - goto loser; - PORT_Assert((unsigned int)hash_size == dig_len); - - /* generate new state */ - HMAC_Begin(cx); - HMAC_Update(cx, state, state_len); - rv = HMAC_Finish(cx, state, &state_len, state_len); - if (rv != SECSuccess) - goto loser; - PORT_Assert(state_len == dig_len); - } - -loser: - if (state != NULL) - PORT_ZFree(state, state_len); - HMAC_Destroy(cx); - - if(rv != SECSuccess) { - SECITEM_ZfreeItem(ret_bits, PR_TRUE); - ret_bits = NULL; - } - - return ret_bits; -} - -/* generate bits for the key and iv determination. if enough bits - * are not generated using PKCS 5, then we need to generate more bits - * based on the extension proposed in PKCS 12 - */ -static SECItem * -sec_pkcs5_generate_bits(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem, - PRBool faulty3DES) -{ - SECItem * hash = NULL; - SECItem * newHash = NULL; - int bits_needed; - int bits_available; - - bits_needed = sec_pkcs5_bits_needed(pbe_param); - bits_available = sec_pkcs5_hash_bits_generated(pbe_param); - - if((bits_needed == -1) || (bits_available == -1)) { - return NULL; - } - - hash = sec_pkcs5_compute_hash(pbe_param, pwitem, faulty3DES); - if(hash == NULL) { - return NULL; - } - - if(bits_needed <= bits_available) { - return hash; - } - - newHash = sec_pkcs5_bit_generator(pbe_param, hash, bits_needed); - if (hash != newHash) - SECITEM_FreeItem(hash, PR_TRUE); - return newHash; -} - -/* compute the IV as per PKCS 5 - */ -static SECItem * -sec_pkcs5_compute_iv(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem, - PRBool faulty3DES) -{ - SECItem *hash = NULL, *iv = NULL; - - if((pbe_param == NULL) || (pwitem == NULL)) { - return NULL; - } - - /* generate iv */ - iv = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(!iv) { - return NULL; - } - - iv->len = sec_pkcs5_iv_length(pbe_param->algorithm); - if(iv->len == -1) { - PORT_Free(iv); - return NULL; - } - - iv->data = (unsigned char *)PORT_ZAlloc(iv->len); - if(iv->data == NULL) { - PORT_Free(iv); - return NULL; - } - - if(sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(pbe_param->algorithm)) { - SECOidTag hashAlg; - PBEBitGenContext *ctxt; - hashAlg = sec_pkcs5_hash_algorithm(pbe_param->algorithm); - ctxt = PBE_CreateContext(hashAlg, pbeBitGenCipherIV, - pwitem, &pbe_param->salt, - iv->len * 8, pbe_param->iter); - if(!ctxt) { - SECITEM_FreeItem(iv, PR_TRUE); - return NULL; - } - - hash = PBE_GenerateBits(ctxt); - PBE_DestroyContext(ctxt); - } else { - hash = sec_pkcs5_generate_bits(pbe_param, pwitem, faulty3DES); - } - - if(!hash) { - SECITEM_FreeItem(iv, PR_TRUE); - return NULL; - } - - PORT_Memcpy(iv->data, (hash->data+(hash->len - iv->len)), iv->len); - SECITEM_FreeItem(hash, PR_TRUE); - - return iv; -} - -/* generate key as per PKCS 5 - */ -static SECItem * -sec_pkcs5_compute_key(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem, - PRBool faulty3DES) -{ - SECItem *hash = NULL, *key = NULL; - - if((pbe_param == NULL) || (pwitem == NULL)) { - return NULL; - } - - key = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(!key) { - return NULL; - } - - key->len = sec_pkcs5_key_length(pbe_param->algorithm); - if(key->len == -1) { - PORT_Free(key); - return NULL; - } - - key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * - key->len); - if(!key->data) { - PORT_Free(key); - return NULL; - } - - - if(sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(pbe_param->algorithm)) { - SECOidTag hashAlg; - PBEBitGenContext *ctxt; - hashAlg = sec_pkcs5_hash_algorithm(pbe_param->algorithm); - ctxt = PBE_CreateContext(hashAlg, pbeBitGenCipherKey, - pwitem, &pbe_param->salt, - key->len * 8, pbe_param->iter); - if(!ctxt) { - SECITEM_FreeItem(key, PR_TRUE); - return NULL; - } - - hash = PBE_GenerateBits(ctxt); - PBE_DestroyContext(ctxt); - } else { - hash = sec_pkcs5_generate_bits(pbe_param, pwitem, faulty3DES); - } - - if(!hash) { - SECITEM_FreeItem(key, PR_TRUE); - return NULL; - } - - if(pbe_param->algorithm == - SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC) { - PORT_Memcpy(key->data, hash->data, (key->len * 2) / 3); - PORT_Memcpy(&(key->data[(key->len * 2) / 3]), key->data, - key->len / 3); - } else { - PORT_Memcpy(key->data, hash->data, key->len); - } - - SECITEM_FreeItem(hash, PR_TRUE); - return key; -} - -/* decode the algid and generate a PKCS 5 parameter from it - */ -static SEC_PKCS5PBEParameter * -sec_pkcs5_convert_algid(SECAlgorithmID *algid) -{ - PRArenaPool *poolp; - SEC_PKCS5PBEParameter *pbe_param = NULL; - SECOidTag algorithm; - SECStatus rv = SECFailure; - - if(algid == NULL) - return NULL; - - algorithm = SECOID_GetAlgorithmTag(algid); - - if(sec_pkcs5_hash_algorithm(algorithm) == SEC_OID_UNKNOWN) - return NULL; - - poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if(poolp == NULL) - return NULL; - - /* allocate memory for the parameter */ - pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp, - sizeof(SEC_PKCS5PBEParameter)); - - /* decode parameter */ - if(pbe_param && !sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { - pbe_param->poolp = poolp; - rv = SEC_ASN1DecodeItem(poolp, pbe_param, - SEC_PKCS5PBEParameterTemplate, &algid->parameters); - if(rv != SECSuccess) { - goto loser; - } - pbe_param->algorithm = algorithm; - pbe_param->iter = DER_GetInteger(&pbe_param->iteration); - } else if(sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { - pbe_param->algorithm = algorithm; - pbe_param->poolp = poolp; - rv = SEC_ASN1DecodeItem(poolp, pbe_param, SEC_V2PKCS12PBEParameterTemplate, - &algid->parameters); - if(rv != SECSuccess) { - goto loser; - } - pbe_param->iter = DER_GetInteger(&pbe_param->iteration); - } - -loser: - if((pbe_param == NULL) || (rv != SECSuccess)) { - PORT_FreeArena(poolp, PR_TRUE); - pbe_param = NULL; - } - - return pbe_param; -} - -/* destroy a pbe parameter. it assumes that the parameter was - * generated using the appropriate create function and therefor - * contains an arena pool. - */ -static void -sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param) -{ - if(pbe_param != NULL) - PORT_FreeArena(pbe_param->poolp, PR_TRUE); -} - - -/* crypto routines */ - -/* function pointer template for crypto functions */ -typedef SECItem *(* pkcs5_crypto_func)(SECItem *key, SECItem *iv, - SECItem *src, PRBool op1, PRBool op2); - -/* map PBE algorithm to crypto algorithm */ -static SECOidTag -sec_pkcs5_encryption_algorithm(SECOidTag algorithm) -{ - switch(algorithm) - { - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: - return SEC_OID_DES_EDE3_CBC; - case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: - return SEC_OID_DES_CBC; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - return SEC_OID_RC2_CBC; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: - return SEC_OID_RC4; - default: - break; - } - return SEC_OID_UNKNOWN; -} - -/* perform DES encryption and decryption. these routines are called - * by SEC_PKCS5CipherData. In the case of an error, NULL is returned. - */ -static SECItem * -sec_pkcs5_des(SECItem *key, - SECItem *iv, - SECItem *src, - PRBool triple_des, - PRBool encrypt) -{ - SECItem *dest; - SECItem *dup_src; - SECStatus rv = SECFailure; - int pad; - - if((src == NULL) || (key == NULL) || (iv == NULL)) - return NULL; - - dup_src = SECITEM_DupItem(src); - if(dup_src == NULL) { - return NULL; - } - - if(encrypt != PR_FALSE) { - void *dummy; - - dummy = DES_PadBuffer(NULL, dup_src->data, - dup_src->len, &dup_src->len); - if(dummy == NULL) { - SECITEM_FreeItem(dup_src, PR_TRUE); - return NULL; - } - dup_src->data = (unsigned char*)dummy; - } - - dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(dest != NULL) { - /* allocate with over flow */ - dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64); - if(dest->data != NULL) { - DESContext *ctxt; - ctxt = DES_CreateContext(key->data, iv->data, - (triple_des ? NSS_DES_EDE3_CBC : NSS_DES_CBC), - encrypt); - - if(ctxt != NULL) { - rv = ((encrypt != PR_TRUE) ? DES_Decrypt : DES_Encrypt)( - ctxt, dest->data, &dest->len, - dup_src->len + 64, dup_src->data, dup_src->len); - - /* remove padding -- assumes 64 bit blocks */ - if((encrypt == PR_FALSE) && (rv == SECSuccess)) { - pad = dest->data[dest->len-1]; - if((pad > 0) && (pad <= 8)) { - if(dest->data[dest->len-pad] != pad) { - rv = SECFailure; - PORT_SetError(SEC_ERROR_BAD_PASSWORD); - } else { - dest->len -= pad; - } - } else { - rv = SECFailure; - PORT_SetError(SEC_ERROR_BAD_PASSWORD); - } - } - DES_DestroyContext(ctxt, PR_TRUE); - } - } - } - - if(rv == SECFailure) { - if(dest != NULL) { - SECITEM_FreeItem(dest, PR_TRUE); - } - dest = NULL; - } - - if(dup_src != NULL) { - SECITEM_FreeItem(dup_src, PR_TRUE); - } - - return dest; -} - -/* perform rc2 encryption/decryption if an error occurs, NULL is returned - */ -static SECItem * -sec_pkcs5_rc2(SECItem *key, - SECItem *iv, - SECItem *src, - PRBool cbc_mode, - PRBool encrypt) -{ - SECItem *dest; - SECItem *dup_src; - SECStatus rv = SECFailure; - int pad; - - if((src == NULL) || (key == NULL) || (iv == NULL)) { - return NULL; - } - - dup_src = SECITEM_DupItem(src); - if(dup_src == NULL) { - return NULL; - } - - if(encrypt != PR_FALSE) { - void *dummy; - - dummy = DES_PadBuffer(NULL, dup_src->data, - dup_src->len, &dup_src->len); - if(dummy == NULL) { - SECITEM_FreeItem(dup_src, PR_TRUE); - return NULL; - } - dup_src->data = (unsigned char*)dummy; - } - - dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(dest != NULL) { - dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64); - if(dest->data != NULL) { - RC2Context *ctxt; - - ctxt = RC2_CreateContext(key->data, key->len, iv->data, - ((cbc_mode != PR_TRUE) ? NSS_RC2 : NSS_RC2_CBC), - key->len); - - if(ctxt != NULL) { - rv = ((encrypt != PR_TRUE) ? RC2_Decrypt : RC2_Encrypt)( - ctxt, dest->data, &dest->len, - dup_src->len + 64, dup_src->data, dup_src->len); - - /* assumes 8 byte blocks -- remove padding */ - if((rv == SECSuccess) && (encrypt != PR_TRUE) && - (cbc_mode == PR_TRUE)) { - pad = dest->data[dest->len-1]; - if((pad > 0) && (pad <= 8)) { - if(dest->data[dest->len-pad] != pad) { - PORT_SetError(SEC_ERROR_BAD_PASSWORD); - rv = SECFailure; - } else { - dest->len -= pad; - } - } else { - PORT_SetError(SEC_ERROR_BAD_PASSWORD); - rv = SECFailure; - } - } - - } - } - } - - if((rv != SECSuccess) && (dest != NULL)) { - SECITEM_FreeItem(dest, PR_TRUE); - dest = NULL; - } - - if(dup_src != NULL) { - SECITEM_FreeItem(dup_src, PR_TRUE); - } - - return dest; -} - -/* perform rc4 encryption and decryption */ -static SECItem * -sec_pkcs5_rc4(SECItem *key, - SECItem *iv, - SECItem *src, - PRBool dummy_op, - PRBool encrypt) -{ - SECItem *dest; - SECStatus rv = SECFailure; - - if((src == NULL) || (key == NULL) || (iv == NULL)) { - return NULL; - } - - dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(dest != NULL) { - dest->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * - (src->len + 64)); - if(dest->data != NULL) { - RC4Context *ctxt; - - ctxt = RC4_CreateContext(key->data, key->len); - if(ctxt) { - rv = ((encrypt != PR_FALSE) ? RC4_Decrypt : RC4_Encrypt)( - ctxt, dest->data, &dest->len, - src->len + 64, src->data, src->len); - RC4_DestroyContext(ctxt, PR_TRUE); - } - } - } - - if((rv != SECSuccess) && (dest)) { - SECITEM_FreeItem(dest, PR_TRUE); - dest = NULL; - } - - return dest; -} - -/* performs the cipher operation on the src and returns the result. - * if an error occurs, NULL is returned. - * - * a null length password is allowed. this corresponds to encrypting - * the data with ust the salt. - */ -/* change this to use PKCS 11? */ -SECItem * -SEC_PKCS5CipherData(SECAlgorithmID *algid, - SECItem *pwitem, - SECItem *src, - PRBool encrypt, PRBool *update) -{ - SEC_PKCS5PBEParameter *pbe_param; - SECOidTag enc_alg; - SECItem *key = NULL, *iv = NULL; - SECItem *dest = NULL; - int iv_len; - - if (update) { - *update = PR_FALSE; - } - - if((algid == NULL) || (pwitem == NULL) || (src == NULL)) { - return NULL; - } - - /* convert algid to pbe parameter */ - pbe_param = sec_pkcs5_convert_algid(algid); - if(pbe_param == NULL) { - return NULL; - } - - /* get algorithm, key, and iv */ - enc_alg = sec_pkcs5_encryption_algorithm(pbe_param->algorithm); - key = sec_pkcs5_compute_key(pbe_param, pwitem, PR_FALSE); - if(key != NULL) { - iv_len = sec_pkcs5_iv_length(pbe_param->algorithm); - iv = sec_pkcs5_compute_iv(pbe_param, pwitem, PR_FALSE); - - if((iv != NULL) || (iv_len == 0)) { - /*perform encryption / decryption */ - PRBool op1 = PR_TRUE; - pkcs5_crypto_func cryptof; - - switch(enc_alg) { - case SEC_OID_DES_EDE3_CBC: - cryptof = sec_pkcs5_des; - break; - case SEC_OID_DES_CBC: - cryptof = sec_pkcs5_des; - op1 = PR_FALSE; - break; - case SEC_OID_RC2_CBC: - cryptof = sec_pkcs5_rc2; - break; - case SEC_OID_RC4: - cryptof = sec_pkcs5_rc4; - break; - default: - cryptof = NULL; - break; - } - - if(cryptof) { - dest = (*cryptof)(key, iv, src, op1, encrypt); - /* - * it's possible for some keys and keydb's to claim to - * be triple des when they're really des. In this case - * we simply try des. If des works we set the update flag - * so the key db knows it needs to update all it's entries. - * The case can only happen on decrypted of a - * SEC_OID_DES_EDE3_CBD. - */ - if ((dest == NULL) && (encrypt == PR_FALSE) && - (enc_alg == SEC_OID_DES_EDE3_CBC)) { - dest = (*cryptof)(key, iv, src, PR_FALSE, encrypt); - if (update && (dest != NULL)) *update = PR_TRUE; - } - } - } - } - - sec_pkcs5_destroy_pbe_param(pbe_param); - - if(key != NULL) { - SECITEM_ZfreeItem(key, PR_TRUE); - } - if(iv != NULL) { - SECITEM_ZfreeItem(iv, PR_TRUE); - } - - return dest; -} - -/* creates a algorithm ID containing the PBE algorithm and appropriate - * parameters. the required parameter is the algorithm. if salt is - * not specified, it is generated randomly. if IV is specified, it overrides - * the PKCS 5 generation of the IV. - * - * the returned SECAlgorithmID should be destroyed using - * SECOID_DestroyAlgorithmID - */ -SECAlgorithmID * -SEC_PKCS5CreateAlgorithmID(SECOidTag algorithm, - SECItem *salt, - int iteration) -{ - PRArenaPool *poolp = NULL; - SECAlgorithmID *algid, *ret_algid; - SECItem der_param; - SECStatus rv = SECFailure; - SEC_PKCS5PBEParameter *pbe_param; - - if(sec_pkcs5_hash_algorithm(algorithm) == SEC_OID_UNKNOWN) - return NULL; - - if(iteration <= 0) { - return NULL; - } - - der_param.data = NULL; - der_param.len = 0; - - /* generate the parameter */ - pbe_param = sec_pkcs5_create_pbe_parameter(algorithm, salt, iteration); - if(!pbe_param) { - return NULL; - } - - poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if(!poolp) { - sec_pkcs5_destroy_pbe_param(pbe_param); - return NULL; - } - - /* generate the algorithm id */ - algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID)); - if(algid != NULL) { - void *dummy; - if(!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { - dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, - SEC_PKCS5PBEParameterTemplate); - } else { - dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, - SEC_V2PKCS12PBEParameterTemplate); - } - - if(dummy) { - rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param); - } - } - - ret_algid = NULL; - if(algid != NULL) { - ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID)); - if(ret_algid != NULL) { - rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid); - if(rv != SECSuccess) { - SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE); - ret_algid = NULL; - } - } - } - - if(poolp != NULL) { - PORT_FreeArena(poolp, PR_TRUE); - algid = NULL; - } - - sec_pkcs5_destroy_pbe_param(pbe_param); - - return ret_algid; -} - -/* wrapper for converting the algid to a pbe parameter. - */ -SEC_PKCS5PBEParameter * -SEC_PKCS5GetPBEParameter(SECAlgorithmID *algid) -{ - if(algid) { - return sec_pkcs5_convert_algid(algid); - } - - return NULL; -} - -/* destroy a pbe parameter */ -void -SEC_PKCS5DestroyPBEParameter(SEC_PKCS5PBEParameter *pbe_param) -{ - sec_pkcs5_destroy_pbe_param(pbe_param); -} - -/* return the initialization vector either the preset one if it - * exists or generated based on pkcs 5. - * - * a null length password is allowed...but not a null password - * secitem. - */ -SECItem * -SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES) -{ - SECItem *iv; - SEC_PKCS5PBEParameter *pbe_param; - - if((algid == NULL) || (pwitem == NULL)) { - return NULL; - } - - pbe_param = sec_pkcs5_convert_algid(algid); - if(!pbe_param) { - return NULL; - } - - iv = sec_pkcs5_compute_iv(pbe_param, pwitem, faulty3DES); - - sec_pkcs5_destroy_pbe_param(pbe_param); - - return iv; -} - -/* generate the key - * a 0 length password is allowed. corresponds to a key generated - * from just the salt. - */ -SECItem * -SEC_PKCS5GetKey(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES) -{ - SECItem *key; - SEC_PKCS5PBEParameter *pbe_param; - - if((algid == NULL) || (pwitem == NULL)) { - return NULL; - } - - pbe_param = sec_pkcs5_convert_algid(algid); - if(pbe_param == NULL) { - return NULL; - } - - key = sec_pkcs5_compute_key(pbe_param, pwitem, faulty3DES); - - sec_pkcs5_destroy_pbe_param(pbe_param); - - return key; -} - -/* retrieve the salt */ -SECItem * -SEC_PKCS5GetSalt(SECAlgorithmID *algid) -{ - SECItem *salt; - SEC_PKCS5PBEParameter *pbe_param; - - if(algid == NULL) - return NULL; - - pbe_param = sec_pkcs5_convert_algid(algid); - if(pbe_param == NULL) - return NULL; - - if(pbe_param->salt.data) { - salt = SECITEM_DupItem(&pbe_param->salt); - } else { - salt = NULL; - } - - sec_pkcs5_destroy_pbe_param(pbe_param); - - return salt; -} - -/* check to see if an oid is a pbe algorithm - */ -PRBool -SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid) -{ - SECOidTag algorithm; - - algorithm = SECOID_GetAlgorithmTag(algid); - if(sec_pkcs5_hash_algorithm(algorithm) == SEC_OID_UNKNOWN) { - return PR_FALSE; - } - - return PR_TRUE; -} - -int -SEC_PKCS5GetKeyLength(SECAlgorithmID *algid) -{ - SEC_PKCS5PBEParameter *pbe_param; - int keyLen = -1; - - if(algid == NULL) - return -1; - - pbe_param = sec_pkcs5_convert_algid(algid); - if(pbe_param == NULL) - return -1; - - keyLen = sec_pkcs5_key_length(pbe_param->algorithm); - - sec_pkcs5_destroy_pbe_param(pbe_param); - - return keyLen; -} - -/* maps crypto algorithm from PBE algorithm. - */ -SECOidTag -SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid) -{ - SEC_PKCS5PBEParameter *pbe_param; - - if(algid == NULL) - return SEC_OID_UNKNOWN; - - pbe_param = sec_pkcs5_convert_algid(algid); - if(pbe_param == NULL) - return SEC_OID_UNKNOWN; - - switch(pbe_param->algorithm) - { - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: - return SEC_OID_DES_EDE3_CBC; - case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: - return SEC_OID_DES_CBC; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - return SEC_OID_RC2_CBC; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: - return SEC_OID_RC4; - default: - break; - } - - sec_pkcs5_destroy_pbe_param(pbe_param); - - return SEC_OID_UNKNOWN; -} - -/* maps PBE algorithm from crypto algorithm, assumes SHA1 hashing. - */ -SECOidTag -SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen) -{ - switch(algTag) - { - case SEC_OID_DES_EDE3_CBC: - switch(keyLen) { - case 168: - case 192: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC; - case 128: - case 92: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC; - default: - break; - } - break; - case SEC_OID_DES_CBC: - return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC; - case SEC_OID_RC2_CBC: - switch(keyLen) { - case 40: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; - case 128: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC; - default: - break; - } - break; - case SEC_OID_RC4: - switch(keyLen) { - case 40: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4; - case 128: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4; - default: - break; - } - break; - default: - break; - } - - return SEC_OID_UNKNOWN; -} - -/* zero length password and salts are allowed. however, the items - * containing the salt and password must be non-null. - */ -PBEBitGenContext * -__PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, - SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, - unsigned int iterations) -{ - PRArenaPool *arena = NULL; - PBEBitGenContext *pbeCtxt = NULL; - HASH_HashType pbeHash; - int vbytes, ubytes; - - unsigned int c; - - if(!pwitem || !salt) { - return NULL; - } - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if(!arena) { - return NULL; - } - - pbeCtxt = (PBEBitGenContext*)PORT_ArenaZAlloc(arena, sizeof(PBEBitGenContext)); - if(!pbeCtxt) { - goto loser; - } - - switch(hashAlgorithm) { - case SEC_OID_MD2: - pbeHash = HASH_AlgMD2; - break; - case SEC_OID_MD5: - pbeHash = HASH_AlgMD5; - break; - case SEC_OID_SHA1: - pbeHash = HASH_AlgSHA1; - break; - default: - goto loser; - } - - pbeCtxt->hashObject = &SECRawHashObjects[pbeHash]; - PORT_Memcpy(&pbeCtxt->pbeParams, &pbeHashAlgorithmParams[pbeHash], - sizeof(pbeBitGenParameters)); - PORT_Assert(pbeCtxt->pbeParams.hashAlgorithm == hashAlgorithm); - - vbytes = pbeCtxt->pbeParams.v / 8; - ubytes = pbeCtxt->pbeParams.u / 8; - - c = (bitsNeeded / pbeCtxt->pbeParams.u); - c += ((bitsNeeded - (pbeCtxt->pbeParams.u * c)) > 0) ? 1 : 0; - pbeCtxt->c = c; - pbeCtxt->n = bitsNeeded; - pbeCtxt->iterations = iterations; - - /* allocate buffers */ - pbeCtxt->D.len = vbytes; - pbeCtxt->S.len = (((salt->len * 8) / pbeCtxt->pbeParams.v) + - ((((salt->len * 8) % pbeCtxt->pbeParams.v) > 0) ? 1 : 0)) * - vbytes; - pbeCtxt->P.len = (((pwitem->len * 8) / pbeCtxt->pbeParams.v) + - ((((pwitem->len * 8) % pbeCtxt->pbeParams.v) > 0) ? 1 : 0)) * - vbytes; - pbeCtxt->I.len = pbeCtxt->S.len + pbeCtxt->P.len; - pbeCtxt->A.len = c * ubytes; - pbeCtxt->B.len = pbeCtxt->D.len; - - pbeCtxt->D.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->D.len); - if(pbeCtxt->S.len) { - pbeCtxt->S.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->S.len); - } - if(pbeCtxt->P.len) { - pbeCtxt->P.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->P.len); - } - if(pbeCtxt->I.len) { - pbeCtxt->I.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->I.len); - } - pbeCtxt->A.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->A.len); - pbeCtxt->B.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->B.len); - - if(!pbeCtxt->D.data || !pbeCtxt->A.data || !pbeCtxt->B.data || - (!pbeCtxt->S.data && pbeCtxt->S.len) || - (!pbeCtxt->P.data && pbeCtxt->P.len) || - (!pbeCtxt->I.data && pbeCtxt->I.len)) { - goto loser; - } - - PORT_Memset(pbeCtxt->D.data, (char)bitGenPurpose, pbeCtxt->D.len); - if(pbeCtxt->P.len) { - unsigned int z = 0; - while(z < pbeCtxt->P.len) { - PORT_Memcpy(&(pbeCtxt->P.data[z]), pwitem->data, - ((z + pwitem->len > pbeCtxt->P.len) ? (pbeCtxt->P.len - z) : - (pwitem->len))); - z += pwitem->len; - } - } - if(pbeCtxt->S.len) { - unsigned int z = 0; - while(z < pbeCtxt->S.len) { - PORT_Memcpy(&(pbeCtxt->S.data[z]), salt->data, - ((z + salt->len > pbeCtxt->S.len) ? (pbeCtxt->S.len - z) : - (salt->len))); - z += salt->len; - } - } - if(pbeCtxt->I.len) { - if(pbeCtxt->S.len) { - PORT_Memcpy(pbeCtxt->I.data, pbeCtxt->S.data, pbeCtxt->S.len); - } - if(pbeCtxt->P.len) { - PORT_Memcpy(&(pbeCtxt->I.data[pbeCtxt->S.len]), pbeCtxt->P.data, - pbeCtxt->P.len); - } - } - - pbeCtxt->arena = arena; - - return pbeCtxt; - -loser: - if(arena) { - PORT_FreeArena(arena, PR_TRUE); - } - - return NULL; -} - -PBEBitGenContext * -PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, - SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, - unsigned int iterations) -{ - return __PBE_CreateContext(hashAlgorithm, bitGenPurpose, pwitem, - salt, bitsNeeded, iterations); -} - -SECItem * -__PBE_GenerateBits(PBEBitGenContext *pbeCtxt) -{ - unsigned int i; - SECItem *A, *D, *I, *B, *S, *P; - unsigned int u, v, c, z, hashLen, n, iter; - unsigned int vbyte, ubyte; - unsigned char *iterBuf; - void *hash = NULL; - - if(!pbeCtxt) { - return NULL; - } - - A = &pbeCtxt->A; - B = &pbeCtxt->B; - I = &pbeCtxt->I; - D = &pbeCtxt->D; - S = &pbeCtxt->S; - P = &pbeCtxt->P; - u = pbeCtxt->pbeParams.u; - v = pbeCtxt->pbeParams.v; - vbyte = v / 8; - ubyte = u / 8; - c = pbeCtxt->c; - n = pbeCtxt->n; - z = 0; - - iterBuf = (unsigned char*)PORT_Alloc(ubyte); - if(!iterBuf) { - goto loser; - } - - for(i = 1; i <= c; i++) { - unsigned int Bidx; - unsigned int k, j; - - - for(iter = 1; iter <= pbeCtxt->iterations; iter++) { - hash = pbeCtxt->hashObject->create(); - if(!hash) { - goto loser; - } - - pbeCtxt->hashObject->begin(hash); - - if(iter == 1) { - pbeCtxt->hashObject->update(hash, D->data, D->len); - pbeCtxt->hashObject->update(hash, I->data, I->len); - } else { - pbeCtxt->hashObject->update(hash, iterBuf, hashLen); - } - - pbeCtxt->hashObject->end(hash, iterBuf, &hashLen, (ubyte)); - pbeCtxt->hashObject->destroy(hash, PR_TRUE); - if(hashLen != (ubyte)) { - goto loser; - } - } - - PORT_Memcpy(&(A->data[z]), iterBuf, (ubyte)); - - Bidx = 0; - while(Bidx < B->len) { - PORT_Memcpy(&(B->data[Bidx]), &(A->data[z]), - (((Bidx + (ubyte)) > B->len) ? (B->len - Bidx) : - (ubyte))); - Bidx += (ubyte); - } - - k = (S->len / (vbyte)) + (P->len / (vbyte)); - for(j = 0; j < k; j++) { - unsigned int byteIdx = (vbyte); - unsigned int q, carryBit = 0; - - while(byteIdx > 0) { - q = (unsigned int)I->data[(j * (vbyte)) + byteIdx - 1]; - q += (unsigned int)B->data[byteIdx - 1]; - q += carryBit; - if(byteIdx == (vbyte)) { - q += 1; - } - - carryBit = ((q > 255) ? 1 : 0); - - I->data[(j * (vbyte)) + byteIdx - 1] = (unsigned char)(q & 255); - - byteIdx--; - } - } - - z += (ubyte); - } - - A->len = (n / 8); - - return SECITEM_DupItem(A); - -loser: - return NULL; -} - -SECItem * -PBE_GenerateBits(PBEBitGenContext *pbeCtxt) -{ - return __PBE_GenerateBits(pbeCtxt); -} - -void -__PBE_DestroyContext(PBEBitGenContext *pbeCtxt) -{ - if(pbeCtxt) { - PORT_FreeArena(pbeCtxt->arena, PR_TRUE); - } -} - -void -PBE_DestroyContext(PBEBitGenContext *pbeCtxt) -{ - __PBE_DestroyContext(pbeCtxt); -} - -SECStatus -PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PRArenaPool *arena, - SECAlgorithmID *algId) -{ - CK_PBE_PARAMS *pbe_param; - SECItem pbeSalt; - SECAlgorithmID *pbeAlgID = NULL; - SECStatus rv; - - if(!param || !algId) { - return SECFailure; - } - - pbe_param = (CK_PBE_PARAMS *)param->data; - pbeSalt.data = (unsigned char *)pbe_param->pSalt; - pbeSalt.len = pbe_param->ulSaltLen; - pbeAlgID = SEC_PKCS5CreateAlgorithmID(algTag, &pbeSalt, - (int)pbe_param->ulIteration); - if(!pbeAlgID) { - return SECFailure; - } - - rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID); - SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE); - return rv; -} diff --git a/security/nss/lib/softoken/secpkcs5.h b/security/nss/lib/softoken/secpkcs5.h deleted file mode 100644 index d538450dd..000000000 --- a/security/nss/lib/softoken/secpkcs5.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * 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. - */ - -#ifndef _SECPKCS5_H_ -#define _SECPKCS5_H_ - -#include "plarena.h" -#include "secitem.h" -#include "seccomon.h" -#include "secoidt.h" -#include "hasht.h" - -typedef SECItem * (* SEC_PKCS5GetPBEPassword)(void *arg); - -/* used for V2 PKCS 12 Draft Spec */ -typedef enum { - pbeBitGenIDNull = 0, - pbeBitGenCipherKey = 0x01, - pbeBitGenCipherIV = 0x02, - pbeBitGenIntegrityKey = 0x03 -} PBEBitGenID; - -typedef struct _pbeBitGenParameters { - unsigned int u, v; - SECOidTag hashAlgorithm; -} pbeBitGenParameters; - -typedef struct _PBEBitGenContext { - PRArenaPool *arena; - - /* hash algorithm information */ - pbeBitGenParameters pbeParams; - const SECHashObject *hashObject; - void *hash; - - /* buffers used in generation of bits */ - SECItem D, S, P, I, A, B; - unsigned int c, n; - unsigned int iterations; -} PBEBitGenContext; - -extern const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[]; -typedef struct SEC_PKCS5PBEParameterStr SEC_PKCS5PBEParameter; - -struct SEC_PKCS5PBEParameterStr { - PRArenaPool *poolp; - SECItem salt; /* octet string */ - SECItem iteration; /* integer */ - - /* used locally */ - SECOidTag algorithm; - int iter; -}; - - -SEC_BEGIN_PROTOS -/* Create a PKCS5 Algorithm ID - * The algorithm ID is set up using the PKCS #5 parameter structure - * algorithm is the PBE algorithm ID for the desired algorithm - * salt can be specified or can be NULL, if salt is NULL then the - * salt is generated from random bytes - * iteration is the number of iterations for which to perform the - * hash prior to key and iv generation. - * If an error occurs or the algorithm specified is not supported - * or is not a password based encryption algorithm, NULL is returned. - * Otherwise, a pointer to the algorithm id is returned. - */ -extern SECAlgorithmID * -SEC_PKCS5CreateAlgorithmID(SECOidTag algorithm, - SECItem *salt, - int iteration); - -/* Get the initialization vector. The password is passed in, hashing - * is performed, and the initialization vector is returned. - * algid is a pointer to a PBE algorithm ID - * pwitem is the password - * If an error occurs or the algorithm id is not a PBE algrithm, - * NULL is returned. Otherwise, the iv is returned in a secitem. - */ -extern SECItem * -SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES); - -/* Get the key. The password is passed in, hashing is performed, - * and the key is returned. - * algid is a pointer to a PBE algorithm ID - * pwitem is the password - * If an error occurs or the algorithm id is not a PBE algrithm, - * NULL is returned. Otherwise, the key is returned in a secitem. - */ -extern SECItem * -SEC_PKCS5GetKey(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES); - -/* Get PBE salt. The salt for the password based algorithm is returned. - * algid is the PBE algorithm identifier - * If an error occurs NULL is returned, otherwise the salt is returned - * in a SECItem. - */ -extern SECItem * -SEC_PKCS5GetSalt(SECAlgorithmID *algid); - -/* Encrypt/Decrypt data using password based encryption. - * algid is the PBE algorithm identifier, - * pwitem is the password, - * src is the source for encryption/decryption, - * encrypt is PR_TRUE for encryption, PR_FALSE for decryption. - * The key and iv are generated based upon PKCS #5 then the src - * is either encrypted or decrypted. If an error occurs, NULL - * is returned, otherwise the ciphered contents is returned. - */ -extern SECItem * -SEC_PKCS5CipherData(SECAlgorithmID *algid, SECItem *pwitem, - SECItem *src, PRBool encrypt, PRBool *update); - -/* Checks to see if algid algorithm is a PBE algorithm. If - * so, PR_TRUE is returned, otherwise PR_FALSE is returned. - */ -extern PRBool -SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid); - -/* Destroys PBE parameter */ -extern void -SEC_PKCS5DestroyPBEParameter(SEC_PKCS5PBEParameter *param); - -/* Convert Algorithm ID to PBE parameter */ -extern SEC_PKCS5PBEParameter * -SEC_PKCS5GetPBEParameter(SECAlgorithmID *algid); - -/* Determine how large the key generated is */ -extern int -SEC_PKCS5GetKeyLength(SECAlgorithmID *algid); - -/* map crypto algorithm to pbe algorithm, assume sha 1 hashing for DES - */ -extern SECOidTag -SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen); - -/* return the underlying crypto algorithm */ -extern SECOidTag -SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid); - -extern PBEBitGenContext * -PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, - SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, - unsigned int interations); - -extern SECItem * -PBE_GenerateBits(PBEBitGenContext *pbeCtxt); - -extern void PBE_DestroyContext(PBEBitGenContext *pbeCtxt); - -extern SECStatus PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, - PRArenaPool *arena, SECAlgorithmID *algId); -SEC_END_PROTOS - -#endif diff --git a/security/nss/lib/softoken/softoken.h b/security/nss/lib/softoken/softoken.h index b13a93461..f9fb06222 100644 --- a/security/nss/lib/softoken/softoken.h +++ b/security/nss/lib/softoken/softoken.h @@ -39,8 +39,7 @@ #define _SOFTOKEN_H_ #include "blapi.h" -#include "keytlow.h" -#include "keytboth.h" +#include "lowkeyti.h" #include "softoknt.h" #include "secoidt.h" @@ -83,23 +82,23 @@ extern unsigned char *RSA_FormatOneBlock(unsigned int modulusLen, * RSA_DecryptBlock. */ extern -SECStatus RSA_Sign(SECKEYLowPrivateKey *key, unsigned char *output, +SECStatus RSA_Sign(NSSLOWKEYPrivateKey *key, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen, unsigned char *input, unsigned int inputLen); extern -SECStatus RSA_CheckSign(SECKEYLowPublicKey *key, unsigned char *sign, +SECStatus RSA_CheckSign(NSSLOWKEYPublicKey *key, unsigned char *sign, unsigned int signLength, unsigned char *hash, unsigned int hashLength); extern -SECStatus RSA_CheckSignRecover(SECKEYLowPublicKey *key, unsigned char *data, +SECStatus RSA_CheckSignRecover(NSSLOWKEYPublicKey *key, unsigned char *data, unsigned int *data_len,unsigned int max_output_len, unsigned char *sign, unsigned int sign_len); extern -SECStatus RSA_EncryptBlock(SECKEYLowPublicKey *key, unsigned char *output, +SECStatus RSA_EncryptBlock(NSSLOWKEYPublicKey *key, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen, unsigned char *input, unsigned int inputLen); extern -SECStatus RSA_DecryptBlock(SECKEYLowPrivateKey *key, unsigned char *output, +SECStatus RSA_DecryptBlock(NSSLOWKEYPrivateKey *key, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen, unsigned char *input, unsigned int inputLen); @@ -108,24 +107,24 @@ SECStatus RSA_DecryptBlock(SECKEYLowPrivateKey *key, unsigned char *output, * RAW is RSA_X_509 */ extern -SECStatus RSA_SignRaw( SECKEYLowPrivateKey *key, unsigned char *output, +SECStatus RSA_SignRaw( NSSLOWKEYPrivateKey *key, unsigned char *output, unsigned int *output_len, unsigned int maxOutputLen, unsigned char *input, unsigned int input_len); extern -SECStatus RSA_CheckSignRaw( SECKEYLowPublicKey *key, unsigned char *sign, +SECStatus RSA_CheckSignRaw( NSSLOWKEYPublicKey *key, unsigned char *sign, unsigned int sign_len, unsigned char *hash, unsigned int hash_len); extern -SECStatus RSA_CheckSignRecoverRaw( SECKEYLowPublicKey *key, unsigned char *data, +SECStatus RSA_CheckSignRecoverRaw( NSSLOWKEYPublicKey *key, unsigned char *data, unsigned int *data_len, unsigned int max_output_len, unsigned char *sign, unsigned int sign_len); extern -SECStatus RSA_EncryptRaw( SECKEYLowPublicKey *key, unsigned char *output, +SECStatus RSA_EncryptRaw( NSSLOWKEYPublicKey *key, unsigned char *output, unsigned int *output_len, unsigned int max_output_len, unsigned char *input, unsigned int input_len); extern -SECStatus RSA_DecryptRaw(SECKEYLowPrivateKey *key, unsigned char *output, +SECStatus RSA_DecryptRaw(NSSLOWKEYPrivateKey *key, unsigned char *output, unsigned int *output_len, unsigned int max_output_len, unsigned char *input, unsigned int input_len); diff --git a/security/nss/lib/softoken/softokn.def b/security/nss/lib/softoken/softokn.def new file mode 100644 index 000000000..443583334 --- /dev/null +++ b/security/nss/lib/softoken/softokn.def @@ -0,0 +1,57 @@ +;+# +;+# 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) 2000 Netscape Communications Corporation. All +;+# Rights Reserved. +;+# +;+# Contributor(s): +;+# Dr Stephen Henson <stephen.henson@gemplus.com> +;+# +;+# 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. +;+# +;+# +;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS +;+# 1. For all unix platforms, the string ";-" means "remove this line" +;+# 2. For all unix platforms, the string " DATA " will be removed from any +;+# line on which it occurs. +;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX. +;+# On AIX, lines containing ";+" will be removed. +;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed. +;+# 5. For all unix platforms, after the above processing has taken place, +;+# all characters after the first ";" on the line will be removed. +;+# And for AIX, the first ";" will also be removed. +;+# This file is passed directly to windows. Since ';' is a comment, all UNIX +;+# directives are hidden behind ";", ";+", and ";-" +;+SOFTOKEN_3.4 { # Softoken 3.4 release +;+ global: +LIBRARY softoken ;- +EXPORTS ;- +NSC_GetFunctionList ; +NSC_ModuleDBFunc ; +FC_GetFunctionList ; +C_GetFunctionList ; Make this function like a real PKCS #11 module as well +;+ local: +;+ *; +;+}; diff --git a/security/nss/lib/softoken/softokn.rc b/security/nss/lib/softoken/softokn.rc new file mode 100644 index 000000000..31bdb2272 --- /dev/null +++ b/security/nss/lib/softoken/softokn.rc @@ -0,0 +1,98 @@ +/* + * 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) 2001 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. + */ + +#include "nss.h" +#include <winver.h> + +#define MY_LIBNAME "softoken" +#define MY_FILEDESCRIPTION "NSS Builtin Crypto PKCS #11 Library" + +#define STRINGIZE(x) #x +#define STRINGIZE2(x) STRINGIZE(x) +#define NSS_VMAJOR_STR STRINGIZE2(NSS_VMAJOR) + +#ifdef _DEBUG +#define MY_DEBUG_STR " (debug)" +#define MY_FILEFLAGS_1 VS_FF_DEBUG +#else +#define MY_DEBUG_STR "" +#define MY_FILEFLAGS_1 0x0L +#endif +#if NSS_BETA +#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE +#else +#define MY_FILEFLAGS_2 MY_FILEFLAGS_1 +#endif + +#ifdef WINNT +#define MY_FILEOS VOS_NT_WINDOWS32 +#else +#define MY_FILEOS VOS__WINDOWS32 +#endif + +#define MY_INTERNAL_NAME MY_LIBNAME NSS_VMAJOR_STR + +///////////////////////////////////////////////////////////////////////////// +// +// Version-information resource +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,0 + PRODUCTVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS MY_FILEFLAGS_2 + FILEOS MY_FILEOS + FILETYPE VFT_DLL + FILESUBTYPE 0x0L // not used + +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" // Lang=US English, CharSet=Unicode + BEGIN + VALUE "CompanyName", "Netscape Communications Corporation\0" + VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0" + VALUE "FileVersion", NSS_VERSION "\0" + VALUE "InternalName", MY_INTERNAL_NAME "\0" + VALUE "LegalCopyright", "Copyright \251 1994-2001 Netscape Communications Corporation\0" + VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0" + VALUE "ProductName", "Network Security Services\0" + VALUE "ProductVersion", NSS_VERSION "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/security/nss/lib/util/sysrand.c b/security/nss/lib/softoken/sysrand.c index f79cb9d53..2f647041a 100644 --- a/security/nss/lib/util/sysrand.c +++ b/security/nss/lib/softoken/sysrand.c @@ -41,3 +41,6 @@ #ifdef XP_MAC #include "mac_rand.c" #endif +#ifdef XP_OS2 +#include "os2_rand.c" +#endif diff --git a/security/nss/lib/util/unix_rand.c b/security/nss/lib/softoken/unix_rand.c index 12b08aea3..12b08aea3 100644 --- a/security/nss/lib/util/unix_rand.c +++ b/security/nss/lib/softoken/unix_rand.c diff --git a/security/nss/lib/util/win_rand.c b/security/nss/lib/softoken/win_rand.c index de2e06ea7..de2e06ea7 100644 --- a/security/nss/lib/util/win_rand.c +++ b/security/nss/lib/softoken/win_rand.c diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index ccff7fb81..6889e5afa 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -4272,7 +4272,7 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) peerKey->arena = arena; peerKey->keyType = rsaKey; peerKey->pkcs11Slot = NULL; - peerKey->pkcs11ID = CK_INVALID_KEY; + peerKey->pkcs11ID = CK_INVALID_HANDLE; if (SECITEM_CopyItem(arena, &peerKey->u.rsa.modulus, &modulus) || SECITEM_CopyItem(arena, &peerKey->u.rsa.publicExponent, &exponent)) { @@ -4354,7 +4354,7 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) peerKey->arena = arena; peerKey->keyType = dhKey; peerKey->pkcs11Slot = NULL; - peerKey->pkcs11ID = CK_INVALID_KEY; + peerKey->pkcs11ID = CK_INVALID_HANDLE; if (SECITEM_CopyItem(arena, &peerKey->u.dh.prime, &dh_p) || SECITEM_CopyItem(arena, &peerKey->u.dh.base, &dh_g) || diff --git a/security/nss/lib/util/manifest.mn b/security/nss/lib/util/manifest.mn index 3e89b483e..d0a9c3755 100644 --- a/security/nss/lib/util/manifest.mn +++ b/security/nss/lib/util/manifest.mn @@ -39,6 +39,7 @@ EXPORTS = \ nssb64t.h \ nsslocks.h \ nssilock.h \ + nssilckt.h \ nssrwlk.h \ nssrwlkt.h \ portreg.h \ @@ -84,19 +85,9 @@ CSRCS = \ sectime.c \ secport.c \ secinit.c \ - sysrand.c \ utf8.c \ $(NULL) -ifeq ($(subst /,,$(shell uname -s)),OS2) - CSRCS += os2_rand.c -endif - -# mac_rand.c -# unix_rand.c -# win_rand.c -# prelib.c - REQUIRES = security dbm LIBRARY_NAME = secutil diff --git a/security/nss/lib/util/nssilckt.h b/security/nss/lib/util/nssilckt.h new file mode 100644 index 000000000..34fa60234 --- /dev/null +++ b/security/nss/lib/util/nssilckt.h @@ -0,0 +1,219 @@ +/* + * 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. + */ + +/* +** nssilock.h - Instrumented locking functions for NSS +** +** Description: +** nssilock provides instrumentation for locks and monitors in +** the NSS libraries. The instrumentation, when enabled, causes +** each call to the instrumented function to record data about +** the call to an external file. The external file +** subsequently used to extract performance data and other +** statistical information about the operation of locks used in +** the nss library. +** +** To enable compilation with instrumentation, build NSS with +** the compile time switch NEED_NSS_ILOCK defined. +** +** say: "gmake OS_CFLAGS+=-DNEED_NSS_ILOCK" at make time. +** +** At runtime, to enable recording from nssilock, one or more +** environment variables must be set. For each nssILockType to +** be recorded, an environment variable of the form NSS_ILOCK_x +** must be set to 1. For example: +** +** set NSS_ILOCK_Cert=1 +** +** nssilock uses PRLOG is used to record to trace data. The +** PRLogModule name associated with nssilock data is: "nssilock". +** To enable recording of nssilock data you will need to set the +** environment variable NSPR_LOG_MODULES to enable +** recording for the nssilock log module. Similarly, you will +** need to set the environment variable NSPR_LOG_FILE to specify +** the filename to receive the recorded data. See prlog.h for usage. +** Example: +** +** export NSPR_LOG_MODULES=nssilock:6 +** export NSPR_LOG_FILE=xxxLogfile +** +** Operation: +** nssilock wraps calls to NSPR's PZLock and PZMonitor functions +** with similarly named functions: PZ_NewLock(), etc. When NSS is +** built with lock instrumentation enabled, the PZ* functions are +** compiled into NSS; when lock instrumentation is disabled, +** calls to PZ* functions are directly mapped to PR* functions +** and the instrumentation arguments to the PZ* functions are +** compiled away. +** +** +** File Format: +** The format of the external file is implementation +** dependent. Where NSPR's PR_LOG() function is used, the file +** contains data defined for PR_LOG() plus the data written by +** the wrapped function. On some platforms and under some +** circumstances, platform dependent logging or +** instrumentation probes may be used. In any case, the +** relevant data provided by the lock instrumentation is: +** +** lockType, func, address, duration, line, file [heldTime] +** +** where: +** +** lockType: a character representation of nssILockType for the +** call. e.g. ... "cert" +** +** func: the function doing the tracing. e.g. "NewLock" +** +** address: address of the instrumented lock or monitor +** +** duration: is how long was spent in the instrumented function, +** in PRIntervalTime "ticks". +** +** line: the line number within the calling function +** +** file: the file from which the call was made +** +** heldTime: how long the lock/monitor was held. field +** present only for PZ_Unlock() and PZ_ExitMonitor(). +** +** Design Notes: +** The design for lock instrumentation was influenced by the +** need to gather performance data on NSS 3.x. It is intended +** that the effort to modify NSS to use lock instrumentation +** be minimized. Existing calls to locking functions need only +** have their names changed to the instrumentation function +** names. +** +** Private NSS Interface: +** nssilock.h defines a private interface for use by NSS. +** nssilock.h is experimental in nature and is subject to +** change or revocation without notice. ... Don't mess with +** it. +** +*/ + +/* + * $Id: + */ + +#ifndef _NSSILCKT_H_ +#define _NSSILCKT_H_ + +#include "prtypes.h" +#include "prmon.h" +#include "prlock.h" +#include "prcvar.h" + +typedef enum { + nssILockArena = 0, + nssILockSession = 1, + nssILockObject = 2, + nssILockRefLock = 3, + nssILockCert = 4, + nssILockCertDB = 5, + nssILockDBM = 6, + nssILockCache = 7, + nssILockSSL = 8, + nssILockList = 9, + nssILockSlot = 10, + nssILockFreelist = 11, + nssILockOID = 12, + nssILockAttribute = 13, + nssILockPK11cxt = 14, /* pk11context */ + nssILockRWLock = 15, + nssILockOther = 16, + nssILockSelfServ = 17, + nssILockLast /* don't use this one! */ +} nssILockType; + +/* +** Declare operation type enumerator +** enumerations identify the function being performed +*/ +typedef enum { + FlushTT = 0, + NewLock = 1, + Lock = 2, + Unlock = 3, + DestroyLock = 4, + NewCondVar = 5, + WaitCondVar = 6, + NotifyCondVar = 7, + NotifyAllCondVar = 8, + DestroyCondVar = 9, + NewMonitor = 10, + EnterMonitor = 11, + ExitMonitor = 12, + Notify = 13, + NotifyAll = 14, + Wait = 15, + DestroyMonitor = 16 +} nssILockOp; + +/* +** Declare the trace record +*/ +struct pzTrace_s { + PRUint32 threadID; /* PR_GetThreadID() */ + nssILockOp op; /* operation being performed */ + nssILockType ltype; /* lock type identifier */ + PRIntervalTime callTime; /* time spent in function */ + PRIntervalTime heldTime; /* lock held time, or -1 */ + void *lock; /* address of lock structure */ + PRIntn line; /* line number */ + char file[24]; /* filename */ +}; + +/* +** conditionally compile in nssilock features +*/ +#if defined(NEED_NSS_ILOCK) + +/* +** declare opaque types. See: nssilock.c +*/ +typedef struct pzlock_s PZLock; +typedef struct pzcondvar_s PZCondVar; +typedef struct pzmonitor_s PZMonitor; + +#else /* NEED_NSS_ILOCK */ + +#define PZLock PRLock +#define PZCondVar PRCondVar +#define PZMonitor PRMonitor + +#endif /* NEED_NSS_ILOCK */ + +PR_END_EXTERN_C +#endif /* _NSSILCKT_H_ */ diff --git a/security/nss/lib/util/nssilock.h b/security/nss/lib/util/nssilock.h index 0ba90193a..38b457387 100644 --- a/security/nss/lib/util/nssilock.h +++ b/security/nss/lib/util/nssilock.h @@ -135,80 +135,12 @@ #include "prlock.h" #include "prcvar.h" -PR_BEGIN_EXTERN_C - -typedef enum { - nssILockArena = 0, - nssILockSession = 1, - nssILockObject = 2, - nssILockRefLock = 3, - nssILockCert = 4, - nssILockCertDB = 5, - nssILockDBM = 6, - nssILockCache = 7, - nssILockSSL = 8, - nssILockList = 9, - nssILockSlot = 10, - nssILockFreelist = 11, - nssILockOID = 12, - nssILockAttribute = 13, - nssILockPK11cxt = 14, /* pk11context */ - nssILockRWLock = 15, - nssILockOther = 16, - nssILockSelfServ = 17, - nssILockLast /* don't use this one! */ -} nssILockType; +#include "nssilckt.h" -/* -** Declare operation type enumerator -** enumerations identify the function being performed -*/ -typedef enum { - FlushTT = 0, - NewLock = 1, - Lock = 2, - Unlock = 3, - DestroyLock = 4, - NewCondVar = 5, - WaitCondVar = 6, - NotifyCondVar = 7, - NotifyAllCondVar = 8, - DestroyCondVar = 9, - NewMonitor = 10, - EnterMonitor = 11, - ExitMonitor = 12, - Notify = 13, - NotifyAll = 14, - Wait = 15, - DestroyMonitor = 16 -} nssILockOp; - -/* -** Declare the trace record -*/ -struct pzTrace_s { - PRUint32 threadID; /* PR_GetThreadID() */ - nssILockOp op; /* operation being performed */ - nssILockType ltype; /* lock type identifier */ - PRIntervalTime callTime; /* time spent in function */ - PRIntervalTime heldTime; /* lock held time, or -1 */ - void *lock; /* address of lock structure */ - PRIntn line; /* line number */ - char file[24]; /* filename */ -}; +PR_BEGIN_EXTERN_C -/* -** conditionally compile in nssilock features -*/ #if defined(NEED_NSS_ILOCK) -/* -** declare opaque types. See: nssilock.c -*/ -typedef struct pzlock_s PZLock; -typedef struct pzcondvar_s PZCondVar; -typedef struct pzmonitor_s PZMonitor; - #define PZ_NewLock(t) pz_NewLock((t),__FILE__,__LINE__) extern PZLock * pz_NewLock( @@ -356,21 +288,17 @@ extern void pz_TraceFlush( void ); #else /* NEED_NSS_ILOCK */ -#define PZLock PRLock - #define PZ_NewLock(t) PR_NewLock() #define PZ_DestroyLock(k) PR_DestroyLock((k)) #define PZ_Lock(k) PR_Lock((k)) #define PZ_Unlock(k) PR_Unlock((k)) -#define PZCondVar PRCondVar #define PZ_NewCondVar(l) PR_NewCondVar((l)) #define PZ_DestroyCondVar(v) PR_DestroyCondVar((v)) #define PZ_WaitCondVar(v,t) PR_WaitCondVar((v),(t)) #define PZ_NotifyCondVar(v) PR_NotifyCondVar((v)) #define PZ_NotifyAllCondVar(v) PR_NotifyAllCondVar((v)) -#define PZMonitor PRMonitor #define PZ_NewMonitor(t) PR_NewMonitor() #define PZ_DestroyMonitor(m) PR_DestroyMonitor((m)) #define PZ_EnterMonitor(m) PR_EnterMonitor((m)) diff --git a/security/nss/lib/util/secoid.c b/security/nss/lib/util/secoid.c index fbe35bae9..c38564861 100644 --- a/security/nss/lib/util/secoid.c +++ b/security/nss/lib/util/secoid.c @@ -385,18 +385,24 @@ CONST_OID dhPublicKey[] = { ANSI_X942_ALGORITHM, 0x1 }; CONST_OID aes128_ECB[] = { AES, 1 }; CONST_OID aes128_CBC[] = { AES, 2 }; +#ifdef DEFINE_ALL_AES_CIPHERS CONST_OID aes128_OFB[] = { AES, 3 }; CONST_OID aes128_CFB[] = { AES, 4 }; +#endif CONST_OID aes192_ECB[] = { AES, 21 }; CONST_OID aes192_CBC[] = { AES, 22 }; +#ifdef DEFINE_ALL_AES_CIPHERS CONST_OID aes192_OFB[] = { AES, 23 }; CONST_OID aes192_CFB[] = { AES, 24 }; +#endif CONST_OID aes256_ECB[] = { AES, 41 }; CONST_OID aes256_CBC[] = { AES, 42 }; +#ifdef DEFINE_ALL_AES_CIPHERS CONST_OID aes256_OFB[] = { AES, 43 }; CONST_OID aes256_CFB[] = { AES, 44 }; +#endif #define OI(x) { siDEROID, (unsigned char *)x, sizeof x } #ifndef SECOID_NO_STRINGS |