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