Make the RAND code available from inside the FIPS module
[openssl.git] / crypto / hmac / hm_meth.c
1 /*
2  * Copyright 2018 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 #include <string.h>
11 #include <openssl/err.h>
12 #include <openssl/ossl_typ.h>
13 #include <openssl/asn1.h>
14 #include <openssl/hmac.h>
15 #include "internal/evp_int.h"
16
17 /* local HMAC context structure */
18
19 /* typedef EVP_MAC_IMPL */
20 struct evp_mac_impl_st {
21     /* tmpmd and tmpengine are set to NULL after a CMAC_Init call */
22     const EVP_MD *tmpmd;         /* HMAC digest */
23     const ENGINE *tmpengine;     /* HMAC digest engine */
24     HMAC_CTX *ctx;               /* HMAC context */
25 };
26
27 static EVP_MAC_IMPL *hmac_new(void)
28 {
29     EVP_MAC_IMPL *hctx;
30
31     if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL
32         || (hctx->ctx = HMAC_CTX_new()) == NULL) {
33         OPENSSL_free(hctx);
34         return NULL;
35     }
36
37     return hctx;
38 }
39
40 static void hmac_free(EVP_MAC_IMPL *hctx)
41 {
42     if (hctx != NULL) {
43         HMAC_CTX_free(hctx->ctx);
44         OPENSSL_free(hctx);
45     }
46 }
47
48 static EVP_MAC_IMPL *hmac_dup(const EVP_MAC_IMPL *hsrc)
49 {
50     EVP_MAC_IMPL *hdst;
51
52     hdst = hmac_new();
53     if (hdst == NULL)
54         return NULL;
55
56     if (!HMAC_CTX_copy(hdst->ctx, hsrc->ctx)) {
57         hmac_free(hdst);
58         return NULL;
59     }
60
61     hdst->tmpengine = hsrc->tmpengine;
62     hdst->tmpmd = hsrc->tmpmd;
63
64     return hdst;
65 }
66
67 static size_t hmac_size(EVP_MAC_IMPL *hctx)
68 {
69     return HMAC_size(hctx->ctx);
70 }
71
72 static int hmac_init(EVP_MAC_IMPL *hctx)
73 {
74     int rv = 1;
75
76     /* HMAC_Init_ex doesn't tolerate all zero params, so we must be careful */
77     if (hctx->tmpmd != NULL)
78         rv = HMAC_Init_ex(hctx->ctx, NULL, 0, hctx->tmpmd,
79                           (ENGINE * )hctx->tmpengine);
80     hctx->tmpengine = NULL;
81     hctx->tmpmd = NULL;
82     return rv;
83 }
84
85 static int hmac_update(EVP_MAC_IMPL *hctx, const unsigned char *data,
86                        size_t datalen)
87 {
88     return HMAC_Update(hctx->ctx, data, datalen);
89 }
90
91 static int hmac_final(EVP_MAC_IMPL *hctx, unsigned char *out)
92 {
93     unsigned int hlen;
94
95     return HMAC_Final(hctx->ctx, out, &hlen);
96 }
97
98 static int hmac_ctrl(EVP_MAC_IMPL *hctx, int cmd, va_list args)
99 {
100     switch (cmd) {
101     case EVP_MAC_CTRL_SET_FLAGS:
102         {
103             unsigned long flags = va_arg(args, unsigned long);
104
105             HMAC_CTX_set_flags(hctx->ctx, flags);
106         }
107         break;
108     case EVP_MAC_CTRL_SET_KEY:
109         {
110             const unsigned char *key = va_arg(args, const unsigned char *);
111             size_t keylen = va_arg(args, size_t);
112             int rv = HMAC_Init_ex(hctx->ctx, key, keylen, hctx->tmpmd,
113                                   (ENGINE *)hctx->tmpengine);
114
115             hctx->tmpengine = NULL;
116             hctx->tmpmd = NULL;
117             return rv;
118         }
119         break;
120     case EVP_MAC_CTRL_SET_MD:
121         hctx->tmpmd = va_arg(args, const EVP_MD *);
122         break;
123     case EVP_MAC_CTRL_SET_ENGINE:
124         hctx->tmpengine = va_arg(args, const ENGINE *);
125         break;
126     default:
127         return -2;
128
129     }
130     return 1;
131 }
132
133 static int hmac_ctrl_int(EVP_MAC_IMPL *hctx, int cmd, ...)
134 {
135     int rv;
136     va_list args;
137
138     va_start(args, cmd);
139     rv = hmac_ctrl(hctx, cmd, args);
140     va_end(args);
141
142     return rv;
143 }
144
145 static int hmac_ctrl_str_cb(void *hctx, int cmd, void *buf, size_t buflen)
146 {
147     return hmac_ctrl_int(hctx, cmd, buf, buflen);
148 }
149
150 static int hmac_ctrl_str(EVP_MAC_IMPL *hctx, const char *type,
151                          const char *value)
152 {
153     if (!value)
154         return 0;
155 #ifndef FIPS_MODE
156     /*
157      * We don't have EVP_get_digestbyname() in FIPS_MODE. That function returns
158      * an EVP_MD without an associated provider implementation (i.e. it is
159      * using "implicit fetch"). We could replace it with an "explicit" fetch
160      * using EVP_MD_fetch(), but we'd then be required to free the returned
161      * EVP_MD somewhere. Probably the complexity isn't worth it as we are
162      * unlikely to need this ctrl in FIPS_MODE anyway.
163      */
164     if (strcmp(type, "digest") == 0) {
165         const EVP_MD *d = EVP_get_digestbyname(value);
166
167         if (d == NULL)
168             return 0;
169         return hmac_ctrl_int(hctx, EVP_MAC_CTRL_SET_MD, d);
170     }
171 #endif
172     if (strcmp(type, "key") == 0)
173         return EVP_str2ctrl(hmac_ctrl_str_cb, hctx, EVP_MAC_CTRL_SET_KEY,
174                             value);
175     if (strcmp(type, "hexkey") == 0)
176         return EVP_hex2ctrl(hmac_ctrl_str_cb, hctx, EVP_MAC_CTRL_SET_KEY,
177                             value);
178     return -2;
179 }
180
181 const EVP_MAC hmac_meth = {
182     EVP_MAC_HMAC,
183     hmac_new,
184     hmac_dup,
185     hmac_free,
186     hmac_size,
187     hmac_init,
188     hmac_update,
189     hmac_final,
190     hmac_ctrl,
191     hmac_ctrl_str
192 };