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/string_util.h"
15#include "crypto/openssl_util.h"
16
17namespace crypto {
18
19SymmetricKey::~SymmetricKey() {
20  std::fill(key_.begin(), key_.end(), '\0');  // Zero out the confidential key.
21}
22
23// static
24SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm,
25                                              size_t key_size_in_bits) {
26  DCHECK_EQ(AES, algorithm);
27  int key_size_in_bytes = key_size_in_bits / 8;
28  DCHECK_EQ(static_cast<int>(key_size_in_bits), key_size_in_bytes * 8);
29
30  if (key_size_in_bits == 0)
31    return NULL;
32
33  OpenSSLErrStackTracer err_tracer(FROM_HERE);
34  scoped_ptr<SymmetricKey> key(new SymmetricKey);
35  uint8* key_data =
36      reinterpret_cast<uint8*>(WriteInto(&key->key_, key_size_in_bytes + 1));
37
38  int rv = RAND_bytes(key_data, key_size_in_bytes);
39  return rv == 1 ? key.release() : NULL;
40}
41
42// static
43SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm,
44                                                  const std::string& password,
45                                                  const std::string& salt,
46                                                  size_t iterations,
47                                                  size_t key_size_in_bits) {
48  DCHECK(algorithm == AES || algorithm == HMAC_SHA1);
49  int key_size_in_bytes = key_size_in_bits / 8;
50  DCHECK_EQ(static_cast<int>(key_size_in_bits), key_size_in_bytes * 8);
51
52  OpenSSLErrStackTracer err_tracer(FROM_HERE);
53  scoped_ptr<SymmetricKey> key(new SymmetricKey);
54  uint8* key_data =
55      reinterpret_cast<uint8*>(WriteInto(&key->key_, key_size_in_bytes + 1));
56  int rv = PKCS5_PBKDF2_HMAC_SHA1(password.data(), password.length(),
57                                  reinterpret_cast<const uint8*>(salt.data()),
58                                  salt.length(), iterations,
59                                  key_size_in_bytes, key_data);
60  return rv == 1 ? key.release() : NULL;
61}
62
63// static
64SymmetricKey* SymmetricKey::Import(Algorithm algorithm,
65                                   const std::string& raw_key) {
66  scoped_ptr<SymmetricKey> key(new SymmetricKey);
67  key->key_ = raw_key;
68  return key.release();
69}
70
71bool SymmetricKey::GetRawKey(std::string* raw_key) {
72  *raw_key = key_;
73  return true;
74}
75
76}  // namespace crypto
77