1 /*
2 * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (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
10 #include <openssl/evp.h>
11
12 #include <string.h>
13
14 #include <openssl/aes.h>
15 #include <openssl/cipher.h>
16
17 #include "../../crypto/fipsmodule/cipher/internal.h"
18 #include "../../crypto/fipsmodule/modes/internal.h"
19
20
21 typedef struct xts128_context {
22 AES_KEY *key1, *key2;
23 block128_f block1, block2;
24 } XTS128_CONTEXT;
25
CRYPTO_xts128_encrypt(const XTS128_CONTEXT * ctx,const uint8_t iv[16],const uint8_t * inp,uint8_t * out,size_t len,int enc)26 static size_t CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx,
27 const uint8_t iv[16], const uint8_t *inp,
28 uint8_t *out, size_t len, int enc) {
29 union {
30 uint64_t u[2];
31 uint32_t d[4];
32 uint8_t c[16];
33 } tweak, scratch;
34 unsigned int i;
35
36 if (len < 16) {
37 return 0;
38 }
39
40 OPENSSL_memcpy(tweak.c, iv, 16);
41
42 (*ctx->block2)(tweak.c, tweak.c, ctx->key2);
43
44 if (!enc && (len % 16)) {
45 len -= 16;
46 }
47
48 while (len >= 16) {
49 OPENSSL_memcpy(scratch.c, inp, 16);
50 scratch.u[0] ^= tweak.u[0];
51 scratch.u[1] ^= tweak.u[1];
52 (*ctx->block1)(scratch.c, scratch.c, ctx->key1);
53 scratch.u[0] ^= tweak.u[0];
54 scratch.u[1] ^= tweak.u[1];
55 OPENSSL_memcpy(out, scratch.c, 16);
56 inp += 16;
57 out += 16;
58 len -= 16;
59
60 if (len == 0) {
61 return 1;
62 }
63
64 unsigned int carry, res;
65
66 res = 0x87 & (((int)tweak.d[3]) >> 31);
67 carry = (unsigned int)(tweak.u[0] >> 63);
68 tweak.u[0] = (tweak.u[0] << 1) ^ res;
69 tweak.u[1] = (tweak.u[1] << 1) | carry;
70 }
71 if (enc) {
72 for (i = 0; i < len; ++i) {
73 uint8_t c = inp[i];
74 out[i] = scratch.c[i];
75 scratch.c[i] = c;
76 }
77 scratch.u[0] ^= tweak.u[0];
78 scratch.u[1] ^= tweak.u[1];
79 (*ctx->block1)(scratch.c, scratch.c, ctx->key1);
80 scratch.u[0] ^= tweak.u[0];
81 scratch.u[1] ^= tweak.u[1];
82 OPENSSL_memcpy(out - 16, scratch.c, 16);
83 } else {
84 union {
85 uint64_t u[2];
86 uint8_t c[16];
87 } tweak1;
88
89 unsigned int carry, res;
90
91 res = 0x87 & (((int)tweak.d[3]) >> 31);
92 carry = (unsigned int)(tweak.u[0] >> 63);
93 tweak1.u[0] = (tweak.u[0] << 1) ^ res;
94 tweak1.u[1] = (tweak.u[1] << 1) | carry;
95 OPENSSL_memcpy(scratch.c, inp, 16);
96 scratch.u[0] ^= tweak1.u[0];
97 scratch.u[1] ^= tweak1.u[1];
98 (*ctx->block1)(scratch.c, scratch.c, ctx->key1);
99 scratch.u[0] ^= tweak1.u[0];
100 scratch.u[1] ^= tweak1.u[1];
101
102 for (i = 0; i < len; ++i) {
103 uint8_t c = inp[16 + i];
104 out[16 + i] = scratch.c[i];
105 scratch.c[i] = c;
106 }
107 scratch.u[0] ^= tweak.u[0];
108 scratch.u[1] ^= tweak.u[1];
109 (*ctx->block1)(scratch.c, scratch.c, ctx->key1);
110 scratch.u[0] ^= tweak.u[0];
111 scratch.u[1] ^= tweak.u[1];
112 OPENSSL_memcpy(out, scratch.c, 16);
113 }
114
115 return 1;
116 }
117
118 typedef struct {
119 union {
120 double align;
121 AES_KEY ks;
122 } ks1, ks2; // AES key schedules to use
123 XTS128_CONTEXT xts;
124 } EVP_AES_XTS_CTX;
125
aes_xts_init_key(EVP_CIPHER_CTX * ctx,const uint8_t * key,const uint8_t * iv,int enc)126 static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
127 const uint8_t *iv, int enc) {
128 EVP_AES_XTS_CTX *xctx = reinterpret_cast<EVP_AES_XTS_CTX *>(ctx->cipher_data);
129 if (!iv && !key) {
130 return 1;
131 }
132
133 if (key) {
134 // key_len is two AES keys
135 if (enc) {
136 AES_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks);
137 xctx->xts.block1 = AES_encrypt;
138 } else {
139 AES_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks);
140 xctx->xts.block1 = AES_decrypt;
141 }
142
143 AES_set_encrypt_key(key + ctx->key_len / 2, ctx->key_len * 4,
144 &xctx->ks2.ks);
145 xctx->xts.block2 = AES_encrypt;
146 xctx->xts.key1 = &xctx->ks1.ks;
147 }
148
149 if (iv) {
150 xctx->xts.key2 = &xctx->ks2.ks;
151 OPENSSL_memcpy(ctx->iv, iv, 16);
152 }
153
154 return 1;
155 }
156
aes_xts_cipher(EVP_CIPHER_CTX * ctx,uint8_t * out,const uint8_t * in,size_t len)157 static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
158 size_t len) {
159 EVP_AES_XTS_CTX *xctx = reinterpret_cast<EVP_AES_XTS_CTX *>(ctx->cipher_data);
160 if (!xctx->xts.key1 || !xctx->xts.key2 || !out || !in ||
161 len < AES_BLOCK_SIZE ||
162 !CRYPTO_xts128_encrypt(&xctx->xts, ctx->iv, in, out, len, ctx->encrypt)) {
163 return 0;
164 }
165 return 1;
166 }
167
aes_xts_ctrl(EVP_CIPHER_CTX * c,int type,int arg,void * ptr)168 static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) {
169 EVP_AES_XTS_CTX *xctx = reinterpret_cast<EVP_AES_XTS_CTX *>(c->cipher_data);
170 if (type == EVP_CTRL_COPY) {
171 EVP_CIPHER_CTX *out = reinterpret_cast<EVP_CIPHER_CTX *>(ptr);
172 EVP_AES_XTS_CTX *xctx_out =
173 reinterpret_cast<EVP_AES_XTS_CTX *>(out->cipher_data);
174 if (xctx->xts.key1) {
175 if (xctx->xts.key1 != &xctx->ks1.ks) {
176 return 0;
177 }
178 xctx_out->xts.key1 = &xctx_out->ks1.ks;
179 }
180 if (xctx->xts.key2) {
181 if (xctx->xts.key2 != &xctx->ks2.ks) {
182 return 0;
183 }
184 xctx_out->xts.key2 = &xctx_out->ks2.ks;
185 }
186 return 1;
187 } else if (type != EVP_CTRL_INIT) {
188 return -1;
189 }
190 // key1 and key2 are used as an indicator both key and IV are set
191 xctx->xts.key1 = NULL;
192 xctx->xts.key2 = NULL;
193 return 1;
194 }
195
196 static const EVP_CIPHER aes_256_xts = {
197 /* nid= */ NID_aes_256_xts,
198 /* block_size= */ 1,
199 /* key_len= */ 64 /* 2 AES-256 keys */,
200 /* iv_len= */ 16,
201 /* ctx_size= */ sizeof(EVP_AES_XTS_CTX),
202 /* flags= */ EVP_CIPH_XTS_MODE | EVP_CIPH_CUSTOM_IV |
203 EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
204 EVP_CIPH_CUSTOM_COPY,
205 /* init= */ aes_xts_init_key,
206 /* cipher= */ aes_xts_cipher,
207 /* cleanup= */ nullptr,
208 /* ctrl= */ aes_xts_ctrl,
209 };
210
EVP_aes_256_xts(void)211 const EVP_CIPHER *EVP_aes_256_xts(void) { return &aes_256_xts; }
212