static void parse_signature(pesign_context *ctx, uint8_t **data, unsigned int *datalen) { int rc; char *sig; size_t siglen; rc = read_file(ctx->insigfd, &sig, &siglen); if (rc < 0) { fprintf(stderr, "pesign: could not read signature.\n"); exit(1); } close(ctx->insigfd); ctx->insigfd = -1; unsigned char *der; unsigned int derlen; /* XXX FIXME: ignoring length for now */ char *base64 = strstr(sig, sig_begin_marker); if (base64) { base64 += strlen(sig_begin_marker); char *end = strstr(base64, sig_end_marker); if (!end) { fprintf(stderr, "pesign: Invalid signature.\n"); exit(1); } derlen = end - base64; base64[derlen] = '\0'; der = ATOB_AsciiToData(base64, &derlen); } else { der = PORT_Alloc(siglen); memmove(der, sig, siglen); derlen = siglen; } free(sig); *data = der; *datalen = derlen; #if 0 SEC_PKCS7DecoderContext *dc = NULL; saw_content = 0; dc = SEC_PKCS7DecoderStart(handle_bytes, NULL, NULL, NULL, NULL, NULL, decryption_allowed); if (dc == NULL) { decoder_error: fprintf(stderr, "pesign: Invalid signature.\n"); PORT_Free(der); exit(1); } SECStatus status = SEC_PKCS7DecoderUpdate(dc, (char *)der, derlen); if (status != SECSuccess) goto decoder_error; SEC_PKCS7ContentInfo *cinfo = SEC_PKCS7DecoderFinish(dc); if (!cinfo) goto decoder_error; ctx->cinfo = cinfo; PORT_Free(der); #endif }
/* * J A R _ g e t _ e r r o r * * This is provided to map internal JAR errors to strings for * the Java console. Also, a DLL may call this function if it does * not have access to the XP_GetString function. * * These strings aren't UI, since they are Java console only. * */ char * JAR_get_error(int status) { char *errstring = NULL; switch (status) { case JAR_ERR_GENERAL: errstring = "General JAR file error"; break; case JAR_ERR_FNF: errstring = "JAR file not found"; break; case JAR_ERR_CORRUPT: errstring = "Corrupt JAR file"; break; case JAR_ERR_MEMORY: errstring = "Out of memory"; break; case JAR_ERR_DISK: errstring = "Disk error (perhaps out of space)"; break; case JAR_ERR_ORDER: errstring = "Inconsistent files in META-INF directory"; break; case JAR_ERR_SIG: errstring = "Invalid digital signature file"; break; case JAR_ERR_METADATA: errstring = "JAR metadata failed verification"; break; case JAR_ERR_ENTRY: errstring = "No Manifest entry for this JAR entry"; break; case JAR_ERR_HASH: errstring = "Invalid Hash of this JAR entry"; break; case JAR_ERR_PK7: errstring = "Strange PKCS7 or RSA failure"; break; case JAR_ERR_PNF: errstring = "Path not found inside JAR file"; break; default: if (jar_fn_GetString) { errstring = jar_fn_GetString (status); } else { /* this is not a normal situation, and would only be called in cases of improper initialization */ char *err = (char*)PORT_Alloc (40); if (err) PR_snprintf (err, 39, "Error %d\n", status); /* leak me! */ else err = "Error! Bad! Out of memory!"; return err; } break; } return errstring; }
/* * read an old style ascii or binary certificate chain */ SECStatus CERT_DecodeCertPackage(char *certbuf, int certlen, CERTImportCertificateFunc f, void *arg) { unsigned char *cp; unsigned char *bincert = NULL; char * ascCert = NULL; SECStatus rv; if ( certbuf == NULL ) { return(SECFailure); } cp = (unsigned char *)certbuf; /* is a DER encoded certificate of some type? */ if ( ( *cp & 0x1f ) == SEC_ASN1_SEQUENCE ) { SECItem certitem; SECItem *pcertitem = &certitem; int seqLen, seqLenLen; cp++; if ( *cp & 0x80) { /* Multibyte length */ seqLenLen = cp[0] & 0x7f; switch (seqLenLen) { case 4: seqLen = ((unsigned long)cp[1]<<24) | ((unsigned long)cp[2]<<16) | (cp[3]<<8) | cp[4]; break; case 3: seqLen = ((unsigned long)cp[1]<<16) | (cp[2]<<8) | cp[3]; break; case 2: seqLen = (cp[1]<<8) | cp[2]; break; case 1: seqLen = cp[1]; break; default: /* indefinite length */ seqLen = 0; } cp += ( seqLenLen + 1 ); } else { seqLenLen = 0; seqLen = *cp; cp++; } /* check entire length if definite length */ if ( seqLen || seqLenLen ) { if ( certlen != ( seqLen + seqLenLen + 2 ) ) { if (certlen > ( seqLen + seqLenLen + 2 )) PORT_SetError(SEC_ERROR_EXTRA_INPUT); else PORT_SetError(SEC_ERROR_INPUT_LEN); goto notder; } } /* check the type string */ /* netscape wrapped DER cert */ if ( ( cp[0] == SEC_ASN1_OCTET_STRING ) && ( cp[1] == CERTIFICATE_TYPE_LEN ) && ( PORT_Strcmp((char *)&cp[2], CERTIFICATE_TYPE_STRING) ) ) { cp += ( CERTIFICATE_TYPE_LEN + 2 ); /* it had better be a certificate by now!! */ certitem.data = cp; certitem.len = certlen - ( cp - (unsigned char *)certbuf ); rv = (* f)(arg, &pcertitem, 1); return(rv); } else if ( cp[0] == SEC_ASN1_OBJECT_ID ) { SECOidData *oiddata; SECItem oiditem; /* XXX - assume DER encoding of OID len!! */ oiditem.len = cp[1]; oiditem.data = (unsigned char *)&cp[2]; oiddata = SECOID_FindOID(&oiditem); if ( oiddata == NULL ) { return(SECFailure); } certitem.data = (unsigned char*)certbuf; certitem.len = certlen; switch ( oiddata->offset ) { case SEC_OID_PKCS7_SIGNED_DATA: return(SEC_ReadPKCS7Certs(&certitem, f, arg)); break; case SEC_OID_NS_TYPE_CERT_SEQUENCE: return(SEC_ReadCertSequence(&certitem, f, arg)); break; default: break; } } else { /* it had better be a certificate by now!! */ certitem.data = (unsigned char*)certbuf; certitem.len = certlen; rv = (* f)(arg, &pcertitem, 1); return(rv); } } /* now look for a netscape base64 ascii encoded cert */ notder: { unsigned char *certbegin = NULL; unsigned char *certend = NULL; char *pc; int cl; /* Convert the ASCII data into a nul-terminated string */ ascCert = (char *)PORT_Alloc(certlen + 1); if (!ascCert) { rv = SECFailure; goto loser; } PORT_Memcpy(ascCert, certbuf, certlen); ascCert[certlen] = '\0'; pc = PORT_Strchr(ascCert, '\n'); /* find an EOL */ if (!pc) { /* maybe this is a MAC file */ pc = ascCert; while (*pc && NULL != (pc = PORT_Strchr(pc, '\r'))) { *pc++ = '\n'; } } cp = (unsigned char *)ascCert; cl = certlen; /* find the beginning marker */ while ( cl > NS_CERT_HEADER_LEN ) { if ( !PORT_Strncasecmp((char *)cp, NS_CERT_HEADER, NS_CERT_HEADER_LEN) ) { cl -= NS_CERT_HEADER_LEN; cp += NS_CERT_HEADER_LEN; certbegin = cp; break; } /* skip to next eol */ do { cp++; cl--; } while ( ( *cp != '\n') && cl ); /* skip all blank lines */ while ( ( *cp == '\n') && cl ) { cp++; cl--; } } if ( certbegin ) { /* find the ending marker */ while ( cl > NS_CERT_TRAILER_LEN ) { if ( !PORT_Strncasecmp((char *)cp, NS_CERT_TRAILER, NS_CERT_TRAILER_LEN) ) { certend = (unsigned char *)cp; break; } /* skip to next eol */ do { cp++; cl--; } while ( ( *cp != '\n') && cl ); /* skip all blank lines */ while ( ( *cp == '\n') && cl ) { cp++; cl--; } } } if ( certbegin && certend ) { unsigned int binLen; *certend = 0; /* convert to binary */ bincert = ATOB_AsciiToData(certbegin, &binLen); if (!bincert) { rv = SECFailure; goto loser; } /* now recurse to decode the binary */ rv = CERT_DecodeCertPackage((char *)bincert, binLen, f, arg); } else { rv = SECFailure; } } loser: if ( bincert ) { PORT_Free(bincert); } if ( ascCert ) { PORT_Free(ascCert); } return(rv); }
nsresult nsNSSCertificateDB::ImportValidCACertsInList(CERTCertList *certList, nsIInterfaceRequestor *ctx) { SECItem **rawArray; /* filter out the certs we don't want */ SECStatus srv = CERT_FilterCertListByUsage(certList, certUsageAnyCA, PR_TRUE); if (srv != SECSuccess) { return NS_ERROR_FAILURE; } /* go down the remaining list of certs and verify that they have * valid chains, if yes, then import. */ PRTime now = PR_Now(); CERTCertListNode *node; for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node,certList); node = CERT_LIST_NEXT(node)) { bool alert_and_skip = false; if (CERT_VerifyCert(CERT_GetDefaultCertDB(), node->cert, PR_TRUE, certUsageVerifyCA, now, ctx, NULL) != SECSuccess) { alert_and_skip = true; } CERTCertificateList *certChain = nsnull; CERTCertificateListCleaner chainCleaner(certChain); if (!alert_and_skip) { certChain = CERT_CertChainFromCert(node->cert, certUsageAnyCA, PR_FALSE); if (!certChain) { alert_and_skip = true; } } if (alert_and_skip) { nsCOMPtr<nsIX509Cert> certToShow = new nsNSSCertificate(node->cert); DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow); continue; } /* * CertChain returns an array of SECItems, import expects an array of * SECItem pointers. Create the SECItem Pointers from the array of * SECItems. */ rawArray = (SECItem **) PORT_Alloc(certChain->len * sizeof(SECItem *)); if (!rawArray) { continue; } for (int i=0; i < certChain->len; i++) { rawArray[i] = &certChain->certs[i]; } CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageAnyCA, certChain->len, rawArray, NULL, PR_TRUE, PR_TRUE, NULL); PORT_Free(rawArray); } return NS_OK; }
static SECStatus ssl3_CngPlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, PRBool isTLS, KeyType keyType) { SECStatus rv = SECFailure; SECURITY_STATUS ncrypt_status; PRBool doDerEncode = PR_FALSE; SECItem hashItem; DWORD signatureLen = 0; DWORD dwFlags = 0; VOID *pPaddingInfo = NULL; /* Always encode using PKCS#1 block type. */ BCRYPT_PKCS1_PADDING_INFO rsaPaddingInfo; if (key->dwKeySpec != CERT_NCRYPT_KEY_SPEC) { PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0); return SECFailure; } if (ssl_InitCng() != SECSuccess) { PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0); return SECFailure; } switch (keyType) { case rsaKey: switch (hash->hashAlg) { case SEC_OID_UNKNOWN: /* No OID/encoded DigestInfo. */ rsaPaddingInfo.pszAlgId = NULL; break; case SEC_OID_SHA1: rsaPaddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM; break; case SEC_OID_SHA256: rsaPaddingInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM; break; case SEC_OID_SHA384: rsaPaddingInfo.pszAlgId = BCRYPT_SHA384_ALGORITHM; break; case SEC_OID_SHA512: rsaPaddingInfo.pszAlgId = BCRYPT_SHA512_ALGORITHM; break; default: PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM); return SECFailure; } hashItem.data = hash->u.raw; hashItem.len = hash->len; dwFlags = BCRYPT_PAD_PKCS1; pPaddingInfo = &rsaPaddingInfo; break; case dsaKey: case ecKey: if (keyType == ecKey) { doDerEncode = PR_TRUE; } else { doDerEncode = isTLS; } if (hash->hashAlg == SEC_OID_UNKNOWN) { hashItem.data = hash->u.s.sha; hashItem.len = sizeof(hash->u.s.sha); } else { hashItem.data = hash->u.raw; hashItem.len = hash->len; } break; default: PORT_SetError(SEC_ERROR_INVALID_KEY); goto done; } PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len)); ncrypt_status = (*pNCryptSignHash)(key->hNCryptKey, pPaddingInfo, (PBYTE)hashItem.data, hashItem.len, NULL, 0, &signatureLen, dwFlags); if (FAILED(ncrypt_status) || signatureLen == 0) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, ncrypt_status); goto done; } buf->data = (unsigned char *)PORT_Alloc(signatureLen); if (!buf->data) { goto done; /* error code was set. */ } ncrypt_status = (*pNCryptSignHash)(key->hNCryptKey, pPaddingInfo, (PBYTE)hashItem.data, hashItem.len, (PBYTE)buf->data, signatureLen, &signatureLen, dwFlags); if (FAILED(ncrypt_status) || signatureLen == 0) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, ncrypt_status); goto done; } buf->len = signatureLen; if (doDerEncode) { SECItem derSig = {siBuffer, NULL, 0}; /* This also works for an ECDSA signature */ rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len); if (rv == SECSuccess) { PORT_Free(buf->data); /* discard unencoded signature. */ *buf = derSig; /* give caller encoded signature. */ } else if (derSig.data) { PORT_Free(derSig.data); } } else { rv = SECSuccess; } PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len)); done: if (rv != SECSuccess && buf->data) { PORT_Free(buf->data); buf->data = NULL; buf->len = 0; } return rv; }
static void* my_alloc_func(void*opaque, uInt items, uInt size) { return PORT_Alloc(items * size); }
SECStatus SSL_ExportKeyingMaterial(PRFileDesc *fd, const char *label, unsigned int labelLen, PRBool hasContext, const unsigned char *context, unsigned int contextLen, unsigned char *out, unsigned int outLen) { sslSocket *ss; unsigned char *val = NULL; unsigned int valLen, i; SECStatus rv = SECFailure; ss = ssl_FindSocket(fd); if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in ExportKeyingMaterial", SSL_GETPID(), fd)); return SECFailure; } if (!label || !labelLen || !out || !outLen || (hasContext && (!context || !contextLen))) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { return tls13_Exporter(ss, ss->ssl3.hs.exporterSecret, label, labelLen, context, hasContext ? contextLen : 0, out, outLen); } /* construct PRF arguments */ valLen = SSL3_RANDOM_LENGTH * 2; if (hasContext) { valLen += 2 /* PRUint16 length */ + contextLen; } val = PORT_Alloc(valLen); if (!val) { return SECFailure; } i = 0; PORT_Memcpy(val + i, &ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH); i += SSL3_RANDOM_LENGTH; PORT_Memcpy(val + i, &ss->ssl3.hs.server_random.rand, SSL3_RANDOM_LENGTH); i += SSL3_RANDOM_LENGTH; if (hasContext) { val[i++] = contextLen >> 8; val[i++] = contextLen; PORT_Memcpy(val + i, context, contextLen); i += contextLen; } PORT_Assert(i == valLen); /* Allow TLS keying material to be exported sooner, when the master * secret is available and we have sent ChangeCipherSpec. */ ssl_GetSpecReadLock(ss); if (!ss->ssl3.cwSpec->master_secret && !ss->ssl3.cwSpec->msItem.len) { PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED); rv = SECFailure; } else { rv = ssl3_TLSPRFWithMasterSecret(ss, ss->ssl3.cwSpec, label, labelLen, val, valLen, out, outLen); } ssl_ReleaseSpecReadLock(ss); PORT_ZFree(val, valLen); return rv; }
SECStatus SECU_ParseCommandLine(int argc, char **argv, char *progName, const secuCommand *cmd) { PRBool found; PLOptState *optstate; PLOptStatus status; char *optstring; PLLongOpt *longopts = NULL; int i, j; int lcmd = 0, lopt = 0; PR_ASSERT(HasNoDuplicates(cmd->commands, cmd->numCommands)); PR_ASSERT(HasNoDuplicates(cmd->options, cmd->numOptions)); optstring = (char *)PORT_Alloc(cmd->numCommands + 2 * cmd->numOptions + 1); if (optstring == NULL) return SECFailure; j = 0; for (i = 0; i < cmd->numCommands; i++) { if (cmd->commands[i].flag) /* single character option ? */ optstring[j++] = cmd->commands[i].flag; if (cmd->commands[i].longform) lcmd++; } for (i = 0; i < cmd->numOptions; i++) { if (cmd->options[i].flag) { optstring[j++] = cmd->options[i].flag; if (cmd->options[i].needsArg) optstring[j++] = ':'; } if (cmd->options[i].longform) lopt++; } optstring[j] = '\0'; if (lcmd + lopt > 0) { longopts = PORT_NewArray(PLLongOpt, lcmd + lopt + 1); if (!longopts) { PORT_Free(optstring); return SECFailure; } j = 0; for (i = 0; j < lcmd && i < cmd->numCommands; i++) { if (cmd->commands[i].longform) { longopts[j].longOptName = cmd->commands[i].longform; longopts[j].longOption = 0; longopts[j++].valueRequired = cmd->commands[i].needsArg; } } lopt += lcmd; for (i = 0; j < lopt && i < cmd->numOptions; i++) { if (cmd->options[i].longform) { longopts[j].longOptName = cmd->options[i].longform; longopts[j].longOption = 0; longopts[j++].valueRequired = cmd->options[i].needsArg; } } longopts[j].longOptName = NULL; } optstate = PL_CreateLongOptState(argc, argv, optstring, longopts); if (!optstate) { PORT_Free(optstring); PORT_Free(longopts); return SECFailure; } /* Parse command line arguments */ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { const char *optstatelong; char option = optstate->option; /* positional parameter, single-char option or long opt? */ if (optstate->longOptIndex == -1) { /* not a long opt */ if (option == '\0') continue; /* it's a positional parameter */ optstatelong = ""; } else { /* long opt */ if (option == '\0') option = '\377'; /* force unequal with all flags */ optstatelong = longopts[optstate->longOptIndex].longOptName; } found = PR_FALSE; for (i = 0; i < cmd->numCommands; i++) { if (cmd->commands[i].flag == option || cmd->commands[i].longform == optstatelong) { cmd->commands[i].activated = PR_TRUE; if (optstate->value) { cmd->commands[i].arg = (char *)optstate->value; } found = PR_TRUE; break; } } if (found) continue; for (i = 0; i < cmd->numOptions; i++) { if (cmd->options[i].flag == option || cmd->options[i].longform == optstatelong) { cmd->options[i].activated = PR_TRUE; if (optstate->value) { cmd->options[i].arg = (char *)optstate->value; } else if (cmd->options[i].needsArg) { status = PL_OPT_BAD; goto loser; } found = PR_TRUE; break; } } if (!found) { status = PL_OPT_BAD; break; } } loser: PL_DestroyOptState(optstate); PORT_Free(optstring); if (longopts) PORT_Free(longopts); if (status == PL_OPT_BAD) return SECFailure; return SECSuccess; }
SECItem * SECITEM_AllocItem(PLArenaPool *arena, SECItem *item, unsigned int len) { SECItem *result = NULL; void *mark = NULL; if (arena != NULL) { mark = PORT_ArenaMark(arena); } if (item == NULL) { if (arena != NULL) { result = PORT_ArenaZAlloc(arena, sizeof(SECItem)); } else { result = PORT_ZAlloc(sizeof(SECItem)); } if (result == NULL) { goto loser; } } else { PORT_Assert(item->data == NULL); result = item; } result->len = len; if (len) { if (arena != NULL) { result->data = PORT_ArenaAlloc(arena, len); } else { result->data = PORT_Alloc(len); } if (result->data == NULL) { goto loser; } } else { result->data = NULL; } if (mark) { PORT_ArenaUnmark(arena, mark); } return (result); loser: if (arena != NULL) { if (mark) { PORT_ArenaRelease(arena, mark); } if (item != NULL) { item->data = NULL; item->len = 0; } } else { if (result != NULL) { SECITEM_FreeItem(result, (item == NULL) ? PR_TRUE : PR_FALSE); } /* * If item is not NULL, the above has set item->data and * item->len to 0. */ } return (NULL); }
/* * load a new module into our address space and initialize it. */ SECStatus secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule) { PRLibrary *library = NULL; CK_C_GetFunctionList entry = NULL; CK_INFO info; CK_ULONG slotCount = 0; SECStatus rv; PRBool alreadyLoaded = PR_FALSE; char *disableUnload = NULL; if (mod->loaded) return SECSuccess; /* intenal modules get loaded from their internal list */ if (mod->internal && (mod->dllName == NULL)) { #ifdef NSS_STATIC if (mod->isFIPS) { entry = FC_GetFunctionList; } else { entry = NSC_GetFunctionList; } if (mod->isModuleDB) { mod->moduleDBFunc = NSC_ModuleDBFunc; } #else /* * Loads softoken as a dynamic library, * even though the rest of NSS assumes this as the "internal" module. */ if (!softokenLib && PR_SUCCESS != PR_CallOnce(&loadSoftokenOnce, &softoken_LoadDSO)) return SECFailure; PR_ATOMIC_INCREMENT(&softokenLoadCount); if (mod->isFIPS) { entry = (CK_C_GetFunctionList) PR_FindSymbol(softokenLib, "FC_GetFunctionList"); } else { entry = (CK_C_GetFunctionList) PR_FindSymbol(softokenLib, "NSC_GetFunctionList"); } if (!entry) return SECFailure; if (mod->isModuleDB) { mod->moduleDBFunc = (CK_C_GetFunctionList) PR_FindSymbol(softokenLib, "NSC_ModuleDBFunc"); } #endif if (mod->moduleDBOnly) { mod->loaded = PR_TRUE; return SECSuccess; } } else { /* Not internal, load the DLL and look up C_GetFunctionList */ if (mod->dllName == NULL) { return SECFailure; } #if defined(NSS_STATIC) && !defined(NSS_DISABLE_ROOT_CERTS) if (strstr(mod->dllName, "nssckbi") != NULL) { mod->library = NULL; PORT_Assert(!mod->moduleDBOnly); entry = builtinsC_GetFunctionList; PORT_Assert(!mod->isModuleDB); goto library_loaded; } #endif /* load the library. If this succeeds, then we have to remember to * unload the library if anything goes wrong from here on out... */ library = PR_LoadLibrary(mod->dllName); mod->library = (void *)library; if (library == NULL) { return SECFailure; } /* * now we need to get the entry point to find the function pointers */ if (!mod->moduleDBOnly) { entry = (CK_C_GetFunctionList) PR_FindSymbol(library, "C_GetFunctionList"); } if (mod->isModuleDB) { mod->moduleDBFunc = (void *) PR_FindSymbol(library, "NSS_ReturnModuleSpecData"); } #if defined(NSS_STATIC) && !defined(NSS_DISABLE_ROOT_CERTS) library_loaded: #endif if (mod->moduleDBFunc == NULL) mod->isModuleDB = PR_FALSE; if (entry == NULL) { if (mod->isModuleDB) { mod->loaded = PR_TRUE; mod->moduleDBOnly = PR_TRUE; return SECSuccess; } PR_UnloadLibrary(library); return SECFailure; } } /* * We need to get the function list */ if ((*entry)((CK_FUNCTION_LIST_PTR *)&mod->functionList) != CKR_OK) goto fail; #ifdef DEBUG_MODULE if (PR_TRUE) { modToDBG = PR_GetEnv("NSS_DEBUG_PKCS11_MODULE"); if (modToDBG && strcmp(mod->commonName, modToDBG) == 0) { mod->functionList = (void *)nss_InsertDeviceLog( (CK_FUNCTION_LIST_PTR)mod->functionList); } } #endif mod->isThreadSafe = PR_TRUE; /* Now we initialize the module */ rv = secmod_ModuleInit(mod, oldModule, &alreadyLoaded); if (rv != SECSuccess) { goto fail; } /* module has been reloaded, this module itself is done, * return to the caller */ if (mod->functionList == NULL) { mod->loaded = PR_TRUE; /* technically the module is loaded.. */ return SECSuccess; } /* check the version number */ if (PK11_GETTAB(mod)->C_GetInfo(&info) != CKR_OK) goto fail2; if (info.cryptokiVersion.major != 2) goto fail2; /* all 2.0 are a priori *not* thread safe */ if (info.cryptokiVersion.minor < 1) { if (!loadSingleThreadedModules) { PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11); goto fail2; } else { mod->isThreadSafe = PR_FALSE; } } mod->cryptokiVersion = info.cryptokiVersion; /* If we don't have a common name, get it from the PKCS 11 module */ if ((mod->commonName == NULL) || (mod->commonName[0] == 0)) { mod->commonName = PK11_MakeString(mod->arena,NULL, (char *)info.libraryDescription, sizeof(info.libraryDescription)); if (mod->commonName == NULL) goto fail2; } /* initialize the Slots */ if (PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, NULL, &slotCount) == CKR_OK) { CK_SLOT_ID *slotIDs; int i; CK_RV crv; mod->slots = (PK11SlotInfo **)PORT_ArenaAlloc(mod->arena, sizeof(PK11SlotInfo *) * slotCount); if (mod->slots == NULL) goto fail2; slotIDs = (CK_SLOT_ID *) PORT_Alloc(sizeof(CK_SLOT_ID)*slotCount); if (slotIDs == NULL) { goto fail2; } crv = PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, slotIDs, &slotCount); if (crv != CKR_OK) { PORT_Free(slotIDs); goto fail2; } /* Initialize each slot */ for (i=0; i < (int)slotCount; i++) { mod->slots[i] = PK11_NewSlotInfo(mod); PK11_InitSlot(mod,slotIDs[i],mod->slots[i]); /* look down the slot info table */ PK11_LoadSlotList(mod->slots[i],mod->slotInfo,mod->slotInfoCount); SECMOD_SetRootCerts(mod->slots[i],mod); /* explicitly mark the internal slot as such if IsInternalKeySlot() * is set */ if (secmod_IsInternalKeySlot(mod) && (i == (mod->isFIPS ? 0 : 1))) { pk11_SetInternalKeySlotIfFirst(mod->slots[i]); } } mod->slotCount = slotCount; mod->slotInfoCount = 0; PORT_Free(slotIDs); } mod->loaded = PR_TRUE; mod->moduleID = nextModuleID++; return SECSuccess; fail2: if (enforceAlreadyInitializedError || (!alreadyLoaded)) { PK11_GETTAB(mod)->C_Finalize(NULL); } fail: mod->functionList = NULL; disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD"); if (library && !disableUnload) { PR_UnloadLibrary(library); } return SECFailure; }
SECStatus SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey, PRUint32 protocolmask, PRUint16 *ciphersuites, int nsuites, PRBool *pcanbypass, void *pwArg) { #ifdef NO_PKCS11_BYPASS if (!pcanbypass) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } *pcanbypass = PR_FALSE; return SECSuccess; #else SECStatus rv; int i; PRUint16 suite; PK11SymKey * pms = NULL; SECKEYPublicKey * srvPubkey = NULL; KeyType privKeytype; PK11SlotInfo * slot = NULL; SECItem param; CK_VERSION version; CK_MECHANISM_TYPE mechanism_array[2]; SECItem enc_pms = {siBuffer, NULL, 0}; PRBool isTLS = PR_FALSE; SSLCipherSuiteInfo csdef; PRBool testrsa = PR_FALSE; PRBool testrsa_export = PR_FALSE; PRBool testecdh = PR_FALSE; PRBool testecdhe = PR_FALSE; #ifdef NSS_ENABLE_ECC SECKEYECParams ecParams = { siBuffer, NULL, 0 }; #endif if (!cert || !srvPrivkey || !ciphersuites || !pcanbypass) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } srvPubkey = CERT_ExtractPublicKey(cert); if (!srvPubkey) return SECFailure; *pcanbypass = PR_TRUE; rv = SECFailure; /* determine which KEAs to test */ /* 0 (SSL_NULL_WITH_NULL_NULL) is used as a list terminator because * SSL3 and TLS specs forbid negotiating that cipher suite number. */ for (i=0; i < nsuites && (suite = *ciphersuites++) != 0; i++) { /* skip SSL2 cipher suites and ones NSS doesn't support */ if (SSL_GetCipherSuiteInfo(suite, &csdef, sizeof(csdef)) != SECSuccess || SSL_IS_SSL2_CIPHER(suite) ) continue; switch (csdef.keaType) { case ssl_kea_rsa: switch (csdef.cipherSuite) { case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA: case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA: case SSL_RSA_EXPORT_WITH_RC4_40_MD5: case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: testrsa_export = PR_TRUE; } if (!testrsa_export) testrsa = PR_TRUE; break; case ssl_kea_ecdh: if (strcmp(csdef.keaTypeName, "ECDHE") == 0) /* ephemeral? */ testecdhe = PR_TRUE; else testecdh = PR_TRUE; break; case ssl_kea_dh: /* this is actually DHE */ default: continue; } } /* For each protocol try to derive and extract an MS. * Failure of function any function except MS extract means * continue with the next cipher test. Stop testing when the list is * exhausted or when the first MS extract--not derive--fails. */ privKeytype = SECKEY_GetPrivateKeyType(srvPrivkey); protocolmask &= SSL_CBP_SSL3|SSL_CBP_TLS1_0; while (protocolmask) { if (protocolmask & SSL_CBP_SSL3) { isTLS = PR_FALSE; protocolmask ^= SSL_CBP_SSL3; } else { isTLS = PR_TRUE; protocolmask ^= SSL_CBP_TLS1_0; } if (privKeytype == rsaKey && testrsa_export) { if (PK11_GetPrivateModulusLen(srvPrivkey) > EXPORT_RSA_KEY_LENGTH) { *pcanbypass = PR_FALSE; rv = SECSuccess; break; } else testrsa = PR_TRUE; } for (; privKeytype == rsaKey && testrsa; ) { /* TLS_RSA */ unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH]; unsigned int outLen = 0; CK_MECHANISM_TYPE target; SECStatus irv; mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN; mechanism_array[1] = CKM_RSA_PKCS; slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg); if (slot == NULL) { PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND); break; } /* Generate the pre-master secret ... (client side) */ version.major = 3 /*MSB(clientHelloVersion)*/; version.minor = 0 /*LSB(clientHelloVersion)*/; param.data = (unsigned char *)&version; param.len = sizeof version; pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, ¶m, 0, pwArg); PK11_FreeSlot(slot); if (!pms) break; /* now wrap it */ enc_pms.len = SECKEY_PublicKeyStrength(srvPubkey); enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len); if (enc_pms.data == NULL) { PORT_SetError(PR_OUT_OF_MEMORY_ERROR); break; } irv = PK11_PubWrapSymKey(CKM_RSA_PKCS, srvPubkey, pms, &enc_pms); if (irv != SECSuccess) break; PK11_FreeSymKey(pms); pms = NULL; /* now do the server side--check the triple bypass first */ rv = PK11_PrivDecryptPKCS1(srvPrivkey, rsaPmsBuf, &outLen, sizeof rsaPmsBuf, (unsigned char *)enc_pms.data, enc_pms.len); /* if decrypt worked we're done with the RSA test */ if (rv == SECSuccess) { *pcanbypass = PR_TRUE; break; } /* check for fallback to double bypass */ target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE : CKM_SSL3_MASTER_KEY_DERIVE; pms = PK11_PubUnwrapSymKey(srvPrivkey, &enc_pms, target, CKA_DERIVE, 0); rv = ssl_canExtractMS(pms, isTLS, PR_FALSE, pcanbypass); if (rv == SECSuccess && *pcanbypass == PR_FALSE) goto done; break; } /* Check for NULL to avoid double free. * SECItem_FreeItem sets data NULL in secitem.c#265 */ if (enc_pms.data != NULL) { SECITEM_FreeItem(&enc_pms, PR_FALSE); } #ifdef NSS_ENABLE_ECC for (; (privKeytype == ecKey && ( testecdh || testecdhe)) || (privKeytype == rsaKey && testecdhe); ) { CK_MECHANISM_TYPE target; SECKEYPublicKey *keapub = NULL; SECKEYPrivateKey *keapriv; SECKEYPublicKey *cpub = NULL; /* client's ephemeral ECDH keys */ SECKEYPrivateKey *cpriv = NULL; SECKEYECParams *pecParams = NULL; if (privKeytype == ecKey && testecdhe) { /* TLS_ECDHE_ECDSA */ pecParams = &srvPubkey->u.ec.DEREncodedParams; } else if (privKeytype == rsaKey && testecdhe) { /* TLS_ECDHE_RSA */ ECName ec_curve; int serverKeyStrengthInBits; int signatureKeyStrength; int requiredECCbits; /* find a curve of equivalent strength to the RSA key's */ requiredECCbits = PK11_GetPrivateModulusLen(srvPrivkey); if (requiredECCbits < 0) break; requiredECCbits *= BPB; serverKeyStrengthInBits = srvPubkey->u.rsa.modulus.len; if (srvPubkey->u.rsa.modulus.data[0] == 0) { serverKeyStrengthInBits--; } /* convert to strength in bits */ serverKeyStrengthInBits *= BPB; signatureKeyStrength = SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits); if ( requiredECCbits > signatureKeyStrength ) requiredECCbits = signatureKeyStrength; ec_curve = ssl3_GetCurveWithECKeyStrength( ssl3_GetSupportedECCurveMask(NULL), requiredECCbits); rv = ssl3_ECName2Params(NULL, ec_curve, &ecParams); if (rv == SECFailure) { break; } pecParams = &ecParams; } if (testecdhe) { /* generate server's ephemeral keys */ keapriv = SECKEY_CreateECPrivateKey(pecParams, &keapub, NULL); if (!keapriv || !keapub) { if (keapriv) SECKEY_DestroyPrivateKey(keapriv); if (keapub) SECKEY_DestroyPublicKey(keapub); PORT_SetError(SEC_ERROR_KEYGEN_FAIL); rv = SECFailure; break; } } else { /* TLS_ECDH_ECDSA */ keapub = srvPubkey; keapriv = srvPrivkey; pecParams = &srvPubkey->u.ec.DEREncodedParams; } /* perform client side ops */ /* generate a pair of ephemeral keys using server's parms */ cpriv = SECKEY_CreateECPrivateKey(pecParams, &cpub, NULL); if (!cpriv || !cpub) { if (testecdhe) { SECKEY_DestroyPrivateKey(keapriv); SECKEY_DestroyPublicKey(keapub); } PORT_SetError(SEC_ERROR_KEYGEN_FAIL); rv = SECFailure; break; } /* now do the server side */ /* determine the PMS using client's public value */ target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE_DH : CKM_SSL3_MASTER_KEY_DERIVE_DH; pms = PK11_PubDeriveWithKDF(keapriv, cpub, PR_FALSE, NULL, NULL, CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, CKD_NULL, NULL, NULL); rv = ssl_canExtractMS(pms, isTLS, PR_TRUE, pcanbypass); SECKEY_DestroyPrivateKey(cpriv); SECKEY_DestroyPublicKey(cpub); if (testecdhe) { SECKEY_DestroyPrivateKey(keapriv); SECKEY_DestroyPublicKey(keapub); } if (rv == SECSuccess && *pcanbypass == PR_FALSE) goto done; break; } /* Check for NULL to avoid double free. */ if (ecParams.data != NULL) { PORT_Free(ecParams.data); ecParams.data = NULL; } #endif /* NSS_ENABLE_ECC */ if (pms) PK11_FreeSymKey(pms); } /* *pcanbypass has been set */ rv = SECSuccess; done: if (pms) PK11_FreeSymKey(pms); /* Check for NULL to avoid double free. * SECItem_FreeItem sets data NULL in secitem.c#265 */ if (enc_pms.data != NULL) { SECITEM_FreeItem(&enc_pms, PR_FALSE); } #ifdef NSS_ENABLE_ECC if (ecParams.data != NULL) { PORT_Free(ecParams.data); ecParams.data = NULL; } #endif /* NSS_ENABLE_ECC */ if (srvPubkey) { SECKEY_DestroyPublicKey(srvPubkey); srvPubkey = NULL; } return rv; #endif /* NO_PKCS11_BYPASS */ }
char * CERT_FormatName(CERTName *name) { CERTRDN **rdns; CERTRDN *rdn; CERTAVA **avas; CERTAVA *ava; char *buf = 0; char *tmpbuf = 0; SECItem *cn = 0; SECItem *email = 0; SECItem *org = 0; SECItem *loc = 0; SECItem *state = 0; SECItem *country = 0; SECItem *dq = 0; unsigned len = 0; int tag; int i; int ou_count = 0; int dc_count = 0; PRBool first; SECItem *orgunit[MAX_OUS]; SECItem *dc[MAX_DC]; /* Loop over name components and gather the interesting ones */ rdns = name->rdns; while ((rdn = *rdns++) != 0) { avas = rdn->avas; while ((ava = *avas++) != 0) { tag = CERT_GetAVATag(ava); switch (tag) { case SEC_OID_AVA_COMMON_NAME: if (cn) { break; } cn = CERT_DecodeAVAValue(&ava->value); if (!cn) { goto loser; } len += cn->len; break; case SEC_OID_AVA_COUNTRY_NAME: if (country) { break; } country = CERT_DecodeAVAValue(&ava->value); if (!country) { goto loser; } len += country->len; break; case SEC_OID_AVA_LOCALITY: if (loc) { break; } loc = CERT_DecodeAVAValue(&ava->value); if (!loc) { goto loser; } len += loc->len; break; case SEC_OID_AVA_STATE_OR_PROVINCE: if (state) { break; } state = CERT_DecodeAVAValue(&ava->value); if (!state) { goto loser; } len += state->len; break; case SEC_OID_AVA_ORGANIZATION_NAME: if (org) { break; } org = CERT_DecodeAVAValue(&ava->value); if (!org) { goto loser; } len += org->len; break; case SEC_OID_AVA_DN_QUALIFIER: if (dq) { break; } dq = CERT_DecodeAVAValue(&ava->value); if (!dq) { goto loser; } len += dq->len; break; case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME: if (ou_count < MAX_OUS) { orgunit[ou_count] = CERT_DecodeAVAValue(&ava->value); if (!orgunit[ou_count]) { goto loser; } len += orgunit[ou_count++]->len; } break; case SEC_OID_AVA_DC: if (dc_count < MAX_DC) { dc[dc_count] = CERT_DecodeAVAValue(&ava->value); if (!dc[dc_count]) { goto loser; } len += dc[dc_count++]->len; } break; case SEC_OID_PKCS9_EMAIL_ADDRESS: case SEC_OID_RFC1274_MAIL: if (email) { break; } email = CERT_DecodeAVAValue(&ava->value); if (!email) { goto loser; } len += email->len; break; default: break; } } } /* XXX - add some for formatting */ len += 128; /* allocate buffer */ buf = (char *)PORT_Alloc(len); if (!buf) { goto loser; } tmpbuf = buf; if (cn) { PORT_Memcpy(tmpbuf, cn->data, cn->len); tmpbuf += cn->len; PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } if (email) { PORT_Memcpy(tmpbuf, email->data, email->len); tmpbuf += (email->len); PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } for (i = ou_count - 1; i >= 0; i--) { PORT_Memcpy(tmpbuf, orgunit[i]->data, orgunit[i]->len); tmpbuf += (orgunit[i]->len); PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } if (dq) { PORT_Memcpy(tmpbuf, dq->data, dq->len); tmpbuf += (dq->len); PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } if (org) { PORT_Memcpy(tmpbuf, org->data, org->len); tmpbuf += (org->len); PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } for (i = dc_count - 1; i >= 0; i--) { PORT_Memcpy(tmpbuf, dc[i]->data, dc[i]->len); tmpbuf += (dc[i]->len); PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } first = PR_TRUE; if (loc) { PORT_Memcpy(tmpbuf, loc->data, loc->len); tmpbuf += (loc->len); first = PR_FALSE; } if (state) { if (!first) { PORT_Memcpy(tmpbuf, COMMA, COMMALEN); tmpbuf += COMMALEN; } PORT_Memcpy(tmpbuf, state->data, state->len); tmpbuf += (state->len); first = PR_FALSE; } if (country) { if (!first) { PORT_Memcpy(tmpbuf, COMMA, COMMALEN); tmpbuf += COMMALEN; } PORT_Memcpy(tmpbuf, country->data, country->len); tmpbuf += (country->len); first = PR_FALSE; } if (!first) { PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } *tmpbuf = 0; /* fall through and clean */ loser: if (cn) { SECITEM_FreeItem(cn, PR_TRUE); } if (email) { SECITEM_FreeItem(email, PR_TRUE); } for (i = ou_count - 1; i >= 0; i--) { SECITEM_FreeItem(orgunit[i], PR_TRUE); } if (dq) { SECITEM_FreeItem(dq, PR_TRUE); } if (org) { SECITEM_FreeItem(org, PR_TRUE); } for (i = dc_count - 1; i >= 0; i--) { SECITEM_FreeItem(dc[i], PR_TRUE); } if (loc) { SECITEM_FreeItem(loc, PR_TRUE); } if (state) { SECITEM_FreeItem(state, PR_TRUE); } if (country) { SECITEM_FreeItem(country, PR_TRUE); } return (buf); }
/* * SecCmsDigestContextStartMultiple - start digest calculation using all the * digest algorithms in "digestalgs" in parallel. */ SecCmsDigestContextRef SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) { SecCmsDigestContextRef cmsdigcx; CSSM_CC_HANDLE digobj; int digcnt; int i; digcnt = (digestalgs == NULL) ? 0 : SecCmsArrayCount((void **)digestalgs); cmsdigcx = (SecCmsDigestContextRef)PORT_Alloc(sizeof(struct SecCmsDigestContextStr)); if (cmsdigcx == NULL) return NULL; if (digcnt > 0) { /* Security check to prevent under-allocation */ if (digcnt >= (int)(INT_MAX/sizeof(CSSM_CC_HANDLE))) { goto loser; } cmsdigcx->digobjs = (CSSM_CC_HANDLE *)PORT_Alloc(digcnt * sizeof(CSSM_CC_HANDLE)); if (cmsdigcx->digobjs == NULL) goto loser; } cmsdigcx->digcnt = 0; /* * Create a digest object context for each algorithm. */ for (i = 0; i < digcnt; i++) { digobj = SecCmsUtilGetHashObjByAlgID(digestalgs[i]); /* * Skip any algorithm we do not even recognize; obviously, * this could be a problem, but if it is critical then the * result will just be that the signature does not verify. * We do not necessarily want to error out here, because * the particular algorithm may not actually be important, * but we cannot know that until later. */ if (digobj) { CSSM_RETURN result; result = CSSM_DigestDataInit(digobj); if (result != CSSM_OK) { goto loser; } } cmsdigcx->digobjs[cmsdigcx->digcnt] = digobj; cmsdigcx->digcnt++; } cmsdigcx->saw_contents = PR_FALSE; return cmsdigcx; loser: if (cmsdigcx) { if (cmsdigcx->digobjs) PORT_Free(cmsdigcx->digobjs); } return NULL; }
/* Time iter repetitions of operation op. */ SECStatus M_TimeOperation(void (*threadFunc)(void *), op_func opfunc, char *op, void *param1, void *param2, void *param3, int iters, int numThreads, PRLock *lock, CK_SESSION_HANDLE session, int isSign, double *rate) { double dUserTime; int i, total; PRIntervalTime startTime, totalTime; PRThread **threadIDs; ThreadData *threadData; pk11_op_func pk11_op = (pk11_op_func)opfunc; SECStatus rv; /* verify operation works before testing performance */ if (session) { rv = (*pk11_op)(session, param1, param2, param3); } else { rv = (*opfunc)(param1, param2, param3); } if (rv != SECSuccess) { SECU_PrintError("Error:", op); return rv; } /* get Data structures */ threadIDs = (PRThread **)PORT_Alloc(numThreads * sizeof(PRThread *)); threadData = (ThreadData *)PORT_Alloc(numThreads * sizeof(ThreadData)); startTime = PR_Now(); if (numThreads == 1) { for (i = 0; i < iters; i++) { if (session) { rv = (*pk11_op)(session, param1, param2, param3); } else { rv = (*opfunc)(param1, param2, param3); } if (rv != SECSuccess) { PORT_Free(threadIDs); PORT_Free(threadData); SECU_PrintError("Error:", op); return rv; } } total = iters; } else { for (i = 0; i < numThreads; i++) { threadData[i].op = opfunc; threadData[i].p1 = (void *)param1; threadData[i].p2 = (void *)param2; threadData[i].p3 = (void *)param3; threadData[i].iters = iters; threadData[i].lock = lock; threadData[i].isSign = isSign; threadIDs[i] = PR_CreateThread(PR_USER_THREAD, threadFunc, (void *)&threadData[i], PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); } total = 0; for (i = 0; i < numThreads; i++) { PR_JoinThread(threadIDs[i]); /* check the status */ total += threadData[i].count; } } totalTime = PR_Now() - startTime; /* SecondsToInterval seems to be broken here ... */ dUserTime = (double)totalTime / (double)1000000; if (dUserTime) { printf(" %-15s count:%4d sec: %3.2f op/sec: %6.2f\n", op, total, dUserTime, (double)total / dUserTime); if (rate) { *rate = ((double)total) / dUserTime; } } PORT_Free(threadIDs); PORT_Free(threadData); return SECSuccess; }
int main(int argc, char **argv) { char *progName; FILE *inFile, *outFile; CERTCertDBHandle *certHandle; struct recipient *recipients, *rcpt; PLOptState *optstate; PLOptStatus status; SECStatus rv; progName = strrchr(argv[0], '/'); progName = progName ? progName + 1 : argv[0]; inFile = NULL; outFile = NULL; recipients = NULL; rcpt = NULL; /* * Parse command line arguments * XXX This needs to be enhanced to allow selection of algorithms * and key sizes (or to look up algorithms and key sizes for each * recipient in the magic database). */ optstate = PL_CreateOptState(argc, argv, "d:i:o:r:"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case '?': Usage(progName); break; case 'd': SECU_ConfigDirectory(optstate->value); break; case 'i': inFile = fopen(optstate->value, "r"); if (!inFile) { fprintf(stderr, "%s: unable to open \"%s\" for reading\n", progName, optstate->value); return -1; } break; case 'o': outFile = fopen(optstate->value, "wb"); if (!outFile) { fprintf(stderr, "%s: unable to open \"%s\" for writing\n", progName, optstate->value); return -1; } break; case 'r': if (rcpt == NULL) { recipients = rcpt = PORT_Alloc(sizeof(struct recipient)); } else { rcpt->next = PORT_Alloc(sizeof(struct recipient)); rcpt = rcpt->next; } if (rcpt == NULL) { fprintf(stderr, "%s: unable to allocate recipient struct\n", progName); return -1; } rcpt->nickname = PORT_Strdup(optstate->value); rcpt->cert = NULL; rcpt->next = NULL; break; } } PL_DestroyOptState(optstate); if (!recipients) Usage(progName); if (!inFile) inFile = stdin; if (!outFile) outFile = stdout; /* Call the NSS initialization routines */ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); rv = NSS_Init(SECU_ConfigDirectory(NULL)); if (rv != SECSuccess) { SECU_PrintPRandOSError(progName); return -1; } /* open cert database */ certHandle = CERT_GetDefaultCertDB(); if (certHandle == NULL) { return -1; } /* find certs */ for (rcpt = recipients; rcpt != NULL; rcpt = rcpt->next) { rcpt->cert = CERT_FindCertByNickname(certHandle, rcpt->nickname); if (rcpt->cert == NULL) { SECU_PrintError(progName, "the cert for name \"%s\" not found in database", rcpt->nickname); return -1; } } if (EncryptFile(outFile, inFile, recipients, progName)) { SECU_PrintError(progName, "problem encrypting data"); return -1; } /* free certs */ for (rcpt = recipients; rcpt != NULL; ) { struct recipient *next = rcpt->next; CERT_DestroyCertificate(rcpt->cert); PORT_Free(rcpt->nickname); PORT_Free(rcpt); rcpt = next; } if (inFile && inFile != stdin) { fclose(inFile); } if (outFile && outFile != stdout) { fclose(outFile); } if (NSS_Shutdown() != SECSuccess) { SECU_PrintError(progName, "NSS shutdown:"); return -1; } return 0; }
NS_IMETHODIMP nsNSSCertificateDB::ImportServerCertificate(PRUint8 * data, PRUint32 length, nsIInterfaceRequestor *ctx) { nsNSSShutDownPreventionLock locker; SECStatus srv = SECFailure; nsresult nsrv = NS_OK; CERTCertificate * cert; SECItem **rawCerts = nsnull; int numcerts; int i; nsNSSCertTrust trust; char *serverNickname = nsnull; PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) return NS_ERROR_OUT_OF_MEMORY; CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length); if (!certCollection) { PORT_FreeArena(arena, PR_FALSE); return NS_ERROR_FAILURE; } cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), certCollection->rawCerts, (char *)NULL, PR_FALSE, PR_TRUE); if (!cert) { nsrv = NS_ERROR_FAILURE; goto loser; } numcerts = certCollection->numcerts; rawCerts = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts); if ( !rawCerts ) { nsrv = NS_ERROR_FAILURE; goto loser; } for ( i = 0; i < numcerts; i++ ) { rawCerts[i] = &certCollection->rawCerts[i]; } serverNickname = nsNSSCertificate::defaultServerNickname(cert); srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageSSLServer, numcerts, rawCerts, NULL, PR_TRUE, PR_FALSE, serverNickname); PR_FREEIF(serverNickname); if ( srv != SECSuccess ) { nsrv = NS_ERROR_FAILURE; goto loser; } trust.SetValidServerPeer(); srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, trust.GetTrust()); if ( srv != SECSuccess ) { nsrv = NS_ERROR_FAILURE; goto loser; } loser: PORT_Free(rawCerts); if (cert) CERT_DestroyCertificate(cert); if (arena) PORT_FreeArena(arena, PR_TRUE); return nsrv; }
/* * [noscript] void importEmailCertificates(in charPtr data, in unsigned long length, * in nsIInterfaceRequestor ctx); */ NS_IMETHODIMP nsNSSCertificateDB::ImportEmailCertificate(PRUint8 * data, PRUint32 length, nsIInterfaceRequestor *ctx) { nsNSSShutDownPreventionLock locker; SECStatus srv = SECFailure; nsresult nsrv = NS_OK; CERTCertDBHandle *certdb; CERTCertificate **certArray = NULL; CERTCertList *certList = NULL; CERTCertListNode *node; PRTime now; SECCertUsage certusage; SECItem **rawArray; int numcerts; int i; PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) return NS_ERROR_OUT_OF_MEMORY; CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length); if (!certCollection) { PORT_FreeArena(arena, PR_FALSE); return NS_ERROR_FAILURE; } certdb = CERT_GetDefaultCertDB(); certusage = certUsageEmailRecipient; numcerts = certCollection->numcerts; rawArray = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts); if ( !rawArray ) { nsrv = NS_ERROR_FAILURE; goto loser; } for (i=0; i < numcerts; i++) { rawArray[i] = &certCollection->rawCerts[i]; } srv = CERT_ImportCerts(certdb, certusage, numcerts, rawArray, &certArray, PR_FALSE, PR_FALSE, NULL); PORT_Free(rawArray); rawArray = NULL; if (srv != SECSuccess) { nsrv = NS_ERROR_FAILURE; goto loser; } // build a CertList for filtering certList = CERT_NewCertList(); if (certList == NULL) { nsrv = NS_ERROR_FAILURE; goto loser; } for (i=0; i < numcerts; i++) { CERTCertificate *cert = certArray[i]; if (cert) cert = CERT_DupCertificate(cert); if (cert) CERT_AddCertToListTail(certList, cert); } /* go down the remaining list of certs and verify that they have * valid chains, then import them. */ now = PR_Now(); for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node,certList); node = CERT_LIST_NEXT(node)) { bool alert_and_skip = false; if (!node->cert) { continue; } if (CERT_VerifyCert(certdb, node->cert, PR_TRUE, certusage, now, ctx, NULL) != SECSuccess) { alert_and_skip = true; } CERTCertificateList *certChain = nsnull; CERTCertificateListCleaner chainCleaner(certChain); if (!alert_and_skip) { certChain = CERT_CertChainFromCert(node->cert, certusage, PR_FALSE); if (!certChain) { alert_and_skip = true; } } if (alert_and_skip) { nsCOMPtr<nsIX509Cert> certToShow = new nsNSSCertificate(node->cert); DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow); continue; } /* * CertChain returns an array of SECItems, import expects an array of * SECItem pointers. Create the SECItem Pointers from the array of * SECItems. */ rawArray = (SECItem **) PORT_Alloc(certChain->len * sizeof(SECItem *)); if (!rawArray) { continue; } for (i=0; i < certChain->len; i++) { rawArray[i] = &certChain->certs[i]; } CERT_ImportCerts(certdb, certusage, certChain->len, rawArray, NULL, PR_TRUE, PR_FALSE, NULL); CERT_SaveSMimeProfile(node->cert, NULL, NULL); PORT_Free(rawArray); } loser: if (certArray) { CERT_DestroyCertArray(certArray, numcerts); } if (certList) { CERT_DestroyCertList(certList); } if (arena) PORT_FreeArena(arena, PR_TRUE); return nsrv; }
/* Computes the ECDSA signature (a concatenation of two values r and s) * on the digest using the given key and the random value kb (used in * computing s). */ SECStatus ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, const SECItem *digest, const unsigned char *kb, const int kblen) { SECStatus rv = SECFailure; #ifdef NSS_ENABLE_ECC mp_int x1; mp_int d, k; /* private key, random integer */ mp_int r, s; /* tuple (r, s) is the signature */ mp_int n; mp_err err = MP_OKAY; ECParams *ecParams = NULL; SECItem kGpoint = { siBuffer, NULL, 0}; int flen = 0; /* length in bytes of the field size */ unsigned olen; /* length in bytes of the base point order */ unsigned obits; /* length in bits of the base point order */ #if EC_DEBUG char mpstr[256]; #endif /* Initialize MPI integers. */ /* must happen before the first potential call to cleanup */ MP_DIGITS(&x1) = 0; MP_DIGITS(&d) = 0; MP_DIGITS(&k) = 0; MP_DIGITS(&r) = 0; MP_DIGITS(&s) = 0; MP_DIGITS(&n) = 0; /* Check args */ if (!key || !signature || !digest || !kb || (kblen < 0)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); goto cleanup; } ecParams = &(key->ecParams); flen = (ecParams->fieldID.size + 7) >> 3; olen = ecParams->order.len; if (signature->data == NULL) { /* a call to get the signature length only */ goto finish; } if (signature->len < 2*olen) { PORT_SetError(SEC_ERROR_OUTPUT_LEN); goto cleanup; } CHECK_MPI_OK( mp_init(&x1) ); CHECK_MPI_OK( mp_init(&d) ); CHECK_MPI_OK( mp_init(&k) ); CHECK_MPI_OK( mp_init(&r) ); CHECK_MPI_OK( mp_init(&s) ); CHECK_MPI_OK( mp_init(&n) ); SECITEM_TO_MPINT( ecParams->order, &n ); SECITEM_TO_MPINT( key->privateValue, &d ); CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) ); /* Make sure k is in the interval [1, n-1] */ if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) { #if EC_DEBUG printf("k is outside [1, n-1]\n"); mp_tohex(&k, mpstr); printf("k : %s \n", mpstr); mp_tohex(&n, mpstr); printf("n : %s \n", mpstr); #endif PORT_SetError(SEC_ERROR_NEED_RANDOM); goto cleanup; } /* ** We do not want timing information to leak the length of k, ** so we compute k*G using an equivalent scalar of fixed ** bit-length. ** Fix based on patch for ECDSA timing attack in the paper ** by Billy Bob Brumley and Nicola Tuveri at ** http://eprint.iacr.org/2011/232 ** ** How do we convert k to a value of a fixed bit-length? ** k starts off as an integer satisfying 0 <= k < n. Hence, ** n <= k+n < 2n, which means k+n has either the same number ** of bits as n or one more bit than n. If k+n has the same ** number of bits as n, the second addition ensures that the ** final value has exactly one more bit than n. Thus, we ** always end up with a value that exactly one more bit than n. */ CHECK_MPI_OK( mp_add(&k, &n, &k) ); if (mpl_significant_bits(&k) <= mpl_significant_bits(&n)) { CHECK_MPI_OK( mp_add(&k, &n, &k) ); } /* ** ANSI X9.62, Section 5.3.2, Step 2 ** ** Compute kG */ kGpoint.len = 2*flen + 1; kGpoint.data = PORT_Alloc(2*flen + 1); if ((kGpoint.data == NULL) || (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint) != SECSuccess)) goto cleanup; /* ** ANSI X9.62, Section 5.3.3, Step 1 ** ** Extract the x co-ordinate of kG into x1 */ CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1, (mp_size) flen) ); /* ** ANSI X9.62, Section 5.3.3, Step 2 ** ** r = x1 mod n NOTE: n is the order of the curve */ CHECK_MPI_OK( mp_mod(&x1, &n, &r) ); /* ** ANSI X9.62, Section 5.3.3, Step 3 ** ** verify r != 0 */ if (mp_cmp_z(&r) == 0) { PORT_SetError(SEC_ERROR_NEED_RANDOM); goto cleanup; } /* ** ANSI X9.62, Section 5.3.3, Step 4 ** ** s = (k**-1 * (HASH(M) + d*r)) mod n */ SECITEM_TO_MPINT(*digest, &s); /* s = HASH(M) */ /* In the definition of EC signing, digests are truncated * to the length of n in bits. * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/ CHECK_MPI_OK( (obits = mpl_significant_bits(&n)) ); if (digest->len*8 > obits) { mpl_rsh(&s,&s,digest->len*8 - obits); } #if EC_DEBUG mp_todecimal(&n, mpstr); printf("n : %s (dec)\n", mpstr); mp_todecimal(&d, mpstr); printf("d : %s (dec)\n", mpstr); mp_tohex(&x1, mpstr); printf("x1: %s\n", mpstr); mp_todecimal(&s, mpstr); printf("digest: %s (decimal)\n", mpstr); mp_todecimal(&r, mpstr); printf("r : %s (dec)\n", mpstr); mp_tohex(&r, mpstr); printf("r : %s\n", mpstr); #endif CHECK_MPI_OK( mp_invmod(&k, &n, &k) ); /* k = k**-1 mod n */ CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) ); /* d = d * r mod n */ CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) ); /* s = s + d mod n */ CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) ); /* s = s * k mod n */ #if EC_DEBUG mp_todecimal(&s, mpstr); printf("s : %s (dec)\n", mpstr); mp_tohex(&s, mpstr); printf("s : %s\n", mpstr); #endif /* ** ANSI X9.62, Section 5.3.3, Step 5 ** ** verify s != 0 */ if (mp_cmp_z(&s) == 0) { PORT_SetError(SEC_ERROR_NEED_RANDOM); goto cleanup; } /* ** ** Signature is tuple (r, s) */ CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) ); CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) ); finish: signature->len = 2*olen; rv = SECSuccess; err = MP_OKAY; cleanup: mp_clear(&x1); mp_clear(&d); mp_clear(&k); mp_clear(&r); mp_clear(&s); mp_clear(&n); if (kGpoint.data) { PORT_ZFree(kGpoint.data, 2*flen + 1); } if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } #if EC_DEBUG printf("ECDSA signing with seed %s\n", (rv == SECSuccess) ? "succeeded" : "failed"); #endif #else PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); #endif /* NSS_ENABLE_ECC */ return rv; }
/* ** Performs an ECDH key derivation by computing the scalar point ** multiplication of privateValue and publicValue (with or without the ** cofactor) and returns the x-coordinate of the resulting elliptic ** curve point in derived secret. If successful, derivedSecret->data ** is set to the address of the newly allocated buffer containing the ** derived secret, and derivedSecret->len is the size of the secret ** produced. It is the caller's responsibility to free the allocated ** buffer containing the derived secret. */ SECStatus ECDH_Derive(SECItem *publicValue, ECParams *ecParams, SECItem *privateValue, PRBool withCofactor, SECItem *derivedSecret) { SECStatus rv = SECFailure; #ifdef NSS_ENABLE_ECC unsigned int len = 0; SECItem pointQ = {siBuffer, NULL, 0}; mp_int k; /* to hold the private value */ mp_int cofactor; mp_err err = MP_OKAY; #if EC_DEBUG int i; #endif if (!publicValue || !ecParams || !privateValue || !derivedSecret) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } MP_DIGITS(&k) = 0; memset(derivedSecret, 0, sizeof *derivedSecret); len = (ecParams->fieldID.size + 7) >> 3; pointQ.len = 2*len + 1; if ((pointQ.data = PORT_Alloc(2*len + 1)) == NULL) goto cleanup; CHECK_MPI_OK( mp_init(&k) ); CHECK_MPI_OK( mp_read_unsigned_octets(&k, privateValue->data, (mp_size) privateValue->len) ); if (withCofactor && (ecParams->cofactor != 1)) { /* multiply k with the cofactor */ MP_DIGITS(&cofactor) = 0; CHECK_MPI_OK( mp_init(&cofactor) ); mp_set(&cofactor, ecParams->cofactor); CHECK_MPI_OK( mp_mul(&k, &cofactor, &k) ); } /* Multiply our private key and peer's public point */ if (ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ) != SECSuccess) goto cleanup; if (ec_point_at_infinity(&pointQ)) { PORT_SetError(SEC_ERROR_BAD_KEY); /* XXX better error code? */ goto cleanup; } /* Allocate memory for the derived secret and copy * the x co-ordinate of pointQ into it. */ SECITEM_AllocItem(NULL, derivedSecret, len); memcpy(derivedSecret->data, pointQ.data + 1, len); rv = SECSuccess; #if EC_DEBUG printf("derived_secret:\n"); for (i = 0; i < derivedSecret->len; i++) printf("%02x:", derivedSecret->data[i]); printf("\n"); #endif cleanup: mp_clear(&k); if (err) { MP_TO_SEC_ERROR(err); } if (pointQ.data) { PORT_ZFree(pointQ.data, 2*len + 1); } #else PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); #endif /* NSS_ENABLE_ECC */ return rv; }