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