]>
Commit | Line | Data |
---|---|---|
8efc0c15 | 1 | /* |
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 | */ | |
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, | |
41 | des_key_schedule ks2, des_cblock *iv2, | |
42 | des_key_schedule ks3, des_cblock *iv3, | |
43 | void *dest, void *src, | |
44 | unsigned int len) | |
45 | { | |
46 | des_cblock iv1; | |
47 | ||
48 | memcpy(&iv1, iv2, 8); | |
49 | ||
50 | des_cbc_encrypt(src, dest, len, ks1, &iv1, DES_ENCRYPT); | |
51 | memcpy(&iv1, dest + len - 8, 8); | |
52 | ||
53 | des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_DECRYPT); | |
54 | memcpy(iv2, &iv1, 8); /* Note how iv1 == iv2 on entry and exit. */ | |
55 | ||
56 | des_cbc_encrypt(dest, dest, len, ks3, iv3, DES_ENCRYPT); | |
57 | memcpy(iv3, dest + len - 8, 8); | |
58 | } | |
59 | ||
60 | void | |
61 | SSH_3CBC_DECRYPT(des_key_schedule ks1, | |
62 | des_key_schedule ks2, des_cblock *iv2, | |
63 | des_key_schedule ks3, des_cblock *iv3, | |
64 | void *dest, void *src, | |
65 | unsigned int len) | |
66 | { | |
67 | des_cblock iv1; | |
68 | ||
69 | memcpy(&iv1, iv2, 8); | |
70 | ||
71 | des_cbc_encrypt(src, dest, len, ks3, iv3, DES_DECRYPT); | |
72 | memcpy(iv3, src + len - 8, 8); | |
73 | ||
74 | des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_ENCRYPT); | |
75 | memcpy(iv2, dest + len - 8, 8); | |
76 | ||
77 | des_cbc_encrypt(dest, dest, len, ks1, &iv1, DES_DECRYPT); | |
78 | /* memcpy(&iv1, iv2, 8); */ /* Note how iv1 == iv2 on entry and exit. */ | |
79 | } | |
80 | ||
81 | /* | |
82 | * SSH uses a variation on Blowfish, all bytes must be swapped before | |
83 | * and after encryption/decryption. Thus the swap_bytes stuff (yuk). | |
84 | */ | |
85 | static | |
86 | void | |
87 | swap_bytes(const unsigned char *src, unsigned char *dst_, int n) | |
88 | { | |
89 | u_int32_t *dst = (u_int32_t *)dst_; /* dst must be properly aligned. */ | |
90 | union { | |
91 | u_int32_t i; | |
92 | char c[4]; | |
93 | } t; | |
94 | ||
8efc0c15 | 95 | /* Process 8 bytes every lap. */ |
96 | for (n = n / 8; n > 0; n--) | |
97 | { | |
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 | } | |
110 | } | |
111 | ||
112 | void (*cipher_attack_detected)(const char *fmt, ...) = fatal; | |
113 | ||
114 | static inline | |
115 | void | |
116 | detect_cbc_attack(const unsigned char *src, | |
117 | unsigned int len) | |
118 | { | |
119 | return; | |
120 | ||
121 | log("CRC-32 CBC insertion attack detected"); | |
122 | cipher_attack_detected("CRC-32 CBC insertion attack detected"); | |
123 | } | |
124 | ||
125 | /* Names of all encryption algorithms. These must match the numbers defined | |
126 | int cipher.h. */ | |
127 | static char *cipher_names[] = | |
128 | { | |
129 | "none", | |
130 | "idea", | |
131 | "des", | |
132 | "3des", | |
133 | "tss", | |
134 | "rc4", | |
135 | "blowfish" | |
136 | }; | |
137 | ||
138 | /* Returns a bit mask indicating which ciphers are supported by this | |
139 | implementation. The bit mask has the corresponding bit set of each | |
140 | supported cipher. */ | |
141 | ||
142 | unsigned int cipher_mask() | |
143 | { | |
144 | unsigned int mask = 0; | |
145 | mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */ | |
146 | mask |= 1 << SSH_CIPHER_BLOWFISH; | |
147 | return mask; | |
148 | } | |
149 | ||
150 | /* Returns the name of the cipher. */ | |
151 | ||
152 | const | |
153 | char *cipher_name(int cipher) | |
154 | { | |
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]; | |
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 | { | |
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; | |
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 | ||
178 | void cipher_set_key_string(CipherContext *context, int cipher, | |
179 | const char *passphrase, int for_encryption) | |
180 | { | |
181 | MD5_CTX md; | |
182 | unsigned char digest[16]; | |
183 | ||
184 | MD5_Init(&md); | |
185 | MD5_Update(&md, (const unsigned char *)passphrase, strlen(passphrase)); | |
186 | MD5_Final(digest, &md); | |
187 | ||
188 | cipher_set_key(context, cipher, digest, 16, for_encryption); | |
189 | ||
190 | memset(digest, 0, sizeof(digest)); | |
191 | memset(&md, 0, sizeof(md)); | |
192 | } | |
193 | ||
194 | /* Selects the cipher to use and sets the key. */ | |
195 | ||
196 | void cipher_set_key(CipherContext *context, int cipher, | |
197 | const unsigned char *key, int keylen, int for_encryption) | |
198 | { | |
199 | unsigned char padded[32]; | |
200 | ||
201 | /* Set cipher type. */ | |
202 | context->type = cipher; | |
203 | ||
204 | /* Get 32 bytes of key data. Pad if necessary. (So that code below does | |
205 | not need to worry about key size). */ | |
206 | memset(padded, 0, sizeof(padded)); | |
207 | memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded)); | |
208 | ||
209 | /* Initialize the initialization vector. */ | |
210 | switch (cipher) | |
211 | { | |
212 | case SSH_CIPHER_NONE: | |
213 | /* Has to stay for authfile saving of private key with no passphrase */ | |
214 | break; | |
215 | ||
216 | case SSH_CIPHER_3DES: | |
217 | /* Note: the least significant bit of each byte of key is parity, | |
218 | and must be ignored by the implementation. 16 bytes of key are | |
219 | used (first and last keys are the same). */ | |
220 | if (keylen < 16) | |
221 | error("Key length %d is insufficient for 3DES.", keylen); | |
222 | des_set_key((void*)padded, context->u.des3.key1); | |
223 | des_set_key((void*)(padded + 8), context->u.des3.key2); | |
224 | if (keylen <= 16) | |
225 | des_set_key((void*)padded, context->u.des3.key3); | |
226 | else | |
227 | des_set_key((void*)(padded + 16), context->u.des3.key3); | |
228 | memset(context->u.des3.iv2, 0, sizeof(context->u.des3.iv2)); | |
229 | memset(context->u.des3.iv3, 0, sizeof(context->u.des3.iv3)); | |
230 | break; | |
231 | ||
232 | case SSH_CIPHER_BLOWFISH: | |
233 | BF_set_key(&context->u.bf.key, keylen, padded); | |
234 | memset(context->u.bf.iv, 0, 8); | |
235 | break; | |
236 | ||
237 | default: | |
4d195447 | 238 | fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher)); |
8efc0c15 | 239 | } |
240 | memset(padded, 0, sizeof(padded)); | |
241 | } | |
242 | ||
243 | /* Encrypts data using the cipher. */ | |
244 | ||
245 | void cipher_encrypt(CipherContext *context, unsigned char *dest, | |
246 | const unsigned char *src, unsigned int len) | |
247 | { | |
5bae4ab8 | 248 | if ((len & 7) != 0) |
249 | fatal("cipher_encrypt: bad plaintext length %d", len); | |
8efc0c15 | 250 | |
251 | switch (context->type) | |
252 | { | |
253 | case SSH_CIPHER_NONE: | |
254 | memcpy(dest, src, len); | |
255 | break; | |
256 | ||
257 | case SSH_CIPHER_3DES: | |
258 | SSH_3CBC_ENCRYPT(context->u.des3.key1, | |
259 | context->u.des3.key2, &context->u.des3.iv2, | |
260 | context->u.des3.key3, &context->u.des3.iv3, | |
261 | dest, (void*)src, len); | |
262 | break; | |
263 | ||
264 | case SSH_CIPHER_BLOWFISH: | |
265 | swap_bytes(src, dest, len); | |
266 | BF_cbc_encrypt(dest, dest, len, | |
267 | &context->u.bf.key, context->u.bf.iv, BF_ENCRYPT); | |
268 | swap_bytes(dest, dest, len); | |
269 | break; | |
270 | ||
271 | default: | |
272 | fatal("cipher_encrypt: unknown cipher: %d", context->type); | |
273 | } | |
274 | } | |
275 | ||
276 | /* Decrypts data using the cipher. */ | |
277 | ||
278 | void cipher_decrypt(CipherContext *context, unsigned char *dest, | |
279 | const unsigned char *src, unsigned int len) | |
280 | { | |
5bae4ab8 | 281 | if ((len & 7) != 0) |
282 | fatal("cipher_decrypt: bad ciphertext length %d", len); | |
8efc0c15 | 283 | |
284 | switch (context->type) | |
285 | { | |
286 | case SSH_CIPHER_NONE: | |
287 | memcpy(dest, src, len); | |
288 | break; | |
289 | ||
290 | case SSH_CIPHER_3DES: | |
291 | /* CRC-32 attack? */ | |
292 | SSH_3CBC_DECRYPT(context->u.des3.key1, | |
293 | context->u.des3.key2, &context->u.des3.iv2, | |
294 | context->u.des3.key3, &context->u.des3.iv3, | |
295 | dest, (void*)src, len); | |
296 | break; | |
297 | ||
298 | case SSH_CIPHER_BLOWFISH: | |
299 | detect_cbc_attack(src, len); | |
300 | swap_bytes(src, dest, len); | |
301 | BF_cbc_encrypt((void*)dest, dest, len, | |
302 | &context->u.bf.key, context->u.bf.iv, BF_DECRYPT); | |
303 | swap_bytes(dest, dest, len); | |
304 | break; | |
305 | ||
306 | default: | |
307 | fatal("cipher_decrypt: unknown cipher: %d", context->type); | |
308 | } | |
309 | } |