-o: accept "-" as name, do nothing (leave stderr as is)
[tfcrypt.git] / tfocb.c
1 #include <string.h>
2 #include "tfdef.h"
3
4 static inline void ocb_block(TF_UNIT_TYPE *x, int tag)
5 {
6         TF_UNIT_TYPE c = (x[0] >> (TF_UNIT_BITS-1));
7         size_t i;
8
9         if (tag) goto _tag;
10         for (i = 0; i < TF_NR_BLOCK_UNITS-1; i++)
11                 x[i] = ((x[i] << 1) | (x[i+1] >> (TF_UNIT_BITS-1)));
12         x[TF_NR_BLOCK_UNITS-1] = ((x[i-1] << 1) ^ (c*IRR_POLY_CONST));
13         return;
14
15 _tag:   for (i = 0; i < TF_NR_BLOCK_UNITS-1; i++)
16                 x[i] ^= ((x[i] << 1) | (x[i+1] >> (TF_UNIT_BITS-1)));
17         x[TF_NR_BLOCK_UNITS-1] ^= ((x[i-1] << 1) ^ (c*IRR_POLY_CONST));
18 }
19
20 static void ocb_encrypt(const void *key, void *ctr, void *out, void *tag, const void *in, size_t sz)
21 {
22         const TF_BYTE_TYPE *uin = in;
23         TF_BYTE_TYPE *uout = out, *s, *d;
24         TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
25         TF_UNIT_TYPE tctr[TF_NR_BLOCK_UNITS], c[TF_NR_BLOCK_UNITS];
26         TF_UNIT_TYPE *uctr = ctr, *utag = tag;
27         const TF_UNIT_TYPE *ukey = key;
28         size_t sl = sz, i;
29
30         tf_encrypt_rawblk(tctr, uctr, ukey);
31         if (tag) {
32                 memcpy(c, tag, TF_BLOCK_SIZE);
33                 data_to_words(c, TF_BLOCK_SIZE);
34         }
35
36         if (sl >= TF_BLOCK_SIZE) {
37                 do {
38                         memcpy(x, uin, TF_BLOCK_SIZE);
39                         uin += TF_BLOCK_SIZE;
40                         data_to_words(x, TF_BLOCK_SIZE);
41
42                         ctr_inc(uctr, TF_NR_BLOCK_UNITS);
43                         ocb_block(tctr, 0);
44                         if (tag) for (i = 0; i < TF_NR_BLOCK_UNITS; i++) c[i] ^= x[i];
45                         for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
46                         tf_encrypt_rawblk(y, x, ukey);
47                         for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= tctr[i];
48
49                         data_to_words(y, TF_BLOCK_SIZE);
50                         memcpy(uout, y, TF_BLOCK_SIZE);
51                         uout += TF_BLOCK_SIZE;
52                 } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE);
53         }
54
55         if (sl) {
56                 ctr_inc(uctr, TF_NR_BLOCK_UNITS);
57                 ocb_block(tctr, 0);
58                 memset(x, 0, TF_BLOCK_SIZE);
59                 x[TF_NR_BLOCK_UNITS-1] = (TF_TO_BITS(sl));
60                 for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
61                 tf_encrypt_rawblk(y, x, ukey);
62
63                 memcpy(x, uin, sl);
64                 data_to_words(x, sl);
65                 s = (TF_BYTE_TYPE *)x; d = (TF_BYTE_TYPE *)y;
66                 memcpy(s+sl, d+sl, TF_BLOCK_SIZE-sl);
67                 if (tag) for (i = 0; i < TF_NR_BLOCK_UNITS; i++) c[i] ^= x[i];
68                 for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= y[i];
69
70                 data_to_words(x, sl);
71                 memcpy(uout, x, sl);
72         }
73
74         if (!tag) goto _done;
75
76         ocb_block(tctr, 1);
77         for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] = tctr[i] ^ c[i];
78         tf_encrypt_rawblk(y, x, ukey);
79         data_to_words(y, TF_BLOCK_SIZE);
80         for (i = 0; i < TF_NR_BLOCK_UNITS; i++) utag[i] ^= y[i];
81
82 _done:  memset(tctr, 0, TF_BLOCK_SIZE);
83         memset(c, 0, TF_BLOCK_SIZE);
84         memset(x, 0, TF_BLOCK_SIZE);
85         memset(y, 0, TF_BLOCK_SIZE);
86 }
87
88 void tf_ocb_encrypt(const void *key, void *ctr, void *out, void *tag, const void *in, size_t sz, size_t bpi)
89 {
90         const TF_BYTE_TYPE *uin = in;
91         TF_BYTE_TYPE *uout = out;
92         size_t sl = sz, sx = TF_BLOCKS_TO_BYTES(bpi);
93
94         if (sl >= sx) {
95                 do {
96                         ocb_encrypt(key, ctr, uout, tag, uin, sx);
97                         uout += sx;
98                         uin += sx;
99                 } while ((sl -= sx) >= sx);
100         }
101
102         if (sl) ocb_encrypt(key, ctr, uout, tag, uin, sl);
103 }
104
105 static void ocb_decrypt(const void *key, void *ctr, void *out, void *tag, const void *in, size_t sz)
106 {
107         const TF_BYTE_TYPE *uin = in;
108         TF_BYTE_TYPE *uout = out;
109         TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
110         TF_UNIT_TYPE tctr[TF_NR_BLOCK_UNITS], c[TF_NR_BLOCK_UNITS];
111         TF_UNIT_TYPE *uctr = ctr, *utag = tag;
112         const TF_UNIT_TYPE *ukey = key;
113         size_t sl = sz, i;
114
115         tf_encrypt_rawblk(tctr, uctr, ukey);
116         if (tag) {
117                 memcpy(c, tag, TF_BLOCK_SIZE);
118                 data_to_words(c, TF_BLOCK_SIZE);
119         }
120
121         if (sl >= TF_BLOCK_SIZE) {
122                 do {
123                         memcpy(x, uin, TF_BLOCK_SIZE);
124                         uin += TF_BLOCK_SIZE;
125                         data_to_words(x, TF_BLOCK_SIZE);
126
127                         ctr_inc(uctr, TF_NR_BLOCK_UNITS);
128                         ocb_block(tctr, 0);
129                         for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
130                         tf_decrypt_rawblk(y, x, ukey);
131                         for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= tctr[i];
132                         if (tag) for (i = 0; i < TF_NR_BLOCK_UNITS; i++) c[i] ^= y[i];
133
134                         data_to_words(y, TF_BLOCK_SIZE);
135                         memcpy(uout, y, TF_BLOCK_SIZE);
136                         uout += TF_BLOCK_SIZE;
137                 } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE);
138         }
139
140         if (sl) {
141                 ctr_inc(uctr, TF_NR_BLOCK_UNITS);
142                 ocb_block(tctr, 0);
143                 memset(x, 0, TF_BLOCK_SIZE);
144                 x[TF_NR_BLOCK_UNITS-1] = (TF_TO_BITS(sl));
145                 for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
146                 tf_encrypt_rawblk(y, x, ukey);
147
148                 memset(x, 0, TF_BLOCK_SIZE);
149                 memcpy(x, uin, sl);
150                 data_to_words(x, sl);
151                 for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= y[i];
152                 if (tag) for (i = 0; i < TF_NR_BLOCK_UNITS; i++) c[i] ^= x[i];
153
154                 data_to_words(x, sl);
155                 memcpy(uout, x, sl);
156         }
157
158         if (!tag) goto _done;
159
160         ocb_block(tctr, 1);
161         for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] = tctr[i] ^ c[i];
162         tf_encrypt_rawblk(y, x, ukey);
163         data_to_words(y, TF_BLOCK_SIZE);
164         for (i = 0; i < TF_NR_BLOCK_UNITS; i++) utag[i] ^= y[i];
165
166 _done:  memset(tctr, 0, TF_BLOCK_SIZE);
167         memset(c, 0, TF_BLOCK_SIZE);
168         memset(x, 0, TF_BLOCK_SIZE);
169         memset(y, 0, TF_BLOCK_SIZE);
170 }
171
172 void tf_ocb_decrypt(const void *key, void *ctr, void *out, void *tag, const void *in, size_t sz, size_t bpi)
173 {
174         const TF_BYTE_TYPE *uin = in;
175         TF_BYTE_TYPE *uout = out;
176         size_t sl = sz, sx = TF_BLOCKS_TO_BYTES(bpi);
177
178         if (sl >= sx) {
179                 do {
180                         ocb_decrypt(key, ctr, uout, tag, uin, sx);
181                         uout += sx;
182                         uin += sx;
183                 } while ((sl -= sx) >= sx);
184         }
185
186         if (sl) ocb_decrypt(key, ctr, uout, tag, uin, sl);
187 }