• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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