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 int blake##variantsize##_internal_final(void *ctx, unsigned char *out, \
139                                      size_t *outl, size_t outsz) \
140 { \
141     struct blake##variant##_md_data_st *b_ctx; \
142  \
143     b_ctx = (struct blake##variant##_md_data_st *)ctx; \
144  \
145     if (!ossl_prov_is_running()) \
146         return 0; \
147  \
148     *outl = b_ctx->ctx.outlen; \
149  \
150     if (outsz == 0) \
151        return 1; \
152  \
153     if (outsz < *outl) { \
154         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_SIZE); \
155         return 0; \
156     } \
157  \
158     return ossl_blake##variant##_final(out, ctx); \
159 } \
160  \
161 static int blake##variantsize##_get_params(OSSL_PARAM params[]) \
162 { \
163     return ossl_digest_default_get_params(params, BLAKE##VARIANT##_BLOCKBYTES, BLAKE##VARIANT##_OUTBYTES, 0); \
164 } \
165  \
166 const OSSL_DISPATCH ossl_blake##variantsize##_functions[] = { \
167     {OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))blake##variantsize##_newctx}, \
168     {OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))ossl_blake##variant##_update}, \
169     {OSSL_FUNC_DIGEST_FINAL, (void (*)(void))blake##variantsize##_internal_final}, \
170     {OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))blake##variantsize##_freectx}, \
171     {OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))blake##variantsize##_dupctx}, \
172     {OSSL_FUNC_DIGEST_GET_PARAMS, (void (*)(void))blake##variantsize##_get_params}, \
173     {OSSL_FUNC_DIGEST_GETTABLE_PARAMS, \
174      (void (*)(void))ossl_digest_default_gettable_params}, \
175     {OSSL_FUNC_DIGEST_INIT, (void (*)(void))blake##variantsize##_internal_init}, \
176     {OSSL_FUNC_DIGEST_GETTABLE_CTX_PARAMS, \
177      (void (*)(void))ossl_blake##variant##_gettable_ctx_params}, \
178     {OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS, \
179      (void (*)(void))ossl_blake##variant##_settable_ctx_params}, \
180     {OSSL_FUNC_DIGEST_GET_CTX_PARAMS, \
181      (void (*)(void))ossl_blake##variant##_get_ctx_params}, \
182     {OSSL_FUNC_DIGEST_SET_CTX_PARAMS, \
183      (void (*)(void))ossl_blake##variant##_set_ctx_params}, \
184     {0, NULL} \
185 };
186 
187 IMPLEMENT_BLAKE_functions(2s, 2S, 2s256)
188 IMPLEMENT_BLAKE_functions(2b, 2B, 2b512)
189