Line data Source code
1 : /*
2 : * Copyright (C) 2011-2018 Free Software Foundation, Inc.
3 : * Copyright (C) 2018 Red Hat, Inc.
4 : *
5 : * Author: Nikos Mavrogiannopoulos
6 : *
7 : * This file is part of GnuTLS.
8 : *
9 : * The GnuTLS is free software; you can redistribute it and/or
10 : * modify it under the terms of the GNU Lesser General Public License
11 : * as published by the Free Software Foundation; either version 2.1 of
12 : * the License, or (at your option) any later version.
13 : *
14 : * This library is distributed in the hope that it will be useful, but
15 : * WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : * Lesser General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU Lesser General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>
21 : *
22 : */
23 :
24 : /*
25 : * The following code is an implementation of the AES-128-CBC cipher
26 : * using intel's AES instruction set.
27 : */
28 :
29 : #include "errors.h"
30 : #include "gnutls_int.h"
31 : #include <gnutls/crypto.h>
32 : #include "errors.h"
33 : #include <aes-x86.h>
34 : #include <sha-x86.h>
35 : #include <x86-common.h>
36 : #ifdef HAVE_LIBNETTLE
37 : # include <nettle/aes.h> /* for key generation in 192 and 256 bits */
38 : # include <sha-padlock.h>
39 : #endif
40 : #include <aes-padlock.h>
41 : #ifdef HAVE_CPUID_H
42 : # include <cpuid.h>
43 : #else
44 : # define __get_cpuid(...) 0
45 : # define __get_cpuid_count(...) 0
46 : #endif
47 :
48 : /* ebx, ecx, edx
49 : * This is a format compatible with openssl's CPUID detection.
50 : */
51 : #if defined(__GNUC__)
52 : __attribute__((visibility("hidden")))
53 : #elif defined(__SUNPRO_C)
54 : __hidden
55 : #endif
56 : unsigned int _gnutls_x86_cpuid_s[4];
57 :
58 : #ifndef bit_SHA
59 : # define bit_SHA (1<<29)
60 : #endif
61 :
62 : /* ecx */
63 : #ifndef bit_AVX512BITALG
64 : # define bit_AVX512BITALG 0x4000
65 : #endif
66 :
67 : #ifndef bit_PCLMUL
68 : # define bit_PCLMUL 0x2
69 : #endif
70 :
71 : #ifndef bit_SSSE3
72 : /* ecx */
73 : # define bit_SSSE3 0x0000200
74 : #endif
75 :
76 : #ifndef bit_AES
77 : # define bit_AES 0x2000000
78 : #endif
79 :
80 : #ifndef bit_AVX
81 : # define bit_AVX 0x10000000
82 : #endif
83 :
84 : #ifndef OSXSAVE_MASK
85 : /* OSXSAVE|MOVBE */
86 : # define OSXSAVE_MASK (0x8000000|0x400000)
87 : #endif
88 :
89 : #ifndef bit_MOVBE
90 : # define bit_MOVBE 0x00400000
91 : #endif
92 :
93 : #define bit_PADLOCK (0x3 << 6)
94 : #define bit_PADLOCK_PHE (0x3 << 10)
95 : #define bit_PADLOCK_PHE_SHA512 (0x3 << 25)
96 :
97 : /* Our internal bit-string for cpu capabilities. Should be set
98 : * in GNUTLS_CPUID_OVERRIDE */
99 : #define EMPTY_SET 1
100 : #define INTEL_AES_NI (1<<1)
101 : #define INTEL_SSSE3 (1<<2)
102 : #define INTEL_PCLMUL (1<<3)
103 : #define INTEL_AVX (1<<4)
104 : #define INTEL_SHA (1<<5)
105 : #define PADLOCK (1<<20)
106 : #define PADLOCK_PHE (1<<21)
107 : #define PADLOCK_PHE_SHA512 (1<<22)
108 :
109 : #ifndef HAVE_GET_CPUID_COUNT
110 : static inline void
111 : get_cpuid_level7(unsigned int *eax, unsigned int *ebx,
112 : unsigned int *ecx, unsigned int *edx)
113 : {
114 : /* we avoid using __get_cpuid_count, because it is not available with gcc 4.8 */
115 : if (__get_cpuid_max(7, 0) < 7)
116 : return;
117 :
118 : __cpuid_count(7, 0, *eax, *ebx, *ecx, *edx);
119 : return;
120 : }
121 : #else
122 : # define get_cpuid_level7(a,b,c,d) __get_cpuid_count(7, 0, a, b, c, d)
123 : #endif
124 :
125 3420 : static unsigned read_cpuid_vals(unsigned int vals[4])
126 : {
127 3420 : unsigned t1, t2, t3;
128 3420 : vals[0] = vals[1] = vals[2] = vals[3] = 0;
129 :
130 3420 : if (!__get_cpuid(1, &t1, &vals[0], &vals[1], &t2))
131 : return 0;
132 : /* suppress AVX512; it works conditionally on certain CPUs on the original code */
133 3420 : vals[1] &= 0xfffff7ff;
134 :
135 3420 : get_cpuid_level7(&t1, &vals[2], &t2, &t3);
136 :
137 : return 1;
138 : }
139 :
140 : /* Based on the example in "How to detect New Instruction support in
141 : * the 4th generation Intel Core processor family.
142 : * https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family
143 : */
144 3420 : static unsigned check_4th_gen_intel_features(unsigned ecx)
145 : {
146 3420 : uint32_t xcr0;
147 :
148 3420 : if ((ecx & OSXSAVE_MASK) != OSXSAVE_MASK)
149 : return 0;
150 :
151 : #if defined(_MSC_VER) && !defined(__clang__)
152 : xcr0 = _xgetbv(0);
153 : #else
154 3420 : __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx");
155 : #endif
156 : /* Check if xmm and ymm state are enabled in XCR0. */
157 3420 : return (xcr0 & 6) == 6;
158 : }
159 :
160 11 : static void capabilities_to_intel_cpuid(unsigned capabilities)
161 : {
162 11 : unsigned a[4];
163 :
164 11 : if (capabilities & EMPTY_SET) {
165 11 : return;
166 : }
167 :
168 0 : if (!read_cpuid_vals(a))
169 : return;
170 :
171 0 : if (capabilities & INTEL_AES_NI) {
172 0 : if (a[1] & bit_AES) {
173 0 : _gnutls_x86_cpuid_s[1] |= bit_AES;
174 : } else {
175 0 : _gnutls_debug_log
176 : ("AESNI acceleration requested but not available\n");
177 : }
178 : }
179 :
180 0 : if (capabilities & INTEL_SSSE3) {
181 0 : if (a[1] & bit_SSSE3) {
182 0 : _gnutls_x86_cpuid_s[1] |= bit_SSSE3;
183 : } else {
184 0 : _gnutls_debug_log
185 : ("SSSE3 acceleration requested but not available\n");
186 : }
187 : }
188 :
189 0 : if (capabilities & INTEL_AVX) {
190 0 : if ((a[1] & bit_AVX) && check_4th_gen_intel_features(a[1])) {
191 0 : _gnutls_x86_cpuid_s[1] |= bit_AVX|OSXSAVE_MASK;
192 : } else {
193 0 : _gnutls_debug_log
194 : ("AVX acceleration requested but not available\n");
195 : }
196 : }
197 :
198 0 : if (capabilities & INTEL_PCLMUL) {
199 0 : if (a[1] & bit_PCLMUL) {
200 0 : _gnutls_x86_cpuid_s[1] |= bit_PCLMUL;
201 : } else {
202 0 : _gnutls_debug_log
203 : ("PCLMUL acceleration requested but not available\n");
204 : }
205 : }
206 :
207 0 : if (capabilities & INTEL_SHA) {
208 0 : if (a[2] & bit_SHA) {
209 0 : _gnutls_x86_cpuid_s[2] |= bit_SHA;
210 : } else {
211 0 : _gnutls_debug_log
212 : ("SHA acceleration requested but not available\n");
213 : }
214 : }
215 : }
216 :
217 :
218 3431 : static unsigned check_optimized_aes(void)
219 : {
220 3431 : return (_gnutls_x86_cpuid_s[1] & bit_AES);
221 : }
222 :
223 6862 : static unsigned check_ssse3(void)
224 : {
225 6862 : return (_gnutls_x86_cpuid_s[1] & bit_SSSE3);
226 : }
227 :
228 3431 : static unsigned check_sha(void)
229 : {
230 3431 : return (_gnutls_x86_cpuid_s[2] & bit_SHA);
231 : }
232 :
233 : #ifdef ASM_X86_64
234 3420 : static unsigned check_avx_movbe(void)
235 : {
236 3420 : if (check_4th_gen_intel_features(_gnutls_x86_cpuid_s[1]) == 0)
237 : return 0;
238 :
239 3420 : return ((_gnutls_x86_cpuid_s[1] & bit_AVX));
240 : }
241 :
242 3420 : static unsigned check_pclmul(void)
243 : {
244 3420 : return (_gnutls_x86_cpuid_s[1] & bit_PCLMUL);
245 : }
246 : #endif
247 :
248 : #ifdef ENABLE_PADLOCK
249 : static unsigned capabilities_to_zhaoxin_edx(unsigned capabilities)
250 : {
251 : unsigned a,b,c,t;
252 :
253 : if (capabilities & EMPTY_SET) {
254 : return 0;
255 : }
256 :
257 : if (!__get_cpuid(1, &t, &a, &b, &c))
258 : return 0;
259 : if (capabilities & PADLOCK) {
260 : if (c & bit_PADLOCK) {
261 : _gnutls_x86_cpuid_s[2] |= bit_PADLOCK;
262 : } else {
263 : _gnutls_debug_log
264 : ("Padlock acceleration requested but not available\n");
265 : }
266 : }
267 :
268 : if (capabilities & PADLOCK_PHE) {
269 : if (c & bit_PADLOCK_PHE) {
270 : _gnutls_x86_cpuid_s[2] |= bit_PADLOCK_PHE;
271 : } else {
272 : _gnutls_debug_log
273 : ("Padlock-PHE acceleration requested but not available\n");
274 : }
275 : }
276 :
277 : if (capabilities & PADLOCK_PHE_SHA512) {
278 : if (c & bit_PADLOCK_PHE_SHA512) {
279 : _gnutls_x86_cpuid_s[2] |= bit_PADLOCK_PHE_SHA512;
280 : } else {
281 : _gnutls_debug_log
282 : ("Padlock-PHE-SHA512 acceleration requested but not available\n");
283 : }
284 : }
285 :
286 : return _gnutls_x86_cpuid_s[2];
287 : }
288 :
289 : static int check_padlock(unsigned edx)
290 : {
291 : return ((edx & bit_PADLOCK) == bit_PADLOCK);
292 : }
293 :
294 : static int check_phe(unsigned edx)
295 : {
296 : return ((edx & bit_PADLOCK_PHE) == bit_PADLOCK_PHE);
297 : }
298 :
299 : /* We are actually checking for SHA512 */
300 : static int check_phe_sha512(unsigned edx)
301 : {
302 : return ((edx & bit_PADLOCK_PHE_SHA512) == bit_PADLOCK_PHE_SHA512);
303 : }
304 :
305 : /* On some of the Zhaoxin CPUs, pclmul has a faster acceleration effect */
306 : static int check_fast_pclmul(void)
307 : {
308 : unsigned int a,b,c,d;
309 : unsigned int family,model;
310 :
311 : if (__get_cpuid(1, &a, &b, &c, &d))
312 : return 0;
313 :
314 : family = ((a >> 8) & 0x0F);
315 : model = ((a >> 4) & 0x0F) + ((a >> 12) & 0xF0);
316 :
317 : if(((family == 0x6) && (model == 0xf || model == 0x19)) ||
318 : ((family == 0x7) && (model == 0x1B || model == 0x3B)))
319 : return 1;
320 : else
321 : return 0;
322 : }
323 :
324 : static int check_phe_partial(void)
325 : {
326 : const char text[64] =
327 : "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
328 : "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
329 : uint32_t iv[5] = { 0x67452301UL, 0xEFCDAB89UL,
330 : 0x98BADCFEUL, 0x10325476UL, 0xC3D2E1F0UL
331 : };
332 :
333 : /* If EAX is set to -1 (this is the case with padlock_sha1_blocks), the
334 : * xsha1 instruction takes a complete SHA-1 block (64 bytes), while it
335 : * takes arbitrary length data otherwise. */
336 : padlock_sha1_blocks(iv, text, 1);
337 :
338 : if (iv[0] == 0xDA4968EBUL && iv[1] == 0x2E377C1FUL &&
339 : iv[2] == 0x884E8F52UL && iv[3] == 0x83524BEBUL &&
340 : iv[4] == 0xE74EBDBDUL)
341 : return 1;
342 : else
343 : return 0;
344 : }
345 :
346 : static unsigned check_zhaoxin(void)
347 : {
348 : unsigned int a, b, c, d;
349 :
350 : if (!__get_cpuid(0, &a, &b, &c, &d))
351 : return 0;
352 :
353 : /* Zhaoxin and VIA CPU was detected */
354 : if ((memcmp(&b, "Cent", 4) == 0 &&
355 : memcmp(&d, "aurH", 4) == 0 &&
356 : memcmp(&c, "auls", 4) == 0) ||
357 : (memcmp(&b, " Sh", 4) == 0 &&
358 : memcmp(&d, "angh", 4) == 0 && memcmp(&c, "ai ", 4) == 0)) {
359 : return 1;
360 : }
361 :
362 : return 0;
363 : }
364 :
365 : static
366 : void register_x86_padlock_crypto(unsigned capabilities)
367 : {
368 : int ret, phe;
369 : unsigned edx;
370 :
371 : memset(_gnutls_x86_cpuid_s, 0, sizeof(_gnutls_x86_cpuid_s));
372 : if (check_zhaoxin() == 0)
373 : return;
374 :
375 : if (capabilities == 0){
376 : if(!read_cpuid_vals(_gnutls_x86_cpuid_s))
377 : return;
378 : edx = padlock_capability();
379 : } else{
380 : capabilities_to_intel_cpuid(capabilities);
381 : edx = capabilities_to_zhaoxin_edx(capabilities);
382 : }
383 :
384 : if (check_ssse3()) {
385 : _gnutls_debug_log("Zhaoxin SSSE3 was detected\n");
386 :
387 : ret =
388 : gnutls_crypto_single_cipher_register
389 : (GNUTLS_CIPHER_AES_128_GCM, 90,
390 : &_gnutls_aes_gcm_x86_ssse3, 0);
391 : if (ret < 0) {
392 : gnutls_assert();
393 : }
394 :
395 : ret =
396 : gnutls_crypto_single_cipher_register
397 : (GNUTLS_CIPHER_AES_192_GCM, 90,
398 : &_gnutls_aes_gcm_x86_ssse3, 0);
399 : if (ret < 0) {
400 : gnutls_assert();
401 : }
402 :
403 : ret =
404 : gnutls_crypto_single_cipher_register
405 : (GNUTLS_CIPHER_AES_256_GCM, 90,
406 : &_gnutls_aes_gcm_x86_ssse3, 0);
407 : if (ret < 0) {
408 : gnutls_assert();
409 : }
410 :
411 : ret =
412 : gnutls_crypto_single_cipher_register
413 : (GNUTLS_CIPHER_AES_128_CBC, 90, &_gnutls_aes_ssse3, 0);
414 : if (ret < 0) {
415 : gnutls_assert();
416 : }
417 :
418 : ret =
419 : gnutls_crypto_single_cipher_register
420 : (GNUTLS_CIPHER_AES_192_CBC, 90, &_gnutls_aes_ssse3, 0);
421 : if (ret < 0) {
422 : gnutls_assert();
423 : }
424 :
425 : ret =
426 : gnutls_crypto_single_cipher_register
427 : (GNUTLS_CIPHER_AES_256_CBC, 90, &_gnutls_aes_ssse3, 0);
428 : if (ret < 0) {
429 : gnutls_assert();
430 : }
431 : }
432 :
433 : if (check_sha() || check_ssse3()) {
434 : if (check_sha())
435 : _gnutls_debug_log("Zhaoxin SHA was detected\n");
436 :
437 : ret =
438 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA1,
439 : 80,
440 : &_gnutls_sha_x86_ssse3, 0);
441 : if (ret < 0) {
442 : gnutls_assert();
443 : }
444 :
445 : ret =
446 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA224,
447 : 80,
448 : &_gnutls_sha_x86_ssse3, 0);
449 : if (ret < 0) {
450 : gnutls_assert();
451 : }
452 :
453 : ret =
454 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA256,
455 : 80,
456 : &_gnutls_sha_x86_ssse3, 0);
457 : if (ret < 0) {
458 : gnutls_assert();
459 : }
460 :
461 :
462 : ret =
463 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA1,
464 : 80,
465 : &_gnutls_hmac_sha_x86_ssse3, 0);
466 : if (ret < 0)
467 : gnutls_assert();
468 :
469 : ret =
470 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA224,
471 : 80,
472 : &_gnutls_hmac_sha_x86_ssse3, 0);
473 : if (ret < 0)
474 : gnutls_assert();
475 :
476 : ret =
477 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA256,
478 : 80,
479 : &_gnutls_hmac_sha_x86_ssse3, 0);
480 : if (ret < 0)
481 : gnutls_assert();
482 :
483 : ret =
484 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA384,
485 : 80,
486 : &_gnutls_sha_x86_ssse3, 0);
487 : if (ret < 0)
488 : gnutls_assert();
489 :
490 : ret =
491 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA512,
492 : 80,
493 : &_gnutls_sha_x86_ssse3, 0);
494 : if (ret < 0)
495 : gnutls_assert();
496 : ret =
497 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA384,
498 : 80,
499 : &_gnutls_hmac_sha_x86_ssse3, 0);
500 : if (ret < 0)
501 : gnutls_assert();
502 :
503 : ret =
504 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA512,
505 : 80,
506 : &_gnutls_hmac_sha_x86_ssse3, 0);
507 : if (ret < 0)
508 : gnutls_assert();
509 : }
510 :
511 : if (check_optimized_aes()) {
512 : _gnutls_debug_log("Zhaoxin AES accelerator was detected\n");
513 : ret =
514 : gnutls_crypto_single_cipher_register
515 : (GNUTLS_CIPHER_AES_128_CBC, 80, &_gnutls_aesni_x86, 0);
516 : if (ret < 0) {
517 : gnutls_assert();
518 : }
519 :
520 : ret =
521 : gnutls_crypto_single_cipher_register
522 : (GNUTLS_CIPHER_AES_192_CBC, 80, &_gnutls_aesni_x86, 0);
523 : if (ret < 0) {
524 : gnutls_assert();
525 : }
526 :
527 : ret =
528 : gnutls_crypto_single_cipher_register
529 : (GNUTLS_CIPHER_AES_256_CBC, 80, &_gnutls_aesni_x86, 0);
530 : if (ret < 0) {
531 : gnutls_assert();
532 : }
533 :
534 : ret =
535 : gnutls_crypto_single_cipher_register
536 : (GNUTLS_CIPHER_AES_128_CCM, 80,
537 : &_gnutls_aes_ccm_x86_aesni, 0);
538 : if (ret < 0) {
539 : gnutls_assert();
540 : }
541 :
542 : ret =
543 : gnutls_crypto_single_cipher_register
544 : (GNUTLS_CIPHER_AES_256_CCM, 80,
545 : &_gnutls_aes_ccm_x86_aesni, 0);
546 : if (ret < 0) {
547 : gnutls_assert();
548 : }
549 :
550 : ret =
551 : gnutls_crypto_single_cipher_register
552 : (GNUTLS_CIPHER_AES_128_CCM_8, 80,
553 : &_gnutls_aes_ccm_x86_aesni, 0);
554 : if (ret < 0) {
555 : gnutls_assert();
556 : }
557 :
558 : ret =
559 : gnutls_crypto_single_cipher_register
560 : (GNUTLS_CIPHER_AES_256_CCM_8, 80,
561 : &_gnutls_aes_ccm_x86_aesni, 0);
562 : if (ret < 0) {
563 : gnutls_assert();
564 : }
565 :
566 : ret =
567 : gnutls_crypto_single_cipher_register
568 : (GNUTLS_CIPHER_AES_128_XTS, 80,
569 : &_gnutls_aes_xts_x86_aesni, 0);
570 : if (ret < 0) {
571 : gnutls_assert();
572 : }
573 :
574 : ret =
575 : gnutls_crypto_single_cipher_register
576 : (GNUTLS_CIPHER_AES_256_XTS, 80,
577 : &_gnutls_aes_xts_x86_aesni, 0);
578 : if (ret < 0) {
579 : gnutls_assert();
580 : }
581 :
582 : #ifdef ASM_X86_64
583 : if (check_pclmul()) {
584 : /* register GCM ciphers */
585 : _gnutls_debug_log
586 : ("Zhaoxin GCM accelerator was detected\n");
587 : if (check_avx_movbe() && !check_fast_pclmul()) {
588 : _gnutls_debug_log
589 : ("Zhaoxin GCM accelerator (AVX) was detected\n");
590 : ret =
591 : gnutls_crypto_single_cipher_register
592 : (GNUTLS_CIPHER_AES_128_GCM, 80,
593 : &_gnutls_aes_gcm_pclmul_avx, 0);
594 : if (ret < 0) {
595 : gnutls_assert();
596 : }
597 :
598 : ret =
599 : gnutls_crypto_single_cipher_register
600 : (GNUTLS_CIPHER_AES_192_GCM, 80,
601 : &_gnutls_aes_gcm_pclmul_avx, 0);
602 : if (ret < 0) {
603 : gnutls_assert();
604 : }
605 :
606 : ret =
607 : gnutls_crypto_single_cipher_register
608 : (GNUTLS_CIPHER_AES_256_GCM, 80,
609 : &_gnutls_aes_gcm_pclmul_avx, 0);
610 : if (ret < 0) {
611 : gnutls_assert();
612 : }
613 : } else {
614 : ret =
615 : gnutls_crypto_single_cipher_register
616 : (GNUTLS_CIPHER_AES_128_GCM, 80,
617 : &_gnutls_aes_gcm_pclmul, 0);
618 : if (ret < 0) {
619 : gnutls_assert();
620 : }
621 :
622 : ret =
623 : gnutls_crypto_single_cipher_register
624 : (GNUTLS_CIPHER_AES_192_GCM, 80,
625 : &_gnutls_aes_gcm_pclmul, 0);
626 : if (ret < 0) {
627 : gnutls_assert();
628 : }
629 :
630 : ret =
631 : gnutls_crypto_single_cipher_register
632 : (GNUTLS_CIPHER_AES_256_GCM, 80,
633 : &_gnutls_aes_gcm_pclmul, 0);
634 : if (ret < 0) {
635 : gnutls_assert();
636 : }
637 : }
638 : } else
639 : #endif
640 : {
641 : ret =
642 : gnutls_crypto_single_cipher_register
643 : (GNUTLS_CIPHER_AES_128_GCM, 80,
644 : &_gnutls_aes_gcm_x86_aesni, 0);
645 : if (ret < 0) {
646 : gnutls_assert();
647 : }
648 :
649 : ret =
650 : gnutls_crypto_single_cipher_register
651 : (GNUTLS_CIPHER_AES_192_GCM, 80,
652 : &_gnutls_aes_gcm_x86_aesni, 0);
653 : if (ret < 0) {
654 : gnutls_assert();
655 : }
656 :
657 : ret =
658 : gnutls_crypto_single_cipher_register
659 : (GNUTLS_CIPHER_AES_256_GCM, 80,
660 : &_gnutls_aes_gcm_x86_aesni, 0);
661 : if (ret < 0) {
662 : gnutls_assert();
663 : }
664 : }
665 : }
666 :
667 : if (check_padlock(edx)) {
668 : _gnutls_debug_log
669 : ("Padlock AES accelerator was detected\n");
670 : ret =
671 : gnutls_crypto_single_cipher_register
672 : (GNUTLS_CIPHER_AES_128_CBC, 80, &_gnutls_aes_padlock, 0);
673 : if (ret < 0) {
674 : gnutls_assert();
675 : }
676 :
677 : /* register GCM ciphers */
678 : ret =
679 : gnutls_crypto_single_cipher_register
680 : (GNUTLS_CIPHER_AES_128_GCM, 90,
681 : &_gnutls_aes_gcm_padlock, 0);
682 : if (ret < 0) {
683 : gnutls_assert();
684 : }
685 :
686 : ret =
687 : gnutls_crypto_single_cipher_register
688 : (GNUTLS_CIPHER_AES_256_CBC, 80, &_gnutls_aes_padlock, 0);
689 : if (ret < 0) {
690 : gnutls_assert();
691 : }
692 :
693 : ret =
694 : gnutls_crypto_single_cipher_register
695 : (GNUTLS_CIPHER_AES_256_GCM, 90,
696 : &_gnutls_aes_gcm_padlock, 0);
697 : if (ret < 0) {
698 : gnutls_assert();
699 : }
700 : }
701 :
702 : if(!check_optimized_aes() && !check_padlock(edx))
703 : _gnutls_priority_update_non_aesni();
704 :
705 : #ifdef HAVE_LIBNETTLE
706 : phe = check_phe(edx);
707 :
708 : if (phe && check_phe_partial()) {
709 : _gnutls_debug_log
710 : ("Padlock SHA1 and SHA256 (partial) accelerator was detected\n");
711 : if (check_phe_sha512(edx)) {
712 : _gnutls_debug_log
713 : ("Padlock SHA512 (partial) accelerator was detected\n");
714 : ret =
715 : gnutls_crypto_single_digest_register
716 : (GNUTLS_DIG_SHA384, 80,
717 : &_gnutls_sha_padlock, 0);
718 : if (ret < 0) {
719 : gnutls_assert();
720 : }
721 :
722 : ret =
723 : gnutls_crypto_single_digest_register
724 : (GNUTLS_DIG_SHA512, 80,
725 : &_gnutls_sha_padlock, 0);
726 : if (ret < 0) {
727 : gnutls_assert();
728 : }
729 :
730 : ret =
731 : gnutls_crypto_single_mac_register
732 : (GNUTLS_MAC_SHA384, 80,
733 : &_gnutls_hmac_sha_padlock, 0);
734 : if (ret < 0) {
735 : gnutls_assert();
736 : }
737 :
738 : ret =
739 : gnutls_crypto_single_mac_register
740 : (GNUTLS_MAC_SHA512, 80,
741 : &_gnutls_hmac_sha_padlock, 0);
742 : if (ret < 0) {
743 : gnutls_assert();
744 : }
745 : }
746 :
747 : ret =
748 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA1,
749 : 90,
750 : &_gnutls_sha_padlock, 0);
751 : if (ret < 0) {
752 : gnutls_assert();
753 : }
754 :
755 : ret =
756 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA224,
757 : 90,
758 : &_gnutls_sha_padlock, 0);
759 : if (ret < 0) {
760 : gnutls_assert();
761 : }
762 :
763 : ret =
764 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA256,
765 : 90,
766 : &_gnutls_sha_padlock, 0);
767 : if (ret < 0) {
768 : gnutls_assert();
769 : }
770 :
771 : ret =
772 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA1,
773 : 90,
774 : &_gnutls_hmac_sha_padlock, 0);
775 : if (ret < 0) {
776 : gnutls_assert();
777 : }
778 :
779 : /* we don't register MAC_SHA224 because it is not used by TLS */
780 :
781 : ret =
782 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA256,
783 : 90,
784 : &_gnutls_hmac_sha_padlock, 0);
785 : if (ret < 0) {
786 : gnutls_assert();
787 : }
788 : } else if (phe) {
789 : /* Original padlock PHE. Does not support incremental operations.
790 : */
791 : _gnutls_debug_log
792 : ("Padlock SHA1 and SHA256 accelerator was detected\n");
793 : ret =
794 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA1,
795 : 90,
796 : &_gnutls_sha_padlock_oneshot, 0);
797 : if (ret < 0) {
798 : gnutls_assert();
799 : }
800 :
801 : ret =
802 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA256,
803 : 90,
804 : &_gnutls_sha_padlock_oneshot, 0);
805 : if (ret < 0) {
806 : gnutls_assert();
807 : }
808 :
809 : ret =
810 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA1,
811 : 90,
812 : &_gnutls_hmac_sha_padlock_oneshot, 0);
813 : if (ret < 0) {
814 : gnutls_assert();
815 : }
816 :
817 : ret =
818 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA256,
819 : 90,
820 : &_gnutls_hmac_sha_padlock_oneshot, 0);
821 : if (ret < 0) {
822 : gnutls_assert();
823 : }
824 : }
825 : #endif
826 :
827 : return;
828 : }
829 : #endif
830 :
831 3431 : static unsigned check_intel_or_amd(void)
832 : {
833 3431 : unsigned int a, b, c, d;
834 :
835 3431 : if (!__get_cpuid(0, &a, &b, &c, &d))
836 : return 0;
837 :
838 3431 : if ((memcmp(&b, "Genu", 4) == 0 &&
839 3431 : memcmp(&d, "ineI", 4) == 0 &&
840 3431 : memcmp(&c, "ntel", 4) == 0) ||
841 0 : (memcmp(&b, "Auth", 4) == 0 &&
842 0 : memcmp(&d, "enti", 4) == 0 && memcmp(&c, "cAMD", 4) == 0)) {
843 3431 : return 1;
844 : }
845 :
846 : return 0;
847 : }
848 :
849 : static
850 3431 : void register_x86_intel_crypto(unsigned capabilities)
851 : {
852 3431 : int ret;
853 :
854 3431 : memset(_gnutls_x86_cpuid_s, 0, sizeof(_gnutls_x86_cpuid_s));
855 :
856 3431 : if (check_intel_or_amd() == 0)
857 : return;
858 :
859 3431 : if (capabilities == 0) {
860 3420 : if (!read_cpuid_vals(_gnutls_x86_cpuid_s))
861 : return;
862 : } else {
863 11 : capabilities_to_intel_cpuid(capabilities);
864 : }
865 :
866 3431 : if (check_ssse3()) {
867 3420 : _gnutls_debug_log("Intel SSSE3 was detected\n");
868 :
869 3420 : ret =
870 3420 : gnutls_crypto_single_cipher_register
871 : (GNUTLS_CIPHER_AES_128_GCM, 90,
872 : &_gnutls_aes_gcm_x86_ssse3, 0);
873 3420 : if (ret < 0) {
874 4 : gnutls_assert();
875 : }
876 :
877 3420 : ret =
878 3420 : gnutls_crypto_single_cipher_register
879 : (GNUTLS_CIPHER_AES_192_GCM, 90,
880 : &_gnutls_aes_gcm_x86_ssse3, 0);
881 3420 : if (ret < 0) {
882 0 : gnutls_assert();
883 : }
884 :
885 3420 : ret =
886 3420 : gnutls_crypto_single_cipher_register
887 : (GNUTLS_CIPHER_AES_256_GCM, 90,
888 : &_gnutls_aes_gcm_x86_ssse3, 0);
889 3420 : if (ret < 0) {
890 0 : gnutls_assert();
891 : }
892 :
893 3420 : ret =
894 3420 : gnutls_crypto_single_cipher_register
895 : (GNUTLS_CIPHER_AES_128_CBC, 90, &_gnutls_aes_ssse3, 0);
896 3420 : if (ret < 0) {
897 1 : gnutls_assert();
898 : }
899 :
900 3420 : ret =
901 3420 : gnutls_crypto_single_cipher_register
902 : (GNUTLS_CIPHER_AES_192_CBC, 90, &_gnutls_aes_ssse3, 0);
903 3420 : if (ret < 0) {
904 0 : gnutls_assert();
905 : }
906 :
907 3420 : ret =
908 3420 : gnutls_crypto_single_cipher_register
909 : (GNUTLS_CIPHER_AES_256_CBC, 90, &_gnutls_aes_ssse3, 0);
910 3420 : if (ret < 0) {
911 0 : gnutls_assert();
912 : }
913 : }
914 :
915 3431 : if (check_sha() || check_ssse3()) {
916 3420 : if (check_sha())
917 0 : _gnutls_debug_log("Intel SHA was detected\n");
918 :
919 3420 : ret =
920 3420 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA1,
921 : 80,
922 : &_gnutls_sha_x86_ssse3, 0);
923 3420 : if (ret < 0) {
924 1 : gnutls_assert();
925 : }
926 :
927 3420 : ret =
928 3420 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA224,
929 : 80,
930 : &_gnutls_sha_x86_ssse3, 0);
931 3420 : if (ret < 0) {
932 0 : gnutls_assert();
933 : }
934 :
935 3420 : ret =
936 3420 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA256,
937 : 80,
938 : &_gnutls_sha_x86_ssse3, 0);
939 3420 : if (ret < 0) {
940 0 : gnutls_assert();
941 : }
942 :
943 :
944 3420 : ret =
945 3420 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA1,
946 : 80,
947 : &_gnutls_hmac_sha_x86_ssse3, 0);
948 3420 : if (ret < 0)
949 0 : gnutls_assert();
950 :
951 3420 : ret =
952 3420 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA224,
953 : 80,
954 : &_gnutls_hmac_sha_x86_ssse3, 0);
955 3420 : if (ret < 0)
956 0 : gnutls_assert();
957 :
958 3420 : ret =
959 3420 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA256,
960 : 80,
961 : &_gnutls_hmac_sha_x86_ssse3, 0);
962 3420 : if (ret < 0)
963 1 : gnutls_assert();
964 :
965 3420 : ret =
966 3420 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA384,
967 : 80,
968 : &_gnutls_sha_x86_ssse3, 0);
969 3420 : if (ret < 0)
970 0 : gnutls_assert();
971 :
972 3420 : ret =
973 3420 : gnutls_crypto_single_digest_register(GNUTLS_DIG_SHA512,
974 : 80,
975 : &_gnutls_sha_x86_ssse3, 0);
976 3420 : if (ret < 0)
977 0 : gnutls_assert();
978 3420 : ret =
979 3420 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA384,
980 : 80,
981 : &_gnutls_hmac_sha_x86_ssse3, 0);
982 3420 : if (ret < 0)
983 0 : gnutls_assert();
984 :
985 3420 : ret =
986 3420 : gnutls_crypto_single_mac_register(GNUTLS_MAC_SHA512,
987 : 80,
988 : &_gnutls_hmac_sha_x86_ssse3, 0);
989 3420 : if (ret < 0)
990 0 : gnutls_assert();
991 : }
992 :
993 3431 : if (check_optimized_aes()) {
994 3420 : _gnutls_debug_log("Intel AES accelerator was detected\n");
995 3420 : ret =
996 3420 : gnutls_crypto_single_cipher_register
997 : (GNUTLS_CIPHER_AES_128_CBC, 80, &_gnutls_aesni_x86, 0);
998 3420 : if (ret < 0) {
999 1 : gnutls_assert();
1000 : }
1001 :
1002 3420 : ret =
1003 3420 : gnutls_crypto_single_cipher_register
1004 : (GNUTLS_CIPHER_AES_192_CBC, 80, &_gnutls_aesni_x86, 0);
1005 3420 : if (ret < 0) {
1006 0 : gnutls_assert();
1007 : }
1008 :
1009 3420 : ret =
1010 3420 : gnutls_crypto_single_cipher_register
1011 : (GNUTLS_CIPHER_AES_256_CBC, 80, &_gnutls_aesni_x86, 0);
1012 3420 : if (ret < 0) {
1013 0 : gnutls_assert();
1014 : }
1015 :
1016 3420 : ret =
1017 3420 : gnutls_crypto_single_cipher_register
1018 : (GNUTLS_CIPHER_AES_128_CCM, 80,
1019 : &_gnutls_aes_ccm_x86_aesni, 0);
1020 3420 : if (ret < 0) {
1021 0 : gnutls_assert();
1022 : }
1023 :
1024 3420 : ret =
1025 3420 : gnutls_crypto_single_cipher_register
1026 : (GNUTLS_CIPHER_AES_256_CCM, 80,
1027 : &_gnutls_aes_ccm_x86_aesni, 0);
1028 3420 : if (ret < 0) {
1029 0 : gnutls_assert();
1030 : }
1031 :
1032 3420 : ret =
1033 3420 : gnutls_crypto_single_cipher_register
1034 : (GNUTLS_CIPHER_AES_128_CCM_8, 80,
1035 : &_gnutls_aes_ccm_x86_aesni, 0);
1036 3420 : if (ret < 0) {
1037 0 : gnutls_assert();
1038 : }
1039 :
1040 3420 : ret =
1041 3420 : gnutls_crypto_single_cipher_register
1042 : (GNUTLS_CIPHER_AES_256_CCM_8, 80,
1043 : &_gnutls_aes_ccm_x86_aesni, 0);
1044 3420 : if (ret < 0) {
1045 0 : gnutls_assert();
1046 : }
1047 :
1048 3420 : ret =
1049 3420 : gnutls_crypto_single_cipher_register
1050 : (GNUTLS_CIPHER_AES_128_XTS, 80,
1051 : &_gnutls_aes_xts_x86_aesni, 0);
1052 3420 : if (ret < 0) {
1053 0 : gnutls_assert();
1054 : }
1055 :
1056 3420 : ret =
1057 3420 : gnutls_crypto_single_cipher_register
1058 : (GNUTLS_CIPHER_AES_256_XTS, 80,
1059 : &_gnutls_aes_xts_x86_aesni, 0);
1060 3420 : if (ret < 0) {
1061 0 : gnutls_assert();
1062 : }
1063 :
1064 : #ifdef ASM_X86_64
1065 3420 : if (check_pclmul()) {
1066 : /* register GCM ciphers */
1067 3420 : if (check_avx_movbe()) {
1068 3420 : _gnutls_debug_log
1069 : ("Intel GCM accelerator (AVX) was detected\n");
1070 3420 : ret =
1071 3420 : gnutls_crypto_single_cipher_register
1072 : (GNUTLS_CIPHER_AES_128_GCM, 80,
1073 : &_gnutls_aes_gcm_pclmul_avx, 0);
1074 3420 : if (ret < 0) {
1075 1 : gnutls_assert();
1076 : }
1077 :
1078 3420 : ret =
1079 3420 : gnutls_crypto_single_cipher_register
1080 : (GNUTLS_CIPHER_AES_192_GCM, 80,
1081 : &_gnutls_aes_gcm_pclmul_avx, 0);
1082 3420 : if (ret < 0) {
1083 0 : gnutls_assert();
1084 : }
1085 :
1086 3420 : ret =
1087 3420 : gnutls_crypto_single_cipher_register
1088 : (GNUTLS_CIPHER_AES_256_GCM, 80,
1089 : &_gnutls_aes_gcm_pclmul_avx, 0);
1090 3420 : if (ret < 0) {
1091 0 : gnutls_assert();
1092 : }
1093 : } else {
1094 0 : _gnutls_debug_log
1095 : ("Intel GCM accelerator was detected\n");
1096 0 : ret =
1097 0 : gnutls_crypto_single_cipher_register
1098 : (GNUTLS_CIPHER_AES_128_GCM, 80,
1099 : &_gnutls_aes_gcm_pclmul, 0);
1100 0 : if (ret < 0) {
1101 0 : gnutls_assert();
1102 : }
1103 :
1104 0 : ret =
1105 0 : gnutls_crypto_single_cipher_register
1106 : (GNUTLS_CIPHER_AES_192_GCM, 80,
1107 : &_gnutls_aes_gcm_pclmul, 0);
1108 0 : if (ret < 0) {
1109 0 : gnutls_assert();
1110 : }
1111 :
1112 0 : ret =
1113 0 : gnutls_crypto_single_cipher_register
1114 : (GNUTLS_CIPHER_AES_256_GCM, 80,
1115 : &_gnutls_aes_gcm_pclmul, 0);
1116 0 : if (ret < 0) {
1117 0 : gnutls_assert();
1118 : }
1119 : }
1120 : } else
1121 : #endif
1122 : {
1123 0 : ret =
1124 0 : gnutls_crypto_single_cipher_register
1125 : (GNUTLS_CIPHER_AES_128_GCM, 80,
1126 : &_gnutls_aes_gcm_x86_aesni, 0);
1127 0 : if (ret < 0) {
1128 0 : gnutls_assert();
1129 : }
1130 :
1131 0 : ret =
1132 0 : gnutls_crypto_single_cipher_register
1133 : (GNUTLS_CIPHER_AES_192_GCM, 80,
1134 : &_gnutls_aes_gcm_x86_aesni, 0);
1135 0 : if (ret < 0) {
1136 0 : gnutls_assert();
1137 : }
1138 :
1139 0 : ret =
1140 0 : gnutls_crypto_single_cipher_register
1141 : (GNUTLS_CIPHER_AES_256_GCM, 80,
1142 : &_gnutls_aes_gcm_x86_aesni, 0);
1143 0 : if (ret < 0) {
1144 0 : gnutls_assert();
1145 : }
1146 : }
1147 : } else {
1148 11 : _gnutls_priority_update_non_aesni();
1149 : }
1150 :
1151 : return;
1152 : }
1153 :
1154 :
1155 3431 : void register_x86_crypto(void)
1156 : {
1157 3431 : unsigned capabilities = 0;
1158 3431 : char *p;
1159 3431 : p = secure_getenv("GNUTLS_CPUID_OVERRIDE");
1160 3431 : if (p) {
1161 12 : capabilities = strtol(p, NULL, 0);
1162 : }
1163 :
1164 3431 : register_x86_intel_crypto(capabilities);
1165 : #ifdef ENABLE_PADLOCK
1166 : register_x86_padlock_crypto(capabilities);
1167 : #endif
1168 3431 : }
1169 :
|