]> andersk Git - openssh.git/blob - dsa.c
- OpenBSD CVS update:
[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 #endif /* HAVE_OPENSSL */
48 #if HAVE_SSL
49 # include <ssl/bn.h>
50 # include <ssl/dh.h>
51 # include <ssl/rsa.h>
52 # include <ssl/dsa.h>
53 # include <ssl/evp.h>
54 # include <ssl/bio.h>
55 # include <ssl/pem.h>
56 #endif /* HAVE_SSL */
57
58 #include <ssl/hmac.h>
59 #include "kex.h"
60 #include "key.h"
61
62 #define INTBLOB_LEN     20
63 #define SIGBLOB_LEN     (2*INTBLOB_LEN)
64
65 Key *
66 dsa_serverkey_from_blob(
67     char *serverhostkey, int serverhostkeylen)
68 {
69         Buffer b;
70         char *ktype;
71         int rlen;
72         DSA *dsa;
73         Key *key;
74
75         /* fetch & parse DSA/DSS pubkey */
76         key = key_new(KEY_DSA);
77         dsa = key->dsa;
78         buffer_init(&b);
79         buffer_append(&b, serverhostkey, serverhostkeylen);
80         ktype = buffer_get_string(&b, NULL);
81         if (strcmp(KEX_DSS, ktype) != 0) {
82                 log("dsa_serverkey_from_blob: cannot handle type  %s", ktype);
83                 key_free(key);
84                 return NULL;
85         }
86         buffer_get_bignum2(&b, dsa->p);
87         buffer_get_bignum2(&b, dsa->q);
88         buffer_get_bignum2(&b, dsa->g);
89         buffer_get_bignum2(&b, dsa->pub_key);
90         rlen = buffer_len(&b);
91         if(rlen != 0)
92                 log("dsa_serverkey_from_blob: remaining bytes in serverhostkey %d", rlen);
93         buffer_free(&b);
94
95         log("keytype %s", ktype);
96 #ifdef DEBUG_DSS
97         DSA_print_fp(stderr, dsa, 8);
98 #endif
99         return key;
100 }
101 DSA *
102 dsa_load_private(char *filename)
103 {
104         DSA *dsa;
105         BIO *in;
106
107         in = BIO_new(BIO_s_file());
108         if (in == NULL)
109                 fatal("BIO_new failed");
110         if (BIO_read_filename(in, filename) <= 0) 
111                 fatal("BIO_read failed %s: %s", filename, strerror(errno));
112         fprintf(stderr, "read DSA private key\n");
113         dsa = PEM_read_bio_DSAPrivateKey(in,NULL,NULL,NULL);
114         if (dsa == NULL)
115                 fatal("PEM_read_bio_DSAPrivateKey failed %s", filename);
116         BIO_free(in);
117         return dsa;
118 }
119 Key *
120 dsa_get_serverkey(char *filename)
121 {
122         Key *k = key_new(KEY_EMPTY);
123         k->type = KEY_DSA;
124         k->dsa = dsa_load_private(filename);
125 #ifdef DEBUG_DSS
126         DSA_print_fp(stderr, dsa, 8);
127 #endif
128         return k;
129 }
130 int
131 dsa_make_serverkey_blob(Key *key, unsigned char **blobp, unsigned int *lenp)
132 {
133         Buffer b;
134         int len;
135         unsigned char *buf;
136
137         if (key == NULL || key->type != KEY_DSA)
138                 return 0;
139         buffer_init(&b);
140         buffer_put_cstring(&b, KEX_DSS);
141         buffer_put_bignum2(&b, key->dsa->p);
142         buffer_put_bignum2(&b, key->dsa->q);
143         buffer_put_bignum2(&b, key->dsa->g);
144         buffer_put_bignum2(&b, key->dsa->pub_key);
145         len = buffer_len(&b);
146         buf = xmalloc(len);
147         memcpy(buf, buffer_ptr(&b), len);
148         memset(buffer_ptr(&b), 0, len);
149         buffer_free(&b);
150         if (lenp != NULL)
151                 *lenp = len;
152         if (blobp != NULL)
153                 *blobp = buf;
154         return len;
155 }
156 int
157 dsa_sign(
158     Key *key,
159     unsigned char **sigp, int *lenp,
160     unsigned char *hash, int hlen)
161 {
162         unsigned char *digest;
163         unsigned char *ret;
164         DSA_SIG *sig;
165         EVP_MD *evp_md = EVP_sha1();
166         EVP_MD_CTX md;
167         unsigned int rlen;
168         unsigned int slen;
169         unsigned int len;
170         unsigned char sigblob[SIGBLOB_LEN];
171         Buffer b;
172
173         if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
174                 log("dsa_sign: no DSA key");
175                 return -1;
176         }
177         digest = xmalloc(evp_md->md_size);
178         EVP_DigestInit(&md, evp_md);
179         EVP_DigestUpdate(&md, hash, hlen);
180         EVP_DigestFinal(&md, digest, NULL);
181
182         sig = DSA_do_sign(digest, evp_md->md_size, key->dsa);
183
184         rlen = BN_num_bytes(sig->r);
185         slen = BN_num_bytes(sig->s);
186         if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
187                 log("bad sig size %d %d", rlen, slen);
188                 DSA_SIG_free(sig);
189                 return -1;
190         }
191         log("sig size %d %d", rlen, slen);
192
193         memset(sigblob, 0, SIGBLOB_LEN);
194         BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
195         BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
196         DSA_SIG_free(sig);
197
198         if (datafellows) {
199                 log("datafellows");
200                 ret = xmalloc(SIGBLOB_LEN);
201                 memcpy(ret, sigblob, SIGBLOB_LEN);
202                 if (lenp != NULL)
203                         *lenp = SIGBLOB_LEN;
204                 if (sigp != NULL)
205                         *sigp = ret;
206         } else {
207                 /* ietf-drafts */
208                 buffer_init(&b);
209                 buffer_put_cstring(&b, KEX_DSS);
210                 buffer_put_string(&b, sigblob, SIGBLOB_LEN);
211                 len = buffer_len(&b);
212                 ret = xmalloc(len);
213                 memcpy(ret, buffer_ptr(&b), len);
214                 buffer_free(&b);
215                 if (lenp != NULL)
216                         *lenp = len;
217                 if (sigp != NULL)
218                         *sigp = ret;
219         }
220         return 0;
221 }
222 int
223 dsa_verify(
224     Key *key,
225     unsigned char *signature, int signaturelen,
226     unsigned char *hash, int hlen)
227 {
228         Buffer b;
229         unsigned char *digest;
230         DSA_SIG *sig;
231         EVP_MD *evp_md = EVP_sha1();
232         EVP_MD_CTX md;
233         char *ktype;
234         unsigned char *sigblob;
235         char *txt;
236         unsigned int len;
237         int rlen;
238         int ret;
239
240         if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
241                 log("dsa_verify: no DSA key");
242                 return -1;
243         }
244
245         if (datafellows && signaturelen != SIGBLOB_LEN) {
246                 log("heh? datafellows ssh2 complies with ietf-drafts????");
247                 datafellows = 0;
248         }
249
250         log("len %d datafellows %d", signaturelen, datafellows);
251
252         /* fetch signature */
253         if (datafellows) {
254                 sigblob = signature;
255                 len = signaturelen;
256         } else {
257                 /* ietf-drafts */
258                 buffer_init(&b);
259                 buffer_append(&b, (char *) signature, signaturelen);
260                 ktype = buffer_get_string(&b, NULL);
261                 sigblob = (unsigned char *)buffer_get_string(&b, &len);
262                 rlen = buffer_len(&b);
263                 if(rlen != 0)
264                         log("remaining bytes in signature %d", rlen);
265                 buffer_free(&b);
266         }
267
268         if (len != SIGBLOB_LEN) {
269                 fatal("bad sigbloblen %d != SIGBLOB_LEN", len);
270         }
271
272         /* parse signature */
273         sig = DSA_SIG_new();
274         sig->r = BN_new();
275         sig->s = BN_new();
276         BN_bin2bn(sigblob, INTBLOB_LEN, sig->r);
277         BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s);
278         if (!datafellows) {
279                 memset(sigblob, 0, len);
280                 xfree(sigblob);
281         }
282         
283         /* sha1 the signed data (== session_id == hash) */
284         digest = xmalloc(evp_md->md_size);
285         EVP_DigestInit(&md, evp_md);
286         EVP_DigestUpdate(&md, hash, hlen);
287         EVP_DigestFinal(&md, digest, NULL);
288
289         ret = DSA_do_verify(digest, evp_md->md_size, sig, key->dsa);
290
291         memset(digest, 0, evp_md->md_size);
292         xfree(digest);
293         DSA_SIG_free(sig);
294
295         switch (ret) {
296         case 1:
297                 txt = "correct";
298                 break;
299         case 0:
300                 txt = "incorrect";
301                 break;
302         case -1:
303         default:
304                 txt = "error";
305                 break;
306         }
307         log("dsa_verify: signature %s", txt);
308         return ret;
309 }
This page took 0.056916 seconds and 5 git commands to generate.