4 * Copyright (c) 2002,2003 Matt Johnston
5 * Copyright (c) 2004 by Mihnea Stoenescu
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
34 /* This file (algo.c) organises the ciphers which can be used, and is used to
35 * decide which ciphers/hashes/compression/signing to use during key exchange*/
37 static int void_cipher(const unsigned char* in
, unsigned char* out
,
38 unsigned long len
, void* UNUSED(cipher_state
)) {
40 memmove(out
, in
, len
);
45 static int void_start(int UNUSED(cipher
), const unsigned char* UNUSED(IV
),
46 const unsigned char* UNUSED(key
),
47 int UNUSED(keylen
), int UNUSED(num_rounds
), void* UNUSED(cipher_state
)) {
51 /* Mappings for ciphers, parameters are
52 {&cipher_desc, keysize, blocksize} */
54 /* Remember to add new ciphers/hashes to regciphers/reghashes too */
56 #ifdef DROPBEAR_AES256
57 static const struct dropbear_cipher dropbear_aes256
=
60 #ifdef DROPBEAR_AES128
61 static const struct dropbear_cipher dropbear_aes128
=
64 #ifdef DROPBEAR_BLOWFISH
65 static const struct dropbear_cipher dropbear_blowfish
=
66 {&blowfish_desc
, 16, 8};
68 #ifdef DROPBEAR_TWOFISH256
69 static const struct dropbear_cipher dropbear_twofish256
=
70 {&twofish_desc
, 32, 16};
72 #ifdef DROPBEAR_TWOFISH128
73 static const struct dropbear_cipher dropbear_twofish128
=
74 {&twofish_desc
, 16, 16};
77 static const struct dropbear_cipher dropbear_3des
=
81 /* used to indicate no encryption, as defined in rfc2410 */
82 const struct dropbear_cipher dropbear_nocipher
=
85 /* A few void* s are required to silence warnings
86 * about the symmetric_CBC vs symmetric_CTR cipher_state pointer */
87 #ifdef DROPBEAR_ENABLE_CBC_MODE
88 const struct dropbear_cipher_mode dropbear_mode_cbc
=
89 {(void*)cbc_start
, (void*)cbc_encrypt
, (void*)cbc_decrypt
};
90 #endif /* DROPBEAR_ENABLE_CBC_MODE */
92 const struct dropbear_cipher_mode dropbear_mode_none
=
93 {void_start
, void_cipher
, void_cipher
};
95 #ifdef DROPBEAR_ENABLE_CTR_MODE
96 /* a wrapper to make ctr_start and cbc_start look the same */
97 static int dropbear_big_endian_ctr_start(int cipher
,
98 const unsigned char *IV
,
99 const unsigned char *key
, int keylen
,
100 int num_rounds
, symmetric_CTR
*ctr
) {
101 return ctr_start(cipher
, IV
, key
, keylen
, num_rounds
, CTR_COUNTER_BIG_ENDIAN
, ctr
);
103 const struct dropbear_cipher_mode dropbear_mode_ctr
=
104 {(void*)dropbear_big_endian_ctr_start
, (void*)ctr_encrypt
, (void*)ctr_decrypt
};
105 #endif /* DROPBEAR_ENABLE_CTR_MODE */
107 /* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc.
108 {&hash_desc, keysize, hashsize} */
110 #ifdef DROPBEAR_SHA1_HMAC
111 static const struct dropbear_hash dropbear_sha1
=
112 {&sha1_desc
, 20, 20};
114 #ifdef DROPBEAR_SHA1_96_HMAC
115 static const struct dropbear_hash dropbear_sha1_96
=
116 {&sha1_desc
, 20, 12};
118 #ifdef DROPBEAR_SHA2_256_HMAC
119 static const struct dropbear_hash dropbear_sha2_256
=
120 {&sha256_desc
, 32, 32};
122 #ifdef DROPBEAR_SHA2_512_HMAC
123 static const struct dropbear_hash dropbear_sha2_512
=
124 {&sha512_desc
, 64, 64};
126 #ifdef DROPBEAR_MD5_HMAC
127 static const struct dropbear_hash dropbear_md5
=
131 const struct dropbear_hash dropbear_nohash
=
132 {NULL
, 16, 0}; /* used initially */
135 /* The following map ssh names to internal values.
136 * The ordering here is important for the client - the first mode
137 * that is also supported by the server will get used. */
139 algo_type sshciphers
[] = {
140 #ifdef DROPBEAR_ENABLE_CTR_MODE
141 #ifdef DROPBEAR_AES128
142 {"aes128-ctr", 0, &dropbear_aes128
, 1, &dropbear_mode_ctr
},
144 #ifdef DROPBEAR_AES256
145 {"aes256-ctr", 0, &dropbear_aes256
, 1, &dropbear_mode_ctr
},
147 #ifdef DROPBEAR_TWOFISH_CTR
148 /* twofish ctr is conditional as it hasn't been tested for interoperability, see options.h */
149 #ifdef DROPBEAR_TWOFISH256
150 {"twofish256-ctr", 0, &dropbear_twofish256
, 1, &dropbear_mode_ctr
},
152 #ifdef DROPBEAR_TWOFISH128
153 {"twofish128-ctr", 0, &dropbear_twofish128
, 1, &dropbear_mode_ctr
},
155 #endif /* DROPBEAR_TWOFISH_CTR */
156 #endif /* DROPBEAR_ENABLE_CTR_MODE */
158 #ifdef DROPBEAR_ENABLE_CBC_MODE
159 #ifdef DROPBEAR_AES128
160 {"aes128-cbc", 0, &dropbear_aes128
, 1, &dropbear_mode_cbc
},
162 #ifdef DROPBEAR_AES256
163 {"aes256-cbc", 0, &dropbear_aes256
, 1, &dropbear_mode_cbc
},
165 #ifdef DROPBEAR_TWOFISH256
166 {"twofish256-cbc", 0, &dropbear_twofish256
, 1, &dropbear_mode_cbc
},
167 {"twofish-cbc", 0, &dropbear_twofish256
, 1, &dropbear_mode_cbc
},
169 #ifdef DROPBEAR_TWOFISH128
170 {"twofish128-cbc", 0, &dropbear_twofish128
, 1, &dropbear_mode_cbc
},
173 {"3des-ctr", 0, &dropbear_3des
, 1, &dropbear_mode_ctr
},
176 {"3des-cbc", 0, &dropbear_3des
, 1, &dropbear_mode_cbc
},
178 #ifdef DROPBEAR_BLOWFISH
179 {"blowfish-cbc", 0, &dropbear_blowfish
, 1, &dropbear_mode_cbc
},
181 #endif /* DROPBEAR_ENABLE_CBC_MODE */
182 #ifdef DROPBEAR_NONE_CIPHER
183 {"none", 0, (void*)&dropbear_nocipher
, 1, &dropbear_mode_none
},
185 {NULL
, 0, NULL
, 0, NULL
}
188 algo_type sshhashes
[] = {
189 #ifdef DROPBEAR_SHA1_96_HMAC
190 {"hmac-sha1-96", 0, &dropbear_sha1_96
, 1, NULL
},
192 #ifdef DROPBEAR_SHA1_HMAC
193 {"hmac-sha1", 0, &dropbear_sha1
, 1, NULL
},
195 #ifdef DROPBEAR_SHA2_256_HMAC
196 {"hmac-sha2-256", 0, &dropbear_sha2_256
, 1, NULL
},
198 #ifdef DROPBEAR_SHA2_512_HMAC
199 {"hmac-sha2-512", 0, &dropbear_sha2_512
, 1, NULL
},
201 #ifdef DROPBEAR_MD5_HMAC
202 {"hmac-md5", 0, (void*)&dropbear_md5
, 1, NULL
},
204 #ifdef DROPBEAR_NONE_INTEGRITY
205 {"none", 0, (void*)&dropbear_nohash
, 1, NULL
},
207 {NULL
, 0, NULL
, 0, NULL
}
211 algo_type ssh_compress
[] = {
212 {"zlib@openssh.com", DROPBEAR_COMP_ZLIB_DELAY
, NULL
, 1, NULL
},
213 {"zlib", DROPBEAR_COMP_ZLIB
, NULL
, 1, NULL
},
214 {"none", DROPBEAR_COMP_NONE
, NULL
, 1, NULL
},
215 {NULL
, 0, NULL
, 0, NULL
}
218 algo_type ssh_delaycompress
[] = {
219 {"zlib@openssh.com", DROPBEAR_COMP_ZLIB_DELAY
, NULL
, 1, NULL
},
220 {"none", DROPBEAR_COMP_NONE
, NULL
, 1, NULL
},
221 {NULL
, 0, NULL
, 0, NULL
}
225 algo_type ssh_nocompress
[] = {
226 {"none", DROPBEAR_COMP_NONE
, NULL
, 1, NULL
},
227 {NULL
, 0, NULL
, 0, NULL
}
230 algo_type sshhostkey
[] = {
231 #ifdef DROPBEAR_ECDSA
232 #ifdef DROPBEAR_ECC_256
233 {"ecdsa-sha2-nistp256", DROPBEAR_SIGNKEY_ECDSA_NISTP256
, NULL
, 1, NULL
},
235 #ifdef DROPBEAR_ECC_384
236 {"ecdsa-sha2-nistp384", DROPBEAR_SIGNKEY_ECDSA_NISTP384
, NULL
, 1, NULL
},
238 #ifdef DROPBEAR_ECC_521
239 {"ecdsa-sha2-nistp521", DROPBEAR_SIGNKEY_ECDSA_NISTP521
, NULL
, 1, NULL
},
243 {"ssh-rsa", DROPBEAR_SIGNKEY_RSA
, NULL
, 1, NULL
},
246 {"ssh-dss", DROPBEAR_SIGNKEY_DSS
, NULL
, 1, NULL
},
248 {NULL
, 0, NULL
, 0, NULL
}
251 static const struct dropbear_kex kex_dh_group1
= {DROPBEAR_KEX_NORMAL_DH
, dh_p_1
, DH_P_1_LEN
, NULL
, &sha1_desc
};
252 static const struct dropbear_kex kex_dh_group14
= {DROPBEAR_KEX_NORMAL_DH
, dh_p_14
, DH_P_14_LEN
, NULL
, &sha1_desc
};
254 /* These can't be const since dropbear_ecc_fill_dp() fills out
255 ecc_curve at runtime */
257 #ifdef DROPBEAR_ECC_256
258 static struct dropbear_kex kex_ecdh_nistp256
= {DROPBEAR_KEX_ECDH
, NULL
, 0, &ecc_curve_nistp256
, &sha256_desc
};
260 #ifdef DROPBEAR_ECC_384
261 static struct dropbear_kex kex_ecdh_nistp384
= {DROPBEAR_KEX_ECDH
, NULL
, 0, &ecc_curve_nistp384
, &sha384_desc
};
263 #ifdef DROPBEAR_ECC_521
264 static struct dropbear_kex kex_ecdh_nistp521
= {DROPBEAR_KEX_ECDH
, NULL
, 0, &ecc_curve_nistp521
, &sha512_desc
};
266 #endif /* DROPBEAR_ECDH */
268 #ifdef DROPBEAR_CURVE25519
269 /* Referred to directly */
270 static const struct dropbear_kex kex_curve25519
= {DROPBEAR_KEX_CURVE25519
, NULL
, 0, NULL
, &sha256_desc
};
273 algo_type sshkex
[] = {
274 #ifdef DROPBEAR_CURVE25519
275 {"curve25519-sha256@libssh.org", 0, &kex_curve25519
, 1, NULL
},
278 #ifdef DROPBEAR_ECC_521
279 {"ecdh-sha2-nistp521", 0, &kex_ecdh_nistp521
, 1, NULL
},
281 #ifdef DROPBEAR_ECC_384
282 {"ecdh-sha2-nistp384", 0, &kex_ecdh_nistp384
, 1, NULL
},
284 #ifdef DROPBEAR_ECC_256
285 {"ecdh-sha2-nistp256", 0, &kex_ecdh_nistp256
, 1, NULL
},
288 {"diffie-hellman-group14-sha1", 0, &kex_dh_group14
, 1, NULL
},
289 {"diffie-hellman-group1-sha1", 0, &kex_dh_group1
, 1, NULL
},
291 {KEXGUESS2_ALGO_NAME
, KEXGUESS2_ALGO_ID
, NULL
, 1, NULL
},
293 {NULL
, 0, NULL
, 0, NULL
}
296 /* algolen specifies the length of algo, algos is our local list to match
298 * Returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE
300 int have_algo(char* algo
, size_t algolen
, algo_type algos
[]) {
304 for (i
= 0; algos
[i
].name
!= NULL
; i
++) {
305 if (strlen(algos
[i
].name
) == algolen
306 && (strncmp(algos
[i
].name
, algo
, algolen
) == 0)) {
307 return DROPBEAR_SUCCESS
;
311 return DROPBEAR_FAILURE
;
314 /* Output a comma separated list of algorithms to a buffer */
315 void buf_put_algolist(buffer
* buf
, algo_type localalgos
[]) {
318 unsigned int donefirst
= 0;
319 buffer
*algolist
= NULL
;
321 algolist
= buf_new(200);
322 for (i
= 0; localalgos
[i
].name
!= NULL
; i
++) {
323 if (localalgos
[i
].usable
) {
325 buf_putbyte(algolist
, ',');
327 len
= strlen(localalgos
[i
].name
);
328 buf_putbytes(algolist
, (const unsigned char *) localalgos
[i
].name
, len
);
331 buf_putstring(buf
, (const char*)algolist
->data
, algolist
->len
);
335 /* match the first algorithm in the comma-separated list in buf which is
336 * also in localalgos[], or return NULL on failure.
337 * (*goodguess) is set to 1 if the preferred client/server algos match,
338 * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
339 * guessed correctly */
340 algo_type
* buf_match_algo(buffer
* buf
, algo_type localalgos
[],
341 enum kexguess2_used
*kexguess2
, int *goodguess
)
344 char * algolist
= NULL
;
345 const char *remotenames
[MAX_PROPOSED_ALGO
], *localnames
[MAX_PROPOSED_ALGO
];
347 unsigned int remotecount
, localcount
, clicount
, servcount
, i
, j
;
348 algo_type
* ret
= NULL
;
349 const char **clinames
, **servnames
;
355 /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
356 algolist
= buf_getstring(buf
, &len
);
357 TRACE(("buf_match_algo: %s", algolist
))
358 if (len
> MAX_PROPOSED_ALGO
*(MAX_NAME_LEN
+1)) {
362 /* remotenames will contain a list of the strings parsed out */
363 /* We will have at least one string (even if it's just "") */
364 remotenames
[0] = algolist
;
366 for (i
= 0; i
< len
; i
++) {
367 if (algolist
[i
] == '\0') {
368 /* someone is trying something strange */
371 if (algolist
[i
] == ',') {
373 remotenames
[remotecount
] = &algolist
[i
+1];
376 if (remotecount
>= MAX_PROPOSED_ALGO
) {
380 if (kexguess2
&& *kexguess2
== KEXGUESS2_LOOK
) {
381 for (i
= 0; i
< remotecount
; i
++)
383 if (strcmp(remotenames
[i
], KEXGUESS2_ALGO_NAME
) == 0) {
384 *kexguess2
= KEXGUESS2_YES
;
388 if (*kexguess2
== KEXGUESS2_LOOK
) {
389 *kexguess2
= KEXGUESS2_NO
;
393 for (i
= 0; localalgos
[i
].name
!= NULL
; i
++) {
394 if (localalgos
[i
].usable
) {
395 localnames
[i
] = localalgos
[i
].name
;
397 localnames
[i
] = NULL
;
402 if (IS_DROPBEAR_SERVER
) {
403 clinames
= remotenames
;
404 clicount
= remotecount
;
405 servnames
= localnames
;
406 servcount
= localcount
;
408 clinames
= localnames
;
409 clicount
= localcount
;
410 servnames
= remotenames
;
411 servcount
= remotecount
;
414 /* iterate and find the first match */
415 for (i
= 0; i
< clicount
; i
++) {
416 for (j
= 0; j
< servcount
; j
++) {
417 if (!(servnames
[j
] && clinames
[i
])) {
418 /* unusable algos are NULL */
421 if (strcmp(servnames
[j
], clinames
[i
]) == 0) {
422 /* set if it was a good guess */
423 if (goodguess
&& kexguess2
) {
424 if (*kexguess2
== KEXGUESS2_YES
) {
430 if (i
== 0 && j
== 0) {
435 /* set the algo to return */
436 if (IS_DROPBEAR_SERVER
) {
437 ret
= &localalgos
[j
];
439 ret
= &localalgos
[i
];
451 #ifdef DROPBEAR_NONE_CIPHER
454 set_algo_usable(algo_type algos
[], const char * algo_name
, int usable
)
457 for (a
= algos
; a
->name
!= NULL
; a
++)
459 if (strcmp(a
->name
, algo_name
) == 0)
468 get_algo_usable(algo_type algos
[], const char * algo_name
)
471 for (a
= algos
; a
->name
!= NULL
; a
++)
473 if (strcmp(a
->name
, algo_name
) == 0)
481 #endif /* DROPBEAR_NONE_CIPHER */
483 #ifdef ENABLE_USER_ALGO_LIST
486 algolist_string(algo_type algos
[])
489 buffer
*b
= buf_new(200);
490 buf_put_algolist(b
, algos
);
491 buf_setpos(b
, b
->len
);
492 buf_putbyte(b
, '\0');
494 ret_list
= m_strdup((const char *) buf_getptr(b
, b
->len
- b
->pos
));
500 check_algo(const char* algo_name
, algo_type
*algos
)
503 for (a
= algos
; a
->name
!= NULL
; a
++)
505 if (strcmp(a
->name
, algo_name
) == 0)
515 try_add_algo(const char *algo_name
, algo_type
*algos
,
516 const char *algo_desc
, algo_type
* new_algos
, int *num_ret
)
518 algo_type
*match_algo
= check_algo(algo_name
, algos
);
521 dropbear_log(LOG_WARNING
, "This Dropbear program does not support '%s' %s algorithm", algo_name
, algo_desc
);
525 new_algos
[*num_ret
] = *match_algo
;
529 /* Checks a user provided comma-separated algorithm list for available
530 * options. Any that are not acceptable are removed in-place. Returns the
531 * number of valid algorithms. */
533 check_user_algos(const char* user_algo_list
, algo_type
* algos
,
534 const char *algo_desc
)
536 algo_type new_algos
[MAX_PROPOSED_ALGO
];
537 /* this has two passes. first we sweep through the given list of
538 * algorithms and mark them as usable=2 in the algo_type[] array... */
540 char *work_list
= m_strdup(user_algo_list
);
541 char *last_name
= work_list
;
543 for (c
= work_list
; *c
; c
++)
548 try_add_algo(last_name
, algos
, algo_desc
, new_algos
, &num_ret
);
553 try_add_algo(last_name
, algos
, algo_desc
, new_algos
, &num_ret
);
556 new_algos
[num_ret
].name
= NULL
;
558 /* Copy one more as a blank delimiter */
559 memcpy(algos
, new_algos
, sizeof(*new_algos
) * (num_ret
+1));
562 #endif /* ENABLE_USER_ALGO_LIST */