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