eef066585076d2ea19b97ecf8716189fe5211ce6
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / base / opensslidentity.cc
1 /*
2  * libjingle
3  * Copyright 2004--2008, Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #if HAVE_OPENSSL_SSL_H
29
30 #include "talk/base/opensslidentity.h"
31
32 // Must be included first before openssl headers.
33 #include "talk/base/win32.h"  // NOLINT
34
35 #include <openssl/ssl.h>
36 #include <openssl/bio.h>
37 #include <openssl/err.h>
38 #include <openssl/pem.h>
39 #include <openssl/bn.h>
40 #include <openssl/rsa.h>
41 #include <openssl/crypto.h>
42
43 #include "talk/base/checks.h"
44 #include "talk/base/helpers.h"
45 #include "talk/base/logging.h"
46 #include "talk/base/openssldigest.h"
47
48 namespace talk_base {
49
50 // We could have exposed a myriad of parameters for the crypto stuff,
51 // but keeping it simple seems best.
52
53 // Strength of generated keys. Those are RSA.
54 static const int KEY_LENGTH = 1024;
55
56 // Random bits for certificate serial number
57 static const int SERIAL_RAND_BITS = 64;
58
59 // Certificate validity lifetime
60 static const int CERTIFICATE_LIFETIME = 60*60*24*30;  // 30 days, arbitrarily
61 // Certificate validity window.
62 // This is to compensate for slightly incorrect system clocks.
63 static const int CERTIFICATE_WINDOW = -60*60*24;
64
65 // Generate a key pair. Caller is responsible for freeing the returned object.
66 static EVP_PKEY* MakeKey() {
67   LOG(LS_INFO) << "Making key pair";
68   EVP_PKEY* pkey = EVP_PKEY_new();
69 #if OPENSSL_VERSION_NUMBER < 0x00908000l
70   // Only RSA_generate_key is available. Use that.
71   RSA* rsa = RSA_generate_key(KEY_LENGTH, 0x10001, NULL, NULL);
72   if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
73     EVP_PKEY_free(pkey);
74     RSA_free(rsa);
75     return NULL;
76   }
77 #else
78   // RSA_generate_key is deprecated. Use _ex version.
79   BIGNUM* exponent = BN_new();
80   RSA* rsa = RSA_new();
81   if (!pkey || !exponent || !rsa ||
82       !BN_set_word(exponent, 0x10001) ||  // 65537 RSA exponent
83       !RSA_generate_key_ex(rsa, KEY_LENGTH, exponent, NULL) ||
84       !EVP_PKEY_assign_RSA(pkey, rsa)) {
85     EVP_PKEY_free(pkey);
86     BN_free(exponent);
87     RSA_free(rsa);
88     return NULL;
89   }
90   // ownership of rsa struct was assigned, don't free it.
91   BN_free(exponent);
92 #endif
93   LOG(LS_INFO) << "Returning key pair";
94   return pkey;
95 }
96
97 // Generate a self-signed certificate, with the public key from the
98 // given key pair. Caller is responsible for freeing the returned object.
99 static X509* MakeCertificate(EVP_PKEY* pkey, const SSLIdentityParams& params) {
100   LOG(LS_INFO) << "Making certificate for " << params.common_name;
101   X509* x509 = NULL;
102   BIGNUM* serial_number = NULL;
103   X509_NAME* name = NULL;
104
105   if ((x509=X509_new()) == NULL)
106     goto error;
107
108   if (!X509_set_pubkey(x509, pkey))
109     goto error;
110
111   // serial number
112   // temporary reference to serial number inside x509 struct
113   ASN1_INTEGER* asn1_serial_number;
114   if ((serial_number = BN_new()) == NULL ||
115       !BN_pseudo_rand(serial_number, SERIAL_RAND_BITS, 0, 0) ||
116       (asn1_serial_number = X509_get_serialNumber(x509)) == NULL ||
117       !BN_to_ASN1_INTEGER(serial_number, asn1_serial_number))
118     goto error;
119
120   if (!X509_set_version(x509, 0L))  // version 1
121     goto error;
122
123   // There are a lot of possible components for the name entries. In
124   // our P2P SSL mode however, the certificates are pre-exchanged
125   // (through the secure XMPP channel), and so the certificate
126   // identification is arbitrary. It can't be empty, so we set some
127   // arbitrary common_name. Note that this certificate goes out in
128   // clear during SSL negotiation, so there may be a privacy issue in
129   // putting anything recognizable here.
130   if ((name = X509_NAME_new()) == NULL ||
131       !X509_NAME_add_entry_by_NID(
132           name, NID_commonName, MBSTRING_UTF8,
133           (unsigned char*)params.common_name.c_str(), -1, -1, 0) ||
134       !X509_set_subject_name(x509, name) ||
135       !X509_set_issuer_name(x509, name))
136     goto error;
137
138   if (!X509_gmtime_adj(X509_get_notBefore(x509), params.not_before) ||
139       !X509_gmtime_adj(X509_get_notAfter(x509), params.not_after))
140     goto error;
141
142   if (!X509_sign(x509, pkey, EVP_sha1()))
143     goto error;
144
145   BN_free(serial_number);
146   X509_NAME_free(name);
147   LOG(LS_INFO) << "Returning certificate";
148   return x509;
149
150  error:
151   BN_free(serial_number);
152   X509_NAME_free(name);
153   X509_free(x509);
154   return NULL;
155 }
156
157 // This dumps the SSL error stack to the log.
158 static void LogSSLErrors(const std::string& prefix) {
159   char error_buf[200];
160   unsigned long err;
161
162   while ((err = ERR_get_error()) != 0) {
163     ERR_error_string_n(err, error_buf, sizeof(error_buf));
164     LOG(LS_ERROR) << prefix << ": " << error_buf << "\n";
165   }
166 }
167
168 OpenSSLKeyPair* OpenSSLKeyPair::Generate() {
169   EVP_PKEY* pkey = MakeKey();
170   if (!pkey) {
171     LogSSLErrors("Generating key pair");
172     return NULL;
173   }
174   return new OpenSSLKeyPair(pkey);
175 }
176
177 OpenSSLKeyPair::~OpenSSLKeyPair() {
178   EVP_PKEY_free(pkey_);
179 }
180
181 void OpenSSLKeyPair::AddReference() {
182   CRYPTO_add(&pkey_->references, 1, CRYPTO_LOCK_EVP_PKEY);
183 }
184
185 #ifdef _DEBUG
186 // Print a certificate to the log, for debugging.
187 static void PrintCert(X509* x509) {
188   BIO* temp_memory_bio = BIO_new(BIO_s_mem());
189   if (!temp_memory_bio) {
190     LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio";
191     return;
192   }
193   X509_print_ex(temp_memory_bio, x509, XN_FLAG_SEP_CPLUS_SPC, 0);
194   BIO_write(temp_memory_bio, "\0", 1);
195   char* buffer;
196   BIO_get_mem_data(temp_memory_bio, &buffer);
197   LOG(LS_VERBOSE) << buffer;
198   BIO_free(temp_memory_bio);
199 }
200 #endif
201
202 OpenSSLCertificate* OpenSSLCertificate::Generate(
203     OpenSSLKeyPair* key_pair, const SSLIdentityParams& params) {
204   SSLIdentityParams actual_params(params);
205   if (actual_params.common_name.empty()) {
206     // Use a random string, arbitrarily 8chars long.
207     actual_params.common_name = CreateRandomString(8);
208   }
209   X509* x509 = MakeCertificate(key_pair->pkey(), actual_params);
210   if (!x509) {
211     LogSSLErrors("Generating certificate");
212     return NULL;
213   }
214 #ifdef _DEBUG
215   PrintCert(x509);
216 #endif
217   OpenSSLCertificate* ret = new OpenSSLCertificate(x509);
218   X509_free(x509);
219   return ret;
220 }
221
222 OpenSSLCertificate* OpenSSLCertificate::FromPEMString(
223     const std::string& pem_string) {
224   BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1);
225   if (!bio)
226     return NULL;
227   (void)BIO_set_close(bio, BIO_NOCLOSE);
228   BIO_set_mem_eof_return(bio, 0);
229   X509 *x509 = PEM_read_bio_X509(bio, NULL, NULL,
230                                  const_cast<char*>("\0"));
231   BIO_free(bio);
232   if (!x509)
233     return NULL;
234
235   OpenSSLCertificate* ret = new OpenSSLCertificate(x509);
236   X509_free(x509);
237   return ret;
238 }
239
240 // NOTE: This implementation only functions correctly after InitializeSSL
241 // and before CleanupSSL.
242 bool OpenSSLCertificate::GetSignatureDigestAlgorithm(
243     std::string* algorithm) const {
244   return OpenSSLDigest::GetDigestName(
245       EVP_get_digestbyobj(x509_->sig_alg->algorithm), algorithm);
246 }
247
248 bool OpenSSLCertificate::ComputeDigest(const std::string &algorithm,
249                                        unsigned char *digest,
250                                        std::size_t size,
251                                        std::size_t *length) const {
252   return ComputeDigest(x509_, algorithm, digest, size, length);
253 }
254
255 bool OpenSSLCertificate::ComputeDigest(const X509 *x509,
256                                        const std::string &algorithm,
257                                        unsigned char *digest,
258                                        std::size_t size,
259                                        std::size_t *length) {
260   const EVP_MD *md;
261   unsigned int n;
262
263   if (!OpenSSLDigest::GetDigestEVP(algorithm, &md))
264     return false;
265
266   if (size < static_cast<size_t>(EVP_MD_size(md)))
267     return false;
268
269   X509_digest(x509, md, digest, &n);
270
271   *length = n;
272
273   return true;
274 }
275
276 OpenSSLCertificate::~OpenSSLCertificate() {
277   X509_free(x509_);
278 }
279
280 std::string OpenSSLCertificate::ToPEMString() const {
281   BIO* bio = BIO_new(BIO_s_mem());
282   if (!bio) {
283     UNREACHABLE();
284     return std::string();
285   }
286   if (!PEM_write_bio_X509(bio, x509_)) {
287     BIO_free(bio);
288     UNREACHABLE();
289     return std::string();
290   }
291   BIO_write(bio, "\0", 1);
292   char* buffer;
293   BIO_get_mem_data(bio, &buffer);
294   std::string ret(buffer);
295   BIO_free(bio);
296   return ret;
297 }
298
299 void OpenSSLCertificate::ToDER(Buffer* der_buffer) const {
300   // In case of failure, make sure to leave the buffer empty.
301   der_buffer->SetData(NULL, 0);
302
303   // Calculates the DER representation of the certificate, from scratch.
304   BIO* bio = BIO_new(BIO_s_mem());
305   if (!bio) {
306     UNREACHABLE();
307     return;
308   }
309   if (!i2d_X509_bio(bio, x509_)) {
310     BIO_free(bio);
311     UNREACHABLE();
312     return;
313   }
314   char* data;
315   size_t length = BIO_get_mem_data(bio, &data);
316   der_buffer->SetData(data, length);
317   BIO_free(bio);
318 }
319
320 void OpenSSLCertificate::AddReference() const {
321   ASSERT(x509_ != NULL);
322   CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509);
323 }
324
325 OpenSSLIdentity* OpenSSLIdentity::GenerateInternal(
326     const SSLIdentityParams& params) {
327   OpenSSLKeyPair *key_pair = OpenSSLKeyPair::Generate();
328   if (key_pair) {
329     OpenSSLCertificate *certificate = OpenSSLCertificate::Generate(
330         key_pair, params);
331     if (certificate)
332       return new OpenSSLIdentity(key_pair, certificate);
333     delete key_pair;
334   }
335   LOG(LS_INFO) << "Identity generation failed";
336   return NULL;
337 }
338
339 OpenSSLIdentity* OpenSSLIdentity::Generate(const std::string& common_name) {
340   SSLIdentityParams params;
341   params.common_name = common_name;
342   params.not_before = CERTIFICATE_WINDOW;
343   params.not_after = CERTIFICATE_LIFETIME;
344   return GenerateInternal(params);
345 }
346
347 OpenSSLIdentity* OpenSSLIdentity::GenerateForTest(
348     const SSLIdentityParams& params) {
349   return GenerateInternal(params);
350 }
351
352 SSLIdentity* OpenSSLIdentity::FromPEMStrings(
353     const std::string& private_key,
354     const std::string& certificate) {
355   scoped_ptr<OpenSSLCertificate> cert(
356       OpenSSLCertificate::FromPEMString(certificate));
357   if (!cert) {
358     LOG(LS_ERROR) << "Failed to create OpenSSLCertificate from PEM string.";
359     return NULL;
360   }
361
362   BIO* bio = BIO_new_mem_buf(const_cast<char*>(private_key.c_str()), -1);
363   if (!bio) {
364     LOG(LS_ERROR) << "Failed to create a new BIO buffer.";
365     return NULL;
366   }
367   (void)BIO_set_close(bio, BIO_NOCLOSE);
368   BIO_set_mem_eof_return(bio, 0);
369   EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL,
370                                            const_cast<char*>("\0"));
371   BIO_free(bio);
372
373   if (!pkey) {
374     LOG(LS_ERROR) << "Failed to create the private key from PEM string.";
375     return NULL;
376   }
377
378   return new OpenSSLIdentity(new OpenSSLKeyPair(pkey),
379                              cert.release());
380 }
381
382 bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) {
383   // 1 is the documented success return code.
384   if (SSL_CTX_use_certificate(ctx, certificate_->x509()) != 1 ||
385      SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) {
386     LogSSLErrors("Configuring key and certificate");
387     return false;
388   }
389   return true;
390 }
391
392 }  // namespace talk_base
393
394 #endif  // HAVE_OPENSSL_SSL_H
395
396