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