Annotation of src/usr.bin/ssh/ssh-dss.c, Revision 1.6
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: *
13: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23: */
24:
25: #include "includes.h"
1.6 ! itojun 26: RCSID("$OpenBSD: ssh-dss.c,v 1.5 2001/02/04 15:32:25 stevesk Exp $");
1.4 markus 27:
28: #include <openssl/bn.h>
29: #include <openssl/evp.h>
1.1 markus 30:
31: #include "xmalloc.h"
32: #include "buffer.h"
33: #include "bufaux.h"
34: #include "compat.h"
1.4 markus 35: #include "log.h"
1.1 markus 36: #include "key.h"
1.6 ! itojun 37: #include "ssh-dss.h"
1.1 markus 38:
39: #define INTBLOB_LEN 20
40: #define SIGBLOB_LEN (2*INTBLOB_LEN)
41:
42: int
43: ssh_dss_sign(
44: Key *key,
1.2 markus 45: u_char **sigp, int *lenp,
46: u_char *data, int datalen)
1.1 markus 47: {
1.2 markus 48: u_char *digest;
49: u_char *ret;
1.1 markus 50: DSA_SIG *sig;
51: EVP_MD *evp_md = EVP_sha1();
52: EVP_MD_CTX md;
1.2 markus 53: u_int rlen;
54: u_int slen;
1.3 markus 55: u_int len, dlen;
1.2 markus 56: u_char sigblob[SIGBLOB_LEN];
1.1 markus 57: Buffer b;
58:
59: if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
60: error("ssh_dss_sign: no DSA key");
61: return -1;
62: }
1.3 markus 63: dlen = evp_md->md_size;
64: digest = xmalloc(dlen);
1.1 markus 65: EVP_DigestInit(&md, evp_md);
66: EVP_DigestUpdate(&md, data, datalen);
67: EVP_DigestFinal(&md, digest, NULL);
68:
1.3 markus 69: sig = DSA_do_sign(digest, dlen, key->dsa);
1.1 markus 70: if (sig == NULL) {
71: fatal("ssh_dss_sign: cannot sign");
72: }
1.3 markus 73: memset(digest, 0, dlen);
74: xfree(digest);
1.1 markus 75:
76: rlen = BN_num_bytes(sig->r);
77: slen = BN_num_bytes(sig->s);
78: if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
79: error("bad sig size %d %d", rlen, slen);
80: DSA_SIG_free(sig);
81: return -1;
82: }
83: debug("sig size %d %d", rlen, slen);
84:
85: memset(sigblob, 0, SIGBLOB_LEN);
86: BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
87: BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
88: DSA_SIG_free(sig);
89:
90: if (datafellows & SSH_BUG_SIGBLOB) {
91: debug("datafellows");
92: ret = xmalloc(SIGBLOB_LEN);
93: memcpy(ret, sigblob, SIGBLOB_LEN);
94: if (lenp != NULL)
95: *lenp = SIGBLOB_LEN;
96: if (sigp != NULL)
97: *sigp = ret;
98: } else {
99: /* ietf-drafts */
100: buffer_init(&b);
101: buffer_put_cstring(&b, "ssh-dss");
102: buffer_put_string(&b, sigblob, SIGBLOB_LEN);
103: len = buffer_len(&b);
104: ret = xmalloc(len);
105: memcpy(ret, buffer_ptr(&b), len);
106: buffer_free(&b);
107: if (lenp != NULL)
108: *lenp = len;
109: if (sigp != NULL)
110: *sigp = ret;
111: }
112: return 0;
113: }
114: int
115: ssh_dss_verify(
116: Key *key,
1.2 markus 117: u_char *signature, int signaturelen,
118: u_char *data, int datalen)
1.1 markus 119: {
120: Buffer b;
1.2 markus 121: u_char *digest;
1.1 markus 122: DSA_SIG *sig;
123: EVP_MD *evp_md = EVP_sha1();
124: EVP_MD_CTX md;
1.2 markus 125: u_char *sigblob;
1.1 markus 126: char *txt;
1.2 markus 127: u_int len, dlen;
1.1 markus 128: int rlen;
129: int ret;
130:
131: if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
132: error("ssh_dss_verify: no DSA key");
133: return -1;
134: }
135:
136: if (!(datafellows & SSH_BUG_SIGBLOB) &&
137: signaturelen == SIGBLOB_LEN) {
138: datafellows |= ~SSH_BUG_SIGBLOB;
139: log("autodetect SSH_BUG_SIGBLOB");
140: } else if ((datafellows & SSH_BUG_SIGBLOB) &&
141: signaturelen != SIGBLOB_LEN) {
142: log("autoremove SSH_BUG_SIGBLOB");
143: datafellows &= ~SSH_BUG_SIGBLOB;
144: }
145:
146: debug("len %d datafellows %d", signaturelen, datafellows);
147:
148: /* fetch signature */
149: if (datafellows & SSH_BUG_SIGBLOB) {
150: sigblob = signature;
151: len = signaturelen;
152: } else {
153: /* ietf-drafts */
154: char *ktype;
155: buffer_init(&b);
156: buffer_append(&b, (char *) signature, signaturelen);
157: ktype = buffer_get_string(&b, NULL);
158: if (strcmp("ssh-dss", ktype) != 0) {
159: error("ssh_dss_verify: cannot handle type %s", ktype);
160: buffer_free(&b);
161: return -1;
162: }
1.2 markus 163: sigblob = (u_char *)buffer_get_string(&b, &len);
1.1 markus 164: rlen = buffer_len(&b);
165: if(rlen != 0) {
166: error("remaining bytes in signature %d", rlen);
167: buffer_free(&b);
168: return -1;
169: }
170: buffer_free(&b);
171: xfree(ktype);
172: }
173:
174: if (len != SIGBLOB_LEN) {
175: fatal("bad sigbloblen %d != SIGBLOB_LEN", len);
176: }
177:
178: /* parse signature */
179: sig = DSA_SIG_new();
180: sig->r = BN_new();
181: sig->s = BN_new();
182: BN_bin2bn(sigblob, INTBLOB_LEN, sig->r);
183: BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s);
184:
185: if (!(datafellows & SSH_BUG_SIGBLOB)) {
186: memset(sigblob, 0, len);
187: xfree(sigblob);
188: }
1.5 stevesk 189:
1.1 markus 190: /* sha1 the data */
191: dlen = evp_md->md_size;
192: digest = xmalloc(dlen);
193: EVP_DigestInit(&md, evp_md);
194: EVP_DigestUpdate(&md, data, datalen);
195: EVP_DigestFinal(&md, digest, NULL);
196:
197: ret = DSA_do_verify(digest, dlen, sig, key->dsa);
198:
199: memset(digest, 0, dlen);
200: xfree(digest);
201: DSA_SIG_free(sig);
202:
203: switch (ret) {
204: case 1:
205: txt = "correct";
206: break;
207: case 0:
208: txt = "incorrect";
209: break;
210: case -1:
211: default:
212: txt = "error";
213: break;
214: }
215: debug("ssh_dss_verify: signature %s", txt);
216: return ret;
217: }