xref: /optee_os/lib/libmbedtls/mbedtls/library/hkdf.c (revision 3d3b05918ec9052ba13de82fbcaba204766eb636)
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