diff options
author | Colin Watson <cjwatson@debian.org> | 2016-02-29 12:15:15 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2016-03-08 11:51:22 +0000 |
commit | 46961f5704f8e86cea3e99253faad55aef4d8f35 (patch) | |
tree | 0dd97fa4fb649a62b4639fe2674380872b1f3e98 /ssh-rsa.c | |
parent | c753fe267efb1b027424fa8706cf0385fc3d14c1 (diff) | |
parent | 85e40e87a75fb80a0bf893ac05a417d6c353537d (diff) |
New upstream release (7.2).
Diffstat (limited to 'ssh-rsa.c')
-rw-r--r-- | ssh-rsa.c | 149 |
1 files changed, 118 insertions, 31 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-rsa.c,v 1.53 2015/06/15 01:32:50 djm Exp $ */ | 1 | /* $OpenBSD: ssh-rsa.c,v 1.58 2015/12/11 04:21:12 mmcc Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> | 3 | * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> |
4 | * | 4 | * |
@@ -36,16 +36,56 @@ | |||
36 | 36 | ||
37 | static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); | 37 | static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); |
38 | 38 | ||
39 | static const char * | ||
40 | rsa_hash_alg_ident(int hash_alg) | ||
41 | { | ||
42 | switch (hash_alg) { | ||
43 | case SSH_DIGEST_SHA1: | ||
44 | return "ssh-rsa"; | ||
45 | case SSH_DIGEST_SHA256: | ||
46 | return "rsa-sha2-256"; | ||
47 | case SSH_DIGEST_SHA512: | ||
48 | return "rsa-sha2-512"; | ||
49 | } | ||
50 | return NULL; | ||
51 | } | ||
52 | |||
53 | static int | ||
54 | rsa_hash_alg_from_ident(const char *ident) | ||
55 | { | ||
56 | if (strcmp(ident, "ssh-rsa") == 0) | ||
57 | return SSH_DIGEST_SHA1; | ||
58 | if (strcmp(ident, "rsa-sha2-256") == 0) | ||
59 | return SSH_DIGEST_SHA256; | ||
60 | if (strcmp(ident, "rsa-sha2-512") == 0) | ||
61 | return SSH_DIGEST_SHA512; | ||
62 | return -1; | ||
63 | } | ||
64 | |||
65 | static int | ||
66 | rsa_hash_alg_nid(int type) | ||
67 | { | ||
68 | switch (type) { | ||
69 | case SSH_DIGEST_SHA1: | ||
70 | return NID_sha1; | ||
71 | case SSH_DIGEST_SHA256: | ||
72 | return NID_sha256; | ||
73 | case SSH_DIGEST_SHA512: | ||
74 | return NID_sha512; | ||
75 | default: | ||
76 | return -1; | ||
77 | } | ||
78 | } | ||
79 | |||
39 | /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ | 80 | /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ |
40 | int | 81 | int |
41 | ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, | 82 | ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, |
42 | const u_char *data, size_t datalen, u_int compat) | 83 | const u_char *data, size_t datalen, const char *alg_ident) |
43 | { | 84 | { |
44 | int hash_alg; | ||
45 | u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; | 85 | u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; |
46 | size_t slen; | 86 | size_t slen; |
47 | u_int dlen, len; | 87 | u_int dlen, len; |
48 | int nid, ret = SSH_ERR_INTERNAL_ERROR; | 88 | int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR; |
49 | struct sshbuf *b = NULL; | 89 | struct sshbuf *b = NULL; |
50 | 90 | ||
51 | if (lenp != NULL) | 91 | if (lenp != NULL) |
@@ -53,16 +93,21 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, | |||
53 | if (sigp != NULL) | 93 | if (sigp != NULL) |
54 | *sigp = NULL; | 94 | *sigp = NULL; |
55 | 95 | ||
56 | if (key == NULL || key->rsa == NULL || | 96 | if (alg_ident == NULL || strlen(alg_ident) == 0 || |
57 | sshkey_type_plain(key->type) != KEY_RSA) | 97 | strncmp(alg_ident, "ssh-rsa-cert", strlen("ssh-rsa-cert")) == 0) |
98 | hash_alg = SSH_DIGEST_SHA1; | ||
99 | else | ||
100 | hash_alg = rsa_hash_alg_from_ident(alg_ident); | ||
101 | if (key == NULL || key->rsa == NULL || hash_alg == -1 || | ||
102 | sshkey_type_plain(key->type) != KEY_RSA || | ||
103 | BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) | ||
58 | return SSH_ERR_INVALID_ARGUMENT; | 104 | return SSH_ERR_INVALID_ARGUMENT; |
59 | slen = RSA_size(key->rsa); | 105 | slen = RSA_size(key->rsa); |
60 | if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) | 106 | if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) |
61 | return SSH_ERR_INVALID_ARGUMENT; | 107 | return SSH_ERR_INVALID_ARGUMENT; |
62 | 108 | ||
63 | /* hash the data */ | 109 | /* hash the data */ |
64 | hash_alg = SSH_DIGEST_SHA1; | 110 | nid = rsa_hash_alg_nid(hash_alg); |
65 | nid = NID_sha1; | ||
66 | if ((dlen = ssh_digest_bytes(hash_alg)) == 0) | 111 | if ((dlen = ssh_digest_bytes(hash_alg)) == 0) |
67 | return SSH_ERR_INTERNAL_ERROR; | 112 | return SSH_ERR_INTERNAL_ERROR; |
68 | if ((ret = ssh_digest_memory(hash_alg, data, datalen, | 113 | if ((ret = ssh_digest_memory(hash_alg, data, datalen, |
@@ -91,7 +136,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, | |||
91 | ret = SSH_ERR_ALLOC_FAIL; | 136 | ret = SSH_ERR_ALLOC_FAIL; |
92 | goto out; | 137 | goto out; |
93 | } | 138 | } |
94 | if ((ret = sshbuf_put_cstring(b, "ssh-rsa")) != 0 || | 139 | if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 || |
95 | (ret = sshbuf_put_string(b, sig, slen)) != 0) | 140 | (ret = sshbuf_put_string(b, sig, slen)) != 0) |
96 | goto out; | 141 | goto out; |
97 | len = sshbuf_len(b); | 142 | len = sshbuf_len(b); |
@@ -111,15 +156,13 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, | |||
111 | explicit_bzero(sig, slen); | 156 | explicit_bzero(sig, slen); |
112 | free(sig); | 157 | free(sig); |
113 | } | 158 | } |
114 | if (b != NULL) | 159 | sshbuf_free(b); |
115 | sshbuf_free(b); | ||
116 | return ret; | 160 | return ret; |
117 | } | 161 | } |
118 | 162 | ||
119 | int | 163 | int |
120 | ssh_rsa_verify(const struct sshkey *key, | 164 | ssh_rsa_verify(const struct sshkey *key, |
121 | const u_char *signature, size_t signaturelen, | 165 | const u_char *sig, size_t siglen, const u_char *data, size_t datalen) |
122 | const u_char *data, size_t datalen, u_int compat) | ||
123 | { | 166 | { |
124 | char *ktype = NULL; | 167 | char *ktype = NULL; |
125 | int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; | 168 | int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; |
@@ -132,13 +175,13 @@ ssh_rsa_verify(const struct sshkey *key, | |||
132 | BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) | 175 | BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) |
133 | return SSH_ERR_INVALID_ARGUMENT; | 176 | return SSH_ERR_INVALID_ARGUMENT; |
134 | 177 | ||
135 | if ((b = sshbuf_from(signature, signaturelen)) == NULL) | 178 | if ((b = sshbuf_from(sig, siglen)) == NULL) |
136 | return SSH_ERR_ALLOC_FAIL; | 179 | return SSH_ERR_ALLOC_FAIL; |
137 | if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { | 180 | if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { |
138 | ret = SSH_ERR_INVALID_FORMAT; | 181 | ret = SSH_ERR_INVALID_FORMAT; |
139 | goto out; | 182 | goto out; |
140 | } | 183 | } |
141 | if (strcmp("ssh-rsa", ktype) != 0) { | 184 | if ((hash_alg = rsa_hash_alg_from_ident(ktype)) == -1) { |
142 | ret = SSH_ERR_KEY_TYPE_MISMATCH; | 185 | ret = SSH_ERR_KEY_TYPE_MISMATCH; |
143 | goto out; | 186 | goto out; |
144 | } | 187 | } |
@@ -167,7 +210,6 @@ ssh_rsa_verify(const struct sshkey *key, | |||
167 | explicit_bzero(sigblob, diff); | 210 | explicit_bzero(sigblob, diff); |
168 | len = modlen; | 211 | len = modlen; |
169 | } | 212 | } |
170 | hash_alg = SSH_DIGEST_SHA1; | ||
171 | if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { | 213 | if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { |
172 | ret = SSH_ERR_INTERNAL_ERROR; | 214 | ret = SSH_ERR_INTERNAL_ERROR; |
173 | goto out; | 215 | goto out; |
@@ -183,10 +225,8 @@ ssh_rsa_verify(const struct sshkey *key, | |||
183 | explicit_bzero(sigblob, len); | 225 | explicit_bzero(sigblob, len); |
184 | free(sigblob); | 226 | free(sigblob); |
185 | } | 227 | } |
186 | if (ktype != NULL) | 228 | free(ktype); |
187 | free(ktype); | 229 | sshbuf_free(b); |
188 | if (b != NULL) | ||
189 | sshbuf_free(b); | ||
190 | explicit_bzero(digest, sizeof(digest)); | 230 | explicit_bzero(digest, sizeof(digest)); |
191 | return ret; | 231 | return ret; |
192 | } | 232 | } |
@@ -196,6 +236,7 @@ ssh_rsa_verify(const struct sshkey *key, | |||
196 | * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ | 236 | * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ |
197 | * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn | 237 | * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn |
198 | */ | 238 | */ |
239 | |||
199 | /* | 240 | /* |
200 | * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) | 241 | * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) |
201 | * oiw(14) secsig(3) algorithms(2) 26 } | 242 | * oiw(14) secsig(3) algorithms(2) 26 } |
@@ -209,25 +250,71 @@ static const u_char id_sha1[] = { | |||
209 | 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ | 250 | 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ |
210 | }; | 251 | }; |
211 | 252 | ||
253 | /* | ||
254 | * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html | ||
255 | * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) | ||
256 | * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) | ||
257 | * id-sha256(1) } | ||
258 | */ | ||
259 | static const u_char id_sha256[] = { | ||
260 | 0x30, 0x31, /* type Sequence, length 0x31 (49) */ | ||
261 | 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ | ||
262 | 0x06, 0x09, /* type OID, length 0x09 */ | ||
263 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */ | ||
264 | 0x05, 0x00, /* NULL */ | ||
265 | 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */ | ||
266 | }; | ||
267 | |||
268 | /* | ||
269 | * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html | ||
270 | * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) | ||
271 | * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) | ||
272 | * id-sha256(3) } | ||
273 | */ | ||
274 | static const u_char id_sha512[] = { | ||
275 | 0x30, 0x51, /* type Sequence, length 0x51 (81) */ | ||
276 | 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ | ||
277 | 0x06, 0x09, /* type OID, length 0x09 */ | ||
278 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */ | ||
279 | 0x05, 0x00, /* NULL */ | ||
280 | 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */ | ||
281 | }; | ||
282 | |||
283 | static int | ||
284 | rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp) | ||
285 | { | ||
286 | switch (hash_alg) { | ||
287 | case SSH_DIGEST_SHA1: | ||
288 | *oidp = id_sha1; | ||
289 | *oidlenp = sizeof(id_sha1); | ||
290 | break; | ||
291 | case SSH_DIGEST_SHA256: | ||
292 | *oidp = id_sha256; | ||
293 | *oidlenp = sizeof(id_sha256); | ||
294 | break; | ||
295 | case SSH_DIGEST_SHA512: | ||
296 | *oidp = id_sha512; | ||
297 | *oidlenp = sizeof(id_sha512); | ||
298 | break; | ||
299 | default: | ||
300 | return SSH_ERR_INVALID_ARGUMENT; | ||
301 | } | ||
302 | return 0; | ||
303 | } | ||
304 | |||
212 | static int | 305 | static int |
213 | openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, | 306 | openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, |
214 | u_char *sigbuf, size_t siglen, RSA *rsa) | 307 | u_char *sigbuf, size_t siglen, RSA *rsa) |
215 | { | 308 | { |
216 | size_t ret, rsasize = 0, oidlen = 0, hlen = 0; | 309 | size_t rsasize = 0, oidlen = 0, hlen = 0; |
217 | int len, oidmatch, hashmatch; | 310 | int ret, len, oidmatch, hashmatch; |
218 | const u_char *oid = NULL; | 311 | const u_char *oid = NULL; |
219 | u_char *decrypted = NULL; | 312 | u_char *decrypted = NULL; |
220 | 313 | ||
314 | if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0) | ||
315 | return ret; | ||
221 | ret = SSH_ERR_INTERNAL_ERROR; | 316 | ret = SSH_ERR_INTERNAL_ERROR; |
222 | switch (hash_alg) { | 317 | hlen = ssh_digest_bytes(hash_alg); |
223 | case SSH_DIGEST_SHA1: | ||
224 | oid = id_sha1; | ||
225 | oidlen = sizeof(id_sha1); | ||
226 | hlen = 20; | ||
227 | break; | ||
228 | default: | ||
229 | goto done; | ||
230 | } | ||
231 | if (hashlen != hlen) { | 318 | if (hashlen != hlen) { |
232 | ret = SSH_ERR_INVALID_ARGUMENT; | 319 | ret = SSH_ERR_INVALID_ARGUMENT; |
233 | goto done; | 320 | goto done; |