Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / net / cert / x509_util_openssl.cc
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_openssl.h"
6
7 #include <algorithm>
8 #include <openssl/asn1.h>
9
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/strings/string_piece.h"
13 #include "base/strings/string_util.h"
14 #include "crypto/ec_private_key.h"
15 #include "crypto/openssl_util.h"
16 #include "crypto/rsa_private_key.h"
17 #include "crypto/scoped_openssl_types.h"
18 #include "net/cert/x509_cert_types.h"
19 #include "net/cert/x509_util.h"
20
21 namespace net {
22
23 namespace {
24
25 typedef crypto::ScopedOpenSSL<ASN1_INTEGER, ASN1_INTEGER_free>::Type
26     ScopedASN1_INTEGER;
27 typedef crypto::ScopedOpenSSL<ASN1_OCTET_STRING, ASN1_OCTET_STRING_free>::Type
28     ScopedASN1_OCTET_STRING;
29 typedef crypto::ScopedOpenSSL<ASN1_STRING, ASN1_STRING_free>::Type
30     ScopedASN1_STRING;
31 typedef crypto::ScopedOpenSSL<ASN1_TIME, ASN1_TIME_free>::Type ScopedASN1_TIME;
32 typedef crypto::ScopedOpenSSL<X509, X509_free>::Type ScopedX509;
33 typedef crypto::ScopedOpenSSL<X509_EXTENSION, X509_EXTENSION_free>::Type
34     ScopedX509_EXTENSION;
35 typedef crypto::ScopedOpenSSL<X509_NAME, X509_NAME_free>::Type ScopedX509_NAME;
36
37 const EVP_MD* ToEVP(x509_util::DigestAlgorithm alg) {
38   switch (alg) {
39     case x509_util::DIGEST_SHA1:
40       return EVP_sha1();
41     case x509_util::DIGEST_SHA256:
42       return EVP_sha256();
43   }
44   return NULL;
45 }
46
47 }  // namespace
48
49 namespace x509_util {
50
51 namespace {
52
53 X509* CreateCertificate(EVP_PKEY* key,
54                         DigestAlgorithm alg,
55                         const std::string& common_name,
56                         uint32_t serial_number,
57                         base::Time not_valid_before,
58                         base::Time not_valid_after) {
59   // Put the serial number into an OpenSSL-friendly object.
60   ScopedASN1_INTEGER asn1_serial(ASN1_INTEGER_new());
61   if (!asn1_serial.get() ||
62       !ASN1_INTEGER_set(asn1_serial.get(), static_cast<long>(serial_number))) {
63     LOG(ERROR) << "Invalid serial number " << serial_number;
64     return NULL;
65   }
66
67   // Do the same for the time stamps.
68   ScopedASN1_TIME asn1_not_before_time(
69       ASN1_TIME_set(NULL, not_valid_before.ToTimeT()));
70   if (!asn1_not_before_time.get()) {
71     LOG(ERROR) << "Invalid not_valid_before time: "
72                << not_valid_before.ToTimeT();
73     return NULL;
74   }
75
76   ScopedASN1_TIME asn1_not_after_time(
77       ASN1_TIME_set(NULL, not_valid_after.ToTimeT()));
78   if (!asn1_not_after_time.get()) {
79     LOG(ERROR) << "Invalid not_valid_after time: " << not_valid_after.ToTimeT();
80     return NULL;
81   }
82
83   // Because |common_name| only contains a common name and starts with 'CN=',
84   // there is no need for a full RFC 2253 parser here. Do some sanity checks
85   // though.
86   static const char kCommonNamePrefix[] = "CN=";
87   const size_t kCommonNamePrefixLen = sizeof(kCommonNamePrefix) - 1;
88   if (common_name.size() < kCommonNamePrefixLen ||
89       strncmp(common_name.c_str(), kCommonNamePrefix, kCommonNamePrefixLen)) {
90     LOG(ERROR) << "Common name must begin with " << kCommonNamePrefix;
91     return NULL;
92   }
93   if (common_name.size() > INT_MAX) {
94     LOG(ERROR) << "Common name too long";
95     return NULL;
96   }
97   unsigned char* common_name_str =
98       reinterpret_cast<unsigned char*>(const_cast<char*>(common_name.data())) +
99       kCommonNamePrefixLen;
100   int common_name_len =
101       static_cast<int>(common_name.size() - kCommonNamePrefixLen);
102
103   ScopedX509_NAME name(X509_NAME_new());
104   if (!name.get() || !X509_NAME_add_entry_by_NID(name.get(),
105                                                  NID_commonName,
106                                                  MBSTRING_ASC,
107                                                  common_name_str,
108                                                  common_name_len,
109                                                  -1,
110                                                  0)) {
111     LOG(ERROR) << "Can't parse common name: " << common_name.c_str();
112     return NULL;
113   }
114
115   // Now create certificate and populate it.
116   ScopedX509 cert(X509_new());
117   if (!cert.get() || !X509_set_version(cert.get(), 2L) /* i.e. version 3 */ ||
118       !X509_set_pubkey(cert.get(), key) ||
119       !X509_set_serialNumber(cert.get(), asn1_serial.get()) ||
120       !X509_set_notBefore(cert.get(), asn1_not_before_time.get()) ||
121       !X509_set_notAfter(cert.get(), asn1_not_after_time.get()) ||
122       !X509_set_subject_name(cert.get(), name.get()) ||
123       !X509_set_issuer_name(cert.get(), name.get())) {
124     LOG(ERROR) << "Could not create certificate";
125     return NULL;
126   }
127
128   return cert.release();
129 }
130
131 // DER-encodes |x509|. On success, returns true and writes the
132 // encoding to |*out_der|.
133 bool DerEncodeCert(X509* x509, std::string* out_der) {
134   int len = i2d_X509(x509, NULL);
135   if (len < 0)
136     return false;
137
138   uint8_t* ptr = reinterpret_cast<uint8_t*>(WriteInto(out_der, len + 1));
139   if (i2d_X509(x509, &ptr) < 0) {
140     NOTREACHED();
141     out_der->clear();
142     return false;
143   }
144   return true;
145 }
146
147 bool SignAndDerEncodeCert(X509* cert,
148                           EVP_PKEY* key,
149                           DigestAlgorithm alg,
150                           std::string* der_encoded) {
151   // Get the message digest algorithm
152   const EVP_MD* md = ToEVP(alg);
153   if (!md) {
154     LOG(ERROR) << "Unrecognized hash algorithm.";
155     return false;
156   }
157
158   // Sign it with the private key.
159   if (!X509_sign(cert, key, md)) {
160     LOG(ERROR) << "Could not sign certificate with key.";
161     return false;
162   }
163
164   // Convert it into a DER-encoded string copied to |der_encoded|.
165   return DerEncodeCert(cert, der_encoded);
166 }
167
168 // There is no OpenSSL NID for the 'originBoundCertificate' extension OID yet,
169 // so create a global ASN1_OBJECT lazily with the right parameters.
170 class DomainBoundOid {
171  public:
172   DomainBoundOid() : obj_(OBJ_txt2obj(kDomainBoundOidText, 1)) { CHECK(obj_); }
173
174   ~DomainBoundOid() {
175     if (obj_)
176       ASN1_OBJECT_free(obj_);
177   }
178
179   ASN1_OBJECT* obj() const { return obj_; }
180
181  private:
182   static const char kDomainBoundOidText[];
183
184   ASN1_OBJECT* obj_;
185 };
186
187 // 1.3.6.1.4.1.11129.2.1.6
188 // (iso.org.dod.internet.private.enterprises.google.googleSecurity.
189 //  certificateExtensions.originBoundCertificate)
190 const char DomainBoundOid::kDomainBoundOidText[] = "1.3.6.1.4.1.11129.2.1.6";
191
192 ASN1_OBJECT* GetDomainBoundOid() {
193   static base::LazyInstance<DomainBoundOid>::Leaky s_lazy =
194       LAZY_INSTANCE_INITIALIZER;
195   return s_lazy.Get().obj();
196 }
197
198
199 struct DERCache {
200   std::string data;
201 };
202
203 void DERCache_free(void* parent, void* ptr, CRYPTO_EX_DATA* ad, int idx,
204                    long argl, void* argp) {
205   DERCache* der_cache = static_cast<DERCache*>(ptr);
206   delete der_cache;
207 }
208
209 class DERCacheInitSingleton {
210  public:
211   DERCacheInitSingleton() {
212     crypto::EnsureOpenSSLInit();
213     der_cache_ex_index_ = X509_get_ex_new_index(0, 0, 0, 0, DERCache_free);
214     DCHECK_NE(-1, der_cache_ex_index_);
215   }
216
217   int der_cache_ex_index() const { return der_cache_ex_index_; }
218
219  private:
220   int der_cache_ex_index_;
221
222   DISALLOW_COPY_AND_ASSIGN(DERCacheInitSingleton);
223 };
224
225 base::LazyInstance<DERCacheInitSingleton>::Leaky g_der_cache_singleton =
226     LAZY_INSTANCE_INITIALIZER;
227
228 }  // namespace
229
230 bool IsSupportedValidityRange(base::Time not_valid_before,
231                               base::Time not_valid_after) {
232   if (not_valid_before > not_valid_after)
233     return false;
234
235   // The validity field of a certificate can only encode years 1-9999.
236
237   // Compute the base::Time values corresponding to Jan 1st,0001 and
238   // Jan 1st, 10000 respectively. Done by using the pre-computed numbers
239   // of days between these dates and the Unix epoch, i.e. Jan 1st, 1970,
240   // using the following Python script:
241   //
242   //     from datetime import date as D
243   //     print (D(1970,1,1)-D(1,1,1))        # -> 719162 days
244   //     print (D(9999,12,31)-D(1970,1,1))   # -> 2932896 days
245   //
246   // Note: This ignores leap seconds, but should be enough in practice.
247   //
248   const int64 kDaysFromYear0001ToUnixEpoch = 719162;
249   const int64 kDaysFromUnixEpochToYear10000 = 2932896 + 1;
250   const base::Time kEpoch = base::Time::UnixEpoch();
251   const base::Time kYear0001 = kEpoch -
252       base::TimeDelta::FromDays(kDaysFromYear0001ToUnixEpoch);
253   const base::Time kYear10000 = kEpoch +
254       base::TimeDelta::FromDays(kDaysFromUnixEpochToYear10000);
255
256   if (not_valid_before < kYear0001 || not_valid_before >= kYear10000 ||
257       not_valid_after < kYear0001 || not_valid_after >= kYear10000)
258     return false;
259
260   return true;
261 }
262
263 bool CreateChannelIDEC(
264     crypto::ECPrivateKey* key,
265     DigestAlgorithm alg,
266     const std::string& domain,
267     uint32 serial_number,
268     base::Time not_valid_before,
269     base::Time not_valid_after,
270     std::string* der_cert) {
271   crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
272   // Create certificate.
273   ScopedX509 cert(CreateCertificate(key->key(),
274                                     alg,
275                                     "CN=anonymous.invalid",
276                                     serial_number,
277                                     not_valid_before,
278                                     not_valid_after));
279   if (!cert.get())
280     return false;
281
282   // Add TLS-Channel-ID extension to the certificate before signing it.
283   // The value must be stored DER-encoded, as a ASN.1 IA5String.
284   ScopedASN1_STRING domain_ia5(ASN1_IA5STRING_new());
285   if (!domain_ia5.get() ||
286       !ASN1_STRING_set(domain_ia5.get(), domain.data(), domain.size()))
287     return false;
288
289   std::string domain_der;
290   int domain_der_len = i2d_ASN1_IA5STRING(domain_ia5.get(), NULL);
291   if (domain_der_len < 0)
292     return false;
293
294   domain_der.resize(domain_der_len);
295   unsigned char* domain_der_data =
296       reinterpret_cast<unsigned char*>(&domain_der[0]);
297   if (i2d_ASN1_IA5STRING(domain_ia5.get(), &domain_der_data) < 0)
298     return false;
299
300   ScopedASN1_OCTET_STRING domain_str(ASN1_OCTET_STRING_new());
301   if (!domain_str.get() ||
302       !ASN1_STRING_set(domain_str.get(), domain_der.data(), domain_der.size()))
303     return false;
304
305   ScopedX509_EXTENSION ext(X509_EXTENSION_create_by_OBJ(
306       NULL, GetDomainBoundOid(), 1 /* critical */, domain_str.get()));
307   if (!ext.get() || !X509_add_ext(cert.get(), ext.get(), -1)) {
308     return false;
309   }
310
311   // Sign and encode it.
312   return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_cert);
313 }
314
315 bool CreateSelfSignedCert(crypto::RSAPrivateKey* key,
316                           DigestAlgorithm alg,
317                           const std::string& common_name,
318                           uint32 serial_number,
319                           base::Time not_valid_before,
320                           base::Time not_valid_after,
321                           std::string* der_encoded) {
322   crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
323   ScopedX509 cert(CreateCertificate(key->key(),
324                                     alg,
325                                     common_name,
326                                     serial_number,
327                                     not_valid_before,
328                                     not_valid_after));
329   if (!cert.get())
330     return false;
331
332   return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_encoded);
333 }
334
335 bool ParsePrincipalKeyAndValue(X509_NAME_ENTRY* entry,
336                                std::string* key,
337                                std::string* value) {
338   if (key) {
339     ASN1_OBJECT* object = X509_NAME_ENTRY_get_object(entry);
340     key->assign(OBJ_nid2sn(OBJ_obj2nid(object)));
341   }
342
343   ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
344   if (!data)
345     return false;
346
347   unsigned char* buf = NULL;
348   int len = ASN1_STRING_to_UTF8(&buf, data);
349   if (len <= 0)
350     return false;
351
352   value->assign(reinterpret_cast<const char*>(buf), len);
353   OPENSSL_free(buf);
354   return true;
355 }
356
357 bool ParsePrincipalKeyAndValueByIndex(X509_NAME* name,
358                                       int index,
359                                       std::string* key,
360                                       std::string* value) {
361   X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, index);
362   if (!entry)
363     return false;
364
365   return ParsePrincipalKeyAndValue(entry, key, value);
366 }
367
368 bool ParsePrincipalValueByIndex(X509_NAME* name,
369                                 int index,
370                                 std::string* value) {
371   return ParsePrincipalKeyAndValueByIndex(name, index, NULL, value);
372 }
373
374 bool ParsePrincipalValueByNID(X509_NAME* name, int nid, std::string* value) {
375   int index = X509_NAME_get_index_by_NID(name, nid, -1);
376   if (index < 0)
377     return false;
378
379   return ParsePrincipalValueByIndex(name, index, value);
380 }
381
382 bool ParseDate(ASN1_TIME* x509_time, base::Time* time) {
383   if (!x509_time ||
384       (x509_time->type != V_ASN1_UTCTIME &&
385        x509_time->type != V_ASN1_GENERALIZEDTIME))
386     return false;
387
388   base::StringPiece str_date(reinterpret_cast<const char*>(x509_time->data),
389                              x509_time->length);
390
391   CertDateFormat format = x509_time->type == V_ASN1_UTCTIME ?
392       CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME;
393   return ParseCertificateDate(str_date, format, time);
394 }
395
396 // Returns true if |der_cache| points to valid data, false otherwise.
397 // (note: the DER-encoded data in |der_cache| is owned by |cert|, callers should
398 // not free it).
399 bool GetDER(X509* x509, base::StringPiece* der_cache) {
400   int x509_der_cache_index =
401       g_der_cache_singleton.Get().der_cache_ex_index();
402
403   // Re-encoding the DER data via i2d_X509 is an expensive operation,
404   // but it's necessary for comparing two certificates. Re-encode at
405   // most once per certificate and cache the data within the X509 cert
406   // using X509_set_ex_data.
407   DERCache* internal_cache = static_cast<DERCache*>(
408       X509_get_ex_data(x509, x509_der_cache_index));
409   if (!internal_cache) {
410     scoped_ptr<DERCache> new_cache(new DERCache);
411     if (!DerEncodeCert(x509, &new_cache->data))
412       return false;
413     internal_cache = new_cache.get();
414     X509_set_ex_data(x509, x509_der_cache_index, new_cache.release());
415   }
416   *der_cache = base::StringPiece(internal_cache->data);
417   return true;
418 }
419
420 }  // namespace x509_util
421
422 }  // namespace net