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