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 const struct dropbear_cipher_mode dropbear_mode_cbc
=
88 {(void*)cbc_start
, (void*)cbc_encrypt
, (void*)cbc_decrypt
};
89 const struct dropbear_cipher_mode dropbear_mode_none
=
90 {void_start
, void_cipher
, void_cipher
};
91 #ifdef DROPBEAR_ENABLE_CTR_MODE
92 /* a wrapper to make ctr_start and cbc_start look the same */
93 static int dropbear_big_endian_ctr_start(int cipher
,
94 const unsigned char *IV
,
95 const unsigned char *key
, int keylen
,
96 int num_rounds
, symmetric_CTR
*ctr
) {
97 return ctr_start(cipher
, IV
, key
, keylen
, num_rounds
, CTR_COUNTER_BIG_ENDIAN
, ctr
);
99 const struct dropbear_cipher_mode dropbear_mode_ctr
=
100 {(void*)dropbear_big_endian_ctr_start
, (void*)ctr_encrypt
, (void*)ctr_decrypt
};
103 /* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc.
104 {&hash_desc, keysize, hashsize} */
106 #ifdef DROPBEAR_SHA1_HMAC
107 static const struct dropbear_hash dropbear_sha1
=
108 {&sha1_desc
, 20, 20};
110 #ifdef DROPBEAR_SHA1_96_HMAC
111 static const struct dropbear_hash dropbear_sha1_96
=
112 {&sha1_desc
, 20, 12};
114 #ifdef DROPBEAR_SHA2_256_HMAC
115 static const struct dropbear_hash dropbear_sha2_256
=
116 {&sha256_desc
, 32, 32};
118 #ifdef DROPBEAR_SHA2_512_HMAC
119 static const struct dropbear_hash dropbear_sha2_512
=
120 {&sha512_desc
, 64, 64};
122 #ifdef DROPBEAR_MD5_HMAC
123 static const struct dropbear_hash dropbear_md5
=
127 const struct dropbear_hash dropbear_nohash
=
128 {NULL
, 16, 0}; /* used initially */
131 /* The following map ssh names to internal values.
132 * The ordering here is important for the client - the first mode
133 * that is also supported by the server will get used. */
135 algo_type sshciphers
[] = {
136 #ifdef DROPBEAR_ENABLE_CTR_MODE
137 #ifdef DROPBEAR_AES128
138 {"aes128-ctr", 0, &dropbear_aes128
, 1, &dropbear_mode_ctr
},
141 {"3des-ctr", 0, &dropbear_3des
, 1, &dropbear_mode_ctr
},
143 #ifdef DROPBEAR_AES256
144 {"aes256-ctr", 0, &dropbear_aes256
, 1, &dropbear_mode_ctr
},
146 #endif /* DROPBEAR_ENABLE_CTR_MODE */
148 /* CBC modes are always enabled */
149 #ifdef DROPBEAR_AES128
150 {"aes128-cbc", 0, &dropbear_aes128
, 1, &dropbear_mode_cbc
},
153 {"3des-cbc", 0, &dropbear_3des
, 1, &dropbear_mode_cbc
},
155 #ifdef DROPBEAR_AES256
156 {"aes256-cbc", 0, &dropbear_aes256
, 1, &dropbear_mode_cbc
},
158 #ifdef DROPBEAR_TWOFISH256
159 {"twofish256-cbc", 0, &dropbear_twofish256
, 1, &dropbear_mode_cbc
},
160 {"twofish-cbc", 0, &dropbear_twofish256
, 1, &dropbear_mode_cbc
},
162 #ifdef DROPBEAR_TWOFISH128
163 {"twofish128-cbc", 0, &dropbear_twofish128
, 1, &dropbear_mode_cbc
},
165 #ifdef DROPBEAR_BLOWFISH
166 {"blowfish-cbc", 0, &dropbear_blowfish
, 1, &dropbear_mode_cbc
},
168 #ifdef DROPBEAR_NONE_CIPHER
169 {"none", 0, (void*)&dropbear_nocipher
, 1, &dropbear_mode_none
},
171 {NULL
, 0, NULL
, 0, NULL
}
174 algo_type sshhashes
[] = {
175 #ifdef DROPBEAR_SHA2_256_HMAC
176 {"hmac-sha2-256", 0, &dropbear_sha2_256
, 1, NULL
},
178 #ifdef DROPBEAR_SHA2_512_HMAC
179 {"hmac-sha2-512", 0, &dropbear_sha2_512
, 1, NULL
},
181 #ifdef DROPBEAR_SHA1_96_HMAC
182 {"hmac-sha1-96", 0, &dropbear_sha1_96
, 1, NULL
},
184 #ifdef DROPBEAR_SHA1_HMAC
185 {"hmac-sha1", 0, &dropbear_sha1
, 1, NULL
},
187 #ifdef DROPBEAR_MD5_HMAC
188 {"hmac-md5", 0, (void*)&dropbear_md5
, 1, NULL
},
190 #ifdef DROPBEAR_NONE_INTEGRITY
191 {"none", 0, (void*)&dropbear_nohash
, 1, NULL
},
193 {NULL
, 0, NULL
, 0, NULL
}
197 algo_type ssh_compress
[] = {
198 {"zlib", DROPBEAR_COMP_ZLIB
, NULL
, 1, NULL
},
199 {"zlib@openssh.com", DROPBEAR_COMP_ZLIB_DELAY
, NULL
, 1, NULL
},
200 {"none", DROPBEAR_COMP_NONE
, NULL
, 1, NULL
},
201 {NULL
, 0, NULL
, 0, NULL
}
205 algo_type ssh_nocompress
[] = {
206 {"none", DROPBEAR_COMP_NONE
, NULL
, 1, NULL
},
207 {NULL
, 0, NULL
, 0, NULL
}
210 algo_type sshhostkey
[] = {
211 #ifdef DROPBEAR_ECDSA
212 #ifdef DROPBEAR_ECC_256
213 {"ecdsa-sha2-nistp256", DROPBEAR_SIGNKEY_ECDSA_NISTP256
, NULL
, 1, NULL
},
215 #ifdef DROPBEAR_ECC_384
216 {"ecdsa-sha2-nistp384", DROPBEAR_SIGNKEY_ECDSA_NISTP384
, NULL
, 1, NULL
},
218 #ifdef DROPBEAR_ECC_521
219 {"ecdsa-sha2-nistp521", DROPBEAR_SIGNKEY_ECDSA_NISTP521
, NULL
, 1, NULL
},
223 {"ssh-rsa", DROPBEAR_SIGNKEY_RSA
, NULL
, 1, NULL
},
226 {"ssh-dss", DROPBEAR_SIGNKEY_DSS
, NULL
, 1, NULL
},
228 {NULL
, 0, NULL
, 0, NULL
}
231 static const struct dropbear_kex kex_dh_group1
= {DROPBEAR_KEX_NORMAL_DH
, dh_p_1
, DH_P_1_LEN
, NULL
, &sha1_desc
};
232 static const struct dropbear_kex kex_dh_group14
= {DROPBEAR_KEX_NORMAL_DH
, dh_p_14
, DH_P_14_LEN
, NULL
, &sha1_desc
};
234 /* These can't be const since dropbear_ecc_fill_dp() fills out
235 ecc_curve at runtime */
237 #ifdef DROPBEAR_ECC_256
238 static struct dropbear_kex kex_ecdh_nistp256
= {DROPBEAR_KEX_ECDH
, NULL
, 0, &ecc_curve_nistp256
, &sha256_desc
};
240 #ifdef DROPBEAR_ECC_384
241 static struct dropbear_kex kex_ecdh_nistp384
= {DROPBEAR_KEX_ECDH
, NULL
, 0, &ecc_curve_nistp384
, &sha384_desc
};
243 #ifdef DROPBEAR_ECC_521
244 static struct dropbear_kex kex_ecdh_nistp521
= {DROPBEAR_KEX_ECDH
, NULL
, 0, &ecc_curve_nistp521
, &sha512_desc
};
246 #endif /* DROPBEAR_ECDH */
248 #ifdef DROPBEAR_CURVE25519
249 /* Referred to directly */
250 static const struct dropbear_kex kex_curve25519
= {DROPBEAR_KEX_CURVE25519
, NULL
, 0, NULL
, &sha256_desc
};
253 algo_type sshkex
[] = {
254 #ifdef DROPBEAR_CURVE25519
255 {"curve25519-sha256@libssh.org", 0, &kex_curve25519
, 1, NULL
},
258 #ifdef DROPBEAR_ECC_521
259 {"ecdh-sha2-nistp521", 0, &kex_ecdh_nistp521
, 1, NULL
},
261 #ifdef DROPBEAR_ECC_384
262 {"ecdh-sha2-nistp384", 0, &kex_ecdh_nistp384
, 1, NULL
},
264 #ifdef DROPBEAR_ECC_256
265 {"ecdh-sha2-nistp256", 0, &kex_ecdh_nistp256
, 1, NULL
},
268 {"diffie-hellman-group1-sha1", 0, &kex_dh_group1
, 1, NULL
},
269 {"diffie-hellman-group14-sha1", 0, &kex_dh_group14
, 1, NULL
},
271 {KEXGUESS2_ALGO_NAME
, KEXGUESS2_ALGO_ID
, NULL
, 1, NULL
},
273 {NULL
, 0, NULL
, 0, NULL
}
276 /* algolen specifies the length of algo, algos is our local list to match
278 * Returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE
280 int have_algo(char* algo
, size_t algolen
, algo_type algos
[]) {
284 for (i
= 0; algos
[i
].name
!= NULL
; i
++) {
285 if (strlen(algos
[i
].name
) == algolen
286 && (strncmp(algos
[i
].name
, algo
, algolen
) == 0)) {
287 return DROPBEAR_SUCCESS
;
291 return DROPBEAR_FAILURE
;
294 /* Output a comma separated list of algorithms to a buffer */
295 void buf_put_algolist(buffer
* buf
, algo_type localalgos
[]) {
298 unsigned int donefirst
= 0;
299 buffer
*algolist
= NULL
;
301 algolist
= buf_new(200);
302 for (i
= 0; localalgos
[i
].name
!= NULL
; i
++) {
303 if (localalgos
[i
].usable
) {
305 buf_putbyte(algolist
, ',');
307 len
= strlen(localalgos
[i
].name
);
308 buf_putbytes(algolist
, localalgos
[i
].name
, len
);
311 buf_putstring(buf
, algolist
->data
, algolist
->len
);
315 /* match the first algorithm in the comma-separated list in buf which is
316 * also in localalgos[], or return NULL on failure.
317 * (*goodguess) is set to 1 if the preferred client/server algos match,
318 * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
319 * guessed correctly */
320 algo_type
* buf_match_algo(buffer
* buf
, algo_type localalgos
[],
321 enum kexguess2_used
*kexguess2
, int *goodguess
)
324 unsigned char * algolist
= NULL
;
325 const unsigned char *remotenames
[MAX_PROPOSED_ALGO
], *localnames
[MAX_PROPOSED_ALGO
];
327 unsigned int remotecount
, localcount
, clicount
, servcount
, i
, j
;
328 algo_type
* ret
= NULL
;
329 const unsigned char **clinames
, **servnames
;
335 /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
336 algolist
= buf_getstring(buf
, &len
);
337 TRACE(("buf_match_algo: %s", algolist
))
338 if (len
> MAX_PROPOSED_ALGO
*(MAX_NAME_LEN
+1)) {
342 /* remotenames will contain a list of the strings parsed out */
343 /* We will have at least one string (even if it's just "") */
344 remotenames
[0] = algolist
;
346 for (i
= 0; i
< len
; i
++) {
347 if (algolist
[i
] == '\0') {
348 /* someone is trying something strange */
351 if (algolist
[i
] == ',') {
353 remotenames
[remotecount
] = &algolist
[i
+1];
356 if (remotecount
>= MAX_PROPOSED_ALGO
) {
360 if (kexguess2
&& *kexguess2
== KEXGUESS2_LOOK
) {
361 for (i
= 0; i
< remotecount
; i
++)
363 if (strcmp(remotenames
[i
], KEXGUESS2_ALGO_NAME
) == 0) {
364 *kexguess2
= KEXGUESS2_YES
;
368 if (*kexguess2
== KEXGUESS2_LOOK
) {
369 *kexguess2
= KEXGUESS2_NO
;
373 for (i
= 0; localalgos
[i
].name
!= NULL
; i
++) {
374 if (localalgos
[i
].usable
) {
375 localnames
[i
] = localalgos
[i
].name
;
377 localnames
[i
] = NULL
;
382 if (IS_DROPBEAR_SERVER
) {
383 clinames
= remotenames
;
384 clicount
= remotecount
;
385 servnames
= localnames
;
386 servcount
= localcount
;
388 clinames
= localnames
;
389 clicount
= localcount
;
390 servnames
= remotenames
;
391 servcount
= remotecount
;
394 /* iterate and find the first match */
395 for (i
= 0; i
< clicount
; i
++) {
396 for (j
= 0; j
< servcount
; j
++) {
397 if (!(servnames
[j
] && clinames
[i
])) {
398 /* unusable algos are NULL */
401 if (strcmp(servnames
[j
], clinames
[i
]) == 0) {
402 /* set if it was a good guess */
403 if (goodguess
&& kexguess2
) {
404 if (*kexguess2
== KEXGUESS2_YES
) {
410 if (i
== 0 && j
== 0) {
415 /* set the algo to return */
416 if (IS_DROPBEAR_SERVER
) {
417 ret
= &localalgos
[j
];
419 ret
= &localalgos
[i
];
431 #ifdef DROPBEAR_NONE_CIPHER
434 set_algo_usable(algo_type algos
[], const char * algo_name
, int usable
)
437 for (a
= algos
; a
->name
!= NULL
; a
++)
439 if (strcmp(a
->name
, algo_name
) == 0)
448 get_algo_usable(algo_type algos
[], const char * algo_name
)
451 for (a
= algos
; a
->name
!= NULL
; a
++)
453 if (strcmp(a
->name
, algo_name
) == 0)
461 #endif /* DROPBEAR_NONE_CIPHER */
463 #ifdef ENABLE_USER_ALGO_LIST
466 algolist_string(algo_type algos
[])
469 buffer
*b
= buf_new(200);
470 buf_put_algolist(b
, algos
);
471 buf_setpos(b
, b
->len
);
472 buf_putbyte(b
, '\0');
474 ret_list
= m_strdup(buf_getptr(b
, b
->len
- b
->pos
));
480 check_algo(const char* algo_name
, algo_type
*algos
)
483 for (a
= algos
; a
->name
!= NULL
; a
++)
485 if (strcmp(a
->name
, algo_name
) == 0)
495 try_add_algo(const char *algo_name
, algo_type
*algos
,
496 const char *algo_desc
, algo_type
* new_algos
, int *num_ret
)
498 algo_type
*match_algo
= check_algo(algo_name
, algos
);
501 dropbear_log(LOG_WARNING
, "This Dropbear program does not support '%s' %s algorithm", algo_name
, algo_desc
);
505 new_algos
[*num_ret
] = *match_algo
;
509 /* Checks a user provided comma-separated algorithm list for available
510 * options. Any that are not acceptable are removed in-place. Returns the
511 * number of valid algorithms. */
513 check_user_algos(const char* user_algo_list
, algo_type
* algos
,
514 const char *algo_desc
)
516 algo_type new_algos
[MAX_PROPOSED_ALGO
];
517 /* this has two passes. first we sweep through the given list of
518 * algorithms and mark them as usable=2 in the algo_type[] array... */
520 char *work_list
= m_strdup(user_algo_list
);
521 char *last_name
= work_list
;
523 for (c
= work_list
; *c
; c
++)
528 try_add_algo(last_name
, algos
, algo_desc
, new_algos
, &num_ret
);
533 try_add_algo(last_name
, algos
, algo_desc
, new_algos
, &num_ret
);
536 new_algos
[num_ret
].name
= NULL
;
538 /* Copy one more as a blank delimiter */
539 memcpy(algos
, new_algos
, sizeof(*new_algos
) * (num_ret
+1));
542 #endif /* ENABLE_USER_ALGO_LIST */