]>
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 | |
5260325f | 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 | ||
124 | /* Names of all encryption algorithms. These must match the numbers defined | |
125 | int cipher.h. */ | |
126 | static char *cipher_names[] = | |
127 | { | |
5260325f | 128 | "none", |
129 | "idea", | |
130 | "des", | |
131 | "3des", | |
132 | "tss", | |
133 | "rc4", | |
134 | "blowfish" | |
8efc0c15 | 135 | }; |
136 | ||
137 | /* Returns a bit mask indicating which ciphers are supported by this | |
138 | implementation. The bit mask has the corresponding bit set of each | |
139 | supported cipher. */ | |
140 | ||
5260325f | 141 | unsigned int |
142 | cipher_mask() | |
8efc0c15 | 143 | { |
5260325f | 144 | unsigned int mask = 0; |
145 | mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */ | |
146 | mask |= 1 << SSH_CIPHER_BLOWFISH; | |
147 | return mask; | |
8efc0c15 | 148 | } |
149 | ||
150 | /* Returns the name of the cipher. */ | |
151 | ||
5260325f | 152 | const char * |
153 | cipher_name(int cipher) | |
8efc0c15 | 154 | { |
5260325f | 155 | if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]) || |
156 | cipher_names[cipher] == NULL) | |
157 | fatal("cipher_name: bad cipher number: %d", cipher); | |
158 | return cipher_names[cipher]; | |
8efc0c15 | 159 | } |
160 | ||
161 | /* Parses the name of the cipher. Returns the number of the corresponding | |
162 | cipher, or -1 on error. */ | |
163 | ||
164 | int | |
165 | cipher_number(const char *name) | |
166 | { | |
5260325f | 167 | int i; |
168 | for (i = 0; i < sizeof(cipher_names) / sizeof(cipher_names[0]); i++) | |
169 | if (strcmp(cipher_names[i], name) == 0 && | |
170 | (cipher_mask() & (1 << i))) | |
171 | return i; | |
172 | return -1; | |
8efc0c15 | 173 | } |
174 | ||
175 | /* Selects the cipher, and keys if by computing the MD5 checksum of the | |
176 | passphrase and using the resulting 16 bytes as the key. */ | |
177 | ||
5260325f | 178 | void |
179 | cipher_set_key_string(CipherContext *context, int cipher, | |
180 | const char *passphrase, int for_encryption) | |
8efc0c15 | 181 | { |
5260325f | 182 | MD5_CTX md; |
183 | unsigned char digest[16]; | |
184 | ||
185 | MD5_Init(&md); | |
186 | MD5_Update(&md, (const unsigned char *) passphrase, strlen(passphrase)); | |
187 | MD5_Final(digest, &md); | |
188 | ||
189 | cipher_set_key(context, cipher, digest, 16, for_encryption); | |
190 | ||
191 | memset(digest, 0, sizeof(digest)); | |
192 | memset(&md, 0, sizeof(md)); | |
8efc0c15 | 193 | } |
194 | ||
195 | /* Selects the cipher to use and sets the key. */ | |
196 | ||
5260325f | 197 | void |
198 | cipher_set_key(CipherContext *context, int cipher, | |
199 | const unsigned char *key, int keylen, int for_encryption) | |
8efc0c15 | 200 | { |
5260325f | 201 | unsigned char padded[32]; |
202 | ||
203 | /* Set cipher type. */ | |
204 | context->type = cipher; | |
205 | ||
206 | /* Get 32 bytes of key data. Pad if necessary. (So that code | |
207 | below does not need to worry about key size). */ | |
208 | memset(padded, 0, sizeof(padded)); | |
209 | memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded)); | |
210 | ||
211 | /* Initialize the initialization vector. */ | |
212 | switch (cipher) { | |
213 | case SSH_CIPHER_NONE: | |
214 | /* Has to stay for authfile saving of private key with | |
215 | no passphrase */ | |
216 | break; | |
217 | ||
218 | case SSH_CIPHER_3DES: | |
219 | /* Note: the least significant bit of each byte of key is | |
220 | parity, and must be ignored by the implementation. 16 | |
221 | bytes of key are used (first and last keys are the | |
222 | same). */ | |
223 | if (keylen < 16) | |
224 | error("Key length %d is insufficient for 3DES.", keylen); | |
225 | des_set_key((void *) padded, context->u.des3.key1); | |
226 | des_set_key((void *) (padded + 8), context->u.des3.key2); | |
227 | if (keylen <= 16) | |
228 | des_set_key((void *) padded, context->u.des3.key3); | |
229 | else | |
230 | des_set_key((void *) (padded + 16), context->u.des3.key3); | |
231 | memset(context->u.des3.iv2, 0, sizeof(context->u.des3.iv2)); | |
232 | memset(context->u.des3.iv3, 0, sizeof(context->u.des3.iv3)); | |
233 | break; | |
234 | ||
235 | case SSH_CIPHER_BLOWFISH: | |
236 | BF_set_key(&context->u.bf.key, keylen, padded); | |
237 | memset(context->u.bf.iv, 0, 8); | |
238 | break; | |
239 | ||
240 | default: | |
241 | fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher)); | |
242 | } | |
243 | memset(padded, 0, sizeof(padded)); | |
8efc0c15 | 244 | } |
245 | ||
246 | /* Encrypts data using the cipher. */ | |
247 | ||
5260325f | 248 | void |
249 | cipher_encrypt(CipherContext *context, unsigned char *dest, | |
250 | const unsigned char *src, unsigned int len) | |
8efc0c15 | 251 | { |
5260325f | 252 | if ((len & 7) != 0) |
253 | fatal("cipher_encrypt: bad plaintext length %d", len); | |
254 | ||
255 | switch (context->type) { | |
256 | case SSH_CIPHER_NONE: | |
257 | memcpy(dest, src, len); | |
258 | break; | |
259 | ||
260 | case SSH_CIPHER_3DES: | |
261 | SSH_3CBC_ENCRYPT(context->u.des3.key1, | |
262 | context->u.des3.key2, &context->u.des3.iv2, | |
263 | context->u.des3.key3, &context->u.des3.iv3, | |
264 | dest, (void *) src, len); | |
265 | break; | |
266 | ||
267 | case SSH_CIPHER_BLOWFISH: | |
268 | swap_bytes(src, dest, len); | |
269 | BF_cbc_encrypt(dest, dest, len, | |
270 | &context->u.bf.key, context->u.bf.iv, | |
271 | BF_ENCRYPT); | |
272 | swap_bytes(dest, dest, len); | |
273 | break; | |
274 | ||
275 | default: | |
276 | fatal("cipher_encrypt: unknown cipher: %s", cipher_name(context->type)); | |
277 | } | |
8efc0c15 | 278 | } |
5260325f | 279 | |
8efc0c15 | 280 | /* Decrypts data using the cipher. */ |
281 | ||
5260325f | 282 | void |
283 | cipher_decrypt(CipherContext *context, unsigned char *dest, | |
284 | const unsigned char *src, unsigned int len) | |
8efc0c15 | 285 | { |
5260325f | 286 | if ((len & 7) != 0) |
287 | fatal("cipher_decrypt: bad ciphertext length %d", len); | |
288 | ||
289 | switch (context->type) { | |
290 | case SSH_CIPHER_NONE: | |
291 | memcpy(dest, src, len); | |
292 | break; | |
293 | ||
294 | case SSH_CIPHER_3DES: | |
295 | /* CRC-32 attack? */ | |
296 | SSH_3CBC_DECRYPT(context->u.des3.key1, | |
297 | context->u.des3.key2, &context->u.des3.iv2, | |
298 | context->u.des3.key3, &context->u.des3.iv3, | |
299 | dest, (void *) src, len); | |
300 | break; | |
301 | ||
302 | case SSH_CIPHER_BLOWFISH: | |
303 | detect_cbc_attack(src, len); | |
304 | swap_bytes(src, dest, len); | |
305 | BF_cbc_encrypt((void *) dest, dest, len, | |
306 | &context->u.bf.key, context->u.bf.iv, | |
307 | BF_DECRYPT); | |
308 | swap_bytes(dest, dest, len); | |
309 | break; | |
310 | ||
311 | default: | |
312 | fatal("cipher_decrypt: unknown cipher: %s", cipher_name(context->type)); | |
313 | } | |
8efc0c15 | 314 | } |