]>
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 | ||
5881cd60 | 14 | #include "config.h" |
8efc0c15 | 15 | #include "includes.h" |
16 | RCSID("$Id$"); | |
17 | ||
18 | #include "ssh.h" | |
19 | #include "cipher.h" | |
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, | |
42 | des_key_schedule ks2, des_cblock *iv2, | |
43 | des_key_schedule ks3, des_cblock *iv3, | |
44 | void *dest, void *src, | |
45 | unsigned int len) | |
46 | { | |
47 | des_cblock iv1; | |
48 | ||
49 | memcpy(&iv1, iv2, 8); | |
50 | ||
51 | des_cbc_encrypt(src, dest, len, ks1, &iv1, DES_ENCRYPT); | |
52 | memcpy(&iv1, dest + len - 8, 8); | |
53 | ||
54 | des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_DECRYPT); | |
55 | memcpy(iv2, &iv1, 8); /* Note how iv1 == iv2 on entry and exit. */ | |
56 | ||
57 | des_cbc_encrypt(dest, dest, len, ks3, iv3, DES_ENCRYPT); | |
58 | memcpy(iv3, dest + len - 8, 8); | |
59 | } | |
60 | ||
61 | void | |
62 | SSH_3CBC_DECRYPT(des_key_schedule ks1, | |
63 | des_key_schedule ks2, des_cblock *iv2, | |
64 | des_key_schedule ks3, des_cblock *iv3, | |
65 | void *dest, void *src, | |
66 | unsigned int len) | |
67 | { | |
68 | des_cblock iv1; | |
69 | ||
70 | memcpy(&iv1, iv2, 8); | |
71 | ||
72 | des_cbc_encrypt(src, dest, len, ks3, iv3, DES_DECRYPT); | |
73 | memcpy(iv3, src + len - 8, 8); | |
74 | ||
75 | des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_ENCRYPT); | |
76 | memcpy(iv2, dest + len - 8, 8); | |
77 | ||
78 | des_cbc_encrypt(dest, dest, len, ks1, &iv1, DES_DECRYPT); | |
79 | /* memcpy(&iv1, iv2, 8); */ /* Note how iv1 == iv2 on entry and exit. */ | |
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 | */ | |
86 | static | |
87 | void | |
88 | swap_bytes(const unsigned char *src, unsigned char *dst_, int n) | |
89 | { | |
90 | u_int32_t *dst = (u_int32_t *)dst_; /* dst must be properly aligned. */ | |
91 | union { | |
92 | u_int32_t i; | |
93 | char c[4]; | |
94 | } t; | |
95 | ||
96 | /* assert((n & 7) == 0); */ | |
97 | ||
98 | /* Process 8 bytes every lap. */ | |
99 | for (n = n / 8; n > 0; n--) | |
100 | { | |
101 | t.c[3] = *src++; | |
102 | t.c[2] = *src++; | |
103 | t.c[1] = *src++; | |
104 | t.c[0] = *src++; | |
105 | *dst++ = t.i; | |
106 | ||
107 | t.c[3] = *src++; | |
108 | t.c[2] = *src++; | |
109 | t.c[1] = *src++; | |
110 | t.c[0] = *src++; | |
111 | *dst++ = t.i; | |
112 | } | |
113 | } | |
114 | ||
115 | void (*cipher_attack_detected)(const char *fmt, ...) = fatal; | |
116 | ||
117 | static inline | |
118 | void | |
119 | detect_cbc_attack(const unsigned char *src, | |
120 | unsigned int len) | |
121 | { | |
122 | return; | |
123 | ||
124 | log("CRC-32 CBC insertion attack detected"); | |
125 | cipher_attack_detected("CRC-32 CBC insertion attack detected"); | |
126 | } | |
127 | ||
128 | /* Names of all encryption algorithms. These must match the numbers defined | |
129 | int cipher.h. */ | |
130 | static char *cipher_names[] = | |
131 | { | |
132 | "none", | |
133 | "idea", | |
134 | "des", | |
135 | "3des", | |
136 | "tss", | |
137 | "rc4", | |
138 | "blowfish" | |
139 | }; | |
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 | ||
145 | unsigned int cipher_mask() | |
146 | { | |
147 | unsigned int mask = 0; | |
148 | mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */ | |
149 | mask |= 1 << SSH_CIPHER_BLOWFISH; | |
150 | return mask; | |
151 | } | |
152 | ||
153 | /* Returns the name of the cipher. */ | |
154 | ||
155 | const | |
156 | char *cipher_name(int cipher) | |
157 | { | |
158 | if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]) || | |
159 | cipher_names[cipher] == NULL) | |
160 | fatal("cipher_name: bad cipher number: %d", cipher); | |
161 | return cipher_names[cipher]; | |
162 | } | |
163 | ||
164 | /* Parses the name of the cipher. Returns the number of the corresponding | |
165 | cipher, or -1 on error. */ | |
166 | ||
167 | int | |
168 | cipher_number(const char *name) | |
169 | { | |
170 | int i; | |
171 | for (i = 0; i < sizeof(cipher_names) / sizeof(cipher_names[0]); i++) | |
172 | if (strcmp(cipher_names[i], name) == 0 && | |
173 | (cipher_mask() & (1 << i))) | |
174 | return i; | |
175 | return -1; | |
176 | } | |
177 | ||
178 | /* Selects the cipher, and keys if by computing the MD5 checksum of the | |
179 | passphrase and using the resulting 16 bytes as the key. */ | |
180 | ||
181 | void cipher_set_key_string(CipherContext *context, int cipher, | |
182 | const char *passphrase, int for_encryption) | |
183 | { | |
184 | MD5_CTX md; | |
185 | unsigned char digest[16]; | |
186 | ||
187 | MD5_Init(&md); | |
188 | MD5_Update(&md, (const unsigned char *)passphrase, strlen(passphrase)); | |
189 | MD5_Final(digest, &md); | |
190 | ||
191 | cipher_set_key(context, cipher, digest, 16, for_encryption); | |
192 | ||
193 | memset(digest, 0, sizeof(digest)); | |
194 | memset(&md, 0, sizeof(md)); | |
195 | } | |
196 | ||
197 | /* Selects the cipher to use and sets the key. */ | |
198 | ||
199 | void cipher_set_key(CipherContext *context, int cipher, | |
200 | const unsigned char *key, int keylen, int for_encryption) | |
201 | { | |
202 | unsigned char padded[32]; | |
203 | ||
204 | /* Set cipher type. */ | |
205 | context->type = cipher; | |
206 | ||
207 | /* Get 32 bytes of key data. Pad if necessary. (So that code below does | |
208 | not need to worry about key size). */ | |
209 | memset(padded, 0, sizeof(padded)); | |
210 | memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded)); | |
211 | ||
212 | /* Initialize the initialization vector. */ | |
213 | switch (cipher) | |
214 | { | |
215 | case SSH_CIPHER_NONE: | |
216 | /* Has to stay for authfile saving of private key with no passphrase */ | |
217 | break; | |
218 | ||
219 | case SSH_CIPHER_3DES: | |
220 | /* Note: the least significant bit of each byte of key is parity, | |
221 | and must be ignored by the implementation. 16 bytes of key are | |
222 | used (first and last keys are the 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: %d", cipher); | |
242 | } | |
243 | memset(padded, 0, sizeof(padded)); | |
244 | } | |
245 | ||
246 | /* Encrypts data using the cipher. */ | |
247 | ||
248 | void cipher_encrypt(CipherContext *context, unsigned char *dest, | |
249 | const unsigned char *src, unsigned int len) | |
250 | { | |
251 | assert((len & 7) == 0); | |
252 | ||
253 | switch (context->type) | |
254 | { | |
255 | case SSH_CIPHER_NONE: | |
256 | memcpy(dest, src, len); | |
257 | break; | |
258 | ||
259 | case SSH_CIPHER_3DES: | |
260 | SSH_3CBC_ENCRYPT(context->u.des3.key1, | |
261 | context->u.des3.key2, &context->u.des3.iv2, | |
262 | context->u.des3.key3, &context->u.des3.iv3, | |
263 | dest, (void*)src, len); | |
264 | break; | |
265 | ||
266 | case SSH_CIPHER_BLOWFISH: | |
267 | swap_bytes(src, dest, len); | |
268 | BF_cbc_encrypt(dest, dest, len, | |
269 | &context->u.bf.key, context->u.bf.iv, BF_ENCRYPT); | |
270 | swap_bytes(dest, dest, len); | |
271 | break; | |
272 | ||
273 | default: | |
274 | fatal("cipher_encrypt: unknown cipher: %d", context->type); | |
275 | } | |
276 | } | |
277 | ||
278 | /* Decrypts data using the cipher. */ | |
279 | ||
280 | void cipher_decrypt(CipherContext *context, unsigned char *dest, | |
281 | const unsigned char *src, unsigned int len) | |
282 | { | |
283 | assert((len & 7) == 0); | |
284 | ||
285 | switch (context->type) | |
286 | { | |
287 | case SSH_CIPHER_NONE: | |
288 | memcpy(dest, src, len); | |
289 | break; | |
290 | ||
291 | case SSH_CIPHER_3DES: | |
292 | /* CRC-32 attack? */ | |
293 | SSH_3CBC_DECRYPT(context->u.des3.key1, | |
294 | context->u.des3.key2, &context->u.des3.iv2, | |
295 | context->u.des3.key3, &context->u.des3.iv3, | |
296 | dest, (void*)src, len); | |
297 | break; | |
298 | ||
299 | case SSH_CIPHER_BLOWFISH: | |
300 | detect_cbc_attack(src, len); | |
301 | swap_bytes(src, dest, len); | |
302 | BF_cbc_encrypt((void*)dest, dest, len, | |
303 | &context->u.bf.key, context->u.bf.iv, BF_DECRYPT); | |
304 | swap_bytes(dest, dest, len); | |
305 | break; | |
306 | ||
307 | default: | |
308 | fatal("cipher_decrypt: unknown cipher: %d", context->type); | |
309 | } | |
310 | } |