Home | History | Annotate | Download | only in dropbear
      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:
     14  *
     15  * The above copyright notice and this permission notice shall be included in
     16  * all copies or substantial portions of the Software.
     17  *
     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. */
     25 
     26 #include "algo.h"
     27 #include "dbutil.h"
     28 
     29 /* This file (algo.c) organises the ciphers which can be used, and is used to
     30  * decide which ciphers/hashes/compression/signing to use during key exchange*/
     31 
     32 /* Mappings for ciphers, parameters are
     33    {&cipher_desc, keysize, blocksize} */
     34 /* NOTE: if keysize > 2*SHA1_HASH_SIZE, code such as hashkeys()
     35    needs revisiting */
     36 
     37 #ifdef DROPBEAR_AES256_CBC
     38 static const struct dropbear_cipher dropbear_aes256 =
     39 	{&aes_desc, 32, 16};
     40 #endif
     41 #ifdef DROPBEAR_AES128_CBC
     42 static const struct dropbear_cipher dropbear_aes128 =
     43 	{&aes_desc, 16, 16};
     44 #endif
     45 #ifdef DROPBEAR_BLOWFISH_CBC
     46 static const struct dropbear_cipher dropbear_blowfish =
     47 	{&blowfish_desc, 16, 8};
     48 #endif
     49 #ifdef DROPBEAR_TWOFISH256_CBC
     50 static const struct dropbear_cipher dropbear_twofish256 =
     51 	{&twofish_desc, 32, 16};
     52 #endif
     53 #ifdef DROPBEAR_TWOFISH128_CBC
     54 static const struct dropbear_cipher dropbear_twofish128 =
     55 	{&twofish_desc, 16, 16};
     56 #endif
     57 #ifdef DROPBEAR_3DES_CBC
     58 static const struct dropbear_cipher dropbear_3des =
     59 	{&des3_desc, 24, 8};
     60 #endif
     61 
     62 /* used to indicate no encryption, as defined in rfc2410 */
     63 const struct dropbear_cipher dropbear_nocipher =
     64 	{NULL, 16, 8};
     65 
     66 /* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc.
     67    {&hash_desc, keysize, hashsize} */
     68 
     69 #ifdef DROPBEAR_SHA1_HMAC
     70 static const struct dropbear_hash dropbear_sha1 =
     71 	{&sha1_desc, 20, 20};
     72 #endif
     73 #ifdef DROPBEAR_SHA1_96_HMAC
     74 static const struct dropbear_hash dropbear_sha1_96 =
     75 	{&sha1_desc, 20, 12};
     76 #endif
     77 #ifdef DROPBEAR_MD5_HMAC
     78 static const struct dropbear_hash dropbear_md5 =
     79 	{&md5_desc, 16, 16};
     80 #endif
     81 
     82 const struct dropbear_hash dropbear_nohash =
     83 	{NULL, 16, 0}; /* used initially */
     84 
     85 
     86 /* The following map ssh names to internal values */
     87 
     88 algo_type sshciphers[] = {
     89 #ifdef DROPBEAR_AES128_CBC
     90 	{"aes128-cbc", 0, (void*)&dropbear_aes128, 1},
     91 #endif
     92 #ifdef DROPBEAR_3DES_CBC
     93 	{"3des-cbc", 0, (void*)&dropbear_3des, 1},
     94 #endif
     95 #ifdef DROPBEAR_AES256_CBC
     96 	{"aes256-cbc", 0, (void*)&dropbear_aes256, 1},
     97 #endif
     98 #ifdef DROPBEAR_TWOFISH256_CBC
     99 	{"twofish256-cbc", 0, (void*)&dropbear_twofish256, 1},
    100 	{"twofish-cbc", 0, (void*)&dropbear_twofish256, 1},
    101 #endif
    102 #ifdef DROPBEAR_TWOFISH128_CBC
    103 	{"twofish128-cbc", 0, (void*)&dropbear_twofish128, 1},
    104 #endif
    105 #ifdef DROPBEAR_BLOWFISH_CBC
    106 	{"blowfish-cbc", 0, (void*)&dropbear_blowfish, 1},
    107 #endif
    108 	{NULL, 0, NULL, 0}
    109 };
    110 
    111 algo_type sshhashes[] = {
    112 #ifdef DROPBEAR_SHA1_96_HMAC
    113 	{"hmac-sha1-96", 0, (void*)&dropbear_sha1_96, 1},
    114 #endif
    115 #ifdef DROPBEAR_SHA1_HMAC
    116 	{"hmac-sha1", 0, (void*)&dropbear_sha1, 1},
    117 #endif
    118 #ifdef DROPBEAR_MD5_HMAC
    119 	{"hmac-md5", 0, (void*)&dropbear_md5, 1},
    120 #endif
    121 	{NULL, 0, NULL, 0}
    122 };
    123 
    124 algo_type sshcompress[] = {
    125 #ifndef DISABLE_ZLIB
    126 	{"zlib", DROPBEAR_COMP_ZLIB, NULL, 1},
    127 #endif
    128 	{"none", DROPBEAR_COMP_NONE, NULL, 1},
    129 	{NULL, 0, NULL, 0}
    130 };
    131 
    132 algo_type sshhostkey[] = {
    133 #ifdef DROPBEAR_RSA
    134 	{"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1},
    135 #endif
    136 #ifdef DROPBEAR_DSS
    137 	{"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1},
    138 #endif
    139 	{NULL, 0, NULL, 0}
    140 };
    141 
    142 algo_type sshkex[] = {
    143 	{"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1},
    144 	{NULL, 0, NULL, 0}
    145 };
    146 
    147 
    148 /* Register the compiled in ciphers.
    149  * This should be run before using any of the ciphers/hashes */
    150 void crypto_init() {
    151 
    152 	const struct ltc_cipher_descriptor *regciphers[] = {
    153 #ifdef DROPBEAR_AES_CBC
    154 		&aes_desc,
    155 #endif
    156 #ifdef DROPBEAR_BLOWFISH_CBC
    157 		&blowfish_desc,
    158 #endif
    159 #ifdef DROPBEAR_TWOFISH_CBC
    160 		&twofish_desc,
    161 #endif
    162 #ifdef DROPBEAR_3DES_CBC
    163 		&des3_desc,
    164 #endif
    165 		NULL
    166 	};
    167 
    168 	const struct ltc_hash_descriptor *reghashes[] = {
    169 		/* we need sha1 for hostkey stuff regardless */
    170 		&sha1_desc,
    171 #ifdef DROPBEAR_MD5_HMAC
    172 		&md5_desc,
    173 #endif
    174 		NULL
    175 	};
    176 	int i;
    177 
    178 	for (i = 0; regciphers[i] != NULL; i++) {
    179 		if (register_cipher(regciphers[i]) == -1) {
    180 			dropbear_exit("error registering crypto");
    181 		}
    182 	}
    183 
    184 	for (i = 0; reghashes[i] != NULL; i++) {
    185 		if (register_hash(reghashes[i]) == -1) {
    186 			dropbear_exit("error registering crypto");
    187 		}
    188 	}
    189 }
    190 
    191 /* algolen specifies the length of algo, algos is our local list to match
    192  * against.
    193  * Returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE
    194  * otherwise */
    195 int have_algo(char* algo, size_t algolen, algo_type algos[]) {
    196 
    197 	int i;
    198 
    199 	for (i = 0; algos[i].name != NULL; i++) {
    200 		if (strlen(algos[i].name) == algolen
    201 				&& (strncmp(algos[i].name, algo, algolen) == 0)) {
    202 			return DROPBEAR_SUCCESS;
    203 		}
    204 	}
    205 
    206 	return DROPBEAR_FAILURE;
    207 }
    208 
    209 
    210 
    211 /* Output a comma separated list of algorithms to a buffer */
    212 void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
    213 
    214 	unsigned int i, len;
    215 	unsigned int donefirst = 0;
    216 	buffer *algolist = NULL;
    217 
    218 	algolist = buf_new(100);
    219 	for (i = 0; localalgos[i].name != NULL; i++) {
    220 		if (localalgos[i].usable) {
    221 			if (donefirst)
    222 				buf_putbyte(algolist, ',');
    223 			donefirst = 1;
    224 			len = strlen(localalgos[i].name);
    225 			buf_putbytes(algolist, localalgos[i].name, len);
    226 		}
    227 	}
    228 	buf_putstring(buf, algolist->data, algolist->len);
    229 	buf_free(algolist);
    230 }
    231