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
30 #include "dh_groups.h"
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 #if DROPBEAR_DH_GROUP1
252 static const struct dropbear_kex kex_dh_group1
= {DROPBEAR_KEX_NORMAL_DH
, dh_p_1
, DH_P_1_LEN
, NULL
, &sha1_desc
};
254 #if DROPBEAR_DH_GROUP14
255 static const struct dropbear_kex kex_dh_group14_sha1
= {DROPBEAR_KEX_NORMAL_DH
, dh_p_14
, DH_P_14_LEN
, NULL
, &sha1_desc
};
256 #if DROPBEAR_DH_GROUP14_256
257 static const struct dropbear_kex kex_dh_group14_sha256
= {DROPBEAR_KEX_NORMAL_DH
, dh_p_14
, DH_P_14_LEN
, NULL
, &sha256_desc
};
260 #if DROPBEAR_DH_GROUP16
261 static const struct dropbear_kex kex_dh_group16_sha512
= {DROPBEAR_KEX_NORMAL_DH
, dh_p_16
, DH_P_16_LEN
, NULL
, &sha512_desc
};
264 /* These can't be const since dropbear_ecc_fill_dp() fills out
265 ecc_curve at runtime */
267 #ifdef DROPBEAR_ECC_256
268 static const struct dropbear_kex kex_ecdh_nistp256
= {DROPBEAR_KEX_ECDH
, NULL
, 0, &ecc_curve_nistp256
, &sha256_desc
};
270 #ifdef DROPBEAR_ECC_384
271 static const struct dropbear_kex kex_ecdh_nistp384
= {DROPBEAR_KEX_ECDH
, NULL
, 0, &ecc_curve_nistp384
, &sha384_desc
};
273 #ifdef DROPBEAR_ECC_521
274 static const struct dropbear_kex kex_ecdh_nistp521
= {DROPBEAR_KEX_ECDH
, NULL
, 0, &ecc_curve_nistp521
, &sha512_desc
};
276 #endif /* DROPBEAR_ECDH */
278 #ifdef DROPBEAR_CURVE25519
279 /* Referred to directly */
280 static const struct dropbear_kex kex_curve25519
= {DROPBEAR_KEX_CURVE25519
, NULL
, 0, NULL
, &sha256_desc
};
283 algo_type sshkex
[] = {
284 #ifdef DROPBEAR_CURVE25519
285 {"curve25519-sha256@libssh.org", 0, &kex_curve25519
, 1, NULL
},
288 #ifdef DROPBEAR_ECC_521
289 {"ecdh-sha2-nistp521", 0, &kex_ecdh_nistp521
, 1, NULL
},
291 #ifdef DROPBEAR_ECC_384
292 {"ecdh-sha2-nistp384", 0, &kex_ecdh_nistp384
, 1, NULL
},
294 #ifdef DROPBEAR_ECC_256
295 {"ecdh-sha2-nistp256", 0, &kex_ecdh_nistp256
, 1, NULL
},
298 #if DROPBEAR_DH_GROUP14
299 #if DROPBEAR_DH_GROUP14_256
300 {"diffie-hellman-group14-sha256", 0, &kex_dh_group14_sha256
, 1, NULL
},
302 {"diffie-hellman-group14-sha1", 0, &kex_dh_group14_sha1
, 1, NULL
},
304 #if DROPBEAR_DH_GROUP1
305 {"diffie-hellman-group1-sha1", 0, &kex_dh_group1
, 1, NULL
},
307 #if DROPBEAR_DH_GROUP16
308 {"diffie-hellman-group16-sha512", 0, &kex_dh_group16_sha512
, 1, NULL
},
311 {KEXGUESS2_ALGO_NAME
, KEXGUESS2_ALGO_ID
, NULL
, 1, NULL
},
313 {NULL
, 0, NULL
, 0, NULL
}
316 /* algolen specifies the length of algo, algos is our local list to match
318 * Returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE
320 int have_algo(char* algo
, size_t algolen
, algo_type algos
[]) {
324 for (i
= 0; algos
[i
].name
!= NULL
; i
++) {
325 if (strlen(algos
[i
].name
) == algolen
326 && (strncmp(algos
[i
].name
, algo
, algolen
) == 0)) {
327 return DROPBEAR_SUCCESS
;
331 return DROPBEAR_FAILURE
;
334 /* Output a comma separated list of algorithms to a buffer */
335 void buf_put_algolist(buffer
* buf
, algo_type localalgos
[]) {
338 unsigned int donefirst
= 0;
339 buffer
*algolist
= NULL
;
341 algolist
= buf_new(300);
342 for (i
= 0; localalgos
[i
].name
!= NULL
; i
++) {
343 if (localalgos
[i
].usable
) {
345 buf_putbyte(algolist
, ',');
347 len
= strlen(localalgos
[i
].name
);
348 buf_putbytes(algolist
, (const unsigned char *) localalgos
[i
].name
, len
);
351 buf_putstring(buf
, (const char*)algolist
->data
, algolist
->len
);
355 /* match the first algorithm in the comma-separated list in buf which is
356 * also in localalgos[], or return NULL on failure.
357 * (*goodguess) is set to 1 if the preferred client/server algos match,
358 * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
359 * guessed correctly */
360 algo_type
* buf_match_algo(buffer
* buf
, algo_type localalgos
[],
361 enum kexguess2_used
*kexguess2
, int *goodguess
)
364 char * algolist
= NULL
;
365 const char *remotenames
[MAX_PROPOSED_ALGO
], *localnames
[MAX_PROPOSED_ALGO
];
367 unsigned int remotecount
, localcount
, clicount
, servcount
, i
, j
;
368 algo_type
* ret
= NULL
;
369 const char **clinames
, **servnames
;
375 /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
376 algolist
= buf_getstring(buf
, &len
);
377 TRACE(("buf_match_algo: %s", algolist
))
378 if (len
> MAX_PROPOSED_ALGO
*(MAX_NAME_LEN
+1)) {
382 /* remotenames will contain a list of the strings parsed out */
383 /* We will have at least one string (even if it's just "") */
384 remotenames
[0] = algolist
;
386 for (i
= 0; i
< len
; i
++) {
387 if (algolist
[i
] == '\0') {
388 /* someone is trying something strange */
391 if (algolist
[i
] == ',') {
393 remotenames
[remotecount
] = &algolist
[i
+1];
396 if (remotecount
>= MAX_PROPOSED_ALGO
) {
400 if (kexguess2
&& *kexguess2
== KEXGUESS2_LOOK
) {
401 for (i
= 0; i
< remotecount
; i
++)
403 if (strcmp(remotenames
[i
], KEXGUESS2_ALGO_NAME
) == 0) {
404 *kexguess2
= KEXGUESS2_YES
;
408 if (*kexguess2
== KEXGUESS2_LOOK
) {
409 *kexguess2
= KEXGUESS2_NO
;
413 for (i
= 0; localalgos
[i
].name
!= NULL
; i
++) {
414 if (localalgos
[i
].usable
) {
415 localnames
[i
] = localalgos
[i
].name
;
417 localnames
[i
] = NULL
;
422 if (IS_DROPBEAR_SERVER
) {
423 clinames
= remotenames
;
424 clicount
= remotecount
;
425 servnames
= localnames
;
426 servcount
= localcount
;
428 clinames
= localnames
;
429 clicount
= localcount
;
430 servnames
= remotenames
;
431 servcount
= remotecount
;
434 /* iterate and find the first match */
435 for (i
= 0; i
< clicount
; i
++) {
436 for (j
= 0; j
< servcount
; j
++) {
437 if (!(servnames
[j
] && clinames
[i
])) {
438 /* unusable algos are NULL */
441 if (strcmp(servnames
[j
], clinames
[i
]) == 0) {
442 /* set if it was a good guess */
443 if (goodguess
&& kexguess2
) {
444 if (*kexguess2
== KEXGUESS2_YES
) {
450 if (i
== 0 && j
== 0) {
455 /* set the algo to return */
456 if (IS_DROPBEAR_SERVER
) {
457 ret
= &localalgos
[j
];
459 ret
= &localalgos
[i
];
471 #ifdef DROPBEAR_NONE_CIPHER
474 set_algo_usable(algo_type algos
[], const char * algo_name
, int usable
)
477 for (a
= algos
; a
->name
!= NULL
; a
++)
479 if (strcmp(a
->name
, algo_name
) == 0)
488 get_algo_usable(algo_type algos
[], const char * algo_name
)
491 for (a
= algos
; a
->name
!= NULL
; a
++)
493 if (strcmp(a
->name
, algo_name
) == 0)
501 #endif /* DROPBEAR_NONE_CIPHER */
503 #ifdef ENABLE_USER_ALGO_LIST
506 algolist_string(algo_type algos
[])
509 buffer
*b
= buf_new(200);
510 buf_put_algolist(b
, algos
);
511 buf_setpos(b
, b
->len
);
512 buf_putbyte(b
, '\0');
514 ret_list
= m_strdup((const char *) buf_getptr(b
, b
->len
- b
->pos
));
520 check_algo(const char* algo_name
, algo_type
*algos
)
523 for (a
= algos
; a
->name
!= NULL
; a
++)
525 if (strcmp(a
->name
, algo_name
) == 0)
535 try_add_algo(const char *algo_name
, algo_type
*algos
,
536 const char *algo_desc
, algo_type
* new_algos
, int *num_ret
)
538 algo_type
*match_algo
= check_algo(algo_name
, algos
);
541 dropbear_log(LOG_WARNING
, "This Dropbear program does not support '%s' %s algorithm", algo_name
, algo_desc
);
545 new_algos
[*num_ret
] = *match_algo
;
549 /* Checks a user provided comma-separated algorithm list for available
550 * options. Any that are not acceptable are removed in-place. Returns the
551 * number of valid algorithms. */
553 check_user_algos(const char* user_algo_list
, algo_type
* algos
,
554 const char *algo_desc
)
556 algo_type new_algos
[MAX_PROPOSED_ALGO
];
557 /* this has two passes. first we sweep through the given list of
558 * algorithms and mark them as usable=2 in the algo_type[] array... */
560 char *work_list
= m_strdup(user_algo_list
);
561 char *last_name
= work_list
;
563 for (c
= work_list
; *c
; c
++)
568 try_add_algo(last_name
, algos
, algo_desc
, new_algos
, &num_ret
);
573 try_add_algo(last_name
, algos
, algo_desc
, new_algos
, &num_ret
);
576 new_algos
[num_ret
].name
= NULL
;
578 /* Copy one more as a blank delimiter */
579 memcpy(algos
, new_algos
, sizeof(*new_algos
) * (num_ret
+1));
582 #endif /* ENABLE_USER_ALGO_LIST */