]>
Commit | Line | Data |
---|---|---|
1be63951 | 1 | |
3a9f26f3 | 2 | /* |
a28d06f3 | 3 | * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. |
3a9f26f3 SL |
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 | ||
c72fa255 MC |
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 | ||
2741128e | 18 | #include <openssl/proverr.h> |
3a9f26f3 | 19 | #include "cipher_aes_xts.h" |
af3e7e1b | 20 | #include "prov/implementations.h" |
f99d3eed | 21 | #include "prov/providercommon.h" |
3a9f26f3 | 22 | |
a054d15c | 23 | #define AES_XTS_FLAGS PROV_CIPHER_FLAG_CUSTOM_IV |
3a9f26f3 SL |
24 | #define AES_XTS_IV_BITS 128 |
25 | #define AES_XTS_BLOCK_BITS 8 | |
26 | ||
3a9f26f3 | 27 | /* forward declarations */ |
363b1e5d DMSP |
28 | static OSSL_FUNC_cipher_encrypt_init_fn aes_xts_einit; |
29 | static OSSL_FUNC_cipher_decrypt_init_fn aes_xts_dinit; | |
30 | static OSSL_FUNC_cipher_update_fn aes_xts_stream_update; | |
31 | static OSSL_FUNC_cipher_final_fn aes_xts_stream_final; | |
32 | static OSSL_FUNC_cipher_cipher_fn aes_xts_cipher; | |
33 | static OSSL_FUNC_cipher_freectx_fn aes_xts_freectx; | |
34 | static OSSL_FUNC_cipher_dupctx_fn aes_xts_dupctx; | |
35 | static OSSL_FUNC_cipher_set_ctx_params_fn aes_xts_set_ctx_params; | |
36 | static OSSL_FUNC_cipher_settable_ctx_params_fn aes_xts_settable_ctx_params; | |
3a9f26f3 SL |
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 | */ | |
54 | static int aes_xts_check_keys_differ(const unsigned char *key, size_t bytes, | |
55 | int enc) | |
56 | { | |
57 | if ((!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 | */ | |
68 | static int aes_xts_init(void *vctx, const unsigned char *key, size_t keylen, | |
69 | const unsigned char *iv, size_t ivlen, int enc) | |
70 | { | |
71 | PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)vctx; | |
72 | PROV_CIPHER_CTX *ctx = &xctx->base; | |
73 | ||
f99d3eed P |
74 | if (!ossl_prov_is_running()) |
75 | return 0; | |
76 | ||
3a9f26f3 SL |
77 | ctx->enc = enc; |
78 | ||
79 | if (iv != NULL) { | |
592dcfd3 | 80 | if (!ossl_cipher_generic_initiv(vctx, iv, ivlen)) |
3a9f26f3 | 81 | return 0; |
3a9f26f3 SL |
82 | } |
83 | if (key != NULL) { | |
84 | if (keylen != ctx->keylen) { | |
85 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); | |
86 | return 0; | |
87 | } | |
88 | if (!aes_xts_check_keys_differ(key, keylen / 2, enc)) | |
89 | return 0; | |
90 | return ctx->hw->init(ctx, key, keylen); | |
91 | } | |
92 | return 1; | |
93 | } | |
94 | ||
95 | static int aes_xts_einit(void *vctx, const unsigned char *key, size_t keylen, | |
96 | const unsigned char *iv, size_t ivlen) | |
97 | { | |
98 | return aes_xts_init(vctx, key, keylen, iv, ivlen, 1); | |
99 | } | |
100 | ||
101 | static int aes_xts_dinit(void *vctx, const unsigned char *key, size_t keylen, | |
102 | const unsigned char *iv, size_t ivlen) | |
103 | { | |
104 | return aes_xts_init(vctx, key, keylen, iv, ivlen, 0); | |
105 | } | |
106 | ||
55c7dc79 SL |
107 | static void *aes_xts_newctx(void *provctx, unsigned int mode, uint64_t flags, |
108 | size_t kbits, size_t blkbits, size_t ivbits) | |
3a9f26f3 SL |
109 | { |
110 | PROV_AES_XTS_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); | |
111 | ||
112 | if (ctx != NULL) { | |
592dcfd3 P |
113 | ossl_cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits, mode, |
114 | flags, ossl_prov_cipher_hw_aes_xts(kbits), | |
115 | NULL); | |
3a9f26f3 SL |
116 | } |
117 | return ctx; | |
118 | } | |
119 | ||
120 | static void aes_xts_freectx(void *vctx) | |
121 | { | |
122 | PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx; | |
123 | ||
592dcfd3 | 124 | ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx); |
3a9f26f3 SL |
125 | OPENSSL_clear_free(ctx, sizeof(*ctx)); |
126 | } | |
127 | ||
128 | static void *aes_xts_dupctx(void *vctx) | |
129 | { | |
130 | PROV_AES_XTS_CTX *in = (PROV_AES_XTS_CTX *)vctx; | |
131 | PROV_AES_XTS_CTX *ret = NULL; | |
132 | ||
f99d3eed P |
133 | if (!ossl_prov_is_running()) |
134 | return NULL; | |
135 | ||
3a9f26f3 SL |
136 | if (in->xts.key1 != NULL) { |
137 | if (in->xts.key1 != &in->ks1) | |
138 | return NULL; | |
139 | } | |
140 | if (in->xts.key2 != NULL) { | |
141 | if (in->xts.key2 != &in->ks2) | |
142 | return NULL; | |
143 | } | |
144 | ret = OPENSSL_malloc(sizeof(*ret)); | |
145 | if (ret == NULL) { | |
146 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
147 | return NULL; | |
148 | } | |
f75abcc0 | 149 | in->base.hw->copyctx(&ret->base, &in->base); |
3a9f26f3 SL |
150 | return ret; |
151 | } | |
152 | ||
153 | static int aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl, | |
154 | size_t outsize, const unsigned char *in, size_t inl) | |
155 | { | |
156 | PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx; | |
157 | ||
f99d3eed P |
158 | if (!ossl_prov_is_running() |
159 | || ctx->xts.key1 == NULL | |
3a9f26f3 | 160 | || ctx->xts.key2 == NULL |
089cb623 | 161 | || !ctx->base.iv_set |
3a9f26f3 SL |
162 | || out == NULL |
163 | || in == NULL | |
164 | || inl < AES_BLOCK_SIZE) | |
165 | return 0; | |
166 | ||
167 | /* | |
79c44b4e | 168 | * Impose a limit of 2^20 blocks per data unit as specified by |
3a9f26f3 SL |
169 | * IEEE Std 1619-2018. The earlier and obsolete IEEE Std 1619-2007 |
170 | * indicated that this was a SHOULD NOT rather than a MUST NOT. | |
171 | * NIST SP 800-38E mandates the same limit. | |
172 | */ | |
173 | if (inl > XTS_MAX_BLOCKS_PER_DATA_UNIT * AES_BLOCK_SIZE) { | |
174 | ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE); | |
175 | return 0; | |
176 | } | |
177 | ||
178 | if (ctx->stream != NULL) | |
179 | (*ctx->stream)(in, out, inl, ctx->xts.key1, ctx->xts.key2, ctx->base.iv); | |
180 | else if (CRYPTO_xts128_encrypt(&ctx->xts, ctx->base.iv, in, out, inl, | |
181 | ctx->base.enc)) | |
182 | return 0; | |
3a9f26f3 SL |
183 | |
184 | *outl = inl; | |
185 | return 1; | |
186 | } | |
187 | ||
188 | static int aes_xts_stream_update(void *vctx, unsigned char *out, size_t *outl, | |
189 | size_t outsize, const unsigned char *in, | |
190 | size_t inl) | |
191 | { | |
192 | PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx; | |
193 | ||
194 | if (outsize < inl) { | |
195 | ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); | |
196 | return 0; | |
197 | } | |
198 | ||
199 | if (!aes_xts_cipher(ctx, out, outl, outsize, in, inl)) { | |
200 | ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); | |
201 | return 0; | |
202 | } | |
203 | ||
3a9f26f3 SL |
204 | return 1; |
205 | } | |
206 | ||
207 | static int aes_xts_stream_final(void *vctx, unsigned char *out, size_t *outl, | |
208 | size_t outsize) | |
209 | { | |
f99d3eed P |
210 | if (!ossl_prov_is_running()) |
211 | return 0; | |
3a9f26f3 SL |
212 | *outl = 0; |
213 | return 1; | |
214 | } | |
215 | ||
216 | static const OSSL_PARAM aes_xts_known_settable_ctx_params[] = { | |
217 | OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), | |
218 | OSSL_PARAM_END | |
219 | }; | |
220 | ||
644c5dd3 P |
221 | static const OSSL_PARAM *aes_xts_settable_ctx_params(ossl_unused void *cctx, |
222 | ossl_unused void *provctx) | |
3a9f26f3 SL |
223 | { |
224 | return aes_xts_known_settable_ctx_params; | |
225 | } | |
226 | ||
227 | static int aes_xts_set_ctx_params(void *vctx, const OSSL_PARAM params[]) | |
228 | { | |
229 | PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; | |
230 | const OSSL_PARAM *p; | |
231 | ||
3a9f26f3 SL |
232 | p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); |
233 | if (p != NULL) { | |
234 | size_t keylen; | |
235 | ||
236 | if (!OSSL_PARAM_get_size_t(p, &keylen)) { | |
237 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); | |
238 | return 0; | |
239 | } | |
240 | /* The key length can not be modified for xts mode */ | |
241 | if (keylen != ctx->keylen) | |
242 | return 0; | |
243 | } | |
244 | ||
245 | return 1; | |
246 | } | |
247 | ||
248 | #define IMPLEMENT_cipher(lcmode, UCMODE, kbits, flags) \ | |
363b1e5d | 249 | static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##lcmode##_get_params; \ |
3a9f26f3 SL |
250 | static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \ |
251 | { \ | |
592dcfd3 | 252 | return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \ |
3a9f26f3 SL |
253 | flags, 2 * kbits, AES_XTS_BLOCK_BITS, \ |
254 | AES_XTS_IV_BITS); \ | |
255 | } \ | |
363b1e5d | 256 | static OSSL_FUNC_cipher_newctx_fn aes_##kbits##_xts_newctx; \ |
3a9f26f3 SL |
257 | static void *aes_##kbits##_xts_newctx(void *provctx) \ |
258 | { \ | |
55c7dc79 | 259 | return aes_xts_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, flags, 2 * kbits, \ |
3a9f26f3 SL |
260 | AES_XTS_BLOCK_BITS, AES_XTS_IV_BITS); \ |
261 | } \ | |
1be63951 | 262 | const OSSL_DISPATCH ossl_aes##kbits##xts_functions[] = { \ |
3a9f26f3 SL |
263 | { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##kbits##_xts_newctx }, \ |
264 | { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_xts_einit }, \ | |
265 | { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_xts_dinit }, \ | |
266 | { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_xts_stream_update }, \ | |
267 | { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_xts_stream_final }, \ | |
268 | { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_xts_cipher }, \ | |
269 | { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_xts_freectx }, \ | |
270 | { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_xts_dupctx }, \ | |
271 | { OSSL_FUNC_CIPHER_GET_PARAMS, \ | |
272 | (void (*)(void))aes_##kbits##_##lcmode##_get_params }, \ | |
273 | { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ | |
592dcfd3 | 274 | (void (*)(void))ossl_cipher_generic_gettable_params }, \ |
3a9f26f3 | 275 | { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ |
592dcfd3 | 276 | (void (*)(void))ossl_cipher_generic_get_ctx_params }, \ |
3a9f26f3 | 277 | { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ |
592dcfd3 | 278 | (void (*)(void))ossl_cipher_generic_gettable_ctx_params }, \ |
3a9f26f3 SL |
279 | { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ |
280 | (void (*)(void))aes_xts_set_ctx_params }, \ | |
281 | { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ | |
282 | (void (*)(void))aes_xts_settable_ctx_params }, \ | |
283 | { 0, NULL } \ | |
284 | } | |
285 | ||
286 | IMPLEMENT_cipher(xts, XTS, 256, AES_XTS_FLAGS); | |
287 | IMPLEMENT_cipher(xts, XTS, 128, AES_XTS_FLAGS); |