summaryrefslogtreecommitdiff
path: root/ssh-rsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-rsa.c')
-rw-r--r--ssh-rsa.c149
1 files changed, 118 insertions, 31 deletions
diff --git a/ssh-rsa.c b/ssh-rsa.c
index cdc18a416..53d44d1f3 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -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
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 (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
65static int
66rsa_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 */
40int 81int
41ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, 82ssh_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
119int 163int
120ssh_rsa_verify(const struct sshkey *key, 164ssh_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 */
259static 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 */
274static 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
283static int
284rsa_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
212static int 305static int
213openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, 306openssh_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;