Add EVP_MAC_provider()
[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_numbers.h>
5 #include "internal/evp_int.h"
6 #include "internal/provider.h"
7 #include "evp_locl.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     OPENSSL_free(mac->name);
31     CRYPTO_THREAD_lock_free(mac->lock);
32     OPENSSL_free(mac);
33 }
34
35 static void *evp_mac_new(void)
36 {
37     EVP_MAC *mac = NULL;
38
39     if ((mac = OPENSSL_zalloc(sizeof(*mac))) == NULL
40         || (mac->lock = CRYPTO_THREAD_lock_new()) == NULL) {
41         evp_mac_free(mac);
42         return NULL;
43     }
44
45     mac->refcnt = 1;
46
47     return mac;
48 }
49
50 static void *evp_mac_from_dispatch(const char *name, 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         || (mac->name = OPENSSL_strdup(name)) == NULL) {
58         EVP_MAC_free(mac);
59         EVPerr(0, ERR_R_MALLOC_FAILURE);
60         return NULL;
61     }
62
63     for (; fns->function_id != 0; fns++) {
64         switch (fns->function_id) {
65         case OSSL_FUNC_MAC_NEWCTX:
66             if (mac->newctx != NULL)
67                 break;
68             mac->newctx = OSSL_get_OP_mac_newctx(fns);
69             fnctxcnt++;
70             break;
71         case OSSL_FUNC_MAC_DUPCTX:
72             if (mac->dupctx != NULL)
73                 break;
74             mac->dupctx = OSSL_get_OP_mac_dupctx(fns);
75             break;
76         case OSSL_FUNC_MAC_FREECTX:
77             if (mac->freectx != NULL)
78                 break;
79             mac->freectx = OSSL_get_OP_mac_freectx(fns);
80             fnctxcnt++;
81             break;
82         case OSSL_FUNC_MAC_INIT:
83             if (mac->init != NULL)
84                 break;
85             mac->init = OSSL_get_OP_mac_init(fns);
86             fnmaccnt++;
87             break;
88         case OSSL_FUNC_MAC_UPDATE:
89             if (mac->update != NULL)
90                 break;
91             mac->update = OSSL_get_OP_mac_update(fns);
92             fnmaccnt++;
93             break;
94         case OSSL_FUNC_MAC_FINAL:
95             if (mac->final != NULL)
96                 break;
97             mac->final = OSSL_get_OP_mac_final(fns);
98             fnmaccnt++;
99             break;
100         case OSSL_FUNC_MAC_GETTABLE_PARAMS:
101             if (mac->gettable_params != NULL)
102                 break;
103             mac->gettable_params =
104                 OSSL_get_OP_mac_gettable_params(fns);
105             break;
106         case OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS:
107             if (mac->gettable_ctx_params != NULL)
108                 break;
109             mac->gettable_ctx_params =
110                 OSSL_get_OP_mac_gettable_ctx_params(fns);
111             break;
112         case OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS:
113             if (mac->settable_ctx_params != NULL)
114                 break;
115             mac->settable_ctx_params =
116                 OSSL_get_OP_mac_settable_ctx_params(fns);
117             break;
118         case OSSL_FUNC_MAC_GET_PARAMS:
119             if (mac->get_params != NULL)
120                 break;
121             mac->get_params = OSSL_get_OP_mac_get_params(fns);
122             break;
123         case OSSL_FUNC_MAC_CTX_GET_PARAMS:
124             if (mac->ctx_get_params != NULL)
125                 break;
126             mac->ctx_get_params = OSSL_get_OP_mac_ctx_get_params(fns);
127             break;
128         case OSSL_FUNC_MAC_CTX_SET_PARAMS:
129             if (mac->ctx_set_params != NULL)
130                 break;
131             mac->ctx_set_params = OSSL_get_OP_mac_ctx_set_params(fns);
132             break;
133         }
134     }
135     if (fnmaccnt != 3
136         || fnctxcnt != 2) {
137         /*
138          * In order to be a consistent set of functions we must have at least
139          * a complete set of "mac" functions, and a complete set of context
140          * management functions, as well as the size function.
141          */
142         evp_mac_free(mac);
143         ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
144         return NULL;
145     }
146     mac->prov = prov;
147     if (prov != NULL)
148         ossl_provider_up_ref(prov);
149
150     return mac;
151 }
152
153 EVP_MAC *EVP_MAC_fetch(OPENSSL_CTX *libctx, const char *algorithm,
154                        const char *properties)
155 {
156     return evp_generic_fetch(libctx, OSSL_OP_MAC, algorithm, properties,
157                              evp_mac_from_dispatch, evp_mac_up_ref,
158                              evp_mac_free);
159 }
160
161 int EVP_MAC_up_ref(EVP_MAC *mac)
162 {
163     return evp_mac_up_ref(mac);
164 }
165
166 void EVP_MAC_free(EVP_MAC *mac)
167 {
168     evp_mac_free(mac);
169 }
170
171 const char *EVP_MAC_name(const EVP_MAC *mac)
172 {
173     return mac->name;
174 }
175
176 const OSSL_PROVIDER *EVP_MAC_provider(const EVP_MAC *mac)
177 {
178     return mac->prov;
179 }
180
181 const OSSL_PARAM *EVP_MAC_gettable_params(const EVP_MAC *mac)
182 {
183     if (mac->gettable_params == NULL)
184         return NULL;
185     return mac->gettable_params();
186 }
187
188 const OSSL_PARAM *EVP_MAC_CTX_gettable_params(const EVP_MAC *mac)
189 {
190     if (mac->gettable_ctx_params == NULL)
191         return NULL;
192     return mac->gettable_ctx_params();
193 }
194
195 const OSSL_PARAM *EVP_MAC_CTX_settable_params(const EVP_MAC *mac)
196 {
197     if (mac->settable_ctx_params == NULL)
198         return NULL;
199     return mac->settable_ctx_params();
200 }