1/*
2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License").  You may not use
5 * this file except in compliance with the License.  You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10/*
11 * HMAC low level APIs are deprecated for public use, but still ok for internal
12 * use.
13 */
14#include "internal/deprecated.h"
15
16#include <stdio.h>
17#include <string.h>
18#include <stdlib.h>
19
20#include "internal/nelem.h"
21
22# include <openssl/hmac.h>
23# include <openssl/sha.h>
24# ifndef OPENSSL_NO_MD5
25#  include <openssl/md5.h>
26# endif
27
28# ifdef CHARSET_EBCDIC
29#  include <openssl/ebcdic.h>
30# endif
31
32#include "testutil.h"
33
34# ifndef OPENSSL_NO_MD5
35static struct test_st {
36    const char key[16];
37    int key_len;
38    const unsigned char data[64];
39    int data_len;
40    const char *digest;
41} test[8] = {
42    {
43        "", 0, "More text test vectors to stuff up EBCDIC machines :-)", 54,
44        "e9139d1e6ee064ef8cf514fc7dc83e86",
45    },
46    {
47        "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
48        16, "Hi There", 8,
49        "9294727a3638bb1c13f48ef8158bfc9d",
50    },
51    {
52        "Jefe", 4, "what do ya want for nothing?", 28,
53        "750c783e6ab0b503eaa86e310a5db738",
54    },
55    {
56        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
57        16, {
58            0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
59            0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
60            0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
61            0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
62            0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd
63        }, 50, "56be34521d144c88dbb8c733f0e8b3f6",
64    },
65    {
66        "", 0, "My test data", 12,
67        "61afdecb95429ef494d61fdee15990cabf0826fc"
68    },
69    {
70        "", 0, "My test data", 12,
71        "2274b195d90ce8e03406f4b526a47e0787a88a65479938f1a5baa3ce0f079776"
72    },
73    {
74        "123456", 6, "My test data", 12,
75        "bab53058ae861a7f191abe2d0145cbb123776a6369ee3f9d79ce455667e411dd"
76    },
77    {
78        "12345", 5, "My test data again", 18,
79        "a12396ceddd2a85f4c656bc1e0aa50c78cffde3e"
80    }
81};
82# endif
83
84static char *pt(unsigned char *md, unsigned int len);
85
86
87# ifndef OPENSSL_NO_MD5
88static int test_hmac_md5(int idx)
89{
90    char *p;
91#  ifdef CHARSET_EBCDIC
92    ebcdic2ascii(test[0].data, test[0].data, test[0].data_len);
93    ebcdic2ascii(test[1].data, test[1].data, test[1].data_len);
94    ebcdic2ascii(test[2].key, test[2].key, test[2].key_len);
95    ebcdic2ascii(test[2].data, test[2].data, test[2].data_len);
96#  endif
97
98    p = pt(HMAC(EVP_md5(),
99                test[idx].key, test[idx].key_len,
100                test[idx].data, test[idx].data_len, NULL, NULL),
101                MD5_DIGEST_LENGTH);
102
103    return TEST_ptr(p) && TEST_str_eq(p, test[idx].digest);
104}
105# endif
106
107static int test_hmac_bad(void)
108{
109    HMAC_CTX *ctx = NULL;
110    int ret = 0;
111
112    ctx = HMAC_CTX_new();
113    if (!TEST_ptr(ctx)
114        || !TEST_ptr_null(HMAC_CTX_get_md(ctx))
115        || !TEST_false(HMAC_Init_ex(ctx, NULL, 0, NULL, NULL))
116        || !TEST_false(HMAC_Update(ctx, test[4].data, test[4].data_len))
117        || !TEST_false(HMAC_Init_ex(ctx, NULL, 0, EVP_sha1(), NULL))
118        || !TEST_false(HMAC_Update(ctx, test[4].data, test[4].data_len)))
119        goto err;
120
121    ret = 1;
122err:
123    HMAC_CTX_free(ctx);
124    return ret;
125}
126
127static int test_hmac_run(void)
128{
129    char *p;
130    HMAC_CTX *ctx = NULL;
131    unsigned char buf[EVP_MAX_MD_SIZE];
132    unsigned int len;
133    int ret = 0;
134
135    if (!TEST_ptr(ctx = HMAC_CTX_new()))
136        return 0;
137    HMAC_CTX_reset(ctx);
138
139    if (!TEST_ptr(ctx)
140        || !TEST_ptr_null(HMAC_CTX_get_md(ctx))
141        || !TEST_false(HMAC_Init_ex(ctx, NULL, 0, NULL, NULL))
142        || !TEST_false(HMAC_Update(ctx, test[4].data, test[4].data_len))
143        || !TEST_false(HMAC_Init_ex(ctx, test[4].key, -1, EVP_sha1(), NULL)))
144        goto err;
145
146    if (!TEST_true(HMAC_Init_ex(ctx, test[4].key, test[4].key_len, EVP_sha1(), NULL))
147        || !TEST_true(HMAC_Update(ctx, test[4].data, test[4].data_len))
148        || !TEST_true(HMAC_Final(ctx, buf, &len)))
149        goto err;
150
151    p = pt(buf, len);
152    if (!TEST_ptr(p) || !TEST_str_eq(p, test[4].digest))
153        goto err;
154
155    if (!TEST_false(HMAC_Init_ex(ctx, NULL, 0, EVP_sha256(), NULL)))
156        goto err;
157
158    if (!TEST_true(HMAC_Init_ex(ctx, test[5].key, test[5].key_len, EVP_sha256(), NULL))
159        || !TEST_ptr_eq(HMAC_CTX_get_md(ctx), EVP_sha256())
160        || !TEST_true(HMAC_Update(ctx, test[5].data, test[5].data_len))
161        || !TEST_true(HMAC_Final(ctx, buf, &len)))
162        goto err;
163
164    p = pt(buf, len);
165    if (!TEST_ptr(p) || !TEST_str_eq(p, test[5].digest))
166        goto err;
167
168    if (!TEST_true(HMAC_Init_ex(ctx, test[6].key, test[6].key_len, NULL, NULL))
169        || !TEST_true(HMAC_Update(ctx, test[6].data, test[6].data_len))
170        || !TEST_true(HMAC_Final(ctx, buf, &len)))
171        goto err;
172    p = pt(buf, len);
173    if (!TEST_ptr(p) || !TEST_str_eq(p, test[6].digest))
174        goto err;
175
176    /* Test reusing a key */
177    if (!TEST_true(HMAC_Init_ex(ctx, NULL, 0, NULL, NULL))
178        || !TEST_true(HMAC_Update(ctx, test[6].data, test[6].data_len))
179        || !TEST_true(HMAC_Final(ctx, buf, &len)))
180        goto err;
181    p = pt(buf, len);
182    if (!TEST_ptr(p) || !TEST_str_eq(p, test[6].digest))
183        goto err;
184
185    /*
186     * Test reusing a key where the digest is provided again but is the same as
187     * last time
188     */
189    if (!TEST_true(HMAC_Init_ex(ctx, NULL, 0, EVP_sha256(), NULL))
190        || !TEST_true(HMAC_Update(ctx, test[6].data, test[6].data_len))
191        || !TEST_true(HMAC_Final(ctx, buf, &len)))
192        goto err;
193    p = pt(buf, len);
194    if (!TEST_ptr(p) || !TEST_str_eq(p, test[6].digest))
195        goto err;
196
197    ret = 1;
198err:
199    HMAC_CTX_free(ctx);
200    return ret;
201}
202
203
204static int test_hmac_single_shot(void)
205{
206    char *p;
207
208    /* Test single-shot with NULL key. */
209    p = pt(HMAC(EVP_sha1(), NULL, 0, test[4].data, test[4].data_len,
210                NULL, NULL), SHA_DIGEST_LENGTH);
211    if (!TEST_ptr(p) || !TEST_str_eq(p, test[4].digest))
212        return 0;
213
214    return 1;
215}
216
217
218static int test_hmac_copy(void)
219{
220    char *p;
221    HMAC_CTX *ctx = NULL, *ctx2 = NULL;
222    unsigned char buf[EVP_MAX_MD_SIZE];
223    unsigned int len;
224    int ret = 0;
225
226    ctx = HMAC_CTX_new();
227    ctx2 = HMAC_CTX_new();
228    if (!TEST_ptr(ctx) || !TEST_ptr(ctx2))
229        goto err;
230
231    if (!TEST_true(HMAC_Init_ex(ctx, test[7].key, test[7].key_len, EVP_sha1(), NULL))
232        || !TEST_true(HMAC_Update(ctx, test[7].data, test[7].data_len))
233        || !TEST_true(HMAC_CTX_copy(ctx2, ctx))
234        || !TEST_true(HMAC_Final(ctx2, buf, &len)))
235        goto err;
236
237    p = pt(buf, len);
238    if (!TEST_ptr(p) || !TEST_str_eq(p, test[7].digest))
239        goto err;
240
241    ret = 1;
242err:
243    HMAC_CTX_free(ctx2);
244    HMAC_CTX_free(ctx);
245    return ret;
246}
247
248static int test_hmac_copy_uninited(void)
249{
250    const unsigned char key[24] = {0};
251    const unsigned char ct[166] = {0};
252    EVP_PKEY *pkey = NULL;
253    EVP_MD_CTX *ctx = NULL;
254    EVP_MD_CTX *ctx_tmp = NULL;
255    int res = 0;
256
257    if (!TEST_ptr(ctx = EVP_MD_CTX_new())
258            || !TEST_ptr(pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
259                                                     key, sizeof(key)))
260            || !TEST_true(EVP_DigestSignInit(ctx, NULL, EVP_sha1(), NULL, pkey))
261            || !TEST_ptr(ctx_tmp = EVP_MD_CTX_new())
262            || !TEST_true(EVP_MD_CTX_copy(ctx_tmp, ctx)))
263        goto err;
264    EVP_MD_CTX_free(ctx);
265    ctx = ctx_tmp;
266    ctx_tmp = NULL;
267
268    if (!TEST_true(EVP_DigestSignUpdate(ctx, ct, sizeof(ct))))
269        goto err;
270    res = 1;
271 err:
272    EVP_MD_CTX_free(ctx);
273    EVP_MD_CTX_free(ctx_tmp);
274    EVP_PKEY_free(pkey);
275    return res;
276}
277
278# ifndef OPENSSL_NO_MD5
279static char *pt(unsigned char *md, unsigned int len)
280{
281    unsigned int i;
282    static char buf[80];
283
284    if (md == NULL)
285        return NULL;
286    for (i = 0; i < len; i++)
287        sprintf(&(buf[i * 2]), "%02x", md[i]);
288    return buf;
289}
290# endif
291
292int setup_tests(void)
293{
294    ADD_ALL_TESTS(test_hmac_md5, 4);
295    ADD_TEST(test_hmac_single_shot);
296    ADD_TEST(test_hmac_bad);
297    ADD_TEST(test_hmac_run);
298    ADD_TEST(test_hmac_copy);
299    ADD_TEST(test_hmac_copy_uninited);
300    return 1;
301}
302
303