pare down ltc

This commit is contained in:
Thomas Fussell 2017-04-11 12:38:20 -04:00
parent 3e2a0fc15f
commit c57e1a2bbe
3 changed files with 76 additions and 852 deletions

View File

@ -44,30 +44,6 @@ namespace {
#define LTC_NO_ROLC
#include "tomcrypt.h"
#define SETUP rijndael_setup
#define ECB_ENC rijndael_ecb_encrypt
#define ECB_DEC rijndael_ecb_decrypt
#define ECB_DONE rijndael_done
#define ECB_KS rijndael_keysize
const struct ltc_cipher_descriptor rijndael_desc =
{
"rijndael",
6,
16, 32, 16, 10,
SETUP, ECB_ENC, ECB_DEC, NULL, ECB_DONE, ECB_KS,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
const struct ltc_cipher_descriptor aes_desc =
{
"aes",
6,
16, 32, 16, 10,
SETUP, ECB_ENC, ECB_DEC, NULL, ECB_DONE, ECB_KS,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
static const ulong32 TE0[256] = {
0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,
0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,
@ -982,27 +958,25 @@ static ulong32 setup_mix(ulong32 temp)
@param skey The key in as scheduled by this function.
@return CRYPT_OK if successful
*/
int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
void rijndael_setup(const unsigned char *key, int keylen, int num_rounds, rijndael_key &skey)
{
int i;
ulong32 temp, *rk;
#ifndef ENCRYPT_ONLY
ulong32 *rrk;
#endif
if (keylen != 16 && keylen != 24 && keylen != 32) {
return CRYPT_INVALID_KEYSIZE;
throw std::runtime_error("");
}
if (num_rounds != 0 && num_rounds != (10 + ((keylen/8)-2)*2)) {
return CRYPT_INVALID_ROUNDS;
throw std::runtime_error("");
}
skey->rijndael.Nr = 10 + ((keylen/8)-2)*2;
skey.Nr = 10 + ((keylen/8)-2)*2;
/* setup the forward key */
i = 0;
rk = skey->rijndael.eK;
rk = skey.eK;
LOAD32H(rk[0], key );
LOAD32H(rk[1], key + 4);
LOAD32H(rk[2], key + 8);
@ -1065,12 +1039,9 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s
rk += 8;
}
} else {
/* this can't happen */
/* coverity[dead_error_line] */
return CRYPT_ERROR;
throw std::runtime_error("");
}
#ifndef ENCRYPT_ONLY
/* setup the inverse key now */
rk = skey->rijndael.dK;
rrk = skey->rijndael.eK + (28 + keylen) - 4;
@ -1086,16 +1057,7 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s
for (i = 1; i < skey->rijndael.Nr; i++) {
rrk -= 4;
rk += 4;
#ifdef LTC_SMALL_CODE
temp = rrk[0];
rk[0] = setup_mix2(temp);
temp = rrk[1];
rk[1] = setup_mix2(temp);
temp = rrk[2];
rk[2] = setup_mix2(temp);
temp = rrk[3];
rk[3] = setup_mix2(temp);
#else
temp = rrk[0];
rk[0] =
Tks0[byte(temp, 3)] ^
@ -1120,8 +1082,6 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s
Tks1[byte(temp, 2)] ^
Tks2[byte(temp, 1)] ^
Tks3[byte(temp, 0)];
#endif
}
/* copy last */
@ -1131,9 +1091,6 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s
*rk++ = *rrk++;
*rk++ = *rrk++;
*rk = *rrk;
#endif /* ENCRYPT_ONLY */
return CRYPT_OK;
}
/**
@ -1143,7 +1100,7 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s
@param skey The key as scheduled
@return CRYPT_OK if successful
*/
int ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
{
ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
int Nr, r;
@ -1253,8 +1210,6 @@ int ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
(Te4_0[byte(t2, 0)]) ^
rk[3];
STORE32H(s3, ct+12);
return CRYPT_OK;
}
/**
@ -1264,7 +1219,7 @@ int ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
@param skey The key as scheduled
@return CRYPT_OK if successful
*/
int ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
{
ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
int Nr, r;
@ -1376,14 +1331,12 @@ int ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
(Td4[byte(t0, 0)] & 0x000000ff) ^
rk[3];
STORE32H(s3, pt+12);
return CRYPT_OK;
}
/** Terminate the context
@param skey The scheduled key
*/
void ECB_DONE(symmetric_key *skey)
void rijndael_done(symmetric_key *skey)
{
LTC_UNUSED_PARAM(skey);
}
@ -1393,25 +1346,22 @@ void ECB_DONE(symmetric_key *skey)
@param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
@return CRYPT_OK if the input key size is acceptable.
*/
int ECB_KS(int *keysize)
void rijndael_keysize(int *keysize)
{
if (*keysize < 16)
return CRYPT_INVALID_KEYSIZE;
throw std::runtime_error("");
if (*keysize < 24) {
*keysize = 16;
return CRYPT_OK;
} else if (*keysize < 32) {
*keysize = 24;
return CRYPT_OK;
} else {
*keysize = 32;
return CRYPT_OK;
}
}
int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc)
void cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc)
{
int x, err;
int x;
unsigned char tmp[16];
#ifdef LTC_FAST
LTC_FAST_TYPE tmpy;
@ -1419,32 +1369,27 @@ int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, s
unsigned char tmpy;
#endif
if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
return err;
if (!cipher_is_valid(cbc->cipher)) {
throw std::runtime_error("");
}
/* is blocklen valid? */
if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV) || cbc->blocklen > (int)sizeof(tmp)) {
return CRYPT_INVALID_ARG;
throw std::runtime_error("");
}
if (len % cbc->blocklen) {
return CRYPT_INVALID_ARG;
throw std::runtime_error("");
}
#ifdef LTC_FAST
if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) {
return CRYPT_INVALID_ARG;
throw std::runtime_error("");
}
#endif
if (cipher_descriptor[cbc->cipher].accel_cbc_decrypt != NULL) {
return cipher_descriptor[cbc->cipher].accel_cbc_decrypt(ct, pt, len / cbc->blocklen, cbc->IV, &cbc->key);
} else {
while (len) {
/* decrypt */
if ((err = cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key)) != CRYPT_OK) {
return err;
}
cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key);
/* xor IV against plaintext */
#if defined(LTC_FAST)
@ -1466,45 +1411,37 @@ int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, s
len -= cbc->blocklen;
}
}
return CRYPT_OK;
}
int cbc_done(symmetric_CBC *cbc)
void cbc_done(symmetric_CBC *cbc)
{
int err;
if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
return err;
if (!cipher_is_valid(cbc->cipher)) {
throw std::runtime_error("");
}
cipher_descriptor[cbc->cipher].done(&cbc->key);
return CRYPT_OK;
}
int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc)
void cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc)
{
int x, err;
int x;
if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
return err;
if (!cipher_is_valid(cbc->cipher)) {
throw std::runtime_error("");
}
// is blocklen valid?
if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV)) {
return CRYPT_INVALID_ARG;
throw std::runtime_error("");
}
if (len % cbc->blocklen) {
return CRYPT_INVALID_ARG;
throw std::runtime_error("");
}
#ifdef LTC_FAST
if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) {
return CRYPT_INVALID_ARG;
throw std::runtime_error("");
}
#endif
if (cipher_descriptor[cbc->cipher].accel_cbc_encrypt != NULL) {
return cipher_descriptor[cbc->cipher].accel_cbc_encrypt(pt, ct, len / cbc->blocklen, cbc->IV, &cbc->key);
} else {
while (len) {
// xor IV against plaintext
#if defined(LTC_FAST)
@ -1518,9 +1455,7 @@ int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s
#endif
// encrypt
if ((err = cipher_descriptor[cbc->cipher].ecb_encrypt(cbc->IV, ct, &cbc->key)) != CRYPT_OK) {
return err;
}
cipher_descriptor[cbc->cipher].ecb_encrypt(cbc->IV, ct, &cbc->key);
// store IV [ciphertext] for a future block
#if defined(LTC_FAST)
@ -1538,23 +1473,19 @@ int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s
len -= cbc->blocklen;
}
}
return CRYPT_OK;
}
int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
void cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
int keylen, int num_rounds, symmetric_CBC *cbc)
{
int x, err;
int x;
/* bad param? */
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
return err;
if (!cipher_is_valid(cipher)) {
throw std::runtime_error("");
}
/* setup cipher */
if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) {
return err;
}
cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cbc->key);
/* copy IV */
cbc->blocklen = cipher_descriptor[cipher].block_length;
@ -1562,7 +1493,6 @@ int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
for (x = 0; x < cbc->blocklen; x++) {
cbc->IV[x] = IV[x];
}
return CRYPT_OK;
}
int register_cipher(const struct ltc_cipher_descriptor *cipher)
@ -1593,98 +1523,66 @@ int register_cipher(const struct ltc_cipher_descriptor *cipher)
}
struct ltc_cipher_descriptor cipher_descriptor[TAB_SIZE] = {
{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }
};
LTC_MUTEX_GLOBAL(ltc_cipher_mutex)
int cipher_is_valid(int idx)
bool cipher_is_valid(int idx)
{
LTC_MUTEX_LOCK(&ltc_cipher_mutex);
if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) {
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return CRYPT_INVALID_CIPHER;
return false;
}
LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
return CRYPT_OK;
return true;
}
int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb)
void ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb)
{
int err;
if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
return err;
if (!cipher_is_valid(ecb->cipher)) {
throw std::runtime_error("");
}
if (len % cipher_descriptor[ecb->cipher].block_length) {
return CRYPT_INVALID_ARG;
throw std::runtime_error("");
}
/* check for accel */
if (cipher_descriptor[ecb->cipher].accel_ecb_decrypt != NULL) {
return cipher_descriptor[ecb->cipher].accel_ecb_decrypt(ct, pt, len / cipher_descriptor[ecb->cipher].block_length, &ecb->key);
} else {
while (len) {
if ((err = cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key)) != CRYPT_OK) {
return err;
}
cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key);
pt += cipher_descriptor[ecb->cipher].block_length;
ct += cipher_descriptor[ecb->cipher].block_length;
len -= cipher_descriptor[ecb->cipher].block_length;
}
}
return CRYPT_OK;
}
int ecb_done(symmetric_ECB *ecb)
void ecb_done(symmetric_ECB *ecb)
{
int err;
if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
return err;
if (!cipher_is_valid(ecb->cipher)) {
throw std::runtime_error("");
}
cipher_descriptor[ecb->cipher].done(&ecb->key);
return CRYPT_OK;
}
int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb)
void ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb)
{
int err;
if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
return err;
if (!cipher_is_valid(ecb->cipher)) {
throw std::runtime_error("");
}
if (len % cipher_descriptor[ecb->cipher].block_length) {
return CRYPT_INVALID_ARG;
throw std::runtime_error("");
}
/* check for accel */
if (cipher_descriptor[ecb->cipher].accel_ecb_encrypt != NULL) {
return cipher_descriptor[ecb->cipher].accel_ecb_encrypt(pt, ct, len / cipher_descriptor[ecb->cipher].block_length, &ecb->key);
} else {
while (len) {
if ((err = cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key)) != CRYPT_OK) {
return err;
}
cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key);
pt += cipher_descriptor[ecb->cipher].block_length;
ct += cipher_descriptor[ecb->cipher].block_length;
len -= cipher_descriptor[ecb->cipher].block_length;
}
}
return CRYPT_OK;
}
int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb)
{
int err;
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
return err;
}
ecb->cipher = cipher;
ecb->blocklen = cipher_descriptor[cipher].block_length;
return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ecb->key);
}
} // namespace
@ -1697,9 +1595,8 @@ std::vector<std::uint8_t> aes_ecb_encrypt(
{
if (input.empty()) return {};
symmetric_ECB ecb;
auto cipher = register_cipher(&aes_desc);
ecb_start(cipher, key.data(), key.size(), 0, &ecb);
rijndael_key rkey;
rijndael_setup(key.data(), key.size(), 0, rkey);
std::vector<std::uint8_t> output(input.size());
ecb_encrypt(input.data(), output.data(), input.size(), &ecb);
ecb_done(&ecb);
@ -1716,7 +1613,7 @@ std::vector<std::uint8_t> aes_ecb_decrypt(
if (input.empty()) return {};
symmetric_ECB ecb;
auto cipher = register_cipher(&aes_desc);
auto cipher = register_cipher(&rijndael_desc);
ecb_start(cipher, key.data(), key.size(), 0, &ecb);
std::vector<std::uint8_t> output(input.size());
ecb_decrypt(input.data(), output.data(), input.size(), &ecb);
@ -1735,7 +1632,7 @@ std::vector<std::uint8_t> aes_cbc_encrypt(
if (input.empty()) return {};
symmetric_CBC cbc;
auto cipher = register_cipher(&aes_desc);
auto cipher = register_cipher(&rijndael_desc);
cbc_start(cipher, iv.data(), key.data(), key.size(), 0, &cbc);
std::vector<std::uint8_t> output(input.size());
cbc_encrypt(input.data(), output.data(), input.size(), &cbc);
@ -1754,7 +1651,7 @@ std::vector<std::uint8_t> aes_cbc_decrypt(
if (input.empty()) return {};
symmetric_CBC cbc;
auto cipher = register_cipher(&aes_desc);
auto cipher = register_cipher(&rijndael_desc);
cbc_start(cipher, iv.data(), key.data(), key.size(), 0, &cbc);
std::vector<std::uint8_t> output(input.size());
cbc_decrypt(input.data(), output.data(), input.size(), &cbc);

View File

@ -26,49 +26,6 @@ extern "C" {
/* descriptor table size */
#define TAB_SIZE 32
/* error codes [will be expanded in future releases] */
enum {
CRYPT_OK=0, /* Result OK */
CRYPT_ERROR, /* Generic Error */
CRYPT_NOP, /* Not a failure but no operation was performed */
CRYPT_INVALID_KEYSIZE, /* Invalid key size given */
CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */
CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */
CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */
CRYPT_INVALID_PACKET, /* Invalid input packet given */
CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */
CRYPT_INVALID_CIPHER, /* Invalid cipher specified */
CRYPT_INVALID_HASH, /* Invalid hash specified */
CRYPT_INVALID_PRNG, /* Invalid PRNG specified */
CRYPT_MEM, /* Out of memory */
CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */
CRYPT_INVALID_ARG, /* Generic invalid argument */
CRYPT_FILE_NOTFOUND, /* File Not Found */
CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */
CRYPT_OVERFLOW, /* An overflow of a value was detected/prevented */
CRYPT_UNUSED1, /* UNUSED1 */
CRYPT_UNUSED2, /* UNUSED2 */
CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */
CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */
CRYPT_PK_INVALID_PADDING, /* Invalid padding on input */
CRYPT_HASH_OVERFLOW /* Hash applied to too many bits */
};
#include "tomcrypt_cfg.h"
#include "tomcrypt_macros.h"
#include "tomcrypt_cipher.h"

View File

@ -1,35 +1,3 @@
/* ---- SYMMETRIC KEY STUFF -----
*
* We put each of the ciphers scheduled keys in their own structs then we put all of
* the key formats in one union. This makes the function prototypes easier to use.
*/
#ifdef LTC_BLOWFISH
struct blowfish_key {
ulong32 S[4][256];
ulong32 K[18];
};
#endif
#ifdef LTC_RC5
struct rc5_key {
int rounds;
ulong32 K[50];
};
#endif
#ifdef LTC_RC6
struct rc6_key {
ulong32 K[44];
};
#endif
#ifdef LTC_SAFERP
struct saferp_key {
unsigned char K[33][16];
long rounds;
};
#endif
#ifdef LTC_RIJNDAEL
struct rijndael_key {
ulong32 eK[60], dK[60];
@ -37,172 +5,9 @@ struct rijndael_key {
};
#endif
#ifdef LTC_KSEED
struct kseed_key {
ulong32 K[32], dK[32];
};
#endif
#ifdef LTC_KASUMI
struct kasumi_key {
ulong32 KLi1[8], KLi2[8],
KOi1[8], KOi2[8], KOi3[8],
KIi1[8], KIi2[8], KIi3[8];
};
#endif
#ifdef LTC_XTEA
struct xtea_key {
unsigned long A[32], B[32];
};
#endif
#ifdef LTC_TWOFISH
#ifndef LTC_TWOFISH_SMALL
struct twofish_key {
ulong32 S[4][256], K[40];
};
#else
struct twofish_key {
ulong32 K[40];
unsigned char S[32], start;
};
#endif
#endif
#ifdef LTC_SAFER
#define LTC_SAFER_K64_DEFAULT_NOF_ROUNDS 6
#define LTC_SAFER_K128_DEFAULT_NOF_ROUNDS 10
#define LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS 8
#define LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS 10
#define LTC_SAFER_MAX_NOF_ROUNDS 13
#define LTC_SAFER_BLOCK_LEN 8
#define LTC_SAFER_KEY_LEN (1 + LTC_SAFER_BLOCK_LEN * (1 + 2 * LTC_SAFER_MAX_NOF_ROUNDS))
typedef unsigned char safer_block_t[LTC_SAFER_BLOCK_LEN];
typedef unsigned char safer_key_t[LTC_SAFER_KEY_LEN];
struct safer_key { safer_key_t key; };
#endif
#ifdef LTC_RC2
struct rc2_key { unsigned xkey[64]; };
#endif
#ifdef LTC_DES
struct des_key {
ulong32 ek[32], dk[32];
};
struct des3_key {
ulong32 ek[3][32], dk[3][32];
};
#endif
#ifdef LTC_CAST5
struct cast5_key {
ulong32 K[32], keylen;
};
#endif
#ifdef LTC_NOEKEON
struct noekeon_key {
ulong32 K[4], dK[4];
};
#endif
#ifdef LTC_SKIPJACK
struct skipjack_key {
unsigned char key[10];
};
#endif
#ifdef LTC_KHAZAD
struct khazad_key {
ulong64 roundKeyEnc[8 + 1];
ulong64 roundKeyDec[8 + 1];
};
#endif
#ifdef LTC_ANUBIS
struct anubis_key {
int keyBits;
int R;
ulong32 roundKeyEnc[18 + 1][4];
ulong32 roundKeyDec[18 + 1][4];
};
#endif
#ifdef LTC_MULTI2
struct multi2_key {
int N;
ulong32 uk[8];
};
#endif
#ifdef LTC_CAMELLIA
struct camellia_key {
int R;
ulong64 kw[4], k[24], kl[6];
};
#endif
typedef union Symmetric_key {
#ifdef LTC_DES
struct des_key des;
struct des3_key des3;
#endif
#ifdef LTC_RC2
struct rc2_key rc2;
#endif
#ifdef LTC_SAFER
struct safer_key safer;
#endif
#ifdef LTC_TWOFISH
struct twofish_key twofish;
#endif
#ifdef LTC_BLOWFISH
struct blowfish_key blowfish;
#endif
#ifdef LTC_RC5
struct rc5_key rc5;
#endif
#ifdef LTC_RC6
struct rc6_key rc6;
#endif
#ifdef LTC_SAFERP
struct saferp_key saferp;
#endif
#ifdef LTC_RIJNDAEL
struct rijndael_key rijndael;
#endif
#ifdef LTC_XTEA
struct xtea_key xtea;
#endif
#ifdef LTC_CAST5
struct cast5_key cast5;
#endif
#ifdef LTC_NOEKEON
struct noekeon_key noekeon;
#endif
#ifdef LTC_SKIPJACK
struct skipjack_key skipjack;
#endif
#ifdef LTC_KHAZAD
struct khazad_key khazad;
#endif
#ifdef LTC_ANUBIS
struct anubis_key anubis;
#endif
#ifdef LTC_KSEED
struct kseed_key kseed;
#endif
#ifdef LTC_KASUMI
struct kasumi_key kasumi;
#endif
#ifdef LTC_MULTI2
struct multi2_key multi2;
#endif
#ifdef LTC_CAMELLIA
struct camellia_key camellia;
#endif
void *data;
} symmetric_key;
@ -358,25 +163,21 @@ extern struct ltc_cipher_descriptor {
@param skey [out] The destination of the scheduled key
@return CRYPT_OK if successful
*/
int (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
void (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
/** Encrypt a block
@param pt The plaintext
@param ct [out] The ciphertext
@param skey The scheduled key
@return CRYPT_OK if successful
*/
int (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
void (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
/** Decrypt a block
@param ct The ciphertext
@param pt [out] The plaintext
@param skey The scheduled key
@return CRYPT_OK if successful
*/
int (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
/** Test the block cipher
@return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
*/
int (*test)(void);
void (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
/** Terminate the context
@param skey The scheduled key
@ -387,420 +188,15 @@ extern struct ltc_cipher_descriptor {
@param keysize [in/out] The size of the key desired and the suggested size
@return CRYPT_OK if successful
*/
int (*keysize)(int *keysize);
/** Accelerators **/
/** Accelerated ECB encryption
@param pt Plaintext
@param ct Ciphertext
@param blocks The number of complete blocks to process
@param skey The scheduled key context
@return CRYPT_OK if successful
*/
int (*accel_ecb_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, symmetric_key *skey);
/** Accelerated ECB decryption
@param pt Plaintext
@param ct Ciphertext
@param blocks The number of complete blocks to process
@param skey The scheduled key context
@return CRYPT_OK if successful
*/
int (*accel_ecb_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, symmetric_key *skey);
/** Accelerated CBC encryption
@param pt Plaintext
@param ct Ciphertext
@param blocks The number of complete blocks to process
@param IV The initial value (input/output)
@param skey The scheduled key context
@return CRYPT_OK if successful
*/
int (*accel_cbc_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, symmetric_key *skey);
/** Accelerated CBC decryption
@param pt Plaintext
@param ct Ciphertext
@param blocks The number of complete blocks to process
@param IV The initial value (input/output)
@param skey The scheduled key context
@return CRYPT_OK if successful
*/
int (*accel_cbc_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, symmetric_key *skey);
/** Accelerated CTR encryption
@param pt Plaintext
@param ct Ciphertext
@param blocks The number of complete blocks to process
@param IV The initial value (input/output)
@param mode little or big endian counter (mode=0 or mode=1)
@param skey The scheduled key context
@return CRYPT_OK if successful
*/
int (*accel_ctr_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, symmetric_key *skey);
/** Accelerated LRW
@param pt Plaintext
@param ct Ciphertext
@param blocks The number of complete blocks to process
@param IV The initial value (input/output)
@param tweak The LRW tweak
@param skey The scheduled key context
@return CRYPT_OK if successful
*/
int (*accel_lrw_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);
/** Accelerated LRW
@param ct Ciphertext
@param pt Plaintext
@param blocks The number of complete blocks to process
@param IV The initial value (input/output)
@param tweak The LRW tweak
@param skey The scheduled key context
@return CRYPT_OK if successful
*/
int (*accel_lrw_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);
/** Accelerated CCM packet (one-shot)
@param key The secret key to use
@param keylen The length of the secret key (octets)
@param uskey A previously scheduled key [optional can be NULL]
@param nonce The session nonce [use once]
@param noncelen The length of the nonce
@param header The header for the session
@param headerlen The length of the header (octets)
@param pt [out] The plaintext
@param ptlen The length of the plaintext (octets)
@param ct [out] The ciphertext
@param tag [out] The destination tag
@param taglen [in/out] The max size and resulting size of the authentication tag
@param direction Encrypt or Decrypt direction (0 or 1)
@return CRYPT_OK if successful
*/
int (*accel_ccm_memory)(
const unsigned char *key, unsigned long keylen,
symmetric_key *uskey,
const unsigned char *nonce, unsigned long noncelen,
const unsigned char *header, unsigned long headerlen,
unsigned char *pt, unsigned long ptlen,
unsigned char *ct,
unsigned char *tag, unsigned long *taglen,
int direction);
/** Accelerated GCM packet (one shot)
@param key The secret key
@param keylen The length of the secret key
@param IV The initial vector
@param IVlen The length of the initial vector
@param adata The additional authentication data (header)
@param adatalen The length of the adata
@param pt The plaintext
@param ptlen The length of the plaintext (ciphertext length is the same)
@param ct The ciphertext
@param tag [out] The MAC tag
@param taglen [in/out] The MAC tag length
@param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
@return CRYPT_OK on success
*/
int (*accel_gcm_memory)(
const unsigned char *key, unsigned long keylen,
const unsigned char *IV, unsigned long IVlen,
const unsigned char *adata, unsigned long adatalen,
unsigned char *pt, unsigned long ptlen,
unsigned char *ct,
unsigned char *tag, unsigned long *taglen,
int direction);
/** Accelerated one shot LTC_OMAC
@param key The secret key
@param keylen The key length (octets)
@param in The message
@param inlen Length of message (octets)
@param out [out] Destination for tag
@param outlen [in/out] Initial and final size of out
@return CRYPT_OK on success
*/
int (*omac_memory)(
const unsigned char *key, unsigned long keylen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
/** Accelerated one shot XCBC
@param key The secret key
@param keylen The key length (octets)
@param in The message
@param inlen Length of message (octets)
@param out [out] Destination for tag
@param outlen [in/out] Initial and final size of out
@return CRYPT_OK on success
*/
int (*xcbc_memory)(
const unsigned char *key, unsigned long keylen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
/** Accelerated one shot F9
@param key The secret key
@param keylen The key length (octets)
@param in The message
@param inlen Length of message (octets)
@param out [out] Destination for tag
@param outlen [in/out] Initial and final size of out
@return CRYPT_OK on success
@remark Requires manual padding
*/
int (*f9_memory)(
const unsigned char *key, unsigned long keylen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
/** Accelerated XTS encryption
@param pt Plaintext
@param ct Ciphertext
@param blocks The number of complete blocks to process
@param tweak The 128-bit encryption tweak (input/output).
The tweak should not be encrypted on input, but
next tweak will be copied encrypted on output.
@param skey1 The first scheduled key context
@param skey2 The second scheduled key context
@return CRYPT_OK if successful
*/
int (*accel_xts_encrypt)(const unsigned char *pt, unsigned char *ct,
unsigned long blocks, unsigned char *tweak, symmetric_key *skey1,
symmetric_key *skey2);
/** Accelerated XTS decryption
@param ct Ciphertext
@param pt Plaintext
@param blocks The number of complete blocks to process
@param tweak The 128-bit encryption tweak (input/output).
The tweak should not be encrypted on input, but
next tweak will be copied encrypted on output.
@param skey1 The first scheduled key context
@param skey2 The second scheduled key context
@return CRYPT_OK if successful
*/
int (*accel_xts_decrypt)(const unsigned char *ct, unsigned char *pt,
unsigned long blocks, unsigned char *tweak, symmetric_key *skey1,
symmetric_key *skey2);
void (*keysize)(int *keysize);
} cipher_descriptor[];
#ifdef LTC_BLOWFISH
int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int blowfish_test(void);
void blowfish_done(symmetric_key *skey);
int blowfish_keysize(int *keysize);
extern const struct ltc_cipher_descriptor blowfish_desc;
#endif
#ifdef LTC_RC5
int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int rc5_test(void);
void rc5_done(symmetric_key *skey);
int rc5_keysize(int *keysize);
extern const struct ltc_cipher_descriptor rc5_desc;
#endif
#ifdef LTC_RC6
int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int rc6_test(void);
void rc6_done(symmetric_key *skey);
int rc6_keysize(int *keysize);
extern const struct ltc_cipher_descriptor rc6_desc;
#endif
#ifdef LTC_RC2
int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int rc2_setup_ex(const unsigned char *key, int keylen, int bits, int num_rounds, symmetric_key *skey);
int rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int rc2_test(void);
void rc2_done(symmetric_key *skey);
int rc2_keysize(int *keysize);
extern const struct ltc_cipher_descriptor rc2_desc;
#endif
#ifdef LTC_SAFERP
int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int saferp_test(void);
void saferp_done(symmetric_key *skey);
int saferp_keysize(int *keysize);
extern const struct ltc_cipher_descriptor saferp_desc;
#endif
#ifdef LTC_SAFER
int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
int safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
int safer_k64_test(void);
int safer_sk64_test(void);
int safer_sk128_test(void);
void safer_done(symmetric_key *skey);
int safer_64_keysize(int *keysize);
int safer_128_keysize(int *keysize);
extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc;
#endif
#ifdef LTC_RIJNDAEL
int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int rijndael_test(void);
void rijndael_done(symmetric_key *skey);
int rijndael_keysize(int *keysize);
int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
void rijndael_enc_done(symmetric_key *skey);
int rijndael_enc_keysize(int *keysize);
extern const struct ltc_cipher_descriptor rijndael_desc, aes_desc;
extern const struct ltc_cipher_descriptor rijndael_enc_desc, aes_enc_desc;
#endif
#ifdef LTC_XTEA
int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int xtea_test(void);
void xtea_done(symmetric_key *skey);
int xtea_keysize(int *keysize);
extern const struct ltc_cipher_descriptor xtea_desc;
#endif
#ifdef LTC_TWOFISH
int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int twofish_test(void);
void twofish_done(symmetric_key *skey);
int twofish_keysize(int *keysize);
extern const struct ltc_cipher_descriptor twofish_desc;
#endif
#ifdef LTC_DES
int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int des_test(void);
void des_done(symmetric_key *skey);
int des_keysize(int *keysize);
int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int des3_test(void);
void des3_done(symmetric_key *skey);
int des3_keysize(int *keysize);
extern const struct ltc_cipher_descriptor des_desc, des3_desc;
#endif
#ifdef LTC_CAST5
int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int cast5_test(void);
void cast5_done(symmetric_key *skey);
int cast5_keysize(int *keysize);
extern const struct ltc_cipher_descriptor cast5_desc;
#endif
#ifdef LTC_NOEKEON
int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int noekeon_test(void);
void noekeon_done(symmetric_key *skey);
int noekeon_keysize(int *keysize);
extern const struct ltc_cipher_descriptor noekeon_desc;
#endif
#ifdef LTC_SKIPJACK
int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int skipjack_test(void);
void skipjack_done(symmetric_key *skey);
int skipjack_keysize(int *keysize);
extern const struct ltc_cipher_descriptor skipjack_desc;
#endif
#ifdef LTC_KHAZAD
int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int khazad_test(void);
void khazad_done(symmetric_key *skey);
int khazad_keysize(int *keysize);
extern const struct ltc_cipher_descriptor khazad_desc;
#endif
#ifdef LTC_ANUBIS
int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int anubis_test(void);
void anubis_done(symmetric_key *skey);
int anubis_keysize(int *keysize);
extern const struct ltc_cipher_descriptor anubis_desc;
#endif
#ifdef LTC_KSEED
int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int kseed_test(void);
void kseed_done(symmetric_key *skey);
int kseed_keysize(int *keysize);
extern const struct ltc_cipher_descriptor kseed_desc;
#endif
#ifdef LTC_KASUMI
int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int kasumi_test(void);
void kasumi_done(symmetric_key *skey);
int kasumi_keysize(int *keysize);
extern const struct ltc_cipher_descriptor kasumi_desc;
#endif
#ifdef LTC_MULTI2
int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int multi2_test(void);
void multi2_done(symmetric_key *skey);
int multi2_keysize(int *keysize);
extern const struct ltc_cipher_descriptor multi2_desc;
#endif
#ifdef LTC_CAMELLIA
int camellia_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int camellia_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int camellia_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
int camellia_test(void);
void camellia_done(symmetric_key *skey);
int camellia_keysize(int *keysize);
extern const struct ltc_cipher_descriptor camellia_desc;
#endif
#ifdef LTC_ECB_MODE
int ecb_start(int cipher, const unsigned char *key,
void ecb_start(int cipher, const unsigned char *key,
int keylen, int num_rounds, symmetric_ECB *ecb);
int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb);
int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb);
int ecb_done(symmetric_ECB *ecb);
void ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb);
void ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb);
void ecb_done(symmetric_ECB *ecb);
#endif
#ifdef LTC_CFB_MODE
@ -824,13 +220,13 @@ int ofb_done(symmetric_OFB *ofb);
#endif
#ifdef LTC_CBC_MODE
int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
void cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
int keylen, int num_rounds, symmetric_CBC *cbc);
int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc);
int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc);
int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc);
int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc);
int cbc_done(symmetric_CBC *cbc);
void cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc);
void cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc);
void cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc);
void cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc);
void cbc_done(symmetric_CBC *cbc);
#endif
#ifdef LTC_CTR_MODE
@ -921,32 +317,6 @@ int find_cipher_any(const char *name, int blocklen, int keylen);
int find_cipher_id(unsigned char ID);
int register_cipher(const struct ltc_cipher_descriptor *cipher);
int unregister_cipher(const struct ltc_cipher_descriptor *cipher);
int cipher_is_valid(int idx);
bool cipher_is_valid(int idx);
LTC_MUTEX_PROTO(ltc_cipher_mutex)
/* ---- stream ciphers ---- */
#ifdef LTC_CHACHA
typedef struct {
ulong32 input[16];
unsigned char kstream[64];
unsigned long ksleft;
unsigned long ivlen;
int rounds;
} chacha_state;
int chacha_setup(chacha_state *st, const unsigned char *key, unsigned long keylen, int rounds);
int chacha_ivctr32(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong32 counter);
int chacha_ivctr64(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter);
int chacha_crypt(chacha_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out);
int chacha_keystream(chacha_state *st, unsigned char *out, unsigned long outlen);
int chacha_done(chacha_state *st);
int chacha_test(void);
#endif /* LTC_CHACHA */
/* $Source$ */
/* $Revision$ */
/* $Date$ */