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