comparison common-algo.c @ 1733:d529a52b2f7c coverity coverity

merge coverity from main
author Matt Johnston <matt@ucc.asn.au>
date Fri, 26 Jun 2020 21:07:34 +0800
parents c2c0f43ff827
children 7c0fcd19e492
comparison
equal deleted inserted replaced
1643:b59623a64678 1733:d529a52b2f7c
28 #include "session.h" 28 #include "session.h"
29 #include "dbutil.h" 29 #include "dbutil.h"
30 #include "dh_groups.h" 30 #include "dh_groups.h"
31 #include "ltc_prng.h" 31 #include "ltc_prng.h"
32 #include "ecc.h" 32 #include "ecc.h"
33 #include "gcm.h"
34 #include "chachapoly.h"
35 #include "ssh.h"
33 36
34 /* This file (algo.c) organises the ciphers which can be used, and is used to 37 /* 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*/ 38 * decide which ciphers/hashes/compression/signing to use during key exchange*/
36 39
37 static int void_cipher(const unsigned char* in, unsigned char* out, 40 static int void_cipher(const unsigned char* in, unsigned char* out,
59 #endif 62 #endif
60 #if DROPBEAR_AES128 63 #if DROPBEAR_AES128
61 static const struct dropbear_cipher dropbear_aes128 = 64 static const struct dropbear_cipher dropbear_aes128 =
62 {&aes_desc, 16, 16}; 65 {&aes_desc, 16, 16};
63 #endif 66 #endif
64 #if DROPBEAR_BLOWFISH
65 static const struct dropbear_cipher dropbear_blowfish =
66 {&blowfish_desc, 16, 8};
67 #endif
68 #if DROPBEAR_TWOFISH256 67 #if DROPBEAR_TWOFISH256
69 static const struct dropbear_cipher dropbear_twofish256 = 68 static const struct dropbear_cipher dropbear_twofish256 =
70 {&twofish_desc, 32, 16}; 69 {&twofish_desc, 32, 16};
71 #endif 70 #endif
72 #if DROPBEAR_TWOFISH128 71 #if DROPBEAR_TWOFISH128
84 83
85 /* A few void* s are required to silence warnings 84 /* A few void* s are required to silence warnings
86 * about the symmetric_CBC vs symmetric_CTR cipher_state pointer */ 85 * about the symmetric_CBC vs symmetric_CTR cipher_state pointer */
87 #if DROPBEAR_ENABLE_CBC_MODE 86 #if DROPBEAR_ENABLE_CBC_MODE
88 const struct dropbear_cipher_mode dropbear_mode_cbc = 87 const struct dropbear_cipher_mode dropbear_mode_cbc =
89 {(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt}; 88 {(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt, NULL, NULL, NULL};
90 #endif /* DROPBEAR_ENABLE_CBC_MODE */ 89 #endif /* DROPBEAR_ENABLE_CBC_MODE */
91 90
92 const struct dropbear_cipher_mode dropbear_mode_none = 91 const struct dropbear_cipher_mode dropbear_mode_none =
93 {void_start, void_cipher, void_cipher}; 92 {void_start, void_cipher, void_cipher, NULL, NULL, NULL};
94 93
95 #if DROPBEAR_ENABLE_CTR_MODE 94 #if DROPBEAR_ENABLE_CTR_MODE
96 /* a wrapper to make ctr_start and cbc_start look the same */ 95 /* a wrapper to make ctr_start and cbc_start look the same */
97 static int dropbear_big_endian_ctr_start(int cipher, 96 static int dropbear_big_endian_ctr_start(int cipher,
98 const unsigned char *IV, 97 const unsigned char *IV,
99 const unsigned char *key, int keylen, 98 const unsigned char *key, int keylen,
100 int num_rounds, symmetric_CTR *ctr) { 99 int num_rounds, symmetric_CTR *ctr) {
101 return ctr_start(cipher, IV, key, keylen, num_rounds, CTR_COUNTER_BIG_ENDIAN, ctr); 100 return ctr_start(cipher, IV, key, keylen, num_rounds, CTR_COUNTER_BIG_ENDIAN, ctr);
102 } 101 }
103 const struct dropbear_cipher_mode dropbear_mode_ctr = 102 const struct dropbear_cipher_mode dropbear_mode_ctr =
104 {(void*)dropbear_big_endian_ctr_start, (void*)ctr_encrypt, (void*)ctr_decrypt}; 103 {(void*)dropbear_big_endian_ctr_start, (void*)ctr_encrypt, (void*)ctr_decrypt, NULL, NULL, NULL};
105 #endif /* DROPBEAR_ENABLE_CTR_MODE */ 104 #endif /* DROPBEAR_ENABLE_CTR_MODE */
106 105
107 /* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc. 106 /* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc.
108 {&hash_desc, keysize, hashsize} */ 107 {&hash_desc, keysize, hashsize} */
109 108
135 /* The following map ssh names to internal values. 134 /* The following map ssh names to internal values.
136 * The ordering here is important for the client - the first mode 135 * The ordering here is important for the client - the first mode
137 * that is also supported by the server will get used. */ 136 * that is also supported by the server will get used. */
138 137
139 algo_type sshciphers[] = { 138 algo_type sshciphers[] = {
139 #if DROPBEAR_CHACHA20POLY1305
140 {"[email protected]", 0, &dropbear_chachapoly, 1, &dropbear_mode_chachapoly},
141 #endif
142
143 #if DROPBEAR_ENABLE_GCM_MODE
144 #if DROPBEAR_AES128
145 {"[email protected]", 0, &dropbear_aes128, 1, &dropbear_mode_gcm},
146 #endif
147 #if DROPBEAR_AES256
148 {"[email protected]", 0, &dropbear_aes256, 1, &dropbear_mode_gcm},
149 #endif
150 #endif /* DROPBEAR_ENABLE_GCM_MODE */
151
140 #if DROPBEAR_ENABLE_CTR_MODE 152 #if DROPBEAR_ENABLE_CTR_MODE
141 #if DROPBEAR_AES128 153 #if DROPBEAR_AES128
142 {"aes128-ctr", 0, &dropbear_aes128, 1, &dropbear_mode_ctr}, 154 {"aes128-ctr", 0, &dropbear_aes128, 1, &dropbear_mode_ctr},
143 #endif 155 #endif
144 #if DROPBEAR_AES256 156 #if DROPBEAR_AES256
167 {"twofish-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc}, 179 {"twofish-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
168 #endif 180 #endif
169 #if DROPBEAR_TWOFISH128 181 #if DROPBEAR_TWOFISH128
170 {"twofish128-cbc", 0, &dropbear_twofish128, 1, &dropbear_mode_cbc}, 182 {"twofish128-cbc", 0, &dropbear_twofish128, 1, &dropbear_mode_cbc},
171 #endif 183 #endif
184 #endif /* DROPBEAR_ENABLE_CBC_MODE */
185
172 #if DROPBEAR_3DES 186 #if DROPBEAR_3DES
187 #if DROPBEAR_ENABLE_CTR_MODE
173 {"3des-ctr", 0, &dropbear_3des, 1, &dropbear_mode_ctr}, 188 {"3des-ctr", 0, &dropbear_3des, 1, &dropbear_mode_ctr},
174 #endif 189 #endif
175 #if DROPBEAR_3DES 190 #if DROPBEAR_ENABLE_CBC_MODE
176 {"3des-cbc", 0, &dropbear_3des, 1, &dropbear_mode_cbc}, 191 {"3des-cbc", 0, &dropbear_3des, 1, &dropbear_mode_cbc},
177 #endif 192 #endif
178 #if DROPBEAR_BLOWFISH 193 #endif /* DROPBEAR_3DES */
179 {"blowfish-cbc", 0, &dropbear_blowfish, 1, &dropbear_mode_cbc}, 194
180 #endif 195 #if DROPBEAR_ENABLE_CBC_MODE
181 #endif /* DROPBEAR_ENABLE_CBC_MODE */ 196 #endif /* DROPBEAR_ENABLE_CBC_MODE */
182 {NULL, 0, NULL, 0, NULL} 197 {NULL, 0, NULL, 0, NULL}
183 }; 198 };
184 199
185 algo_type sshhashes[] = { 200 algo_type sshhashes[] = {
219 algo_type ssh_nocompress[] = { 234 algo_type ssh_nocompress[] = {
220 {"none", DROPBEAR_COMP_NONE, NULL, 1, NULL}, 235 {"none", DROPBEAR_COMP_NONE, NULL, 1, NULL},
221 {NULL, 0, NULL, 0, NULL} 236 {NULL, 0, NULL, 0, NULL}
222 }; 237 };
223 238
224 algo_type sshhostkey[] = { 239 algo_type sigalgs[] = {
240 #if DROPBEAR_ED25519
241 {"ssh-ed25519", DROPBEAR_SIGNATURE_ED25519, NULL, 1, NULL},
242 #endif
225 #if DROPBEAR_ECDSA 243 #if DROPBEAR_ECDSA
226 #if DROPBEAR_ECC_256 244 #if DROPBEAR_ECC_256
227 {"ecdsa-sha2-nistp256", DROPBEAR_SIGNKEY_ECDSA_NISTP256, NULL, 1, NULL}, 245 {"ecdsa-sha2-nistp256", DROPBEAR_SIGNATURE_ECDSA_NISTP256, NULL, 1, NULL},
228 #endif 246 #endif
229 #if DROPBEAR_ECC_384 247 #if DROPBEAR_ECC_384
230 {"ecdsa-sha2-nistp384", DROPBEAR_SIGNKEY_ECDSA_NISTP384, NULL, 1, NULL}, 248 {"ecdsa-sha2-nistp384", DROPBEAR_SIGNATURE_ECDSA_NISTP384, NULL, 1, NULL},
231 #endif 249 #endif
232 #if DROPBEAR_ECC_521 250 #if DROPBEAR_ECC_521
233 {"ecdsa-sha2-nistp521", DROPBEAR_SIGNKEY_ECDSA_NISTP521, NULL, 1, NULL}, 251 {"ecdsa-sha2-nistp521", DROPBEAR_SIGNATURE_ECDSA_NISTP521, NULL, 1, NULL},
234 #endif 252 #endif
235 #endif 253 #endif
236 #if DROPBEAR_RSA 254 #if DROPBEAR_RSA
237 {"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1, NULL}, 255 #if DROPBEAR_RSA_SHA256
256 {"rsa-sha2-256", DROPBEAR_SIGNATURE_RSA_SHA256, NULL, 1, NULL},
257 #endif
258 #if DROPBEAR_RSA_SHA1
259 {"ssh-rsa", DROPBEAR_SIGNATURE_RSA_SHA1, NULL, 1, NULL},
260 #endif
238 #endif 261 #endif
239 #if DROPBEAR_DSS 262 #if DROPBEAR_DSS
240 {"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1, NULL}, 263 {"ssh-dss", DROPBEAR_SIGNATURE_DSS, NULL, 1, NULL},
241 #endif 264 #endif
242 {NULL, 0, NULL, 0, NULL} 265 {NULL, 0, NULL, 0, NULL}
243 }; 266 };
244 267
245 #if DROPBEAR_DH_GROUP1 268 #if DROPBEAR_DH_GROUP1
253 #endif 276 #endif
254 #if DROPBEAR_DH_GROUP16 277 #if DROPBEAR_DH_GROUP16
255 static const struct dropbear_kex kex_dh_group16_sha512 = {DROPBEAR_KEX_NORMAL_DH, dh_p_16, DH_P_16_LEN, NULL, &sha512_desc }; 278 static const struct dropbear_kex kex_dh_group16_sha512 = {DROPBEAR_KEX_NORMAL_DH, dh_p_16, DH_P_16_LEN, NULL, &sha512_desc };
256 #endif 279 #endif
257 280
258 /* These can't be const since dropbear_ecc_fill_dp() fills out
259 ecc_curve at runtime */
260 #if DROPBEAR_ECDH 281 #if DROPBEAR_ECDH
261 #if DROPBEAR_ECC_256 282 #if DROPBEAR_ECC_256
262 static const struct dropbear_kex kex_ecdh_nistp256 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp256, &sha256_desc }; 283 static const struct dropbear_kex kex_ecdh_nistp256 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp256, &sha256_desc };
263 #endif 284 #endif
264 #if DROPBEAR_ECC_384 285 #if DROPBEAR_ECC_384
272 #if DROPBEAR_CURVE25519 293 #if DROPBEAR_CURVE25519
273 /* Referred to directly */ 294 /* Referred to directly */
274 static const struct dropbear_kex kex_curve25519 = {DROPBEAR_KEX_CURVE25519, NULL, 0, NULL, &sha256_desc }; 295 static const struct dropbear_kex kex_curve25519 = {DROPBEAR_KEX_CURVE25519, NULL, 0, NULL, &sha256_desc };
275 #endif 296 #endif
276 297
298 /* data == NULL for non-kex algorithm identifiers */
277 algo_type sshkex[] = { 299 algo_type sshkex[] = {
278 #if DROPBEAR_CURVE25519 300 #if DROPBEAR_CURVE25519
279 {"curve25519-sha256", 0, &kex_curve25519, 1, NULL}, 301 {"curve25519-sha256", 0, &kex_curve25519, 1, NULL},
280 {"[email protected]", 0, &kex_curve25519, 1, NULL}, 302 {"[email protected]", 0, &kex_curve25519, 1, NULL},
281 #endif 303 #endif
301 #endif 323 #endif
302 #if DROPBEAR_DH_GROUP16 324 #if DROPBEAR_DH_GROUP16
303 {"diffie-hellman-group16-sha512", 0, &kex_dh_group16_sha512, 1, NULL}, 325 {"diffie-hellman-group16-sha512", 0, &kex_dh_group16_sha512, 1, NULL},
304 #endif 326 #endif
305 #if DROPBEAR_KEXGUESS2 327 #if DROPBEAR_KEXGUESS2
306 {KEXGUESS2_ALGO_NAME, KEXGUESS2_ALGO_ID, NULL, 1, NULL}, 328 {KEXGUESS2_ALGO_NAME, 0, NULL, 1, NULL},
329 #endif
330 #if DROPBEAR_EXT_INFO
331 #if DROPBEAR_CLIENT
332 /* Set unusable by svr_algos_initialise() */
333 {SSH_EXT_INFO_C, 0, NULL, 1, NULL},
334 #endif
307 #endif 335 #endif
308 {NULL, 0, NULL, 0, NULL} 336 {NULL, 0, NULL, 0, NULL}
309 }; 337 };
310 338
311 /* algolen specifies the length of algo, algos is our local list to match
312 * against.
313 * Returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE
314 * otherwise */
315 int have_algo(const char* algo, size_t algolen, const algo_type algos[]) {
316
317 int i;
318
319 for (i = 0; algos[i].name != NULL; i++) {
320 if (strlen(algos[i].name) == algolen
321 && (strncmp(algos[i].name, algo, algolen) == 0)) {
322 return DROPBEAR_SUCCESS;
323 }
324 }
325
326 return DROPBEAR_FAILURE;
327 }
328
329 /* Output a comma separated list of algorithms to a buffer */ 339 /* Output a comma separated list of algorithms to a buffer */
330 void buf_put_algolist(buffer * buf, const algo_type localalgos[]) { 340 void buf_put_algolist_all(buffer * buf, const algo_type localalgos[], int useall) {
331
332 unsigned int i, len; 341 unsigned int i, len;
333 unsigned int donefirst = 0; 342 unsigned int donefirst = 0;
334 buffer *algolist = NULL; 343 unsigned int startpos;
335 344
336 algolist = buf_new(300); 345 startpos = buf->pos;
346 /* Placeholder for length */
347 buf_putint(buf, 0);
337 for (i = 0; localalgos[i].name != NULL; i++) { 348 for (i = 0; localalgos[i].name != NULL; i++) {
338 if (localalgos[i].usable) { 349 if (localalgos[i].usable || useall) {
339 if (donefirst) 350 if (donefirst) {
340 buf_putbyte(algolist, ','); 351 buf_putbyte(buf, ',');
352 }
341 donefirst = 1; 353 donefirst = 1;
342 len = strlen(localalgos[i].name); 354 len = strlen(localalgos[i].name);
343 buf_putbytes(algolist, (const unsigned char *) localalgos[i].name, len); 355 buf_putbytes(buf, (const unsigned char *) localalgos[i].name, len);
344 } 356 }
345 } 357 }
346 buf_putstring(buf, (const char*)algolist->data, algolist->len); 358 /* Fill out the length */
347 TRACE(("algolist add '%*s'", algolist->len, algolist->data)) 359 len = buf->pos - startpos - 4;
348 buf_free(algolist); 360 buf_setpos(buf, startpos);
361 buf_putint(buf, len);
362 TRACE(("algolist add %d '%*s'", len, len, buf_getptr(buf, len)))
363 buf_incrwritepos(buf, len);
364 }
365
366 void buf_put_algolist(buffer * buf, const algo_type localalgos[]) {
367 buf_put_algolist_all(buf, localalgos, 0);
368 }
369
370 /* returns a list of pointers into algolist, of null-terminated names.
371 ret_list should be passed in with space for *ret_count elements,
372 on return *ret_count has the number of names filled.
373 algolist is modified. */
374 static void get_algolist(char* algolist, unsigned int algolist_len,
375 const char* *ret_list, unsigned int *ret_count) {
376 unsigned int max_count = *ret_count;
377 unsigned int i;
378
379 if (*ret_count == 0) {
380 return;
381 }
382 if (algolist_len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
383 *ret_count = 0;
384 }
385
386 /* ret_list will contain a list of the strings parsed out.
387 We will have at least one string (even if it's just "") */
388 ret_list[0] = algolist;
389 *ret_count = 1;
390 for (i = 0; i < algolist_len; i++) {
391 if (algolist[i] == '\0') {
392 /* someone is trying something strange */
393 *ret_count = 0;
394 return;
395 }
396
397 if (algolist[i] == ',') {
398 if (*ret_count >= max_count) {
399 /* Too many */
400 *ret_count = 0;
401 return;
402 }
403 algolist[i] = '\0';
404 ret_list[*ret_count] = &algolist[i+1];
405 (*ret_count)++;
406 }
407 }
408 }
409
410 /* Return DROPBEAR_SUCCESS if the namelist contains algo,
411 DROPBEAR_FAILURE otherwise. buf position is not incremented. */
412 int buf_has_algo(buffer *buf, const char *algo) {
413 unsigned char* algolist = NULL;
414 unsigned int orig_pos = buf->pos;
415 unsigned int len, remotecount, i;
416 const char *remotenames[MAX_PROPOSED_ALGO];
417 int ret = DROPBEAR_FAILURE;
418
419 algolist = buf_getstring(buf, &len);
420 remotecount = MAX_PROPOSED_ALGO;
421 get_algolist(algolist, len, remotenames, &remotecount);
422 for (i = 0; i < remotecount; i++)
423 {
424 if (strcmp(remotenames[i], algo) == 0) {
425 ret = DROPBEAR_SUCCESS;
426 break;
427 }
428 }
429 if (algolist) {
430 m_free(algolist);
431 }
432 buf_setpos(buf, orig_pos);
433 return ret;
434 }
435
436 algo_type * first_usable_algo(algo_type algos[]) {
437 int i;
438 for (i = 0; algos[i].name != NULL; i++) {
439 if (algos[i].usable) {
440 return &algos[i];
441 }
442 }
443 return NULL;
349 } 444 }
350 445
351 /* match the first algorithm in the comma-separated list in buf which is 446 /* match the first algorithm in the comma-separated list in buf which is
352 * also in localalgos[], or return NULL on failure. 447 * also in localalgos[], or return NULL on failure.
353 * (*goodguess) is set to 1 if the preferred client/server algos match, 448 * (*goodguess) is set to 1 if the preferred client/server algos match,
354 * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are 449 * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
355 * guessed correctly */ 450 * guessed correctly */
356 algo_type * buf_match_algo(buffer* buf, algo_type localalgos[], 451 algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
357 enum kexguess2_used *kexguess2, int *goodguess) 452 int kexguess2, int *goodguess) {
358 {
359
360 char * algolist = NULL; 453 char * algolist = NULL;
361 const char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO]; 454 const char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO];
362 unsigned int len; 455 unsigned int len;
363 unsigned int remotecount, localcount, clicount, servcount, i, j; 456 unsigned int remotecount, localcount, clicount, servcount, i, j;
364 algo_type * ret = NULL; 457 algo_type * ret = NULL;
369 } 462 }
370 463
371 /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */ 464 /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
372 algolist = buf_getstring(buf, &len); 465 algolist = buf_getstring(buf, &len);
373 TRACE(("buf_match_algo: %s", algolist)) 466 TRACE(("buf_match_algo: %s", algolist))
374 if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) { 467 remotecount = MAX_PROPOSED_ALGO;
375 goto out; 468 get_algolist(algolist, len, remotenames, &remotecount);
376 }
377
378 /* remotenames will contain a list of the strings parsed out */
379 /* We will have at least one string (even if it's just "") */
380 remotenames[0] = algolist;
381 remotecount = 1;
382 for (i = 0; i < len; i++) {
383 if (algolist[i] == '\0') {
384 /* someone is trying something strange */
385 goto out;
386 }
387 if (algolist[i] == ',') {
388 algolist[i] = '\0';
389 remotenames[remotecount] = &algolist[i+1];
390 remotecount++;
391 }
392 if (remotecount >= MAX_PROPOSED_ALGO) {
393 break;
394 }
395 }
396 if (kexguess2 && *kexguess2 == KEXGUESS2_LOOK) {
397 for (i = 0; i < remotecount; i++)
398 {
399 if (strcmp(remotenames[i], KEXGUESS2_ALGO_NAME) == 0) {
400 *kexguess2 = KEXGUESS2_YES;
401 break;
402 }
403 }
404 if (*kexguess2 == KEXGUESS2_LOOK) {
405 *kexguess2 = KEXGUESS2_NO;
406 }
407 }
408 469
409 for (i = 0; localalgos[i].name != NULL; i++) { 470 for (i = 0; localalgos[i].name != NULL; i++) {
410 if (localalgos[i].usable) { 471 if (localalgos[i].usable) {
411 localnames[i] = localalgos[i].name; 472 localnames[i] = localalgos[i].name;
412 } else { 473 } else {
434 /* unusable algos are NULL */ 495 /* unusable algos are NULL */
435 continue; 496 continue;
436 } 497 }
437 if (strcmp(servnames[j], clinames[i]) == 0) { 498 if (strcmp(servnames[j], clinames[i]) == 0) {
438 /* set if it was a good guess */ 499 /* set if it was a good guess */
439 if (goodguess && kexguess2) { 500 if (goodguess != NULL) {
440 if (*kexguess2 == KEXGUESS2_YES) { 501 if (kexguess2) {
441 if (i == 0) { 502 if (i == 0) {
442 *goodguess = 1; 503 *goodguess = 1;
443 } 504 }
444
445 } else { 505 } else {
446 if (i == 0 && j == 0) { 506 if (i == 0 && j == 0) {
447 *goodguess = 1; 507 *goodguess = 1;
448 } 508 }
449 } 509 }