updates.
[crypto.git] / lib / silccrypt / rc5.c
1 /*
2  * rc5.c                                RC5-32/16/b
3  *
4  * Copyright (c) 1999 Pekka Riikonen <priikone@poseidon.pspt.fi>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish, dis-
10  * tribute, sublicense, and/or sell copies of the Software, and to permit
11  * persons to whom the Software is furnished to do so, subject to the fol-
12  * lowing conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
19  * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
20  * SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL-
21  * ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23  * IN THE SOFTWARE.
24  *
25  * Except as contained in this notice, the name of the authors shall
26  * not be used in advertising or otherwise to promote the sale, use or
27  * other dealings in this Software without prior written authorization from
28  * the authors.
29  *
30  */
31
32 /*
33  * Based on RC5 reference code and on description of Bruce Schneier's 
34  * Applied Cryptography.
35  *
36  * This implementation has a word size of 32 bits, a rounds of 16 and 
37  * variable key length from 128 and 192 up to 256 bits.
38  *
39  */
40
41 #include "silcincludes.h"
42 #include "rc5.h"
43
44 /* 
45  * SILC Crypto API for RC5
46  */
47
48 /* Sets the key for the cipher. */
49
50 SILC_CIPHER_API_SET_KEY(aes)
51 {
52   uint32 k[8];
53
54   SILC_GET_WORD_KEY(key, k, keylen);
55   rc5_set_key((RC5Context *)context, k, keylen);
56
57   return TRUE;
58 }
59
60 /* Sets the string as a new key for the cipher. The string is first
61    hashed and then used as a new key. */
62
63 SILC_CIPHER_API_SET_KEY_WITH_STRING(aes)
64 {
65   /*  unsigned char key[md5_hash_len];
66   SilcMarsContext *ctx = (SilcMarsContext *)context;
67
68   make_md5_hash(string, &key);
69   memcpy(&ctx->key, mars_set_key(&key, keylen), keylen);
70   memset(&key, 'F', sizeoof(key));
71   */
72
73   return 1;
74 }
75
76 /* Returns the size of the cipher context. */
77
78 SILC_CIPHER_API_CONTEXT_LEN(aes)
79 {
80   return sizeof(RC5Context);
81 }
82
83 /* Encrypts with the cipher in CBC mode. Source and destination buffers
84    maybe one and same. */
85
86 SILC_CIPHER_API_ENCRYPT_CBC(aes)
87 {
88   uint32 tiv[4];
89   int i;
90
91   SILC_CBC_GET_IV(tiv, iv);
92
93   SILC_CBC_ENC_PRE(tiv, src);
94   rc5_encrypt((RC5Context *)context, tiv, tiv);
95   SILC_CBC_ENC_POST(tiv, dst, src);
96
97   for (i = 16; i < len; i += 16) {
98     SILC_CBC_ENC_PRE(tiv, src);
99     rc5_encrypt((RC5Context *)context, tiv, tiv);
100     SILC_CBC_ENC_POST(tiv, dst, src);
101   }
102
103   SILC_CBC_PUT_IV(tiv, iv);
104
105   return TRUE;
106 }
107
108 /* Decrypts with the cipher in CBC mode. Source and destination buffers
109    maybe one and same. */
110
111 SILC_CIPHER_API_DECRYPT_CBC(aes)
112 {
113   uint32 tmp[4], tmp2[4], tiv[4];
114   int i;
115
116   SILC_CBC_GET_IV(tiv, iv);
117
118   SILC_CBC_DEC_PRE(tmp, src);
119   rc5_decrypt((RC5Context *)context, tmp, tmp2);
120   SILC_CBC_DEC_POST(tmp2, dst, src, tmp, tiv);
121
122   for (i = 16; i < len; i += 16) {
123     SILC_CBC_DEC_PRE(tmp, src);
124     rc5_decrypt((RC5Context *)context, tmp, tmp2); 
125     SILC_CBC_DEC_POST(tmp2, dst, src, tmp, tiv);
126   }
127   
128   SILC_CBC_PUT_IV(tiv, iv);
129   
130   return TRUE;
131 }
132
133 /* RC5 encryption */
134 #define RC5E(i, A, B)                           \
135                 A = A ^ B;                      \
136                 A = rotl(A, B) + S[i];          \
137                 B = B ^ A;                      \
138                 B = rotl(B, A) + S[i + 1];
139
140 /* RC5 decryption */
141 #define RC5D(i, A, B)                           \
142                 B = B - S[i + 1];               \
143                 B = rotr(B, A) ^ A;             \
144                 A = A - S[i];                   \
145                 A = rotr(A, B) ^ B;
146
147 /* Sets RC5 key */
148
149 int rc5_set_key(RC5Context *ctx, const uint32 in_key[], int key_len)
150 {
151         u32 i, j, k, A, B, L[c];
152         u32 *out_key = ctx->out_key;
153
154         if (key_len < b || key_len > (2 * b))
155                 return -1;
156
157         /* init L */
158         for (i = 0; i < key_len / w; i++)
159                 L[i] = in_key[i];
160
161         /* init key array (S) */
162         out_key[0] = 0xb7e15163;
163         for (i = 1; i < t; i++)
164                 out_key[i] = out_key[i - 1] + 0x9e3779b9;
165
166         /* mix L and key array (S) */
167         A = B = 0;
168         for (k = i = j = 0; k < (3 * t); k++) {
169                 A = rotl(out_key[i] + (A + B), 3);
170                 B += A;
171                 B = rotl(L[j] + B, B);
172                 out_key[i] = A;
173                 L[j] = B;
174                 i = (i + 1) % t;
175                 j = (j + 1) % c;
176         }
177
178         return 0;
179 }
180
181 /* Encrypts *one* block at a time. */
182
183 int rc5_encrypt(RC5Context *ctx, u32 *in, u32 *out)
184 {
185         u32 A, B;
186         u32 *S = ctx->out_key;
187
188         A = in[0] + S[0];
189         B = in[1] + S[1];
190
191         RC5E(2, A, B); RC5E(4, A, B);
192         RC5E(6, A, B); RC5E(8, A, B);
193         RC5E(10, A, B); RC5E(12, A, B);
194         RC5E(14, A, B); RC5E(16, A, B);
195         RC5E(18, A, B); RC5E(20, A, B);
196         RC5E(22, A, B); RC5E(24, A, B);
197         RC5E(26, A, B); RC5E(28, A, B);
198         RC5E(30, A, B); RC5E(32, A, B);
199
200         out[0] = A;
201         out[1] = B;
202
203         return 0;
204 }
205
206 /* Decrypts *one* block at a time. */
207
208 int rc5_decrypt(RC5Context *ctx, u32 *in, u32 *out)
209 {
210         u32 A, B;
211         u32 *S = ctx->out_key;
212
213         A = in[0];
214         B = in[1];
215
216         RC5D(32, A, B); RC5D(30, A, B); 
217         RC5D(28, A, B); RC5D(26, A, B); 
218         RC5D(24, A, B); RC5D(22, A, B); 
219         RC5D(20, A, B); RC5D(18, A, B);
220         RC5D(16, A, B); RC5D(14, A, B);
221         RC5D(12, A, B); RC5D(10, A, B);
222         RC5D(8, A, B); RC5D(6, A, B);
223         RC5D(4, A, B); RC5D(2, A, B);
224
225         out[0] = A - S[0];
226         out[1] = B - S[1];
227
228         return 0;
229 }