~cjwatson/ubuntu/precise/openssh/precise-proposed

« back to all changes in this revision

Viewing changes to ssh-ecdsa.c

  • Committer: Colin Watson
  • Date: 2011-01-24 12:43:25 UTC
  • mfrom: (2660.2.14 gssapi)
  • mto: This revision was merged to the branch mainline in revision 3226.
  • Revision ID: cjwatson@debian.org-20110124124325-lpg368jr1esoeqtt
* New upstream release (http://www.openssh.org/txt/release-5.7):
  - Implement Elliptic Curve Cryptography modes for key exchange (ECDH)
    and host/user keys (ECDSA) as specified by RFC5656.  ECDH and ECDSA
    offer better performance than plain DH and DSA at the same equivalent
    symmetric key length, as well as much shorter keys.
  - sftp(1)/sftp-server(8): add a protocol extension to support a hard
    link operation.  It is available through the "ln" command in the
    client.  The old "ln" behaviour of creating a symlink is available
    using its "-s" option or through the preexisting "symlink" command.
  - scp(1): Add a new -3 option to scp: Copies between two remote hosts
    are transferred through the local host (closes: #508613).
  - ssh(1): "atomically" create the listening mux socket by binding it on
    a temporary name and then linking it into position after listen() has
    succeeded.  This allows the mux clients to determine that the server
    socket is either ready or stale without races (closes: #454784).
    Stale server sockets are now automatically removed (closes: #523250).
  - ssh(1): install a SIGCHLD handler to reap expired child process
    (closes: #594687).
  - ssh(1)/ssh-agent(1): honour $TMPDIR for client xauth and ssh-agent
    temporary directories (closes: #357469, although only if you arrange
    for ssh-agent to actually see $TMPDIR since the setgid bit will cause
    it to be stripped off).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $OpenBSD: ssh-ecdsa.c,v 1.4 2010/09/10 01:04:10 djm Exp $ */
 
2
/*
 
3
 * Copyright (c) 2000 Markus Friedl.  All rights reserved.
 
4
 * Copyright (c) 2010 Damien Miller.  All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions
 
8
 * are met:
 
9
 * 1. Redistributions of source code must retain the above copyright
 
10
 *    notice, this list of conditions and the following disclaimer.
 
11
 * 2. Redistributions in binary form must reproduce the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer in the
 
13
 *    documentation and/or other materials provided with the distribution.
 
14
 *
 
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
18
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
25
 */
 
26
 
 
27
#include "includes.h"
 
28
 
 
29
#ifdef OPENSSL_HAS_ECC
 
30
 
 
31
#include <sys/types.h>
 
32
 
 
33
#include <openssl/bn.h>
 
34
#include <openssl/ec.h>
 
35
#include <openssl/ecdsa.h>
 
36
#include <openssl/evp.h>
 
37
 
 
38
#include <string.h>
 
39
 
 
40
#include "xmalloc.h"
 
41
#include "buffer.h"
 
42
#include "compat.h"
 
43
#include "log.h"
 
44
#include "key.h"
 
45
 
 
46
int
 
47
ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp,
 
48
    const u_char *data, u_int datalen)
 
49
{
 
50
        ECDSA_SIG *sig;
 
51
        const EVP_MD *evp_md;
 
52
        EVP_MD_CTX md;
 
53
        u_char digest[EVP_MAX_MD_SIZE];
 
54
        u_int len, dlen;
 
55
        Buffer b, bb;
 
56
 
 
57
        if (key == NULL || key->ecdsa == NULL ||
 
58
            (key->type != KEY_ECDSA && key->type != KEY_ECDSA_CERT)) {
 
59
                error("%s: no ECDSA key", __func__);
 
60
                return -1;
 
61
        }
 
62
        evp_md = key_ec_nid_to_evpmd(key->ecdsa_nid);
 
63
        EVP_DigestInit(&md, evp_md);
 
64
        EVP_DigestUpdate(&md, data, datalen);
 
65
        EVP_DigestFinal(&md, digest, &dlen);
 
66
 
 
67
        sig = ECDSA_do_sign(digest, dlen, key->ecdsa);
 
68
        memset(digest, 'd', sizeof(digest));
 
69
 
 
70
        if (sig == NULL) {
 
71
                error("%s: sign failed", __func__);
 
72
                return -1;
 
73
        }
 
74
 
 
75
        buffer_init(&bb);
 
76
        buffer_put_bignum2(&bb, sig->r);
 
77
        buffer_put_bignum2(&bb, sig->s);
 
78
        ECDSA_SIG_free(sig);
 
79
 
 
80
        buffer_init(&b);
 
81
        buffer_put_cstring(&b, key_ssh_name_plain(key));
 
82
        buffer_put_string(&b, buffer_ptr(&bb), buffer_len(&bb));
 
83
        buffer_free(&bb);
 
84
        len = buffer_len(&b);
 
85
        if (lenp != NULL)
 
86
                *lenp = len;
 
87
        if (sigp != NULL) {
 
88
                *sigp = xmalloc(len);
 
89
                memcpy(*sigp, buffer_ptr(&b), len);
 
90
        }
 
91
        buffer_free(&b);
 
92
 
 
93
        return 0;
 
94
}
 
95
int
 
96
ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
 
97
    const u_char *data, u_int datalen)
 
98
{
 
99
        ECDSA_SIG *sig;
 
100
        const EVP_MD *evp_md;
 
101
        EVP_MD_CTX md;
 
102
        u_char digest[EVP_MAX_MD_SIZE], *sigblob;
 
103
        u_int len, dlen;
 
104
        int rlen, ret;
 
105
        Buffer b, bb;
 
106
        char *ktype;
 
107
 
 
108
        if (key == NULL || key->ecdsa == NULL ||
 
109
            (key->type != KEY_ECDSA && key->type != KEY_ECDSA_CERT)) {
 
110
                error("%s: no ECDSA key", __func__);
 
111
                return -1;
 
112
        }
 
113
        evp_md = key_ec_nid_to_evpmd(key->ecdsa_nid);
 
114
 
 
115
        /* fetch signature */
 
116
        buffer_init(&b);
 
117
        buffer_append(&b, signature, signaturelen);
 
118
        ktype = buffer_get_string(&b, NULL);
 
119
        if (strcmp(key_ssh_name_plain(key), ktype) != 0) {
 
120
                error("%s: cannot handle type %s", __func__, ktype);
 
121
                buffer_free(&b);
 
122
                xfree(ktype);
 
123
                return -1;
 
124
        }
 
125
        xfree(ktype);
 
126
        sigblob = buffer_get_string(&b, &len);
 
127
        rlen = buffer_len(&b);
 
128
        buffer_free(&b);
 
129
        if (rlen != 0) {
 
130
                error("%s: remaining bytes in signature %d", __func__, rlen);
 
131
                xfree(sigblob);
 
132
                return -1;
 
133
        }
 
134
 
 
135
        /* parse signature */
 
136
        if ((sig = ECDSA_SIG_new()) == NULL)
 
137
                fatal("%s: ECDSA_SIG_new failed", __func__);
 
138
        if ((sig->r = BN_new()) == NULL ||
 
139
            (sig->s = BN_new()) == NULL)
 
140
                fatal("%s: BN_new failed", __func__);
 
141
 
 
142
        buffer_init(&bb);
 
143
        buffer_append(&bb, sigblob, len);
 
144
        buffer_get_bignum2(&bb, sig->r);
 
145
        buffer_get_bignum2(&bb, sig->s);
 
146
        if (buffer_len(&bb) != 0)
 
147
                fatal("%s: remaining bytes in inner sigblob", __func__);
 
148
 
 
149
        /* clean up */
 
150
        memset(sigblob, 0, len);
 
151
        xfree(sigblob);
 
152
 
 
153
        /* hash the data */
 
154
        EVP_DigestInit(&md, evp_md);
 
155
        EVP_DigestUpdate(&md, data, datalen);
 
156
        EVP_DigestFinal(&md, digest, &dlen);
 
157
 
 
158
        ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa);
 
159
        memset(digest, 'd', sizeof(digest));
 
160
 
 
161
        ECDSA_SIG_free(sig);
 
162
 
 
163
        debug("%s: signature %s", __func__,
 
164
            ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error");
 
165
        return ret;
 
166
}
 
167
 
 
168
#endif /* OPENSSL_HAS_ECC */