1*b077aed3SPierre Pronchery /*
2*b077aed3SPierre Pronchery  * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
3*b077aed3SPierre Pronchery  *
4*b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7*b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8*b077aed3SPierre Pronchery  */
9*b077aed3SPierre Pronchery 
10*b077aed3SPierre Pronchery /*
11*b077aed3SPierre Pronchery  * AES low level APIs are deprecated for public use, but still ok for internal
12*b077aed3SPierre Pronchery  * use where we're using them to implement the higher level EVP interface, as is
13*b077aed3SPierre Pronchery  * the case here.
14*b077aed3SPierre Pronchery  */
15*b077aed3SPierre Pronchery #include "internal/deprecated.h"
16*b077aed3SPierre Pronchery 
17*b077aed3SPierre Pronchery #include <openssl/proverr.h>
18*b077aed3SPierre Pronchery #include "cipher_aes_ocb.h"
19*b077aed3SPierre Pronchery #include "prov/providercommon.h"
20*b077aed3SPierre Pronchery #include "prov/ciphercommon_aead.h"
21*b077aed3SPierre Pronchery #include "prov/implementations.h"
22*b077aed3SPierre Pronchery 
23*b077aed3SPierre Pronchery #define AES_OCB_FLAGS AEAD_FLAGS
24*b077aed3SPierre Pronchery 
25*b077aed3SPierre Pronchery #define OCB_DEFAULT_TAG_LEN 16
26*b077aed3SPierre Pronchery #define OCB_DEFAULT_IV_LEN  12
27*b077aed3SPierre Pronchery #define OCB_MIN_IV_LEN      1
28*b077aed3SPierre Pronchery #define OCB_MAX_IV_LEN      15
29*b077aed3SPierre Pronchery 
30*b077aed3SPierre Pronchery PROV_CIPHER_FUNC(int, ocb_cipher, (PROV_AES_OCB_CTX *ctx,
31*b077aed3SPierre Pronchery                                    const unsigned char *in, unsigned char *out,
32*b077aed3SPierre Pronchery                                    size_t nextblock));
33*b077aed3SPierre Pronchery /* forward declarations */
34*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_encrypt_init_fn aes_ocb_einit;
35*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_decrypt_init_fn aes_ocb_dinit;
36*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_update_fn aes_ocb_block_update;
37*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_final_fn aes_ocb_block_final;
38*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_cipher_fn aes_ocb_cipher;
39*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_freectx_fn aes_ocb_freectx;
40*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_dupctx_fn aes_ocb_dupctx;
41*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_get_ctx_params_fn aes_ocb_get_ctx_params;
42*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_set_ctx_params_fn aes_ocb_set_ctx_params;
43*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_gettable_ctx_params_fn cipher_ocb_gettable_ctx_params;
44*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_settable_ctx_params_fn cipher_ocb_settable_ctx_params;
45*b077aed3SPierre Pronchery 
46*b077aed3SPierre Pronchery /*
47*b077aed3SPierre Pronchery  * The following methods could be moved into PROV_AES_OCB_HW if
48*b077aed3SPierre Pronchery  * multiple hardware implementations are ever needed.
49*b077aed3SPierre Pronchery  */
50*b077aed3SPierre Pronchery static ossl_inline int aes_generic_ocb_setiv(PROV_AES_OCB_CTX *ctx,
51*b077aed3SPierre Pronchery                                              const unsigned char *iv,
52*b077aed3SPierre Pronchery                                              size_t ivlen, size_t taglen)
53*b077aed3SPierre Pronchery {
54*b077aed3SPierre Pronchery     return (CRYPTO_ocb128_setiv(&ctx->ocb, iv, ivlen, taglen) == 1);
55*b077aed3SPierre Pronchery }
56*b077aed3SPierre Pronchery 
57*b077aed3SPierre Pronchery static ossl_inline int aes_generic_ocb_setaad(PROV_AES_OCB_CTX *ctx,
58*b077aed3SPierre Pronchery                                               const unsigned char *aad,
59*b077aed3SPierre Pronchery                                               size_t alen)
60*b077aed3SPierre Pronchery {
61*b077aed3SPierre Pronchery     return CRYPTO_ocb128_aad(&ctx->ocb, aad, alen) == 1;
62*b077aed3SPierre Pronchery }
63*b077aed3SPierre Pronchery 
64*b077aed3SPierre Pronchery static ossl_inline int aes_generic_ocb_gettag(PROV_AES_OCB_CTX *ctx,
65*b077aed3SPierre Pronchery                                               unsigned char *tag, size_t tlen)
66*b077aed3SPierre Pronchery {
67*b077aed3SPierre Pronchery     return CRYPTO_ocb128_tag(&ctx->ocb, tag, tlen) > 0;
68*b077aed3SPierre Pronchery }
69*b077aed3SPierre Pronchery 
70*b077aed3SPierre Pronchery static ossl_inline int aes_generic_ocb_final(PROV_AES_OCB_CTX *ctx)
71*b077aed3SPierre Pronchery {
72*b077aed3SPierre Pronchery     return (CRYPTO_ocb128_finish(&ctx->ocb, ctx->tag, ctx->taglen) == 0);
73*b077aed3SPierre Pronchery }
74*b077aed3SPierre Pronchery 
75*b077aed3SPierre Pronchery static ossl_inline void aes_generic_ocb_cleanup(PROV_AES_OCB_CTX *ctx)
76*b077aed3SPierre Pronchery {
77*b077aed3SPierre Pronchery     CRYPTO_ocb128_cleanup(&ctx->ocb);
78*b077aed3SPierre Pronchery }
79*b077aed3SPierre Pronchery 
80*b077aed3SPierre Pronchery static ossl_inline int aes_generic_ocb_cipher(PROV_AES_OCB_CTX *ctx,
81*b077aed3SPierre Pronchery                                               const unsigned char *in,
82*b077aed3SPierre Pronchery                                               unsigned char *out, size_t len)
83*b077aed3SPierre Pronchery {
84*b077aed3SPierre Pronchery     if (ctx->base.enc) {
85*b077aed3SPierre Pronchery         if (!CRYPTO_ocb128_encrypt(&ctx->ocb, in, out, len))
86*b077aed3SPierre Pronchery             return 0;
87*b077aed3SPierre Pronchery     } else {
88*b077aed3SPierre Pronchery         if (!CRYPTO_ocb128_decrypt(&ctx->ocb, in, out, len))
89*b077aed3SPierre Pronchery             return 0;
90*b077aed3SPierre Pronchery     }
91*b077aed3SPierre Pronchery     return 1;
92*b077aed3SPierre Pronchery }
93*b077aed3SPierre Pronchery 
94*b077aed3SPierre Pronchery static ossl_inline int aes_generic_ocb_copy_ctx(PROV_AES_OCB_CTX *dst,
95*b077aed3SPierre Pronchery                                                 PROV_AES_OCB_CTX *src)
96*b077aed3SPierre Pronchery {
97*b077aed3SPierre Pronchery     return CRYPTO_ocb128_copy_ctx(&dst->ocb, &src->ocb,
98*b077aed3SPierre Pronchery                                   &dst->ksenc.ks, &dst->ksdec.ks);
99*b077aed3SPierre Pronchery }
100*b077aed3SPierre Pronchery 
101*b077aed3SPierre Pronchery /*-
102*b077aed3SPierre Pronchery  * Provider dispatch functions
103*b077aed3SPierre Pronchery  */
104*b077aed3SPierre Pronchery static int aes_ocb_init(void *vctx, const unsigned char *key, size_t keylen,
105*b077aed3SPierre Pronchery                         const unsigned char *iv, size_t ivlen,
106*b077aed3SPierre Pronchery                         const OSSL_PARAM params[], int enc)
107*b077aed3SPierre Pronchery {
108*b077aed3SPierre Pronchery     PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
109*b077aed3SPierre Pronchery 
110*b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
111*b077aed3SPierre Pronchery         return 0;
112*b077aed3SPierre Pronchery 
113*b077aed3SPierre Pronchery     ctx->aad_buf_len = 0;
114*b077aed3SPierre Pronchery     ctx->data_buf_len = 0;
115*b077aed3SPierre Pronchery     ctx->base.enc = enc;
116*b077aed3SPierre Pronchery 
117*b077aed3SPierre Pronchery     if (iv != NULL) {
118*b077aed3SPierre Pronchery         if (ivlen != ctx->base.ivlen) {
119*b077aed3SPierre Pronchery             /* IV len must be 1 to 15 */
120*b077aed3SPierre Pronchery             if (ivlen < OCB_MIN_IV_LEN || ivlen > OCB_MAX_IV_LEN) {
121*b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
122*b077aed3SPierre Pronchery                 return 0;
123*b077aed3SPierre Pronchery             }
124*b077aed3SPierre Pronchery             ctx->base.ivlen = ivlen;
125*b077aed3SPierre Pronchery         }
126*b077aed3SPierre Pronchery         if (!ossl_cipher_generic_initiv(&ctx->base, iv, ivlen))
127*b077aed3SPierre Pronchery             return 0;
128*b077aed3SPierre Pronchery         ctx->iv_state = IV_STATE_BUFFERED;
129*b077aed3SPierre Pronchery     }
130*b077aed3SPierre Pronchery     if (key != NULL) {
131*b077aed3SPierre Pronchery         if (keylen != ctx->base.keylen) {
132*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
133*b077aed3SPierre Pronchery             return 0;
134*b077aed3SPierre Pronchery         }
135*b077aed3SPierre Pronchery         if (!ctx->base.hw->init(&ctx->base, key, keylen))
136*b077aed3SPierre Pronchery             return 0;
137*b077aed3SPierre Pronchery     }
138*b077aed3SPierre Pronchery     return aes_ocb_set_ctx_params(ctx, params);
139*b077aed3SPierre Pronchery }
140*b077aed3SPierre Pronchery 
141*b077aed3SPierre Pronchery static int aes_ocb_einit(void *vctx, const unsigned char *key, size_t keylen,
142*b077aed3SPierre Pronchery                          const unsigned char *iv, size_t ivlen,
143*b077aed3SPierre Pronchery                          const OSSL_PARAM params[])
144*b077aed3SPierre Pronchery {
145*b077aed3SPierre Pronchery     return aes_ocb_init(vctx, key, keylen, iv, ivlen, params, 1);
146*b077aed3SPierre Pronchery }
147*b077aed3SPierre Pronchery 
148*b077aed3SPierre Pronchery static int aes_ocb_dinit(void *vctx, const unsigned char *key, size_t keylen,
149*b077aed3SPierre Pronchery                          const unsigned char *iv, size_t ivlen,
150*b077aed3SPierre Pronchery                          const OSSL_PARAM params[])
151*b077aed3SPierre Pronchery {
152*b077aed3SPierre Pronchery     return aes_ocb_init(vctx, key, keylen, iv, ivlen, params, 0);
153*b077aed3SPierre Pronchery }
154*b077aed3SPierre Pronchery 
155*b077aed3SPierre Pronchery /*
156*b077aed3SPierre Pronchery  * Because of the way OCB works, both the AAD and data are buffered in the
157*b077aed3SPierre Pronchery  * same way. Only the last block can be a partial block.
158*b077aed3SPierre Pronchery  */
159*b077aed3SPierre Pronchery static int aes_ocb_block_update_internal(PROV_AES_OCB_CTX *ctx,
160*b077aed3SPierre Pronchery                                          unsigned char *buf, size_t *bufsz,
161*b077aed3SPierre Pronchery                                          unsigned char *out, size_t *outl,
162*b077aed3SPierre Pronchery                                          size_t outsize, const unsigned char *in,
163*b077aed3SPierre Pronchery                                          size_t inl, OSSL_ocb_cipher_fn ciph)
164*b077aed3SPierre Pronchery {
165*b077aed3SPierre Pronchery     size_t nextblocks;
166*b077aed3SPierre Pronchery     size_t outlint = 0;
167*b077aed3SPierre Pronchery 
168*b077aed3SPierre Pronchery     if (*bufsz != 0)
169*b077aed3SPierre Pronchery         nextblocks = ossl_cipher_fillblock(buf, bufsz, AES_BLOCK_SIZE, &in, &inl);
170*b077aed3SPierre Pronchery     else
171*b077aed3SPierre Pronchery         nextblocks = inl & ~(AES_BLOCK_SIZE-1);
172*b077aed3SPierre Pronchery 
173*b077aed3SPierre Pronchery     if (*bufsz == AES_BLOCK_SIZE) {
174*b077aed3SPierre Pronchery         if (outsize < AES_BLOCK_SIZE) {
175*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
176*b077aed3SPierre Pronchery             return 0;
177*b077aed3SPierre Pronchery         }
178*b077aed3SPierre Pronchery         if (!ciph(ctx, buf, out, AES_BLOCK_SIZE)) {
179*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
180*b077aed3SPierre Pronchery             return 0;
181*b077aed3SPierre Pronchery         }
182*b077aed3SPierre Pronchery         *bufsz = 0;
183*b077aed3SPierre Pronchery         outlint = AES_BLOCK_SIZE;
184*b077aed3SPierre Pronchery         if (out != NULL)
185*b077aed3SPierre Pronchery             out += AES_BLOCK_SIZE;
186*b077aed3SPierre Pronchery     }
187*b077aed3SPierre Pronchery     if (nextblocks > 0) {
188*b077aed3SPierre Pronchery         outlint += nextblocks;
189*b077aed3SPierre Pronchery         if (outsize < outlint) {
190*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
191*b077aed3SPierre Pronchery             return 0;
192*b077aed3SPierre Pronchery         }
193*b077aed3SPierre Pronchery         if (!ciph(ctx, in, out, nextblocks)) {
194*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
195*b077aed3SPierre Pronchery             return 0;
196*b077aed3SPierre Pronchery         }
197*b077aed3SPierre Pronchery         in += nextblocks;
198*b077aed3SPierre Pronchery         inl -= nextblocks;
199*b077aed3SPierre Pronchery     }
200*b077aed3SPierre Pronchery     if (inl != 0
201*b077aed3SPierre Pronchery         && !ossl_cipher_trailingdata(buf, bufsz, AES_BLOCK_SIZE, &in, &inl)) {
202*b077aed3SPierre Pronchery         /* PROVerr already called */
203*b077aed3SPierre Pronchery         return 0;
204*b077aed3SPierre Pronchery     }
205*b077aed3SPierre Pronchery 
206*b077aed3SPierre Pronchery     *outl = outlint;
207*b077aed3SPierre Pronchery     return inl == 0;
208*b077aed3SPierre Pronchery }
209*b077aed3SPierre Pronchery 
210*b077aed3SPierre Pronchery /* A wrapper function that has the same signature as cipher */
211*b077aed3SPierre Pronchery static int cipher_updateaad(PROV_AES_OCB_CTX *ctx, const unsigned char *in,
212*b077aed3SPierre Pronchery                             unsigned char *out, size_t len)
213*b077aed3SPierre Pronchery {
214*b077aed3SPierre Pronchery     return aes_generic_ocb_setaad(ctx, in, len);
215*b077aed3SPierre Pronchery }
216*b077aed3SPierre Pronchery 
217*b077aed3SPierre Pronchery static int update_iv(PROV_AES_OCB_CTX *ctx)
218*b077aed3SPierre Pronchery {
219*b077aed3SPierre Pronchery     if (ctx->iv_state == IV_STATE_FINISHED
220*b077aed3SPierre Pronchery         || ctx->iv_state == IV_STATE_UNINITIALISED)
221*b077aed3SPierre Pronchery         return 0;
222*b077aed3SPierre Pronchery     if (ctx->iv_state == IV_STATE_BUFFERED) {
223*b077aed3SPierre Pronchery         if (!aes_generic_ocb_setiv(ctx, ctx->base.iv, ctx->base.ivlen,
224*b077aed3SPierre Pronchery                                    ctx->taglen))
225*b077aed3SPierre Pronchery             return 0;
226*b077aed3SPierre Pronchery         ctx->iv_state = IV_STATE_COPIED;
227*b077aed3SPierre Pronchery     }
228*b077aed3SPierre Pronchery     return 1;
229*b077aed3SPierre Pronchery }
230*b077aed3SPierre Pronchery 
231*b077aed3SPierre Pronchery static int aes_ocb_block_update(void *vctx, unsigned char *out, size_t *outl,
232*b077aed3SPierre Pronchery                                 size_t outsize, const unsigned char *in,
233*b077aed3SPierre Pronchery                                 size_t inl)
234*b077aed3SPierre Pronchery {
235*b077aed3SPierre Pronchery     PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
236*b077aed3SPierre Pronchery     unsigned char *buf;
237*b077aed3SPierre Pronchery     size_t *buflen;
238*b077aed3SPierre Pronchery     OSSL_ocb_cipher_fn fn;
239*b077aed3SPierre Pronchery 
240*b077aed3SPierre Pronchery     if (!ctx->key_set || !update_iv(ctx))
241*b077aed3SPierre Pronchery         return 0;
242*b077aed3SPierre Pronchery 
243*b077aed3SPierre Pronchery     if (inl == 0) {
244*b077aed3SPierre Pronchery         *outl = 0;
245*b077aed3SPierre Pronchery         return 1;
246*b077aed3SPierre Pronchery     }
247*b077aed3SPierre Pronchery 
248*b077aed3SPierre Pronchery     /* Are we dealing with AAD or normal data here? */
249*b077aed3SPierre Pronchery     if (out == NULL) {
250*b077aed3SPierre Pronchery         buf = ctx->aad_buf;
251*b077aed3SPierre Pronchery         buflen = &ctx->aad_buf_len;
252*b077aed3SPierre Pronchery         fn = cipher_updateaad;
253*b077aed3SPierre Pronchery     } else {
254*b077aed3SPierre Pronchery         buf = ctx->data_buf;
255*b077aed3SPierre Pronchery         buflen = &ctx->data_buf_len;
256*b077aed3SPierre Pronchery         fn = aes_generic_ocb_cipher;
257*b077aed3SPierre Pronchery     }
258*b077aed3SPierre Pronchery     return aes_ocb_block_update_internal(ctx, buf, buflen, out, outl, outsize,
259*b077aed3SPierre Pronchery                                          in, inl, fn);
260*b077aed3SPierre Pronchery }
261*b077aed3SPierre Pronchery 
262*b077aed3SPierre Pronchery static int aes_ocb_block_final(void *vctx, unsigned char *out, size_t *outl,
263*b077aed3SPierre Pronchery                                size_t outsize)
264*b077aed3SPierre Pronchery {
265*b077aed3SPierre Pronchery     PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
266*b077aed3SPierre Pronchery 
267*b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
268*b077aed3SPierre Pronchery         return 0;
269*b077aed3SPierre Pronchery 
270*b077aed3SPierre Pronchery     /* If no block_update has run then the iv still needs to be set */
271*b077aed3SPierre Pronchery     if (!ctx->key_set || !update_iv(ctx))
272*b077aed3SPierre Pronchery         return 0;
273*b077aed3SPierre Pronchery 
274*b077aed3SPierre Pronchery     /*
275*b077aed3SPierre Pronchery      * Empty the buffer of any partial block that we might have been provided,
276*b077aed3SPierre Pronchery      * both for data and AAD
277*b077aed3SPierre Pronchery      */
278*b077aed3SPierre Pronchery     *outl = 0;
279*b077aed3SPierre Pronchery     if (ctx->data_buf_len > 0) {
280*b077aed3SPierre Pronchery         if (!aes_generic_ocb_cipher(ctx, ctx->data_buf, out, ctx->data_buf_len))
281*b077aed3SPierre Pronchery             return 0;
282*b077aed3SPierre Pronchery         *outl = ctx->data_buf_len;
283*b077aed3SPierre Pronchery         ctx->data_buf_len = 0;
284*b077aed3SPierre Pronchery     }
285*b077aed3SPierre Pronchery     if (ctx->aad_buf_len > 0) {
286*b077aed3SPierre Pronchery         if (!aes_generic_ocb_setaad(ctx, ctx->aad_buf, ctx->aad_buf_len))
287*b077aed3SPierre Pronchery             return 0;
288*b077aed3SPierre Pronchery         ctx->aad_buf_len = 0;
289*b077aed3SPierre Pronchery     }
290*b077aed3SPierre Pronchery     if (ctx->base.enc) {
291*b077aed3SPierre Pronchery         /* If encrypting then just get the tag */
292*b077aed3SPierre Pronchery         if (!aes_generic_ocb_gettag(ctx, ctx->tag, ctx->taglen))
293*b077aed3SPierre Pronchery             return 0;
294*b077aed3SPierre Pronchery     } else {
295*b077aed3SPierre Pronchery         /* If decrypting then verify */
296*b077aed3SPierre Pronchery         if (ctx->taglen == 0)
297*b077aed3SPierre Pronchery             return 0;
298*b077aed3SPierre Pronchery         if (!aes_generic_ocb_final(ctx))
299*b077aed3SPierre Pronchery             return 0;
300*b077aed3SPierre Pronchery     }
301*b077aed3SPierre Pronchery     /* Don't reuse the IV */
302*b077aed3SPierre Pronchery     ctx->iv_state = IV_STATE_FINISHED;
303*b077aed3SPierre Pronchery     return 1;
304*b077aed3SPierre Pronchery }
305*b077aed3SPierre Pronchery 
306*b077aed3SPierre Pronchery static void *aes_ocb_newctx(void *provctx, size_t kbits, size_t blkbits,
307*b077aed3SPierre Pronchery                             size_t ivbits, unsigned int mode, uint64_t flags)
308*b077aed3SPierre Pronchery {
309*b077aed3SPierre Pronchery     PROV_AES_OCB_CTX *ctx;
310*b077aed3SPierre Pronchery 
311*b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
312*b077aed3SPierre Pronchery         return NULL;
313*b077aed3SPierre Pronchery 
314*b077aed3SPierre Pronchery     ctx = OPENSSL_zalloc(sizeof(*ctx));
315*b077aed3SPierre Pronchery     if (ctx != NULL) {
316*b077aed3SPierre Pronchery         ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
317*b077aed3SPierre Pronchery                                     ossl_prov_cipher_hw_aes_ocb(kbits), NULL);
318*b077aed3SPierre Pronchery         ctx->taglen = OCB_DEFAULT_TAG_LEN;
319*b077aed3SPierre Pronchery     }
320*b077aed3SPierre Pronchery     return ctx;
321*b077aed3SPierre Pronchery }
322*b077aed3SPierre Pronchery 
323*b077aed3SPierre Pronchery static void aes_ocb_freectx(void *vctx)
324*b077aed3SPierre Pronchery {
325*b077aed3SPierre Pronchery     PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
326*b077aed3SPierre Pronchery 
327*b077aed3SPierre Pronchery     if (ctx != NULL) {
328*b077aed3SPierre Pronchery         aes_generic_ocb_cleanup(ctx);
329*b077aed3SPierre Pronchery         ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
330*b077aed3SPierre Pronchery         OPENSSL_clear_free(ctx,  sizeof(*ctx));
331*b077aed3SPierre Pronchery     }
332*b077aed3SPierre Pronchery }
333*b077aed3SPierre Pronchery 
334*b077aed3SPierre Pronchery static void *aes_ocb_dupctx(void *vctx)
335*b077aed3SPierre Pronchery {
336*b077aed3SPierre Pronchery     PROV_AES_OCB_CTX *in = (PROV_AES_OCB_CTX *)vctx;
337*b077aed3SPierre Pronchery     PROV_AES_OCB_CTX *ret;
338*b077aed3SPierre Pronchery 
339*b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
340*b077aed3SPierre Pronchery         return NULL;
341*b077aed3SPierre Pronchery 
342*b077aed3SPierre Pronchery     ret = OPENSSL_malloc(sizeof(*ret));
343*b077aed3SPierre Pronchery     if (ret == NULL) {
344*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
345*b077aed3SPierre Pronchery         return NULL;
346*b077aed3SPierre Pronchery     }
347*b077aed3SPierre Pronchery     *ret = *in;
348*b077aed3SPierre Pronchery     if (!aes_generic_ocb_copy_ctx(ret, in)) {
349*b077aed3SPierre Pronchery         OPENSSL_free(ret);
350*b077aed3SPierre Pronchery         ret = NULL;
351*b077aed3SPierre Pronchery     }
352*b077aed3SPierre Pronchery     return ret;
353*b077aed3SPierre Pronchery }
354*b077aed3SPierre Pronchery 
355*b077aed3SPierre Pronchery static int aes_ocb_set_ctx_params(void *vctx, const OSSL_PARAM params[])
356*b077aed3SPierre Pronchery {
357*b077aed3SPierre Pronchery     PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
358*b077aed3SPierre Pronchery     const OSSL_PARAM *p;
359*b077aed3SPierre Pronchery     size_t sz;
360*b077aed3SPierre Pronchery 
361*b077aed3SPierre Pronchery     if (params == NULL)
362*b077aed3SPierre Pronchery         return 1;
363*b077aed3SPierre Pronchery 
364*b077aed3SPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
365*b077aed3SPierre Pronchery     if (p != NULL) {
366*b077aed3SPierre Pronchery         if (p->data_type != OSSL_PARAM_OCTET_STRING) {
367*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
368*b077aed3SPierre Pronchery             return 0;
369*b077aed3SPierre Pronchery         }
370*b077aed3SPierre Pronchery         if (p->data == NULL) {
371*b077aed3SPierre Pronchery             /* Tag len must be 0 to 16 */
372*b077aed3SPierre Pronchery             if (p->data_size > OCB_MAX_TAG_LEN)
373*b077aed3SPierre Pronchery                 return 0;
374*b077aed3SPierre Pronchery             ctx->taglen = p->data_size;
375*b077aed3SPierre Pronchery         } else {
376*b077aed3SPierre Pronchery             if (p->data_size != ctx->taglen || ctx->base.enc)
377*b077aed3SPierre Pronchery                 return 0;
378*b077aed3SPierre Pronchery             memcpy(ctx->tag, p->data, p->data_size);
379*b077aed3SPierre Pronchery         }
380*b077aed3SPierre Pronchery      }
381*b077aed3SPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN);
382*b077aed3SPierre Pronchery     if (p != NULL) {
383*b077aed3SPierre Pronchery         if (!OSSL_PARAM_get_size_t(p, &sz)) {
384*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
385*b077aed3SPierre Pronchery             return 0;
386*b077aed3SPierre Pronchery         }
387*b077aed3SPierre Pronchery         /* IV len must be 1 to 15 */
388*b077aed3SPierre Pronchery         if (sz < OCB_MIN_IV_LEN || sz > OCB_MAX_IV_LEN)
389*b077aed3SPierre Pronchery             return 0;
390*b077aed3SPierre Pronchery         ctx->base.ivlen = sz;
391*b077aed3SPierre Pronchery     }
392*b077aed3SPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
393*b077aed3SPierre Pronchery     if (p != NULL) {
394*b077aed3SPierre Pronchery         size_t keylen;
395*b077aed3SPierre Pronchery 
396*b077aed3SPierre Pronchery         if (!OSSL_PARAM_get_size_t(p, &keylen)) {
397*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
398*b077aed3SPierre Pronchery             return 0;
399*b077aed3SPierre Pronchery         }
400*b077aed3SPierre Pronchery         if (ctx->base.keylen != keylen) {
401*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
402*b077aed3SPierre Pronchery             return 0;
403*b077aed3SPierre Pronchery         }
404*b077aed3SPierre Pronchery     }
405*b077aed3SPierre Pronchery     return 1;
406*b077aed3SPierre Pronchery }
407*b077aed3SPierre Pronchery 
408*b077aed3SPierre Pronchery static int aes_ocb_get_ctx_params(void *vctx, OSSL_PARAM params[])
409*b077aed3SPierre Pronchery {
410*b077aed3SPierre Pronchery     PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
411*b077aed3SPierre Pronchery     OSSL_PARAM *p;
412*b077aed3SPierre Pronchery 
413*b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
414*b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.ivlen)) {
415*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
416*b077aed3SPierre Pronchery         return 0;
417*b077aed3SPierre Pronchery     }
418*b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
419*b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.keylen)) {
420*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
421*b077aed3SPierre Pronchery         return 0;
422*b077aed3SPierre Pronchery     }
423*b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
424*b077aed3SPierre Pronchery     if (p != NULL) {
425*b077aed3SPierre Pronchery         if (!OSSL_PARAM_set_size_t(p, ctx->taglen)) {
426*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
427*b077aed3SPierre Pronchery             return 0;
428*b077aed3SPierre Pronchery         }
429*b077aed3SPierre Pronchery     }
430*b077aed3SPierre Pronchery 
431*b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
432*b077aed3SPierre Pronchery     if (p != NULL) {
433*b077aed3SPierre Pronchery         if (ctx->base.ivlen > p->data_size) {
434*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
435*b077aed3SPierre Pronchery             return 0;
436*b077aed3SPierre Pronchery         }
437*b077aed3SPierre Pronchery         if (!OSSL_PARAM_set_octet_string(p, ctx->base.oiv, ctx->base.ivlen)
438*b077aed3SPierre Pronchery             && !OSSL_PARAM_set_octet_ptr(p, &ctx->base.oiv, ctx->base.ivlen)) {
439*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
440*b077aed3SPierre Pronchery             return 0;
441*b077aed3SPierre Pronchery         }
442*b077aed3SPierre Pronchery     }
443*b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV);
444*b077aed3SPierre Pronchery     if (p != NULL) {
445*b077aed3SPierre Pronchery         if (ctx->base.ivlen > p->data_size) {
446*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
447*b077aed3SPierre Pronchery             return 0;
448*b077aed3SPierre Pronchery         }
449*b077aed3SPierre Pronchery         if (!OSSL_PARAM_set_octet_string(p, ctx->base.iv, ctx->base.ivlen)
450*b077aed3SPierre Pronchery             && !OSSL_PARAM_set_octet_ptr(p, &ctx->base.iv, ctx->base.ivlen)) {
451*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
452*b077aed3SPierre Pronchery             return 0;
453*b077aed3SPierre Pronchery         }
454*b077aed3SPierre Pronchery     }
455*b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
456*b077aed3SPierre Pronchery     if (p != NULL) {
457*b077aed3SPierre Pronchery         if (p->data_type != OSSL_PARAM_OCTET_STRING) {
458*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
459*b077aed3SPierre Pronchery             return 0;
460*b077aed3SPierre Pronchery         }
461*b077aed3SPierre Pronchery         if (!ctx->base.enc || p->data_size != ctx->taglen) {
462*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
463*b077aed3SPierre Pronchery             return 0;
464*b077aed3SPierre Pronchery         }
465*b077aed3SPierre Pronchery         memcpy(p->data, ctx->tag, ctx->taglen);
466*b077aed3SPierre Pronchery     }
467*b077aed3SPierre Pronchery     return 1;
468*b077aed3SPierre Pronchery }
469*b077aed3SPierre Pronchery 
470*b077aed3SPierre Pronchery static const OSSL_PARAM cipher_ocb_known_gettable_ctx_params[] = {
471*b077aed3SPierre Pronchery     OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
472*b077aed3SPierre Pronchery     OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
473*b077aed3SPierre Pronchery     OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
474*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
475*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_UPDATED_IV, NULL, 0),
476*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
477*b077aed3SPierre Pronchery     OSSL_PARAM_END
478*b077aed3SPierre Pronchery };
479*b077aed3SPierre Pronchery static const OSSL_PARAM *cipher_ocb_gettable_ctx_params(ossl_unused void *cctx,
480*b077aed3SPierre Pronchery                                                         ossl_unused void *p_ctx)
481*b077aed3SPierre Pronchery {
482*b077aed3SPierre Pronchery     return cipher_ocb_known_gettable_ctx_params;
483*b077aed3SPierre Pronchery }
484*b077aed3SPierre Pronchery 
485*b077aed3SPierre Pronchery static const OSSL_PARAM cipher_ocb_known_settable_ctx_params[] = {
486*b077aed3SPierre Pronchery     OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
487*b077aed3SPierre Pronchery     OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL),
488*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
489*b077aed3SPierre Pronchery     OSSL_PARAM_END
490*b077aed3SPierre Pronchery };
491*b077aed3SPierre Pronchery static const OSSL_PARAM *cipher_ocb_settable_ctx_params(ossl_unused void *cctx,
492*b077aed3SPierre Pronchery                                                         ossl_unused void *p_ctx)
493*b077aed3SPierre Pronchery {
494*b077aed3SPierre Pronchery     return cipher_ocb_known_settable_ctx_params;
495*b077aed3SPierre Pronchery }
496*b077aed3SPierre Pronchery 
497*b077aed3SPierre Pronchery static int aes_ocb_cipher(void *vctx, unsigned char *out, size_t *outl,
498*b077aed3SPierre Pronchery                           size_t outsize, const unsigned char *in, size_t inl)
499*b077aed3SPierre Pronchery {
500*b077aed3SPierre Pronchery     PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
501*b077aed3SPierre Pronchery 
502*b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
503*b077aed3SPierre Pronchery         return 0;
504*b077aed3SPierre Pronchery 
505*b077aed3SPierre Pronchery     if (outsize < inl) {
506*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
507*b077aed3SPierre Pronchery         return 0;
508*b077aed3SPierre Pronchery     }
509*b077aed3SPierre Pronchery 
510*b077aed3SPierre Pronchery     if (!aes_generic_ocb_cipher(ctx, in, out, inl)) {
511*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
512*b077aed3SPierre Pronchery         return 0;
513*b077aed3SPierre Pronchery     }
514*b077aed3SPierre Pronchery 
515*b077aed3SPierre Pronchery     *outl = inl;
516*b077aed3SPierre Pronchery     return 1;
517*b077aed3SPierre Pronchery }
518*b077aed3SPierre Pronchery 
519*b077aed3SPierre Pronchery #define IMPLEMENT_cipher(mode, UCMODE, flags, kbits, blkbits, ivbits)          \
520*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##mode##_get_params;       \
521*b077aed3SPierre Pronchery static int aes_##kbits##_##mode##_get_params(OSSL_PARAM params[])              \
522*b077aed3SPierre Pronchery {                                                                              \
523*b077aed3SPierre Pronchery     return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,    \
524*b077aed3SPierre Pronchery                                           flags, kbits, blkbits, ivbits);      \
525*b077aed3SPierre Pronchery }                                                                              \
526*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_newctx_fn aes_##kbits##_##mode##_newctx;               \
527*b077aed3SPierre Pronchery static void *aes_##kbits##_##mode##_newctx(void *provctx)                      \
528*b077aed3SPierre Pronchery {                                                                              \
529*b077aed3SPierre Pronchery     return aes_##mode##_newctx(provctx, kbits, blkbits, ivbits,                \
530*b077aed3SPierre Pronchery                                EVP_CIPH_##UCMODE##_MODE, flags);               \
531*b077aed3SPierre Pronchery }                                                                              \
532*b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_##aes##kbits##mode##_functions[] = {                  \
533*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_NEWCTX,                                                 \
534*b077aed3SPierre Pronchery         (void (*)(void))aes_##kbits##_##mode##_newctx },                       \
535*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit },     \
536*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_##mode##_dinit },     \
537*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_block_update },    \
538*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_block_final },      \
539*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_ocb_cipher },               \
540*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx },        \
541*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_##mode##_dupctx },          \
542*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_GET_PARAMS,                                             \
543*b077aed3SPierre Pronchery         (void (*)(void))aes_##kbits##_##mode##_get_params },                   \
544*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,                                         \
545*b077aed3SPierre Pronchery         (void (*)(void))aes_##mode##_get_ctx_params },                         \
546*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,                                         \
547*b077aed3SPierre Pronchery         (void (*)(void))aes_##mode##_set_ctx_params },                         \
548*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,                                        \
549*b077aed3SPierre Pronchery         (void (*)(void))ossl_cipher_generic_gettable_params },                 \
550*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,                                    \
551*b077aed3SPierre Pronchery         (void (*)(void))cipher_ocb_gettable_ctx_params },                      \
552*b077aed3SPierre Pronchery     { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,                                    \
553*b077aed3SPierre Pronchery         (void (*)(void))cipher_ocb_settable_ctx_params },                      \
554*b077aed3SPierre Pronchery     { 0, NULL }                                                                \
555*b077aed3SPierre Pronchery }
556*b077aed3SPierre Pronchery 
557*b077aed3SPierre Pronchery IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 256, 128, OCB_DEFAULT_IV_LEN * 8);
558*b077aed3SPierre Pronchery IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 192, 128, OCB_DEFAULT_IV_LEN * 8);
559*b077aed3SPierre Pronchery IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 128, 128, OCB_DEFAULT_IV_LEN * 8);
560