Upstream version 5.34.104.0
[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/bio.h>
36 #include <openssl/err.h>
37 #include <openssl/pem.h>
38 #include <openssl/bn.h>
39 #include <openssl/rsa.h>
40 #include <openssl/crypto.h>
41
42 #include "talk/base/checks.h"
43 #include "talk/base/helpers.h"
44 #include "talk/base/logging.h"
45 #include "talk/base/openssl.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   // RSA_generate_key is deprecated. Use _ex version.
70   BIGNUM* exponent = BN_new();
71   RSA* rsa = RSA_new();
72   if (!pkey || !exponent || !rsa ||
73       !BN_set_word(exponent, 0x10001) ||  // 65537 RSA exponent
74       !RSA_generate_key_ex(rsa, KEY_LENGTH, exponent, NULL) ||
75       !EVP_PKEY_assign_RSA(pkey, rsa)) {
76     EVP_PKEY_free(pkey);
77     BN_free(exponent);
78     RSA_free(rsa);
79     return NULL;
80   }
81   // ownership of rsa struct was assigned, don't free it.
82   BN_free(exponent);
83   LOG(LS_INFO) << "Returning key pair";
84   return pkey;
85 }
86
87 // Generate a self-signed certificate, with the public key from the
88 // given key pair. Caller is responsible for freeing the returned object.
89 static X509* MakeCertificate(EVP_PKEY* pkey, const SSLIdentityParams& params) {
90   LOG(LS_INFO) << "Making certificate for " << params.common_name;
91   X509* x509 = NULL;
92   BIGNUM* serial_number = NULL;
93   X509_NAME* name = NULL;
94
95   if ((x509=X509_new()) == NULL)
96     goto error;
97
98   if (!X509_set_pubkey(x509, pkey))
99     goto error;
100
101   // serial number
102   // temporary reference to serial number inside x509 struct
103   ASN1_INTEGER* asn1_serial_number;
104   if ((serial_number = BN_new()) == NULL ||
105       !BN_pseudo_rand(serial_number, SERIAL_RAND_BITS, 0, 0) ||
106       (asn1_serial_number = X509_get_serialNumber(x509)) == NULL ||
107       !BN_to_ASN1_INTEGER(serial_number, asn1_serial_number))
108     goto error;
109
110   if (!X509_set_version(x509, 0L))  // version 1
111     goto error;
112
113   // There are a lot of possible components for the name entries. In
114   // our P2P SSL mode however, the certificates are pre-exchanged
115   // (through the secure XMPP channel), and so the certificate
116   // identification is arbitrary. It can't be empty, so we set some
117   // arbitrary common_name. Note that this certificate goes out in
118   // clear during SSL negotiation, so there may be a privacy issue in
119   // putting anything recognizable here.
120   if ((name = X509_NAME_new()) == NULL ||
121       !X509_NAME_add_entry_by_NID(
122           name, NID_commonName, MBSTRING_UTF8,
123           (unsigned char*)params.common_name.c_str(), -1, -1, 0) ||
124       !X509_set_subject_name(x509, name) ||
125       !X509_set_issuer_name(x509, name))
126     goto error;
127
128   if (!X509_gmtime_adj(X509_get_notBefore(x509), params.not_before) ||
129       !X509_gmtime_adj(X509_get_notAfter(x509), params.not_after))
130     goto error;
131
132   if (!X509_sign(x509, pkey, EVP_sha1()))
133     goto error;
134
135   BN_free(serial_number);
136   X509_NAME_free(name);
137   LOG(LS_INFO) << "Returning certificate";
138   return x509;
139
140  error:
141   BN_free(serial_number);
142   X509_NAME_free(name);
143   X509_free(x509);
144   return NULL;
145 }
146
147 // This dumps the SSL error stack to the log.
148 static void LogSSLErrors(const std::string& prefix) {
149   char error_buf[200];
150   unsigned long err;
151
152   while ((err = ERR_get_error()) != 0) {
153     ERR_error_string_n(err, error_buf, sizeof(error_buf));
154     LOG(LS_ERROR) << prefix << ": " << error_buf << "\n";
155   }
156 }
157
158 OpenSSLKeyPair* OpenSSLKeyPair::Generate() {
159   EVP_PKEY* pkey = MakeKey();
160   if (!pkey) {
161     LogSSLErrors("Generating key pair");
162     return NULL;
163   }
164   return new OpenSSLKeyPair(pkey);
165 }
166
167 OpenSSLKeyPair::~OpenSSLKeyPair() {
168   EVP_PKEY_free(pkey_);
169 }
170
171 void OpenSSLKeyPair::AddReference() {
172   CRYPTO_add(&pkey_->references, 1, CRYPTO_LOCK_EVP_PKEY);
173 }
174
175 #ifdef _DEBUG
176 // Print a certificate to the log, for debugging.
177 static void PrintCert(X509* x509) {
178   BIO* temp_memory_bio = BIO_new(BIO_s_mem());
179   if (!temp_memory_bio) {
180     LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio";
181     return;
182   }
183   X509_print_ex(temp_memory_bio, x509, XN_FLAG_SEP_CPLUS_SPC, 0);
184   BIO_write(temp_memory_bio, "\0", 1);
185   char* buffer;
186   BIO_get_mem_data(temp_memory_bio, &buffer);
187   LOG(LS_VERBOSE) << buffer;
188   BIO_free(temp_memory_bio);
189 }
190 #endif
191
192 OpenSSLCertificate* OpenSSLCertificate::Generate(
193     OpenSSLKeyPair* key_pair, const SSLIdentityParams& params) {
194   SSLIdentityParams actual_params(params);
195   if (actual_params.common_name.empty()) {
196     // Use a random string, arbitrarily 8chars long.
197     actual_params.common_name = CreateRandomString(8);
198   }
199   X509* x509 = MakeCertificate(key_pair->pkey(), actual_params);
200   if (!x509) {
201     LogSSLErrors("Generating certificate");
202     return NULL;
203   }
204 #ifdef _DEBUG
205   PrintCert(x509);
206 #endif
207   OpenSSLCertificate* ret = new OpenSSLCertificate(x509);
208   X509_free(x509);
209   return ret;
210 }
211
212 OpenSSLCertificate* OpenSSLCertificate::FromPEMString(
213     const std::string& pem_string) {
214   BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1);
215   if (!bio)
216     return NULL;
217   BIO_set_mem_eof_return(bio, 0);
218   X509 *x509 = PEM_read_bio_X509(bio, NULL, NULL,
219                                  const_cast<char*>("\0"));
220   BIO_free(bio);  // Frees the BIO, but not the pointed-to string.
221
222   if (!x509)
223     return NULL;
224
225   OpenSSLCertificate* ret = new OpenSSLCertificate(x509);
226   X509_free(x509);
227   return ret;
228 }
229
230 // NOTE: This implementation only functions correctly after InitializeSSL
231 // and before CleanupSSL.
232 bool OpenSSLCertificate::GetSignatureDigestAlgorithm(
233     std::string* algorithm) const {
234   return OpenSSLDigest::GetDigestName(
235       EVP_get_digestbyobj(x509_->sig_alg->algorithm), algorithm);
236 }
237
238 bool OpenSSLCertificate::ComputeDigest(const std::string &algorithm,
239                                        unsigned char *digest,
240                                        std::size_t size,
241                                        std::size_t *length) const {
242   return ComputeDigest(x509_, algorithm, digest, size, length);
243 }
244
245 bool OpenSSLCertificate::ComputeDigest(const X509 *x509,
246                                        const std::string &algorithm,
247                                        unsigned char *digest,
248                                        std::size_t size,
249                                        std::size_t *length) {
250   const EVP_MD *md;
251   unsigned int n;
252
253   if (!OpenSSLDigest::GetDigestEVP(algorithm, &md))
254     return false;
255
256   if (size < static_cast<size_t>(EVP_MD_size(md)))
257     return false;
258
259   X509_digest(x509, md, digest, &n);
260
261   *length = n;
262
263   return true;
264 }
265
266 OpenSSLCertificate::~OpenSSLCertificate() {
267   X509_free(x509_);
268 }
269
270 std::string OpenSSLCertificate::ToPEMString() const {
271   BIO* bio = BIO_new(BIO_s_mem());
272   if (!bio) {
273     UNREACHABLE();
274     return std::string();
275   }
276   if (!PEM_write_bio_X509(bio, x509_)) {
277     BIO_free(bio);
278     UNREACHABLE();
279     return std::string();
280   }
281   BIO_write(bio, "\0", 1);
282   char* buffer;
283   BIO_get_mem_data(bio, &buffer);
284   std::string ret(buffer);
285   BIO_free(bio);
286   return ret;
287 }
288
289 void OpenSSLCertificate::ToDER(Buffer* der_buffer) const {
290   // In case of failure, make sure to leave the buffer empty.
291   der_buffer->SetData(NULL, 0);
292
293   // Calculates the DER representation of the certificate, from scratch.
294   BIO* bio = BIO_new(BIO_s_mem());
295   if (!bio) {
296     UNREACHABLE();
297     return;
298   }
299   if (!i2d_X509_bio(bio, x509_)) {
300     BIO_free(bio);
301     UNREACHABLE();
302     return;
303   }
304   char* data;
305   size_t length = BIO_get_mem_data(bio, &data);
306   der_buffer->SetData(data, length);
307   BIO_free(bio);
308 }
309
310 void OpenSSLCertificate::AddReference() const {
311   ASSERT(x509_ != NULL);
312   CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509);
313 }
314
315 OpenSSLIdentity* OpenSSLIdentity::GenerateInternal(
316     const SSLIdentityParams& params) {
317   OpenSSLKeyPair *key_pair = OpenSSLKeyPair::Generate();
318   if (key_pair) {
319     OpenSSLCertificate *certificate = OpenSSLCertificate::Generate(
320         key_pair, params);
321     if (certificate)
322       return new OpenSSLIdentity(key_pair, certificate);
323     delete key_pair;
324   }
325   LOG(LS_INFO) << "Identity generation failed";
326   return NULL;
327 }
328
329 OpenSSLIdentity* OpenSSLIdentity::Generate(const std::string& common_name) {
330   SSLIdentityParams params;
331   params.common_name = common_name;
332   params.not_before = CERTIFICATE_WINDOW;
333   params.not_after = CERTIFICATE_LIFETIME;
334   return GenerateInternal(params);
335 }
336
337 OpenSSLIdentity* OpenSSLIdentity::GenerateForTest(
338     const SSLIdentityParams& params) {
339   return GenerateInternal(params);
340 }
341
342 SSLIdentity* OpenSSLIdentity::FromPEMStrings(
343     const std::string& private_key,
344     const std::string& certificate) {
345   scoped_ptr<OpenSSLCertificate> cert(
346       OpenSSLCertificate::FromPEMString(certificate));
347   if (!cert) {
348     LOG(LS_ERROR) << "Failed to create OpenSSLCertificate from PEM string.";
349     return NULL;
350   }
351
352   BIO* bio = BIO_new_mem_buf(const_cast<char*>(private_key.c_str()), -1);
353   if (!bio) {
354     LOG(LS_ERROR) << "Failed to create a new BIO buffer.";
355     return NULL;
356   }
357   BIO_set_mem_eof_return(bio, 0);
358   EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL,
359                                            const_cast<char*>("\0"));
360   BIO_free(bio);  // Frees the BIO, but not the pointed-to string.
361
362   if (!pkey) {
363     LOG(LS_ERROR) << "Failed to create the private key from PEM string.";
364     return NULL;
365   }
366
367   return new OpenSSLIdentity(new OpenSSLKeyPair(pkey),
368                              cert.release());
369 }
370
371 bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) {
372   // 1 is the documented success return code.
373   if (SSL_CTX_use_certificate(ctx, certificate_->x509()) != 1 ||
374      SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) {
375     LogSSLErrors("Configuring key and certificate");
376     return false;
377   }
378   return true;
379 }
380
381 }  // namespace talk_base
382
383 #endif  // HAVE_OPENSSL_SSL_H