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