Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hkdf.c Source File

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 */