1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/*
11e1051a39Sopenharmony_ci * HMAC low level APIs are deprecated for public use, but still ok for internal
12e1051a39Sopenharmony_ci * use.
13e1051a39Sopenharmony_ci */
14e1051a39Sopenharmony_ci#include "internal/deprecated.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci#include <stdio.h>
17e1051a39Sopenharmony_ci#include <stdlib.h>
18e1051a39Sopenharmony_ci#include <string.h>
19e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
20e1051a39Sopenharmony_ci#include <openssl/opensslconf.h>
21e1051a39Sopenharmony_ci#include <openssl/hmac.h>
22e1051a39Sopenharmony_ci#include <openssl/core_names.h>
23e1051a39Sopenharmony_ci#include "hmac_local.h"
24e1051a39Sopenharmony_ci
25e1051a39Sopenharmony_ciint HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
26e1051a39Sopenharmony_ci                 const EVP_MD *md, ENGINE *impl)
27e1051a39Sopenharmony_ci{
28e1051a39Sopenharmony_ci    int rv = 0, reset = 0;
29e1051a39Sopenharmony_ci    int i, j;
30e1051a39Sopenharmony_ci    unsigned char pad[HMAC_MAX_MD_CBLOCK_SIZE];
31e1051a39Sopenharmony_ci    unsigned int keytmp_length;
32e1051a39Sopenharmony_ci    unsigned char keytmp[HMAC_MAX_MD_CBLOCK_SIZE];
33e1051a39Sopenharmony_ci
34e1051a39Sopenharmony_ci    /* If we are changing MD then we must have a key */
35e1051a39Sopenharmony_ci    if (md != NULL && md != ctx->md && (key == NULL || len < 0))
36e1051a39Sopenharmony_ci        return 0;
37e1051a39Sopenharmony_ci
38e1051a39Sopenharmony_ci    if (md != NULL)
39e1051a39Sopenharmony_ci        ctx->md = md;
40e1051a39Sopenharmony_ci    else if (ctx->md != NULL)
41e1051a39Sopenharmony_ci        md = ctx->md;
42e1051a39Sopenharmony_ci    else
43e1051a39Sopenharmony_ci        return 0;
44e1051a39Sopenharmony_ci
45e1051a39Sopenharmony_ci    /*
46e1051a39Sopenharmony_ci     * The HMAC construction is not allowed to be used with the
47e1051a39Sopenharmony_ci     * extendable-output functions (XOF) shake128 and shake256.
48e1051a39Sopenharmony_ci     */
49e1051a39Sopenharmony_ci    if ((EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF) != 0)
50e1051a39Sopenharmony_ci        return 0;
51e1051a39Sopenharmony_ci
52e1051a39Sopenharmony_ci    if (key != NULL) {
53e1051a39Sopenharmony_ci        reset = 1;
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_ci        j = EVP_MD_get_block_size(md);
56e1051a39Sopenharmony_ci        if (!ossl_assert(j <= (int)sizeof(keytmp)))
57e1051a39Sopenharmony_ci            return 0;
58e1051a39Sopenharmony_ci        if (j < 0)
59e1051a39Sopenharmony_ci            return 0;
60e1051a39Sopenharmony_ci        if (j < len) {
61e1051a39Sopenharmony_ci            if (!EVP_DigestInit_ex(ctx->md_ctx, md, impl)
62e1051a39Sopenharmony_ci                    || !EVP_DigestUpdate(ctx->md_ctx, key, len)
63e1051a39Sopenharmony_ci                    || !EVP_DigestFinal_ex(ctx->md_ctx, keytmp,
64e1051a39Sopenharmony_ci                                           &keytmp_length))
65e1051a39Sopenharmony_ci                return 0;
66e1051a39Sopenharmony_ci        } else {
67e1051a39Sopenharmony_ci            if (len < 0 || len > (int)sizeof(keytmp))
68e1051a39Sopenharmony_ci                return 0;
69e1051a39Sopenharmony_ci            memcpy(keytmp, key, len);
70e1051a39Sopenharmony_ci            keytmp_length = len;
71e1051a39Sopenharmony_ci        }
72e1051a39Sopenharmony_ci        if (keytmp_length != HMAC_MAX_MD_CBLOCK_SIZE)
73e1051a39Sopenharmony_ci            memset(&keytmp[keytmp_length], 0,
74e1051a39Sopenharmony_ci                   HMAC_MAX_MD_CBLOCK_SIZE - keytmp_length);
75e1051a39Sopenharmony_ci
76e1051a39Sopenharmony_ci        for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++)
77e1051a39Sopenharmony_ci            pad[i] = 0x36 ^ keytmp[i];
78e1051a39Sopenharmony_ci        if (!EVP_DigestInit_ex(ctx->i_ctx, md, impl)
79e1051a39Sopenharmony_ci                || !EVP_DigestUpdate(ctx->i_ctx, pad,
80e1051a39Sopenharmony_ci                                     EVP_MD_get_block_size(md)))
81e1051a39Sopenharmony_ci            goto err;
82e1051a39Sopenharmony_ci
83e1051a39Sopenharmony_ci        for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++)
84e1051a39Sopenharmony_ci            pad[i] = 0x5c ^ keytmp[i];
85e1051a39Sopenharmony_ci        if (!EVP_DigestInit_ex(ctx->o_ctx, md, impl)
86e1051a39Sopenharmony_ci                || !EVP_DigestUpdate(ctx->o_ctx, pad,
87e1051a39Sopenharmony_ci                                     EVP_MD_get_block_size(md)))
88e1051a39Sopenharmony_ci            goto err;
89e1051a39Sopenharmony_ci    }
90e1051a39Sopenharmony_ci    if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->i_ctx))
91e1051a39Sopenharmony_ci        goto err;
92e1051a39Sopenharmony_ci    rv = 1;
93e1051a39Sopenharmony_ci err:
94e1051a39Sopenharmony_ci    if (reset) {
95e1051a39Sopenharmony_ci        OPENSSL_cleanse(keytmp, sizeof(keytmp));
96e1051a39Sopenharmony_ci        OPENSSL_cleanse(pad, sizeof(pad));
97e1051a39Sopenharmony_ci    }
98e1051a39Sopenharmony_ci    return rv;
99e1051a39Sopenharmony_ci}
100e1051a39Sopenharmony_ci
101e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_1_1_0
102e1051a39Sopenharmony_ciint HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md)
103e1051a39Sopenharmony_ci{
104e1051a39Sopenharmony_ci    if (key && md)
105e1051a39Sopenharmony_ci        HMAC_CTX_reset(ctx);
106e1051a39Sopenharmony_ci    return HMAC_Init_ex(ctx, key, len, md, NULL);
107e1051a39Sopenharmony_ci}
108e1051a39Sopenharmony_ci#endif
109e1051a39Sopenharmony_ci
110e1051a39Sopenharmony_ciint HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len)
111e1051a39Sopenharmony_ci{
112e1051a39Sopenharmony_ci    if (!ctx->md)
113e1051a39Sopenharmony_ci        return 0;
114e1051a39Sopenharmony_ci    return EVP_DigestUpdate(ctx->md_ctx, data, len);
115e1051a39Sopenharmony_ci}
116e1051a39Sopenharmony_ci
117e1051a39Sopenharmony_ciint HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len)
118e1051a39Sopenharmony_ci{
119e1051a39Sopenharmony_ci    unsigned int i;
120e1051a39Sopenharmony_ci    unsigned char buf[EVP_MAX_MD_SIZE];
121e1051a39Sopenharmony_ci
122e1051a39Sopenharmony_ci    if (!ctx->md)
123e1051a39Sopenharmony_ci        goto err;
124e1051a39Sopenharmony_ci
125e1051a39Sopenharmony_ci    if (!EVP_DigestFinal_ex(ctx->md_ctx, buf, &i))
126e1051a39Sopenharmony_ci        goto err;
127e1051a39Sopenharmony_ci    if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->o_ctx))
128e1051a39Sopenharmony_ci        goto err;
129e1051a39Sopenharmony_ci    if (!EVP_DigestUpdate(ctx->md_ctx, buf, i))
130e1051a39Sopenharmony_ci        goto err;
131e1051a39Sopenharmony_ci    if (!EVP_DigestFinal_ex(ctx->md_ctx, md, len))
132e1051a39Sopenharmony_ci        goto err;
133e1051a39Sopenharmony_ci    return 1;
134e1051a39Sopenharmony_ci err:
135e1051a39Sopenharmony_ci    return 0;
136e1051a39Sopenharmony_ci}
137e1051a39Sopenharmony_ci
138e1051a39Sopenharmony_cisize_t HMAC_size(const HMAC_CTX *ctx)
139e1051a39Sopenharmony_ci{
140e1051a39Sopenharmony_ci    int size = EVP_MD_get_size((ctx)->md);
141e1051a39Sopenharmony_ci
142e1051a39Sopenharmony_ci    return (size < 0) ? 0 : size;
143e1051a39Sopenharmony_ci}
144e1051a39Sopenharmony_ci
145e1051a39Sopenharmony_ciHMAC_CTX *HMAC_CTX_new(void)
146e1051a39Sopenharmony_ci{
147e1051a39Sopenharmony_ci    HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX));
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_ci    if (ctx != NULL) {
150e1051a39Sopenharmony_ci        if (!HMAC_CTX_reset(ctx)) {
151e1051a39Sopenharmony_ci            HMAC_CTX_free(ctx);
152e1051a39Sopenharmony_ci            return NULL;
153e1051a39Sopenharmony_ci        }
154e1051a39Sopenharmony_ci    }
155e1051a39Sopenharmony_ci    return ctx;
156e1051a39Sopenharmony_ci}
157e1051a39Sopenharmony_ci
158e1051a39Sopenharmony_cistatic void hmac_ctx_cleanup(HMAC_CTX *ctx)
159e1051a39Sopenharmony_ci{
160e1051a39Sopenharmony_ci    EVP_MD_CTX_reset(ctx->i_ctx);
161e1051a39Sopenharmony_ci    EVP_MD_CTX_reset(ctx->o_ctx);
162e1051a39Sopenharmony_ci    EVP_MD_CTX_reset(ctx->md_ctx);
163e1051a39Sopenharmony_ci    ctx->md = NULL;
164e1051a39Sopenharmony_ci}
165e1051a39Sopenharmony_ci
166e1051a39Sopenharmony_civoid HMAC_CTX_free(HMAC_CTX *ctx)
167e1051a39Sopenharmony_ci{
168e1051a39Sopenharmony_ci    if (ctx != NULL) {
169e1051a39Sopenharmony_ci        hmac_ctx_cleanup(ctx);
170e1051a39Sopenharmony_ci        EVP_MD_CTX_free(ctx->i_ctx);
171e1051a39Sopenharmony_ci        EVP_MD_CTX_free(ctx->o_ctx);
172e1051a39Sopenharmony_ci        EVP_MD_CTX_free(ctx->md_ctx);
173e1051a39Sopenharmony_ci        OPENSSL_free(ctx);
174e1051a39Sopenharmony_ci    }
175e1051a39Sopenharmony_ci}
176e1051a39Sopenharmony_ci
177e1051a39Sopenharmony_cistatic int hmac_ctx_alloc_mds(HMAC_CTX *ctx)
178e1051a39Sopenharmony_ci{
179e1051a39Sopenharmony_ci    if (ctx->i_ctx == NULL)
180e1051a39Sopenharmony_ci        ctx->i_ctx = EVP_MD_CTX_new();
181e1051a39Sopenharmony_ci    if (ctx->i_ctx == NULL)
182e1051a39Sopenharmony_ci        return 0;
183e1051a39Sopenharmony_ci    if (ctx->o_ctx == NULL)
184e1051a39Sopenharmony_ci        ctx->o_ctx = EVP_MD_CTX_new();
185e1051a39Sopenharmony_ci    if (ctx->o_ctx == NULL)
186e1051a39Sopenharmony_ci        return 0;
187e1051a39Sopenharmony_ci    if (ctx->md_ctx == NULL)
188e1051a39Sopenharmony_ci        ctx->md_ctx = EVP_MD_CTX_new();
189e1051a39Sopenharmony_ci    if (ctx->md_ctx == NULL)
190e1051a39Sopenharmony_ci        return 0;
191e1051a39Sopenharmony_ci    return 1;
192e1051a39Sopenharmony_ci}
193e1051a39Sopenharmony_ci
194e1051a39Sopenharmony_ciint HMAC_CTX_reset(HMAC_CTX *ctx)
195e1051a39Sopenharmony_ci{
196e1051a39Sopenharmony_ci    hmac_ctx_cleanup(ctx);
197e1051a39Sopenharmony_ci    if (!hmac_ctx_alloc_mds(ctx)) {
198e1051a39Sopenharmony_ci        hmac_ctx_cleanup(ctx);
199e1051a39Sopenharmony_ci        return 0;
200e1051a39Sopenharmony_ci    }
201e1051a39Sopenharmony_ci    return 1;
202e1051a39Sopenharmony_ci}
203e1051a39Sopenharmony_ci
204e1051a39Sopenharmony_ciint HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx)
205e1051a39Sopenharmony_ci{
206e1051a39Sopenharmony_ci    if (!hmac_ctx_alloc_mds(dctx))
207e1051a39Sopenharmony_ci        goto err;
208e1051a39Sopenharmony_ci    if (!EVP_MD_CTX_copy_ex(dctx->i_ctx, sctx->i_ctx))
209e1051a39Sopenharmony_ci        goto err;
210e1051a39Sopenharmony_ci    if (!EVP_MD_CTX_copy_ex(dctx->o_ctx, sctx->o_ctx))
211e1051a39Sopenharmony_ci        goto err;
212e1051a39Sopenharmony_ci    if (!EVP_MD_CTX_copy_ex(dctx->md_ctx, sctx->md_ctx))
213e1051a39Sopenharmony_ci        goto err;
214e1051a39Sopenharmony_ci    dctx->md = sctx->md;
215e1051a39Sopenharmony_ci    return 1;
216e1051a39Sopenharmony_ci err:
217e1051a39Sopenharmony_ci    hmac_ctx_cleanup(dctx);
218e1051a39Sopenharmony_ci    return 0;
219e1051a39Sopenharmony_ci}
220e1051a39Sopenharmony_ci
221e1051a39Sopenharmony_ciunsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
222e1051a39Sopenharmony_ci                    const unsigned char *data, size_t data_len,
223e1051a39Sopenharmony_ci                    unsigned char *md, unsigned int *md_len)
224e1051a39Sopenharmony_ci{
225e1051a39Sopenharmony_ci    static unsigned char static_md[EVP_MAX_MD_SIZE];
226e1051a39Sopenharmony_ci    int size = EVP_MD_get_size(evp_md);
227e1051a39Sopenharmony_ci    size_t temp_md_len = 0;
228e1051a39Sopenharmony_ci    unsigned char *ret = NULL;
229e1051a39Sopenharmony_ci
230e1051a39Sopenharmony_ci    if (size >= 0) {
231e1051a39Sopenharmony_ci        ret = EVP_Q_mac(NULL, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL,
232e1051a39Sopenharmony_ci                        key, key_len, data, data_len,
233e1051a39Sopenharmony_ci                        md == NULL ? static_md : md, size, &temp_md_len);
234e1051a39Sopenharmony_ci        if (md_len != NULL)
235e1051a39Sopenharmony_ci            *md_len = (unsigned int)temp_md_len;
236e1051a39Sopenharmony_ci    }
237e1051a39Sopenharmony_ci    return ret;
238e1051a39Sopenharmony_ci}
239e1051a39Sopenharmony_ci
240e1051a39Sopenharmony_civoid HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags)
241e1051a39Sopenharmony_ci{
242e1051a39Sopenharmony_ci    EVP_MD_CTX_set_flags(ctx->i_ctx, flags);
243e1051a39Sopenharmony_ci    EVP_MD_CTX_set_flags(ctx->o_ctx, flags);
244e1051a39Sopenharmony_ci    EVP_MD_CTX_set_flags(ctx->md_ctx, flags);
245e1051a39Sopenharmony_ci}
246e1051a39Sopenharmony_ci
247e1051a39Sopenharmony_ciconst EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx)
248e1051a39Sopenharmony_ci{
249e1051a39Sopenharmony_ci    return ctx->md;
250e1051a39Sopenharmony_ci}
251