nsresult nsNSSCertificateDB::FindCertByDBKey(const char* aDBKey, UniqueCERTCertificate& cert) { static_assert(sizeof(uint64_t) == 8, "type size sanity check"); static_assert(sizeof(uint32_t) == 4, "type size sanity check"); // (From nsNSSCertificate::GetDbKey) // The format of the key is the base64 encoding of the following: // 4 bytes: {0, 0, 0, 0} (this was intended to be the module ID, but it was // never implemented) // 4 bytes: {0, 0, 0, 0} (this was intended to be the slot ID, but it was // never implemented) // 4 bytes: <serial number length in big-endian order> // 4 bytes: <DER-encoded issuer distinguished name length in big-endian order> // n bytes: <bytes of serial number> // m bytes: <DER-encoded issuer distinguished name> nsAutoCString decoded; nsAutoCString tmpDBKey(aDBKey); // Filter out any whitespace for backwards compatibility. tmpDBKey.StripWhitespace(); nsresult rv = Base64Decode(tmpDBKey, decoded); if (NS_FAILED(rv)) { return rv; } if (decoded.Length() < 16) { return NS_ERROR_ILLEGAL_INPUT; } const char* reader = decoded.BeginReading(); uint64_t zeroes = *BitwiseCast<const uint64_t*, const char*>(reader); if (zeroes != 0) { return NS_ERROR_ILLEGAL_INPUT; } reader += sizeof(uint64_t); // Note: We surround the ntohl() argument with parentheses to stop the macro // from thinking two arguments were passed. uint32_t serialNumberLen = ntohl( (*BitwiseCast<const uint32_t*, const char*>(reader))); reader += sizeof(uint32_t); uint32_t issuerLen = ntohl( (*BitwiseCast<const uint32_t*, const char*>(reader))); reader += sizeof(uint32_t); if (decoded.Length() != 16ULL + serialNumberLen + issuerLen) { return NS_ERROR_ILLEGAL_INPUT; } CERTIssuerAndSN issuerSN; issuerSN.serialNumber.len = serialNumberLen; issuerSN.serialNumber.data = BitwiseCast<unsigned char*, const char*>(reader); reader += serialNumberLen; issuerSN.derIssuer.len = issuerLen; issuerSN.derIssuer.data = BitwiseCast<unsigned char*, const char*>(reader); reader += issuerLen; MOZ_ASSERT(reader == decoded.EndReading()); cert.reset(CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(), &issuerSN)); return NS_OK; }
void nsNSSCertificateDB::get_default_nickname(CERTCertificate *cert, nsIInterfaceRequestor* ctx, nsCString &nickname, const nsNSSShutDownPreventionLock &/*proofOfLock*/) { static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); nickname.Truncate(); nsresult rv; CK_OBJECT_HANDLE keyHandle; CERTCertDBHandle *defaultcertdb = CERT_GetDefaultCertDB(); nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv)); if (NS_FAILED(rv)) return; nsAutoCString username; UniquePORTString tempCN(CERT_GetCommonName(&cert->subject)); if (tempCN) { username = tempCN.get(); } nsAutoCString caname; UniquePORTString tempIssuerOrg(CERT_GetOrgName(&cert->issuer)); if (tempIssuerOrg) { caname = tempIssuerOrg.get(); } nsAutoString tmpNickFmt; nssComponent->GetPIPNSSBundleString("nick_template", tmpNickFmt); NS_ConvertUTF16toUTF8 nickFmt(tmpNickFmt); nsAutoCString baseName; baseName.AppendPrintf(nickFmt.get(), username.get(), caname.get()); if (baseName.IsEmpty()) { return; } nickname = baseName; /* * We need to see if the private key exists on a token, if it does * then we need to check for nicknames that already exist on the smart * card. */ UniquePK11SlotInfo slot(PK11_KeyForCertExists(cert, &keyHandle, ctx)); if (!slot) return; if (!PK11_IsInternal(slot.get())) { nsAutoCString tmp; tmp.AppendPrintf("%s:%s", PK11_GetTokenName(slot.get()), baseName.get()); if (tmp.IsEmpty()) { nickname.Truncate(); return; } baseName = tmp; nickname = baseName; } int count = 1; while (true) { if ( count > 1 ) { nsAutoCString tmp; tmp.AppendPrintf("%s #%d", baseName.get(), count); if (tmp.IsEmpty()) { nickname.Truncate(); return; } nickname = tmp; } UniqueCERTCertificate dummycert; if (PK11_IsInternal(slot.get())) { /* look up the nickname to make sure it isn't in use already */ dummycert.reset(CERT_FindCertByNickname(defaultcertdb, nickname.get())); } else { // Check the cert against others that already live on the smart card. dummycert.reset(PK11_FindCertFromNickname(nickname.get(), ctx)); if (dummycert) { // Make sure the subject names are different. if (CERT_CompareName(&cert->subject, &dummycert->subject) == SECEqual) { /* * There is another certificate with the same nickname and * the same subject name on the smart card, so let's use this * nickname. */ dummycert = nullptr; } } } if (!dummycert) { break; } count++; } }