OLD | NEW |
1 /* ***** BEGIN LICENSE BLOCK ***** | 1 /* ***** BEGIN LICENSE BLOCK ***** |
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
3 * | 3 * |
4 * The contents of this file are subject to the Mozilla Public License Version | 4 * The contents of this file are subject to the Mozilla Public License Version |
5 * 1.1 (the "License"); you may not use this file except in compliance with | 5 * 1.1 (the "License"); you may not use this file except in compliance with |
6 * the License. You may obtain a copy of the License at | 6 * the License. You may obtain a copy of the License at |
7 * http://www.mozilla.org/MPL/ | 7 * http://www.mozilla.org/MPL/ |
8 * | 8 * |
9 * Software distributed under the License is distributed on an "AS IS" basis, | 9 * Software distributed under the License is distributed on an "AS IS" basis, |
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
(...skipping 29 matching lines...) Expand all Loading... |
40 #endif | 40 #endif |
41 | 41 |
42 #include "prinit.h" | 42 #include "prinit.h" |
43 #include "prerr.h" | 43 #include "prerr.h" |
44 #include "secerr.h" | 44 #include "secerr.h" |
45 | 45 |
46 #include "prtypes.h" | 46 #include "prtypes.h" |
47 #include "blapi.h" | 47 #include "blapi.h" |
48 #include "rijndael.h" | 48 #include "rijndael.h" |
49 | 49 |
| 50 #include "cts.h" |
| 51 #include "ctr.h" |
| 52 #include "gcm.h" |
| 53 |
50 #if USE_HW_AES | 54 #if USE_HW_AES |
51 #include "intel-aes.h" | 55 #include "intel-aes.h" |
52 #include "mpi.h" | 56 #include "mpi.h" |
53 #endif | 57 #endif |
54 | 58 |
55 /* | 59 /* |
56 * There are currently five ways to build this code, varying in performance | 60 * There are currently five ways to build this code, varying in performance |
57 * and code size. | 61 * and code size. |
58 * | 62 * |
59 * RIJNDAEL_INCLUDE_TABLES Include all tables from rijndael32.tab | 63 * RIJNDAEL_INCLUDE_TABLES Include all tables from rijndael32.tab |
(...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 * BLAPI for the AES cipher, Rijndael. | 985 * BLAPI for the AES cipher, Rijndael. |
982 * | 986 * |
983 ***********************************************************************/ | 987 ***********************************************************************/ |
984 | 988 |
985 AESContext * AES_AllocateContext(void) | 989 AESContext * AES_AllocateContext(void) |
986 { | 990 { |
987 return PORT_ZNew(AESContext); | 991 return PORT_ZNew(AESContext); |
988 } | 992 } |
989 | 993 |
990 | 994 |
991 SECStatus | 995 /* |
992 AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize, | 996 ** Initialize a new AES context suitable for AES encryption/decryption in |
| 997 ** the ECB or CBC mode. |
| 998 ** » "mode" the mode of operation, which must be NSS_AES or NSS_AES_CBC |
| 999 */ |
| 1000 static SECStatus |
| 1001 aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize, |
993 const unsigned char *iv, int mode, unsigned int encrypt, | 1002 const unsigned char *iv, int mode, unsigned int encrypt, |
994 unsigned int blocksize) | 1003 unsigned int blocksize) |
995 { | 1004 { |
996 #if USE_HW_AES | 1005 #if USE_HW_AES |
997 static int has_intel_aes; | 1006 static int has_intel_aes; |
998 PRBool use_hw_aes = PR_FALSE; | 1007 PRBool use_hw_aes = PR_FALSE; |
999 #endif | 1008 #endif |
1000 unsigned int Nk; | 1009 unsigned int Nk; |
1001 /* According to Rijndael AES Proposal, section 12.1, block and key | 1010 /* According to Rijndael AES Proposal, section 12.1, block and key |
1002 * lengths between 128 and 256 bits are supported, as long as the | 1011 * lengths between 128 and 256 bits are supported, as long as the |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1043 cx->Nb = blocksize / 4; | 1052 cx->Nb = blocksize / 4; |
1044 /* Nk = (key size in bits) / 32 */ | 1053 /* Nk = (key size in bits) / 32 */ |
1045 Nk = keysize / 4; | 1054 Nk = keysize / 4; |
1046 /* Obtain number of rounds from "table" */ | 1055 /* Obtain number of rounds from "table" */ |
1047 cx->Nr = RIJNDAEL_NUM_ROUNDS(Nk, cx->Nb); | 1056 cx->Nr = RIJNDAEL_NUM_ROUNDS(Nk, cx->Nb); |
1048 /* copy in the iv, if neccessary */ | 1057 /* copy in the iv, if neccessary */ |
1049 if (mode == NSS_AES_CBC) { | 1058 if (mode == NSS_AES_CBC) { |
1050 memcpy(cx->iv, iv, blocksize); | 1059 memcpy(cx->iv, iv, blocksize); |
1051 #if USE_HW_AES | 1060 #if USE_HW_AES |
1052 if (use_hw_aes) { | 1061 if (use_hw_aes) { |
1053 » cx->worker = intel_aes_cbc_worker(encrypt, keysize); | 1062 » cx->worker = (freeblCipherFunc) |
| 1063 » » » » intel_aes_cbc_worker(encrypt, keysize); |
1054 } else | 1064 } else |
1055 #endif | 1065 #endif |
1056 » cx->worker = (encrypt | 1066 » cx->worker = (freeblCipherFunc) (encrypt |
1057 ? &rijndael_encryptCBC : &rijndael_decryptCBC); | 1067 ? &rijndael_encryptCBC : &rijndael_decryptCBC); |
1058 } else { | 1068 } else { |
1059 #if USE_HW_AES | 1069 #if USE_HW_AES |
1060 if (use_hw_aes) { | 1070 if (use_hw_aes) { |
1061 » cx->worker = intel_aes_ecb_worker(encrypt, keysize); | 1071 » cx->worker = (freeblCipherFunc) |
| 1072 » » » » intel_aes_ecb_worker(encrypt, keysize); |
1062 } else | 1073 } else |
1063 #endif | 1074 #endif |
1064 » cx->worker = (encrypt | 1075 » cx->worker = (freeblCipherFunc) (encrypt |
1065 ? &rijndael_encryptECB : &rijndael_decryptECB); | 1076 ? &rijndael_encryptECB : &rijndael_decryptECB); |
1066 } | 1077 } |
1067 PORT_Assert((cx->Nb * (cx->Nr + 1)) <= RIJNDAEL_MAX_EXP_KEY_SIZE); | 1078 PORT_Assert((cx->Nb * (cx->Nr + 1)) <= RIJNDAEL_MAX_EXP_KEY_SIZE); |
1068 if ((cx->Nb * (cx->Nr + 1)) > RIJNDAEL_MAX_EXP_KEY_SIZE) { | 1079 if ((cx->Nb * (cx->Nr + 1)) > RIJNDAEL_MAX_EXP_KEY_SIZE) { |
1069 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1080 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1070 goto cleanup; | 1081 goto cleanup; |
1071 } | 1082 } |
1072 #ifdef USE_HW_AES | 1083 #ifdef USE_HW_AES |
1073 if (use_hw_aes) { | 1084 if (use_hw_aes) { |
1074 intel_aes_init(encrypt, keysize); | 1085 intel_aes_init(encrypt, keysize); |
(...skipping 12 matching lines...) Expand all Loading... |
1087 #endif | 1098 #endif |
1088 /* Generate expanded key */ | 1099 /* Generate expanded key */ |
1089 if (encrypt) { | 1100 if (encrypt) { |
1090 if (rijndael_key_expansion(cx, key, Nk) != SECSuccess) | 1101 if (rijndael_key_expansion(cx, key, Nk) != SECSuccess) |
1091 goto cleanup; | 1102 goto cleanup; |
1092 } else { | 1103 } else { |
1093 if (rijndael_invkey_expansion(cx, key, Nk) != SECSuccess) | 1104 if (rijndael_invkey_expansion(cx, key, Nk) != SECSuccess) |
1094 goto cleanup; | 1105 goto cleanup; |
1095 } | 1106 } |
1096 } | 1107 } |
| 1108 cx->worker_cx = cx; |
| 1109 cx->destroy = NULL; |
| 1110 cx->isBlock = PR_TRUE; |
1097 return SECSuccess; | 1111 return SECSuccess; |
1098 cleanup: | 1112 cleanup: |
1099 return SECFailure; | 1113 return SECFailure; |
1100 } | 1114 } |
1101 | 1115 |
| 1116 SECStatus |
| 1117 AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize, |
| 1118 const unsigned char *iv, int mode, unsigned int encrypt, |
| 1119 unsigned int blocksize) |
| 1120 { |
| 1121 int basemode = mode; |
| 1122 PRBool baseencrypt = encrypt; |
| 1123 SECStatus rv; |
| 1124 |
| 1125 switch (mode) { |
| 1126 case NSS_AES_CTS: |
| 1127 basemode = NSS_AES_CBC; |
| 1128 break; |
| 1129 case NSS_AES_GCM: |
| 1130 case NSS_AES_CTR: |
| 1131 basemode = NSS_AES; |
| 1132 baseencrypt = PR_TRUE; |
| 1133 break; |
| 1134 } |
| 1135 rv = aes_InitContext(cx, key, keysize, iv, basemode, |
| 1136 baseencrypt, blocksize); |
| 1137 if (rv != SECSuccess) { |
| 1138 AES_DestroyContext(cx, PR_TRUE); |
| 1139 return rv; |
| 1140 } |
| 1141 |
| 1142 /* finally, set up any mode specific contexts */ |
| 1143 switch (mode) { |
| 1144 case NSS_AES_CTS: |
| 1145 cx->worker_cx = CTS_CreateContext(cx, cx->worker, iv, blocksize); |
| 1146 cx->worker = (freeblCipherFunc) |
| 1147 (encrypt ? CTS_EncryptUpdate : CTS_DecryptUpdate); |
| 1148 cx->destroy = (freeblDestroyFunc) CTS_DestroyContext; |
| 1149 cx->isBlock = PR_FALSE; |
| 1150 break; |
| 1151 case NSS_AES_GCM: |
| 1152 cx->worker_cx = GCM_CreateContext(cx, cx->worker, iv, blocksize); |
| 1153 cx->worker = (freeblCipherFunc) |
| 1154 (encrypt ? GCM_EncryptUpdate : GCM_DecryptUpdate); |
| 1155 cx->destroy = (freeblDestroyFunc) GCM_DestroyContext; |
| 1156 cx->isBlock = PR_FALSE; |
| 1157 break; |
| 1158 case NSS_AES_CTR: |
| 1159 cx->worker_cx = CTR_CreateContext(cx, cx->worker, iv, blocksize); |
| 1160 cx->worker = (freeblCipherFunc) CTR_Update ; |
| 1161 cx->destroy = (freeblDestroyFunc) CTR_DestroyContext; |
| 1162 cx->isBlock = PR_FALSE; |
| 1163 break; |
| 1164 default: |
| 1165 /* everything has already been set up by aes_InitContext, just |
| 1166 * return */ |
| 1167 return SECSuccess; |
| 1168 } |
| 1169 /* check to see if we succeeded in getting the worker context */ |
| 1170 if (cx->worker_cx == NULL) { |
| 1171 /* no, just destroy the existing context */ |
| 1172 cx->destroy = NULL; /* paranoia, though you can see a dozen lines */ |
| 1173 /* below that this isn't necessary */ |
| 1174 AES_DestroyContext(cx, PR_TRUE); |
| 1175 return SECFailure; |
| 1176 } |
| 1177 return SECSuccess; |
| 1178 } |
1102 | 1179 |
1103 /* AES_CreateContext | 1180 /* AES_CreateContext |
1104 * | 1181 * |
1105 * create a new context for Rijndael operations | 1182 * create a new context for Rijndael operations |
1106 */ | 1183 */ |
1107 AESContext * | 1184 AESContext * |
1108 AES_CreateContext(const unsigned char *key, const unsigned char *iv, | 1185 AES_CreateContext(const unsigned char *key, const unsigned char *iv, |
1109 int mode, int encrypt, | 1186 int mode, int encrypt, |
1110 unsigned int keysize, unsigned int blocksize) | 1187 unsigned int keysize, unsigned int blocksize) |
1111 { | 1188 { |
(...skipping 12 matching lines...) Expand all Loading... |
1124 /* | 1201 /* |
1125 * AES_DestroyContext | 1202 * AES_DestroyContext |
1126 * | 1203 * |
1127 * Zero an AES cipher context. If freeit is true, also free the pointer | 1204 * Zero an AES cipher context. If freeit is true, also free the pointer |
1128 * to the context. | 1205 * to the context. |
1129 */ | 1206 */ |
1130 void | 1207 void |
1131 AES_DestroyContext(AESContext *cx, PRBool freeit) | 1208 AES_DestroyContext(AESContext *cx, PRBool freeit) |
1132 { | 1209 { |
1133 /* memset(cx, 0, sizeof *cx); */ | 1210 /* memset(cx, 0, sizeof *cx); */ |
| 1211 if (cx->worker_cx && cx->destroy) { |
| 1212 (*cx->destroy)(cx->worker_cx, PR_TRUE); |
| 1213 } |
1134 if (freeit) | 1214 if (freeit) |
1135 PORT_Free(cx); | 1215 PORT_Free(cx); |
1136 } | 1216 } |
1137 | 1217 |
1138 /* | 1218 /* |
1139 * AES_Encrypt | 1219 * AES_Encrypt |
1140 * | 1220 * |
1141 * Encrypt an arbitrary-length buffer. The output buffer must already be | 1221 * Encrypt an arbitrary-length buffer. The output buffer must already be |
1142 * allocated to at least inputLen. | 1222 * allocated to at least inputLen. |
1143 */ | 1223 */ |
1144 SECStatus | 1224 SECStatus |
1145 AES_Encrypt(AESContext *cx, unsigned char *output, | 1225 AES_Encrypt(AESContext *cx, unsigned char *output, |
1146 unsigned int *outputLen, unsigned int maxOutputLen, | 1226 unsigned int *outputLen, unsigned int maxOutputLen, |
1147 const unsigned char *input, unsigned int inputLen) | 1227 const unsigned char *input, unsigned int inputLen) |
1148 { | 1228 { |
1149 int blocksize; | 1229 int blocksize; |
1150 /* Check args */ | 1230 /* Check args */ |
1151 if (cx == NULL || output == NULL || input == NULL) { | 1231 if (cx == NULL || output == NULL || input == NULL) { |
1152 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 1232 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
1153 return SECFailure; | 1233 return SECFailure; |
1154 } | 1234 } |
1155 blocksize = 4 * cx->Nb; | 1235 blocksize = 4 * cx->Nb; |
1156 if (inputLen % blocksize != 0) { | 1236 if (cx->isBlock && (inputLen % blocksize != 0)) { |
1157 PORT_SetError(SEC_ERROR_INPUT_LEN); | 1237 PORT_SetError(SEC_ERROR_INPUT_LEN); |
1158 return SECFailure; | 1238 return SECFailure; |
1159 } | 1239 } |
1160 if (maxOutputLen < inputLen) { | 1240 if (maxOutputLen < inputLen) { |
1161 PORT_SetError(SEC_ERROR_OUTPUT_LEN); | 1241 PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
1162 return SECFailure; | 1242 return SECFailure; |
1163 } | 1243 } |
1164 *outputLen = inputLen; | 1244 *outputLen = inputLen; |
1165 return (*cx->worker)(cx, output, outputLen, maxOutputLen,» | 1245 return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,» |
1166 input, inputLen, blocksize); | 1246 input, inputLen, blocksize); |
1167 } | 1247 } |
1168 | 1248 |
1169 /* | 1249 /* |
1170 * AES_Decrypt | 1250 * AES_Decrypt |
1171 * | 1251 * |
1172 * Decrypt and arbitrary-length buffer. The output buffer must already be | 1252 * Decrypt and arbitrary-length buffer. The output buffer must already be |
1173 * allocated to at least inputLen. | 1253 * allocated to at least inputLen. |
1174 */ | 1254 */ |
1175 SECStatus | 1255 SECStatus |
1176 AES_Decrypt(AESContext *cx, unsigned char *output, | 1256 AES_Decrypt(AESContext *cx, unsigned char *output, |
1177 unsigned int *outputLen, unsigned int maxOutputLen, | 1257 unsigned int *outputLen, unsigned int maxOutputLen, |
1178 const unsigned char *input, unsigned int inputLen) | 1258 const unsigned char *input, unsigned int inputLen) |
1179 { | 1259 { |
1180 int blocksize; | 1260 int blocksize; |
1181 /* Check args */ | 1261 /* Check args */ |
1182 if (cx == NULL || output == NULL || input == NULL) { | 1262 if (cx == NULL || output == NULL || input == NULL) { |
1183 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 1263 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
1184 return SECFailure; | 1264 return SECFailure; |
1185 } | 1265 } |
1186 blocksize = 4 * cx->Nb; | 1266 blocksize = 4 * cx->Nb; |
1187 if (inputLen % blocksize != 0) { | 1267 if (cx->isBlock && (inputLen % blocksize != 0)) { |
1188 PORT_SetError(SEC_ERROR_INPUT_LEN); | 1268 PORT_SetError(SEC_ERROR_INPUT_LEN); |
1189 return SECFailure; | 1269 return SECFailure; |
1190 } | 1270 } |
1191 if (maxOutputLen < inputLen) { | 1271 if (maxOutputLen < inputLen) { |
1192 PORT_SetError(SEC_ERROR_OUTPUT_LEN); | 1272 PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
1193 return SECFailure; | 1273 return SECFailure; |
1194 } | 1274 } |
1195 *outputLen = inputLen; | 1275 *outputLen = inputLen; |
1196 return (*cx->worker)(cx, output, outputLen, maxOutputLen,» | 1276 return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,» |
1197 input, inputLen, blocksize); | 1277 input, inputLen, blocksize); |
1198 } | 1278 } |
OLD | NEW |