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