xref: /dflybsd-src/crypto/openssh/ssh-dss.c (revision 18de8d7fff95ec279dc99590be94fa1e199430dc)
1*18de8d7fSPeter Avalos /* $OpenBSD: ssh-dss.c,v 1.24 2006/11/06 21:25:28 markus Exp $ */
2*18de8d7fSPeter Avalos /*
3*18de8d7fSPeter Avalos  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
4*18de8d7fSPeter Avalos  *
5*18de8d7fSPeter Avalos  * Redistribution and use in source and binary forms, with or without
6*18de8d7fSPeter Avalos  * modification, are permitted provided that the following conditions
7*18de8d7fSPeter Avalos  * are met:
8*18de8d7fSPeter Avalos  * 1. Redistributions of source code must retain the above copyright
9*18de8d7fSPeter Avalos  *    notice, this list of conditions and the following disclaimer.
10*18de8d7fSPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
11*18de8d7fSPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
12*18de8d7fSPeter Avalos  *    documentation and/or other materials provided with the distribution.
13*18de8d7fSPeter Avalos  *
14*18de8d7fSPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15*18de8d7fSPeter Avalos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16*18de8d7fSPeter Avalos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17*18de8d7fSPeter Avalos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18*18de8d7fSPeter Avalos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19*18de8d7fSPeter Avalos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20*18de8d7fSPeter Avalos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21*18de8d7fSPeter Avalos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22*18de8d7fSPeter Avalos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23*18de8d7fSPeter Avalos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24*18de8d7fSPeter Avalos  */
25*18de8d7fSPeter Avalos 
26*18de8d7fSPeter Avalos #include "includes.h"
27*18de8d7fSPeter Avalos 
28*18de8d7fSPeter Avalos #include <sys/types.h>
29*18de8d7fSPeter Avalos 
30*18de8d7fSPeter Avalos #include <openssl/bn.h>
31*18de8d7fSPeter Avalos #include <openssl/evp.h>
32*18de8d7fSPeter Avalos 
33*18de8d7fSPeter Avalos #include <stdarg.h>
34*18de8d7fSPeter Avalos #include <string.h>
35*18de8d7fSPeter Avalos 
36*18de8d7fSPeter Avalos #include "xmalloc.h"
37*18de8d7fSPeter Avalos #include "buffer.h"
38*18de8d7fSPeter Avalos #include "compat.h"
39*18de8d7fSPeter Avalos #include "log.h"
40*18de8d7fSPeter Avalos #include "key.h"
41*18de8d7fSPeter Avalos 
42*18de8d7fSPeter Avalos #define INTBLOB_LEN	20
43*18de8d7fSPeter Avalos #define SIGBLOB_LEN	(2*INTBLOB_LEN)
44*18de8d7fSPeter Avalos 
45*18de8d7fSPeter Avalos int
46*18de8d7fSPeter Avalos ssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp,
47*18de8d7fSPeter Avalos     const u_char *data, u_int datalen)
48*18de8d7fSPeter Avalos {
49*18de8d7fSPeter Avalos 	DSA_SIG *sig;
50*18de8d7fSPeter Avalos 	const EVP_MD *evp_md = EVP_sha1();
51*18de8d7fSPeter Avalos 	EVP_MD_CTX md;
52*18de8d7fSPeter Avalos 	u_char digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN];
53*18de8d7fSPeter Avalos 	u_int rlen, slen, len, dlen;
54*18de8d7fSPeter Avalos 	Buffer b;
55*18de8d7fSPeter Avalos 
56*18de8d7fSPeter Avalos 	if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
57*18de8d7fSPeter Avalos 		error("ssh_dss_sign: no DSA key");
58*18de8d7fSPeter Avalos 		return -1;
59*18de8d7fSPeter Avalos 	}
60*18de8d7fSPeter Avalos 	EVP_DigestInit(&md, evp_md);
61*18de8d7fSPeter Avalos 	EVP_DigestUpdate(&md, data, datalen);
62*18de8d7fSPeter Avalos 	EVP_DigestFinal(&md, digest, &dlen);
63*18de8d7fSPeter Avalos 
64*18de8d7fSPeter Avalos 	sig = DSA_do_sign(digest, dlen, key->dsa);
65*18de8d7fSPeter Avalos 	memset(digest, 'd', sizeof(digest));
66*18de8d7fSPeter Avalos 
67*18de8d7fSPeter Avalos 	if (sig == NULL) {
68*18de8d7fSPeter Avalos 		error("ssh_dss_sign: sign failed");
69*18de8d7fSPeter Avalos 		return -1;
70*18de8d7fSPeter Avalos 	}
71*18de8d7fSPeter Avalos 
72*18de8d7fSPeter Avalos 	rlen = BN_num_bytes(sig->r);
73*18de8d7fSPeter Avalos 	slen = BN_num_bytes(sig->s);
74*18de8d7fSPeter Avalos 	if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
75*18de8d7fSPeter Avalos 		error("bad sig size %u %u", rlen, slen);
76*18de8d7fSPeter Avalos 		DSA_SIG_free(sig);
77*18de8d7fSPeter Avalos 		return -1;
78*18de8d7fSPeter Avalos 	}
79*18de8d7fSPeter Avalos 	memset(sigblob, 0, SIGBLOB_LEN);
80*18de8d7fSPeter Avalos 	BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
81*18de8d7fSPeter Avalos 	BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
82*18de8d7fSPeter Avalos 	DSA_SIG_free(sig);
83*18de8d7fSPeter Avalos 
84*18de8d7fSPeter Avalos 	if (datafellows & SSH_BUG_SIGBLOB) {
85*18de8d7fSPeter Avalos 		if (lenp != NULL)
86*18de8d7fSPeter Avalos 			*lenp = SIGBLOB_LEN;
87*18de8d7fSPeter Avalos 		if (sigp != NULL) {
88*18de8d7fSPeter Avalos 			*sigp = xmalloc(SIGBLOB_LEN);
89*18de8d7fSPeter Avalos 			memcpy(*sigp, sigblob, SIGBLOB_LEN);
90*18de8d7fSPeter Avalos 		}
91*18de8d7fSPeter Avalos 	} else {
92*18de8d7fSPeter Avalos 		/* ietf-drafts */
93*18de8d7fSPeter Avalos 		buffer_init(&b);
94*18de8d7fSPeter Avalos 		buffer_put_cstring(&b, "ssh-dss");
95*18de8d7fSPeter Avalos 		buffer_put_string(&b, sigblob, SIGBLOB_LEN);
96*18de8d7fSPeter Avalos 		len = buffer_len(&b);
97*18de8d7fSPeter Avalos 		if (lenp != NULL)
98*18de8d7fSPeter Avalos 			*lenp = len;
99*18de8d7fSPeter Avalos 		if (sigp != NULL) {
100*18de8d7fSPeter Avalos 			*sigp = xmalloc(len);
101*18de8d7fSPeter Avalos 			memcpy(*sigp, buffer_ptr(&b), len);
102*18de8d7fSPeter Avalos 		}
103*18de8d7fSPeter Avalos 		buffer_free(&b);
104*18de8d7fSPeter Avalos 	}
105*18de8d7fSPeter Avalos 	return 0;
106*18de8d7fSPeter Avalos }
107*18de8d7fSPeter Avalos int
108*18de8d7fSPeter Avalos ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen,
109*18de8d7fSPeter Avalos     const u_char *data, u_int datalen)
110*18de8d7fSPeter Avalos {
111*18de8d7fSPeter Avalos 	DSA_SIG *sig;
112*18de8d7fSPeter Avalos 	const EVP_MD *evp_md = EVP_sha1();
113*18de8d7fSPeter Avalos 	EVP_MD_CTX md;
114*18de8d7fSPeter Avalos 	u_char digest[EVP_MAX_MD_SIZE], *sigblob;
115*18de8d7fSPeter Avalos 	u_int len, dlen;
116*18de8d7fSPeter Avalos 	int rlen, ret;
117*18de8d7fSPeter Avalos 	Buffer b;
118*18de8d7fSPeter Avalos 
119*18de8d7fSPeter Avalos 	if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
120*18de8d7fSPeter Avalos 		error("ssh_dss_verify: no DSA key");
121*18de8d7fSPeter Avalos 		return -1;
122*18de8d7fSPeter Avalos 	}
123*18de8d7fSPeter Avalos 
124*18de8d7fSPeter Avalos 	/* fetch signature */
125*18de8d7fSPeter Avalos 	if (datafellows & SSH_BUG_SIGBLOB) {
126*18de8d7fSPeter Avalos 		sigblob = xmalloc(signaturelen);
127*18de8d7fSPeter Avalos 		memcpy(sigblob, signature, signaturelen);
128*18de8d7fSPeter Avalos 		len = signaturelen;
129*18de8d7fSPeter Avalos 	} else {
130*18de8d7fSPeter Avalos 		/* ietf-drafts */
131*18de8d7fSPeter Avalos 		char *ktype;
132*18de8d7fSPeter Avalos 		buffer_init(&b);
133*18de8d7fSPeter Avalos 		buffer_append(&b, signature, signaturelen);
134*18de8d7fSPeter Avalos 		ktype = buffer_get_string(&b, NULL);
135*18de8d7fSPeter Avalos 		if (strcmp("ssh-dss", ktype) != 0) {
136*18de8d7fSPeter Avalos 			error("ssh_dss_verify: cannot handle type %s", ktype);
137*18de8d7fSPeter Avalos 			buffer_free(&b);
138*18de8d7fSPeter Avalos 			xfree(ktype);
139*18de8d7fSPeter Avalos 			return -1;
140*18de8d7fSPeter Avalos 		}
141*18de8d7fSPeter Avalos 		xfree(ktype);
142*18de8d7fSPeter Avalos 		sigblob = buffer_get_string(&b, &len);
143*18de8d7fSPeter Avalos 		rlen = buffer_len(&b);
144*18de8d7fSPeter Avalos 		buffer_free(&b);
145*18de8d7fSPeter Avalos 		if (rlen != 0) {
146*18de8d7fSPeter Avalos 			error("ssh_dss_verify: "
147*18de8d7fSPeter Avalos 			    "remaining bytes in signature %d", rlen);
148*18de8d7fSPeter Avalos 			xfree(sigblob);
149*18de8d7fSPeter Avalos 			return -1;
150*18de8d7fSPeter Avalos 		}
151*18de8d7fSPeter Avalos 	}
152*18de8d7fSPeter Avalos 
153*18de8d7fSPeter Avalos 	if (len != SIGBLOB_LEN) {
154*18de8d7fSPeter Avalos 		fatal("bad sigbloblen %u != SIGBLOB_LEN", len);
155*18de8d7fSPeter Avalos 	}
156*18de8d7fSPeter Avalos 
157*18de8d7fSPeter Avalos 	/* parse signature */
158*18de8d7fSPeter Avalos 	if ((sig = DSA_SIG_new()) == NULL)
159*18de8d7fSPeter Avalos 		fatal("ssh_dss_verify: DSA_SIG_new failed");
160*18de8d7fSPeter Avalos 	if ((sig->r = BN_new()) == NULL)
161*18de8d7fSPeter Avalos 		fatal("ssh_dss_verify: BN_new failed");
162*18de8d7fSPeter Avalos 	if ((sig->s = BN_new()) == NULL)
163*18de8d7fSPeter Avalos 		fatal("ssh_dss_verify: BN_new failed");
164*18de8d7fSPeter Avalos 	if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) ||
165*18de8d7fSPeter Avalos 	    (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL))
166*18de8d7fSPeter Avalos 		fatal("ssh_dss_verify: BN_bin2bn failed");
167*18de8d7fSPeter Avalos 
168*18de8d7fSPeter Avalos 	/* clean up */
169*18de8d7fSPeter Avalos 	memset(sigblob, 0, len);
170*18de8d7fSPeter Avalos 	xfree(sigblob);
171*18de8d7fSPeter Avalos 
172*18de8d7fSPeter Avalos 	/* sha1 the data */
173*18de8d7fSPeter Avalos 	EVP_DigestInit(&md, evp_md);
174*18de8d7fSPeter Avalos 	EVP_DigestUpdate(&md, data, datalen);
175*18de8d7fSPeter Avalos 	EVP_DigestFinal(&md, digest, &dlen);
176*18de8d7fSPeter Avalos 
177*18de8d7fSPeter Avalos 	ret = DSA_do_verify(digest, dlen, sig, key->dsa);
178*18de8d7fSPeter Avalos 	memset(digest, 'd', sizeof(digest));
179*18de8d7fSPeter Avalos 
180*18de8d7fSPeter Avalos 	DSA_SIG_free(sig);
181*18de8d7fSPeter Avalos 
182*18de8d7fSPeter Avalos 	debug("ssh_dss_verify: signature %s",
183*18de8d7fSPeter Avalos 	    ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error");
184*18de8d7fSPeter Avalos 	return ret;
185*18de8d7fSPeter Avalos }
186