diff options
author | mkaply%us.ibm.com <devnull@localhost> | 2004-02-10 20:19:15 +0000 |
---|---|---|
committer | mkaply%us.ibm.com <devnull@localhost> | 2004-02-10 20:19:15 +0000 |
commit | ded9650079adb3f060e6af226caec428e840b070 (patch) | |
tree | 4d1d60c60437c6c60ae7a867b05d392e009ec7df | |
parent | c3c3fe2a2fe2c6f5688d26a59b23543484a638e7 (diff) | |
download | nss-hg-ded9650079adb3f060e6af226caec428e840b070.tar.gz |
a=mkaply - NSS 3.9 on the 1.6 branch
66 files changed, 1372 insertions, 641 deletions
diff --git a/security/coreconf/WIN32.mk b/security/coreconf/WIN32.mk index 42347d850..d275300b2 100644 --- a/security/coreconf/WIN32.mk +++ b/security/coreconf/WIN32.mk @@ -136,7 +136,8 @@ else # !NS_USE_GCC USERNAME := $(subst -,_,$(USERNAME)) DEFINES += -DDEBUG -D_DEBUG -UNDEBUG -DDEBUG_$(USERNAME) DLLFLAGS += -DEBUG -DEBUGTYPE:CV -OUT:"$@" - LDFLAGS += -DEBUG -DEBUGTYPE:CV -PDB:NONE + # Purify requires /FIXED:NO when linking EXEs. + LDFLAGS += -DEBUG -DEBUGTYPE:CV -PDB:NONE /FIXED:NO endif endif # NS_USE_GCC diff --git a/security/nss/cmd/dbck/dbck.c b/security/nss/cmd/dbck/dbck.c index a5fa1e6fd..cba8e0287 100644 --- a/security/nss/cmd/dbck/dbck.c +++ b/security/nss/cmd/dbck/dbck.c @@ -265,8 +265,8 @@ dumpCertificate(CERTCertificate *cert, int num, PRFileDesc *outfile) int64 timeBefore, timeAfter; PRExplodedTime beforePrintable, afterPrintable; char *beforestr, *afterstr; - CERT_DecodeTimeChoice(&timeBefore, &cert->validity.notBefore); - CERT_DecodeTimeChoice(&timeAfter, &cert->validity.notAfter); + DER_DecodeTimeChoice(&timeBefore, &cert->validity.notBefore); + DER_DecodeTimeChoice(&timeAfter, &cert->validity.notAfter); PR_ExplodeTime(timeBefore, PR_GMTParameters, &beforePrintable); PR_ExplodeTime(timeAfter, PR_GMTParameters, &afterPrintable); beforestr = PORT_Alloc(100); diff --git a/security/nss/cmd/lib/secutil.c b/security/nss/cmd/lib/secutil.c index b01b6dada..f27c1d067 100644 --- a/security/nss/cmd/lib/secutil.c +++ b/security/nss/cmd/lib/secutil.c @@ -712,8 +712,6 @@ SECU_PrintAsHex(FILE *out, SECItem *data, const char *m, int level) if (!isString) for (i = 0; i < data->len; i++) { - unsigned char val = data->data[i]; - if (i != data->len - 1) { fprintf(out, "%02x:", data->data[i]); column += 3; diff --git a/security/nss/cmd/signver/pk7print.c b/security/nss/cmd/signver/pk7print.c index 2b19df1d1..71851fb17 100644 --- a/security/nss/cmd/signver/pk7print.c +++ b/security/nss/cmd/signver/pk7print.c @@ -110,7 +110,7 @@ sv_PrintTime(FILE *out, SECItem *t, char *m) char *timeString; int rv; - rv = CERT_DecodeTimeChoice(&time, t); + rv = DER_DecodeTimeChoice(&time, t); if (rv) return rv; /* Convert to local time */ diff --git a/security/nss/cmd/smimetools/cmsutil.c b/security/nss/cmd/smimetools/cmsutil.c index 6b7a06b21..ddaef6c83 100644 --- a/security/nss/cmd/smimetools/cmsutil.c +++ b/security/nss/cmd/smimetools/cmsutil.c @@ -87,6 +87,7 @@ DigestFile(PLArenaPool *poolp, SECItem ***digests, SECItem *input, SECAlgorithmID **algids) { NSSCMSDigestContext *digcx; + SECStatus rv; digcx = NSS_CMSDigestContext_StartMultiple(algids); if (digcx == NULL) @@ -94,7 +95,8 @@ DigestFile(PLArenaPool *poolp, SECItem ***digests, SECItem *input, NSS_CMSDigestContext_Update(digcx, input->data, input->len); - return NSS_CMSDigestContext_FinishMultiple(digcx, poolp, digests); + rv = NSS_CMSDigestContext_FinishMultiple(digcx, poolp, digests); + return rv; } @@ -105,9 +107,11 @@ Usage(char *progName) "Usage: %s [-C|-D|-E|-O|-S] [<options>] [-d dbdir] [-u certusage]\n" " -C create a CMS encrypted data message\n" " -D decode a CMS message\n" +" -b decode a batch of files named in infile\n" " -c content use this detached content\n" " -n suppress output of content\n" " -h num display num levels of CMS message info as email headers\n" +" -k keep decoded encryption certs in perm cert db\n" " -E create a CMS enveloped data message\n" " -r id,... create envelope for these recipients,\n" " where id can be a certificate nickname or email address\n" @@ -155,11 +159,12 @@ struct optionsStr { struct decodeOptionsStr { struct optionsStr *options; - PRFileDesc *contentFile; + SECItem content; int headerLevel; PRBool suppressContent; NSSCMSGetDecryptKeyCallback dkcb; PK11SymKey *bulkkey; + PRBool keepCerts; }; struct signOptionsStr { @@ -195,22 +200,14 @@ struct encryptOptionsStr { }; static NSSCMSMessage * -decode(FILE *out, SECItem *output, SECItem *input, - const struct decodeOptionsStr *decodeOptions) +decode(FILE *out, SECItem *input, const struct decodeOptionsStr *decodeOptions) { NSSCMSDecoderContext *dcx; NSSCMSMessage *cmsg; - NSSCMSContentInfo *cinfo; - NSSCMSSignedData *sigd = NULL; - NSSCMSEnvelopedData *envd; - NSSCMSEncryptedData *encd; - int nlevels, i, nsigners, j; - char *signercn; - NSSCMSSignerInfo *si; - SECOidTag typetag; - SECItem **digests; + int nlevels, i; SECItem sitem = { 0, 0, 0 }; + PORT_SetError(0); dcx = NSS_CMSDecoder_Start(NULL, NULL, NULL, /* content callback */ pwcb, pwcb_arg, /* password callback */ @@ -230,6 +227,9 @@ decode(FILE *out, SECItem *output, SECItem *input, nlevels = NSS_CMSMessage_ContentLevelCount(cmsg); for (i = 0; i < nlevels; i++) { + NSSCMSContentInfo *cinfo; + SECOidTag typetag; + cinfo = NSS_CMSMessage_ContentLevel(cmsg, i); typetag = NSS_CMSContentInfo_GetContentTypeTag(cinfo); @@ -238,25 +238,28 @@ decode(FILE *out, SECItem *output, SECItem *input, switch (typetag) { case SEC_OID_PKCS7_SIGNED_DATA: + { + NSSCMSSignedData *sigd = NULL; + SECItem **digests; + int nsigners; + int j; + if (decodeOptions->headerLevel >= 0) fprintf(out, "type=signedData; "); sigd = (NSSCMSSignedData *)NSS_CMSContentInfo_GetContent(cinfo); if (sigd == NULL) { - SECU_PrintError(progName, - "problem finding signedData component"); + SECU_PrintError(progName, "signedData component missing"); goto loser; } /* if we have a content file, but no digests for this signedData */ - if (decodeOptions->contentFile != NULL && + if (decodeOptions->content.data != NULL && !NSS_CMSSignedData_HasDigests(sigd)) { PLArenaPool *poolp; SECAlgorithmID **digestalgs; /* detached content: grab content file */ - if (!sitem.data) { - SECU_FileToItem(&sitem, decodeOptions->contentFile); - } + sitem = decodeOptions->content; if ((poolp = PORT_NewArena(1024)) == NULL) { fprintf(stderr, "cmsutil: Out of memory.\n"); @@ -267,13 +270,14 @@ decode(FILE *out, SECItem *output, SECItem *input, != SECSuccess) { SECU_PrintError(progName, "problem computing message digest"); + PORT_FreeArena(poolp, PR_FALSE); goto loser; } if (NSS_CMSSignedData_SetDigests(sigd, digestalgs, digests) != SECSuccess) { - SECU_PrintError(progName, "problem setting message digests"); + PORT_FreeArena(poolp, PR_FALSE); goto loser; } PORT_FreeArena(poolp, PR_FALSE); @@ -283,7 +287,7 @@ decode(FILE *out, SECItem *output, SECItem *input, if (NSS_CMSSignedData_ImportCerts(sigd, decodeOptions->options->certHandle, decodeOptions->options->certUsage, - PR_FALSE) + decodeOptions->keepCerts) != SECSuccess) { SECU_PrintError(progName, "cert import failed"); goto loser; @@ -294,13 +298,11 @@ decode(FILE *out, SECItem *output, SECItem *input, if (decodeOptions->headerLevel >= 0) fprintf(out, "nsigners=%d; ", nsigners); if (nsigners == 0) { - /* must be a cert transport message */ + /* Might be a cert transport message + ** or might be an invalid message, such as a QA test message + ** or a message from an attacker. + */ SECStatus rv; - /* XXX workaround for bug #54014 */ - NSS_CMSSignedData_ImportCerts(sigd, - decodeOptions->options->certHandle, - decodeOptions->options->certUsage, - PR_TRUE); rv = NSS_CMSSignedData_VerifyCertsOnly(sigd, decodeOptions->options->certHandle, decodeOptions->options->certUsage); @@ -318,16 +320,23 @@ decode(FILE *out, SECItem *output, SECItem *input, } for (j = 0; j < nsigners; j++) { - SECStatus bad; - NSSCMSVerificationStatus vs; const char * svs; + NSSCMSSignerInfo *si; + NSSCMSVerificationStatus vs; + SECStatus bad; si = NSS_CMSSignedData_GetSignerInfo(sigd, j); - signercn = NSS_CMSSignerInfo_GetSignerCommonName(si); - if (signercn == NULL) - signercn = ""; - if (decodeOptions->headerLevel >= 0) + if (decodeOptions->headerLevel >= 0) { + char *signercn; + static char empty[] = { "" }; + + signercn = NSS_CMSSignerInfo_GetSignerCommonName(si); + if (signercn == NULL) + signercn = empty; fprintf(out, "\n\t\tsigner%d.id=\"%s\"; ", j, signercn); + if (signercn != empty) + PORT_Free(signercn); + } bad = NSS_CMSSignedData_VerifySignerInfo(sigd, j, decodeOptions->options->certHandle, decodeOptions->options->certUsage); @@ -341,17 +350,32 @@ decode(FILE *out, SECItem *output, SECItem *input, goto loser; } } - break; + } + break; case SEC_OID_PKCS7_ENVELOPED_DATA: + { + NSSCMSEnvelopedData *envd; if (decodeOptions->headerLevel >= 0) fprintf(out, "type=envelopedData; "); envd = (NSSCMSEnvelopedData *)NSS_CMSContentInfo_GetContent(cinfo); - break; + if (envd == NULL) { + SECU_PrintError(progName, "envelopedData component missing"); + goto loser; + } + } + break; case SEC_OID_PKCS7_ENCRYPTED_DATA: + { + NSSCMSEncryptedData *encd; if (decodeOptions->headerLevel >= 0) fprintf(out, "type=encryptedData; "); encd = (NSSCMSEncryptedData *)NSS_CMSContentInfo_GetContent(cinfo); - break; + if (encd == NULL) { + SECU_PrintError(progName, "encryptedData component missing"); + goto loser; + } + } + break; case SEC_OID_PKCS7_DATA: if (decodeOptions->headerLevel >= 0) fprintf(out, "type=data; "); @@ -363,11 +387,12 @@ decode(FILE *out, SECItem *output, SECItem *input, fprintf(out, "\n"); } - if (!decodeOptions->suppressContent) { - SECItem *item = (sitem.data) - ? &sitem - : NSS_CMSMessage_GetContent(cmsg); - SECITEM_CopyItem(NULL, output, item); + if (!decodeOptions->suppressContent && out) { + SECItem *item = (sitem.data ? &sitem + : NSS_CMSMessage_GetContent(cmsg)); + if (item && item->data && item->len) { + fwrite(item->data, item->len, 1, out); + } } return cmsg; @@ -953,8 +978,87 @@ loser: return NULL; } +static char * +pl_fgets(char * buf, int size, PRFileDesc * fd) +{ + char * bp = buf; + int nb = 0;; + + while (size > 1) { + nb = PR_Read(fd, bp, 1); + if (nb < 0) { + /* deal with error */ + return NULL; + } else if (nb == 0) { + /* deal with EOF */ + return NULL; + } else if (*bp == '\n') { + /* deal with EOL */ + ++bp; /* keep EOL character */ + break; + } else { + /* ordinary character */ + ++bp; + --size; + } + } + *bp = '\0'; + return buf; +} + typedef enum { UNKNOWN, DECODE, SIGN, ENCRYPT, ENVELOPE, CERTSONLY } Mode; +static int +doBatchDecode(FILE *outFile, PRFileDesc *batchFile, + const struct decodeOptionsStr *decodeOptions) +{ + char * str; + int exitStatus = 0; + char batchLine[512]; + + while (NULL != (str = pl_fgets(batchLine, sizeof batchLine, batchFile))) { + NSSCMSMessage *cmsg = NULL; + PRFileDesc * inFile; + int len = strlen(str); + SECStatus rv; + SECItem input = {0, 0, 0}; + char cc; + + while (len > 0 && + ((cc = str[len - 1]) == '\n' || cc == '\r')) { + str[--len] = '\0'; + } + if (!len) /* skip empty line */ + continue; + if (str[0] == '#') + continue; /* skip comment line */ + fprintf(outFile, "========== %s ==========\n", str); + inFile = PR_Open(str, PR_RDONLY, 00660); + if (inFile == NULL) { + fprintf(outFile, "%s: unable to open \"%s\" for reading\n", + progName, str); + exitStatus = 1; + continue; + } + rv = SECU_FileToItem(&input, inFile); + PR_Close(inFile); + if (rv != SECSuccess) { + SECU_PrintError(progName, "unable to read infile"); + exitStatus = 1; + continue; + } + cmsg = decode(outFile, &input, decodeOptions); + SECITEM_FreeItem(&input, PR_FALSE); + if (cmsg) + NSS_CMSMessage_Destroy(cmsg); + else { + SECU_PrintError(progName, "problem decoding"); + exitStatus = 1; + } + } + return exitStatus; +} + int main(int argc, char **argv) { @@ -976,10 +1080,17 @@ main(int argc, char **argv) char *str, *tok; char *envFileName; SECItem input = { 0, 0, 0}; - SECItem output = { 0, 0, 0}; - SECItem dummy = { 0, 0, 0 }; SECItem envmsg = { 0, 0, 0 }; SECStatus rv; + PRFileDesc *contentFile = NULL; + PRBool batch = PR_FALSE; + +#ifdef NISCC_TESTING + const char *ev = PR_GetEnv("NSS_DISABLE_ARENA_FREE_LIST"); + PORT_Assert(ev); + ev = PR_GetEnv("NSS_STRICT_SHUTDOWN"); + PORT_Assert(ev); +#endif progName = strrchr(argv[0], '/'); if (!progName) @@ -990,9 +1101,11 @@ main(int argc, char **argv) outFile = stdout; envFileName = NULL; mode = UNKNOWN; - decodeOptions.contentFile = NULL; + decodeOptions.content.data = NULL; + decodeOptions.content.len = 0; decodeOptions.suppressContent = PR_FALSE; decodeOptions.headerLevel = -1; + decodeOptions.keepCerts = PR_FALSE; options.certUsage = certUsageEmailSigner; options.password = NULL; signOptions.nickname = NULL; @@ -1013,7 +1126,7 @@ main(int argc, char **argv) * Parse command line arguments */ optstate = PL_CreateOptState(argc, argv, - "CDEGH:N:OPSTY:c:d:e:h:i:no:p:r:s:u:v"); + "CDEGH:N:OPSTY:bc:d:e:h:i:kno:p:r:s:u:v"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case 'C': @@ -1112,6 +1225,17 @@ main(int argc, char **argv) signOptions.encryptionKeyPreferenceNick = strdup(optstate->value); break; + case 'b': + if (mode != DECODE) { + fprintf(stderr, + "%s: option -b only supported with option -D.\n", + progName); + Usage(progName); + exit(1); + } + batch = PR_TRUE; + break; + case 'c': if (mode != DECODE) { fprintf(stderr, @@ -1120,12 +1244,25 @@ main(int argc, char **argv) Usage(progName); exit(1); } - if ((decodeOptions.contentFile = - PR_Open(optstate->value, PR_RDONLY, 006600)) == NULL) { + contentFile = PR_Open(optstate->value, PR_RDONLY, 006600); + if (contentFile == NULL) { fprintf(stderr, "%s: unable to open \"%s\" for reading.\n", progName, optstate->value); exit(1); } + + rv = SECU_FileToItem(&decodeOptions.content, contentFile); + PR_Close(contentFile); + if (rv != SECSuccess) { + SECU_PrintError(progName, "problem reading content file"); + exit(1); + } + if (!decodeOptions.content.data) { + /* file was zero length */ + decodeOptions.content.data = (unsigned char *)PORT_Strdup(""); + decodeOptions.content.len = 0; + } + break; case 'd': SECU_ConfigDirectory(optstate->value); @@ -1158,6 +1295,17 @@ main(int argc, char **argv) } break; + case 'k': + if (mode != DECODE) { + fprintf(stderr, + "%s: option -k only supported with option -D.\n", + progName); + Usage(progName); + exit(1); + } + decodeOptions.keepCerts = PR_TRUE; + break; + case 'n': if (mode != DECODE) { fprintf(stderr, @@ -1227,10 +1375,16 @@ main(int argc, char **argv) if (mode == UNKNOWN) Usage(progName); - if (mode != CERTSONLY) - SECU_FileToItem(&input, inFile); - if (inFile != PR_STDIN) - PR_Close(inFile); + if (mode != CERTSONLY && !batch) { + rv = SECU_FileToItem(&input, inFile); + if (rv != SECSuccess) { + SECU_PrintError(progName, "unable to read infile"); + exit(1); + } + if (inFile != PR_STDIN) { + PR_Close(inFile); + } + } if (cms_verbose) { fprintf(stderr, "received commands\n"); } @@ -1289,8 +1443,7 @@ main(int argc, char **argv) */ SECU_FileToItem(&envmsg, encryptOptions.envFile); decodeOptions.options = &options; - encryptOptions.envmsg = decode(NULL, &dummy, &envmsg, - &decodeOptions); + encryptOptions.envmsg = decode(NULL, &envmsg, &decodeOptions); if (!encryptOptions.envmsg) { SECU_PrintError(progName, "problem decoding env msg"); exitstatus = 1; @@ -1300,12 +1453,18 @@ main(int argc, char **argv) decodeOptions.dkcb = dkcb; decodeOptions.bulkkey = encryptOptions.bulkkey; } - cmsg = decode(outFile, &output, &input, &decodeOptions); - if (!cmsg) { - SECU_PrintError(progName, "problem decoding"); - exitstatus = 1; + if (!batch) { + cmsg = decode(outFile, &input, &decodeOptions); + if (!cmsg) { + SECU_PrintError(progName, "problem decoding"); + exitstatus = 1; + } + } else { + exitstatus = doBatchDecode(outFile, inFile, &decodeOptions); + if (inFile != PR_STDIN) { + PR_Close(inFile); + } } - fwrite(output.data, output.len, 1, outFile); break; case SIGN: /* -S */ signOptions.options = &options; @@ -1338,8 +1497,7 @@ main(int argc, char **argv) } else { SECU_FileToItem(&envmsg, encryptOptions.envFile); decodeOptions.options = &options; - encryptOptions.envmsg = decode(NULL, &dummy, &envmsg, - &decodeOptions); + encryptOptions.envmsg = decode(NULL, &envmsg, &decodeOptions); if (encryptOptions.envmsg == NULL) { SECU_PrintError(progName, "problem decrypting env msg"); exitstatus = 1; @@ -1433,7 +1591,6 @@ main(int argc, char **argv) if (cms_verbose) { fprintf(stderr, "encoding passed\n"); } - /*PR_Write(output.data, output.len);*/ fwrite(output.data, output.len, 1, outFile); if (cms_verbose) { fprintf(stderr, "wrote to file\n"); @@ -1445,10 +1602,13 @@ main(int argc, char **argv) if (outFile != stdout) fclose(outFile); - if (decodeOptions.contentFile) - PR_Close(decodeOptions.contentFile); + SECITEM_FreeItem(&decodeOptions.content, PR_FALSE); + SECITEM_FreeItem(&envmsg, PR_FALSE); + SECITEM_FreeItem(&input, PR_FALSE); if (NSS_Shutdown() != SECSuccess) { - exit(1); + SECU_PrintError(progName, "NSS_Shutdown failed"); + exitstatus = 1; } - exit(exitstatus); + PR_Cleanup(); + return exitstatus; } diff --git a/security/nss/cmd/symkeyutil/symkeyutil.c b/security/nss/cmd/symkeyutil/symkeyutil.c index 5c355e33b..f1f3d1c41 100644 --- a/security/nss/cmd/symkeyutil/symkeyutil.c +++ b/security/nss/cmd/symkeyutil/symkeyutil.c @@ -1093,7 +1093,7 @@ main(int argc, char **argv) goto shutdown; } rv = SECFailure; - newKey = PK11_MoveKey(target, CKA_ENCRYPT, 0, PR_TRUE, symKey); + newKey = PK11_MoveSymKey(target, CKA_ENCRYPT, 0, PR_TRUE, symKey); if (!newKey) { PR_fprintf(PR_STDERR, "%s: Couldn't move the key \n",progName); goto shutdown; diff --git a/security/nss/lib/base/error.c b/security/nss/lib/base/error.c index 3e736b2b0..ce5825159 100644 --- a/security/nss/lib/base/error.c +++ b/security/nss/lib/base/error.c @@ -45,6 +45,9 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #ifndef BASE_H #include "base.h" #endif /* BASE_H */ +#include <string.h> /* for memmove */ + +#define NSS_MAX_ERROR_STACK_COUNT 16 /* error codes */ /* * The stack itself has a header, and a sequence of integers. @@ -87,12 +90,8 @@ static PRCallOnceType error_call_once; * * This is the once-called callback. */ - static PRStatus -error_once_function -( - void -) +error_once_function ( void) { return nss_NewThreadPrivateIndex(&error_stack_index,PR_Free); /* return PR_NewThreadPrivateIndex(&error_stack_index, PR_Free); */ @@ -107,10 +106,7 @@ error_once_function */ static error_stack * -error_get_my_stack -( - void -) +error_get_my_stack ( void) { PRStatus st; error_stack *rv; @@ -129,18 +125,16 @@ error_get_my_stack if( (error_stack *)NULL == rv ) { /* Doesn't exist; create one */ new_size = 16; + } else if( rv->header.count == rv->header.space && + rv->header.count < NSS_MAX_ERROR_STACK_COUNT ) { + /* Too small, expand it */ + new_size = PR_MIN( rv->header.space * 2, NSS_MAX_ERROR_STACK_COUNT); } else { - if( rv->header.count == rv->header.space ) { - /* Too small, expand it */ - new_size = rv->header.space + 16; - } else { - /* Okay, return it */ - return rv; - } + /* Okay, return it */ + return rv; } - new_bytes = (new_size * sizeof(PRInt32)) + - sizeof(struct stack_header_str); + new_bytes = (new_size * sizeof(PRInt32)) + sizeof(error_stack); /* Use NSPR's calloc/realloc, not NSS's, to avoid loops! */ new_stack = PR_Calloc(1, new_bytes); @@ -187,10 +181,7 @@ error_get_my_stack */ NSS_IMPLEMENT PRInt32 -NSS_GetError -( - void -) +NSS_GetError ( void) { error_stack *es = error_get_my_stack(); @@ -224,10 +215,7 @@ NSS_GetError */ NSS_IMPLEMENT PRInt32 * -NSS_GetErrorStack -( - void -) +NSS_GetErrorStack ( void) { error_stack *es = error_get_my_stack(); @@ -250,10 +238,7 @@ NSS_GetErrorStack */ NSS_IMPLEMENT void -nss_SetError -( - PRUint32 error -) +nss_SetError ( PRUint32 error) { error_stack *es; @@ -268,8 +253,13 @@ nss_SetError return; } - es->stack[ es->header.count ] = error; - es->header.count++; + if (es->header.count < es->header.space) { + es->stack[ es->header.count++ ] = error; + } else { + memmove(es->stack, es->stack + 1, + (es->header.space - 1) * (sizeof es->stack[0])); + es->stack[ es->header.space - 1 ] = error; + } return; } @@ -280,10 +270,7 @@ nss_SetError */ NSS_IMPLEMENT void -nss_ClearErrorStack -( - void -) +nss_ClearErrorStack ( void) { error_stack *es = error_get_my_stack(); if( (error_stack *)NULL == es ) { diff --git a/security/nss/lib/certdb/alg1485.c b/security/nss/lib/certdb/alg1485.c index f1a450f47..916f09cbe 100644 --- a/security/nss/lib/certdb/alg1485.c +++ b/security/nss/lib/certdb/alg1485.c @@ -1102,6 +1102,7 @@ CERT_GetCertEmailAddress(CERTName *name) return(emailAddr); } +/* The return value must be freed with PORT_Free. */ char * CERT_GetCommonName(CERTName *name) { diff --git a/security/nss/lib/certdb/cert.h b/security/nss/lib/certdb/cert.h index 34f0339cb..a154cba78 100644 --- a/security/nss/lib/certdb/cert.h +++ b/security/nss/lib/certdb/cert.h @@ -733,6 +733,7 @@ extern const char * CERT_GetFirstEmailAddress(CERTCertificate * cert); extern const char * CERT_GetNextEmailAddress(CERTCertificate * cert, const char * prev); +/* The return value must be freed with PORT_Free. */ extern char *CERT_GetCommonName(CERTName *name); extern char *CERT_GetCountryName(CERTName *name); diff --git a/security/nss/lib/certdb/certdb.c b/security/nss/lib/certdb/certdb.c index 5c1adc99d..5cd21baab 100644 --- a/security/nss/lib/certdb/certdb.c +++ b/security/nss/lib/certdb/certdb.c @@ -963,13 +963,13 @@ CERT_GetCertTimes(CERTCertificate *c, PRTime *notBefore, PRTime *notAfter) } /* convert DER not-before time */ - rv = CERT_DecodeTimeChoice(notBefore, &c->validity.notBefore); + rv = DER_DecodeTimeChoice(notBefore, &c->validity.notBefore); if (rv) { return(SECFailure); } /* convert DER not-after time */ - rv = CERT_DecodeTimeChoice(notAfter, &c->validity.notAfter); + rv = DER_DecodeTimeChoice(notAfter, &c->validity.notAfter); if (rv) { return(SECFailure); } @@ -1020,14 +1020,14 @@ SEC_GetCrlTimes(CERTCrl *date, PRTime *notBefore, PRTime *notAfter) int rv; /* convert DER not-before time */ - rv = CERT_DecodeTimeChoice(notBefore, &date->lastUpdate); + rv = DER_DecodeTimeChoice(notBefore, &date->lastUpdate); if (rv) { return(SECFailure); } /* convert DER not-after time */ if (date->nextUpdate.data) { - rv = CERT_DecodeTimeChoice(notAfter, &date->nextUpdate); + rv = DER_DecodeTimeChoice(notAfter, &date->nextUpdate); if (rv) { return(SECFailure); } @@ -2245,7 +2245,7 @@ CERT_ImportCerts(CERTCertDBHandle *certdb, SECCertUsage usage, unsigned int fcerts = 0; if ( ncerts ) { - certs = (CERTCertificate**)PORT_ZAlloc(sizeof(CERTCertificate *) * ncerts ); + certs = PORT_ZNewArray(CERTCertificate*, ncerts); if ( certs == NULL ) { return(SECFailure); } @@ -2306,18 +2306,7 @@ CERT_ImportCerts(CERTCertDBHandle *certdb, SECCertUsage usage, } } - return(SECSuccess); - -#if 0 /* dead code here - why ?? XXX */ -loser: - if ( retCerts ) { - *retCerts = NULL; - } - if ( certs ) { - CERT_DestroyCertArray(certs, ncerts); - } - return(SECFailure); -#endif + return (fcerts ? SECSuccess : SECFailure); } /* @@ -2609,7 +2598,7 @@ CERT_FilterCertListByUsage(CERTCertList *certList, SECCertUsage usage, * takes trust flags into consideration. Should probably * fix the cert decoding code to do this. */ - PRBool dummyret = CERT_IsCACert(node->cert, &certType); + (void)CERT_IsCACert(node->cert, &certType); } else { certType = node->cert->nsCertType; } diff --git a/security/nss/lib/certdb/certv3.c b/security/nss/lib/certdb/certv3.c index e50c66279..f4e11b3ae 100644 --- a/security/nss/lib/certdb/certv3.c +++ b/security/nss/lib/certdb/certv3.c @@ -294,19 +294,28 @@ SECStatus CERT_FindSubjectKeyIDExtension(CERTCertificate *cert, SECItem *retItem) { - SECItem encodedValue; SECStatus rv; + SECItem encodedValue = {siBuffer, NULL, 0 }; + SECItem decodedValue = {siBuffer, NULL, 0 }; - encodedValue.data = NULL; rv = cert_FindExtension (cert->extensions, SEC_OID_X509_SUBJECT_KEY_ID, &encodedValue); - if (rv != SECSuccess) - return (rv); - rv = SEC_ASN1DecodeItem (NULL, retItem, SEC_OctetStringTemplate, - &encodedValue); - PORT_Free (encodedValue.data); - - return (rv); + if (rv == SECSuccess) { + PLArenaPool * tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (tmpArena) { + rv = SEC_QuickDERDecodeItem(tmpArena, &decodedValue, + SEC_OctetStringTemplate, + &encodedValue); + if (rv == SECSuccess) { + rv = SECITEM_CopyItem(NULL, retItem, &decodedValue); + } + PORT_FreeArena(tmpArena, PR_FALSE); + } else { + rv = SECFailure; + } + } + SECITEM_FreeItem(&encodedValue, PR_FALSE); + return rv; } SECStatus diff --git a/security/nss/lib/certdb/crl.c b/security/nss/lib/certdb/crl.c index d3d07db92..9957e1dd2 100644 --- a/security/nss/lib/certdb/crl.c +++ b/security/nss/lib/certdb/crl.c @@ -1875,7 +1875,7 @@ CERT_CheckCRL(CERTCertificate* cert, CERTCertificate* issuer, SECItem* dp, /* check the time if we have one */ if (entry->revocationDate.data && entry->revocationDate.len) { int64 revocationDate = 0; - if (SECSuccess == CERT_DecodeTimeChoice(&revocationDate, + if (SECSuccess == DER_DecodeTimeChoice(&revocationDate, &entry->revocationDate)) { /* we got a good revocation date, only consider the certificate revoked if the time we are inquiring about diff --git a/security/nss/lib/certdb/genname.c b/security/nss/lib/certdb/genname.c index 05feaaaa9..93c437778 100644 --- a/security/nss/lib/certdb/genname.c +++ b/security/nss/lib/certdb/genname.c @@ -120,7 +120,7 @@ static const SEC_ASN1Template CERT_DNSNameTemplate[] = { }; static const SEC_ASN1Template CERT_X400AddressTemplate[] = { - { SEC_ASN1_ANY | SEC_ASN1_CONTEXT_SPECIFIC | 3, + { SEC_ASN1_CONTEXT_SPECIFIC | 3, offsetof(CERTGeneralName, name.other), SEC_AnyTemplate, sizeof (CERTGeneralName)} }; @@ -133,7 +133,7 @@ static const SEC_ASN1Template CERT_DirectoryNameTemplate[] = { static const SEC_ASN1Template CERT_EDIPartyNameTemplate[] = { - { SEC_ASN1_ANY | SEC_ASN1_CONTEXT_SPECIFIC | 5, + { SEC_ASN1_CONTEXT_SPECIFIC | 5, offsetof(CERTGeneralName, name.other), SEC_AnyTemplate, sizeof (CERTGeneralName)} }; @@ -438,7 +438,7 @@ CERT_DecodeGeneralName(PRArenaPool *arena, case certX400Address: template = CERT_X400AddressTemplate; break; case certDirectoryName: template = CERT_DirectoryNameTemplate; break; default: - PORT_Assert(0); goto loser; + goto loser; } rv = SEC_ASN1DecodeItem(arena, genName, template, encodedName); if (rv != SECSuccess) diff --git a/security/nss/lib/certdb/secname.c b/security/nss/lib/certdb/secname.c index 6ddadc355..5a40249da 100644 --- a/security/nss/lib/certdb/secname.c +++ b/security/nss/lib/certdb/secname.c @@ -161,24 +161,24 @@ SetupAVAValue(PRArenaPool *arena, int valueType, char *value, SECItem *it, break; case SEC_ASN1_UNIVERSAL_STRING: valueLen = PORT_Strlen(value); - ucs4Val = (unsigned char *)PORT_ArenaZAlloc(arena, - PORT_Strlen(value) * 6); - ucs4MaxLen = PORT_Strlen(value) * 6; - if(!ucs4Val || !PORT_UCS4_UTF8Conversion(PR_TRUE, (unsigned char *)value, valueLen, + ucs4MaxLen = valueLen * 6; + ucs4Val = (unsigned char *)PORT_ArenaZAlloc(arena, ucs4MaxLen); + if(!ucs4Val || !PORT_UCS4_UTF8Conversion(PR_TRUE, + (unsigned char *)value, valueLen, ucs4Val, ucs4MaxLen, &ucs4Len)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } value = (char *)ucs4Val; valueLen = ucs4Len; + maxLen *= 4; break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } - if (((valueType != SEC_ASN1_UNIVERSAL_STRING) && (valueLen > maxLen)) || - ((valueType == SEC_ASN1_UNIVERSAL_STRING) && (valueLen > (maxLen * 4)))) { + if (valueLen > maxLen) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } @@ -654,9 +654,11 @@ CERT_DecodeAVAValue(const SECItem *derAVAValue) unsigned char *utf8Val = (unsigned char*) PORT_ArenaZAlloc(newarena, utf8ValLen); - if(!PORT_UCS4_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, + if(avaValue.len % 4 != 0 || + !PORT_UCS4_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, utf8Val, utf8ValLen, &utf8ValLen)) { PORT_FreeArena(newarena, PR_FALSE); + PORT_SetError(SEC_ERROR_INVALID_AVA); return NULL; } @@ -669,9 +671,11 @@ CERT_DecodeAVAValue(const SECItem *derAVAValue) unsigned char *utf8Val = (unsigned char*) PORT_ArenaZAlloc(newarena, utf8ValLen); - if(!PORT_UCS2_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, + if(avaValue.len % 2 != 0 || + !PORT_UCS2_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, utf8Val, utf8ValLen, &utf8ValLen)) { PORT_FreeArena(newarena, PR_FALSE); + PORT_SetError(SEC_ERROR_INVALID_AVA); return NULL; } diff --git a/security/nss/lib/certdb/stanpcertdb.c b/security/nss/lib/certdb/stanpcertdb.c index 61e9508bc..7d607e255 100644 --- a/security/nss/lib/certdb/stanpcertdb.c +++ b/security/nss/lib/certdb/stanpcertdb.c @@ -154,6 +154,7 @@ __CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, NSSCertificate *c = STAN_GetNSSCertificate(cert); context = c->object.cryptoContext; if (!context) { + PORT_SetError(SEC_ERROR_ADDING_CERT); return SECFailure; /* wasn't a temp cert */ } stanNick = nssCertificate_GetNickname(c, NULL); diff --git a/security/nss/lib/cryptohi/dsautil.c b/security/nss/lib/cryptohi/dsautil.c index 39eb3191b..9cd0b820e 100644 --- a/security/nss/lib/cryptohi/dsautil.c +++ b/security/nss/lib/cryptohi/dsautil.c @@ -34,6 +34,7 @@ * may use your version of this file under either the MPL or the * GPL. */ +#include "cryptohi.h" #include "secasn1.h" #include "secitem.h" #include "prerr.h" @@ -138,7 +139,7 @@ common_EncodeDerSig(SECItem *dest, SECItem *src) DSA_ASN1Signature sig; unsigned char *signedR; unsigned char *signedS; - int len; + unsigned int len; /* Allocate memory with room for an extra byte that * may be required if the top bit in the first byte @@ -191,7 +192,7 @@ common_EncodeDerSig(SECItem *dest, SECItem *src) ** For ECDSA, len depends on the key size used to create the signature. */ static SECItem * -common_DecodeDerSig(SECItem *item, int len) +common_DecodeDerSig(SECItem *item, unsigned int len) { SECItem * result = NULL; SECStatus status; @@ -264,7 +265,7 @@ DSAU_EncodeDerSig(SECItem *dest, SECItem *src) ** by len/2 bytes of s). dest is the signature DER encoded. */ SECStatus -DSAU_EncodeDerSigWithLen(SECItem *dest, SECItem *src, int len) +DSAU_EncodeDerSigWithLen(SECItem *dest, SECItem *src, unsigned int len) { PORT_Assert((src->len == len) && (len % 2 == 0)); @@ -293,7 +294,7 @@ DSAU_DecodeDerSig(SECItem *item) ** r followed by s (both padded to take up exactly len/2 bytes). */ SECItem * -DSAU_DecodeDerSigToLen(SECItem *item, int len) +DSAU_DecodeDerSigToLen(SECItem *item, unsigned int len) { return common_DecodeDerSig(item, len/2); } diff --git a/security/nss/lib/cryptohi/seckey.c b/security/nss/lib/cryptohi/seckey.c index 11f625164..d1b3f6a05 100644 --- a/security/nss/lib/cryptohi/seckey.c +++ b/security/nss/lib/cryptohi/seckey.c @@ -1113,7 +1113,7 @@ CERT_KMIDPublicKey(CERTCertificate *cert) } int -SECKEY_ECParams2KeySize(SECItem *encodedParams) +SECKEY_ECParamsToKeySize(const SECItem *encodedParams) { SECOidTag tag; SECItem oid = { siBuffer, NULL, 0}; @@ -1268,7 +1268,7 @@ SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk) /* Get the key size in bits and adjust */ if (pubk->u.ec.size == 0) { pubk->u.ec.size = - SECKEY_ECParams2KeySize(&pubk->u.ec.DEREncodedParams); + SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams); } return (pubk->u.ec.size + 7)/8; #endif /* NSS_ENABLE_ECC */ @@ -1292,7 +1292,7 @@ SECKEY_PublicKeyStrengthInBits(SECKEYPublicKey *pubk) case ecKey: if (pubk->u.ec.size == 0) { pubk->u.ec.size = - SECKEY_ECParams2KeySize(&pubk->u.ec.DEREncodedParams); + SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams); } return pubk->u.ec.size; #endif /* NSS_ENABLE_ECC */ diff --git a/security/nss/lib/cryptohi/secvfy.c b/security/nss/lib/cryptohi/secvfy.c index f7e9f1114..efc65b8ec 100644 --- a/security/nss/lib/cryptohi/secvfy.c +++ b/security/nss/lib/cryptohi/secvfy.c @@ -360,7 +360,6 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig) unsigned part; SECItem hash,dsasig; /* dsasig is also used for ECDSA */ SECStatus rv; - int rawSigLen; if ((cx->hasSignature == PR_FALSE) && (sig == NULL)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); diff --git a/security/nss/lib/fortcrypt/swfort/swfutl.c b/security/nss/lib/fortcrypt/swfort/swfutl.c index eee677f65..c725bbad1 100644 --- a/security/nss/lib/fortcrypt/swfort/swfutl.c +++ b/security/nss/lib/fortcrypt/swfort/swfutl.c @@ -703,7 +703,9 @@ static int path_table_size = sizeof(path_table)/sizeof(path_table[0]); char *fort_LookupFORTEZZAInitFile(void) { char *fname = NULL; +#if defined(XP_UNIX) || defined(XP_WIN) char *home = NULL; +#endif #ifdef XP_UNIX char unix_home[512]; #endif diff --git a/security/nss/lib/freebl/ecl/README b/security/nss/lib/freebl/ecl/README index 0265675c3..d12eb3610 100644 --- a/security/nss/lib/freebl/ecl/README +++ b/security/nss/lib/freebl/ecl/README @@ -46,7 +46,7 @@ that does not have access to mp_ints. ecl-curve.h - Provides hex encodings (in the form of ECCurveParams structs) of standardizes elliptic curve domain parameters and mappings -from ECCurveName to ECCurveParams. For use be code that does not have +from ECCurveName to ECCurveParams. For use by code that does not have access to mp_ints. ecl.h - Interface to constructors for curve parameters and group object, diff --git a/security/nss/lib/freebl/manifest.mn b/security/nss/lib/freebl/manifest.mn index 00715a2ee..12f067249 100644 --- a/security/nss/lib/freebl/manifest.mn +++ b/security/nss/lib/freebl/manifest.mn @@ -62,7 +62,6 @@ EXPORTS = \ blapit.h \ shsign.h \ ecl-exp.h \ - ecl-curve.h \ $(NULL) PRIVATE_EXPORTS = \ @@ -71,6 +70,7 @@ PRIVATE_EXPORTS = \ secrng.h \ ec.h \ ecl.h \ + ecl-curve.h \ $(NULL) MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h diff --git a/security/nss/lib/freebl/rsa.c b/security/nss/lib/freebl/rsa.c index e1d973fdb..5bbf31f20 100644 --- a/security/nss/lib/freebl/rsa.c +++ b/security/nss/lib/freebl/rsa.c @@ -61,6 +61,9 @@ */ #define MAX_KEY_GEN_ATTEMPTS 10 +#define MAX_RSA_MODULUS 1024 /* bytes, 8k bits */ +#define MAX_RSA_EXPONENT 8 /* bytes, 64 bits */ + /* ** RSABlindingParamsStr ** @@ -310,7 +313,7 @@ RSA_PublicKeyOp(RSAPublicKey *key, unsigned char *output, const unsigned char *input) { - unsigned int modLen; + unsigned int modLen, expLen; mp_int n, e, m, c; mp_err err = MP_OKAY; SECStatus rv = SECSuccess; @@ -327,9 +330,22 @@ RSA_PublicKeyOp(RSAPublicKey *key, CHECK_MPI_OK( mp_init(&m) ); CHECK_MPI_OK( mp_init(&c) ); modLen = rsa_modulusLen(&key->modulus); + expLen = rsa_modulusLen(&key->publicExponent); /* 1. Obtain public key (n, e) */ + if (expLen > modLen || modLen > MAX_RSA_MODULUS || expLen > MAX_RSA_EXPONENT) { + /* exponent should not be greater than modulus */ + PORT_SetError(SEC_ERROR_INVALID_KEY); + rv = SECFailure; + goto cleanup; + } SECITEM_TO_MPINT(key->modulus, &n); SECITEM_TO_MPINT(key->publicExponent, &e); + if (e.used > n.used) { + /* exponent should not be greater than modulus */ + PORT_SetError(SEC_ERROR_INVALID_KEY); + rv = SECFailure; + goto cleanup; + } /* 2. Represent message as integer in range [0..n-1] */ CHECK_MPI_OK( mp_read_unsigned_octets(&m, input, modLen) ); /* 3. Compute c = m**e mod n */ diff --git a/security/nss/lib/jar/jarver.c b/security/nss/lib/jar/jarver.c index a6e13d9f5..4252a8d5f 100644 --- a/security/nss/lib/jar/jarver.c +++ b/security/nss/lib/jar/jarver.c @@ -1377,7 +1377,9 @@ static char *jar_choose_nickname (CERTCertificate *cert) char *JAR_cert_html (JAR *jar, int style, long keylen, void *key, int *result) { +#ifdef notdef char *html; +#endif CERTCertificate *cert; *result = -1; diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index 9b002400c..40e959697 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -758,23 +758,23 @@ SECKEY_PublicKeyStrengthInBits; ;+}; ;+NSS_3.9 { # NSS 3.9 release ;+ global: -CERT_DecodeTimeChoice; CERT_DestroyOidSequence; -CERT_EncodeTimeChoice; CERT_GetOidString; ;;CERT_TimeChoiceTemplate DATA ; +DER_DecodeTimeChoice; +DER_EncodeTimeChoice; DSAU_DecodeDerSigToLen; DSAU_EncodeDerSigWithLen; NSS_Get_CERT_TimeChoiceTemplate; PK11_DeriveWithFlagsPerm; PK11_ExportEncryptedPrivKeyInfo; -PK11_FindSlotsByAliases; +PK11_FindSlotsByNames; PK11_GetSymKeyType; -PK11_MoveKey; -PK11_PubDeriveExtended; +PK11_MoveSymKey; +PK11_PubDeriveWithKDF; PK11_PubUnwrapSymKeyWithFlagsPerm; PK11_UnwrapSymKeyWithFlagsPerm; -SECKEY_ECParams2KeySize; +SECITEM_ArenaDupItem; SECMOD_GetDBModuleList; SECMOD_GetDeadModuleList; SEC_ASN1DecoderAbort; diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h index 43106c15a..6f6b578eb 100644 --- a/security/nss/lib/nss/nss.h +++ b/security/nss/lib/nss/nss.h @@ -49,11 +49,11 @@ SEC_BEGIN_PROTOS * The format of the version string should be * "<major version>.<minor version>[.<patch level>] [<Beta>]" */ -#define NSS_VERSION "3.9 Beta 3" +#define NSS_VERSION "3.9" #define NSS_VMAJOR 3 #define NSS_VMINOR 9 #define NSS_VPATCH 0 -#define NSS_BETA PR_TRUE +#define NSS_BETA PR_FALSE /* diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c index d2b2cd578..a100caca3 100644 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ b/security/nss/lib/pk11wrap/pk11cert.c @@ -3525,17 +3525,40 @@ PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey *privKey) return pk11_GetLowLevelKeyFromHandle(privKey->pkcs11Slot,privKey->pkcs11ID); } +/* argument type for listCertsCallback */ +typedef struct { + CERTCertList *list; + PK11SlotInfo *slot; +} ListCertsArg; + static SECStatus listCertsCallback(CERTCertificate* cert, void*arg) { - CERTCertList *list = (CERTCertList*)arg; + ListCertsArg *cdata = (ListCertsArg*)arg; char *nickname = NULL; + nssCryptokiObject *instance, **ci; + nssCryptokiObject **instances; + NSSCertificate *c = STAN_GetNSSCertificate(cert); - if (cert->nickname) { - nickname = PORT_ArenaStrdup(list->arena,cert->nickname); + instances = nssPKIObject_GetInstances(&c->object); + instance = NULL; + for (ci = instances; *ci; ci++) { + if ((*ci)->token->pk11slot == cdata->slot) { + instance = *ci; + break; + } + } + PORT_Assert(instance != NULL); + if (!instance) { + nssCryptokiObjectArray_Destroy(instances); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; } + nickname = STAN_GetCERTCertificateNameForInstance(cdata->list->arena, + c, instance); + nssCryptokiObjectArray_Destroy(instances); - return CERT_AddCertToListTailWithData(list, + return CERT_AddCertToListTailWithData(cdata->list, CERT_DupCertificate(cert),nickname); } @@ -3544,12 +3567,15 @@ PK11_ListCertsInSlot(PK11SlotInfo *slot) { SECStatus status; CERTCertList *certs; + ListCertsArg cdata; certs = CERT_NewCertList(); if(certs == NULL) return NULL; + cdata.list = certs; + cdata.slot = slot; status = PK11_TraverseCertsInSlot(slot, listCertsCallback, - (void*)certs); + &cdata); if( status != SECSuccess ) { CERT_DestroyCertList(certs); diff --git a/security/nss/lib/pk11wrap/pk11func.h b/security/nss/lib/pk11wrap/pk11func.h index 179f11960..ddd968d22 100644 --- a/security/nss/lib/pk11wrap/pk11func.h +++ b/security/nss/lib/pk11wrap/pk11func.h @@ -140,12 +140,12 @@ SECStatus PK11_TokenRefresh(PK11SlotInfo *slot); PK11SlotInfo *PK11_FindSlotByName(char *name); PK11SlotInfo *PK11_FindSlotBySerial(char *serial); /****************************************************************** - * PK11_FindSlotsByAliases searches for a PK11SlotInfo using one or + * PK11_FindSlotsByNames searches for a PK11SlotInfo using one or * more criteria : dllName, slotName and tokenName . In addition, if * presentOnly is set , only slots with a token inserted will be * returned. ******************************************************************/ -PK11SlotList *PK11_FindSlotsByAliases(const char *dllName, +PK11SlotList *PK11_FindSlotsByNames(const char *dllName, const char* slotName, const char* tokenName, PRBool presentOnly); PRBool PK11_IsReadOnly(PK11SlotInfo *slot); PRBool PK11_IsInternal(PK11SlotInfo *slot); @@ -304,7 +304,7 @@ SECStatus PK11_WrapSymKey(CK_MECHANISM_TYPE type, SECItem *params, * operation or the flags and making the key permanent at the same time. * If the key is moved to the same slot, operation and flags values are * currently ignored */ -PK11SymKey *PK11_MoveKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation, +PK11SymKey *PK11_MoveSymKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags, PRBool perm, PK11SymKey *symKey); /* * derive a new key from the base key. @@ -330,11 +330,11 @@ PK11SymKey *PK11_PubDerive( SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, PRBool isSender, SECItem *randomA, SECItem *randomB, CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize,void *wincx) ; -PK11SymKey *PK11_PubDeriveExtended( SECKEYPrivateKey *privKey, +PK11SymKey *PK11_PubDeriveWithKDF( SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, PRBool isSender, SECItem *randomA, SECItem *randomB, CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, - CK_ATTRIBUTE_TYPE operation, int keySize,void *wincx, - CK_ULONG kdf, SECItem *sharedData); + CK_ATTRIBUTE_TYPE operation, int keySize, + CK_ULONG kdf, SECItem *sharedData, void *wincx); /* * unwrap a new key with a symetric key. diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index 062a22f4a..35c553507 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -73,7 +73,7 @@ static PRBool pk11_FindAttrInTemplate(CK_ATTRIBUTE *attr, unsigned int numAttrs, CK_ATTRIBUTE_TYPE target); #ifdef NSS_ENABLE_ECC -extern int SECKEY_ECParams2KeySize(SECItem *params); +extern int SECKEY_ECParamsToKeySize(const SECItem *params); #endif /* NSS_ENABLE_ECC */ /* @@ -1281,7 +1281,7 @@ PK11_SignatureLen(SECKEYPrivateKey *key) if (theTemplate.pValue != NULL) { params.len = theTemplate.ulValueLen; params.data = (unsigned char *) theTemplate.pValue; - length = SECKEY_ECParams2KeySize(¶ms); + length = SECKEY_ECParamsToKeySize(¶ms); PORT_Free(theTemplate.pValue); } length = ((length + 7)/8) * 2; @@ -1428,7 +1428,7 @@ pk11_ForceSlot(PK11SymKey *symKey,CK_MECHANISM_TYPE type, } PK11SymKey * -PK11_MoveKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation, +PK11_MoveSymKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags, PRBool perm, PK11SymKey *symKey) { if (symKey->slot == slot) { @@ -3000,11 +3000,11 @@ PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, } PK11SymKey * -PK11_PubDeriveExtended(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, +PK11_PubDeriveWithKDF(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, PRBool isSender, SECItem *randomA, SECItem *randomB, CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, - CK_ATTRIBUTE_TYPE operation, int keySize,void *wincx, - CK_ULONG kdf, SECItem *sharedData) + CK_ATTRIBUTE_TYPE operation, int keySize, + CK_ULONG kdf, SECItem *sharedData, void *wincx) { PK11SlotInfo *slot = privKey->pkcs11Slot; PK11SymKey *symKey; diff --git a/security/nss/lib/pk11wrap/pk11slot.c b/security/nss/lib/pk11wrap/pk11slot.c index 7533f61c6..875495940 100644 --- a/security/nss/lib/pk11wrap/pk11slot.c +++ b/security/nss/lib/pk11wrap/pk11slot.c @@ -566,7 +566,7 @@ SECMOD_HasRootCerts(void) * Functions to find specific slots. ***********************************************************/ PK11SlotList * -PK11_FindSlotsByAliases(const char *dllName, const char* slotName, +PK11_FindSlotsByNames(const char *dllName, const char* slotName, const char* tokenName, PRBool presentOnly) { SECMODModuleList *mlp; @@ -2852,11 +2852,10 @@ PK11_AddMechanismEntry(CK_MECHANISM_TYPE type, CK_KEY_TYPE key, if (size > tableSize) { int oldTableSize = tableSize; tableSize += 10; - newt = (pk11MechanismData *) - PORT_Alloc(tableSize*sizeof(pk11MechanismData)); + newt = PORT_NewArray(pk11MechanismData, tableSize); if (newt == NULL) return; - if (old) PORT_Memcpy(newt,old,oldTableSize*sizeof(pk11MechanismData)); + if (old) PORT_Memcpy(newt, old, oldTableSize*sizeof(*newt)); } else old = NULL; newt[entry].type = type; @@ -2936,6 +2935,8 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type,unsigned long len) case CKM_AES_MAC_GENERAL: case CKM_AES_CBC_PAD: case CKM_AES_KEY_GEN: + case CKM_NETSCAPE_AES_KEY_WRAP: + case CKM_NETSCAPE_AES_KEY_WRAP_PAD: return CKK_AES; case CKM_DES_ECB: case CKM_DES_CBC: @@ -3768,120 +3769,109 @@ static unsigned long rc2_unmap(unsigned long x) SECItem * PK11_ParamFromAlgid(SECAlgorithmID *algid) { - CK_RC2_CBC_PARAMS *rc2_params = NULL; - CK_RC2_PARAMS *rc2_ecb_params = NULL; - CK_RC5_CBC_PARAMS *rc5_params_cbc; - CK_RC5_PARAMS *rc5_params_ecb; - SECItem iv; - sec_rc2cbcParameter rc2; - sec_rc5cbcParameter rc5; - SECItem *mech; - CK_MECHANISM_TYPE type; - SECOidTag algtag; - SECStatus rv; + CK_RC2_CBC_PARAMS * rc2_cbc_params = NULL; + CK_RC2_PARAMS * rc2_ecb_params = NULL; + CK_RC5_CBC_PARAMS * rc5_cbc_params = NULL; + CK_RC5_PARAMS * rc5_ecb_params = NULL; + PRArenaPool * arena = NULL; + SECItem * mech = NULL; + SECOidTag algtag; + SECStatus rv; + CK_MECHANISM_TYPE type; + /* initialize these to prevent UMRs in the ASN1 decoder. */ + SECItem iv = {siBuffer, NULL, 0}; + sec_rc2cbcParameter rc2 = { {siBuffer, NULL, 0}, {siBuffer, NULL, 0} }; + sec_rc5cbcParameter rc5 = { {siBuffer, NULL, 0}, {siBuffer, NULL, 0}, + {siBuffer, NULL, 0}, {siBuffer, NULL, 0} }; algtag = SECOID_GetAlgorithmTag(algid); type = PK11_AlgtagToMechanism(algtag); - mech = (SECItem *) PORT_Alloc(sizeof(SECItem)); - if (mech == NULL) return NULL; + mech = PORT_New(SECItem); + if (mech == NULL) { + return NULL; + } mech->type = siBuffer; + mech->data = NULL; + mech->len = 0; + arena = PORT_NewArena(1024); + if (!arena) { + goto loser; + } /* handle the complicated cases */ switch (type) { case CKM_RC2_ECB: - rv = SEC_ASN1DecodeItem(NULL, &rc2 ,sec_rc2ecb_parameter_template, + rv = SEC_ASN1DecodeItem(arena, &rc2 ,sec_rc2ecb_parameter_template, &(algid->parameters)); if (rv != SECSuccess) { - PORT_Free(mech); - return NULL; + goto loser; } - rc2_ecb_params = (CK_RC2_PARAMS *)PORT_Alloc(sizeof(CK_RC2_PARAMS)); + rc2_ecb_params = PORT_New(CK_RC2_PARAMS); if (rc2_ecb_params == NULL) { - PORT_Free(rc2.rc2ParameterVersion.data); - PORT_Free(mech); - return NULL; + goto loser; } *rc2_ecb_params = rc2_map(&rc2.rc2ParameterVersion); - PORT_Free(rc2.rc2ParameterVersion.data); mech->data = (unsigned char *) rc2_ecb_params; - mech->len = sizeof(CK_RC2_PARAMS); - return mech; + mech->len = sizeof *rc2_ecb_params; + break; case CKM_RC2_CBC: case CKM_RC2_CBC_PAD: - rv = SEC_ASN1DecodeItem(NULL, &rc2 ,sec_rc2cbc_parameter_template, + rv = SEC_ASN1DecodeItem(arena, &rc2 ,sec_rc2cbc_parameter_template, &(algid->parameters)); if (rv != SECSuccess) { - PORT_Free(mech); - return NULL; + goto loser; } - rc2_params = (CK_RC2_CBC_PARAMS *)PORT_Alloc(sizeof(CK_RC2_CBC_PARAMS)); - if (rc2_params == NULL) { - PORT_Free(rc2.iv.data); - PORT_Free(rc2.rc2ParameterVersion.data); - PORT_Free(mech); - return NULL; + rc2_cbc_params = PORT_New(CK_RC2_CBC_PARAMS); + if (rc2_cbc_params == NULL) { + goto loser; } - rc2_params->ulEffectiveBits = rc2_map(&rc2.rc2ParameterVersion); - PORT_Free(rc2.rc2ParameterVersion.data); - PORT_Memcpy(rc2_params->iv,rc2.iv.data,sizeof(rc2_params->iv)); - PORT_Free(rc2.iv.data); - mech->data = (unsigned char *) rc2_params; - mech->len = sizeof(CK_RC2_CBC_PARAMS); - return mech; + mech->data = (unsigned char *) rc2_cbc_params; + mech->len = sizeof *rc2_cbc_params; + rc2_cbc_params->ulEffectiveBits = rc2_map(&rc2.rc2ParameterVersion); + if (rc2.iv.len != sizeof rc2_cbc_params->iv) { + PORT_SetError(SEC_ERROR_INPUT_LEN); + goto loser; + } + PORT_Memcpy(rc2_cbc_params->iv, rc2.iv.data, rc2.iv.len); + break; case CKM_RC5_ECB: - rv = SEC_ASN1DecodeItem(NULL, &rc5 ,sec_rc5ecb_parameter_template, + rv = SEC_ASN1DecodeItem(arena, &rc5 ,sec_rc5ecb_parameter_template, &(algid->parameters)); if (rv != SECSuccess) { - PORT_Free(mech); - return NULL; + goto loser; } - rc5_params_ecb=(CK_RC5_PARAMS *)PORT_Alloc(sizeof(CK_RC5_PARAMS)); - PORT_Free(rc5.version.data); - if (rc5_params_ecb == NULL) { - PORT_Free(rc5.rounds.data); - PORT_Free(rc5.blockSizeInBits.data); - PORT_Free(mech); - return NULL; + rc5_ecb_params = PORT_New(CK_RC5_PARAMS); + if (rc5_ecb_params == NULL) { + goto loser; } - rc5_params_ecb->ulRounds = DER_GetInteger(&rc5.rounds); - rc5_params_ecb->ulWordsize = DER_GetInteger(&rc5.blockSizeInBits)/8; - PORT_Free(rc5.rounds.data); - PORT_Free(rc5.blockSizeInBits.data); - mech->data = (unsigned char *) rc5_params_ecb; - mech->len = sizeof(CK_RC5_PARAMS); - return mech; + rc5_ecb_params->ulRounds = DER_GetInteger(&rc5.rounds); + rc5_ecb_params->ulWordsize = DER_GetInteger(&rc5.blockSizeInBits)/8; + mech->data = (unsigned char *) rc5_ecb_params; + mech->len = sizeof *rc5_ecb_params; + break; case CKM_RC5_CBC: case CKM_RC5_CBC_PAD: - rv = SEC_ASN1DecodeItem(NULL, &rc5 ,sec_rc5cbc_parameter_template, + rv = SEC_ASN1DecodeItem(arena, &rc5 ,sec_rc5cbc_parameter_template, &(algid->parameters)); if (rv != SECSuccess) { - PORT_Free(mech); - return NULL; + goto loser; } - rc5_params_cbc = (CK_RC5_CBC_PARAMS *) + rc5_cbc_params = (CK_RC5_CBC_PARAMS *) PORT_Alloc(sizeof(CK_RC5_CBC_PARAMS) + rc5.iv.len); - PORT_Free(rc5.version.data); - if (rc2_params == NULL) { - PORT_Free(rc5.iv.data); - PORT_Free(rc5.rounds.data); - PORT_Free(rc5.blockSizeInBits.data); - PORT_Free(mech); - return NULL; + if (rc5_cbc_params == NULL) { + goto loser; } - rc5_params_cbc->ulRounds = DER_GetInteger(&rc5.rounds); - rc5_params_cbc->ulWordsize = DER_GetInteger(&rc5.blockSizeInBits)/8; - PORT_Free(rc5.rounds.data); - PORT_Free(rc5.blockSizeInBits.data); - rc5_params_cbc->pIv = ((CK_BYTE_PTR)rc5_params_cbc) + mech->data = (unsigned char *) rc5_cbc_params; + mech->len = sizeof *rc5_cbc_params; + rc5_cbc_params->ulRounds = DER_GetInteger(&rc5.rounds); + rc5_cbc_params->ulWordsize = DER_GetInteger(&rc5.blockSizeInBits)/8; + rc5_cbc_params->pIv = ((CK_BYTE_PTR)rc5_cbc_params) + sizeof(CK_RC5_CBC_PARAMS); - PORT_Memcpy(rc5_params_cbc->pIv,rc5.iv.data,rc5.iv.len); - rc5_params_cbc->ulIvLen = rc5.iv.len; - PORT_Free(rc5.iv.data); - mech->data = (unsigned char *) rc5_params_cbc; - mech->len = sizeof(CK_RC5_CBC_PARAMS); - return mech; + rc5_cbc_params->ulIvLen = rc5.iv.len; + PORT_Memcpy(rc5_cbc_params->pIv, rc5.iv.data, rc5.iv.len); + break; case CKM_PBE_MD2_DES_CBC: case CKM_PBE_MD5_DES_CBC: case CKM_NETSCAPE_PBE_SHA1_DES_CBC: @@ -3899,25 +3889,9 @@ PK11_ParamFromAlgid(SECAlgorithmID *algid) case CKM_PBE_SHA1_RC4_128: rv = pbe_PK11AlgidToParam(algid,mech); if (rv != SECSuccess) { - PORT_Free(mech); - return NULL; + goto loser; } - return mech; - default: - /* must be a simple case */ break; - } - - /* simple cases are simpley Octect encoded IV's */ - rv = SEC_ASN1DecodeItem(NULL, &iv, SEC_OctetStringTemplate, - &(algid->parameters)); - if (rv != SECSuccess) { - iv.data = NULL; - iv.len = 0; - } - - rv = SECSuccess; - switch (type) { case CKM_RC4: case CKM_AES_ECB: case CKM_DES_ECB: @@ -3927,15 +3901,13 @@ PK11_ParamFromAlgid(SECAlgorithmID *algid) case CKM_CAST_ECB: case CKM_CAST3_ECB: case CKM_CAST5_ECB: - mech->data = NULL; - mech->len = 0; break; + default: if (pk11_lookup(type)->iv == 0) { - mech->data = NULL; - mech->len = 0; break; } + /* FALL THROUGH */ case CKM_AES_CBC: case CKM_DES_CBC: case CKM_DES3_CBC: @@ -3968,25 +3940,29 @@ PK11_ParamFromAlgid(SECAlgorithmID *algid) case CKM_JUNIPER_CBC128: case CKM_JUNIPER_COUNTER: case CKM_JUNIPER_SHUFFLE: - if (iv.data == NULL) { - rv = SECFailure; - break; + /* simple cases are simply octet string encoded IVs */ + rv = SEC_ASN1DecodeItem(arena, &iv, SEC_OctetStringTemplate, + &(algid->parameters)); + if (rv != SECSuccess || iv.data == NULL) { + goto loser; } + /* XXX Should be some IV length sanity check here. */ mech->data = (unsigned char*)PORT_Alloc(iv.len); if (mech->data == NULL) { - rv = SECFailure; - break; + goto loser; } - PORT_Memcpy(mech->data,iv.data,iv.len); + PORT_Memcpy(mech->data, iv.data, iv.len); mech->len = iv.len; break; } - if (iv.data) PORT_Free(iv.data); - if (rv != SECSuccess) { - SECITEM_FreeItem(mech,PR_TRUE); - return NULL; - } + PORT_FreeArena(arena, PR_FALSE); return mech; + +loser: + if (arena) + PORT_FreeArena(arena, PR_FALSE); + SECITEM_FreeItem(mech,PR_TRUE); + return NULL; } SECStatus diff --git a/security/nss/lib/pkcs12/p12d.c b/security/nss/lib/pkcs12/p12d.c index cbdc352f7..624592117 100644 --- a/security/nss/lib/pkcs12/p12d.c +++ b/security/nss/lib/pkcs12/p12d.c @@ -1098,6 +1098,7 @@ p12u_DigestRead(void *arg, unsigned char *buf, unsigned long len) SEC_PKCS12DecoderContext* p12cxt = arg; if(!buf || len == 0 || !p12cxt->buffer) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); return -1; } @@ -1105,7 +1106,7 @@ p12u_DigestRead(void *arg, unsigned char *buf, unsigned long len) /* trying to read past the end of the buffer */ toread = p12cxt->filesize - p12cxt->currentpos; } - memcpy(buf, (void*)((char*)p12cxt->buffer + p12cxt->currentpos), toread); + memcpy(buf, (char*)p12cxt->buffer + p12cxt->currentpos, toread); p12cxt->currentpos += toread; return toread; } @@ -1136,7 +1137,7 @@ p12u_DigestWrite(void *arg, unsigned char *buf, unsigned long len) p12cxt->allocated = newsize; } PR_ASSERT(p12cxt->buffer); - memcpy((void*)((char*)p12cxt->buffer + p12cxt->currentpos), buf, len); + memcpy((char*)p12cxt->buffer + p12cxt->currentpos, buf, len); p12cxt->currentpos += len; return len; } @@ -1291,10 +1292,8 @@ loser: #define IN_BUF_LEN 1024 #ifdef DEBUG static const char bufferEnd[] = { "BufferEnd" } ; -#define FUDGE sizeof bufferEnd -#else -#define FUDGE 128 /* extra protection when assertions disabled. */ #endif +#define FUDGE 128 /* must be as large as bufferEnd or more. */ /* verify the hmac by reading the data from the temporary file * using the routines specified when the decodingContext was @@ -1318,6 +1317,7 @@ sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx) CK_MECHANISM_TYPE integrityMech; if(!p12dcx || p12dcx->error) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } buf = (unsigned char *)PORT_Alloc(IN_BUF_LEN + FUDGE); @@ -1388,7 +1388,7 @@ sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx) if (bytesRead > IN_BUF_LEN) { /* dRead callback overflowed buffer. */ - PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_READ); + PORT_SetError(SEC_ERROR_INPUT_LEN); goto loser; } diff --git a/security/nss/lib/pkcs7/p7create.c b/security/nss/lib/pkcs7/p7create.c index 6454db74c..62573cb46 100644 --- a/security/nss/lib/pkcs7/p7create.c +++ b/security/nss/lib/pkcs7/p7create.c @@ -617,7 +617,7 @@ SEC_PKCS7AddSigningTime (SEC_PKCS7ContentInfo *cinfo) if (signerinfos == NULL || signerinfos[0] == NULL) return SECFailure; - rv = CERT_EncodeTimeChoice(NULL, &stime, PR_Now()); + rv = DER_EncodeTimeChoice(NULL, &stime, PR_Now()); if (rv != SECSuccess) return rv; diff --git a/security/nss/lib/pkcs7/p7decode.c b/security/nss/lib/pkcs7/p7decode.c index cba3ac9ef..e4d565fb5 100644 --- a/security/nss/lib/pkcs7/p7decode.c +++ b/security/nss/lib/pkcs7/p7decode.c @@ -1573,7 +1573,7 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo, */ encoded_stime = SEC_PKCS7GetSigningTime (cinfo); if (encoded_stime != NULL) { - if (CERT_DecodeTimeChoice (&stime, encoded_stime) != SECSuccess) + if (DER_DecodeTimeChoice (&stime, encoded_stime) != SECSuccess) encoded_stime = NULL; /* conversion failed, so pretend none */ } diff --git a/security/nss/lib/pki/pkibase.c b/security/nss/lib/pki/pkibase.c index 5ee2a4ee9..ecbb6872b 100644 --- a/security/nss/lib/pki/pkibase.c +++ b/security/nss/lib/pki/pkibase.c @@ -217,12 +217,11 @@ nssPKIObject_RemoveInstanceForToken ( } } if (--object->numInstances > 0) { - object->instances = nss_ZREALLOCARRAY(object->instances, + nssCryptokiObject **instances = nss_ZREALLOCARRAY(object->instances, nssCryptokiObject *, object->numInstances); - if (!object->instances) { - PZ_Unlock(object->lock); - return PR_FAILURE; + if (instances) { + object->instances = instances; } } else { nss_ZFreeIf(object->instances); @@ -244,10 +243,12 @@ nssPKIObject_DeleteStoredObject ( { PRUint32 i, numNotDestroyed; PRStatus status = PR_SUCCESS; +#ifndef NSS_3_4_CODE NSSTrustDomain *td = object->trustDomain; NSSCallback *pwcb = uhh ? /* is this optional? */ uhh : nssTrustDomain_GetDefaultCallback(td, NULL); +#endif numNotDestroyed = 0; PZ_Lock(object->lock); for (i=0; i<object->numInstances; i++) { diff --git a/security/nss/lib/pki/tdcache.c b/security/nss/lib/pki/tdcache.c index c9fd8012f..77e71a08a 100644 --- a/security/nss/lib/pki/tdcache.c +++ b/security/nss/lib/pki/tdcache.c @@ -715,6 +715,50 @@ add_email_entry ( extern const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE; +static void +remove_object_instances ( + nssPKIObject *object, + nssCryptokiObject **instances, + int numInstances +) +{ + int i; + + for (i = 0; i < numInstances; i++) { + nssPKIObject_RemoveInstanceForToken(object, instances[i]->token); + } +} + +static SECStatus +merge_object_instances ( + nssPKIObject *to, + nssPKIObject *from +) +{ + nssCryptokiObject **instances, **ci; + int i; + SECStatus rv = SECSuccess; + + instances = nssPKIObject_GetInstances(from); + if (instances == NULL) { + return SECFailure; + } + for (ci = instances, i = 0; *ci; ci++, i++) { + nssCryptokiObject *instance = nssCryptokiObject_Clone(*ci); + if (instance) { + if (nssPKIObject_AddInstance(to, instance) == SECSuccess) { + continue; + } + nssCryptokiObject_Destroy(instance); + } + remove_object_instances(to, instances, i); + rv = SECFailure; + break; + } + nssCryptokiObjectArray_Destroy(instances); + return rv; +} + static NSSCertificate * add_cert_to_cache ( NSSTrustDomain *td, @@ -743,6 +787,13 @@ add_cert_to_cache ( /* collision - somebody else already added the cert * to the cache before this thread got around to it. */ + /* merge the instances of the cert */ + if (merge_object_instances(&rvCert->object, &cert->object) + != SECSuccess) { + nssCertificate_Destroy(rvCert); + return NULL; + } + STAN_ForceCERTCertificateUpdate(rvCert); nssCertificate_Destroy(cert); return rvCert; } diff --git a/security/nss/lib/smime/cms.h b/security/nss/lib/smime/cms.h index 0538f1a37..7003a6e27 100644 --- a/security/nss/lib/smime/cms.h +++ b/security/nss/lib/smime/cms.h @@ -563,9 +563,6 @@ extern SECStatus NSS_CMSSignedData_AddSignerInfo(NSSCMSSignedData *sigd, NSSCMSSignerInfo *signerinfo); -extern SECItem * -NSS_CMSSignedData_GetDigestByAlgTag(NSSCMSSignedData *sigd, SECOidTag algtag); - extern SECStatus NSS_CMSSignedData_SetDigests(NSSCMSSignedData *sigd, SECAlgorithmID **digestalgs, @@ -673,7 +670,7 @@ NSS_CMSSignerInfo_GetSigningCertificate(NSSCMSSignerInfo *signerinfo, CERTCertDB * * sinfo - signerInfo data for this signer * - * Returns a pointer to allocated memory, which must be freed. + * Returns a pointer to allocated memory, which must be freed with PORT_Free. * A return value of NULL is an error. */ extern char * diff --git a/security/nss/lib/smime/cmsarray.c b/security/nss/lib/smime/cmsarray.c index 68d7e1963..2673770d9 100644 --- a/security/nss/lib/smime/cmsarray.c +++ b/security/nss/lib/smime/cmsarray.c @@ -91,6 +91,10 @@ NSS_CMSArray_Add(PRArenaPool *poolp, void ***array, void *obj) (n + 1) * sizeof(void *), (n + 2) * sizeof(void *)); } + + if (dest == NULL) + return SECFailure; + dest[n] = obj; dest[n+1] = NULL; *array = dest; diff --git a/security/nss/lib/smime/cmsattr.c b/security/nss/lib/smime/cmsattr.c index 03b516f9e..250670745 100644 --- a/security/nss/lib/smime/cmsattr.c +++ b/security/nss/lib/smime/cmsattr.c @@ -86,13 +86,11 @@ NSS_CMSAttribute_Create(PRArenaPool *poolp, SECOidTag oidtag, SECItem *value, PR goto loser; if (value != NULL) { - if ((copiedvalue = SECITEM_AllocItem(poolp, NULL, value->len)) == NULL) + if ((copiedvalue = SECITEM_ArenaDupItem(poolp, value)) == NULL) goto loser; - if (SECITEM_CopyItem(poolp, copiedvalue, value) != SECSuccess) + if (NSS_CMSArray_Add(poolp, (void ***)&(attr->values), (void *)copiedvalue) != SECSuccess) goto loser; - - NSS_CMSArray_Add(poolp, (void ***)&(attr->values), (void *)copiedvalue); } attr->encoded = encoded; @@ -113,18 +111,22 @@ loser: SECStatus NSS_CMSAttribute_AddValue(PLArenaPool *poolp, NSSCMSAttribute *attr, SECItem *value) { - SECItem copiedvalue; + SECItem *copiedvalue; void *mark; PORT_Assert (poolp != NULL); mark = PORT_ArenaMark(poolp); - /* XXX we need an object memory model #$%#$%! */ - if (SECITEM_CopyItem(poolp, &copiedvalue, value) != SECSuccess) + if (value == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto loser; + } + + if ((copiedvalue = SECITEM_ArenaDupItem(poolp, value)) == NULL) goto loser; - if (NSS_CMSArray_Add(poolp, (void ***)&(attr->values), (void *)&copiedvalue) != SECSuccess) + if (NSS_CMSArray_Add(poolp, (void ***)&(attr->values), (void *)copiedvalue) != SECSuccess) goto loser; PORT_ArenaUnmark(poolp, mark); @@ -217,9 +219,12 @@ cms_attr_choose_attr_value_template(void *src_or_dest, PRBool encoding) attribute = (NSSCMSAttribute *)src_or_dest; - if (encoding && attribute->encoded) - /* we're encoding, and the attribute value is already encoded. */ - return SEC_ASN1_GET(SEC_AnyTemplate); + if (encoding && (!attribute->values || !attribute->values[0] || + attribute->encoded)) { + /* we're encoding, and the attribute has no value or the attribute + * value is already encoded. */ + return SEC_ASN1_GET(SEC_AnyTemplate); + } /* get attribute's typeTag */ oiddata = attribute->typeTag; diff --git a/security/nss/lib/smime/cmscinfo.c b/security/nss/lib/smime/cmscinfo.c index d01c5962b..ceb99c605 100644 --- a/security/nss/lib/smime/cmscinfo.c +++ b/security/nss/lib/smime/cmscinfo.c @@ -76,6 +76,11 @@ NSS_CMSContentInfo_Destroy(NSSCMSContentInfo *cinfo) /* XXX Anything else that needs to be "manually" freed/destroyed? */ break; } + if (cinfo->digcx) { + /* must destroy digest objects */ + NSS_CMSDigestContext_Cancel(cinfo->digcx); + cinfo->digcx = NULL; + } if (cinfo->bulkkey) PK11_FreeSymKey(cinfo->bulkkey); @@ -204,7 +209,10 @@ NSS_CMSContentInfo_SetContent_EncryptedData(NSSCMSMessage *cmsg, NSSCMSContentIn void * NSS_CMSContentInfo_GetContent(NSSCMSContentInfo *cinfo) { - switch (cinfo->contentTypeTag->offset) { + SECOidTag tag = (cinfo && cinfo->contentTypeTag) + ? cinfo->contentTypeTag->offset + : SEC_OID_UNKNOWN; + switch (tag) { case SEC_OID_PKCS7_DATA: case SEC_OID_PKCS7_SIGNED_DATA: case SEC_OID_PKCS7_ENVELOPED_DATA: @@ -225,22 +233,28 @@ SECItem * NSS_CMSContentInfo_GetInnerContent(NSSCMSContentInfo *cinfo) { NSSCMSContentInfo *ccinfo; + SECOidTag tag; + SECItem *pItem = NULL; - switch (NSS_CMSContentInfo_GetContentTypeTag(cinfo)) { + tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo); + switch (tag) { case SEC_OID_PKCS7_DATA: - return cinfo->content.data; /* end of recursion - every message has to have a data cinfo */ + /* end of recursion - every message has to have a data cinfo */ + pItem = cinfo->content.data; + break; case SEC_OID_PKCS7_DIGESTED_DATA: case SEC_OID_PKCS7_ENCRYPTED_DATA: case SEC_OID_PKCS7_ENVELOPED_DATA: case SEC_OID_PKCS7_SIGNED_DATA: - if ((ccinfo = NSS_CMSContentInfo_GetChildContentInfo(cinfo)) == NULL) - break; - return NSS_CMSContentInfo_GetContent(ccinfo); + ccinfo = NSS_CMSContentInfo_GetChildContentInfo(cinfo); + if (ccinfo != NULL) + pItem = NSS_CMSContentInfo_GetContent(ccinfo); + break; default: PORT_Assert(0); break; } - return NULL; + return pItem; } /* diff --git a/security/nss/lib/smime/cmscipher.c b/security/nss/lib/smime/cmscipher.c index 6d73beaff..71cd9682a 100644 --- a/security/nss/lib/smime/cmscipher.c +++ b/security/nss/lib/smime/cmscipher.c @@ -507,7 +507,6 @@ NSS_CMSCipherContext_Decrypt(NSSCMSCipherContext *cc, unsigned char *output, * If we do not, there is something wrong, either with our own * logic or with (length of) the data given to us. */ - PORT_Assert ((padsize == 0) || (pcount % padsize) == 0); if ((padsize != 0) && (pcount % padsize) != 0) { PORT_Assert (final); PORT_SetError (SEC_ERROR_BAD_DATA); diff --git a/security/nss/lib/smime/cmsdecode.c b/security/nss/lib/smime/cmsdecode.c index 8ba2b33dd..1abc1772c 100644 --- a/security/nss/lib/smime/cmsdecode.c +++ b/security/nss/lib/smime/cmsdecode.c @@ -48,15 +48,15 @@ #include "secerr.h" struct NSSCMSDecoderContextStr { - SEC_ASN1DecoderContext * dcx; /* ASN.1 decoder context */ - NSSCMSMessage * cmsg; /* backpointer to the root message */ - SECOidTag type; /* type of message */ - NSSCMSContent content; /* pointer to message */ - NSSCMSDecoderContext * childp7dcx; /* inner CMS decoder context */ - PRBool saw_contents; - int error; - NSSCMSContentCallback cb; - void * cb_arg; + SEC_ASN1DecoderContext * dcx; /* ASN.1 decoder context */ + NSSCMSMessage * cmsg; /* backpointer to the root message */ + SECOidTag type; /* type of message */ + NSSCMSContent content; /* pointer to message */ + NSSCMSDecoderContext * childp7dcx; /* inner CMS decoder context */ + PRBool saw_contents; + int error; + NSSCMSContentCallback cb; + void * cb_arg; }; struct NSSCMSDecoderDataStr { @@ -66,13 +66,13 @@ struct NSSCMSDecoderDataStr { typedef struct NSSCMSDecoderDataStr NSSCMSDecoderData; -static void nss_cms_decoder_update_filter (void *arg, const char *data, unsigned long len, - int depth, SEC_ASN1EncodingPart data_kind); +static void nss_cms_decoder_update_filter (void *arg, const char *data, + unsigned long len, int depth, SEC_ASN1EncodingPart data_kind); static SECStatus nss_cms_before_data(NSSCMSDecoderContext *p7dcx); static SECStatus nss_cms_after_data(NSSCMSDecoderContext *p7dcx); static SECStatus nss_cms_after_end(NSSCMSDecoderContext *p7dcx); -static void nss_cms_decoder_work_data(NSSCMSDecoderContext *p7dcx, - const unsigned char *data, unsigned long len, PRBool final); +static void nss_cms_decoder_work_data(NSSCMSDecoderContext *p7dcx, + const unsigned char *data, unsigned long len, PRBool final); static NSSCMSDecoderData *nss_cms_create_decoder_data(PRArenaPool *poolp); extern const SEC_ASN1Template NSSCMSMessageTemplate[]; @@ -129,7 +129,8 @@ nss_cms_decoder_notify(void *arg, PRBool before, void *dest, int depth) */ if (after && dest == &(rootcinfo->contentType)) { p7dcx->type = NSS_CMSContentInfo_GetContentTypeTag(rootcinfo); - p7dcx->content = rootcinfo->content; /* is this ready already ? need to alloc? */ + p7dcx->content = rootcinfo->content; + /* is this ready already ? need to alloc? */ /* XXX yes we need to alloc -- continue here */ } break; @@ -138,8 +139,10 @@ nss_cms_decoder_notify(void *arg, PRBool before, void *dest, int depth) /* otherwise, we handle this type implicitely in the inner decoders */ if (before && dest == &(rootcinfo->content)) { - /* fake it to cause the filter to put the data in the right place... */ - /* we want the ASN.1 decoder to deliver the decoded bytes to us from now on */ + /* cause the filter to put the data in the right place... + ** We want the ASN.1 decoder to deliver the decoded bytes to us + ** from now on + */ SEC_ASN1DecoderSetFilterProc(p7dcx->dcx, nss_cms_decoder_update_filter, p7dcx, @@ -159,13 +162,14 @@ nss_cms_decoder_notify(void *arg, PRBool before, void *dest, int depth) case SEC_OID_PKCS7_ENCRYPTED_DATA: if (before && dest == &(rootcinfo->content)) - break; /* we're not there yet */ + break; /* we're not there yet */ if (p7dcx->content.pointer == NULL) p7dcx->content = rootcinfo->content; /* get this data type's inner contentInfo */ - cinfo = NSS_CMSContent_GetContentInfo(p7dcx->content.pointer, p7dcx->type); + cinfo = NSS_CMSContent_GetContentInfo(p7dcx->content.pointer, + p7dcx->type); if (before && dest == &(cinfo->contentType)) { /* at this point, set up the &%$&$ back pointer */ @@ -191,14 +195,18 @@ nss_cms_decoder_notify(void *arg, PRBool before, void *dest, int depth) } if (before && dest == &(cinfo->rawContent)) { - /* we want the ASN.1 decoder to deliver the decoded bytes to us from now on */ - SEC_ASN1DecoderSetFilterProc(p7dcx->dcx, nss_cms_decoder_update_filter, - p7dcx, (PRBool)(p7dcx->cb != NULL)); + /* we want the ASN.1 decoder to deliver the decoded bytes to us + ** from now on + */ + SEC_ASN1DecoderSetFilterProc(p7dcx->dcx, + nss_cms_decoder_update_filter, + p7dcx, (PRBool)(p7dcx->cb != NULL)); /* we're right in front of the data */ if (nss_cms_before_data(p7dcx) != SECSuccess) { - SEC_ASN1DecoderClearFilterProc(p7dcx->dcx); /* stop all processing */ + SEC_ASN1DecoderClearFilterProc(p7dcx->dcx); + /* stop all processing */ p7dcx->error = PORT_GetError(); } } @@ -216,7 +224,7 @@ nss_cms_decoder_notify(void *arg, PRBool before, void *dest, int depth) case SEC_OID_PKCS7_AUTHENTICATED_DATA: #endif default: - /* unsupported or unknown message type - fail (more or less) gracefully */ + /* unsupported or unknown message type - fail gracefully */ p7dcx->error = SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE; break; } @@ -244,28 +252,24 @@ nss_cms_before_data(NSSCMSDecoderContext *p7dcx) case SEC_OID_PKCS7_SIGNED_DATA: /* we're decoding a signedData, so set up the digests */ rv = NSS_CMSSignedData_Decode_BeforeData(p7dcx->content.signedData); - if (rv != SECSuccess) - return SECFailure; break; case SEC_OID_PKCS7_DIGESTED_DATA: /* we're encoding a digestedData, so set up the digest */ rv = NSS_CMSDigestedData_Decode_BeforeData(p7dcx->content.digestedData); - if (rv != SECSuccess) - return SECFailure; break; case SEC_OID_PKCS7_ENVELOPED_DATA: - rv = NSS_CMSEnvelopedData_Decode_BeforeData(p7dcx->content.envelopedData); - if (rv != SECSuccess) - return SECFailure; + rv = NSS_CMSEnvelopedData_Decode_BeforeData( + p7dcx->content.envelopedData); break; case SEC_OID_PKCS7_ENCRYPTED_DATA: - rv = NSS_CMSEncryptedData_Decode_BeforeData(p7dcx->content.encryptedData); - if (rv != SECSuccess) - return SECFailure; + rv = NSS_CMSEncryptedData_Decode_BeforeData( + p7dcx->content.encryptedData); break; default: return SECFailure; } + if (rv != SECSuccess) + return SECFailure; /* ok, now we have a pointer to cinfo */ /* find out what kind of data is encapsulated */ @@ -288,7 +292,7 @@ nss_cms_before_data(NSSCMSDecoderContext *p7dcx) if ((template = NSS_CMSUtil_GetTemplateByTypeTag(childtype)) == NULL) return SECFailure; - childp7dcx = (NSSCMSDecoderContext *)PORT_ZAlloc(sizeof(NSSCMSDecoderContext)); + childp7dcx = PORT_ZNew(NSSCMSDecoderContext); if (childp7dcx == NULL) return SECFailure; @@ -301,12 +305,14 @@ nss_cms_before_data(NSSCMSDecoderContext *p7dcx) goto loser; /* start the child decoder */ - childp7dcx->dcx = SEC_ASN1DecoderStart(poolp, childp7dcx->content.pointer, template); + childp7dcx->dcx = SEC_ASN1DecoderStart(poolp, childp7dcx->content.pointer, + template); if (childp7dcx->dcx == NULL) goto loser; /* the new decoder needs to notify, too */ - SEC_ASN1DecoderSetNotifyProc(childp7dcx->dcx, nss_cms_decoder_notify, childp7dcx); + SEC_ASN1DecoderSetNotifyProc(childp7dcx->dcx, nss_cms_decoder_notify, + childp7dcx); /* tell the parent decoder that it needs to feed us the content data */ p7dcx->childp7dcx = childp7dcx; @@ -315,7 +321,9 @@ nss_cms_before_data(NSSCMSDecoderContext *p7dcx) childp7dcx->cmsg = p7dcx->cmsg; /* backpointer to root message */ - /* should the child decoder encounter real data, it needs to give it to the caller */ + /* should the child decoder encounter real data, + ** it must give it to the caller + */ childp7dcx->cb = p7dcx->cb; childp7dcx->cb_arg = p7dcx->cb_arg; @@ -339,12 +347,9 @@ loser: static SECStatus nss_cms_after_data(NSSCMSDecoderContext *p7dcx) { - PLArenaPool *poolp; NSSCMSDecoderContext *childp7dcx; SECStatus rv = SECFailure; - poolp = p7dcx->cmsg->poolp; - /* Handle last block. This is necessary to flush out the last bytes * of a possibly incomplete block */ nss_cms_decoder_work_data(p7dcx, NULL, 0, PR_TRUE); @@ -372,13 +377,16 @@ nss_cms_after_data(NSSCMSDecoderContext *p7dcx) rv = NSS_CMSSignedData_Decode_AfterData(p7dcx->content.signedData); break; case SEC_OID_PKCS7_ENVELOPED_DATA: - rv = NSS_CMSEnvelopedData_Decode_AfterData(p7dcx->content.envelopedData); + rv = NSS_CMSEnvelopedData_Decode_AfterData( + p7dcx->content.envelopedData); break; case SEC_OID_PKCS7_DIGESTED_DATA: - rv = NSS_CMSDigestedData_Decode_AfterData(p7dcx->content.digestedData); + rv = NSS_CMSDigestedData_Decode_AfterData( + p7dcx->content.digestedData); break; case SEC_OID_PKCS7_ENCRYPTED_DATA: - rv = NSS_CMSEncryptedData_Decode_AfterData(p7dcx->content.encryptedData); + rv = NSS_CMSEncryptedData_Decode_AfterData( + p7dcx->content.encryptedData); break; case SEC_OID_PKCS7_DATA: /* do nothing */ @@ -394,26 +402,29 @@ done: static SECStatus nss_cms_after_end(NSSCMSDecoderContext *p7dcx) { - SECStatus rv; - PLArenaPool *poolp; - - poolp = p7dcx->cmsg->poolp; + SECStatus rv = SECSuccess; switch (p7dcx->type) { case SEC_OID_PKCS7_SIGNED_DATA: - rv = NSS_CMSSignedData_Decode_AfterEnd(p7dcx->content.signedData); + if (p7dcx->content.signedData) + rv = NSS_CMSSignedData_Decode_AfterEnd(p7dcx->content.signedData); break; case SEC_OID_PKCS7_ENVELOPED_DATA: - rv = NSS_CMSEnvelopedData_Decode_AfterEnd(p7dcx->content.envelopedData); + if (p7dcx->content.envelopedData) + rv = NSS_CMSEnvelopedData_Decode_AfterEnd( + p7dcx->content.envelopedData); break; case SEC_OID_PKCS7_DIGESTED_DATA: - rv = NSS_CMSDigestedData_Decode_AfterEnd(p7dcx->content.digestedData); + if (p7dcx->content.digestedData) + rv = NSS_CMSDigestedData_Decode_AfterEnd( + p7dcx->content.digestedData); break; case SEC_OID_PKCS7_ENCRYPTED_DATA: - rv = NSS_CMSEncryptedData_Decode_AfterEnd(p7dcx->content.encryptedData); + if (p7dcx->content.encryptedData) + rv = NSS_CMSEncryptedData_Decode_AfterEnd( + p7dcx->content.encryptedData); break; case SEC_OID_PKCS7_DATA: - rv = SECSuccess; break; default: rv = SECFailure; /* we should not have got that far... */ @@ -518,9 +529,10 @@ nss_cms_decoder_work_data(NSSCMSDecoderContext *p7dcx, if (cinfo->digcx) NSS_CMSDigestContext_Update(cinfo->digcx, data, len); - /* at this point, we have the plain decoded & decrypted data */ - /* which is either more encoded DER which we need to hand to the child decoder */ - /* or data we need to hand back to our caller */ + /* at this point, we have the plain decoded & decrypted data + ** which is either more encoded DER (which we need to hand to the child + ** decoder) or data we need to hand back to our caller + */ /* pass the content back to our caller or */ /* feed our freshly decrypted and decoded data into child decoder */ @@ -589,7 +601,8 @@ nss_cms_decoder_update_filter (void *arg, const char *data, unsigned long len, /* pass on the content bytes only */ if (data_kind == SEC_ASN1_Contents) - nss_cms_decoder_work_data(p7dcx, (const unsigned char *) data, len, PR_FALSE); + nss_cms_decoder_work_data(p7dcx, (const unsigned char *) data, len, + PR_FALSE); } /* @@ -604,7 +617,8 @@ NSSCMSDecoderContext * NSS_CMSDecoder_Start(PRArenaPool *poolp, NSSCMSContentCallback cb, void *cb_arg, PK11PasswordFunc pwfn, void *pwfn_arg, - NSSCMSGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg) + NSSCMSGetDecryptKeyCallback decrypt_key_cb, + void *decrypt_key_cb_arg) { NSSCMSDecoderContext *p7dcx; NSSCMSMessage *cmsg; @@ -613,10 +627,10 @@ NSS_CMSDecoder_Start(PRArenaPool *poolp, if (cmsg == NULL) return NULL; - NSS_CMSMessage_SetEncodingParams(cmsg, pwfn, pwfn_arg, decrypt_key_cb, decrypt_key_cb_arg, - NULL, NULL); + NSS_CMSMessage_SetEncodingParams(cmsg, pwfn, pwfn_arg, decrypt_key_cb, + decrypt_key_cb_arg, NULL, NULL); - p7dcx = (NSSCMSDecoderContext*)PORT_ZAlloc(sizeof(NSSCMSDecoderContext)); + p7dcx = PORT_ZNew(NSSCMSDecoderContext); if (p7dcx == NULL) { NSS_CMSMessage_Destroy(cmsg); return NULL; @@ -644,10 +658,14 @@ NSS_CMSDecoder_Start(PRArenaPool *poolp, * NSS_CMSDecoder_Update - feed DER-encoded data to decoder */ SECStatus -NSS_CMSDecoder_Update(NSSCMSDecoderContext *p7dcx, const char *buf, unsigned long len) +NSS_CMSDecoder_Update(NSSCMSDecoderContext *p7dcx, const char *buf, + unsigned long len) { - if (p7dcx->dcx != NULL && p7dcx->error == 0) { /* if error is set already, don't bother */ - if (SEC_ASN1DecoderUpdate (p7dcx->dcx, buf, len) != SECSuccess) { + SECStatus rv; + if (p7dcx->dcx != NULL && p7dcx->error == 0) { + /* if error is set already, don't bother */ + rv = SEC_ASN1DecoderUpdate(p7dcx->dcx, buf, len); + if (rv != SECSuccess) { p7dcx->error = PORT_GetError(); PORT_Assert (p7dcx->error); if (p7dcx->error == 0) @@ -691,10 +709,11 @@ NSS_CMSDecoder_Finish(NSSCMSDecoderContext *p7dcx) cmsg = p7dcx->cmsg; - if (p7dcx->dcx == NULL || SEC_ASN1DecoderFinish(p7dcx->dcx) != SECSuccess || + if (p7dcx->dcx == NULL || + SEC_ASN1DecoderFinish(p7dcx->dcx) != SECSuccess || nss_cms_after_end(p7dcx) != SECSuccess) { - NSS_CMSMessage_Destroy(cmsg); /* needs to get rid of pool if it's ours */ + NSS_CMSMessage_Destroy(cmsg); /* get rid of pool if it's ours */ cmsg = NULL; } @@ -706,13 +725,15 @@ NSSCMSMessage * NSS_CMSMessage_CreateFromDER(SECItem *DERmessage, NSSCMSContentCallback cb, void *cb_arg, PK11PasswordFunc pwfn, void *pwfn_arg, - NSSCMSGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg) + NSSCMSGetDecryptKeyCallback decrypt_key_cb, + void *decrypt_key_cb_arg) { NSSCMSDecoderContext *p7dcx; /* first arg(poolp) == NULL => create our own pool */ - p7dcx = NSS_CMSDecoder_Start(NULL, cb, cb_arg, pwfn, pwfn_arg, decrypt_key_cb, decrypt_key_cb_arg); - (void) NSS_CMSDecoder_Update(p7dcx, (char *)DERmessage->data, DERmessage->len); + p7dcx = NSS_CMSDecoder_Start(NULL, cb, cb_arg, pwfn, pwfn_arg, + decrypt_key_cb, decrypt_key_cb_arg); + NSS_CMSDecoder_Update(p7dcx, (char *)DERmessage->data, DERmessage->len); return NSS_CMSDecoder_Finish(p7dcx); } diff --git a/security/nss/lib/smime/cmsdigdata.c b/security/nss/lib/smime/cmsdigdata.c index 9d57a5266..23337446f 100644 --- a/security/nss/lib/smime/cmsdigdata.c +++ b/security/nss/lib/smime/cmsdigdata.c @@ -151,15 +151,17 @@ NSS_CMSDigestedData_Encode_BeforeData(NSSCMSDigestedData *digd) SECStatus NSS_CMSDigestedData_Encode_AfterData(NSSCMSDigestedData *digd) { + SECStatus rv = SECSuccess; /* did we have digest calculation going on? */ if (digd->contentInfo.digcx) { - if (NSS_CMSDigestContext_FinishSingle(digd->contentInfo.digcx, - digd->cmsg->poolp, &(digd->digest)) != SECSuccess) - return SECFailure; /* error has been set by NSS_CMSDigestContext_FinishSingle */ + rv = NSS_CMSDigestContext_FinishSingle(digd->contentInfo.digcx, + digd->cmsg->poolp, + &(digd->digest)); + /* error has been set by NSS_CMSDigestContext_FinishSingle */ digd->contentInfo.digcx = NULL; } - return SECSuccess; + return rv; } /* @@ -193,15 +195,17 @@ NSS_CMSDigestedData_Decode_BeforeData(NSSCMSDigestedData *digd) SECStatus NSS_CMSDigestedData_Decode_AfterData(NSSCMSDigestedData *digd) { + SECStatus rv = SECSuccess; /* did we have digest calculation going on? */ if (digd->contentInfo.digcx) { - if (NSS_CMSDigestContext_FinishSingle(digd->contentInfo.digcx, - digd->cmsg->poolp, &(digd->cdigest)) != SECSuccess) - return SECFailure; /* error has been set by NSS_CMSDigestContext_FinishSingle */ + rv = NSS_CMSDigestContext_FinishSingle(digd->contentInfo.digcx, + digd->cmsg->poolp, + &(digd->cdigest)); + /* error has been set by NSS_CMSDigestContext_FinishSingle */ digd->contentInfo.digcx = NULL; } - return SECSuccess; + return rv; } /* diff --git a/security/nss/lib/smime/cmsdigest.c b/security/nss/lib/smime/cmsdigest.c index 6c7bd918b..6acc5127e 100644 --- a/security/nss/lib/smime/cmsdigest.c +++ b/security/nss/lib/smime/cmsdigest.c @@ -47,14 +47,26 @@ #include "prtime.h" #include "secerr.h" +/* #define CMS_FIND_LEAK_MULTIPLE 1 */ +#ifdef CMS_FIND_LEAK_MULTIPLE +static int stop_on_err = 1; +static int global_num_digests = 0; +#endif + +struct digestPairStr { + const SECHashObject * digobj; + void * digcx; +}; +typedef struct digestPairStr digestPair; struct NSSCMSDigestContextStr { PRBool saw_contents; + PLArenaPool * pool; int digcnt; - void ** digcxs; -const SECHashObject ** digobjs; + digestPair * digPairs; }; + /* * NSS_CMSDigestContext_StartMultiple - start digest calculation using all the * digest algorithms in "digestalgs" in parallel. @@ -62,31 +74,43 @@ const SECHashObject ** digobjs; NSSCMSDigestContext * NSS_CMSDigestContext_StartMultiple(SECAlgorithmID **digestalgs) { + PLArenaPool * pool; NSSCMSDigestContext *cmsdigcx; - const SECHashObject *digobj; - void *digcx; int digcnt; int i; - digcnt = (digestalgs == NULL) ? 0 : NSS_CMSArray_Count((void **)digestalgs); +#ifdef CMS_FIND_LEAK_MULTIPLE + PORT_Assert(global_num_digests == 0 || !stop_on_err); +#endif - cmsdigcx = (NSSCMSDigestContext *)PORT_Alloc(sizeof(NSSCMSDigestContext)); + digcnt = (digestalgs == NULL) ? 0 : NSS_CMSArray_Count((void **)digestalgs); + /* It's OK if digcnt is zero. We have to allow this for "certs only" + ** messages. + */ + pool = PORT_NewArena(2048); + if (!pool) + return NULL; + + cmsdigcx = PORT_ArenaNew(pool, NSSCMSDigestContext); if (cmsdigcx == NULL) - return NULL; + goto loser; - if (digcnt > 0) { - cmsdigcx->digcxs = (void **)PORT_Alloc(digcnt * sizeof (void *)); - cmsdigcx->digobjs = (const SECHashObject **)PORT_Alloc(digcnt * sizeof(SECHashObject *)); - if (cmsdigcx->digcxs == NULL || cmsdigcx->digobjs == NULL) - goto loser; - } + cmsdigcx->saw_contents = PR_FALSE; + cmsdigcx->pool = pool; + cmsdigcx->digcnt = digcnt; - cmsdigcx->digcnt = 0; + cmsdigcx->digPairs = PORT_ArenaZNewArray(pool, digestPair, digcnt); + if (cmsdigcx->digPairs == NULL) { + goto loser; + } /* * Create a digest object context for each algorithm. */ for (i = 0; i < digcnt; i++) { + const SECHashObject *digobj; + void *digcx; + digobj = NSS_CMSUtil_GetHashObjByAlgID(digestalgs[i]); /* * Skip any algorithm we do not even recognize; obviously, @@ -102,29 +126,26 @@ NSS_CMSDigestContext_StartMultiple(SECAlgorithmID **digestalgs) digcx = (*digobj->create)(); if (digcx != NULL) { (*digobj->begin) (digcx); - cmsdigcx->digobjs[cmsdigcx->digcnt] = digobj; - cmsdigcx->digcxs[cmsdigcx->digcnt] = digcx; - cmsdigcx->digcnt++; + cmsdigcx->digPairs[i].digobj = digobj; + cmsdigcx->digPairs[i].digcx = digcx; +#ifdef CMS_FIND_LEAK_MULTIPLE + global_num_digests++; +#endif } } - - cmsdigcx->saw_contents = PR_FALSE; - return cmsdigcx; loser: - if (cmsdigcx) { - if (cmsdigcx->digobjs) - PORT_Free(cmsdigcx->digobjs); - if (cmsdigcx->digcxs) - PORT_Free(cmsdigcx->digcxs); + /* no digest objects have been created, or need to be destroyed. */ + if (pool) { + PORT_FreeArena(pool, PR_FALSE); } return NULL; } /* - * NSS_CMSDigestContext_StartSingle - same as NSS_CMSDigestContext_StartMultiple, but - * only one algorithm. + * NSS_CMSDigestContext_StartSingle - same as + * NSS_CMSDigestContext_StartMultiple, but only one algorithm. */ NSSCMSDigestContext * NSS_CMSDigestContext_StartSingle(SECAlgorithmID *digestalg) @@ -139,14 +160,19 @@ NSS_CMSDigestContext_StartSingle(SECAlgorithmID *digestalg) * NSS_CMSDigestContext_Update - feed more data into the digest machine */ void -NSS_CMSDigestContext_Update(NSSCMSDigestContext *cmsdigcx, const unsigned char *data, int len) +NSS_CMSDigestContext_Update(NSSCMSDigestContext *cmsdigcx, + const unsigned char *data, int len) { int i; + digestPair *pair = cmsdigcx->digPairs; cmsdigcx->saw_contents = PR_TRUE; - for (i = 0; i < cmsdigcx->digcnt; i++) - (*cmsdigcx->digobjs[i]->update)(cmsdigcx->digcxs[i], data, len); + for (i = 0; i < cmsdigcx->digcnt; i++, pair++) { + if (pair->digcx) { + (*pair->digobj->update)(pair->digcx, data, len); + } + } } /* @@ -156,9 +182,20 @@ void NSS_CMSDigestContext_Cancel(NSSCMSDigestContext *cmsdigcx) { int i; - - for (i = 0; i < cmsdigcx->digcnt; i++) - (*cmsdigcx->digobjs[i]->destroy)(cmsdigcx->digcxs[i], PR_TRUE); + digestPair *pair = cmsdigcx->digPairs; + + for (i = 0; i < cmsdigcx->digcnt; i++, pair++) { + if (pair->digcx) { + (*pair->digobj->destroy)(pair->digcx, PR_TRUE); +#ifdef CMS_FIND_LEAK_MULTIPLE + --global_num_digests; +#endif + } + } +#ifdef CMS_FIND_LEAK_MULTIPLE + PORT_Assert(global_num_digests == 0 || !stop_on_err); +#endif + PORT_FreeArena(cmsdigcx->pool, PR_FALSE); } /* @@ -166,20 +203,18 @@ NSS_CMSDigestContext_Cancel(NSSCMSDigestContext *cmsdigcx) * into an array of SECItems (allocated on poolp) */ SECStatus -NSS_CMSDigestContext_FinishMultiple(NSSCMSDigestContext *cmsdigcx, PLArenaPool *poolp, - SECItem ***digestsp) +NSS_CMSDigestContext_FinishMultiple(NSSCMSDigestContext *cmsdigcx, + PLArenaPool *poolp, + SECItem ***digestsp) { - const SECHashObject *digobj; - void *digcx; - SECItem **digests, *digest; - int i; - void *mark; - SECStatus rv = SECFailure; + SECItem ** digests = NULL; + digestPair *pair; + void * mark; + int i; + SECStatus rv; - /* no contents? do not update digests */ + /* no contents? do not finish digests */ if (digestsp == NULL || !cmsdigcx->saw_contents) { - for (i = 0; i < cmsdigcx->digcnt; i++) - (*cmsdigcx->digobjs[i]->destroy)(cmsdigcx->digcxs[i], PR_TRUE); rv = SECSuccess; goto cleanup; } @@ -187,52 +222,53 @@ NSS_CMSDigestContext_FinishMultiple(NSSCMSDigestContext *cmsdigcx, PLArenaPool * mark = PORT_ArenaMark (poolp); /* allocate digest array & SECItems on arena */ - digests = (SECItem **)PORT_ArenaAlloc(poolp, (cmsdigcx->digcnt+1) * sizeof(SECItem *)); - digest = (SECItem *)PORT_ArenaZAlloc(poolp, cmsdigcx->digcnt * sizeof(SECItem)); - if (digests == NULL || digest == NULL) { - goto loser; - } + digests = PORT_ArenaNewArray( poolp, SECItem *, cmsdigcx->digcnt + 1); - for (i = 0; i < cmsdigcx->digcnt; i++, digest++) { - digcx = cmsdigcx->digcxs[i]; - digobj = cmsdigcx->digobjs[i]; - - digest->data = (unsigned char*)PORT_ArenaAlloc(poolp, digobj->length); - if (digest->data == NULL) - goto loser; - digest->len = digobj->length; - (* digobj->end)(digcx, digest->data, &(digest->len), digest->len); - digests[i] = digest; - (* digobj->destroy)(digcx, PR_TRUE); - } - digests[i] = NULL; - *digestsp = digests; + rv = ((digests == NULL) ? SECFailure : SECSuccess); + pair = cmsdigcx->digPairs; + for (i = 0; rv == SECSuccess && i < cmsdigcx->digcnt; i++, pair++) { + SECItem digest; + unsigned char hash[HASH_LENGTH_MAX]; - rv = SECSuccess; + if (!pair->digcx) { + digests[i] = NULL; + continue; + } -loser: - if (rv == SECSuccess) + digest.type = siBuffer; + digest.data = hash; + digest.len = pair->digobj->length; + (* pair->digobj->end)(pair->digcx, hash, &digest.len, digest.len); + digests[i] = SECITEM_ArenaDupItem(poolp, &digest); + if (!digests[i]) { + rv = SECFailure; + } + } + digests[i] = NULL; + if (rv == SECSuccess) { PORT_ArenaUnmark(poolp, mark); - else + } else PORT_ArenaRelease(poolp, mark); cleanup: - if (cmsdigcx->digcnt > 0) { - PORT_Free(cmsdigcx->digcxs); - PORT_Free(cmsdigcx->digobjs); + NSS_CMSDigestContext_Cancel(cmsdigcx); + /* Don't change the caller's digests pointer if we have no digests. + ** NSS_CMSSignedData_Encode_AfterData depends on this behavior. + */ + if (rv == SECSuccess && digestsp && digests) { + *digestsp = digests; } - PORT_Free(cmsdigcx); - return rv; } /* - * NSS_CMSDigestContext_FinishSingle - same as NSS_CMSDigestContext_FinishMultiple, - * but for one digest. + * NSS_CMSDigestContext_FinishSingle - same as + * NSS_CMSDigestContext_FinishMultiple, but for one digest. */ SECStatus -NSS_CMSDigestContext_FinishSingle(NSSCMSDigestContext *cmsdigcx, PLArenaPool *poolp, - SECItem *digest) +NSS_CMSDigestContext_FinishSingle(NSSCMSDigestContext *cmsdigcx, + PLArenaPool *poolp, + SECItem *digest) { SECStatus rv = SECFailure; SECItem **dp; @@ -242,15 +278,11 @@ NSS_CMSDigestContext_FinishSingle(NSSCMSDigestContext *cmsdigcx, PLArenaPool *po goto loser; /* get the digests into arena, then copy the first digest into poolp */ - if (NSS_CMSDigestContext_FinishMultiple(cmsdigcx, arena, &dp) != SECSuccess) - goto loser; - - /* now copy it into poolp */ - if (SECITEM_CopyItem(poolp, digest, dp[0]) != SECSuccess) - goto loser; - - rv = SECSuccess; - + rv = NSS_CMSDigestContext_FinishMultiple(cmsdigcx, arena, &dp); + if (rv == SECSuccess) { + /* now copy it into poolp */ + rv = SECITEM_CopyItem(poolp, digest, dp[0]); + } loser: if (arena) PORT_FreeArena(arena, PR_FALSE); diff --git a/security/nss/lib/smime/cmsenvdata.c b/security/nss/lib/smime/cmsenvdata.c index 111ada533..de1420fbf 100644 --- a/security/nss/lib/smime/cmsenvdata.c +++ b/security/nss/lib/smime/cmsenvdata.c @@ -360,7 +360,11 @@ NSS_CMSEnvelopedData_Decode_BeforeData(NSSCMSEnvelopedData *envd) cinfo = &(envd->contentInfo); bulkalgtag = NSS_CMSContentInfo_GetContentEncAlgTag(cinfo); - bulkkey = NSS_CMSRecipientInfo_UnwrapBulkKey(ri,recipient->subIndex, + if (bulkalgtag == SEC_OID_UNKNOWN) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + } else + bulkkey = + NSS_CMSRecipientInfo_UnwrapBulkKey(ri,recipient->subIndex, recipient->cert, recipient->privkey, bulkalgtag); @@ -404,7 +408,7 @@ loser: SECStatus NSS_CMSEnvelopedData_Decode_AfterData(NSSCMSEnvelopedData *envd) { - if (envd->contentInfo.ciphcx) { + if (envd && envd->contentInfo.ciphcx) { NSS_CMSCipherContext_Destroy(envd->contentInfo.ciphcx); envd->contentInfo.ciphcx = NULL; } diff --git a/security/nss/lib/smime/cmsmessage.c b/security/nss/lib/smime/cmsmessage.c index 7e785cc1f..c9b076af2 100644 --- a/security/nss/lib/smime/cmsmessage.c +++ b/security/nss/lib/smime/cmsmessage.c @@ -178,7 +178,9 @@ SECItem * NSS_CMSMessage_GetContent(NSSCMSMessage *cmsg) { /* this is a shortcut */ - return NSS_CMSContentInfo_GetInnerContent(NSS_CMSMessage_GetContentInfo(cmsg)); + NSSCMSContentInfo * cinfo = NSS_CMSMessage_GetContentInfo(cmsg); + SECItem * pItem = NSS_CMSContentInfo_GetInnerContent(cinfo); + return pItem; } /* diff --git a/security/nss/lib/smime/cmspubkey.c b/security/nss/lib/smime/cmspubkey.c index 1cf0336e4..10eee8155 100644 --- a/security/nss/lib/smime/cmspubkey.c +++ b/security/nss/lib/smime/cmspubkey.c @@ -128,7 +128,14 @@ PK11SymKey * NSS_CMSUtil_DecryptSymKey_RSA(SECKEYPrivateKey *privkey, SECItem *encKey, SECOidTag bulkalgtag) { /* that's easy */ - return PK11_PubUnwrapSymKey(privkey, encKey, PK11_AlgtagToMechanism(bulkalgtag), CKA_DECRYPT, 0); + CK_MECHANISM_TYPE target; + PORT_Assert(bulkalgtag != SEC_OID_UNKNOWN); + target = PK11_AlgtagToMechanism(bulkalgtag); + if (bulkalgtag == SEC_OID_UNKNOWN || target == CKM_INVALID_MECHANISM) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + return NULL; + } + return PK11_PubUnwrapSymKey(privkey, encKey, target, CKA_DECRYPT, 0); } /* ====== MISSI (Fortezza) ========================================================== */ diff --git a/security/nss/lib/smime/cmssigdata.c b/security/nss/lib/smime/cmssigdata.c index 98a8fcbc5..573663b9c 100644 --- a/security/nss/lib/smime/cmssigdata.c +++ b/security/nss/lib/smime/cmssigdata.c @@ -54,6 +54,11 @@ NSS_CMSSignedData_Create(NSSCMSMessage *cmsg) NSSCMSSignedData *sigd; PLArenaPool *poolp; + if (!cmsg) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } + poolp = cmsg->poolp; mark = PORT_ArenaMark(poolp); @@ -132,6 +137,11 @@ NSS_CMSSignedData_Encode_BeforeStart(NSSCMSSignedData *sigd) int n, i; PLArenaPool *poolp; + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + poolp = sigd->cmsg->poolp; /* we assume that we have precomputed digests if there is a list of algorithms, and */ @@ -198,9 +208,16 @@ loser: SECStatus NSS_CMSSignedData_Encode_BeforeData(NSSCMSSignedData *sigd) { + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } /* set up the digests */ - if (sigd->digestAlgorithms != NULL) { - sigd->contentInfo.digcx = NSS_CMSDigestContext_StartMultiple(sigd->digestAlgorithms); + if (sigd->digests && sigd->digests[0]) { + sigd->contentInfo.digcx = NULL; /* don't attempt to make new ones. */ + } else if (sigd->digestAlgorithms != NULL) { + sigd->contentInfo.digcx = + NSS_CMSDigestContext_StartMultiple(sigd->digestAlgorithms); if (sigd->contentInfo.digcx == NULL) return SECFailure; } @@ -232,15 +249,22 @@ NSS_CMSSignedData_Encode_AfterData(NSSCMSSignedData *sigd) CERTCertificateList *certlist; extern const SEC_ASN1Template NSSCMSSignerInfoTemplate[]; + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + poolp = sigd->cmsg->poolp; cinfo = &(sigd->contentInfo); /* did we have digest calculation going on? */ if (cinfo->digcx) { - rv = NSS_CMSDigestContext_FinishMultiple(cinfo->digcx, poolp, &(sigd->digests)); - if (rv != SECSuccess) - goto loser; /* error has been set by NSS_CMSDigestContext_FinishMultiple */ + rv = NSS_CMSDigestContext_FinishMultiple(cinfo->digcx, poolp, + &(sigd->digests)); + /* error has been set by NSS_CMSDigestContext_FinishMultiple */ cinfo->digcx = NULL; + if (rv != SECSuccess) + goto loser; } signerinfos = sigd->signerInfos; @@ -359,6 +383,10 @@ loser: SECStatus NSS_CMSSignedData_Decode_BeforeData(NSSCMSSignedData *sigd) { + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } /* set up the digests */ if (sigd->digestAlgorithms != NULL && sigd->digests == NULL) { /* if digests are already there, do nothing */ @@ -370,19 +398,27 @@ NSS_CMSSignedData_Decode_BeforeData(NSSCMSSignedData *sigd) } /* - * NSS_CMSSignedData_Decode_AfterData - do all the necessary things to a SignedData - * after all the encapsulated data was passed through the decoder. + * NSS_CMSSignedData_Decode_AfterData - do all the necessary things to a + * SignedData after all the encapsulated data was passed through the decoder. */ SECStatus NSS_CMSSignedData_Decode_AfterData(NSSCMSSignedData *sigd) { + SECStatus rv = SECSuccess; + + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + /* did we have digest calculation going on? */ if (sigd->contentInfo.digcx) { - if (NSS_CMSDigestContext_FinishMultiple(sigd->contentInfo.digcx, sigd->cmsg->poolp, &(sigd->digests)) != SECSuccess) - return SECFailure; /* error has been set by NSS_CMSDigestContext_FinishMultiple */ + rv = NSS_CMSDigestContext_FinishMultiple(sigd->contentInfo.digcx, + sigd->cmsg->poolp, &(sigd->digests)); + /* error set by NSS_CMSDigestContext_FinishMultiple */ sigd->contentInfo.digcx = NULL; } - return SECSuccess; + return rv; } /* @@ -392,9 +428,14 @@ NSS_CMSSignedData_Decode_AfterData(NSSCMSSignedData *sigd) SECStatus NSS_CMSSignedData_Decode_AfterEnd(NSSCMSSignedData *sigd) { - NSSCMSSignerInfo **signerinfos; + NSSCMSSignerInfo **signerinfos = NULL; int i; + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + /* set cmsg for all the signerinfos */ signerinfos = sigd->signerInfos; @@ -413,18 +454,30 @@ NSS_CMSSignedData_Decode_AfterEnd(NSSCMSSignedData *sigd) NSSCMSSignerInfo ** NSS_CMSSignedData_GetSignerInfos(NSSCMSSignedData *sigd) { + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } return sigd->signerInfos; } int NSS_CMSSignedData_SignerInfoCount(NSSCMSSignedData *sigd) { + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return 0; + } return NSS_CMSArray_Count((void **)sigd->signerInfos); } NSSCMSSignerInfo * NSS_CMSSignedData_GetSignerInfo(NSSCMSSignedData *sigd, int i) { + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } return sigd->signerInfos[i]; } @@ -434,6 +487,10 @@ NSS_CMSSignedData_GetSignerInfo(NSSCMSSignedData *sigd, int i) SECAlgorithmID ** NSS_CMSSignedData_GetDigestAlgs(NSSCMSSignedData *sigd) { + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } return sigd->digestAlgorithms; } @@ -443,6 +500,10 @@ NSS_CMSSignedData_GetDigestAlgs(NSSCMSSignedData *sigd) NSSCMSContentInfo * NSS_CMSSignedData_GetContentInfo(NSSCMSSignedData *sigd) { + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } return &(sigd->contentInfo); } @@ -452,6 +513,10 @@ NSS_CMSSignedData_GetContentInfo(NSSCMSSignedData *sigd) SECItem ** NSS_CMSSignedData_GetCertificateList(NSSCMSSignedData *sigd) { + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } return sigd->rawCerts; } @@ -468,6 +533,11 @@ NSS_CMSSignedData_ImportCerts(NSSCMSSignedData *sigd, CERTCertDBHandle *certdb, int i; PRTime now; + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + certcount = NSS_CMSArray_Count((void **)sigd->rawCerts); /* get the certs in the temp DB */ @@ -584,22 +654,34 @@ NSS_CMSSignedData_VerifySignerInfo(NSSCMSSignedData *sigd, int i, NSSCMSContentInfo *cinfo; SECOidData *algiddata; SECItem *contentType, *digest; + SECOidTag oidTag; + SECStatus rv; + + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } cinfo = &(sigd->contentInfo); signerinfo = sigd->signerInfos[i]; /* verify certificate */ - if (NSS_CMSSignerInfo_VerifyCertificate(signerinfo, certdb, certusage) != SECSuccess) - return SECFailure; /* error is set by NSS_CMSSignerInfo_VerifyCertificate */ + rv = NSS_CMSSignerInfo_VerifyCertificate(signerinfo, certdb, certusage); + if (rv != SECSuccess) + return rv; /* error is set */ /* find digest and contentType for signerinfo */ algiddata = NSS_CMSSignerInfo_GetDigestAlg(signerinfo); - digest = NSS_CMSSignedData_GetDigestByAlgTag(sigd, algiddata->offset); + oidTag = algiddata ? algiddata->offset : SEC_OID_UNKNOWN; + digest = NSS_CMSSignedData_GetDigestValue(sigd, oidTag); + /* NULL digest is acceptable. */ contentType = NSS_CMSContentInfo_GetContentTypeOID(cinfo); + /* NULL contentType is acceptable. */ /* now verify signature */ - return NSS_CMSSignerInfo_Verify(signerinfo, digest, contentType); + rv = NSS_CMSSignerInfo_Verify(signerinfo, digest, contentType); + return rv; } /* @@ -647,6 +729,10 @@ NSS_CMSSignedData_VerifyCertsOnly(NSSCMSSignedData *sigd, PRBool NSS_CMSSignedData_HasDigests(NSSCMSSignedData *sigd) { + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return PR_FALSE; + } return (sigd->digests != NULL); } @@ -655,10 +741,10 @@ NSS_CMSSignedData_AddCertList(NSSCMSSignedData *sigd, CERTCertificateList *certl { SECStatus rv; - PORT_Assert(certlist != NULL); - - if (certlist == NULL) - return SECFailure; + if (!sigd || !certlist) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } /* XXX memory?? a certlist has an arena of its own and is not refcounted!?!? */ rv = NSS_CMSArray_Add(sigd->cmsg->poolp, (void ***)&(sigd->certLists), (void *)certlist); @@ -678,6 +764,11 @@ NSS_CMSSignedData_AddCertChain(NSSCMSSignedData *sigd, CERTCertificate *cert) usage = certUsageEmailSigner; + if (!sigd || !cert) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + /* do not include root */ certlist = CERT_CertChainFromCert(cert, usage, PR_FALSE); if (certlist == NULL) @@ -694,10 +785,10 @@ NSS_CMSSignedData_AddCertificate(NSSCMSSignedData *sigd, CERTCertificate *cert) CERTCertificate *c; SECStatus rv; - PORT_Assert(cert != NULL); - - if (cert == NULL) - return SECFailure; + if (!sigd || !cert) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } c = CERT_DupCertificate(cert); rv = NSS_CMSArray_Add(sigd->cmsg->poolp, (void ***)&(sigd->certs), (void *)c); @@ -707,6 +798,10 @@ NSS_CMSSignedData_AddCertificate(NSSCMSSignedData *sigd, CERTCertificate *cert) PRBool NSS_CMSSignedData_ContainsCertsOrCrls(NSSCMSSignedData *sigd) { + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return PR_FALSE; + } if (sigd->rawCerts != NULL && sigd->rawCerts[0] != NULL) return PR_TRUE; else if (sigd->crls != NULL && sigd->crls[0] != NULL) @@ -724,6 +819,11 @@ NSS_CMSSignedData_AddSignerInfo(NSSCMSSignedData *sigd, SECOidTag digestalgtag; PLArenaPool *poolp; + if (!sigd || !signerinfo) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + poolp = sigd->cmsg->poolp; mark = PORT_ArenaMark(poolp); @@ -756,15 +856,6 @@ loser: return SECFailure; } -SECItem * -NSS_CMSSignedData_GetDigestByAlgTag(NSSCMSSignedData *sigd, SECOidTag algtag) -{ - int idx; - - idx = NSS_CMSAlgArray_GetIndexByAlgTag(sigd->digestAlgorithms, algtag); - return sigd->digests[idx]; -} - /* * NSS_CMSSignedData_SetDigests - set a signedData's digests member * @@ -778,6 +869,11 @@ NSS_CMSSignedData_SetDigests(NSSCMSSignedData *sigd, { int cnt, i, idx; + if (!sigd || !digestalgs || !digests) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (sigd->digestAlgorithms == NULL) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; @@ -805,6 +901,13 @@ NSS_CMSSignedData_SetDigests(NSSCMSSignedData *sigd, PORT_SetError(SEC_ERROR_DIGEST_NOT_FOUND); return SECFailure; } + if (!digests[idx]) { + /* We have no digest for this algorithm, probably because it is + ** unrecognized or unsupported. We'll ignore this here. If this + ** digest is needed later, an error will be be generated then. + */ + continue; + } /* found it - now set it */ if ((sigd->digests[i] = SECITEM_AllocItem(sigd->cmsg->poolp, NULL, 0)) == NULL || @@ -827,6 +930,11 @@ NSS_CMSSignedData_SetDigestValue(NSSCMSSignedData *sigd, void *mark; int n, cnt; + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + poolp = sigd->cmsg->poolp; mark = PORT_ArenaMark(poolp); @@ -880,6 +988,11 @@ NSS_CMSSignedData_AddDigest(PRArenaPool *poolp, SECAlgorithmID *digestalg; void *mark; + if (!sigd || !poolp) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + mark = PORT_ArenaMark(poolp); digestalg = PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID)); @@ -904,13 +1017,21 @@ loser: return SECFailure; } +/* XXX This function doesn't set the error code on failure. */ SECItem * NSS_CMSSignedData_GetDigestValue(NSSCMSSignedData *sigd, SECOidTag digestalgtag) { int n; - if (sigd->digestAlgorithms == NULL) + if (!sigd) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } + + if (sigd->digestAlgorithms == NULL || sigd->digests == NULL) { + PORT_SetError(SEC_ERROR_DIGEST_NOT_FOUND); return NULL; + } n = NSS_CMSAlgArray_GetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag); @@ -941,6 +1062,11 @@ NSS_CMSSignedData_CreateCertsOnly(NSSCMSMessage *cmsg, CERTCertificate *cert, PR PLArenaPool *poolp; SECStatus rv; + if (!cmsg || !cert) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } + poolp = cmsg->poolp; mark = PORT_ArenaMark(poolp); diff --git a/security/nss/lib/smime/cmssiginfo.c b/security/nss/lib/smime/cmssiginfo.c index 89b942222..bcd6839d7 100644 --- a/security/nss/lib/smime/cmssiginfo.c +++ b/security/nss/lib/smime/cmssiginfo.c @@ -309,7 +309,7 @@ NSS_CMSSignerInfo_VerifyCertificate(NSSCMSSignerInfo *signerinfo, CERTCertDBHand * email profile. */ if (NSS_CMSSignerInfo_GetSigningTime (signerinfo, &stime) != SECSuccess) - stime = PR_Now(); /* not found or conversion failed, so check against now */ + stime = PR_Now(); /* not found or conversion failed, so check against now */ /* * XXX This uses the signing time, if available. Additionally, we @@ -319,7 +319,8 @@ NSS_CMSSignerInfo_VerifyCertificate(NSSCMSSignerInfo *signerinfo, CERTCertDBHand * in a time (and for non-S/MIME callers to pass in nothing, or * maybe make them pass in the current time, always?). */ - if (CERT_VerifyCert(certdb, cert, PR_TRUE, certusage, stime, signerinfo->cmsg->pwfn_arg, NULL) != SECSuccess) { + if (CERT_VerifyCert(certdb, cert, PR_TRUE, certusage, stime, + signerinfo->cmsg->pwfn_arg, NULL) != SECSuccess) { signerinfo->verificationStatus = NSSCMSVS_SigningCertNotTrusted; return SECFailure; } @@ -329,11 +330,13 @@ NSS_CMSSignerInfo_VerifyCertificate(NSSCMSSignerInfo *signerinfo, CERTCertDBHand /* * NSS_CMSSignerInfo_Verify - verify the signature of a single SignerInfo * - * Just verifies the signature. The assumption is that verification of the certificate - * is done already. + * Just verifies the signature. The assumption is that verification of + * the certificate is done already. */ SECStatus -NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo, SECItem *digest, SECItem *contentType) +NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo, + SECItem *digest, /* may be NULL */ + SECItem *contentType) /* may be NULL */ { SECKEYPublicKey *publickey = NULL; NSSCMSAttribute *attr; @@ -345,9 +348,11 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo, SECItem *digest, SECItem if (signerinfo == NULL) return SECFailure; - /* NSS_CMSSignerInfo_GetSigningCertificate will fail if 2nd parm is NULL and */ - /* cert has not been verified */ - if ((cert = NSS_CMSSignerInfo_GetSigningCertificate(signerinfo, NULL)) == NULL) { + /* NSS_CMSSignerInfo_GetSigningCertificate will fail if 2nd parm is NULL + ** and cert has not been verified + */ + cert = NSS_CMSSignerInfo_GetSigningCertificate(signerinfo, NULL); + if (cert == NULL) { vs = NSSCMSVS_SigningCertNotFound; goto loser; } @@ -390,9 +395,9 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo, SECItem *digest, SECItem * be one for message digest which matches our message digest. * So check these things first. */ - if ((attr = NSS_CMSAttributeArray_FindAttrByOidTag(signerinfo->authAttr, - SEC_OID_PKCS9_CONTENT_TYPE, PR_TRUE)) == NULL) - { + attr = NSS_CMSAttributeArray_FindAttrByOidTag(signerinfo->authAttr, + SEC_OID_PKCS9_CONTENT_TYPE, PR_TRUE); + if (attr == NULL) { vs = NSSCMSVS_MalformedSignature; goto loser; } @@ -406,12 +411,14 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo, SECItem *digest, SECItem /* * Check digest */ - if ((attr = NSS_CMSAttributeArray_FindAttrByOidTag(signerinfo->authAttr, SEC_OID_PKCS9_MESSAGE_DIGEST, PR_TRUE)) == NULL) - { + attr = NSS_CMSAttributeArray_FindAttrByOidTag(signerinfo->authAttr, + SEC_OID_PKCS9_MESSAGE_DIGEST, PR_TRUE); + if (attr == NULL) { vs = NSSCMSVS_MalformedSignature; goto loser; } - if (NSS_CMSAttribute_CompareValue(attr, digest) == PR_FALSE) { + if (!digest || + NSS_CMSAttribute_CompareValue(attr, digest) == PR_FALSE) { vs = NSSCMSVS_DigestMismatch; goto loser; } @@ -426,14 +433,15 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo, SECItem *digest, SECItem * * The signature is based on a digest of the DER-encoded authenticated * attributes. So, first we encode and then we digest/verify. - * we trust the decoder to have the attributes in the right (sorted) order + * we trust the decoder to have the attributes in the right (sorted) + * order */ encoded_attrs.data = NULL; encoded_attrs.len = 0; - if (NSS_CMSAttributeArray_Encode(poolp, &(signerinfo->authAttr), &encoded_attrs) == NULL || - encoded_attrs.data == NULL || encoded_attrs.len == 0) - { + if (NSS_CMSAttributeArray_Encode(poolp, &(signerinfo->authAttr), + &encoded_attrs) == NULL || + encoded_attrs.data == NULL || encoded_attrs.len == 0) { vs = NSSCMSVS_ProcessingError; goto loser; } @@ -441,21 +449,26 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo, SECItem *digest, SECItem vs = (VFY_VerifyData (encoded_attrs.data, encoded_attrs.len, publickey, &(signerinfo->encDigest), SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)), - signerinfo->cmsg->pwfn_arg) != SECSuccess) ? NSSCMSVS_BadSignature : NSSCMSVS_GoodSignature; + signerinfo->cmsg->pwfn_arg) != SECSuccess) + ? NSSCMSVS_BadSignature : NSSCMSVS_GoodSignature; - PORT_FreeArena(poolp, PR_FALSE); /* awkward memory management :-( */ + PORT_FreeArena(poolp, PR_FALSE); /* awkward memory management :-( */ } else { SECItem *sig; - /* No authenticated attributes. The signature is based on the plain message digest. */ + /* No authenticated attributes. + ** The signature is based on the plain message digest. + */ sig = &(signerinfo->encDigest); if (sig->len == 0) goto loser; - vs = (VFY_VerifyDigest(digest, publickey, sig, + vs = (!digest || + VFY_VerifyDigest(digest, publickey, sig, SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)), - signerinfo->cmsg->pwfn_arg) != SECSuccess) ? NSSCMSVS_BadSignature : NSSCMSVS_GoodSignature; + signerinfo->cmsg->pwfn_arg) != SECSuccess) + ? NSSCMSVS_BadSignature : NSSCMSVS_GoodSignature; } if (vs == NSSCMSVS_BadSignature) { @@ -513,6 +526,11 @@ NSS_CMSSignerInfo_GetDigestAlgTag(NSSCMSSignerInfo *signerinfo) { SECOidData *algdata; + if (!signerinfo) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SEC_OID_UNKNOWN; + } + algdata = SECOID_FindOID (&(signerinfo->digestAlg.algorithm)); if (algdata != NULL) return algdata->offset; @@ -566,7 +584,7 @@ NSS_CMSSignerInfo_GetSigningTime(NSSCMSSignerInfo *sinfo, PRTime *stime) /* XXXX multi-valued attributes NIH */ if (attr == NULL || (value = NSS_CMSAttribute_GetValue(attr)) == NULL) return SECFailure; - if (CERT_DecodeTimeChoice(stime, value) != SECSuccess) + if (DER_DecodeTimeChoice(stime, value) != SECSuccess) return SECFailure; sinfo->signingTime = *stime; /* make cached copy */ return SECSuccess; @@ -620,7 +638,7 @@ NSS_CMSSignerInfo_GetSigningCertificate(NSSCMSSignerInfo *signerinfo, CERTCertDB * * sinfo - signerInfo data for this signer * - * Returns a pointer to allocated memory, which must be freed. + * Returns a pointer to allocated memory, which must be freed with PORT_Free. * A return value of NULL is an error. */ char * @@ -703,7 +721,7 @@ NSS_CMSSignerInfo_AddSigningTime(NSSCMSSignerInfo *signerinfo, PRTime t) mark = PORT_ArenaMark(poolp); /* create new signing time attribute */ - if (CERT_EncodeTimeChoice(NULL, &stime, t) != SECSuccess) + if (DER_EncodeTimeChoice(NULL, &stime, t) != SECSuccess) goto loser; if ((attr = NSS_CMSAttribute_Create(poolp, SEC_OID_PKCS9_SIGNING_TIME, &stime, PR_FALSE)) == NULL) { diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c index 92ea37d25..f02c3de80 100644 --- a/security/nss/lib/softoken/keydb.c +++ b/security/nss/lib/softoken/keydb.c @@ -52,6 +52,7 @@ #include "lowpbe.h" #include "secerr.h" #include "cdbhdl.h" +#include "nsslocks.h" #include "keydbi.h" @@ -163,6 +164,36 @@ free_dbt(DBT *dbt) return; } +static int keydb_Get(DB *db, DBT *key, DBT *data, unsigned int flags); +static int keydb_Put(DB *db, DBT *key, DBT *data, unsigned int flags); +static int keydb_Sync(DB *db, unsigned int flags); +static int keydb_Del(DB *db, DBT *key, unsigned int flags); +static int keydb_Seq(DB *db, DBT *key, DBT *data, unsigned int flags); +static void keydb_Close(DB *db); + +static PZLock *kdbLock = NULL; + +static void +keydb_InitLocks(NSSLOWKEYDBHandle *handle) +{ + if (kdbLock == NULL) { + nss_InitLock(&kdbLock, nssILockKeyDB); + } + + return; +} + +static void +keydb_DestroyLocks(NSSLOWKEYDBHandle *handle) +{ + if (kdbLock != NULL) { + PZ_DestroyLock(kdbLock); + kdbLock = NULL; + } + + return; +} + /* * format of key database entries for version 3 of database: * byte offset field @@ -320,7 +351,7 @@ get_dbkey(NSSLOWKEYDBHandle *handle, DBT *index) int ret; /* get it from the database */ - ret = (* handle->db->get)(handle->db, index, &entry, 0); + ret = keydb_Get(handle->db, index, &entry, 0); if ( ret ) { PORT_SetError(SEC_ERROR_BAD_DATABASE); return NULL; @@ -346,10 +377,9 @@ put_dbkey(NSSLOWKEYDBHandle *handle, DBT *index, NSSLOWKEYDBKey *dbkey, PRBool u /* put it in the database */ if ( update ) { - status = (* handle->db->put)(handle->db, index, keydata, 0); + status = keydb_Put(handle->db, index, keydata, 0); } else { - status = (* handle->db->put)(handle->db, index, keydata, - R_NOOVERWRITE); + status = keydb_Put(handle->db, index, keydata, R_NOOVERWRITE); } if ( status ) { @@ -357,7 +387,7 @@ put_dbkey(NSSLOWKEYDBHandle *handle, DBT *index, NSSLOWKEYDBKey *dbkey, PRBool u } /* sync the database */ - status = (* handle->db->sync)(handle->db, 0); + status = keydb_Sync(handle->db, 0); if ( status ) { goto loser; } @@ -387,7 +417,7 @@ nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle, return(SECFailure); } - ret = (* handle->db->seq)(handle->db, &key, &data, R_FIRST); + ret = keydb_Seq(handle->db, &key, &data, R_FIRST); if ( ret ) { return(SECFailure); } @@ -414,7 +444,7 @@ nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle, return(status); } } - } while ( (* handle->db->seq)(handle->db, &key, &data, R_NEXT) == 0 ); + } while ( keydb_Seq(handle->db, &key, &data, R_NEXT) == 0 ); return(SECSuccess); } @@ -494,7 +524,7 @@ GetKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle) saltKey.data = SALT_STRING; saltKey.size = sizeof(SALT_STRING) - 1; - ret = (* handle->db->get)(handle->db, &saltKey, &saltData, 0); + ret = keydb_Get(handle->db, &saltKey, &saltData, 0); if ( ret ) { return(NULL); } @@ -516,7 +546,7 @@ StoreKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle) saltData.size = handle->global_salt->len; /* put global salt into the database now */ - status = (* handle->db->put)( handle->db, &saltKey, &saltData, 0); + status = keydb_Put(handle->db, &saltKey, &saltData, 0); if ( status ) { return(SECFailure); } @@ -539,7 +569,7 @@ makeGlobalVersion(NSSLOWKEYDBHandle *handle) versionKey.size = sizeof(VERSION_STRING)-1; /* put version string into the database now */ - status = (* handle->db->put)(handle->db, &versionKey, &versionData, 0); + status = keydb_Put(handle->db, &versionKey, &versionData, 0); if ( status ) { return(SECFailure); } @@ -565,7 +595,7 @@ makeGlobalSalt(NSSLOWKEYDBHandle *handle) RNG_GenerateGlobalRandomBytes(saltbuf, sizeof(saltbuf)); /* put global salt into the database now */ - status = (* handle->db->put)( handle->db, &saltKey, &saltData, 0); + status = keydb_Put(handle->db, &saltKey, &saltData, 0); if ( status ) { return(SECFailure); } @@ -605,7 +635,7 @@ nsslowkey_version(DB *db) versionKey.size = sizeof(VERSION_STRING)-1; /* lookup version string in database */ - ret = (* db->get)( db, &versionKey, &versionData, 0 ); + ret = keydb_Get( db, &versionKey, &versionData, 0 ); /* error accessing the database */ if ( ret < 0 ) { @@ -626,7 +656,7 @@ seckey_HasAServerKey(DB *db) int ret; PRBool found = PR_FALSE; - ret = (* db->seq)(db, &key, &data, R_FIRST); + ret = keydb_Seq(db, &key, &data, R_FIRST); if ( ret ) { return PR_FALSE; } @@ -663,7 +693,7 @@ seckey_HasAServerKey(DB *db) } } - } while ( (* db->seq)(db, &key, &data, R_NEXT) == 0 ); + } while ( keydb_Seq(db, &key, &data, R_NEXT) == 0 ); return found; } @@ -702,7 +732,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) saltKey.data = SALT_STRING; saltKey.size = sizeof(SALT_STRING) - 1; - ret = (* handle->updatedb->get)(handle->updatedb, &saltKey, &saltData, 0); + ret = keydb_Get(handle->updatedb, &saltKey, &saltData, 0); if ( ret ) { /* no salt in old db, so it is corrupted */ goto done; @@ -720,7 +750,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) checkKey.data = KEYDB_PW_CHECK_STRING; checkKey.size = KEYDB_PW_CHECK_LEN; - ret = (* handle->updatedb->get)(handle->updatedb, &checkKey, + ret = keydb_Get(handle->updatedb, &checkKey, &checkData, 0 ); if (ret) { /* @@ -741,11 +771,11 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) fcheckData.data = "1"; fcheckData.size = 1; /* put global salt into the new database now */ - ret = (* handle->db->put)( handle->db, &saltKey, &saltData, 0); + ret = keydb_Put( handle->db, &saltKey, &saltData, 0); if ( ret ) { goto done; } - ret = (* handle->db->put)( handle->db, &fcheckKey, &fcheckData, 0); + ret = keydb_Put( handle->db, &fcheckKey, &fcheckData, 0); if ( ret ) { goto done; } @@ -754,7 +784,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) } } else { /* put global salt into the new database now */ - ret = (* handle->db->put)( handle->db, &saltKey, &saltData, 0); + ret = keydb_Put( handle->db, &saltKey, &saltData, 0); if ( ret ) { goto done; } @@ -784,7 +814,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) /* now traverse the database */ - ret = (* handle->updatedb->seq)(handle->updatedb, &key, &data, R_FIRST); + ret = keydb_Seq(handle->updatedb, &key, &data, R_FIRST); if ( ret ) { goto done; } @@ -830,16 +860,16 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) sec_destroy_dbkey(dbkey); } - } while ( (* handle->updatedb->seq)(handle->updatedb, &key, &data, + } while ( keydb_Seq(handle->updatedb, &key, &data, R_NEXT) == 0 ); dbkey = NULL; done: /* sync the database */ - ret = (* handle->db->sync)(handle->db, 0); + ret = keydb_Sync(handle->db, 0); - (* handle->updatedb->close)(handle->updatedb); + keydb_Close(handle->updatedb); handle->updatedb = NULL; if ( rc4key ) { @@ -902,10 +932,10 @@ openNewDB(const char *appName, const char *prefix, const char *dbname, if (updatedb) { handle->version = nsslowkey_version(updatedb); if (handle->version != NSSLOWKEY_DB_FILE_VERSION) { - (updatedb->close)(updatedb); + keydb_Close(updatedb); } else { db_Copy(handle->db, updatedb); - (updatedb->close)(updatedb); + keydb_Close(updatedb); db_FinishTransaction(handle->db,PR_FALSE); db_InitComplete(handle->db); return SECSuccess; @@ -951,7 +981,7 @@ openNewDB(const char *appName, const char *prefix, const char *dbname, } /* sync the database */ - ret = (* handle->db->sync)(handle->db, 0); + ret = keydb_Sync(handle->db, 0); if ( ret ) { rv = SECFailure; goto loser; @@ -981,7 +1011,7 @@ openOldDB(const char *appName, const char *prefix, const char *dbname, *version = nsslowkey_version(db); if (*version != NSSLOWKEY_DB_FILE_VERSION ) { /* bogus version number record, reset the database */ - (* db->close)( db ); + keydb_Close( db ); db = NULL; } } @@ -1015,6 +1045,8 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix, (prefix ? PORT_Strdup(prefix) : NULL); handle->readOnly = readOnly; + keydb_InitLocks(handle); + handle->db = openOldDB(appName, prefix, dbname, openflags, &handle->version); @@ -1042,7 +1074,6 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix, } else if (rv != SECSuccess) { goto loser; } - } handle->global_salt = GetKeyDBGlobalSalt(handle); @@ -1057,10 +1088,10 @@ loser: PORT_SetError(SEC_ERROR_BAD_DATABASE); if ( handle->db ) { - (* handle->db->close)(handle->db); + keydb_Close(handle->db); } if ( handle->updatedb ) { - (* handle->updatedb->close)(handle->updatedb); + keydb_Close(handle->updatedb); } PORT_Free(handle); return NULL; @@ -1074,13 +1105,14 @@ nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle) { if (handle != NULL) { if (handle->db != NULL) { - (* handle->db->close)(handle->db); + keydb_Close(handle->db); } if (handle->dbname) PORT_Free(handle->dbname); if (handle->appname) PORT_Free(handle->appname); if (handle->global_salt) { SECITEM_FreeItem(handle->global_salt,PR_TRUE); } + keydb_DestroyLocks(handle); PORT_Free(handle); } @@ -1114,14 +1146,14 @@ nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle, SECItem *pubkey) namekey.size = pubkey->len; /* delete it from the database */ - ret = (* handle->db->del)(handle->db, &namekey, 0); + ret = keydb_Del(handle->db, &namekey, 0); if ( ret ) { PORT_SetError(SEC_ERROR_BAD_DATABASE); return(SECFailure); } /* sync the database */ - ret = (* handle->db->sync)(handle->db, 0); + ret = keydb_Sync(handle->db, 0); if ( ret ) { PORT_SetError(SEC_ERROR_BAD_DATABASE); return(SECFailure); @@ -1166,7 +1198,7 @@ nsslowkey_KeyForIDExists(NSSLOWKEYDBHandle *handle, SECItem *id) namekey.data = (char *)id->data; namekey.size = id->len; - status = (* handle->db->get)(handle->db, &namekey, &dummy, 0); + status = keydb_Get(handle->db, &namekey, &dummy, 0); if ( status ) { return PR_FALSE; } @@ -1224,7 +1256,7 @@ nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cer namekey.size = sizeof(buf); } - status = (* handle->db->get)(handle->db, &namekey, &dummy, 0); + status = keydb_Get(handle->db, &namekey, &dummy, 0); /* some databases have the key stored as a signed value */ if (status) { unsigned char *buf = (unsigned char *)PORT_Alloc(namekey.size+1); @@ -1233,7 +1265,7 @@ nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cer buf[0] = 0; namekey.data = buf; namekey.size ++; - status = (* handle->db->get)(handle->db, &namekey, &dummy, 0); + status = keydb_Get(handle->db, &namekey, &dummy, 0); PORT_Free(buf); } } @@ -1261,12 +1293,12 @@ nsslowkey_HasKeyDBPassword(NSSLOWKEYDBHandle *handle) checkkey.data = KEYDB_PW_CHECK_STRING; checkkey.size = KEYDB_PW_CHECK_LEN; - ret = (* handle->db->get)(handle->db, &checkkey, &checkdata, 0 ); + ret = keydb_Get(handle->db, &checkkey, &checkdata, 0 ); if ( ret ) { /* see if this was an updated DB first */ checkkey.data = KEYDB_FAKE_PW_CHECK_STRING; checkkey.size = KEYDB_FAKE_PW_CHECK_LEN; - ret = (* handle->db->get)(handle->db, &checkkey, &checkdata, 0 ); + ret = keydb_Get(handle->db, &checkkey, &checkdata, 0 ); if ( ret ) { return(SECFailure); } @@ -2381,8 +2413,7 @@ nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem) if ( dbkey == NULL ) { checkkey.data = KEYDB_FAKE_PW_CHECK_STRING; checkkey.size = KEYDB_FAKE_PW_CHECK_LEN; - ret = (* handle->db->get)(handle->db, &checkkey, - &checkdata, 0 ); + ret = keydb_Get(handle->db, &checkkey, &checkdata, 0 ); if (ret) { goto loser; } @@ -2527,7 +2558,7 @@ ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, } /* delete the old record */ - ret = (* handle->db->del)(handle->db, &node->key, 0); + ret = keydb_Del(handle->db, &node->key, 0); if ( ret ) { PORT_SetError(SEC_ERROR_BAD_DATABASE); rv = SECFailure; @@ -2644,7 +2675,7 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle) return SECFailure; } - (* handle->db->close)(handle->db); + keydb_Close(handle->db); if (handle->appname) { handle->db= rdbopen(handle->appname, handle->dbname, "key", NO_CREATE, NULL); @@ -2676,8 +2707,104 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle) done: /* sync the database */ - ret = (* handle->db->sync)(handle->db, 0); + ret = keydb_Sync(handle->db, 0); db_InitComplete(handle->db); return (errors == 0 ? SECSuccess : SECFailure); } + +static int +keydb_Get(DB *db, DBT *key, DBT *data, unsigned int flags) +{ + PRStatus prstat; + int ret; + + PORT_Assert(kdbLock != NULL); + PZ_Lock(kdbLock); + + ret = (* db->get)(db, key, data, flags); + + prstat = PZ_Unlock(kdbLock); + + return(ret); +} + +static int +keydb_Put(DB *db, DBT *key, DBT *data, unsigned int flags) +{ + PRStatus prstat; + int ret = 0; + + PORT_Assert(kdbLock != NULL); + PZ_Lock(kdbLock); + + ret = (* db->put)(db, key, data, flags); + + prstat = PZ_Unlock(kdbLock); + + return(ret); +} + +static int +keydb_Sync(DB *db, unsigned int flags) +{ + PRStatus prstat; + int ret; + + PORT_Assert(kdbLock != NULL); + PZ_Lock(kdbLock); + + ret = (* db->sync)(db, flags); + + prstat = PZ_Unlock(kdbLock); + + return(ret); +} + +static int +keydb_Del(DB *db, DBT *key, unsigned int flags) +{ + PRStatus prstat; + int ret; + + PORT_Assert(kdbLock != NULL); + PZ_Lock(kdbLock); + + ret = (* db->del)(db, key, flags); + + prstat = PZ_Unlock(kdbLock); + + return(ret); +} + +static int +keydb_Seq(DB *db, DBT *key, DBT *data, unsigned int flags) +{ + PRStatus prstat; + int ret; + + PORT_Assert(kdbLock != NULL); + PZ_Lock(kdbLock); + + ret = (* db->seq)(db, key, data, flags); + + prstat = PZ_Unlock(kdbLock); + + return(ret); +} + +static void +keydb_Close(DB *db) +{ + PRStatus prstat; + + PORT_Assert(kdbLock != NULL); + PZ_Lock(kdbLock); + + (* db->close)(db); + + prstat = PZ_Unlock(kdbLock); + + return; +} + diff --git a/security/nss/lib/softoken/lowcert.c b/security/nss/lib/softoken/lowcert.c index 1ef4021fb..652c444c6 100644 --- a/security/nss/lib/softoken/lowcert.c +++ b/security/nss/lib/softoken/lowcert.c @@ -288,13 +288,13 @@ nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *not } /* convert DER not-before time */ - rv = CERT_DecodeTimeChoice(notBefore, &validity.notBefore); + rv = DER_DecodeTimeChoice(notBefore, &validity.notBefore); if (rv) { return(SECFailure); } /* convert DER not-after time */ - rv = CERT_DecodeTimeChoice(notAfter, &validity.notAfter); + rv = DER_DecodeTimeChoice(notAfter, &validity.notAfter); if (rv) { return(SECFailure); } diff --git a/security/nss/lib/softoken/pcert.h b/security/nss/lib/softoken/pcert.h index 9743a8619..e2b5b8c6c 100644 --- a/security/nss/lib/softoken/pcert.h +++ b/security/nss/lib/softoken/pcert.h @@ -219,6 +219,9 @@ PRBool nsslowcert_hasTrust(NSSLOWCERTCertTrust *trust); void +nsslowcert_DestroyFreeLists(void); + +void nsslowcert_DestroyGlobalLocks(void); void diff --git a/security/nss/lib/softoken/pcertdb.c b/security/nss/lib/softoken/pcertdb.c index fb7ff6b87..2a3aaa7c2 100644 --- a/security/nss/lib/softoken/pcertdb.c +++ b/security/nss/lib/softoken/pcertdb.c @@ -1038,6 +1038,7 @@ CreateCertEntry(void) entryListCount--; entryListHead = entry->next; } + PORT_Assert(entryListCount >= 0); nsslowcert_UnlockFreeList(); if (entry) { return entry; @@ -1046,6 +1047,22 @@ CreateCertEntry(void) return PORT_ZAlloc(sizeof(certDBEntryCert)); } +static void +DestroyCertEntryFreeList(void) +{ + certDBEntryCert *entry; + + nsslowcert_LockFreeList(); + while (NULL != (entry = entryListHead)) { + entryListCount--; + entryListHead = entry->next; + PORT_Free(entry); + } + PORT_Assert(!entryListCount); + entryListCount = 0; + nsslowcert_UnlockFreeList(); +} + /* * Read a certificate entry */ @@ -2681,7 +2698,7 @@ nsslowcert_UpdateSubjectEmailAddr(NSSLOWCERTCertDBHandle *dbhandle, } if ( entry->emailAddrs ) { - for (i=0; i < entry->nemailAddrs; i++) { + for (i=0; i < (int)(entry->nemailAddrs); i++) { if (PORT_Strcmp(entry->emailAddrs[i],emailAddr) == 0) { index = i; } @@ -2695,7 +2712,7 @@ nsslowcert_UpdateSubjectEmailAddr(NSSLOWCERTCertDBHandle *dbhandle, } entry->nemailAddrs--; - for (i=index; i < entry->nemailAddrs; i++) { + for (i=index; i < (int)(entry->nemailAddrs); i++) { entry->emailAddrs[i] = entry->emailAddrs[i+1]; } } else { @@ -2708,7 +2725,7 @@ nsslowcert_UpdateSubjectEmailAddr(NSSLOWCERTCertDBHandle *dbhandle, if (!newAddrs) { goto loser; } - for (i=0; i < entry->nemailAddrs; i++) { + for (i=0; i < (int)(entry->nemailAddrs); i++) { newAddrs[i] = entry->emailAddrs[i]; } newAddrs[entry->nemailAddrs] = @@ -4296,6 +4313,7 @@ CreateTrust(void) trustListCount--; trustListHead = trust->next; } + PORT_Assert(trustListCount >= 0); nsslowcert_UnlockFreeList(); if (trust) { return trust; @@ -4304,9 +4322,25 @@ CreateTrust(void) return PORT_ZAlloc(sizeof(NSSLOWCERTTrust)); } +static void +DestroyTrustFreeList(void) +{ + NSSLOWCERTTrust *trust; + + nsslowcert_LockFreeList(); + while (NULL != (trust = trustListHead)) { + trustListCount--; + trustListHead = trust->next; + PORT_Free(trust); + } + PORT_Assert(!trustListCount); + trustListCount = 0; + nsslowcert_UnlockFreeList(); +} static NSSLOWCERTTrust * -DecodeTrustEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryCert *entry, SECItem *dbKey) +DecodeTrustEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryCert *entry, + SECItem *dbKey) { NSSLOWCERTTrust *trust = CreateTrust(); if (trust == NULL) { @@ -5000,14 +5034,30 @@ nsslowcert_CreateCert(void) certListHead = cert->next; certListCount--; } + PORT_Assert(certListCount >= 0); nsslowcert_UnlockFreeList(); - if (cert) { return cert; } return (NSSLOWCERTCertificate *) PORT_ZAlloc(sizeof(NSSLOWCERTCertificate)); } +static void +DestroyCertFreeList(void) +{ + NSSLOWCERTCertificate *cert; + + nsslowcert_LockFreeList(); + while (NULL != (cert = certListHead)) { + certListCount--; + certListHead = cert->next; + PORT_Free(cert); + } + PORT_Assert(!certListCount); + certListCount = 0; + nsslowcert_UnlockFreeList(); +} + void nsslowcert_DestroyTrust(NSSLOWCERTTrust *trust) { @@ -5248,8 +5298,21 @@ nsslowcert_SaveSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, char *emailAddr, return(rv); } +/* If the freeListLock doesn't exist when this function is called, +** this function will create it, use it 3 times, and delete it. +*/ +void +nsslowcert_DestroyFreeLists(void) +{ + DestroyCertEntryFreeList(); + DestroyTrustFreeList(); + DestroyCertFreeList(); + PZ_DestroyLock(freeListLock); + freeListLock = NULL; +} + void -nsslowcert_DestroyGlobalLocks() +nsslowcert_DestroyGlobalLocks(void) { if (dbLock) { PZ_DestroyLock(dbLock); diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index d0fe96637..0d77670f2 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -1040,7 +1040,6 @@ pk11_handlePublicKeyObject(PK11Session *session, PK11Object *object, CK_BBOOL derive = CK_FALSE; CK_BBOOL verify = CK_TRUE; CK_ATTRIBUTE_TYPE pubKeyAttr = CKA_VALUE; - PK11Attribute *attribute; CK_RV crv; switch (key_type) { @@ -2852,6 +2851,8 @@ CK_RV nsc_CommonFinalize (CK_VOID_PTR pReserved, PRBool isFIPS) return CKR_OK; } + pk11_CleanupFreeLists(); + nsslowcert_DestroyFreeLists(); nsslowcert_DestroyGlobalLocks(); #ifdef LEAK_TEST @@ -2867,7 +2868,6 @@ CK_RV nsc_CommonFinalize (CK_VOID_PTR pReserved, PRBool isFIPS) RNG_RNGShutdown(); #endif - pk11_CleanupFreeLists(); /* tell freeBL to clean up after itself */ BL_Cleanup(); /* clean up the default OID table */ diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c index 046dcdde6..7b1fddf38 100644 --- a/security/nss/lib/softoken/pkcs11u.c +++ b/security/nss/lib/softoken/pkcs11u.c @@ -45,6 +45,7 @@ #include "secasn1.h" #include "blapi.h" #include "secerr.h" +#include "prnetdb.h" /* for PR_ntohl */ /* * ******************** Attribute Utilities ******************************* @@ -1323,7 +1324,6 @@ pk11_ConstrainAttribute(PK11Object *object, CK_ATTRIBUTE_TYPE type, PK11Attribute *attribute; unsigned int size; unsigned char *ptr; - int i,j; attribute = pk11_FindAttribute(object, type); if (!attribute) { @@ -1922,7 +1922,6 @@ CK_RV pk11_GetULongAttribute(PK11Object *object, CK_ATTRIBUTE_TYPE type, CK_ULONG *longData) { - int len; PK11Attribute *attribute; attribute = pk11_FindAttribute(object, type); diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 603e3ab88..1b2cd4fc1 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -3759,9 +3759,9 @@ sendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) } /* Determine the PMS */ - pms = PK11_PubDeriveExtended(privKey, svrPubKey, PR_FALSE, NULL, NULL, - CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, NULL, - kdf, NULL); + pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL, + CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, + kdf, NULL, NULL); if (pms == NULL) { ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); @@ -6983,9 +6983,9 @@ ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b, } /* Determine the PMS */ - pms = PK11_PubDeriveExtended(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL, - CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, NULL, - kdf, NULL); + pms = PK11_PubDeriveWithKDF(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL, + CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, + kdf, NULL, NULL); PORT_Free(clntPubKey.u.ec.publicValue.data); diff --git a/security/nss/lib/ssl/sslgathr.c b/security/nss/lib/ssl/sslgathr.c index 9f06a25e3..1e0253c8b 100644 --- a/security/nss/lib/ssl/sslgathr.c +++ b/security/nss/lib/ssl/sslgathr.c @@ -195,6 +195,10 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags) /* is_escape = (gs->hdr[0] & 0x40) != 0; */ gs->recordPadding = gs->hdr[2]; } + if (!gs->count) { + PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); + goto cleanup; + } if (gs->count > gs->buf.space) { err = sslBuffer_Grow(&gs->buf, gs->count); diff --git a/security/nss/lib/util/dertime.c b/security/nss/lib/util/dertime.c index 50036f258..a4d065229 100644 --- a/security/nss/lib/util/dertime.c +++ b/security/nss/lib/util/dertime.c @@ -125,9 +125,15 @@ DER_TimeToUTCTime(SECItem *dst, int64 gmttime) return DER_TimeToUTCTimeArena(NULL, dst, gmttime); } - +/* The caller of DER_AsciiToItem MUST ENSURE that either +** a) "string" points to a null-terminated ASCII string, or +** b) "string" points to a buffer containing a valid UTCTime, +** whether null terminated or not. +** otherwise, this function may UMR and/or crash. +** It suffices to ensure that the input "string" is at least 17 bytes long. +*/ SECStatus -DER_AsciiToTime(int64 *dst, char *string) +DER_AsciiToTime(int64 *dst, const char *string) { long year, month, mday, hour, minute, second, hourOff, minOff, days; int64 result, tmp1, tmp2; @@ -223,9 +229,27 @@ DER_AsciiToTime(int64 *dst, char *string) } SECStatus -DER_UTCTimeToTime(int64 *dst, SECItem *time) +DER_UTCTimeToTime(int64 *dst, const SECItem *time) { - return DER_AsciiToTime(dst, (char*) time->data); + const char * string; + char localBuf[20]; + + /* Minimum valid UTCTime is yymmddhhmmZ which is 11 bytes. + ** Maximum valid UTCTime is yymmddhhmmss+0000 which is 17 bytes. + ** 20 should be large enough for all valid encoded times. + */ + if (!time || !time->data || time->len < 11) { + PORT_SetError(SEC_ERROR_INVALID_TIME); + return SECFailure; + } + if (time->len >= sizeof localBuf) { + string = (const char *)time->data; + } else { + memset(localBuf, 0, sizeof localBuf); + memcpy(localBuf, time->data, time->len); + string = (const char *)localBuf; + } + return DER_AsciiToTime(dst, string); } /* @@ -292,15 +316,29 @@ DER_TimeToGeneralizedTime(SECItem *dst, int64 gmttime) the certificate should be consider invalid!? */ SECStatus -DER_GeneralizedTimeToTime(int64 *dst, SECItem *time) +DER_GeneralizedTimeToTime(int64 *dst, const SECItem *time) { PRExplodedTime genTime; - char *string; + const char *string; long hourOff, minOff; uint16 century; + char localBuf[20]; + + /* Minimum valid GeneralizedTime is ccyymmddhhmmZ which is 13 bytes. + ** Maximum valid GeneralizedTime is ccyymmddhhmmss+0000 which is 19 bytes. + ** 20 should be large enough for all valid encoded times. + */ + if (!time || !time->data || time->len < 13) + goto loser; + if (time->len >= sizeof localBuf) { + string = (const char *)time->data; + } else { + memset(localBuf, 0, sizeof localBuf); + memcpy(localBuf, time->data, time->len); + string = (const char *)localBuf; + } - string = (char *)time->data; - PORT_Memset (&genTime, 0, sizeof (genTime)); + memset(&genTime, 0, sizeof genTime); /* Verify time is formatted properly and capture information */ hourOff = 0; diff --git a/security/nss/lib/util/nssilckt.h b/security/nss/lib/util/nssilckt.h index e0b49902f..b516df9d6 100644 --- a/security/nss/lib/util/nssilckt.h +++ b/security/nss/lib/util/nssilckt.h @@ -154,6 +154,7 @@ typedef enum { nssILockRWLock = 15, nssILockOther = 16, nssILockSelfServ = 17, + nssILockKeyDB = 18, nssILockLast /* don't use this one! */ } nssILockType; diff --git a/security/nss/lib/util/secasn1d.c b/security/nss/lib/util/secasn1d.c index 965fa702d..2663abd3b 100644 --- a/security/nss/lib/util/secasn1d.c +++ b/security/nss/lib/util/secasn1d.c @@ -959,7 +959,7 @@ sec_asn1d_parse_more_length (sec_asn1d_state *state, count = 0; while (len && state->pending) { - if (HIGH_BITS (state->contents_length, 8) != 0) { + if (HIGH_BITS (state->contents_length, 9) != 0) { /* * The given full content length overflows our container; * just give up. diff --git a/security/nss/lib/util/secder.h b/security/nss/lib/util/secder.h index a54967f61..dcb43abd7 100644 --- a/security/nss/lib/util/secder.h +++ b/security/nss/lib/util/secder.h @@ -148,12 +148,12 @@ extern SECStatus DER_TimeToUTCTimeArena(PRArenaPool* arenaOpt, ** "result" the resulting "UNIX" time ** "string" the der notation ascii value to decode */ -extern SECStatus DER_AsciiToTime(int64 *result, char *string); +extern SECStatus DER_AsciiToTime(int64 *result, const char *string); /* ** Same as DER_AsciiToTime except takes an SECItem instead of a string */ -extern SECStatus DER_UTCTimeToTime(int64 *result, SECItem *time); +extern SECStatus DER_UTCTimeToTime(int64 *result, const SECItem *time); /* ** Convert a DER encoded UTC time to an ascii time representation @@ -186,7 +186,7 @@ extern SECStatus DER_TimeToGeneralizedTimeArena(PRArenaPool* arenaOpt, ** "dst" the resulting "UNIX" time ** "string" the der notation ascii value to decode */ -extern SECStatus DER_GeneralizedTimeToTime(int64 *dst, SECItem *time); +extern SECStatus DER_GeneralizedTimeToTime(int64 *dst, const SECItem *time); /* ** Convert from a int64 UTC time value to a formatted ascii value. The @@ -206,12 +206,12 @@ extern char *CERT_GenTime2FormattedAscii (int64 genTime, char *format); ** or a SEC_ASN1_UTC_TIME */ -extern SECStatus CERT_DecodeTimeChoice(PRTime* output, SECItem* input); +extern SECStatus DER_DecodeTimeChoice(PRTime* output, const SECItem* input); /* encode a PRTime to an ASN.1 DER SECItem containing either a SEC_ASN1_GENERALIZED_TIME or a SEC_ASN1_UTC_TIME */ -extern SECStatus CERT_EncodeTimeChoice(PRArenaPool* arena, SECItem* output, +extern SECStatus DER_EncodeTimeChoice(PRArenaPool* arena, SECItem* output, PRTime input); SEC_END_PROTOS diff --git a/security/nss/lib/util/secitem.c b/security/nss/lib/util/secitem.c index eb4683ca4..daf550d62 100644 --- a/security/nss/lib/util/secitem.c +++ b/security/nss/lib/util/secitem.c @@ -180,18 +180,32 @@ SECITEM_ItemsAreEqual(const SECItem *a, const SECItem *b) SECItem * SECITEM_DupItem(const SECItem *from) { + return SECITEM_ArenaDupItem(NULL, from); +} + +SECItem * +SECITEM_ArenaDupItem(PRArenaPool *arena, const SECItem *from) +{ SECItem *to; if ( from == NULL ) { return(NULL); } - to = (SECItem *)PORT_Alloc(sizeof(SECItem)); + if ( arena != NULL ) { + to = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem)); + } else { + to = (SECItem *)PORT_Alloc(sizeof(SECItem)); + } if ( to == NULL ) { return(NULL); } - to->data = (unsigned char *)PORT_Alloc(from->len); + if ( arena != NULL ) { + to->data = (unsigned char *)PORT_ArenaAlloc(arena, from->len); + } else { + to->data = (unsigned char *)PORT_Alloc(from->len); + } if ( to->data == NULL ) { PORT_Free(to); return(NULL); @@ -199,7 +213,9 @@ SECITEM_DupItem(const SECItem *from) to->len = from->len; to->type = from->type; - PORT_Memcpy(to->data, from->data, to->len); + if ( to->len ) { + PORT_Memcpy(to->data, from->data, to->len); + } return(to); } diff --git a/security/nss/lib/util/secitem.h b/security/nss/lib/util/secitem.h index 76a5d16fb..d957ba0eb 100644 --- a/security/nss/lib/util/secitem.h +++ b/security/nss/lib/util/secitem.h @@ -93,6 +93,13 @@ extern SECStatus SECITEM_CopyItem(PRArenaPool *arena, SECItem *to, extern SECItem *SECITEM_DupItem(const SECItem *from); /* +** Allocate an item and copy "from" into it. The item itself and the +** data it points to are both allocated from the arena. If arena is +** NULL, this function is equivalent to SECITEM_DupItem. +*/ +extern SECItem *SECITEM_ArenaDupItem(PRArenaPool *arena, const SECItem *from); + +/* ** Free "zap". If freeit is PR_TRUE then "zap" itself is freed. */ extern void SECITEM_FreeItem(SECItem *zap, PRBool freeit); diff --git a/security/nss/lib/util/secoid.c b/security/nss/lib/util/secoid.c index f9bb70b07..61c6d9aa0 100644 --- a/security/nss/lib/util/secoid.c +++ b/security/nss/lib/util/secoid.c @@ -1584,7 +1584,7 @@ secoid_Init(void) int i; if (oidhash) { - return PR_SUCCESS; + return SECSuccess; } oidhash = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, diff --git a/security/nss/lib/util/secport.c b/security/nss/lib/util/secport.c index fb0892101..7d276f9b7 100644 --- a/security/nss/lib/util/secport.c +++ b/security/nss/lib/util/secport.c @@ -207,6 +207,8 @@ PORT_NewArena(unsigned long chunksize) return(&pool->arena); } +#define MAX_SIZE 0x7fffffffUL + void * PORT_ArenaAlloc(PLArenaPool *arena, size_t size) { @@ -218,6 +220,9 @@ PORT_ArenaAlloc(PLArenaPool *arena, size_t size) size = 1; } + if (size > MAX_SIZE) { + /* you lose. */ + } else /* Is it one of ours? Assume so and check the magic */ if (ARENAPOOL_MAGIC == pool->magic ) { PZ_Lock(pool->lock); diff --git a/security/nss/lib/util/sectime.c b/security/nss/lib/util/sectime.c index 678021853..475a8c18f 100644 --- a/security/nss/lib/util/sectime.c +++ b/security/nss/lib/util/sectime.c @@ -45,7 +45,7 @@ const SEC_ASN1Template CERT_TimeChoiceTemplate[] = { { 0 } }; -SEC_ASN1_CHOOSER_IMPLEMENT(CERT_TimeChoiceTemplate); +SEC_ASN1_CHOOSER_IMPLEMENT(CERT_TimeChoiceTemplate) const SEC_ASN1Template CERT_ValidityTemplate[] = { { SEC_ASN1_SEQUENCE, @@ -122,9 +122,9 @@ CERT_CreateValidity(int64 notBefore, int64 notAfter) v = (CERTValidity*) PORT_ArenaZAlloc(arena, sizeof(CERTValidity)); if (v) { v->arena = arena; - rv = CERT_EncodeTimeChoice(arena, &v->notBefore, notBefore); + rv = DER_EncodeTimeChoice(arena, &v->notBefore, notBefore); if (rv) goto loser; - rv = CERT_EncodeTimeChoice(arena, &v->notAfter, notAfter); + rv = DER_EncodeTimeChoice(arena, &v->notAfter, notAfter); if (rv) goto loser; } return v; @@ -228,7 +228,7 @@ DecodeGeneralizedTime2FormattedAscii (SECItem *generalizedTimeDER, char *format /* decode a SECItem containing either a SEC_ASN1_GENERALIZED_TIME or a SEC_ASN1_UTC_TIME */ -SECStatus CERT_DecodeTimeChoice(PRTime* output, SECItem* input) +SECStatus DER_DecodeTimeChoice(PRTime* output, const SECItem* input) { switch (input->type) { case siGeneralizedTime: @@ -247,7 +247,7 @@ SECStatus CERT_DecodeTimeChoice(PRTime* output, SECItem* input) /* encode a PRTime to an ASN.1 DER SECItem containing either a SEC_ASN1_GENERALIZED_TIME or a SEC_ASN1_UTC_TIME */ -SECStatus CERT_EncodeTimeChoice(PRArenaPool* arena, SECItem* output, PRTime input) +SECStatus DER_EncodeTimeChoice(PRArenaPool* arena, SECItem* output, PRTime input) { if (LL_CMP(input, >, January1st2050)) { return DER_TimeToGeneralizedTimeArena(arena, output, input); diff --git a/security/nss/lib/util/utf8.c b/security/nss/lib/util/utf8.c index 7a3c3954d..013f202a9 100644 --- a/security/nss/lib/util/utf8.c +++ b/security/nss/lib/util/utf8.c @@ -236,6 +236,11 @@ sec_port_ucs4_utf8_conversion_function return PR_TRUE; } else { unsigned int i, len = 0; + PORT_Assert((inBufLen % 4) == 0); + if ((inBufLen % 4) != 0) { + *outBufLen = 0; + return PR_FALSE; + } for( i = 0; i < inBufLen; i += 4 ) { if( inBuf[i+L_0] >= 0x04 ) len += 6; @@ -457,6 +462,11 @@ sec_port_ucs2_utf8_conversion_function return PR_TRUE; } else { unsigned int i, len = 0; + PORT_Assert((inBufLen % 2) == 0); + if ((inBufLen % 2) != 0) { + *outBufLen = 0; + return PR_FALSE; + } for( i = 0; i < inBufLen; i += 2 ) { if( (inBuf[i+H_0] == 0x00) && ((inBuf[i+H_0] & 0x80) == 0x00) ) len += 1; diff --git a/security/nss/manifest.mn b/security/nss/manifest.mn index 286954d04..98dc19a6a 100644 --- a/security/nss/manifest.mn +++ b/security/nss/manifest.mn @@ -33,7 +33,7 @@ CORE_DEPTH = .. DEPTH = .. -IMPORTS = nspr20/v4.3 \ +IMPORTS = nspr20/v4.4.1 \ dbm/DBM_1_61_RTM \ $(NULL) |