1*b077aed3SPierre Pronchery
2*b077aed3SPierre Pronchery /*
3*b077aed3SPierre Pronchery * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
4*b077aed3SPierre Pronchery *
5*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
6*b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy
7*b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at
8*b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html
9*b077aed3SPierre Pronchery */
10*b077aed3SPierre Pronchery
11*b077aed3SPierre Pronchery /*
12*b077aed3SPierre Pronchery * AES low level APIs are deprecated for public use, but still ok for internal
13*b077aed3SPierre Pronchery * use where we're using them to implement the higher level EVP interface, as is
14*b077aed3SPierre Pronchery * the case here.
15*b077aed3SPierre Pronchery */
16*b077aed3SPierre Pronchery #include "internal/deprecated.h"
17*b077aed3SPierre Pronchery
18*b077aed3SPierre Pronchery #include <openssl/proverr.h>
19*b077aed3SPierre Pronchery #include "cipher_aes_xts.h"
20*b077aed3SPierre Pronchery #include "prov/implementations.h"
21*b077aed3SPierre Pronchery #include "prov/providercommon.h"
22*b077aed3SPierre Pronchery
23*b077aed3SPierre Pronchery #define AES_XTS_FLAGS PROV_CIPHER_FLAG_CUSTOM_IV
24*b077aed3SPierre Pronchery #define AES_XTS_IV_BITS 128
25*b077aed3SPierre Pronchery #define AES_XTS_BLOCK_BITS 8
26*b077aed3SPierre Pronchery
27*b077aed3SPierre Pronchery /* forward declarations */
28*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_encrypt_init_fn aes_xts_einit;
29*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_decrypt_init_fn aes_xts_dinit;
30*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_update_fn aes_xts_stream_update;
31*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_final_fn aes_xts_stream_final;
32*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_cipher_fn aes_xts_cipher;
33*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_freectx_fn aes_xts_freectx;
34*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_dupctx_fn aes_xts_dupctx;
35*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_set_ctx_params_fn aes_xts_set_ctx_params;
36*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_settable_ctx_params_fn aes_xts_settable_ctx_params;
37*b077aed3SPierre Pronchery
38*b077aed3SPierre Pronchery /*
39*b077aed3SPierre Pronchery * Verify that the two keys are different.
40*b077aed3SPierre Pronchery *
41*b077aed3SPierre Pronchery * This addresses the vulnerability described in Rogaway's
42*b077aed3SPierre Pronchery * September 2004 paper:
43*b077aed3SPierre Pronchery *
44*b077aed3SPierre Pronchery * "Efficient Instantiations of Tweakable Blockciphers and
45*b077aed3SPierre Pronchery * Refinements to Modes OCB and PMAC".
46*b077aed3SPierre Pronchery * (http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf)
47*b077aed3SPierre Pronchery *
48*b077aed3SPierre Pronchery * FIPS 140-2 IG A.9 XTS-AES Key Generation Requirements states
49*b077aed3SPierre Pronchery * that:
50*b077aed3SPierre Pronchery * "The check for Key_1 != Key_2 shall be done at any place
51*b077aed3SPierre Pronchery * BEFORE using the keys in the XTS-AES algorithm to process
52*b077aed3SPierre Pronchery * data with them."
53*b077aed3SPierre Pronchery */
aes_xts_check_keys_differ(const unsigned char * key,size_t bytes,int enc)54*b077aed3SPierre Pronchery static int aes_xts_check_keys_differ(const unsigned char *key, size_t bytes,
55*b077aed3SPierre Pronchery int enc)
56*b077aed3SPierre Pronchery {
57*b077aed3SPierre Pronchery if ((!ossl_aes_xts_allow_insecure_decrypt || enc)
58*b077aed3SPierre Pronchery && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
59*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DUPLICATED_KEYS);
60*b077aed3SPierre Pronchery return 0;
61*b077aed3SPierre Pronchery }
62*b077aed3SPierre Pronchery return 1;
63*b077aed3SPierre Pronchery }
64*b077aed3SPierre Pronchery
65*b077aed3SPierre Pronchery /*-
66*b077aed3SPierre Pronchery * Provider dispatch functions
67*b077aed3SPierre Pronchery */
aes_xts_init(void * vctx,const unsigned char * key,size_t keylen,const unsigned char * iv,size_t ivlen,const OSSL_PARAM params[],int enc)68*b077aed3SPierre Pronchery static int aes_xts_init(void *vctx, const unsigned char *key, size_t keylen,
69*b077aed3SPierre Pronchery const unsigned char *iv, size_t ivlen,
70*b077aed3SPierre Pronchery const OSSL_PARAM params[], int enc)
71*b077aed3SPierre Pronchery {
72*b077aed3SPierre Pronchery PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)vctx;
73*b077aed3SPierre Pronchery PROV_CIPHER_CTX *ctx = &xctx->base;
74*b077aed3SPierre Pronchery
75*b077aed3SPierre Pronchery if (!ossl_prov_is_running())
76*b077aed3SPierre Pronchery return 0;
77*b077aed3SPierre Pronchery
78*b077aed3SPierre Pronchery ctx->enc = enc;
79*b077aed3SPierre Pronchery
80*b077aed3SPierre Pronchery if (iv != NULL) {
81*b077aed3SPierre Pronchery if (!ossl_cipher_generic_initiv(vctx, iv, ivlen))
82*b077aed3SPierre Pronchery return 0;
83*b077aed3SPierre Pronchery }
84*b077aed3SPierre Pronchery if (key != NULL) {
85*b077aed3SPierre Pronchery if (keylen != ctx->keylen) {
86*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
87*b077aed3SPierre Pronchery return 0;
88*b077aed3SPierre Pronchery }
89*b077aed3SPierre Pronchery if (!aes_xts_check_keys_differ(key, keylen / 2, enc))
90*b077aed3SPierre Pronchery return 0;
91*b077aed3SPierre Pronchery if (!ctx->hw->init(ctx, key, keylen))
92*b077aed3SPierre Pronchery return 0;
93*b077aed3SPierre Pronchery }
94*b077aed3SPierre Pronchery return aes_xts_set_ctx_params(ctx, params);
95*b077aed3SPierre Pronchery }
96*b077aed3SPierre Pronchery
aes_xts_einit(void * vctx,const unsigned char * key,size_t keylen,const unsigned char * iv,size_t ivlen,const OSSL_PARAM params[])97*b077aed3SPierre Pronchery static int aes_xts_einit(void *vctx, const unsigned char *key, size_t keylen,
98*b077aed3SPierre Pronchery const unsigned char *iv, size_t ivlen,
99*b077aed3SPierre Pronchery const OSSL_PARAM params[])
100*b077aed3SPierre Pronchery {
101*b077aed3SPierre Pronchery return aes_xts_init(vctx, key, keylen, iv, ivlen, params, 1);
102*b077aed3SPierre Pronchery }
103*b077aed3SPierre Pronchery
aes_xts_dinit(void * vctx,const unsigned char * key,size_t keylen,const unsigned char * iv,size_t ivlen,const OSSL_PARAM params[])104*b077aed3SPierre Pronchery static int aes_xts_dinit(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[])
107*b077aed3SPierre Pronchery {
108*b077aed3SPierre Pronchery return aes_xts_init(vctx, key, keylen, iv, ivlen, params, 0);
109*b077aed3SPierre Pronchery }
110*b077aed3SPierre Pronchery
aes_xts_newctx(void * provctx,unsigned int mode,uint64_t flags,size_t kbits,size_t blkbits,size_t ivbits)111*b077aed3SPierre Pronchery static void *aes_xts_newctx(void *provctx, unsigned int mode, uint64_t flags,
112*b077aed3SPierre Pronchery size_t kbits, size_t blkbits, size_t ivbits)
113*b077aed3SPierre Pronchery {
114*b077aed3SPierre Pronchery PROV_AES_XTS_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
115*b077aed3SPierre Pronchery
116*b077aed3SPierre Pronchery if (ctx != NULL) {
117*b077aed3SPierre Pronchery ossl_cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits, mode,
118*b077aed3SPierre Pronchery flags, ossl_prov_cipher_hw_aes_xts(kbits),
119*b077aed3SPierre Pronchery NULL);
120*b077aed3SPierre Pronchery }
121*b077aed3SPierre Pronchery return ctx;
122*b077aed3SPierre Pronchery }
123*b077aed3SPierre Pronchery
aes_xts_freectx(void * vctx)124*b077aed3SPierre Pronchery static void aes_xts_freectx(void *vctx)
125*b077aed3SPierre Pronchery {
126*b077aed3SPierre Pronchery PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
127*b077aed3SPierre Pronchery
128*b077aed3SPierre Pronchery ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
129*b077aed3SPierre Pronchery OPENSSL_clear_free(ctx, sizeof(*ctx));
130*b077aed3SPierre Pronchery }
131*b077aed3SPierre Pronchery
aes_xts_dupctx(void * vctx)132*b077aed3SPierre Pronchery static void *aes_xts_dupctx(void *vctx)
133*b077aed3SPierre Pronchery {
134*b077aed3SPierre Pronchery PROV_AES_XTS_CTX *in = (PROV_AES_XTS_CTX *)vctx;
135*b077aed3SPierre Pronchery PROV_AES_XTS_CTX *ret = NULL;
136*b077aed3SPierre Pronchery
137*b077aed3SPierre Pronchery if (!ossl_prov_is_running())
138*b077aed3SPierre Pronchery return NULL;
139*b077aed3SPierre Pronchery
140*b077aed3SPierre Pronchery if (in->xts.key1 != NULL) {
141*b077aed3SPierre Pronchery if (in->xts.key1 != &in->ks1)
142*b077aed3SPierre Pronchery return NULL;
143*b077aed3SPierre Pronchery }
144*b077aed3SPierre Pronchery if (in->xts.key2 != NULL) {
145*b077aed3SPierre Pronchery if (in->xts.key2 != &in->ks2)
146*b077aed3SPierre Pronchery return NULL;
147*b077aed3SPierre Pronchery }
148*b077aed3SPierre Pronchery ret = OPENSSL_malloc(sizeof(*ret));
149*b077aed3SPierre Pronchery if (ret == NULL) {
150*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
151*b077aed3SPierre Pronchery return NULL;
152*b077aed3SPierre Pronchery }
153*b077aed3SPierre Pronchery in->base.hw->copyctx(&ret->base, &in->base);
154*b077aed3SPierre Pronchery return ret;
155*b077aed3SPierre Pronchery }
156*b077aed3SPierre Pronchery
aes_xts_cipher(void * vctx,unsigned char * out,size_t * outl,size_t outsize,const unsigned char * in,size_t inl)157*b077aed3SPierre Pronchery static int aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl,
158*b077aed3SPierre Pronchery size_t outsize, const unsigned char *in, size_t inl)
159*b077aed3SPierre Pronchery {
160*b077aed3SPierre Pronchery PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
161*b077aed3SPierre Pronchery
162*b077aed3SPierre Pronchery if (!ossl_prov_is_running()
163*b077aed3SPierre Pronchery || ctx->xts.key1 == NULL
164*b077aed3SPierre Pronchery || ctx->xts.key2 == NULL
165*b077aed3SPierre Pronchery || !ctx->base.iv_set
166*b077aed3SPierre Pronchery || out == NULL
167*b077aed3SPierre Pronchery || in == NULL
168*b077aed3SPierre Pronchery || inl < AES_BLOCK_SIZE)
169*b077aed3SPierre Pronchery return 0;
170*b077aed3SPierre Pronchery
171*b077aed3SPierre Pronchery /*
172*b077aed3SPierre Pronchery * Impose a limit of 2^20 blocks per data unit as specified by
173*b077aed3SPierre Pronchery * IEEE Std 1619-2018. The earlier and obsolete IEEE Std 1619-2007
174*b077aed3SPierre Pronchery * indicated that this was a SHOULD NOT rather than a MUST NOT.
175*b077aed3SPierre Pronchery * NIST SP 800-38E mandates the same limit.
176*b077aed3SPierre Pronchery */
177*b077aed3SPierre Pronchery if (inl > XTS_MAX_BLOCKS_PER_DATA_UNIT * AES_BLOCK_SIZE) {
178*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE);
179*b077aed3SPierre Pronchery return 0;
180*b077aed3SPierre Pronchery }
181*b077aed3SPierre Pronchery
182*b077aed3SPierre Pronchery if (ctx->stream != NULL)
183*b077aed3SPierre Pronchery (*ctx->stream)(in, out, inl, ctx->xts.key1, ctx->xts.key2, ctx->base.iv);
184*b077aed3SPierre Pronchery else if (CRYPTO_xts128_encrypt(&ctx->xts, ctx->base.iv, in, out, inl,
185*b077aed3SPierre Pronchery ctx->base.enc))
186*b077aed3SPierre Pronchery return 0;
187*b077aed3SPierre Pronchery
188*b077aed3SPierre Pronchery *outl = inl;
189*b077aed3SPierre Pronchery return 1;
190*b077aed3SPierre Pronchery }
191*b077aed3SPierre Pronchery
aes_xts_stream_update(void * vctx,unsigned char * out,size_t * outl,size_t outsize,const unsigned char * in,size_t inl)192*b077aed3SPierre Pronchery static int aes_xts_stream_update(void *vctx, unsigned char *out, size_t *outl,
193*b077aed3SPierre Pronchery size_t outsize, const unsigned char *in,
194*b077aed3SPierre Pronchery size_t inl)
195*b077aed3SPierre Pronchery {
196*b077aed3SPierre Pronchery PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
197*b077aed3SPierre Pronchery
198*b077aed3SPierre Pronchery if (outsize < inl) {
199*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
200*b077aed3SPierre Pronchery return 0;
201*b077aed3SPierre Pronchery }
202*b077aed3SPierre Pronchery
203*b077aed3SPierre Pronchery if (!aes_xts_cipher(ctx, out, outl, outsize, in, inl)) {
204*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
205*b077aed3SPierre Pronchery return 0;
206*b077aed3SPierre Pronchery }
207*b077aed3SPierre Pronchery
208*b077aed3SPierre Pronchery return 1;
209*b077aed3SPierre Pronchery }
210*b077aed3SPierre Pronchery
aes_xts_stream_final(void * vctx,unsigned char * out,size_t * outl,size_t outsize)211*b077aed3SPierre Pronchery static int aes_xts_stream_final(void *vctx, unsigned char *out, size_t *outl,
212*b077aed3SPierre Pronchery size_t outsize)
213*b077aed3SPierre Pronchery {
214*b077aed3SPierre Pronchery if (!ossl_prov_is_running())
215*b077aed3SPierre Pronchery return 0;
216*b077aed3SPierre Pronchery *outl = 0;
217*b077aed3SPierre Pronchery return 1;
218*b077aed3SPierre Pronchery }
219*b077aed3SPierre Pronchery
220*b077aed3SPierre Pronchery static const OSSL_PARAM aes_xts_known_settable_ctx_params[] = {
221*b077aed3SPierre Pronchery OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
222*b077aed3SPierre Pronchery OSSL_PARAM_END
223*b077aed3SPierre Pronchery };
224*b077aed3SPierre Pronchery
aes_xts_settable_ctx_params(ossl_unused void * cctx,ossl_unused void * provctx)225*b077aed3SPierre Pronchery static const OSSL_PARAM *aes_xts_settable_ctx_params(ossl_unused void *cctx,
226*b077aed3SPierre Pronchery ossl_unused void *provctx)
227*b077aed3SPierre Pronchery {
228*b077aed3SPierre Pronchery return aes_xts_known_settable_ctx_params;
229*b077aed3SPierre Pronchery }
230*b077aed3SPierre Pronchery
aes_xts_set_ctx_params(void * vctx,const OSSL_PARAM params[])231*b077aed3SPierre Pronchery static int aes_xts_set_ctx_params(void *vctx, const OSSL_PARAM params[])
232*b077aed3SPierre Pronchery {
233*b077aed3SPierre Pronchery PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
234*b077aed3SPierre Pronchery const OSSL_PARAM *p;
235*b077aed3SPierre Pronchery
236*b077aed3SPierre Pronchery if (params == NULL)
237*b077aed3SPierre Pronchery return 1;
238*b077aed3SPierre Pronchery
239*b077aed3SPierre Pronchery p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
240*b077aed3SPierre Pronchery if (p != NULL) {
241*b077aed3SPierre Pronchery size_t keylen;
242*b077aed3SPierre Pronchery
243*b077aed3SPierre Pronchery if (!OSSL_PARAM_get_size_t(p, &keylen)) {
244*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
245*b077aed3SPierre Pronchery return 0;
246*b077aed3SPierre Pronchery }
247*b077aed3SPierre Pronchery /* The key length can not be modified for xts mode */
248*b077aed3SPierre Pronchery if (keylen != ctx->keylen)
249*b077aed3SPierre Pronchery return 0;
250*b077aed3SPierre Pronchery }
251*b077aed3SPierre Pronchery
252*b077aed3SPierre Pronchery return 1;
253*b077aed3SPierre Pronchery }
254*b077aed3SPierre Pronchery
255*b077aed3SPierre Pronchery #define IMPLEMENT_cipher(lcmode, UCMODE, kbits, flags) \
256*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##lcmode##_get_params; \
257*b077aed3SPierre Pronchery static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
258*b077aed3SPierre Pronchery { \
259*b077aed3SPierre Pronchery return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
260*b077aed3SPierre Pronchery flags, 2 * kbits, AES_XTS_BLOCK_BITS, \
261*b077aed3SPierre Pronchery AES_XTS_IV_BITS); \
262*b077aed3SPierre Pronchery } \
263*b077aed3SPierre Pronchery static OSSL_FUNC_cipher_newctx_fn aes_##kbits##_xts_newctx; \
264*b077aed3SPierre Pronchery static void *aes_##kbits##_xts_newctx(void *provctx) \
265*b077aed3SPierre Pronchery { \
266*b077aed3SPierre Pronchery return aes_xts_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, flags, 2 * kbits, \
267*b077aed3SPierre Pronchery AES_XTS_BLOCK_BITS, AES_XTS_IV_BITS); \
268*b077aed3SPierre Pronchery } \
269*b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_aes##kbits##xts_functions[] = { \
270*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##kbits##_xts_newctx }, \
271*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_xts_einit }, \
272*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_xts_dinit }, \
273*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_xts_stream_update }, \
274*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_xts_stream_final }, \
275*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_xts_cipher }, \
276*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_xts_freectx }, \
277*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_xts_dupctx }, \
278*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_GET_PARAMS, \
279*b077aed3SPierre Pronchery (void (*)(void))aes_##kbits##_##lcmode##_get_params }, \
280*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
281*b077aed3SPierre Pronchery (void (*)(void))ossl_cipher_generic_gettable_params }, \
282*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
283*b077aed3SPierre Pronchery (void (*)(void))ossl_cipher_generic_get_ctx_params }, \
284*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
285*b077aed3SPierre Pronchery (void (*)(void))ossl_cipher_generic_gettable_ctx_params }, \
286*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
287*b077aed3SPierre Pronchery (void (*)(void))aes_xts_set_ctx_params }, \
288*b077aed3SPierre Pronchery { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
289*b077aed3SPierre Pronchery (void (*)(void))aes_xts_settable_ctx_params }, \
290*b077aed3SPierre Pronchery { 0, NULL } \
291*b077aed3SPierre Pronchery }
292*b077aed3SPierre Pronchery
293*b077aed3SPierre Pronchery IMPLEMENT_cipher(xts, XTS, 256, AES_XTS_FLAGS);
294*b077aed3SPierre Pronchery IMPLEMENT_cipher(xts, XTS, 128, AES_XTS_FLAGS);
295