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 983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1043 cx->Nb = blocksize / 4; | 1047 cx->Nb = blocksize / 4; |
1044 /* Nk = (key size in bits) / 32 */ | 1048 /* Nk = (key size in bits) / 32 */ |
1045 Nk = keysize / 4; | 1049 Nk = keysize / 4; |
1046 /* Obtain number of rounds from "table" */ | 1050 /* Obtain number of rounds from "table" */ |
1047 cx->Nr = RIJNDAEL_NUM_ROUNDS(Nk, cx->Nb); | 1051 cx->Nr = RIJNDAEL_NUM_ROUNDS(Nk, cx->Nb); |
1048 /* copy in the iv, if neccessary */ | 1052 /* copy in the iv, if neccessary */ |
1049 if (mode == NSS_AES_CBC) { | 1053 if (mode == NSS_AES_CBC) { |
1050 memcpy(cx->iv, iv, blocksize); | 1054 memcpy(cx->iv, iv, blocksize); |
1051 #if USE_HW_AES | 1055 #if USE_HW_AES |
1052 if (use_hw_aes) { | 1056 if (use_hw_aes) { |
1053 » cx->worker = intel_aes_cbc_worker(encrypt, keysize); | 1057 » cx->worker = (freeblCipherFunc) |
1058 » » » » intel_aes_cbc_worker(encrypt, keysize); | |
1054 } else | 1059 } else |
1055 #endif | 1060 #endif |
1056 » cx->worker = (encrypt | 1061 » cx->worker = (freeblCipherFunc) (encrypt |
1057 ? &rijndael_encryptCBC : &rijndael_decryptCBC); | 1062 ? &rijndael_encryptCBC : &rijndael_decryptCBC); |
1058 } else { | 1063 } else { |
1059 #if USE_HW_AES | 1064 #if USE_HW_AES |
1060 if (use_hw_aes) { | 1065 if (use_hw_aes) { |
1061 » cx->worker = intel_aes_ecb_worker(encrypt, keysize); | 1066 » cx->worker = (freeblCipherFunc) |
1067 » » » » intel_aes_ecb_worker(encrypt, keysize); | |
1062 } else | 1068 } else |
1063 #endif | 1069 #endif |
1064 » cx->worker = (encrypt | 1070 » cx->worker = (freeblCipherFunc) (encrypt |
1065 ? &rijndael_encryptECB : &rijndael_decryptECB); | 1071 ? &rijndael_encryptECB : &rijndael_decryptECB); |
1066 } | 1072 } |
1067 PORT_Assert((cx->Nb * (cx->Nr + 1)) <= RIJNDAEL_MAX_EXP_KEY_SIZE); | 1073 PORT_Assert((cx->Nb * (cx->Nr + 1)) <= RIJNDAEL_MAX_EXP_KEY_SIZE); |
1068 if ((cx->Nb * (cx->Nr + 1)) > RIJNDAEL_MAX_EXP_KEY_SIZE) { | 1074 if ((cx->Nb * (cx->Nr + 1)) > RIJNDAEL_MAX_EXP_KEY_SIZE) { |
1069 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1075 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1070 goto cleanup; | 1076 goto cleanup; |
1071 } | 1077 } |
1072 #ifdef USE_HW_AES | 1078 #ifdef USE_HW_AES |
1073 if (use_hw_aes) { | 1079 if (use_hw_aes) { |
1074 intel_aes_init(encrypt, keysize); | 1080 intel_aes_init(encrypt, keysize); |
(...skipping 12 matching lines...) Expand all Loading... | |
1087 #endif | 1093 #endif |
1088 /* Generate expanded key */ | 1094 /* Generate expanded key */ |
1089 if (encrypt) { | 1095 if (encrypt) { |
1090 if (rijndael_key_expansion(cx, key, Nk) != SECSuccess) | 1096 if (rijndael_key_expansion(cx, key, Nk) != SECSuccess) |
1091 goto cleanup; | 1097 goto cleanup; |
1092 } else { | 1098 } else { |
1093 if (rijndael_invkey_expansion(cx, key, Nk) != SECSuccess) | 1099 if (rijndael_invkey_expansion(cx, key, Nk) != SECSuccess) |
1094 goto cleanup; | 1100 goto cleanup; |
1095 } | 1101 } |
1096 } | 1102 } |
1103 cx->worker_cx = cx; | |
1104 cx->destroy = NULL; | |
1105 cx->isBlock = PR_TRUE; | |
1097 return SECSuccess; | 1106 return SECSuccess; |
1098 cleanup: | 1107 cleanup: |
1099 return SECFailure; | 1108 return SECFailure; |
1100 } | 1109 } |
1101 | 1110 |
1102 | 1111 |
1103 /* AES_CreateContext | 1112 /* AES_CreateContext |
1104 * | 1113 * |
1105 * create a new context for Rijndael operations | 1114 * create a new context for Rijndael operations |
1106 */ | 1115 */ |
1107 AESContext * | 1116 AESContext * |
1108 AES_CreateContext(const unsigned char *key, const unsigned char *iv, | 1117 AES_CreateContext(const unsigned char *key, const unsigned char *iv, |
1109 int mode, int encrypt, | 1118 int mode, int encrypt, |
1110 unsigned int keysize, unsigned int blocksize) | 1119 unsigned int keysize, unsigned int blocksize) |
1111 { | 1120 { |
1112 AESContext *cx = AES_AllocateContext(); | 1121 AESContext *cx = AES_AllocateContext(); |
1113 if (cx) { | 1122 int basemode = mode;; |
1114 » SECStatus rv = AES_InitContext(cx, key, keysize, iv, mode, encrypt, | 1123 PRBool baseencrypt = encrypt; |
1115 » » » » blocksize); | 1124 SECStatus rv; |
1116 » if (rv != SECSuccess) { | 1125 |
1117 » AES_DestroyContext(cx, PR_TRUE); | 1126 switch (mode) { |
1118 » cx = NULL; | 1127 case NSS_AES_CTS: |
1119 » } | 1128 » basemode = NSS_AES_CBC; |
1129 » break; | |
1130 case NSS_AES_GCM: | |
1131 case NSS_AES_CTR: | |
1132 » basemode = NSS_AES; | |
1133 » baseencrypt = PR_TRUE; | |
1134 » break; | |
1135 } | |
1136 if (cx == NULL) { | |
1137 » return NULL; | |
1138 } | |
1139 rv = AES_InitContext(cx, key, keysize, iv, basemode, | |
1140 » » » » » baseencrypt, blocksize); | |
1141 if (rv != SECSuccess) { | |
1142 » AES_DestroyContext(cx, PR_TRUE); | |
1143 » return NULL; | |
1144 } | |
1145 | |
1146 /* finally, set up any mode specific contexts */ | |
1147 switch (mode) { | |
1148 case NSS_AES_CTS: | |
1149 » cx->worker_cx = CTS_CreateContext(cx, cx->worker, iv, blocksize); | |
1150 » cx->worker = (freeblCipherFunc) | |
1151 » » » (encrypt ? CTS_EncryptUpdate : CTS_DecryptUpdate); | |
1152 » cx->destroy = (freeblDestroyFunc) CTS_DestroyContext; | |
1153 » cx->isBlock = PR_FALSE; | |
1154 » break; | |
1155 case NSS_AES_GCM: | |
1156 » cx->worker_cx = GCM_CreateContext(cx, cx->worker, iv, blocksize); | |
1157 » cx->worker = (freeblCipherFunc) | |
1158 » » » (encrypt ? GCM_EncryptUpdate : GCM_DecryptUpdate); | |
1159 » cx->destroy = (freeblDestroyFunc) GCM_DestroyContext; | |
1160 » cx->isBlock = PR_FALSE; | |
1161 » break; | |
1162 case NSS_AES_CTR: | |
1163 » cx->worker_cx = CTR_CreateContext(cx, cx->worker, iv, blocksize); | |
1164 » cx->worker = (freeblCipherFunc) CTR_Update ; | |
1165 » cx->destroy = (freeblDestroyFunc) CTR_DestroyContext; | |
1166 » cx->isBlock = PR_FALSE; | |
1167 » break; | |
1168 default: | |
1169 » /* everything has already been set up by AES_InitContext, just return*/ | |
1170 » return cx; | |
1171 } | |
1172 /* check to see if we succeeded in getting the worker context */ | |
1173 if (cx->worker_cx == NULL) { | |
1174 » /* no, just destroy the existing context */ | |
1175 » cx->destroy = NULL; /* paranoia, though you can see a dozen lines */ | |
1176 » » » /* below that this isn't necessary */ | |
1177 » AES_DestroyContext(cx, PR_TRUE); | |
1178 » return NULL; | |
1120 } | 1179 } |
1121 return cx; | 1180 return cx; |
1122 } | 1181 } |
1123 | 1182 |
1183 | |
1124 /* | 1184 /* |
1125 * AES_DestroyContext | 1185 * AES_DestroyContext |
1126 * | 1186 * |
1127 * Zero an AES cipher context. If freeit is true, also free the pointer | 1187 * Zero an AES cipher context. If freeit is true, also free the pointer |
1128 * to the context. | 1188 * to the context. |
1129 */ | 1189 */ |
1130 void | 1190 void |
1131 AES_DestroyContext(AESContext *cx, PRBool freeit) | 1191 AES_DestroyContext(AESContext *cx, PRBool freeit) |
1132 { | 1192 { |
1133 /* memset(cx, 0, sizeof *cx); */ | 1193 /* memset(cx, 0, sizeof *cx); */ |
1194 if (freeit && cx->worker_cx && cx->destroy) { | |
Ryan Sleevi
2012/09/11 19:34:30
It's not clear why you switch on freeit here.
My
rjrejyea
2012/09/19 22:19:33
It's ugly and has to do with psuedo private caller
| |
1195 (*cx->destroy)(cx->worker_cx, freeit); | |
1196 } | |
1134 if (freeit) | 1197 if (freeit) |
1135 PORT_Free(cx); | 1198 PORT_Free(cx); |
1136 } | 1199 } |
1137 | 1200 |
1138 /* | 1201 /* |
1139 * AES_Encrypt | 1202 * AES_Encrypt |
1140 * | 1203 * |
1141 * Encrypt an arbitrary-length buffer. The output buffer must already be | 1204 * Encrypt an arbitrary-length buffer. The output buffer must already be |
1142 * allocated to at least inputLen. | 1205 * allocated to at least inputLen. |
1143 */ | 1206 */ |
1144 SECStatus | 1207 SECStatus |
1145 AES_Encrypt(AESContext *cx, unsigned char *output, | 1208 AES_Encrypt(AESContext *cx, unsigned char *output, |
1146 unsigned int *outputLen, unsigned int maxOutputLen, | 1209 unsigned int *outputLen, unsigned int maxOutputLen, |
1147 const unsigned char *input, unsigned int inputLen) | 1210 const unsigned char *input, unsigned int inputLen) |
1148 { | 1211 { |
1149 int blocksize; | 1212 int blocksize; |
1150 /* Check args */ | 1213 /* Check args */ |
1151 if (cx == NULL || output == NULL || input == NULL) { | 1214 if (cx == NULL || output == NULL || input == NULL) { |
1152 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 1215 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
1153 return SECFailure; | 1216 return SECFailure; |
1154 } | 1217 } |
1155 blocksize = 4 * cx->Nb; | 1218 blocksize = 4 * cx->Nb; |
1156 if (inputLen % blocksize != 0) { | 1219 if (cx->isBlock && (inputLen % blocksize != 0)) { |
1157 PORT_SetError(SEC_ERROR_INPUT_LEN); | 1220 PORT_SetError(SEC_ERROR_INPUT_LEN); |
1158 return SECFailure; | 1221 return SECFailure; |
1159 } | 1222 } |
1160 if (maxOutputLen < inputLen) { | 1223 if (maxOutputLen < inputLen) { |
1161 PORT_SetError(SEC_ERROR_OUTPUT_LEN); | 1224 PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
1162 return SECFailure; | 1225 return SECFailure; |
1163 } | 1226 } |
1164 *outputLen = inputLen; | 1227 *outputLen = inputLen; |
1165 return (*cx->worker)(cx, output, outputLen, maxOutputLen,» | 1228 return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,» |
1166 input, inputLen, blocksize); | 1229 input, inputLen, blocksize); |
1167 } | 1230 } |
1168 | 1231 |
1169 /* | 1232 /* |
1170 * AES_Decrypt | 1233 * AES_Decrypt |
1171 * | 1234 * |
1172 * Decrypt and arbitrary-length buffer. The output buffer must already be | 1235 * Decrypt and arbitrary-length buffer. The output buffer must already be |
1173 * allocated to at least inputLen. | 1236 * allocated to at least inputLen. |
1174 */ | 1237 */ |
1175 SECStatus | 1238 SECStatus |
1176 AES_Decrypt(AESContext *cx, unsigned char *output, | 1239 AES_Decrypt(AESContext *cx, unsigned char *output, |
1177 unsigned int *outputLen, unsigned int maxOutputLen, | 1240 unsigned int *outputLen, unsigned int maxOutputLen, |
1178 const unsigned char *input, unsigned int inputLen) | 1241 const unsigned char *input, unsigned int inputLen) |
1179 { | 1242 { |
1180 int blocksize; | 1243 int blocksize; |
1181 /* Check args */ | 1244 /* Check args */ |
1182 if (cx == NULL || output == NULL || input == NULL) { | 1245 if (cx == NULL || output == NULL || input == NULL) { |
1183 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 1246 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
1184 return SECFailure; | 1247 return SECFailure; |
1185 } | 1248 } |
1186 blocksize = 4 * cx->Nb; | 1249 blocksize = 4 * cx->Nb; |
1187 if (inputLen % blocksize != 0) { | 1250 if (cx->isBlock && (inputLen % blocksize != 0)) { |
1188 PORT_SetError(SEC_ERROR_INPUT_LEN); | 1251 PORT_SetError(SEC_ERROR_INPUT_LEN); |
1189 return SECFailure; | 1252 return SECFailure; |
1190 } | 1253 } |
1191 if (maxOutputLen < inputLen) { | 1254 if (maxOutputLen < inputLen) { |
1192 PORT_SetError(SEC_ERROR_OUTPUT_LEN); | 1255 PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
1193 return SECFailure; | 1256 return SECFailure; |
1194 } | 1257 } |
1195 *outputLen = inputLen; | 1258 *outputLen = inputLen; |
1196 return (*cx->worker)(cx, output, outputLen, maxOutputLen,» | 1259 return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,» |
1197 input, inputLen, blocksize); | 1260 input, inputLen, blocksize); |
1198 } | 1261 } |
OLD | NEW |