Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Side by Side Diff: nss/mozilla/security/nss/lib/freebl/rijndael.c

Issue 10919163: Add GCM, CTR, and CTS modes to AES. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/
Patch Set: Fix comments as rsleevi suggested, fix a 32-bit bug and miscellaneous issues Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698