17689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong/* 27689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong * Copyright 2015 The Android Open Source Project 37689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong * 47689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong * Licensed under the Apache License, Version 2.0 (the "License"); 57689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong * you may not use this file except in compliance with the License. 67689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong * You may obtain a copy of the License at 77689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong * 87689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong * http://www.apache.org/licenses/LICENSE-2.0 97689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong * 107689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong * Unless required by applicable law or agreed to in writing, software 117689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong * distributed under the License is distributed on an "AS IS" BASIS, 127689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong * See the License for the specific language governing permissions and 147689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong * limitations under the License. 157689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong */ 167689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong 177689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong#include "hkdf.h" 187689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong 19f38a002624126ca837865826f948edc9100d6e8aJanis Danisevskis#include <keymaster/new> 200f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden 210f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden#include <keymaster/android_keymaster_utils.h> 220f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden 230f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden#include "hmac.h" 240f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden 257689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duongnamespace keymaster { 267689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong 27f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyenbool Rfc5869Sha256Kdf::GenerateKey(const uint8_t* info, size_t info_len, uint8_t* output, 28f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen size_t output_len) { 29f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen if (!is_initialized_ || output == nullptr) 30f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen return false; 31f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen /** 32f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen * Step 1. Extract: PRK = HMAC-SHA256(actual_salt, secret) 33f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen * https://tools.ietf.org/html/rfc5869#section-2.2 34f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen */ 3560eebdc0b92724cd550aeba92d124cd50c4db5aeThai Duong HmacSha256 prk_hmac; 3660eebdc0b92724cd550aeba92d124cd50c4db5aeThai Duong bool result; 37f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen if (salt_.get() != nullptr && salt_len_ > 0) { 38f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen result = prk_hmac.Init(salt_.get(), salt_len_); 397689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong } else { 40f38a002624126ca837865826f948edc9100d6e8aJanis Danisevskis UniquePtr<uint8_t[]> zeros(new(std::nothrow) uint8_t[digest_size_]); 41f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen if (zeros.get() == nullptr) 42f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen return false; 43f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen /* If salt is not given, digest size of zeros are used. */ 44f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen memset(zeros.get(), 0, digest_size_); 45f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen result = prk_hmac.Init(zeros.get(), digest_size_); 467689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong } 47f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen if (!result) 48fabacaf3e6019804cc8a98a2b8296be1d0125519Thai Duong return false; 497689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong 50f38a002624126ca837865826f948edc9100d6e8aJanis Danisevskis UniquePtr<uint8_t[]> pseudo_random_key(new(std::nothrow) uint8_t[digest_size_]); 51f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen if (pseudo_random_key.get() == nullptr || digest_size_ != prk_hmac.DigestLength()) 52fabacaf3e6019804cc8a98a2b8296be1d0125519Thai Duong return false; 53f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen result = 54f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen prk_hmac.Sign(secret_key_.get(), secret_key_len_, pseudo_random_key.get(), digest_size_); 55f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen if (!result) 56fabacaf3e6019804cc8a98a2b8296be1d0125519Thai Duong return false; 577689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong 58f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen /** 59f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen * Step 2. Expand: OUTPUT = HKDF-Expand(PRK, info) 60f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen * https://tools.ietf.org/html/rfc5869#section-2.3 61f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen */ 62f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen const size_t num_blocks = (output_len + digest_size_ - 1) / digest_size_; 63f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen if (num_blocks >= 256u) 64fabacaf3e6019804cc8a98a2b8296be1d0125519Thai Duong return false; 657689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong 66f38a002624126ca837865826f948edc9100d6e8aJanis Danisevskis UniquePtr<uint8_t[]> buf(new(std::nothrow) uint8_t[digest_size_ + info_len + 1]); 67f38a002624126ca837865826f948edc9100d6e8aJanis Danisevskis UniquePtr<uint8_t[]> digest(new(std::nothrow) uint8_t[digest_size_]); 68f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen if (buf.get() == nullptr || digest.get() == nullptr) 69f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen return false; 707689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong HmacSha256 hmac; 71f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen result = hmac.Init(pseudo_random_key.get(), digest_size_); 72f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen if (!result) 73fabacaf3e6019804cc8a98a2b8296be1d0125519Thai Duong return false; 747689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong 75f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen for (size_t i = 0; i < num_blocks; i++) { 76f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen size_t block_input_len = 0; 77f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen if (i != 0) { 78f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen memcpy(buf.get(), digest.get(), digest_size_); 79f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen block_input_len = digest_size_; 8060eebdc0b92724cd550aeba92d124cd50c4db5aeThai Duong } 81f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen if (info != nullptr && info_len > 0) 82f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen memcpy(buf.get() + block_input_len, info, info_len); 83f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen block_input_len += info_len; 84f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen *(buf.get() + block_input_len++) = static_cast<uint8_t>(i + 1); 85f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen result = hmac.Sign(buf.get(), block_input_len, digest.get(), digest_size_); 86fabacaf3e6019804cc8a98a2b8296be1d0125519Thai Duong if (!result) 87fabacaf3e6019804cc8a98a2b8296be1d0125519Thai Duong return false; 88f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen size_t block_output_len = digest_size_ < output_len - i * digest_size_ 89f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen ? digest_size_ 90f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen : output_len - i * digest_size_; 91f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen memcpy(output + i * digest_size_, digest.get(), block_output_len); 9260eebdc0b92724cd550aeba92d124cd50c4db5aeThai Duong } 93fabacaf3e6019804cc8a98a2b8296be1d0125519Thai Duong return true; 947689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong} 957689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong 967689ed6e95e5cb712c4983cb30ad383520cfaa33Thai Duong} // namespace keymaster 97