Path: blob/main/crypto/openssl/providers/implementations/ciphers/cipher_aes_xts.c
48383 views
1/*2* Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.3*4* Licensed under the Apache License 2.0 (the "License"). You may not use5* this file except in compliance with the License. You can obtain a copy6* in the file LICENSE in the source distribution or at7* https://www.openssl.org/source/license.html8*/910/*11* AES low level APIs are deprecated for public use, but still ok for internal12* use where we're using them to implement the higher level EVP interface, as is13* the case here.14*/15#include "internal/deprecated.h"1617#include <openssl/proverr.h>18#include "cipher_aes_xts.h"19#include "prov/implementations.h"20#include "prov/providercommon.h"2122#define AES_XTS_FLAGS PROV_CIPHER_FLAG_CUSTOM_IV23#define AES_XTS_IV_BITS 12824#define AES_XTS_BLOCK_BITS 82526/* forward declarations */27static OSSL_FUNC_cipher_encrypt_init_fn aes_xts_einit;28static OSSL_FUNC_cipher_decrypt_init_fn aes_xts_dinit;29static OSSL_FUNC_cipher_update_fn aes_xts_stream_update;30static OSSL_FUNC_cipher_final_fn aes_xts_stream_final;31static OSSL_FUNC_cipher_cipher_fn aes_xts_cipher;32static OSSL_FUNC_cipher_freectx_fn aes_xts_freectx;33static OSSL_FUNC_cipher_dupctx_fn aes_xts_dupctx;34static OSSL_FUNC_cipher_set_ctx_params_fn aes_xts_set_ctx_params;35static OSSL_FUNC_cipher_settable_ctx_params_fn aes_xts_settable_ctx_params;3637/*38* Verify that the two keys are different.39*40* This addresses the vulnerability described in Rogaway's41* September 2004 paper:42*43* "Efficient Instantiations of Tweakable Blockciphers and44* Refinements to Modes OCB and PMAC".45* (http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf)46*47* FIPS 140-2 IG A.9 XTS-AES Key Generation Requirements states48* that:49* "The check for Key_1 != Key_2 shall be done at any place50* BEFORE using the keys in the XTS-AES algorithm to process51* data with them."52*/53static int aes_xts_check_keys_differ(const unsigned char *key, size_t bytes,54int enc)55{56if ((!ossl_aes_xts_allow_insecure_decrypt || enc)57&& CRYPTO_memcmp(key, key + bytes, bytes) == 0) {58ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DUPLICATED_KEYS);59return 0;60}61return 1;62}6364#ifdef AES_XTS_S390X65# include "cipher_aes_xts_s390x.inc"66#endif6768/*-69* Provider dispatch functions70*/71static int aes_xts_init(void *vctx, const unsigned char *key, size_t keylen,72const unsigned char *iv, size_t ivlen,73const OSSL_PARAM params[], int enc)74{75PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)vctx;76PROV_CIPHER_CTX *ctx = &xctx->base;7778if (!ossl_prov_is_running())79return 0;8081ctx->enc = enc;8283if (iv != NULL) {84if (!ossl_cipher_generic_initiv(vctx, iv, ivlen))85return 0;86}87if (key != NULL) {88if (keylen != ctx->keylen) {89ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);90return 0;91}92if (!aes_xts_check_keys_differ(key, keylen / 2, enc))93return 0;94if (!ctx->hw->init(ctx, key, keylen))95return 0;96}97return aes_xts_set_ctx_params(ctx, params);98}99100static int aes_xts_einit(void *vctx, const unsigned char *key, size_t keylen,101const unsigned char *iv, size_t ivlen,102const OSSL_PARAM params[])103{104#ifdef AES_XTS_S390X105if (s390x_aes_xts_einit(vctx, key, keylen, iv, ivlen, params) == 1)106return 1;107#endif108return aes_xts_init(vctx, key, keylen, iv, ivlen, params, 1);109}110111static int aes_xts_dinit(void *vctx, const unsigned char *key, size_t keylen,112const unsigned char *iv, size_t ivlen,113const OSSL_PARAM params[])114{115#ifdef AES_XTS_S390X116if (s390x_aes_xts_dinit(vctx, key, keylen, iv, ivlen, params) == 1)117return 1;118#endif119return aes_xts_init(vctx, key, keylen, iv, ivlen, params, 0);120}121122static void *aes_xts_newctx(void *provctx, unsigned int mode, uint64_t flags,123size_t kbits, size_t blkbits, size_t ivbits)124{125PROV_AES_XTS_CTX *ctx;126127if (!ossl_prov_is_running())128return NULL;129130ctx = OPENSSL_zalloc(sizeof(*ctx));131if (ctx != NULL) {132ossl_cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits, mode,133flags, ossl_prov_cipher_hw_aes_xts(kbits),134NULL);135}136return ctx;137}138139static void aes_xts_freectx(void *vctx)140{141PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;142143ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);144OPENSSL_clear_free(ctx, sizeof(*ctx));145}146147static void *aes_xts_dupctx(void *vctx)148{149PROV_AES_XTS_CTX *in = (PROV_AES_XTS_CTX *)vctx;150PROV_AES_XTS_CTX *ret = NULL;151152if (!ossl_prov_is_running())153return NULL;154155#ifdef AES_XTS_S390X156if (in->plat.s390x.fc)157return s390x_aes_xts_dupctx(vctx);158#endif159160if (in->xts.key1 != NULL) {161if (in->xts.key1 != &in->ks1)162return NULL;163}164if (in->xts.key2 != NULL) {165if (in->xts.key2 != &in->ks2)166return NULL;167}168ret = OPENSSL_malloc(sizeof(*ret));169if (ret == NULL)170return NULL;171in->base.hw->copyctx(&ret->base, &in->base);172return ret;173}174175static int aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl,176size_t outsize, const unsigned char *in, size_t inl)177{178PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;179180#ifdef AES_XTS_S390X181if (ctx->plat.s390x.fc)182return s390x_aes_xts_cipher(vctx, out, outl, outsize, in, inl);183#endif184185if (!ossl_prov_is_running()186|| ctx->xts.key1 == NULL187|| ctx->xts.key2 == NULL188|| !ctx->base.iv_set189|| out == NULL190|| in == NULL191|| inl < AES_BLOCK_SIZE)192return 0;193194/*195* Impose a limit of 2^20 blocks per data unit as specified by196* IEEE Std 1619-2018. The earlier and obsolete IEEE Std 1619-2007197* indicated that this was a SHOULD NOT rather than a MUST NOT.198* NIST SP 800-38E mandates the same limit.199*/200if (inl > XTS_MAX_BLOCKS_PER_DATA_UNIT * AES_BLOCK_SIZE) {201ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE);202return 0;203}204205if (ctx->stream != NULL)206(*ctx->stream)(in, out, inl, ctx->xts.key1, ctx->xts.key2, ctx->base.iv);207else if (CRYPTO_xts128_encrypt(&ctx->xts, ctx->base.iv, in, out, inl,208ctx->base.enc))209return 0;210211*outl = inl;212return 1;213}214215static int aes_xts_stream_update(void *vctx, unsigned char *out, size_t *outl,216size_t outsize, const unsigned char *in,217size_t inl)218{219PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;220221if (outsize < inl) {222ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);223return 0;224}225226if (!aes_xts_cipher(ctx, out, outl, outsize, in, inl)) {227ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);228return 0;229}230231return 1;232}233234static int aes_xts_stream_final(void *vctx, unsigned char *out, size_t *outl,235size_t outsize)236{237if (!ossl_prov_is_running())238return 0;239*outl = 0;240return 1;241}242243static const OSSL_PARAM aes_xts_known_settable_ctx_params[] = {244OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),245OSSL_PARAM_END246};247248static const OSSL_PARAM *aes_xts_settable_ctx_params(ossl_unused void *cctx,249ossl_unused void *provctx)250{251return aes_xts_known_settable_ctx_params;252}253254static int aes_xts_set_ctx_params(void *vctx, const OSSL_PARAM params[])255{256PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;257const OSSL_PARAM *p;258259if (ossl_param_is_empty(params))260return 1;261262p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);263if (p != NULL) {264size_t keylen;265266if (!OSSL_PARAM_get_size_t(p, &keylen)) {267ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);268return 0;269}270/* The key length can not be modified for xts mode */271if (keylen != ctx->keylen)272return 0;273}274275return 1;276}277278#define IMPLEMENT_cipher(lcmode, UCMODE, kbits, flags) \279static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##lcmode##_get_params; \280static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \281{ \282return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \283flags, 2 * kbits, AES_XTS_BLOCK_BITS, \284AES_XTS_IV_BITS); \285} \286static OSSL_FUNC_cipher_newctx_fn aes_##kbits##_xts_newctx; \287static void *aes_##kbits##_xts_newctx(void *provctx) \288{ \289return aes_xts_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, flags, 2 * kbits, \290AES_XTS_BLOCK_BITS, AES_XTS_IV_BITS); \291} \292const OSSL_DISPATCH ossl_aes##kbits##xts_functions[] = { \293{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##kbits##_xts_newctx }, \294{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_xts_einit }, \295{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_xts_dinit }, \296{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_xts_stream_update }, \297{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_xts_stream_final }, \298{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_xts_cipher }, \299{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_xts_freectx }, \300{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_xts_dupctx }, \301{ OSSL_FUNC_CIPHER_GET_PARAMS, \302(void (*)(void))aes_##kbits##_##lcmode##_get_params }, \303{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \304(void (*)(void))ossl_cipher_generic_gettable_params }, \305{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \306(void (*)(void))ossl_cipher_generic_get_ctx_params }, \307{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \308(void (*)(void))ossl_cipher_generic_gettable_ctx_params }, \309{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \310(void (*)(void))aes_xts_set_ctx_params }, \311{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \312(void (*)(void))aes_xts_settable_ctx_params }, \313OSSL_DISPATCH_END \314}315316IMPLEMENT_cipher(xts, XTS, 256, AES_XTS_FLAGS);317IMPLEMENT_cipher(xts, XTS, 128, AES_XTS_FLAGS);318319320