Index: mozilla/security/nss/lib/freebl/rijndael.c |
=================================================================== |
--- mozilla/security/nss/lib/freebl/rijndael.c (revision 180567) |
+++ mozilla/security/nss/lib/freebl/rijndael.c (working copy) |
@@ -1,7 +1,7 @@ |
/* This Source Code Form is subject to the terms of the Mozilla Public |
* License, v. 2.0. If a copy of the MPL was not distributed with this |
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
-/* $Id: rijndael.c,v 1.28 2012/09/28 22:46:32 rrelyea%redhat.com Exp $ */ |
+/* $Id: rijndael.c,v 1.30 2013/01/25 18:02:53 rrelyea%redhat.com Exp $ */ |
#ifdef FREEBL_NO_DEPEND |
#include "stubs.h" |
@@ -20,8 +20,16 @@ |
#include "gcm.h" |
#if USE_HW_AES |
+#include "intel-gcm.h" |
#include "intel-aes.h" |
#include "mpi.h" |
+ |
+static int has_intel_aes = 0; |
+static int has_intel_avx = 0; |
+static int has_intel_clmul = 0; |
+static PRBool use_hw_aes = PR_FALSE; |
+static PRBool use_hw_avx = PR_FALSE; |
+static PRBool use_hw_gcm = PR_FALSE; |
#endif |
/* |
@@ -970,10 +978,6 @@ |
const unsigned char *iv, int mode, unsigned int encrypt, |
unsigned int blocksize) |
{ |
-#if USE_HW_AES |
- static int has_intel_aes; |
- PRBool use_hw_aes = PR_FALSE; |
-#endif |
unsigned int Nk; |
/* According to Rijndael AES Proposal, section 12.1, block and key |
* lengths between 128 and 256 bits are supported, as long as the |
@@ -1009,12 +1013,18 @@ |
if (disable_hw_aes == NULL) { |
freebl_cpuid(1, &eax, &ebx, &ecx, &edx); |
has_intel_aes = (ecx & (1 << 25)) != 0 ? 1 : -1; |
+ has_intel_clmul = (ecx & (1 << 1)) != 0 ? 1 : -1; |
+ has_intel_avx = (ecx & (1 << 28)) != 0 ? 1 : -1; |
} else { |
has_intel_aes = -1; |
+ has_intel_avx = -1; |
+ has_intel_clmul = -1; |
} |
} |
use_hw_aes = (PRBool) |
(has_intel_aes > 0 && (keysize % 8) == 0 && blocksize == 16); |
+ use_hw_gcm = (PRBool) |
+ (use_hw_aes && has_intel_avx>0 && has_intel_clmul>0); |
#endif |
/* Nb = (block size in bits) / 32 */ |
cx->Nb = blocksize / 4; |
@@ -1100,10 +1110,13 @@ |
baseencrypt = PR_TRUE; |
break; |
} |
+ /* make sure enough is initializes so we can safely call Destroy */ |
+ cx->worker_cx = NULL; |
+ cx->destroy = NULL; |
rv = aes_InitContext(cx, key, keysize, iv, basemode, |
baseencrypt, blocksize); |
if (rv != SECSuccess) { |
- AES_DestroyContext(cx, PR_TRUE); |
+ AES_DestroyContext(cx, PR_FALSE); |
return rv; |
} |
@@ -1117,11 +1130,22 @@ |
cx->isBlock = PR_FALSE; |
break; |
case NSS_AES_GCM: |
+#if USE_HW_AES |
+ if(use_hw_gcm) { |
+ cx->worker_cx = intel_AES_GCM_CreateContext(cx, cx->worker, iv, blocksize); |
+ cx->worker = (freeblCipherFunc) |
+ (encrypt ? intel_AES_GCM_EncryptUpdate : intel_AES_GCM_DecryptUpdate); |
+ cx->destroy = (freeblDestroyFunc) intel_AES_GCM_DestroyContext; |
+ cx->isBlock = PR_FALSE; |
+ } else |
+#endif |
+ { |
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); |
@@ -1139,7 +1163,7 @@ |
/* 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); |
+ AES_DestroyContext(cx, PR_FALSE); |
return SECFailure; |
} |
return SECSuccess; |
@@ -1175,9 +1199,10 @@ |
void |
AES_DestroyContext(AESContext *cx, PRBool freeit) |
{ |
-/* memset(cx, 0, sizeof *cx); */ |
if (cx->worker_cx && cx->destroy) { |
(*cx->destroy)(cx->worker_cx, PR_TRUE); |
+ cx->worker_cx = NULL; |
+ cx->destroy = NULL; |
} |
if (freeit) |
PORT_Free(cx); |