1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/cert/x509_certificate.h"
7 #include <CommonCrypto/CommonDigest.h>
8 #include <Security/Security.h>
24 #include "base/logging.h"
25 #include "base/mac/scoped_cftyperef.h"
26 #include "base/memory/scoped_ptr.h"
27 #include "base/pickle.h"
28 #include "base/time/time.h"
29 #include "crypto/nss_util.h"
30 #include "crypto/scoped_nss_types.h"
31 #include "net/base/net_errors.h"
32 #include "net/cert/asn1_util.h"
33 #include "net/cert/cert_status_flags.h"
34 #include "net/cert/cert_verify_result.h"
35 #include "net/cert/ev_root_ca_metadata.h"
36 #include "net/cert/x509_util_ios.h"
37 #include "net/cert/x509_util_nss.h"
39 using base::ScopedCFTypeRef
;
43 // Returns true if a given |cert_handle| is actually a valid X.509 certificate
46 // SecCertificateCreateFromData() does not always force the immediate parsing of
47 // the certificate, and as such, may return a SecCertificateRef for an
48 // invalid/unparsable certificate. Force parsing to occur to ensure that the
49 // SecCertificateRef is correct. On later versions where
50 // SecCertificateCreateFromData() immediately parses, rather than lazily, this
51 // call is cheap, as the subject is cached.
52 bool IsValidOSCertHandle(SecCertificateRef cert_handle
) {
53 ScopedCFTypeRef
<CFStringRef
> sanity_check(
54 SecCertificateCopySubjectSummary(cert_handle
));
55 return sanity_check
!= NULL
;
59 void X509Certificate::Initialize() {
60 x509_util_ios::NSSCertificate
nss_cert(cert_handle_
);
61 CERTCertificate
* cert_handle
= nss_cert
.cert_handle();
63 x509_util::ParsePrincipal(&cert_handle
->subject
, &subject_
);
64 x509_util::ParsePrincipal(&cert_handle
->issuer
, &issuer_
);
65 x509_util::ParseDate(&cert_handle
->validity
.notBefore
, &valid_start_
);
66 x509_util::ParseDate(&cert_handle
->validity
.notAfter
, &valid_expiry_
);
67 serial_number_
= x509_util::ParseSerialNumber(cert_handle
);
69 fingerprint_
= CalculateFingerprint(cert_handle_
);
70 ca_fingerprint_
= CalculateCAFingerprint(intermediate_ca_certs_
);
73 bool X509Certificate::IsIssuedByEncoded(
74 const std::vector
<std::string
>& valid_issuers
) {
75 x509_util_ios::NSSCertChain
nss_chain(this);
76 // Convert to scoped CERTName* list.
77 std::vector
<CERTName
*> issuers
;
78 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
79 if (!x509_util::GetIssuersFromEncodedList(valid_issuers
,
84 return x509_util::IsCertificateIssuedBy(
85 nss_chain
.cert_chain(), issuers
);
88 void X509Certificate::GetSubjectAltName(
89 std::vector
<std::string
>* dns_names
,
90 std::vector
<std::string
>* ip_addrs
) const {
91 x509_util_ios::NSSCertificate
nss_cert(cert_handle_
);
92 CERTCertificate
* cert_handle
= nss_cert
.cert_handle();
100 x509_util::GetSubjectAltName(cert_handle
, dns_names
, ip_addrs
);
104 bool X509Certificate::GetDEREncoded(OSCertHandle cert_handle
,
105 std::string
* encoded
) {
108 ScopedCFTypeRef
<CFDataRef
> der_data(SecCertificateCopyData(cert_handle
));
111 encoded
->assign(reinterpret_cast<const char*>(CFDataGetBytePtr(der_data
)),
112 CFDataGetLength(der_data
));
117 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a
,
118 X509Certificate::OSCertHandle b
) {
124 ScopedCFTypeRef
<CFDataRef
> a_data(SecCertificateCopyData(a
));
125 ScopedCFTypeRef
<CFDataRef
> b_data(SecCertificateCopyData(b
));
126 return a_data
&& b_data
&&
127 CFDataGetLength(a_data
) == CFDataGetLength(b_data
) &&
128 memcmp(CFDataGetBytePtr(a_data
), CFDataGetBytePtr(b_data
),
129 CFDataGetLength(a_data
)) == 0;
133 X509Certificate::OSCertHandle
X509Certificate::CreateOSCertHandleFromBytes(
134 const char* data
, int length
) {
135 ScopedCFTypeRef
<CFDataRef
> cert_data(CFDataCreateWithBytesNoCopy(
136 kCFAllocatorDefault
, reinterpret_cast<const UInt8
*>(data
), length
,
140 OSCertHandle cert_handle
= SecCertificateCreateWithData(NULL
, cert_data
);
143 if (!IsValidOSCertHandle(cert_handle
)) {
144 CFRelease(cert_handle
);
151 X509Certificate::OSCertHandles
X509Certificate::CreateOSCertHandlesFromBytes(
155 return x509_util::CreateOSCertHandlesFromBytes(data
, length
, format
);
159 X509Certificate::OSCertHandle
X509Certificate::DupOSCertHandle(
160 OSCertHandle handle
) {
163 return reinterpret_cast<OSCertHandle
>(const_cast<void*>(CFRetain(handle
)));
167 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle
) {
169 CFRelease(cert_handle
);
173 SHA1HashValue
X509Certificate::CalculateFingerprint(
176 memset(sha1
.data
, 0, sizeof(sha1
.data
));
178 ScopedCFTypeRef
<CFDataRef
> cert_data(SecCertificateCopyData(cert
));
181 DCHECK(CFDataGetBytePtr(cert_data
));
182 DCHECK_NE(0, CFDataGetLength(cert_data
));
183 CC_SHA1(CFDataGetBytePtr(cert_data
), CFDataGetLength(cert_data
), sha1
.data
);
189 SHA256HashValue
X509Certificate::CalculateFingerprint256(OSCertHandle cert
) {
190 SHA256HashValue sha256
;
191 memset(sha256
.data
, 0, sizeof(sha256
.data
));
193 ScopedCFTypeRef
<CFDataRef
> cert_data(SecCertificateCopyData(cert
));
196 DCHECK(CFDataGetBytePtr(cert_data
));
197 DCHECK_NE(0, CFDataGetLength(cert_data
));
199 CFDataGetBytePtr(cert_data
), CFDataGetLength(cert_data
), sha256
.data
);
205 SHA1HashValue
X509Certificate::CalculateCAFingerprint(
206 const OSCertHandles
& intermediates
) {
208 memset(sha1
.data
, 0, sizeof(sha1
.data
));
210 // The CC_SHA(3cc) man page says all CC_SHA1_xxx routines return 1, so
211 // we don't check their return values.
212 CC_SHA1_CTX sha1_ctx
;
213 CC_SHA1_Init(&sha1_ctx
);
214 for (size_t i
= 0; i
< intermediates
.size(); ++i
) {
215 ScopedCFTypeRef
<CFDataRef
>
216 cert_data(SecCertificateCopyData(intermediates
[i
]));
219 CC_SHA1_Update(&sha1_ctx
,
220 CFDataGetBytePtr(cert_data
),
221 CFDataGetLength(cert_data
));
223 CC_SHA1_Final(sha1
.data
, &sha1_ctx
);
228 X509Certificate::OSCertHandle
X509Certificate::ReadOSCertHandleFromPickle(
229 base::PickleIterator
* pickle_iter
) {
230 return x509_util::ReadOSCertHandleFromPickle(pickle_iter
);
234 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle
,
235 base::Pickle
* pickle
) {
236 ScopedCFTypeRef
<CFDataRef
> cert_data(SecCertificateCopyData(cert_handle
));
240 return pickle
->WriteData(
241 reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data
)),
242 CFDataGetLength(cert_data
));
246 void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle
,
248 PublicKeyType
* type
) {
249 x509_util_ios::NSSCertificate
nss_cert(cert_handle
);
250 x509_util::GetPublicKeyInfo(nss_cert
.cert_handle(), size_bits
, type
);
254 bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle
) {
255 x509_util_ios::NSSCertificate
nss_cert(cert_handle
);
256 crypto::ScopedSECKEYPublicKey
public_key(
257 CERT_ExtractPublicKey(nss_cert
.cert_handle()));
258 if (!public_key
.get())
260 return SECSuccess
== CERT_VerifySignedDataWithPublicKey(
261 &nss_cert
.cert_handle()->signatureWrap
, public_key
.get(), NULL
);