1/* BEGIN_HEADER */
2#include "mbedtls/hkdf.h"
3#include "mbedtls/md_internal.h"
4/* END_HEADER */
5
6/* BEGIN_DEPENDENCIES
7 * depends_on:MBEDTLS_HKDF_C
8 * END_DEPENDENCIES
9 */
10
11/* BEGIN_CASE */
12void test_hkdf( int md_alg, char *hex_ikm_string, char *hex_salt_string,
13                char *hex_info_string, char *hex_okm_string )
14{
15    int ret;
16    size_t ikm_len, salt_len, info_len, okm_len;
17    unsigned char ikm[128] = { '\0' };
18    unsigned char salt[128] = { '\0' };
19    unsigned char info[128] = { '\0' };
20    unsigned char expected_okm[128] = { '\0' };
21    unsigned char okm[128] = { '\0' };
22    /*
23     * okm_hex is the string representation of okm,
24     * so its size is twice the size of okm, and an extra null-termination.
25     */
26    unsigned char okm_hex[257] = { '\0' };
27
28    const mbedtls_md_info_t *md = mbedtls_md_info_from_type( md_alg );
29    TEST_ASSERT( md != NULL );
30
31    ikm_len = unhexify( ikm, hex_ikm_string );
32    salt_len = unhexify( salt, hex_salt_string );
33    info_len = unhexify( info, hex_info_string );
34    okm_len = unhexify( expected_okm, hex_okm_string );
35
36    ret = mbedtls_hkdf( md, salt, salt_len, ikm, ikm_len, info, info_len, okm,
37                        okm_len);
38    TEST_ASSERT( ret == 0 );
39
40    // Run hexify on it so that it looks nicer if the assertion fails
41    hexify( okm_hex, okm, okm_len );
42    TEST_ASSERT( !strcmp( (char *)okm_hex, hex_okm_string ) );
43}
44/* END_CASE */
45
46/* BEGIN_CASE */
47void test_hkdf_extract( int md_alg, char *hex_ikm_string,
48                        char *hex_salt_string, char *hex_prk_string )
49{
50    int ret;
51    unsigned char *ikm = NULL;
52    unsigned char *salt = NULL;
53    unsigned char *prk = NULL;
54    unsigned char *output_prk = NULL;
55    size_t ikm_len, salt_len, prk_len, output_prk_len;
56
57    const mbedtls_md_info_t *md = mbedtls_md_info_from_type( md_alg );
58    TEST_ASSERT( md != NULL );
59
60    output_prk_len = mbedtls_md_get_size( md );
61    output_prk = mbedtls_calloc( 1, output_prk_len );
62
63    ikm = unhexify_alloc( hex_ikm_string, &ikm_len );
64    salt = unhexify_alloc( hex_salt_string, &salt_len );
65    prk = unhexify_alloc( hex_prk_string, &prk_len );
66    TEST_ASSERT( prk_len == output_prk_len );
67
68    ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, output_prk );
69    TEST_ASSERT( ret == 0 );
70
71    TEST_ASSERT( !memcmp( output_prk, prk, prk_len ) );
72
73exit:
74    mbedtls_free(ikm);
75    mbedtls_free(salt);
76    mbedtls_free(prk);
77    mbedtls_free(output_prk);
78}
79/* END_CASE */
80
81/* BEGIN_CASE */
82void test_hkdf_expand( int md_alg, char *hex_info_string,
83                       char *hex_prk_string, char *hex_okm_string )
84{
85    enum { OKM_LEN  = 1024 };
86    int ret;
87    unsigned char *info = NULL;
88    unsigned char *prk = NULL;
89    unsigned char *okm = NULL;
90    unsigned char *output_okm = NULL;
91    size_t info_len, prk_len, okm_len;
92
93    const mbedtls_md_info_t *md = mbedtls_md_info_from_type( md_alg );
94    TEST_ASSERT( md != NULL );
95
96    output_okm = mbedtls_calloc( OKM_LEN, 1 );
97
98    prk = unhexify_alloc( hex_prk_string, &prk_len );
99    info = unhexify_alloc( hex_info_string, &info_len );
100    okm = unhexify_alloc( hex_okm_string, &okm_len );
101    TEST_ASSERT( prk_len == mbedtls_md_get_size( md ) );
102    TEST_ASSERT( okm_len < OKM_LEN );
103
104    ret = mbedtls_hkdf_expand( md, prk, prk_len, info, info_len,
105                               output_okm, OKM_LEN );
106    TEST_ASSERT( ret == 0 );
107    TEST_ASSERT( !memcmp( output_okm, okm, okm_len ) );
108
109exit:
110    mbedtls_free(info);
111    mbedtls_free(prk);
112    mbedtls_free(okm);
113    mbedtls_free(output_okm);
114}
115/* END_CASE */
116
117/* BEGIN_CASE */
118void test_hkdf_extract_ret( int hash_len, int ret )
119{
120    int output_ret;
121    unsigned char *salt = NULL;
122    unsigned char *ikm = NULL;
123    unsigned char *prk = NULL;
124    size_t salt_len, ikm_len;
125    struct mbedtls_md_info_t fake_md_info;
126
127    memset( &fake_md_info, 0, sizeof( fake_md_info ) );
128    fake_md_info.type = MBEDTLS_MD_NONE;
129    fake_md_info.size = hash_len;
130
131    prk = mbedtls_calloc( MBEDTLS_MD_MAX_SIZE, 1 );
132    salt_len = 0;
133    ikm_len = 0;
134
135    output_ret = mbedtls_hkdf_extract( &fake_md_info, salt, salt_len,
136                                       ikm, ikm_len, prk );
137    TEST_ASSERT( output_ret == ret );
138
139exit:
140    mbedtls_free(prk);
141}
142/* END_CASE */
143
144/* BEGIN_CASE */
145void test_hkdf_expand_ret( int hash_len, int prk_len, int okm_len, int ret )
146{
147    int output_ret;
148    unsigned char *info = NULL;
149    unsigned char *prk = NULL;
150    unsigned char *okm = NULL;
151    size_t info_len;
152    struct mbedtls_md_info_t fake_md_info;
153
154    memset( &fake_md_info, 0, sizeof( fake_md_info ) );
155    fake_md_info.type = MBEDTLS_MD_NONE;
156    fake_md_info.size = hash_len;
157
158    info_len = 0;
159
160    if (prk_len > 0)
161        prk = mbedtls_calloc( prk_len, 1 );
162
163    if (okm_len > 0)
164        okm = mbedtls_calloc( okm_len, 1 );
165
166    output_ret = mbedtls_hkdf_expand( &fake_md_info, prk, prk_len,
167                                      info, info_len, okm, okm_len );
168    TEST_ASSERT( output_ret == ret );
169
170exit:
171    mbedtls_free(prk);
172    mbedtls_free(okm);
173}
174/* END_CASE */
175