2 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
31 RCSID("$OpenBSD: dsa.c,v 1.9 2000/06/20 01:39:41 markus Exp $");
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>
47 #include <openssl/hmac.h>
52 #define INTBLOB_LEN 20
53 #define SIGBLOB_LEN (2*INTBLOB_LEN)
66 dump_base64(stderr, blob, blen);
68 /* fetch & parse DSA/DSS pubkey */
69 key = key_new(KEY_DSA);
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);
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);
85 error("dsa_key_from_blob: remaining bytes in key blob %d", rlen);
88 debug("keytype %s", ktype);
90 DSA_print_fp(stderr, dsa, 8);
95 dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp)
101 if (key == NULL || key->type != KEY_DSA)
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);
111 memcpy(buf, buffer_ptr(&b), len);
112 memset(buffer_ptr(&b), 0, len);
123 unsigned char **sigp, int *lenp,
124 unsigned char *data, int datalen)
126 unsigned char *digest;
129 EVP_MD *evp_md = EVP_sha1();
134 unsigned char sigblob[SIGBLOB_LEN];
137 if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
138 error("dsa_sign: no DSA key");
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);
146 sig = DSA_do_sign(digest, evp_md->md_size, key->dsa);
148 fatal("dsa_sign: cannot sign");
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);
158 debug("sig size %d %d", rlen, slen);
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);
165 if (datafellows & SSH_BUG_SIGBLOB) {
166 debug("datafellows");
167 ret = xmalloc(SIGBLOB_LEN);
168 memcpy(ret, sigblob, SIGBLOB_LEN);
176 buffer_put_cstring(&b, KEX_DSS);
177 buffer_put_string(&b, sigblob, SIGBLOB_LEN);
178 len = buffer_len(&b);
180 memcpy(ret, buffer_ptr(&b), len);
192 unsigned char *signature, int signaturelen,
193 unsigned char *data, int datalen)
196 unsigned char *digest;
198 EVP_MD *evp_md = EVP_sha1();
200 unsigned char *sigblob;
206 if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
207 error("dsa_verify: no DSA key");
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;
221 debug("len %d datafellows %d", signaturelen, datafellows);
223 /* fetch signature */
224 if (datafellows & SSH_BUG_SIGBLOB) {
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);
238 sigblob = (unsigned char *)buffer_get_string(&b, &len);
239 rlen = buffer_len(&b);
241 error("remaining bytes in signature %d", rlen);
249 if (len != SIGBLOB_LEN) {
250 fatal("bad sigbloblen %d != SIGBLOB_LEN", len);
253 /* parse signature */
257 BN_bin2bn(sigblob, INTBLOB_LEN, sig->r);
258 BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s);
260 if (!(datafellows & SSH_BUG_SIGBLOB)) {
261 memset(sigblob, 0, len);
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);
271 ret = DSA_do_verify(digest, evp_md->md_size, sig, key->dsa);
273 memset(digest, 0, evp_md->md_size);
289 debug("dsa_verify: signature %s", txt);
294 dsa_generate_key(unsigned int bits)
296 DSA *dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
299 fatal("DSA_generate_parameters failed");
301 if (!DSA_generate_key(dsa)) {
302 fatal("DSA_generate_keys failed");
305 k = key_new(KEY_EMPTY);