1#include <openssl/evp.h>
2#include <openssl/err.h>
3#include <openssl/core.h>
4#include <openssl/core_numbers.h>
5#include "crypto/evp.h"
6#include "internal/provider.h"
7#include "evp_local.h"
8
9static int evp_mac_up_ref(void *vmac)
10{
11 EVP_MAC *mac = vmac;
12 int ref = 0;
13
14 CRYPTO_UP_REF(&mac->refcnt, &ref, mac->lock);
15 return 1;
16}
17
18static void evp_mac_free(void *vmac)
19{
20 EVP_MAC *mac = vmac;
21 int ref = 0;
22
23 if (mac == NULL)
24 return;
25
26 CRYPTO_DOWN_REF(&mac->refcnt, &ref, mac->lock);
27 if (ref > 0)
28 return;
29 ossl_provider_free(mac->prov);
30 CRYPTO_THREAD_lock_free(mac->lock);
31 OPENSSL_free(mac);
32}
33
34static void *evp_mac_new(void)
35{
36 EVP_MAC *mac = NULL;
37
38 if ((mac = OPENSSL_zalloc(sizeof(*mac))) == NULL
39 || (mac->lock = CRYPTO_THREAD_lock_new()) == NULL) {
40 evp_mac_free(mac);
41 return NULL;
42 }
43
44 mac->refcnt = 1;
45
46 return mac;
47}
48
49static void *evp_mac_from_dispatch(int name_id,
50 const OSSL_DISPATCH *fns,
51 OSSL_PROVIDER *prov)
52{
53 EVP_MAC *mac = NULL;
54 int fnmaccnt = 0, fnctxcnt = 0;
55
56 if ((mac = evp_mac_new()) == NULL) {
57 EVPerr(0, ERR_R_MALLOC_FAILURE);
58 return NULL;
59 }
60 mac->name_id = name_id;
61
62 for (; fns->function_id != 0; fns++) {
63 switch (fns->function_id) {
64 case OSSL_FUNC_MAC_NEWCTX:
65 if (mac->newctx != NULL)
66 break;
67 mac->newctx = OSSL_get_OP_mac_newctx(fns);
68 fnctxcnt++;
69 break;
70 case OSSL_FUNC_MAC_DUPCTX:
71 if (mac->dupctx != NULL)
72 break;
73 mac->dupctx = OSSL_get_OP_mac_dupctx(fns);
74 break;
75 case OSSL_FUNC_MAC_FREECTX:
76 if (mac->freectx != NULL)
77 break;
78 mac->freectx = OSSL_get_OP_mac_freectx(fns);
79 fnctxcnt++;
80 break;
81 case OSSL_FUNC_MAC_INIT:
82 if (mac->init != NULL)
83 break;
84 mac->init = OSSL_get_OP_mac_init(fns);
85 fnmaccnt++;
86 break;
87 case OSSL_FUNC_MAC_UPDATE:
88 if (mac->update != NULL)
89 break;
90 mac->update = OSSL_get_OP_mac_update(fns);
91 fnmaccnt++;
92 break;
93 case OSSL_FUNC_MAC_FINAL:
94 if (mac->final != NULL)
95 break;
96 mac->final = OSSL_get_OP_mac_final(fns);
97 fnmaccnt++;
98 break;
99 case OSSL_FUNC_MAC_GETTABLE_PARAMS:
100 if (mac->gettable_params != NULL)
101 break;
102 mac->gettable_params =
103 OSSL_get_OP_mac_gettable_params(fns);
104 break;
105 case OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS:
106 if (mac->gettable_ctx_params != NULL)
107 break;
108 mac->gettable_ctx_params =
109 OSSL_get_OP_mac_gettable_ctx_params(fns);
110 break;
111 case OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS:
112 if (mac->settable_ctx_params != NULL)
113 break;
114 mac->settable_ctx_params =
115 OSSL_get_OP_mac_settable_ctx_params(fns);
116 break;
117 case OSSL_FUNC_MAC_GET_PARAMS:
118 if (mac->get_params != NULL)
119 break;
120 mac->get_params = OSSL_get_OP_mac_get_params(fns);
121 break;
122 case OSSL_FUNC_MAC_GET_CTX_PARAMS:
123 if (mac->get_ctx_params != NULL)
124 break;
125 mac->get_ctx_params = OSSL_get_OP_mac_get_ctx_params(fns);
126 break;
127 case OSSL_FUNC_MAC_SET_CTX_PARAMS:
128 if (mac->set_ctx_params != NULL)
129 break;
130 mac->set_ctx_params = OSSL_get_OP_mac_set_ctx_params(fns);
131 break;
132 }
133 }
134 if (fnmaccnt != 3
135 || fnctxcnt != 2) {
136 /*
137 * In order to be a consistent set of functions we must have at least
138 * a complete set of "mac" functions, and a complete set of context
139 * management functions, as well as the size function.
140 */
141 evp_mac_free(mac);
142 ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
143 return NULL;
144 }
145 mac->prov = prov;
146 if (prov != NULL)
147 ossl_provider_up_ref(prov);
148
149 return mac;
150}
151
152EVP_MAC *EVP_MAC_fetch(OPENSSL_CTX *libctx, const char *algorithm,
153 const char *properties)
154{
155 return evp_generic_fetch(libctx, OSSL_OP_MAC, algorithm, properties,
156 evp_mac_from_dispatch, evp_mac_up_ref,
157 evp_mac_free);
158}
159
160int EVP_MAC_up_ref(EVP_MAC *mac)
161{
162 return evp_mac_up_ref(mac);
163}
164
165void EVP_MAC_free(EVP_MAC *mac)
166{
167 evp_mac_free(mac);
168}
169
170const OSSL_PROVIDER *EVP_MAC_provider(const EVP_MAC *mac)
171{
172 return mac->prov;
173}
174
175const OSSL_PARAM *EVP_MAC_gettable_params(const EVP_MAC *mac)
176{
177 if (mac->gettable_params == NULL)
178 return NULL;
179 return mac->gettable_params();
180}
181
182const OSSL_PARAM *EVP_MAC_gettable_ctx_params(const EVP_MAC *mac)
183{
184 if (mac->gettable_ctx_params == NULL)
185 return NULL;
186 return mac->gettable_ctx_params();
187}
188
189const OSSL_PARAM *EVP_MAC_settable_ctx_params(const EVP_MAC *mac)
190{
191 if (mac->settable_ctx_params == NULL)
192 return NULL;
193 return mac->settable_ctx_params();
194}
195
196void EVP_MAC_do_all_provided(OPENSSL_CTX *libctx,
197 void (*fn)(EVP_MAC *mac, void *arg),
198 void *arg)
199{
200 evp_generic_do_all(libctx, OSSL_OP_MAC,
201 (void (*)(void *, void *))fn, arg,
202 evp_mac_from_dispatch, evp_mac_free);
203}
204