Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / crypto / symmetric_key_openssl.cc
1 // Copyright (c) 2011 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 "crypto/symmetric_key.h"
6
7 #include <openssl/evp.h>
8 #include <openssl/rand.h>
9
10 #include <algorithm>
11
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/strings/string_util.h"
15 #include "crypto/openssl_util.h"
16
17 namespace crypto {
18
19 SymmetricKey::~SymmetricKey() {
20   std::fill(key_.begin(), key_.end(), '\0');  // Zero out the confidential key.
21 }
22
23 // static
24 SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm,
25                                               size_t key_size_in_bits) {
26   DCHECK_EQ(AES, algorithm);
27
28   // Whitelist supported key sizes to avoid accidentaly relying on
29   // algorithms available in NSS but not BoringSSL and vice
30   // versa. Note that BoringSSL does not support AES-192.
31   if (key_size_in_bits != 128 && key_size_in_bits != 256)
32     return NULL;
33
34   size_t key_size_in_bytes = key_size_in_bits / 8;
35   DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
36
37   if (key_size_in_bytes == 0)
38     return NULL;
39
40   OpenSSLErrStackTracer err_tracer(FROM_HERE);
41   scoped_ptr<SymmetricKey> key(new SymmetricKey);
42   uint8* key_data =
43       reinterpret_cast<uint8*>(WriteInto(&key->key_, key_size_in_bytes + 1));
44
45   int rv = RAND_bytes(key_data, static_cast<int>(key_size_in_bytes));
46   return rv == 1 ? key.release() : NULL;
47 }
48
49 // static
50 SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm,
51                                                   const std::string& password,
52                                                   const std::string& salt,
53                                                   size_t iterations,
54                                                   size_t key_size_in_bits) {
55   DCHECK(algorithm == AES || algorithm == HMAC_SHA1);
56
57   if (algorithm == AES) {
58     // Whitelist supported key sizes to avoid accidentaly relying on
59     // algorithms available in NSS but not BoringSSL and vice
60     // versa. Note that BoringSSL does not support AES-192.
61     if (key_size_in_bits != 128 && key_size_in_bits != 256)
62       return NULL;
63   }
64
65   size_t key_size_in_bytes = key_size_in_bits / 8;
66   DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
67
68   if (key_size_in_bytes == 0)
69     return NULL;
70
71   OpenSSLErrStackTracer err_tracer(FROM_HERE);
72   scoped_ptr<SymmetricKey> key(new SymmetricKey);
73   uint8* key_data =
74       reinterpret_cast<uint8*>(WriteInto(&key->key_, key_size_in_bytes + 1));
75   int rv = PKCS5_PBKDF2_HMAC_SHA1(password.data(), password.length(),
76                                   reinterpret_cast<const uint8*>(salt.data()),
77                                   salt.length(), iterations,
78                                   static_cast<int>(key_size_in_bytes),
79                                   key_data);
80   return rv == 1 ? key.release() : NULL;
81 }
82
83 // static
84 SymmetricKey* SymmetricKey::Import(Algorithm algorithm,
85                                    const std::string& raw_key) {
86   if (algorithm == AES) {
87     // Whitelist supported key sizes to avoid accidentaly relying on
88     // algorithms available in NSS but not BoringSSL and vice
89     // versa. Note that BoringSSL does not support AES-192.
90     if (raw_key.size() != 128/8 && raw_key.size() != 256/8)
91       return NULL;
92   }
93
94   scoped_ptr<SymmetricKey> key(new SymmetricKey);
95   key->key_ = raw_key;
96   return key.release();
97 }
98
99 bool SymmetricKey::GetRawKey(std::string* raw_key) {
100   *raw_key = key_;
101   return true;
102 }
103
104 }  // namespace crypto