]>
Commit | Line | Data |
---|---|---|
8efc0c15 | 1 | /* |
5260325f | 2 | * |
3 | * cipher.c | |
4 | * | |
5 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | |
6 | * | |
7 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | |
8 | * All rights reserved | |
9 | * | |
10 | * Created: Wed Apr 19 17:41:39 1995 ylo | |
11 | * | |
12 | */ | |
8efc0c15 | 13 | |
14 | #include "includes.h" | |
15 | RCSID("$Id$"); | |
16 | ||
17 | #include "ssh.h" | |
18 | #include "cipher.h" | |
19 | ||
5881cd60 | 20 | #ifdef HAVE_OPENSSL |
8efc0c15 | 21 | #include <openssl/md5.h> |
5881cd60 | 22 | #endif |
23 | #ifdef HAVE_SSL | |
24 | #include <ssl/md5.h> | |
25 | #endif | |
8efc0c15 | 26 | |
27 | /* | |
28 | * What kind of tripple DES are these 2 routines? | |
29 | * | |
30 | * Why is there a redundant initialization vector? | |
31 | * | |
32 | * If only iv3 was used, then, this would till effect have been | |
33 | * outer-cbc. However, there is also a private iv1 == iv2 which | |
34 | * perhaps makes differential analysis easier. On the other hand, the | |
35 | * private iv1 probably makes the CRC-32 attack ineffective. This is a | |
36 | * result of that there is no longer any known iv1 to use when | |
37 | * choosing the X block. | |
38 | */ | |
39 | void | |
40 | SSH_3CBC_ENCRYPT(des_key_schedule ks1, | |
5260325f | 41 | des_key_schedule ks2, des_cblock * iv2, |
42 | des_key_schedule ks3, des_cblock * iv3, | |
8efc0c15 | 43 | void *dest, void *src, |
44 | unsigned int len) | |
45 | { | |
5260325f | 46 | des_cblock iv1; |
8efc0c15 | 47 | |
5260325f | 48 | memcpy(&iv1, iv2, 8); |
8efc0c15 | 49 | |
5260325f | 50 | des_cbc_encrypt(src, dest, len, ks1, &iv1, DES_ENCRYPT); |
51 | memcpy(&iv1, dest + len - 8, 8); | |
8efc0c15 | 52 | |
5260325f | 53 | des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_DECRYPT); |
54 | memcpy(iv2, &iv1, 8); /* Note how iv1 == iv2 on entry and exit. */ | |
8efc0c15 | 55 | |
5260325f | 56 | des_cbc_encrypt(dest, dest, len, ks3, iv3, DES_ENCRYPT); |
57 | memcpy(iv3, dest + len - 8, 8); | |
8efc0c15 | 58 | } |
59 | ||
60 | void | |
61 | SSH_3CBC_DECRYPT(des_key_schedule ks1, | |
5260325f | 62 | des_key_schedule ks2, des_cblock * iv2, |
63 | des_key_schedule ks3, des_cblock * iv3, | |
8efc0c15 | 64 | void *dest, void *src, |
65 | unsigned int len) | |
66 | { | |
5260325f | 67 | des_cblock iv1; |
8efc0c15 | 68 | |
5260325f | 69 | memcpy(&iv1, iv2, 8); |
8efc0c15 | 70 | |
5260325f | 71 | des_cbc_encrypt(src, dest, len, ks3, iv3, DES_DECRYPT); |
72 | memcpy(iv3, src + len - 8, 8); | |
8efc0c15 | 73 | |
5260325f | 74 | des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_ENCRYPT); |
75 | memcpy(iv2, dest + len - 8, 8); | |
8efc0c15 | 76 | |
5260325f | 77 | des_cbc_encrypt(dest, dest, len, ks1, &iv1, DES_DECRYPT); |
78 | /* memcpy(&iv1, iv2, 8); */ | |
79 | /* Note how iv1 == iv2 on entry and exit. */ | |
8efc0c15 | 80 | } |
81 | ||
82 | /* | |
83 | * SSH uses a variation on Blowfish, all bytes must be swapped before | |
84 | * and after encryption/decryption. Thus the swap_bytes stuff (yuk). | |
85 | */ | |
5260325f | 86 | static void |
8efc0c15 | 87 | swap_bytes(const unsigned char *src, unsigned char *dst_, int n) |
88 | { | |
5260325f | 89 | /* dst must be properly aligned. */ |
90 | u_int32_t *dst = (u_int32_t *) dst_; | |
91 | union { | |
92 | u_int32_t i; | |
93 | char c[4]; | |
94 | } t; | |
95 | ||
96 | /* Process 8 bytes every lap. */ | |
97 | for (n = n / 8; n > 0; n--) { | |
98 | t.c[3] = *src++; | |
99 | t.c[2] = *src++; | |
100 | t.c[1] = *src++; | |
101 | t.c[0] = *src++; | |
102 | *dst++ = t.i; | |
103 | ||
104 | t.c[3] = *src++; | |
105 | t.c[2] = *src++; | |
106 | t.c[1] = *src++; | |
107 | t.c[0] = *src++; | |
108 | *dst++ = t.i; | |
109 | } | |
8efc0c15 | 110 | } |
111 | ||
5260325f | 112 | void (*cipher_attack_detected) (const char *fmt,...) = fatal; |
8efc0c15 | 113 | |
847e8865 | 114 | static INLINE void |
8efc0c15 | 115 | detect_cbc_attack(const unsigned char *src, |
116 | unsigned int len) | |
117 | { | |
5260325f | 118 | return; |
119 | ||
120 | log("CRC-32 CBC insertion attack detected"); | |
121 | cipher_attack_detected("CRC-32 CBC insertion attack detected"); | |
8efc0c15 | 122 | } |
123 | ||
aa3378df | 124 | /* |
125 | * Names of all encryption algorithms. | |
126 | * These must match the numbers defined in cipher.h. | |
127 | */ | |
8efc0c15 | 128 | static char *cipher_names[] = |
129 | { | |
5260325f | 130 | "none", |
131 | "idea", | |
132 | "des", | |
133 | "3des", | |
134 | "tss", | |
135 | "rc4", | |
136 | "blowfish" | |
8efc0c15 | 137 | }; |
138 | ||
aa3378df | 139 | /* |
140 | * Returns a bit mask indicating which ciphers are supported by this | |
141 | * implementation. The bit mask has the corresponding bit set of each | |
142 | * supported cipher. | |
143 | */ | |
8efc0c15 | 144 | |
5260325f | 145 | unsigned int |
146 | cipher_mask() | |
8efc0c15 | 147 | { |
5260325f | 148 | unsigned int mask = 0; |
149 | mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */ | |
150 | mask |= 1 << SSH_CIPHER_BLOWFISH; | |
151 | return mask; | |
8efc0c15 | 152 | } |
153 | ||
154 | /* Returns the name of the cipher. */ | |
155 | ||
5260325f | 156 | const char * |
157 | cipher_name(int cipher) | |
8efc0c15 | 158 | { |
5260325f | 159 | if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]) || |
160 | cipher_names[cipher] == NULL) | |
161 | fatal("cipher_name: bad cipher number: %d", cipher); | |
162 | return cipher_names[cipher]; | |
8efc0c15 | 163 | } |
164 | ||
aa3378df | 165 | /* |
166 | * Parses the name of the cipher. Returns the number of the corresponding | |
167 | * cipher, or -1 on error. | |
168 | */ | |
8efc0c15 | 169 | |
170 | int | |
171 | cipher_number(const char *name) | |
172 | { | |
5260325f | 173 | int i; |
174 | for (i = 0; i < sizeof(cipher_names) / sizeof(cipher_names[0]); i++) | |
175 | if (strcmp(cipher_names[i], name) == 0 && | |
176 | (cipher_mask() & (1 << i))) | |
177 | return i; | |
178 | return -1; | |
8efc0c15 | 179 | } |
180 | ||
aa3378df | 181 | /* |
182 | * Selects the cipher, and keys if by computing the MD5 checksum of the | |
183 | * passphrase and using the resulting 16 bytes as the key. | |
184 | */ | |
8efc0c15 | 185 | |
5260325f | 186 | void |
187 | cipher_set_key_string(CipherContext *context, int cipher, | |
188 | const char *passphrase, int for_encryption) | |
8efc0c15 | 189 | { |
5260325f | 190 | MD5_CTX md; |
191 | unsigned char digest[16]; | |
192 | ||
193 | MD5_Init(&md); | |
194 | MD5_Update(&md, (const unsigned char *) passphrase, strlen(passphrase)); | |
195 | MD5_Final(digest, &md); | |
196 | ||
197 | cipher_set_key(context, cipher, digest, 16, for_encryption); | |
198 | ||
199 | memset(digest, 0, sizeof(digest)); | |
200 | memset(&md, 0, sizeof(md)); | |
8efc0c15 | 201 | } |
202 | ||
203 | /* Selects the cipher to use and sets the key. */ | |
204 | ||
5260325f | 205 | void |
206 | cipher_set_key(CipherContext *context, int cipher, | |
207 | const unsigned char *key, int keylen, int for_encryption) | |
8efc0c15 | 208 | { |
5260325f | 209 | unsigned char padded[32]; |
210 | ||
211 | /* Set cipher type. */ | |
212 | context->type = cipher; | |
213 | ||
214 | /* Get 32 bytes of key data. Pad if necessary. (So that code | |
215 | below does not need to worry about key size). */ | |
216 | memset(padded, 0, sizeof(padded)); | |
217 | memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded)); | |
218 | ||
219 | /* Initialize the initialization vector. */ | |
220 | switch (cipher) { | |
221 | case SSH_CIPHER_NONE: | |
aa3378df | 222 | /* |
223 | * Has to stay for authfile saving of private key with no | |
224 | * passphrase | |
225 | */ | |
5260325f | 226 | break; |
227 | ||
228 | case SSH_CIPHER_3DES: | |
aa3378df | 229 | /* |
230 | * Note: the least significant bit of each byte of key is | |
231 | * parity, and must be ignored by the implementation. 16 | |
232 | * bytes of key are used (first and last keys are the same). | |
233 | */ | |
5260325f | 234 | if (keylen < 16) |
235 | error("Key length %d is insufficient for 3DES.", keylen); | |
236 | des_set_key((void *) padded, context->u.des3.key1); | |
237 | des_set_key((void *) (padded + 8), context->u.des3.key2); | |
238 | if (keylen <= 16) | |
239 | des_set_key((void *) padded, context->u.des3.key3); | |
240 | else | |
241 | des_set_key((void *) (padded + 16), context->u.des3.key3); | |
242 | memset(context->u.des3.iv2, 0, sizeof(context->u.des3.iv2)); | |
243 | memset(context->u.des3.iv3, 0, sizeof(context->u.des3.iv3)); | |
244 | break; | |
245 | ||
246 | case SSH_CIPHER_BLOWFISH: | |
247 | BF_set_key(&context->u.bf.key, keylen, padded); | |
248 | memset(context->u.bf.iv, 0, 8); | |
249 | break; | |
250 | ||
251 | default: | |
252 | fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher)); | |
253 | } | |
254 | memset(padded, 0, sizeof(padded)); | |
8efc0c15 | 255 | } |
256 | ||
257 | /* Encrypts data using the cipher. */ | |
258 | ||
5260325f | 259 | void |
260 | cipher_encrypt(CipherContext *context, unsigned char *dest, | |
261 | const unsigned char *src, unsigned int len) | |
8efc0c15 | 262 | { |
5260325f | 263 | if ((len & 7) != 0) |
264 | fatal("cipher_encrypt: bad plaintext length %d", len); | |
265 | ||
266 | switch (context->type) { | |
267 | case SSH_CIPHER_NONE: | |
268 | memcpy(dest, src, len); | |
269 | break; | |
270 | ||
271 | case SSH_CIPHER_3DES: | |
272 | SSH_3CBC_ENCRYPT(context->u.des3.key1, | |
273 | context->u.des3.key2, &context->u.des3.iv2, | |
274 | context->u.des3.key3, &context->u.des3.iv3, | |
275 | dest, (void *) src, len); | |
276 | break; | |
277 | ||
278 | case SSH_CIPHER_BLOWFISH: | |
279 | swap_bytes(src, dest, len); | |
280 | BF_cbc_encrypt(dest, dest, len, | |
281 | &context->u.bf.key, context->u.bf.iv, | |
282 | BF_ENCRYPT); | |
283 | swap_bytes(dest, dest, len); | |
284 | break; | |
285 | ||
286 | default: | |
287 | fatal("cipher_encrypt: unknown cipher: %s", cipher_name(context->type)); | |
288 | } | |
8efc0c15 | 289 | } |
5260325f | 290 | |
8efc0c15 | 291 | /* Decrypts data using the cipher. */ |
292 | ||
5260325f | 293 | void |
294 | cipher_decrypt(CipherContext *context, unsigned char *dest, | |
295 | const unsigned char *src, unsigned int len) | |
8efc0c15 | 296 | { |
5260325f | 297 | if ((len & 7) != 0) |
298 | fatal("cipher_decrypt: bad ciphertext length %d", len); | |
299 | ||
300 | switch (context->type) { | |
301 | case SSH_CIPHER_NONE: | |
302 | memcpy(dest, src, len); | |
303 | break; | |
304 | ||
305 | case SSH_CIPHER_3DES: | |
306 | /* CRC-32 attack? */ | |
307 | SSH_3CBC_DECRYPT(context->u.des3.key1, | |
308 | context->u.des3.key2, &context->u.des3.iv2, | |
309 | context->u.des3.key3, &context->u.des3.iv3, | |
310 | dest, (void *) src, len); | |
311 | break; | |
312 | ||
313 | case SSH_CIPHER_BLOWFISH: | |
314 | detect_cbc_attack(src, len); | |
315 | swap_bytes(src, dest, len); | |
316 | BF_cbc_encrypt((void *) dest, dest, len, | |
317 | &context->u.bf.key, context->u.bf.iv, | |
318 | BF_DECRYPT); | |
319 | swap_bytes(dest, dest, len); | |
320 | break; | |
321 | ||
322 | default: | |
323 | fatal("cipher_decrypt: unknown cipher: %s", cipher_name(context->type)); | |
324 | } | |
8efc0c15 | 325 | } |