1b077aed3SPierre Pronchery /*
2*e7be843bSPierre Pronchery * Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery *
4b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at
7b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html
8b077aed3SPierre Pronchery */
9b077aed3SPierre Pronchery
10b077aed3SPierre Pronchery #include <string.h>
11b077aed3SPierre Pronchery #include <openssl/core_dispatch.h>
12b077aed3SPierre Pronchery #include <openssl/core_names.h>
13b077aed3SPierre Pronchery #include <openssl/params.h>
14b077aed3SPierre Pronchery #include <openssl/evp.h>
15b077aed3SPierre Pronchery #include <openssl/err.h>
16b077aed3SPierre Pronchery #include <openssl/proverr.h>
17b077aed3SPierre Pronchery
18b077aed3SPierre Pronchery #include "crypto/siphash.h"
19b077aed3SPierre Pronchery
20b077aed3SPierre Pronchery #include "prov/implementations.h"
21b077aed3SPierre Pronchery #include "prov/providercommon.h"
22b077aed3SPierre Pronchery
23b077aed3SPierre Pronchery /*
24b077aed3SPierre Pronchery * Forward declaration of everything implemented here. This is not strictly
25b077aed3SPierre Pronchery * necessary for the compiler, but provides an assurance that the signatures
26b077aed3SPierre Pronchery * of the functions in the dispatch table are correct.
27b077aed3SPierre Pronchery */
28b077aed3SPierre Pronchery static OSSL_FUNC_mac_newctx_fn siphash_new;
29b077aed3SPierre Pronchery static OSSL_FUNC_mac_dupctx_fn siphash_dup;
30b077aed3SPierre Pronchery static OSSL_FUNC_mac_freectx_fn siphash_free;
31b077aed3SPierre Pronchery static OSSL_FUNC_mac_gettable_ctx_params_fn siphash_gettable_ctx_params;
32b077aed3SPierre Pronchery static OSSL_FUNC_mac_get_ctx_params_fn siphash_get_ctx_params;
33b077aed3SPierre Pronchery static OSSL_FUNC_mac_settable_ctx_params_fn siphash_settable_ctx_params;
34b077aed3SPierre Pronchery static OSSL_FUNC_mac_set_ctx_params_fn siphash_set_params;
35b077aed3SPierre Pronchery static OSSL_FUNC_mac_init_fn siphash_init;
36b077aed3SPierre Pronchery static OSSL_FUNC_mac_update_fn siphash_update;
37b077aed3SPierre Pronchery static OSSL_FUNC_mac_final_fn siphash_final;
38b077aed3SPierre Pronchery
39b077aed3SPierre Pronchery struct siphash_data_st {
40b077aed3SPierre Pronchery void *provctx;
41b077aed3SPierre Pronchery SIPHASH siphash; /* Siphash data */
42b077aed3SPierre Pronchery SIPHASH sipcopy; /* Siphash data copy for reinitialization */
43b077aed3SPierre Pronchery unsigned int crounds, drounds;
44b077aed3SPierre Pronchery };
45b077aed3SPierre Pronchery
crounds(struct siphash_data_st * ctx)46b077aed3SPierre Pronchery static unsigned int crounds(struct siphash_data_st *ctx)
47b077aed3SPierre Pronchery {
48b077aed3SPierre Pronchery return ctx->crounds != 0 ? ctx->crounds : SIPHASH_C_ROUNDS;
49b077aed3SPierre Pronchery }
50b077aed3SPierre Pronchery
drounds(struct siphash_data_st * ctx)51b077aed3SPierre Pronchery static unsigned int drounds(struct siphash_data_st *ctx)
52b077aed3SPierre Pronchery {
53b077aed3SPierre Pronchery return ctx->drounds != 0 ? ctx->drounds : SIPHASH_D_ROUNDS;
54b077aed3SPierre Pronchery }
55b077aed3SPierre Pronchery
siphash_new(void * provctx)56b077aed3SPierre Pronchery static void *siphash_new(void *provctx)
57b077aed3SPierre Pronchery {
58b077aed3SPierre Pronchery struct siphash_data_st *ctx;
59b077aed3SPierre Pronchery
60b077aed3SPierre Pronchery if (!ossl_prov_is_running())
61b077aed3SPierre Pronchery return NULL;
62b077aed3SPierre Pronchery ctx = OPENSSL_zalloc(sizeof(*ctx));
63b077aed3SPierre Pronchery if (ctx != NULL)
64b077aed3SPierre Pronchery ctx->provctx = provctx;
65b077aed3SPierre Pronchery return ctx;
66b077aed3SPierre Pronchery }
67b077aed3SPierre Pronchery
siphash_free(void * vmacctx)68b077aed3SPierre Pronchery static void siphash_free(void *vmacctx)
69b077aed3SPierre Pronchery {
70b077aed3SPierre Pronchery OPENSSL_free(vmacctx);
71b077aed3SPierre Pronchery }
72b077aed3SPierre Pronchery
siphash_dup(void * vsrc)73b077aed3SPierre Pronchery static void *siphash_dup(void *vsrc)
74b077aed3SPierre Pronchery {
75b077aed3SPierre Pronchery struct siphash_data_st *ssrc = vsrc;
76b077aed3SPierre Pronchery struct siphash_data_st *sdst;
77b077aed3SPierre Pronchery
78b077aed3SPierre Pronchery if (!ossl_prov_is_running())
79b077aed3SPierre Pronchery return NULL;
80b077aed3SPierre Pronchery sdst = OPENSSL_malloc(sizeof(*sdst));
81b077aed3SPierre Pronchery if (sdst == NULL)
82b077aed3SPierre Pronchery return NULL;
83b077aed3SPierre Pronchery
84b077aed3SPierre Pronchery *sdst = *ssrc;
85b077aed3SPierre Pronchery return sdst;
86b077aed3SPierre Pronchery }
87b077aed3SPierre Pronchery
siphash_size(void * vmacctx)88b077aed3SPierre Pronchery static size_t siphash_size(void *vmacctx)
89b077aed3SPierre Pronchery {
90b077aed3SPierre Pronchery struct siphash_data_st *ctx = vmacctx;
91b077aed3SPierre Pronchery
92b077aed3SPierre Pronchery return SipHash_hash_size(&ctx->siphash);
93b077aed3SPierre Pronchery }
94b077aed3SPierre Pronchery
siphash_setkey(struct siphash_data_st * ctx,const unsigned char * key,size_t keylen)95b077aed3SPierre Pronchery static int siphash_setkey(struct siphash_data_st *ctx,
96b077aed3SPierre Pronchery const unsigned char *key, size_t keylen)
97b077aed3SPierre Pronchery {
98b077aed3SPierre Pronchery int ret;
99b077aed3SPierre Pronchery
100b077aed3SPierre Pronchery if (keylen != SIPHASH_KEY_SIZE)
101b077aed3SPierre Pronchery return 0;
102b077aed3SPierre Pronchery ret = SipHash_Init(&ctx->siphash, key, crounds(ctx), drounds(ctx));
103b077aed3SPierre Pronchery if (ret)
104b077aed3SPierre Pronchery ctx->sipcopy = ctx->siphash;
105b077aed3SPierre Pronchery return ret;
106b077aed3SPierre Pronchery }
107b077aed3SPierre Pronchery
siphash_init(void * vmacctx,const unsigned char * key,size_t keylen,const OSSL_PARAM params[])108b077aed3SPierre Pronchery static int siphash_init(void *vmacctx, const unsigned char *key, size_t keylen,
109b077aed3SPierre Pronchery const OSSL_PARAM params[])
110b077aed3SPierre Pronchery {
111b077aed3SPierre Pronchery struct siphash_data_st *ctx = vmacctx;
112b077aed3SPierre Pronchery
113b077aed3SPierre Pronchery if (!ossl_prov_is_running() || !siphash_set_params(ctx, params))
114b077aed3SPierre Pronchery return 0;
115b077aed3SPierre Pronchery /*
116b077aed3SPierre Pronchery * Without a key, there is not much to do here,
117b077aed3SPierre Pronchery * The actual initialization happens through controls.
118b077aed3SPierre Pronchery */
119b077aed3SPierre Pronchery if (key == NULL) {
120b077aed3SPierre Pronchery ctx->siphash = ctx->sipcopy;
121b077aed3SPierre Pronchery return 1;
122b077aed3SPierre Pronchery }
123b077aed3SPierre Pronchery return siphash_setkey(ctx, key, keylen);
124b077aed3SPierre Pronchery }
125b077aed3SPierre Pronchery
siphash_update(void * vmacctx,const unsigned char * data,size_t datalen)126b077aed3SPierre Pronchery static int siphash_update(void *vmacctx, const unsigned char *data,
127b077aed3SPierre Pronchery size_t datalen)
128b077aed3SPierre Pronchery {
129b077aed3SPierre Pronchery struct siphash_data_st *ctx = vmacctx;
130b077aed3SPierre Pronchery
131b077aed3SPierre Pronchery if (datalen == 0)
132b077aed3SPierre Pronchery return 1;
133b077aed3SPierre Pronchery
134b077aed3SPierre Pronchery SipHash_Update(&ctx->siphash, data, datalen);
135b077aed3SPierre Pronchery return 1;
136b077aed3SPierre Pronchery }
137b077aed3SPierre Pronchery
siphash_final(void * vmacctx,unsigned char * out,size_t * outl,size_t outsize)138b077aed3SPierre Pronchery static int siphash_final(void *vmacctx, unsigned char *out, size_t *outl,
139b077aed3SPierre Pronchery size_t outsize)
140b077aed3SPierre Pronchery {
141b077aed3SPierre Pronchery struct siphash_data_st *ctx = vmacctx;
142b077aed3SPierre Pronchery size_t hlen = siphash_size(ctx);
143b077aed3SPierre Pronchery
144b077aed3SPierre Pronchery if (!ossl_prov_is_running() || outsize < hlen)
145b077aed3SPierre Pronchery return 0;
146b077aed3SPierre Pronchery
147b077aed3SPierre Pronchery *outl = hlen;
148b077aed3SPierre Pronchery return SipHash_Final(&ctx->siphash, out, hlen);
149b077aed3SPierre Pronchery }
150b077aed3SPierre Pronchery
siphash_gettable_ctx_params(ossl_unused void * ctx,ossl_unused void * provctx)151b077aed3SPierre Pronchery static const OSSL_PARAM *siphash_gettable_ctx_params(ossl_unused void *ctx,
152b077aed3SPierre Pronchery ossl_unused void *provctx)
153b077aed3SPierre Pronchery {
154b077aed3SPierre Pronchery static const OSSL_PARAM known_gettable_ctx_params[] = {
155b077aed3SPierre Pronchery OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
156b077aed3SPierre Pronchery OSSL_PARAM_uint(OSSL_MAC_PARAM_C_ROUNDS, NULL),
157b077aed3SPierre Pronchery OSSL_PARAM_uint(OSSL_MAC_PARAM_D_ROUNDS, NULL),
158b077aed3SPierre Pronchery OSSL_PARAM_END
159b077aed3SPierre Pronchery };
160b077aed3SPierre Pronchery
161b077aed3SPierre Pronchery return known_gettable_ctx_params;
162b077aed3SPierre Pronchery }
163b077aed3SPierre Pronchery
siphash_get_ctx_params(void * vmacctx,OSSL_PARAM params[])164b077aed3SPierre Pronchery static int siphash_get_ctx_params(void *vmacctx, OSSL_PARAM params[])
165b077aed3SPierre Pronchery {
166b077aed3SPierre Pronchery struct siphash_data_st *ctx = vmacctx;
167b077aed3SPierre Pronchery OSSL_PARAM *p;
168b077aed3SPierre Pronchery
169b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL
170b077aed3SPierre Pronchery && !OSSL_PARAM_set_size_t(p, siphash_size(vmacctx)))
171b077aed3SPierre Pronchery return 0;
172b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_C_ROUNDS)) != NULL
173b077aed3SPierre Pronchery && !OSSL_PARAM_set_uint(p, crounds(ctx)))
174b077aed3SPierre Pronchery return 0;
175b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_D_ROUNDS)) != NULL
176b077aed3SPierre Pronchery && !OSSL_PARAM_set_uint(p, drounds(ctx)))
177b077aed3SPierre Pronchery return 0;
178b077aed3SPierre Pronchery return 1;
179b077aed3SPierre Pronchery }
180b077aed3SPierre Pronchery
siphash_settable_ctx_params(ossl_unused void * ctx,void * provctx)181b077aed3SPierre Pronchery static const OSSL_PARAM *siphash_settable_ctx_params(ossl_unused void *ctx,
182b077aed3SPierre Pronchery void *provctx)
183b077aed3SPierre Pronchery {
184b077aed3SPierre Pronchery static const OSSL_PARAM known_settable_ctx_params[] = {
185b077aed3SPierre Pronchery OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
186b077aed3SPierre Pronchery OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
187b077aed3SPierre Pronchery OSSL_PARAM_uint(OSSL_MAC_PARAM_C_ROUNDS, NULL),
188b077aed3SPierre Pronchery OSSL_PARAM_uint(OSSL_MAC_PARAM_D_ROUNDS, NULL),
189b077aed3SPierre Pronchery OSSL_PARAM_END
190b077aed3SPierre Pronchery };
191b077aed3SPierre Pronchery
192b077aed3SPierre Pronchery return known_settable_ctx_params;
193b077aed3SPierre Pronchery }
194b077aed3SPierre Pronchery
siphash_set_params(void * vmacctx,const OSSL_PARAM * params)195b077aed3SPierre Pronchery static int siphash_set_params(void *vmacctx, const OSSL_PARAM *params)
196b077aed3SPierre Pronchery {
197b077aed3SPierre Pronchery struct siphash_data_st *ctx = vmacctx;
198b077aed3SPierre Pronchery const OSSL_PARAM *p = NULL;
199b077aed3SPierre Pronchery size_t size;
200b077aed3SPierre Pronchery
201*e7be843bSPierre Pronchery if (ossl_param_is_empty(params))
202b077aed3SPierre Pronchery return 1;
203b077aed3SPierre Pronchery
204b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SIZE)) != NULL) {
205b077aed3SPierre Pronchery if (!OSSL_PARAM_get_size_t(p, &size)
206b077aed3SPierre Pronchery || !SipHash_set_hash_size(&ctx->siphash, size)
207b077aed3SPierre Pronchery || !SipHash_set_hash_size(&ctx->sipcopy, size))
208b077aed3SPierre Pronchery return 0;
209b077aed3SPierre Pronchery }
210b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_C_ROUNDS)) != NULL
211b077aed3SPierre Pronchery && !OSSL_PARAM_get_uint(p, &ctx->crounds))
212b077aed3SPierre Pronchery return 0;
213b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_D_ROUNDS)) != NULL
214b077aed3SPierre Pronchery && !OSSL_PARAM_get_uint(p, &ctx->drounds))
215b077aed3SPierre Pronchery return 0;
216b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL)
217b077aed3SPierre Pronchery if (p->data_type != OSSL_PARAM_OCTET_STRING
218b077aed3SPierre Pronchery || !siphash_setkey(ctx, p->data, p->data_size))
219b077aed3SPierre Pronchery return 0;
220b077aed3SPierre Pronchery return 1;
221b077aed3SPierre Pronchery }
222b077aed3SPierre Pronchery
223b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_siphash_functions[] = {
224b077aed3SPierre Pronchery { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))siphash_new },
225b077aed3SPierre Pronchery { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))siphash_dup },
226b077aed3SPierre Pronchery { OSSL_FUNC_MAC_FREECTX, (void (*)(void))siphash_free },
227b077aed3SPierre Pronchery { OSSL_FUNC_MAC_INIT, (void (*)(void))siphash_init },
228b077aed3SPierre Pronchery { OSSL_FUNC_MAC_UPDATE, (void (*)(void))siphash_update },
229b077aed3SPierre Pronchery { OSSL_FUNC_MAC_FINAL, (void (*)(void))siphash_final },
230b077aed3SPierre Pronchery { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,
231b077aed3SPierre Pronchery (void (*)(void))siphash_gettable_ctx_params },
232b077aed3SPierre Pronchery { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))siphash_get_ctx_params },
233b077aed3SPierre Pronchery { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
234b077aed3SPierre Pronchery (void (*)(void))siphash_settable_ctx_params },
235b077aed3SPierre Pronchery { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))siphash_set_params },
236*e7be843bSPierre Pronchery OSSL_DISPATCH_END
237b077aed3SPierre Pronchery };
238