Line data Source code
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 "CTVerifyResult.h"
8 : #include "mozilla/Casting.h"
9 : #include "nsSSLStatus.h"
10 : #include "nsIClassInfoImpl.h"
11 : #include "nsIObjectOutputStream.h"
12 : #include "nsIObjectInputStream.h"
13 : #include "nsNSSCertificate.h"
14 : #include "ssl.h"
15 :
16 : NS_IMETHODIMP
17 0 : nsSSLStatus::GetServerCert(nsIX509Cert** aServerCert)
18 : {
19 0 : NS_ENSURE_ARG_POINTER(aServerCert);
20 :
21 0 : nsCOMPtr<nsIX509Cert> cert = mServerCert;
22 0 : cert.forget(aServerCert);
23 0 : return NS_OK;
24 : }
25 :
26 : NS_IMETHODIMP
27 0 : nsSSLStatus::GetKeyLength(uint32_t* aKeyLength)
28 : {
29 0 : NS_ENSURE_ARG_POINTER(aKeyLength);
30 0 : if (!mHaveCipherSuiteAndProtocol) {
31 0 : return NS_ERROR_NOT_AVAILABLE;
32 : }
33 :
34 : SSLCipherSuiteInfo cipherInfo;
35 0 : if (SSL_GetCipherSuiteInfo(mCipherSuite, &cipherInfo,
36 : sizeof(cipherInfo)) != SECSuccess) {
37 0 : return NS_ERROR_FAILURE;
38 : }
39 :
40 0 : *aKeyLength = cipherInfo.symKeyBits;
41 0 : return NS_OK;
42 : }
43 :
44 : NS_IMETHODIMP
45 0 : nsSSLStatus::GetSecretKeyLength(uint32_t* aSecretKeyLength)
46 : {
47 0 : NS_ENSURE_ARG_POINTER(aSecretKeyLength);
48 0 : if (!mHaveCipherSuiteAndProtocol) {
49 0 : return NS_ERROR_NOT_AVAILABLE;
50 : }
51 :
52 : SSLCipherSuiteInfo cipherInfo;
53 0 : if (SSL_GetCipherSuiteInfo(mCipherSuite, &cipherInfo,
54 : sizeof(cipherInfo)) != SECSuccess) {
55 0 : return NS_ERROR_FAILURE;
56 : }
57 :
58 0 : *aSecretKeyLength = cipherInfo.effectiveKeyBits;
59 0 : return NS_OK;
60 : }
61 :
62 : NS_IMETHODIMP
63 0 : nsSSLStatus::GetCipherName(nsACString& aCipherName)
64 : {
65 0 : if (!mHaveCipherSuiteAndProtocol) {
66 0 : return NS_ERROR_NOT_AVAILABLE;
67 : }
68 :
69 : SSLCipherSuiteInfo cipherInfo;
70 0 : if (SSL_GetCipherSuiteInfo(mCipherSuite, &cipherInfo,
71 : sizeof(cipherInfo)) != SECSuccess) {
72 0 : return NS_ERROR_FAILURE;
73 : }
74 :
75 0 : aCipherName.Assign(cipherInfo.cipherSuiteName);
76 0 : return NS_OK;
77 : }
78 :
79 : NS_IMETHODIMP
80 0 : nsSSLStatus::GetProtocolVersion(uint16_t* aProtocolVersion)
81 : {
82 0 : NS_ENSURE_ARG_POINTER(aProtocolVersion);
83 0 : if (!mHaveCipherSuiteAndProtocol) {
84 0 : return NS_ERROR_NOT_AVAILABLE;
85 : }
86 :
87 0 : *aProtocolVersion = mProtocolVersion;
88 0 : return NS_OK;
89 : }
90 :
91 : NS_IMETHODIMP
92 0 : nsSSLStatus::GetCertificateTransparencyStatus(
93 : uint16_t* aCertificateTransparencyStatus)
94 : {
95 0 : NS_ENSURE_ARG_POINTER(aCertificateTransparencyStatus);
96 :
97 0 : *aCertificateTransparencyStatus = mCertificateTransparencyStatus;
98 0 : return NS_OK;
99 : }
100 :
101 : NS_IMETHODIMP
102 0 : nsSSLStatus::GetIsDomainMismatch(bool* aIsDomainMismatch)
103 : {
104 0 : NS_ENSURE_ARG_POINTER(aIsDomainMismatch);
105 :
106 0 : *aIsDomainMismatch = mHaveCertErrorBits && mIsDomainMismatch;
107 0 : return NS_OK;
108 : }
109 :
110 : NS_IMETHODIMP
111 0 : nsSSLStatus::GetIsNotValidAtThisTime(bool* aIsNotValidAtThisTime)
112 : {
113 0 : NS_ENSURE_ARG_POINTER(aIsNotValidAtThisTime);
114 :
115 0 : *aIsNotValidAtThisTime = mHaveCertErrorBits && mIsNotValidAtThisTime;
116 0 : return NS_OK;
117 : }
118 :
119 : NS_IMETHODIMP
120 0 : nsSSLStatus::GetIsUntrusted(bool* aIsUntrusted)
121 : {
122 0 : NS_ENSURE_ARG_POINTER(aIsUntrusted);
123 :
124 0 : *aIsUntrusted = mHaveCertErrorBits && mIsUntrusted;
125 0 : return NS_OK;
126 : }
127 :
128 : NS_IMETHODIMP
129 0 : nsSSLStatus::GetIsExtendedValidation(bool* aIsEV)
130 : {
131 0 : NS_ENSURE_ARG_POINTER(aIsEV);
132 0 : *aIsEV = false;
133 :
134 : // Never allow bad certs for EV, regardless of overrides.
135 0 : if (mHaveCertErrorBits) {
136 0 : return NS_OK;
137 : }
138 :
139 0 : if (mHasIsEVStatus) {
140 0 : *aIsEV = mIsEV;
141 0 : return NS_OK;
142 : }
143 :
144 0 : return NS_ERROR_NOT_AVAILABLE;
145 : }
146 :
147 : NS_IMETHODIMP
148 0 : nsSSLStatus::Read(nsIObjectInputStream* aStream)
149 : {
150 0 : nsCOMPtr<nsISupports> cert;
151 0 : nsresult rv = aStream->ReadObject(true, getter_AddRefs(cert));
152 0 : NS_ENSURE_SUCCESS(rv, rv);
153 :
154 0 : mServerCert = do_QueryInterface(cert);
155 0 : if (!mServerCert) {
156 0 : return NS_NOINTERFACE;
157 : }
158 :
159 0 : rv = aStream->Read16(&mCipherSuite);
160 0 : NS_ENSURE_SUCCESS(rv, rv);
161 :
162 : // The code below is a workaround to allow serializing new fields
163 : // while preserving binary compatibility with older streams. For more details
164 : // on the binary compatibility requirement, refer to bug 1248628.
165 : // Here, we take advantage of the fact that mProtocolVersion was originally
166 : // stored as a 16 bits integer, but the highest 8 bits were never used.
167 : // These bits are now used for stream versioning.
168 : uint16_t protocolVersionAndStreamFormatVersion;
169 0 : rv = aStream->Read16(&protocolVersionAndStreamFormatVersion);
170 0 : NS_ENSURE_SUCCESS(rv, rv);
171 0 : mProtocolVersion = protocolVersionAndStreamFormatVersion & 0xFF;
172 : const uint8_t streamFormatVersion =
173 0 : (protocolVersionAndStreamFormatVersion >> 8) & 0xFF;
174 :
175 0 : rv = aStream->ReadBoolean(&mIsDomainMismatch);
176 0 : NS_ENSURE_SUCCESS(rv, rv);
177 0 : rv = aStream->ReadBoolean(&mIsNotValidAtThisTime);
178 0 : NS_ENSURE_SUCCESS(rv, rv);
179 0 : rv = aStream->ReadBoolean(&mIsUntrusted);
180 0 : NS_ENSURE_SUCCESS(rv, rv);
181 0 : rv = aStream->ReadBoolean(&mIsEV);
182 0 : NS_ENSURE_SUCCESS(rv, rv);
183 :
184 0 : rv = aStream->ReadBoolean(&mHasIsEVStatus);
185 0 : NS_ENSURE_SUCCESS(rv, rv);
186 0 : rv = aStream->ReadBoolean(&mHaveCipherSuiteAndProtocol);
187 0 : NS_ENSURE_SUCCESS(rv, rv);
188 0 : rv = aStream->ReadBoolean(&mHaveCertErrorBits);
189 0 : NS_ENSURE_SUCCESS(rv, rv);
190 :
191 : // Added in version 1 (see bug 1305289).
192 0 : if (streamFormatVersion >= 1) {
193 0 : rv = aStream->Read16(&mCertificateTransparencyStatus);
194 0 : NS_ENSURE_SUCCESS(rv, rv);
195 : }
196 :
197 0 : return NS_OK;
198 : }
199 :
200 : NS_IMETHODIMP
201 0 : nsSSLStatus::Write(nsIObjectOutputStream* aStream)
202 : {
203 : // The current version of the binary stream format.
204 0 : const uint8_t STREAM_FORMAT_VERSION = 1;
205 :
206 : nsresult rv = aStream->WriteCompoundObject(mServerCert,
207 : NS_GET_IID(nsIX509Cert),
208 0 : true);
209 0 : NS_ENSURE_SUCCESS(rv, rv);
210 :
211 0 : rv = aStream->Write16(mCipherSuite);
212 0 : NS_ENSURE_SUCCESS(rv, rv);
213 :
214 : uint16_t protocolVersionAndStreamFormatVersion =
215 0 : mozilla::AssertedCast<uint8_t>(mProtocolVersion) |
216 0 : (STREAM_FORMAT_VERSION << 8);
217 0 : rv = aStream->Write16(protocolVersionAndStreamFormatVersion);
218 0 : NS_ENSURE_SUCCESS(rv, rv);
219 :
220 0 : rv = aStream->WriteBoolean(mIsDomainMismatch);
221 0 : NS_ENSURE_SUCCESS(rv, rv);
222 0 : rv = aStream->WriteBoolean(mIsNotValidAtThisTime);
223 0 : NS_ENSURE_SUCCESS(rv, rv);
224 0 : rv = aStream->WriteBoolean(mIsUntrusted);
225 0 : NS_ENSURE_SUCCESS(rv, rv);
226 0 : rv = aStream->WriteBoolean(mIsEV);
227 0 : NS_ENSURE_SUCCESS(rv, rv);
228 :
229 0 : rv = aStream->WriteBoolean(mHasIsEVStatus);
230 0 : NS_ENSURE_SUCCESS(rv, rv);
231 0 : rv = aStream->WriteBoolean(mHaveCipherSuiteAndProtocol);
232 0 : NS_ENSURE_SUCCESS(rv, rv);
233 0 : rv = aStream->WriteBoolean(mHaveCertErrorBits);
234 0 : NS_ENSURE_SUCCESS(rv, rv);
235 :
236 : // Added in version 1.
237 0 : rv = aStream->Write16(mCertificateTransparencyStatus);
238 0 : NS_ENSURE_SUCCESS(rv, rv);
239 :
240 0 : return NS_OK;
241 : }
242 :
243 : NS_IMETHODIMP
244 0 : nsSSLStatus::GetInterfaces(uint32_t* aCount, nsIID*** aArray)
245 : {
246 0 : *aCount = 0;
247 0 : *aArray = nullptr;
248 0 : return NS_OK;
249 : }
250 :
251 : NS_IMETHODIMP
252 0 : nsSSLStatus::GetScriptableHelper(nsIXPCScriptable** aHelper)
253 : {
254 0 : *aHelper = nullptr;
255 0 : return NS_OK;
256 : }
257 :
258 : NS_IMETHODIMP
259 0 : nsSSLStatus::GetContractID(char** aContractID)
260 : {
261 0 : *aContractID = nullptr;
262 0 : return NS_OK;
263 : }
264 :
265 : NS_IMETHODIMP
266 0 : nsSSLStatus::GetClassDescription(char** aClassDescription)
267 : {
268 0 : *aClassDescription = nullptr;
269 0 : return NS_OK;
270 : }
271 :
272 : NS_IMETHODIMP
273 0 : nsSSLStatus::GetClassID(nsCID** aClassID)
274 : {
275 0 : *aClassID = (nsCID*) moz_xmalloc(sizeof(nsCID));
276 0 : if (!*aClassID) {
277 0 : return NS_ERROR_OUT_OF_MEMORY;
278 : }
279 0 : return GetClassIDNoAlloc(*aClassID);
280 : }
281 :
282 : NS_IMETHODIMP
283 0 : nsSSLStatus::GetFlags(uint32_t* aFlags)
284 : {
285 0 : *aFlags = 0;
286 0 : return NS_OK;
287 : }
288 :
289 : static NS_DEFINE_CID(kSSLStatusCID, NS_SSLSTATUS_CID);
290 :
291 : NS_IMETHODIMP
292 0 : nsSSLStatus::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
293 : {
294 0 : *aClassIDNoAlloc = kSSLStatusCID;
295 0 : return NS_OK;
296 : }
297 :
298 0 : nsSSLStatus::nsSSLStatus()
299 : : mCipherSuite(0)
300 : , mProtocolVersion(0)
301 : , mCertificateTransparencyStatus(nsISSLStatus::
302 : CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE)
303 : , mIsDomainMismatch(false)
304 : , mIsNotValidAtThisTime(false)
305 : , mIsUntrusted(false)
306 : , mIsEV(false)
307 : , mHasIsEVStatus(false)
308 : , mHaveCipherSuiteAndProtocol(false)
309 0 : , mHaveCertErrorBits(false)
310 : {
311 0 : }
312 :
313 0 : NS_IMPL_ISUPPORTS(nsSSLStatus, nsISSLStatus, nsISerializable, nsIClassInfo)
314 :
315 0 : nsSSLStatus::~nsSSLStatus()
316 : {
317 0 : }
318 :
319 : void
320 0 : nsSSLStatus::SetServerCert(nsNSSCertificate* aServerCert, EVStatus aEVStatus)
321 : {
322 0 : MOZ_ASSERT(aServerCert);
323 :
324 0 : mServerCert = aServerCert;
325 0 : mIsEV = (aEVStatus == EVStatus::EV);
326 0 : mHasIsEVStatus = true;
327 0 : }
328 :
329 : void
330 0 : nsSSLStatus::SetCertificateTransparencyInfo(
331 : const mozilla::psm::CertificateTransparencyInfo& info)
332 : {
333 : using mozilla::ct::CTPolicyCompliance;
334 :
335 0 : mCertificateTransparencyStatus =
336 : nsISSLStatus::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE;
337 :
338 0 : if (!info.enabled) {
339 : // CT disabled.
340 0 : return;
341 : }
342 :
343 0 : switch (info.policyCompliance) {
344 : case CTPolicyCompliance::Compliant:
345 0 : mCertificateTransparencyStatus =
346 : nsISSLStatus::CERTIFICATE_TRANSPARENCY_POLICY_COMPLIANT;
347 0 : break;
348 : case CTPolicyCompliance::NotEnoughScts:
349 0 : mCertificateTransparencyStatus =
350 : nsISSLStatus::CERTIFICATE_TRANSPARENCY_POLICY_NOT_ENOUGH_SCTS;
351 0 : break;
352 : case CTPolicyCompliance::NotDiverseScts:
353 0 : mCertificateTransparencyStatus =
354 : nsISSLStatus::CERTIFICATE_TRANSPARENCY_POLICY_NOT_DIVERSE_SCTS;
355 0 : break;
356 : case CTPolicyCompliance::Unknown:
357 : default:
358 0 : MOZ_ASSERT_UNREACHABLE("Unexpected CTPolicyCompliance type");
359 : }
360 : }
|