dropbar: Update to version 2013.60.1.
[tomato.git] / release / src / router / dropbear / common-algo.c
blob14c157b0bd6364dfcc8ec1fbfacfcfea44a2ec97
1 /*
2 * Dropbear SSH
3 *
4 * Copyright (c) 2002,2003 Matt Johnston
5 * Copyright (c) 2004 by Mihnea Stoenescu
6 * All rights reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE. */
26 #include "algo.h"
27 #include "session.h"
28 #include "dbutil.h"
30 /* This file (algo.c) organises the ciphers which can be used, and is used to
31 * decide which ciphers/hashes/compression/signing to use during key exchange*/
33 static int void_cipher(const unsigned char* in, unsigned char* out,
34 unsigned long len, void *cipher_state) {
35 if (in != out) {
36 memmove(out, in, len);
38 return CRYPT_OK;
41 static int void_start(int cipher, const unsigned char *IV,
42 const unsigned char *key,
43 int keylen, int num_rounds, void *cipher_state) {
44 return CRYPT_OK;
47 /* Mappings for ciphers, parameters are
48 {&cipher_desc, keysize, blocksize} */
50 /* Remember to add new ciphers/hashes to regciphers/reghashes too */
52 #ifdef DROPBEAR_AES256
53 static const struct dropbear_cipher dropbear_aes256 =
54 {&aes_desc, 32, 16};
55 #endif
56 #ifdef DROPBEAR_AES128
57 static const struct dropbear_cipher dropbear_aes128 =
58 {&aes_desc, 16, 16};
59 #endif
60 #ifdef DROPBEAR_BLOWFISH
61 static const struct dropbear_cipher dropbear_blowfish =
62 {&blowfish_desc, 16, 8};
63 #endif
64 #ifdef DROPBEAR_TWOFISH256
65 static const struct dropbear_cipher dropbear_twofish256 =
66 {&twofish_desc, 32, 16};
67 #endif
68 #ifdef DROPBEAR_TWOFISH128
69 static const struct dropbear_cipher dropbear_twofish128 =
70 {&twofish_desc, 16, 16};
71 #endif
72 #ifdef DROPBEAR_3DES
73 static const struct dropbear_cipher dropbear_3des =
74 {&des3_desc, 24, 8};
75 #endif
77 /* used to indicate no encryption, as defined in rfc2410 */
78 const struct dropbear_cipher dropbear_nocipher =
79 {NULL, 16, 8};
81 /* A few void* s are required to silence warnings
82 * about the symmetric_CBC vs symmetric_CTR cipher_state pointer */
83 const struct dropbear_cipher_mode dropbear_mode_cbc =
84 {(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt};
85 const struct dropbear_cipher_mode dropbear_mode_none =
86 {void_start, void_cipher, void_cipher};
87 #ifdef DROPBEAR_ENABLE_CTR_MODE
88 /* a wrapper to make ctr_start and cbc_start look the same */
89 static int dropbear_big_endian_ctr_start(int cipher,
90 const unsigned char *IV,
91 const unsigned char *key, int keylen,
92 int num_rounds, symmetric_CTR *ctr) {
93 return ctr_start(cipher, IV, key, keylen, num_rounds, CTR_COUNTER_BIG_ENDIAN, ctr);
95 const struct dropbear_cipher_mode dropbear_mode_ctr =
96 {(void*)dropbear_big_endian_ctr_start, (void*)ctr_encrypt, (void*)ctr_decrypt};
97 #endif
99 /* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc.
100 {&hash_desc, keysize, hashsize} */
102 #ifdef DROPBEAR_SHA1_HMAC
103 static const struct dropbear_hash dropbear_sha1 =
104 {&sha1_desc, 20, 20};
105 #endif
106 #ifdef DROPBEAR_SHA1_96_HMAC
107 static const struct dropbear_hash dropbear_sha1_96 =
108 {&sha1_desc, 20, 12};
109 #endif
110 #ifdef DROPBEAR_SHA2_256_HMAC
111 static const struct dropbear_hash dropbear_sha2_256 =
112 {&sha256_desc, 32, 32};
113 #endif
114 #ifdef DROPBEAR_SHA2_512_HMAC
115 static const struct dropbear_hash dropbear_sha2_512 =
116 {&sha512_desc, 64, 64};
117 #endif
118 #ifdef DROPBEAR_MD5_HMAC
119 static const struct dropbear_hash dropbear_md5 =
120 {&md5_desc, 16, 16};
121 #endif
123 const struct dropbear_hash dropbear_nohash =
124 {NULL, 16, 0}; /* used initially */
127 /* The following map ssh names to internal values.
128 * The ordering here is important for the client - the first mode
129 * that is also supported by the server will get used. */
131 algo_type sshciphers[] = {
132 #ifdef DROPBEAR_ENABLE_CTR_MODE
133 #ifdef DROPBEAR_AES128
134 {"aes128-ctr", 0, &dropbear_aes128, 1, &dropbear_mode_ctr},
135 #endif
136 #ifdef DROPBEAR_3DES
137 {"3des-ctr", 0, &dropbear_3des, 1, &dropbear_mode_ctr},
138 #endif
139 #ifdef DROPBEAR_AES256
140 {"aes256-ctr", 0, &dropbear_aes256, 1, &dropbear_mode_ctr},
141 #endif
142 #endif /* DROPBEAR_ENABLE_CTR_MODE */
144 /* CBC modes are always enabled */
145 #ifdef DROPBEAR_AES128
146 {"aes128-cbc", 0, &dropbear_aes128, 1, &dropbear_mode_cbc},
147 #endif
148 #ifdef DROPBEAR_3DES
149 {"3des-cbc", 0, &dropbear_3des, 1, &dropbear_mode_cbc},
150 #endif
151 #ifdef DROPBEAR_AES256
152 {"aes256-cbc", 0, &dropbear_aes256, 1, &dropbear_mode_cbc},
153 #endif
154 #ifdef DROPBEAR_TWOFISH256
155 {"twofish256-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
156 {"twofish-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
157 #endif
158 #ifdef DROPBEAR_TWOFISH128
159 {"twofish128-cbc", 0, &dropbear_twofish128, 1, &dropbear_mode_cbc},
160 #endif
161 #ifdef DROPBEAR_BLOWFISH
162 {"blowfish-cbc", 0, &dropbear_blowfish, 1, &dropbear_mode_cbc},
163 #endif
164 #ifdef DROPBEAR_NONE_CIPHER
165 {"none", 0, (void*)&dropbear_nocipher, 1, &dropbear_mode_none},
166 #endif
167 {NULL, 0, NULL, 0, NULL}
170 algo_type sshhashes[] = {
171 #ifdef DROPBEAR_SHA2_256_HMAC
172 {"hmac-sha2-256", 0, &dropbear_sha2_256, 1, NULL},
173 #endif
174 #ifdef DROPBEAR_SHA2_512_HMAC
175 {"hmac-sha2-512", 0, &dropbear_sha2_512, 1, NULL},
176 #endif
177 #ifdef DROPBEAR_SHA1_96_HMAC
178 {"hmac-sha1-96", 0, &dropbear_sha1_96, 1, NULL},
179 #endif
180 #ifdef DROPBEAR_SHA1_HMAC
181 {"hmac-sha1", 0, &dropbear_sha1, 1, NULL},
182 #endif
183 #ifdef DROPBEAR_MD5_HMAC
184 {"hmac-md5", 0, (void*)&dropbear_md5, 1, NULL},
185 #endif
186 #ifdef DROPBEAR_NONE_INTEGRITY
187 {"none", 0, (void*)&dropbear_nohash, 1, NULL},
188 #endif
189 {NULL, 0, NULL, 0, NULL}
192 #ifndef DISABLE_ZLIB
193 algo_type ssh_compress[] = {
194 {"zlib", DROPBEAR_COMP_ZLIB, NULL, 1, NULL},
195 {"zlib@openssh.com", DROPBEAR_COMP_ZLIB_DELAY, NULL, 1, NULL},
196 {"none", DROPBEAR_COMP_NONE, NULL, 1, NULL},
197 {NULL, 0, NULL, 0, NULL}
199 #endif
201 algo_type ssh_nocompress[] = {
202 {"none", DROPBEAR_COMP_NONE, NULL, 1, NULL},
203 {NULL, 0, NULL, 0, NULL}
206 algo_type sshhostkey[] = {
207 #ifdef DROPBEAR_RSA
208 {"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1, NULL},
209 #endif
210 #ifdef DROPBEAR_DSS
211 {"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1, NULL},
212 #endif
213 {NULL, 0, NULL, 0, NULL}
216 algo_type sshkex[] = {
217 {"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1, NULL},
218 {"diffie-hellman-group14-sha1", DROPBEAR_KEX_DH_GROUP14, NULL, 1, NULL},
219 #ifdef USE_KEXGUESS2
220 {KEXGUESS2_ALGO_NAME, KEXGUESS2_ALGO_ID, NULL, 1, NULL},
221 #endif
222 {NULL, 0, NULL, 0, NULL}
226 /* Register the compiled in ciphers.
227 * This should be run before using any of the ciphers/hashes */
228 void crypto_init() {
230 const struct ltc_cipher_descriptor *regciphers[] = {
231 #ifdef DROPBEAR_AES
232 &aes_desc,
233 #endif
234 #ifdef DROPBEAR_BLOWFISH
235 &blowfish_desc,
236 #endif
237 #ifdef DROPBEAR_TWOFISH
238 &twofish_desc,
239 #endif
240 #ifdef DROPBEAR_3DES
241 &des3_desc,
242 #endif
243 NULL
246 const struct ltc_hash_descriptor *reghashes[] = {
247 /* we need sha1 for hostkey stuff regardless */
248 &sha1_desc,
249 #ifdef DROPBEAR_MD5_HMAC
250 &md5_desc,
251 #endif
252 #ifdef DROPBEAR_SHA2_256_HMAC
253 &sha256_desc,
254 #endif
255 #ifdef DROPBEAR_SHA2_512_HMAC
256 &sha512_desc,
257 #endif
258 NULL
260 int i;
262 for (i = 0; regciphers[i] != NULL; i++) {
263 if (register_cipher(regciphers[i]) == -1) {
264 dropbear_exit("Error registering crypto");
268 for (i = 0; reghashes[i] != NULL; i++) {
269 if (register_hash(reghashes[i]) == -1) {
270 dropbear_exit("Error registering crypto");
275 /* algolen specifies the length of algo, algos is our local list to match
276 * against.
277 * Returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE
278 * otherwise */
279 int have_algo(char* algo, size_t algolen, algo_type algos[]) {
281 int i;
283 for (i = 0; algos[i].name != NULL; i++) {
284 if (strlen(algos[i].name) == algolen
285 && (strncmp(algos[i].name, algo, algolen) == 0)) {
286 return DROPBEAR_SUCCESS;
290 return DROPBEAR_FAILURE;
293 /* Output a comma separated list of algorithms to a buffer */
294 void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
296 unsigned int i, len;
297 unsigned int donefirst = 0;
298 buffer *algolist = NULL;
300 algolist = buf_new(160);
301 for (i = 0; localalgos[i].name != NULL; i++) {
302 if (localalgos[i].usable) {
303 if (donefirst)
304 buf_putbyte(algolist, ',');
305 donefirst = 1;
306 len = strlen(localalgos[i].name);
307 buf_putbytes(algolist, localalgos[i].name, len);
310 buf_putstring(buf, algolist->data, algolist->len);
311 buf_free(algolist);
314 /* match the first algorithm in the comma-separated list in buf which is
315 * also in localalgos[], or return NULL on failure.
316 * (*goodguess) is set to 1 if the preferred client/server algos match,
317 * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
318 * guessed correctly */
319 algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
320 enum kexguess2_used *kexguess2, int *goodguess)
323 unsigned char * algolist = NULL;
324 const unsigned char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO];
325 unsigned int len;
326 unsigned int remotecount, localcount, clicount, servcount, i, j;
327 algo_type * ret = NULL;
328 const unsigned char **clinames, **servnames;
330 if (goodguess) {
331 *goodguess = 0;
334 /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
335 algolist = buf_getstring(buf, &len);
336 TRACE(("buf_match_algo: %s", algolist))
337 if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
338 goto out;
341 /* remotenames will contain a list of the strings parsed out */
342 /* We will have at least one string (even if it's just "") */
343 remotenames[0] = algolist;
344 remotecount = 1;
345 for (i = 0; i < len; i++) {
346 if (algolist[i] == '\0') {
347 /* someone is trying something strange */
348 goto out;
350 if (algolist[i] == ',') {
351 algolist[i] = '\0';
352 remotenames[remotecount] = &algolist[i+1];
353 remotecount++;
355 if (remotecount >= MAX_PROPOSED_ALGO) {
356 break;
359 if (kexguess2 && *kexguess2 == KEXGUESS2_LOOK) {
360 for (i = 0; i < remotecount; i++)
362 if (strcmp(remotenames[i], KEXGUESS2_ALGO_NAME) == 0) {
363 *kexguess2 = KEXGUESS2_YES;
364 break;
367 if (*kexguess2 == KEXGUESS2_LOOK) {
368 *kexguess2 = KEXGUESS2_NO;
372 for (i = 0; localalgos[i].name != NULL; i++) {
373 if (localalgos[i].usable) {
374 localnames[i] = localalgos[i].name;
375 } else {
376 localnames[i] = NULL;
379 localcount = i;
381 if (IS_DROPBEAR_SERVER) {
382 clinames = remotenames;
383 clicount = remotecount;
384 servnames = localnames;
385 servcount = localcount;
386 } else {
387 clinames = localnames;
388 clicount = localcount;
389 servnames = remotenames;
390 servcount = remotecount;
393 /* iterate and find the first match */
394 for (i = 0; i < clicount; i++) {
395 for (j = 0; j < servcount; j++) {
396 if (!(servnames[j] && clinames[i])) {
397 // unusable algos are NULL
398 continue;
400 if (strcmp(servnames[j], clinames[i]) == 0) {
401 /* set if it was a good guess */
402 if (goodguess && kexguess2) {
403 if (*kexguess2 == KEXGUESS2_YES) {
404 if (i == 0) {
405 *goodguess = 1;
408 } else {
409 if (i == 0 && j == 0) {
410 *goodguess = 1;
414 /* set the algo to return */
415 if (IS_DROPBEAR_SERVER) {
416 ret = &localalgos[j];
417 } else {
418 ret = &localalgos[i];
420 goto out;
425 out:
426 m_free(algolist);
427 return ret;
430 #ifdef DROPBEAR_NONE_CIPHER
432 void
433 set_algo_usable(algo_type algos[], const char * algo_name, int usable)
435 algo_type *a;
436 for (a = algos; a->name != NULL; a++)
438 if (strcmp(a->name, algo_name) == 0)
440 a->usable = usable;
441 return;
447 get_algo_usable(algo_type algos[], const char * algo_name)
449 algo_type *a;
450 for (a = algos; a->name != NULL; a++)
452 if (strcmp(a->name, algo_name) == 0)
454 return a->usable;
457 return 0;
460 #endif // DROPBEAR_NONE_CIPHER
462 #ifdef ENABLE_USER_ALGO_LIST
464 char *
465 algolist_string(algo_type algos[])
467 char *ret_list;
468 buffer *b = buf_new(200);
469 buf_put_algolist(b, algos);
470 buf_setpos(b, b->len);
471 buf_putbyte(b, '\0');
472 buf_setpos(b, 4);
473 ret_list = m_strdup(buf_getptr(b, b->len - b->pos));
474 buf_free(b);
475 return ret_list;
478 static algo_type*
479 check_algo(const char* algo_name, algo_type *algos)
481 algo_type *a;
482 for (a = algos; a->name != NULL; a++)
484 if (strcmp(a->name, algo_name) == 0)
486 return a;
490 return NULL;
493 static void
494 try_add_algo(const char *algo_name, algo_type *algos,
495 const char *algo_desc, algo_type * new_algos, int *num_ret)
497 algo_type *match_algo = check_algo(algo_name, algos);
498 if (!match_algo)
500 dropbear_log(LOG_WARNING, "This Dropbear program does not support '%s' %s algorithm", algo_name, algo_desc);
501 return;
504 new_algos[*num_ret] = *match_algo;
505 (*num_ret)++;
508 /* Checks a user provided comma-separated algorithm list for available
509 * options. Any that are not acceptable are removed in-place. Returns the
510 * number of valid algorithms. */
512 check_user_algos(const char* user_algo_list, algo_type * algos,
513 const char *algo_desc)
515 algo_type new_algos[MAX_PROPOSED_ALGO];
516 /* this has two passes. first we sweep through the given list of
517 * algorithms and mark them as usable=2 in the algo_type[] array... */
518 int num_ret = 0;
519 char *work_list = m_strdup(user_algo_list);
520 char *last_name = work_list;
521 char *c;
522 for (c = work_list; *c; c++)
524 if (*c == ',')
526 *c = '\0';
527 try_add_algo(last_name, algos, algo_desc, new_algos, &num_ret);
528 c++;
529 last_name = c;
532 try_add_algo(last_name, algos, algo_desc, new_algos, &num_ret);
533 m_free(work_list);
535 new_algos[num_ret].name = NULL;
537 /* Copy one more as a blank delimiter */
538 memcpy(algos, new_algos, sizeof(*new_algos) * (num_ret+1));
539 return num_ret;
541 #endif // ENABLE_USER_ALGO_LIST