c22ebd335fc370044ccef75169bbff3348ee5ecc
[oweals/openssl.git] / crypto / evp / mac_meth.c
1 #include <openssl/evp.h>
2 #include <openssl/err.h>
3 #include <openssl/core.h>
4 #include <openssl/core_dispatch.h>
5 #include "crypto/evp.h"
6 #include "internal/provider.h"
7 #include "evp_local.h"
8
9 static 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
18 static 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
34 static 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
49 static 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
152 EVP_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
160 int EVP_MAC_up_ref(EVP_MAC *mac)
161 {
162     return evp_mac_up_ref(mac);
163 }
164
165 void EVP_MAC_free(EVP_MAC *mac)
166 {
167     evp_mac_free(mac);
168 }
169
170 const OSSL_PROVIDER *EVP_MAC_provider(const EVP_MAC *mac)
171 {
172     return mac->prov;
173 }
174
175 const 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
182 const 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
189 const 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
196 void 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 }