From: Arkadiusz Miśkiewicz Date: Fri, 14 Sep 2018 10:08:08 +0000 (+0200) Subject: - rel 4; build with openssl 1.1.1 X-Git-Tag: auto/th/openssh-7.8p1-4 X-Git-Url: http://git.pld-linux.org/?p=packages%2Fopenssh.git;a=commitdiff_plain;h=d2583ea730d6bd3aa5a80149aeb246b81662e294 - rel 4; build with openssl 1.1.1 --- diff --git a/openssh-bug-2905.patch b/openssh-bug-2905.patch new file mode 100644 index 0000000..94f34df --- /dev/null +++ b/openssh-bug-2905.patch @@ -0,0 +1,12 @@ +--- openssh-portable/sandbox-seccomp-filter.c.org 2018-09-14 10:56:00.557388954 +0200 ++++ openssh-portable/sandbox-seccomp-filter.c 2018-09-14 11:13:00.051826982 +0200 +@@ -166,6 +166,9 @@ static const struct sock_filter preauth_ + #ifdef __NR_exit_group + SC_ALLOW(__NR_exit_group), + #endif ++#ifdef __NR_futex ++ SC_ALLOW(__NR_futex), ++#endif + #ifdef __NR_geteuid + SC_ALLOW(__NR_geteuid), + #endif diff --git a/openssh.spec b/openssh.spec index a0799c0..adb4ee8 100644 --- a/openssh.spec +++ b/openssh.spec @@ -36,7 +36,7 @@ Summary(ru.UTF-8): OpenSSH - свободная реализация прото Summary(uk.UTF-8): OpenSSH - вільна реалізація протоколу Secure Shell (SSH) Name: openssh Version: 7.8p1 -Release: 3 +Release: 4 Epoch: 2 License: BSD Group: Applications/Networking @@ -54,7 +54,7 @@ Source9: sshd.service Source10: sshd-keygen Source11: sshd.socket Source12: sshd@.service - +Patch0: openssl.patch Patch1: %{name}-tests-reuseport.patch Patch2: %{name}-pam_misc.patch Patch3: %{name}-sigpipe.patch @@ -69,6 +69,8 @@ Patch8: ldap-helper-sigpipe.patch Patch9: %{name}-5.2p1-hpn13v6.diff Patch10: %{name}-include.patch Patch11: %{name}-chroot.patch +Patch12: openssh-bug-2905.patch + Patch14: %{name}-bind.patch Patch15: %{name}-disable_ldap.patch URL: http://www.openssh.com/portable.html @@ -520,7 +522,7 @@ openldap-a. %prep %setup -q - +%patch0 -p1 %patch1 -p1 %patch2 -p1 %patch3 -p1 @@ -533,6 +535,7 @@ openldap-a. %{?with_hpn:%patch9 -p1} %patch10 -p1 %patch11 -p1 +%patch12 -p1 %patch14 -p1 %{!?with_ldap:%patch15 -p1} diff --git a/openssl.patch b/openssl.patch new file mode 100644 index 0000000..9c32ab8 --- /dev/null +++ b/openssl.patch @@ -0,0 +1,4262 @@ +commit a70fd4ad7bd9f2ed223ff635a3d41e483057f23b +Author: djm@openbsd.org +Date: Wed Sep 12 01:31:30 2018 +0000 + + upstream: add cert->signature_type field and keep it in sync with + + certificate signature wrt loading and certification operations; ok markus@ + + OpenBSD-Commit-ID: e8b8b9f76b66707a0cd926109c4383db8f664df3 + +diff --git a/sshkey.c b/sshkey.c +index 72c08c7e..b467571f 100644 +--- a/sshkey.c ++++ b/sshkey.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: sshkey.c,v 1.66 2018/07/03 13:20:25 djm Exp $ */ ++/* $OpenBSD: sshkey.c,v 1.67 2018/09/12 01:31:30 djm Exp $ */ + /* + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2008 Alexander von Gernler. All rights reserved. +@@ -78,6 +78,7 @@ int sshkey_private_serialize_opt(const struct sshkey *key, + struct sshbuf *buf, enum sshkey_serialize_rep); + static int sshkey_from_blob_internal(struct sshbuf *buf, + struct sshkey **keyp, int allow_cert); ++static int get_sigtype(const u_char *sig, size_t siglen, char **sigtypep); + + /* Supported key types */ + struct keytype { +@@ -453,6 +454,7 @@ cert_free(struct sshkey_cert *cert) + free(cert->principals[i]); + free(cert->principals); + sshkey_free(cert->signature_key); ++ free(cert->signature_type); + freezero(cert, sizeof(*cert)); + } + +@@ -472,6 +474,7 @@ cert_new(void) + cert->key_id = NULL; + cert->principals = NULL; + cert->signature_key = NULL; ++ cert->signature_type = NULL; + return cert; + } + +@@ -1695,54 +1698,68 @@ sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key) + u_int i; + const struct sshkey_cert *from; + struct sshkey_cert *to; +- int ret = SSH_ERR_INTERNAL_ERROR; +- +- if (to_key->cert != NULL) { +- cert_free(to_key->cert); +- to_key->cert = NULL; +- } ++ int r = SSH_ERR_INTERNAL_ERROR; + +- if ((from = from_key->cert) == NULL) ++ if (to_key == NULL || (from = from_key->cert) == NULL) + return SSH_ERR_INVALID_ARGUMENT; + +- if ((to = to_key->cert = cert_new()) == NULL) ++ if ((to = cert_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + +- if ((ret = sshbuf_putb(to->certblob, from->certblob)) != 0 || +- (ret = sshbuf_putb(to->critical, from->critical)) != 0 || +- (ret = sshbuf_putb(to->extensions, from->extensions)) != 0) +- return ret; ++ if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 || ++ (r = sshbuf_putb(to->critical, from->critical)) != 0 || ++ (r = sshbuf_putb(to->extensions, from->extensions)) != 0) ++ goto out; + + to->serial = from->serial; + to->type = from->type; + if (from->key_id == NULL) + to->key_id = NULL; +- else if ((to->key_id = strdup(from->key_id)) == NULL) +- return SSH_ERR_ALLOC_FAIL; ++ else if ((to->key_id = strdup(from->key_id)) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + to->valid_after = from->valid_after; + to->valid_before = from->valid_before; + if (from->signature_key == NULL) + to->signature_key = NULL; +- else if ((ret = sshkey_from_private(from->signature_key, ++ else if ((r = sshkey_from_private(from->signature_key, + &to->signature_key)) != 0) +- return ret; +- +- if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) +- return SSH_ERR_INVALID_ARGUMENT; ++ goto out; ++ if (from->signature_type != NULL && ++ (to->signature_type = strdup(from->signature_type)) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) { ++ r = SSH_ERR_INVALID_ARGUMENT; ++ goto out; ++ } + if (from->nprincipals > 0) { + if ((to->principals = calloc(from->nprincipals, +- sizeof(*to->principals))) == NULL) +- return SSH_ERR_ALLOC_FAIL; ++ sizeof(*to->principals))) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + for (i = 0; i < from->nprincipals; i++) { + to->principals[i] = strdup(from->principals[i]); + if (to->principals[i] == NULL) { + to->nprincipals = i; +- return SSH_ERR_ALLOC_FAIL; ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; + } + } + } + to->nprincipals = from->nprincipals; +- return 0; ++ ++ /* success */ ++ cert_free(to_key->cert); ++ to_key->cert = to; ++ to = NULL; ++ r = 0; ++ out: ++ cert_free(to); ++ return r; + } + + int +@@ -1954,6 +1971,8 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) + if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, + sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0) + goto out; ++ if ((ret = get_sigtype(sig, slen, &key->cert->signature_type)) != 0) ++ goto out; + + /* Success */ + ret = 0; +@@ -2531,7 +2550,8 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, + u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; + size_t i, ca_len, sig_len; + int ret = SSH_ERR_INTERNAL_ERROR; +- struct sshbuf *cert; ++ struct sshbuf *cert = NULL; ++ char *sigtype = NULL; + + if (k == NULL || k->cert == NULL || + k->cert->certblob == NULL || ca == NULL) +@@ -2541,6 +2561,16 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, + if (!sshkey_type_is_valid_ca(ca->type)) + return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; + ++ /* ++ * If no alg specified as argument but a signature_type was set, ++ * then prefer that. If both were specified, then they must match. ++ */ ++ if (alg == NULL) ++ alg = k->cert->signature_type; ++ else if (k->cert->signature_type != NULL && ++ strcmp(alg, k->cert->signature_type) != 0) ++ return SSH_ERR_INVALID_ARGUMENT; ++ + if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0) + return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; + +@@ -2629,7 +2659,17 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, + if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), + sshbuf_len(cert), alg, 0, signer_ctx)) != 0) + goto out; +- ++ /* Check and update signature_type against what was actually used */ ++ if ((ret = get_sigtype(sig_blob, sig_len, &sigtype)) != 0) ++ goto out; ++ if (alg != NULL && strcmp(alg, sigtype) != 0) { ++ ret = SSH_ERR_SIGN_ALG_UNSUPPORTED; ++ goto out; ++ } ++ if (k->cert->signature_type == NULL) { ++ k->cert->signature_type = sigtype; ++ sigtype = NULL; ++ } + /* Append signature and we are done */ + if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0) + goto out; +@@ -2639,6 +2679,7 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, + sshbuf_reset(cert); + free(sig_blob); + free(ca_blob); ++ free(sigtype); + sshbuf_free(principals); + return ret; + } +diff --git a/sshkey.h b/sshkey.h +index 9060b2ec..b8f279a6 100644 +--- a/sshkey.h ++++ b/sshkey.h +@@ -1,4 +1,4 @@ +-/* $OpenBSD: sshkey.h,v 1.26 2018/07/03 13:20:25 djm Exp $ */ ++/* $OpenBSD: sshkey.h,v 1.27 2018/09/12 01:31:30 djm Exp $ */ + + /* + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. +@@ -102,6 +102,7 @@ struct sshkey_cert { + struct sshbuf *critical; + struct sshbuf *extensions; + struct sshkey *signature_key; ++ char *signature_type; + }; + + /* XXX opaquify? */ +commit ba9e788315b1f6a350f910cb2a9e95b2ce584e89 +Author: djm@openbsd.org +Date: Wed Sep 12 01:32:54 2018 +0000 + + upstream: add sshkey_check_cert_sigtype() that checks a + + cert->signature_type against a supplied whitelist; ok markus + + OpenBSD-Commit-ID: caadb8073292ed7a9535e5adc067d11d356d9302 + +diff --git a/sshkey.c b/sshkey.c +index b467571f..50ebdc25 100644 +--- a/sshkey.c ++++ b/sshkey.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: sshkey.c,v 1.67 2018/09/12 01:31:30 djm Exp $ */ ++/* $OpenBSD: sshkey.c,v 1.68 2018/09/12 01:32:54 djm Exp $ */ + /* + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2008 Alexander von Gernler. All rights reserved. +@@ -2260,6 +2260,27 @@ get_sigtype(const u_char *sig, size_t siglen, char **sigtypep) + return r; + } + ++/* ++ * ++ * Checks whether a certificate's signature type is allowed. ++ * Returns 0 (success) if the certificate signature type appears in the ++ * "allowed" pattern-list, or the key is not a certificate to begin with. ++ * Otherwise returns a ssherr.h code. ++ */ ++int ++sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed) ++{ ++ if (key == NULL || allowed == NULL) ++ return SSH_ERR_INVALID_ARGUMENT; ++ if (!sshkey_type_is_cert(key->type)) ++ return 0; ++ if (key->cert == NULL || key->cert->signature_type == NULL) ++ return SSH_ERR_INVALID_ARGUMENT; ++ if (match_pattern_list(key->cert->signature_type, allowed, 0) != 1) ++ return SSH_ERR_SIGN_ALG_UNSUPPORTED; ++ return 0; ++} ++ + /* + * Returns the expected signature algorithm for a given public key algorithm. + */ +diff --git a/sshkey.h b/sshkey.h +index b8f279a6..5a22a66f 100644 +--- a/sshkey.h ++++ b/sshkey.h +@@ -1,4 +1,4 @@ +-/* $OpenBSD: sshkey.h,v 1.27 2018/09/12 01:31:30 djm Exp $ */ ++/* $OpenBSD: sshkey.h,v 1.28 2018/09/12 01:32:54 djm Exp $ */ + + /* + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. +@@ -158,6 +158,7 @@ int sshkey_cert_check_authority(const struct sshkey *, int, int, + const char *, const char **); + size_t sshkey_format_cert_validity(const struct sshkey_cert *, + char *, size_t) __attribute__((__bounded__(__string__, 2, 3))); ++int sshkey_check_cert_sigtype(const struct sshkey *, const char *); + + int sshkey_certify(struct sshkey *, struct sshkey *, const char *); + /* Variant allowing use of a custom signature function (e.g. for ssh-agent) */ +commit 2de78bc7da70e1338b32feeefcc6045cf49efcd4 +Author: djm@openbsd.org +Date: Wed Sep 12 01:22:43 2018 +0000 + + upstream: s/sshkey_demote/sshkey_from_private/g + + OpenBSD-Regress-ID: 782bde7407d94a87aa8d1db7c23750e09d4443c4 + +diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c +index 72367bde..7e03b7e5 100644 +--- a/regress/unittests/sshkey/test_sshkey.c ++++ b/regress/unittests/sshkey/test_sshkey.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: test_sshkey.c,v 1.14 2018/07/13 02:13:19 djm Exp $ */ ++/* $OpenBSD: test_sshkey.c,v 1.15 2018/09/12 01:22:43 djm Exp $ */ + /* + * Regress test for sshkey.h key management API + * +@@ -318,7 +318,7 @@ sshkey_tests(void) + TEST_DONE(); + + TEST_START("demote KEY_RSA"); +- ASSERT_INT_EQ(sshkey_demote(kr, &k1), 0); ++ ASSERT_INT_EQ(sshkey_from_private(kr, &k1), 0); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(kr, k1); + ASSERT_INT_EQ(k1->type, KEY_RSA); +@@ -334,7 +334,7 @@ sshkey_tests(void) + TEST_DONE(); + + TEST_START("demote KEY_DSA"); +- ASSERT_INT_EQ(sshkey_demote(kd, &k1), 0); ++ ASSERT_INT_EQ(sshkey_from_private(kd, &k1), 0); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(kd, k1); + ASSERT_INT_EQ(k1->type, KEY_DSA); +@@ -350,7 +350,7 @@ sshkey_tests(void) + + #ifdef OPENSSL_HAS_ECC + TEST_START("demote KEY_ECDSA"); +- ASSERT_INT_EQ(sshkey_demote(ke, &k1), 0); ++ ASSERT_INT_EQ(sshkey_from_private(ke, &k1), 0); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(ke, k1); + ASSERT_INT_EQ(k1->type, KEY_ECDSA); +@@ -367,7 +367,7 @@ sshkey_tests(void) + #endif + + TEST_START("demote KEY_ED25519"); +- ASSERT_INT_EQ(sshkey_demote(kf, &k1), 0); ++ ASSERT_INT_EQ(sshkey_from_private(kf, &k1), 0); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(kf, k1); + ASSERT_INT_EQ(k1->type, KEY_ED25519); + +commit d70d061828730a56636ab6f1f24fe4a8ccefcfc1 +Author: djm@openbsd.org +Date: Wed Sep 12 01:36:45 2018 +0000 + + upstream: Include certs with multiple RSA signature variants in + + test data Ensure that cert->signature_key is populated correctly + + OpenBSD-Regress-ID: 56e68f70fe46cb3a193ca207385bdb301fd6603a + +diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha1 b/regress/unittests/sshkey/testdata/rsa_1_sha1 +new file mode 100644 +index 00000000..5de3f842 +--- /dev/null ++++ b/regress/unittests/sshkey/testdata/rsa_1_sha1 +@@ -0,0 +1,15 @@ ++-----BEGIN RSA PRIVATE KEY----- ++MIICXAIBAAKBgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18u ++d6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKd ++NSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wIDAQAB ++AoGAXyj5mpjmbD+YlxGIWz/zrM4hGsWgd4VteKEJxT6MMI4uzCRpkMd0ck8oHiwZ ++GAI/SwUzIsgtONQuH3AXVsUgghW4Ynn+8ksEv0IZ918WDMDwqvqkyrVzsOsZzqYj ++Pf8DUDKCpwFjnlknJ04yvWBZvVhWtY4OiZ8GV0Ttsu3k+GECQQD1YHfvBb5FdJBv ++Uhde2Il+jaFia8mwVVNNaiD2ECxXx6CzGz54ZLEB9NPVfDUZK8lJ4UJDqelWNh3i ++PF3RefWDAkEA1CVBzAFL4mNwpleVPzrfy69xP3gWOa26MxM/GE6zx9jC7HgQ3KPa ++WKdG/FuHs085aTRDaDLmGcZ8IvMuu7NgKQJAcIOKmxR0Gd8IN7NZugjqixggb0Pj ++mLKXXwESGiJyYtHL0zTj4Uqyi6Ya2GJ66o7UXscmnmYz828fJtTtZBdbRwJBALfi ++C2QvA32Zv/0PEXibKXy996WSC4G3ShwXZKtHHKHvCxY5BDSbehk59VesZrVPyG2e ++NYdOBxD0cIlCzJE56/ECQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/ ++h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZs= ++-----END RSA PRIVATE KEY----- +diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha1-cert.pub b/regress/unittests/sshkey/testdata/rsa_1_sha1-cert.pub +new file mode 100644 +index 00000000..ff49d759 +--- /dev/null ++++ b/regress/unittests/sshkey/testdata/rsa_1_sha1-cert.pub +@@ -0,0 +1 @@ ++ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgy5PGFfSaEuSuXsjvKlMZGXYD0xlnqdZftuW9tMkUYz4AAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wAAAAAAAAABAAAAAQAAAARodWdvAAAAEgAAAAV1c2VyMQAAAAV1c2VyMgAAAAA2i4NgAAAAAE0d4eAAAABEAAAADWZvcmNlLWNvbW1hbmQAAAALAAAABy9iaW4vbHMAAAAOc291cmNlLWFkZHJlc3MAAAAOAAAACjEwLjAuMC4wLzgAAABkAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQD00RRenvxICSYvj54CPiYHM86OT5xwI9XORNH6Zkl3JPCQkAEdQ3hyfhraROaHsSv43wJcKyKrEg5XUZ8fZ/BoKIGU4Rd5AmL9wyPGv2RVY7gWELqXVSpu89R2tQJRmMVMD38CH0wqCTuoZirlKMTen6yfgYuFEpuqar0uOIeAyaQG6/9rVKWK36tcfM7YXx8fmGSN4eK/JhWDDjlo28YJ7ZFF9umh5baZG2Ai/vL3BJ7C3pqaEQNdKj8XqaSoDvFWKfOujk1620Rcuj3W0D0dvp/rH8xz8YkM1dMqGlYIZ4nrF5acB58Nk5FYBjtj1hu4DGEQlWL1Avk1agU4DQLrAAABDwAAAAdzc2gtcnNhAAABAF5BtPY8FbmIekK/zNq6/Lp5agKT5zEVxqAyZKhp75bLRP+kOMZBVB9ZWrekZk6IAVAOCZGQzTsD4mxIQsxBLl8k5hvEWb90/+w9/BzW9ScOGQe+y0COa0QWWR7L3k1S8WX2oAGvtDWOj7Md85nij4ZSU9/QQQFVDF8VilWPSMxUf/3I1fqyDq7AWcZkGk/bFUN6K6RsCSxIPlGmKt0IauyvSMI2IT0XeRT242RngeeUW8vFrn9TXy9YxJRW+cSeLKCuu8agBYyQMXWQ+q39eZZqVYSoo7nFEEhtaLs8d6jzgGkcE9wGJ9KLgfY/mG2vX3gI4IzncKkVJRoeiDzXFIk= RSA test key #1 +diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha1.pub b/regress/unittests/sshkey/testdata/rsa_1_sha1.pub +new file mode 100644 +index 00000000..23ef872e +--- /dev/null ++++ b/regress/unittests/sshkey/testdata/rsa_1_sha1.pub +@@ -0,0 +1 @@ ++ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+w== RSA test key #1 +diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha512 b/regress/unittests/sshkey/testdata/rsa_1_sha512 +new file mode 100644 +index 00000000..5de3f842 +--- /dev/null ++++ b/regress/unittests/sshkey/testdata/rsa_1_sha512 +@@ -0,0 +1,15 @@ ++-----BEGIN RSA PRIVATE KEY----- ++MIICXAIBAAKBgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18u ++d6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKd ++NSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wIDAQAB ++AoGAXyj5mpjmbD+YlxGIWz/zrM4hGsWgd4VteKEJxT6MMI4uzCRpkMd0ck8oHiwZ ++GAI/SwUzIsgtONQuH3AXVsUgghW4Ynn+8ksEv0IZ918WDMDwqvqkyrVzsOsZzqYj ++Pf8DUDKCpwFjnlknJ04yvWBZvVhWtY4OiZ8GV0Ttsu3k+GECQQD1YHfvBb5FdJBv ++Uhde2Il+jaFia8mwVVNNaiD2ECxXx6CzGz54ZLEB9NPVfDUZK8lJ4UJDqelWNh3i ++PF3RefWDAkEA1CVBzAFL4mNwpleVPzrfy69xP3gWOa26MxM/GE6zx9jC7HgQ3KPa ++WKdG/FuHs085aTRDaDLmGcZ8IvMuu7NgKQJAcIOKmxR0Gd8IN7NZugjqixggb0Pj ++mLKXXwESGiJyYtHL0zTj4Uqyi6Ya2GJ66o7UXscmnmYz828fJtTtZBdbRwJBALfi ++C2QvA32Zv/0PEXibKXy996WSC4G3ShwXZKtHHKHvCxY5BDSbehk59VesZrVPyG2e ++NYdOBxD0cIlCzJE56/ECQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/ ++h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZs= ++-----END RSA PRIVATE KEY----- +diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha512-cert.pub b/regress/unittests/sshkey/testdata/rsa_1_sha512-cert.pub +new file mode 100644 +index 00000000..47451968 +--- /dev/null ++++ b/regress/unittests/sshkey/testdata/rsa_1_sha512-cert.pub +@@ -0,0 +1 @@ ++ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg/bUEmnMYHxlv1N7iXvnYPYdzDjlTRKoaIGEPkaQQQDwAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wAAAAAAAAABAAAAAQAAAARodWdvAAAAEgAAAAV1c2VyMQAAAAV1c2VyMgAAAAA2i4NgAAAAAE0d4eAAAABEAAAADWZvcmNlLWNvbW1hbmQAAAALAAAABy9iaW4vbHMAAAAOc291cmNlLWFkZHJlc3MAAAAOAAAACjEwLjAuMC4wLzgAAABkAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQD00RRenvxICSYvj54CPiYHM86OT5xwI9XORNH6Zkl3JPCQkAEdQ3hyfhraROaHsSv43wJcKyKrEg5XUZ8fZ/BoKIGU4Rd5AmL9wyPGv2RVY7gWELqXVSpu89R2tQJRmMVMD38CH0wqCTuoZirlKMTen6yfgYuFEpuqar0uOIeAyaQG6/9rVKWK36tcfM7YXx8fmGSN4eK/JhWDDjlo28YJ7ZFF9umh5baZG2Ai/vL3BJ7C3pqaEQNdKj8XqaSoDvFWKfOujk1620Rcuj3W0D0dvp/rH8xz8YkM1dMqGlYIZ4nrF5acB58Nk5FYBjtj1hu4DGEQlWL1Avk1agU4DQLrAAABFAAAAAxyc2Etc2hhMi01MTIAAAEA7/GoZsJqrq4xYotsRbpM8arZDjCzT6kohXeD/GVy26s5E/YWXRYCrOMIzSZxjuN5rAaNRW8ffxq14JyI94566Kg2OeoxQ6rK/dTqkk7I1RyypSXunT3I4++RPs1Q+hu9eS/WBzur0/D3dMejhuc3IBg6iB0481I4pGBGcD8/KjQFfhlCuGVXwB1ALk2zfXFT1HYYrs6bYZuQqjgvArnjYJ0do3fTSDC20/ydV4BHnI3fVAY2THVjX45V2ppPadl/rpczaJqW1ZtpnpJkV8Un316stQSD0xLHUDjp89O6d9Yq5S0kDdfwTRJIPm9f2cGNakJwN5qzmmmdDroRKODYcg== RSA test key #1 +diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha512.pub b/regress/unittests/sshkey/testdata/rsa_1_sha512.pub +new file mode 100644 +index 00000000..23ef872e +--- /dev/null ++++ b/regress/unittests/sshkey/testdata/rsa_1_sha512.pub +@@ -0,0 +1 @@ ++ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+w== RSA test key #1 +commit 482d23bcacdd3664f21cc82a5135f66fc598275f +Author: djm@openbsd.org +Date: Thu Sep 13 02:08:33 2018 +0000 + + upstream: hold our collective noses and use the openssl-1.1.x API in + + OpenSSH; feedback and ok tb@ jsing@ markus@ + + OpenBSD-Commit-ID: cacbcac87ce5da0d3ca7ef1b38a6f7fb349e4417 + +diff --git a/auth2.c b/auth2.c +index ab879589..4d19957a 100644 +--- a/auth2.c ++++ b/auth2.c +@@ -706,7 +706,7 @@ auth2_record_key(Authctxt *authctxt, int authenticated, + struct sshkey **tmp, *dup; + int r; + +- if ((r = sshkey_demote(key, &dup)) != 0) ++ if ((r = sshkey_from_private(key, &dup)) != 0) + fatal("%s: copy key: %s", __func__, ssh_err(r)); + sshkey_free(authctxt->auth_method_key); + authctxt->auth_method_key = dup; +@@ -715,7 +715,7 @@ auth2_record_key(Authctxt *authctxt, int authenticated, + return; + + /* If authenticated, make sure we don't accept this key again */ +- if ((r = sshkey_demote(key, &dup)) != 0) ++ if ((r = sshkey_from_private(key, &dup)) != 0) + fatal("%s: copy key: %s", __func__, ssh_err(r)); + if (authctxt->nprev_keys >= INT_MAX || + (tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys, +diff --git a/cipher.c b/cipher.c +index a72682a8..df43826e 100644 +--- a/cipher.c ++++ b/cipher.c +@@ -446,7 +446,7 @@ cipher_get_keyiv_len(const struct sshcipher_ctx *cc) + } + + int +-cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len) ++cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, size_t len) + { + #ifdef WITH_OPENSSL + const struct sshcipher *c = cc->cipher; +@@ -473,7 +473,7 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len) + return 0; + else if (evplen < 0) + return SSH_ERR_LIBCRYPTO_ERROR; +- if ((u_int)evplen != len) ++ if ((size_t)evplen != len) + return SSH_ERR_INVALID_ARGUMENT; + #ifndef OPENSSL_HAVE_EVPCTR + if (c->evptype == evp_aes_128_ctr) +@@ -484,14 +484,14 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len) + if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, + len, iv)) + return SSH_ERR_LIBCRYPTO_ERROR; +- } else +- memcpy(iv, cc->evp->iv, len); ++ } else if (!EVP_CIPHER_CTX_get_iv(cc->evp, iv, len)) ++ return SSH_ERR_LIBCRYPTO_ERROR; + #endif + return 0; + } + + int +-cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv) ++cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv, size_t len) + { + #ifdef WITH_OPENSSL + const struct sshcipher *c = cc->cipher; +@@ -507,6 +507,8 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv) + evplen = EVP_CIPHER_CTX_iv_length(cc->evp); + if (evplen <= 0) + return SSH_ERR_LIBCRYPTO_ERROR; ++ if ((size_t)evplen != len) ++ return SSH_ERR_INVALID_ARGUMENT; + #ifndef OPENSSL_HAVE_EVPCTR + /* XXX iv arg is const, but ssh_aes_ctr_iv isn't */ + if (c->evptype == evp_aes_128_ctr) +@@ -518,8 +520,8 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv) + if (!EVP_CIPHER_CTX_ctrl(cc->evp, + EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv)) + return SSH_ERR_LIBCRYPTO_ERROR; +- } else +- memcpy(cc->evp->iv, iv, evplen); ++ } else if (!EVP_CIPHER_CTX_set_iv(cc->evp, iv, evplen)) ++ return SSH_ERR_LIBCRYPTO_ERROR; + #endif + return 0; + } +diff --git a/cipher.h b/cipher.h +index dc7ecf11..dc1571d2 100644 +--- a/cipher.h ++++ b/cipher.h +@@ -68,8 +68,8 @@ u_int cipher_is_cbc(const struct sshcipher *); + + u_int cipher_ctx_is_plaintext(struct sshcipher_ctx *); + +-int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, u_int); +-int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *); ++int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, size_t); ++int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *, size_t); + int cipher_get_keyiv_len(const struct sshcipher_ctx *); + + #endif /* CIPHER_H */ +diff --git a/dh.c b/dh.c +index ac8d5a0a..d0d4527b 100644 +--- a/dh.c ++++ b/dh.c +@@ -216,14 +216,17 @@ choose_dh(int min, int wantbits, int max) + /* diffie-hellman-groupN-sha1 */ + + int +-dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) ++dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub) + { + int i; + int n = BN_num_bits(dh_pub); + int bits_set = 0; + BIGNUM *tmp; ++ const BIGNUM *dh_p; + +- if (dh_pub->neg) { ++ DH_get0_pqg(dh, &dh_p, NULL, NULL); ++ ++ if (BN_is_negative(dh_pub)) { + logit("invalid public DH value: negative"); + return 0; + } +@@ -236,7 +239,7 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) + error("%s: BN_new failed", __func__); + return 0; + } +- if (!BN_sub(tmp, dh->p, BN_value_one()) || ++ if (!BN_sub(tmp, dh_p, BN_value_one()) || + BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */ + BN_clear_free(tmp); + logit("invalid public DH value: >= p-1"); +@@ -247,14 +250,14 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) + for (i = 0; i <= n; i++) + if (BN_is_bit_set(dh_pub, i)) + bits_set++; +- debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p)); ++ debug2("bits set: %d/%d", bits_set, BN_num_bits(dh_p)); + + /* + * if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial + */ + if (bits_set < 4) { + logit("invalid public DH value (%d/%d)", +- bits_set, BN_num_bits(dh->p)); ++ bits_set, BN_num_bits(dh_p)); + return 0; + } + return 1; +@@ -264,9 +267,12 @@ int + dh_gen_key(DH *dh, int need) + { + int pbits; ++ const BIGNUM *dh_p, *pub_key; ++ ++ DH_get0_pqg(dh, &dh_p, NULL, NULL); + +- if (need < 0 || dh->p == NULL || +- (pbits = BN_num_bits(dh->p)) <= 0 || ++ if (need < 0 || dh_p == NULL || ++ (pbits = BN_num_bits(dh_p)) <= 0 || + need > INT_MAX / 2 || 2 * need > pbits) + return SSH_ERR_INVALID_ARGUMENT; + if (need < 256) +@@ -275,13 +281,14 @@ dh_gen_key(DH *dh, int need) + * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)), + * so double requested need here. + */ +- dh->length = MINIMUM(need * 2, pbits - 1); +- if (DH_generate_key(dh) == 0 || +- !dh_pub_is_valid(dh, dh->pub_key)) { +- BN_clear_free(dh->priv_key); +- dh->priv_key = NULL; ++ if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1))) + return SSH_ERR_LIBCRYPTO_ERROR; +- } ++ ++ if (DH_generate_key(dh) == 0) ++ return SSH_ERR_LIBCRYPTO_ERROR; ++ DH_get0_key(dh, &pub_key, NULL); ++ if (!dh_pub_is_valid(dh, pub_key)) ++ return SSH_ERR_INVALID_FORMAT; + return 0; + } + +@@ -289,22 +296,27 @@ DH * + dh_new_group_asc(const char *gen, const char *modulus) + { + DH *dh; ++ BIGNUM *dh_p = NULL, *dh_g = NULL; + + if ((dh = DH_new()) == NULL) + return NULL; +- if (BN_hex2bn(&dh->p, modulus) == 0 || +- BN_hex2bn(&dh->g, gen) == 0) { +- DH_free(dh); +- return NULL; +- } +- return (dh); ++ if (BN_hex2bn(&dh_p, modulus) == 0 || ++ BN_hex2bn(&dh_g, gen) == 0) ++ goto fail; ++ if (!DH_set0_pqg(dh, dh_p, NULL, dh_g)) ++ goto fail; ++ return dh; ++ fail: ++ DH_free(dh); ++ BN_clear_free(dh_p); ++ BN_clear_free(dh_g); ++ return NULL; + } + + /* + * This just returns the group, we still need to generate the exchange + * value. + */ +- + DH * + dh_new_group(BIGNUM *gen, BIGNUM *modulus) + { +@@ -312,10 +324,12 @@ dh_new_group(BIGNUM *gen, BIGNUM *modulus) + + if ((dh = DH_new()) == NULL) + return NULL; +- dh->p = modulus; +- dh->g = gen; ++ if (!DH_set0_pqg(dh, modulus, NULL, gen)) { ++ DH_free(dh); ++ return NULL; ++ } + +- return (dh); ++ return dh; + } + + /* rfc2409 "Second Oakley Group" (1024 bits) */ +diff --git a/dh.h b/dh.h +index bcd485cf..344b29e3 100644 +--- a/dh.h ++++ b/dh.h +@@ -42,7 +42,7 @@ DH *dh_new_group18(void); + DH *dh_new_group_fallback(int); + + int dh_gen_key(DH *, int); +-int dh_pub_is_valid(DH *, BIGNUM *); ++int dh_pub_is_valid(const DH *, const BIGNUM *); + + u_int dh_estimate(int); + +diff --git a/digest-openssl.c b/digest-openssl.c +index 27709992..da7ed72b 100644 +--- a/digest-openssl.c ++++ b/digest-openssl.c +@@ -43,7 +43,7 @@ + + struct ssh_digest_ctx { + int alg; +- EVP_MD_CTX mdctx; ++ EVP_MD_CTX *mdctx; + }; + + struct ssh_digest { +@@ -106,7 +106,7 @@ ssh_digest_bytes(int alg) + size_t + ssh_digest_blocksize(struct ssh_digest_ctx *ctx) + { +- return EVP_MD_CTX_block_size(&ctx->mdctx); ++ return EVP_MD_CTX_block_size(ctx->mdctx); + } + + struct ssh_digest_ctx * +@@ -118,11 +118,14 @@ ssh_digest_start(int alg) + if (digest == NULL || ((ret = calloc(1, sizeof(*ret))) == NULL)) + return NULL; + ret->alg = alg; +- EVP_MD_CTX_init(&ret->mdctx); +- if (EVP_DigestInit_ex(&ret->mdctx, digest->mdfunc(), NULL) != 1) { ++ if ((ret->mdctx = EVP_MD_CTX_new()) == NULL) { + free(ret); + return NULL; + } ++ if (EVP_DigestInit_ex(ret->mdctx, digest->mdfunc(), NULL) != 1) { ++ ssh_digest_free(ret); ++ return NULL; ++ } + return ret; + } + +@@ -132,7 +135,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to) + if (from->alg != to->alg) + return SSH_ERR_INVALID_ARGUMENT; + /* we have bcopy-style order while openssl has memcpy-style */ +- if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx)) ++ if (!EVP_MD_CTX_copy_ex(to->mdctx, from->mdctx)) + return SSH_ERR_LIBCRYPTO_ERROR; + return 0; + } +@@ -140,7 +143,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to) + int + ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) + { +- if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1) ++ if (EVP_DigestUpdate(ctx->mdctx, m, mlen) != 1) + return SSH_ERR_LIBCRYPTO_ERROR; + return 0; + } +@@ -161,7 +164,7 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) + return SSH_ERR_INVALID_ARGUMENT; + if (dlen < digest->digest_len) /* No truncation allowed */ + return SSH_ERR_INVALID_ARGUMENT; +- if (EVP_DigestFinal_ex(&ctx->mdctx, d, &l) != 1) ++ if (EVP_DigestFinal_ex(ctx->mdctx, d, &l) != 1) + return SSH_ERR_LIBCRYPTO_ERROR; + if (l != digest->digest_len) /* sanity */ + return SSH_ERR_INTERNAL_ERROR; +@@ -171,11 +174,10 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) + void + ssh_digest_free(struct ssh_digest_ctx *ctx) + { +- if (ctx != NULL) { +- EVP_MD_CTX_cleanup(&ctx->mdctx); +- explicit_bzero(ctx, sizeof(*ctx)); +- free(ctx); +- } ++ if (ctx == NULL) ++ return; ++ EVP_MD_CTX_free(ctx->mdctx); ++ freezero(ctx, sizeof(*ctx)); + } + + int +diff --git a/kexdhc.c b/kexdhc.c +index 9a9f1ea7..a8b74247 100644 +--- a/kexdhc.c ++++ b/kexdhc.c +@@ -56,6 +56,7 @@ kexdh_client(struct ssh *ssh) + { + struct kex *kex = ssh->kex; + int r; ++ const BIGNUM *pub_key; + + /* generate and send 'e', client DH public key */ + switch (kex->kex_type) { +@@ -81,15 +82,17 @@ kexdh_client(struct ssh *ssh) + goto out; + } + debug("sending SSH2_MSG_KEXDH_INIT"); +- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 || +- (r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 || +- (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || ++ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) ++ goto out; ++ DH_get0_key(kex->dh, &pub_key, NULL); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; + #ifdef DEBUG_KEXDH + DHparams_print_fp(stderr, kex->dh); + fprintf(stderr, "pub= "); +- BN_print_fp(stderr, kex->dh->pub_key); ++ BN_print_fp(stderr, pub_key); + fprintf(stderr, "\n"); + #endif + debug("expecting SSH2_MSG_KEXDH_REPLY"); +@@ -104,6 +107,7 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) + { + struct kex *kex = ssh->kex; + BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; ++ const BIGNUM *pub_key; + struct sshkey *server_host_key = NULL; + u_char *kbuf = NULL, *server_host_key_blob = NULL, *signature = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; +@@ -168,6 +172,7 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) + #endif + + /* calc and verify H */ ++ DH_get0_key(kex->dh, &pub_key, NULL); + hashlen = sizeof(hash); + if ((r = kex_dh_hash( + kex->hash_alg, +@@ -176,7 +181,7 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) + sshbuf_ptr(kex->my), sshbuf_len(kex->my), + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), + server_host_key_blob, sbloblen, +- kex->dh->pub_key, ++ pub_key, + dh_server_pub, + shared_secret, + hash, &hashlen)) != 0) +diff --git a/kexdhs.c b/kexdhs.c +index 5dfca0a2..8367c6c3 100644 +--- a/kexdhs.c ++++ b/kexdhs.c +@@ -95,6 +95,7 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) + { + struct kex *kex = ssh->kex; + BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; ++ const BIGNUM *pub_key; + struct sshkey *server_host_public, *server_host_private; + u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; +@@ -121,6 +122,7 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) + r = SSH_ERR_ALLOC_FAIL; + goto out; + } ++ DH_get0_key(kex->dh, &pub_key, NULL); + if ((r = sshpkt_get_bignum2(ssh, dh_client_pub)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; +@@ -130,12 +132,9 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) + BN_print_fp(stderr, dh_client_pub); + fprintf(stderr, "\n"); + debug("bits %d", BN_num_bits(dh_client_pub)); +-#endif +- +-#ifdef DEBUG_KEXDH + DHparams_print_fp(stderr, kex->dh); + fprintf(stderr, "pub= "); +- BN_print_fp(stderr, kex->dh->pub_key); ++ BN_print_fp(stderr, pub_key); + fprintf(stderr, "\n"); + #endif + if (!dh_pub_is_valid(kex->dh, dh_client_pub)) { +@@ -171,7 +170,7 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) + sshbuf_ptr(kex->my), sshbuf_len(kex->my), + server_host_key_blob, sbloblen, + dh_client_pub, +- kex->dh->pub_key, ++ pub_key, + shared_secret, + hash, &hashlen)) != 0) + goto out; +@@ -197,7 +196,7 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) + /* send server hostkey, DH pubkey 'f' and signed H */ + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 || + (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || +- (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || /* f */ ++ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */ + (r = sshpkt_put_string(ssh, signature, slen)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; +diff --git a/kexgexc.c b/kexgexc.c +index 762a9a32..955bc837 100644 +--- a/kexgexc.c ++++ b/kexgexc.c +@@ -93,6 +93,7 @@ input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh) + { + struct kex *kex = ssh->kex; + BIGNUM *p = NULL, *g = NULL; ++ const BIGNUM *pub_key; + int r, bits; + + debug("got SSH2_MSG_KEX_DH_GEX_GROUP"); +@@ -118,16 +119,18 @@ input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh) + p = g = NULL; /* belong to kex->dh now */ + + /* generate and send 'e', client DH public key */ +- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 || +- (r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 || +- (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || ++ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) ++ goto out; ++ DH_get0_key(kex->dh, &pub_key, NULL); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; + debug("SSH2_MSG_KEX_DH_GEX_INIT sent"); + #ifdef DEBUG_KEXDH + DHparams_print_fp(stderr, kex->dh); + fprintf(stderr, "pub= "); +- BN_print_fp(stderr, kex->dh->pub_key); ++ BN_print_fp(stderr, pub_key); + fprintf(stderr, "\n"); + #endif + ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, NULL); +@@ -144,6 +147,7 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) + { + struct kex *kex = ssh->kex; + BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; ++ const BIGNUM *pub_key, *dh_p, *dh_g; + struct sshkey *server_host_key = NULL; + u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; +@@ -211,6 +215,8 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) + kex->min = kex->max = -1; + + /* calc and verify H */ ++ DH_get0_key(kex->dh, &pub_key, NULL); ++ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); + hashlen = sizeof(hash); + if ((r = kexgex_hash( + kex->hash_alg, +@@ -220,8 +226,8 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), + server_host_key_blob, sbloblen, + kex->min, kex->nbits, kex->max, +- kex->dh->p, kex->dh->g, +- kex->dh->pub_key, ++ dh_p, dh_g, ++ pub_key, + dh_server_pub, + shared_secret, + hash, &hashlen)) != 0) +diff --git a/kexgexs.c b/kexgexs.c +index f6983fd6..2a4aa7e8 100644 +--- a/kexgexs.c ++++ b/kexgexs.c +@@ -72,6 +72,7 @@ input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh) + struct kex *kex = ssh->kex; + int r; + u_int min = 0, max = 0, nbits = 0; ++ const BIGNUM *dh_p, *dh_g; + + debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); + if ((r = sshpkt_get_u32(ssh, &min)) != 0 || +@@ -101,9 +102,10 @@ input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh) + goto out; + } + debug("SSH2_MSG_KEX_DH_GEX_GROUP sent"); ++ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); + if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_GROUP)) != 0 || +- (r = sshpkt_put_bignum2(ssh, kex->dh->p)) != 0 || +- (r = sshpkt_put_bignum2(ssh, kex->dh->g)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; + +@@ -123,6 +125,7 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) + { + struct kex *kex = ssh->kex; + BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; ++ const BIGNUM *pub_key, *dh_p, *dh_g; + struct sshkey *server_host_public, *server_host_private; + u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; +@@ -153,17 +156,17 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) + (r = sshpkt_get_end(ssh)) != 0) + goto out; + ++ DH_get0_key(kex->dh, &pub_key, NULL); ++ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); ++ + #ifdef DEBUG_KEXDH + fprintf(stderr, "dh_client_pub= "); + BN_print_fp(stderr, dh_client_pub); + fprintf(stderr, "\n"); + debug("bits %d", BN_num_bits(dh_client_pub)); +-#endif +- +-#ifdef DEBUG_KEXDH + DHparams_print_fp(stderr, kex->dh); + fprintf(stderr, "pub= "); +- BN_print_fp(stderr, kex->dh->pub_key); ++ BN_print_fp(stderr, pub_key); + fprintf(stderr, "\n"); + #endif + if (!dh_pub_is_valid(kex->dh, dh_client_pub)) { +@@ -199,9 +202,9 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) + sshbuf_ptr(kex->my), sshbuf_len(kex->my), + server_host_key_blob, sbloblen, + kex->min, kex->nbits, kex->max, +- kex->dh->p, kex->dh->g, ++ dh_p, dh_g, + dh_client_pub, +- kex->dh->pub_key, ++ pub_key, + shared_secret, + hash, &hashlen)) != 0) + goto out; +@@ -227,7 +230,7 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) + /* send server hostkey, DH pubkey 'f' and signed H */ + if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 || + (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || +- (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || /* f */ ++ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */ + (r = sshpkt_put_string(ssh, signature, slen)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; +diff --git a/monitor.c b/monitor.c +index d4b4b047..b30813b4 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -566,6 +566,7 @@ int + mm_answer_moduli(int sock, struct sshbuf *m) + { + DH *dh; ++ const BIGNUM *dh_p, *dh_g; + int r; + u_int min, want, max; + +@@ -590,9 +591,10 @@ mm_answer_moduli(int sock, struct sshbuf *m) + return (0); + } else { + /* Send first bignum */ ++ DH_get0_pqg(dh, &dh_p, NULL, &dh_g); + if ((r = sshbuf_put_u8(m, 1)) != 0 || +- (r = sshbuf_put_bignum2(m, dh->p)) != 0 || +- (r = sshbuf_put_bignum2(m, dh->g)) != 0) ++ (r = sshbuf_put_bignum2(m, dh_p)) != 0 || ++ (r = sshbuf_put_bignum2(m, dh_g)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + + DH_free(dh); +diff --git a/ssh-dss.c b/ssh-dss.c +index 9f832ee2..631b1571 100644 +--- a/ssh-dss.c ++++ b/ssh-dss.c +@@ -51,6 +51,7 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat) + { + DSA_SIG *sig = NULL; ++ const BIGNUM *sig_r, *sig_s; + u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; + size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); + struct sshbuf *b = NULL; +@@ -76,15 +77,16 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + goto out; + } + +- rlen = BN_num_bytes(sig->r); +- slen = BN_num_bytes(sig->s); ++ DSA_SIG_get0(sig, &sig_r, &sig_s); ++ rlen = BN_num_bytes(sig_r); ++ slen = BN_num_bytes(sig_s); + if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { + ret = SSH_ERR_INTERNAL_ERROR; + goto out; + } + explicit_bzero(sigblob, SIGBLOB_LEN); +- BN_bn2bin(sig->r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen); +- BN_bn2bin(sig->s, sigblob + SIGBLOB_LEN - slen); ++ BN_bn2bin(sig_r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen); ++ BN_bn2bin(sig_s, sigblob + SIGBLOB_LEN - slen); + + if ((b = sshbuf_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; +@@ -118,6 +120,7 @@ ssh_dss_verify(const struct sshkey *key, + const u_char *data, size_t datalen, u_int compat) + { + DSA_SIG *sig = NULL; ++ BIGNUM *sig_r = NULL, *sig_s = NULL; + u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL; + size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); + int ret = SSH_ERR_INTERNAL_ERROR; +@@ -155,16 +158,21 @@ ssh_dss_verify(const struct sshkey *key, + + /* parse signature */ + if ((sig = DSA_SIG_new()) == NULL || +- (sig->r = BN_new()) == NULL || +- (sig->s = BN_new()) == NULL) { ++ (sig_r = BN_new()) == NULL || ++ (sig_s = BN_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) || +- (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) { ++ if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig_r) == NULL) || ++ (BN_bin2bn(sigblob + INTBLOB_LEN, INTBLOB_LEN, sig_s) == NULL)) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } ++ if (!DSA_SIG_set0(sig, sig_r, sig_s)) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ sig_r = sig_s = NULL; /* transferred */ + + /* sha1 the data */ + if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, +@@ -186,6 +194,8 @@ ssh_dss_verify(const struct sshkey *key, + out: + explicit_bzero(digest, sizeof(digest)); + DSA_SIG_free(sig); ++ BN_clear_free(sig_r); ++ BN_clear_free(sig_s); + sshbuf_free(b); + free(ktype); + if (sigblob != NULL) { +diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c +index 3d3b78d7..9e92af04 100644 +--- a/ssh-ecdsa.c ++++ b/ssh-ecdsa.c +@@ -49,6 +49,7 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat) + { + ECDSA_SIG *sig = NULL; ++ const BIGNUM *sig_r, *sig_s; + int hash_alg; + u_char digest[SSH_DIGEST_MAX_LENGTH]; + size_t len, dlen; +@@ -80,8 +81,9 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((ret = sshbuf_put_bignum2(bb, sig->r)) != 0 || +- (ret = sshbuf_put_bignum2(bb, sig->s)) != 0) ++ ECDSA_SIG_get0(sig, &sig_r, &sig_s); ++ if ((ret = sshbuf_put_bignum2(bb, sig_r)) != 0 || ++ (ret = sshbuf_put_bignum2(bb, sig_s)) != 0) + goto out; + if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 || + (ret = sshbuf_put_stringb(b, bb)) != 0) +@@ -112,6 +114,7 @@ ssh_ecdsa_verify(const struct sshkey *key, + const u_char *data, size_t datalen, u_int compat) + { + ECDSA_SIG *sig = NULL; ++ BIGNUM *sig_r = NULL, *sig_s = NULL; + int hash_alg; + u_char digest[SSH_DIGEST_MAX_LENGTH]; + size_t dlen; +@@ -146,15 +149,23 @@ ssh_ecdsa_verify(const struct sshkey *key, + } + + /* parse signature */ +- if ((sig = ECDSA_SIG_new()) == NULL) { ++ if ((sig = ECDSA_SIG_new()) == NULL || ++ (sig_r = BN_new()) == NULL || ++ (sig_s = BN_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if (sshbuf_get_bignum2(sigbuf, sig->r) != 0 || +- sshbuf_get_bignum2(sigbuf, sig->s) != 0) { ++ if (sshbuf_get_bignum2(sigbuf, sig_r) != 0 || ++ sshbuf_get_bignum2(sigbuf, sig_s) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } ++ if (!ECDSA_SIG_set0(sig, sig_r, sig_s)) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ sig_r = sig_s = NULL; /* transferred */ ++ + if (sshbuf_len(sigbuf) != 0) { + ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; + goto out; +@@ -180,6 +191,8 @@ ssh_ecdsa_verify(const struct sshkey *key, + sshbuf_free(sigbuf); + sshbuf_free(b); + ECDSA_SIG_free(sig); ++ BN_clear_free(sig_r); ++ BN_clear_free(sig_s); + free(ktype); + return ret; + } +diff --git a/ssh-keygen.c b/ssh-keygen.c +index 748ce37d..a70fd1f8 100644 +--- a/ssh-keygen.c ++++ b/ssh-keygen.c +@@ -450,7 +450,10 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) + u_int magic, i1, i2, i3, i4; + size_t slen; + u_long e; +- ++ BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; ++ BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; ++ BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; ++ BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL; + if ((b = sshbuf_from(blob, blen)) == NULL) + fatal("%s: sshbuf_from failed", __func__); + if ((r = sshbuf_get_u32(b, &magic)) != 0) +@@ -494,11 +497,23 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) + + switch (key->type) { + case KEY_DSA: +- buffer_get_bignum_bits(b, key->dsa->p); +- buffer_get_bignum_bits(b, key->dsa->g); +- buffer_get_bignum_bits(b, key->dsa->q); +- buffer_get_bignum_bits(b, key->dsa->pub_key); +- buffer_get_bignum_bits(b, key->dsa->priv_key); ++ if ((dsa_p = BN_new()) == NULL || ++ (dsa_q = BN_new()) == NULL || ++ (dsa_g = BN_new()) == NULL || ++ (dsa_pub_key = BN_new()) == NULL || ++ (dsa_priv_key = BN_new()) == NULL) ++ fatal("%s: BN_new", __func__); ++ buffer_get_bignum_bits(b, dsa_p); ++ buffer_get_bignum_bits(b, dsa_g); ++ buffer_get_bignum_bits(b, dsa_q); ++ buffer_get_bignum_bits(b, dsa_pub_key); ++ buffer_get_bignum_bits(b, dsa_priv_key); ++ if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) ++ fatal("%s: DSA_set0_pqg failed", __func__); ++ dsa_p = dsa_q = dsa_g = NULL; /* transferred */ ++ if (!DSA_set0_key(key->dsa, dsa_pub_key, dsa_priv_key)) ++ fatal("%s: DSA_set0_key failed", __func__); ++ dsa_pub_key = dsa_priv_key = NULL; /* transferred */ + break; + case KEY_RSA: + if ((r = sshbuf_get_u8(b, &e1)) != 0 || +@@ -515,18 +530,34 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) + e += e3; + debug("e %lx", e); + } +- if (!BN_set_word(key->rsa->e, e)) { ++ if ((rsa_e = BN_new()) == NULL) ++ fatal("%s: BN_new", __func__); ++ if (!BN_set_word(rsa_e, e)) { ++ BN_clear_free(rsa_e); + sshbuf_free(b); + sshkey_free(key); + return NULL; + } +- buffer_get_bignum_bits(b, key->rsa->d); +- buffer_get_bignum_bits(b, key->rsa->n); +- buffer_get_bignum_bits(b, key->rsa->iqmp); +- buffer_get_bignum_bits(b, key->rsa->q); +- buffer_get_bignum_bits(b, key->rsa->p); +- if ((r = ssh_rsa_generate_additional_parameters(key)) != 0) ++ if ((rsa_n = BN_new()) == NULL || ++ (rsa_d = BN_new()) == NULL || ++ (rsa_p = BN_new()) == NULL || ++ (rsa_q = BN_new()) == NULL || ++ (rsa_iqmp = BN_new()) == NULL) ++ fatal("%s: BN_new", __func__); ++ buffer_get_bignum_bits(b, rsa_d); ++ buffer_get_bignum_bits(b, rsa_n); ++ buffer_get_bignum_bits(b, rsa_iqmp); ++ buffer_get_bignum_bits(b, rsa_q); ++ buffer_get_bignum_bits(b, rsa_p); ++ if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, rsa_d)) ++ fatal("%s: RSA_set0_key failed", __func__); ++ rsa_n = rsa_e = rsa_d = NULL; /* transferred */ ++ if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q)) ++ fatal("%s: RSA_set0_factors failed", __func__); ++ rsa_p = rsa_q = NULL; /* transferred */ ++ if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0) + fatal("generate RSA parameters failed: %s", ssh_err(r)); ++ BN_clear_free(rsa_iqmp); + break; + } + rlen = sshbuf_len(b); +@@ -634,7 +665,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private) + identity_file); + } + fclose(fp); +- switch (EVP_PKEY_type(pubkey->type)) { ++ switch (EVP_PKEY_base_id(pubkey)) { + case EVP_PKEY_RSA: + if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) + fatal("sshkey_new failed"); +@@ -658,7 +689,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private) + #endif + default: + fatal("%s: unsupported pubkey type %d", __func__, +- EVP_PKEY_type(pubkey->type)); ++ EVP_PKEY_base_id(pubkey)); + } + EVP_PKEY_free(pubkey); + return; +diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c +index 028b272c..bcc18c6b 100644 +--- a/ssh-pkcs11-client.c ++++ b/ssh-pkcs11-client.c +@@ -156,12 +156,14 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, + static int + wrap_key(RSA *rsa) + { +- static RSA_METHOD helper_rsa; ++ static RSA_METHOD *helper_rsa; + +- memcpy(&helper_rsa, RSA_get_default_method(), sizeof(helper_rsa)); +- helper_rsa.name = "ssh-pkcs11-helper"; +- helper_rsa.rsa_priv_enc = pkcs11_rsa_private_encrypt; +- RSA_set_method(rsa, &helper_rsa); ++ if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL) ++ fatal("%s: RSA_meth_dup failed", __func__); ++ if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper") || ++ !RSA_meth_set_priv_enc(helper_rsa, pkcs11_rsa_private_encrypt)) ++ fatal("%s: failed to prepare method", __func__); ++ RSA_set_method(rsa, helper_rsa); + return (0); + } + +diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c +index 65a7b589..c35f9415 100644 +--- a/ssh-pkcs11.c ++++ b/ssh-pkcs11.c +@@ -67,7 +67,7 @@ struct pkcs11_key { + struct pkcs11_provider *provider; + CK_ULONG slotidx; + int (*orig_finish)(RSA *rsa); +- RSA_METHOD rsa_method; ++ RSA_METHOD *rsa_method; + char *keyid; + int keyid_len; + }; +@@ -182,6 +182,7 @@ pkcs11_rsa_finish(RSA *rsa) + rv = k11->orig_finish(rsa); + if (k11->provider) + pkcs11_provider_unref(k11->provider); ++ RSA_meth_free(k11->rsa_method); + free(k11->keyid); + free(k11); + } +@@ -326,13 +327,18 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, + k11->keyid = xmalloc(k11->keyid_len); + memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); + } +- k11->orig_finish = def->finish; +- memcpy(&k11->rsa_method, def, sizeof(k11->rsa_method)); +- k11->rsa_method.name = "pkcs11"; +- k11->rsa_method.rsa_priv_enc = pkcs11_rsa_private_encrypt; +- k11->rsa_method.rsa_priv_dec = pkcs11_rsa_private_decrypt; +- k11->rsa_method.finish = pkcs11_rsa_finish; +- RSA_set_method(rsa, &k11->rsa_method); ++ k11->rsa_method = RSA_meth_dup(def); ++ if (k11->rsa_method == NULL) ++ fatal("%s: RSA_meth_dup failed", __func__); ++ k11->orig_finish = RSA_meth_get_finish(def); ++ if (!RSA_meth_set1_name(k11->rsa_method, "pkcs11") || ++ !RSA_meth_set_priv_enc(k11->rsa_method, ++ pkcs11_rsa_private_encrypt) || ++ !RSA_meth_set_priv_dec(k11->rsa_method, ++ pkcs11_rsa_private_decrypt) || ++ !RSA_meth_set_finish(k11->rsa_method, pkcs11_rsa_finish)) ++ fatal("%s: setup pkcs11 method failed", __func__); ++ RSA_set_method(rsa, k11->rsa_method); + RSA_set_app_data(rsa, k11); + return (0); + } +@@ -444,6 +450,15 @@ pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key) + return (0); + } + ++static int ++have_rsa_key(const RSA *rsa) ++{ ++ const BIGNUM *rsa_n, *rsa_e; ++ ++ RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL); ++ return rsa_n != NULL && rsa_e != NULL; ++} ++ + static int + pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3], +@@ -512,10 +527,20 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, + if ((rsa = RSA_new()) == NULL) { + error("RSA_new failed"); + } else { +- rsa->n = BN_bin2bn(attribs[1].pValue, ++ BIGNUM *rsa_n, *rsa_e; ++ ++ rsa_n = BN_bin2bn(attribs[1].pValue, + attribs[1].ulValueLen, NULL); +- rsa->e = BN_bin2bn(attribs[2].pValue, ++ rsa_e = BN_bin2bn(attribs[2].pValue, + attribs[2].ulValueLen, NULL); ++ if (rsa_n != NULL && rsa_e != NULL) { ++ if (!RSA_set0_key(rsa, ++ rsa_n, rsa_e, NULL)) ++ fatal("%s: set key", __func__); ++ rsa_n = rsa_e = NULL; /* transferred */ ++ } ++ BN_free(rsa_n); ++ BN_free(rsa_e); + } + } else { + cp = attribs[2].pValue; +@@ -525,16 +550,16 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, + == NULL) { + error("d2i_X509 failed"); + } else if ((evp = X509_get_pubkey(x509)) == NULL || +- evp->type != EVP_PKEY_RSA || +- evp->pkey.rsa == NULL) { ++ EVP_PKEY_base_id(evp) != EVP_PKEY_RSA || ++ EVP_PKEY_get0_RSA(evp) == NULL) { + debug("X509_get_pubkey failed or no rsa"); +- } else if ((rsa = RSAPublicKey_dup(evp->pkey.rsa)) +- == NULL) { ++ } else if ((rsa = RSAPublicKey_dup( ++ EVP_PKEY_get0_RSA(evp))) == NULL) { + error("RSAPublicKey_dup"); + } + X509_free(x509); + } +- if (rsa && rsa->n && rsa->e && ++ if (rsa && have_rsa_key(rsa) && + pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { + if ((key = sshkey_new(KEY_UNSPEC)) == NULL) + fatal("sshkey_new failed"); +diff --git a/ssh-rsa.c b/ssh-rsa.c +index 1756315b..2788f334 100644 +--- a/ssh-rsa.c ++++ b/ssh-rsa.c +@@ -104,38 +104,55 @@ rsa_hash_alg_nid(int type) + } + + int +-ssh_rsa_generate_additional_parameters(struct sshkey *key) ++ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp) + { +- BIGNUM *aux = NULL; ++ const BIGNUM *rsa_p, *rsa_q, *rsa_d; ++ BIGNUM *aux = NULL, *d_consttime = NULL; ++ BIGNUM *rsa_dmq1 = NULL, *rsa_dmp1 = NULL, *rsa_iqmp = NULL; + BN_CTX *ctx = NULL; +- BIGNUM d; + int r; + + if (key == NULL || key->rsa == NULL || + sshkey_type_plain(key->type) != KEY_RSA) + return SSH_ERR_INVALID_ARGUMENT; + ++ RSA_get0_key(key->rsa, NULL, NULL, &rsa_d); ++ RSA_get0_factors(key->rsa, &rsa_p, &rsa_q); ++ + if ((ctx = BN_CTX_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; +- if ((aux = BN_new()) == NULL) { ++ if ((aux = BN_new()) == NULL || ++ (rsa_dmq1 = BN_new()) == NULL || ++ (rsa_dmp1 = BN_new()) == NULL) ++ return SSH_ERR_ALLOC_FAIL; ++ if ((d_consttime = BN_dup(rsa_d)) == NULL || ++ (rsa_iqmp = BN_dup(iqmp)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + BN_set_flags(aux, BN_FLG_CONSTTIME); ++ BN_set_flags(d_consttime, BN_FLG_CONSTTIME); + +- BN_init(&d); +- BN_with_flags(&d, key->rsa->d, BN_FLG_CONSTTIME); +- +- if ((BN_sub(aux, key->rsa->q, BN_value_one()) == 0) || +- (BN_mod(key->rsa->dmq1, &d, aux, ctx) == 0) || +- (BN_sub(aux, key->rsa->p, BN_value_one()) == 0) || +- (BN_mod(key->rsa->dmp1, &d, aux, ctx) == 0)) { ++ if ((BN_sub(aux, rsa_q, BN_value_one()) == 0) || ++ (BN_mod(rsa_dmq1, d_consttime, aux, ctx) == 0) || ++ (BN_sub(aux, rsa_p, BN_value_one()) == 0) || ++ (BN_mod(rsa_dmp1, d_consttime, aux, ctx) == 0)) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (!RSA_set0_crt_params(key->rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } ++ rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL; /* transferred */ ++ /* success */ + r = 0; + out: + BN_clear_free(aux); ++ BN_clear_free(d_consttime); ++ BN_clear_free(rsa_dmp1); ++ BN_clear_free(rsa_dmq1); ++ BN_clear_free(rsa_iqmp); + BN_CTX_free(ctx); + return r; + } +@@ -145,6 +162,7 @@ int + ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, const char *alg_ident) + { ++ const BIGNUM *rsa_n; + u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; + size_t slen = 0; + u_int dlen, len; +@@ -163,7 +181,8 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + if (key == NULL || key->rsa == NULL || hash_alg == -1 || + sshkey_type_plain(key->type) != KEY_RSA) + return SSH_ERR_INVALID_ARGUMENT; +- if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) ++ RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); ++ if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) + return SSH_ERR_KEY_LENGTH; + slen = RSA_size(key->rsa); + if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) +@@ -225,6 +244,7 @@ ssh_rsa_verify(const struct sshkey *key, + const u_char *sig, size_t siglen, const u_char *data, size_t datalen, + const char *alg) + { ++ const BIGNUM *rsa_n; + char *sigtype = NULL; + int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR; + size_t len = 0, diff, modlen, dlen; +@@ -235,7 +255,8 @@ ssh_rsa_verify(const struct sshkey *key, + sshkey_type_plain(key->type) != KEY_RSA || + sig == NULL || siglen == 0) + return SSH_ERR_INVALID_ARGUMENT; +- if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) ++ RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); ++ if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) + return SSH_ERR_KEY_LENGTH; + + if ((b = sshbuf_from(sig, siglen)) == NULL) +diff --git a/sshd.c b/sshd.c +index a738c3ab..98beb1ed 100644 +--- a/sshd.c ++++ b/sshd.c +@@ -493,8 +493,8 @@ demote_sensitive_data(void) + + for (i = 0; i < options.num_host_key_files; i++) { + if (sensitive_data.host_keys[i]) { +- if ((r = sshkey_demote(sensitive_data.host_keys[i], +- &tmp)) != 0) ++ if ((r = sshkey_from_private( ++ sensitive_data.host_keys[i], &tmp)) != 0) + fatal("could not demote host %s key: %s", + sshkey_type(sensitive_data.host_keys[i]), + ssh_err(r)); +@@ -1772,7 +1772,7 @@ main(int ac, char **av) + error("Error loading host key \"%s\": %s", + options.host_key_files[i], ssh_err(r)); + if (pubkey == NULL && key != NULL) +- if ((r = sshkey_demote(key, &pubkey)) != 0) ++ if ((r = sshkey_from_private(key, &pubkey)) != 0) + fatal("Could not demote key: \"%s\": %s", + options.host_key_files[i], ssh_err(r)); + sensitive_data.host_keys[i] = key; +diff --git a/sshkey.c b/sshkey.c +index 50ebdc25..085f1707 100644 +--- a/sshkey.c ++++ b/sshkey.c +@@ -289,14 +289,24 @@ sshkey_names_valid2(const char *names, int allow_wildcard) + u_int + sshkey_size(const struct sshkey *k) + { ++#ifdef WITH_OPENSSL ++ const BIGNUM *rsa_n, *dsa_p; ++#endif /* WITH_OPENSSL */ ++ + switch (k->type) { + #ifdef WITH_OPENSSL + case KEY_RSA: + case KEY_RSA_CERT: +- return BN_num_bits(k->rsa->n); ++ if (k->rsa == NULL) ++ return 0; ++ RSA_get0_key(k->rsa, &rsa_n, NULL, NULL); ++ return BN_num_bits(rsa_n); + case KEY_DSA: + case KEY_DSA_CERT: +- return BN_num_bits(k->dsa->p); ++ if (k->dsa == NULL) ++ return 0; ++ DSA_get0_pqg(k->dsa, &dsa_p, NULL, NULL); ++ return BN_num_bits(dsa_p); + case KEY_ECDSA: + case KEY_ECDSA_CERT: + return sshkey_curve_nid_to_bits(k->ecdsa_nid); +@@ -503,10 +513,7 @@ sshkey_new(int type) + #ifdef WITH_OPENSSL + case KEY_RSA: + case KEY_RSA_CERT: +- if ((rsa = RSA_new()) == NULL || +- (rsa->n = BN_new()) == NULL || +- (rsa->e = BN_new()) == NULL) { +- RSA_free(rsa); ++ if ((rsa = RSA_new()) == NULL) { + free(k); + return NULL; + } +@@ -514,12 +521,7 @@ sshkey_new(int type) + break; + case KEY_DSA: + case KEY_DSA_CERT: +- if ((dsa = DSA_new()) == NULL || +- (dsa->p = BN_new()) == NULL || +- (dsa->q = BN_new()) == NULL || +- (dsa->g = BN_new()) == NULL || +- (dsa->pub_key = BN_new()) == NULL) { +- DSA_free(dsa); ++ if ((dsa = DSA_new()) == NULL) { + free(k); + return NULL; + } +@@ -553,47 +555,7 @@ sshkey_new(int type) + return k; + } + +-int +-sshkey_add_private(struct sshkey *k) +-{ +- switch (k->type) { +-#ifdef WITH_OPENSSL +- case KEY_RSA: +- case KEY_RSA_CERT: +-#define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL) +- if (bn_maybe_alloc_failed(k->rsa->d) || +- bn_maybe_alloc_failed(k->rsa->iqmp) || +- bn_maybe_alloc_failed(k->rsa->q) || +- bn_maybe_alloc_failed(k->rsa->p) || +- bn_maybe_alloc_failed(k->rsa->dmq1) || +- bn_maybe_alloc_failed(k->rsa->dmp1)) +- return SSH_ERR_ALLOC_FAIL; +- break; +- case KEY_DSA: +- case KEY_DSA_CERT: +- if (bn_maybe_alloc_failed(k->dsa->priv_key)) +- return SSH_ERR_ALLOC_FAIL; +- break; +-#undef bn_maybe_alloc_failed +- case KEY_ECDSA: +- case KEY_ECDSA_CERT: +- /* Cannot do anything until we know the group */ +- break; +-#endif /* WITH_OPENSSL */ +- case KEY_ED25519: +- case KEY_ED25519_CERT: +- case KEY_XMSS: +- case KEY_XMSS_CERT: +- /* no need to prealloc */ +- break; +- case KEY_UNSPEC: +- break; +- default: +- return SSH_ERR_INVALID_ARGUMENT; +- } +- return 0; +-} +- ++/* XXX garbage-collect this API */ + struct sshkey * + sshkey_new_private(int type) + { +@@ -601,10 +563,6 @@ sshkey_new_private(int type) + + if (k == NULL) + return NULL; +- if (sshkey_add_private(k) != 0) { +- sshkey_free(k); +- return NULL; +- } + return k; + } + +@@ -686,9 +644,15 @@ cert_compare(struct sshkey_cert *a, struct sshkey_cert *b) + int + sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) + { +-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) ++#if defined(WITH_OPENSSL) ++ const BIGNUM *rsa_e_a, *rsa_n_a; ++ const BIGNUM *rsa_e_b, *rsa_n_b; ++ const BIGNUM *dsa_p_a, *dsa_q_a, *dsa_g_a, *dsa_pub_key_a; ++ const BIGNUM *dsa_p_b, *dsa_q_b, *dsa_g_b, *dsa_pub_key_b; ++# if defined(OPENSSL_HAS_ECC) + BN_CTX *bnctx; +-#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ ++# endif /* OPENSSL_HAS_ECC */ ++#endif /* WITH_OPENSSL */ + + if (a == NULL || b == NULL || + sshkey_type_plain(a->type) != sshkey_type_plain(b->type)) +@@ -698,16 +662,24 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) + #ifdef WITH_OPENSSL + case KEY_RSA_CERT: + case KEY_RSA: +- return a->rsa != NULL && b->rsa != NULL && +- BN_cmp(a->rsa->e, b->rsa->e) == 0 && +- BN_cmp(a->rsa->n, b->rsa->n) == 0; ++ if (a->rsa == NULL || b->rsa == NULL) ++ return 0; ++ RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL); ++ RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL); ++ return BN_cmp(rsa_e_a, rsa_e_b) == 0 && ++ BN_cmp(rsa_n_a, rsa_n_b) == 0; + case KEY_DSA_CERT: + case KEY_DSA: +- return a->dsa != NULL && b->dsa != NULL && +- BN_cmp(a->dsa->p, b->dsa->p) == 0 && +- BN_cmp(a->dsa->q, b->dsa->q) == 0 && +- BN_cmp(a->dsa->g, b->dsa->g) == 0 && +- BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; ++ if (a->dsa == NULL || b->dsa == NULL) ++ return 0; ++ DSA_get0_pqg(a->dsa, &dsa_p_a, &dsa_q_a, &dsa_g_a); ++ DSA_get0_pqg(b->dsa, &dsa_p_b, &dsa_q_b, &dsa_g_b); ++ DSA_get0_key(a->dsa, &dsa_pub_key_a, NULL); ++ DSA_get0_key(b->dsa, &dsa_pub_key_b, NULL); ++ return BN_cmp(dsa_p_a, dsa_p_b) == 0 && ++ BN_cmp(dsa_q_a, dsa_q_b) == 0 && ++ BN_cmp(dsa_g_a, dsa_g_b) == 0 && ++ BN_cmp(dsa_pub_key_a, dsa_pub_key_b) == 0; + # ifdef OPENSSL_HAS_ECC + case KEY_ECDSA_CERT: + case KEY_ECDSA: +@@ -764,6 +736,9 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, + { + int type, ret = SSH_ERR_INTERNAL_ERROR; + const char *typename; ++#ifdef WITH_OPENSSL ++ const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; ++#endif /* WITH_OPENSSL */ + + if (key == NULL) + return SSH_ERR_INVALID_ARGUMENT; +@@ -796,11 +771,13 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, + case KEY_DSA: + if (key->dsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; ++ DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g); ++ DSA_get0_key(key->dsa, &dsa_pub_key, NULL); + if ((ret = sshbuf_put_cstring(b, typename)) != 0 || +- (ret = sshbuf_put_bignum2(b, key->dsa->p)) != 0 || +- (ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 || +- (ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || +- (ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0) ++ (ret = sshbuf_put_bignum2(b, dsa_p)) != 0 || ++ (ret = sshbuf_put_bignum2(b, dsa_q)) != 0 || ++ (ret = sshbuf_put_bignum2(b, dsa_g)) != 0 || ++ (ret = sshbuf_put_bignum2(b, dsa_pub_key)) != 0) + return ret; + break; + # ifdef OPENSSL_HAS_ECC +@@ -817,9 +794,10 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, + case KEY_RSA: + if (key->rsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; ++ RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL); + if ((ret = sshbuf_put_cstring(b, typename)) != 0 || +- (ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || +- (ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0) ++ (ret = sshbuf_put_bignum2(b, rsa_e)) != 0 || ++ (ret = sshbuf_put_bignum2(b, rsa_n)) != 0) + return ret; + break; + #endif /* WITH_OPENSSL */ +@@ -1767,59 +1745,95 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) + { + struct sshkey *n = NULL; + int ret = SSH_ERR_INTERNAL_ERROR; ++ int r = SSH_ERR_INTERNAL_ERROR; ++#ifdef WITH_OPENSSL ++ const BIGNUM *rsa_n, *rsa_e; ++ BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL; ++ const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; ++ BIGNUM *dsa_p_dup = NULL, *dsa_q_dup = NULL, *dsa_g_dup = NULL; ++ BIGNUM *dsa_pub_key_dup = NULL; ++#endif /* WITH_OPENSSL */ + + *pkp = NULL; + switch (k->type) { + #ifdef WITH_OPENSSL + case KEY_DSA: + case KEY_DSA_CERT: +- if ((n = sshkey_new(k->type)) == NULL) +- return SSH_ERR_ALLOC_FAIL; +- if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) || +- (BN_copy(n->dsa->q, k->dsa->q) == NULL) || +- (BN_copy(n->dsa->g, k->dsa->g) == NULL) || +- (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) { +- sshkey_free(n); +- return SSH_ERR_ALLOC_FAIL; ++ if ((n = sshkey_new(k->type)) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g); ++ DSA_get0_key(k->dsa, &dsa_pub_key, NULL); ++ if ((dsa_p_dup = BN_dup(dsa_p)) == NULL || ++ (dsa_q_dup = BN_dup(dsa_q)) == NULL || ++ (dsa_g_dup = BN_dup(dsa_g)) == NULL || ++ (dsa_pub_key_dup = BN_dup(dsa_pub_key)) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; + } ++ if (!DSA_set0_pqg(n->dsa, dsa_p_dup, dsa_q_dup, dsa_g_dup)) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ dsa_p_dup = dsa_q_dup = dsa_g_dup = NULL; /* transferred */ ++ if (!DSA_set0_key(n->dsa, dsa_pub_key_dup, NULL)) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ dsa_pub_key_dup = NULL; /* transferred */ ++ + break; + # ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + case KEY_ECDSA_CERT: +- if ((n = sshkey_new(k->type)) == NULL) +- return SSH_ERR_ALLOC_FAIL; ++ if ((n = sshkey_new(k->type)) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + n->ecdsa_nid = k->ecdsa_nid; + n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); + if (n->ecdsa == NULL) { +- sshkey_free(n); +- return SSH_ERR_ALLOC_FAIL; ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; + } + if (EC_KEY_set_public_key(n->ecdsa, + EC_KEY_get0_public_key(k->ecdsa)) != 1) { +- sshkey_free(n); +- return SSH_ERR_LIBCRYPTO_ERROR; ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; + } + break; + # endif /* OPENSSL_HAS_ECC */ + case KEY_RSA: + case KEY_RSA_CERT: +- if ((n = sshkey_new(k->type)) == NULL) +- return SSH_ERR_ALLOC_FAIL; +- if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) || +- (BN_copy(n->rsa->e, k->rsa->e) == NULL)) { +- sshkey_free(n); +- return SSH_ERR_ALLOC_FAIL; ++ if ((n = sshkey_new(k->type)) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; + } ++ RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL); ++ if ((rsa_n_dup = BN_dup(rsa_n)) == NULL || ++ (rsa_e_dup = BN_dup(rsa_e)) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if (!RSA_set0_key(n->rsa, rsa_n_dup, rsa_e_dup, NULL)) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ rsa_n_dup = rsa_e_dup = NULL; /* transferred */ + break; + #endif /* WITH_OPENSSL */ + case KEY_ED25519: + case KEY_ED25519_CERT: +- if ((n = sshkey_new(k->type)) == NULL) +- return SSH_ERR_ALLOC_FAIL; ++ if ((n = sshkey_new(k->type)) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + if (k->ed25519_pk != NULL) { + if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { +- sshkey_free(n); +- return SSH_ERR_ALLOC_FAIL; ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; + } + memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); + } +@@ -1827,37 +1841,46 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) + #ifdef WITH_XMSS + case KEY_XMSS: + case KEY_XMSS_CERT: +- if ((n = sshkey_new(k->type)) == NULL) +- return SSH_ERR_ALLOC_FAIL; +- if ((ret = sshkey_xmss_init(n, k->xmss_name)) != 0) { +- sshkey_free(n); +- return ret; ++ if ((n = sshkey_new(k->type)) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; + } ++ if ((r = sshkey_xmss_init(n, k->xmss_name)) != 0) ++ goto out; + if (k->xmss_pk != NULL) { + size_t pklen = sshkey_xmss_pklen(k); + if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) { +- sshkey_free(n); +- return SSH_ERR_INTERNAL_ERROR; ++ r = SSH_ERR_INTERNAL_ERROR; ++ goto out; + } + if ((n->xmss_pk = malloc(pklen)) == NULL) { +- sshkey_free(n); +- return SSH_ERR_ALLOC_FAIL; ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; + } + memcpy(n->xmss_pk, k->xmss_pk, pklen); + } + break; + #endif /* WITH_XMSS */ + default: +- return SSH_ERR_KEY_TYPE_UNKNOWN; +- } +- if (sshkey_is_cert(k)) { +- if ((ret = sshkey_cert_copy(k, n)) != 0) { +- sshkey_free(n); +- return ret; +- } ++ r = SSH_ERR_KEY_TYPE_UNKNOWN; ++ goto out; + } ++ if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0) ++ goto out; ++ /* success */ + *pkp = n; +- return 0; ++ n = NULL; ++ r = 0; ++ out: ++ sshkey_free(n); ++ BN_clear_free(rsa_n_dup); ++ BN_clear_free(rsa_e_dup); ++ BN_clear_free(dsa_p_dup); ++ BN_clear_free(dsa_q_dup); ++ BN_clear_free(dsa_g_dup); ++ BN_clear_free(dsa_pub_key_dup); ++ ++ return r; + } + + static int +@@ -1985,6 +2008,17 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) + return ret; + } + ++static int ++check_rsa_length(const RSA *rsa) ++{ ++ const BIGNUM *rsa_n; ++ ++ RSA_get0_key(rsa, &rsa_n, NULL, NULL); ++ if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) ++ return SSH_ERR_KEY_LENGTH; ++ return 0; ++} ++ + static int + sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, + int allow_cert) +@@ -1995,9 +2029,13 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, + size_t len; + u_char *pk = NULL; + struct sshbuf *copy; +-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) ++#if defined(WITH_OPENSSL) ++ BIGNUM *rsa_n = NULL, *rsa_e = NULL; ++ BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL; ++# if defined(OPENSSL_HAS_ECC) + EC_POINT *q = NULL; +-#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ ++# endif /* OPENSSL_HAS_ECC */ ++#endif /* WITH_OPENSSL */ + + #ifdef DEBUG_PK /* XXX */ + sshbuf_dump(b, stderr); +@@ -2032,15 +2070,23 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if (sshbuf_get_bignum2(b, key->rsa->e) != 0 || +- sshbuf_get_bignum2(b, key->rsa->n) != 0) { ++ if ((rsa_e = BN_new()) == NULL || ++ (rsa_n = BN_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if (sshbuf_get_bignum2(b, rsa_e) != 0 || ++ sshbuf_get_bignum2(b, rsa_n) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } +- if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { +- ret = SSH_ERR_KEY_LENGTH; ++ 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 = check_rsa_length(key->rsa)) != 0) ++ goto out; + #ifdef DEBUG_PK + RSA_print_fp(stderr, key->rsa, 8); + #endif +@@ -2057,13 +2103,30 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if (sshbuf_get_bignum2(b, key->dsa->p) != 0 || +- sshbuf_get_bignum2(b, key->dsa->q) != 0 || +- sshbuf_get_bignum2(b, key->dsa->g) != 0 || +- sshbuf_get_bignum2(b, key->dsa->pub_key) != 0) { ++ if ((dsa_p = BN_new()) == NULL || ++ (dsa_q = BN_new()) == NULL || ++ (dsa_g = BN_new()) == NULL || ++ (dsa_pub_key = BN_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if (sshbuf_get_bignum2(b, dsa_p) != 0 || ++ sshbuf_get_bignum2(b, dsa_q) != 0 || ++ sshbuf_get_bignum2(b, dsa_g) != 0 || ++ sshbuf_get_bignum2(b, dsa_pub_key) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } ++ if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ dsa_p = dsa_q = dsa_g = NULL; /* transferred */ ++ if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ dsa_pub_key = NULL; /* transferred */ + #ifdef DEBUG_PK + DSA_print_fp(stderr, key->dsa, 8); + #endif +@@ -2197,9 +2260,17 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, + free(ktype); + free(curve); + free(pk); +-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) ++#if defined(WITH_OPENSSL) ++ BN_clear_free(rsa_n); ++ BN_clear_free(rsa_e); ++ BN_clear_free(dsa_p); ++ BN_clear_free(dsa_q); ++ BN_clear_free(dsa_g); ++ BN_clear_free(dsa_pub_key); ++# if defined(OPENSSL_HAS_ECC) + EC_POINT_free(q); +-#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ ++# endif /* OPENSSL_HAS_ECC */ ++#endif /* WITH_OPENSSL */ + return ret; + } + +@@ -2401,120 +2472,6 @@ sshkey_verify(const struct sshkey *key, + } + } + +-/* Converts a private to a public key */ +-int +-sshkey_demote(const struct sshkey *k, struct sshkey **dkp) +-{ +- struct sshkey *pk; +- int ret = SSH_ERR_INTERNAL_ERROR; +- +- *dkp = NULL; +- if ((pk = calloc(1, sizeof(*pk))) == NULL) +- return SSH_ERR_ALLOC_FAIL; +- pk->type = k->type; +- pk->flags = k->flags; +- pk->ecdsa_nid = k->ecdsa_nid; +- pk->dsa = NULL; +- pk->ecdsa = NULL; +- pk->rsa = NULL; +- pk->ed25519_pk = NULL; +- pk->ed25519_sk = NULL; +- pk->xmss_pk = NULL; +- pk->xmss_sk = NULL; +- +- switch (k->type) { +-#ifdef WITH_OPENSSL +- case KEY_RSA_CERT: +- if ((ret = sshkey_cert_copy(k, pk)) != 0) +- goto fail; +- /* FALLTHROUGH */ +- case KEY_RSA: +- if ((pk->rsa = RSA_new()) == NULL || +- (pk->rsa->e = BN_dup(k->rsa->e)) == NULL || +- (pk->rsa->n = BN_dup(k->rsa->n)) == NULL) { +- ret = SSH_ERR_ALLOC_FAIL; +- goto fail; +- } +- break; +- case KEY_DSA_CERT: +- if ((ret = sshkey_cert_copy(k, pk)) != 0) +- goto fail; +- /* FALLTHROUGH */ +- case KEY_DSA: +- if ((pk->dsa = DSA_new()) == NULL || +- (pk->dsa->p = BN_dup(k->dsa->p)) == NULL || +- (pk->dsa->q = BN_dup(k->dsa->q)) == NULL || +- (pk->dsa->g = BN_dup(k->dsa->g)) == NULL || +- (pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) { +- ret = SSH_ERR_ALLOC_FAIL; +- goto fail; +- } +- break; +- case KEY_ECDSA_CERT: +- if ((ret = sshkey_cert_copy(k, pk)) != 0) +- goto fail; +- /* FALLTHROUGH */ +-# ifdef OPENSSL_HAS_ECC +- case KEY_ECDSA: +- pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid); +- if (pk->ecdsa == NULL) { +- ret = SSH_ERR_ALLOC_FAIL; +- goto fail; +- } +- if (EC_KEY_set_public_key(pk->ecdsa, +- EC_KEY_get0_public_key(k->ecdsa)) != 1) { +- ret = SSH_ERR_LIBCRYPTO_ERROR; +- goto fail; +- } +- break; +-# endif /* OPENSSL_HAS_ECC */ +-#endif /* WITH_OPENSSL */ +- case KEY_ED25519_CERT: +- if ((ret = sshkey_cert_copy(k, pk)) != 0) +- goto fail; +- /* FALLTHROUGH */ +- case KEY_ED25519: +- if (k->ed25519_pk != NULL) { +- if ((pk->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { +- ret = SSH_ERR_ALLOC_FAIL; +- goto fail; +- } +- memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); +- } +- break; +-#ifdef WITH_XMSS +- case KEY_XMSS_CERT: +- if ((ret = sshkey_cert_copy(k, pk)) != 0) +- goto fail; +- /* FALLTHROUGH */ +- case KEY_XMSS: +- if ((ret = sshkey_xmss_init(pk, k->xmss_name)) != 0) +- goto fail; +- if (k->xmss_pk != NULL) { +- size_t pklen = sshkey_xmss_pklen(k); +- +- if (pklen == 0 || sshkey_xmss_pklen(pk) != pklen) { +- ret = SSH_ERR_INTERNAL_ERROR; +- goto fail; +- } +- if ((pk->xmss_pk = malloc(pklen)) == NULL) { +- ret = SSH_ERR_ALLOC_FAIL; +- goto fail; +- } +- memcpy(pk->xmss_pk, k->xmss_pk, pklen); +- } +- break; +-#endif /* WITH_XMSS */ +- default: +- ret = SSH_ERR_KEY_TYPE_UNKNOWN; +- fail: +- sshkey_free(pk); +- return ret; +- } +- *dkp = pk; +- return 0; +-} +- + /* Convert a plain key to their _CERT equivalent */ + int + sshkey_to_certified(struct sshkey *k) +@@ -2573,6 +2530,9 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, + int ret = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *cert = NULL; + char *sigtype = NULL; ++#ifdef WITH_OPENSSL ++ const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; ++#endif /* WITH_OPENSSL */ + + if (k == NULL || k->cert == NULL || + k->cert->certblob == NULL || ca == NULL) +@@ -2609,10 +2569,12 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, + switch (k->type) { + #ifdef WITH_OPENSSL + case KEY_DSA_CERT: +- if ((ret = sshbuf_put_bignum2(cert, k->dsa->p)) != 0 || +- (ret = sshbuf_put_bignum2(cert, k->dsa->q)) != 0 || +- (ret = sshbuf_put_bignum2(cert, k->dsa->g)) != 0 || +- (ret = sshbuf_put_bignum2(cert, k->dsa->pub_key)) != 0) ++ DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g); ++ DSA_get0_key(k->dsa, &dsa_pub_key, NULL); ++ if ((ret = sshbuf_put_bignum2(cert, dsa_p)) != 0 || ++ (ret = sshbuf_put_bignum2(cert, dsa_q)) != 0 || ++ (ret = sshbuf_put_bignum2(cert, dsa_g)) != 0 || ++ (ret = sshbuf_put_bignum2(cert, dsa_pub_key)) != 0) + goto out; + break; + # ifdef OPENSSL_HAS_ECC +@@ -2626,8 +2588,9 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, + break; + # endif /* OPENSSL_HAS_ECC */ + case KEY_RSA_CERT: +- if ((ret = sshbuf_put_bignum2(cert, k->rsa->e)) != 0 || +- (ret = sshbuf_put_bignum2(cert, k->rsa->n)) != 0) ++ RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL); ++ if ((ret = sshbuf_put_bignum2(cert, rsa_e)) != 0 || ++ (ret = sshbuf_put_bignum2(cert, rsa_n)) != 0) + goto out; + break; + #endif /* WITH_OPENSSL */ +@@ -2820,18 +2783,25 @@ sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b, + enum sshkey_serialize_rep opts) + { + int r = SSH_ERR_INTERNAL_ERROR; ++#ifdef WITH_OPENSSL ++ const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q; ++ const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key, *dsa_priv_key; ++#endif /* WITH_OPENSSL */ + + if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0) + goto out; + switch (key->type) { + #ifdef WITH_OPENSSL + case KEY_RSA: +- if ((r = sshbuf_put_bignum2(b, key->rsa->n)) != 0 || +- (r = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || +- (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 || +- (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || +- (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || +- (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) ++ RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d); ++ RSA_get0_factors(key->rsa, &rsa_p, &rsa_q); ++ RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp); ++ if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 || ++ (r = sshbuf_put_bignum2(b, rsa_e)) != 0 || ++ (r = sshbuf_put_bignum2(b, rsa_d)) != 0 || ++ (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 || ++ (r = sshbuf_put_bignum2(b, rsa_p)) != 0 || ++ (r = sshbuf_put_bignum2(b, rsa_q)) != 0) + goto out; + break; + case KEY_RSA_CERT: +@@ -2839,19 +2809,24 @@ sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b, + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } ++ RSA_get0_key(key->rsa, NULL, NULL, &rsa_d); ++ RSA_get0_factors(key->rsa, &rsa_p, &rsa_q); ++ RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp); + if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || +- (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 || +- (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || +- (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || +- (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) ++ (r = sshbuf_put_bignum2(b, rsa_d)) != 0 || ++ (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 || ++ (r = sshbuf_put_bignum2(b, rsa_p)) != 0 || ++ (r = sshbuf_put_bignum2(b, rsa_q)) != 0) + goto out; + break; + case KEY_DSA: +- if ((r = sshbuf_put_bignum2(b, key->dsa->p)) != 0 || +- (r = sshbuf_put_bignum2(b, key->dsa->q)) != 0 || +- (r = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || +- (r = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0 || +- (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0) ++ DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g); ++ DSA_get0_key(key->dsa, &dsa_pub_key, &dsa_priv_key); ++ if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 || ++ (r = sshbuf_put_bignum2(b, dsa_q)) != 0 || ++ (r = sshbuf_put_bignum2(b, dsa_g)) != 0 || ++ (r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0 || ++ (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0) + goto out; + break; + case KEY_DSA_CERT: +@@ -2859,8 +2834,9 @@ sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b, + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } ++ DSA_get0_key(key->dsa, NULL, &dsa_priv_key); + if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || +- (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0) ++ (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0) + goto out; + break; + # ifdef OPENSSL_HAS_ECC +@@ -2961,6 +2937,10 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + u_char *xmss_pk = NULL, *xmss_sk = NULL; + #ifdef WITH_OPENSSL + BIGNUM *exponent = NULL; ++ BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; ++ BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL; ++ BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; ++ BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; + #endif /* WITH_OPENSSL */ + + if (kp != NULL) +@@ -2975,18 +2955,44 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((r = sshbuf_get_bignum2(buf, k->dsa->p)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->dsa->q)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->dsa->g)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->dsa->pub_key)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) ++ if ((dsa_p = BN_new()) == NULL || ++ (dsa_q = BN_new()) == NULL || ++ (dsa_g = BN_new()) == NULL || ++ (dsa_pub_key = BN_new()) == NULL || ++ (dsa_priv_key = BN_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if ((r = sshbuf_get_bignum2(buf, dsa_p)) != 0 || ++ (r = sshbuf_get_bignum2(buf, dsa_q)) != 0 || ++ (r = sshbuf_get_bignum2(buf, dsa_g)) != 0 || ++ (r = sshbuf_get_bignum2(buf, dsa_pub_key)) != 0 || ++ (r = sshbuf_get_bignum2(buf, dsa_priv_key)) != 0) + goto out; ++ if (!DSA_set0_pqg(k->dsa, dsa_p, dsa_q, dsa_g)) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ dsa_p = dsa_q = dsa_g = NULL; /* transferred */ ++ if (!DSA_set0_key(k->dsa, dsa_pub_key, dsa_priv_key)) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ dsa_pub_key = dsa_priv_key = NULL; /* transferred */ + break; + case KEY_DSA_CERT: ++ if ((dsa_priv_key = BN_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + if ((r = sshkey_froms(buf, &k)) != 0 || +- (r = sshkey_add_private(k)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) ++ (r = sshbuf_get_bignum2(buf, dsa_priv_key)) != 0) ++ goto out; ++ if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; ++ } ++ dsa_priv_key = NULL; /* transferred */ + break; + # ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: +@@ -3027,7 +3033,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + goto out; + } + if ((r = sshkey_froms(buf, &k)) != 0 || +- (r = sshkey_add_private(k)) != 0 || + (r = sshbuf_get_bignum2(buf, exponent)) != 0) + goto out; + if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { +@@ -3045,32 +3050,65 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((r = sshbuf_get_bignum2(buf, k->rsa->n)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->rsa->e)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || +- (r = ssh_rsa_generate_additional_parameters(k)) != 0) ++ if ((rsa_n = BN_new()) == NULL || ++ (rsa_e = BN_new()) == NULL || ++ (rsa_d = BN_new()) == NULL || ++ (rsa_iqmp = BN_new()) == NULL || ++ (rsa_p = BN_new()) == NULL || ++ (rsa_q = BN_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if ((r = sshbuf_get_bignum2(buf, rsa_n)) != 0 || ++ (r = sshbuf_get_bignum2(buf, rsa_e)) != 0 || ++ (r = sshbuf_get_bignum2(buf, rsa_d)) != 0 || ++ (r = sshbuf_get_bignum2(buf, rsa_iqmp)) != 0 || ++ (r = sshbuf_get_bignum2(buf, rsa_p)) != 0 || ++ (r = sshbuf_get_bignum2(buf, rsa_q)) != 0) + goto out; +- if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { +- r = SSH_ERR_KEY_LENGTH; ++ if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, rsa_d)) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ rsa_n = rsa_e = rsa_d = NULL; /* transferred */ ++ if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } ++ rsa_p = rsa_q = NULL; /* transferred */ ++ if ((r = check_rsa_length(k->rsa)) != 0) ++ goto out; ++ if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0) ++ goto out; + break; + case KEY_RSA_CERT: ++ if ((rsa_d = BN_new()) == NULL || ++ (rsa_iqmp = BN_new()) == NULL || ++ (rsa_p = BN_new()) == NULL || ++ (rsa_q = BN_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + if ((r = sshkey_froms(buf, &k)) != 0 || +- (r = sshkey_add_private(k)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || +- (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || +- (r = ssh_rsa_generate_additional_parameters(k)) != 0) ++ (r = sshbuf_get_bignum2(buf, rsa_d)) != 0 || ++ (r = sshbuf_get_bignum2(buf, rsa_iqmp)) != 0 || ++ (r = sshbuf_get_bignum2(buf, rsa_p)) != 0 || ++ (r = sshbuf_get_bignum2(buf, rsa_q)) != 0) ++ goto out; ++ if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; +- if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { +- r = SSH_ERR_KEY_LENGTH; ++ } ++ rsa_d = NULL; /* transferred */ ++ if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } ++ rsa_p = rsa_q = NULL; /* transferred */ ++ if ((r = check_rsa_length(k->rsa)) != 0) ++ goto out; ++ if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0) ++ goto out; + break; + #endif /* WITH_OPENSSL */ + case KEY_ED25519: +@@ -3091,7 +3129,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + break; + case KEY_ED25519_CERT: + if ((r = sshkey_froms(buf, &k)) != 0 || +- (r = sshkey_add_private(k)) != 0 || + (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || + (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) + goto out; +@@ -3128,7 +3165,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + break; + case KEY_XMSS_CERT: + if ((r = sshkey_froms(buf, &k)) != 0 || +- (r = sshkey_add_private(k)) != 0 || + (r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 || + (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 || + (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0) +@@ -3177,6 +3213,17 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + free(curve); + #ifdef WITH_OPENSSL + BN_clear_free(exponent); ++ BN_clear_free(dsa_p); ++ BN_clear_free(dsa_q); ++ BN_clear_free(dsa_g); ++ BN_clear_free(dsa_pub_key); ++ BN_clear_free(dsa_priv_key); ++ BN_clear_free(rsa_n); ++ BN_clear_free(rsa_e); ++ BN_clear_free(rsa_d); ++ BN_clear_free(rsa_p); ++ BN_clear_free(rsa_q); ++ BN_clear_free(rsa_iqmp); + #endif /* WITH_OPENSSL */ + sshkey_free(k); + freezero(ed25519_pk, pklen); +@@ -3831,7 +3878,9 @@ translate_libcrypto_error(unsigned long pem_err) + switch (pem_reason) { + case EVP_R_BAD_DECRYPT: + return SSH_ERR_KEY_WRONG_PASSPHRASE; ++#ifdef EVP_R_BN_DECODE_ERROR + case EVP_R_BN_DECODE_ERROR: ++#endif + case EVP_R_DECODE_ERROR: + #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR + case EVP_R_PRIVATE_KEY_DECODE_ERROR: +@@ -3896,7 +3945,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, + r = convert_libcrypto_error(); + goto out; + } +- if (pk->type == EVP_PKEY_RSA && ++ if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA && + (type == KEY_UNSPEC || type == KEY_RSA)) { + if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; +@@ -3911,11 +3960,9 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- if (BN_num_bits(prv->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { +- r = SSH_ERR_KEY_LENGTH; ++ if ((r = check_rsa_length(prv->rsa)) != 0) + goto out; +- } +- } else if (pk->type == EVP_PKEY_DSA && ++ } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA && + (type == KEY_UNSPEC || type == KEY_DSA)) { + if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; +@@ -3927,7 +3974,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, + DSA_print_fp(stderr, prv->dsa, 8); + #endif + #ifdef OPENSSL_HAS_ECC +- } else if (pk->type == EVP_PKEY_EC && ++ } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC && + (type == KEY_UNSPEC || type == KEY_ECDSA)) { + if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; +diff --git a/sshkey.h b/sshkey.h +index 5a22a66f..4147ad92 100644 +--- a/sshkey.h ++++ b/sshkey.h +@@ -39,6 +39,7 @@ + # define EC_POINT void + # endif /* OPENSSL_HAS_ECC */ + #else /* WITH_OPENSSL */ ++# define BIGNUM void + # define RSA void + # define DSA void + # define EC_KEY void +@@ -127,10 +128,8 @@ struct sshkey { + #define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES + + struct sshkey *sshkey_new(int); +-int sshkey_add_private(struct sshkey *); +-struct sshkey *sshkey_new_private(int); ++struct sshkey *sshkey_new_private(int); /* XXX garbage collect */ + void sshkey_free(struct sshkey *); +-int sshkey_demote(const struct sshkey *, struct sshkey **); + int sshkey_equal_public(const struct sshkey *, + const struct sshkey *); + int sshkey_equal(const struct sshkey *, const struct sshkey *); +@@ -220,7 +219,7 @@ int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, + const char *passphrase, struct sshkey **keyp, char **commentp); + + /* XXX should be internal, but used by ssh-keygen */ +-int ssh_rsa_generate_additional_parameters(struct sshkey *); ++int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *); + + /* stateful keys (e.g. XMSS) */ + #ifdef NO_ATTRIBUTE_ON_PROTOTYPE_ARGS + +commit 86112951d63d48839f035b5795be62635a463f99 +Author: Damien Miller +Date: Thu Sep 13 12:12:42 2018 +1000 + + forgot to stage these test files in commit d70d061 + +diff --git a/regress/unittests/sshkey/mktestdata.sh b/regress/unittests/sshkey/mktestdata.sh +index 8047bc62..93da34c6 100755 +--- a/regress/unittests/sshkey/mktestdata.sh ++++ b/regress/unittests/sshkey/mktestdata.sh +@@ -1,5 +1,5 @@ + #!/bin/sh +-# $OpenBSD: mktestdata.sh,v 1.6 2017/04/30 23:33:48 djm Exp $ ++# $OpenBSD: mktestdata.sh,v 1.7 2018/09/12 01:36:45 djm Exp $ + + PW=mekmitasdigoat + +@@ -128,6 +128,18 @@ ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 4 ed25519_1.pub + ++# Make a few RSA variant signature too. ++cp rsa_1 rsa_1_sha1 ++cp rsa_1 rsa_1_sha512 ++cp rsa_1.pub rsa_1_sha1.pub ++cp rsa_1.pub rsa_1_sha512.pub ++ssh-keygen -s rsa_2 -I hugo -n user1,user2 -t ssh-rsa \ ++ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ ++ -V 19990101:20110101 -z 1 rsa_1_sha1.pub ++ssh-keygen -s rsa_2 -I hugo -n user1,user2 -t rsa-sha2-512 \ ++ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ ++ -V 19990101:20110101 -z 1 rsa_1_sha512.pub ++ + ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ + -V 19990101:20110101 -z 5 rsa_1.pub + ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ +diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c +index 99b7e21c..0636e84b 100644 +--- a/regress/unittests/sshkey/test_file.c ++++ b/regress/unittests/sshkey/test_file.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: test_file.c,v 1.6 2017/04/30 23:33:48 djm Exp $ */ ++/* $OpenBSD: test_file.c,v 1.7 2018/09/12 01:36:45 djm Exp $ */ + /* + * Regress test for sshkey.h key management API + * +@@ -105,6 +105,24 @@ sshkey_file_tests(void) + sshkey_free(k2); + TEST_DONE(); + ++ TEST_START("load RSA cert with SHA1 signature"); ++ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha1"), &k2), 0); ++ ASSERT_PTR_NE(k2, NULL); ++ ASSERT_INT_EQ(k2->type, KEY_RSA_CERT); ++ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); ++ ASSERT_STRING_EQ(k2->cert->signature_type, "ssh-rsa"); ++ sshkey_free(k2); ++ TEST_DONE(); ++ ++ TEST_START("load RSA cert with SHA512 signature"); ++ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha512"), &k2), 0); ++ ASSERT_PTR_NE(k2, NULL); ++ ASSERT_INT_EQ(k2->type, KEY_RSA_CERT); ++ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); ++ ASSERT_STRING_EQ(k2->cert->signature_type, "rsa-sha2-512"); ++ sshkey_free(k2); ++ TEST_DONE(); ++ + TEST_START("load RSA cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + +commit 48f54b9d12c1c79fba333bc86d455d8f4cda8cfc +Author: Damien Miller +Date: Thu Sep 13 12:13:50 2018 +1000 + + adapt -portable to OpenSSL 1.1x API + + Polyfill missing API with replacement functions extracted from LibreSSL + +diff --git a/auth-pam.c b/auth-pam.c +index 8c013836..1dec53e9 100644 +--- a/auth-pam.c ++++ b/auth-pam.c +@@ -128,6 +128,10 @@ extern u_int utmp_len; + typedef pthread_t sp_pthread_t; + #else + typedef pid_t sp_pthread_t; ++#define pthread_exit fake_pthread_exit ++#define pthread_create fake_pthread_create ++#define pthread_cancel fake_pthread_cancel ++#define pthread_join fake_pthread_join + #endif + + struct pam_ctxt { +diff --git a/cipher.c b/cipher.c +index df43826e..12c59888 100644 +--- a/cipher.c ++++ b/cipher.c +@@ -525,41 +525,3 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv, size_t len) + #endif + return 0; + } +- +-#ifdef WITH_OPENSSL +-#define EVP_X_STATE(evp) (evp)->cipher_data +-#define EVP_X_STATE_LEN(evp) (evp)->cipher->ctx_size +-#endif +- +-int +-cipher_get_keycontext(const struct sshcipher_ctx *cc, u_char *dat) +-{ +-#if defined(WITH_OPENSSL) && !defined(OPENSSL_NO_RC4) +- const struct sshcipher *c = cc->cipher; +- int plen = 0; +- +- if (c->evptype == EVP_rc4) { +- plen = EVP_X_STATE_LEN(cc->evp); +- if (dat == NULL) +- return (plen); +- memcpy(dat, EVP_X_STATE(cc->evp), plen); +- } +- return (plen); +-#else +- return 0; +-#endif +-} +- +-void +-cipher_set_keycontext(struct sshcipher_ctx *cc, const u_char *dat) +-{ +-#if defined(WITH_OPENSSL) && !defined(OPENSSL_NO_RC4) +- const struct sshcipher *c = cc->cipher; +- int plen; +- +- if (c->evptype == EVP_rc4) { +- plen = EVP_X_STATE_LEN(cc->evp); +- memcpy(EVP_X_STATE(cc->evp), dat, plen); +- } +-#endif +-} +diff --git a/configure.ac b/configure.ac +index 83e53075..c0e120fe 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2602,9 +2602,10 @@ if test "x$openssl" = "xyes" ; then + AC_MSG_ERROR([OpenSSL >= 1.0.1 required (have "$ssl_library_ver")]) + ;; + 100*) ;; # 1.0.x ++ 101*) ;; # 1.1.x + 200*) ;; # LibreSSL + *) +- AC_MSG_ERROR([OpenSSL >= 1.1.0 is not yet supported (have "$ssl_library_ver")]) ++ AC_MSG_ERROR([OpenSSL > 1.1.x is not yet supported (have "$ssl_library_ver")]) + ;; + esac + AC_MSG_RESULT([$ssl_library_ver]) +@@ -2777,6 +2778,115 @@ if test "x$openssl" = "xyes" ; then + [AC_DEFINE([HAVE_EVP_CIPHER_CTX_CTRL], [1], + [Define if libcrypto has EVP_CIPHER_CTX_ctrl])]) + ++ # LibreSSL/OpenSSL 1.1x API ++ AC_SEARCH_LIBS([DH_get0_key], [crypto], ++ [AC_DEFINE([HAVE_DH_GET0_KEY], [1], ++ [Define if libcrypto has DH_get0_key])]) ++ AC_SEARCH_LIBS([DH_get0_pqg], [crypto], ++ [AC_DEFINE([HAVE_DH_GET0_PQG], [1], ++ [Define if libcrypto has DH_get0_pqg])]) ++ AC_SEARCH_LIBS([DH_set0_key], [crypto], ++ [AC_DEFINE([HAVE_DH_SET0_KEY], [1], ++ [Define if libcrypto has DH_set0_key])]) ++ AC_SEARCH_LIBS([DH_set_length], [crypto], ++ [AC_DEFINE([HAVE_DH_SET_LENGTH], [1], ++ [Define if libcrypto has DH_set_length])]) ++ AC_SEARCH_LIBS([DH_set0_pqg], [crypto], ++ [AC_DEFINE([HAVE_DH_SET0_PQG], [1], ++ [Define if libcrypto has DH_set0_pqg])]) ++ ++ AC_SEARCH_LIBS([DSA_get0_key], [crypto], ++ [AC_DEFINE([HAVE_DSA_GET0_KEY], [1], ++ [Define if libcrypto has DSA_get0_key])]) ++ AC_SEARCH_LIBS([DSA_get0_pqg], [crypto], ++ [AC_DEFINE([HAVE_DSA_GET0_PQG], [1], ++ [Define if libcrypto has DSA_get0_pqg])]) ++ AC_SEARCH_LIBS([DSA_set0_key], [crypto], ++ [AC_DEFINE([HAVE_DSA_SET0_KEY], [1], ++ [Define if libcrypto has DSA_set0_key])]) ++ AC_SEARCH_LIBS([DSA_set0_pqg], [crypto], ++ [AC_DEFINE([HAVE_DSA_SET0_PQG], [1], ++ [Define if libcrypto has DSA_set0_pqg])]) ++ ++ AC_SEARCH_LIBS([DSA_SIG_get0], [crypto], ++ [AC_DEFINE([HAVE_DSA_SIG_GET0], [1], ++ [Define if libcrypto has DSA_SIG_get0])]) ++ AC_SEARCH_LIBS([DSA_SIG_set0], [crypto], ++ [AC_DEFINE([HAVE_DSA_SIG_SET0], [1], ++ [Define if libcrypto has DSA_SIG_set0])]) ++ ++ AC_SEARCH_LIBS([ECDSA_SIG_get0], [crypto], ++ [AC_DEFINE([HAVE_ECDSA_SIG_GET0], [1], ++ [Define if libcrypto has ECDSA_SIG_get0])]) ++ AC_SEARCH_LIBS([ECDSA_SIG_set0], [crypto], ++ [AC_DEFINE([HAVE_ECDSA_SIG_SET0], [1], ++ [Define if libcrypto has ECDSA_SIG_set0])]) ++ ++ AC_SEARCH_LIBS([EVP_CIPHER_CTX_iv], [crypto], ++ [AC_DEFINE([HAVE_EVP_CIPHER_CTX_IV], [1], ++ [Define if libcrypto has EVP_CIPHER_CTX_iv])]) ++ AC_SEARCH_LIBS([EVP_CIPHER_CTX_iv_noconst], [crypto], ++ [AC_DEFINE([HAVE_EVP_CIPHER_CTX_IV_NOCONST], [1], ++ [Define if libcrypto has EVP_CIPHER_CTX_iv_noconst])]) ++ AC_SEARCH_LIBS([EVP_CIPHER_CTX_get_iv], [crypto], ++ [AC_DEFINE([HAVE_EVP_CIPHER_CTX_GET_IV], [1], ++ [Define if libcrypto has EVP_CIPHER_CTX_get_iv])]) ++ AC_SEARCH_LIBS([EVP_CIPHER_CTX_set_iv], [crypto], ++ [AC_DEFINE([HAVE_EVP_CIPHER_CTX_GET_IV], [1], ++ [Define if libcrypto has EVP_CIPHER_CTX_set_iv])]) ++ ++ AC_SEARCH_LIBS([RSA_get0_crt_params], [crypto], ++ [AC_DEFINE([HAVE_RSA_GET0_CRT_PARAMS], [1], ++ [Define if libcrypto has RSA_get0_crt_params])]) ++ AC_SEARCH_LIBS([RSA_get0_factors], [crypto], ++ [AC_DEFINE([HAVE_RSA_GET0_FACTORS], [1], ++ [Define if libcrypto has RSA_get0_factors])]) ++ AC_SEARCH_LIBS([RSA_get0_key], [crypto], ++ [AC_DEFINE([HAVE_RSA_GET0_KEY], [1], ++ [Define if libcrypto has RSA_get0_key])]) ++ AC_SEARCH_LIBS([RSA_set0_crt_params], [crypto], ++ [AC_DEFINE([HAVE_RSA_SET0_CRT_PARAMS], [1], ++ [Define if libcrypto has RSA_get0_srt_params])]) ++ AC_SEARCH_LIBS([RSA_set0_factors], [crypto], ++ [AC_DEFINE([HAVE_RSA_SET0_FACTORS], [1], ++ [Define if libcrypto has RSA_set0_factors])]) ++ AC_SEARCH_LIBS([RSA_set0_key], [crypto], ++ [AC_DEFINE([HAVE_RSA_SET0_KEY], [1], ++ [Define if libcrypto has RSA_set0_key])]) ++ ++ AC_SEARCH_LIBS([RSA_meth_free], [crypto], ++ [AC_DEFINE([HAVE_RSA_METH_FREE], [1], ++ [Define if libcrypto has RSA_meth_free])]) ++ AC_SEARCH_LIBS([RSA_meth_dup], [crypto], ++ [AC_DEFINE([HAVE_RSA_METH_DUP], [1], ++ [Define if libcrypto has RSA_meth_dup])]) ++ AC_SEARCH_LIBS([RSA_meth_set1_name], [crypto], ++ [AC_DEFINE([HAVE_RSA_METH_SET1_NAME], [1], ++ [Define if libcrypto has RSA_meth_set1_name])]) ++ AC_SEARCH_LIBS([RSA_meth_get_finish], [crypto], ++ [AC_DEFINE([HAVE_RSA_METH_GET_FINISH], [1], ++ [Define if libcrypto has RSA_meth_get_finish])]) ++ AC_SEARCH_LIBS([RSA_meth_set_priv_enc], [crypto], ++ [AC_DEFINE([HAVE_RSA_METH_SET_PRIV_ENC], [1], ++ [Define if libcrypto has RSA_meth_set_priv_enc])]) ++ AC_SEARCH_LIBS([RSA_meth_set_priv_dec], [crypto], ++ [AC_DEFINE([HAVE_RSA_METH_SET_PRIV_DEC], [1], ++ [Define if libcrypto has RSA_meth_set_priv_dec])]) ++ AC_SEARCH_LIBS([RSA_meth_set_finish], [crypto], ++ [AC_DEFINE([HAVE_RSA_METH_SET_FINISH], [1], ++ [Define if libcrypto has RSA_meth_set_finish])]) ++ ++ AC_SEARCH_LIBS([EVP_PKEY_get0_RSA], [crypto], ++ [AC_DEFINE([HAVE_EVP_PKEY_GET0_RSA], [1], ++ [Define if libcrypto has EVP_PKEY_get0_RSA])]) ++ ++ AC_SEARCH_LIBS([EVP_MD_CTX_new], [crypto], ++ [AC_DEFINE([HAVE_EVP_MD_CTX_NEW], [1], ++ [Define if libcrypto has EVP_MD_CTX_new])]) ++ AC_SEARCH_LIBS([EVP_MD_CTX_free], [crypto], ++ [AC_DEFINE([HAVE_EVP_MD_CTX_FREE], [1], ++ [Define if libcrypto has EVP_MD_CTX_free])]) ++ + AC_MSG_CHECKING([if EVP_DigestUpdate returns an int]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ +diff --git a/dh.c b/dh.c +index d0d4527b..f3ed3882 100644 +--- a/dh.c ++++ b/dh.c +@@ -43,6 +43,8 @@ + #include "misc.h" + #include "ssherr.h" + ++#include "openbsd-compat/openssl-compat.h" ++ + static int + parse_prime(int linenum, char *line, struct dhgroup *dhg) + { +diff --git a/kexdh.c b/kexdh.c +index 0bf0dc13..e6925b18 100644 +--- a/kexdh.c ++++ b/kexdh.c +@@ -33,6 +33,8 @@ + + #include + ++#include "openbsd-compat/openssl-compat.h" ++ + #include "ssh2.h" + #include "sshkey.h" + #include "cipher.h" +diff --git a/kexdhc.c b/kexdhc.c +index a8b74247..8b56377a 100644 +--- a/kexdhc.c ++++ b/kexdhc.c +@@ -36,6 +36,8 @@ + #include + #include + ++#include "openbsd-compat/openssl-compat.h" ++ + #include "sshkey.h" + #include "cipher.h" + #include "digest.h" +diff --git a/kexdhs.c b/kexdhs.c +index 8367c6c3..337aab5b 100644 +--- a/kexdhs.c ++++ b/kexdhs.c +@@ -35,6 +35,8 @@ + + #include + ++#include "openbsd-compat/openssl-compat.h" ++ + #include "sshkey.h" + #include "cipher.h" + #include "digest.h" +diff --git a/kexgex.c b/kexgex.c +index 8b0d8333..3ca4bd37 100644 +--- a/kexgex.c ++++ b/kexgex.c +@@ -33,6 +33,8 @@ + #include + #include + ++#include "openbsd-compat/openssl-compat.h" ++ + #include "sshkey.h" + #include "cipher.h" + #include "kex.h" +diff --git a/kexgexc.c b/kexgexc.c +index 955bc837..0d07f73c 100644 +--- a/kexgexc.c ++++ b/kexgexc.c +@@ -37,6 +37,8 @@ + #include + #include + ++#include "openbsd-compat/openssl-compat.h" ++ + #include "sshkey.h" + #include "cipher.h" + #include "digest.h" +diff --git a/kexgexs.c b/kexgexs.c +index 2a4aa7e8..ce934f88 100644 +--- a/kexgexs.c ++++ b/kexgexs.c +@@ -36,6 +36,8 @@ + + #include + ++#include "openbsd-compat/openssl-compat.h" ++ + #include "sshkey.h" + #include "cipher.h" + #include "digest.h" +diff --git a/monitor.c b/monitor.c +index b30813b4..531b2993 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -29,7 +29,6 @@ + + #include + #include +-#include "openbsd-compat/sys-tree.h" + #include + + #include +@@ -60,7 +59,10 @@ + #include + #endif + ++#include "openbsd-compat/sys-tree.h" + #include "openbsd-compat/sys-queue.h" ++#include "openbsd-compat/openssl-compat.h" ++ + #include "atomicio.h" + #include "xmalloc.h" + #include "ssh.h" +diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in +index 2fd9b952..c1e14cbd 100644 +--- a/openbsd-compat/Makefile.in ++++ b/openbsd-compat/Makefile.in +@@ -85,6 +85,7 @@ COMPAT= arc4random.o \ + getrrsetbyname-ldns.o \ + kludge-fd_set.o \ + openssl-compat.o \ ++ libressl-api-compat.o \ + xcrypt.o + + PORTS= port-aix.o \ +diff --git a/openbsd-compat/libressl-api-compat.c b/openbsd-compat/libressl-api-compat.c +new file mode 100644 +index 00000000..de3e64a6 +--- /dev/null ++++ b/openbsd-compat/libressl-api-compat.c +@@ -0,0 +1,636 @@ ++/* $OpenBSD: dsa_lib.c,v 1.29 2018/04/14 07:09:21 tb Exp $ */ ++/* $OpenBSD: rsa_lib.c,v 1.37 2018/04/14 07:09:21 tb Exp $ */ ++/* $OpenBSD: evp_lib.c,v 1.17 2018/09/12 06:35:38 djm Exp $ */ ++/* $OpenBSD: dh_lib.c,v 1.32 2018/05/02 15:48:38 tb Exp $ */ ++/* $OpenBSD: p_lib.c,v 1.24 2018/05/30 15:40:50 tb Exp $ */ ++/* $OpenBSD: digest.c,v 1.30 2018/04/14 07:09:21 tb Exp $ */ ++/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) ++ * All rights reserved. ++ * ++ * This package is an SSL implementation written ++ * by Eric Young (eay@cryptsoft.com). ++ * The implementation was written so as to conform with Netscapes SSL. ++ * ++ * This library is free for commercial and non-commercial use as long as ++ * the following conditions are aheared to. The following conditions ++ * apply to all code found in this distribution, be it the RC4, RSA, ++ * lhash, DES, etc., code; not just the SSL code. The SSL documentation ++ * included with this distribution is covered by the same copyright terms ++ * except that the holder is Tim Hudson (tjh@cryptsoft.com). ++ * ++ * Copyright remains Eric Young's, and as such any Copyright notices in ++ * the code are not to be removed. ++ * If this package is used in a product, Eric Young should be given attribution ++ * as the author of the parts of the library used. ++ * This can be in the form of a textual message at program startup or ++ * in documentation (online or textual) provided with the package. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * "This product includes cryptographic software written by ++ * Eric Young (eay@cryptsoft.com)" ++ * The word 'cryptographic' can be left out if the rouines from the library ++ * being used are not cryptographic related :-). ++ * 4. If you include any Windows specific code (or a derivative thereof) from ++ * the apps directory (application code) you must include an acknowledgement: ++ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" ++ * ++ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * The licence and distribution terms for any publically available version or ++ * derivative of this code cannot be changed. i.e. this code cannot simply be ++ * copied and put under another distribution licence ++ * [including the GNU Public Licence.] ++ */ ++ ++/* $OpenBSD: dsa_asn1.c,v 1.22 2018/06/14 17:03:19 jsing Exp $ */ ++/* $OpenBSD: ecs_asn1.c,v 1.9 2018/03/17 15:24:44 tb Exp $ */ ++/* $OpenBSD: digest.c,v 1.30 2018/04/14 07:09:21 tb Exp $ */ ++/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL ++ * project 2000. ++ */ ++/* ==================================================================== ++ * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * 3. All advertising materials mentioning features or use of this ++ * software must display the following acknowledgment: ++ * "This product includes software developed by the OpenSSL Project ++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" ++ * ++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to ++ * endorse or promote products derived from this software without ++ * prior written permission. For written permission, please contact ++ * licensing@OpenSSL.org. ++ * ++ * 5. Products derived from this software may not be called "OpenSSL" ++ * nor may "OpenSSL" appear in their names without prior written ++ * permission of the OpenSSL Project. ++ * ++ * 6. Redistributions of any form whatsoever must retain the following ++ * acknowledgment: ++ * "This product includes software developed by the OpenSSL Project ++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY ++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ++ * OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ==================================================================== ++ * ++ * This product includes cryptographic software written by Eric Young ++ * (eay@cryptsoft.com). This product includes software written by Tim ++ * Hudson (tjh@cryptsoft.com). ++ * ++ */ ++ ++/* $OpenBSD: rsa_meth.c,v 1.2 2018/09/12 06:35:38 djm Exp $ */ ++/* ++ * Copyright (c) 2018 Theo Buehler ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include "includes.h" ++ ++#ifdef WITH_OPENSSL ++ ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef HAVE_DSA_GET0_PQG ++void ++DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) ++{ ++ if (p != NULL) ++ *p = d->p; ++ if (q != NULL) ++ *q = d->q; ++ if (g != NULL) ++ *g = d->g; ++} ++#endif /* HAVE_DSA_GET0_PQG */ ++ ++#ifndef HAVE_DSA_SET0_PQG ++int ++DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) ++{ ++ if ((d->p == NULL && p == NULL) || (d->q == NULL && q == NULL) || ++ (d->g == NULL && g == NULL)) ++ return 0; ++ ++ if (p != NULL) { ++ BN_free(d->p); ++ d->p = p; ++ } ++ if (q != NULL) { ++ BN_free(d->q); ++ d->q = q; ++ } ++ if (g != NULL) { ++ BN_free(d->g); ++ d->g = g; ++ } ++ ++ return 1; ++} ++#endif /* HAVE_DSA_SET0_PQG */ ++ ++#ifndef HAVE_DSA_GET0_KEY ++void ++DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key) ++{ ++ if (pub_key != NULL) ++ *pub_key = d->pub_key; ++ if (priv_key != NULL) ++ *priv_key = d->priv_key; ++} ++#endif /* HAVE_DSA_GET0_KEY */ ++ ++#ifndef HAVE_DSA_SET0_KEY ++int ++DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) ++{ ++ if (d->pub_key == NULL && pub_key == NULL) ++ return 0; ++ ++ if (pub_key != NULL) { ++ BN_free(d->pub_key); ++ d->pub_key = pub_key; ++ } ++ if (priv_key != NULL) { ++ BN_free(d->priv_key); ++ d->priv_key = priv_key; ++ } ++ ++ return 1; ++} ++#endif /* HAVE_DSA_SET0_KEY */ ++ ++#ifndef HAVE_RSA_GET0_KEY ++void ++RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) ++{ ++ if (n != NULL) ++ *n = r->n; ++ if (e != NULL) ++ *e = r->e; ++ if (d != NULL) ++ *d = r->d; ++} ++#endif /* HAVE_RSA_GET0_KEY */ ++ ++#ifndef HAVE_RSA_SET0_KEY ++int ++RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) ++{ ++ if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL)) ++ return 0; ++ ++ if (n != NULL) { ++ BN_free(r->n); ++ r->n = n; ++ } ++ if (e != NULL) { ++ BN_free(r->e); ++ r->e = e; ++ } ++ if (d != NULL) { ++ BN_free(r->d); ++ r->d = d; ++ } ++ ++ return 1; ++} ++#endif /* HAVE_RSA_SET0_KEY */ ++ ++#ifndef HAVE_RSA_GET0_CRT_PARAMS ++void ++RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, ++ const BIGNUM **iqmp) ++{ ++ if (dmp1 != NULL) ++ *dmp1 = r->dmp1; ++ if (dmq1 != NULL) ++ *dmq1 = r->dmq1; ++ if (iqmp != NULL) ++ *iqmp = r->iqmp; ++} ++#endif /* HAVE_RSA_GET0_CRT_PARAMS */ ++ ++#ifndef HAVE_RSA_SET0_CRT_PARAMS ++int ++RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) ++{ ++ if ((r->dmp1 == NULL && dmp1 == NULL) || ++ (r->dmq1 == NULL && dmq1 == NULL) || ++ (r->iqmp == NULL && iqmp == NULL)) ++ return 0; ++ ++ if (dmp1 != NULL) { ++ BN_free(r->dmp1); ++ r->dmp1 = dmp1; ++ } ++ if (dmq1 != NULL) { ++ BN_free(r->dmq1); ++ r->dmq1 = dmq1; ++ } ++ if (iqmp != NULL) { ++ BN_free(r->iqmp); ++ r->iqmp = iqmp; ++ } ++ ++ return 1; ++} ++#endif /* HAVE_RSA_SET0_CRT_PARAMS */ ++ ++#ifndef HAVE_RSA_GET0_FACTORS ++void ++RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) ++{ ++ if (p != NULL) ++ *p = r->p; ++ if (q != NULL) ++ *q = r->q; ++} ++#endif /* HAVE_RSA_GET0_FACTORS */ ++ ++#ifndef HAVE_RSA_SET0_FACTORS ++int ++RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) ++{ ++ if ((r->p == NULL && p == NULL) || (r->q == NULL && q == NULL)) ++ return 0; ++ ++ if (p != NULL) { ++ BN_free(r->p); ++ r->p = p; ++ } ++ if (q != NULL) { ++ BN_free(r->q); ++ r->q = q; ++ } ++ ++ return 1; ++} ++#endif /* HAVE_RSA_SET0_FACTORS */ ++ ++#ifndef HAVE_EVP_CIPHER_CTX_GET_IV ++int ++EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, unsigned char *iv, size_t len) ++{ ++ if (ctx == NULL) ++ return 0; ++ if (EVP_CIPHER_CTX_iv_length(ctx) < 0) ++ return 0; ++ if (len != (size_t)EVP_CIPHER_CTX_iv_length(ctx)) ++ return 0; ++ if (len > EVP_MAX_IV_LENGTH) ++ return 0; /* sanity check; shouldn't happen */ ++ /* ++ * Skip the memcpy entirely when the requested IV length is zero, ++ * since the iv pointer may be NULL or invalid. ++ */ ++ if (len != 0) { ++ if (iv == NULL) ++ return 0; ++# ifdef HAVE_EVP_CIPHER_CTX_IV ++ memcpy(iv, EVP_CIPHER_CTX_iv(ctx), len); ++# else ++ memcpy(iv, ctx->iv, len); ++# endif /* HAVE_EVP_CIPHER_CTX_IV */ ++ } ++ return 1; ++} ++#endif /* HAVE_EVP_CIPHER_CTX_GET_IV */ ++ ++#ifndef HAVE_EVP_CIPHER_CTX_SET_IV ++int ++EVP_CIPHER_CTX_set_iv(EVP_CIPHER_CTX *ctx, const unsigned char *iv, size_t len) ++{ ++ if (ctx == NULL) ++ return 0; ++ if (EVP_CIPHER_CTX_iv_length(ctx) < 0) ++ return 0; ++ if (len != (size_t)EVP_CIPHER_CTX_iv_length(ctx)) ++ return 0; ++ if (len > EVP_MAX_IV_LENGTH) ++ return 0; /* sanity check; shouldn't happen */ ++ /* ++ * Skip the memcpy entirely when the requested IV length is zero, ++ * since the iv pointer may be NULL or invalid. ++ */ ++ if (len != 0) { ++ if (iv == NULL) ++ return 0; ++# ifdef HAVE_EVP_CIPHER_CTX_IV_NOCONST ++ memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, len); ++# else ++ memcpy(ctx->iv, iv, len); ++# endif /* HAVE_EVP_CIPHER_CTX_IV_NOCONST */ ++ } ++ return 1; ++} ++#endif /* HAVE_EVP_CIPHER_CTX_SET_IV */ ++ ++#ifndef HAVE_DSA_SIG_GET0 ++void ++DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) ++{ ++ if (pr != NULL) ++ *pr = sig->r; ++ if (ps != NULL) ++ *ps = sig->s; ++} ++#endif /* HAVE_DSA_SIG_GET0 */ ++ ++#ifndef HAVE_DSA_SIG_SET0 ++int ++DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) ++{ ++ if (r == NULL || s == NULL) ++ return 0; ++ ++ BN_clear_free(sig->r); ++ sig->r = r; ++ BN_clear_free(sig->s); ++ sig->s = s; ++ ++ return 1; ++} ++#endif /* HAVE_DSA_SIG_SET0 */ ++ ++#ifndef HAVE_ECDSA_SIG_GET0 ++void ++ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) ++{ ++ if (pr != NULL) ++ *pr = sig->r; ++ if (ps != NULL) ++ *ps = sig->s; ++} ++#endif /* HAVE_ECDSA_SIG_GET0 */ ++ ++#ifndef HAVE_ECDSA_SIG_SET0 ++int ++ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) ++{ ++ if (r == NULL || s == NULL) ++ return 0; ++ ++ BN_clear_free(sig->r); ++ BN_clear_free(sig->s); ++ sig->r = r; ++ sig->s = s; ++ return 1; ++} ++#endif /* HAVE_ECDSA_SIG_SET0 */ ++ ++#ifndef HAVE_DH_GET0_PQG ++void ++DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) ++{ ++ if (p != NULL) ++ *p = dh->p; ++ if (q != NULL) ++ *q = dh->q; ++ if (g != NULL) ++ *g = dh->g; ++} ++#endif /* HAVE_DH_GET0_PQG */ ++ ++#ifndef HAVE_DH_SET0_PQG ++int ++DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) ++{ ++ if ((dh->p == NULL && p == NULL) || (dh->g == NULL && g == NULL)) ++ return 0; ++ ++ if (p != NULL) { ++ BN_free(dh->p); ++ dh->p = p; ++ } ++ if (q != NULL) { ++ BN_free(dh->q); ++ dh->q = q; ++ } ++ if (g != NULL) { ++ BN_free(dh->g); ++ dh->g = g; ++ } ++ ++ return 1; ++} ++#endif /* HAVE_DH_SET0_PQG */ ++ ++#ifndef HAVE_DH_GET0_KEY ++void ++DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) ++{ ++ if (pub_key != NULL) ++ *pub_key = dh->pub_key; ++ if (priv_key != NULL) ++ *priv_key = dh->priv_key; ++} ++#endif /* HAVE_DH_GET0_KEY */ ++ ++#ifndef HAVE_DH_SET0_KEY ++int ++DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) ++{ ++ if (pub_key != NULL) { ++ BN_free(dh->pub_key); ++ dh->pub_key = pub_key; ++ } ++ if (priv_key != NULL) { ++ BN_free(dh->priv_key); ++ dh->priv_key = priv_key; ++ } ++ ++ return 1; ++} ++#endif /* HAVE_DH_SET0_KEY */ ++ ++#ifndef HAVE_DH_SET_LENGTH ++int ++DH_set_length(DH *dh, long length) ++{ ++ if (length < 0 || length > INT_MAX) ++ return 0; ++ ++ dh->length = length; ++ return 1; ++} ++#endif /* HAVE_DH_SET_LENGTH */ ++ ++#ifndef HAVE_RSA_METH_FREE ++void ++RSA_meth_free(RSA_METHOD *meth) ++{ ++ if (meth != NULL) { ++ free((char *)meth->name); ++ free(meth); ++ } ++} ++#endif /* HAVE_RSA_METH_FREE */ ++ ++#ifndef HAVE_RSA_METH_DUP ++RSA_METHOD * ++RSA_meth_dup(const RSA_METHOD *meth) ++{ ++ RSA_METHOD *copy; ++ ++ if ((copy = calloc(1, sizeof(*copy))) == NULL) ++ return NULL; ++ memcpy(copy, meth, sizeof(*copy)); ++ if ((copy->name = strdup(meth->name)) == NULL) { ++ free(copy); ++ return NULL; ++ } ++ ++ return copy; ++} ++#endif /* HAVE_RSA_METH_DUP */ ++ ++#ifndef HAVE_RSA_METH_SET1_NAME ++int ++RSA_meth_set1_name(RSA_METHOD *meth, const char *name) ++{ ++ char *copy; ++ ++ if ((copy = strdup(name)) == NULL) ++ return 0; ++ free((char *)meth->name); ++ meth->name = copy; ++ return 1; ++} ++#endif /* HAVE_RSA_METH_SET1_NAME */ ++ ++#ifndef HAVE_RSA_METH_GET_FINISH ++int ++(*RSA_meth_get_finish(const RSA_METHOD *meth))(RSA *rsa) ++{ ++ return meth->finish; ++} ++#endif /* HAVE_RSA_METH_GET_FINISH */ ++ ++#ifndef HAVE_RSA_METH_SET_PRIV_ENC ++int ++RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc)(int flen, ++ const unsigned char *from, unsigned char *to, RSA *rsa, int padding)) ++{ ++ meth->rsa_priv_enc = priv_enc; ++ return 1; ++} ++#endif /* HAVE_RSA_METH_SET_PRIV_ENC */ ++ ++#ifndef HAVE_RSA_METH_SET_PRIV_DEC ++int ++RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec)(int flen, ++ const unsigned char *from, unsigned char *to, RSA *rsa, int padding)) ++{ ++ meth->rsa_priv_dec = priv_dec; ++ return 1; ++} ++#endif /* HAVE_RSA_METH_SET_PRIV_DEC */ ++ ++#ifndef HAVE_RSA_METH_SET_FINISH ++int ++RSA_meth_set_finish(RSA_METHOD *meth, int (*finish)(RSA *rsa)) ++{ ++ meth->finish = finish; ++ return 1; ++} ++#endif /* HAVE_RSA_METH_SET_FINISH */ ++ ++#ifndef HAVE_EVP_PKEY_GET0_RSA ++RSA * ++EVP_PKEY_get0_RSA(EVP_PKEY *pkey) ++{ ++ if (pkey->type != EVP_PKEY_RSA) { ++ /* EVPerror(EVP_R_EXPECTING_AN_RSA_KEY); */ ++ return NULL; ++ } ++ return pkey->pkey.rsa; ++} ++#endif /* HAVE_EVP_PKEY_GET0_RSA */ ++ ++#ifndef HAVE_EVP_MD_CTX_NEW ++EVP_MD_CTX * ++EVP_MD_CTX_new(void) ++{ ++ return calloc(1, sizeof(EVP_MD_CTX)); ++} ++#endif /* HAVE_EVP_MD_CTX_NEW */ ++ ++#ifndef HAVE_EVP_MD_CTX_FREE ++void ++EVP_MD_CTX_free(EVP_MD_CTX *ctx) ++{ ++ if (ctx == NULL) ++ return; ++ ++ EVP_MD_CTX_cleanup(ctx); ++ ++ free(ctx); ++} ++#endif /* HAVE_EVP_MD_CTX_FREE */ ++ ++#endif /* WITH_OPENSSL */ +diff --git a/openbsd-compat/openssl-compat.h b/openbsd-compat/openssl-compat.h +index 2ae42bac..9e0264c0 100644 +--- a/openbsd-compat/openssl-compat.h ++++ b/openbsd-compat/openssl-compat.h +@@ -24,6 +24,8 @@ + #include + #include + #include ++#include ++#include + + int ssh_compatible_openssl(long, long); + +@@ -96,5 +98,139 @@ void ssh_OpenSSL_add_all_algorithms(void); + + #endif /* SSH_DONT_OVERLOAD_OPENSSL_FUNCS */ + ++/* LibreSSL/OpenSSL 1.1x API compat */ ++#ifndef HAVE_DSA_GET0_PQG ++void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, ++ const BIGNUM **g); ++#endif /* HAVE_DSA_GET0_PQG */ ++ ++#ifndef HAVE_DSA_SET0_PQG ++int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g); ++#endif /* HAVE_DSA_SET0_PQG */ ++ ++#ifndef HAVE_DSA_GET0_KEY ++void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, ++ const BIGNUM **priv_key); ++#endif /* HAVE_DSA_GET0_KEY */ ++ ++#ifndef HAVE_DSA_SET0_KEY ++int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); ++#endif /* HAVE_DSA_SET0_KEY */ ++ ++#ifndef HAVE_EVP_CIPHER_CTX_GET_IV ++int EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, ++ unsigned char *iv, size_t len); ++#endif /* HAVE_EVP_CIPHER_CTX_GET_IV */ ++ ++#ifndef HAVE_EVP_CIPHER_CTX_SET_IV ++int EVP_CIPHER_CTX_set_iv(EVP_CIPHER_CTX *ctx, ++ const unsigned char *iv, size_t len); ++#endif /* HAVE_EVP_CIPHER_CTX_SET_IV */ ++ ++#ifndef HAVE_RSA_GET0_KEY ++void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, ++ const BIGNUM **d); ++#endif /* HAVE_RSA_GET0_KEY */ ++ ++#ifndef HAVE_RSA_SET0_KEY ++int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); ++#endif /* HAVE_RSA_SET0_KEY */ ++ ++#ifndef HAVE_RSA_GET0_CRT_PARAMS ++void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, ++ const BIGNUM **iqmp); ++#endif /* HAVE_RSA_GET0_CRT_PARAMS */ ++ ++#ifndef HAVE_RSA_SET0_CRT_PARAMS ++int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp); ++#endif /* HAVE_RSA_SET0_CRT_PARAMS */ ++ ++#ifndef HAVE_RSA_GET0_FACTORS ++void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); ++#endif /* HAVE_RSA_GET0_FACTORS */ ++ ++#ifndef HAVE_RSA_SET0_FACTORS ++int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); ++#endif /* HAVE_RSA_SET0_FACTORS */ ++ ++#ifndef DSA_SIG_GET0 ++void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); ++#endif /* DSA_SIG_GET0 */ ++ ++#ifndef DSA_SIG_SET0 ++int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s); ++#endif /* DSA_SIG_SET0 */ ++ ++#ifndef HAVE_ECDSA_SIG_GET0 ++void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); ++#endif /* HAVE_ECDSA_SIG_GET0 */ ++ ++#ifndef HAVE_ECDSA_SIG_SET0 ++int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); ++#endif /* HAVE_ECDSA_SIG_SET0 */ ++ ++#ifndef HAVE_DH_GET0_PQG ++void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, ++ const BIGNUM **g); ++#endif /* HAVE_DH_GET0_PQG */ ++ ++#ifndef HAVE_DH_SET0_PQG ++int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); ++#endif /* HAVE_DH_SET0_PQG */ ++ ++#ifndef HAVE_DH_GET0_KEY ++void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key); ++#endif /* HAVE_DH_GET0_KEY */ ++ ++#ifndef HAVE_DH_SET0_KEY ++int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); ++#endif /* HAVE_DH_SET0_KEY */ ++ ++#ifndef HAVE_DH_SET_LENGTH ++int DH_set_length(DH *dh, long length); ++#endif /* HAVE_DH_SET_LENGTH */ ++ ++#ifndef HAVE_RSA_METH_FREE ++void RSA_meth_free(RSA_METHOD *meth); ++#endif /* HAVE_RSA_METH_FREE */ ++ ++#ifndef HAVE_RSA_METH_DUP ++RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth); ++#endif /* HAVE_RSA_METH_DUP */ ++ ++#ifndef HAVE_RSA_METH_SET1_NAME ++int RSA_meth_set1_name(RSA_METHOD *meth, const char *name); ++#endif /* HAVE_RSA_METH_SET1_NAME */ ++ ++#ifndef HAVE_RSA_METH_GET_FINISH ++int (*RSA_meth_get_finish(const RSA_METHOD *meth))(RSA *rsa); ++#endif /* HAVE_RSA_METH_GET_FINISH */ ++ ++#ifndef HAVE_RSA_METH_SET_PRIV_ENC ++int RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc)(int flen, ++ const unsigned char *from, unsigned char *to, RSA *rsa, int padding)); ++#endif /* HAVE_RSA_METH_SET_PRIV_ENC */ ++ ++#ifndef HAVE_RSA_METH_SET_PRIV_DEC ++int RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec)(int flen, ++ const unsigned char *from, unsigned char *to, RSA *rsa, int padding)); ++#endif /* HAVE_RSA_METH_SET_PRIV_DEC */ ++ ++#ifndef HAVE_RSA_METH_SET_FINISH ++int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish)(RSA *rsa)); ++#endif /* HAVE_RSA_METH_SET_FINISH */ ++ ++#ifndef HAVE_EVP_PKEY_GET0_RSA ++RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey); ++#endif /* HAVE_EVP_PKEY_GET0_RSA */ ++ ++#ifndef HAVE_EVP_MD_CTX_new ++EVP_MD_CTX *EVP_MD_CTX_new(void); ++#endif /* HAVE_EVP_MD_CTX_new */ ++ ++#ifndef HAVE_EVP_MD_CTX_free ++void EVP_MD_CTX_free(EVP_MD_CTX *ctx); ++#endif /* HAVE_EVP_MD_CTX_free */ ++ + #endif /* WITH_OPENSSL */ + #endif /* _OPENSSL_COMPAT_H */ +diff --git a/ssh-dss.c b/ssh-dss.c +index 631b1571..a23c383d 100644 +--- a/ssh-dss.c ++++ b/ssh-dss.c +@@ -43,6 +43,8 @@ + #define SSHKEY_INTERNAL + #include "sshkey.h" + ++#include "openbsd-compat/openssl-compat.h" ++ + #define INTBLOB_LEN 20 + #define SIGBLOB_LEN (2*INTBLOB_LEN) + +diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c +index 9e92af04..2f553175 100644 +--- a/ssh-ecdsa.c ++++ b/ssh-ecdsa.c +@@ -43,6 +43,8 @@ + #define SSHKEY_INTERNAL + #include "sshkey.h" + ++#include "openbsd-compat/openssl-compat.h" ++ + /* ARGSUSED */ + int + ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, +diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c +index bcc18c6b..d1241ce6 100644 +--- a/ssh-pkcs11-client.c ++++ b/ssh-pkcs11-client.c +@@ -32,6 +32,8 @@ + + #include + ++#include "openbsd-compat/openssl-compat.h" ++ + #include "pathnames.h" + #include "xmalloc.h" + #include "sshbuf.h" +diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c +index c35f9415..775de964 100644 +--- a/ssh-pkcs11.c ++++ b/ssh-pkcs11.c +@@ -30,6 +30,7 @@ + #include + + #include "openbsd-compat/sys-queue.h" ++#include "openbsd-compat/openssl-compat.h" + + #include + +diff --git a/ssh-rsa.c b/ssh-rsa.c +index 2788f334..9b14f9a9 100644 +--- a/ssh-rsa.c ++++ b/ssh-rsa.c +@@ -35,6 +35,8 @@ + #include "digest.h" + #include "log.h" + ++#include "openbsd-compat/openssl-compat.h" ++ + static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); + + static const char * +diff --git a/sshkey.c b/sshkey.c +index 085f1707..6f2c9d44 100644 +--- a/sshkey.c ++++ b/sshkey.c +@@ -60,6 +60,8 @@ + + #include "xmss_fast.h" + ++#include "openbsd-compat/openssl-compat.h" ++ + /* openssh private key file format */ + #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" + #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n" +@@ -1744,7 +1746,6 @@ int + sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) + { + struct sshkey *n = NULL; +- int ret = SSH_ERR_INTERNAL_ERROR; + int r = SSH_ERR_INTERNAL_ERROR; + #ifdef WITH_OPENSSL + const BIGNUM *rsa_n, *rsa_e; + +commit 86e0a9f3d249d5580390daf58e015e68b01cef10 +Author: djm@openbsd.org +Date: Thu Sep 13 05:06:51 2018 +0000 + + upstream: use only openssl-1.1.x API here too + + OpenBSD-Regress-ID: ae877064597c349954b1b443769723563cecbc8f + +diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c +index 7e03b7e5..8e35f441 100644 +--- a/regress/unittests/sshkey/test_sshkey.c ++++ b/regress/unittests/sshkey/test_sshkey.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: test_sshkey.c,v 1.15 2018/09/12 01:22:43 djm Exp $ */ ++/* $OpenBSD: test_sshkey.c,v 1.16 2018/09/13 05:06:51 djm Exp $ */ + /* + * Regress test for sshkey.h key management API + * +@@ -173,6 +173,61 @@ get_private(const char *n) + return ret; + } + ++static const BIGNUM * ++rsa_n(struct sshkey *k) ++{ ++ const BIGNUM *n = NULL; ++ ++ ASSERT_PTR_NE(k, NULL); ++ ASSERT_PTR_NE(k->rsa, NULL); ++ RSA_get0_key(k->rsa, &n, NULL, NULL); ++ return n; ++} ++ ++static const BIGNUM * ++rsa_e(struct sshkey *k) ++{ ++ const BIGNUM *e = NULL; ++ ++ ASSERT_PTR_NE(k, NULL); ++ ASSERT_PTR_NE(k->rsa, NULL); ++ RSA_get0_key(k->rsa, NULL, &e, NULL); ++ return e; ++} ++ ++static const BIGNUM * ++rsa_p(struct sshkey *k) ++{ ++ const BIGNUM *p = NULL; ++ ++ ASSERT_PTR_NE(k, NULL); ++ ASSERT_PTR_NE(k->rsa, NULL); ++ RSA_get0_factors(k->rsa, &p, NULL); ++ return p; ++} ++ ++static const BIGNUM * ++dsa_g(struct sshkey *k) ++{ ++ const BIGNUM *g = NULL; ++ ++ ASSERT_PTR_NE(k, NULL); ++ ASSERT_PTR_NE(k->dsa, NULL); ++ DSA_get0_pqg(k->dsa, NULL, NULL, &g); ++ return g; ++} ++ ++static const BIGNUM * ++dsa_priv_key(struct sshkey *k) ++{ ++ const BIGNUM *priv_key = NULL; ++ ++ ASSERT_PTR_NE(k, NULL); ++ ASSERT_PTR_NE(k->dsa, NULL); ++ DSA_get0_key(k->dsa, NULL, &priv_key); ++ return priv_key; ++} ++ + void + sshkey_tests(void) + { +@@ -197,9 +252,6 @@ sshkey_tests(void) + k1 = sshkey_new(KEY_RSA); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(k1->rsa, NULL); +- ASSERT_PTR_NE(k1->rsa->n, NULL); +- ASSERT_PTR_NE(k1->rsa->e, NULL); +- ASSERT_PTR_EQ(k1->rsa->p, NULL); + sshkey_free(k1); + TEST_DONE(); + +@@ -207,8 +259,6 @@ sshkey_tests(void) + k1 = sshkey_new(KEY_DSA); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(k1->dsa, NULL); +- ASSERT_PTR_NE(k1->dsa->g, NULL); +- ASSERT_PTR_EQ(k1->dsa->priv_key, NULL); + sshkey_free(k1); + TEST_DONE(); + +@@ -230,27 +280,6 @@ sshkey_tests(void) + sshkey_free(k1); + TEST_DONE(); + +- TEST_START("new_private KEY_RSA"); +- k1 = sshkey_new_private(KEY_RSA); +- ASSERT_PTR_NE(k1, NULL); +- ASSERT_PTR_NE(k1->rsa, NULL); +- ASSERT_PTR_NE(k1->rsa->n, NULL); +- ASSERT_PTR_NE(k1->rsa->e, NULL); +- ASSERT_PTR_NE(k1->rsa->p, NULL); +- ASSERT_INT_EQ(sshkey_add_private(k1), 0); +- sshkey_free(k1); +- TEST_DONE(); +- +- TEST_START("new_private KEY_DSA"); +- k1 = sshkey_new_private(KEY_DSA); +- ASSERT_PTR_NE(k1, NULL); +- ASSERT_PTR_NE(k1->dsa, NULL); +- ASSERT_PTR_NE(k1->dsa->g, NULL); +- ASSERT_PTR_NE(k1->dsa->priv_key, NULL); +- ASSERT_INT_EQ(sshkey_add_private(k1), 0); +- sshkey_free(k1); +- TEST_DONE(); +- + TEST_START("generate KEY_RSA too small modulus"); + ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 128, &k1), + SSH_ERR_KEY_LENGTH); +@@ -285,18 +314,18 @@ sshkey_tests(void) + ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &kr), 0); + ASSERT_PTR_NE(kr, NULL); + ASSERT_PTR_NE(kr->rsa, NULL); +- ASSERT_PTR_NE(kr->rsa->n, NULL); +- ASSERT_PTR_NE(kr->rsa->e, NULL); +- ASSERT_PTR_NE(kr->rsa->p, NULL); +- ASSERT_INT_EQ(BN_num_bits(kr->rsa->n), 1024); ++ ASSERT_PTR_NE(rsa_n(kr), NULL); ++ ASSERT_PTR_NE(rsa_e(kr), NULL); ++ ASSERT_PTR_NE(rsa_p(kr), NULL); ++ ASSERT_INT_EQ(BN_num_bits(rsa_n(kr)), 1024); + TEST_DONE(); + + TEST_START("generate KEY_DSA"); + ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &kd), 0); + ASSERT_PTR_NE(kd, NULL); + ASSERT_PTR_NE(kd->dsa, NULL); +- ASSERT_PTR_NE(kd->dsa->g, NULL); +- ASSERT_PTR_NE(kd->dsa->priv_key, NULL); ++ ASSERT_PTR_NE(dsa_g(kd), NULL); ++ ASSERT_PTR_NE(dsa_priv_key(kd), NULL); + TEST_DONE(); + + #ifdef OPENSSL_HAS_ECC +@@ -323,9 +352,9 @@ sshkey_tests(void) + ASSERT_PTR_NE(kr, k1); + ASSERT_INT_EQ(k1->type, KEY_RSA); + ASSERT_PTR_NE(k1->rsa, NULL); +- ASSERT_PTR_NE(k1->rsa->n, NULL); +- ASSERT_PTR_NE(k1->rsa->e, NULL); +- ASSERT_PTR_EQ(k1->rsa->p, NULL); ++ ASSERT_PTR_NE(rsa_n(k1), NULL); ++ ASSERT_PTR_NE(rsa_e(k1), NULL); ++ ASSERT_PTR_EQ(rsa_p(k1), NULL); + TEST_DONE(); + + TEST_START("equal KEY_RSA/demoted KEY_RSA"); +@@ -339,8 +368,8 @@ sshkey_tests(void) + ASSERT_PTR_NE(kd, k1); + ASSERT_INT_EQ(k1->type, KEY_DSA); + ASSERT_PTR_NE(k1->dsa, NULL); +- ASSERT_PTR_NE(k1->dsa->g, NULL); +- ASSERT_PTR_EQ(k1->dsa->priv_key, NULL); ++ ASSERT_PTR_NE(dsa_g(k1), NULL); ++ ASSERT_PTR_EQ(dsa_priv_key(k1), NULL); + TEST_DONE(); + + TEST_START("equal KEY_DSA/demoted KEY_DSA"); + +commit a3fd8074e2e2f06602e25618721f9556c731312c +Author: djm@openbsd.org +Date: Thu Sep 13 09:03:20 2018 +0000 + + upstream: missed a bit of openssl-1.0.x API in this unittest + + OpenBSD-Regress-ID: a73a54d7f7381856a3f3a2d25947bee7a9a5dbc9 + +diff --git a/regress/unittests/sshkey/common.c b/regress/unittests/sshkey/common.c +index b598f05c..548da684 100644 +--- a/regress/unittests/sshkey/common.c ++++ b/regress/unittests/sshkey/common.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: common.c,v 1.2 2015/01/08 13:10:58 djm Exp $ */ ++/* $OpenBSD: common.c,v 1.3 2018/09/13 09:03:20 djm Exp $ */ + /* + * Helpers for key API tests + * +@@ -82,3 +82,80 @@ load_bignum(const char *name) + return ret; + } + ++const BIGNUM * ++rsa_n(struct sshkey *k) ++{ ++ const BIGNUM *n = NULL; ++ ++ ASSERT_PTR_NE(k, NULL); ++ ASSERT_PTR_NE(k->rsa, NULL); ++ RSA_get0_key(k->rsa, &n, NULL, NULL); ++ return n; ++} ++ ++const BIGNUM * ++rsa_e(struct sshkey *k) ++{ ++ const BIGNUM *e = NULL; ++ ++ ASSERT_PTR_NE(k, NULL); ++ ASSERT_PTR_NE(k->rsa, NULL); ++ RSA_get0_key(k->rsa, NULL, &e, NULL); ++ return e; ++} ++ ++const BIGNUM * ++rsa_p(struct sshkey *k) ++{ ++ const BIGNUM *p = NULL; ++ ++ ASSERT_PTR_NE(k, NULL); ++ ASSERT_PTR_NE(k->rsa, NULL); ++ RSA_get0_factors(k->rsa, &p, NULL); ++ return p; ++} ++ ++const BIGNUM * ++rsa_q(struct sshkey *k) ++{ ++ const BIGNUM *q = NULL; ++ ++ ASSERT_PTR_NE(k, NULL); ++ ASSERT_PTR_NE(k->rsa, NULL); ++ RSA_get0_factors(k->rsa, NULL, &q); ++ return q; ++} ++ ++const BIGNUM * ++dsa_g(struct sshkey *k) ++{ ++ const BIGNUM *g = NULL; ++ ++ ASSERT_PTR_NE(k, NULL); ++ ASSERT_PTR_NE(k->dsa, NULL); ++ DSA_get0_pqg(k->dsa, NULL, NULL, &g); ++ return g; ++} ++ ++const BIGNUM * ++dsa_pub_key(struct sshkey *k) ++{ ++ const BIGNUM *pub_key = NULL; ++ ++ ASSERT_PTR_NE(k, NULL); ++ ASSERT_PTR_NE(k->dsa, NULL); ++ DSA_get0_key(k->dsa, &pub_key, NULL); ++ return pub_key; ++} ++ ++const BIGNUM * ++dsa_priv_key(struct sshkey *k) ++{ ++ const BIGNUM *priv_key = NULL; ++ ++ ASSERT_PTR_NE(k, NULL); ++ ASSERT_PTR_NE(k->dsa, NULL); ++ DSA_get0_key(k->dsa, NULL, &priv_key); ++ return priv_key; ++} ++ +diff --git a/regress/unittests/sshkey/common.h b/regress/unittests/sshkey/common.h +index bf7d19dc..7a514fdc 100644 +--- a/regress/unittests/sshkey/common.h ++++ b/regress/unittests/sshkey/common.h +@@ -1,4 +1,4 @@ +-/* $OpenBSD: common.h,v 1.1 2014/06/24 01:14:18 djm Exp $ */ ++/* $OpenBSD: common.h,v 1.2 2018/09/13 09:03:20 djm Exp $ */ + /* + * Helpers for key API tests + * +@@ -14,3 +14,12 @@ struct sshbuf *load_text_file(const char *name); + /* Load a bignum from a file */ + BIGNUM *load_bignum(const char *name); + ++/* Accessors for key components */ ++const BIGNUM *rsa_n(struct sshkey *k); ++const BIGNUM *rsa_e(struct sshkey *k); ++const BIGNUM *rsa_p(struct sshkey *k); ++const BIGNUM *rsa_q(struct sshkey *k); ++const BIGNUM *dsa_g(struct sshkey *k); ++const BIGNUM *dsa_pub_key(struct sshkey *k); ++const BIGNUM *dsa_priv_key(struct sshkey *k); ++ +diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c +index 0636e84b..65610dac 100644 +--- a/regress/unittests/sshkey/test_file.c ++++ b/regress/unittests/sshkey/test_file.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: test_file.c,v 1.7 2018/09/12 01:36:45 djm Exp $ */ ++/* $OpenBSD: test_file.c,v 1.8 2018/09/13 09:03:20 djm Exp $ */ + /* + * Regress test for sshkey.h key management API + * +@@ -60,9 +60,9 @@ sshkey_file_tests(void) + a = load_bignum("rsa_1.param.n"); + b = load_bignum("rsa_1.param.p"); + c = load_bignum("rsa_1.param.q"); +- ASSERT_BIGNUM_EQ(k1->rsa->n, a); +- ASSERT_BIGNUM_EQ(k1->rsa->p, b); +- ASSERT_BIGNUM_EQ(k1->rsa->q, c); ++ ASSERT_BIGNUM_EQ(rsa_n(k1), a); ++ ASSERT_BIGNUM_EQ(rsa_p(k1), b); ++ ASSERT_BIGNUM_EQ(rsa_q(k1), c); + BN_free(a); + BN_free(b); + BN_free(c); +@@ -169,9 +169,9 @@ sshkey_file_tests(void) + a = load_bignum("dsa_1.param.g"); + b = load_bignum("dsa_1.param.priv"); + c = load_bignum("dsa_1.param.pub"); +- ASSERT_BIGNUM_EQ(k1->dsa->g, a); +- ASSERT_BIGNUM_EQ(k1->dsa->priv_key, b); +- ASSERT_BIGNUM_EQ(k1->dsa->pub_key, c); ++ ASSERT_BIGNUM_EQ(dsa_g(k1), a); ++ ASSERT_BIGNUM_EQ(dsa_priv_key(k1), b); ++ ASSERT_BIGNUM_EQ(dsa_pub_key(k1), c); + BN_free(a); + BN_free(b); + BN_free(c); +diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c +index 8e35f441..47a03fad 100644 +--- a/regress/unittests/sshkey/test_sshkey.c ++++ b/regress/unittests/sshkey/test_sshkey.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: test_sshkey.c,v 1.16 2018/09/13 05:06:51 djm Exp $ */ ++/* $OpenBSD: test_sshkey.c,v 1.17 2018/09/13 09:03:20 djm Exp $ */ + /* + * Regress test for sshkey.h key management API + * +@@ -173,61 +173,6 @@ get_private(const char *n) + return ret; + } + +-static const BIGNUM * +-rsa_n(struct sshkey *k) +-{ +- const BIGNUM *n = NULL; +- +- ASSERT_PTR_NE(k, NULL); +- ASSERT_PTR_NE(k->rsa, NULL); +- RSA_get0_key(k->rsa, &n, NULL, NULL); +- return n; +-} +- +-static const BIGNUM * +-rsa_e(struct sshkey *k) +-{ +- const BIGNUM *e = NULL; +- +- ASSERT_PTR_NE(k, NULL); +- ASSERT_PTR_NE(k->rsa, NULL); +- RSA_get0_key(k->rsa, NULL, &e, NULL); +- return e; +-} +- +-static const BIGNUM * +-rsa_p(struct sshkey *k) +-{ +- const BIGNUM *p = NULL; +- +- ASSERT_PTR_NE(k, NULL); +- ASSERT_PTR_NE(k->rsa, NULL); +- RSA_get0_factors(k->rsa, &p, NULL); +- return p; +-} +- +-static const BIGNUM * +-dsa_g(struct sshkey *k) +-{ +- const BIGNUM *g = NULL; +- +- ASSERT_PTR_NE(k, NULL); +- ASSERT_PTR_NE(k->dsa, NULL); +- DSA_get0_pqg(k->dsa, NULL, NULL, &g); +- return g; +-} +- +-static const BIGNUM * +-dsa_priv_key(struct sshkey *k) +-{ +- const BIGNUM *priv_key = NULL; +- +- ASSERT_PTR_NE(k, NULL); +- ASSERT_PTR_NE(k->dsa, NULL); +- DSA_get0_key(k->dsa, NULL, &priv_key); +- return priv_key; +-} +- + void + sshkey_tests(void) + { + +commit d64e78526596f098096113fcf148216798c327ff +Author: Damien Miller +Date: Thu Sep 13 19:05:48 2018 +1000 + + add compat header + +diff --git a/regress/unittests/sshkey/common.c b/regress/unittests/sshkey/common.c +index 548da684..e63465c4 100644 +--- a/regress/unittests/sshkey/common.c ++++ b/regress/unittests/sshkey/common.c +@@ -27,6 +27,8 @@ + # include + #endif + ++#include "openbsd-compat/openssl-compat.h" ++ + #include "../test_helper/test_helper.h" + + #include "ssherr.h"