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