Branch data Line data Source code
1 : : /* $OpenBSD: ssh-ecdsa.c,v 1.10 2014/02/03 23:28:00 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 : : #include "digest.h"
46 : :
47 : : int
48 : 84 : ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp,
49 : : const u_char *data, u_int datalen)
50 : : {
51 : : ECDSA_SIG *sig;
52 : : int hash_alg;
53 : : u_char digest[SSH_DIGEST_MAX_LENGTH];
54 : : u_int len, dlen;
55 : : Buffer b, bb;
56 : :
57 [ + - ][ + - ]: 84 : if (key == NULL || key_type_plain(key->type) != KEY_ECDSA ||
[ - + ]
58 : 84 : key->ecdsa == NULL) {
59 : 0 : error("%s: no ECDSA key", __func__);
60 : 0 : return -1;
61 : : }
62 : :
63 : 84 : hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid);
64 [ - + ]: 84 : if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
65 : 0 : error("%s: bad hash algorithm %d", __func__, hash_alg);
66 : 0 : return -1;
67 : : }
68 [ - + ]: 84 : if (ssh_digest_memory(hash_alg, data, datalen,
69 : : digest, sizeof(digest)) != 0) {
70 : 0 : error("%s: digest_memory failed", __func__);
71 : 0 : return -1;
72 : : }
73 : :
74 : 84 : sig = ECDSA_do_sign(digest, dlen, key->ecdsa);
75 : 84 : explicit_bzero(digest, sizeof(digest));
76 : :
77 [ - + ]: 84 : if (sig == NULL) {
78 : 0 : error("%s: sign failed", __func__);
79 : 0 : return -1;
80 : : }
81 : :
82 : 84 : buffer_init(&bb);
83 : 84 : buffer_put_bignum2(&bb, sig->r);
84 : 84 : buffer_put_bignum2(&bb, sig->s);
85 : 84 : ECDSA_SIG_free(sig);
86 : :
87 : 84 : buffer_init(&b);
88 : 84 : buffer_put_cstring(&b, key_ssh_name_plain(key));
89 : 84 : buffer_put_string(&b, buffer_ptr(&bb), buffer_len(&bb));
90 : 84 : buffer_free(&bb);
91 : 84 : len = buffer_len(&b);
92 [ + - ]: 84 : if (lenp != NULL)
93 : 84 : *lenp = len;
94 [ + - ]: 84 : if (sigp != NULL) {
95 : 84 : *sigp = xmalloc(len);
96 : 84 : memcpy(*sigp, buffer_ptr(&b), len);
97 : : }
98 : 84 : buffer_free(&b);
99 : :
100 : 84 : return 0;
101 : : }
102 : : int
103 : 324 : ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
104 : : const u_char *data, u_int datalen)
105 : : {
106 : : ECDSA_SIG *sig;
107 : : int hash_alg;
108 : : u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob;
109 : : u_int len, dlen;
110 : : int rlen, ret;
111 : : Buffer b, bb;
112 : : char *ktype;
113 : :
114 [ + - ][ + - ]: 324 : if (key == NULL || key_type_plain(key->type) != KEY_ECDSA ||
[ - + ]
115 : 324 : key->ecdsa == NULL) {
116 : 0 : error("%s: no ECDSA key", __func__);
117 : 0 : return -1;
118 : : }
119 : :
120 : : /* fetch signature */
121 : 324 : buffer_init(&b);
122 : 324 : buffer_append(&b, signature, signaturelen);
123 : 324 : ktype = buffer_get_string(&b, NULL);
124 [ - + ]: 324 : if (strcmp(key_ssh_name_plain(key), ktype) != 0) {
125 : 0 : error("%s: cannot handle type %s", __func__, ktype);
126 : 0 : buffer_free(&b);
127 : 0 : free(ktype);
128 : 0 : return -1;
129 : : }
130 : 324 : free(ktype);
131 : 324 : sigblob = buffer_get_string(&b, &len);
132 : 324 : rlen = buffer_len(&b);
133 : 324 : buffer_free(&b);
134 [ - + ]: 324 : if (rlen != 0) {
135 : 0 : error("%s: remaining bytes in signature %d", __func__, rlen);
136 : 0 : free(sigblob);
137 : 0 : return -1;
138 : : }
139 : :
140 : : /* parse signature */
141 [ - + ]: 324 : if ((sig = ECDSA_SIG_new()) == NULL)
142 : 0 : fatal("%s: ECDSA_SIG_new failed", __func__);
143 : :
144 : 324 : buffer_init(&bb);
145 : 324 : buffer_append(&bb, sigblob, len);
146 : 324 : buffer_get_bignum2(&bb, sig->r);
147 : 324 : buffer_get_bignum2(&bb, sig->s);
148 [ - + ]: 324 : if (buffer_len(&bb) != 0)
149 : 0 : fatal("%s: remaining bytes in inner sigblob", __func__);
150 : 324 : buffer_free(&bb);
151 : :
152 : : /* clean up */
153 : 324 : explicit_bzero(sigblob, len);
154 : 324 : free(sigblob);
155 : :
156 : : /* hash the data */
157 : 324 : hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid);
158 [ - + ]: 324 : if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
159 : 0 : error("%s: bad hash algorithm %d", __func__, hash_alg);
160 : 0 : return -1;
161 : : }
162 [ - + ]: 324 : if (ssh_digest_memory(hash_alg, data, datalen,
163 : : digest, sizeof(digest)) != 0) {
164 : 0 : error("%s: digest_memory failed", __func__);
165 : 0 : return -1;
166 : : }
167 : :
168 : 324 : ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa);
169 : 324 : explicit_bzero(digest, sizeof(digest));
170 : :
171 : 324 : ECDSA_SIG_free(sig);
172 : :
173 [ - + ]: 324 : debug("%s: signature %s", __func__,
174 [ # # ]: 0 : ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error");
175 : 324 : return ret;
176 : : }
177 : :
178 : : #endif /* OPENSSL_HAS_ECC */
|