OLD | NEW |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | 1 /* This Source Code Form is subject to the terms of the Mozilla Public |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | 2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | 4 |
5 #ifdef FREEBL_NO_DEPEND | 5 #ifdef FREEBL_NO_DEPEND |
6 #include "stubs.h" | 6 #include "stubs.h" |
7 #endif | 7 #endif |
8 | 8 |
9 #include "prinit.h" | 9 #include "prinit.h" |
10 #include "prerr.h" | 10 #include "prerr.h" |
11 #include "secerr.h" | 11 #include "secerr.h" |
12 | 12 |
13 #include "prtypes.h" | 13 #include "prtypes.h" |
14 #include "blapi.h" | 14 #include "blapi.h" |
15 #include "rijndael.h" | 15 #include "rijndael.h" |
16 | 16 |
17 #include "cts.h" | 17 #include "cts.h" |
18 #include "ctr.h" | 18 #include "ctr.h" |
19 #include "gcm.h" | 19 #include "gcm.h" |
20 | 20 |
21 #if USE_HW_AES | 21 #if USE_HW_AES |
22 #include "intel-gcm.h" | 22 #include "intel-gcm.h" |
23 #include "intel-aes.h" | 23 #include "intel-aes.h" |
24 #include "mpi.h" | 24 #include "mpi.h" |
25 | 25 |
26 static int has_intel_aes = 0; | 26 static int has_intel_aes = 0; |
27 static int has_intel_avx = 0; | 27 static int has_intel_avx = 0; |
28 static int has_intel_clmul = 0; | 28 static int has_intel_clmul = 0; |
29 static PRBool use_hw_aes = PR_FALSE; | 29 static PRBool use_hw_aes = PR_FALSE; |
30 static PRBool use_hw_avx = PR_FALSE; | |
31 static PRBool use_hw_gcm = PR_FALSE; | 30 static PRBool use_hw_gcm = PR_FALSE; |
32 #endif | 31 #endif |
33 | 32 |
34 /* | 33 /* |
35 * There are currently five ways to build this code, varying in performance | 34 * There are currently five ways to build this code, varying in performance |
36 * and code size. | 35 * and code size. |
37 * | 36 * |
38 * RIJNDAEL_INCLUDE_TABLES Include all tables from rijndael32.tab | 37 * RIJNDAEL_INCLUDE_TABLES Include all tables from rijndael32.tab |
39 * RIJNDAEL_GENERATE_TABLES Generate tables on first | 38 * RIJNDAEL_GENERATE_TABLES Generate tables on first |
40 * encryption/decryption, then store them; | 39 * encryption/decryption, then store them; |
(...skipping 919 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
960 * BLAPI for the AES cipher, Rijndael. | 959 * BLAPI for the AES cipher, Rijndael. |
961 * | 960 * |
962 ***********************************************************************/ | 961 ***********************************************************************/ |
963 | 962 |
964 AESContext * AES_AllocateContext(void) | 963 AESContext * AES_AllocateContext(void) |
965 { | 964 { |
966 return PORT_ZNew(AESContext); | 965 return PORT_ZNew(AESContext); |
967 } | 966 } |
968 | 967 |
969 | 968 |
| 969 #if USE_HW_AES |
| 970 /* |
| 971 * Adapted from the example code in "How to detect New Instruction support in |
| 972 * the 4th generation Intel Core processor family" by Max Locktyukhin. |
| 973 */ |
| 974 static PRBool |
| 975 check_xcr0_ymm() |
| 976 { |
| 977 PRUint32 xcr0; |
| 978 #if defined(_MSC_VER) |
| 979 xcr0 = (PRUint32)_xgetbv(0); /* Requires VS2010 SP1 or later. */ |
| 980 #else |
| 981 __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx"); |
| 982 #endif |
| 983 /* Check if xmm and ymm state are enabled in XCR0. */ |
| 984 return (xcr0 & 6) == 6; |
| 985 } |
| 986 #endif |
| 987 |
970 /* | 988 /* |
971 ** Initialize a new AES context suitable for AES encryption/decryption in | 989 ** Initialize a new AES context suitable for AES encryption/decryption in |
972 ** the ECB or CBC mode. | 990 ** the ECB or CBC mode. |
973 ** "mode" the mode of operation, which must be NSS_AES or NSS_AES_CBC | 991 ** "mode" the mode of operation, which must be NSS_AES or NSS_AES_CBC |
974 */ | 992 */ |
975 static SECStatus | 993 static SECStatus |
976 aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize, | 994 aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize, |
977 const unsigned char *iv, int mode, unsigned int encrypt, | 995 const unsigned char *iv, int mode, unsigned int encrypt, |
978 unsigned int blocksize) | 996 unsigned int blocksize) |
979 { | 997 { |
(...skipping 26 matching lines...) Expand all Loading... |
1006 } | 1024 } |
1007 #if USE_HW_AES | 1025 #if USE_HW_AES |
1008 if (has_intel_aes == 0) { | 1026 if (has_intel_aes == 0) { |
1009 unsigned long eax, ebx, ecx, edx; | 1027 unsigned long eax, ebx, ecx, edx; |
1010 char *disable_hw_aes = getenv("NSS_DISABLE_HW_AES"); | 1028 char *disable_hw_aes = getenv("NSS_DISABLE_HW_AES"); |
1011 | 1029 |
1012 if (disable_hw_aes == NULL) { | 1030 if (disable_hw_aes == NULL) { |
1013 freebl_cpuid(1, &eax, &ebx, &ecx, &edx); | 1031 freebl_cpuid(1, &eax, &ebx, &ecx, &edx); |
1014 has_intel_aes = (ecx & (1 << 25)) != 0 ? 1 : -1; | 1032 has_intel_aes = (ecx & (1 << 25)) != 0 ? 1 : -1; |
1015 has_intel_clmul = (ecx & (1 << 1)) != 0 ? 1 : -1; | 1033 has_intel_clmul = (ecx & (1 << 1)) != 0 ? 1 : -1; |
1016 » has_intel_avx = (ecx & (1 << 28)) != 0 ? 1 : -1; | 1034 » if ((ecx & (1 << 27)) != 0 && (ecx & (1 << 28)) != 0 && |
| 1035 » » check_xcr0_ymm()) { |
| 1036 » » has_intel_avx = 1; |
| 1037 » } else { |
| 1038 » » has_intel_avx = -1; |
| 1039 » } |
1017 } else { | 1040 } else { |
1018 has_intel_aes = -1; | 1041 has_intel_aes = -1; |
1019 has_intel_avx = -1; | 1042 has_intel_avx = -1; |
1020 has_intel_clmul = -1; | 1043 has_intel_clmul = -1; |
1021 } | 1044 } |
1022 } | 1045 } |
1023 use_hw_aes = (PRBool) | 1046 use_hw_aes = (PRBool) |
1024 (has_intel_aes > 0 && (keysize % 8) == 0 && blocksize == 16); | 1047 (has_intel_aes > 0 && (keysize % 8) == 0 && blocksize == 16); |
1025 use_hw_gcm = (PRBool) | 1048 use_hw_gcm = (PRBool) |
1026 (use_hw_aes && has_intel_avx>0 && has_intel_clmul>0); | 1049 (use_hw_aes && has_intel_avx>0 && has_intel_clmul>0); |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1261 return SECFailure; | 1284 return SECFailure; |
1262 } | 1285 } |
1263 if (maxOutputLen < inputLen) { | 1286 if (maxOutputLen < inputLen) { |
1264 PORT_SetError(SEC_ERROR_OUTPUT_LEN); | 1287 PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
1265 return SECFailure; | 1288 return SECFailure; |
1266 } | 1289 } |
1267 *outputLen = inputLen; | 1290 *outputLen = inputLen; |
1268 return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen, | 1291 return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen, |
1269 input, inputLen, blocksize); | 1292 input, inputLen, blocksize); |
1270 } | 1293 } |
OLD | NEW |