1 /*
2  * Copyright 2019-2023 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 <openssl/crypto.h>
11 #include <openssl/core_names.h>
12 #include <openssl/proverr.h>
13 #include <openssl/err.h>
14 #include "prov/blake2.h"
15 #include "prov/digestcommon.h"
16 #include "prov/implementations.h"
17 
18 #define IMPLEMENT_BLAKE_functions(variant, VARIANT, variantsize) \
19 static const OSSL_PARAM known_blake##variant##_ctx_params[] = { \
20     {OSSL_DIGEST_PARAM_SIZE, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0}, \
21     OSSL_PARAM_END \
22 }; \
23  \
24 const OSSL_PARAM *ossl_blake##variant##_gettable_ctx_params(ossl_unused void *ctx, \
25                                                    ossl_unused void *pctx) \
26 { \
27     return known_blake##variant##_ctx_params; \
28 } \
29  \
30 const OSSL_PARAM *ossl_blake##variant##_settable_ctx_params(ossl_unused void *ctx, \
31                                                    ossl_unused void *pctx) \
32 { \
33     return known_blake##variant##_ctx_params; \
34 } \
35  \
36 int ossl_blake##variant##_get_ctx_params(void *vctx, OSSL_PARAM params[]) \
37 { \
38     struct blake##variant##_md_data_st *mdctx = vctx; \
39     OSSL_PARAM *p; \
40  \
41     BLAKE##VARIANT##_CTX *ctx = &mdctx->ctx; \
42  \
43     if (ctx == NULL) \
44         return 0; \
45     if (ossl_param_is_empty(params)) \
46         return 1; \
47  \
48     p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_SIZE); \
49     if (p != NULL \
50         && !OSSL_PARAM_set_uint(p, (unsigned int)mdctx->params.digest_length)) { \
51         ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); \
52         return 0; \
53     } \
54  \
55     return 1; \
56 } \
57  \
58 int ossl_blake##variant##_set_ctx_params(void *vctx, const OSSL_PARAM params[]) \
59 { \
60     size_t size; \
61     struct blake##variant##_md_data_st *mdctx = vctx; \
62     const OSSL_PARAM *p; \
63  \
64     BLAKE##VARIANT##_CTX *ctx = &mdctx->ctx; \
65  \
66     if (ctx == NULL) \
67         return 0; \
68     if (ossl_param_is_empty(params)) \
69         return 1; \
70  \
71     p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_SIZE); \
72     if (p != NULL) { \
73         if (!OSSL_PARAM_get_size_t(p, &size)) { \
74             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); \
75             return 0; \
76         } \
77         if (size < 1 || size > BLAKE##VARIANT##_OUTBYTES) { \
78             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_SIZE); \
79             return 0; \
80         } \
81         ossl_blake##variant##_param_set_digest_length(&mdctx->params, (uint8_t)size); \
82     } \
83  \
84     return 1; \
85 } \
86  \
87 static int ossl_blake##variantsize##_init(void *ctx) \
88 { \
89     struct blake##variant##_md_data_st *mdctx = ctx; \
90     uint8_t digest_length = mdctx->params.digest_length; \
91  \
92     ossl_blake##variant##_param_init(&mdctx->params); \
93     if (digest_length != 0) \
94         mdctx->params.digest_length = digest_length; \
95     return ossl_blake##variant##_init(&mdctx->ctx, &mdctx->params); \
96 } \
97  \
98 static OSSL_FUNC_digest_init_fn blake##variantsize##_internal_init; \
99 static OSSL_FUNC_digest_newctx_fn blake##variantsize##_newctx; \
100 static OSSL_FUNC_digest_freectx_fn blake##variantsize##_freectx; \
101 static OSSL_FUNC_digest_dupctx_fn blake##variantsize##_dupctx; \
102 static OSSL_FUNC_digest_final_fn blake##variantsize##_internal_final; \
103 static OSSL_FUNC_digest_get_params_fn blake##variantsize##_get_params; \
104  \
105 static int blake##variantsize##_internal_init(void *ctx, const OSSL_PARAM params[]) \
106 { \
107     return ossl_prov_is_running() && ossl_blake##variant##_set_ctx_params(ctx, params) \
108         && ossl_blake##variantsize##_init(ctx); \
109 } \
110  \
111 static void *blake##variantsize##_newctx(void *prov_ctx) \
112 { \
113     struct blake##variant##_md_data_st *ctx; \
114  \
115     ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx)) : NULL; \
116     return ctx; \
117 } \
118  \
119 static void blake##variantsize##_freectx(void *vctx) \
120 { \
121     struct blake##variant##_md_data_st *ctx; \
122  \
123     ctx = (struct blake##variant##_md_data_st *)vctx; \
124     OPENSSL_clear_free(ctx, sizeof(*ctx)); \
125 } \
126  \
127 static void *blake##variantsize##_dupctx(void *ctx) \
128 { \
129     struct blake##variant##_md_data_st *in, *ret; \
130  \
131     in = (struct blake##variant##_md_data_st *)ctx; \
132     ret = ossl_prov_is_running()? OPENSSL_malloc(sizeof(*ret)) : NULL; \
133     if (ret != NULL) \
134         *ret = *in; \
135     return ret; \
136 } \
137 \
138 static void blake##variantsize##_copyctx(void *voutctx, void *vinctx) \
139 { \
140     struct blake##variant##_md_data_st *inctx, *outctx; \
141  \
142     outctx = (struct blake##variant##_md_data_st *)voutctx; \
143     inctx = (struct blake##variant##_md_data_st *)vinctx; \
144     *outctx = *inctx; \
145 } \
146  \
147 static int blake##variantsize##_internal_final(void *ctx, unsigned char *out, \
148                                      size_t *outl, size_t outsz) \
149 { \
150     struct blake##variant##_md_data_st *b_ctx; \
151  \
152     b_ctx = (struct blake##variant##_md_data_st *)ctx; \
153  \
154     if (!ossl_prov_is_running()) \
155         return 0; \
156  \
157     *outl = b_ctx->ctx.outlen; \
158  \
159     if (outsz == 0) \
160        return 1; \
161  \
162     if (outsz < *outl) { \
163         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_SIZE); \
164         return 0; \
165     } \
166  \
167     return ossl_blake##variant##_final(out, ctx); \
168 } \
169  \
170 static int blake##variantsize##_get_params(OSSL_PARAM params[]) \
171 { \
172     return ossl_digest_default_get_params(params, BLAKE##VARIANT##_BLOCKBYTES, BLAKE##VARIANT##_OUTBYTES, 0); \
173 } \
174  \
175 const OSSL_DISPATCH ossl_blake##variantsize##_functions[] = { \
176     {OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))blake##variantsize##_newctx}, \
177     {OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))ossl_blake##variant##_update}, \
178     {OSSL_FUNC_DIGEST_FINAL, (void (*)(void))blake##variantsize##_internal_final}, \
179     {OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))blake##variantsize##_freectx}, \
180     {OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))blake##variantsize##_dupctx}, \
181     {OSSL_FUNC_DIGEST_COPYCTX, (void (*)(void))blake##variantsize##_copyctx}, \
182     {OSSL_FUNC_DIGEST_GET_PARAMS, (void (*)(void))blake##variantsize##_get_params}, \
183     {OSSL_FUNC_DIGEST_GETTABLE_PARAMS, \
184      (void (*)(void))ossl_digest_default_gettable_params}, \
185     {OSSL_FUNC_DIGEST_INIT, (void (*)(void))blake##variantsize##_internal_init}, \
186     {OSSL_FUNC_DIGEST_GETTABLE_CTX_PARAMS, \
187      (void (*)(void))ossl_blake##variant##_gettable_ctx_params}, \
188     {OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS, \
189      (void (*)(void))ossl_blake##variant##_settable_ctx_params}, \
190     {OSSL_FUNC_DIGEST_GET_CTX_PARAMS, \
191      (void (*)(void))ossl_blake##variant##_get_ctx_params}, \
192     {OSSL_FUNC_DIGEST_SET_CTX_PARAMS, \
193      (void (*)(void))ossl_blake##variant##_set_ctx_params}, \
194     {0, NULL} \
195 };
196 
197 IMPLEMENT_BLAKE_functions(2s, 2S, 2s256)
198 IMPLEMENT_BLAKE_functions(2b, 2B, 2b512)
199