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