Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: net/base/x509_util_nss.cc

Issue 10928107: Support x509 certificate on iOS. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fix windows compilation Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/base/x509_util_nss.h ('k') | net/net.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <nss.h>
10 #include <pk11pub.h> 11 #include <pk11pub.h>
11 #include <prerror.h> 12 #include <prerror.h>
13 #include <secder.h>
12 #include <secmod.h> 14 #include <secmod.h>
13 #include <secport.h> 15 #include <secport.h>
14 16
15 #include "base/debug/leak_annotations.h" 17 #include "base/debug/leak_annotations.h"
16 #include "base/logging.h" 18 #include "base/logging.h"
17 #include "base/memory/scoped_ptr.h" 19 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/singleton.h" 20 #include "base/memory/singleton.h"
21 #include "base/pickle.h"
19 #include "crypto/ec_private_key.h" 22 #include "crypto/ec_private_key.h"
20 #include "crypto/nss_util.h" 23 #include "crypto/nss_util.h"
21 #include "crypto/nss_util_internal.h" 24 #include "crypto/nss_util_internal.h"
22 #include "crypto/scoped_nss_types.h" 25 #include "crypto/scoped_nss_types.h"
23 #include "crypto/third_party/nss/chromium-nss.h" 26 #include "crypto/third_party/nss/chromium-nss.h"
27 #include "net/base/x509_certificate.h"
28
29 namespace net {
24 30
25 namespace { 31 namespace {
26 32
27 class DomainBoundCertOIDWrapper { 33 class DomainBoundCertOIDWrapper {
28 public: 34 public:
29 static DomainBoundCertOIDWrapper* GetInstance() { 35 static DomainBoundCertOIDWrapper* GetInstance() {
30 // Instantiated as a leaky singleton to allow the singleton to be 36 // Instantiated as a leaky singleton to allow the singleton to be
31 // constructed on a worker thead that is not joined when a process 37 // constructed on a worker thead that is not joined when a process
32 // shuts down. 38 // shuts down.
33 return Singleton<DomainBoundCertOIDWrapper, 39 return Singleton<DomainBoundCertOIDWrapper,
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 247
242 DCHECK(cert->derCert.len); 248 DCHECK(cert->derCert.len);
243 // XXX copied from X509Certificate::GetDEREncoded 249 // XXX copied from X509Certificate::GetDEREncoded
244 der_cert->clear(); 250 der_cert->clear();
245 der_cert->append(reinterpret_cast<char*>(cert->derCert.data), 251 der_cert->append(reinterpret_cast<char*>(cert->derCert.data),
246 cert->derCert.len); 252 cert->derCert.len);
247 CERT_DestroyCertificate(cert); 253 CERT_DestroyCertificate(cert);
248 return true; 254 return true;
249 } 255 }
250 256
257 // Callback for CERT_DecodeCertPackage(), used in
258 // CreateOSCertHandlesFromBytes().
259 SECStatus PR_CALLBACK CollectCertsCallback(void* arg,
260 SECItem** certs,
261 int num_certs) {
262 X509Certificate::OSCertHandles* results =
263 reinterpret_cast<X509Certificate::OSCertHandles*>(arg);
264
265 for (int i = 0; i < num_certs; ++i) {
266 X509Certificate::OSCertHandle handle =
267 X509Certificate::CreateOSCertHandleFromBytes(
268 reinterpret_cast<char*>(certs[i]->data), certs[i]->len);
269 if (handle)
270 results->push_back(handle);
271 }
272
273 return SECSuccess;
274 }
275
251 } // namespace 276 } // namespace
252 277
253 namespace net {
254
255 namespace x509_util { 278 namespace x509_util {
256 279
257 CERTCertificate* CreateSelfSignedCert( 280 CERTCertificate* CreateSelfSignedCert(
258 SECKEYPublicKey* public_key, 281 SECKEYPublicKey* public_key,
259 SECKEYPrivateKey* private_key, 282 SECKEYPrivateKey* private_key,
260 const std::string& subject, 283 const std::string& subject,
261 uint32 serial_number, 284 uint32 serial_number,
262 base::Time not_valid_before, 285 base::Time not_valid_before,
263 base::Time not_valid_after) { 286 base::Time not_valid_after) {
264 CERTCertificate* cert = CreateCertificate(public_key, 287 CERTCertificate* cert = CreateCertificate(public_key,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 DCHECK(key); 323 DCHECK(key);
301 return CreateDomainBoundCertInternal(key->public_key(), 324 return CreateDomainBoundCertInternal(key->public_key(),
302 key->key(), 325 key->key(),
303 domain, 326 domain,
304 serial_number, 327 serial_number,
305 not_valid_before, 328 not_valid_before,
306 not_valid_after, 329 not_valid_after,
307 der_cert); 330 der_cert);
308 } 331 }
309 332
333 #if defined(USE_NSS) || defined(OS_IOS)
334 void ParsePrincipal(CERTName* name, CertPrincipal* principal) {
335 typedef char* (*CERTGetNameFunc)(CERTName* name);
336
337 // TODO(jcampan): add business_category and serial_number.
338 // TODO(wtc): NSS has the CERT_GetOrgName, CERT_GetOrgUnitName, and
339 // CERT_GetDomainComponentName functions, but they return only the most
340 // general (the first) RDN. NSS doesn't have a function for the street
341 // address.
342 static const SECOidTag kOIDs[] = {
343 SEC_OID_AVA_STREET_ADDRESS,
344 SEC_OID_AVA_ORGANIZATION_NAME,
345 SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME,
346 SEC_OID_AVA_DC };
347
348 std::vector<std::string>* values[] = {
349 &principal->street_addresses,
350 &principal->organization_names,
351 &principal->organization_unit_names,
352 &principal->domain_components };
353 DCHECK_EQ(arraysize(kOIDs), arraysize(values));
354
355 CERTRDN** rdns = name->rdns;
356 for (size_t rdn = 0; rdns[rdn]; ++rdn) {
357 CERTAVA** avas = rdns[rdn]->avas;
358 for (size_t pair = 0; avas[pair] != 0; ++pair) {
359 SECOidTag tag = CERT_GetAVATag(avas[pair]);
360 for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
361 if (kOIDs[oid] == tag) {
362 SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value);
363 if (!decode_item)
364 break;
365 // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
366 std::string value(reinterpret_cast<char*>(decode_item->data),
367 decode_item->len);
368 values[oid]->push_back(value);
369 SECITEM_FreeItem(decode_item, PR_TRUE);
370 break;
371 }
372 }
373 }
374 }
375
376 // Get CN, L, S, and C.
377 CERTGetNameFunc get_name_funcs[4] = {
378 CERT_GetCommonName, CERT_GetLocalityName,
379 CERT_GetStateName, CERT_GetCountryName };
380 std::string* single_values[4] = {
381 &principal->common_name, &principal->locality_name,
382 &principal->state_or_province_name, &principal->country_name };
383 for (size_t i = 0; i < arraysize(get_name_funcs); ++i) {
384 char* value = get_name_funcs[i](name);
385 if (value) {
386 single_values[i]->assign(value);
387 PORT_Free(value);
388 }
389 }
390 }
391
392 void ParseDate(const SECItem* der_date, base::Time* result) {
393 PRTime prtime;
394 SECStatus rv = DER_DecodeTimeChoice(&prtime, der_date);
395 DCHECK_EQ(SECSuccess, rv);
396 *result = crypto::PRTimeToBaseTime(prtime);
397 }
398
399 std::string ParseSerialNumber(const CERTCertificate* certificate) {
400 return std::string(reinterpret_cast<char*>(certificate->serialNumber.data),
401 certificate->serialNumber.len);
402 }
403
404 void GetSubjectAltName(CERTCertificate* cert_handle,
405 std::vector<std::string>* dns_names,
406 std::vector<std::string>* ip_addrs) {
407 if (dns_names)
408 dns_names->clear();
409 if (ip_addrs)
410 ip_addrs->clear();
411
412 SECItem alt_name;
413 SECStatus rv = CERT_FindCertExtension(cert_handle,
414 SEC_OID_X509_SUBJECT_ALT_NAME,
415 &alt_name);
416 if (rv != SECSuccess)
417 return;
418
419 PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
420 DCHECK(arena != NULL);
421
422 CERTGeneralName* alt_name_list;
423 alt_name_list = CERT_DecodeAltNameExtension(arena, &alt_name);
424 SECITEM_FreeItem(&alt_name, PR_FALSE);
425
426 CERTGeneralName* name = alt_name_list;
427 while (name) {
428 // DNSName and IPAddress are encoded as IA5String and OCTET STRINGs
429 // respectively, both of which can be byte copied from
430 // SECItemType::data into the appropriate output vector.
431 if (dns_names && name->type == certDNSName) {
432 dns_names->push_back(std::string(
433 reinterpret_cast<char*>(name->name.other.data),
434 name->name.other.len));
435 } else if (ip_addrs && name->type == certIPAddress) {
436 ip_addrs->push_back(std::string(
437 reinterpret_cast<char*>(name->name.other.data),
438 name->name.other.len));
439 }
440 name = CERT_GetNextGeneralName(name);
441 if (name == alt_name_list)
442 break;
443 }
444 PORT_FreeArena(arena, PR_FALSE);
445 }
446
447 X509Certificate::OSCertHandles CreateOSCertHandlesFromBytes(
448 const char* data,
449 int length,
450 X509Certificate::Format format) {
451 X509Certificate::OSCertHandles results;
452 if (length < 0)
453 return results;
454
455 crypto::EnsureNSSInit();
456
457 if (!NSS_IsInitialized())
458 return results;
459
460 switch (format) {
461 case X509Certificate::FORMAT_SINGLE_CERTIFICATE: {
462 X509Certificate::OSCertHandle handle =
463 X509Certificate::CreateOSCertHandleFromBytes(data, length);
464 if (handle)
465 results.push_back(handle);
466 break;
467 }
468 case X509Certificate::FORMAT_PKCS7: {
469 // Make a copy since CERT_DecodeCertPackage may modify it
470 std::vector<char> data_copy(data, data + length);
471
472 SECStatus result = CERT_DecodeCertPackage(&data_copy[0],
473 length, CollectCertsCallback, &results);
474 if (result != SECSuccess)
475 results.clear();
476 break;
477 }
478 default:
479 NOTREACHED() << "Certificate format " << format << " unimplemented";
480 break;
481 }
482
483 return results;
484 }
485
486 X509Certificate::OSCertHandle ReadOSCertHandleFromPickle(
487 PickleIterator* pickle_iter) {
488 const char* data;
489 int length;
490 if (!pickle_iter->ReadData(&data, &length))
491 return NULL;
492
493 return X509Certificate::CreateOSCertHandleFromBytes(data, length);
494 }
495
496 void GetPublicKeyInfo(CERTCertificate* handle,
497 size_t* size_bits,
498 X509Certificate::PublicKeyType* type) {
499 // Since we might fail, set the output parameters to default values first.
500 *type = X509Certificate::kPublicKeyTypeUnknown;
501 *size_bits = 0;
502
503 crypto::ScopedSECKEYPublicKey key(CERT_ExtractPublicKey(handle));
504 if (!key.get())
505 return;
506
507 *size_bits = SECKEY_PublicKeyStrengthInBits(key.get());
508
509 switch (key->keyType) {
510 case rsaKey:
511 *type = X509Certificate::kPublicKeyTypeRSA;
512 break;
513 case dsaKey:
514 *type = X509Certificate::kPublicKeyTypeDSA;
515 break;
516 case dhKey:
517 *type = X509Certificate::kPublicKeyTypeDH;
518 break;
519 case ecKey:
520 *type = X509Certificate::kPublicKeyTypeECDSA;
521 break;
522 default:
523 *type = X509Certificate::kPublicKeyTypeUnknown;
524 *size_bits = 0;
525 break;
526 }
527 }
528 #endif // defined(USE_NSS) || defined(OS_IOS)
529
310 } // namespace x509_util 530 } // namespace x509_util
311 531
312 } // namespace net 532 } // namespace net
OLDNEW
« no previous file with comments | « net/base/x509_util_nss.h ('k') | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698