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

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: Revert unneeded changes 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
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"
24 28
25 namespace { 29 namespace {
26 30
27 class DomainBoundCertOIDWrapper { 31 class DomainBoundCertOIDWrapper {
28 public: 32 public:
29 static DomainBoundCertOIDWrapper* GetInstance() { 33 static DomainBoundCertOIDWrapper* GetInstance() {
30 // Instantiated as a leaky singleton to allow the singleton to be 34 // Instantiated as a leaky singleton to allow the singleton to be
31 // constructed on a worker thead that is not joined when a process 35 // constructed on a worker thead that is not joined when a process
32 // shuts down. 36 // shuts down.
33 return Singleton<DomainBoundCertOIDWrapper, 37 return Singleton<DomainBoundCertOIDWrapper,
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 245
242 DCHECK(cert->derCert.len); 246 DCHECK(cert->derCert.len);
243 // XXX copied from X509Certificate::GetDEREncoded 247 // XXX copied from X509Certificate::GetDEREncoded
244 der_cert->clear(); 248 der_cert->clear();
245 der_cert->append(reinterpret_cast<char*>(cert->derCert.data), 249 der_cert->append(reinterpret_cast<char*>(cert->derCert.data),
246 cert->derCert.len); 250 cert->derCert.len);
247 CERT_DestroyCertificate(cert); 251 CERT_DestroyCertificate(cert);
248 return true; 252 return true;
249 } 253 }
250 254
255 // Callback for CERT_DecodeCertPackage(), used in
256 // CreateOSCertHandlesFromBytes().
257 SECStatus PR_CALLBACK CollectCertsCallback(void* arg,
258 SECItem** certs,
259 int num_certs) {
260 net::X509Certificate::OSCertHandles* results =
261 reinterpret_cast<net::X509Certificate::OSCertHandles*>(arg);
262
263 for (int i = 0; i < num_certs; ++i) {
264 net::X509Certificate::OSCertHandle handle =
265 net::X509Certificate::CreateOSCertHandleFromBytes(
266 reinterpret_cast<char*>(certs[i]->data), certs[i]->len);
267 if (handle)
268 results->push_back(handle);
269 }
270
271 return SECSuccess;
272 }
273
251 } // namespace 274 } // namespace
252 275
253 namespace net { 276 namespace net {
Ryan Sleevi 2012/09/12 19:34:44 nit: Move this to line 28, and you can avoid havin
254 277
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) {
(...skipping 36 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 void ParsePrincipal(CERTName* name, CertPrincipal* principal) {
334 typedef char* (*CERTGetNameFunc)(CERTName* name);
335
336 // TODO(jcampan): add business_category and serial_number.
337 // TODO(wtc): NSS has the CERT_GetOrgName, CERT_GetOrgUnitName, and
338 // CERT_GetDomainComponentName functions, but they return only the most
339 // general (the first) RDN. NSS doesn't have a function for the street
340 // address.
341 static const SECOidTag kOIDs[] = {
342 SEC_OID_AVA_STREET_ADDRESS,
343 SEC_OID_AVA_ORGANIZATION_NAME,
344 SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME,
345 SEC_OID_AVA_DC };
346
347 std::vector<std::string>* values[] = {
348 &principal->street_addresses,
349 &principal->organization_names,
350 &principal->organization_unit_names,
351 &principal->domain_components };
352 DCHECK(arraysize(kOIDs) == arraysize(values));
Ryan Sleevi 2012/09/12 19:34:44 nit: DCHECK_EQ
353
354 CERTRDN** rdns = name->rdns;
355 for (size_t rdn = 0; rdns[rdn]; ++rdn) {
356 CERTAVA** avas = rdns[rdn]->avas;
357 for (size_t pair = 0; avas[pair] != 0; ++pair) {
358 SECOidTag tag = CERT_GetAVATag(avas[pair]);
359 for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
360 if (kOIDs[oid] == tag) {
361 SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value);
362 if (!decode_item)
363 break;
364 // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
365 std::string value(reinterpret_cast<char*>(decode_item->data),
366 decode_item->len);
367 values[oid]->push_back(value);
368 SECITEM_FreeItem(decode_item, PR_TRUE);
369 break;
370 }
371 }
372 }
373 }
374
375 // Get CN, L, S, and C.
376 CERTGetNameFunc get_name_funcs[4] = {
377 CERT_GetCommonName, CERT_GetLocalityName,
378 CERT_GetStateName, CERT_GetCountryName };
379 std::string* single_values[4] = {
380 &principal->common_name, &principal->locality_name,
381 &principal->state_or_province_name, &principal->country_name };
382 for (size_t i = 0; i < arraysize(get_name_funcs); ++i) {
383 char* value = get_name_funcs[i](name);
384 if (value) {
385 single_values[i]->assign(value);
386 PORT_Free(value);
387 }
388 }
389 }
390
391 void ParseDate(const SECItem* der_date, base::Time* result) {
392 PRTime prtime;
393 SECStatus rv = DER_DecodeTimeChoice(&prtime, der_date);
394 DCHECK_EQ(SECSuccess, rv);
395 *result = crypto::PRTimeToBaseTime(prtime);
396 }
397
398 std::string ParseSerialNumber(const CERTCertificate* certificate) {
399 return std::string(reinterpret_cast<char*>(certificate->serialNumber.data),
400 certificate->serialNumber.len);
401 }
402
403 void GetSubjectAltName(CERTCertificate* cert_handle,
404 std::vector<std::string>* dns_names,
405 std::vector<std::string>* ip_addrs) {
406 if (dns_names)
407 dns_names->clear();
408 if (ip_addrs)
409 ip_addrs->clear();
410
411 SECItem alt_name;
412 SECStatus rv = CERT_FindCertExtension(cert_handle,
413 SEC_OID_X509_SUBJECT_ALT_NAME,
414 &alt_name);
415 if (rv != SECSuccess)
416 return;
417
418 PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
419 DCHECK(arena != NULL);
420
421 CERTGeneralName* alt_name_list;
422 alt_name_list = CERT_DecodeAltNameExtension(arena, &alt_name);
423 SECITEM_FreeItem(&alt_name, PR_FALSE);
424
425 CERTGeneralName* name = alt_name_list;
426 while (name) {
427 // DNSName and IPAddress are encoded as IA5String and OCTET STRINGs
428 // respectively, both of which can be byte copied from
429 // SECItemType::data into the appropriate output vector.
430 if (dns_names && name->type == certDNSName) {
431 dns_names->push_back(std::string(
432 reinterpret_cast<char*>(name->name.other.data),
433 name->name.other.len));
434 } else if (ip_addrs && name->type == certIPAddress) {
435 ip_addrs->push_back(std::string(
436 reinterpret_cast<char*>(name->name.other.data),
437 name->name.other.len));
438 }
439 name = CERT_GetNextGeneralName(name);
440 if (name == alt_name_list)
441 break;
442 }
443 PORT_FreeArena(arena, PR_FALSE);
444 }
445
446 X509Certificate::OSCertHandles CreateOSCertHandlesFromBytes(
447 const char* data,
448 int length,
449 X509Certificate::Format format) {
450 X509Certificate::OSCertHandles results;
451 if (length < 0)
452 return results;
453
454 crypto::EnsureNSSInit();
455
456 if (!NSS_IsInitialized())
457 return results;
458
459 switch (format) {
460 case X509Certificate::FORMAT_SINGLE_CERTIFICATE: {
461 X509Certificate::OSCertHandle handle =
462 X509Certificate::CreateOSCertHandleFromBytes(data, length);
463 if (handle)
464 results.push_back(handle);
465 break;
466 }
467 case X509Certificate::FORMAT_PKCS7: {
468 // Make a copy since CERT_DecodeCertPackage may modify it
469 std::vector<char> data_copy(data, data + length);
470
471 SECStatus result = CERT_DecodeCertPackage(&data_copy[0],
472 length, CollectCertsCallback, &results);
473 if (result != SECSuccess)
474 results.clear();
475 break;
476 }
477 default:
478 NOTREACHED() << "Certificate format " << format << " unimplemented";
479 break;
480 }
481
482 return results;
483 }
484
485 X509Certificate::OSCertHandle ReadOSCertHandleFromPickle(
486 PickleIterator* pickle_iter) {
487 const char* data;
488 int length;
489 if (!pickle_iter->ReadData(&data, &length))
490 return NULL;
491
492 return X509Certificate::CreateOSCertHandleFromBytes(data, length);
493 }
494
495 void GetPublicKeyInfo(CERTCertificate* handle,
496 size_t* size_bits,
497 X509Certificate::PublicKeyType* type) {
498 // Since we might fail, set the output parameters to default values first.
499 *type = X509Certificate::kPublicKeyTypeUnknown;
500 *size_bits = 0;
501
502 crypto::ScopedSECKEYPublicKey key(CERT_ExtractPublicKey(handle));
503 if (!key.get())
504 return;
505
506 *size_bits = SECKEY_PublicKeyStrengthInBits(key.get());
507
508 switch (key->keyType) {
509 case rsaKey:
510 *type = X509Certificate::kPublicKeyTypeRSA;
511 break;
512 case dsaKey:
513 *type = X509Certificate::kPublicKeyTypeDSA;
514 break;
515 case dhKey:
516 *type = X509Certificate::kPublicKeyTypeDH;
517 break;
518 case ecKey:
519 *type = X509Certificate::kPublicKeyTypeECDSA;
520 break;
521 default:
522 *type = X509Certificate::kPublicKeyTypeUnknown;
523 *size_bits = 0;
524 break;
525 }
526 }
527
310 } // namespace x509_util 528 } // namespace x509_util
311 529
312 } // namespace net 530 } // namespace net
OLDNEW
« net/base/x509_util_ios.cc ('K') | « 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