2 * Dropbear - a SSH2 server
4 * Copyright (c) 2002,2003 Matt Johnston
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 /* This file (algo.c) organises the ciphers which can be used, and is used to
28 * decide which ciphers/hashes/compression/signing to use during key exchange*/
30 /* Mappings for ciphers, parameters are
31 {&cipher_desc, keysize, blocksize} */
33 #ifdef DROPBEAR_AES128_CBC
34 const struct dropbear_cipher dropbear_aes128 =
35 {&rijndael_desc, 16, 16};
37 #ifdef DROPBEAR_BLOWFISH_CBC
38 const struct dropbear_cipher dropbear_blowfish =
39 {&blowfish_desc, 16, 8};
41 #ifdef DROPBEAR_TWOFISH128_CBC
42 const struct dropbear_cipher dropbear_twofish128 =
43 {&twofish_desc, 16, 16};
45 #ifdef DROPBEAR_3DES_CBC
46 const struct dropbear_cipher dropbear_3des =
50 /* used to indicate no encryption, as defined in rfc2410 */
51 const struct dropbear_cipher dropbear_nocipher =
54 /* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc.
55 {&hash_desc, keysize, hashsize} */
57 #ifdef DROPBEAR_SHA1_HMAC
58 const struct dropbear_hash dropbear_sha1 =
61 #ifdef DROPBEAR_MD5_HMAC
62 const struct dropbear_hash dropbear_md5 =
66 const struct dropbear_hash dropbear_nohash =
67 {NULL, 16, 0}; /* used initially */
70 /* The following map ssh names to internal values */
72 algo_type sshciphers[] = {
73 #ifdef DROPBEAR_AES128_CBC
74 {"aes128-cbc", 0, (void*)&dropbear_aes128, 1},
76 #ifdef DROPBEAR_BLOWFISH_CBC
77 {"blowfish-cbc", 0, (void*)&dropbear_blowfish, 1},
79 #ifdef DROPBEAR_TWOFISH128_CBC
80 {"twofish-cbc", 0, (void*)&dropbear_twofish128, 1},
82 #ifdef DROPBEAR_3DES_CBC
83 {"3des-cbc", 0, (void*)&dropbear_3des, 1},
88 algo_type sshhashes[] = {
89 #ifdef DROPBEAR_SHA1_HMAC
90 {"hmac-sha1", 0, (void*)&dropbear_sha1, 1},
92 #ifdef DROPBEAR_MD5_HMAC
93 {"hmac-md5", 0, (void*)&dropbear_md5, 1},
98 algo_type sshcompress[] = {
99 {"none", DROPBEAR_COMP_NONE, NULL, 1},
101 {"zlib", DROPBEAR_COMP_ZLIB, NULL, 1},
106 algo_type sshhostkey[] = {
108 {"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1},
111 {"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1},
116 algo_type sshkex[] = {
117 {"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1},
122 /* Register the compiled in ciphers.
123 * This should be run before using any of the ciphers/hashes */
126 const struct _cipher_descriptor *regciphers[] = {
127 #ifdef DROPBEAR_AES128_CBC
130 #ifdef DROPBEAR_BLOWFISH_CBC
133 #ifdef DROPBEAR_TWOFISH128_CBC
136 #ifdef DROPBEAR_3DES_CBC
142 const struct _hash_descriptor *reghashes[] = {
143 /* we need sha1 for hostkey stuff regardless */
145 #ifdef DROPBEAR_MD5_HMAC
152 for (i = 0; regciphers[i] != NULL; i++) {
153 if (register_cipher(regciphers[i]) == -1) {
154 dropbear_exit("error registering crypto");
158 for (i = 0; reghashes[i] != NULL; i++) {
159 if (register_hash(reghashes[i]) == -1) {
160 dropbear_exit("error registering crypto");
165 /* returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE
167 int have_algo(char* algo, size_t algolen, algo_type algos[]) {
170 while (algos[i].name != NULL) {
171 if (strlen(algos[i].name) == algolen
172 && (strncmp(algos[i].name, algo, algolen) == 0)) {
173 return DROPBEAR_SUCCESS;
178 return DROPBEAR_FAILURE;
182 /* match the first algorithm in the comma-seperated list in buf which is
183 * also in localalgos[], or return NULL on failure. */
184 algo_type * buf_match_algo(buffer* buf, algo_type localalgos[]) {
186 unsigned char * algolist = NULL;
187 unsigned char * remotealgos[MAX_PROPOSED_ALGO];
189 unsigned int count, i, j;
190 algo_type * ret = NULL;
192 /* get the comma-seperated list from the buffer ie "algo1,algo2,algo3" */
193 algolist = buf_getstring(buf, &len);
194 if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
195 goto out; /* just a sanity check, no other use */
198 /* remotealgos will contain a list of the strings parsed out */
199 /* We will have at least one string (even if it's just "") */
200 remotealgos[0] = algolist;
202 /* Iterate through, replacing ','s with NULs, to split it into
204 for (i = 0; i < len; i++) {
205 if (algolist[i] == '\0') {
206 /* someone is trying something strange */
209 if (algolist[i] == ',' && i != len) {
211 remotealgos[count] = &algolist[i+1];
214 if (count == MAX_PROPOSED_ALGO) {
219 /* iterate and find the first match */
220 for (i = 0; i < count; i++) {
221 len = strlen(remotealgos[i]);
222 for (j = 0; localalgos[j].name != NULL; j++) {
223 if (!localalgos[j].usable) {
226 if (len == strlen(localalgos[j].name)
227 && strcmp(localalgos[j].name, remotealgos[i]) == 0) {
228 ret = &localalgos[j];
239 /* Output a comma seperated list of algorithms to a buffer */
240 void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
242 unsigned int pos = 0, i, len;
243 char str[50]; /* enough for local algo storage */
245 for (i = 0; localalgos[i].name != NULL; i++) {
246 if (localalgos[i].usable) {
247 len = strlen(localalgos[i].name);
248 memcpy(&str[pos], localalgos[i].name, len);
254 buf_putstring(buf, str, pos-1);