Index: patches/nss-intel-aes-windows.patch |
diff --git a/patches/nss-intel-aes-windows.patch b/patches/nss-intel-aes-windows.patch |
new file mode 100644 |
index 0000000000000000000000000000000000000000..67811e79df07ea82f03144030f231ce8d2255848 |
--- /dev/null |
+++ b/patches/nss-intel-aes-windows.patch |
@@ -0,0 +1,272 @@ |
+diff --git a/nss/lib/freebl/ctr.c b/nss/lib/freebl/ctr.c |
+index 3a2f1a6..4d26daa 100644 |
+--- a/nss/lib/freebl/ctr.c |
++++ b/nss/lib/freebl/ctr.c |
+@@ -12,6 +12,11 @@ |
+ #include "pkcs11t.h" |
+ #include "secerr.h" |
+ |
++#ifdef USE_HW_AES |
++#include "intel-aes.h" |
++#include "rijndael.h" |
++#endif |
++ |
+ SECStatus |
+ CTR_InitContext(CTRContext *ctr, void *context, freeblCipherFunc cipher, |
+ const unsigned char *param, unsigned int blocksize) |
+@@ -165,3 +170,60 @@ CTR_Update(CTRContext *ctr, unsigned char *outbuf, |
+ *outlen += inlen; |
+ return SECSuccess; |
+ } |
++ |
++#if defined(USE_HW_AES) && defined(_MSC_VER) |
++SECStatus |
++CTR_Update_HW_AES(CTRContext *ctr, unsigned char *outbuf, |
++ unsigned int *outlen, unsigned int maxout, |
++ const unsigned char *inbuf, unsigned int inlen, |
++ unsigned int blocksize) |
++{ |
++ unsigned int fullblocks; |
++ unsigned int tmp; |
++ SECStatus rv; |
++ |
++ if (maxout < inlen) { |
++ *outlen = inlen; |
++ PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
++ return SECFailure; |
++ } |
++ *outlen = 0; |
++ if (ctr->bufPtr != blocksize) { |
++ unsigned int needed = PR_MIN(blocksize-ctr->bufPtr, inlen); |
++ ctr_xor(outbuf, inbuf, ctr->buffer+ctr->bufPtr, needed); |
++ ctr->bufPtr += needed; |
++ outbuf += needed; |
++ inbuf += needed; |
++ *outlen += needed; |
++ inlen -= needed; |
++ if (inlen == 0) { |
++ return SECSuccess; |
++ } |
++ PORT_Assert(ctr->bufPtr == blocksize); |
++ } |
++ |
++ intel_aes_ctr_worker(((AESContext*)(ctr->context))->Nr)( |
++ ctr, outbuf, outlen, maxout, inbuf, inlen, blocksize); |
++ /* XXX intel_aes_ctr_worker should set *outlen. */ |
++ PORT_Assert(*outlen == 0); |
++ fullblocks = (inlen/blocksize)*blocksize; |
++ *outlen += fullblocks; |
++ outbuf += fullblocks; |
++ inbuf += fullblocks; |
++ inlen -= fullblocks; |
++ |
++ if (inlen == 0) { |
++ return SECSuccess; |
++ } |
++ rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize, |
++ ctr->counter, blocksize, blocksize); |
++ ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize); |
++ if (rv != SECSuccess) { |
++ return SECFailure; |
++ } |
++ ctr_xor(outbuf, inbuf, ctr->buffer, inlen); |
++ ctr->bufPtr = inlen; |
++ *outlen += inlen; |
++ return SECSuccess; |
++} |
++#endif |
+diff --git a/nss/lib/freebl/ctr.h b/nss/lib/freebl/ctr.h |
+index 69ef150..e7645a2 100644 |
+--- a/nss/lib/freebl/ctr.h |
++++ b/nss/lib/freebl/ctr.h |
+@@ -41,4 +41,11 @@ SECStatus CTR_Update(CTRContext *ctr, unsigned char *outbuf, |
+ const unsigned char *inbuf, unsigned int inlen, |
+ unsigned int blocksize); |
+ |
++#ifdef USE_HW_AES |
++SECStatus CTR_Update_HW_AES(CTRContext *ctr, unsigned char *outbuf, |
++ unsigned int *outlen, unsigned int maxout, |
++ const unsigned char *inbuf, unsigned int inlen, |
++ unsigned int blocksize); |
++#endif |
++ |
+ #endif |
+diff --git a/nss/lib/freebl/intel-aes.h b/nss/lib/freebl/intel-aes.h |
+index 1e18007..3b71e5f 100644 |
+--- a/nss/lib/freebl/intel-aes.h |
++++ b/nss/lib/freebl/intel-aes.h |
+@@ -33,6 +33,12 @@ SECStatus intel_aes_decrypt_cbc_128(AESContext *cx, unsigned char *output, |
+ const unsigned char *input, |
+ unsigned int inputLen, |
+ unsigned int blocksize); |
++SECStatus intel_aes_encrypt_ctr_128(CTRContext *cx, unsigned char *output, |
++ unsigned int *outputLen, |
++ unsigned int maxOutputLen, |
++ const unsigned char *input, |
++ unsigned int inputLen, |
++ unsigned int blocksize); |
+ SECStatus intel_aes_encrypt_ecb_192(AESContext *cx, unsigned char *output, |
+ unsigned int *outputLen, |
+ unsigned int maxOutputLen, |
+@@ -57,6 +63,12 @@ SECStatus intel_aes_decrypt_cbc_192(AESContext *cx, unsigned char *output, |
+ const unsigned char *input, |
+ unsigned int inputLen, |
+ unsigned int blocksize); |
++SECStatus intel_aes_encrypt_ctr_192(CTRContext *cx, unsigned char *output, |
++ unsigned int *outputLen, |
++ unsigned int maxOutputLen, |
++ const unsigned char *input, |
++ unsigned int inputLen, |
++ unsigned int blocksize); |
+ SECStatus intel_aes_encrypt_ecb_256(AESContext *cx, unsigned char *output, |
+ unsigned int *outputLen, |
+ unsigned int maxOutputLen, |
+@@ -81,6 +93,12 @@ SECStatus intel_aes_decrypt_cbc_256(AESContext *cx, unsigned char *output, |
+ const unsigned char *input, |
+ unsigned int inputLen, |
+ unsigned int blocksize); |
++SECStatus intel_aes_encrypt_ctr_256(CTRContext *cx, unsigned char *output, |
++ unsigned int *outputLen, |
++ unsigned int maxOutputLen, |
++ const unsigned char *input, |
++ unsigned int inputLen, |
++ unsigned int blocksize); |
+ |
+ |
+ #define intel_aes_ecb_worker(encrypt, keysize) \ |
+@@ -102,6 +120,11 @@ SECStatus intel_aes_decrypt_cbc_256(AESContext *cx, unsigned char *output, |
+ (keysize) == 24 ? intel_aes_decrypt_cbc_192 : \ |
+ intel_aes_decrypt_cbc_256)) |
+ |
++#define intel_aes_ctr_worker(nr) \ |
++ ((nr) == 10 ? intel_aes_encrypt_ctr_128 : \ |
++ (nr) == 12 ? intel_aes_encrypt_ctr_192 : \ |
++ intel_aes_encrypt_ctr_256) |
++ |
+ |
+ #define intel_aes_init(encrypt, keysize) \ |
+ do { \ |
+diff --git a/nss/lib/freebl/intel-gcm-wrap.c b/nss/lib/freebl/intel-gcm-wrap.c |
+index b2f6f5e..afd3029 100644 |
+--- a/nss/lib/freebl/intel-gcm-wrap.c |
++++ b/nss/lib/freebl/intel-gcm-wrap.c |
+@@ -3,7 +3,7 @@ |
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
+ /* Copyright(c) 2013, Intel Corp. */ |
+ |
+-/* Wrapper funcions for Intel optimized implementation of AES-GCM */ |
++/* Wrapper functions for Intel optimized implementation of AES-GCM */ |
+ |
+ #ifdef USE_HW_AES |
+ |
+@@ -24,12 +24,8 @@ |
+ #include "intel-gcm.h" |
+ #include "rijndael.h" |
+ |
+-#if defined(__INTEL_COMPILER) |
+-#include <ia32intrin.h> |
+-#elif defined(__GNUC__) |
+ #include <emmintrin.h> |
+ #include <tmmintrin.h> |
+-#endif |
+ |
+ |
+ struct intel_AES_GCMContextStr{ |
+@@ -143,9 +139,9 @@ void intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit) |
+ |
+ SECStatus intel_AES_GCM_EncryptUpdate(intel_AES_GCMContext *gcm, |
+ unsigned char *outbuf, |
+- unsigned int *outlen, unsigned int maxout, |
+- const unsigned char *inbuf, unsigned int inlen, |
+- unsigned int blocksize) |
++ unsigned int *outlen, unsigned int maxout, |
++ const unsigned char *inbuf, unsigned int inlen, |
++ unsigned int blocksize) |
+ { |
+ unsigned int tagBytes; |
+ unsigned char T[AES_BLOCK_SIZE]; |
+@@ -189,9 +185,9 @@ SECStatus intel_AES_GCM_EncryptUpdate(intel_AES_GCMContext *gcm, |
+ |
+ SECStatus intel_AES_GCM_DecryptUpdate(intel_AES_GCMContext *gcm, |
+ unsigned char *outbuf, |
+- unsigned int *outlen, unsigned int maxout, |
+- const unsigned char *inbuf, unsigned int inlen, |
+- unsigned int blocksize) |
++ unsigned int *outlen, unsigned int maxout, |
++ const unsigned char *inbuf, unsigned int inlen, |
++ unsigned int blocksize) |
+ { |
+ unsigned int tagBytes; |
+ unsigned char T[AES_BLOCK_SIZE]; |
+@@ -201,13 +197,19 @@ SECStatus intel_AES_GCM_DecryptUpdate(intel_AES_GCMContext *gcm, |
+ |
+ /* get the authentication block */ |
+ if (inlen < tagBytes) { |
+- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
++ PORT_SetError(SEC_ERROR_INPUT_LEN); |
+ return SECFailure; |
+ } |
+ |
+ inlen -= tagBytes; |
+ intag = inbuf + inlen; |
+ |
++ if (maxout < inlen) { |
++ *outlen = inlen; |
++ PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
++ return SECFailure; |
++ } |
++ |
+ intel_aes_gcmDEC( |
+ inbuf, |
+ outbuf, |
+@@ -224,6 +226,8 @@ SECStatus intel_AES_GCM_DecryptUpdate(intel_AES_GCMContext *gcm, |
+ T); |
+ |
+ if (NSS_SecureMemcmp(T, intag, tagBytes) != 0) { |
++ memset(outbuf, 0, inlen); |
++ *outlen = 0; |
+ /* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */ |
+ PORT_SetError(SEC_ERROR_BAD_DATA); |
+ return SECFailure; |
+diff --git a/nss/lib/freebl/rijndael.c b/nss/lib/freebl/rijndael.c |
+index 8bb8905..9703867 100644 |
+--- a/nss/lib/freebl/rijndael.c |
++++ b/nss/lib/freebl/rijndael.c |
+@@ -1063,8 +1063,10 @@ aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize, |
+ intel_aes_cbc_worker(encrypt, keysize); |
+ } else |
+ #endif |
++ { |
+ cx->worker = (freeblCipherFunc) (encrypt |
+ ? &rijndael_encryptCBC : &rijndael_decryptCBC); |
++ } |
+ } else { |
+ #if USE_HW_AES |
+ if (use_hw_aes) { |
+@@ -1072,8 +1074,10 @@ aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize, |
+ intel_aes_ecb_worker(encrypt, keysize); |
+ } else |
+ #endif |
++ { |
+ cx->worker = (freeblCipherFunc) (encrypt |
+ ? &rijndael_encryptECB : &rijndael_decryptECB); |
++ } |
+ } |
+ PORT_Assert((cx->Nb * (cx->Nr + 1)) <= RIJNDAEL_MAX_EXP_KEY_SIZE); |
+ if ((cx->Nb * (cx->Nr + 1)) > RIJNDAEL_MAX_EXP_KEY_SIZE) { |
+@@ -1171,7 +1175,14 @@ AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize, |
+ break; |
+ case NSS_AES_CTR: |
+ cx->worker_cx = CTR_CreateContext(cx, cx->worker, iv, blocksize); |
+- cx->worker = (freeblCipherFunc) CTR_Update ; |
++#if defined(USE_HW_AES) && defined(_MSC_VER) |
++ if (use_hw_aes) { |
++ cx->worker = (freeblCipherFunc) CTR_Update_HW_AES; |
++ } else |
++#endif |
++ { |
++ cx->worker = (freeblCipherFunc) CTR_Update; |
++ } |
+ cx->destroy = (freeblDestroyFunc) CTR_DestroyContext; |
+ cx->isBlock = PR_FALSE; |
+ break; |