OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/base/x509_util.h" | 5 #include "net/base/x509_util.h" |
6 #include "net/base/x509_util_nss.h" | 6 #include "net/base/x509_util_nss.h" |
7 | 7 |
8 #include <cert.h> | 8 #include <cert.h> |
9 #include <cryptohi.h> | 9 #include <cryptohi.h> |
10 #include <pk11pub.h> | 10 #include <pk11pub.h> |
11 #include <prerror.h> | 11 #include <prerror.h> |
12 #include <secmod.h> | 12 #include <secmod.h> |
13 #include <secport.h> | 13 #include <secport.h> |
14 | 14 |
15 #include "base/debug/leak_annotations.h" | 15 #include "base/debug/leak_annotations.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/memory/scoped_ptr.h" | 17 #include "base/memory/scoped_ptr.h" |
18 #include "base/memory/singleton.h" | 18 #include "base/memory/singleton.h" |
19 #include "crypto/ec_private_key.h" | 19 #include "crypto/ec_private_key.h" |
20 #include "crypto/nss_util.h" | 20 #include "crypto/nss_util.h" |
21 #include "crypto/nss_util_internal.h" | 21 #include "crypto/nss_util_internal.h" |
22 #include "crypto/scoped_nss_types.h" | 22 #include "crypto/scoped_nss_types.h" |
23 #include "crypto/third_party/nss/chromium-nss.h" | 23 #include "crypto/third_party/nss/chromium-nss.h" |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
27 class ObCertOIDWrapper { | 27 class DomainBoundCertOIDWrapper { |
28 public: | 28 public: |
29 static ObCertOIDWrapper* GetInstance() { | 29 static DomainBoundCertOIDWrapper* GetInstance() { |
30 // Instantiated as a leaky singleton to allow the singleton to be | 30 // Instantiated as a leaky singleton to allow the singleton to be |
31 // constructed on a worker thead that is not joined when a process | 31 // constructed on a worker thead that is not joined when a process |
32 // shuts down. | 32 // shuts down. |
33 return Singleton<ObCertOIDWrapper, | 33 return Singleton<DomainBoundCertOIDWrapper, |
34 LeakySingletonTraits<ObCertOIDWrapper> >::get(); | 34 LeakySingletonTraits<DomainBoundCertOIDWrapper> >::get(); |
35 } | 35 } |
36 | 36 |
37 SECOidTag ob_cert_oid_tag() const { | 37 SECOidTag domain_bound_cert_oid_tag() const { |
38 return ob_cert_oid_tag_; | 38 return domain_bound_cert_oid_tag_; |
39 } | 39 } |
40 | 40 |
41 private: | 41 private: |
42 friend struct DefaultSingletonTraits<ObCertOIDWrapper>; | 42 friend struct DefaultSingletonTraits<DomainBoundCertOIDWrapper>; |
43 | 43 |
44 ObCertOIDWrapper(); | 44 DomainBoundCertOIDWrapper(); |
45 | 45 |
46 SECOidTag ob_cert_oid_tag_; | 46 SECOidTag domain_bound_cert_oid_tag_; |
47 | 47 |
48 DISALLOW_COPY_AND_ASSIGN(ObCertOIDWrapper); | 48 DISALLOW_COPY_AND_ASSIGN(DomainBoundCertOIDWrapper); |
49 }; | 49 }; |
50 | 50 |
51 ObCertOIDWrapper::ObCertOIDWrapper(): ob_cert_oid_tag_(SEC_OID_UNKNOWN) { | 51 DomainBoundCertOIDWrapper::DomainBoundCertOIDWrapper() |
| 52 : domain_bound_cert_oid_tag_(SEC_OID_UNKNOWN) { |
52 // 1.3.6.1.4.1.11129.2.1.6 | 53 // 1.3.6.1.4.1.11129.2.1.6 |
53 // (iso.org.dod.internet.private.enterprises.google.googleSecurity. | 54 // (iso.org.dod.internet.private.enterprises.google.googleSecurity. |
54 // certificateExtensions.originBoundCertificate) | 55 // certificateExtensions.originBoundCertificate) |
55 static const uint8 kObCertOID[] = { | 56 static const uint8 kObCertOID[] = { |
56 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x06 | 57 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x06 |
57 }; | 58 }; |
58 SECOidData oid_data; | 59 SECOidData oid_data; |
59 memset(&oid_data, 0, sizeof(oid_data)); | 60 memset(&oid_data, 0, sizeof(oid_data)); |
60 oid_data.oid.data = const_cast<uint8*>(kObCertOID); | 61 oid_data.oid.data = const_cast<uint8*>(kObCertOID); |
61 oid_data.oid.len = sizeof(kObCertOID); | 62 oid_data.oid.len = sizeof(kObCertOID); |
62 oid_data.offset = SEC_OID_UNKNOWN; | 63 oid_data.offset = SEC_OID_UNKNOWN; |
63 oid_data.desc = "Origin Bound Certificate"; | 64 oid_data.desc = "Origin Bound Certificate"; |
64 oid_data.mechanism = CKM_INVALID_MECHANISM; | 65 oid_data.mechanism = CKM_INVALID_MECHANISM; |
65 oid_data.supportedExtension = SUPPORTED_CERT_EXTENSION; | 66 oid_data.supportedExtension = SUPPORTED_CERT_EXTENSION; |
66 ob_cert_oid_tag_ = SECOID_AddEntry(&oid_data); | 67 domain_bound_cert_oid_tag_ = SECOID_AddEntry(&oid_data); |
67 if (ob_cert_oid_tag_ == SEC_OID_UNKNOWN) | 68 if (domain_bound_cert_oid_tag_ == SEC_OID_UNKNOWN) |
68 LOG(ERROR) << "OB_CERT OID tag creation failed"; | 69 LOG(ERROR) << "OB_CERT OID tag creation failed"; |
69 } | 70 } |
70 | 71 |
71 // Creates a Certificate object that may be passed to the SignCertificate | 72 // Creates a Certificate object that may be passed to the SignCertificate |
72 // method to generate an X509 certificate. | 73 // method to generate an X509 certificate. |
73 // Returns NULL if an error is encountered in the certificate creation | 74 // Returns NULL if an error is encountered in the certificate creation |
74 // process. | 75 // process. |
75 // Caller responsible for freeing returned certificate object. | 76 // Caller responsible for freeing returned certificate object. |
76 CERTCertificate* CreateCertificate( | 77 CERTCertificate* CreateCertificate( |
77 SECKEYPublicKey* public_key, | 78 SECKEYPublicKey* public_key, |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 DLOG(ERROR) << "DerSignData: " << PORT_GetError(); | 163 DLOG(ERROR) << "DerSignData: " << PORT_GetError(); |
163 return false; | 164 return false; |
164 } | 165 } |
165 | 166 |
166 // Save the signed result to the cert. | 167 // Save the signed result to the cert. |
167 cert->derCert = *result; | 168 cert->derCert = *result; |
168 | 169 |
169 return true; | 170 return true; |
170 } | 171 } |
171 | 172 |
172 bool CreateOriginBoundCertInternal( | 173 bool CreateDomainBoundCertInternal( |
173 SECKEYPublicKey* public_key, | 174 SECKEYPublicKey* public_key, |
174 SECKEYPrivateKey* private_key, | 175 SECKEYPrivateKey* private_key, |
175 const std::string& origin, | 176 const std::string& domain, |
176 uint32 serial_number, | 177 uint32 serial_number, |
177 base::Time not_valid_before, | 178 base::Time not_valid_before, |
178 base::Time not_valid_after, | 179 base::Time not_valid_after, |
179 std::string* der_cert) { | 180 std::string* der_cert) { |
180 | 181 |
181 CERTCertificate* cert = CreateCertificate(public_key, | 182 CERTCertificate* cert = CreateCertificate(public_key, |
182 "CN=anonymous.invalid", | 183 "CN=anonymous.invalid", |
183 serial_number, | 184 serial_number, |
184 not_valid_before, | 185 not_valid_before, |
185 not_valid_after); | 186 not_valid_after); |
186 | 187 |
187 if (!cert) | 188 if (!cert) |
188 return false; | 189 return false; |
189 | 190 |
190 // Create opaque handle used to add extensions later. | 191 // Create opaque handle used to add extensions later. |
191 void* cert_handle; | 192 void* cert_handle; |
192 if ((cert_handle = CERT_StartCertExtensions(cert)) == NULL) { | 193 if ((cert_handle = CERT_StartCertExtensions(cert)) == NULL) { |
193 LOG(ERROR) << "Unable to get opaque handle for adding extensions"; | 194 LOG(ERROR) << "Unable to get opaque handle for adding extensions"; |
194 CERT_DestroyCertificate(cert); | 195 CERT_DestroyCertificate(cert); |
195 return false; | 196 return false; |
196 } | 197 } |
197 | 198 |
198 // Create SECItem for IA5String encoding. | 199 // Create SECItem for IA5String encoding. |
199 SECItem origin_string_item = { | 200 SECItem domain_string_item = { |
200 siAsciiString, | 201 siAsciiString, |
201 (unsigned char*)origin.data(), | 202 (unsigned char*)domain.data(), |
202 origin.size() | 203 domain.size() |
203 }; | 204 }; |
204 | 205 |
205 // IA5Encode and arena allocate SECItem | 206 // IA5Encode and arena allocate SECItem |
206 SECItem* asn1_origin_string = SEC_ASN1EncodeItem( | 207 SECItem* asn1_domain_string = SEC_ASN1EncodeItem( |
207 cert->arena, NULL, &origin_string_item, | 208 cert->arena, NULL, &domain_string_item, |
208 SEC_ASN1_GET(SEC_IA5StringTemplate)); | 209 SEC_ASN1_GET(SEC_IA5StringTemplate)); |
209 if (asn1_origin_string == NULL) { | 210 if (asn1_domain_string == NULL) { |
210 LOG(ERROR) << "Unable to get ASN1 encoding for origin in ob_cert extension"; | 211 LOG(ERROR) << "Unable to get ASN1 encoding for domain in domain_bound_cert" |
| 212 " extension"; |
211 CERT_DestroyCertificate(cert); | 213 CERT_DestroyCertificate(cert); |
212 return false; | 214 return false; |
213 } | 215 } |
214 | 216 |
215 // Add the extension to the opaque handle | 217 // Add the extension to the opaque handle |
216 if (CERT_AddExtension(cert_handle, | 218 if (CERT_AddExtension( |
217 ObCertOIDWrapper::GetInstance()->ob_cert_oid_tag(), | 219 cert_handle, |
218 asn1_origin_string, | 220 DomainBoundCertOIDWrapper::GetInstance()->domain_bound_cert_oid_tag(), |
219 PR_TRUE, PR_TRUE) != SECSuccess){ | 221 asn1_domain_string, PR_TRUE, PR_TRUE) != SECSuccess){ |
220 LOG(ERROR) << "Unable to add origin bound cert extension to opaque handle"; | 222 LOG(ERROR) << "Unable to add domain bound cert extension to opaque handle"; |
221 CERT_DestroyCertificate(cert); | 223 CERT_DestroyCertificate(cert); |
222 return false; | 224 return false; |
223 } | 225 } |
224 | 226 |
225 // Copy extension into x509 cert | 227 // Copy extension into x509 cert |
226 if (CERT_FinishExtensions(cert_handle) != SECSuccess){ | 228 if (CERT_FinishExtensions(cert_handle) != SECSuccess){ |
227 LOG(ERROR) << "Unable to copy extension to X509 cert"; | 229 LOG(ERROR) << "Unable to copy extension to X509 cert"; |
228 CERT_DestroyCertificate(cert); | 230 CERT_DestroyCertificate(cert); |
229 return false; | 231 return false; |
230 } | 232 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 return NULL; | 267 return NULL; |
266 | 268 |
267 if (!SignCertificate(cert, private_key)) { | 269 if (!SignCertificate(cert, private_key)) { |
268 CERT_DestroyCertificate(cert); | 270 CERT_DestroyCertificate(cert); |
269 return NULL; | 271 return NULL; |
270 } | 272 } |
271 | 273 |
272 return cert; | 274 return cert; |
273 } | 275 } |
274 | 276 |
275 bool CreateOriginBoundCertEC( | 277 bool CreateDomainBoundCertEC( |
276 crypto::ECPrivateKey* key, | 278 crypto::ECPrivateKey* key, |
277 const std::string& origin, | 279 const std::string& domain, |
278 uint32 serial_number, | 280 uint32 serial_number, |
279 base::Time not_valid_before, | 281 base::Time not_valid_before, |
280 base::Time not_valid_after, | 282 base::Time not_valid_after, |
281 std::string* der_cert) { | 283 std::string* der_cert) { |
282 DCHECK(key); | 284 DCHECK(key); |
283 return CreateOriginBoundCertInternal(key->public_key(), | 285 return CreateDomainBoundCertInternal(key->public_key(), |
284 key->key(), | 286 key->key(), |
285 origin, | 287 domain, |
286 serial_number, | 288 serial_number, |
287 not_valid_before, | 289 not_valid_before, |
288 not_valid_after, | 290 not_valid_after, |
289 der_cert); | 291 der_cert); |
290 } | 292 } |
291 | 293 |
292 } // namespace x509_util | 294 } // namespace x509_util |
293 | 295 |
294 } // namespace net | 296 } // namespace net |
OLD | NEW |