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.
40 # include <openssl/bn.h>
41 # include <openssl/dh.h>
42 # include <openssl/rsa.h>
43 # include <openssl/dsa.h>
44 # include <openssl/evp.h>
45 # include <openssl/bio.h>
46 # include <openssl/pem.h>
47 # include <openssl/hmac.h>
48 #endif /* HAVE_OPENSSL */
57 # include <ssl/hmac.h>
63 #define INTBLOB_LEN 20
64 #define SIGBLOB_LEN (2*INTBLOB_LEN)
67 dsa_serverkey_from_blob(
68 char *serverhostkey, int serverhostkeylen)
76 /* fetch & parse DSA/DSS pubkey */
77 key = key_new(KEY_DSA);
80 buffer_append(&b, serverhostkey, serverhostkeylen);
81 ktype = buffer_get_string(&b, NULL);
82 if (strcmp(KEX_DSS, ktype) != 0) {
83 error("dsa_serverkey_from_blob: cannot handle type %s", ktype);
87 buffer_get_bignum2(&b, dsa->p);
88 buffer_get_bignum2(&b, dsa->q);
89 buffer_get_bignum2(&b, dsa->g);
90 buffer_get_bignum2(&b, dsa->pub_key);
91 rlen = buffer_len(&b);
93 error("dsa_serverkey_from_blob: remaining bytes in serverhostkey %d", rlen);
96 debug("keytype %s", ktype);
98 DSA_print_fp(stderr, dsa, 8);
103 dsa_load_private(char *filename)
108 in = BIO_new(BIO_s_file());
110 fatal("BIO_new failed");
111 if (BIO_read_filename(in, filename) <= 0)
112 fatal("BIO_read failed %s: %s", filename, strerror(errno));
113 fprintf(stderr, "read DSA private key\n");
114 dsa = PEM_read_bio_DSAPrivateKey(in,NULL,NULL,NULL);
116 fatal("PEM_read_bio_DSAPrivateKey failed %s", filename);
121 dsa_get_serverkey(char *filename)
123 Key *k = key_new(KEY_EMPTY);
125 k->dsa = dsa_load_private(filename);
127 DSA_print_fp(stderr, dsa, 8);
132 dsa_make_serverkey_blob(Key *key, unsigned char **blobp, unsigned int *lenp)
138 if (key == NULL || key->type != KEY_DSA)
141 buffer_put_cstring(&b, KEX_DSS);
142 buffer_put_bignum2(&b, key->dsa->p);
143 buffer_put_bignum2(&b, key->dsa->q);
144 buffer_put_bignum2(&b, key->dsa->g);
145 buffer_put_bignum2(&b, key->dsa->pub_key);
146 len = buffer_len(&b);
148 memcpy(buf, buffer_ptr(&b), len);
149 memset(buffer_ptr(&b), 0, len);
160 unsigned char **sigp, int *lenp,
161 unsigned char *hash, int hlen)
163 unsigned char *digest;
166 EVP_MD *evp_md = EVP_sha1();
171 unsigned char sigblob[SIGBLOB_LEN];
174 if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
175 error("dsa_sign: no DSA key");
178 digest = xmalloc(evp_md->md_size);
179 EVP_DigestInit(&md, evp_md);
180 EVP_DigestUpdate(&md, hash, hlen);
181 EVP_DigestFinal(&md, digest, NULL);
183 sig = DSA_do_sign(digest, evp_md->md_size, key->dsa);
185 rlen = BN_num_bytes(sig->r);
186 slen = BN_num_bytes(sig->s);
187 if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
188 error("bad sig size %d %d", rlen, slen);
192 debug("sig size %d %d", rlen, slen);
194 memset(sigblob, 0, SIGBLOB_LEN);
195 BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
196 BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
200 debug("datafellows");
201 ret = xmalloc(SIGBLOB_LEN);
202 memcpy(ret, sigblob, SIGBLOB_LEN);
210 buffer_put_cstring(&b, KEX_DSS);
211 buffer_put_string(&b, sigblob, SIGBLOB_LEN);
212 len = buffer_len(&b);
214 memcpy(ret, buffer_ptr(&b), len);
226 unsigned char *signature, int signaturelen,
227 unsigned char *hash, int hlen)
230 unsigned char *digest;
232 EVP_MD *evp_md = EVP_sha1();
235 unsigned char *sigblob;
241 if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
242 error("dsa_verify: no DSA key");
246 if (datafellows && signaturelen != SIGBLOB_LEN) {
247 log("heh? datafellows ssh2 complies with ietf-drafts????");
251 debug("len %d datafellows %d", signaturelen, datafellows);
253 /* fetch signature */
260 buffer_append(&b, (char *) signature, signaturelen);
261 ktype = buffer_get_string(&b, NULL);
262 sigblob = (unsigned char *)buffer_get_string(&b, &len);
263 rlen = buffer_len(&b);
265 error("remaining bytes in signature %d", rlen);
269 if (len != SIGBLOB_LEN) {
270 fatal("bad sigbloblen %d != SIGBLOB_LEN", len);
273 /* parse signature */
277 BN_bin2bn(sigblob, INTBLOB_LEN, sig->r);
278 BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s);
280 memset(sigblob, 0, len);
284 /* sha1 the signed data (== session_id == hash) */
285 digest = xmalloc(evp_md->md_size);
286 EVP_DigestInit(&md, evp_md);
287 EVP_DigestUpdate(&md, hash, hlen);
288 EVP_DigestFinal(&md, digest, NULL);
290 ret = DSA_do_verify(digest, evp_md->md_size, sig, key->dsa);
292 memset(digest, 0, evp_md->md_size);
308 debug("dsa_verify: signature %s", txt);