#include "stdafx.h" #include "tunsafe_types.h" #include "tunsafe_endian.h" #include "tunsafe_cpu.h" #include "crypto/aesgcm/aes.h" #include #include #include //#include #include "crypto/chacha20poly1305.h" #define AESNIGCM_ASM 1 #define AESGCM_ASM 1 #define AESNI_GCM 1 // We only implement AES stuff on X86-64 #if WITH_AESGCM extern "C" { void gcm_init_clmul(aesgcm_u128 Htable[16],const uint64 Xi[2]); void gcm_gmult_clmul(uint64 Xi[2],const aesgcm_u128 Htable[16]); void gcm_ghash_clmul(uint64 Xi[2],const aesgcm_u128 Htable[16],const uint8 *inp,size_t len); void gcm_init_avx(aesgcm_u128 Htable[16],const uint64 Xi[2]); void gcm_gmult_avx(uint64 Xi[2],const aesgcm_u128 Htable[16]); void gcm_ghash_avx(uint64 Xi[2],const aesgcm_u128 Htable[16],const uint8 *inp,size_t len); void gcm_gmult_4bit(uint64 Xi[2], const aesgcm_u128 Htable[16]); void gcm_ghash_4bit(uint64 Xi[2],const aesgcm_u128 Htable[16], const uint8 *inp,size_t len); // ivec points to Yi followed by Xi // h_and_htable points at h and htable from the static context size_t aesni_gcm_encrypt(const uint8 *in,uint8 *out,size_t len,const void *key,uint8 ivec_and_xi[16],uint64 *h_and_htable); size_t aesni_gcm_decrypt(const uint8 *in,uint8 *out,size_t len,const void *key,uint8 ivec_and_xi[16],uint64 *h_and_htable); void aesni_ctr32_encrypt_blocks(const void *in, void *out, size_t blocks, const AesContext *key, const uint8 *ivec); void aesni_encrypt(const void *inp, void *out, const AesContext *key); void aesni_decrypt(const void *inp, void *out, const AesContext *key); int aesni_set_encrypt_key(const unsigned char *inp, int bits, AesContext *key); int aesni_set_decrypt_key(const unsigned char *inp, int bits, AesContext *key); }; #define GCM_MUL(ctx,Xi) (*gcm_gmult_p)(ctx->Xi.u,sctx->Htable) #define GHASH(ctx,in,len) (*gcm_ghash_p)(ctx->Xi.u,sctx->Htable,in,len) #define GHASH_CHUNK (3*1024) void CRYPTO_gcm128_aad(AesGcm128TempContext *ctx,const uint8 *aad,size_t len) { size_t i; unsigned int n; AesGcm128StaticContext *sctx = ctx->sctx; uint64 alen = ctx->len.u[0]; void (*gcm_gmult_p)(uint64 Xi[2],const aesgcm_u128 Htable[16]) = sctx->gmult; void (*gcm_ghash_p)(uint64 Xi[2],const aesgcm_u128 Htable[16], const uint8 *inp,size_t len) = sctx->ghash; assert(!ctx->len.u[1]); // if () return -2; alen += len; // if (alen>(uint64(1)<<61) || (sizeof(len)==8 && alenlen.u[0] = alen; n = ctx->ares; if (n) { while (n && len) { ctx->Xi.c[n] ^= *(aad++); --len; n = (n+1)%16; } if (n==0) GCM_MUL(ctx,Xi); else { ctx->ares = n; return; } } #ifdef GHASH if ((i = (len&(size_t)-16))) { GHASH(ctx,aad,i); aad += i; len -= i; } #else while (len>=16) { for (i=0; i<16; ++i) ctx->Xi.c[i] ^= aad[i]; GCM_MUL(ctx,Xi); aad += 16; len -= 16; } #endif if (len) { n = (unsigned int)len; for (i=0; iXi.c[i] ^= aad[i]; } ctx->ares = n; } void CRYPTO_gcm128_encrypt_ctr32(AesGcm128TempContext *ctx, const uint8 *in, uint8 *out, size_t len) { unsigned int n, ctr; size_t i; AesGcm128StaticContext *sctx = ctx->sctx; uint64 mlen = ctx->len.u[1]; void (*gcm_gmult_p)(uint64 Xi[2],const aesgcm_u128 Htable[16]) = sctx->gmult; void (*gcm_ghash_p)(uint64 Xi[2],const aesgcm_u128 Htable[16], const uint8 *inp,size_t len) = sctx->ghash; mlen += len; // if (mlen>((uint64(1)<<36)-32) || (sizeof(len)==8 && mlenlen.u[1] = mlen; if (ctx->ares) { /* First call to encrypt finalizes GHASH(AAD) */ GCM_MUL(ctx,Xi); ctx->ares = 0; } n = ctx->mres; if (n) { while (n && len) { ctx->Xi.c[n] ^= *(out++) = *(in++)^ctx->EKi.c[n]; --len; n = (n+1)%16; } if (n==0) GCM_MUL(ctx,Xi); else { ctx->mres = n; return; } } #if defined(AESNI_GCM) if (sctx->use_aesni_gcm_crypt && len >= 0x120) { // |aesni_gcm_encrypt| may not process all the input given to it. It may // not process *any* of its input if it is deemed too small. size_t bulk = aesni_gcm_encrypt(in, out, len, &sctx->aes, ctx->Yi.c, sctx->H.u); in += bulk; out += bulk; len -= bulk; } #endif ctr = ReadBE32(ctx->Yi.c + 12); #if defined(STRICT_ALIGNMENT) if (((size_t)in | (size_t)out) % sizeof(size_t) != 0) { for (i = 0; iYi.c, ctx->EKi.c, &sctx->aes); ++ctr; WriteBE32(ctx->Yi.c + 12, ctr); } ctx->Xi.c[n] ^= out[i] = in[i] ^ ctx->EKi.c[n]; n = (n + 1) % 16; if (n == 0) GCM_MUL(ctx, Xi); } ctx->mres = n; return; } #endif while (len>=GHASH_CHUNK) { aesni_ctr32_encrypt_blocks(in, out, GHASH_CHUNK / 16, &sctx->aes, ctx->Yi.c); GHASH(ctx, out, GHASH_CHUNK); ctr += GHASH_CHUNK / 16; WriteBE32(ctx->Yi.c + 12, ctr); in += GHASH_CHUNK; out += GHASH_CHUNK; len -= GHASH_CHUNK; } if ((i = (len&(size_t)-16))) { aesni_ctr32_encrypt_blocks(in, out, i / 16, &sctx->aes, ctx->Yi.c); GHASH(ctx, out, i); ctr += (uint32)(i / 16); WriteBE32(ctx->Yi.c + 12, ctr); out += i; in += i; len -= i; } if (len) { aesni_encrypt(ctx->Yi.c, ctx->EKi.c, &sctx->aes); ++ctr; WriteBE32(ctx->Yi.c+12,ctr); while (len--) { ctx->Xi.c[n] ^= out[n] = in[n] ^ ctx->EKi.c[n]; ++n; } } ctx->mres = n; } void CRYPTO_gcm128_decrypt_ctr32(AesGcm128TempContext *ctx, const uint8 *in, uint8 *out, size_t len) { unsigned int n, ctr; size_t i; uint64 mlen = ctx->len.u[1]; AesGcm128StaticContext *sctx = ctx->sctx; void (*gcm_gmult_p)(uint64 Xi[2],const aesgcm_u128 Htable[16]) = sctx->gmult; void (*gcm_ghash_p)(uint64 Xi[2],const aesgcm_u128 Htable[16], const uint8 *inp,size_t len) = sctx->ghash; mlen += len; // if (mlen>((uint64(1)<<36)-32) || (sizeof(len)==8 && mlenlen.u[1] = mlen; if (ctx->ares) { /* First call to decrypt finalizes GHASH(AAD) */ GCM_MUL(ctx,Xi); ctx->ares = 0; } n = ctx->mres; if (n) { while (n && len) { uint8 c = *(in++); *(out++) = c^ctx->EKi.c[n]; ctx->Xi.c[n] ^= c; --len; n = (n+1)%16; } if (n==0) GCM_MUL (ctx,Xi); else { ctx->mres = n; return; } } #if defined(AESNI_GCM) if (sctx->use_aesni_gcm_crypt) { // |aesni_gcm_decrypt| may not process all the input given to it. It may // not process *any* of its input if it is deemed too small. size_t bulk = aesni_gcm_decrypt(in, out, len, &sctx->aes, ctx->Yi.c, sctx->H.u); in += bulk; out += bulk; len -= bulk; } #endif ctr = ReadBE32(ctx->Yi.c + 12); #if defined(STRICT_ALIGNMENT) if (((size_t)in|(size_t)out)%sizeof(size_t) != 0) { for (i=0;iYi.c, ctx->EKi.c, key); ++ctr; WriteBE32(ctx->Yi.c+12,ctr); } c = in[i]; out[i] = c^ctx->EKi.c[n]; ctx->Xi.c[n] ^= c; n = (n+1)%16; if (n==0) GCM_MUL(ctx,Xi); } ctx->mres = n; return; } #endif while (len >= GHASH_CHUNK) { GHASH(ctx, in, GHASH_CHUNK); aesni_ctr32_encrypt_blocks(in, out, GHASH_CHUNK / 16, &sctx->aes, ctx->Yi.c); ctr += GHASH_CHUNK / 16; WriteBE32(ctx->Yi.c + 12, ctr); in += GHASH_CHUNK; out += GHASH_CHUNK; len -= GHASH_CHUNK; } if ((i = (len&(size_t)-16))) { GHASH(ctx, in, i); aesni_ctr32_encrypt_blocks(in, out, i / 16, &sctx->aes, ctx->Yi.c); ctr += (uint32)(i / 16); WriteBE32(ctx->Yi.c + 12, ctr); out += i; in += i; len -= i; } if (len) { aesni_encrypt(ctx->Yi.c, ctx->EKi.c, &sctx->aes); ++ctr; WriteBE32(ctx->Yi.c+12,ctr); while (len--) { uint8 c = in[n]; ctx->Xi.c[n] ^= c; out[n] = c^ctx->EKi.c[n]; ++n; } } ctx->mres = n; } void CRYPTO_gcm128_finish(AesGcm128TempContext *ctx,uint8 *tag, size_t len) { uint64 alen = ctx->len.u[0]<<3; uint64 clen = ctx->len.u[1]<<3; AesGcm128StaticContext *sctx = ctx->sctx; void (*gcm_gmult_p)(uint64 Xi[2],const aesgcm_u128 Htable[16]) = sctx->gmult; if (ctx->mres || ctx->ares) GCM_MUL(ctx,Xi); alen = ToBE64(alen); clen = ToBE64(clen); ctx->Xi.u[0] ^= alen; ctx->Xi.u[1] ^= clen; GCM_MUL(ctx,Xi); ctx->Xi.u[0] ^= ctx->EK0.u[0]; ctx->Xi.u[1] ^= ctx->EK0.u[1]; memcpy(tag, ctx->Xi.c,len); } #define REDUCE1BIT(V) do { \ if (sizeof(size_t)==8) { \ uint64 T = 0xe100000000000000ull & (0-(V.lo&1)); \ V.lo = (V.hi<<63)|(V.lo>>1); \ V.hi = (V.hi>>1 )^T; \ } else { \ uint32 T = 0xe1000000U & (0-(uint32)(V.lo&1)); \ V.lo = (V.hi<<63)|(V.lo>>1); \ V.hi = (V.hi>>1 )^((uint64)T<<32); \ } \ } while(0) static void gcm_init_4bit(aesgcm_u128 Htable[16], uint64 H[2]) { aesgcm_u128 V; Htable[0].hi = 0; Htable[0].lo = 0; V.hi = H[0]; V.lo = H[1]; Htable[8] = V; REDUCE1BIT(V); Htable[4] = V; REDUCE1BIT(V); Htable[2] = V; REDUCE1BIT(V); Htable[1] = V; Htable[3].hi = V.hi^Htable[2].hi, Htable[3].lo = V.lo^Htable[2].lo; V=Htable[4]; Htable[5].hi = V.hi^Htable[1].hi, Htable[5].lo = V.lo^Htable[1].lo; Htable[6].hi = V.hi^Htable[2].hi, Htable[6].lo = V.lo^Htable[2].lo; Htable[7].hi = V.hi^Htable[3].hi, Htable[7].lo = V.lo^Htable[3].lo; V=Htable[8]; Htable[9].hi = V.hi^Htable[1].hi, Htable[9].lo = V.lo^Htable[1].lo; Htable[10].hi = V.hi^Htable[2].hi, Htable[10].lo = V.lo^Htable[2].lo; Htable[11].hi = V.hi^Htable[3].hi, Htable[11].lo = V.lo^Htable[3].lo; Htable[12].hi = V.hi^Htable[4].hi, Htable[12].lo = V.lo^Htable[4].lo; Htable[13].hi = V.hi^Htable[5].hi, Htable[13].lo = V.lo^Htable[5].lo; Htable[14].hi = V.hi^Htable[6].hi, Htable[14].lo = V.lo^Htable[6].lo; Htable[15].hi = V.hi^Htable[7].hi, Htable[15].lo = V.lo^Htable[7].lo; } #if !AESGCM_ASM #define PACK(s) ((size_t)(s)<<(sizeof(size_t)*8-16)) static const size_t rem_4bit[16] = { PACK(0x0000), PACK(0x1C20), PACK(0x3840), PACK(0x2460), PACK(0x7080), PACK(0x6CA0), PACK(0x48C0), PACK(0x54E0), PACK(0xE100), PACK(0xFD20), PACK(0xD940), PACK(0xC560), PACK(0x9180), PACK(0x8DA0), PACK(0xA9C0), PACK(0xB5E0)}; void gcm_gmult_4bit(uint64 Xi[2], const aesgcm_u128 Htable[16]) { aesgcm_u128 Z; int cnt = 15; size_t rem, nlo, nhi; const union { long one; char little; } is_endian = {1}; nlo = ((const uint8 *)Xi)[15]; nhi = nlo>>4; nlo &= 0xf; Z.hi = Htable[nlo].hi; Z.lo = Htable[nlo].lo; while (1) { rem = (size_t)Z.lo&0xf; Z.lo = (Z.hi<<60)|(Z.lo>>4); Z.hi = (Z.hi>>4); if (sizeof(size_t)==8) Z.hi ^= rem_4bit[rem]; else Z.hi ^= (uint64)rem_4bit[rem]<<32; Z.hi ^= Htable[nhi].hi; Z.lo ^= Htable[nhi].lo; if (--cnt<0) break; nlo = ((const uint8 *)Xi)[cnt]; nhi = nlo>>4; nlo &= 0xf; rem = (size_t)Z.lo&0xf; Z.lo = (Z.hi<<60)|(Z.lo>>4); Z.hi = (Z.hi>>4); if (sizeof(size_t)==8) Z.hi ^= rem_4bit[rem]; else Z.hi ^= (uint64)rem_4bit[rem]<<32; Z.hi ^= Htable[nlo].hi; Z.lo ^= Htable[nlo].lo; } Xi[0] = ToBE64(Z.hi); Xi[1] = ToBE64(Z.lo); } void gcm_ghash_4bit(uint64 Xi[2],const aesgcm_u128 Htable[16], const uint8 *inp,size_t len) { aesgcm_u128 Z; int cnt; size_t rem, nlo, nhi; do { cnt = 15; nlo = ((const uint8 *)Xi)[15]; nlo ^= inp[15]; nhi = nlo>>4; nlo &= 0xf; Z.hi = Htable[nlo].hi; Z.lo = Htable[nlo].lo; while (1) { rem = (size_t)Z.lo&0xf; Z.lo = (Z.hi<<60)|(Z.lo>>4); Z.hi = (Z.hi>>4); if (sizeof(size_t)==8) Z.hi ^= rem_4bit[rem]; else Z.hi ^= (uint64)rem_4bit[rem]<<32; Z.hi ^= Htable[nhi].hi; Z.lo ^= Htable[nhi].lo; if (--cnt<0) break; nlo = ((const uint8 *)Xi)[cnt]; nlo ^= inp[cnt]; nhi = nlo>>4; nlo &= 0xf; rem = (size_t)Z.lo&0xf; Z.lo = (Z.hi<<60)|(Z.lo>>4); Z.hi = (Z.hi>>4); if (sizeof(size_t)==8) Z.hi ^= rem_4bit[rem]; else Z.hi ^= (uint64)rem_4bit[rem]<<32; Z.hi ^= Htable[nlo].hi; Z.lo ^= Htable[nlo].lo; } Xi[0] = ToBE64(Z.hi); Xi[1] = ToBE64(Z.lo); } while (inp+=16, len-=16); } #endif void CRYPTO_gcm128_init(AesGcm128StaticContext *ctx, const uint8 *key, int key_size) { memset(ctx,0,sizeof(*ctx)); ctx->use_aesni_gcm_crypt = X86_PCAP_MOVBE; aesni_set_encrypt_key(key, key_size, &ctx->aes); aesni_encrypt(ctx->H.c,ctx->H.c, &ctx->aes); ctx->H.u[0] = ToBE64(ctx->H.u[0]); ctx->H.u[1] = ToBE64(ctx->H.u[1]); if (X86_PCAP_AVX) { gcm_init_avx(ctx->Htable,ctx->H.u); ctx->gmult = gcm_gmult_avx; ctx->ghash = gcm_ghash_avx; } else if (X86_PCAP_PCLMULQDQ) { gcm_init_clmul(ctx->Htable,ctx->H.u); ctx->gmult = gcm_gmult_clmul; ctx->ghash = gcm_ghash_clmul; } else { gcm_init_4bit(ctx->Htable, ctx->H.u); ctx->gmult = gcm_gmult_4bit; ctx->ghash = gcm_ghash_4bit; } } void CRYPTO_gcm128_setiv(AesGcm128TempContext *ctx, AesGcm128StaticContext *sctx, const unsigned char *iv, size_t len) { unsigned int ctr; void (*gcm_gmult_p)(uint64 Xi[2],const aesgcm_u128 Htable[16]) = sctx->gmult; ctx->sctx = sctx; ctx->Yi.u[0] = 0; ctx->Yi.u[1] = 0; ctx->Xi.u[0] = 0; ctx->Xi.u[1] = 0; ctx->len.u[0] = 0; /* AAD length */ ctx->len.u[1] = 0; /* message length */ ctx->ares = 0; ctx->mres = 0; if (len==12) { memcpy(ctx->Yi.c,iv,12); ctx->Yi.c[15]=1; ctr=1; } else { size_t i; uint64 len0 = len; while (len>=16) { for (i=0; i<16; ++i) ctx->Yi.c[i] ^= iv[i]; GCM_MUL(ctx,Yi); iv += 16; len -= 16; } if (len) { for (i=0; iYi.c[i] ^= iv[i]; GCM_MUL(ctx,Yi); } len0 <<= 3; ctx->Yi.u[1] ^= ToBE64(len0); GCM_MUL(ctx,Yi); ctr = ToBE32(ctx->Yi.d[3]); } aesni_encrypt(ctx->Yi.c, ctx->EK0.c, &sctx->aes); ++ctr; ctx->Yi.d[3] = ToBE32(ctr); } union AesGcmIV { uint32 nonce[3]; uint8 nonceb[12]; }; void aesgcm_encrypt(uint8 *dst, const uint8 *src, const size_t src_len, const uint8 *ad, const size_t ad_len, const uint64 nonce, AesGcm128StaticContext *sctx) { AesGcm128TempContext ctx; AesGcmIV iv; WriteLE64(iv.nonce, nonce); iv.nonce[2] = 0; CRYPTO_gcm128_setiv(&ctx, sctx, iv.nonceb, sizeof(iv)); CRYPTO_gcm128_aad(&ctx, ad, ad_len); CRYPTO_gcm128_encrypt_ctr32(&ctx, src, dst, src_len); CRYPTO_gcm128_finish(&ctx, dst + src_len, 16); } void aesgcm_decrypt_get_mac(uint8 *dst, const uint8 *src, const size_t src_len, const uint8 *ad, const size_t ad_len, const uint64 nonce, AesGcm128StaticContext *sctx, uint8 mac[16]) { AesGcm128TempContext ctx; AesGcmIV iv; WriteLE64(iv.nonce, nonce); iv.nonce[2] = 0; CRYPTO_gcm128_setiv(&ctx, sctx, iv.nonceb, sizeof(iv)); CRYPTO_gcm128_aad(&ctx, ad, ad_len); CRYPTO_gcm128_decrypt_ctr32(&ctx, src, dst, src_len); CRYPTO_gcm128_finish(&ctx, mac, 16); } #if 1 /* * GCM test vectors from: * * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip */ #define MAX_TESTS 6 static int key_index[MAX_TESTS] = { 0, 0, 1, 1, 1, 1 }; static uint8 key[MAX_TESTS][32] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, }; static size_t iv_len[MAX_TESTS] = { 12, 12, 12, 12, 8, 60 }; static int iv_index[MAX_TESTS] = { 0, 0, 1, 1, 1, 2 }; static uint8 iv[MAX_TESTS][64] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }, { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, 0xa6, 0x37, 0xb3, 0x9b }, }; static size_t add_len[MAX_TESTS] = { 0, 0, 0, 20, 20, 20 }; int add_index[MAX_TESTS] = { 0, 0, 0, 1, 1, 1 }; static uint8 additional[MAX_TESTS][64] = { { 0x00 }, { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2 }, }; static size_t pt_len[MAX_TESTS] = { 0, 16, 64, 60, 60, 60 }; static int pt_index[MAX_TESTS] = { 0, 0, 1, 1, 1, 1 }; static uint8 pt[MAX_TESTS][64] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, }; static uint8 ct[MAX_TESTS * 3][64] = { { 0x00 }, { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91 }, { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, 0xc2, 0x3f, 0x45, 0x98 }, { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, 0x4c, 0x34, 0xae, 0xe5 }, { 0x00 }, { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, 0xcc, 0xda, 0x27, 0x10 }, { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, 0xa0, 0xf0, 0x62, 0xf7 }, { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, 0xe9, 0xb7, 0x37, 0x3b }, { 0x00 }, { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 0xbc, 0xc9, 0xf6, 0x62 }, { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, 0xf4, 0x7c, 0x9b, 0x1f }, { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, 0x44, 0xae, 0x7e, 0x3f }, }; static uint8 tag[MAX_TESTS * 3][16] = { { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, }; int gcm_self_test() { uint8 buf[64]; uint8 tag_buf[16]; int i, j; AesGcm128TempContext ctx; AesGcm128StaticContext sctx; { AesContext aes; uint8 key[16] = {43,126,21,22,40,174,210,166,171,247,21,136,9,207,79,60}; uint8 in[16] = {107,193,190,226,46,64,159,150,233,61,126,17,115,147,23,42}; uint8 out[16] = {58,215,123,180,13,122,54,96,168,158,202,243,36,102,239,151}, t[16]; aesni_set_encrypt_key(key, 128, &aes); aesni_encrypt(in, t, &aes); if (memcmp(t, out,16)) { printf("AES test fail!\n"); return 1; } aesni_set_decrypt_key(key, 128, &aes); aesni_decrypt(out, t, &aes); if (memcmp(t, in,16)) { printf("AES test fail!\n"); return 1; } } uint8 correct[] = { 62,85,184,249,224,220,4,77,201,216,202,172,121,7,25,200, }; if (0) { uint8 buf[512 + 16]; for (size_t i = 0; i < 512; i++) buf[i] = (uint8)(i >> 4);// 0x11; uint8 buf2[512 + 16]; for (size_t i = 0; i < 512; i++) buf2[i] = buf[i]; size_t pp = 0x60; CRYPTO_gcm128_init(&sctx, key[0], 128); sctx.use_aesni_gcm_crypt = 1; aesgcm_decrypt_get_mac(buf, buf, pp, NULL, 0, 1, &sctx, buf + pp); sctx.use_aesni_gcm_crypt = 0; aesgcm_decrypt_get_mac(buf2, buf2, pp, NULL, 0, 1, &sctx, buf2 + pp); //aesgcm_encrypt(buf, buf, 0x120 + 32, NULL, 0, 1, &sctx); for (size_t i = 0; i < 16; i++) printf("%d,", buf[pp + i]); printf("\n"); for (size_t i = 0; i < 16; i++) printf("%d,", buf2[pp + i]); printf("\n"); if (memcmp(buf2 + pp, buf + pp, 16) == 0) printf("CORRECT!!\n"); else printf("******** FAIL ************\n"); // for(size_t i = 0; i < 16; i++) // printf("%d,", buf[pp +i]); printf("\n"); } return 0; for( j = 0; j < 3; j++ ) { int key_len = 128 + 64 * j; for( i = 0; i < MAX_TESTS; i++ ) { CRYPTO_gcm128_init(&sctx, key[key_index[i]], key_len); CRYPTO_gcm128_setiv(&ctx, &sctx, iv[iv_index[i]], iv_len[i]); CRYPTO_gcm128_aad(&ctx, additional[add_index[i]], add_len[i]); CRYPTO_gcm128_encrypt_ctr32(&ctx, pt[pt_index[i]], buf, pt_len[i]); CRYPTO_gcm128_finish(&ctx, tag_buf, 16); if(memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) { printf( "AES-GCM-%3d #%d (%s): failed\n", key_len, i, "enc" ); return( 1 ); } CRYPTO_gcm128_init(&sctx, key[key_index[i]], key_len); CRYPTO_gcm128_setiv(&ctx, &sctx, iv[iv_index[i]], iv_len[i]); CRYPTO_gcm128_aad(&ctx, additional[add_index[i]], add_len[i]); CRYPTO_gcm128_decrypt_ctr32(&ctx, ct[j * 6 + i], buf, pt_len[i]); CRYPTO_gcm128_finish(&ctx, tag_buf, 16); if(memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) { printf( "AES-GCM-%3d #%d (%s): failed\n", key_len, i, "dec" ); return( 1 ); } } } return( 0 ); } //int main() { // gcm_self_test(); //} #endif #endif // #if WITH_AESGCM