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