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