source: trunk/third/openssh/ssh-dss.c @ 18759

Revision 18759, 4.9 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18758, which included commits to RCS files with non-trunk default branches.
Line 
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"
26RCSID("$OpenBSD: ssh-dss.c,v 1.17 2002/07/04 10:41:47 markus Exp $");
27
28#include <openssl/bn.h>
29#include <openssl/evp.h>
30
31#include "xmalloc.h"
32#include "buffer.h"
33#include "bufaux.h"
34#include "compat.h"
35#include "log.h"
36#include "key.h"
37#include "ssh-dss.h"
38
39#define INTBLOB_LEN     20
40#define SIGBLOB_LEN     (2*INTBLOB_LEN)
41
42int
43ssh_dss_sign(Key *key, u_char **sigp, u_int *lenp,
44    u_char *data, u_int datalen)
45{
46        DSA_SIG *sig;
47        const EVP_MD *evp_md = EVP_sha1();
48        EVP_MD_CTX md;
49        u_char digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN];
50        u_int rlen, slen, len, dlen;
51        Buffer b;
52
53        if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
54                error("ssh_dss_sign: no DSA key");
55                return -1;
56        }
57        EVP_DigestInit(&md, evp_md);
58        EVP_DigestUpdate(&md, data, datalen);
59        EVP_DigestFinal(&md, digest, &dlen);
60
61        sig = DSA_do_sign(digest, dlen, key->dsa);
62        memset(digest, 'd', sizeof(digest));
63
64        if (sig == NULL) {
65                error("ssh_dss_sign: sign failed");
66                return -1;
67        }
68
69        rlen = BN_num_bytes(sig->r);
70        slen = BN_num_bytes(sig->s);
71        if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
72                error("bad sig size %u %u", rlen, slen);
73                DSA_SIG_free(sig);
74                return -1;
75        }
76        memset(sigblob, 0, SIGBLOB_LEN);
77        BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
78        BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
79        DSA_SIG_free(sig);
80
81        if (datafellows & SSH_BUG_SIGBLOB) {
82                if (lenp != NULL)
83                        *lenp = SIGBLOB_LEN;
84                if (sigp != NULL) {
85                        *sigp = xmalloc(SIGBLOB_LEN);
86                        memcpy(*sigp, sigblob, SIGBLOB_LEN);
87                }
88        } else {
89                /* ietf-drafts */
90                buffer_init(&b);
91                buffer_put_cstring(&b, "ssh-dss");
92                buffer_put_string(&b, sigblob, SIGBLOB_LEN);
93                len = buffer_len(&b);
94                if (lenp != NULL)
95                        *lenp = len;
96                if (sigp != NULL) {
97                        *sigp = xmalloc(len);
98                        memcpy(*sigp, buffer_ptr(&b), len);
99                }
100                buffer_free(&b);
101        }
102        return 0;
103}
104int
105ssh_dss_verify(Key *key, u_char *signature, u_int signaturelen,
106    u_char *data, u_int datalen)
107{
108        DSA_SIG *sig;
109        const EVP_MD *evp_md = EVP_sha1();
110        EVP_MD_CTX md;
111        u_char digest[EVP_MAX_MD_SIZE], *sigblob;
112        u_int len, dlen;
113        int rlen, ret;
114        Buffer b;
115
116        if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
117                error("ssh_dss_verify: no DSA key");
118                return -1;
119        }
120
121        /* fetch signature */
122        if (datafellows & SSH_BUG_SIGBLOB) {
123                sigblob = signature;
124                len = signaturelen;
125        } else {
126                /* ietf-drafts */
127                char *ktype;
128                buffer_init(&b);
129                buffer_append(&b, signature, signaturelen);
130                ktype = buffer_get_string(&b, NULL);
131                if (strcmp("ssh-dss", ktype) != 0) {
132                        error("ssh_dss_verify: cannot handle type %s", ktype);
133                        buffer_free(&b);
134                        xfree(ktype);
135                        return -1;
136                }
137                xfree(ktype);
138                sigblob = buffer_get_string(&b, &len);
139                rlen = buffer_len(&b);
140                buffer_free(&b);
141                if (rlen != 0) {
142                        error("ssh_dss_verify: "
143                            "remaining bytes in signature %d", rlen);
144                        xfree(sigblob);
145                        return -1;
146                }
147        }
148
149        if (len != SIGBLOB_LEN) {
150                fatal("bad sigbloblen %u != SIGBLOB_LEN", len);
151        }
152
153        /* parse signature */
154        if ((sig = DSA_SIG_new()) == NULL)
155                fatal("ssh_dss_verify: DSA_SIG_new failed");
156        if ((sig->r = BN_new()) == NULL)
157                fatal("ssh_dss_verify: BN_new failed");
158        if ((sig->s = BN_new()) == NULL)
159                fatal("ssh_dss_verify: BN_new failed");
160        BN_bin2bn(sigblob, INTBLOB_LEN, sig->r);
161        BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s);
162
163        if (!(datafellows & SSH_BUG_SIGBLOB)) {
164                memset(sigblob, 0, len);
165                xfree(sigblob);
166        }
167
168        /* sha1 the data */
169        EVP_DigestInit(&md, evp_md);
170        EVP_DigestUpdate(&md, data, datalen);
171        EVP_DigestFinal(&md, digest, &dlen);
172
173        ret = DSA_do_verify(digest, dlen, sig, key->dsa);
174        memset(digest, 'd', sizeof(digest));
175
176        DSA_SIG_free(sig);
177
178        debug("ssh_dss_verify: signature %s",
179            ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error");
180        return ret;
181}
Note: See TracBrowser for help on using the repository browser.