crypto.c revision 1.2
1/*	$OpenBSD: crypto.c,v 1.2 1998/11/15 00:43:51 niklas Exp $	*/
2
3/*
4 * Copyright (c) 1998 Niels Provos.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *	This product includes software developed by Ericsson Radio Systems.
17 * 4. The name of the author may not be used to endorse or promote products
18 *    derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 * This code was written under funding by Ericsson Radio Systems.
34 */
35
36#include <sys/param.h>
37#include <stdlib.h>
38#include <string.h>
39
40#include "crypto.h"
41#include "log.h"
42
43enum cryptoerr des1_init (struct keystate *, u_int8_t *, u_int16_t);
44enum cryptoerr des3_init (struct keystate *, u_int8_t *, u_int16_t);
45enum cryptoerr blf_init (struct keystate *, u_int8_t *, u_int16_t);
46enum cryptoerr cast_init (struct keystate *, u_int8_t *, u_int16_t);
47void des1_encrypt (struct keystate *, u_int8_t *, u_int16_t);
48void des1_decrypt (struct keystate *, u_int8_t *, u_int16_t);
49void des3_encrypt (struct keystate *, u_int8_t *, u_int16_t);
50void des3_decrypt (struct keystate *, u_int8_t *, u_int16_t);
51void blf_encrypt (struct keystate *, u_int8_t *, u_int16_t);
52void blf_decrypt (struct keystate *, u_int8_t *, u_int16_t);
53void cast1_encrypt (struct keystate *, u_int8_t *, u_int16_t);
54void cast1_decrypt (struct keystate *, u_int8_t *, u_int16_t);
55
56struct crypto_xf transforms[] = {
57  {
58    DES_CBC, "Data Encryption Standard (CBC-Mode)", 8, 8, BLOCKSIZE, NULL,
59    des1_init,
60    des1_encrypt, des1_decrypt
61  },
62  {
63    TRIPLEDES_CBC, "Triple-DES (CBC-Mode)", 24, 24, BLOCKSIZE, NULL,
64    des3_init,
65    des3_encrypt, des3_decrypt
66  },
67  {
68    BLOWFISH_CBC, "Blowfish (CBC-Mode)", 12, 56, BLOCKSIZE, NULL,
69    blf_init,
70    blf_encrypt, blf_decrypt
71  },
72  {
73    CAST_CBC, "CAST (CBC-Mode)", 12, 16, BLOCKSIZE, NULL,
74    cast_init,
75    cast1_encrypt, cast1_decrypt
76  },
77};
78
79/* Hmm, the function prototypes for des are really dumb */
80#define DC	(des_cblock *)
81
82enum cryptoerr
83des1_init (struct keystate *ks, u_int8_t *key, u_int16_t len)
84{
85  /* des_set_key returns -1 for parity problems, and -2 for weak keys */
86  des_set_odd_parity (DC key);
87  switch (des_set_key (DC key, ks->ks_des[0]))
88    {
89    case -2:
90      return EWEAKKEY;
91    default:
92      return EOKAY;
93    }
94}
95
96void
97des1_encrypt (struct keystate *ks, u_int8_t *d, u_int16_t len)
98{
99  des_cbc_encrypt (DC d, DC d, len, ks->ks_des[0], DC ks->riv, DES_ENCRYPT);
100}
101
102void
103des1_decrypt (struct keystate *ks, u_int8_t *d, u_int16_t len)
104{
105  des_cbc_encrypt (DC d, DC d, len, ks->ks_des[0], DC ks->riv, DES_DECRYPT);
106}
107
108enum cryptoerr
109des3_init (struct keystate *ks, u_int8_t *key, u_int16_t len)
110{
111  des_set_odd_parity (DC key);
112  des_set_odd_parity (DC key + 1);
113  des_set_odd_parity (DC key + 2);
114
115  /* As of the draft Tripe-DES does not check for weak keys */
116  des_set_key (DC key, ks->ks_des[0]);
117  des_set_key (DC key + 1, ks->ks_des[1]);
118  des_set_key (DC key + 2, ks->ks_des[2]);
119
120  return EOKAY;
121}
122
123void
124des3_encrypt (struct keystate *ks, u_int8_t *data, u_int16_t len)
125{
126  u_int8_t iv[MAXBLK];
127
128  memcpy (iv, ks->riv, ks->xf->blocksize);
129  des_ede3_cbc_encrypt (DC data, DC data, len, ks->ks_des[0], ks->ks_des[1],
130			ks->ks_des[2], DC iv, DES_ENCRYPT);
131}
132
133void
134des3_decrypt (struct keystate *ks, u_int8_t *data, u_int16_t len)
135{
136  u_int8_t iv[MAXBLK];
137
138  memcpy (iv, ks->riv, ks->xf->blocksize);
139  des_ede3_cbc_encrypt (DC data, DC data, len, ks->ks_des[0], ks->ks_des[1],
140			ks->ks_des[2], DC iv, DES_DECRYPT);
141}
142#undef DC
143
144enum cryptoerr
145blf_init (struct keystate *ks, u_int8_t *key, u_int16_t len)
146{
147  blf_key (&ks->ks_blf, key, len);
148
149  return EOKAY;
150}
151
152void
153blf_encrypt (struct keystate *ks, u_int8_t *data, u_int16_t len)
154{
155  u_int16_t i, blocksize = ks->xf->blocksize;
156  u_int8_t *iv = ks->liv;
157  u_int32_t xl, xr;
158
159  memcpy (iv, ks->riv, blocksize);
160
161  for (i = 0; i < len; data += blocksize, i += blocksize)
162    {
163      XOR64 (data, iv);
164      xl = GET_32BIT_BIG (data);
165      xr = GET_32BIT_BIG (data + 4);
166      Blowfish_encipher (&ks->ks_blf, &xl, &xr);
167      SET_32BIT_BIG (data, xl);
168      SET_32BIT_BIG (data + 4, xr);
169      SET64 (iv, data);
170    }
171}
172
173void
174blf_decrypt (struct keystate *ks, u_int8_t *data, u_int16_t len)
175{
176  u_int16_t i, blocksize = ks->xf->blocksize;
177  u_int32_t xl, xr;
178
179  data += len - blocksize;
180  for (i = len - blocksize; i >= blocksize; data -= blocksize, i -= blocksize)
181    {
182      xl = GET_32BIT_BIG (data);
183      xr = GET_32BIT_BIG (data + 4);
184      Blowfish_decipher (&ks->ks_blf, &xl, &xr);
185      SET_32BIT_BIG (data, xl);
186      SET_32BIT_BIG (data + 4, xr);
187      XOR64 (data, data - blocksize);
188
189    }
190  xl = GET_32BIT_BIG (data);
191  xr = GET_32BIT_BIG (data + 4);
192  Blowfish_decipher (&ks->ks_blf, &xl, &xr);
193  SET_32BIT_BIG (data, xl);
194  SET_32BIT_BIG (data + 4, xr);
195  XOR64 (data, ks->riv);
196}
197
198enum cryptoerr
199cast_init (struct keystate *ks, u_int8_t *key, u_int16_t len)
200{
201  cast_setkey (&ks->ks_cast, key, len);
202  return EOKAY;
203}
204
205void
206cast1_encrypt (struct keystate *ks, u_int8_t *data, u_int16_t len)
207{
208  u_int16_t i, blocksize = ks->xf->blocksize;
209  u_int8_t *iv = ks->liv;
210
211  memcpy (iv, ks->riv, blocksize);
212
213  for (i = 0; i < len; data += blocksize, i += blocksize)
214    {
215      XOR64 (data, iv);
216      cast_encrypt (&ks->ks_cast, data, data);
217      SET64 (iv, data);
218    }
219}
220
221void
222cast1_decrypt (struct keystate *ks, u_int8_t *data, u_int16_t len)
223{
224  u_int16_t i, blocksize = ks->xf->blocksize;
225
226  data += len - blocksize;
227  for (i = len - blocksize; i >= blocksize; data -= blocksize, i -= blocksize)
228    {
229      cast_decrypt (&ks->ks_cast, data, data);
230      XOR64 (data, data - blocksize);
231    }
232  cast_decrypt (&ks->ks_cast, data, data);
233  XOR64 (data, ks->riv);
234}
235
236struct crypto_xf *
237crypto_get (enum transform id)
238{
239  int i;
240
241  for (i = 0; i < sizeof transforms / sizeof transforms[0]; i++)
242    if (id == transforms[i].id)
243      return &transforms[i];
244
245  return 0;
246}
247
248struct keystate *
249crypto_init (struct crypto_xf *xf, u_int8_t *key, u_int16_t len,
250	     enum cryptoerr *err)
251{
252  struct keystate *ks = NULL;
253
254  if (len < xf->keymin || len > xf->keymax)
255    {
256      log_debug (LOG_CRYPTO, 10, "crypto_init: invalid key length %d", len);
257      *err = EKEYLEN;
258      return NULL;
259    }
260
261  if ((ks = calloc (1, sizeof (struct keystate))) == NULL)
262    {
263      *err = ENOCRYPTO;
264      return NULL;
265    }
266
267  ks->xf = xf;
268
269  /* Set up the iv */
270  ks->riv = ks->iv;
271  ks->liv = ks->iv2;
272
273  log_debug_buf (LOG_CRYPTO, 40, "crypto_init: key", key, len);
274
275  *err = xf->init (ks, key, len);
276  if (*err != EOKAY)
277    {
278      log_debug (LOG_CRYPTO, 30, "crypto_init: weak key found for %s",
279		 xf->name);
280      free (ks);
281      return NULL;
282    }
283
284  return ks;
285}
286
287void
288crypto_update_iv (struct keystate *ks)
289{
290  u_int8_t *tmp;
291
292  tmp = ks->riv;
293  ks->riv = ks->liv;
294  ks->liv = tmp;
295
296  log_debug_buf (LOG_CRYPTO, 50, "crypto_update_iv: updated IV", ks->riv,
297		 ks->xf->blocksize);
298}
299
300void
301crypto_init_iv (struct keystate *ks, u_int8_t *buf, size_t len)
302{
303  memcpy (ks->riv, buf, len);
304
305  log_debug_buf (LOG_CRYPTO, 50, "crypto_update_iv: initialized IV", ks->riv,
306		 len);
307}
308
309void
310crypto_encrypt (struct keystate *ks, u_int8_t *buf, u_int16_t len)
311{
312  log_debug_buf (LOG_CRYPTO, 10, "crypto_encrypt: before encryption", buf,
313		 len);
314  ks->xf->encrypt (ks, buf, len);
315  memcpy (ks->liv, buf + len - ks->xf->blocksize, ks->xf->blocksize);
316  log_debug_buf (LOG_CRYPTO, 30, "crypto_encrypt: after encryption", buf,
317		 len);
318}
319
320void
321crypto_decrypt (struct keystate *ks, u_int8_t *buf, u_int16_t len)
322{
323  log_debug_buf (LOG_CRYPTO, 10, "crypto_decrypt: before decryption", buf,
324		 len);
325  /*
326   * XXX There is controversy about the correctness of updating the IV
327   * like this.
328   */
329  memcpy (ks->liv, buf + len - ks->xf->blocksize, ks->xf->blocksize);
330  ks->xf->decrypt (ks, buf, len);;
331  log_debug_buf (LOG_CRYPTO, 30, "crypto_decrypt: after decryption", buf,
332		 len);
333}
334
335struct keystate *
336crypto_clone_keystate (struct keystate *oks)
337{
338  struct keystate *ks;
339
340  ks = malloc (sizeof *ks);
341  if (!ks)
342    return 0;
343  memcpy (ks, oks, sizeof *ks);
344  if (oks->riv == oks->iv)
345    {
346      ks->riv = ks->iv;
347      ks->liv = ks->iv2;
348    }
349  else
350    {
351      ks->riv = ks->iv2;
352      ks->liv = ks->iv;
353    }
354  return ks;
355}
356