/* * This code was written by KAMADA Ken'ichi, * and is in the public domain. * * AES-CTS implementation with OpenSSL AES APIs. * (cf. RFC 2040 and RFC 3962) */ #include void AES_cts_encrypt(const unsigned char *in, unsigned char *out, const unsigned long length, const AES_KEY *key, unsigned char *ivec, const int enc) { char lastblk[AES_BLOCK_SIZE]; size_t cbclen, fraglen, i; /* XXX */ if (length <= AES_BLOCK_SIZE) return AES_cbc_encrypt(in, out, length, key, ivec, enc); fraglen = (length - 1) % AES_BLOCK_SIZE + 1; cbclen = length - fraglen - AES_BLOCK_SIZE; if (enc == AES_ENCRYPT) { /* Same with CBC until the last 2 blocks. */ AES_cbc_encrypt(in, out, cbclen + AES_BLOCK_SIZE, key, ivec, AES_ENCRYPT); /* Adjust the second last plainblock. */ memcpy(out + cbclen + AES_BLOCK_SIZE, out + cbclen, fraglen); /* Encrypt the last plainblock. */ memcpy(lastblk, ivec, AES_BLOCK_SIZE); for (i = 0; i < fraglen; i++) lastblk[i] ^= (in + cbclen + AES_BLOCK_SIZE)[i]; AES_encrypt(lastblk, out + cbclen, key); } else { /* Decrypt the last plainblock. */ AES_decrypt(in + cbclen, lastblk, key); for (i = 0; i < fraglen; i++) (out + cbclen + AES_BLOCK_SIZE)[i] = lastblk[i] ^ (in + cbclen + AES_BLOCK_SIZE)[i]; /* Decrypt the second last block. */ memcpy(lastblk, in + cbclen + AES_BLOCK_SIZE, fraglen); AES_decrypt(lastblk, out + cbclen, key); if (cbclen == 0) for (i = 0; i < AES_BLOCK_SIZE; i++) (out + cbclen)[i] ^= ivec[i]; else for (i = 0; i < AES_BLOCK_SIZE; i++) (out + cbclen)[i] ^= (in + cbclen - AES_BLOCK_SIZE)[i]; /* Same with CBC until the last 2 blocks. */ AES_cbc_encrypt(in, out, cbclen, key, ivec, AES_DECRYPT); } }