=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/ssh-rsa.c,v retrieving revision 1.73 retrieving revision 1.74 diff -u -r1.73 -r1.74 --- src/usr.bin/ssh/ssh-rsa.c 2022/10/28 00:41:17 1.73 +++ src/usr.bin/ssh/ssh-rsa.c 2022/10/28 00:41:52 1.74 @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-rsa.c,v 1.73 2022/10/28 00:41:17 djm Exp $ */ +/* $OpenBSD: ssh-rsa.c,v 1.74 2022/10/28 00:41:52 djm Exp $ */ /* * Copyright (c) 2000, 2003 Markus Friedl * @@ -32,6 +32,26 @@ static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); +int +sshkey_check_rsa_length(const struct sshkey *k, int min_size) +{ +#ifdef WITH_OPENSSL + const BIGNUM *rsa_n; + int nbits; + + if (k == NULL || k->rsa == NULL || + (k->type != KEY_RSA && k->type != KEY_RSA_CERT)) + return 0; + RSA_get0_key(k->rsa, &rsa_n, NULL, NULL); + nbits = BN_num_bits(rsa_n); + if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE || + (min_size > 0 && nbits < min_size)) + return SSH_ERR_KEY_LENGTH; +#endif /* WITH_OPENSSL */ + return 0; +} + + static u_int ssh_rsa_size(const struct sshkey *key) { @@ -81,7 +101,7 @@ static int ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b, - const char *typename, enum sshkey_serialize_rep opts) + enum sshkey_serialize_rep opts) { int r; const BIGNUM *rsa_n, *rsa_e; @@ -89,8 +109,7 @@ if (key->rsa == NULL) return SSH_ERR_INVALID_ARGUMENT; RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL); - if ((r = sshbuf_put_cstring(b, typename)) != 0 || - (r = sshbuf_put_bignum2(b, rsa_e)) != 0 || + if ((r = sshbuf_put_bignum2(b, rsa_e)) != 0 || (r = sshbuf_put_bignum2(b, rsa_n)) != 0) return r; @@ -151,6 +170,36 @@ return r; } +static int +ssh_rsa_deserialize_public(const char *ktype, struct sshbuf *b, + struct sshkey *key) +{ + int ret = SSH_ERR_INTERNAL_ERROR; + BIGNUM *rsa_n = NULL, *rsa_e = NULL; + + if (sshbuf_get_bignum2(b, &rsa_e) != 0 || + sshbuf_get_bignum2(b, &rsa_n) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + rsa_n = rsa_e = NULL; /* transferred */ + if ((ret = sshkey_check_rsa_length(key, 0)) != 0) + goto out; +#ifdef DEBUG_PK + RSA_print_fp(stderr, key->rsa, 8); +#endif + /* success */ + ret = 0; + out: + BN_clear_free(rsa_n); + BN_clear_free(rsa_e); + return ret; +} + static const char * rsa_hash_alg_ident(int hash_alg) { @@ -565,6 +614,7 @@ /* .cleanup = */ ssh_rsa_cleanup, /* .equal = */ ssh_rsa_equal, /* .ssh_serialize_public = */ ssh_rsa_serialize_public, + /* .ssh_deserialize_public = */ ssh_rsa_deserialize_public, /* .generate = */ ssh_rsa_generate, /* .copy_public = */ ssh_rsa_copy_public, };