| /* LibTomCrypt, modular cryptographic library -- Tom St Denis |
| * |
| * LibTomCrypt is a library that provides various cryptographic |
| * algorithms in a highly modular and flexible manner. |
| * |
| * The library is free for all purposes without any express |
| * guarantee it works. |
| * |
| * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com |
| */ |
| #include "tomcrypt.h" |
| |
| /** |
| @file ctr_encrypt.c |
| CTR implementation, encrypt data, Tom St Denis |
| */ |
| |
| |
| #ifdef LTC_CTR_MODE |
| |
| /** |
| CTR encrypt |
| @param pt Plaintext |
| @param ct [out] Ciphertext |
| @param len Length of plaintext (octets) |
| @param ctr CTR state |
| @return CRYPT_OK if successful |
| */ |
| int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) |
| { |
| int x, err; |
| |
| LTC_ARGCHK(pt != NULL); |
| LTC_ARGCHK(ct != NULL); |
| LTC_ARGCHK(ctr != NULL); |
| |
| if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) { |
| return err; |
| } |
| |
| /* is blocklen/padlen valid? */ |
| if (ctr->blocklen < 1 || ctr->blocklen > (int)sizeof(ctr->ctr) || |
| ctr->padlen < 0 || ctr->padlen > (int)sizeof(ctr->pad)) { |
| return CRYPT_INVALID_ARG; |
| } |
| |
| #ifdef LTC_FAST |
| if (ctr->blocklen % sizeof(LTC_FAST_TYPE)) { |
| return CRYPT_INVALID_ARG; |
| } |
| #endif |
| |
| /* handle acceleration only if pad is empty, accelerator is present and length is >= a block size */ |
| if ((ctr->padlen == ctr->blocklen) && cipher_descriptor[ctr->cipher].accel_ctr_encrypt != NULL && (len >= (unsigned long)ctr->blocklen)) { |
| if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) { |
| return err; |
| } |
| len %= ctr->blocklen; |
| } |
| |
| while (len) { |
| /* is the pad empty? */ |
| if (ctr->padlen == ctr->blocklen) { |
| /* increment counter */ |
| if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) { |
| /* little-endian */ |
| for (x = 0; x < ctr->blocklen; x++) { |
| ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; |
| if (ctr->ctr[x] != (unsigned char)0) { |
| break; |
| } |
| } |
| } else { |
| /* big-endian */ |
| for (x = ctr->blocklen-1; x >= 0; x--) { |
| ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; |
| if (ctr->ctr[x] != (unsigned char)0) { |
| break; |
| } |
| } |
| } |
| |
| /* encrypt it */ |
| if ((err = cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key)) != CRYPT_OK) { |
| return err; |
| } |
| ctr->padlen = 0; |
| } |
| #ifdef LTC_FAST |
| if (ctr->padlen == 0 && len >= (unsigned long)ctr->blocklen) { |
| for (x = 0; x < ctr->blocklen; x += sizeof(LTC_FAST_TYPE)) { |
| *((LTC_FAST_TYPE*)((unsigned char *)ct + x)) = *((LTC_FAST_TYPE*)((unsigned char *)pt + x)) ^ |
| *((LTC_FAST_TYPE*)((unsigned char *)ctr->pad + x)); |
| } |
| pt += ctr->blocklen; |
| ct += ctr->blocklen; |
| len -= ctr->blocklen; |
| ctr->padlen = ctr->blocklen; |
| continue; |
| } |
| #endif |
| *ct++ = *pt++ ^ ctr->pad[ctr->padlen++]; |
| --len; |
| } |
| return CRYPT_OK; |
| } |
| |
| #endif |
| |
| /* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_encrypt.c,v $ */ |
| /* $Revision: 1.20 $ */ |
| /* $Date: 2006/11/21 00:18:23 $ */ |