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 #ifdef USE_HW_AES |
22 #include "intel-gcm.h" | |
23 #include "intel-aes.h" | 22 #include "intel-aes.h" |
24 #include "mpi.h" | 23 #include "mpi.h" |
25 | 24 |
26 static int has_intel_aes = 0; | 25 static int has_intel_aes = 0; |
| 26 static PRBool use_hw_aes = PR_FALSE; |
| 27 |
| 28 #ifdef INTEL_GCM |
| 29 #include "intel-gcm.h" |
27 static int has_intel_avx = 0; | 30 static int has_intel_avx = 0; |
28 static int has_intel_clmul = 0; | 31 static int has_intel_clmul = 0; |
29 static PRBool use_hw_aes = PR_FALSE; | |
30 static PRBool use_hw_gcm = PR_FALSE; | 32 static PRBool use_hw_gcm = PR_FALSE; |
31 #endif | 33 #endif |
| 34 #endif /* USE_HW_AES */ |
32 | 35 |
33 /* | 36 /* |
34 * There are currently five ways to build this code, varying in performance | 37 * There are currently five ways to build this code, varying in performance |
35 * and code size. | 38 * and code size. |
36 * | 39 * |
37 * RIJNDAEL_INCLUDE_TABLES Include all tables from rijndael32.tab | 40 * RIJNDAEL_INCLUDE_TABLES Include all tables from rijndael32.tab |
38 * RIJNDAEL_GENERATE_TABLES Generate tables on first | 41 * RIJNDAEL_GENERATE_TABLES Generate tables on first |
39 * encryption/decryption, then store them; | 42 * encryption/decryption, then store them; |
40 * use the function gfm | 43 * use the function gfm |
41 * RIJNDAEL_GENERATE_TABLES_MACRO Same as above, but use macros to do | 44 * RIJNDAEL_GENERATE_TABLES_MACRO Same as above, but use macros to do |
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
826 | 829 |
827 static SECStatus | 830 static SECStatus |
828 rijndael_encryptECB(AESContext *cx, unsigned char *output, | 831 rijndael_encryptECB(AESContext *cx, unsigned char *output, |
829 unsigned int *outputLen, unsigned int maxOutputLen, | 832 unsigned int *outputLen, unsigned int maxOutputLen, |
830 const unsigned char *input, unsigned int inputLen, | 833 const unsigned char *input, unsigned int inputLen, |
831 unsigned int blocksize) | 834 unsigned int blocksize) |
832 { | 835 { |
833 SECStatus rv; | 836 SECStatus rv; |
834 AESBlockFunc *encryptor; | 837 AESBlockFunc *encryptor; |
835 | 838 |
836 | |
837 encryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE) | 839 encryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE) |
838 ? &rijndael_encryptBlock128 | 840 ? &rijndael_encryptBlock128 |
839 : &rijndael_encryptBlock; | 841 : &rijndael_encryptBlock; |
840 while (inputLen > 0) { | 842 while (inputLen > 0) { |
841 rv = (*encryptor)(cx, output, input); | 843 rv = (*encryptor)(cx, output, input); |
842 if (rv != SECSuccess) | 844 if (rv != SECSuccess) |
843 return rv; | 845 return rv; |
844 output += blocksize; | 846 output += blocksize; |
845 input += blocksize; | 847 input += blocksize; |
846 inputLen -= blocksize; | 848 inputLen -= blocksize; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 * BLAPI for the AES cipher, Rijndael. | 961 * BLAPI for the AES cipher, Rijndael. |
960 * | 962 * |
961 ***********************************************************************/ | 963 ***********************************************************************/ |
962 | 964 |
963 AESContext * AES_AllocateContext(void) | 965 AESContext * AES_AllocateContext(void) |
964 { | 966 { |
965 return PORT_ZNew(AESContext); | 967 return PORT_ZNew(AESContext); |
966 } | 968 } |
967 | 969 |
968 | 970 |
969 #if USE_HW_AES | 971 #ifdef INTEL_GCM |
970 /* | 972 /* |
971 * Adapted from the example code in "How to detect New Instruction support in | 973 * Adapted from the example code in "How to detect New Instruction support in |
972 * the 4th generation Intel Core processor family" by Max Locktyukhin. | 974 * the 4th generation Intel Core processor family" by Max Locktyukhin. |
| 975 * |
| 976 * XGETBV: |
| 977 * Reads an extended control register (XCR) specified by ECX into EDX:EAX. |
973 */ | 978 */ |
974 static PRBool | 979 static PRBool |
975 check_xcr0_ymm() | 980 check_xcr0_ymm() |
976 { | 981 { |
977 PRUint32 xcr0; | 982 PRUint32 xcr0; |
978 #if defined(_MSC_VER) | 983 #if defined(_MSC_VER) |
| 984 #if defined(_M_IX86) |
| 985 __asm { |
| 986 mov ecx, 0 |
| 987 xgetbv |
| 988 mov xcr0, eax |
| 989 } |
| 990 #else |
979 xcr0 = (PRUint32)_xgetbv(0); /* Requires VS2010 SP1 or later. */ | 991 xcr0 = (PRUint32)_xgetbv(0); /* Requires VS2010 SP1 or later. */ |
| 992 #endif |
980 #else | 993 #else |
981 __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx"); | 994 __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx"); |
982 #endif | 995 #endif |
983 /* Check if xmm and ymm state are enabled in XCR0. */ | 996 /* Check if xmm and ymm state are enabled in XCR0. */ |
984 return (xcr0 & 6) == 6; | 997 return (xcr0 & 6) == 6; |
985 } | 998 } |
986 #endif | 999 #endif |
987 | 1000 |
988 /* | 1001 /* |
989 ** Initialize a new AES context suitable for AES encryption/decryption in | 1002 ** Initialize a new AES context suitable for AES encryption/decryption in |
(...skipping 25 matching lines...) Expand all Loading... |
1015 return SECFailure; | 1028 return SECFailure; |
1016 } | 1029 } |
1017 if (mode == NSS_AES_CBC && iv == NULL) { | 1030 if (mode == NSS_AES_CBC && iv == NULL) { |
1018 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 1031 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
1019 return SECFailure; | 1032 return SECFailure; |
1020 } | 1033 } |
1021 if (!cx) { | 1034 if (!cx) { |
1022 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 1035 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
1023 return SECFailure; | 1036 return SECFailure; |
1024 } | 1037 } |
1025 #if USE_HW_AES | 1038 #ifdef USE_HW_AES |
1026 if (has_intel_aes == 0) { | 1039 if (has_intel_aes == 0) { |
1027 unsigned long eax, ebx, ecx, edx; | 1040 unsigned long eax, ebx, ecx, edx; |
1028 char *disable_hw_aes = getenv("NSS_DISABLE_HW_AES"); | 1041 char *disable_hw_aes = getenv("NSS_DISABLE_HW_AES"); |
1029 | 1042 |
1030 if (disable_hw_aes == NULL) { | 1043 if (disable_hw_aes == NULL) { |
1031 freebl_cpuid(1, &eax, &ebx, &ecx, &edx); | 1044 freebl_cpuid(1, &eax, &ebx, &ecx, &edx); |
1032 has_intel_aes = (ecx & (1 << 25)) != 0 ? 1 : -1; | 1045 has_intel_aes = (ecx & (1 << 25)) != 0 ? 1 : -1; |
| 1046 #ifdef INTEL_GCM |
1033 has_intel_clmul = (ecx & (1 << 1)) != 0 ? 1 : -1; | 1047 has_intel_clmul = (ecx & (1 << 1)) != 0 ? 1 : -1; |
1034 if ((ecx & (1 << 27)) != 0 && (ecx & (1 << 28)) != 0 && | 1048 if ((ecx & (1 << 27)) != 0 && (ecx & (1 << 28)) != 0 && |
1035 check_xcr0_ymm()) { | 1049 check_xcr0_ymm()) { |
1036 has_intel_avx = 1; | 1050 has_intel_avx = 1; |
1037 } else { | 1051 } else { |
1038 has_intel_avx = -1; | 1052 has_intel_avx = -1; |
1039 } | 1053 } |
| 1054 #endif |
1040 } else { | 1055 } else { |
1041 has_intel_aes = -1; | 1056 has_intel_aes = -1; |
| 1057 #ifdef INTEL_GCM |
1042 has_intel_avx = -1; | 1058 has_intel_avx = -1; |
1043 has_intel_clmul = -1; | 1059 has_intel_clmul = -1; |
| 1060 #endif |
1044 } | 1061 } |
1045 } | 1062 } |
1046 use_hw_aes = (PRBool) | 1063 use_hw_aes = (PRBool) |
1047 (has_intel_aes > 0 && (keysize % 8) == 0 && blocksize == 16); | 1064 (has_intel_aes > 0 && (keysize % 8) == 0 && blocksize == 16); |
| 1065 #ifdef INTEL_GCM |
1048 use_hw_gcm = (PRBool) | 1066 use_hw_gcm = (PRBool) |
1049 (use_hw_aes && has_intel_avx>0 && has_intel_clmul>0); | 1067 (use_hw_aes && has_intel_avx>0 && has_intel_clmul>0); |
1050 #endif | 1068 #endif |
| 1069 #endif /* USE_HW_AES */ |
1051 /* Nb = (block size in bits) / 32 */ | 1070 /* Nb = (block size in bits) / 32 */ |
1052 cx->Nb = blocksize / 4; | 1071 cx->Nb = blocksize / 4; |
1053 /* Nk = (key size in bits) / 32 */ | 1072 /* Nk = (key size in bits) / 32 */ |
1054 Nk = keysize / 4; | 1073 Nk = keysize / 4; |
1055 /* Obtain number of rounds from "table" */ | 1074 /* Obtain number of rounds from "table" */ |
1056 cx->Nr = RIJNDAEL_NUM_ROUNDS(Nk, cx->Nb); | 1075 cx->Nr = RIJNDAEL_NUM_ROUNDS(Nk, cx->Nb); |
1057 /* copy in the iv, if neccessary */ | 1076 /* copy in the iv, if neccessary */ |
1058 if (mode == NSS_AES_CBC) { | 1077 if (mode == NSS_AES_CBC) { |
1059 memcpy(cx->iv, iv, blocksize); | 1078 memcpy(cx->iv, iv, blocksize); |
1060 #if USE_HW_AES | 1079 #ifdef USE_HW_AES |
1061 if (use_hw_aes) { | 1080 if (use_hw_aes) { |
1062 cx->worker = (freeblCipherFunc) | 1081 cx->worker = (freeblCipherFunc) |
1063 intel_aes_cbc_worker(encrypt, keysize); | 1082 intel_aes_cbc_worker(encrypt, keysize); |
1064 } else | 1083 } else |
1065 #endif | 1084 #endif |
1066 { | 1085 { |
1067 cx->worker = (freeblCipherFunc) (encrypt | 1086 cx->worker = (freeblCipherFunc) (encrypt |
1068 ? &rijndael_encryptCBC : &rijndael_decryptCBC); | 1087 ? &rijndael_encryptCBC : &rijndael_decryptCBC); |
1069 } | 1088 } |
1070 } else { | 1089 } else { |
1071 #if USE_HW_AES | 1090 #ifdef USE_HW_AES |
1072 if (use_hw_aes) { | 1091 if (use_hw_aes) { |
1073 cx->worker = (freeblCipherFunc) | 1092 cx->worker = (freeblCipherFunc) |
1074 intel_aes_ecb_worker(encrypt, keysize); | 1093 intel_aes_ecb_worker(encrypt, keysize); |
1075 } else | 1094 } else |
1076 #endif | 1095 #endif |
1077 { | 1096 { |
1078 cx->worker = (freeblCipherFunc) (encrypt | 1097 cx->worker = (freeblCipherFunc) (encrypt |
1079 ? &rijndael_encryptECB : &rijndael_decryptECB); | 1098 ? &rijndael_encryptECB : &rijndael_decryptECB); |
1080 } | 1099 } |
1081 } | 1100 } |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1149 /* finally, set up any mode specific contexts */ | 1168 /* finally, set up any mode specific contexts */ |
1150 switch (mode) { | 1169 switch (mode) { |
1151 case NSS_AES_CTS: | 1170 case NSS_AES_CTS: |
1152 cx->worker_cx = CTS_CreateContext(cx, cx->worker, iv, blocksize); | 1171 cx->worker_cx = CTS_CreateContext(cx, cx->worker, iv, blocksize); |
1153 cx->worker = (freeblCipherFunc) | 1172 cx->worker = (freeblCipherFunc) |
1154 (encrypt ? CTS_EncryptUpdate : CTS_DecryptUpdate); | 1173 (encrypt ? CTS_EncryptUpdate : CTS_DecryptUpdate); |
1155 cx->destroy = (freeblDestroyFunc) CTS_DestroyContext; | 1174 cx->destroy = (freeblDestroyFunc) CTS_DestroyContext; |
1156 cx->isBlock = PR_FALSE; | 1175 cx->isBlock = PR_FALSE; |
1157 break; | 1176 break; |
1158 case NSS_AES_GCM: | 1177 case NSS_AES_GCM: |
1159 #if USE_HW_AES | 1178 #ifdef INTEL_GCM |
1160 if(use_hw_gcm) { | 1179 if(use_hw_gcm) { |
1161 cx->worker_cx = intel_AES_GCM_CreateContext(cx, cx->worker, iv,
blocksize); | 1180 cx->worker_cx = intel_AES_GCM_CreateContext(cx, cx->worker, iv,
blocksize); |
1162 cx->worker = (freeblCipherFunc) | 1181 cx->worker = (freeblCipherFunc) |
1163 (encrypt ? intel_AES_GCM_EncryptUpdate : intel_AES_GCM_D
ecryptUpdate); | 1182 (encrypt ? intel_AES_GCM_EncryptUpdate : intel_AES_GCM_D
ecryptUpdate); |
1164 cx->destroy = (freeblDestroyFunc) intel_AES_GCM_DestroyContext; | 1183 cx->destroy = (freeblDestroyFunc) intel_AES_GCM_DestroyContext; |
1165 cx->isBlock = PR_FALSE; | 1184 cx->isBlock = PR_FALSE; |
1166 } else | 1185 } else |
1167 #endif | 1186 #endif |
1168 { | 1187 { |
1169 cx->worker_cx = GCM_CreateContext(cx, cx->worker, iv, blocksize); | 1188 cx->worker_cx = GCM_CreateContext(cx, cx->worker, iv, blocksize); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1295 return SECFailure; | 1314 return SECFailure; |
1296 } | 1315 } |
1297 if (maxOutputLen < inputLen) { | 1316 if (maxOutputLen < inputLen) { |
1298 PORT_SetError(SEC_ERROR_OUTPUT_LEN); | 1317 PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
1299 return SECFailure; | 1318 return SECFailure; |
1300 } | 1319 } |
1301 *outputLen = inputLen; | 1320 *outputLen = inputLen; |
1302 return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen, | 1321 return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen, |
1303 input, inputLen, blocksize); | 1322 input, inputLen, blocksize); |
1304 } | 1323 } |
OLD | NEW |