1a8e1175bSopenharmony_ci/* 2a8e1175bSopenharmony_ci * HKDF implementation -- RFC 5869 3a8e1175bSopenharmony_ci * 4a8e1175bSopenharmony_ci * Copyright The Mbed TLS Contributors 5a8e1175bSopenharmony_ci * SPDX-License-Identifier: Apache-2.0 6a8e1175bSopenharmony_ci * 7a8e1175bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); you may 8a8e1175bSopenharmony_ci * not use this file except in compliance with the License. 9a8e1175bSopenharmony_ci * You may obtain a copy of the License at 10a8e1175bSopenharmony_ci * 11a8e1175bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12a8e1175bSopenharmony_ci * 13a8e1175bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14a8e1175bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15a8e1175bSopenharmony_ci * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16a8e1175bSopenharmony_ci * See the License for the specific language governing permissions and 17a8e1175bSopenharmony_ci * limitations under the License. 18a8e1175bSopenharmony_ci */ 19a8e1175bSopenharmony_ci#include "common.h" 20a8e1175bSopenharmony_ci 21a8e1175bSopenharmony_ci#if defined(MBEDTLS_HKDF_C) 22a8e1175bSopenharmony_ci 23a8e1175bSopenharmony_ci#include <string.h> 24a8e1175bSopenharmony_ci#include "mbedtls/hkdf.h" 25a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h" 26a8e1175bSopenharmony_ci#include "mbedtls/error.h" 27a8e1175bSopenharmony_ci 28a8e1175bSopenharmony_ciint mbedtls_hkdf(const mbedtls_md_info_t *md, const unsigned char *salt, 29a8e1175bSopenharmony_ci size_t salt_len, const unsigned char *ikm, size_t ikm_len, 30a8e1175bSopenharmony_ci const unsigned char *info, size_t info_len, 31a8e1175bSopenharmony_ci unsigned char *okm, size_t okm_len) 32a8e1175bSopenharmony_ci{ 33a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 34a8e1175bSopenharmony_ci unsigned char prk[MBEDTLS_MD_MAX_SIZE]; 35a8e1175bSopenharmony_ci 36a8e1175bSopenharmony_ci ret = mbedtls_hkdf_extract(md, salt, salt_len, ikm, ikm_len, prk); 37a8e1175bSopenharmony_ci 38a8e1175bSopenharmony_ci if (ret == 0) { 39a8e1175bSopenharmony_ci ret = mbedtls_hkdf_expand(md, prk, mbedtls_md_get_size(md), 40a8e1175bSopenharmony_ci info, info_len, okm, okm_len); 41a8e1175bSopenharmony_ci } 42a8e1175bSopenharmony_ci 43a8e1175bSopenharmony_ci mbedtls_platform_zeroize(prk, sizeof(prk)); 44a8e1175bSopenharmony_ci 45a8e1175bSopenharmony_ci return ret; 46a8e1175bSopenharmony_ci} 47a8e1175bSopenharmony_ci 48a8e1175bSopenharmony_ciint mbedtls_hkdf_extract(const mbedtls_md_info_t *md, 49a8e1175bSopenharmony_ci const unsigned char *salt, size_t salt_len, 50a8e1175bSopenharmony_ci const unsigned char *ikm, size_t ikm_len, 51a8e1175bSopenharmony_ci unsigned char *prk) 52a8e1175bSopenharmony_ci{ 53a8e1175bSopenharmony_ci unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' }; 54a8e1175bSopenharmony_ci 55a8e1175bSopenharmony_ci if (salt == NULL) { 56a8e1175bSopenharmony_ci size_t hash_len; 57a8e1175bSopenharmony_ci 58a8e1175bSopenharmony_ci if (salt_len != 0) { 59a8e1175bSopenharmony_ci return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; 60a8e1175bSopenharmony_ci } 61a8e1175bSopenharmony_ci 62a8e1175bSopenharmony_ci hash_len = mbedtls_md_get_size(md); 63a8e1175bSopenharmony_ci 64a8e1175bSopenharmony_ci if (hash_len == 0) { 65a8e1175bSopenharmony_ci return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; 66a8e1175bSopenharmony_ci } 67a8e1175bSopenharmony_ci 68a8e1175bSopenharmony_ci salt = null_salt; 69a8e1175bSopenharmony_ci salt_len = hash_len; 70a8e1175bSopenharmony_ci } 71a8e1175bSopenharmony_ci 72a8e1175bSopenharmony_ci return mbedtls_md_hmac(md, salt, salt_len, ikm, ikm_len, prk); 73a8e1175bSopenharmony_ci} 74a8e1175bSopenharmony_ci 75a8e1175bSopenharmony_ciint mbedtls_hkdf_expand(const mbedtls_md_info_t *md, const unsigned char *prk, 76a8e1175bSopenharmony_ci size_t prk_len, const unsigned char *info, 77a8e1175bSopenharmony_ci size_t info_len, unsigned char *okm, size_t okm_len) 78a8e1175bSopenharmony_ci{ 79a8e1175bSopenharmony_ci size_t hash_len; 80a8e1175bSopenharmony_ci size_t where = 0; 81a8e1175bSopenharmony_ci size_t n; 82a8e1175bSopenharmony_ci size_t t_len = 0; 83a8e1175bSopenharmony_ci size_t i; 84a8e1175bSopenharmony_ci int ret = 0; 85a8e1175bSopenharmony_ci mbedtls_md_context_t ctx; 86a8e1175bSopenharmony_ci unsigned char t[MBEDTLS_MD_MAX_SIZE]; 87a8e1175bSopenharmony_ci 88a8e1175bSopenharmony_ci if (okm == NULL) { 89a8e1175bSopenharmony_ci return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; 90a8e1175bSopenharmony_ci } 91a8e1175bSopenharmony_ci 92a8e1175bSopenharmony_ci hash_len = mbedtls_md_get_size(md); 93a8e1175bSopenharmony_ci 94a8e1175bSopenharmony_ci if (prk_len < hash_len || hash_len == 0) { 95a8e1175bSopenharmony_ci return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; 96a8e1175bSopenharmony_ci } 97a8e1175bSopenharmony_ci 98a8e1175bSopenharmony_ci if (info == NULL) { 99a8e1175bSopenharmony_ci info = (const unsigned char *) ""; 100a8e1175bSopenharmony_ci info_len = 0; 101a8e1175bSopenharmony_ci } 102a8e1175bSopenharmony_ci 103a8e1175bSopenharmony_ci n = okm_len / hash_len; 104a8e1175bSopenharmony_ci 105a8e1175bSopenharmony_ci if (okm_len % hash_len != 0) { 106a8e1175bSopenharmony_ci n++; 107a8e1175bSopenharmony_ci } 108a8e1175bSopenharmony_ci 109a8e1175bSopenharmony_ci /* 110a8e1175bSopenharmony_ci * Per RFC 5869 Section 2.3, okm_len must not exceed 111a8e1175bSopenharmony_ci * 255 times the hash length 112a8e1175bSopenharmony_ci */ 113a8e1175bSopenharmony_ci if (n > 255) { 114a8e1175bSopenharmony_ci return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; 115a8e1175bSopenharmony_ci } 116a8e1175bSopenharmony_ci 117a8e1175bSopenharmony_ci mbedtls_md_init(&ctx); 118a8e1175bSopenharmony_ci 119a8e1175bSopenharmony_ci if ((ret = mbedtls_md_setup(&ctx, md, 1)) != 0) { 120a8e1175bSopenharmony_ci goto exit; 121a8e1175bSopenharmony_ci } 122a8e1175bSopenharmony_ci 123a8e1175bSopenharmony_ci memset(t, 0, hash_len); 124a8e1175bSopenharmony_ci 125a8e1175bSopenharmony_ci /* 126a8e1175bSopenharmony_ci * Compute T = T(1) | T(2) | T(3) | ... | T(N) 127a8e1175bSopenharmony_ci * Where T(N) is defined in RFC 5869 Section 2.3 128a8e1175bSopenharmony_ci */ 129a8e1175bSopenharmony_ci for (i = 1; i <= n; i++) { 130a8e1175bSopenharmony_ci size_t num_to_copy; 131a8e1175bSopenharmony_ci unsigned char c = i & 0xff; 132a8e1175bSopenharmony_ci 133a8e1175bSopenharmony_ci ret = mbedtls_md_hmac_starts(&ctx, prk, prk_len); 134a8e1175bSopenharmony_ci if (ret != 0) { 135a8e1175bSopenharmony_ci goto exit; 136a8e1175bSopenharmony_ci } 137a8e1175bSopenharmony_ci 138a8e1175bSopenharmony_ci ret = mbedtls_md_hmac_update(&ctx, t, t_len); 139a8e1175bSopenharmony_ci if (ret != 0) { 140a8e1175bSopenharmony_ci goto exit; 141a8e1175bSopenharmony_ci } 142a8e1175bSopenharmony_ci 143a8e1175bSopenharmony_ci ret = mbedtls_md_hmac_update(&ctx, info, info_len); 144a8e1175bSopenharmony_ci if (ret != 0) { 145a8e1175bSopenharmony_ci goto exit; 146a8e1175bSopenharmony_ci } 147a8e1175bSopenharmony_ci 148a8e1175bSopenharmony_ci /* The constant concatenated to the end of each T(n) is a single octet. 149a8e1175bSopenharmony_ci * */ 150a8e1175bSopenharmony_ci ret = mbedtls_md_hmac_update(&ctx, &c, 1); 151a8e1175bSopenharmony_ci if (ret != 0) { 152a8e1175bSopenharmony_ci goto exit; 153a8e1175bSopenharmony_ci } 154a8e1175bSopenharmony_ci 155a8e1175bSopenharmony_ci ret = mbedtls_md_hmac_finish(&ctx, t); 156a8e1175bSopenharmony_ci if (ret != 0) { 157a8e1175bSopenharmony_ci goto exit; 158a8e1175bSopenharmony_ci } 159a8e1175bSopenharmony_ci 160a8e1175bSopenharmony_ci num_to_copy = i != n ? hash_len : okm_len - where; 161a8e1175bSopenharmony_ci memcpy(okm + where, t, num_to_copy); 162a8e1175bSopenharmony_ci where += hash_len; 163a8e1175bSopenharmony_ci t_len = hash_len; 164a8e1175bSopenharmony_ci } 165a8e1175bSopenharmony_ci 166a8e1175bSopenharmony_ciexit: 167a8e1175bSopenharmony_ci mbedtls_md_free(&ctx); 168a8e1175bSopenharmony_ci mbedtls_platform_zeroize(t, sizeof(t)); 169a8e1175bSopenharmony_ci 170a8e1175bSopenharmony_ci return ret; 171a8e1175bSopenharmony_ci} 172a8e1175bSopenharmony_ci 173a8e1175bSopenharmony_ci#endif /* MBEDTLS_HKDF_C */ 174