nsNSSCertificate.cpp (20779B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "nsNSSCertificate.h" 7 8 #include "CertVerifier.h" 9 #include "ExtendedValidation.h" 10 #include "NSSCertDBTrustDomain.h" 11 #include "X509CertValidity.h" 12 #include "certdb.h" 13 #include "ipc/IPCMessageUtils.h" 14 #include "ipc/IPCMessageUtilsSpecializations.h" 15 #include "mozilla/Base64.h" 16 #include "mozilla/Casting.h" 17 #include "mozilla/Span.h" 18 #include "mozilla/ipc/TransportSecurityInfoUtils.h" 19 #include "mozilla/net/DNS.h" 20 #include "mozpkix/Result.h" 21 #include "mozpkix/pkixnss.h" 22 #include "mozpkix/pkixtypes.h" 23 #include "mozpkix/pkixutil.h" 24 #include "nsArray.h" 25 #include "nsCOMPtr.h" 26 #include "nsIClassInfoImpl.h" 27 #include "nsIObjectInputStream.h" 28 #include "nsIObjectOutputStream.h" 29 #include "nsIX509Cert.h" 30 #include "nsNSSCertHelper.h" 31 #include "nsNSSCertTrust.h" 32 #include "nsPK11TokenDB.h" 33 #include "nsPKCS12Blob.h" 34 #include "nsProxyRelease.h" 35 #include "nsReadableUtils.h" 36 #include "nsString.h" 37 #include "nsThreadUtils.h" 38 #include "nsUnicharUtils.h" 39 #include "nspr.h" 40 #include "prerror.h" 41 #include "secasn1.h" 42 #include "secder.h" 43 #include "secerr.h" 44 #include "ssl.h" 45 46 #ifdef XP_WIN 47 # include <winsock.h> // for htonl 48 #endif 49 50 using namespace mozilla; 51 using namespace mozilla::psm; 52 53 extern LazyLogModule gPIPNSSLog; 54 55 NS_IMPL_ISUPPORTS(nsNSSCertificate, nsIX509Cert, nsISerializable, nsIClassInfo) 56 57 nsNSSCertificate::nsNSSCertificate() : mCert("nsNSSCertificate::mCert") {} 58 59 nsNSSCertificate::nsNSSCertificate(CERTCertificate* cert) 60 : mCert("nsNSSCertificate::mCert") { 61 if (cert) { 62 mDER.AppendElements(cert->derCert.data, cert->derCert.len); 63 auto lock = mCert.Lock(); 64 auto& maybeCert = lock.ref(); 65 maybeCert.emplace(UniqueCERTCertificate(CERT_DupCertificate(cert))); 66 } 67 } 68 69 nsNSSCertificate::nsNSSCertificate(nsTArray<uint8_t>&& der) 70 : mDER(std::move(der)), mCert("nsNSSCertificate::mCert") {} 71 72 UniqueCERTCertificate nsNSSCertificate::GetOrInstantiateCert() { 73 auto lock = mCert.Lock(); 74 auto& maybeCert = lock.ref(); 75 if (maybeCert.isSome()) { 76 return UniqueCERTCertificate(CERT_DupCertificate((*maybeCert).get())); 77 } 78 79 if (!EnsureNSSInitializedChromeOrContent()) { 80 return nullptr; 81 } 82 83 SECItem derItem = {siBuffer, mDER.Elements(), 84 static_cast<unsigned int>(mDER.Length())}; 85 UniqueCERTCertificate cert(CERT_NewTempCertificate( 86 CERT_GetDefaultCertDB(), &derItem, nullptr, false, true)); 87 if (!cert) { 88 return nullptr; 89 } 90 maybeCert.emplace(std::move(cert)); 91 92 return UniqueCERTCertificate(CERT_DupCertificate((*maybeCert).get())); 93 } 94 95 nsresult nsNSSCertificate::GetCertType(uint32_t* aCertType) { 96 UniqueCERTCertificate cert(GetOrInstantiateCert()); 97 if (!cert) { 98 return NS_ERROR_FAILURE; 99 } 100 CERTCertTrust certTrust{0, 0, 0}; 101 // If there is no stored trust information, CERT_GetCertTrust will return 102 // SECFailure. This isn't a failure. In this case, all trust bits will remain 103 // unset. 104 (void)CERT_GetCertTrust(cert.get(), &certTrust); 105 nsNSSCertTrust trust(&certTrust); 106 if (cert->nickname && trust.HasAnyUser()) { 107 *aCertType = nsIX509Cert::USER_CERT; 108 return NS_OK; 109 } 110 if (trust.HasAnyCA()) { 111 *aCertType = nsIX509Cert::CA_CERT; 112 return NS_OK; 113 } 114 if (trust.HasPeer(true, false)) { 115 *aCertType = nsIX509Cert::SERVER_CERT; 116 return NS_OK; 117 } 118 if (trust.HasPeer(false, true) && cert->emailAddr) { 119 *aCertType = nsIX509Cert::EMAIL_CERT; 120 return NS_OK; 121 } 122 if (CERT_IsCACert(cert.get(), nullptr)) { 123 *aCertType = nsIX509Cert::CA_CERT; 124 return NS_OK; 125 } 126 if (cert->emailAddr) { 127 *aCertType = nsIX509Cert::EMAIL_CERT; 128 return NS_OK; 129 } 130 *aCertType = nsIX509Cert::UNKNOWN_CERT; 131 return NS_OK; 132 } 133 134 NS_IMETHODIMP 135 nsNSSCertificate::GetDbKey(nsACString& aDbKey) { 136 static_assert(sizeof(uint64_t) == 8, "type size consistency check"); 137 static_assert(sizeof(uint32_t) == 4, "type size consistency check"); 138 139 pkix::Input certInput; 140 pkix::Result result = certInput.Init(mDER.Elements(), mDER.Length()); 141 if (result != pkix::Result::Success) { 142 return NS_ERROR_INVALID_ARG; 143 } 144 // NB: since we're not building a trust path, the endEntityOrCA parameter is 145 // irrelevant. 146 pkix::BackCert cert(certInput, pkix::EndEntityOrCA::MustBeEndEntity, nullptr); 147 result = cert.Init(); 148 if (result != pkix::Result::Success) { 149 return NS_ERROR_INVALID_ARG; 150 } 151 152 // The format of the key is the base64 encoding of the following: 153 // 4 bytes: {0, 0, 0, 0} (this was intended to be the module ID, but it was 154 // never implemented) 155 // 4 bytes: {0, 0, 0, 0} (this was intended to be the slot ID, but it was 156 // never implemented) 157 // 4 bytes: <serial number length in big-endian order> 158 // 4 bytes: <DER-encoded issuer distinguished name length in big-endian order> 159 // n bytes: <bytes of serial number> 160 // m bytes: <DER-encoded issuer distinguished name> 161 nsAutoCString buf; 162 const char leadingZeroes[] = {0, 0, 0, 0, 0, 0, 0, 0}; 163 buf.Append(leadingZeroes, sizeof(leadingZeroes)); 164 uint32_t serialNumberLen = htonl(cert.GetSerialNumber().GetLength()); 165 buf.Append(BitwiseCast<const char*, const uint32_t*>(&serialNumberLen), 166 sizeof(uint32_t)); 167 uint32_t issuerLen = htonl(cert.GetIssuer().GetLength()); 168 buf.Append(BitwiseCast<const char*, const uint32_t*>(&issuerLen), 169 sizeof(uint32_t)); 170 buf.Append(BitwiseCast<const char*, const unsigned char*>( 171 cert.GetSerialNumber().UnsafeGetData()), 172 cert.GetSerialNumber().GetLength()); 173 buf.Append(BitwiseCast<const char*, const unsigned char*>( 174 cert.GetIssuer().UnsafeGetData()), 175 cert.GetIssuer().GetLength()); 176 177 return Base64Encode(buf, aDbKey); 178 } 179 180 NS_IMETHODIMP 181 nsNSSCertificate::GetDisplayName(nsAString& aDisplayName) { 182 aDisplayName.Truncate(); 183 184 UniqueCERTCertificate cert(GetOrInstantiateCert()); 185 if (!cert) { 186 return NS_ERROR_FAILURE; 187 } 188 189 UniquePORTString commonName(CERT_GetCommonName(&cert->subject)); 190 UniquePORTString organizationalUnitName(CERT_GetOrgUnitName(&cert->subject)); 191 UniquePORTString organizationName(CERT_GetOrgName(&cert->subject)); 192 193 // Only use the nickname for built-in roots where we already have a hard-coded 194 // reasonable display name (unfortunately we have to strip off the leading 195 // slot identifier followed by a ':'). Otherwise, attempt to use the following 196 // in order: 197 // - the common name, if present 198 // - an organizational unit name, if present 199 // - an organization name, if present 200 // - the entire subject distinguished name, if non-empty 201 // - an email address, if one can be found 202 // In the unlikely event that none of these fields are present and non-empty 203 // (the subject really shouldn't be empty), an empty string is returned. 204 nsAutoCString builtInRootNickname; 205 nsAutoCString fullNickname(cert->nickname); 206 static const nsLiteralCString kBuiltinObjectTokenPrefix = 207 "Builtin Object Token:"_ns; 208 if (StringBeginsWith(fullNickname, kBuiltinObjectTokenPrefix)) { 209 // Substring will gracefully handle the case where index is the last 210 // character in the string (that is, if the nickname is just 211 // "Builtin Object Token:"). In that case, we'll get an empty string. 212 builtInRootNickname = 213 Substring(fullNickname, kBuiltinObjectTokenPrefix.Length()); 214 } 215 const char* nameOptions[] = {builtInRootNickname.get(), 216 commonName.get(), 217 organizationalUnitName.get(), 218 organizationName.get(), 219 cert->subjectName, 220 cert->emailAddr}; 221 222 for (auto nameOption : nameOptions) { 223 if (nameOption) { 224 size_t len = strlen(nameOption); 225 if (len > 0) { 226 LossyUTF8ToUTF16(nameOption, len, aDisplayName); 227 return NS_OK; 228 } 229 } 230 } 231 232 return NS_OK; 233 } 234 235 NS_IMETHODIMP 236 nsNSSCertificate::GetEmailAddress(nsAString& aEmailAddress) { 237 UniqueCERTCertificate cert(GetOrInstantiateCert()); 238 if (!cert) { 239 return NS_ERROR_FAILURE; 240 } 241 if (cert->emailAddr) { 242 CopyUTF8toUTF16(MakeStringSpan(cert->emailAddr), aEmailAddress); 243 } else { 244 GetPIPNSSBundleString("CertNoEmailAddress", aEmailAddress); 245 } 246 return NS_OK; 247 } 248 249 NS_IMETHODIMP 250 nsNSSCertificate::GetEmailAddresses(nsTArray<nsString>& aAddresses) { 251 UniqueCERTCertificate cert(GetOrInstantiateCert()); 252 if (!cert) { 253 return NS_ERROR_FAILURE; 254 } 255 uint32_t length = 0; 256 for (const char* aAddr = CERT_GetFirstEmailAddress(cert.get()); aAddr; 257 aAddr = CERT_GetNextEmailAddress(cert.get(), aAddr)) { 258 ++(length); 259 } 260 261 aAddresses.SetCapacity(length); 262 263 for (const char* aAddr = CERT_GetFirstEmailAddress(cert.get()); aAddr; 264 aAddr = CERT_GetNextEmailAddress(cert.get(), aAddr)) { 265 CopyASCIItoUTF16(MakeStringSpan(aAddr), *aAddresses.AppendElement()); 266 } 267 268 return NS_OK; 269 } 270 271 NS_IMETHODIMP 272 nsNSSCertificate::ContainsEmailAddress(const nsAString& aEmailAddress, 273 bool* result) { 274 NS_ENSURE_ARG(result); 275 *result = false; 276 277 UniqueCERTCertificate cert(GetOrInstantiateCert()); 278 if (!cert) { 279 return NS_ERROR_FAILURE; 280 } 281 for (const char* aAddr = CERT_GetFirstEmailAddress(cert.get()); aAddr; 282 aAddr = CERT_GetNextEmailAddress(cert.get(), aAddr)) { 283 nsAutoString certAddr; 284 LossyUTF8ToUTF16(aAddr, strlen(aAddr), certAddr); 285 ToLowerCase(certAddr); 286 287 nsAutoString testAddr(aEmailAddress); 288 ToLowerCase(testAddr); 289 290 if (certAddr == testAddr) { 291 *result = true; 292 break; 293 } 294 } 295 296 return NS_OK; 297 } 298 299 NS_IMETHODIMP 300 nsNSSCertificate::GetCommonName(nsAString& aCommonName) { 301 aCommonName.Truncate(); 302 UniqueCERTCertificate cert(GetOrInstantiateCert()); 303 if (!cert) { 304 return NS_ERROR_FAILURE; 305 } 306 UniquePORTString commonName(CERT_GetCommonName(&cert->subject)); 307 if (commonName) { 308 LossyUTF8ToUTF16(commonName.get(), strlen(commonName.get()), aCommonName); 309 } 310 return NS_OK; 311 } 312 313 NS_IMETHODIMP 314 nsNSSCertificate::GetOrganization(nsAString& aOrganization) { 315 aOrganization.Truncate(); 316 UniqueCERTCertificate cert(GetOrInstantiateCert()); 317 if (!cert) { 318 return NS_ERROR_FAILURE; 319 } 320 UniquePORTString organization(CERT_GetOrgName(&cert->subject)); 321 if (organization) { 322 LossyUTF8ToUTF16(organization.get(), strlen(organization.get()), 323 aOrganization); 324 } 325 return NS_OK; 326 } 327 328 NS_IMETHODIMP 329 nsNSSCertificate::GetIssuerCommonName(nsAString& aCommonName) { 330 aCommonName.Truncate(); 331 UniqueCERTCertificate cert(GetOrInstantiateCert()); 332 if (!cert) { 333 return NS_ERROR_FAILURE; 334 } 335 UniquePORTString commonName(CERT_GetCommonName(&cert->issuer)); 336 if (commonName) { 337 LossyUTF8ToUTF16(commonName.get(), strlen(commonName.get()), aCommonName); 338 } 339 return NS_OK; 340 } 341 342 NS_IMETHODIMP 343 nsNSSCertificate::GetIssuerOrganization(nsAString& aOrganization) { 344 aOrganization.Truncate(); 345 UniqueCERTCertificate cert(GetOrInstantiateCert()); 346 if (!cert) { 347 return NS_ERROR_FAILURE; 348 } 349 UniquePORTString organization(CERT_GetOrgName(&cert->issuer)); 350 if (organization) { 351 LossyUTF8ToUTF16(organization.get(), strlen(organization.get()), 352 aOrganization); 353 } 354 return NS_OK; 355 } 356 357 NS_IMETHODIMP 358 nsNSSCertificate::GetIssuerOrganizationUnit(nsAString& aOrganizationUnit) { 359 aOrganizationUnit.Truncate(); 360 UniqueCERTCertificate cert(GetOrInstantiateCert()); 361 if (!cert) { 362 return NS_ERROR_FAILURE; 363 } 364 UniquePORTString organizationUnit(CERT_GetOrgUnitName(&cert->issuer)); 365 if (organizationUnit) { 366 LossyUTF8ToUTF16(organizationUnit.get(), strlen(organizationUnit.get()), 367 aOrganizationUnit); 368 } 369 return NS_OK; 370 } 371 372 NS_IMETHODIMP 373 nsNSSCertificate::GetOrganizationalUnit(nsAString& aOrganizationalUnit) { 374 aOrganizationalUnit.Truncate(); 375 UniqueCERTCertificate cert(GetOrInstantiateCert()); 376 if (!cert) { 377 return NS_ERROR_FAILURE; 378 } 379 UniquePORTString orgunit(CERT_GetOrgUnitName(&cert->subject)); 380 if (orgunit) { 381 LossyUTF8ToUTF16(orgunit.get(), strlen(orgunit.get()), aOrganizationalUnit); 382 } 383 return NS_OK; 384 } 385 386 NS_IMETHODIMP 387 nsNSSCertificate::GetSubjectName(nsAString& _subjectName) { 388 _subjectName.Truncate(); 389 UniqueCERTCertificate cert(GetOrInstantiateCert()); 390 if (!cert) { 391 return NS_ERROR_FAILURE; 392 } 393 if (cert->subjectName) { 394 LossyUTF8ToUTF16(cert->subjectName, strlen(cert->subjectName), 395 _subjectName); 396 } 397 return NS_OK; 398 } 399 400 NS_IMETHODIMP 401 nsNSSCertificate::GetIssuerName(nsAString& _issuerName) { 402 _issuerName.Truncate(); 403 UniqueCERTCertificate cert(GetOrInstantiateCert()); 404 if (!cert) { 405 return NS_ERROR_FAILURE; 406 } 407 if (cert->issuerName) { 408 LossyUTF8ToUTF16(cert->issuerName, strlen(cert->issuerName), _issuerName); 409 } 410 return NS_OK; 411 } 412 413 NS_IMETHODIMP 414 nsNSSCertificate::GetSerialNumber(nsAString& _serialNumber) { 415 _serialNumber.Truncate(); 416 UniqueCERTCertificate cert(GetOrInstantiateCert()); 417 if (!cert) { 418 return NS_ERROR_FAILURE; 419 } 420 UniquePORTString tmpstr( 421 CERT_Hexify(&cert->serialNumber, true /* use colon delimiters */)); 422 if (tmpstr) { 423 _serialNumber = NS_ConvertASCIItoUTF16(tmpstr.get()); 424 return NS_OK; 425 } 426 return NS_ERROR_FAILURE; 427 } 428 429 nsresult nsNSSCertificate::GetCertificateHash(nsAString& aFingerprint, 430 SECOidTag aHashAlg) { 431 aFingerprint.Truncate(); 432 433 if (!EnsureNSSInitializedChromeOrContent()) { 434 return NS_ERROR_NOT_AVAILABLE; 435 } 436 437 nsTArray<uint8_t> digestArray; 438 nsresult rv = 439 Digest::DigestBuf(aHashAlg, mDER.Elements(), mDER.Length(), digestArray); 440 if (NS_FAILED(rv)) { 441 return rv; 442 } 443 SECItem digestItem = {siBuffer, digestArray.Elements(), 444 static_cast<unsigned int>(digestArray.Length())}; 445 446 UniquePORTString fpStr( 447 CERT_Hexify(&digestItem, true /* use colon delimiters */)); 448 if (!fpStr) { 449 return NS_ERROR_FAILURE; 450 } 451 452 aFingerprint.AssignASCII(fpStr.get()); 453 return NS_OK; 454 } 455 456 NS_IMETHODIMP 457 nsNSSCertificate::GetSha256Fingerprint(nsAString& aSha256Fingerprint) { 458 return GetCertificateHash(aSha256Fingerprint, SEC_OID_SHA256); 459 } 460 461 NS_IMETHODIMP 462 nsNSSCertificate::GetSha1Fingerprint(nsAString& _sha1Fingerprint) { 463 return GetCertificateHash(_sha1Fingerprint, SEC_OID_SHA1); 464 } 465 466 NS_IMETHODIMP 467 nsNSSCertificate::GetTokenName(nsAString& aTokenName) { 468 UniqueCERTCertificate cert(GetOrInstantiateCert()); 469 if (!cert) { 470 return NS_ERROR_FAILURE; 471 } 472 UniquePK11SlotInfo internalSlot(PK11_GetInternalSlot()); 473 if (!internalSlot) { 474 return NS_ERROR_FAILURE; 475 } 476 nsCOMPtr<nsIPK11Token> token( 477 new nsPK11Token(cert->slot ? cert->slot : internalSlot.get())); 478 nsAutoCString tmp; 479 nsresult rv = token->GetTokenName(tmp); 480 if (NS_FAILED(rv)) { 481 return rv; 482 } 483 aTokenName.Assign(NS_ConvertUTF8toUTF16(tmp)); 484 return NS_OK; 485 } 486 487 NS_IMETHODIMP 488 nsNSSCertificate::GetSubjectPublicKeyInfo(nsTArray<uint8_t>& aSPKI) { 489 aSPKI.Clear(); 490 491 pkix::Input certInput; 492 pkix::Result result = certInput.Init(mDER.Elements(), mDER.Length()); 493 if (result != pkix::Result::Success) { 494 return NS_ERROR_INVALID_ARG; 495 } 496 // NB: since we're not building a trust path, the endEntityOrCA parameter is 497 // irrelevant. 498 pkix::BackCert cert(certInput, pkix::EndEntityOrCA::MustBeEndEntity, nullptr); 499 result = cert.Init(); 500 if (result != pkix::Result::Success) { 501 return NS_ERROR_INVALID_ARG; 502 } 503 pkix::Input spki = cert.GetSubjectPublicKeyInfo(); 504 aSPKI.AppendElements(spki.UnsafeGetData(), spki.GetLength()); 505 return NS_OK; 506 } 507 508 NS_IMETHODIMP 509 nsNSSCertificate::GetSha256SubjectPublicKeyInfoDigest( 510 nsACString& aSha256SPKIDigest) { 511 aSha256SPKIDigest.Truncate(); 512 513 if (!EnsureNSSInitializedChromeOrContent()) { 514 return NS_ERROR_NOT_AVAILABLE; 515 } 516 517 pkix::Input certInput; 518 pkix::Result result = certInput.Init(mDER.Elements(), mDER.Length()); 519 if (result != pkix::Result::Success) { 520 return NS_ERROR_INVALID_ARG; 521 } 522 // NB: since we're not building a trust path, the endEntityOrCA parameter is 523 // irrelevant. 524 pkix::BackCert cert(certInput, pkix::EndEntityOrCA::MustBeEndEntity, nullptr); 525 result = cert.Init(); 526 if (result != pkix::Result::Success) { 527 return NS_ERROR_INVALID_ARG; 528 } 529 pkix::Input derPublicKey = cert.GetSubjectPublicKeyInfo(); 530 nsTArray<uint8_t> digestArray; 531 nsresult rv = Digest::DigestBuf(SEC_OID_SHA256, derPublicKey.UnsafeGetData(), 532 derPublicKey.GetLength(), digestArray); 533 if (NS_FAILED(rv)) { 534 return rv; 535 } 536 rv = Base64Encode(nsDependentCSubstring( 537 reinterpret_cast<const char*>(digestArray.Elements()), 538 digestArray.Length()), 539 aSha256SPKIDigest); 540 if (NS_WARN_IF(NS_FAILED(rv))) { 541 return rv; 542 } 543 return NS_OK; 544 } 545 546 NS_IMETHODIMP 547 nsNSSCertificate::GetRawDER(nsTArray<uint8_t>& aArray) { 548 aArray.SetLength(mDER.Length()); 549 memcpy(aArray.Elements(), mDER.Elements(), mDER.Length()); 550 return NS_OK; 551 } 552 553 NS_IMETHODIMP 554 nsNSSCertificate::GetBase64DERString(nsACString& base64DERString) { 555 nsDependentCSubstring derString( 556 reinterpret_cast<const char*>(mDER.Elements()), mDER.Length()); 557 nsresult rv = Base64Encode(derString, base64DERString); 558 if (NS_FAILED(rv)) { 559 return rv; 560 } 561 return NS_OK; 562 } 563 564 CERTCertificate* nsNSSCertificate::GetCert() { 565 UniqueCERTCertificate cert(GetOrInstantiateCert()); 566 return cert.release(); // caller takes ownership 567 } 568 569 NS_IMETHODIMP 570 nsNSSCertificate::GetValidity(nsIX509CertValidity** aValidity) { 571 NS_ENSURE_ARG(aValidity); 572 pkix::Input certInput; 573 pkix::Result rv = certInput.Init(mDER.Elements(), mDER.Length()); 574 if (rv != pkix::Success) { 575 return NS_ERROR_FAILURE; 576 } 577 nsCOMPtr<nsIX509CertValidity> validity = new X509CertValidity(certInput); 578 validity.forget(aValidity); 579 return NS_OK; 580 } 581 582 // NB: Any updates (except disk-only fields) must be kept in sync with 583 // |SerializeToIPC|. 584 NS_IMETHODIMP 585 nsNSSCertificate::Write(nsIObjectOutputStream* aStream) { 586 // This field used to be the cached EV status, but it is no longer necessary. 587 nsresult rv = aStream->Write32(0); 588 if (NS_FAILED(rv)) { 589 return rv; 590 } 591 rv = aStream->Write32(mDER.Length()); 592 if (NS_FAILED(rv)) { 593 return rv; 594 } 595 return aStream->WriteBytes(Span(mDER)); 596 } 597 598 // NB: Any updates (except disk-only fields) must be kept in sync with 599 // |DeserializeFromIPC|. 600 NS_IMETHODIMP 601 nsNSSCertificate::Read(nsIObjectInputStream* aStream) { 602 auto lock = mCert.Lock(); 603 auto& maybeCert = lock.ref(); 604 if (!mDER.IsEmpty() || maybeCert.isSome()) { 605 return NS_ERROR_ALREADY_INITIALIZED; 606 } 607 608 // This field is no longer used. 609 uint32_t unusedCachedEVStatus; 610 nsresult rv = aStream->Read32(&unusedCachedEVStatus); 611 if (NS_FAILED(rv)) { 612 return rv; 613 } 614 615 uint32_t len; 616 rv = aStream->Read32(&len); 617 if (NS_FAILED(rv)) { 618 return rv; 619 } 620 621 rv = aStream->ReadByteArray(len, mDER); 622 if (NS_FAILED(rv)) { 623 return rv; 624 } 625 return NS_OK; 626 } 627 628 void nsNSSCertificate::SerializeToIPC(IPC::MessageWriter* aWriter) { 629 bool hasCert = !mDER.IsEmpty(); 630 WriteParam(aWriter, hasCert); 631 632 if (!hasCert) { 633 return; 634 } 635 636 WriteParam(aWriter, mDER); 637 } 638 639 bool nsNSSCertificate::DeserializeFromIPC(IPC::MessageReader* aReader) { 640 auto lock = mCert.Lock(); 641 auto& maybeCert = lock.ref(); 642 if (!mDER.IsEmpty() || maybeCert.isSome()) { 643 return false; 644 } 645 646 bool hasCert = false; 647 if (!ReadParam(aReader, &hasCert)) { 648 return false; 649 } 650 651 if (!hasCert) { 652 return true; 653 } 654 655 if (!ReadParam(aReader, &mDER)) { 656 return false; 657 } 658 return true; 659 } 660 661 NS_IMETHODIMP 662 nsNSSCertificate::GetInterfaces(nsTArray<nsIID>& array) { 663 array.Clear(); 664 return NS_OK; 665 } 666 667 NS_IMETHODIMP 668 nsNSSCertificate::GetScriptableHelper(nsIXPCScriptable** _retval) { 669 *_retval = nullptr; 670 return NS_OK; 671 } 672 673 NS_IMETHODIMP 674 nsNSSCertificate::GetContractID(nsACString& aContractID) { 675 aContractID.SetIsVoid(true); 676 return NS_OK; 677 } 678 679 NS_IMETHODIMP 680 nsNSSCertificate::GetClassDescription(nsACString& aClassDescription) { 681 aClassDescription.SetIsVoid(true); 682 return NS_OK; 683 } 684 685 NS_IMETHODIMP 686 nsNSSCertificate::GetClassID(nsCID** aClassID) { 687 *aClassID = (nsCID*)moz_xmalloc(sizeof(nsCID)); 688 return GetClassIDNoAlloc(*aClassID); 689 } 690 691 NS_IMETHODIMP 692 nsNSSCertificate::GetFlags(uint32_t* aFlags) { 693 *aFlags = nsIClassInfo::THREADSAFE; 694 return NS_OK; 695 } 696 697 NS_IMETHODIMP 698 nsNSSCertificate::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) { 699 static NS_DEFINE_CID(kNSSCertificateCID, NS_X509CERT_CID); 700 701 *aClassIDNoAlloc = kNSSCertificateCID; 702 return NS_OK; 703 }