]> andersk Git - openssh.git/blame - dsa.c
- OpenBSD CVS Updates:
[openssh.git] / dsa.c
CommitLineData
4f8c6159 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"
74fc9186 31RCSID("$OpenBSD: dsa.c,v 1.9 2000/06/20 01:39:41 markus Exp $");
4f8c6159 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"
a306f2dd 50#include "uuencode.h"
4f8c6159 51
52#define INTBLOB_LEN 20
53#define SIGBLOB_LEN (2*INTBLOB_LEN)
54
55Key *
a306f2dd 56dsa_key_from_blob(
57 char *blob, int blen)
4f8c6159 58{
59 Buffer b;
60 char *ktype;
61 int rlen;
62 DSA *dsa;
63 Key *key;
64
a306f2dd 65#ifdef DEBUG_DSS
1d1ffb87 66 dump_base64(stderr, blob, blen);
a306f2dd 67#endif
4f8c6159 68 /* fetch & parse DSA/DSS pubkey */
69 key = key_new(KEY_DSA);
70 dsa = key->dsa;
71 buffer_init(&b);
a306f2dd 72 buffer_append(&b, blob, blen);
4f8c6159 73 ktype = buffer_get_string(&b, NULL);
74 if (strcmp(KEX_DSS, ktype) != 0) {
74fc9186 75 error("dsa_key_from_blob: cannot handle type %s", ktype);
4f8c6159 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)
a306f2dd 85 error("dsa_key_from_blob: remaining bytes in key blob %d", rlen);
4f8c6159 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}
4f8c6159 94int
a306f2dd 95dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp)
4f8c6159 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}
120int
121dsa_sign(
122 Key *key,
123 unsigned char **sigp, int *lenp,
a306f2dd 124 unsigned char *data, int datalen)
4f8c6159 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);
a306f2dd 143 EVP_DigestUpdate(&md, data, datalen);
4f8c6159 144 EVP_DigestFinal(&md, digest, NULL);
145
146 sig = DSA_do_sign(digest, evp_md->md_size, key->dsa);
a306f2dd 147 if (sig == NULL) {
148 fatal("dsa_sign: cannot sign");
149 }
4f8c6159 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
d0c832f3 165 if (datafellows & SSH_BUG_SIGBLOB) {
4f8c6159 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}
189int
190dsa_verify(
191 Key *key,
192 unsigned char *signature, int signaturelen,
a306f2dd 193 unsigned char *data, int datalen)
4f8c6159 194{
195 Buffer b;
196 unsigned char *digest;
197 DSA_SIG *sig;
198 EVP_MD *evp_md = EVP_sha1();
199 EVP_MD_CTX md;
4f8c6159 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
d0c832f3 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;
4f8c6159 219 }
220
221 debug("len %d datafellows %d", signaturelen, datafellows);
222
223 /* fetch signature */
d0c832f3 224 if (datafellows & SSH_BUG_SIGBLOB) {
4f8c6159 225 sigblob = signature;
226 len = signaturelen;
227 } else {
228 /* ietf-drafts */
74fc9186 229 char *ktype;
4f8c6159 230 buffer_init(&b);
231 buffer_append(&b, (char *) signature, signaturelen);
232 ktype = buffer_get_string(&b, NULL);
74fc9186 233 if (strcmp(KEX_DSS, ktype) != 0) {
234 error("dsa_verify: cannot handle type %s", ktype);
235 buffer_free(&b);
236 return -1;
237 }
4f8c6159 238 sigblob = (unsigned char *)buffer_get_string(&b, &len);
239 rlen = buffer_len(&b);
74fc9186 240 if(rlen != 0) {
4f8c6159 241 error("remaining bytes in signature %d", rlen);
74fc9186 242 buffer_free(&b);
243 return -1;
244 }
4f8c6159 245 buffer_free(&b);
74fc9186 246 xfree(ktype);
4f8c6159 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);
d0c832f3 259
260 if (!(datafellows & SSH_BUG_SIGBLOB)) {
4f8c6159 261 memset(sigblob, 0, len);
262 xfree(sigblob);
263 }
264
a306f2dd 265 /* sha1 the data */
4f8c6159 266 digest = xmalloc(evp_md->md_size);
267 EVP_DigestInit(&md, evp_md);
a306f2dd 268 EVP_DigestUpdate(&md, data, datalen);
4f8c6159 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}
a306f2dd 292
293Key *
294dsa_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.090497 seconds and 5 git commands to generate.