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