OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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" | |
20 #include "crypto/nss_util.h" | 19 #include "crypto/nss_util.h" |
21 #include "crypto/nss_util_internal.h" | 20 #include "crypto/nss_util_internal.h" |
22 #include "crypto/rsa_private_key.h" | 21 #include "crypto/rsa_private_key.h" |
23 #include "crypto/scoped_nss_types.h" | 22 #include "crypto/scoped_nss_types.h" |
24 #include "crypto/third_party/nss/chromium-nss.h" | |
25 | 23 |
26 namespace { | 24 namespace { |
27 | 25 |
28 class ObCertOIDWrapper { | 26 class ObCertOIDWrapper { |
29 public: | 27 public: |
30 static ObCertOIDWrapper* GetInstance() { | 28 static ObCertOIDWrapper* GetInstance() { |
31 // Instantiated as a leaky singleton to allow the singleton to be | 29 // Instantiated as a leaky singleton to allow the singleton to be |
32 // constructed on a worker thead that is not joined when a process | 30 // constructed on a worker thead that is not joined when a process |
33 // shuts down. | 31 // shuts down. |
34 return Singleton<ObCertOIDWrapper, | 32 return Singleton<ObCertOIDWrapper, |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 arena, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate)); | 150 arena, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate)); |
153 if (!encode_result) | 151 if (!encode_result) |
154 return false; | 152 return false; |
155 | 153 |
156 // Allocate space to contain the signed cert. | 154 // Allocate space to contain the signed cert. |
157 SECItem* result = SECITEM_AllocItem(arena, NULL, 0); | 155 SECItem* result = SECITEM_AllocItem(arena, NULL, 0); |
158 if (!result) | 156 if (!result) |
159 return false; | 157 return false; |
160 | 158 |
161 // Sign the ASN1 encoded cert and save it to |result|. | 159 // Sign the ASN1 encoded cert and save it to |result|. |
162 rv = DerSignData(arena, result, &der, key, algo_id); | 160 rv = SEC_DerSignData(arena, result, der.data, der.len, key, algo_id); |
163 if (rv != SECSuccess) { | 161 if (rv != SECSuccess) |
164 DLOG(ERROR) << "DerSignData: " << PORT_GetError(); | |
165 return false; | 162 return false; |
166 } | |
167 | 163 |
168 // Save the signed result to the cert. | 164 // Save the signed result to the cert. |
169 cert->derCert = *result; | 165 cert->derCert = *result; |
170 | 166 |
171 return true; | 167 return true; |
172 } | 168 } |
173 | 169 |
174 bool CreateOriginBoundCertInternal( | |
175 SECKEYPublicKey* public_key, | |
176 SECKEYPrivateKey* private_key, | |
177 const std::string& origin, | |
178 uint32 serial_number, | |
179 base::TimeDelta valid_duration, | |
180 std::string* der_cert) { | |
181 | |
182 CERTCertificate* cert = CreateCertificate(public_key, | |
183 "CN=anonymous.invalid", | |
184 serial_number, | |
185 valid_duration); | |
186 | |
187 if (!cert) | |
188 return false; | |
189 | |
190 // Create opaque handle used to add extensions later. | |
191 void* cert_handle; | |
192 if ((cert_handle = CERT_StartCertExtensions(cert)) == NULL) { | |
193 LOG(ERROR) << "Unable to get opaque handle for adding extensions"; | |
194 CERT_DestroyCertificate(cert); | |
195 return false; | |
196 } | |
197 | |
198 // Create SECItem for IA5String encoding. | |
199 SECItem origin_string_item = { | |
200 siAsciiString, | |
201 (unsigned char*)origin.data(), | |
202 origin.size() | |
203 }; | |
204 | |
205 // IA5Encode and arena allocate SECItem | |
206 SECItem* asn1_origin_string = SEC_ASN1EncodeItem( | |
207 cert->arena, NULL, &origin_string_item, | |
208 SEC_ASN1_GET(SEC_IA5StringTemplate)); | |
209 if (asn1_origin_string == NULL) { | |
210 LOG(ERROR) << "Unable to get ASN1 encoding for origin in ob_cert extension"; | |
211 CERT_DestroyCertificate(cert); | |
212 return false; | |
213 } | |
214 | |
215 // Add the extension to the opaque handle | |
216 if (CERT_AddExtension(cert_handle, | |
217 ObCertOIDWrapper::GetInstance()->ob_cert_oid_tag(), | |
218 asn1_origin_string, | |
219 PR_TRUE, PR_TRUE) != SECSuccess){ | |
220 LOG(ERROR) << "Unable to add origin bound cert extension to opaque handle"; | |
221 CERT_DestroyCertificate(cert); | |
222 return false; | |
223 } | |
224 | |
225 // Copy extension into x509 cert | |
226 if (CERT_FinishExtensions(cert_handle) != SECSuccess){ | |
227 LOG(ERROR) << "Unable to copy extension to X509 cert"; | |
228 CERT_DestroyCertificate(cert); | |
229 return false; | |
230 } | |
231 | |
232 if (!SignCertificate(cert, private_key)) { | |
233 CERT_DestroyCertificate(cert); | |
234 return false; | |
235 } | |
236 | |
237 DCHECK(cert->derCert.len); | |
238 // XXX copied from X509Certificate::GetDEREncoded | |
239 der_cert->clear(); | |
240 der_cert->append(reinterpret_cast<char*>(cert->derCert.data), | |
241 cert->derCert.len); | |
242 CERT_DestroyCertificate(cert); | |
243 return true; | |
244 } | |
245 | |
246 } // namespace | 170 } // namespace |
247 | 171 |
248 namespace net { | 172 namespace net { |
249 | 173 |
250 namespace x509_util { | 174 namespace x509_util { |
251 | 175 |
252 CERTCertificate* CreateSelfSignedCert( | 176 CERTCertificate* CreateSelfSignedCert( |
253 SECKEYPublicKey* public_key, | 177 SECKEYPublicKey* public_key, |
254 SECKEYPrivateKey* private_key, | 178 SECKEYPrivateKey* private_key, |
255 const std::string& subject, | 179 const std::string& subject, |
256 uint32 serial_number, | 180 uint32 serial_number, |
257 base::TimeDelta valid_duration) { | 181 base::TimeDelta valid_duration) { |
258 CERTCertificate* cert = CreateCertificate(public_key, | 182 CERTCertificate* cert = CreateCertificate(public_key, |
259 subject, | 183 subject, |
260 serial_number, | 184 serial_number, |
261 valid_duration); | 185 valid_duration); |
262 if (!cert) | 186 if (!cert) |
263 return NULL; | 187 return NULL; |
264 | 188 |
265 if (!SignCertificate(cert, private_key)) { | 189 if (!SignCertificate(cert, private_key)) { |
266 CERT_DestroyCertificate(cert); | 190 CERT_DestroyCertificate(cert); |
267 return NULL; | 191 return NULL; |
268 } | 192 } |
269 | 193 |
270 return cert; | 194 return cert; |
271 } | 195 } |
272 | 196 |
273 bool CreateOriginBoundCertRSA( | 197 bool CreateOriginBoundCert( |
274 crypto::RSAPrivateKey* key, | 198 crypto::RSAPrivateKey* key, |
275 const std::string& origin, | 199 const std::string& origin, |
276 uint32 serial_number, | 200 uint32 serial_number, |
277 base::TimeDelta valid_duration, | 201 base::TimeDelta valid_duration, |
278 std::string* der_cert) { | 202 std::string* der_cert) { |
279 DCHECK(key); | 203 DCHECK(key); |
280 | 204 |
281 SECKEYPublicKey* public_key; | 205 SECKEYPublicKey* public_key; |
282 SECKEYPrivateKey* private_key; | 206 SECKEYPrivateKey* private_key; |
283 #if defined(USE_NSS) | 207 #if defined(USE_NSS) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 | 242 |
319 public_key = SECKEY_ConvertToPublicKey(private_key); | 243 public_key = SECKEY_ConvertToPublicKey(private_key); |
320 if (!public_key) { | 244 if (!public_key) { |
321 NOTREACHED(); | 245 NOTREACHED(); |
322 return NULL; | 246 return NULL; |
323 } | 247 } |
324 scoped_public_key.reset(public_key); | 248 scoped_public_key.reset(public_key); |
325 } | 249 } |
326 #endif | 250 #endif |
327 | 251 |
328 return CreateOriginBoundCertInternal(public_key, | 252 CERTCertificate* cert = CreateCertificate(public_key, |
329 private_key, | 253 "CN=anonymous.invalid", |
330 origin, | 254 serial_number, |
331 serial_number, | 255 valid_duration); |
332 valid_duration, | |
333 der_cert); | |
334 } | |
335 | 256 |
336 bool CreateOriginBoundCertEC( | 257 if (!cert) |
337 crypto::ECPrivateKey* key, | 258 return false; |
338 const std::string& origin, | 259 |
339 uint32 serial_number, | 260 // Create opaque handle used to add extensions later. |
340 base::TimeDelta valid_duration, | 261 void* cert_handle; |
341 std::string* der_cert) { | 262 if ((cert_handle = CERT_StartCertExtensions(cert)) == NULL) { |
342 DCHECK(key); | 263 LOG(ERROR) << "Unable to get opaque handle for adding extensions"; |
343 return CreateOriginBoundCertInternal(key->public_key(), | 264 CERT_DestroyCertificate(cert); |
344 key->key(), | 265 return false; |
345 origin, | 266 } |
346 serial_number, | 267 |
347 valid_duration, | 268 // Create SECItem for IA5String encoding. |
348 der_cert); | 269 SECItem origin_string_item = { |
| 270 siAsciiString, |
| 271 (unsigned char*)origin.data(), |
| 272 origin.size() |
| 273 }; |
| 274 |
| 275 // IA5Encode and arena allocate SECItem |
| 276 SECItem* asn1_origin_string = SEC_ASN1EncodeItem( |
| 277 cert->arena, NULL, &origin_string_item, |
| 278 SEC_ASN1_GET(SEC_IA5StringTemplate)); |
| 279 if (asn1_origin_string == NULL) { |
| 280 LOG(ERROR) << "Unable to get ASN1 encoding for origin in ob_cert extension"; |
| 281 CERT_DestroyCertificate(cert); |
| 282 return false; |
| 283 } |
| 284 |
| 285 // Add the extension to the opaque handle |
| 286 if (CERT_AddExtension(cert_handle, |
| 287 ObCertOIDWrapper::GetInstance()->ob_cert_oid_tag(), |
| 288 asn1_origin_string, |
| 289 PR_TRUE, PR_TRUE) != SECSuccess){ |
| 290 LOG(ERROR) << "Unable to add origin bound cert extension to opaque handle"; |
| 291 CERT_DestroyCertificate(cert); |
| 292 return false; |
| 293 } |
| 294 |
| 295 // Copy extension into x509 cert |
| 296 if (CERT_FinishExtensions(cert_handle) != SECSuccess){ |
| 297 LOG(ERROR) << "Unable to copy extension to X509 cert"; |
| 298 CERT_DestroyCertificate(cert); |
| 299 return false; |
| 300 } |
| 301 |
| 302 if (!SignCertificate(cert, private_key)) { |
| 303 CERT_DestroyCertificate(cert); |
| 304 return false; |
| 305 } |
| 306 |
| 307 DCHECK(cert->derCert.len); |
| 308 // XXX copied from X509Certificate::GetDEREncoded |
| 309 der_cert->clear(); |
| 310 der_cert->append(reinterpret_cast<char*>(cert->derCert.data), |
| 311 cert->derCert.len); |
| 312 CERT_DestroyCertificate(cert); |
| 313 return true; |
349 } | 314 } |
350 | 315 |
351 } // namespace x509_util | 316 } // namespace x509_util |
352 | 317 |
353 } // namespace net | 318 } // namespace net |
OLD | NEW |