# BRCM_VERSION=3
[bcm963xx.git] / userapps / opensource / sshd / signkey.c
1 /*
2  * Dropbear - a SSH2 server
3  * 
4  * Copyright (c) 2002,2003 Matt Johnston
5  * All rights reserved.
6  * 
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:
13  * 
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  * 
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
23  * SOFTWARE. */
24
25 #include "includes.h"
26 #include "util.h"
27 #include "signkey.h"
28 #include "buffer.h"
29 #include "ssh.h"
30
31 /* malloc a new sign_key and set the dss and rsa keys to NULL */
32 sign_key * new_sign_key() {
33
34         sign_key * ret;
35
36         ret = (sign_key*)m_malloc(sizeof(sign_key));
37 #ifdef DROPBEAR_DSS
38         ret->dsskey = NULL;
39 #endif
40 #ifdef DROPBEAR_RSA
41         ret->rsakey = NULL;
42 #endif
43         return ret;
44
45 }
46
47 /* returns DROPBEAR_SUCCESS on success, DROPBEAR_FAILURE on fail */
48 int buf_get_pub_key(buffer *buf, sign_key *key, int type) {
49
50         unsigned char* ident;
51         unsigned int len;
52
53         ident = buf_getstring(buf, &len);
54
55 #ifdef DROPBEAR_DSS
56         if (memcmp(ident, SSH_SIGNKEY_DSS, len) == 0
57                         && (type == DROPBEAR_SIGNKEY_ANY || type == DROPBEAR_SIGNKEY_DSS)) {
58                 m_free(ident);
59                 buf_setpos(buf, buf->pos - len - 4);
60                 dss_key_free(key->dsskey);
61                 key->dsskey = (dss_key*)m_malloc(sizeof(dss_key));
62                 return buf_get_dss_pub_key(buf, key->dsskey);
63         }
64 #endif
65 #ifdef DROPBEAR_RSA
66         if (memcmp(ident, SSH_SIGNKEY_RSA, len) == 0
67                         && (type == DROPBEAR_SIGNKEY_ANY || type == DROPBEAR_SIGNKEY_RSA)) {
68                 m_free(ident);
69                 buf_setpos(buf, buf->pos - len - 4);
70                 rsa_key_free(key->rsakey);
71                 key->rsakey = (rsa_key*)m_malloc(sizeof(rsa_key));
72                 return buf_get_rsa_pub_key(buf, key->rsakey);
73         }
74 #endif
75
76         m_free(ident);
77
78         return DROPBEAR_FAILURE;
79         
80 }
81
82 /* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
83 int buf_get_priv_key(buffer *buf, sign_key *key, int type) {
84
85         unsigned char* ident;
86         unsigned int len;
87         int ret;
88
89         TRACE(("enter buf_get_priv_key"));
90         ident = buf_getstring(buf, &len);
91
92 #ifdef DROPBEAR_DSS
93         if (memcmp(ident, SSH_SIGNKEY_DSS, len) == 0
94                         && (type == DROPBEAR_SIGNKEY_ANY || type == DROPBEAR_SIGNKEY_DSS)) {
95                 m_free(ident);
96                 buf_setpos(buf, buf->pos - len - 4);
97                 dss_key_free(key->dsskey);
98                 key->dsskey = (dss_key*)m_malloc(sizeof(dss_key));
99                 ret = buf_get_dss_priv_key(buf, key->dsskey);
100                 if (ret == DROPBEAR_FAILURE) {
101                         m_free(key->dsskey);
102                 }
103                 TRACE(("leave buf_get_priv_key: done get dss"));
104                 return ret;
105         }
106 #endif
107 #ifdef DROPBEAR_RSA
108         if (memcmp(ident, SSH_SIGNKEY_RSA, len) == 0
109                         && (type == DROPBEAR_SIGNKEY_ANY || type == DROPBEAR_SIGNKEY_RSA)) {
110                 m_free(ident);
111                 buf_setpos(buf, buf->pos - len - 4);
112                 rsa_key_free(key->rsakey);
113                 key->rsakey = (rsa_key*)m_malloc(sizeof(rsa_key));
114                 ret = buf_get_rsa_priv_key(buf, key->rsakey);
115                 if (ret == DROPBEAR_FAILURE) {
116                         m_free(key->rsakey);
117                 }
118                 TRACE(("leave buf_get_priv_key: done get rsa"));
119                 return ret;
120         }
121 #endif
122
123         m_free(ident);
124         
125         TRACE(("leave buf_get_priv_key"));
126         return DROPBEAR_FAILURE;
127         
128 }
129
130 /* type is either DROPBEAR_SIGNKEY_DSS or DROPBEAR_SIGNKEY_RSA */
131 void buf_put_pub_key(buffer* buf, sign_key *key, int type) {
132
133         buffer *pubkeys;
134
135         TRACE(("enter buf_put_pub_key"));
136         pubkeys = buf_new(1000);
137         
138 #ifdef DROPBEAR_DSS
139         if (type == DROPBEAR_SIGNKEY_DSS) {
140                 buf_put_dss_pub_key(pubkeys, key->dsskey);
141         }
142 #endif
143 #ifdef DROPBEAR_RSA
144         if (type == DROPBEAR_SIGNKEY_RSA) {
145                 buf_put_rsa_pub_key(pubkeys, key->rsakey);
146         }
147 #endif
148         if (pubkeys->len == 0) {
149                 dropbear_exit("bad key types in buf_put_pub_key");
150         }
151
152         buf_setpos(pubkeys, 0);
153         buf_putstring(buf, buf_getptr(pubkeys, pubkeys->len),
154                         pubkeys->len);
155         
156         buf_free(pubkeys);
157         TRACE(("leave buf_put_pub_key"));
158 }
159
160 /* type is either DROPBEAR_SIGNKEY_DSS or DROPBEAR_SIGNKEY_RSA */
161 void buf_put_priv_key(buffer* buf, sign_key *key, int type) {
162
163         TRACE(("enter buf_put_priv_key"));
164         TRACE(("type is %d\n", type));
165
166 #ifdef DROPBEAR_DSS
167         if (type == DROPBEAR_SIGNKEY_DSS) {
168                 buf_put_dss_priv_key(buf, key->dsskey);
169         TRACE(("leave buf_put_priv_key: dss done"));
170         return;
171         }
172 #endif
173 #ifdef DROPBEAR_RSA
174         if (type == DROPBEAR_SIGNKEY_RSA) {
175                 buf_put_rsa_priv_key(buf, key->rsakey);
176         TRACE(("leave buf_put_priv_key: rsa done"));
177         return;
178         }
179 #endif
180         dropbear_exit("bad key types in put pub key");
181 }
182
183 void sign_key_free(sign_key *key) {
184
185         TRACE(("enter sign_key_free"));
186
187 #ifdef DROPBEAR_DSS
188         dss_key_free(key->dsskey);
189 #endif
190 #ifdef DROPBEAR_RSA
191         rsa_key_free(key->rsakey);
192 #endif
193
194         m_free(key);
195         TRACE(("leave sign_key_free"));
196 }
197
198 void buf_put_sign(buffer* buf, sign_key *key, int type, 
199                 const unsigned char *data, unsigned int len) {
200
201         buffer *sigblob;
202
203         sigblob = buf_new(1000);
204
205 #ifdef DROPBEAR_DSS
206         if (type == DROPBEAR_SIGNKEY_DSS) {
207                 buf_put_dss_sign(sigblob, key->dsskey, data, len);
208         }
209 #endif
210 #ifdef DROPBEAR_RSA
211         if (type == DROPBEAR_SIGNKEY_RSA) {
212                 buf_put_rsa_sign(sigblob, key->rsakey, data, len);
213         }
214 #endif
215         if (sigblob->len == 0) {
216                 dropbear_exit("non-matching signing type");
217         }
218
219         buf_setpos(sigblob, 0);
220         buf_putstring(buf, buf_getptr(sigblob, sigblob->len),
221                         sigblob->len);
222                         
223         buf_free(sigblob);
224
225 }
226
227 #ifdef DROPBEAR_SIGNKEY_VERIFY
228 /* Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE.
229  * If FAILURE is returned, the position of
230  * buf is undefined. If SUCCESS is returned, buf will be positioned after the
231  * signature blob */
232 int buf_verify(buffer * buf, sign_key *key, const unsigned char *data,
233                 unsigned int len) {
234         
235         unsigned int bloblen;
236         unsigned char * ident = NULL;
237         unsigned int identlen = 0;
238
239         bloblen = buf_getint(buf);
240         ident = buf_getstring(buf, &identlen);
241
242 #ifdef DROPBEAR_DSS
243         if (bloblen == DSS_SIGNATURE_SIZE &&
244                         memcmp(ident, SSH_SIGNKEY_DSS, identlen) == 0) {
245                 m_free(ident);
246                 return buf_dss_verify(buf, key->dsskey, data, len);
247         }
248 #endif
249
250 #ifdef DROPBEAR_RSA
251         if (memcmp(ident, SSH_SIGNKEY_RSA, identlen) == 0) {
252                 m_free(ident);
253                 return buf_rsa_verify(buf, key->rsakey, data, len);
254         }
255 #endif
256
257         m_free(ident);
258         dropbear_exit("non-matching signing type");
259         return DROPBEAR_FAILURE;
260 }
261 #endif /* DROPBEAR_SIGNKEY_VERIFY */