blob: 21ac96a49a1fd4169480049205e7ceb2c944a607 [file] [log] [blame]
The Android Open Source Projectf7fc46c2009-03-03 19:29:23 -08001/*
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}