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