1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// found in the LICENSE file.
4513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/symmetric_key.h"
6513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
74a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <openssl/evp.h>
84a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <openssl/rand.h>
94a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <algorithm>
114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
12513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/logging.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/string_util.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/openssl_util.h"
16513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace crypto {
18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
19513209b27ff55e2841eac0e4120199c23acce758Ben MurdochSymmetricKey::~SymmetricKey() {
204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  std::fill(key_.begin(), key_.end(), '\0');  // Zero out the confidential key.
21513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
22513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
23513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
24513209b27ff55e2841eac0e4120199c23acce758Ben MurdochSymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm,
25513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                              size_t key_size_in_bits) {
264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DCHECK_EQ(AES, algorithm);
274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  int key_size_in_bytes = key_size_in_bits / 8;
284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DCHECK_EQ(static_cast<int>(key_size_in_bits), key_size_in_bytes * 8);
294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (key_size_in_bits == 0)
314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return NULL;
324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
33201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  OpenSSLErrStackTracer err_tracer(FROM_HERE);
344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  scoped_ptr<SymmetricKey> key(new SymmetricKey);
354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  uint8* key_data =
364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      reinterpret_cast<uint8*>(WriteInto(&key->key_, key_size_in_bytes + 1));
374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
38201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  int rv = RAND_bytes(key_data, key_size_in_bytes);
39201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return rv == 1 ? key.release() : NULL;
40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
43513209b27ff55e2841eac0e4120199c23acce758Ben MurdochSymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm,
44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                                  const std::string& password,
45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                                  const std::string& salt,
46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                                  size_t iterations,
47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                                  size_t key_size_in_bits) {
484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DCHECK(algorithm == AES || algorithm == HMAC_SHA1);
494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  int key_size_in_bytes = key_size_in_bits / 8;
504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DCHECK_EQ(static_cast<int>(key_size_in_bits), key_size_in_bytes * 8);
514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
52201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  OpenSSLErrStackTracer err_tracer(FROM_HERE);
534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  scoped_ptr<SymmetricKey> key(new SymmetricKey);
544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  uint8* key_data =
554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      reinterpret_cast<uint8*>(WriteInto(&key->key_, key_size_in_bytes + 1));
56201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  int rv = PKCS5_PBKDF2_HMAC_SHA1(password.data(), password.length(),
57201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                  reinterpret_cast<const uint8*>(salt.data()),
58201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                  salt.length(), iterations,
59201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                  key_size_in_bytes, key_data);
60201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return rv == 1 ? key.release() : NULL;
61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
64513209b27ff55e2841eac0e4120199c23acce758Ben MurdochSymmetricKey* SymmetricKey::Import(Algorithm algorithm,
65513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   const std::string& raw_key) {
664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  scoped_ptr<SymmetricKey> key(new SymmetricKey);
674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  key->key_ = raw_key;
684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return key.release();
69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
71513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool SymmetricKey::GetRawKey(std::string* raw_key) {
724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  *raw_key = key_;
734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return true;
74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}  // namespace crypto
77