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. 4 5 #include "net/cert/x509_util.h" 6 7 #include "base/basictypes.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/time/time.h" 10 #include "crypto/ec_private_key.h" 11 #include "crypto/rsa_private_key.h" 12 #include "net/cert/x509_certificate.h" 13 14 namespace net { 15 16 namespace x509_util { 17 18 // RSA keys created by CreateKeyAndSelfSignedCert will be of this length. 19 static const uint16 kRSAKeyLength = 1024; 20 21 // Certificates made by CreateKeyAndSelfSignedCert and 22 // CreateKeyAndDomainBoundCertEC will be signed using this digest algorithm. 23 static const DigestAlgorithm kSignatureDigestAlgorithm = DIGEST_SHA256; 24 25 ClientCertSorter::ClientCertSorter() : now_(base::Time::Now()) {} 26 27 bool ClientCertSorter::operator()( 28 const scoped_refptr<X509Certificate>& a, 29 const scoped_refptr<X509Certificate>& b) const { 30 // Certificates that are null are sorted last. 31 if (!a.get() || !b.get()) 32 return a.get() && !b.get(); 33 34 // Certificates that are expired/not-yet-valid are sorted last. 35 bool a_is_valid = now_ >= a->valid_start() && now_ <= a->valid_expiry(); 36 bool b_is_valid = now_ >= b->valid_start() && now_ <= b->valid_expiry(); 37 if (a_is_valid != b_is_valid) 38 return a_is_valid && !b_is_valid; 39 40 // Certificates with longer expirations appear as higher priority (less 41 // than) certificates with shorter expirations. 42 if (a->valid_expiry() != b->valid_expiry()) 43 return a->valid_expiry() > b->valid_expiry(); 44 45 // If the expiration dates are equivalent, certificates that were issued 46 // more recently should be prioritized over older certificates. 47 if (a->valid_start() != b->valid_start()) 48 return a->valid_start() > b->valid_start(); 49 50 // Otherwise, prefer client certificates with shorter chains. 51 const X509Certificate::OSCertHandles& a_intermediates = 52 a->GetIntermediateCertificates(); 53 const X509Certificate::OSCertHandles& b_intermediates = 54 b->GetIntermediateCertificates(); 55 return a_intermediates.size() < b_intermediates.size(); 56 } 57 58 bool CreateKeyAndDomainBoundCertEC(const std::string& domain, 59 uint32 serial_number, 60 base::Time not_valid_before, 61 base::Time not_valid_after, 62 scoped_ptr<crypto::ECPrivateKey>* key, 63 std::string* der_cert) { 64 scoped_ptr<crypto::ECPrivateKey> new_key(crypto::ECPrivateKey::Create()); 65 if (!new_key.get()) 66 return false; 67 68 bool success = CreateDomainBoundCertEC(new_key.get(), 69 kSignatureDigestAlgorithm, 70 domain, 71 serial_number, 72 not_valid_before, 73 not_valid_after, 74 der_cert); 75 if (success) 76 key->reset(new_key.release()); 77 78 return success; 79 } 80 81 bool CreateKeyAndSelfSignedCert(const std::string& subject, 82 uint32 serial_number, 83 base::Time not_valid_before, 84 base::Time not_valid_after, 85 scoped_ptr<crypto::RSAPrivateKey>* key, 86 std::string* der_cert) { 87 scoped_ptr<crypto::RSAPrivateKey> new_key( 88 crypto::RSAPrivateKey::Create(kRSAKeyLength)); 89 if (!new_key.get()) 90 return false; 91 92 bool success = CreateSelfSignedCert(new_key.get(), 93 kSignatureDigestAlgorithm, 94 subject, 95 serial_number, 96 not_valid_before, 97 not_valid_after, 98 der_cert); 99 if (success) 100 key->reset(new_key.release()); 101 102 return success; 103 } 104 105 } // namespace x509_util 106 107 } // namespace net 108