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