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
28
/* This file (algo.c) organises the ciphers which can be used, and is used to
29
* decide which ciphers/hashes/compression/signing to use during key exchange*/
31
/* Mappings for ciphers, parameters are
32
{&cipher_desc, keysize, blocksize} */
34
#ifdef DROPBEAR_AES128_CBC
35
const struct dropbear_cipher dropbear_aes128 =
36
{&rijndael_desc, 16, 16};
38
#ifdef DROPBEAR_BLOWFISH_CBC
39
const struct dropbear_cipher dropbear_blowfish =
40
{&blowfish_desc, 16, 8};
42
#ifdef DROPBEAR_TWOFISH128_CBC
43
const struct dropbear_cipher dropbear_twofish128 =
44
{&twofish_desc, 16, 16};
46
#ifdef DROPBEAR_3DES_CBC
47
const struct dropbear_cipher dropbear_3des =
51
/* used to indicate no encryption, as defined in rfc2410 */
52
const struct dropbear_cipher dropbear_nocipher =
55
/* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc.
56
{&hash_desc, keysize, hashsize} */
58
#ifdef DROPBEAR_SHA1_HMAC
59
const struct dropbear_hash dropbear_sha1 =
62
#ifdef DROPBEAR_MD5_HMAC
63
const struct dropbear_hash dropbear_md5 =
67
const struct dropbear_hash dropbear_nohash =
68
{NULL, 16, 0}; /* used initially */
71
/* The following map ssh names to internal values */
73
algo_type sshciphers[] = {
74
#ifdef DROPBEAR_AES128_CBC
75
{"aes128-cbc", 0, (void*)&dropbear_aes128, 1},
77
#ifdef DROPBEAR_BLOWFISH_CBC
78
{"blowfish-cbc", 0, (void*)&dropbear_blowfish, 1},
80
#ifdef DROPBEAR_TWOFISH128_CBC
81
{"twofish-cbc", 0, (void*)&dropbear_twofish128, 1},
83
#ifdef DROPBEAR_3DES_CBC
84
{"3des-cbc", 0, (void*)&dropbear_3des, 1},
89
algo_type sshhashes[] = {
90
#ifdef DROPBEAR_SHA1_HMAC
91
{"hmac-sha1", 0, (void*)&dropbear_sha1, 1},
93
#ifdef DROPBEAR_MD5_HMAC
94
{"hmac-md5", 0, (void*)&dropbear_md5, 1},
99
algo_type sshcompress[] = {
100
{"none", DROPBEAR_COMP_NONE, NULL, 1},
102
{"zlib", DROPBEAR_COMP_ZLIB, NULL, 1},
107
algo_type sshhostkey[] = {
109
{"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1},
112
{"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1},
117
algo_type sshkex[] = {
118
{"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1},
123
/* Register the compiled in ciphers.
124
* This should be run before using any of the ciphers/hashes */
127
const struct _cipher_descriptor *regciphers[] = {
128
#ifdef DROPBEAR_AES128_CBC
131
#ifdef DROPBEAR_BLOWFISH_CBC
134
#ifdef DROPBEAR_TWOFISH128_CBC
137
#ifdef DROPBEAR_3DES_CBC
143
const struct _hash_descriptor *reghashes[] = {
144
/* we need sha1 for hostkey stuff regardless */
146
#ifdef DROPBEAR_MD5_HMAC
153
for (i = 0; regciphers[i] != NULL; i++) {
154
if (register_cipher(regciphers[i]) == -1) {
155
dropbear_exit("error registering crypto");
159
for (i = 0; reghashes[i] != NULL; i++) {
160
if (register_hash(reghashes[i]) == -1) {
161
dropbear_exit("error registering crypto");
166
/* algolen specifies the length of algo, algos is our local list to match
168
* Returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE
170
int have_algo(char* algo, size_t algolen, algo_type algos[]) {
174
for (i = 0; algos[i].name != NULL; i++) {
175
if (strlen(algos[i].name) == algolen
176
&& (strncmp(algos[i].name, algo, algolen) == 0)) {
177
return DROPBEAR_SUCCESS;
181
return DROPBEAR_FAILURE;
185
/* match the first algorithm in the comma-separated list in buf which is
186
* also in localalgos[], or return NULL on failure.
187
* (*goodguess) is set to 1 if the preferred client/server algos match,
188
* 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
189
* guessed correctly */
190
algo_type * buf_match_algo(buffer* buf, algo_type localalgos[], int *goodguess)
193
unsigned char * algolist = NULL;
194
unsigned char * remotealgos[MAX_PROPOSED_ALGO];
196
unsigned int count, i, j;
197
algo_type * ret = NULL;
199
/* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
200
algolist = buf_getstring(buf, &len);
202
TRACE(("buf_match_algo: %s", algolist));
203
if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
204
goto out; /* just a sanity check, no other use */
207
/* remotealgos will contain a list of the strings parsed out */
208
/* We will have at least one string (even if it's just "") */
209
remotealgos[0] = algolist;
211
/* Iterate through, replacing ','s with NULs, to split it into
213
for (i = 0; i < len; i++) {
214
if (algolist[i] == '\0') {
215
/* someone is trying something strange */
218
if (algolist[i] == ',') {
220
remotealgos[count] = &algolist[i+1];
223
if (count == MAX_PROPOSED_ALGO) {
228
/* iterate and find the first match */
229
for (i = 0; i < count; i++) {
231
len = strlen(remotealgos[i]);
233
for (j = 0; localalgos[j].name != NULL; j++) {
234
if (localalgos[j].usable) {
235
if (len == strlen(localalgos[j].name) &&
236
strncmp(localalgos[j].name, remotealgos[i], len) == 0) {
237
/* set if it was a good guess */
238
if (i == 0 && j == 0) {
243
/* set the algo to return */
244
ret = &localalgos[j];
256
/* Output a comma separated list of algorithms to a buffer */
257
void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
259
unsigned int pos = 0, i, len;
260
char str[50]; /* enough for local algo storage */
262
for (i = 0; localalgos[i].name != NULL; i++) {
263
if (localalgos[i].usable) {
264
/* Avoid generating a trailing comma */
267
len = strlen(localalgos[i].name);
268
memcpy(&str[pos], localalgos[i].name, len);
274
TRACE(("buf_put_algolist: %s", str));
275
buf_putstring(buf, str, pos);