1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 *
4 * LibTomCrypt is a library that provides various cryptographic
5 * algorithms in a highly modular and flexible manner.
6 *
7 * The library is free for all purposes without any express
8 * guarantee it works.
9 */
10 #include "tomcrypt_private.h"
11
12 /**
13 @file ctr_start.c
14 CTR implementation, start chain, Tom St Denis
15 */
16
17
18 #ifdef LTC_CTR_MODE
19
20 /**
21 Initialize a CTR context
22 @param cipher The index of the cipher desired
23 @param IV The initialization vector
24 @param key The secret key
25 @param keylen The length of the secret key (octets)
26 @param num_rounds Number of rounds in the cipher desired (0 for default)
27 @param ctr_mode The counter mode (CTR_COUNTER_LITTLE_ENDIAN or CTR_COUNTER_BIG_ENDIAN)
28 @param ctr The CTR state to initialize
29 @return CRYPT_OK if successful
30 */
ctr_start(int cipher,const unsigned char * IV,const unsigned char * key,int keylen,int num_rounds,int ctr_mode,symmetric_CTR * ctr)31 int ctr_start( int cipher,
32 const unsigned char *IV,
33 const unsigned char *key, int keylen,
34 int num_rounds, int ctr_mode,
35 symmetric_CTR *ctr)
36 {
37 int x, err;
38
39 LTC_ARGCHK(IV != NULL);
40 LTC_ARGCHK(key != NULL);
41 LTC_ARGCHK(ctr != NULL);
42
43 /* bad param? */
44 if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
45 return err;
46 }
47
48 /* ctrlen == counter width */
49 ctr->ctrlen = (ctr_mode & 255) ? (ctr_mode & 255) : cipher_descriptor[cipher]->block_length;
50 if (ctr->ctrlen > cipher_descriptor[cipher]->block_length) {
51 return CRYPT_INVALID_ARG;
52 }
53
54 if ((ctr_mode & 0x1000) == CTR_COUNTER_BIG_ENDIAN) {
55 ctr->ctrlen = cipher_descriptor[cipher]->block_length - ctr->ctrlen;
56 }
57
58 /* setup cipher */
59 if ((err = cipher_descriptor[cipher]->setup(key, keylen, num_rounds, &ctr->key)) != CRYPT_OK) {
60 return err;
61 }
62
63 /* copy ctr */
64 ctr->blocklen = cipher_descriptor[cipher]->block_length;
65 ctr->cipher = cipher;
66 ctr->padlen = 0;
67 ctr->mode = ctr_mode & 0x1000;
68 for (x = 0; x < ctr->blocklen; x++) {
69 ctr->ctr[x] = IV[x];
70 }
71
72 if (ctr_mode & LTC_CTR_RFC3686) {
73 /* increment the IV as per RFC 3686 */
74 if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) {
75 /* little-endian */
76 for (x = 0; x < ctr->ctrlen; x++) {
77 ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
78 if (ctr->ctr[x] != (unsigned char)0) {
79 break;
80 }
81 }
82 } else {
83 /* big-endian */
84 for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) {
85 ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
86 if (ctr->ctr[x] != (unsigned char)0) {
87 break;
88 }
89 }
90 }
91 }
92
93 return cipher_descriptor[ctr->cipher]->ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key);
94 }
95
96 #endif
97
98 /* ref: $Format:%D$ */
99 /* git commit: $Format:%H$ */
100 /* commit time: $Format:%ai$ */
101