Annotation of src/usr.bin/ssh/dsa.c, Revision 1.8
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.8 ! markus 31: RCSID("$Id: dsa.c,v 1.7 2000/05/08 17:42:24 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"
1.5 markus 50: #include "uuencode.h"
1.1 markus 51:
52: #define INTBLOB_LEN 20
53: #define SIGBLOB_LEN (2*INTBLOB_LEN)
54:
55: Key *
1.5 markus 56: dsa_key_from_blob(
57: char *blob, int blen)
1.1 markus 58: {
59: Buffer b;
60: char *ktype;
61: int rlen;
62: DSA *dsa;
63: Key *key;
64:
1.5 markus 65: #ifdef DEBUG_DSS
1.6 markus 66: dump_base64(stderr, blob, blen);
1.5 markus 67: #endif
1.1 markus 68: /* fetch & parse DSA/DSS pubkey */
69: key = key_new(KEY_DSA);
70: dsa = key->dsa;
71: buffer_init(&b);
1.5 markus 72: buffer_append(&b, blob, blen);
1.1 markus 73: ktype = buffer_get_string(&b, NULL);
74: if (strcmp(KEX_DSS, ktype) != 0) {
1.8 ! markus 75: error("dsa_key_from_blob: cannot handle type %s", ktype);
1.1 markus 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)
1.5 markus 85: error("dsa_key_from_blob: remaining bytes in key blob %d", rlen);
1.1 markus 86: buffer_free(&b);
87:
1.2 markus 88: debug("keytype %s", ktype);
1.1 markus 89: #ifdef DEBUG_DSS
90: DSA_print_fp(stderr, dsa, 8);
91: #endif
92: return key;
93: }
94: int
1.5 markus 95: dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp)
1.1 markus 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,
1.5 markus 124: unsigned char *data, int datalen)
1.1 markus 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) {
1.2 markus 138: error("dsa_sign: no DSA key");
1.1 markus 139: return -1;
140: }
141: digest = xmalloc(evp_md->md_size);
142: EVP_DigestInit(&md, evp_md);
1.5 markus 143: EVP_DigestUpdate(&md, data, datalen);
1.1 markus 144: EVP_DigestFinal(&md, digest, NULL);
145:
146: sig = DSA_do_sign(digest, evp_md->md_size, key->dsa);
1.5 markus 147: if (sig == NULL) {
148: fatal("dsa_sign: cannot sign");
149: }
1.1 markus 150:
1.4 markus 151: rlen = BN_num_bytes(sig->r);
152: slen = BN_num_bytes(sig->s);
153: if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
1.2 markus 154: error("bad sig size %d %d", rlen, slen);
1.1 markus 155: DSA_SIG_free(sig);
156: return -1;
157: }
1.2 markus 158: debug("sig size %d %d", rlen, slen);
1.1 markus 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:
1.7 markus 165: if (datafellows & SSH_BUG_SIGBLOB) {
1.2 markus 166: debug("datafellows");
1.1 markus 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,
1.5 markus 193: unsigned char *data, int datalen)
1.1 markus 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) {
1.2 markus 207: error("dsa_verify: no DSA key");
1.1 markus 208: return -1;
209: }
210:
1.7 markus 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;
1.1 markus 219: }
220:
1.2 markus 221: debug("len %d datafellows %d", signaturelen, datafellows);
1.1 markus 222:
223: /* fetch signature */
1.7 markus 224: if (datafellows & SSH_BUG_SIGBLOB) {
1.1 markus 225: sigblob = signature;
226: len = signaturelen;
227: } else {
228: /* ietf-drafts */
1.8 ! markus 229: char *ktype;
1.1 markus 230: buffer_init(&b);
231: buffer_append(&b, (char *) signature, signaturelen);
232: ktype = buffer_get_string(&b, NULL);
1.8 ! markus 233: if (strcmp(KEX_DSS, ktype) != 0) {
! 234: error("dsa_verify: cannot handle type %s", ktype);
! 235: buffer_free(&b);
! 236: return -1;
! 237: }
1.1 markus 238: sigblob = (unsigned char *)buffer_get_string(&b, &len);
239: rlen = buffer_len(&b);
1.8 ! markus 240: if(rlen != 0) {
1.2 markus 241: error("remaining bytes in signature %d", rlen);
1.8 ! markus 242: buffer_free(&b);
! 243: return -1;
! 244: }
1.1 markus 245: buffer_free(&b);
1.8 ! markus 246: xfree(ktype);
1.1 markus 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);
1.7 markus 259:
260: if (!(datafellows & SSH_BUG_SIGBLOB)) {
1.1 markus 261: memset(sigblob, 0, len);
262: xfree(sigblob);
263: }
264:
1.5 markus 265: /* sha1 the data */
1.1 markus 266: digest = xmalloc(evp_md->md_size);
267: EVP_DigestInit(&md, evp_md);
1.5 markus 268: EVP_DigestUpdate(&md, data, datalen);
1.1 markus 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: }
1.2 markus 289: debug("dsa_verify: signature %s", txt);
1.1 markus 290: return ret;
1.5 markus 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;
1.1 markus 309: }