| 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 |