source: trunk/third/ssh/cipher.c @ 12646

Revision 12646, 9.4 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12645, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2
3cipher.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8                   All rights reserved
9
10Created: Wed Apr 19 17:41:39 1995 ylo
11
12*/
13
14/*
15 * $Id: cipher.c,v 1.1.1.3 1999-03-08 17:43:18 danw Exp $
16 * $Log: not supported by cvs2svn $
17 * Revision 1.12  1998/05/23  20:21:09  kivinen
18 *      Changed () -> (void).
19 *
20 * Revision 1.11  1998/04/30  01:51:32  kivinen
21 *      Reserved cipher number 7 to Bernard Perrot
22 *      <perrot@lal.in2p3.fr> for some weak 40 bit encryption method.
23 *
24 * Revision 1.10  1998/03/27 17:23:43  kivinen
25 *      Removed TSS.
26 *
27 * Revision 1.9  1997/03/26 07:03:04  kivinen
28 *      Added check that warning about arcfour is given only once.
29 *
30 * Revision 1.8  1997/03/25 05:38:50  kivinen
31 *      #ifndef WITH_IDEA -> #ifdef WITH_IDEA.
32 *
33 * Revision 1.7  1997/03/19 22:26:38  kivinen
34 *      Removed WITH_3DES ifdefs, as it is mandatory.
35 *
36 * Revision 1.6  1997/03/19 22:17:11  kivinen
37 *      Enabled none encryption internally anyway, because it is
38 *      required to read host keys.
39 *
40 * Revision 1.5  1997/03/19 21:29:45  kivinen
41 *      Added missing }.
42 *
43 * Revision 1.4  1997/03/19 17:34:56  kivinen
44 *      Made all ciphers optional.
45 *
46 * Revision 1.3  1996/09/28 12:01:04  ylo
47 *      Removed TSS (put inside #ifdef WITH_TSS).
48 *
49 * Revision 1.2  1996/09/27 13:55:02  ttsalo
50 *      Added blowfish
51 *
52 * Revision 1.1.1.1  1996/02/18 21:38:11  ylo
53 *      Imported ssh-1.2.13.
54 *
55 * Revision 1.3  1995/08/18  22:48:01  ylo
56 *      Added code to permit compiling without idea.
57 *
58 *      With triple-des, if the key length is only 16 bytes, reuse the
59 *      beginning of the key for the third DES key.
60 *
61 * Revision 1.2  1995/07/13  01:19:45  ylo
62 *      Removed "Last modified" header.
63 *      Added cvs log.
64 *
65 * $Endlog$
66 */
67
68#include "includes.h"
69#include "ssh.h"
70#include "cipher.h"
71
72/* Names of all encryption algorithms.  These must match the numbers defined
73   int cipher.h. */
74static char *cipher_names[] =
75{ "none", "idea", "des", "3des", "used to be tss", "arcfour", "blowfish",
76  "reserved"};
77
78/* Returns a bit mask indicating which ciphers are supported by this
79   implementation.  The bit mask has the corresponding bit set of each
80   supported cipher. */
81
82unsigned int cipher_mask(void)
83{
84  unsigned int mask = 0;
85 
86#ifdef WITH_NONE
87  mask |= 1 << SSH_CIPHER_NONE;
88#endif /* WITH_NONE */
89 
90#ifdef WITH_IDEA
91  mask |= 1 << SSH_CIPHER_IDEA;
92#endif /* WITH_IDEA */
93 
94#ifdef WITH_DES
95  mask |= 1 << SSH_CIPHER_DES;
96#endif /* WITH_DES */
97
98  mask |= 1 << SSH_CIPHER_3DES;
99 
100#ifdef WITH_ARCFOUR
101  mask |= 1 << SSH_CIPHER_ARCFOUR;
102#endif /* WITH_ARCFOUR */
103 
104#ifdef WITH_BLOWFISH
105  mask |= 1 << SSH_CIPHER_BLOWFISH;
106#endif /* WITH_BLOWFISH */
107  return mask;
108}
109
110/* Returns the name of the cipher. */
111
112const char *cipher_name(int cipher)
113{
114  if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]))
115    fatal("cipher_name: bad cipher number: %d", cipher);
116  return cipher_names[cipher];
117}
118
119/* Parses the name of the cipher.  Returns the number of the corresponding
120   cipher, or -1 on error. */
121
122int cipher_number(const char *name)
123{
124  int i;
125  static int warning_given = 0;
126
127  /* Recognize other nam for backward compatibility. */
128  if (name[0] == 'r' && name[1] == 'c' && name[2] == '4' && name[3] == '\0')
129    {
130#if defined(WITH_ARCFOUR) || !defined(WITH_BLOWFISH)
131      return SSH_CIPHER_ARCFOUR;
132#else
133      if (!warning_given)
134        log_msg("Arcfour cipher is disabled in this host, using blowfish cipher instead");
135      warning_given = 1;
136      return SSH_CIPHER_BLOWFISH;
137#endif
138    }
139
140  for (i = 0; i < sizeof(cipher_names) / sizeof(cipher_names[0]); i++)
141    if (strcmp(cipher_names[i], name) == 0)
142      {
143#if !defined(WITH_ARCFOUR) && defined(WITH_BLOWFISH)
144        if (i == SSH_CIPHER_ARCFOUR)
145          {
146            if (!warning_given)
147              log_msg("Arcfour cipher is disabled in this host, using blowfish cipher instead");
148            warning_given = 1;
149            return SSH_CIPHER_BLOWFISH;
150          }
151#endif
152        return i;
153      }
154  return -1;
155}
156
157/* Selects the cipher, and keys if by computing the MD5 checksum of the
158   passphrase and using the resulting 16 bytes as the key. */
159
160void cipher_set_key_string(CipherContext *context, int cipher,
161                           const char *passphrase, int for_encryption)
162{
163  struct MD5Context md;
164  unsigned char digest[16];
165 
166  MD5Init(&md);
167  MD5Update(&md, (const unsigned char *)passphrase, strlen(passphrase));
168  MD5Final(digest, &md);
169
170  cipher_set_key(context, cipher, digest, 16, for_encryption);
171 
172  memset(digest, 0, sizeof(digest));
173  memset(&md, 0, sizeof(md));
174}
175
176/* Selects the cipher to use and sets the key. */
177
178void cipher_set_key(CipherContext *context, int cipher,
179                    const unsigned char *key, int keylen, int for_encryption)
180{
181  unsigned char padded[32];
182
183  /* Clear the context to remove any traces of old keys. */
184  memset(context, 0, sizeof(*context));
185
186  /* Set cipher type. */
187  context->type = cipher;
188
189  /* Get 32 bytes of key data.  Pad if necessary.  (So that code below does
190     not need to worry about key size). */
191  memset(padded, 0, sizeof(padded));
192  memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded));
193
194  /* Initialize the initialization vector. */
195  switch (cipher)
196    {
197    case SSH_CIPHER_NONE:
198      break;
199
200#ifdef WITH_IDEA
201    case SSH_CIPHER_IDEA:
202      if (keylen < 16)
203        error("Key length %d is insufficient for IDEA.", keylen);
204      idea_set_key(&context->u.idea.key, padded);
205      memset(context->u.idea.iv, 0, sizeof(context->u.idea.iv));
206      break;
207#endif /* WITH_IDEA */
208
209#ifdef WITH_DES
210    case SSH_CIPHER_DES:
211      /* Note: the least significant bit of each byte of key is parity,
212         and must be ignored by the implementation.  8 bytes of key are
213         used. */
214      if (keylen < 8)
215        error("Key length %d is insufficient for DES.", keylen);
216      des_set_key(padded, &context->u.des.key);
217      memset(context->u.des.iv, 0, sizeof(context->u.des.iv));
218      break;
219#endif /* WITH_DES */
220
221    case SSH_CIPHER_3DES:
222      /* Note: the least significant bit of each byte of key is parity,
223         and must be ignored by the implementation.  16 bytes of key are
224         used (first and last keys are the same). */
225      if (keylen < 16)
226        error("Key length %d is insufficient for 3DES.", keylen);
227      des_set_key(padded, &context->u.des3.key1);
228      des_set_key(padded + 8, &context->u.des3.key2);
229      if (keylen <= 16)
230        des_set_key(padded, &context->u.des3.key3);
231      else
232        des_set_key(padded + 16, &context->u.des3.key3);
233      memset(context->u.des3.iv1, 0, sizeof(context->u.des3.iv1));
234      memset(context->u.des3.iv2, 0, sizeof(context->u.des3.iv2));
235      memset(context->u.des3.iv3, 0, sizeof(context->u.des3.iv3));
236      break;
237
238#ifdef WITH_ARCFOUR
239    case SSH_CIPHER_ARCFOUR:
240      arcfour_init(&context->u.arcfour, key, keylen);
241      break;
242#endif /* WITH_ARCFOUR */
243
244#ifdef WITH_BLOWFISH
245    case SSH_CIPHER_BLOWFISH:
246      if (keylen < 8)
247        error("Key length %d is insufficient for Blowfish", keylen);
248      blowfish_set_key(&context->u.blowfish, key, keylen, for_encryption);
249      break;
250#endif /* WITH_BLOWFISH */
251    default:
252      fatal("cipher_set_key: unknown cipher: %d", cipher);
253    }
254  memset(padded, 0, sizeof(padded));
255}
256
257/* Encrypts data using the cipher. */
258
259void cipher_encrypt(CipherContext *context, unsigned char *dest,
260                    const unsigned char *src, unsigned int len)
261{
262  switch (context->type)
263    {
264    case SSH_CIPHER_NONE:
265      memcpy(dest, src, len);
266      break;
267
268#ifdef WITH_IDEA
269    case SSH_CIPHER_IDEA:
270      idea_cfb_encrypt(&context->u.idea.key, context->u.idea.iv,
271                       dest, src, len);
272      break;
273#endif /* WITH_IDEA */
274
275#ifdef WITH_DES
276    case SSH_CIPHER_DES:
277      des_cbc_encrypt(&context->u.des.key, context->u.des.iv, dest, src, len);
278      break;
279#endif /* WITH_DES */
280
281    case SSH_CIPHER_3DES:
282      des_3cbc_encrypt(&context->u.des3.key1, context->u.des3.iv1,
283                       &context->u.des3.key2, context->u.des3.iv2,
284                       &context->u.des3.key3, context->u.des3.iv3,
285                       dest, src, len);
286      break;
287
288#ifdef WITH_ARCFOUR
289    case SSH_CIPHER_ARCFOUR:
290      arcfour_encrypt(&context->u.arcfour, dest, src, len);
291      break;
292#endif /* WITH_ARCFOUR */
293
294#ifdef WITH_BLOWFISH
295    case SSH_CIPHER_BLOWFISH:
296      blowfish_cbc_encrypt(&context->u.blowfish, dest, src, len);
297      break;
298#endif /* WITH_BLOWFISH */
299     
300    default:
301      fatal("cipher_encrypt: unknown cipher: %d", context->type);
302    }
303}
304 
305/* Decrypts data using the cipher. */
306
307void cipher_decrypt(CipherContext *context, unsigned char *dest,
308                    const unsigned char *src, unsigned int len)
309{
310  switch (context->type)
311    {
312    case SSH_CIPHER_NONE:
313      memcpy(dest, src, len);
314      break;
315
316#ifdef WITH_IDEA
317    case SSH_CIPHER_IDEA:
318      idea_cfb_decrypt(&context->u.idea.key, context->u.idea.iv,
319                       dest, src, len);
320      break;
321#endif /* WITH_IDEA */
322
323#ifdef WITH_DES
324    case SSH_CIPHER_DES:
325      des_cbc_decrypt(&context->u.des.key, context->u.des.iv, dest, src, len);
326      break;
327#endif /* WITH_DES */
328
329    case SSH_CIPHER_3DES:
330      des_3cbc_decrypt(&context->u.des3.key1, context->u.des3.iv1,
331                       &context->u.des3.key2, context->u.des3.iv2,
332                       &context->u.des3.key3, context->u.des3.iv3,
333                       dest, src, len);
334      break;
335
336#ifdef WITH_ARCFOUR
337    case SSH_CIPHER_ARCFOUR:
338      arcfour_decrypt(&context->u.arcfour, dest, src, len);
339      break;
340#endif /* WITH_ARCFOUR */
341
342#ifdef WITH_BLOWFISH
343    case SSH_CIPHER_BLOWFISH:
344      blowfish_cbc_decrypt(&context->u.blowfish, dest, src, len);
345      break;
346#endif /* WITH_BLOWFISH */
347     
348    default:
349      fatal("cipher_decrypt: unknown cipher: %d", context->type);
350    }
351}
Note: See TracBrowser for help on using the repository browser.