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; }
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; }