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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: nss/mozilla/security/nss/lib/freebl/rijndael.c
===================================================================
--- nss/mozilla/security/nss/lib/freebl/rijndael.c (revision 155503)
+++ nss/mozilla/security/nss/lib/freebl/rijndael.c (working copy)
@@ -47,6 +47,10 @@
#include "blapi.h"
#include "rijndael.h"
+#include "cts.h"
+#include "ctr.h"
+#include "gcm.h"
+
#if USE_HW_AES
#include "intel-aes.h"
#include "mpi.h"
@@ -988,8 +992,13 @@
}
-SECStatus
-AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
+/*
+** Initialize a new AES context suitable for AES encryption/decryption in
+** the ECB or CBC mode.
+** "mode" the mode of operation, which must be NSS_AES or NSS_AES_CBC
+*/
+static SECStatus
+aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
const unsigned char *iv, int mode, unsigned int encrypt,
unsigned int blocksize)
{
@@ -1050,18 +1059,20 @@
memcpy(cx->iv, iv, blocksize);
#if USE_HW_AES
if (use_hw_aes) {
- cx->worker = intel_aes_cbc_worker(encrypt, keysize);
+ cx->worker = (freeblCipherFunc)
+ intel_aes_cbc_worker(encrypt, keysize);
} else
#endif
- cx->worker = (encrypt
+ cx->worker = (freeblCipherFunc) (encrypt
? &rijndael_encryptCBC : &rijndael_decryptCBC);
} else {
#if USE_HW_AES
if (use_hw_aes) {
- cx->worker = intel_aes_ecb_worker(encrypt, keysize);
+ cx->worker = (freeblCipherFunc)
+ intel_aes_ecb_worker(encrypt, keysize);
} else
#endif
- cx->worker = (encrypt
+ cx->worker = (freeblCipherFunc) (encrypt
? &rijndael_encryptECB : &rijndael_decryptECB);
}
PORT_Assert((cx->Nb * (cx->Nr + 1)) <= RIJNDAEL_MAX_EXP_KEY_SIZE);
@@ -1094,12 +1105,78 @@
goto cleanup;
}
}
+ cx->worker_cx = cx;
+ cx->destroy = NULL;
+ cx->isBlock = PR_TRUE;
return SECSuccess;
cleanup:
return SECFailure;
}
+SECStatus
+AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
+ const unsigned char *iv, int mode, unsigned int encrypt,
+ unsigned int blocksize)
+{
+ int basemode = mode;
+ PRBool baseencrypt = encrypt;
+ SECStatus rv;
+ switch (mode) {
+ case NSS_AES_CTS:
+ basemode = NSS_AES_CBC;
+ break;
+ case NSS_AES_GCM:
+ case NSS_AES_CTR:
+ basemode = NSS_AES;
+ baseencrypt = PR_TRUE;
+ break;
+ }
+ rv = aes_InitContext(cx, key, keysize, iv, basemode,
+ baseencrypt, blocksize);
+ if (rv != SECSuccess) {
+ AES_DestroyContext(cx, PR_TRUE);
+ return rv;
+ }
+
+ /* finally, set up any mode specific contexts */
+ switch (mode) {
+ case NSS_AES_CTS:
+ cx->worker_cx = CTS_CreateContext(cx, cx->worker, iv, blocksize);
+ cx->worker = (freeblCipherFunc)
+ (encrypt ? CTS_EncryptUpdate : CTS_DecryptUpdate);
+ cx->destroy = (freeblDestroyFunc) CTS_DestroyContext;
+ cx->isBlock = PR_FALSE;
+ break;
+ case NSS_AES_GCM:
+ cx->worker_cx = GCM_CreateContext(cx, cx->worker, iv, blocksize);
+ cx->worker = (freeblCipherFunc)
+ (encrypt ? GCM_EncryptUpdate : GCM_DecryptUpdate);
+ cx->destroy = (freeblDestroyFunc) GCM_DestroyContext;
+ cx->isBlock = PR_FALSE;
+ break;
+ case NSS_AES_CTR:
+ cx->worker_cx = CTR_CreateContext(cx, cx->worker, iv, blocksize);
+ cx->worker = (freeblCipherFunc) CTR_Update ;
+ cx->destroy = (freeblDestroyFunc) CTR_DestroyContext;
+ cx->isBlock = PR_FALSE;
+ break;
+ default:
+ /* everything has already been set up by aes_InitContext, just
+ * return */
+ return SECSuccess;
+ }
+ /* check to see if we succeeded in getting the worker context */
+ if (cx->worker_cx == NULL) {
+ /* no, just destroy the existing context */
+ cx->destroy = NULL; /* paranoia, though you can see a dozen lines */
+ /* below that this isn't necessary */
+ AES_DestroyContext(cx, PR_TRUE);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
/* AES_CreateContext
*
* create a new context for Rijndael operations
@@ -1131,6 +1208,9 @@
AES_DestroyContext(AESContext *cx, PRBool freeit)
{
/* memset(cx, 0, sizeof *cx); */
+ if (cx->worker_cx && cx->destroy) {
+ (*cx->destroy)(cx->worker_cx, PR_TRUE);
+ }
if (freeit)
PORT_Free(cx);
}
@@ -1153,7 +1233,7 @@
return SECFailure;
}
blocksize = 4 * cx->Nb;
- if (inputLen % blocksize != 0) {
+ if (cx->isBlock && (inputLen % blocksize != 0)) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
@@ -1162,7 +1242,7 @@
return SECFailure;
}
*outputLen = inputLen;
- return (*cx->worker)(cx, output, outputLen, maxOutputLen,
+ return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,
input, inputLen, blocksize);
}
@@ -1184,7 +1264,7 @@
return SECFailure;
}
blocksize = 4 * cx->Nb;
- if (inputLen % blocksize != 0) {
+ if (cx->isBlock && (inputLen % blocksize != 0)) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
@@ -1193,6 +1273,6 @@
return SECFailure;
}
*outputLen = inputLen;
- return (*cx->worker)(cx, output, outputLen, maxOutputLen,
+ return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,
input, inputLen, blocksize);
}

Powered by Google App Engine
This is Rietveld 408576698