| 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);
|
| }
|
|
|