diff options
author | Damien Miller <djm@mindrot.org> | 2014-07-02 15:28:02 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2014-07-02 15:28:02 +1000 |
commit | 8668706d0f52654fe64c0ca41a96113aeab8d2b8 (patch) | |
tree | 73e78e1ea3d39206e39870bbe0af17d6c430fb51 /ssh-ed25519.c | |
parent | 2cd7929250cf9e9f658d70dcd452f529ba08c942 (diff) |
- djm@cvs.openbsd.org 2014/06/24 01:13:21
[Makefile.in auth-bsdauth.c auth-chall.c auth-options.c auth-rsa.c
[auth2-none.c auth2-pubkey.c authfile.c authfile.h cipher-3des1.c
[cipher-chachapoly.c cipher-chachapoly.h cipher.c cipher.h
[digest-libc.c digest-openssl.c digest.h dns.c entropy.c hmac.h
[hostfile.c key.c key.h krl.c monitor.c packet.c rsa.c rsa.h
[ssh-add.c ssh-agent.c ssh-dss.c ssh-ecdsa.c ssh-ed25519.c
[ssh-keygen.c ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c
[ssh-rsa.c sshbuf-misc.c sshbuf.h sshconnect.c sshconnect1.c
[sshconnect2.c sshd.c sshkey.c sshkey.h
[openbsd-compat/openssl-compat.c openbsd-compat/openssl-compat.h]
New key API: refactor key-related functions to be more library-like,
existing API is offered as a set of wrappers.
with and ok markus@
Thanks also to Ben Hawkes, David Tomaschik, Ivan Fratric, Matthew
Dempsky and Ron Bowes for a detailed review a few months ago.
NB. This commit also removes portable OpenSSH support for OpenSSL
<0.9.8e.
Diffstat (limited to 'ssh-ed25519.c')
-rw-r--r-- | ssh-ed25519.c | 183 |
1 files changed, 100 insertions, 83 deletions
diff --git a/ssh-ed25519.c b/ssh-ed25519.c index 160d1f23b..cb87d4790 100644 --- a/ssh-ed25519.c +++ b/ssh-ed25519.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-ed25519.c,v 1.3 2014/02/23 20:03:42 djm Exp $ */ | 1 | /* $OpenBSD: ssh-ed25519.c,v 1.4 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2013 Markus Friedl <markus@openbsd.org> | 3 | * Copyright (c) 2013 Markus Friedl <markus@openbsd.org> |
4 | * | 4 | * |
@@ -18,132 +18,149 @@ | |||
18 | #include "includes.h" | 18 | #include "includes.h" |
19 | 19 | ||
20 | #include <sys/types.h> | 20 | #include <sys/types.h> |
21 | #include <limits.h> | ||
21 | 22 | ||
22 | #include "crypto_api.h" | 23 | #include "crypto_api.h" |
23 | 24 | ||
24 | #include <limits.h> | ||
25 | #include <string.h> | 25 | #include <string.h> |
26 | #include <stdarg.h> | 26 | #include <stdarg.h> |
27 | 27 | ||
28 | #include "xmalloc.h" | 28 | #include "xmalloc.h" |
29 | #include "log.h" | 29 | #include "log.h" |
30 | #include "buffer.h" | 30 | #include "buffer.h" |
31 | #include "key.h" | 31 | #define SSHKEY_INTERNAL |
32 | #include "sshkey.h" | ||
33 | #include "ssherr.h" | ||
32 | #include "ssh.h" | 34 | #include "ssh.h" |
33 | 35 | ||
34 | int | 36 | int |
35 | ssh_ed25519_sign(const Key *key, u_char **sigp, u_int *lenp, | 37 | ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, |
36 | const u_char *data, u_int datalen) | 38 | const u_char *data, size_t datalen, u_int compat) |
37 | { | 39 | { |
38 | u_char *sig; | 40 | u_char *sig = NULL; |
39 | u_int slen, len; | 41 | size_t slen = 0, len; |
40 | unsigned long long smlen; | 42 | unsigned long long smlen; |
41 | int ret; | 43 | int r, ret; |
42 | Buffer b; | 44 | struct sshbuf *b = NULL; |
43 | 45 | ||
44 | if (key == NULL || key_type_plain(key->type) != KEY_ED25519 || | 46 | if (lenp != NULL) |
45 | key->ed25519_sk == NULL) { | 47 | *lenp = 0; |
46 | error("%s: no ED25519 key", __func__); | 48 | if (sigp != NULL) |
47 | return -1; | 49 | *sigp = NULL; |
48 | } | ||
49 | 50 | ||
50 | if (datalen >= UINT_MAX - crypto_sign_ed25519_BYTES) { | 51 | if (key == NULL || |
51 | error("%s: datalen %u too long", __func__, datalen); | 52 | sshkey_type_plain(key->type) != KEY_ED25519 || |
52 | return -1; | 53 | key->ed25519_sk == NULL || |
53 | } | 54 | datalen >= INT_MAX - crypto_sign_ed25519_BYTES) |
55 | return SSH_ERR_INVALID_ARGUMENT; | ||
54 | smlen = slen = datalen + crypto_sign_ed25519_BYTES; | 56 | smlen = slen = datalen + crypto_sign_ed25519_BYTES; |
55 | sig = xmalloc(slen); | 57 | if ((sig = malloc(slen)) == NULL) |
58 | return SSH_ERR_ALLOC_FAIL; | ||
56 | 59 | ||
57 | if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen, | 60 | if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen, |
58 | key->ed25519_sk)) != 0 || smlen <= datalen) { | 61 | key->ed25519_sk)) != 0 || smlen <= datalen) { |
59 | error("%s: crypto_sign_ed25519 failed: %d", __func__, ret); | 62 | r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */ |
60 | free(sig); | 63 | goto out; |
61 | return -1; | ||
62 | } | 64 | } |
63 | /* encode signature */ | 65 | /* encode signature */ |
64 | buffer_init(&b); | 66 | if ((b = sshbuf_new()) == NULL) { |
65 | buffer_put_cstring(&b, "ssh-ed25519"); | 67 | r = SSH_ERR_ALLOC_FAIL; |
66 | buffer_put_string(&b, sig, smlen - datalen); | 68 | goto out; |
67 | len = buffer_len(&b); | 69 | } |
70 | if ((r = sshbuf_put_cstring(b, "ssh-ed25519")) != 0 || | ||
71 | (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0) | ||
72 | goto out; | ||
73 | len = sshbuf_len(b); | ||
74 | if (sigp != NULL) { | ||
75 | if ((*sigp = malloc(len)) == NULL) { | ||
76 | r = SSH_ERR_ALLOC_FAIL; | ||
77 | goto out; | ||
78 | } | ||
79 | memcpy(*sigp, sshbuf_ptr(b), len); | ||
80 | } | ||
68 | if (lenp != NULL) | 81 | if (lenp != NULL) |
69 | *lenp = len; | 82 | *lenp = len; |
70 | if (sigp != NULL) { | 83 | /* success */ |
71 | *sigp = xmalloc(len); | 84 | r = 0; |
72 | memcpy(*sigp, buffer_ptr(&b), len); | 85 | out: |
86 | sshbuf_free(b); | ||
87 | if (sig != NULL) { | ||
88 | explicit_bzero(sig, slen); | ||
89 | free(sig); | ||
73 | } | 90 | } |
74 | buffer_free(&b); | ||
75 | explicit_bzero(sig, slen); | ||
76 | free(sig); | ||
77 | 91 | ||
78 | return 0; | 92 | return r; |
79 | } | 93 | } |
80 | 94 | ||
81 | int | 95 | int |
82 | ssh_ed25519_verify(const Key *key, const u_char *signature, u_int signaturelen, | 96 | ssh_ed25519_verify(const struct sshkey *key, |
83 | const u_char *data, u_int datalen) | 97 | const u_char *signature, size_t signaturelen, |
98 | const u_char *data, size_t datalen, u_int compat) | ||
84 | { | 99 | { |
85 | Buffer b; | 100 | struct sshbuf *b = NULL; |
86 | char *ktype; | 101 | char *ktype = NULL; |
87 | u_char *sigblob, *sm, *m; | 102 | const u_char *sigblob; |
88 | u_int len; | 103 | u_char *sm = NULL, *m = NULL; |
89 | unsigned long long smlen, mlen; | 104 | size_t len; |
90 | int rlen, ret; | 105 | unsigned long long smlen = 0, mlen = 0; |
106 | int r, ret; | ||
91 | 107 | ||
92 | if (key == NULL || key_type_plain(key->type) != KEY_ED25519 || | 108 | if (key == NULL || |
93 | key->ed25519_pk == NULL) { | 109 | sshkey_type_plain(key->type) != KEY_ED25519 || |
94 | error("%s: no ED25519 key", __func__); | 110 | key->ed25519_pk == NULL || |
95 | return -1; | 111 | datalen >= INT_MAX - crypto_sign_ed25519_BYTES) |
96 | } | 112 | return SSH_ERR_INVALID_ARGUMENT; |
97 | buffer_init(&b); | 113 | |
98 | buffer_append(&b, signature, signaturelen); | 114 | if ((b = sshbuf_from(signature, signaturelen)) == NULL) |
99 | ktype = buffer_get_cstring(&b, NULL); | 115 | return SSH_ERR_ALLOC_FAIL; |
116 | if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 || | ||
117 | (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0) | ||
118 | goto out; | ||
100 | if (strcmp("ssh-ed25519", ktype) != 0) { | 119 | if (strcmp("ssh-ed25519", ktype) != 0) { |
101 | error("%s: cannot handle type %s", __func__, ktype); | 120 | r = SSH_ERR_KEY_TYPE_MISMATCH; |
102 | buffer_free(&b); | 121 | goto out; |
103 | free(ktype); | ||
104 | return -1; | ||
105 | } | 122 | } |
106 | free(ktype); | 123 | if (sshbuf_len(b) != 0) { |
107 | sigblob = buffer_get_string(&b, &len); | 124 | r = SSH_ERR_UNEXPECTED_TRAILING_DATA; |
108 | rlen = buffer_len(&b); | 125 | goto out; |
109 | buffer_free(&b); | ||
110 | if (rlen != 0) { | ||
111 | error("%s: remaining bytes in signature %d", __func__, rlen); | ||
112 | free(sigblob); | ||
113 | return -1; | ||
114 | } | 126 | } |
115 | if (len > crypto_sign_ed25519_BYTES) { | 127 | if (len > crypto_sign_ed25519_BYTES) { |
116 | error("%s: len %u > crypto_sign_ed25519_BYTES %u", __func__, | 128 | r = SSH_ERR_INVALID_FORMAT; |
117 | len, crypto_sign_ed25519_BYTES); | 129 | goto out; |
118 | free(sigblob); | ||
119 | return -1; | ||
120 | } | 130 | } |
131 | if (datalen >= SIZE_MAX - len) | ||
132 | return SSH_ERR_INVALID_ARGUMENT; | ||
121 | smlen = len + datalen; | 133 | smlen = len + datalen; |
122 | sm = xmalloc(smlen); | 134 | mlen = smlen; |
135 | if ((sm = malloc(smlen)) == NULL || (m = xmalloc(mlen)) == NULL) { | ||
136 | r = SSH_ERR_ALLOC_FAIL; | ||
137 | goto out; | ||
138 | } | ||
123 | memcpy(sm, sigblob, len); | 139 | memcpy(sm, sigblob, len); |
124 | memcpy(sm+len, data, datalen); | 140 | memcpy(sm+len, data, datalen); |
125 | mlen = smlen; | ||
126 | m = xmalloc(mlen); | ||
127 | if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen, | 141 | if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen, |
128 | key->ed25519_pk)) != 0) { | 142 | key->ed25519_pk)) != 0) { |
129 | debug2("%s: crypto_sign_ed25519_open failed: %d", | 143 | debug2("%s: crypto_sign_ed25519_open failed: %d", |
130 | __func__, ret); | 144 | __func__, ret); |
131 | } | 145 | } |
132 | if (ret == 0 && mlen != datalen) { | 146 | if (ret != 0 || mlen != datalen) { |
133 | debug2("%s: crypto_sign_ed25519_open " | 147 | r = SSH_ERR_SIGNATURE_INVALID; |
134 | "mlen != datalen (%llu != %u)", __func__, mlen, datalen); | 148 | goto out; |
135 | ret = -1; | ||
136 | } | 149 | } |
137 | /* XXX compare 'm' and 'data' ? */ | 150 | /* XXX compare 'm' and 'data' ? */ |
138 | 151 | /* success */ | |
139 | explicit_bzero(sigblob, len); | 152 | r = 0; |
140 | explicit_bzero(sm, smlen); | 153 | out: |
141 | explicit_bzero(m, smlen); /* NB. mlen may be invalid if ret != 0 */ | 154 | if (sm != NULL) { |
142 | free(sigblob); | 155 | explicit_bzero(sm, smlen); |
143 | free(sm); | 156 | free(sm); |
144 | free(m); | 157 | } |
145 | debug("%s: signature %scorrect", __func__, (ret != 0) ? "in" : ""); | 158 | if (m != NULL) { |
146 | 159 | explicit_bzero(m, smlen); /* NB mlen may be invalid if r != 0 */ | |
147 | /* translate return code carefully */ | 160 | free(m); |
148 | return (ret == 0) ? 1 : -1; | 161 | } |
162 | sshbuf_free(b); | ||
163 | free(ktype); | ||
164 | return r; | ||
149 | } | 165 | } |
166 | |||