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

Unified Diff: nss/lib/freebl/intel-gcm-wrap.c

Issue 214183004: Implement AES in different modes of operation, using AES-NI and (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss.git@master
Patch Set: Remove an assertion. ctr->cipher doesn't set *outlen. Created 6 years, 8 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
« no previous file with comments | « nss/lib/freebl/intel-gcm.h ('k') | nss/lib/freebl/intel-gcm-x64-masm.asm » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: nss/lib/freebl/intel-gcm-wrap.c
diff --git a/nss/lib/freebl/intel-gcm-wrap.c b/nss/lib/freebl/intel-gcm-wrap.c
new file mode 100644
index 0000000000000000000000000000000000000000..afd3029383739922578f305f487b5bb4a14d0c79
--- /dev/null
+++ b/nss/lib/freebl/intel-gcm-wrap.c
@@ -0,0 +1,240 @@
+/* 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/. */
+/* Copyright(c) 2013, Intel Corp. */
+
+/* Wrapper functions for Intel optimized implementation of AES-GCM */
+
+#ifdef USE_HW_AES
+
+#ifdef FREEBL_NO_DEPEND
+#include "stubs.h"
+#endif
+
+#include "blapii.h"
+#include "blapit.h"
+#include "gcm.h"
+#include "ctr.h"
+#include "secerr.h"
+#include "prtypes.h"
+#include "pkcs11t.h"
+
+#include <limits.h>
+
+#include "intel-gcm.h"
+#include "rijndael.h"
+
+#include <emmintrin.h>
+#include <tmmintrin.h>
+
+
+struct intel_AES_GCMContextStr{
+ unsigned char Htbl[16*AES_BLOCK_SIZE];
+ unsigned char X0[AES_BLOCK_SIZE];
+ unsigned char T[AES_BLOCK_SIZE];
+ unsigned char CTR[AES_BLOCK_SIZE];
+ AESContext *aes_context;
+ unsigned long tagBits;
+ unsigned long Alen;
+ unsigned long Mlen;
+};
+
+intel_AES_GCMContext *intel_AES_GCM_CreateContext(void *context,
+ freeblCipherFunc cipher,
+ const unsigned char *params,
+ unsigned int blocksize)
+{
+ intel_AES_GCMContext *gcm = NULL;
+ AESContext *aes = (AESContext*)context;
+ const CK_GCM_PARAMS *gcmParams = (const CK_GCM_PARAMS *)params;
+ unsigned char buff[AES_BLOCK_SIZE]; /* aux buffer */
+
+ int IV_whole_len = gcmParams->ulIvLen&(~0xf);
+ int IV_remainder_len = gcmParams->ulIvLen&0xf;
+ int AAD_whole_len = gcmParams->ulAADLen&(~0xf);
+ int AAD_remainder_len = gcmParams->ulAADLen&0xf;
+
+ __m128i BSWAP_MASK = _mm_setr_epi8(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0);
+ __m128i ONE = _mm_set_epi32(0,0,0,1);
+ unsigned int j;
+ SECStatus rv;
+
+ if (blocksize != AES_BLOCK_SIZE) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return NULL;
+ }
+ gcm = PORT_ZNew(intel_AES_GCMContext);
+
+ if (gcm == NULL) {
+ return NULL;
+ }
+ /* initialize context fields */
+ gcm->aes_context = aes;
+ gcm->tagBits = gcmParams->ulTagBits;
+ gcm->Alen = 0;
+ gcm->Mlen = 0;
+ /* first prepare H and its derivatives for ghash */
+ intel_aes_gcmINIT(gcm->Htbl, (unsigned char*)aes->expandedKey, aes->Nr);
+ /* Initial TAG value is zero*/
+ _mm_storeu_si128((__m128i*)gcm->T, _mm_setzero_si128());
+ _mm_storeu_si128((__m128i*)gcm->X0, _mm_setzero_si128());
+ /* Init the counter */
+ if(gcmParams->ulIvLen == 12) {
+ _mm_storeu_si128((__m128i*)gcm->CTR, _mm_setr_epi32(((unsigned int*)gcmParams->pIv)[0], ((unsigned int*)gcmParams->pIv)[1], ((unsigned int*)gcmParams->pIv)[2], 0x01000000));
+ } else {
+ /* If IV size is not 96 bits, then the initial counter value is GHASH of the IV */
+ intel_aes_gcmAAD(gcm->Htbl, gcmParams->pIv, IV_whole_len, gcm->T);
+ /* Partial block */
+ if(IV_remainder_len) {
+ PORT_Memset(buff, 0, AES_BLOCK_SIZE);
+ PORT_Memcpy(buff, gcmParams->pIv + IV_whole_len, IV_remainder_len);
+ intel_aes_gcmAAD(gcm->Htbl, buff, AES_BLOCK_SIZE, gcm->T);
+ }
+
+ intel_aes_gcmTAG
+ (
+ gcm->Htbl,
+ gcm->T,
+ gcmParams->ulIvLen,
+ 0,
+ gcm->X0,
+ gcm->CTR
+ );
+ /* TAG should be zero again */
+ _mm_storeu_si128((__m128i*)gcm->T, _mm_setzero_si128());
+ }
+ /* Encrypt the initial counter, will be used to encrypt the GHASH value, in the end */
+ rv = (*cipher)(context, gcm->X0, &j, AES_BLOCK_SIZE, gcm->CTR, AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ /* Promote the counter by 1 */
+ _mm_storeu_si128((__m128i*)gcm->CTR, _mm_shuffle_epi8(_mm_add_epi32(ONE, _mm_shuffle_epi8(_mm_loadu_si128((__m128i*)gcm->CTR), BSWAP_MASK)), BSWAP_MASK));
+
+/* Now hash AAD - it would actually make sense to seperate the context creation from the AAD,
+ * because that would allow to reuse the H, which only changes when the AES key changes,
+ * and not every package, like the IV and AAD */
+ intel_aes_gcmAAD(gcm->Htbl, gcmParams->pAAD, AAD_whole_len, gcm->T);
+ if(AAD_remainder_len) {
+ PORT_Memset(buff, 0, AES_BLOCK_SIZE);
+ PORT_Memcpy(buff, gcmParams->pAAD + AAD_whole_len, AAD_remainder_len);
+ intel_aes_gcmAAD(gcm->Htbl, buff, AES_BLOCK_SIZE, gcm->T);
+ }
+ gcm->Alen += gcmParams->ulAADLen;
+ return gcm;
+
+ loser:
+ if (gcm) {
+ PORT_Free(gcm);
+ }
+ return NULL;
+}
+
+void intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit)
+{
+ if (freeit) {
+ PORT_Free(gcm);
+ }
+}
+
+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 tagBytes;
+ unsigned char T[AES_BLOCK_SIZE];
+ int j;
+
+ tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE-1)) / PR_BITS_PER_BYTE;
+ if (UINT_MAX - inlen < tagBytes) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ return SECFailure;
+ }
+ if (maxout < inlen + tagBytes) {
+ *outlen = inlen + tagBytes;
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ return SECFailure;
+ }
+
+ intel_aes_gcmENC(
+ inbuf,
+ outbuf,
+ gcm,
+ inlen);
+
+ gcm->Mlen += inlen;
+
+ intel_aes_gcmTAG(
+ gcm->Htbl,
+ gcm->T,
+ gcm->Mlen,
+ gcm->Alen,
+ gcm->X0,
+ T);
+
+ *outlen = inlen + tagBytes;
+
+ for(j=0; j<tagBytes; j++)
+ {
+ outbuf[inlen+j] = T[j];
+ }
+ return SECSuccess;
+}
+
+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 tagBytes;
+ unsigned char T[AES_BLOCK_SIZE];
+ const unsigned char *intag;
+
+ tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE-1)) / PR_BITS_PER_BYTE;
+
+ /* get the authentication block */
+ if (inlen < tagBytes) {
+ 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,
+ gcm,
+ inlen);
+
+ gcm->Mlen += inlen;
+ intel_aes_gcmTAG(
+ gcm->Htbl,
+ gcm->T,
+ gcm->Mlen,
+ gcm->Alen,
+ gcm->X0,
+ 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;
+ }
+ *outlen = inlen;
+
+ return SECSuccess;
+}
+
+#endif
« no previous file with comments | « nss/lib/freebl/intel-gcm.h ('k') | nss/lib/freebl/intel-gcm-x64-masm.asm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698