summaryrefslogtreecommitdiff
path: root/ssh-rsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-rsa.c')
-rw-r--r--ssh-rsa.c136
1 files changed, 113 insertions, 23 deletions
diff --git a/ssh-rsa.c b/ssh-rsa.c
index 08090d14e..81dab05b3 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-rsa.c,v 1.54 2015/09/09 00:52:44 djm Exp $ */ 1/* $OpenBSD: ssh-rsa.c,v 1.55 2015/12/04 16:41:28 markus 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,60 @@
36 36
37static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); 37static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
38 38
39static const char *
40rsa_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
53static int
54rsa_hash_alg_from_ident(const char *ident)
55{
56 if (ident == NULL || strlen(ident) == 0)
57 return SSH_DIGEST_SHA1;
58 if (strcmp(ident, "ssh-rsa") == 0)
59 return SSH_DIGEST_SHA1;
60 if (strcmp(ident, "rsa-sha2-256") == 0)
61 return SSH_DIGEST_SHA256;
62 if (strcmp(ident, "rsa-sha2-512") == 0)
63 return SSH_DIGEST_SHA512;
64 if (strncmp(ident, "ssh-rsa-cert", strlen("ssh-rsa-cert")) == 0)
65 return SSH_DIGEST_SHA1;
66 return -1;
67}
68
69static int
70rsa_hash_alg_nid(int type)
71{
72 switch (type) {
73 case SSH_DIGEST_SHA1:
74 return NID_sha1;
75 case SSH_DIGEST_SHA256:
76 return NID_sha256;
77 case SSH_DIGEST_SHA512:
78 return NID_sha512;
79 default:
80 return -1;
81 }
82}
83
39/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ 84/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
40int 85int
41ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, 86ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
42 const u_char *data, size_t datalen, u_int compat) 87 const u_char *data, size_t datalen, const char *alg_ident)
43{ 88{
44 int hash_alg;
45 u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; 89 u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL;
46 size_t slen; 90 size_t slen;
47 u_int dlen, len; 91 u_int dlen, len;
48 int nid, ret = SSH_ERR_INTERNAL_ERROR; 92 int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
49 struct sshbuf *b = NULL; 93 struct sshbuf *b = NULL;
50 94
51 if (lenp != NULL) 95 if (lenp != NULL)
@@ -53,16 +97,17 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
53 if (sigp != NULL) 97 if (sigp != NULL)
54 *sigp = NULL; 98 *sigp = NULL;
55 99
56 if (key == NULL || key->rsa == NULL || 100 hash_alg = rsa_hash_alg_from_ident(alg_ident);
57 sshkey_type_plain(key->type) != KEY_RSA) 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);
@@ -118,8 +163,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
118 163
119int 164int
120ssh_rsa_verify(const struct sshkey *key, 165ssh_rsa_verify(const struct sshkey *key,
121 const u_char *signature, size_t signaturelen, 166 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{ 167{
124 char *ktype = NULL; 168 char *ktype = NULL;
125 int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; 169 int hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
@@ -132,13 +176,13 @@ ssh_rsa_verify(const struct sshkey *key,
132 BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) 176 BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
133 return SSH_ERR_INVALID_ARGUMENT; 177 return SSH_ERR_INVALID_ARGUMENT;
134 178
135 if ((b = sshbuf_from(signature, signaturelen)) == NULL) 179 if ((b = sshbuf_from(sig, siglen)) == NULL)
136 return SSH_ERR_ALLOC_FAIL; 180 return SSH_ERR_ALLOC_FAIL;
137 if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { 181 if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
138 ret = SSH_ERR_INVALID_FORMAT; 182 ret = SSH_ERR_INVALID_FORMAT;
139 goto out; 183 goto out;
140 } 184 }
141 if (strcmp("ssh-rsa", ktype) != 0) { 185 if ((hash_alg = rsa_hash_alg_from_ident(ktype)) == -1) {
142 ret = SSH_ERR_KEY_TYPE_MISMATCH; 186 ret = SSH_ERR_KEY_TYPE_MISMATCH;
143 goto out; 187 goto out;
144 } 188 }
@@ -167,7 +211,6 @@ ssh_rsa_verify(const struct sshkey *key,
167 explicit_bzero(sigblob, diff); 211 explicit_bzero(sigblob, diff);
168 len = modlen; 212 len = modlen;
169 } 213 }
170 hash_alg = SSH_DIGEST_SHA1;
171 if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { 214 if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
172 ret = SSH_ERR_INTERNAL_ERROR; 215 ret = SSH_ERR_INTERNAL_ERROR;
173 goto out; 216 goto out;
@@ -196,6 +239,7 @@ ssh_rsa_verify(const struct sshkey *key,
196 * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ 239 * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
197 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn 240 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
198 */ 241 */
242
199/* 243/*
200 * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) 244 * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
201 * oiw(14) secsig(3) algorithms(2) 26 } 245 * oiw(14) secsig(3) algorithms(2) 26 }
@@ -209,6 +253,58 @@ static const u_char id_sha1[] = {
209 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ 253 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
210}; 254};
211 255
256/*
257 * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
258 * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
259 * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
260 * id-sha256(1) }
261 */
262static const u_char id_sha256[] = {
263 0x30, 0x31, /* type Sequence, length 0x31 (49) */
264 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
265 0x06, 0x09, /* type OID, length 0x09 */
266 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */
267 0x05, 0x00, /* NULL */
268 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */
269};
270
271/*
272 * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
273 * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
274 * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
275 * id-sha256(3) }
276 */
277static const u_char id_sha512[] = {
278 0x30, 0x51, /* type Sequence, length 0x51 (81) */
279 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
280 0x06, 0x09, /* type OID, length 0x09 */
281 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */
282 0x05, 0x00, /* NULL */
283 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */
284};
285
286static int
287rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp)
288{
289 switch (hash_alg) {
290 case SSH_DIGEST_SHA1:
291 *oidp = id_sha1;
292 *oidlenp = sizeof(id_sha1);
293 break;
294 case SSH_DIGEST_SHA256:
295 *oidp = id_sha256;
296 *oidlenp = sizeof(id_sha256);
297 break;
298 case SSH_DIGEST_SHA512:
299 *oidp = id_sha512;
300 *oidlenp = sizeof(id_sha512);
301 break;
302 default:
303 return SSH_ERR_INVALID_ARGUMENT;
304 }
305 return 0;
306}
307
212static int 308static int
213openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, 309openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
214 u_char *sigbuf, size_t siglen, RSA *rsa) 310 u_char *sigbuf, size_t siglen, RSA *rsa)
@@ -218,16 +314,10 @@ openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
218 const u_char *oid = NULL; 314 const u_char *oid = NULL;
219 u_char *decrypted = NULL; 315 u_char *decrypted = NULL;
220 316
317 if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0)
318 return ret;
221 ret = SSH_ERR_INTERNAL_ERROR; 319 ret = SSH_ERR_INTERNAL_ERROR;
222 switch (hash_alg) { 320 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) { 321 if (hashlen != hlen) {
232 ret = SSH_ERR_INVALID_ARGUMENT; 322 ret = SSH_ERR_INVALID_ARGUMENT;
233 goto done; 323 goto done;