]> git.ipfire.org Git - thirdparty/openssl.git/blame - providers/implementations/ciphers/cipher_chacha20_poly1305.c
prov: prefix all exposed 'cipher' symbols with ossl_
[thirdparty/openssl.git] / providers / implementations / ciphers / cipher_chacha20_poly1305.c
CommitLineData
3d5a7578 1/*
fbd2ece1 2 * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
3d5a7578
SL
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/* Dispatch functions for chacha20_poly1305 cipher */
11
12#include "cipher_chacha20_poly1305.h"
13#include "prov/implementations.h"
f99d3eed 14#include "prov/providercommon.h"
3d5a7578
SL
15#include "prov/providercommonerr.h"
16
17
18#define CHACHA20_POLY1305_KEYLEN CHACHA_KEY_SIZE
19#define CHACHA20_POLY1305_BLKLEN 1
20#define CHACHA20_POLY1305_MAX_IVLEN 12
21#define CHACHA20_POLY1305_MODE 0
22/* TODO(3.0) Figure out what flags are required */
23#define CHACHA20_POLY1305_FLAGS (EVP_CIPH_FLAG_AEAD_CIPHER \
24 | EVP_CIPH_ALWAYS_CALL_INIT \
25 | EVP_CIPH_CTRL_INIT \
26 | EVP_CIPH_CUSTOM_COPY \
27 | EVP_CIPH_FLAG_CUSTOM_CIPHER \
28 | EVP_CIPH_CUSTOM_IV \
29 | EVP_CIPH_CUSTOM_IV_LENGTH)
30
363b1e5d
DMSP
31static OSSL_FUNC_cipher_newctx_fn chacha20_poly1305_newctx;
32static OSSL_FUNC_cipher_freectx_fn chacha20_poly1305_freectx;
33static OSSL_FUNC_cipher_encrypt_init_fn chacha20_poly1305_einit;
34static OSSL_FUNC_cipher_decrypt_init_fn chacha20_poly1305_dinit;
35static OSSL_FUNC_cipher_get_params_fn chacha20_poly1305_get_params;
36static OSSL_FUNC_cipher_get_ctx_params_fn chacha20_poly1305_get_ctx_params;
37static OSSL_FUNC_cipher_set_ctx_params_fn chacha20_poly1305_set_ctx_params;
38static OSSL_FUNC_cipher_cipher_fn chacha20_poly1305_cipher;
39static OSSL_FUNC_cipher_final_fn chacha20_poly1305_final;
40static OSSL_FUNC_cipher_gettable_ctx_params_fn chacha20_poly1305_gettable_ctx_params;
592dcfd3
P
41#define chacha20_poly1305_settable_ctx_params ossl_cipher_aead_settable_ctx_params
42#define chacha20_poly1305_gettable_params ossl_cipher_generic_gettable_params
3d5a7578
SL
43#define chacha20_poly1305_update chacha20_poly1305_cipher
44
45static void *chacha20_poly1305_newctx(void *provctx)
46{
f99d3eed 47 PROV_CHACHA20_POLY1305_CTX *ctx;
3d5a7578 48
f99d3eed
P
49 if (!ossl_prov_is_running())
50 return NULL;
51
52 ctx = OPENSSL_zalloc(sizeof(*ctx));
3d5a7578 53 if (ctx != NULL) {
592dcfd3
P
54 ossl_cipher_generic_initkey(&ctx->base, CHACHA20_POLY1305_KEYLEN * 8,
55 CHACHA20_POLY1305_BLKLEN * 8,
56 CHACHA20_POLY1305_IVLEN * 8,
57 CHACHA20_POLY1305_MODE,
58 CHACHA20_POLY1305_FLAGS,
59 ossl_prov_cipher_hw_chacha20_poly1305(
60 CHACHA20_POLY1305_KEYLEN * 8),
61 NULL);
3d5a7578
SL
62 ctx->nonce_len = CHACHA20_POLY1305_IVLEN;
63 ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
64 chacha20_initctx(&ctx->chacha);
65 }
66 return ctx;
67}
68
69static void chacha20_poly1305_freectx(void *vctx)
70{
71 PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)vctx;
72
63ee6ec1 73 if (ctx != NULL) {
592dcfd3 74 ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
5e58733b 75 OPENSSL_clear_free(ctx, sizeof(*ctx));
63ee6ec1 76 }
3d5a7578
SL
77}
78
79static int chacha20_poly1305_get_params(OSSL_PARAM params[])
80{
592dcfd3
P
81 return ossl_cipher_generic_get_params(params, 0, CHACHA20_POLY1305_FLAGS,
82 CHACHA20_POLY1305_KEYLEN * 8,
83 CHACHA20_POLY1305_BLKLEN * 8,
84 CHACHA20_POLY1305_IVLEN * 8);
3d5a7578
SL
85}
86
87static int chacha20_poly1305_get_ctx_params(void *vctx, OSSL_PARAM params[])
88{
89 PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)vctx;
90 OSSL_PARAM *p;
91
92 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
93 if (p != NULL) {
94 if (!OSSL_PARAM_set_size_t(p, ctx->nonce_len)) {
95 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
96 return 0;
97 }
98 }
99 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
100 if (p != NULL && !OSSL_PARAM_set_size_t(p, CHACHA20_POLY1305_KEYLEN)) {
101 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
102 return 0;
103 }
104 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
105 if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tag_len)) {
106 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
107 return 0;
108 }
109 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
110 if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) {
111 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
112 return 0;
113 }
114
115 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
116 if (p != NULL) {
117 if (p->data_type != OSSL_PARAM_OCTET_STRING) {
118 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
119 return 0;
120 }
121 if (!ctx->base.enc) {
122 ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOTSET);
123 return 0;
124 }
125 if (p->data_size == 0 || p->data_size > POLY1305_BLOCK_SIZE) {
126 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAGLEN);
127 return 0;
128 }
129 memcpy(p->data, ctx->tag, p->data_size);
130 }
131
132 return 1;
133}
134
135static const OSSL_PARAM chacha20_poly1305_known_gettable_ctx_params[] = {
136 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
137 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
138 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
139 OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
140 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
141 OSSL_PARAM_END
142};
1017ab21
P
143static const OSSL_PARAM *chacha20_poly1305_gettable_ctx_params
144 (ossl_unused void *provctx)
3d5a7578
SL
145{
146 return chacha20_poly1305_known_gettable_ctx_params;
147}
148
149static int chacha20_poly1305_set_ctx_params(void *vctx,
150 const OSSL_PARAM params[])
151{
152 const OSSL_PARAM *p;
153 size_t len;
154 PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)vctx;
155 PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
156 (PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->base.hw;
157
158 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
159 if (p != NULL) {
160 if (!OSSL_PARAM_get_size_t(p, &len)) {
161 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
162 return 0;
163 }
164 if (len != CHACHA20_POLY1305_KEYLEN) {
165 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
166 return 0;
167 }
168 }
169 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN);
170 if (p != NULL) {
171 if (!OSSL_PARAM_get_size_t(p, &len)) {
172 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
173 return 0;
174 }
175 if (len == 0 || len > CHACHA20_POLY1305_MAX_IVLEN) {
176 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
177 return 0;
178 }
179 ctx->nonce_len = len;
180 }
181
182 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
183 if (p != NULL) {
184 if (p->data_type != OSSL_PARAM_OCTET_STRING) {
185 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
186 return 0;
187 }
188 if (p->data_size == 0 || p->data_size > POLY1305_BLOCK_SIZE) {
189 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAGLEN);
190 return 0;
191 }
192 if (p->data != NULL) {
193 if (ctx->base.enc) {
194 ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED);
195 return 0;
196 }
197 memcpy(ctx->tag, p->data, p->data_size);
198 }
199 ctx->tag_len = p->data_size;
200 }
201
202 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
203 if (p != NULL) {
204 if (p->data_type != OSSL_PARAM_OCTET_STRING) {
205 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
206 return 0;
207 }
208 len = hw->tls_init(&ctx->base, p->data, p->data_size);
209 if (len == 0) {
210 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA);
211 return 0;
212 }
213 ctx->tls_aad_pad_sz = len;
214 }
215
216 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED);
217 if (p != NULL) {
218 if (p->data_type != OSSL_PARAM_OCTET_STRING) {
219 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
220 return 0;
221 }
222 if (hw->tls_iv_set_fixed(&ctx->base, p->data, p->data_size) == 0) {
223 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
224 return 0;
225 }
226 }
227 /* ignore OSSL_CIPHER_PARAM_AEAD_MAC_KEY */
228 return 1;
229}
230
231static int chacha20_poly1305_einit(void *vctx, const unsigned char *key,
232 size_t keylen, const unsigned char *iv,
233 size_t ivlen)
234{
235 int ret;
236
f99d3eed 237 /* The generic function checks for ossl_prov_is_running() */
592dcfd3 238 ret = ossl_cipher_generic_einit(vctx, key, keylen, iv, ivlen);
3d5a7578
SL
239 if (ret && iv != NULL) {
240 PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
241 PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
242 (PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->hw;
243
244 hw->initiv(ctx);
245 }
246 return ret;
247}
248
249static int chacha20_poly1305_dinit(void *vctx, const unsigned char *key,
250 size_t keylen, const unsigned char *iv,
251 size_t ivlen)
252{
253 int ret;
254
f99d3eed 255 /* The generic function checks for ossl_prov_is_running() */
592dcfd3 256 ret = ossl_cipher_generic_dinit(vctx, key, keylen, iv, ivlen);
3d5a7578
SL
257 if (ret && iv != NULL) {
258 PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
259 PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
260 (PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->hw;
261
262 hw->initiv(ctx);
263 }
264 return ret;
265}
266
267static int chacha20_poly1305_cipher(void *vctx, unsigned char *out,
268 size_t *outl, size_t outsize,
269 const unsigned char *in, size_t inl)
270{
271 PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
272 PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
273 (PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->hw;
274
f99d3eed
P
275 if (!ossl_prov_is_running())
276 return 0;
277
4b9c750b
MC
278 if (inl == 0) {
279 *outl = 0;
280 return 1;
281 }
282
3d5a7578
SL
283 if (outsize < inl) {
284 ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
285 return 0;
286 }
287
288 if (!hw->aead_cipher(ctx, out, outl, in, inl))
289 return 0;
290
3d5a7578
SL
291 return 1;
292}
293
294static int chacha20_poly1305_final(void *vctx, unsigned char *out, size_t *outl,
295 size_t outsize)
296{
297 PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
298 PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
299 (PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->hw;
300
f99d3eed
P
301 if (!ossl_prov_is_running())
302 return 0;
303
3d5a7578
SL
304 if (hw->aead_cipher(ctx, out, outl, NULL, 0) <= 0)
305 return 0;
306
307 *outl = 0;
308 return 1;
309}
310
1be63951
P
311/* ossl_chacha20_ossl_poly1305_functions */
312const OSSL_DISPATCH ossl_chacha20_ossl_poly1305_functions[] = {
3d5a7578
SL
313 { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))chacha20_poly1305_newctx },
314 { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))chacha20_poly1305_freectx },
315 { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))chacha20_poly1305_einit },
316 { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))chacha20_poly1305_dinit },
317 { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))chacha20_poly1305_update },
318 { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))chacha20_poly1305_final },
319 { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))chacha20_poly1305_cipher },
320 { OSSL_FUNC_CIPHER_GET_PARAMS,
321 (void (*)(void))chacha20_poly1305_get_params },
322 { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,
323 (void (*)(void))chacha20_poly1305_gettable_params },
324 { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,
325 (void (*)(void))chacha20_poly1305_get_ctx_params },
326 { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
327 (void (*)(void))chacha20_poly1305_gettable_ctx_params },
328 { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,
329 (void (*)(void))chacha20_poly1305_set_ctx_params },
330 { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
331 (void (*)(void))chacha20_poly1305_settable_ctx_params },
332 { 0, NULL }
333};
334