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 /* $Id: rijndael.c,v 1.28 2012/09/28 22:46:32 rrelyea%redhat.com Exp $ */ | 4 /* $Id: rijndael.c,v 1.30 2013/01/25 18:02:53 rrelyea%redhat.com Exp $ */ |
5 | 5 |
6 #ifdef FREEBL_NO_DEPEND | 6 #ifdef FREEBL_NO_DEPEND |
7 #include "stubs.h" | 7 #include "stubs.h" |
8 #endif | 8 #endif |
9 | 9 |
10 #include "prinit.h" | 10 #include "prinit.h" |
11 #include "prerr.h" | 11 #include "prerr.h" |
12 #include "secerr.h" | 12 #include "secerr.h" |
13 | 13 |
14 #include "prtypes.h" | 14 #include "prtypes.h" |
15 #include "blapi.h" | 15 #include "blapi.h" |
16 #include "rijndael.h" | 16 #include "rijndael.h" |
17 | 17 |
18 #include "cts.h" | 18 #include "cts.h" |
19 #include "ctr.h" | 19 #include "ctr.h" |
20 #include "gcm.h" | 20 #include "gcm.h" |
21 | 21 |
22 #if USE_HW_AES | 22 #if USE_HW_AES |
| 23 #include "intel-gcm.h" |
23 #include "intel-aes.h" | 24 #include "intel-aes.h" |
24 #include "mpi.h" | 25 #include "mpi.h" |
| 26 |
| 27 static int has_intel_aes = 0; |
| 28 static int has_intel_avx = 0; |
| 29 static int has_intel_clmul = 0; |
| 30 static PRBool use_hw_aes = PR_FALSE; |
| 31 static PRBool use_hw_avx = PR_FALSE; |
| 32 static PRBool use_hw_gcm = PR_FALSE; |
25 #endif | 33 #endif |
26 | 34 |
27 /* | 35 /* |
28 * There are currently five ways to build this code, varying in performance | 36 * There are currently five ways to build this code, varying in performance |
29 * and code size. | 37 * and code size. |
30 * | 38 * |
31 * RIJNDAEL_INCLUDE_TABLES Include all tables from rijndael32.tab | 39 * RIJNDAEL_INCLUDE_TABLES Include all tables from rijndael32.tab |
32 * RIJNDAEL_GENERATE_TABLES Generate tables on first | 40 * RIJNDAEL_GENERATE_TABLES Generate tables on first |
33 * encryption/decryption, then store them; | 41 * encryption/decryption, then store them; |
34 * use the function gfm | 42 * use the function gfm |
(...skipping 928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
963 /* | 971 /* |
964 ** Initialize a new AES context suitable for AES encryption/decryption in | 972 ** Initialize a new AES context suitable for AES encryption/decryption in |
965 ** the ECB or CBC mode. | 973 ** the ECB or CBC mode. |
966 ** "mode" the mode of operation, which must be NSS_AES or NSS_AES_CBC | 974 ** "mode" the mode of operation, which must be NSS_AES or NSS_AES_CBC |
967 */ | 975 */ |
968 static SECStatus | 976 static SECStatus |
969 aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize, | 977 aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize, |
970 const unsigned char *iv, int mode, unsigned int encrypt, | 978 const unsigned char *iv, int mode, unsigned int encrypt, |
971 unsigned int blocksize) | 979 unsigned int blocksize) |
972 { | 980 { |
973 #if USE_HW_AES | |
974 static int has_intel_aes; | |
975 PRBool use_hw_aes = PR_FALSE; | |
976 #endif | |
977 unsigned int Nk; | 981 unsigned int Nk; |
978 /* According to Rijndael AES Proposal, section 12.1, block and key | 982 /* According to Rijndael AES Proposal, section 12.1, block and key |
979 * lengths between 128 and 256 bits are supported, as long as the | 983 * lengths between 128 and 256 bits are supported, as long as the |
980 * length in bytes is divisible by 4. | 984 * length in bytes is divisible by 4. |
981 */ | 985 */ |
982 if (key == NULL || | 986 if (key == NULL || |
983 keysize < RIJNDAEL_MIN_BLOCKSIZE || | 987 keysize < RIJNDAEL_MIN_BLOCKSIZE || |
984 keysize > RIJNDAEL_MAX_BLOCKSIZE || | 988 keysize > RIJNDAEL_MAX_BLOCKSIZE || |
985 keysize % 4 != 0 || | 989 keysize % 4 != 0 || |
986 blocksize < RIJNDAEL_MIN_BLOCKSIZE || | 990 blocksize < RIJNDAEL_MIN_BLOCKSIZE || |
(...skipping 15 matching lines...) Expand all Loading... |
1002 return SECFailure; | 1006 return SECFailure; |
1003 } | 1007 } |
1004 #if USE_HW_AES | 1008 #if USE_HW_AES |
1005 if (has_intel_aes == 0) { | 1009 if (has_intel_aes == 0) { |
1006 unsigned long eax, ebx, ecx, edx; | 1010 unsigned long eax, ebx, ecx, edx; |
1007 char *disable_hw_aes = getenv("NSS_DISABLE_HW_AES"); | 1011 char *disable_hw_aes = getenv("NSS_DISABLE_HW_AES"); |
1008 | 1012 |
1009 if (disable_hw_aes == NULL) { | 1013 if (disable_hw_aes == NULL) { |
1010 freebl_cpuid(1, &eax, &ebx, &ecx, &edx); | 1014 freebl_cpuid(1, &eax, &ebx, &ecx, &edx); |
1011 has_intel_aes = (ecx & (1 << 25)) != 0 ? 1 : -1; | 1015 has_intel_aes = (ecx & (1 << 25)) != 0 ? 1 : -1; |
| 1016 has_intel_clmul = (ecx & (1 << 1)) != 0 ? 1 : -1; |
| 1017 has_intel_avx = (ecx & (1 << 28)) != 0 ? 1 : -1; |
1012 } else { | 1018 } else { |
1013 has_intel_aes = -1; | 1019 has_intel_aes = -1; |
| 1020 has_intel_avx = -1; |
| 1021 has_intel_clmul = -1; |
1014 } | 1022 } |
1015 } | 1023 } |
1016 use_hw_aes = (PRBool) | 1024 use_hw_aes = (PRBool) |
1017 (has_intel_aes > 0 && (keysize % 8) == 0 && blocksize == 16); | 1025 (has_intel_aes > 0 && (keysize % 8) == 0 && blocksize == 16); |
| 1026 use_hw_gcm = (PRBool) |
| 1027 (use_hw_aes && has_intel_avx>0 && has_intel_clmul>0); |
1018 #endif | 1028 #endif |
1019 /* Nb = (block size in bits) / 32 */ | 1029 /* Nb = (block size in bits) / 32 */ |
1020 cx->Nb = blocksize / 4; | 1030 cx->Nb = blocksize / 4; |
1021 /* Nk = (key size in bits) / 32 */ | 1031 /* Nk = (key size in bits) / 32 */ |
1022 Nk = keysize / 4; | 1032 Nk = keysize / 4; |
1023 /* Obtain number of rounds from "table" */ | 1033 /* Obtain number of rounds from "table" */ |
1024 cx->Nr = RIJNDAEL_NUM_ROUNDS(Nk, cx->Nb); | 1034 cx->Nr = RIJNDAEL_NUM_ROUNDS(Nk, cx->Nb); |
1025 /* copy in the iv, if neccessary */ | 1035 /* copy in the iv, if neccessary */ |
1026 if (mode == NSS_AES_CBC) { | 1036 if (mode == NSS_AES_CBC) { |
1027 memcpy(cx->iv, iv, blocksize); | 1037 memcpy(cx->iv, iv, blocksize); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1093 switch (mode) { | 1103 switch (mode) { |
1094 case NSS_AES_CTS: | 1104 case NSS_AES_CTS: |
1095 basemode = NSS_AES_CBC; | 1105 basemode = NSS_AES_CBC; |
1096 break; | 1106 break; |
1097 case NSS_AES_GCM: | 1107 case NSS_AES_GCM: |
1098 case NSS_AES_CTR: | 1108 case NSS_AES_CTR: |
1099 basemode = NSS_AES; | 1109 basemode = NSS_AES; |
1100 baseencrypt = PR_TRUE; | 1110 baseencrypt = PR_TRUE; |
1101 break; | 1111 break; |
1102 } | 1112 } |
| 1113 /* make sure enough is initializes so we can safely call Destroy */ |
| 1114 cx->worker_cx = NULL; |
| 1115 cx->destroy = NULL; |
1103 rv = aes_InitContext(cx, key, keysize, iv, basemode, | 1116 rv = aes_InitContext(cx, key, keysize, iv, basemode, |
1104 baseencrypt, blocksize); | 1117 baseencrypt, blocksize); |
1105 if (rv != SECSuccess) { | 1118 if (rv != SECSuccess) { |
1106 » AES_DestroyContext(cx, PR_TRUE); | 1119 » AES_DestroyContext(cx, PR_FALSE); |
1107 return rv; | 1120 return rv; |
1108 } | 1121 } |
1109 | 1122 |
1110 /* finally, set up any mode specific contexts */ | 1123 /* finally, set up any mode specific contexts */ |
1111 switch (mode) { | 1124 switch (mode) { |
1112 case NSS_AES_CTS: | 1125 case NSS_AES_CTS: |
1113 cx->worker_cx = CTS_CreateContext(cx, cx->worker, iv, blocksize); | 1126 cx->worker_cx = CTS_CreateContext(cx, cx->worker, iv, blocksize); |
1114 cx->worker = (freeblCipherFunc) | 1127 cx->worker = (freeblCipherFunc) |
1115 (encrypt ? CTS_EncryptUpdate : CTS_DecryptUpdate); | 1128 (encrypt ? CTS_EncryptUpdate : CTS_DecryptUpdate); |
1116 cx->destroy = (freeblDestroyFunc) CTS_DestroyContext; | 1129 cx->destroy = (freeblDestroyFunc) CTS_DestroyContext; |
1117 cx->isBlock = PR_FALSE; | 1130 cx->isBlock = PR_FALSE; |
1118 break; | 1131 break; |
1119 case NSS_AES_GCM: | 1132 case NSS_AES_GCM: |
| 1133 #if USE_HW_AES |
| 1134 if(use_hw_gcm) { |
| 1135 cx->worker_cx = intel_AES_GCM_CreateContext(cx, cx->worker, iv,
blocksize); |
| 1136 cx->worker = (freeblCipherFunc) |
| 1137 (encrypt ? intel_AES_GCM_EncryptUpdate : intel_AES_GCM_D
ecryptUpdate); |
| 1138 cx->destroy = (freeblDestroyFunc) intel_AES_GCM_DestroyContext; |
| 1139 cx->isBlock = PR_FALSE; |
| 1140 } else |
| 1141 #endif |
| 1142 { |
1120 cx->worker_cx = GCM_CreateContext(cx, cx->worker, iv, blocksize); | 1143 cx->worker_cx = GCM_CreateContext(cx, cx->worker, iv, blocksize); |
1121 cx->worker = (freeblCipherFunc) | 1144 cx->worker = (freeblCipherFunc) |
1122 (encrypt ? GCM_EncryptUpdate : GCM_DecryptUpdate); | 1145 (encrypt ? GCM_EncryptUpdate : GCM_DecryptUpdate); |
1123 cx->destroy = (freeblDestroyFunc) GCM_DestroyContext; | 1146 cx->destroy = (freeblDestroyFunc) GCM_DestroyContext; |
1124 cx->isBlock = PR_FALSE; | 1147 cx->isBlock = PR_FALSE; |
| 1148 } |
1125 break; | 1149 break; |
1126 case NSS_AES_CTR: | 1150 case NSS_AES_CTR: |
1127 cx->worker_cx = CTR_CreateContext(cx, cx->worker, iv, blocksize); | 1151 cx->worker_cx = CTR_CreateContext(cx, cx->worker, iv, blocksize); |
1128 cx->worker = (freeblCipherFunc) CTR_Update ; | 1152 cx->worker = (freeblCipherFunc) CTR_Update ; |
1129 cx->destroy = (freeblDestroyFunc) CTR_DestroyContext; | 1153 cx->destroy = (freeblDestroyFunc) CTR_DestroyContext; |
1130 cx->isBlock = PR_FALSE; | 1154 cx->isBlock = PR_FALSE; |
1131 break; | 1155 break; |
1132 default: | 1156 default: |
1133 /* everything has already been set up by aes_InitContext, just | 1157 /* everything has already been set up by aes_InitContext, just |
1134 * return */ | 1158 * return */ |
1135 return SECSuccess; | 1159 return SECSuccess; |
1136 } | 1160 } |
1137 /* check to see if we succeeded in getting the worker context */ | 1161 /* check to see if we succeeded in getting the worker context */ |
1138 if (cx->worker_cx == NULL) { | 1162 if (cx->worker_cx == NULL) { |
1139 /* no, just destroy the existing context */ | 1163 /* no, just destroy the existing context */ |
1140 cx->destroy = NULL; /* paranoia, though you can see a dozen lines */ | 1164 cx->destroy = NULL; /* paranoia, though you can see a dozen lines */ |
1141 /* below that this isn't necessary */ | 1165 /* below that this isn't necessary */ |
1142 » AES_DestroyContext(cx, PR_TRUE); | 1166 » AES_DestroyContext(cx, PR_FALSE); |
1143 return SECFailure; | 1167 return SECFailure; |
1144 } | 1168 } |
1145 return SECSuccess; | 1169 return SECSuccess; |
1146 } | 1170 } |
1147 | 1171 |
1148 /* AES_CreateContext | 1172 /* AES_CreateContext |
1149 * | 1173 * |
1150 * create a new context for Rijndael operations | 1174 * create a new context for Rijndael operations |
1151 */ | 1175 */ |
1152 AESContext * | 1176 AESContext * |
(...skipping 15 matching lines...) Expand all Loading... |
1168 | 1192 |
1169 /* | 1193 /* |
1170 * AES_DestroyContext | 1194 * AES_DestroyContext |
1171 * | 1195 * |
1172 * Zero an AES cipher context. If freeit is true, also free the pointer | 1196 * Zero an AES cipher context. If freeit is true, also free the pointer |
1173 * to the context. | 1197 * to the context. |
1174 */ | 1198 */ |
1175 void | 1199 void |
1176 AES_DestroyContext(AESContext *cx, PRBool freeit) | 1200 AES_DestroyContext(AESContext *cx, PRBool freeit) |
1177 { | 1201 { |
1178 /* memset(cx, 0, sizeof *cx); */ | |
1179 if (cx->worker_cx && cx->destroy) { | 1202 if (cx->worker_cx && cx->destroy) { |
1180 (*cx->destroy)(cx->worker_cx, PR_TRUE); | 1203 (*cx->destroy)(cx->worker_cx, PR_TRUE); |
| 1204 cx->worker_cx = NULL; |
| 1205 cx->destroy = NULL; |
1181 } | 1206 } |
1182 if (freeit) | 1207 if (freeit) |
1183 PORT_Free(cx); | 1208 PORT_Free(cx); |
1184 } | 1209 } |
1185 | 1210 |
1186 /* | 1211 /* |
1187 * AES_Encrypt | 1212 * AES_Encrypt |
1188 * | 1213 * |
1189 * Encrypt an arbitrary-length buffer. The output buffer must already be | 1214 * Encrypt an arbitrary-length buffer. The output buffer must already be |
1190 * allocated to at least inputLen. | 1215 * allocated to at least inputLen. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1237 return SECFailure; | 1262 return SECFailure; |
1238 } | 1263 } |
1239 if (maxOutputLen < inputLen) { | 1264 if (maxOutputLen < inputLen) { |
1240 PORT_SetError(SEC_ERROR_OUTPUT_LEN); | 1265 PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
1241 return SECFailure; | 1266 return SECFailure; |
1242 } | 1267 } |
1243 *outputLen = inputLen; | 1268 *outputLen = inputLen; |
1244 return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen, | 1269 return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen, |
1245 input, inputLen, blocksize); | 1270 input, inputLen, blocksize); |
1246 } | 1271 } |
OLD | NEW |