• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
crypto_init()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 */
have_algo(char * algo,size_t algolen,algo_type algos[])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 */
buf_put_algolist(buffer * buf,algo_type localalgos[])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