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