PRStatus PR_CALLBACK nsNSSComponent::IdentityInfoInit() { for (size_t iEV=0; iEV < (sizeof(myTrustedEVInfos)/sizeof(nsMyTrustedEVInfo)); ++iEV) { nsMyTrustedEVInfo &entry = myTrustedEVInfos[iEV]; if (!entry.oid_name) // invalid or placeholder list entry continue; SECStatus rv; CERTIssuerAndSN ias; rv = ATOB_ConvertAsciiToItem(&ias.derIssuer, const_cast<char*>(entry.issuer_base64)); NS_ASSERTION(rv==SECSuccess, "error converting ascii to binary."); rv = ATOB_ConvertAsciiToItem(&ias.serialNumber, const_cast<char*>(entry.serial_base64)); NS_ASSERTION(rv==SECSuccess, "error converting ascii to binary."); entry.cert = CERT_FindCertByIssuerAndSN(nsnull, &ias); NS_ASSERTION(entry.cert, "Could not find EV root in NSS storage"); if (!entry.cert) continue; nsNSSCertificate c(entry.cert); nsAutoString fingerprint; c.GetSha1Fingerprint(fingerprint); NS_ConvertASCIItoUTF16 sha1(entry.ev_root_sha1_fingerprint); if (sha1 != fingerprint) { NS_ASSERTION(sha1 == fingerprint, "found EV root with unexpected SHA1 mismatch"); CERT_DestroyCertificate(entry.cert); entry.cert = nsnull; continue; } SECItem ev_oid_item; ev_oid_item.data = nsnull; ev_oid_item.len = 0; SECStatus srv = SEC_StringToOID(nsnull, &ev_oid_item, entry.dotted_oid, 0); if (srv != SECSuccess) continue; entry.oid_tag = register_oid(&ev_oid_item, entry.oid_name); SECITEM_FreeItem(&ev_oid_item, PR_FALSE); } #ifdef PSM_ENABLE_TEST_EV_ROOTS if (!testEVInfosLoaded) { testEVInfosLoaded = PR_TRUE; testEVInfos = new testEVArray; if (testEVInfos) { loadTestEVInfos(); } } #endif return PR_SUCCESS; }
char *oauth_sign_rsa_sha1 (const char *m, const char *k) { PK11SlotInfo *slot = NULL; SECKEYPrivateKey *pkey = NULL; SECItem signature; SECStatus s; SECItem der; char *rv=NULL; char *key = oauth_strip_pkcs(k, NS_PRIV_HEADER, NS_PRIV_TRAILER); if (!key) return NULL; oauth_init_nss(); slot = PK11_GetInternalKeySlot(); if (!slot) goto looser; s = ATOB_ConvertAsciiToItem(&der, key); if (s != SECSuccess) goto looser; s = PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, &der, NULL, NULL, PR_FALSE, PR_TRUE, KU_ALL, &pkey, NULL); SECITEM_FreeItem(&der, PR_FALSE); if (s != SECSuccess) goto looser; if (!pkey) goto looser; if (pkey->keyType != rsaKey) goto looser; s = SEC_SignData(&signature, (unsigned char*) m, strlen(m), pkey, SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE); if (s != SECSuccess) goto looser; rv=oauth_encode_base64(signature.len, signature.data); SECITEM_FreeItem(&signature, PR_FALSE); looser: if (pkey) SECKEY_DestroyPrivateKey(pkey); if (slot) PK11_FreeSlot(slot); free(key); return rv; }
static SECStatus nss_load_crl(const char* crlfilename) { PRFileDesc *infile; PRFileInfo info; SECItem filedata = { 0, NULL, 0 }; SECItem crlDER = { 0, NULL, 0 }; char *body; infile = PR_Open(crlfilename, PR_RDONLY, 0); if(!infile) return SECFailure; if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info)) goto fail; if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1)) goto fail; if(info.size != PR_Read(infile, filedata.data, info.size)) goto fail; /* place a trailing zero right after the visible data */ body = (char*)filedata.data; body[--filedata.len] = '\0'; body = strstr(body, "-----BEGIN"); if(body) { /* assume ASCII */ char *trailer; char *begin = PORT_Strchr(body, '\n'); if(!begin) begin = PORT_Strchr(body, '\r'); if(!begin) goto fail; trailer = strstr(++begin, "-----END"); if(!trailer) goto fail; /* retrieve DER from ASCII */ *trailer = '\0'; if(ATOB_ConvertAsciiToItem(&crlDER, begin)) goto fail; SECITEM_FreeItem(&filedata, PR_FALSE); } else /* assume DER */ crlDER = filedata; PR_Close(infile); return nss_cache_crl(&crlDER); fail: PR_Close(infile); SECITEM_FreeItem(&filedata, PR_FALSE); return SECFailure; }
SECStatus SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii) { SECStatus rv; if (ascii) { /* First convert ascii to binary */ SECItem filedata; char *asc, *body; /* Read in ascii data */ rv = SECU_FileToItem(&filedata, inFile); asc = (char *)filedata.data; if (!asc) { fprintf(stderr, "unable to read data from input file\n"); return SECFailure; } /* check for headers and trailers and remove them */ if ((body = strstr(asc, "-----BEGIN")) != NULL) { char *trailer = NULL; asc = body; body = PORT_Strchr(body, '\n'); if (!body) body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */ if (body) trailer = strstr(++body, "-----END"); if (trailer != NULL) { *trailer = '\0'; } else { fprintf(stderr, "input has header but no trailer\n"); PORT_Free(filedata.data); return SECFailure; } } else { body = asc; } /* Convert to binary */ rv = ATOB_ConvertAsciiToItem(der, body); if (rv) { fprintf(stderr, "error converting ascii to binary (%d)\n", PORT_GetError()); PORT_Free(filedata.data); return SECFailure; } PORT_Free(filedata.data); } else { /* Read in binary der */ rv = SECU_FileToItem(der, inFile); if (rv) { fprintf(stderr, "error converting der (%d)\n", PORT_GetError()); return SECFailure; } } return SECSuccess; }
UtlBoolean SmimeBody::convertPemToDer(UtlString& pemData, UtlString& derData) { UtlBoolean conversionSucceeded = FALSE; derData.remove(0); #ifdef ENABLE_NSS_SMIME // Code from NSS secutil.c char* body = NULL; char* pemDataPtr = (char*) pemData.data(); /* check for headers and trailers and remove them */ if ((body = strstr(pemDataPtr, "-----BEGIN")) != NULL) { char *trailer = NULL; pemData = strdup(body); body = PORT_Strchr(body, '\n'); if (!body) body = PORT_Strchr(pemDataPtr, '\r'); /* maybe this is a MAC file */ if (body) trailer = strstr(++body, "-----END"); if (trailer != NULL) { *trailer = '\0'; } else { Os::Logger::instance().log(FAC_SIP, PRI_ERR, "input has header but no trailer\n"); } } else { body = pemDataPtr; } /* Convert to binary */ SECItem derItem; derItem.data = NULL; derItem.len = 0; if(ATOB_ConvertAsciiToItem(&derItem, body)) { Os::Logger::instance().log(FAC_SIP, PRI_ERR, "error converting PEM base64 data to binary"); } else { derData.append(((char*)derItem.data), derItem.len); conversionSucceeded = TRUE; } #else Os::Logger::instance().log(FAC_SIP, PRI_ERR, "SmimeBody::convertPemToDer implemented with NSS and OpenSSL disabled"); #endif return(conversionSucceeded); }
int oauth_verify_rsa_sha1 (const char *m, const char *c, const char *sig) { PK11SlotInfo *slot = NULL; SECKEYPublicKey *pkey = NULL; CERTCertificate *cert = NULL; SECItem signature; SECStatus s; SECItem der; int rv=0; char *key = oauth_strip_pkcs(c, NS_CERT_HEADER, NS_CERT_TRAILER); if (!key) return 0; oauth_init_nss(); s = ATOB_ConvertAsciiToItem(&signature, (char*) sig); // XXX cast (const char*) -> (char*) if (s != SECSuccess) goto looser; slot = PK11_GetInternalKeySlot(); if (!slot) goto looser; s = ATOB_ConvertAsciiToItem(&der, key); if (s != SECSuccess) goto looser; cert = __CERT_DecodeDERCertificate(&der, PR_TRUE, NULL); SECITEM_FreeItem(&der, PR_FALSE); if (!cert) goto looser; pkey = CERT_ExtractPublicKey(cert); if (!pkey) goto looser; if (pkey->keyType != rsaKey) goto looser; s = VFY_VerifyData((unsigned char*) m, strlen(m), pkey, &signature, SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE, NULL); if (s == SECSuccess) rv=1; #if 0 else if (PR_GetError()!= SEC_ERROR_BAD_SIGNATURE) rv=-1; #endif looser: if (pkey) SECKEY_DestroyPublicKey(pkey); if (slot) PK11_FreeSlot(slot); free(key); return rv; }
CERTCertificate * CERT_ConvertAndDecodeCertificate(char *certstr) { CERTCertificate *cert; SECStatus rv; SECItem der; rv = ATOB_ConvertAsciiToItem(&der, certstr); if (rv != SECSuccess) return NULL; cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der, NULL, PR_FALSE, PR_TRUE); PORT_Free(der.data); return cert; }
/* Modified from NSS source */ SECStatus SECU_ReadDER(SECItem *der, std::string data) { SECStatus rv; /* First convert ascii to binary */ //SECItem filedata; char *asc, *body; /* Read in ascii data */ asc = const_cast<char*>(data.data()); if (!asc) { fprintf(stderr, "unable to read data from input file\n"); return SECFailure; } /* check for headers and trailers and remove them */ if ((body = strstr(asc, "-----BEGIN")) != NULL) { char *trailer = NULL; asc = body; body = PORT_Strchr(body, '\n'); if (!body) body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */ if (body) trailer = strstr(++body, "-----END"); if (trailer != NULL) { *trailer = '\0'; } else { fprintf(stderr, "input has header but no trailer\n"); return SECFailure; } } else { body = asc; } /* Convert to binary */ rv = ATOB_ConvertAsciiToItem(der, body); if (rv) { return SECFailure; } return SECSuccess; }
static void loadTestEVInfos() { if (!testEVInfos) return; testEVInfos->Clear(); char *env_val = getenv("ENABLE_TEST_EV_ROOTS_FILE"); if (!env_val) return; int enabled_val = atoi(env_val); if (!enabled_val) return; nsCOMPtr<nsIFile> aFile; NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(aFile)); if (!aFile) return; aFile->AppendNative(NS_LITERAL_CSTRING(kTestEVRootsFileName)); nsresult rv; nsCOMPtr<nsIInputStream> fileInputStream; rv = NS_NewLocalFileInputStream(getter_AddRefs(fileInputStream), aFile); if (NS_FAILED(rv)) return; nsCOMPtr<nsILineInputStream> lineInputStream = do_QueryInterface(fileInputStream, &rv); if (NS_FAILED(rv)) return; nsCAutoString buffer; PRBool isMore = PR_TRUE; /* file format * * file format must be strictly followed * strings in file must be UTF-8 * each record consists of multiple lines * each line consists of a descriptor, a single space, and the data * the descriptors are: * 1_fingerprint (in format XX:XX:XX:...) * 2_readable_oid (treated as a comment) * the input file must strictly follow this order * the input file may contain 0, 1 or many records * completely empty lines are ignored * lines that start with the # char are ignored */ int line_counter = 0; PRBool found_error = PR_FALSE; enum { pos_fingerprint, pos_readable_oid, pos_issuer, pos_serial } reader_position = pos_fingerprint; nsCString fingerprint, readable_oid, issuer, serial; while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore))) { ++line_counter; if (buffer.IsEmpty() || buffer.First() == '#') { continue; } PRInt32 seperatorIndex = buffer.FindChar(' ', 0); if (seperatorIndex == 0) { found_error = PR_TRUE; break; } const nsASingleFragmentCString &descriptor = Substring(buffer, 0, seperatorIndex); const nsASingleFragmentCString &data = Substring(buffer, seperatorIndex + 1, buffer.Length() - seperatorIndex + 1); if (reader_position == pos_fingerprint && descriptor.EqualsLiteral(("1_fingerprint"))) { fingerprint = data; reader_position = pos_readable_oid; continue; } else if (reader_position == pos_readable_oid && descriptor.EqualsLiteral(("2_readable_oid"))) { readable_oid = data; reader_position = pos_issuer; continue; } else if (reader_position == pos_issuer && descriptor.EqualsLiteral(("3_issuer"))) { issuer = data; reader_position = pos_serial; continue; } else if (reader_position == pos_serial && descriptor.EqualsLiteral(("4_serial"))) { serial = data; reader_position = pos_fingerprint; } else { found_error = PR_TRUE; break; } nsMyTrustedEVInfoClass *temp_ev = new nsMyTrustedEVInfoClass; if (!temp_ev) return; temp_ev->ev_root_sha1_fingerprint = strdup(fingerprint.get()); temp_ev->oid_name = strdup(readable_oid.get()); temp_ev->dotted_oid = strdup(readable_oid.get()); temp_ev->issuer_base64 = strdup(issuer.get()); temp_ev->serial_base64 = strdup(serial.get()); SECStatus rv; CERTIssuerAndSN ias; rv = ATOB_ConvertAsciiToItem(&ias.derIssuer, const_cast<char*>(temp_ev->issuer_base64)); NS_ASSERTION(rv==SECSuccess, "error converting ascii to binary."); rv = ATOB_ConvertAsciiToItem(&ias.serialNumber, const_cast<char*>(temp_ev->serial_base64)); NS_ASSERTION(rv==SECSuccess, "error converting ascii to binary."); temp_ev->cert = CERT_FindCertByIssuerAndSN(nsnull, &ias); NS_ASSERTION(temp_ev->cert, "Could not find EV root in NSS storage"); if (!temp_ev->cert) return; nsNSSCertificate c(temp_ev->cert); nsAutoString fingerprint; c.GetSha1Fingerprint(fingerprint); NS_ConvertASCIItoUTF16 sha1(temp_ev->ev_root_sha1_fingerprint); if (sha1 != fingerprint) { NS_ASSERTION(sha1 == fingerprint, "found EV root with unexpected SHA1 mismatch"); CERT_DestroyCertificate(temp_ev->cert); temp_ev->cert = nsnull; return; } SECItem ev_oid_item; ev_oid_item.data = nsnull; ev_oid_item.len = 0; SECStatus srv = SEC_StringToOID(nsnull, &ev_oid_item, readable_oid.get(), readable_oid.Length()); if (srv != SECSuccess) { delete temp_ev; found_error = PR_TRUE; break; } temp_ev->oid_tag = register_oid(&ev_oid_item, temp_ev->oid_name); SECITEM_FreeItem(&ev_oid_item, PR_FALSE); testEVInfos->AppendElement(temp_ev); } if (found_error) { fprintf(stderr, "invalid line %d in test_ev_roots file\n", line_counter); } }
static PRStatus IdentityInfoInit() { for (size_t iEV = 0; iEV < PR_ARRAY_SIZE(myTrustedEVInfos); ++iEV) { nsMyTrustedEVInfo& entry = myTrustedEVInfos[iEV]; SECStatus rv; CERTIssuerAndSN ias; rv = ATOB_ConvertAsciiToItem(&ias.derIssuer, const_cast<char*>(entry.issuer_base64)); PR_ASSERT(rv == SECSuccess); if (rv != SECSuccess) { return PR_FAILURE; } rv = ATOB_ConvertAsciiToItem(&ias.serialNumber, const_cast<char*>(entry.serial_base64)); PR_ASSERT(rv == SECSuccess); if (rv != SECSuccess) { SECITEM_FreeItem(&ias.derIssuer, false); return PR_FAILURE; } ias.serialNumber.type = siUnsignedInteger; entry.cert = CERT_FindCertByIssuerAndSN(nullptr, &ias); SECITEM_FreeItem(&ias.derIssuer, false); SECITEM_FreeItem(&ias.serialNumber, false); // If an entry is missing in the NSS root database, it may be because the // root database is out of sync with what we expect (e.g. a different // version of system NSS is installed). We will just silently avoid // treating that root cert as EV. if (!entry.cert) { #ifdef DEBUG // The debug CA info is at position 0, and is NOT on the NSS root db if (iEV == 0) { continue; } #endif PR_NOT_REACHED("Could not find EV root in NSS storage"); continue; } unsigned char certFingerprint[20]; rv = PK11_HashBuf(SEC_OID_SHA1, certFingerprint, entry.cert->derCert.data, entry.cert->derCert.len); PR_ASSERT(rv == SECSuccess); if (rv == SECSuccess) { bool same = !memcmp(certFingerprint, entry.ev_root_sha1_fingerprint, 20); PR_ASSERT(same); if (same) { SECItem ev_oid_item; ev_oid_item.data = nullptr; ev_oid_item.len = 0; rv = SEC_StringToOID(nullptr, &ev_oid_item, entry.dotted_oid, 0); PR_ASSERT(rv == SECSuccess); if (rv == SECSuccess) { entry.oid_tag = register_oid(&ev_oid_item, entry.oid_name); if (entry.oid_tag == SEC_OID_UNKNOWN) { rv = SECFailure; } SECITEM_FreeItem(&ev_oid_item, false); } } else { PR_SetError(SEC_ERROR_BAD_DATA, 0); rv = SECFailure; } } if (rv != SECSuccess) { CERT_DestroyCertificate(entry.cert); entry.cert = nullptr; entry.oid_tag = SEC_OID_UNKNOWN; return PR_FAILURE; } } return PR_SUCCESS; }
static int nss_load_crl(const char* crlfilename, PRBool ascii) { PRFileDesc *infile; PRStatus prstat; PRFileInfo info; PRInt32 nb; int rv; SECItem crlDER; CERTSignedCrl *crl=NULL; PK11SlotInfo *slot=NULL; infile = PR_Open(crlfilename,PR_RDONLY,0); if (!infile) { return 0; } crlDER.data = NULL; prstat = PR_GetOpenFileInfo(infile,&info); if (prstat!=PR_SUCCESS) return 0; if (ascii) { SECItem filedata; char *asc,*body; filedata.data = NULL; if (!SECITEM_AllocItem(NULL,&filedata,info.size)) return 0; nb = PR_Read(infile,filedata.data,info.size); if (nb!=info.size) return 0; asc = (char*)filedata.data; if (!asc) return 0; body=strstr(asc,"-----BEGIN"); if (body != NULL) { char *trailer=NULL; asc = body; body = PORT_Strchr(asc,'\n'); if (!body) body = PORT_Strchr(asc,'\r'); if (body) trailer = strstr(++body,"-----END"); if (trailer!=NULL) *trailer='\0'; else return 0; } else { body = asc; } rv = ATOB_ConvertAsciiToItem(&crlDER,body); PORT_Free(filedata.data); if (rv) return 0; } else { if (!SECITEM_AllocItem(NULL,&crlDER,info.size)) return 0; nb = PR_Read(infile,crlDER.data,info.size); if (nb!=info.size) return 0; } slot = PK11_GetInternalKeySlot(); crl = PK11_ImportCRL(slot,&crlDER, NULL,SEC_CRL_TYPE, NULL,CRL_IMPORT_DEFAULT_OPTIONS, NULL,(CRL_DECODE_DEFAULT_OPTIONS| CRL_DECODE_DONT_COPY_DER)); if (slot) PK11_FreeSlot(slot); if (!crl) return 0; SEC_DestroyCrl(crl); return 1; }
pubkey_error_code pubkey_from_base64 (const char *pubkstr, pubkey_data **dst) { /* This is the ugly part. Inspired by https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/nss_sample_code/NSS_Sample_Code_sample5 */ if (!NSS_IsInitialized ()) { if (SECSuccess != NSS_NoDB_Init (".")) { return pubkey_ec_nss_internal; } } PK11SlotInfo *slot = PK11_GetInternalKeySlot (); if (slot == NULL) { return pubkey_ec_nss_internal; } SECItem der; der.data = NULL; der.len = 0; der.type = 0; if (SECSuccess != ATOB_ConvertAsciiToItem (&der, pubkstr)) { PK11_FreeSlot(slot); return pubkey_ec_nss_internal; } SECKEYPublicKey *pubkey = my_SECKEY_DecodeDERPublicKey (&der); pubkey_error_code ec = pubkey_ec_ok; if (!pubkey) { ec = pubkey_ec_nss_internal; } SECITEM_FreeItem (&der, 0); // if (!ec && rsaKey != pubkey->keyType) { // ec = pubkey_ec_nss_internal; // } if (!ec && (siUnsignedInteger != pubkey->u.rsa.modulus.type)) { ec = pubkey_ec_nss_internal; } if (!ec && (siUnsignedInteger != pubkey->u.rsa.publicExponent.type)) { ec = pubkey_ec_nss_internal; } if (!ec && (PUBKEY_USE_MAX_MOD_LEN < pubkey->u.rsa.modulus.len)) { ec = pubkey_ec_too_large; } if (!ec && (4 < pubkey->u.rsa.publicExponent.len)) { ec = pubkey_ec_too_large; } *dst = NULL; if (!ec) { *dst = malloc (sizeof (pubkey_data)); if (!*dst) { ec = pubkey_ec_nss_internal; // Lie. } } if (!ec) { assert(*dst); (*dst)->exponent = 0; const unsigned int e_len = pubkey->u.rsa.publicExponent.len; for (unsigned int i = 0; i < e_len; ++i) { (*dst)->exponent <<= 8; (*dst)->exponent |= pubkey->u.rsa.publicExponent.data[i]; } const unsigned int m_len = pubkey->u.rsa.modulus.len; assert (m_len <= PUBKEY_USE_MAX_MOD_LEN); (*dst)->modulus_length = m_len; memcpy ((*dst)->modulus, pubkey->u.rsa.modulus.data, m_len); } if (pubkey) { SECKEY_DestroyPublicKey (pubkey); } assert (slot); PK11_FreeSlot (slot); return ec; }