705bf7fd2aa1c0892db1cae5acc850f75119a8eb
[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 int hmac_copy(EVP_MAC_IMPL *hdst, EVP_MAC_IMPL *hsrc)
49 {
50     if (!HMAC_CTX_copy(hdst->ctx, hsrc->ctx))
51         return 0;
52
53     hdst->tmpengine = hsrc->tmpengine;
54     hdst->tmpmd = hsrc->tmpmd;
55     return 1;
56 }
57
58 static size_t hmac_size(EVP_MAC_IMPL *hctx)
59 {
60     return HMAC_size(hctx->ctx);
61 }
62
63 static int hmac_init(EVP_MAC_IMPL *hctx)
64 {
65     int rv = 1;
66
67     /* HMAC_Init_ex doesn't tolerate all zero params, so we must be careful */
68     if (hctx->tmpmd != NULL)
69         rv = HMAC_Init_ex(hctx->ctx, NULL, 0, hctx->tmpmd,
70                           (ENGINE * )hctx->tmpengine);
71     hctx->tmpengine = NULL;
72     hctx->tmpmd = NULL;
73     return rv;
74 }
75
76 static int hmac_update(EVP_MAC_IMPL *hctx, const unsigned char *data,
77                        size_t datalen)
78 {
79     return HMAC_Update(hctx->ctx, data, datalen);
80 }
81
82 static int hmac_final(EVP_MAC_IMPL *hctx, unsigned char *out)
83 {
84     unsigned int hlen;
85
86     return HMAC_Final(hctx->ctx, out, &hlen);
87 }
88
89 static int hmac_ctrl(EVP_MAC_IMPL *hctx, int cmd, va_list args)
90 {
91     switch (cmd) {
92     case EVP_MAC_CTRL_SET_FLAGS:
93         {
94             unsigned long flags = va_arg(args, unsigned long);
95
96             HMAC_CTX_set_flags(hctx->ctx, flags);
97         }
98         break;
99     case EVP_MAC_CTRL_SET_KEY:
100         {
101             const unsigned char *key = va_arg(args, const unsigned char *);
102             size_t keylen = va_arg(args, size_t);
103             int rv = HMAC_Init_ex(hctx->ctx, key, keylen, hctx->tmpmd,
104                                   (ENGINE *)hctx->tmpengine);
105
106             hctx->tmpengine = NULL;
107             hctx->tmpmd = NULL;
108             return rv;
109         }
110         break;
111     case EVP_MAC_CTRL_SET_MD:
112         hctx->tmpmd = va_arg(args, const EVP_MD *);
113         break;
114     case EVP_MAC_CTRL_SET_ENGINE:
115         hctx->tmpengine = va_arg(args, const ENGINE *);
116         break;
117     default:
118         return -2;
119
120     }
121     return 1;
122 }
123
124 static int hmac_ctrl_int(EVP_MAC_IMPL *hctx, int cmd, ...)
125 {
126     int rv;
127     va_list args;
128
129     va_start(args, cmd);
130     rv = hmac_ctrl(hctx, cmd, args);
131     va_end(args);
132
133     return rv;
134 }
135
136 static int hmac_ctrl_str_cb(void *hctx, int cmd, void *buf, size_t buflen)
137 {
138     return hmac_ctrl_int(hctx, cmd, buf, buflen);
139 }
140
141 static int hmac_ctrl_str(EVP_MAC_IMPL *hctx, const char *type,
142                          const char *value)
143 {
144     if (!value)
145         return 0;
146     if (strcmp(type, "digest") == 0) {
147         const EVP_MD *d = EVP_get_digestbyname(value);
148
149         if (d == NULL)
150             return 0;
151         return hmac_ctrl_int(hctx, EVP_MAC_CTRL_SET_MD, d);
152     }
153     if (strcmp(type, "key") == 0)
154         return EVP_str2ctrl(hmac_ctrl_str_cb, hctx, EVP_MAC_CTRL_SET_KEY,
155                             value);
156     if (strcmp(type, "hexkey") == 0)
157         return EVP_hex2ctrl(hmac_ctrl_str_cb, hctx, EVP_MAC_CTRL_SET_KEY,
158                             value);
159     return -2;
160 }
161
162 const EVP_MAC hmac_meth = {
163     EVP_MAC_HMAC,
164     hmac_new,
165     hmac_copy,
166     hmac_free,
167     hmac_size,
168     hmac_init,
169     hmac_update,
170     hmac_final,
171     hmac_ctrl,
172     hmac_ctrl_str
173 };