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
) {
106 ScopedCFTypeRef
<CFDataRef
> der_data(SecCertificateCopyData(cert_handle
));
109 encoded
->assign(reinterpret_cast<const char*>(CFDataGetBytePtr(der_data
)),
110 CFDataGetLength(der_data
));
115 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a
,
116 X509Certificate::OSCertHandle b
) {
122 ScopedCFTypeRef
<CFDataRef
> a_data(SecCertificateCopyData(a
));
123 ScopedCFTypeRef
<CFDataRef
> b_data(SecCertificateCopyData(b
));
124 return a_data
&& b_data
&&
125 CFDataGetLength(a_data
) == CFDataGetLength(b_data
) &&
126 memcmp(CFDataGetBytePtr(a_data
), CFDataGetBytePtr(b_data
),
127 CFDataGetLength(a_data
)) == 0;
131 X509Certificate::OSCertHandle
X509Certificate::CreateOSCertHandleFromBytes(
132 const char* data
, int length
) {
133 ScopedCFTypeRef
<CFDataRef
> cert_data(CFDataCreateWithBytesNoCopy(
134 kCFAllocatorDefault
, reinterpret_cast<const UInt8
*>(data
), length
,
138 OSCertHandle cert_handle
= SecCertificateCreateWithData(NULL
, cert_data
);
141 if (!IsValidOSCertHandle(cert_handle
)) {
142 CFRelease(cert_handle
);
149 X509Certificate::OSCertHandles
X509Certificate::CreateOSCertHandlesFromBytes(
153 return x509_util::CreateOSCertHandlesFromBytes(data
, length
, format
);
157 X509Certificate::OSCertHandle
X509Certificate::DupOSCertHandle(
158 OSCertHandle handle
) {
161 return reinterpret_cast<OSCertHandle
>(const_cast<void*>(CFRetain(handle
)));
165 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle
) {
167 CFRelease(cert_handle
);
171 SHA1HashValue
X509Certificate::CalculateFingerprint(
174 memset(sha1
.data
, 0, sizeof(sha1
.data
));
176 ScopedCFTypeRef
<CFDataRef
> cert_data(SecCertificateCopyData(cert
));
179 DCHECK(CFDataGetBytePtr(cert_data
));
180 DCHECK_NE(0, CFDataGetLength(cert_data
));
181 CC_SHA1(CFDataGetBytePtr(cert_data
), CFDataGetLength(cert_data
), sha1
.data
);
187 SHA1HashValue
X509Certificate::CalculateCAFingerprint(
188 const OSCertHandles
& intermediates
) {
190 memset(sha1
.data
, 0, sizeof(sha1
.data
));
192 // The CC_SHA(3cc) man page says all CC_SHA1_xxx routines return 1, so
193 // we don't check their return values.
194 CC_SHA1_CTX sha1_ctx
;
195 CC_SHA1_Init(&sha1_ctx
);
196 for (size_t i
= 0; i
< intermediates
.size(); ++i
) {
197 ScopedCFTypeRef
<CFDataRef
>
198 cert_data(SecCertificateCopyData(intermediates
[i
]));
201 CC_SHA1_Update(&sha1_ctx
,
202 CFDataGetBytePtr(cert_data
),
203 CFDataGetLength(cert_data
));
205 CC_SHA1_Final(sha1
.data
, &sha1_ctx
);
210 X509Certificate::OSCertHandle
211 X509Certificate::ReadOSCertHandleFromPickle(PickleIterator
* pickle_iter
) {
212 return x509_util::ReadOSCertHandleFromPickle(pickle_iter
);
216 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle
,
218 ScopedCFTypeRef
<CFDataRef
> cert_data(SecCertificateCopyData(cert_handle
));
222 return pickle
->WriteData(
223 reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data
)),
224 CFDataGetLength(cert_data
));
228 void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle
,
230 PublicKeyType
* type
) {
231 x509_util_ios::NSSCertificate
nss_cert(cert_handle
);
232 x509_util::GetPublicKeyInfo(nss_cert
.cert_handle(), size_bits
, type
);