Coverage Report

Created: 2026-09-12 06:55

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