1 /* $OpenBSD: ssh-rsa.c,v 1.78 2022/10/28 02:47:04 djm Exp $ */ 2 /* 3 * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include "includes.h" 19 20 #ifdef WITH_OPENSSL 21 22 #include <sys/types.h> 23 24 #include <openssl/evp.h> 25 #include <openssl/err.h> 26 27 #include <stdarg.h> 28 #include <string.h> 29 30 #include "sshbuf.h" 31 #include "compat.h" 32 #include "ssherr.h" 33 #define SSHKEY_INTERNAL 34 #include "sshkey.h" 35 #include "digest.h" 36 #include "log.h" 37 38 #include "openbsd-compat/openssl-compat.h" 39 40 static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); 41 42 static u_int 43 ssh_rsa_size(const struct sshkey *key) 44 { 45 const BIGNUM *rsa_n; 46 47 if (key->rsa == NULL) 48 return 0; 49 RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); 50 return BN_num_bits(rsa_n); 51 } 52 53 static int 54 ssh_rsa_alloc(struct sshkey *k) 55 { 56 if ((k->rsa = RSA_new()) == NULL) 57 return SSH_ERR_ALLOC_FAIL; 58 return 0; 59 } 60 61 static void 62 ssh_rsa_cleanup(struct sshkey *k) 63 { 64 RSA_free(k->rsa); 65 k->rsa = NULL; 66 } 67 68 static int 69 ssh_rsa_equal(const struct sshkey *a, const struct sshkey *b) 70 { 71 const BIGNUM *rsa_e_a, *rsa_n_a; 72 const BIGNUM *rsa_e_b, *rsa_n_b; 73 74 if (a->rsa == NULL || b->rsa == NULL) 75 return 0; 76 RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL); 77 RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL); 78 if (rsa_e_a == NULL || rsa_e_b == NULL) 79 return 0; 80 if (rsa_n_a == NULL || rsa_n_b == NULL) 81 return 0; 82 if (BN_cmp(rsa_e_a, rsa_e_b) != 0) 83 return 0; 84 if (BN_cmp(rsa_n_a, rsa_n_b) != 0) 85 return 0; 86 return 1; 87 } 88 89 static int 90 ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b, 91 enum sshkey_serialize_rep opts) 92 { 93 int r; 94 const BIGNUM *rsa_n, *rsa_e; 95 96 if (key->rsa == NULL) 97 return SSH_ERR_INVALID_ARGUMENT; 98 RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL); 99 if ((r = sshbuf_put_bignum2(b, rsa_e)) != 0 || 100 (r = sshbuf_put_bignum2(b, rsa_n)) != 0) 101 return r; 102 103 return 0; 104 } 105 106 static int 107 ssh_rsa_serialize_private(const struct sshkey *key, struct sshbuf *b, 108 enum sshkey_serialize_rep opts) 109 { 110 int r; 111 const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q; 112 113 RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d); 114 RSA_get0_factors(key->rsa, &rsa_p, &rsa_q); 115 RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp); 116 117 if (!sshkey_is_cert(key)) { 118 /* Note: can't reuse ssh_rsa_serialize_public: e, n vs. n, e */ 119 if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 || 120 (r = sshbuf_put_bignum2(b, rsa_e)) != 0) 121 return r; 122 } 123 if ((r = sshbuf_put_bignum2(b, rsa_d)) != 0 || 124 (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 || 125 (r = sshbuf_put_bignum2(b, rsa_p)) != 0 || 126 (r = sshbuf_put_bignum2(b, rsa_q)) != 0) 127 return r; 128 129 return 0; 130 } 131 132 static int 133 ssh_rsa_generate(struct sshkey *k, int bits) 134 { 135 RSA *private = NULL; 136 BIGNUM *f4 = NULL; 137 int ret = SSH_ERR_INTERNAL_ERROR; 138 139 if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE || 140 bits > SSHBUF_MAX_BIGNUM * 8) 141 return SSH_ERR_KEY_LENGTH; 142 if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) { 143 ret = SSH_ERR_ALLOC_FAIL; 144 goto out; 145 } 146 if (!BN_set_word(f4, RSA_F4) || 147 !RSA_generate_key_ex(private, bits, f4, NULL)) { 148 ret = SSH_ERR_LIBCRYPTO_ERROR; 149 goto out; 150 } 151 k->rsa = private; 152 private = NULL; 153 ret = 0; 154 out: 155 RSA_free(private); 156 BN_free(f4); 157 return ret; 158 } 159 160 static int 161 ssh_rsa_copy_public(const struct sshkey *from, struct sshkey *to) 162 { 163 const BIGNUM *rsa_n, *rsa_e; 164 BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL; 165 int r = SSH_ERR_INTERNAL_ERROR; 166 167 RSA_get0_key(from->rsa, &rsa_n, &rsa_e, NULL); 168 if ((rsa_n_dup = BN_dup(rsa_n)) == NULL || 169 (rsa_e_dup = BN_dup(rsa_e)) == NULL) { 170 r = SSH_ERR_ALLOC_FAIL; 171 goto out; 172 } 173 if (!RSA_set0_key(to->rsa, rsa_n_dup, rsa_e_dup, NULL)) { 174 r = SSH_ERR_LIBCRYPTO_ERROR; 175 goto out; 176 } 177 rsa_n_dup = rsa_e_dup = NULL; /* transferred */ 178 /* success */ 179 r = 0; 180 out: 181 BN_clear_free(rsa_n_dup); 182 BN_clear_free(rsa_e_dup); 183 return r; 184 } 185 186 static int 187 ssh_rsa_deserialize_public(const char *ktype, struct sshbuf *b, 188 struct sshkey *key) 189 { 190 int ret = SSH_ERR_INTERNAL_ERROR; 191 BIGNUM *rsa_n = NULL, *rsa_e = NULL; 192 193 if (sshbuf_get_bignum2(b, &rsa_e) != 0 || 194 sshbuf_get_bignum2(b, &rsa_n) != 0) { 195 ret = SSH_ERR_INVALID_FORMAT; 196 goto out; 197 } 198 if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) { 199 ret = SSH_ERR_LIBCRYPTO_ERROR; 200 goto out; 201 } 202 rsa_n = rsa_e = NULL; /* transferred */ 203 if ((ret = sshkey_check_rsa_length(key, 0)) != 0) 204 goto out; 205 #ifdef DEBUG_PK 206 RSA_print_fp(stderr, key->rsa, 8); 207 #endif 208 /* success */ 209 ret = 0; 210 out: 211 BN_clear_free(rsa_n); 212 BN_clear_free(rsa_e); 213 return ret; 214 } 215 216 static int 217 ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b, 218 struct sshkey *key) 219 { 220 int r; 221 BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; 222 BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL; 223 224 /* Note: can't reuse ssh_rsa_deserialize_public: e, n vs. n, e */ 225 if (!sshkey_is_cert(key)) { 226 if ((r = sshbuf_get_bignum2(b, &rsa_n)) != 0 || 227 (r = sshbuf_get_bignum2(b, &rsa_e)) != 0) 228 goto out; 229 if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) { 230 r = SSH_ERR_LIBCRYPTO_ERROR; 231 goto out; 232 } 233 rsa_n = rsa_e = NULL; /* transferred */ 234 } 235 if ((r = sshbuf_get_bignum2(b, &rsa_d)) != 0 || 236 (r = sshbuf_get_bignum2(b, &rsa_iqmp)) != 0 || 237 (r = sshbuf_get_bignum2(b, &rsa_p)) != 0 || 238 (r = sshbuf_get_bignum2(b, &rsa_q)) != 0) 239 goto out; 240 if (!RSA_set0_key(key->rsa, NULL, NULL, rsa_d)) { 241 r = SSH_ERR_LIBCRYPTO_ERROR; 242 goto out; 243 } 244 rsa_d = NULL; /* transferred */ 245 if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q)) { 246 r = SSH_ERR_LIBCRYPTO_ERROR; 247 goto out; 248 } 249 rsa_p = rsa_q = NULL; /* transferred */ 250 if ((r = sshkey_check_rsa_length(key, 0)) != 0) 251 goto out; 252 if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0) 253 goto out; 254 if (RSA_blinding_on(key->rsa, NULL) != 1) { 255 r = SSH_ERR_LIBCRYPTO_ERROR; 256 goto out; 257 } 258 /* success */ 259 r = 0; 260 out: 261 BN_clear_free(rsa_n); 262 BN_clear_free(rsa_e); 263 BN_clear_free(rsa_d); 264 BN_clear_free(rsa_p); 265 BN_clear_free(rsa_q); 266 BN_clear_free(rsa_iqmp); 267 return r; 268 } 269 270 static const char * 271 rsa_hash_alg_ident(int hash_alg) 272 { 273 switch (hash_alg) { 274 case SSH_DIGEST_SHA1: 275 return "ssh-rsa"; 276 case SSH_DIGEST_SHA256: 277 return "rsa-sha2-256"; 278 case SSH_DIGEST_SHA512: 279 return "rsa-sha2-512"; 280 } 281 return NULL; 282 } 283 284 /* 285 * Returns the hash algorithm ID for a given algorithm identifier as used 286 * inside the signature blob, 287 */ 288 static int 289 rsa_hash_id_from_ident(const char *ident) 290 { 291 if (strcmp(ident, "ssh-rsa") == 0) 292 return SSH_DIGEST_SHA1; 293 if (strcmp(ident, "rsa-sha2-256") == 0) 294 return SSH_DIGEST_SHA256; 295 if (strcmp(ident, "rsa-sha2-512") == 0) 296 return SSH_DIGEST_SHA512; 297 return -1; 298 } 299 300 /* 301 * Return the hash algorithm ID for the specified key name. This includes 302 * all the cases of rsa_hash_id_from_ident() but also the certificate key 303 * types. 304 */ 305 static int 306 rsa_hash_id_from_keyname(const char *alg) 307 { 308 int r; 309 310 if ((r = rsa_hash_id_from_ident(alg)) != -1) 311 return r; 312 if (strcmp(alg, "ssh-rsa-cert-v01@openssh.com") == 0) 313 return SSH_DIGEST_SHA1; 314 if (strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0) 315 return SSH_DIGEST_SHA256; 316 if (strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0) 317 return SSH_DIGEST_SHA512; 318 return -1; 319 } 320 321 static int 322 rsa_hash_alg_nid(int type) 323 { 324 switch (type) { 325 case SSH_DIGEST_SHA1: 326 return NID_sha1; 327 case SSH_DIGEST_SHA256: 328 return NID_sha256; 329 case SSH_DIGEST_SHA512: 330 return NID_sha512; 331 default: 332 return -1; 333 } 334 } 335 336 int 337 ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp) 338 { 339 const BIGNUM *rsa_p, *rsa_q, *rsa_d; 340 BIGNUM *aux = NULL, *d_consttime = NULL; 341 BIGNUM *rsa_dmq1 = NULL, *rsa_dmp1 = NULL, *rsa_iqmp = NULL; 342 BN_CTX *ctx = NULL; 343 int r; 344 345 if (key == NULL || key->rsa == NULL || 346 sshkey_type_plain(key->type) != KEY_RSA) 347 return SSH_ERR_INVALID_ARGUMENT; 348 349 RSA_get0_key(key->rsa, NULL, NULL, &rsa_d); 350 RSA_get0_factors(key->rsa, &rsa_p, &rsa_q); 351 352 if ((ctx = BN_CTX_new()) == NULL) 353 return SSH_ERR_ALLOC_FAIL; 354 if ((aux = BN_new()) == NULL || 355 (rsa_dmq1 = BN_new()) == NULL || 356 (rsa_dmp1 = BN_new()) == NULL) 357 return SSH_ERR_ALLOC_FAIL; 358 if ((d_consttime = BN_dup(rsa_d)) == NULL || 359 (rsa_iqmp = BN_dup(iqmp)) == NULL) { 360 r = SSH_ERR_ALLOC_FAIL; 361 goto out; 362 } 363 BN_set_flags(aux, BN_FLG_CONSTTIME); 364 BN_set_flags(d_consttime, BN_FLG_CONSTTIME); 365 366 if ((BN_sub(aux, rsa_q, BN_value_one()) == 0) || 367 (BN_mod(rsa_dmq1, d_consttime, aux, ctx) == 0) || 368 (BN_sub(aux, rsa_p, BN_value_one()) == 0) || 369 (BN_mod(rsa_dmp1, d_consttime, aux, ctx) == 0)) { 370 r = SSH_ERR_LIBCRYPTO_ERROR; 371 goto out; 372 } 373 if (!RSA_set0_crt_params(key->rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp)) { 374 r = SSH_ERR_LIBCRYPTO_ERROR; 375 goto out; 376 } 377 rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL; /* transferred */ 378 /* success */ 379 r = 0; 380 out: 381 BN_clear_free(aux); 382 BN_clear_free(d_consttime); 383 BN_clear_free(rsa_dmp1); 384 BN_clear_free(rsa_dmq1); 385 BN_clear_free(rsa_iqmp); 386 BN_CTX_free(ctx); 387 return r; 388 } 389 390 /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ 391 static int 392 ssh_rsa_sign(struct sshkey *key, 393 u_char **sigp, size_t *lenp, 394 const u_char *data, size_t datalen, 395 const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) 396 { 397 const BIGNUM *rsa_n; 398 u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; 399 size_t slen = 0; 400 u_int hlen, len; 401 int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR; 402 struct sshbuf *b = NULL; 403 404 if (lenp != NULL) 405 *lenp = 0; 406 if (sigp != NULL) 407 *sigp = NULL; 408 409 if (alg == NULL || strlen(alg) == 0) 410 hash_alg = SSH_DIGEST_SHA1; 411 else 412 hash_alg = rsa_hash_id_from_keyname(alg); 413 if (key == NULL || key->rsa == NULL || hash_alg == -1 || 414 sshkey_type_plain(key->type) != KEY_RSA) 415 return SSH_ERR_INVALID_ARGUMENT; 416 RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); 417 if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) 418 return SSH_ERR_KEY_LENGTH; 419 slen = RSA_size(key->rsa); 420 if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) 421 return SSH_ERR_INVALID_ARGUMENT; 422 423 /* hash the data */ 424 nid = rsa_hash_alg_nid(hash_alg); 425 if ((hlen = ssh_digest_bytes(hash_alg)) == 0) 426 return SSH_ERR_INTERNAL_ERROR; 427 if ((ret = ssh_digest_memory(hash_alg, data, datalen, 428 digest, sizeof(digest))) != 0) 429 goto out; 430 431 if ((sig = malloc(slen)) == NULL) { 432 ret = SSH_ERR_ALLOC_FAIL; 433 goto out; 434 } 435 436 if (RSA_sign(nid, digest, hlen, sig, &len, key->rsa) != 1) { 437 ret = SSH_ERR_LIBCRYPTO_ERROR; 438 goto out; 439 } 440 if (len < slen) { 441 size_t diff = slen - len; 442 memmove(sig + diff, sig, len); 443 explicit_bzero(sig, diff); 444 } else if (len > slen) { 445 ret = SSH_ERR_INTERNAL_ERROR; 446 goto out; 447 } 448 /* encode signature */ 449 if ((b = sshbuf_new()) == NULL) { 450 ret = SSH_ERR_ALLOC_FAIL; 451 goto out; 452 } 453 if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 || 454 (ret = sshbuf_put_string(b, sig, slen)) != 0) 455 goto out; 456 len = sshbuf_len(b); 457 if (sigp != NULL) { 458 if ((*sigp = malloc(len)) == NULL) { 459 ret = SSH_ERR_ALLOC_FAIL; 460 goto out; 461 } 462 memcpy(*sigp, sshbuf_ptr(b), len); 463 } 464 if (lenp != NULL) 465 *lenp = len; 466 ret = 0; 467 out: 468 explicit_bzero(digest, sizeof(digest)); 469 freezero(sig, slen); 470 sshbuf_free(b); 471 return ret; 472 } 473 474 static int 475 ssh_rsa_verify(const struct sshkey *key, 476 const u_char *sig, size_t siglen, 477 const u_char *data, size_t dlen, const char *alg, u_int compat, 478 struct sshkey_sig_details **detailsp) 479 { 480 const BIGNUM *rsa_n; 481 char *sigtype = NULL; 482 int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR; 483 size_t len = 0, diff, modlen, hlen; 484 struct sshbuf *b = NULL; 485 u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; 486 487 if (key == NULL || key->rsa == NULL || 488 sshkey_type_plain(key->type) != KEY_RSA || 489 sig == NULL || siglen == 0) 490 return SSH_ERR_INVALID_ARGUMENT; 491 RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); 492 if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) 493 return SSH_ERR_KEY_LENGTH; 494 495 if ((b = sshbuf_from(sig, siglen)) == NULL) 496 return SSH_ERR_ALLOC_FAIL; 497 if (sshbuf_get_cstring(b, &sigtype, NULL) != 0) { 498 ret = SSH_ERR_INVALID_FORMAT; 499 goto out; 500 } 501 if ((hash_alg = rsa_hash_id_from_ident(sigtype)) == -1) { 502 ret = SSH_ERR_KEY_TYPE_MISMATCH; 503 goto out; 504 } 505 /* 506 * Allow ssh-rsa-cert-v01 certs to generate SHA2 signatures for 507 * legacy reasons, but otherwise the signature type should match. 508 */ 509 if (alg != NULL && strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) { 510 if ((want_alg = rsa_hash_id_from_keyname(alg)) == -1) { 511 ret = SSH_ERR_INVALID_ARGUMENT; 512 goto out; 513 } 514 if (hash_alg != want_alg) { 515 ret = SSH_ERR_SIGNATURE_INVALID; 516 goto out; 517 } 518 } 519 if (sshbuf_get_string(b, &sigblob, &len) != 0) { 520 ret = SSH_ERR_INVALID_FORMAT; 521 goto out; 522 } 523 if (sshbuf_len(b) != 0) { 524 ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; 525 goto out; 526 } 527 /* RSA_verify expects a signature of RSA_size */ 528 modlen = RSA_size(key->rsa); 529 if (len > modlen) { 530 ret = SSH_ERR_KEY_BITS_MISMATCH; 531 goto out; 532 } else if (len < modlen) { 533 diff = modlen - len; 534 osigblob = sigblob; 535 if ((sigblob = realloc(sigblob, modlen)) == NULL) { 536 sigblob = osigblob; /* put it back for clear/free */ 537 ret = SSH_ERR_ALLOC_FAIL; 538 goto out; 539 } 540 memmove(sigblob + diff, sigblob, len); 541 explicit_bzero(sigblob, diff); 542 len = modlen; 543 } 544 if ((hlen = ssh_digest_bytes(hash_alg)) == 0) { 545 ret = SSH_ERR_INTERNAL_ERROR; 546 goto out; 547 } 548 if ((ret = ssh_digest_memory(hash_alg, data, dlen, 549 digest, sizeof(digest))) != 0) 550 goto out; 551 552 ret = openssh_RSA_verify(hash_alg, digest, hlen, sigblob, len, 553 key->rsa); 554 out: 555 freezero(sigblob, len); 556 free(sigtype); 557 sshbuf_free(b); 558 explicit_bzero(digest, sizeof(digest)); 559 return ret; 560 } 561 562 /* 563 * See: 564 * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ 565 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn 566 */ 567 568 /* 569 * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) 570 * oiw(14) secsig(3) algorithms(2) 26 } 571 */ 572 static const u_char id_sha1[] = { 573 0x30, 0x21, /* type Sequence, length 0x21 (33) */ 574 0x30, 0x09, /* type Sequence, length 0x09 */ 575 0x06, 0x05, /* type OID, length 0x05 */ 576 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ 577 0x05, 0x00, /* NULL */ 578 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ 579 }; 580 581 /* 582 * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html 583 * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) 584 * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 585 * id-sha256(1) } 586 */ 587 static const u_char id_sha256[] = { 588 0x30, 0x31, /* type Sequence, length 0x31 (49) */ 589 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ 590 0x06, 0x09, /* type OID, length 0x09 */ 591 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */ 592 0x05, 0x00, /* NULL */ 593 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */ 594 }; 595 596 /* 597 * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html 598 * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) 599 * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 600 * id-sha256(3) } 601 */ 602 static const u_char id_sha512[] = { 603 0x30, 0x51, /* type Sequence, length 0x51 (81) */ 604 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ 605 0x06, 0x09, /* type OID, length 0x09 */ 606 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */ 607 0x05, 0x00, /* NULL */ 608 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */ 609 }; 610 611 static int 612 rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp) 613 { 614 switch (hash_alg) { 615 case SSH_DIGEST_SHA1: 616 *oidp = id_sha1; 617 *oidlenp = sizeof(id_sha1); 618 break; 619 case SSH_DIGEST_SHA256: 620 *oidp = id_sha256; 621 *oidlenp = sizeof(id_sha256); 622 break; 623 case SSH_DIGEST_SHA512: 624 *oidp = id_sha512; 625 *oidlenp = sizeof(id_sha512); 626 break; 627 default: 628 return SSH_ERR_INVALID_ARGUMENT; 629 } 630 return 0; 631 } 632 633 static int 634 openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, 635 u_char *sigbuf, size_t siglen, RSA *rsa) 636 { 637 size_t rsasize = 0, oidlen = 0, hlen = 0; 638 int ret, len, oidmatch, hashmatch; 639 const u_char *oid = NULL; 640 u_char *decrypted = NULL; 641 642 if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0) 643 return ret; 644 ret = SSH_ERR_INTERNAL_ERROR; 645 hlen = ssh_digest_bytes(hash_alg); 646 if (hashlen != hlen) { 647 ret = SSH_ERR_INVALID_ARGUMENT; 648 goto done; 649 } 650 rsasize = RSA_size(rsa); 651 if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM || 652 siglen == 0 || siglen > rsasize) { 653 ret = SSH_ERR_INVALID_ARGUMENT; 654 goto done; 655 } 656 if ((decrypted = malloc(rsasize)) == NULL) { 657 ret = SSH_ERR_ALLOC_FAIL; 658 goto done; 659 } 660 if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, 661 RSA_PKCS1_PADDING)) < 0) { 662 ret = SSH_ERR_LIBCRYPTO_ERROR; 663 goto done; 664 } 665 if (len < 0 || (size_t)len != hlen + oidlen) { 666 ret = SSH_ERR_INVALID_FORMAT; 667 goto done; 668 } 669 oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0; 670 hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0; 671 if (!oidmatch || !hashmatch) { 672 ret = SSH_ERR_SIGNATURE_INVALID; 673 goto done; 674 } 675 ret = 0; 676 done: 677 freezero(decrypted, rsasize); 678 return ret; 679 } 680 681 static const struct sshkey_impl_funcs sshkey_rsa_funcs = { 682 /* .size = */ ssh_rsa_size, 683 /* .alloc = */ ssh_rsa_alloc, 684 /* .cleanup = */ ssh_rsa_cleanup, 685 /* .equal = */ ssh_rsa_equal, 686 /* .ssh_serialize_public = */ ssh_rsa_serialize_public, 687 /* .ssh_deserialize_public = */ ssh_rsa_deserialize_public, 688 /* .ssh_serialize_private = */ ssh_rsa_serialize_private, 689 /* .ssh_deserialize_private = */ ssh_rsa_deserialize_private, 690 /* .generate = */ ssh_rsa_generate, 691 /* .copy_public = */ ssh_rsa_copy_public, 692 /* .sign = */ ssh_rsa_sign, 693 /* .verify = */ ssh_rsa_verify, 694 }; 695 696 const struct sshkey_impl sshkey_rsa_impl = { 697 /* .name = */ "ssh-rsa", 698 /* .shortname = */ "RSA", 699 /* .sigalg = */ NULL, 700 /* .type = */ KEY_RSA, 701 /* .nid = */ 0, 702 /* .cert = */ 0, 703 /* .sigonly = */ 0, 704 /* .keybits = */ 0, 705 /* .funcs = */ &sshkey_rsa_funcs, 706 }; 707 708 const struct sshkey_impl sshkey_rsa_cert_impl = { 709 /* .name = */ "ssh-rsa-cert-v01@openssh.com", 710 /* .shortname = */ "RSA-CERT", 711 /* .sigalg = */ NULL, 712 /* .type = */ KEY_RSA_CERT, 713 /* .nid = */ 0, 714 /* .cert = */ 1, 715 /* .sigonly = */ 0, 716 /* .keybits = */ 0, 717 /* .funcs = */ &sshkey_rsa_funcs, 718 }; 719 720 /* SHA2 signature algorithms */ 721 722 const struct sshkey_impl sshkey_rsa_sha256_impl = { 723 /* .name = */ "rsa-sha2-256", 724 /* .shortname = */ "RSA", 725 /* .sigalg = */ NULL, 726 /* .type = */ KEY_RSA, 727 /* .nid = */ 0, 728 /* .cert = */ 0, 729 /* .sigonly = */ 1, 730 /* .keybits = */ 0, 731 /* .funcs = */ &sshkey_rsa_funcs, 732 }; 733 734 const struct sshkey_impl sshkey_rsa_sha512_impl = { 735 /* .name = */ "rsa-sha2-512", 736 /* .shortname = */ "RSA", 737 /* .sigalg = */ NULL, 738 /* .type = */ KEY_RSA, 739 /* .nid = */ 0, 740 /* .cert = */ 0, 741 /* .sigonly = */ 1, 742 /* .keybits = */ 0, 743 /* .funcs = */ &sshkey_rsa_funcs, 744 }; 745 746 const struct sshkey_impl sshkey_rsa_sha256_cert_impl = { 747 /* .name = */ "rsa-sha2-256-cert-v01@openssh.com", 748 /* .shortname = */ "RSA-CERT", 749 /* .sigalg = */ "rsa-sha2-256", 750 /* .type = */ KEY_RSA_CERT, 751 /* .nid = */ 0, 752 /* .cert = */ 1, 753 /* .sigonly = */ 1, 754 /* .keybits = */ 0, 755 /* .funcs = */ &sshkey_rsa_funcs, 756 }; 757 758 const struct sshkey_impl sshkey_rsa_sha512_cert_impl = { 759 /* .name = */ "rsa-sha2-512-cert-v01@openssh.com", 760 /* .shortname = */ "RSA-CERT", 761 /* .sigalg = */ "rsa-sha2-512", 762 /* .type = */ KEY_RSA_CERT, 763 /* .nid = */ 0, 764 /* .cert = */ 1, 765 /* .sigonly = */ 1, 766 /* .keybits = */ 0, 767 /* .funcs = */ &sshkey_rsa_funcs, 768 }; 769 #endif /* WITH_OPENSSL */ 770