1 /* 2 * Copyright 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <keymaster/km_openssl/hkdf.h> 18 19 #include <keymaster/android_keymaster_utils.h> 20 #include <keymaster/km_openssl/hmac.h> 21 #include <keymaster/new.h> 22 23 namespace keymaster { 24 25 bool Rfc5869Sha256Kdf::GenerateKey(const uint8_t* info, size_t info_len, uint8_t* output, 26 size_t output_len) { 27 if (!is_initialized_ || output == nullptr) 28 return false; 29 /** 30 * Step 1. Extract: PRK = HMAC-SHA256(actual_salt, secret) 31 * https://tools.ietf.org/html/rfc5869#section-2.2 32 */ 33 HmacSha256 prk_hmac; 34 bool result; 35 if (salt_.get() != nullptr && salt_len_ > 0) { 36 result = prk_hmac.Init(salt_.get(), salt_len_); 37 } else { 38 UniquePtr<uint8_t[]> zeros(new(std::nothrow) uint8_t[digest_size_]); 39 if (zeros.get() == nullptr) 40 return false; 41 /* If salt is not given, digest size of zeros are used. */ 42 memset(zeros.get(), 0, digest_size_); 43 result = prk_hmac.Init(zeros.get(), digest_size_); 44 } 45 if (!result) 46 return false; 47 48 UniquePtr<uint8_t[]> pseudo_random_key(new(std::nothrow) uint8_t[digest_size_]); 49 if (pseudo_random_key.get() == nullptr || digest_size_ != prk_hmac.DigestLength()) 50 return false; 51 result = 52 prk_hmac.Sign(secret_key_.get(), secret_key_len_, pseudo_random_key.get(), digest_size_); 53 if (!result) 54 return false; 55 56 /** 57 * Step 2. Expand: OUTPUT = HKDF-Expand(PRK, info) 58 * https://tools.ietf.org/html/rfc5869#section-2.3 59 */ 60 const size_t num_blocks = (output_len + digest_size_ - 1) / digest_size_; 61 if (num_blocks >= 256u) 62 return false; 63 64 UniquePtr<uint8_t[]> buf(new(std::nothrow) uint8_t[digest_size_ + info_len + 1]); 65 UniquePtr<uint8_t[]> digest(new(std::nothrow) uint8_t[digest_size_]); 66 if (buf.get() == nullptr || digest.get() == nullptr) 67 return false; 68 HmacSha256 hmac; 69 result = hmac.Init(pseudo_random_key.get(), digest_size_); 70 if (!result) 71 return false; 72 73 for (size_t i = 0; i < num_blocks; i++) { 74 size_t block_input_len = 0; 75 if (i != 0) { 76 memcpy(buf.get(), digest.get(), digest_size_); 77 block_input_len = digest_size_; 78 } 79 if (info != nullptr && info_len > 0) 80 memcpy(buf.get() + block_input_len, info, info_len); 81 block_input_len += info_len; 82 *(buf.get() + block_input_len++) = static_cast<uint8_t>(i + 1); 83 result = hmac.Sign(buf.get(), block_input_len, digest.get(), digest_size_); 84 if (!result) 85 return false; 86 size_t block_output_len = digest_size_ < output_len - i * digest_size_ 87 ? digest_size_ 88 : output_len - i * digest_size_; 89 memcpy(output + i * digest_size_, digest.get(), block_output_len); 90 } 91 return true; 92 } 93 94 } // namespace keymaster 95