Chromium Code Reviews| 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 |