TransportSecurityInfo.cpp (34926B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "TransportSecurityInfo.h" 8 9 #include "ipc/IPCMessageUtils.h" 10 #include "ipc/IPCMessageUtilsSpecializations.h" 11 #include "mozilla/Base64.h" 12 #include "mozpkix/pkixtypes.h" 13 #include "nsBase64Encoder.h" 14 #include "nsIObjectInputStream.h" 15 #include "nsIObjectOutputStream.h" 16 #include "nsIWebProgressListener.h" 17 #include "nsNSSCertHelper.h" 18 #include "nsNSSComponent.h" 19 #include "nsNSSHelper.h" 20 #include "nsReadableUtils.h" 21 #include "nsServiceManagerUtils.h" 22 #include "nsStringStream.h" 23 #include "nsXULAppAPI.h" 24 #include "nsIX509Cert.h" 25 #include "secerr.h" 26 #include "ssl.h" 27 28 // nsITransportSecurityInfo should not be created via do_CreateInstance. This 29 // stub prevents that. 30 template <> 31 already_AddRefed<nsISupports> 32 mozCreateComponent<mozilla::psm::TransportSecurityInfo>() { 33 return nullptr; 34 } 35 36 namespace mozilla { 37 namespace psm { 38 39 TransportSecurityInfo::TransportSecurityInfo( 40 uint32_t aSecurityState, PRErrorCode aErrorCode, 41 nsTArray<RefPtr<nsIX509Cert>>&& aHandshakeCertificates, 42 nsCOMPtr<nsIX509Cert>& aServerCert, 43 nsTArray<RefPtr<nsIX509Cert>>&& aSucceededCertChain, 44 Maybe<uint16_t> aCipherSuite, Maybe<nsCString> aKeaGroupName, 45 Maybe<nsCString> aSignatureSchemeName, Maybe<uint16_t> aProtocolVersion, 46 uint16_t aCertificateTransparencyStatus, Maybe<bool> aIsAcceptedEch, 47 Maybe<bool> aIsDelegatedCredential, 48 Maybe<OverridableErrorCategory> aOverridableErrorCategory, 49 bool aMadeOCSPRequests, bool aUsedPrivateDNS, Maybe<bool> aIsEV, 50 bool aNPNCompleted, const nsCString& aNegotiatedNPN, bool aResumed, 51 bool aIsBuiltCertChainRootBuiltInRoot, const nsCString& aPeerId) 52 : mSecurityState(aSecurityState), 53 mErrorCode(aErrorCode), 54 mHandshakeCertificates(std::move(aHandshakeCertificates)), 55 mServerCert(aServerCert), 56 mSucceededCertChain(std::move(aSucceededCertChain)), 57 mCipherSuite(aCipherSuite), 58 mKeaGroupName(aKeaGroupName), 59 mSignatureSchemeName(aSignatureSchemeName), 60 mProtocolVersion(aProtocolVersion), 61 mCertificateTransparencyStatus(aCertificateTransparencyStatus), 62 mIsAcceptedEch(aIsAcceptedEch), 63 mIsDelegatedCredential(aIsDelegatedCredential), 64 mOverridableErrorCategory(aOverridableErrorCategory), 65 mMadeOCSPRequests(aMadeOCSPRequests), 66 mUsedPrivateDNS(aUsedPrivateDNS), 67 mIsEV(aIsEV), 68 mNPNCompleted(aNPNCompleted), 69 mNegotiatedNPN(aNegotiatedNPN), 70 mResumed(aResumed), 71 mIsBuiltCertChainRootBuiltInRoot(aIsBuiltCertChainRootBuiltInRoot), 72 mPeerId(aPeerId) {} 73 74 NS_IMPL_ISUPPORTS(TransportSecurityInfo, nsITransportSecurityInfo) 75 76 NS_IMETHODIMP 77 TransportSecurityInfo::GetSecurityState(uint32_t* state) { 78 *state = mSecurityState; 79 return NS_OK; 80 } 81 82 NS_IMETHODIMP 83 TransportSecurityInfo::GetErrorCode(int32_t* state) { 84 *state = mErrorCode; 85 return NS_OK; 86 } 87 88 NS_IMETHODIMP 89 TransportSecurityInfo::GetErrorCodeString(nsAString& aErrorString) { 90 const char* codeName = PR_ErrorToName(mErrorCode); 91 aErrorString.Truncate(); 92 if (codeName) { 93 aErrorString = NS_ConvertASCIItoUTF16(codeName); 94 } 95 96 return NS_OK; 97 } 98 99 // 16786594-0296-4471-8096-8f84497ca428 100 #define TRANSPORTSECURITYINFO_CID \ 101 {0x16786594, 0x0296, 0x4471, {0x80, 0x96, 0x8f, 0x84, 0x49, 0x7c, 0xa4, 0x28}} 102 static NS_DEFINE_CID(kTransportSecurityInfoCID, TRANSPORTSECURITYINFO_CID); 103 104 // This is a new magic value. However, it re-uses the first 4 bytes 105 // of the previous value. This is so when older versions attempt to 106 // read a newer serialized TransportSecurityInfo, they will actually 107 // fail and return NS_ERROR_FAILURE instead of silently failing. 108 #define TRANSPORTSECURITYINFOMAGIC \ 109 {0xa9863a23, 0x1faa, 0x4169, {0xb0, 0xd2, 0x81, 0x29, 0xec, 0x7c, 0xb1, 0xde}} 110 static NS_DEFINE_CID(kTransportSecurityInfoMagic, TRANSPORTSECURITYINFOMAGIC); 111 112 NS_IMETHODIMP 113 TransportSecurityInfo::ToString(nsACString& aResult) { 114 RefPtr<nsBase64Encoder> stream(new nsBase64Encoder()); 115 nsCOMPtr<nsIObjectOutputStream> objStream(NS_NewObjectOutputStream(stream)); 116 nsresult rv = objStream->WriteID(kTransportSecurityInfoCID); 117 if (NS_FAILED(rv)) { 118 return rv; 119 } 120 rv = objStream->WriteID(NS_ISUPPORTS_IID); 121 if (NS_FAILED(rv)) { 122 return rv; 123 } 124 125 rv = objStream->WriteID(kTransportSecurityInfoMagic); 126 if (NS_FAILED(rv)) { 127 return rv; 128 } 129 130 rv = objStream->Write32(mSecurityState); 131 if (NS_FAILED(rv)) { 132 return rv; 133 } 134 // mSubRequestsBrokenSecurity was removed in bug 748809 135 rv = objStream->Write32(0); 136 if (NS_FAILED(rv)) { 137 return rv; 138 } 139 // mSubRequestsNoSecurity was removed in bug 748809 140 rv = objStream->Write32(0); 141 if (NS_FAILED(rv)) { 142 return rv; 143 } 144 rv = objStream->Write32(static_cast<uint32_t>(mErrorCode)); 145 if (NS_FAILED(rv)) { 146 return rv; 147 } 148 149 // Re-purpose mErrorMessageCached to represent serialization version 150 // If string doesn't match exact version it will be treated as older 151 // serialization. 152 rv = objStream->WriteWStringZ(NS_ConvertUTF8toUTF16("9").get()); 153 if (NS_FAILED(rv)) { 154 return rv; 155 } 156 157 // moved from nsISSLStatus 158 rv = NS_WriteOptionalCompoundObject(objStream, mServerCert, 159 NS_GET_IID(nsIX509Cert), true); 160 NS_ENSURE_SUCCESS(rv, rv); 161 162 rv = objStream->Write16(mCipherSuite.isSome() ? *mCipherSuite : 0); 163 NS_ENSURE_SUCCESS(rv, rv); 164 165 rv = objStream->Write16(mProtocolVersion.isSome() ? *mProtocolVersion : 0); 166 NS_ENSURE_SUCCESS(rv, rv); 167 168 rv = objStream->Write32(mOverridableErrorCategory.isSome() 169 ? *mOverridableErrorCategory 170 : OverridableErrorCategory::ERROR_UNSET); 171 NS_ENSURE_SUCCESS(rv, rv); 172 rv = objStream->WriteBoolean(mIsEV.isSome() ? *mIsEV : false); 173 NS_ENSURE_SUCCESS(rv, rv); 174 175 rv = objStream->WriteBoolean(mIsEV.isSome()); // previously mHasIsEV 176 NS_ENSURE_SUCCESS(rv, rv); 177 rv = objStream->WriteBoolean( 178 mCipherSuite.isSome()); // previously mHaveCipherSuiteAndProtocol 179 NS_ENSURE_SUCCESS(rv, rv); 180 rv = objStream->WriteBoolean( 181 mOverridableErrorCategory.isSome()); // previously mHaveCertErrorBits 182 NS_ENSURE_SUCCESS(rv, rv); 183 184 rv = objStream->Write16(mCertificateTransparencyStatus); 185 NS_ENSURE_SUCCESS(rv, rv); 186 187 rv = objStream->WriteStringZ(mKeaGroupName.isSome() ? (*mKeaGroupName).get() 188 : ""); 189 NS_ENSURE_SUCCESS(rv, rv); 190 191 rv = objStream->WriteStringZ( 192 mSignatureSchemeName.isSome() ? (*mSignatureSchemeName).get() : ""); 193 NS_ENSURE_SUCCESS(rv, rv); 194 195 rv = objStream->Write16(mSucceededCertChain.Length()); 196 NS_ENSURE_SUCCESS(rv, rv); 197 198 for (const auto& cert : mSucceededCertChain) { 199 rv = objStream->WriteCompoundObject(cert, NS_GET_IID(nsIX509Cert), true); 200 NS_ENSURE_SUCCESS(rv, rv); 201 } 202 // END moved from nsISSLStatus 203 rv = objStream->Write16(mHandshakeCertificates.Length()); 204 NS_ENSURE_SUCCESS(rv, rv); 205 for (const auto& cert : mHandshakeCertificates) { 206 rv = objStream->WriteCompoundObject(cert, NS_GET_IID(nsIX509Cert), true); 207 NS_ENSURE_SUCCESS(rv, rv); 208 } 209 210 rv = objStream->WriteBoolean( 211 mIsDelegatedCredential.isSome() ? *mIsDelegatedCredential : false); 212 if (NS_FAILED(rv)) { 213 return rv; 214 } 215 216 rv = objStream->WriteBoolean(mNPNCompleted); 217 if (NS_FAILED(rv)) { 218 return rv; 219 } 220 221 rv = objStream->WriteStringZ(mNegotiatedNPN.get()); 222 if (NS_FAILED(rv)) { 223 return rv; 224 } 225 226 rv = objStream->WriteBoolean(mResumed); 227 if (NS_FAILED(rv)) { 228 return rv; 229 } 230 231 rv = objStream->WriteBoolean(mIsBuiltCertChainRootBuiltInRoot); 232 if (NS_FAILED(rv)) { 233 return rv; 234 } 235 236 rv = objStream->WriteBoolean(mIsAcceptedEch.isSome() ? *mIsAcceptedEch 237 : false); 238 if (NS_FAILED(rv)) { 239 return rv; 240 } 241 242 rv = objStream->WriteStringZ(mPeerId.get()); 243 if (NS_FAILED(rv)) { 244 return rv; 245 } 246 247 rv = objStream->WriteBoolean(mMadeOCSPRequests); 248 if (NS_FAILED(rv)) { 249 return rv; 250 } 251 252 rv = objStream->WriteBoolean(mUsedPrivateDNS); 253 if (NS_FAILED(rv)) { 254 return rv; 255 } 256 257 rv = stream->Finish(aResult); 258 if (NS_FAILED(rv)) { 259 return rv; 260 } 261 262 return NS_OK; 263 } 264 265 nsresult TransportSecurityInfo::ReadOldOverridableErrorBits( 266 nsIObjectInputStream* aStream, 267 OverridableErrorCategory& aOverridableErrorCategory) { 268 bool isDomainMismatch; 269 nsresult rv = aStream->ReadBoolean(&isDomainMismatch); 270 NS_ENSURE_SUCCESS(rv, rv); 271 bool isNotValidAtThisTime; 272 rv = aStream->ReadBoolean(&isNotValidAtThisTime); 273 NS_ENSURE_SUCCESS(rv, rv); 274 bool isUntrusted; 275 rv = aStream->ReadBoolean(&isUntrusted); 276 NS_ENSURE_SUCCESS(rv, rv); 277 if (isUntrusted) { 278 aOverridableErrorCategory = 279 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TRUST; 280 } else if (isDomainMismatch) { 281 aOverridableErrorCategory = 282 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_DOMAIN; 283 } else if (isNotValidAtThisTime) { 284 aOverridableErrorCategory = 285 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TIME; 286 } else { 287 aOverridableErrorCategory = 288 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET; 289 } 290 291 return NS_OK; 292 } 293 294 // This is for backward compatibility to be able to read nsISSLStatus 295 // serialized object. 296 nsresult TransportSecurityInfo::ReadSSLStatus( 297 nsIObjectInputStream* aStream, nsCOMPtr<nsIX509Cert>& aServerCert, 298 Maybe<uint16_t>& aCipherSuite, Maybe<uint16_t>& aProtocolVersion, 299 Maybe<OverridableErrorCategory>& aOverridableErrorCategory, 300 Maybe<bool>& aIsEV, uint16_t& aCertificateTransparencyStatus, 301 Maybe<nsCString>& aKeaGroupName, Maybe<nsCString>& aSignatureSchemeName, 302 nsTArray<RefPtr<nsIX509Cert>>& aSucceededCertChain) { 303 bool nsISSLStatusPresent; 304 nsresult rv = aStream->ReadBoolean(&nsISSLStatusPresent); 305 NS_ENSURE_SUCCESS(rv, rv); 306 if (!nsISSLStatusPresent) { 307 return NS_OK; 308 } 309 // nsISSLStatus present. Prepare to read elements. 310 // Throw away cid, validate iid 311 nsCID cid; 312 nsIID iid; 313 rv = aStream->ReadID(&cid); 314 NS_ENSURE_SUCCESS(rv, rv); 315 rv = aStream->ReadID(&iid); 316 NS_ENSURE_SUCCESS(rv, rv); 317 318 static const nsIID nsSSLStatusIID = { 319 0xfa9ba95b, 320 0xca3b, 321 0x498a, 322 {0xb8, 0x89, 0x7c, 0x79, 0xcf, 0x28, 0xfe, 0xe8}}; 323 if (!iid.Equals(nsSSLStatusIID)) { 324 return NS_ERROR_UNEXPECTED; 325 } 326 327 nsCOMPtr<nsISupports> cert; 328 rv = aStream->ReadObject(true, getter_AddRefs(cert)); 329 NS_ENSURE_SUCCESS(rv, rv); 330 331 if (cert) { 332 aServerCert = do_QueryInterface(cert); 333 if (!aServerCert) { 334 return NS_NOINTERFACE; 335 } 336 } 337 338 uint16_t cipherSuite; 339 rv = aStream->Read16(&cipherSuite); 340 NS_ENSURE_SUCCESS(rv, rv); 341 342 // The code below is a workaround to allow serializing new fields 343 // while preserving binary compatibility with older streams. For more details 344 // on the binary compatibility requirement, refer to bug 1248628. 345 // Here, we take advantage of the fact that mProtocolVersion was originally 346 // stored as a 16 bits integer, but the highest 8 bits were never used. 347 // These bits are now used for stream versioning. 348 uint16_t protocolVersionAndStreamFormatVersion; 349 rv = aStream->Read16(&protocolVersionAndStreamFormatVersion); 350 NS_ENSURE_SUCCESS(rv, rv); 351 const uint8_t streamFormatVersion = 352 (protocolVersionAndStreamFormatVersion >> 8) & 0xFF; 353 354 OverridableErrorCategory overridableErrorCategory; 355 rv = ReadOldOverridableErrorBits(aStream, overridableErrorCategory); 356 NS_ENSURE_SUCCESS(rv, rv); 357 bool isEV; 358 rv = aStream->ReadBoolean(&isEV); 359 NS_ENSURE_SUCCESS(rv, rv); 360 bool hasIsEVStatus; 361 rv = aStream->ReadBoolean(&hasIsEVStatus); 362 NS_ENSURE_SUCCESS(rv, rv); 363 if (hasIsEVStatus) { 364 aIsEV.emplace(isEV); 365 } 366 bool haveCipherSuiteAndProtocol; 367 rv = aStream->ReadBoolean(&haveCipherSuiteAndProtocol); 368 if (haveCipherSuiteAndProtocol) { 369 aCipherSuite.emplace(cipherSuite); 370 aProtocolVersion.emplace(protocolVersionAndStreamFormatVersion & 0xFF); 371 } 372 NS_ENSURE_SUCCESS(rv, rv); 373 bool haveCertErrorBits; 374 rv = aStream->ReadBoolean(&haveCertErrorBits); 375 NS_ENSURE_SUCCESS(rv, rv); 376 if (haveCertErrorBits) { 377 aOverridableErrorCategory.emplace(overridableErrorCategory); 378 } 379 380 // Added in version 1 (see bug 1305289). 381 if (streamFormatVersion >= 1) { 382 rv = aStream->Read16(&aCertificateTransparencyStatus); 383 NS_ENSURE_SUCCESS(rv, rv); 384 } 385 386 // Added in version 2 (see bug 1304923). 387 if (streamFormatVersion >= 2) { 388 nsCString keaGroupName; 389 rv = aStream->ReadCString(keaGroupName); 390 NS_ENSURE_SUCCESS(rv, rv); 391 if (haveCipherSuiteAndProtocol) { 392 aKeaGroupName.emplace(keaGroupName); 393 } 394 395 nsCString signatureSchemeName; 396 rv = aStream->ReadCString(signatureSchemeName); 397 NS_ENSURE_SUCCESS(rv, rv); 398 if (haveCipherSuiteAndProtocol) { 399 aSignatureSchemeName.emplace(signatureSchemeName); 400 } 401 } 402 403 // Added in version 3 (see bug 1406856). 404 if (streamFormatVersion >= 3) { 405 rv = ReadCertList(aStream, aSucceededCertChain); 406 if (NS_FAILED(rv)) { 407 return rv; 408 } 409 410 // Read only to consume bytes from the stream. 411 nsTArray<RefPtr<nsIX509Cert>> handshakeCertificates; 412 rv = ReadCertList(aStream, handshakeCertificates); 413 if (NS_FAILED(rv)) { 414 return rv; 415 } 416 } 417 return rv; 418 } 419 420 // This is for backward compatability to be able to read nsIX509CertList 421 // serialized object. 422 nsresult TransportSecurityInfo::ReadCertList( 423 nsIObjectInputStream* aStream, nsTArray<RefPtr<nsIX509Cert>>& aCertList) { 424 bool nsIX509CertListPresent; 425 426 nsresult rv = aStream->ReadBoolean(&nsIX509CertListPresent); 427 NS_ENSURE_SUCCESS(rv, rv); 428 if (!nsIX509CertListPresent) { 429 return NS_OK; 430 } 431 // nsIX509CertList present. Prepare to read elements. 432 // Throw away cid, validate iid 433 nsCID cid; 434 nsIID iid; 435 rv = aStream->ReadID(&cid); 436 NS_ENSURE_SUCCESS(rv, rv); 437 rv = aStream->ReadID(&iid); 438 NS_ENSURE_SUCCESS(rv, rv); 439 440 static const nsIID nsIX509CertListIID = { 441 0xae74cda5, 442 0xcd2f, 443 0x473f, 444 {0x96, 0xf5, 0xf0, 0xb7, 0xff, 0xf6, 0x2c, 0x68}}; 445 446 if (!iid.Equals(nsIX509CertListIID)) { 447 return NS_ERROR_UNEXPECTED; 448 } 449 450 uint32_t certListSize; 451 rv = aStream->Read32(&certListSize); 452 NS_ENSURE_SUCCESS(rv, rv); 453 454 return ReadCertificatesFromStream(aStream, certListSize, aCertList); 455 } 456 457 nsresult TransportSecurityInfo::ReadCertificatesFromStream( 458 nsIObjectInputStream* aStream, uint32_t aSize, 459 nsTArray<RefPtr<nsIX509Cert>>& aCertList) { 460 nsresult rv; 461 for (uint32_t i = 0; i < aSize; ++i) { 462 nsCOMPtr<nsISupports> support; 463 rv = aStream->ReadObject(true, getter_AddRefs(support)); 464 NS_ENSURE_SUCCESS(rv, rv); 465 nsCOMPtr<nsIX509Cert> cert = do_QueryInterface(support); 466 if (!cert) { 467 return NS_ERROR_UNEXPECTED; 468 } 469 RefPtr<nsIX509Cert> castedCert(cert.get()); 470 aCertList.AppendElement(castedCert); 471 } 472 return NS_OK; 473 } 474 475 static nsITransportSecurityInfo::OverridableErrorCategory 476 IntToOverridableErrorCategory(uint32_t intVal) { 477 switch (intVal) { 478 case static_cast<uint32_t>( 479 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TRUST): 480 return nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TRUST; 481 case static_cast<uint32_t>( 482 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_DOMAIN): 483 return nsITransportSecurityInfo::OverridableErrorCategory::ERROR_DOMAIN; 484 case static_cast<uint32_t>( 485 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TIME): 486 return nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TIME; 487 default: 488 break; 489 } 490 return nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET; 491 } 492 493 nsresult TransportSecurityInfo::Read(const nsCString& aSerializedSecurityInfo, 494 nsITransportSecurityInfo** aResult) { 495 *aResult = nullptr; 496 497 nsCString decodedSecurityInfo; 498 nsresult rv = Base64Decode(aSerializedSecurityInfo, decodedSecurityInfo); 499 if (NS_FAILED(rv)) { 500 return rv; 501 } 502 nsCOMPtr<nsIInputStream> inputStream; 503 rv = NS_NewCStringInputStream(getter_AddRefs(inputStream), 504 std::move(decodedSecurityInfo)); 505 if (NS_FAILED(rv)) { 506 return rv; 507 } 508 nsCOMPtr<nsIObjectInputStream> objStream( 509 NS_NewObjectInputStream(inputStream)); 510 if (!objStream) { 511 return rv; 512 } 513 514 nsCID cid; 515 rv = objStream->ReadID(&cid); 516 if (NS_FAILED(rv)) { 517 return rv; 518 } 519 if (!cid.Equals(kTransportSecurityInfoCID)) { 520 return NS_ERROR_UNEXPECTED; 521 } 522 nsIID iid; 523 rv = objStream->ReadID(&iid); 524 if (NS_FAILED(rv)) { 525 return rv; 526 } 527 if (!iid.Equals(NS_ISUPPORTS_IID)) { 528 return rv; 529 } 530 531 nsID id; 532 rv = objStream->ReadID(&id); 533 if (NS_FAILED(rv)) { 534 return rv; 535 } 536 if (!id.Equals(kTransportSecurityInfoMagic)) { 537 return NS_ERROR_UNEXPECTED; 538 } 539 540 uint32_t aSecurityState = 0; 541 PRErrorCode aErrorCode = 0; 542 nsTArray<RefPtr<nsIX509Cert>> aHandshakeCertificates; 543 nsCOMPtr<nsIX509Cert> aServerCert; 544 nsTArray<RefPtr<nsIX509Cert>> aSucceededCertChain; 545 Maybe<uint16_t> aCipherSuite; 546 Maybe<nsCString> aKeaGroupName; 547 Maybe<nsCString> aSignatureSchemeName; 548 Maybe<uint16_t> aProtocolVersion; 549 uint16_t aCertificateTransparencyStatus; 550 Maybe<bool> aIsAcceptedEch; 551 Maybe<bool> aIsDelegatedCredential; 552 Maybe<OverridableErrorCategory> aOverridableErrorCategory; 553 bool aMadeOCSPRequests = false; 554 bool aUsedPrivateDNS = false; 555 Maybe<bool> aIsEV; 556 bool aNPNCompleted = false; 557 nsCString aNegotiatedNPN; 558 bool aResumed = false; 559 bool aIsBuiltCertChainRootBuiltInRoot = false; 560 nsCString aPeerId; 561 rv = objStream->Read32(&aSecurityState); 562 if (NS_FAILED(rv)) { 563 return rv; 564 } 565 // mSubRequestsBrokenSecurity was removed in bug 748809 566 uint32_t unusedSubRequestsBrokenSecurity; 567 rv = objStream->Read32(&unusedSubRequestsBrokenSecurity); 568 if (NS_FAILED(rv)) { 569 return rv; 570 } 571 // mSubRequestsNoSecurity was removed in bug 748809 572 uint32_t unusedSubRequestsNoSecurity; 573 rv = objStream->Read32(&unusedSubRequestsNoSecurity); 574 if (NS_FAILED(rv)) { 575 return rv; 576 } 577 uint32_t errorCode; 578 rv = objStream->Read32(&errorCode); 579 if (NS_FAILED(rv)) { 580 return rv; 581 } 582 // PRErrorCode will be a negative value 583 aErrorCode = static_cast<PRErrorCode>(errorCode); 584 585 // Re-purpose mErrorMessageCached to represent serialization version 586 // If string doesn't match exact version it will be treated as older 587 // serialization. 588 nsAutoString serVersion; 589 rv = objStream->ReadString(serVersion); 590 if (NS_FAILED(rv)) { 591 return rv; 592 } 593 594 int32_t serVersionParsedToInt = 0; 595 596 if (!serVersion.IsEmpty()) { 597 char first = serVersion.First(); 598 // Check whether the first character of serVersion is a number 599 // since ToInteger() skipps some non integer values. 600 if (first >= '0' && first <= '9') { 601 nsresult error = NS_OK; 602 serVersionParsedToInt = serVersion.ToInteger(&error); 603 if (NS_FAILED(error)) { 604 return error; 605 } 606 } 607 } 608 609 // moved from nsISSLStatus 610 if (serVersionParsedToInt < 1) { 611 // nsISSLStatus may be present 612 rv = ReadSSLStatus(objStream, aServerCert, aCipherSuite, aProtocolVersion, 613 aOverridableErrorCategory, aIsEV, 614 aCertificateTransparencyStatus, aKeaGroupName, 615 aSignatureSchemeName, aSucceededCertChain); 616 NS_ENSURE_SUCCESS(rv, rv); 617 } else { 618 nsCOMPtr<nsISupports> cert; 619 rv = NS_ReadOptionalObject(objStream, true, getter_AddRefs(cert)); 620 NS_ENSURE_SUCCESS(rv, rv); 621 622 if (cert) { 623 aServerCert = do_QueryInterface(cert); 624 if (!aServerCert) { 625 return NS_NOINTERFACE; 626 } 627 } 628 629 uint16_t cipherSuite; 630 rv = objStream->Read16(&cipherSuite); 631 NS_ENSURE_SUCCESS(rv, rv); 632 633 uint16_t protocolVersion; 634 rv = objStream->Read16(&protocolVersion); 635 NS_ENSURE_SUCCESS(rv, rv); 636 637 OverridableErrorCategory overridableErrorCategory; 638 if (serVersionParsedToInt < 8) { 639 rv = ReadOldOverridableErrorBits(objStream, overridableErrorCategory); 640 NS_ENSURE_SUCCESS(rv, rv); 641 } else { 642 uint32_t overridableErrorCategoryInt; 643 rv = objStream->Read32(&overridableErrorCategoryInt); 644 NS_ENSURE_SUCCESS(rv, rv); 645 overridableErrorCategory = 646 IntToOverridableErrorCategory(overridableErrorCategoryInt); 647 } 648 bool isEV; 649 rv = objStream->ReadBoolean(&isEV); 650 NS_ENSURE_SUCCESS(rv, rv); 651 bool hasIsEVStatus; 652 rv = objStream->ReadBoolean(&hasIsEVStatus); 653 NS_ENSURE_SUCCESS(rv, rv); 654 if (hasIsEVStatus) { 655 aIsEV.emplace(isEV); 656 } 657 bool haveCipherSuiteAndProtocol; 658 rv = objStream->ReadBoolean(&haveCipherSuiteAndProtocol); 659 NS_ENSURE_SUCCESS(rv, rv); 660 if (haveCipherSuiteAndProtocol) { 661 aCipherSuite.emplace(cipherSuite); 662 aProtocolVersion.emplace(protocolVersion); 663 } 664 bool haveCertErrorBits; 665 rv = objStream->ReadBoolean(&haveCertErrorBits); 666 NS_ENSURE_SUCCESS(rv, rv); 667 if (haveCertErrorBits) { 668 aOverridableErrorCategory.emplace(overridableErrorCategory); 669 } 670 671 rv = objStream->Read16(&aCertificateTransparencyStatus); 672 NS_ENSURE_SUCCESS(rv, rv); 673 674 nsCString keaGroupName; 675 rv = objStream->ReadCString(keaGroupName); 676 NS_ENSURE_SUCCESS(rv, rv); 677 if (haveCipherSuiteAndProtocol) { 678 aKeaGroupName.emplace(keaGroupName); 679 } 680 681 nsCString signatureSchemeName; 682 rv = objStream->ReadCString(signatureSchemeName); 683 NS_ENSURE_SUCCESS(rv, rv); 684 if (haveCipherSuiteAndProtocol) { 685 aSignatureSchemeName.emplace(signatureSchemeName); 686 } 687 688 if (serVersionParsedToInt < 3) { 689 // The old data structure of certList(nsIX509CertList) presents 690 rv = ReadCertList(objStream, aSucceededCertChain); 691 NS_ENSURE_SUCCESS(rv, rv); 692 } else { 693 uint16_t certCount; 694 rv = objStream->Read16(&certCount); 695 NS_ENSURE_SUCCESS(rv, rv); 696 697 rv = 698 ReadCertificatesFromStream(objStream, certCount, aSucceededCertChain); 699 NS_ENSURE_SUCCESS(rv, rv); 700 } 701 } 702 // END moved from nsISSLStatus 703 if (serVersionParsedToInt < 3) { 704 // The old data structure of certList(nsIX509CertList) presents 705 rv = ReadCertList(objStream, aHandshakeCertificates); 706 NS_ENSURE_SUCCESS(rv, rv); 707 } else { 708 uint16_t certCount; 709 rv = objStream->Read16(&certCount); 710 NS_ENSURE_SUCCESS(rv, rv); 711 712 rv = ReadCertificatesFromStream(objStream, certCount, 713 aHandshakeCertificates); 714 NS_ENSURE_SUCCESS(rv, rv); 715 } 716 717 // mIsDelegatedCredential added in bug 1562773 718 if (serVersionParsedToInt >= 2) { 719 bool isDelegatedCredential; 720 rv = objStream->ReadBoolean(&isDelegatedCredential); 721 if (NS_FAILED(rv)) { 722 return rv; 723 } 724 // If aCipherSuite is Some, the serialized TransportSecurityinfo had its 725 // cipher suite and protocol information, which means it has this 726 // information. 727 if (aCipherSuite.isSome()) { 728 aIsDelegatedCredential.emplace(isDelegatedCredential); 729 } 730 } 731 732 // mNPNCompleted, mNegotiatedNPN, mResumed added in bug 1584104 733 if (serVersionParsedToInt >= 4) { 734 rv = objStream->ReadBoolean(&aNPNCompleted); 735 if (NS_FAILED(rv)) { 736 return rv; 737 } 738 739 rv = objStream->ReadCString(aNegotiatedNPN); 740 if (NS_FAILED(rv)) { 741 return rv; 742 } 743 744 rv = objStream->ReadBoolean(&aResumed); 745 if (NS_FAILED(rv)) { 746 return rv; 747 } 748 } 749 750 // mIsBuiltCertChainRootBuiltInRoot added in bug 1485652 751 if (serVersionParsedToInt >= 5) { 752 rv = objStream->ReadBoolean(&aIsBuiltCertChainRootBuiltInRoot); 753 if (NS_FAILED(rv)) { 754 return rv; 755 } 756 } 757 758 // mIsAcceptedEch added in bug 1678079 759 if (serVersionParsedToInt >= 6) { 760 bool isAcceptedEch; 761 rv = objStream->ReadBoolean(&isAcceptedEch); 762 if (NS_FAILED(rv)) { 763 return rv; 764 } 765 // If aCipherSuite is Some, the serialized TransportSecurityinfo had its 766 // cipher suite and protocol information, which means it has this 767 // information. 768 if (aCipherSuite.isSome()) { 769 aIsAcceptedEch.emplace(isAcceptedEch); 770 } 771 } 772 773 // mPeerId added in bug 1738664 774 if (serVersionParsedToInt >= 7) { 775 rv = objStream->ReadCString(aPeerId); 776 if (NS_FAILED(rv)) { 777 return rv; 778 } 779 } 780 781 if (serVersionParsedToInt >= 9) { 782 rv = objStream->ReadBoolean(&aMadeOCSPRequests); 783 if (NS_FAILED(rv)) { 784 return rv; 785 } 786 787 rv = objStream->ReadBoolean(&aUsedPrivateDNS); 788 if (NS_FAILED(rv)) { 789 return rv; 790 }; 791 } 792 793 RefPtr<nsITransportSecurityInfo> securityInfo(new TransportSecurityInfo( 794 aSecurityState, aErrorCode, std::move(aHandshakeCertificates), 795 aServerCert, std::move(aSucceededCertChain), aCipherSuite, aKeaGroupName, 796 aSignatureSchemeName, aProtocolVersion, aCertificateTransparencyStatus, 797 aIsAcceptedEch, aIsDelegatedCredential, aOverridableErrorCategory, 798 aMadeOCSPRequests, aUsedPrivateDNS, aIsEV, aNPNCompleted, aNegotiatedNPN, 799 aResumed, aIsBuiltCertChainRootBuiltInRoot, aPeerId)); 800 securityInfo.forget(aResult); 801 return NS_OK; 802 } 803 804 void TransportSecurityInfo::SerializeToIPC(IPC::MessageWriter* aWriter) { 805 WriteParam(aWriter, mSecurityState); 806 WriteParam(aWriter, mErrorCode); 807 WriteParam(aWriter, mHandshakeCertificates); 808 WriteParam(aWriter, mServerCert); 809 WriteParam(aWriter, mSucceededCertChain); 810 WriteParam(aWriter, mCipherSuite); 811 WriteParam(aWriter, mKeaGroupName); 812 WriteParam(aWriter, mSignatureSchemeName); 813 WriteParam(aWriter, mProtocolVersion); 814 WriteParam(aWriter, mCertificateTransparencyStatus); 815 WriteParam(aWriter, mIsAcceptedEch); 816 WriteParam(aWriter, mIsDelegatedCredential); 817 WriteParam(aWriter, mOverridableErrorCategory); 818 WriteParam(aWriter, mMadeOCSPRequests); 819 WriteParam(aWriter, mUsedPrivateDNS); 820 WriteParam(aWriter, mIsEV); 821 WriteParam(aWriter, mNPNCompleted); 822 WriteParam(aWriter, mNegotiatedNPN); 823 WriteParam(aWriter, mResumed); 824 WriteParam(aWriter, mIsBuiltCertChainRootBuiltInRoot); 825 WriteParam(aWriter, mPeerId); 826 } 827 828 bool TransportSecurityInfo::DeserializeFromIPC( 829 IPC::MessageReader* aReader, RefPtr<nsITransportSecurityInfo>* aResult) { 830 uint32_t aSecurityState; 831 PRErrorCode aErrorCode; 832 nsTArray<RefPtr<nsIX509Cert>> aHandshakeCertificates; 833 nsCOMPtr<nsIX509Cert> aServerCert; 834 nsTArray<RefPtr<nsIX509Cert>> aSucceededCertChain; 835 Maybe<uint16_t> aCipherSuite; 836 Maybe<nsCString> aKeaGroupName; 837 Maybe<nsCString> aSignatureSchemeName; 838 Maybe<uint16_t> aProtocolVersion; 839 uint16_t aCertificateTransparencyStatus; 840 Maybe<bool> aIsAcceptedEch; 841 Maybe<bool> aIsDelegatedCredential; 842 Maybe<OverridableErrorCategory> aOverridableErrorCategory; 843 bool aMadeOCSPRequests; 844 bool aUsedPrivateDNS; 845 Maybe<bool> aIsEV; 846 bool aNPNCompleted; 847 nsCString aNegotiatedNPN; 848 bool aResumed; 849 bool aIsBuiltCertChainRootBuiltInRoot; 850 nsCString aPeerId; 851 852 if (!ReadParam(aReader, &aSecurityState) || 853 !ReadParam(aReader, &aErrorCode) || 854 !ReadParam(aReader, &aHandshakeCertificates) || 855 !ReadParam(aReader, &aServerCert) || 856 !ReadParam(aReader, &aSucceededCertChain) || 857 !ReadParam(aReader, &aCipherSuite) || 858 !ReadParam(aReader, &aKeaGroupName) || 859 !ReadParam(aReader, &aSignatureSchemeName) || 860 !ReadParam(aReader, &aProtocolVersion) || 861 !ReadParam(aReader, &aCertificateTransparencyStatus) || 862 !ReadParam(aReader, &aIsAcceptedEch) || 863 !ReadParam(aReader, &aIsDelegatedCredential) || 864 !ReadParam(aReader, &aOverridableErrorCategory) || 865 !ReadParam(aReader, &aMadeOCSPRequests) || 866 !ReadParam(aReader, &aUsedPrivateDNS) || !ReadParam(aReader, &aIsEV) || 867 !ReadParam(aReader, &aNPNCompleted) || 868 !ReadParam(aReader, &aNegotiatedNPN) || !ReadParam(aReader, &aResumed) || 869 !ReadParam(aReader, &aIsBuiltCertChainRootBuiltInRoot) || 870 !ReadParam(aReader, &aPeerId)) { 871 return false; 872 } 873 874 RefPtr<nsITransportSecurityInfo> securityInfo(new TransportSecurityInfo( 875 aSecurityState, aErrorCode, std::move(aHandshakeCertificates), 876 aServerCert, std::move(aSucceededCertChain), aCipherSuite, aKeaGroupName, 877 aSignatureSchemeName, aProtocolVersion, aCertificateTransparencyStatus, 878 aIsAcceptedEch, aIsDelegatedCredential, aOverridableErrorCategory, 879 aMadeOCSPRequests, aUsedPrivateDNS, aIsEV, aNPNCompleted, aNegotiatedNPN, 880 aResumed, aIsBuiltCertChainRootBuiltInRoot, aPeerId)); 881 *aResult = std::move(securityInfo); 882 return true; 883 } 884 885 NS_IMETHODIMP 886 TransportSecurityInfo::GetHandshakeCertificates( 887 nsTArray<RefPtr<nsIX509Cert>>& aHandshakeCertificates) { 888 MOZ_ASSERT(aHandshakeCertificates.IsEmpty()); 889 if (!aHandshakeCertificates.IsEmpty()) { 890 return NS_ERROR_INVALID_ARG; 891 } 892 aHandshakeCertificates.AppendElements(mHandshakeCertificates); 893 return NS_OK; 894 } 895 896 NS_IMETHODIMP TransportSecurityInfo::GetServerCert(nsIX509Cert** aServerCert) { 897 NS_ENSURE_ARG_POINTER(aServerCert); 898 nsCOMPtr<nsIX509Cert> cert = mServerCert; 899 cert.forget(aServerCert); 900 return NS_OK; 901 } 902 903 NS_IMETHODIMP 904 TransportSecurityInfo::GetSucceededCertChain( 905 nsTArray<RefPtr<nsIX509Cert>>& aSucceededCertChain) { 906 MOZ_ASSERT(aSucceededCertChain.IsEmpty()); 907 if (!aSucceededCertChain.IsEmpty()) { 908 return NS_ERROR_INVALID_ARG; 909 } 910 aSucceededCertChain.AppendElements(mSucceededCertChain); 911 return NS_OK; 912 } 913 914 NS_IMETHODIMP TransportSecurityInfo::GetIsBuiltCertChainRootBuiltInRoot( 915 bool* aIsBuiltInRoot) { 916 NS_ENSURE_ARG_POINTER(aIsBuiltInRoot); 917 *aIsBuiltInRoot = mIsBuiltCertChainRootBuiltInRoot; 918 return NS_OK; 919 } 920 921 NS_IMETHODIMP 922 TransportSecurityInfo::GetCipherName(nsACString& aCipherName) { 923 if (mCipherSuite.isNothing()) { 924 return NS_ERROR_NOT_AVAILABLE; 925 } 926 SSLCipherSuiteInfo cipherInfo; 927 if (SSL_GetCipherSuiteInfo(*mCipherSuite, &cipherInfo, sizeof(cipherInfo)) != 928 SECSuccess) { 929 return NS_ERROR_FAILURE; 930 } 931 932 aCipherName.Assign(cipherInfo.cipherSuiteName); 933 return NS_OK; 934 } 935 936 NS_IMETHODIMP 937 TransportSecurityInfo::GetKeyLength(uint32_t* aKeyLength) { 938 NS_ENSURE_ARG_POINTER(aKeyLength); 939 940 if (mCipherSuite.isNothing()) { 941 return NS_ERROR_NOT_AVAILABLE; 942 } 943 SSLCipherSuiteInfo cipherInfo; 944 if (SSL_GetCipherSuiteInfo(*mCipherSuite, &cipherInfo, sizeof(cipherInfo)) != 945 SECSuccess) { 946 return NS_ERROR_FAILURE; 947 } 948 949 *aKeyLength = cipherInfo.symKeyBits; 950 return NS_OK; 951 } 952 953 NS_IMETHODIMP 954 TransportSecurityInfo::GetSecretKeyLength(uint32_t* aSecretKeyLength) { 955 NS_ENSURE_ARG_POINTER(aSecretKeyLength); 956 957 if (mCipherSuite.isNothing()) { 958 return NS_ERROR_NOT_AVAILABLE; 959 } 960 SSLCipherSuiteInfo cipherInfo; 961 if (SSL_GetCipherSuiteInfo(*mCipherSuite, &cipherInfo, sizeof(cipherInfo)) != 962 SECSuccess) { 963 return NS_ERROR_FAILURE; 964 } 965 966 *aSecretKeyLength = cipherInfo.effectiveKeyBits; 967 return NS_OK; 968 } 969 970 NS_IMETHODIMP 971 TransportSecurityInfo::GetKeaGroupName(nsACString& aKeaGroupName) { 972 if (mKeaGroupName.isNothing()) { 973 return NS_ERROR_NOT_AVAILABLE; 974 } 975 aKeaGroupName.Assign(*mKeaGroupName); 976 return NS_OK; 977 } 978 979 NS_IMETHODIMP 980 TransportSecurityInfo::GetSignatureSchemeName(nsACString& aSignatureScheme) { 981 if (mSignatureSchemeName.isNothing()) { 982 return NS_ERROR_NOT_AVAILABLE; 983 } 984 aSignatureScheme.Assign(*mSignatureSchemeName); 985 return NS_OK; 986 } 987 988 NS_IMETHODIMP 989 TransportSecurityInfo::GetProtocolVersion(uint16_t* aProtocolVersion) { 990 if (mProtocolVersion.isNothing()) { 991 return NS_ERROR_NOT_AVAILABLE; 992 } 993 *aProtocolVersion = *mProtocolVersion; 994 return NS_OK; 995 } 996 997 NS_IMETHODIMP 998 TransportSecurityInfo::GetCertificateTransparencyStatus( 999 uint16_t* aCertificateTransparencyStatus) { 1000 NS_ENSURE_ARG_POINTER(aCertificateTransparencyStatus); 1001 1002 *aCertificateTransparencyStatus = mCertificateTransparencyStatus; 1003 return NS_OK; 1004 } 1005 1006 NS_IMETHODIMP 1007 TransportSecurityInfo::GetMadeOCSPRequests(bool* aMadeOCSPRequests) { 1008 *aMadeOCSPRequests = mMadeOCSPRequests; 1009 return NS_OK; 1010 } 1011 1012 NS_IMETHODIMP 1013 TransportSecurityInfo::GetUsedPrivateDNS(bool* aUsedPrivateDNS) { 1014 *aUsedPrivateDNS = mUsedPrivateDNS; 1015 return NS_OK; 1016 } 1017 1018 // static 1019 uint16_t TransportSecurityInfo::ConvertCertificateTransparencyInfoToStatus( 1020 const mozilla::psm::CertificateTransparencyInfo& info) { 1021 using mozilla::ct::CTPolicyCompliance; 1022 1023 if (!info.enabled || info.policyCompliance.isNothing()) { 1024 // CT disabled. 1025 return nsITransportSecurityInfo::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE; 1026 } 1027 1028 switch (*info.policyCompliance) { 1029 case CTPolicyCompliance::Compliant: 1030 return nsITransportSecurityInfo:: 1031 CERTIFICATE_TRANSPARENCY_POLICY_COMPLIANT; 1032 case CTPolicyCompliance::NotEnoughScts: 1033 return nsITransportSecurityInfo :: 1034 CERTIFICATE_TRANSPARENCY_POLICY_NOT_ENOUGH_SCTS; 1035 case CTPolicyCompliance::NotDiverseScts: 1036 return nsITransportSecurityInfo :: 1037 CERTIFICATE_TRANSPARENCY_POLICY_NOT_DIVERSE_SCTS; 1038 default: 1039 MOZ_ASSERT_UNREACHABLE("Unexpected CTPolicyCompliance type"); 1040 } 1041 1042 return nsITransportSecurityInfo::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE; 1043 } 1044 1045 NS_IMETHODIMP 1046 TransportSecurityInfo::GetOverridableErrorCategory( 1047 OverridableErrorCategory* aOverridableErrorCategory) { 1048 NS_ENSURE_ARG_POINTER(aOverridableErrorCategory); 1049 1050 if (mOverridableErrorCategory.isSome()) { 1051 *aOverridableErrorCategory = *mOverridableErrorCategory; 1052 } else { 1053 *aOverridableErrorCategory = OverridableErrorCategory::ERROR_UNSET; 1054 } 1055 return NS_OK; 1056 } 1057 1058 NS_IMETHODIMP 1059 TransportSecurityInfo::GetIsExtendedValidation(bool* aIsEV) { 1060 NS_ENSURE_ARG_POINTER(aIsEV); 1061 1062 *aIsEV = false; 1063 // Never allow bad certs for EV, regardless of overrides. 1064 if (mOverridableErrorCategory.isSome()) { 1065 return NS_OK; 1066 } 1067 1068 if (!mIsEV.isSome()) { 1069 return NS_ERROR_NOT_AVAILABLE; 1070 } 1071 1072 *aIsEV = *mIsEV; 1073 return NS_OK; 1074 } 1075 1076 NS_IMETHODIMP 1077 TransportSecurityInfo::GetIsAcceptedEch(bool* aIsAcceptedEch) { 1078 NS_ENSURE_ARG_POINTER(aIsAcceptedEch); 1079 1080 if (mIsAcceptedEch.isNothing()) { 1081 return NS_ERROR_NOT_AVAILABLE; 1082 } 1083 *aIsAcceptedEch = *mIsAcceptedEch; 1084 return NS_OK; 1085 } 1086 1087 NS_IMETHODIMP 1088 TransportSecurityInfo::GetIsDelegatedCredential(bool* aIsDelegatedCredential) { 1089 NS_ENSURE_ARG_POINTER(aIsDelegatedCredential); 1090 1091 if (mIsDelegatedCredential.isNothing()) { 1092 return NS_ERROR_NOT_AVAILABLE; 1093 } 1094 *aIsDelegatedCredential = *mIsDelegatedCredential; 1095 return NS_OK; 1096 } 1097 1098 NS_IMETHODIMP 1099 TransportSecurityInfo::GetNegotiatedNPN(nsACString& aNegotiatedNPN) { 1100 if (!mNPNCompleted) { 1101 return NS_ERROR_NOT_CONNECTED; 1102 } 1103 1104 aNegotiatedNPN = mNegotiatedNPN; 1105 return NS_OK; 1106 } 1107 1108 NS_IMETHODIMP 1109 TransportSecurityInfo::GetResumed(bool* aResumed) { 1110 NS_ENSURE_ARG_POINTER(aResumed); 1111 *aResumed = mResumed; 1112 return NS_OK; 1113 } 1114 1115 NS_IMETHODIMP 1116 TransportSecurityInfo::GetPeerId(nsACString& aResult) { 1117 aResult.Assign(mPeerId); 1118 return NS_OK; 1119 } 1120 1121 } // namespace psm 1122 } // namespace mozilla