Exemple #1
0
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;
        }
    }
}
Exemple #2
0
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;
}
Exemple #7
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;
}
Exemple #9
0
/*
 * 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;
}
Exemple #11
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;
}
Exemple #13
0
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;
}