Annotation of src/usr.bin/ssh/ssh-dss.c, Revision 1.5
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.5 ! stevesk 26: RCSID("$OpenBSD: ssh-dss.c,v 1.4 2001/01/21 19:05:57 markus 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"
37:
38: #define INTBLOB_LEN 20
39: #define SIGBLOB_LEN (2*INTBLOB_LEN)
40:
41: int
42: ssh_dss_sign(
43: Key *key,
1.2 markus 44: u_char **sigp, int *lenp,
45: u_char *data, int datalen)
1.1 markus 46: {
1.2 markus 47: u_char *digest;
48: u_char *ret;
1.1 markus 49: DSA_SIG *sig;
50: EVP_MD *evp_md = EVP_sha1();
51: EVP_MD_CTX md;
1.2 markus 52: u_int rlen;
53: u_int slen;
1.3 markus 54: u_int len, dlen;
1.2 markus 55: u_char sigblob[SIGBLOB_LEN];
1.1 markus 56: Buffer b;
57:
58: if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
59: error("ssh_dss_sign: no DSA key");
60: return -1;
61: }
1.3 markus 62: dlen = evp_md->md_size;
63: digest = xmalloc(dlen);
1.1 markus 64: EVP_DigestInit(&md, evp_md);
65: EVP_DigestUpdate(&md, data, datalen);
66: EVP_DigestFinal(&md, digest, NULL);
67:
1.3 markus 68: sig = DSA_do_sign(digest, dlen, key->dsa);
1.1 markus 69: if (sig == NULL) {
70: fatal("ssh_dss_sign: cannot sign");
71: }
1.3 markus 72: memset(digest, 0, dlen);
73: xfree(digest);
1.1 markus 74:
75: rlen = BN_num_bytes(sig->r);
76: slen = BN_num_bytes(sig->s);
77: if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
78: error("bad sig size %d %d", rlen, slen);
79: DSA_SIG_free(sig);
80: return -1;
81: }
82: debug("sig size %d %d", rlen, slen);
83:
84: memset(sigblob, 0, SIGBLOB_LEN);
85: BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
86: BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
87: DSA_SIG_free(sig);
88:
89: if (datafellows & SSH_BUG_SIGBLOB) {
90: debug("datafellows");
91: ret = xmalloc(SIGBLOB_LEN);
92: memcpy(ret, sigblob, SIGBLOB_LEN);
93: if (lenp != NULL)
94: *lenp = SIGBLOB_LEN;
95: if (sigp != NULL)
96: *sigp = ret;
97: } else {
98: /* ietf-drafts */
99: buffer_init(&b);
100: buffer_put_cstring(&b, "ssh-dss");
101: buffer_put_string(&b, sigblob, SIGBLOB_LEN);
102: len = buffer_len(&b);
103: ret = xmalloc(len);
104: memcpy(ret, buffer_ptr(&b), len);
105: buffer_free(&b);
106: if (lenp != NULL)
107: *lenp = len;
108: if (sigp != NULL)
109: *sigp = ret;
110: }
111: return 0;
112: }
113: int
114: ssh_dss_verify(
115: Key *key,
1.2 markus 116: u_char *signature, int signaturelen,
117: u_char *data, int datalen)
1.1 markus 118: {
119: Buffer b;
1.2 markus 120: u_char *digest;
1.1 markus 121: DSA_SIG *sig;
122: EVP_MD *evp_md = EVP_sha1();
123: EVP_MD_CTX md;
1.2 markus 124: u_char *sigblob;
1.1 markus 125: char *txt;
1.2 markus 126: u_int len, dlen;
1.1 markus 127: int rlen;
128: int ret;
129:
130: if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
131: error("ssh_dss_verify: no DSA key");
132: return -1;
133: }
134:
135: if (!(datafellows & SSH_BUG_SIGBLOB) &&
136: signaturelen == SIGBLOB_LEN) {
137: datafellows |= ~SSH_BUG_SIGBLOB;
138: log("autodetect SSH_BUG_SIGBLOB");
139: } else if ((datafellows & SSH_BUG_SIGBLOB) &&
140: signaturelen != SIGBLOB_LEN) {
141: log("autoremove SSH_BUG_SIGBLOB");
142: datafellows &= ~SSH_BUG_SIGBLOB;
143: }
144:
145: debug("len %d datafellows %d", signaturelen, datafellows);
146:
147: /* fetch signature */
148: if (datafellows & SSH_BUG_SIGBLOB) {
149: sigblob = signature;
150: len = signaturelen;
151: } else {
152: /* ietf-drafts */
153: char *ktype;
154: buffer_init(&b);
155: buffer_append(&b, (char *) signature, signaturelen);
156: ktype = buffer_get_string(&b, NULL);
157: if (strcmp("ssh-dss", ktype) != 0) {
158: error("ssh_dss_verify: cannot handle type %s", ktype);
159: buffer_free(&b);
160: return -1;
161: }
1.2 markus 162: sigblob = (u_char *)buffer_get_string(&b, &len);
1.1 markus 163: rlen = buffer_len(&b);
164: if(rlen != 0) {
165: error("remaining bytes in signature %d", rlen);
166: buffer_free(&b);
167: return -1;
168: }
169: buffer_free(&b);
170: xfree(ktype);
171: }
172:
173: if (len != SIGBLOB_LEN) {
174: fatal("bad sigbloblen %d != SIGBLOB_LEN", len);
175: }
176:
177: /* parse signature */
178: sig = DSA_SIG_new();
179: sig->r = BN_new();
180: sig->s = BN_new();
181: BN_bin2bn(sigblob, INTBLOB_LEN, sig->r);
182: BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s);
183:
184: if (!(datafellows & SSH_BUG_SIGBLOB)) {
185: memset(sigblob, 0, len);
186: xfree(sigblob);
187: }
1.5 ! stevesk 188:
1.1 markus 189: /* sha1 the data */
190: dlen = evp_md->md_size;
191: digest = xmalloc(dlen);
192: EVP_DigestInit(&md, evp_md);
193: EVP_DigestUpdate(&md, data, datalen);
194: EVP_DigestFinal(&md, digest, NULL);
195:
196: ret = DSA_do_verify(digest, dlen, sig, key->dsa);
197:
198: memset(digest, 0, dlen);
199: xfree(digest);
200: DSA_SIG_free(sig);
201:
202: switch (ret) {
203: case 1:
204: txt = "correct";
205: break;
206: case 0:
207: txt = "incorrect";
208: break;
209: case -1:
210: default:
211: txt = "error";
212: break;
213: }
214: debug("ssh_dss_verify: signature %s", txt);
215: return ret;
216: }