| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "crypto/hkdf.h" | 5 #include "crypto/hkdf.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| 11 | 11 |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "crypto/hmac.h" | 13 #include "crypto/hmac.h" |
| 14 | 14 |
| 15 namespace crypto { | 15 namespace crypto { |
| 16 | 16 |
| 17 const size_t kSHA256HashLength = 32; | 17 const size_t kSHA256HashLength = 32; |
| 18 | 18 |
| 19 HKDF::HKDF(const base::StringPiece& secret, | 19 HKDF::HKDF(const base::StringPiece& secret, |
| 20 const base::StringPiece& salt, | 20 const base::StringPiece& salt, |
| 21 const base::StringPiece& info, | 21 const base::StringPiece& info, |
| 22 size_t key_bytes_to_generate, | 22 size_t key_bytes_to_generate, |
| 23 size_t iv_bytes_to_generate, | 23 size_t iv_bytes_to_generate, |
| 24 size_t subkey_secret_bytes_to_generate) |
| 25 : HKDF(secret, |
| 26 salt, |
| 27 info, |
| 28 key_bytes_to_generate, |
| 29 key_bytes_to_generate, |
| 30 iv_bytes_to_generate, |
| 31 iv_bytes_to_generate, |
| 32 subkey_secret_bytes_to_generate) {} |
| 33 |
| 34 HKDF::HKDF(const base::StringPiece& secret, |
| 35 const base::StringPiece& salt, |
| 36 const base::StringPiece& info, |
| 37 size_t client_key_bytes_to_generate, |
| 38 size_t server_key_bytes_to_generate, |
| 39 size_t client_iv_bytes_to_generate, |
| 40 size_t server_iv_bytes_to_generate, |
| 24 size_t subkey_secret_bytes_to_generate) { | 41 size_t subkey_secret_bytes_to_generate) { |
| 25 // https://tools.ietf.org/html/rfc5869#section-2.2 | 42 // https://tools.ietf.org/html/rfc5869#section-2.2 |
| 26 base::StringPiece actual_salt = salt; | 43 base::StringPiece actual_salt = salt; |
| 27 char zeros[kSHA256HashLength]; | 44 char zeros[kSHA256HashLength]; |
| 28 if (actual_salt.empty()) { | 45 if (actual_salt.empty()) { |
| 29 // If salt is not given, HashLength zeros are used. | 46 // If salt is not given, HashLength zeros are used. |
| 30 memset(zeros, 0, sizeof(zeros)); | 47 memset(zeros, 0, sizeof(zeros)); |
| 31 actual_salt.set(zeros, sizeof(zeros)); | 48 actual_salt.set(zeros, sizeof(zeros)); |
| 32 } | 49 } |
| 33 | 50 |
| 34 // Perform the Extract step to transform the input key and | 51 // Perform the Extract step to transform the input key and |
| 35 // salt into the pseudorandom key (PRK) used for Expand. | 52 // salt into the pseudorandom key (PRK) used for Expand. |
| 36 HMAC prk_hmac(HMAC::SHA256); | 53 HMAC prk_hmac(HMAC::SHA256); |
| 37 bool result = prk_hmac.Init(actual_salt); | 54 bool result = prk_hmac.Init(actual_salt); |
| 38 DCHECK(result); | 55 DCHECK(result); |
| 39 | 56 |
| 40 // |prk| is a pseudorandom key (of kSHA256HashLength octets). | 57 // |prk| is a pseudorandom key (of kSHA256HashLength octets). |
| 41 uint8_t prk[kSHA256HashLength]; | 58 uint8_t prk[kSHA256HashLength]; |
| 42 DCHECK_EQ(sizeof(prk), prk_hmac.DigestLength()); | 59 DCHECK_EQ(sizeof(prk), prk_hmac.DigestLength()); |
| 43 result = prk_hmac.Sign(secret, prk, sizeof(prk)); | 60 result = prk_hmac.Sign(secret, prk, sizeof(prk)); |
| 44 DCHECK(result); | 61 DCHECK(result); |
| 45 | 62 |
| 46 // https://tools.ietf.org/html/rfc5869#section-2.3 | 63 // https://tools.ietf.org/html/rfc5869#section-2.3 |
| 47 // Perform the Expand phase to turn the pseudorandom key | 64 // Perform the Expand phase to turn the pseudorandom key |
| 48 // and info into the output keying material. | 65 // and info into the output keying material. |
| 49 const size_t material_length = 2 * key_bytes_to_generate + | 66 const size_t material_length = |
| 50 2 * iv_bytes_to_generate + | 67 client_key_bytes_to_generate + client_iv_bytes_to_generate + |
| 51 subkey_secret_bytes_to_generate; | 68 server_key_bytes_to_generate + server_iv_bytes_to_generate + |
| 52 const size_t n = (material_length + kSHA256HashLength-1) / | 69 subkey_secret_bytes_to_generate; |
| 53 kSHA256HashLength; | 70 const size_t n = |
| 71 (material_length + kSHA256HashLength - 1) / kSHA256HashLength; |
| 54 DCHECK_LT(n, 256u); | 72 DCHECK_LT(n, 256u); |
| 55 | 73 |
| 56 output_.resize(n * kSHA256HashLength); | 74 output_.resize(n * kSHA256HashLength); |
| 57 base::StringPiece previous; | 75 base::StringPiece previous; |
| 58 | 76 |
| 59 std::unique_ptr<char[]> buf(new char[kSHA256HashLength + info.size() + 1]); | 77 std::unique_ptr<char[]> buf(new char[kSHA256HashLength + info.size() + 1]); |
| 60 uint8_t digest[kSHA256HashLength]; | 78 uint8_t digest[kSHA256HashLength]; |
| 61 | 79 |
| 62 HMAC hmac(HMAC::SHA256); | 80 HMAC hmac(HMAC::SHA256); |
| 63 result = hmac.Init(prk, sizeof(prk)); | 81 result = hmac.Init(prk, sizeof(prk)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 75 | 93 |
| 76 memcpy(&output_[i*sizeof(digest)], digest, sizeof(digest)); | 94 memcpy(&output_[i*sizeof(digest)], digest, sizeof(digest)); |
| 77 previous = base::StringPiece(reinterpret_cast<char*>(digest), | 95 previous = base::StringPiece(reinterpret_cast<char*>(digest), |
| 78 sizeof(digest)); | 96 sizeof(digest)); |
| 79 } | 97 } |
| 80 | 98 |
| 81 size_t j = 0; | 99 size_t j = 0; |
| 82 // On Windows, when the size of output_ is zero, dereference of 0'th element | 100 // On Windows, when the size of output_ is zero, dereference of 0'th element |
| 83 // results in a crash. C++11 solves this problem by adding a data() getter | 101 // results in a crash. C++11 solves this problem by adding a data() getter |
| 84 // method to std::vector. | 102 // method to std::vector. |
| 85 if (key_bytes_to_generate) { | 103 if (client_key_bytes_to_generate) { |
| 86 client_write_key_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]), | 104 client_write_key_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]), |
| 87 key_bytes_to_generate); | 105 client_key_bytes_to_generate); |
| 88 j += key_bytes_to_generate; | 106 j += client_key_bytes_to_generate; |
| 89 server_write_key_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]), | |
| 90 key_bytes_to_generate); | |
| 91 j += key_bytes_to_generate; | |
| 92 } | 107 } |
| 93 | 108 |
| 94 if (iv_bytes_to_generate) { | 109 if (server_key_bytes_to_generate) { |
| 110 server_write_key_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]), |
| 111 server_key_bytes_to_generate); |
| 112 j += server_key_bytes_to_generate; |
| 113 } |
| 114 |
| 115 if (client_iv_bytes_to_generate) { |
| 95 client_write_iv_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]), | 116 client_write_iv_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]), |
| 96 iv_bytes_to_generate); | 117 client_iv_bytes_to_generate); |
| 97 j += iv_bytes_to_generate; | 118 j += client_iv_bytes_to_generate; |
| 119 } |
| 120 |
| 121 if (server_iv_bytes_to_generate) { |
| 98 server_write_iv_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]), | 122 server_write_iv_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]), |
| 99 iv_bytes_to_generate); | 123 server_iv_bytes_to_generate); |
| 100 j += iv_bytes_to_generate; | 124 j += server_iv_bytes_to_generate; |
| 101 } | 125 } |
| 126 |
| 102 if (subkey_secret_bytes_to_generate) { | 127 if (subkey_secret_bytes_to_generate) { |
| 103 subkey_secret_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]), | 128 subkey_secret_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]), |
| 104 subkey_secret_bytes_to_generate); | 129 subkey_secret_bytes_to_generate); |
| 105 } | 130 } |
| 106 } | 131 } |
| 107 | 132 |
| 108 HKDF::~HKDF() { | 133 HKDF::~HKDF() { |
| 109 } | 134 } |
| 110 | 135 |
| 111 } // namespace crypto | 136 } // namespace crypto |
| OLD | NEW |