]> pd.if.org Git - zpackage/blob - pelican.c
6a4dde649f8f55b7a7fd7ce205c170e207a431cb
[zpackage] / pelican.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 pelican.c
13    Pelican MAC, initialize state, by Tom St Denis
14 */
15
16 #ifdef LTC_PELICAN
17
18 #define __LTC_AES_TAB_C__
19 #define ENCRYPT_ONLY
20 #define PELI_TAB
21 #include "../../ciphers/aes/aes_tab.c"
22
23 /**
24    Initialize a Pelican state
25    @param pelmac    The Pelican state to initialize
26    @param key       The secret key
27    @param keylen    The length of the secret key (octets)
28    @return CRYPT_OK if successful
29 */
30 int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen)
31 {
32     int err;
33
34     LTC_ARGCHK(pelmac != NULL);
35     LTC_ARGCHK(key    != NULL);
36
37 #ifdef LTC_FAST
38     if (16 % sizeof(LTC_FAST_TYPE)) {
39         return CRYPT_INVALID_ARG;
40     }
41 #endif
42
43     if ((err = aes_setup(key, keylen, 0, &pelmac->K)) != CRYPT_OK) {
44        return err;
45     }
46
47     zeromem(pelmac->state, 16);
48     aes_ecb_encrypt(pelmac->state, pelmac->state, &pelmac->K);
49     pelmac->buflen = 0;
50
51     return CRYPT_OK;
52 }
53
54 static void _four_rounds(pelican_state *pelmac)
55 {
56     ulong32 s0, s1, s2, s3, t0, t1, t2, t3;
57     int r;
58
59     LOAD32H(s0, pelmac->state      );
60     LOAD32H(s1, pelmac->state  +  4);
61     LOAD32H(s2, pelmac->state  +  8);
62     LOAD32H(s3, pelmac->state  + 12);
63     for (r = 0; r < 4; r++) {
64         t0 =
65             Te0(byte(s0, 3)) ^
66             Te1(byte(s1, 2)) ^
67             Te2(byte(s2, 1)) ^
68             Te3(byte(s3, 0));
69         t1 =
70             Te0(byte(s1, 3)) ^
71             Te1(byte(s2, 2)) ^
72             Te2(byte(s3, 1)) ^
73             Te3(byte(s0, 0));
74         t2 =
75             Te0(byte(s2, 3)) ^
76             Te1(byte(s3, 2)) ^
77             Te2(byte(s0, 1)) ^
78             Te3(byte(s1, 0));
79         t3 =
80             Te0(byte(s3, 3)) ^
81             Te1(byte(s0, 2)) ^
82             Te2(byte(s1, 1)) ^
83             Te3(byte(s2, 0));
84         s0 = t0; s1 = t1; s2 = t2; s3 = t3;
85     }
86     STORE32H(s0, pelmac->state      );
87     STORE32H(s1, pelmac->state  +  4);
88     STORE32H(s2, pelmac->state  +  8);
89     STORE32H(s3, pelmac->state  + 12);
90 }
91
92 /**
93   Process a block of text through Pelican
94   @param pelmac       The Pelican MAC state
95   @param in           The input
96   @param inlen        The length input (octets)
97   @return CRYPT_OK on success
98   */
99 int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen)
100 {
101
102    LTC_ARGCHK(pelmac != NULL);
103    LTC_ARGCHK(in     != NULL);
104
105    /* check range */
106    if (pelmac->buflen < 0 || pelmac->buflen > 15) {
107       return CRYPT_INVALID_ARG;
108    }
109
110 #ifdef LTC_FAST
111    if (pelmac->buflen == 0) {
112       while (inlen & ~15) {
113          int x;
114          for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) {
115             *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pelmac->state + x)) ^= *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)in + x));
116          }
117          _four_rounds(pelmac);
118          in    += 16;
119          inlen -= 16;
120       }
121    }
122 #endif
123
124    while (inlen--) {
125        pelmac->state[pelmac->buflen++] ^= *in++;
126        if (pelmac->buflen == 16) {
127           _four_rounds(pelmac);
128           pelmac->buflen = 0;
129        }
130    }
131    return CRYPT_OK;
132 }
133
134 /**
135   Terminate Pelican MAC
136   @param pelmac      The Pelican MAC state
137   @param out         [out] The TAG
138   @return CRYPT_OK on sucess
139 */
140 int pelican_done(pelican_state *pelmac, unsigned char *out)
141 {
142    LTC_ARGCHK(pelmac  != NULL);
143    LTC_ARGCHK(out     != NULL);
144
145    /* check range */
146    if (pelmac->buflen < 0 || pelmac->buflen > 16) {
147       return CRYPT_INVALID_ARG;
148    }
149
150    if  (pelmac->buflen == 16) {
151        _four_rounds(pelmac);
152        pelmac->buflen = 0;
153    }
154    pelmac->state[pelmac->buflen++] ^= 0x80;
155    aes_ecb_encrypt(pelmac->state, out, &pelmac->K);
156    aes_done(&pelmac->K);
157    return CRYPT_OK;
158 }
159
160 #endif
161
162 /* ref:         $Format:%D$ */
163 /* git commit:  $Format:%H$ */
164 /* commit time: $Format:%ai$ */