]>
Commit | Line | Data |
---|---|---|
440e5d80 | 1 | /* |
1212818e | 2 | * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. |
5b172463 | 3 | * |
ab3fa1c0 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
440e5d80 RS |
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 | |
5b172463 AP |
8 | */ |
9 | ||
5b172463 AP |
10 | #include <stdio.h> |
11 | #include <string.h> | |
12 | ||
63d74075 | 13 | #include <openssl/opensslconf.h> |
5b172463 | 14 | #include <openssl/crypto.h> |
5b172463 AP |
15 | #include <openssl/engine.h> |
16 | #include <openssl/evp.h> | |
5158c763 | 17 | #include <openssl/aes.h> |
c7439661 | 18 | #include <openssl/rand.h> |
3eeaab4b | 19 | #include <openssl/err.h> |
50452b2e | 20 | #include <openssl/modes.h> |
5b172463 | 21 | |
469ce8ff | 22 | #ifndef OPENSSL_NO_PADLOCKENG |
5b172463 | 23 | |
0f113f3e MC |
24 | /* |
25 | * VIA PadLock AES is available *ONLY* on some x86 CPUs. Not only that it | |
26 | * doesn't exist elsewhere, but it even can't be compiled on other platforms! | |
27 | */ | |
28 | ||
469ce8ff RL |
29 | # undef COMPILE_PADLOCKENG |
30 | # if defined(PADLOCK_ASM) | |
31 | # define COMPILE_PADLOCKENG | |
32 | # ifdef OPENSSL_NO_DYNAMIC_ENGINE | |
0f113f3e | 33 | static ENGINE *ENGINE_padlock(void); |
eb164d0b | 34 | # endif |
469ce8ff | 35 | # endif |
5b172463 | 36 | |
469ce8ff | 37 | # ifdef OPENSSL_NO_DYNAMIC_ENGINE |
b3599dbb MC |
38 | void engine_load_padlock_int(void); |
39 | void engine_load_padlock_int(void) | |
5b172463 AP |
40 | { |
41 | /* On non-x86 CPUs it just returns. */ | |
469ce8ff | 42 | # ifdef COMPILE_PADLOCKENG |
0f113f3e MC |
43 | ENGINE *toadd = ENGINE_padlock(); |
44 | if (!toadd) | |
45 | return; | |
46 | ENGINE_add(toadd); | |
47 | ENGINE_free(toadd); | |
48 | ERR_clear_error(); | |
469ce8ff | 49 | # endif |
5b172463 AP |
50 | } |
51 | ||
469ce8ff | 52 | # endif |
eb164d0b | 53 | |
469ce8ff | 54 | # ifdef COMPILE_PADLOCKENG |
c38ff58b | 55 | |
5b172463 AP |
56 | /* Function for ENGINE detection and control */ |
57 | static int padlock_available(void); | |
58 | static int padlock_init(ENGINE *e); | |
59 | ||
60 | /* RNG Stuff */ | |
61 | static RAND_METHOD padlock_rand; | |
62 | ||
63 | /* Cipher Stuff */ | |
0f113f3e MC |
64 | static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, |
65 | const int **nids, int nid); | |
5b172463 AP |
66 | |
67 | /* Engine names */ | |
68 | static const char *padlock_id = "padlock"; | |
69 | static char padlock_name[100]; | |
70 | ||
71 | /* Available features */ | |
0f113f3e MC |
72 | static int padlock_use_ace = 0; /* Advanced Cryptography Engine */ |
73 | static int padlock_use_rng = 0; /* Random Number Generator */ | |
5b172463 AP |
74 | |
75 | /* ===== Engine "management" functions ===== */ | |
76 | ||
77 | /* Prepare the ENGINE structure for registration */ | |
0f113f3e | 78 | static int padlock_bind_helper(ENGINE *e) |
5b172463 | 79 | { |
0f113f3e MC |
80 | /* Check available features */ |
81 | padlock_available(); | |
82 | ||
6f91b017 RS |
83 | /* |
84 | * RNG is currently disabled for reasons discussed in commentary just | |
85 | * before padlock_rand_bytes function. | |
86 | */ | |
0f113f3e | 87 | padlock_use_rng = 0; |
0f113f3e MC |
88 | |
89 | /* Generate a nice engine name with available features */ | |
90 | BIO_snprintf(padlock_name, sizeof(padlock_name), | |
91 | "VIA PadLock (%s, %s)", | |
92 | padlock_use_rng ? "RNG" : "no-RNG", | |
93 | padlock_use_ace ? "ACE" : "no-ACE"); | |
94 | ||
95 | /* Register everything or return with an error */ | |
96 | if (!ENGINE_set_id(e, padlock_id) || | |
97 | !ENGINE_set_name(e, padlock_name) || | |
98 | !ENGINE_set_init_function(e, padlock_init) || | |
0f113f3e | 99 | (padlock_use_ace && !ENGINE_set_ciphers(e, padlock_ciphers)) || |
0f113f3e MC |
100 | (padlock_use_rng && !ENGINE_set_RAND(e, &padlock_rand))) { |
101 | return 0; | |
102 | } | |
103 | ||
104 | /* Everything looks good */ | |
105 | return 1; | |
5b172463 AP |
106 | } |
107 | ||
469ce8ff | 108 | # ifdef OPENSSL_NO_DYNAMIC_ENGINE |
5b172463 | 109 | /* Constructor */ |
0f113f3e | 110 | static ENGINE *ENGINE_padlock(void) |
5b172463 | 111 | { |
0f113f3e | 112 | ENGINE *eng = ENGINE_new(); |
5b172463 | 113 | |
55646005 | 114 | if (eng == NULL) { |
0f113f3e MC |
115 | return NULL; |
116 | } | |
5b172463 | 117 | |
0f113f3e MC |
118 | if (!padlock_bind_helper(eng)) { |
119 | ENGINE_free(eng); | |
120 | return NULL; | |
121 | } | |
5b172463 | 122 | |
0f113f3e | 123 | return eng; |
5b172463 | 124 | } |
469ce8ff | 125 | # endif |
5b172463 AP |
126 | |
127 | /* Check availability of the engine */ | |
0f113f3e | 128 | static int padlock_init(ENGINE *e) |
5b172463 | 129 | { |
0f113f3e | 130 | return (padlock_use_rng || padlock_use_ace); |
5b172463 AP |
131 | } |
132 | ||
0f113f3e MC |
133 | /* |
134 | * This stuff is needed if this ENGINE is being compiled into a | |
135 | * self-contained shared-library. | |
5b172463 | 136 | */ |
469ce8ff | 137 | # ifndef OPENSSL_NO_DYNAMIC_ENGINE |
0f113f3e | 138 | static int padlock_bind_fn(ENGINE *e, const char *id) |
5b172463 | 139 | { |
0f113f3e MC |
140 | if (id && (strcmp(id, padlock_id) != 0)) { |
141 | return 0; | |
142 | } | |
5b172463 | 143 | |
0f113f3e MC |
144 | if (!padlock_bind_helper(e)) { |
145 | return 0; | |
146 | } | |
5b172463 | 147 | |
0f113f3e | 148 | return 1; |
5b172463 AP |
149 | } |
150 | ||
097f9d8c | 151 | IMPLEMENT_DYNAMIC_CHECK_FN() |
a57bfe43 | 152 | IMPLEMENT_DYNAMIC_BIND_FN(padlock_bind_fn) |
469ce8ff | 153 | # endif /* !OPENSSL_NO_DYNAMIC_ENGINE */ |
5b172463 | 154 | /* ===== Here comes the "real" engine ===== */ |
5158c763 | 155 | |
5b172463 | 156 | /* Some AES-related constants */ |
469ce8ff RL |
157 | # define AES_BLOCK_SIZE 16 |
158 | # define AES_KEY_SIZE_128 16 | |
159 | # define AES_KEY_SIZE_192 24 | |
160 | # define AES_KEY_SIZE_256 32 | |
0f113f3e MC |
161 | /* |
162 | * Here we store the status information relevant to the current context. | |
163 | */ | |
164 | /* | |
165 | * BIG FAT WARNING: Inline assembler in PADLOCK_XCRYPT_ASM() depends on | |
166 | * the order of items in this structure. Don't blindly modify, reorder, | |
167 | * etc! | |
168 | */ | |
169 | struct padlock_cipher_data { | |
170 | unsigned char iv[AES_BLOCK_SIZE]; /* Initialization vector */ | |
171 | union { | |
172 | unsigned int pad[4]; | |
173 | struct { | |
174 | int rounds:4; | |
175 | int dgst:1; /* n/a in C3 */ | |
176 | int align:1; /* n/a in C3 */ | |
177 | int ciphr:1; /* n/a in C3 */ | |
178 | unsigned int keygen:1; | |
179 | int interm:1; | |
180 | unsigned int encdec:1; | |
181 | int ksize:2; | |
182 | } b; | |
183 | } cword; /* Control word */ | |
184 | AES_KEY ks; /* Encryption key */ | |
5b172463 | 185 | }; |
127186bf | 186 | |
ed28aef8 | 187 | /* Interface to assembler module */ |
3f5abab9 | 188 | unsigned int padlock_capability(void); |
ed28aef8 AP |
189 | void padlock_key_bswap(AES_KEY *key); |
190 | void padlock_verify_context(struct padlock_cipher_data *ctx); | |
3f5abab9 | 191 | void padlock_reload_key(void); |
ed28aef8 | 192 | void padlock_aes_block(void *out, const void *inp, |
0f113f3e MC |
193 | struct padlock_cipher_data *ctx); |
194 | int padlock_ecb_encrypt(void *out, const void *inp, | |
195 | struct padlock_cipher_data *ctx, size_t len); | |
196 | int padlock_cbc_encrypt(void *out, const void *inp, | |
197 | struct padlock_cipher_data *ctx, size_t len); | |
198 | int padlock_cfb_encrypt(void *out, const void *inp, | |
199 | struct padlock_cipher_data *ctx, size_t len); | |
200 | int padlock_ofb_encrypt(void *out, const void *inp, | |
201 | struct padlock_cipher_data *ctx, size_t len); | |
202 | int padlock_ctr32_encrypt(void *out, const void *inp, | |
203 | struct padlock_cipher_data *ctx, size_t len); | |
204 | int padlock_xstore(void *out, int edx); | |
205 | void padlock_sha1_oneshot(void *ctx, const void *inp, size_t len); | |
206 | void padlock_sha1(void *ctx, const void *inp, size_t len); | |
207 | void padlock_sha256_oneshot(void *ctx, const void *inp, size_t len); | |
208 | void padlock_sha256(void *ctx, const void *inp, size_t len); | |
209 | ||
210 | /* | |
211 | * Load supported features of the CPU to see if the PadLock is available. | |
212 | */ | |
213 | static int padlock_available(void) | |
127186bf | 214 | { |
0f113f3e | 215 | unsigned int edx = padlock_capability(); |
127186bf | 216 | |
0f113f3e MC |
217 | /* Fill up some flags */ |
218 | padlock_use_ace = ((edx & (0x3 << 6)) == (0x3 << 6)); | |
219 | padlock_use_rng = ((edx & (0x3 << 2)) == (0x3 << 2)); | |
127186bf | 220 | |
0f113f3e | 221 | return padlock_use_ace + padlock_use_rng; |
127186bf AP |
222 | } |
223 | ||
5b172463 AP |
224 | /* ===== AES encryption/decryption ===== */ |
225 | ||
469ce8ff RL |
226 | # if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb) |
227 | # define NID_aes_128_cfb NID_aes_128_cfb128 | |
228 | # endif | |
5b172463 | 229 | |
469ce8ff RL |
230 | # if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb) |
231 | # define NID_aes_128_ofb NID_aes_128_ofb128 | |
232 | # endif | |
5b172463 | 233 | |
469ce8ff RL |
234 | # if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb) |
235 | # define NID_aes_192_cfb NID_aes_192_cfb128 | |
236 | # endif | |
5b172463 | 237 | |
469ce8ff RL |
238 | # if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb) |
239 | # define NID_aes_192_ofb NID_aes_192_ofb128 | |
240 | # endif | |
5b172463 | 241 | |
469ce8ff RL |
242 | # if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb) |
243 | # define NID_aes_256_cfb NID_aes_256_cfb128 | |
244 | # endif | |
5b172463 | 245 | |
469ce8ff RL |
246 | # if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb) |
247 | # define NID_aes_256_ofb NID_aes_256_ofb128 | |
248 | # endif | |
5b172463 AP |
249 | |
250 | /* List of supported ciphers. */ | |
f756fb43 | 251 | static const int padlock_cipher_nids[] = { |
0f113f3e MC |
252 | NID_aes_128_ecb, |
253 | NID_aes_128_cbc, | |
254 | NID_aes_128_cfb, | |
255 | NID_aes_128_ofb, | |
256 | NID_aes_128_ctr, | |
257 | ||
258 | NID_aes_192_ecb, | |
259 | NID_aes_192_cbc, | |
260 | NID_aes_192_cfb, | |
261 | NID_aes_192_ofb, | |
262 | NID_aes_192_ctr, | |
263 | ||
264 | NID_aes_256_ecb, | |
265 | NID_aes_256_cbc, | |
266 | NID_aes_256_cfb, | |
267 | NID_aes_256_ofb, | |
268 | NID_aes_256_ctr | |
5b172463 | 269 | }; |
0f113f3e MC |
270 | |
271 | static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids) / | |
272 | sizeof(padlock_cipher_nids[0])); | |
5b172463 AP |
273 | |
274 | /* Function prototypes ... */ | |
275 | static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, | |
0f113f3e | 276 | const unsigned char *iv, int enc); |
5b172463 | 277 | |
469ce8ff | 278 | # define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) + \ |
0f113f3e | 279 | ( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F ) ) |
469ce8ff | 280 | # define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\ |
44ab2dfd | 281 | NEAREST_ALIGNED(EVP_CIPHER_CTX_get_cipher_data(ctx))) |
5b172463 | 282 | |
ed28aef8 AP |
283 | static int |
284 | padlock_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, | |
0f113f3e | 285 | const unsigned char *in_arg, size_t nbytes) |
ed28aef8 | 286 | { |
0f113f3e MC |
287 | return padlock_ecb_encrypt(out_arg, in_arg, |
288 | ALIGNED_CIPHER_DATA(ctx), nbytes); | |
ed28aef8 | 289 | } |
0f113f3e | 290 | |
ed28aef8 AP |
291 | static int |
292 | padlock_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, | |
0f113f3e | 293 | const unsigned char *in_arg, size_t nbytes) |
ed28aef8 | 294 | { |
0f113f3e MC |
295 | struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); |
296 | int ret; | |
ed28aef8 | 297 | |
936166af | 298 | memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); |
0f113f3e | 299 | if ((ret = padlock_cbc_encrypt(out_arg, in_arg, cdata, nbytes))) |
936166af | 300 | memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); |
0f113f3e | 301 | return ret; |
ed28aef8 AP |
302 | } |
303 | ||
304 | static int | |
305 | padlock_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, | |
0f113f3e | 306 | const unsigned char *in_arg, size_t nbytes) |
ed28aef8 | 307 | { |
0f113f3e MC |
308 | struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); |
309 | size_t chunk; | |
310 | ||
936166af RL |
311 | if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */ |
312 | unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx); | |
0f113f3e MC |
313 | |
314 | if (chunk >= AES_BLOCK_SIZE) | |
315 | return 0; /* bogus value */ | |
316 | ||
936166af | 317 | if (EVP_CIPHER_CTX_encrypting(ctx)) |
0f113f3e MC |
318 | while (chunk < AES_BLOCK_SIZE && nbytes != 0) { |
319 | ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk]; | |
320 | chunk++, nbytes--; | |
321 | } else | |
322 | while (chunk < AES_BLOCK_SIZE && nbytes != 0) { | |
323 | unsigned char c = *(in_arg++); | |
324 | *(out_arg++) = c ^ ivp[chunk]; | |
325 | ivp[chunk++] = c, nbytes--; | |
326 | } | |
327 | ||
936166af | 328 | EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE); |
0f113f3e MC |
329 | } |
330 | ||
331 | if (nbytes == 0) | |
332 | return 1; | |
333 | ||
936166af | 334 | memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); |
0f113f3e MC |
335 | |
336 | if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) { | |
337 | if (!padlock_cfb_encrypt(out_arg, in_arg, cdata, chunk)) | |
338 | return 0; | |
339 | nbytes -= chunk; | |
340 | } | |
341 | ||
342 | if (nbytes) { | |
343 | unsigned char *ivp = cdata->iv; | |
344 | ||
345 | out_arg += chunk; | |
346 | in_arg += chunk; | |
936166af | 347 | EVP_CIPHER_CTX_set_num(ctx, nbytes); |
0f113f3e MC |
348 | if (cdata->cword.b.encdec) { |
349 | cdata->cword.b.encdec = 0; | |
350 | padlock_reload_key(); | |
351 | padlock_aes_block(ivp, ivp, cdata); | |
352 | cdata->cword.b.encdec = 1; | |
353 | padlock_reload_key(); | |
354 | while (nbytes) { | |
355 | unsigned char c = *(in_arg++); | |
356 | *(out_arg++) = c ^ *ivp; | |
357 | *(ivp++) = c, nbytes--; | |
358 | } | |
359 | } else { | |
360 | padlock_reload_key(); | |
361 | padlock_aes_block(ivp, ivp, cdata); | |
362 | padlock_reload_key(); | |
363 | while (nbytes) { | |
364 | *ivp = *(out_arg++) = *(in_arg++) ^ *ivp; | |
365 | ivp++, nbytes--; | |
366 | } | |
367 | } | |
368 | } | |
369 | ||
936166af | 370 | memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); |
0f113f3e MC |
371 | |
372 | return 1; | |
ed28aef8 AP |
373 | } |
374 | ||
375 | static int | |
376 | padlock_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, | |
0f113f3e | 377 | const unsigned char *in_arg, size_t nbytes) |
ed28aef8 | 378 | { |
0f113f3e MC |
379 | struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); |
380 | size_t chunk; | |
381 | ||
382 | /* | |
383 | * ctx->num is maintained in byte-oriented modes, such as CFB and OFB... | |
384 | */ | |
936166af RL |
385 | if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */ |
386 | unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx); | |
0f113f3e MC |
387 | |
388 | if (chunk >= AES_BLOCK_SIZE) | |
389 | return 0; /* bogus value */ | |
390 | ||
391 | while (chunk < AES_BLOCK_SIZE && nbytes != 0) { | |
392 | *(out_arg++) = *(in_arg++) ^ ivp[chunk]; | |
393 | chunk++, nbytes--; | |
394 | } | |
395 | ||
936166af | 396 | EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE); |
0f113f3e MC |
397 | } |
398 | ||
399 | if (nbytes == 0) | |
400 | return 1; | |
401 | ||
936166af | 402 | memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); |
0f113f3e MC |
403 | |
404 | if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) { | |
405 | if (!padlock_ofb_encrypt(out_arg, in_arg, cdata, chunk)) | |
406 | return 0; | |
407 | nbytes -= chunk; | |
408 | } | |
409 | ||
410 | if (nbytes) { | |
411 | unsigned char *ivp = cdata->iv; | |
412 | ||
413 | out_arg += chunk; | |
414 | in_arg += chunk; | |
936166af | 415 | EVP_CIPHER_CTX_set_num(ctx, nbytes); |
0f113f3e MC |
416 | padlock_reload_key(); /* empirically found */ |
417 | padlock_aes_block(ivp, ivp, cdata); | |
418 | padlock_reload_key(); /* empirically found */ | |
419 | while (nbytes) { | |
420 | *(out_arg++) = *(in_arg++) ^ *ivp; | |
421 | ivp++, nbytes--; | |
422 | } | |
423 | } | |
424 | ||
936166af | 425 | memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); |
0f113f3e MC |
426 | |
427 | return 1; | |
ed28aef8 AP |
428 | } |
429 | ||
50452b2e | 430 | static void padlock_ctr32_encrypt_glue(const unsigned char *in, |
0f113f3e MC |
431 | unsigned char *out, size_t blocks, |
432 | struct padlock_cipher_data *ctx, | |
433 | const unsigned char *ivec) | |
50452b2e | 434 | { |
0f113f3e MC |
435 | memcpy(ctx->iv, ivec, AES_BLOCK_SIZE); |
436 | padlock_ctr32_encrypt(out, in, ctx, AES_BLOCK_SIZE * blocks); | |
50452b2e AP |
437 | } |
438 | ||
439 | static int | |
440 | padlock_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, | |
0f113f3e | 441 | const unsigned char *in_arg, size_t nbytes) |
50452b2e | 442 | { |
0f113f3e | 443 | struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); |
936166af | 444 | unsigned int num = EVP_CIPHER_CTX_num(ctx); |
50452b2e | 445 | |
0f113f3e | 446 | CRYPTO_ctr128_encrypt_ctr32(in_arg, out_arg, nbytes, |
936166af RL |
447 | cdata, EVP_CIPHER_CTX_iv_noconst(ctx), |
448 | EVP_CIPHER_CTX_buf_noconst(ctx), &num, | |
0f113f3e | 449 | (ctr128_f) padlock_ctr32_encrypt_glue); |
50452b2e | 450 | |
936166af | 451 | EVP_CIPHER_CTX_set_num(ctx, (size_t)num); |
0f113f3e | 452 | return 1; |
50452b2e AP |
453 | } |
454 | ||
469ce8ff RL |
455 | # define EVP_CIPHER_block_size_ECB AES_BLOCK_SIZE |
456 | # define EVP_CIPHER_block_size_CBC AES_BLOCK_SIZE | |
457 | # define EVP_CIPHER_block_size_OFB 1 | |
458 | # define EVP_CIPHER_block_size_CFB 1 | |
459 | # define EVP_CIPHER_block_size_CTR 1 | |
0f113f3e MC |
460 | |
461 | /* | |
462 | * Declaring so many ciphers by hand would be a pain. Instead introduce a bit | |
463 | * of preprocessor magic :-) | |
464 | */ | |
469ce8ff | 465 | # define DECLARE_AES_EVP(ksize,lmode,umode) \ |
39e8d0ce RL |
466 | static EVP_CIPHER *_hidden_aes_##ksize##_##lmode = NULL; \ |
467 | static const EVP_CIPHER *padlock_aes_##ksize##_##lmode(void) \ | |
468 | { \ | |
469 | if (_hidden_aes_##ksize##_##lmode == NULL \ | |
470 | && ((_hidden_aes_##ksize##_##lmode = \ | |
471 | EVP_CIPHER_meth_new(NID_aes_##ksize##_##lmode, \ | |
472 | EVP_CIPHER_block_size_##umode, \ | |
473 | AES_KEY_SIZE_##ksize)) == NULL \ | |
474 | || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_##ksize##_##lmode, \ | |
475 | AES_BLOCK_SIZE) \ | |
476 | || !EVP_CIPHER_meth_set_flags(_hidden_aes_##ksize##_##lmode, \ | |
477 | 0 | EVP_CIPH_##umode##_MODE) \ | |
478 | || !EVP_CIPHER_meth_set_init(_hidden_aes_##ksize##_##lmode, \ | |
479 | padlock_aes_init_key) \ | |
480 | || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_##ksize##_##lmode, \ | |
481 | padlock_##lmode##_cipher) \ | |
482 | || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_##ksize##_##lmode, \ | |
483 | sizeof(struct padlock_cipher_data) + 16) \ | |
484 | || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_aes_##ksize##_##lmode, \ | |
485 | EVP_CIPHER_set_asn1_iv) \ | |
486 | || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_aes_##ksize##_##lmode, \ | |
487 | EVP_CIPHER_get_asn1_iv))) { \ | |
488 | EVP_CIPHER_meth_free(_hidden_aes_##ksize##_##lmode); \ | |
489 | _hidden_aes_##ksize##_##lmode = NULL; \ | |
490 | } \ | |
491 | return _hidden_aes_##ksize##_##lmode; \ | |
5b172463 AP |
492 | } |
493 | ||
39e8d0ce RL |
494 | DECLARE_AES_EVP(128, ecb, ECB) |
495 | DECLARE_AES_EVP(128, cbc, CBC) | |
496 | DECLARE_AES_EVP(128, cfb, CFB) | |
497 | DECLARE_AES_EVP(128, ofb, OFB) | |
498 | DECLARE_AES_EVP(128, ctr, CTR) | |
5b172463 | 499 | |
39e8d0ce RL |
500 | DECLARE_AES_EVP(192, ecb, ECB) |
501 | DECLARE_AES_EVP(192, cbc, CBC) | |
502 | DECLARE_AES_EVP(192, cfb, CFB) | |
503 | DECLARE_AES_EVP(192, ofb, OFB) | |
504 | DECLARE_AES_EVP(192, ctr, CTR) | |
5b172463 | 505 | |
39e8d0ce RL |
506 | DECLARE_AES_EVP(256, ecb, ECB) |
507 | DECLARE_AES_EVP(256, cbc, CBC) | |
508 | DECLARE_AES_EVP(256, cfb, CFB) | |
509 | DECLARE_AES_EVP(256, ofb, OFB) | |
510 | DECLARE_AES_EVP(256, ctr, CTR) | |
5b172463 AP |
511 | |
512 | static int | |
0f113f3e MC |
513 | padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, |
514 | int nid) | |
5b172463 | 515 | { |
0f113f3e MC |
516 | /* No specific cipher => return a list of supported nids ... */ |
517 | if (!cipher) { | |
518 | *nids = padlock_cipher_nids; | |
519 | return padlock_cipher_nids_num; | |
520 | } | |
521 | ||
522 | /* ... or the requested "cipher" otherwise */ | |
523 | switch (nid) { | |
524 | case NID_aes_128_ecb: | |
39e8d0ce | 525 | *cipher = padlock_aes_128_ecb(); |
0f113f3e MC |
526 | break; |
527 | case NID_aes_128_cbc: | |
39e8d0ce | 528 | *cipher = padlock_aes_128_cbc(); |
0f113f3e MC |
529 | break; |
530 | case NID_aes_128_cfb: | |
39e8d0ce | 531 | *cipher = padlock_aes_128_cfb(); |
0f113f3e MC |
532 | break; |
533 | case NID_aes_128_ofb: | |
39e8d0ce | 534 | *cipher = padlock_aes_128_ofb(); |
0f113f3e MC |
535 | break; |
536 | case NID_aes_128_ctr: | |
39e8d0ce | 537 | *cipher = padlock_aes_128_ctr(); |
0f113f3e MC |
538 | break; |
539 | ||
540 | case NID_aes_192_ecb: | |
39e8d0ce | 541 | *cipher = padlock_aes_192_ecb(); |
0f113f3e MC |
542 | break; |
543 | case NID_aes_192_cbc: | |
39e8d0ce | 544 | *cipher = padlock_aes_192_cbc(); |
0f113f3e MC |
545 | break; |
546 | case NID_aes_192_cfb: | |
39e8d0ce | 547 | *cipher = padlock_aes_192_cfb(); |
0f113f3e MC |
548 | break; |
549 | case NID_aes_192_ofb: | |
39e8d0ce | 550 | *cipher = padlock_aes_192_ofb(); |
0f113f3e MC |
551 | break; |
552 | case NID_aes_192_ctr: | |
39e8d0ce | 553 | *cipher = padlock_aes_192_ctr(); |
0f113f3e MC |
554 | break; |
555 | ||
556 | case NID_aes_256_ecb: | |
39e8d0ce | 557 | *cipher = padlock_aes_256_ecb(); |
0f113f3e MC |
558 | break; |
559 | case NID_aes_256_cbc: | |
39e8d0ce | 560 | *cipher = padlock_aes_256_cbc(); |
0f113f3e MC |
561 | break; |
562 | case NID_aes_256_cfb: | |
39e8d0ce | 563 | *cipher = padlock_aes_256_cfb(); |
0f113f3e MC |
564 | break; |
565 | case NID_aes_256_ofb: | |
39e8d0ce | 566 | *cipher = padlock_aes_256_ofb(); |
0f113f3e MC |
567 | break; |
568 | case NID_aes_256_ctr: | |
39e8d0ce | 569 | *cipher = padlock_aes_256_ctr(); |
0f113f3e MC |
570 | break; |
571 | ||
572 | default: | |
573 | /* Sorry, we don't support this NID */ | |
574 | *cipher = NULL; | |
575 | return 0; | |
576 | } | |
577 | ||
578 | return 1; | |
5b172463 AP |
579 | } |
580 | ||
581 | /* Prepare the encryption key for PadLock usage */ | |
582 | static int | |
0f113f3e MC |
583 | padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, |
584 | const unsigned char *iv, int enc) | |
5b172463 | 585 | { |
0f113f3e MC |
586 | struct padlock_cipher_data *cdata; |
587 | int key_len = EVP_CIPHER_CTX_key_length(ctx) * 8; | |
588 | unsigned long mode = EVP_CIPHER_CTX_mode(ctx); | |
589 | ||
590 | if (key == NULL) | |
591 | return 0; /* ERROR */ | |
592 | ||
593 | cdata = ALIGNED_CIPHER_DATA(ctx); | |
16f8d4eb | 594 | memset(cdata, 0, sizeof(*cdata)); |
0f113f3e MC |
595 | |
596 | /* Prepare Control word. */ | |
597 | if (mode == EVP_CIPH_OFB_MODE || mode == EVP_CIPH_CTR_MODE) | |
598 | cdata->cword.b.encdec = 0; | |
599 | else | |
936166af | 600 | cdata->cword.b.encdec = (EVP_CIPHER_CTX_encrypting(ctx) == 0); |
0f113f3e MC |
601 | cdata->cword.b.rounds = 10 + (key_len - 128) / 32; |
602 | cdata->cword.b.ksize = (key_len - 128) / 64; | |
603 | ||
604 | switch (key_len) { | |
605 | case 128: | |
606 | /* | |
607 | * PadLock can generate an extended key for AES128 in hardware | |
608 | */ | |
609 | memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128); | |
610 | cdata->cword.b.keygen = 0; | |
611 | break; | |
612 | ||
613 | case 192: | |
614 | case 256: | |
615 | /* | |
616 | * Generate an extended AES key in software. Needed for AES192/AES256 | |
617 | */ | |
618 | /* | |
619 | * Well, the above applies to Stepping 8 CPUs and is listed as | |
620 | * hardware errata. They most likely will fix it at some point and | |
621 | * then a check for stepping would be due here. | |
622 | */ | |
623 | if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) | |
624 | && !enc) | |
625 | AES_set_decrypt_key(key, key_len, &cdata->ks); | |
626 | else | |
627 | AES_set_encrypt_key(key, key_len, &cdata->ks); | |
469ce8ff | 628 | # ifndef AES_ASM |
0f113f3e MC |
629 | /* |
630 | * OpenSSL C functions use byte-swapped extended key. | |
631 | */ | |
632 | padlock_key_bswap(&cdata->ks); | |
469ce8ff | 633 | # endif |
0f113f3e MC |
634 | cdata->cword.b.keygen = 1; |
635 | break; | |
636 | ||
637 | default: | |
638 | /* ERROR */ | |
639 | return 0; | |
640 | } | |
641 | ||
642 | /* | |
643 | * This is done to cover for cases when user reuses the | |
644 | * context for new key. The catch is that if we don't do | |
645 | * this, padlock_eas_cipher might proceed with old key... | |
646 | */ | |
647 | padlock_reload_key(); | |
648 | ||
649 | return 1; | |
5b172463 AP |
650 | } |
651 | ||
5b172463 AP |
652 | /* ===== Random Number Generator ===== */ |
653 | /* | |
654 | * This code is not engaged. The reason is that it does not comply | |
655 | * with recommendations for VIA RNG usage for secure applications | |
656 | * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it | |
657 | * provide meaningful error control... | |
658 | */ | |
0f113f3e MC |
659 | /* |
660 | * Wrapper that provides an interface between the API and the raw PadLock | |
661 | * RNG | |
662 | */ | |
663 | static int padlock_rand_bytes(unsigned char *output, int count) | |
5b172463 | 664 | { |
0f113f3e MC |
665 | unsigned int eax, buf; |
666 | ||
667 | while (count >= 8) { | |
668 | eax = padlock_xstore(output, 0); | |
669 | if (!(eax & (1 << 6))) | |
670 | return 0; /* RNG disabled */ | |
671 | /* this ---vv--- covers DC bias, Raw Bits and String Filter */ | |
672 | if (eax & (0x1F << 10)) | |
673 | return 0; | |
674 | if ((eax & 0x1F) == 0) | |
675 | continue; /* no data, retry... */ | |
676 | if ((eax & 0x1F) != 8) | |
677 | return 0; /* fatal failure... */ | |
678 | output += 8; | |
679 | count -= 8; | |
680 | } | |
681 | while (count > 0) { | |
682 | eax = padlock_xstore(&buf, 3); | |
683 | if (!(eax & (1 << 6))) | |
684 | return 0; /* RNG disabled */ | |
685 | /* this ---vv--- covers DC bias, Raw Bits and String Filter */ | |
686 | if (eax & (0x1F << 10)) | |
687 | return 0; | |
688 | if ((eax & 0x1F) == 0) | |
689 | continue; /* no data, retry... */ | |
690 | if ((eax & 0x1F) != 1) | |
691 | return 0; /* fatal failure... */ | |
692 | *output++ = (unsigned char)buf; | |
693 | count--; | |
694 | } | |
6c13488c | 695 | OPENSSL_cleanse(&buf, sizeof(buf)); |
0f113f3e MC |
696 | |
697 | return 1; | |
5b172463 AP |
698 | } |
699 | ||
700 | /* Dummy but necessary function */ | |
0f113f3e | 701 | static int padlock_rand_status(void) |
5b172463 | 702 | { |
0f113f3e | 703 | return 1; |
5b172463 AP |
704 | } |
705 | ||
706 | /* Prepare structure for registration */ | |
707 | static RAND_METHOD padlock_rand = { | |
0f113f3e MC |
708 | NULL, /* seed */ |
709 | padlock_rand_bytes, /* bytes */ | |
710 | NULL, /* cleanup */ | |
711 | NULL, /* add */ | |
712 | padlock_rand_bytes, /* pseudorand */ | |
713 | padlock_rand_status, /* rand status */ | |
5b172463 AP |
714 | }; |
715 | ||
469ce8ff RL |
716 | # endif /* COMPILE_PADLOCKENG */ |
717 | #endif /* !OPENSSL_NO_PADLOCKENG */ | |
a57bfe43 | 718 | |
469ce8ff | 719 | #if defined(OPENSSL_NO_PADLOCKENG) || !defined(COMPILE_PADLOCKENG) |
a57bfe43 | 720 | # ifndef OPENSSL_NO_DYNAMIC_ENGINE |
e6b0c000 | 721 | OPENSSL_EXPORT |
0f113f3e | 722 | int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); |
eb164d0b | 723 | OPENSSL_EXPORT |
0f113f3e MC |
724 | int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) |
725 | { | |
726 | return 0; | |
727 | } | |
5b172463 | 728 | |
0f113f3e | 729 | IMPLEMENT_DYNAMIC_CHECK_FN() |
a57bfe43 MC |
730 | # endif |
731 | #endif |