void AES_bi_ige_encrypt (const unsigned char *in, unsigned char *out, size_t length, const AES_KEY * key, const AES_KEY * key2, const unsigned char *ivec, const int enc) { size_t n; size_t len = length; unsigned char tmp[AES_BLOCK_SIZE]; unsigned char tmp2[AES_BLOCK_SIZE]; unsigned char tmp3[AES_BLOCK_SIZE]; unsigned char prev[AES_BLOCK_SIZE]; const unsigned char *iv; const unsigned char *iv2; OPENSSL_assert (in && out && key && ivec); OPENSSL_assert ((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); OPENSSL_assert ((length % AES_BLOCK_SIZE) == 0); if (AES_ENCRYPT == enc) { /* XXX: Do a separate case for when in != out (strictly should check for overlap, too) */ /* First the forward pass */ iv = ivec; iv2 = ivec + AES_BLOCK_SIZE; while (len >= AES_BLOCK_SIZE) { for (n = 0; n < AES_BLOCK_SIZE; ++n) out[n] = in[n] ^ iv[n]; AES_encrypt (out, out, key); for (n = 0; n < AES_BLOCK_SIZE; ++n) out[n] ^= iv2[n]; iv = out; memcpy (prev, in, AES_BLOCK_SIZE); iv2 = prev; len -= AES_BLOCK_SIZE; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } /* And now backwards */ iv = ivec + AES_BLOCK_SIZE * 2; iv2 = ivec + AES_BLOCK_SIZE * 3; len = length; while (len >= AES_BLOCK_SIZE) { out -= AES_BLOCK_SIZE; /* XXX: reduce copies by alternating between buffers */ memcpy (tmp, out, AES_BLOCK_SIZE); for (n = 0; n < AES_BLOCK_SIZE; ++n) out[n] ^= iv[n]; /* hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE); */ AES_encrypt (out, out, key); /* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ /* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ for (n = 0; n < AES_BLOCK_SIZE; ++n) out[n] ^= iv2[n]; /* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ iv = out; memcpy (prev, tmp, AES_BLOCK_SIZE); iv2 = prev; len -= AES_BLOCK_SIZE; } } else { /* First backwards */ iv = ivec + AES_BLOCK_SIZE * 2; iv2 = ivec + AES_BLOCK_SIZE * 3; in += length; out += length; while (len >= AES_BLOCK_SIZE) { in -= AES_BLOCK_SIZE; out -= AES_BLOCK_SIZE; memcpy (tmp, in, AES_BLOCK_SIZE); memcpy (tmp2, in, AES_BLOCK_SIZE); for (n = 0; n < AES_BLOCK_SIZE; ++n) tmp[n] ^= iv2[n]; AES_decrypt (tmp, out, key); for (n = 0; n < AES_BLOCK_SIZE; ++n) out[n] ^= iv[n]; memcpy (tmp3, tmp2, AES_BLOCK_SIZE); iv = tmp3; iv2 = out; len -= AES_BLOCK_SIZE; } /* And now forwards */ iv = ivec; iv2 = ivec + AES_BLOCK_SIZE; len = length; while (len >= AES_BLOCK_SIZE) { memcpy (tmp, out, AES_BLOCK_SIZE); memcpy (tmp2, out, AES_BLOCK_SIZE); for (n = 0; n < AES_BLOCK_SIZE; ++n) tmp[n] ^= iv2[n]; AES_decrypt (tmp, out, key); for (n = 0; n < AES_BLOCK_SIZE; ++n) out[n] ^= iv[n]; memcpy (tmp3, tmp2, AES_BLOCK_SIZE); iv = tmp3; iv2 = out; len -= AES_BLOCK_SIZE; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } } }
void AES_ige_encrypt (const unsigned char *in, unsigned char *out, size_t length, const AES_KEY * key, unsigned char *ivec, const int enc) { size_t n; size_t len = length; OPENSSL_assert (in && out && key && ivec); OPENSSL_assert ((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); OPENSSL_assert ((length % AES_BLOCK_SIZE) == 0); len = length / AES_BLOCK_SIZE; if (AES_ENCRYPT == enc) { if (in != out && (UNALIGNED_MEMOPS_ARE_FAST || ((size_t) in | (size_t) out | (size_t) ivec) % sizeof (long) == 0)) { aes_block_t *ivp = (aes_block_t *) ivec; aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE); while (len) { aes_block_t *inp = (aes_block_t *) in; aes_block_t *outp = (aes_block_t *) out; for (n = 0; n < N_WORDS; ++n) outp->data[n] = inp->data[n] ^ ivp->data[n]; AES_encrypt ((unsigned char *) outp->data, (unsigned char *) outp->data, key); for (n = 0; n < N_WORDS; ++n) outp->data[n] ^= iv2p->data[n]; ivp = outp; iv2p = inp; --len; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } memcpy (ivec, ivp->data, AES_BLOCK_SIZE); memcpy (ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); } else { aes_block_t tmp, tmp2; aes_block_t iv; aes_block_t iv2; load_block (iv, ivec); load_block (iv2, ivec + AES_BLOCK_SIZE); while (len) { load_block (tmp, in); for (n = 0; n < N_WORDS; ++n) tmp2.data[n] = tmp.data[n] ^ iv.data[n]; AES_encrypt ((unsigned char *) tmp2.data, (unsigned char *) tmp2.data, key); for (n = 0; n < N_WORDS; ++n) tmp2.data[n] ^= iv2.data[n]; store_block (out, tmp2); iv = tmp2; iv2 = tmp; --len; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } memcpy (ivec, iv.data, AES_BLOCK_SIZE); memcpy (ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); } } else { if (in != out && (UNALIGNED_MEMOPS_ARE_FAST || ((size_t) in | (size_t) out | (size_t) ivec) % sizeof (long) == 0)) { aes_block_t *ivp = (aes_block_t *) ivec; aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE); while (len) { aes_block_t tmp; aes_block_t *inp = (aes_block_t *) in; aes_block_t *outp = (aes_block_t *) out; for (n = 0; n < N_WORDS; ++n) tmp.data[n] = inp->data[n] ^ iv2p->data[n]; AES_decrypt ((unsigned char *) tmp.data, (unsigned char *) outp->data, key); for (n = 0; n < N_WORDS; ++n) outp->data[n] ^= ivp->data[n]; ivp = inp; iv2p = outp; --len; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } memcpy (ivec, ivp->data, AES_BLOCK_SIZE); memcpy (ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); } else { aes_block_t tmp, tmp2; aes_block_t iv; aes_block_t iv2; load_block (iv, ivec); load_block (iv2, ivec + AES_BLOCK_SIZE); while (len) { load_block (tmp, in); tmp2 = tmp; for (n = 0; n < N_WORDS; ++n) tmp.data[n] ^= iv2.data[n]; AES_decrypt ((unsigned char *) tmp.data, (unsigned char *) tmp.data, key); for (n = 0; n < N_WORDS; ++n) tmp.data[n] ^= iv.data[n]; store_block (out, tmp); iv = tmp2; iv2 = tmp; --len; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } memcpy (ivec, iv.data, AES_BLOCK_SIZE); memcpy (ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); } } }
static void aes_block_encrypt(__ops_crypt_t *crypt, void *out, const void *in) { AES_encrypt(in, out, crypt->encrypt_key); }
/* ***************** * * UTILITY FUNCTIONS * * ***************** * */ static void aes_encrypt(const char *key, const char *in, char *out) { AES_KEY aes_key; AES_set_encrypt_key(key, AES_KEY_SIZE*8, &aes_key); AES_encrypt(in, out, &aes_key); }
int crypto_aead_encrypt( unsigned char *c,unsigned long long *clen, const unsigned char *m,unsigned long long mlen, const unsigned char *ad,unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k ) { const unsigned char* in = m; unsigned char* out = c; unsigned long long remaining = mlen; uint8_t buf[16] = { 0 }; __m128i W, Wtmp; __m128i block, Lup, Ldown; __m128i Lup1, Lup2, Lup3, Lup4, Lup5, Lup6, Lup7, Lup8; __m128i Ldown1, Ldown2, Ldown3, Ldown4, Ldown5, Ldown6, Ldown7, Ldown8; __m128i block1, block2, block3, block4; __m128i block5, block6, block7, block8; __m128i checksum = { 0 }; __m128i LL = { 0 }; __m128i expkey[11]; /* key schedule */ AES_set_encrypt_key(k, expkey); /* set ouput length */ *clen = mlen + 16; LL = AES_encrypt(LL, expkey); /* LL = AES(0) */ Lup = LL; Ldown = gf128_mul3(gf128_mul3(LL)); /* Ldown = 3^2*LL */ /* mac AD + nonce */ W = mac(ad, adlen, npub, LL, expkey); Lup8 = Lup; Ldown8 = Ldown; while (remaining > 8*16) { Lup1 = gf128_mul2(Lup8); Lup2 = gf128_mul2(Lup1); Lup3 = gf128_mul2(Lup2); Lup4 = gf128_mul2(Lup3); Lup5 = gf128_mul2(Lup4); Lup6 = gf128_mul2(Lup5); Lup7 = gf128_mul2(Lup6); Lup8 = gf128_mul2(Lup7); block1 = byte_swap(_mm_loadu_si128((__m128i*)in)); block2 = byte_swap(_mm_loadu_si128((__m128i*)in+1)); block3 = byte_swap(_mm_loadu_si128((__m128i*)in+2)); block4 = byte_swap(_mm_loadu_si128((__m128i*)in+3)); block5 = byte_swap(_mm_loadu_si128((__m128i*)in+4)); block6 = byte_swap(_mm_loadu_si128((__m128i*)in+5)); block7 = byte_swap(_mm_loadu_si128((__m128i*)in+6)); block8 = byte_swap(_mm_loadu_si128((__m128i*)in+7)); checksum ^= block1 ^ block2 ^ block3 ^ block4; checksum ^= block5 ^ block6 ^ block7 ^ block8; block1 ^= Lup1; block2 ^= Lup2; block3 ^= Lup3; block4 ^= Lup4; block5 ^= Lup5; block6 ^= Lup6; block7 ^= Lup7; block8 ^= Lup8; AES_ENCRYPT8(block1,block2,block3,block4,block5,block6,block7,block8, expkey); Ldown1 = gf128_mul2(Ldown8); Ldown2 = gf128_mul2(Ldown1); Ldown3 = gf128_mul2(Ldown2); Ldown4 = gf128_mul2(Ldown3); Ldown5 = gf128_mul2(Ldown4); Ldown6 = gf128_mul2(Ldown5); Ldown7 = gf128_mul2(Ldown6); Ldown8 = gf128_mul2(Ldown7); rho(block1, W, Wtmp); rho(block2, W, Wtmp); rho(block3, W, Wtmp); rho(block4, W, Wtmp); rho(block5, W, Wtmp); rho(block6, W, Wtmp); rho(block7, W, Wtmp); rho(block8, W, Wtmp); AES_ENCRYPT8(block1,block2,block3,block4,block5,block6,block7,block8, expkey); block1 ^= Ldown1; block2 ^= Ldown2; block3 ^= Ldown3; block4 ^= Ldown4; block5 ^= Ldown5; block6 ^= Ldown6; block7 ^= Ldown7; block8 ^= Ldown8; _mm_storeu_si128((__m128i*)out, byte_swap(block1)); _mm_storeu_si128((__m128i*)out+1, byte_swap(block2)); _mm_storeu_si128((__m128i*)out+2, byte_swap(block3)); _mm_storeu_si128((__m128i*)out+3, byte_swap(block4)); _mm_storeu_si128((__m128i*)out+4, byte_swap(block5)); _mm_storeu_si128((__m128i*)out+5, byte_swap(block6)); _mm_storeu_si128((__m128i*)out+6, byte_swap(block7)); _mm_storeu_si128((__m128i*)out+7, byte_swap(block8)); in += 8*16; out += 8*16; remaining -= 8*16; } Lup = Lup8; Ldown = Ldown8; while (remaining > 16) { Lup = gf128_mul2(Lup); Ldown = gf128_mul2(Ldown); block = _mm_loadu_si128((__m128i*)in); block = byte_swap(block); checksum ^= block; block ^= Lup; block = AES_encrypt(block, expkey); /* (Y,W') = rho(block, W) */ rho(block, W, Wtmp); block = AES_encrypt(block, expkey); block ^= Ldown; _mm_storeu_si128((__m128i*)out, byte_swap(block)); in += 16; out += 16; remaining -= 16; } /* XOR checksum into last block (padded if necessary) */ memcpy(buf, in, remaining); Lup = gf128_mul7(Lup); Ldown = gf128_mul7(Ldown); if (remaining < 16) { buf[remaining] = 0x80; Lup = gf128_mul7(Lup); Ldown = gf128_mul7(Ldown); } block = _mm_loadu_si128((__m128i*)buf); block = byte_swap(block); checksum ^= block; block = checksum ^ Lup; block = AES_encrypt(block, expkey); /* (Y,W') = rho(block, W) */ rho(block, W, Wtmp); block = AES_encrypt(block, expkey); block ^= Ldown; _mm_storeu_si128((__m128i*)out, byte_swap(block)); out += 16; /* could stop here if remaining == 0 */ if (remaining == 0) return 0; /* Duplicate last block */ Lup = gf128_mul2(Lup); Ldown = gf128_mul2(Ldown); block = checksum ^ Lup; block = AES_encrypt(block, expkey); /* (Y,W') = rho(block, W) */ rho(block, W, Wtmp); block = AES_encrypt(block, expkey); block ^= Ldown; _mm_storeu_si128((__m128i*)buf, byte_swap(block)); memcpy(out, buf, remaining); return 0; }
int crypto_aead_decrypt( unsigned char *m,unsigned long long *mlen, unsigned char *nsec, const unsigned char *c,unsigned long long clen, const unsigned char *ad,unsigned long long adlen, const unsigned char *npub, const unsigned char *k ) { const unsigned char* in = c; unsigned char* out = m; unsigned long long remaining; unsigned int i; uint8_t buf[16] = { 0 }; __m128i W, Wtmp; __m128i block, Lup, Ldown; __m128i Lup1, Lup2, Lup3, Lup4, Lup5, Lup6, Lup7, Lup8; __m128i Ldown1, Ldown2, Ldown3, Ldown4, Ldown5, Ldown6, Ldown7, Ldown8; __m128i block1, block2, block3, block4; __m128i block5, block6, block7, block8; __m128i checksum = { 0 }; __m128i LL = { 0 }; __m128i expkey[11]; __m128i decexpkey[11]; /* key schedule */ AES_set_encrypt_key(k, expkey); AES_set_decrypt_key(expkey, decexpkey); if (clen < 16) { return -1; } /* Set output length */ *mlen = remaining = clen - 16; LL = AES_encrypt(LL, expkey); /* LL = AES(0) */ Lup = LL; Ldown = gf128_mul3(gf128_mul3(LL)); /* Ldown = 3^2*LL */ /* mac AD + nonce */ W = mac(ad, adlen, npub, LL, expkey); /* Decrypt 8 blocks parallel */ Lup8 = Lup; Ldown8 = Ldown; while (remaining > 8*16) { Ldown1 = gf128_mul2(Ldown8); Ldown2 = gf128_mul2(Ldown1); Ldown3 = gf128_mul2(Ldown2); Ldown4 = gf128_mul2(Ldown3); Ldown5 = gf128_mul2(Ldown4); Ldown6 = gf128_mul2(Ldown5); Ldown7 = gf128_mul2(Ldown6); Ldown8 = gf128_mul2(Ldown7); block1 = byte_swap(_mm_loadu_si128((__m128i*)in)); block2 = byte_swap(_mm_loadu_si128((__m128i*)in+1)); block3 = byte_swap(_mm_loadu_si128((__m128i*)in+2)); block4 = byte_swap(_mm_loadu_si128((__m128i*)in+3)); block5 = byte_swap(_mm_loadu_si128((__m128i*)in+4)); block6 = byte_swap(_mm_loadu_si128((__m128i*)in+5)); block7 = byte_swap(_mm_loadu_si128((__m128i*)in+6)); block8 = byte_swap(_mm_loadu_si128((__m128i*)in+7)); block1 ^= Ldown1; block2 ^= Ldown2; block3 ^= Ldown3; block4 ^= Ldown4; block5 ^= Ldown5; block6 ^= Ldown6; block7 ^= Ldown7; block8 ^= Ldown8; AES_DECRYPT8(block1,block2,block3,block4,block5,block6,block7,block8, decexpkey); Lup1 = gf128_mul2(Lup8); Lup2 = gf128_mul2(Lup1); Lup3 = gf128_mul2(Lup2); Lup4 = gf128_mul2(Lup3); Lup5 = gf128_mul2(Lup4); Lup6 = gf128_mul2(Lup5); Lup7 = gf128_mul2(Lup6); Lup8 = gf128_mul2(Lup7); rho_inv(block1, W, Wtmp); rho_inv(block2, W, Wtmp); rho_inv(block3, W, Wtmp); rho_inv(block4, W, Wtmp); rho_inv(block5, W, Wtmp); rho_inv(block6, W, Wtmp); rho_inv(block7, W, Wtmp); rho_inv(block8, W, Wtmp); AES_DECRYPT8(block1,block2,block3,block4,block5,block6,block7,block8, decexpkey); block1 ^= Lup1; block2 ^= Lup2; block3 ^= Lup3; block4 ^= Lup4; block5 ^= Lup5; block6 ^= Lup6; block7 ^= Lup7; block8 ^= Lup8; checksum ^= block1 ^ block2 ^ block3 ^ block4; checksum ^= block5 ^ block6 ^ block7 ^ block8; _mm_storeu_si128((__m128i*)out, byte_swap(block1)); _mm_storeu_si128((__m128i*)out+1, byte_swap(block2)); _mm_storeu_si128((__m128i*)out+2, byte_swap(block3)); _mm_storeu_si128((__m128i*)out+3, byte_swap(block4)); _mm_storeu_si128((__m128i*)out+4, byte_swap(block5)); _mm_storeu_si128((__m128i*)out+5, byte_swap(block6)); _mm_storeu_si128((__m128i*)out+6, byte_swap(block7)); _mm_storeu_si128((__m128i*)out+7, byte_swap(block8)); in += 8*16; out += 8*16; remaining -= 8*16; } Lup = Lup8; Ldown = Ldown8; /* Decrypt */ while (remaining > 16) { Lup = gf128_mul2(Lup); Ldown = gf128_mul2(Ldown); block = byte_swap(_mm_loadu_si128((__m128i*)in)); block ^= Ldown; block = AES_decrypt(block, decexpkey); /* (X,W') = rho^-1(block, W) */ rho_inv(block, W, Wtmp); block = AES_decrypt(block, decexpkey); block ^= Lup; checksum ^= block; _mm_storeu_si128((__m128i*)out, byte_swap(block)); in += 16; out += 16; remaining -= 16; } Lup = gf128_mul7(Lup); Ldown = gf128_mul7(Ldown); if (remaining < 16) { Lup = gf128_mul7(Lup); Ldown = gf128_mul7(Ldown); } block = _mm_loadu_si128((__m128i*)in); block = byte_swap(block); block ^= Ldown; block = AES_decrypt(block, decexpkey); /* (X,W') = rho^-1(block, W) */ rho_inv(block, W, Wtmp); block = AES_decrypt(block, decexpkey); block ^= Lup; /* block now contains M[l] = M[l+1] */ checksum ^= block; /* checksum now contains M*[l] */ in += 16; /* output last (maybe partial) plaintext block */ _mm_storeu_si128((__m128i*)buf, byte_swap(checksum)); memcpy(out, buf, remaining); /* work on M[l+1] */ Lup = gf128_mul2(Lup); Ldown = gf128_mul2(Ldown); block ^= Lup; block = AES_encrypt(block, expkey); /* (Y,W') = rho(block, W) */ rho(block, W, Wtmp); block = AES_encrypt(block, expkey); block ^= Ldown; /* block now contains C'[l+1] */ _mm_storeu_si128((__m128i*)buf, byte_swap(block)); if (memcmp(in, buf, remaining) != 0) { return -1; } if (remaining < 16) { _mm_storeu_si128((__m128i*)buf, byte_swap(checksum)); if (buf[remaining] != 0x80) { return -1; } for (i = remaining+1; i < 16; i++) { if (buf[i] != 0) { return -1; } } } return 0; }
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, const unsigned long length, const AES_KEY *key, unsigned char *ivec, const int enc) { unsigned long n; unsigned long len = length; unsigned char tmp[AES_BLOCK_SIZE]; const unsigned char *iv = ivec; assert(in && out && key && ivec); assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc)); if (AES_ENCRYPT == enc) { while (len >= AES_BLOCK_SIZE) { for(n=0; n < AES_BLOCK_SIZE; ++n) out[n] = in[n] ^ iv[n]; AES_encrypt(out, out, key); iv = out; len -= AES_BLOCK_SIZE; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } if (len) { for(n=0; n < len; ++n) out[n] = in[n] ^ iv[n]; for(n=len; n < AES_BLOCK_SIZE; ++n) out[n] = iv[n]; AES_encrypt(out, out, key); iv = out; } memcpy(ivec,iv,AES_BLOCK_SIZE); } else if (in != out) { while (len >= AES_BLOCK_SIZE) { AES_decrypt(in, out, key); for(n=0; n < AES_BLOCK_SIZE; ++n) out[n] ^= iv[n]; iv = in; len -= AES_BLOCK_SIZE; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } if (len) { AES_decrypt(in,tmp,key); for(n=0; n < len; ++n) out[n] = tmp[n] ^ iv[n]; iv = in; } memcpy(ivec,iv,AES_BLOCK_SIZE); } else { while (len >= AES_BLOCK_SIZE) { memcpy(tmp, in, AES_BLOCK_SIZE); AES_decrypt(in, out, key); for(n=0; n < AES_BLOCK_SIZE; ++n) out[n] ^= ivec[n]; memcpy(ivec, tmp, AES_BLOCK_SIZE); len -= AES_BLOCK_SIZE; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } if (len) { memcpy(tmp, in, AES_BLOCK_SIZE); AES_decrypt(tmp, out, key); for(n=0; n < len; ++n) out[n] ^= ivec[n]; for(n=len; n < AES_BLOCK_SIZE; ++n) out[n] = tmp[n]; memcpy(ivec, tmp, AES_BLOCK_SIZE); } } }
__m128i mac(const unsigned char* in, unsigned long long len, const unsigned char* nonce, const __m128i LL, const __m128i* expkey) { __m128i v, block, delta; __m128i delta1, delta2, delta3, delta4, delta5, delta6, delta7, delta8; __m128i block1, block2, block3, block4, block5, block6, block7, block8; uint8_t buf[16] = { 0 }; /* convention: do not pad empty AD */ delta = gf128_mul3(LL); v = _mm_set_epi64x(0, *(uint64_t*)nonce); v = byte_swap(v); v ^= delta; v = AES_encrypt(v, expkey); /* mac blocks in parallel */ delta8 = delta; while (len >= 8*16) { delta1 = gf128_mul2(delta8); delta2 = gf128_mul2(delta1); delta3 = gf128_mul2(delta2); delta4 = gf128_mul2(delta3); delta5 = gf128_mul2(delta4); delta6 = gf128_mul2(delta5); delta7 = gf128_mul2(delta6); delta8 = gf128_mul2(delta7); block1 = byte_swap(_mm_loadu_si128((__m128i*)in)); block2 = byte_swap(_mm_loadu_si128((__m128i*)in+1)); block3 = byte_swap(_mm_loadu_si128((__m128i*)in+2)); block4 = byte_swap(_mm_loadu_si128((__m128i*)in+3)); block5 = byte_swap(_mm_loadu_si128((__m128i*)in+4)); block6 = byte_swap(_mm_loadu_si128((__m128i*)in+5)); block7 = byte_swap(_mm_loadu_si128((__m128i*)in+6)); block8 = byte_swap(_mm_loadu_si128((__m128i*)in+7)); block1 ^= delta1; block2 ^= delta2; block3 ^= delta3; block4 ^= delta4; block5 ^= delta5; block6 ^= delta6; block7 ^= delta7; block8 ^= delta8; AES_ENCRYPT8(block1,block2,block3,block4,block5,block6,block7,block8, expkey); v ^= block1 ^ block2 ^ block3 ^ block4; v ^= block5 ^ block6 ^ block7 ^ block8; in += 8*16; len -= 8*16; } /* mac full blocks */ delta = delta8; while (len >= 16) { delta = gf128_mul2(delta); block = _mm_loadu_si128((__m128i*)in); block = byte_swap(block); block ^= delta; block = AES_encrypt(block, expkey); v ^= block; in += 16; len -= 16; } if (len > 0) { /* last block partial */ delta = gf128_mul7(delta); memcpy(buf, in, len); buf[len] ^= 0x80; /* padding */ block = _mm_loadu_si128((__m128i*) buf); block = byte_swap(block); block ^= delta; block = AES_encrypt(block, expkey); v ^= block; } return v; }
/* * The life of a pregen thread: * Find empty keystream queues and fill them using their counter. * When done, update counter for the next fill. */ static void * thread_loop(void *x) { AES_KEY key; STATS_STRUCT(stats); struct ssh_aes_ctr_ctx *c = x; struct kq *q; int i; int qidx; /* Threads stats on cancellation */ STATS_INIT(stats); #ifdef CIPHER_THREAD_STATS pthread_cleanup_push(thread_loop_stats, &stats); #endif /* Thread local copy of AES key */ memcpy(&key, &c->aes_ctx, sizeof(key)); /* * Handle the special case of startup, one thread must fill * the first KQ then mark it as draining. Lock held throughout. */ if (pthread_equal(pthread_self(), c->tid[0])) { q = &c->q[0]; pthread_mutex_lock(&q->lock); if (q->qstate == KQINIT) { for (i = 0; i < KQLEN; i++) { AES_encrypt(q->ctr, q->keys[i], &key); ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE); } ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE); q->qstate = KQDRAINING; STATS_FILL(stats); pthread_cond_broadcast(&q->cond); } pthread_mutex_unlock(&q->lock); } else STATS_SKIP(stats); /* * Normal case is to find empty queues and fill them, skipping over * queues already filled by other threads and stopping to wait for * a draining queue to become empty. * * Multiple threads may be waiting on a draining queue and awoken * when empty. The first thread to wake will mark it as filling, * others will move on to fill, skip, or wait on the next queue. */ for (qidx = 1;; qidx = (qidx + 1) % NUMKQ) { /* Check if I was cancelled, also checked in cond_wait */ pthread_testcancel(); /* Lock queue and block if its draining */ q = &c->q[qidx]; pthread_mutex_lock(&q->lock); pthread_cleanup_push(thread_loop_cleanup, &q->lock); while (q->qstate == KQDRAINING || q->qstate == KQINIT) { STATS_WAIT(stats); pthread_cond_wait(&q->cond, &q->lock); } pthread_cleanup_pop(0); /* If filling or full, somebody else got it, skip */ if (q->qstate != KQEMPTY) { pthread_mutex_unlock(&q->lock); STATS_SKIP(stats); continue; } /* * Empty, let's fill it. * Queue lock is relinquished while we do this so others * can see that it's being filled. */ q->qstate = KQFILLING; pthread_mutex_unlock(&q->lock); for (i = 0; i < KQLEN; i++) { AES_encrypt(q->ctr, q->keys[i], &key); ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE); } /* Re-lock, mark full and signal consumer */ pthread_mutex_lock(&q->lock); ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE); q->qstate = KQFULL; STATS_FILL(stats); pthread_cond_signal(&q->cond); pthread_mutex_unlock(&q->lock); } #ifdef CIPHER_THREAD_STATS /* Stats */ pthread_cleanup_pop(1); #endif return NULL; }
int ciphersql_fpe_encrypt(ciphersql_fpe_t *fpe, const char *in, const unsigned char *tweak, size_t tweaklen, char *out) { size_t inlen; int llen, rlen; uint32_t lval, rval; unsigned char pblock[16] = { 0x01, 0x02, 0x01, 0x0a, 0x00, 0x00, 0x0a, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00}; unsigned char qblock[16]; char lbuf[CIPHERSQL_FPE_MAX_DIGITS/2 + 2]; uint64_t yval; int i; assert(out); assert(in); assert(tweak); inlen = strlen(in); if (inlen < CIPHERSQL_FPE_MIN_DIGITS || inlen > CIPHERSQL_FPE_MAX_DIGITS) { fprintf(stderr, "%s: invalid digits length\n", __FUNCTION__); return -1; } for (i = 0; i < inlen; i++) { if (!isdigit(in[i])) { fprintf(stderr, "%s: invalid digits format\n", __FUNCTION__); return -1; } } llen = inlen / 2; rlen = inlen - llen; if (tweaklen < CIPHERSQL_FPE_MIN_TWEAKLEN || tweaklen > CIPHERSQL_FPE_MAX_TWEAKLEN) { fprintf(stderr, "%s: invalid tweak length\n", __FUNCTION__); return -1; } memcpy(lbuf, in, llen); lbuf[llen] = 0; lval = atoi(lbuf); rval = atoi(in + llen); pblock[7] = llen & 0xff; pblock[8] = inlen & 0xff; pblock[12] = tweaklen & 0xff; AES_encrypt(pblock, pblock, &fpe->key); memset(qblock, 0, sizeof(qblock)); memcpy(qblock, tweak, tweaklen); for (i = 0; i < CIPHERSQL_FPE_NUM_ROUNDS; i += 2) { unsigned char rblock[16]; int j; qblock[11] = i & 0xff; memcpy(qblock + 12, &rval, sizeof(rval)); for (j = 0; j < sizeof(rblock); j++) { rblock[j] = pblock[j] ^ qblock[j]; } AES_encrypt(rblock, rblock, &fpe->key); yval = *((uint64_t *)rblock) % modulo[llen]; lval = (lval + yval) % modulo[llen]; qblock[11] = (i + 1) & 0xff; memcpy(qblock + 12, &lval, sizeof(lval)); for (j = 0; j < sizeof(rblock); j++) { rblock[j] = pblock[j] ^ qblock[j]; } AES_encrypt(rblock, rblock, &fpe->key); yval = *((uint64_t *)rblock) % modulo[rlen]; rval = (rval + yval) % modulo[rlen]; } memset(out, '0', inlen); sprintf(lbuf, "%d", rval); memcpy(out + rlen - strlen(lbuf), lbuf, strlen(lbuf)); sprintf(lbuf, "%d", lval); strcpy(out + inlen - strlen(lbuf), lbuf); return 0; }
void QtAes::encryptBlock(const unsigned char *inbuffer, QByteArray &out) const { unsigned char outbuffer[AES_BLOCK_SIZE]; AES_encrypt(inbuffer, outbuffer, &encryptKey); out.append((const char *)outbuffer, AES_BLOCK_SIZE); }
/* * plaintext, message length in byte, ciphertext, associated data, and associated data length in byte tag, and tag length in byte */ int ae_encrypt(ae_cxt* cxt, byte* pt, unsigned long long mlen, byte* ct, byte* tag, unsigned long long tlen, int enc_dec) { cxt->pt = pt; cxt->ptlen = mlen; cxt->ct = ct; cxt->ctlen = mlen; cxt->tag = tag; cxt->tlen = tlen; byte* es = cxt->es; byte* ts = cxt->ts; AES_KEY *ekey = cxt->pt_ekey; unsigned long long pc = 0; while((pc + STATE_LEN) < mlen){ if(enc_dec == ENC){ // encryption xor_bytes(es, pt+pc, STATE_LEN); pstate2("After xoring message block:", es); memcpy(ct+pc, es, STATE_LEN); } else{ // decryption xor_bytes2(pt+pc, ct+pc, es, STATE_LEN); pstate2("After xoring ciphertext block:", es); memcpy(es, ct+pc, STATE_LEN); } xor_bytes(ts, es, STATE_LEN); pstate2("tag state:", ts); pstate2("Enc:", NULL); AES_encrypt(ts, ts, ekey); /* apply fix1 */ es[0] |= 0x80; pstate2("After applying fix1:", es); pstate2("Enc:", NULL); AES_encrypt(es, es, ekey); pc += STATE_LEN; } /* process the last block */ unsigned long long lastblocklen = mlen - pc; if(lastblocklen > 0){ if(enc_dec == ENC){ // encryption xor_bytes(es, pt+pc, lastblocklen); pstate2("After xoring last partial message block:", es); memcpy(ct+pc, es, lastblocklen); } else{ // decryption xor_bytes2(pt+pc, ct+pc, es, lastblocklen); pstate2("After xoring last partial ciphertext block:", es); memcpy(es, ct+pc, lastblocklen); } xor_bytes(ts, es, lastblocklen); pstate2("tag state:", ts); pstate2("Enc:", NULL); AES_encrypt(ts, ts, ekey); } /* encode the adlen and process */ unsigned long long t_adlen = mlen; unsigned long long i; for(i = 0; i < sizeof(unsigned long long); i++) { ts[STATE_LEN-1-i] ^= t_adlen & 0xff; t_adlen >>= 8; } pstate2("After xoring the legnth of message:", ts); g(ts); pstate2("After applying g:", ts); pstate2("Enc:", NULL); AES_encrypt(ts, ts, ekey); memcpy(tag, ts, tlen); return SUCCESS; }
int main() { SHA256_CTX md_ctx; AES_KEY key; _AES_CTX ctx; uint8_t buf[64], nb[32], enb[32]; int i, len; int nk = BITS >> 5, nr = 6 + nk, key_nb = (nr + 1) * AES_NB * 4; FILE *fp, *ofp; struct timeval tv_start, tv_end; for (len = 0; len < 64; len += 32) { SHA256_Init(&md_ctx); if (len == 0) { SHA256_Update(&md_ctx, KEY, strlen(KEY)); SHA256_Final(buf, &md_ctx); } else { SHA256_Update(&md_ctx, buf + len - 32, 32); SHA256_Update(&md_ctx, KEY, strlen(KEY)); SHA256_Final(buf + len, &md_ctx); } } AES_set_encrypt_key(buf, BITS, &key); hex_dump((uint8_t *)key.rd_key, key_nb); expand_key(&(ctx.key), buf, BITS); ctx.encrypt = _AES_ecb_encrypt; ctx.decrypt = _AES_ecb_decrypt; hex_dump(ctx.key.rd_key, key_nb); for (i = 0; i < 32; i++) nb[i] = '\0'; gettimeofday(&tv_start, NULL); for (i = 0; i < 1024; i++) AES_encrypt(nb, enb, &key); gettimeofday(&tv_end, NULL); print_elapsed_time(&tv_start, &tv_end); hex_dump(enb, 16); gettimeofday(&tv_start, NULL); for (i = 0; i < 1024; i++) ctx.encrypt(nb, enb, &ctx); gettimeofday(&tv_end, NULL); print_elapsed_time(&tv_start, &tv_end); hex_dump(enb, 16); for (i = 0; i < 32; i++) nb[i] = enb[i]; ctx.decrypt(nb, enb, &ctx); hex_dump(enb, 16); if ((fp = fopen("test.bin", "r")) == NULL) { fprintf(stderr, "File open failed\n"); exit(-1); } while (!feof(fp)) { if (fread(nb, 1, _AES_BLOCK_SIZE, fp) == 0) { fprintf(stderr, "Failed in call to fread()\n"); exit(-1); } } fseek(fp, 0, SEEK_SET); i = 0; gettimeofday(&tv_start, NULL); while (!feof(fp)) { ++i; if (fread(nb, 1, _AES_BLOCK_SIZE, fp) == 0) { fprintf(stderr, "Failed in call to fread()\n"); exit(-1); } AES_encrypt(nb, enb, &key); } gettimeofday(&tv_end, NULL); print_elapsed_time(&tv_start, &tv_end); printf("blocks = %d\n", i); fseek(fp, 0, SEEK_SET); i = 0; gettimeofday(&tv_start, NULL); while (!feof(fp)) { ++i; if (fread(nb, 1, _AES_BLOCK_SIZE, fp) == 0) { fprintf(stderr, "Failed in call to fread()\n"); exit(-1); } ctx.encrypt(nb, enb, &ctx); } gettimeofday(&tv_end, NULL); print_elapsed_time(&tv_start, &tv_end); printf("blocks = %d\n", i); fclose(fp); fp = fopen("test.enc", "r"); ofp = fopen("tmp.bin", "w"); ctx.encrypt = _AES_cbc_encrypt; ctx.decrypt = _AES_cbc_decrypt; memcpy(ctx.ivec, buf + 32, _AES_BLOCK_SIZE); while (!feof(fp)) { if (fread(nb, 1, _AES_BLOCK_SIZE, fp) == 0) { fprintf(stderr, "Failed in call to fread()\n"); exit(-1); } ctx.decrypt(nb, enb, &ctx); fwrite(enb, 1, _AES_BLOCK_SIZE, ofp); } fclose(fp); fclose(ofp); return 0; }