#include "tomcrypt.h"
#ifdef LTC_CTR_MODE
#ifdef MACTOMCRYPT
int ctr_start(int cipher, const unsigned char *IV, const unsigned char *key, int keylen, const unsigned char *tweak, int tweaklen,
int num_rounds, int ctr_mode, symmetric_CTR *ctr)
#else
int ctr_start(int cipher, const unsigned char *IV, const unsigned char *key, int keylen,
int num_rounds, int ctr_mode, symmetric_CTR *ctr)
#endif
{
int x, err;
LTC_ARGCHK(IV != NULL);
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ctr != NULL);
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
return err;
}
ctr->ctrlen = (ctr_mode & 255) ? (ctr_mode & 255) : cipher_descriptor[cipher].block_length;
if (ctr->ctrlen > cipher_descriptor[cipher].block_length) {
return CRYPT_INVALID_ARG;
}
if ((ctr_mode & 0x1000) == CTR_COUNTER_BIG_ENDIAN) {
ctr->ctrlen = cipher_descriptor[cipher].block_length - ctr->ctrlen;
}
if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ctr->key)) != CRYPT_OK) {
return err;
}
ctr->blocklen = cipher_descriptor[cipher].block_length;
ctr->cipher = cipher;
ctr->padlen = 0;
ctr->mode = ctr_mode & 0x1000;
for (x = 0; x < ctr->blocklen; x++) {
ctr->ctr[x] = IV[x];
}
if (ctr_mode & LTC_CTR_RFC3686) {
if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) {
for (x = 0; x < ctr->ctrlen; x++) {
ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
if (ctr->ctr[x] != (unsigned char)0) {
break;
}
}
} else {
for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) {
ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
if (ctr->ctr[x] != (unsigned char)0) {
break;
}
}
}
}
return cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key);
}
#endif