]> andersk Git - openssh.git/blob - dsa.c
3c1a5f461aec42f3705b3ae2c754fb6da8cd015d
[openssh.git] / dsa.c
1 /*
2  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. All advertising materials mentioning features or use of this software
13  *    must display the following acknowledgement:
14  *      This product includes software developed by Markus Friedl.
15  * 4. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "includes.h"
31 RCSID("$Id$");
32
33 #include "ssh.h"
34 #include "xmalloc.h"
35 #include "buffer.h"
36 #include "bufaux.h"
37 #include "compat.h"
38
39 #if HAVE_OPENSSL
40 # include <openssl/bn.h>
41 # include <openssl/dh.h>
42 # include <openssl/rsa.h>
43 # include <openssl/dsa.h>
44 # include <openssl/evp.h>
45 # include <openssl/bio.h>
46 # include <openssl/pem.h>
47 # include <openssl/hmac.h>
48 #endif /* HAVE_OPENSSL */
49 #if HAVE_SSL
50 # include <ssl/bn.h>
51 # include <ssl/dh.h>
52 # include <ssl/rsa.h>
53 # include <ssl/dsa.h>
54 # include <ssl/evp.h>
55 # include <ssl/bio.h>
56 # include <ssl/pem.h>
57 # include <ssl/hmac.h>
58 #endif /* HAVE_SSL */
59
60 #include "kex.h"
61 #include "key.h"
62
63 #define INTBLOB_LEN     20
64 #define SIGBLOB_LEN     (2*INTBLOB_LEN)
65
66 Key *
67 dsa_serverkey_from_blob(
68     char *serverhostkey, int serverhostkeylen)
69 {
70         Buffer b;
71         char *ktype;
72         int rlen;
73         DSA *dsa;
74         Key *key;
75
76         /* fetch & parse DSA/DSS pubkey */
77         key = key_new(KEY_DSA);
78         dsa = key->dsa;
79         buffer_init(&b);
80         buffer_append(&b, serverhostkey, serverhostkeylen);
81         ktype = buffer_get_string(&b, NULL);
82         if (strcmp(KEX_DSS, ktype) != 0) {
83                 error("dsa_serverkey_from_blob: cannot handle type  %s", ktype);
84                 key_free(key);
85                 return NULL;
86         }
87         buffer_get_bignum2(&b, dsa->p);
88         buffer_get_bignum2(&b, dsa->q);
89         buffer_get_bignum2(&b, dsa->g);
90         buffer_get_bignum2(&b, dsa->pub_key);
91         rlen = buffer_len(&b);
92         if(rlen != 0)
93                 error("dsa_serverkey_from_blob: remaining bytes in serverhostkey %d", rlen);
94         buffer_free(&b);
95
96         debug("keytype %s", ktype);
97 #ifdef DEBUG_DSS
98         DSA_print_fp(stderr, dsa, 8);
99 #endif
100         return key;
101 }
102 DSA *
103 dsa_load_private(char *filename)
104 {
105         DSA *dsa;
106         BIO *in;
107
108         in = BIO_new(BIO_s_file());
109         if (in == NULL)
110                 fatal("BIO_new failed");
111         if (BIO_read_filename(in, filename) <= 0) 
112                 fatal("BIO_read failed %s: %s", filename, strerror(errno));
113         fprintf(stderr, "read DSA private key\n");
114         dsa = PEM_read_bio_DSAPrivateKey(in,NULL,NULL,NULL);
115         if (dsa == NULL)
116                 fatal("PEM_read_bio_DSAPrivateKey failed %s", filename);
117         BIO_free(in);
118         return dsa;
119 }
120 Key *
121 dsa_get_serverkey(char *filename)
122 {
123         Key *k = key_new(KEY_EMPTY);
124         k->type = KEY_DSA;
125         k->dsa = dsa_load_private(filename);
126 #ifdef DEBUG_DSS
127         DSA_print_fp(stderr, dsa, 8);
128 #endif
129         return k;
130 }
131 int
132 dsa_make_serverkey_blob(Key *key, unsigned char **blobp, unsigned int *lenp)
133 {
134         Buffer b;
135         int len;
136         unsigned char *buf;
137
138         if (key == NULL || key->type != KEY_DSA)
139                 return 0;
140         buffer_init(&b);
141         buffer_put_cstring(&b, KEX_DSS);
142         buffer_put_bignum2(&b, key->dsa->p);
143         buffer_put_bignum2(&b, key->dsa->q);
144         buffer_put_bignum2(&b, key->dsa->g);
145         buffer_put_bignum2(&b, key->dsa->pub_key);
146         len = buffer_len(&b);
147         buf = xmalloc(len);
148         memcpy(buf, buffer_ptr(&b), len);
149         memset(buffer_ptr(&b), 0, len);
150         buffer_free(&b);
151         if (lenp != NULL)
152                 *lenp = len;
153         if (blobp != NULL)
154                 *blobp = buf;
155         return len;
156 }
157 int
158 dsa_sign(
159     Key *key,
160     unsigned char **sigp, int *lenp,
161     unsigned char *hash, int hlen)
162 {
163         unsigned char *digest;
164         unsigned char *ret;
165         DSA_SIG *sig;
166         EVP_MD *evp_md = EVP_sha1();
167         EVP_MD_CTX md;
168         unsigned int rlen;
169         unsigned int slen;
170         unsigned int len;
171         unsigned char sigblob[SIGBLOB_LEN];
172         Buffer b;
173
174         if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
175                 error("dsa_sign: no DSA key");
176                 return -1;
177         }
178         digest = xmalloc(evp_md->md_size);
179         EVP_DigestInit(&md, evp_md);
180         EVP_DigestUpdate(&md, hash, hlen);
181         EVP_DigestFinal(&md, digest, NULL);
182
183         sig = DSA_do_sign(digest, evp_md->md_size, key->dsa);
184
185         rlen = BN_num_bytes(sig->r);
186         slen = BN_num_bytes(sig->s);
187         if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
188                 error("bad sig size %d %d", rlen, slen);
189                 DSA_SIG_free(sig);
190                 return -1;
191         }
192         debug("sig size %d %d", rlen, slen);
193
194         memset(sigblob, 0, SIGBLOB_LEN);
195         BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
196         BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
197         DSA_SIG_free(sig);
198
199         if (datafellows) {
200                 debug("datafellows");
201                 ret = xmalloc(SIGBLOB_LEN);
202                 memcpy(ret, sigblob, SIGBLOB_LEN);
203                 if (lenp != NULL)
204                         *lenp = SIGBLOB_LEN;
205                 if (sigp != NULL)
206                         *sigp = ret;
207         } else {
208                 /* ietf-drafts */
209                 buffer_init(&b);
210                 buffer_put_cstring(&b, KEX_DSS);
211                 buffer_put_string(&b, sigblob, SIGBLOB_LEN);
212                 len = buffer_len(&b);
213                 ret = xmalloc(len);
214                 memcpy(ret, buffer_ptr(&b), len);
215                 buffer_free(&b);
216                 if (lenp != NULL)
217                         *lenp = len;
218                 if (sigp != NULL)
219                         *sigp = ret;
220         }
221         return 0;
222 }
223 int
224 dsa_verify(
225     Key *key,
226     unsigned char *signature, int signaturelen,
227     unsigned char *hash, int hlen)
228 {
229         Buffer b;
230         unsigned char *digest;
231         DSA_SIG *sig;
232         EVP_MD *evp_md = EVP_sha1();
233         EVP_MD_CTX md;
234         char *ktype;
235         unsigned char *sigblob;
236         char *txt;
237         unsigned int len;
238         int rlen;
239         int ret;
240
241         if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
242                 error("dsa_verify: no DSA key");
243                 return -1;
244         }
245
246         if (datafellows && signaturelen != SIGBLOB_LEN) {
247                 log("heh? datafellows ssh2 complies with ietf-drafts????");
248                 datafellows = 0;
249         }
250
251         debug("len %d datafellows %d", signaturelen, datafellows);
252
253         /* fetch signature */
254         if (datafellows) {
255                 sigblob = signature;
256                 len = signaturelen;
257         } else {
258                 /* ietf-drafts */
259                 buffer_init(&b);
260                 buffer_append(&b, (char *) signature, signaturelen);
261                 ktype = buffer_get_string(&b, NULL);
262                 sigblob = (unsigned char *)buffer_get_string(&b, &len);
263                 rlen = buffer_len(&b);
264                 if(rlen != 0)
265                         error("remaining bytes in signature %d", rlen);
266                 buffer_free(&b);
267         }
268
269         if (len != SIGBLOB_LEN) {
270                 fatal("bad sigbloblen %d != SIGBLOB_LEN", len);
271         }
272
273         /* parse signature */
274         sig = DSA_SIG_new();
275         sig->r = BN_new();
276         sig->s = BN_new();
277         BN_bin2bn(sigblob, INTBLOB_LEN, sig->r);
278         BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s);
279         if (!datafellows) {
280                 memset(sigblob, 0, len);
281                 xfree(sigblob);
282         }
283         
284         /* sha1 the signed data (== session_id == hash) */
285         digest = xmalloc(evp_md->md_size);
286         EVP_DigestInit(&md, evp_md);
287         EVP_DigestUpdate(&md, hash, hlen);
288         EVP_DigestFinal(&md, digest, NULL);
289
290         ret = DSA_do_verify(digest, evp_md->md_size, sig, key->dsa);
291
292         memset(digest, 0, evp_md->md_size);
293         xfree(digest);
294         DSA_SIG_free(sig);
295
296         switch (ret) {
297         case 1:
298                 txt = "correct";
299                 break;
300         case 0:
301                 txt = "incorrect";
302                 break;
303         case -1:
304         default:
305                 txt = "error";
306                 break;
307         }
308         debug("dsa_verify: signature %s", txt);
309         return ret;
310 }
This page took 0.05289 seconds and 3 git commands to generate.