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