Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
hkdf.c
00001 /* 00002 * HKDF implementation -- RFC 5869 00003 * 00004 * Copyright (C) 2016-2018, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 #if !defined(MBEDTLS_CONFIG_FILE) 00022 #include "mbedtls/config.h" 00023 #else 00024 #include MBEDTLS_CONFIG_FILE 00025 #endif 00026 00027 #if defined(MBEDTLS_HKDF_C) 00028 00029 #include <string.h> 00030 #include "mbedtls/hkdf.h" 00031 #include "mbedtls/platform_util.h" 00032 00033 int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, 00034 size_t salt_len, const unsigned char *ikm, size_t ikm_len, 00035 const unsigned char *info, size_t info_len, 00036 unsigned char *okm, size_t okm_len ) 00037 { 00038 int ret; 00039 unsigned char prk[MBEDTLS_MD_MAX_SIZE]; 00040 00041 ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk ); 00042 00043 if( ret == 0 ) 00044 { 00045 ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ), 00046 info, info_len, okm, okm_len ); 00047 } 00048 00049 mbedtls_platform_zeroize( prk, sizeof( prk ) ); 00050 00051 return( ret ); 00052 } 00053 00054 int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, 00055 const unsigned char *salt, size_t salt_len, 00056 const unsigned char *ikm, size_t ikm_len, 00057 unsigned char *prk ) 00058 { 00059 unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' }; 00060 00061 if( salt == NULL ) 00062 { 00063 size_t hash_len; 00064 00065 if( salt_len != 0 ) 00066 { 00067 return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; 00068 } 00069 00070 hash_len = mbedtls_md_get_size( md ); 00071 00072 if( hash_len == 0 ) 00073 { 00074 return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; 00075 } 00076 00077 salt = null_salt; 00078 salt_len = hash_len; 00079 } 00080 00081 return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) ); 00082 } 00083 00084 int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, 00085 size_t prk_len, const unsigned char *info, 00086 size_t info_len, unsigned char *okm, size_t okm_len ) 00087 { 00088 size_t hash_len; 00089 size_t where = 0; 00090 size_t n; 00091 size_t t_len = 0; 00092 size_t i; 00093 int ret = 0; 00094 mbedtls_md_context_t ctx; 00095 unsigned char t[MBEDTLS_MD_MAX_SIZE]; 00096 00097 if( okm == NULL ) 00098 { 00099 return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); 00100 } 00101 00102 hash_len = mbedtls_md_get_size( md ); 00103 00104 if( prk_len < hash_len || hash_len == 0 ) 00105 { 00106 return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); 00107 } 00108 00109 if( info == NULL ) 00110 { 00111 info = (const unsigned char *) ""; 00112 info_len = 0; 00113 } 00114 00115 n = okm_len / hash_len; 00116 00117 if( (okm_len % hash_len) != 0 ) 00118 { 00119 n++; 00120 } 00121 00122 /* 00123 * Per RFC 5869 Section 2.3, okm_len must not exceed 00124 * 255 times the hash length 00125 */ 00126 if( n > 255 ) 00127 { 00128 return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); 00129 } 00130 00131 mbedtls_md_init( &ctx ); 00132 00133 if( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 ) 00134 { 00135 goto exit; 00136 } 00137 00138 /* 00139 * Compute T = T(1) | T(2) | T(3) | ... | T(N) 00140 * Where T(N) is defined in RFC 5869 Section 2.3 00141 */ 00142 for( i = 1; i <= n; i++ ) 00143 { 00144 size_t num_to_copy; 00145 unsigned char c = i & 0xff; 00146 00147 ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len ); 00148 if( ret != 0 ) 00149 { 00150 goto exit; 00151 } 00152 00153 ret = mbedtls_md_hmac_update( &ctx, t, t_len ); 00154 if( ret != 0 ) 00155 { 00156 goto exit; 00157 } 00158 00159 ret = mbedtls_md_hmac_update( &ctx, info, info_len ); 00160 if( ret != 0 ) 00161 { 00162 goto exit; 00163 } 00164 00165 /* The constant concatenated to the end of each T(n) is a single octet. 00166 * */ 00167 ret = mbedtls_md_hmac_update( &ctx, &c, 1 ); 00168 if( ret != 0 ) 00169 { 00170 goto exit; 00171 } 00172 00173 ret = mbedtls_md_hmac_finish( &ctx, t ); 00174 if( ret != 0 ) 00175 { 00176 goto exit; 00177 } 00178 00179 num_to_copy = i != n ? hash_len : okm_len - where; 00180 memcpy( okm + where, t, num_to_copy ); 00181 where += hash_len; 00182 t_len = hash_len; 00183 } 00184 00185 exit: 00186 mbedtls_md_free( &ctx ); 00187 mbedtls_platform_zeroize( t, sizeof( t ) ); 00188 00189 return( ret ); 00190 } 00191 00192 #endif /* MBEDTLS_HKDF_C */
Generated on Tue Aug 9 2022 00:37:08 by
1.7.2