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
38static const struct dropbear_cipher dropbear_aes256 =
39	{&aes_desc, 32, 16};
40#endif
41#ifdef DROPBEAR_AES128_CBC
42static const struct dropbear_cipher dropbear_aes128 =
43	{&aes_desc, 16, 16};
44#endif
45#ifdef DROPBEAR_BLOWFISH_CBC
46static const struct dropbear_cipher dropbear_blowfish =
47	{&blowfish_desc, 16, 8};
48#endif
49#ifdef DROPBEAR_TWOFISH256_CBC
50static const struct dropbear_cipher dropbear_twofish256 =
51	{&twofish_desc, 32, 16};
52#endif
53#ifdef DROPBEAR_TWOFISH128_CBC
54static const struct dropbear_cipher dropbear_twofish128 =
55	{&twofish_desc, 16, 16};
56#endif
57#ifdef DROPBEAR_3DES_CBC
58static const struct dropbear_cipher dropbear_3des =
59	{&des3_desc, 24, 8};
60#endif
61
62/* used to indicate no encryption, as defined in rfc2410 */
63const 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
70static const struct dropbear_hash dropbear_sha1 =
71	{&sha1_desc, 20, 20};
72#endif
73#ifdef DROPBEAR_SHA1_96_HMAC
74static const struct dropbear_hash dropbear_sha1_96 =
75	{&sha1_desc, 20, 12};
76#endif
77#ifdef DROPBEAR_MD5_HMAC
78static const struct dropbear_hash dropbear_md5 =
79	{&md5_desc, 16, 16};
80#endif
81
82const struct dropbear_hash dropbear_nohash =
83	{NULL, 16, 0}; /* used initially */
84
85
86/* The following map ssh names to internal values */
87
88algo_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
111algo_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
124algo_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
132algo_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
142algo_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 */
150void 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 */
195int 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 */
212void 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