diff --git a/libs/libssh/Makefile b/libs/libssh/Makefile index 17dd3ba40..cc410c058 100644 --- a/libs/libssh/Makefile +++ b/libs/libssh/Makefile @@ -12,7 +12,7 @@ PKG_MAINTAINER:=Mislav Novakovic PKG_NAME:=libssh PKG_VERSION:=0.7.5 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://red.libssh.org/attachments/download/218/ diff --git a/libs/libssh/patches/005-openssl-1.1.patch b/libs/libssh/patches/005-openssl-1.1.patch new file mode 100644 index 000000000..a5916a575 --- /dev/null +++ b/libs/libssh/patches/005-openssl-1.1.patch @@ -0,0 +1,1159 @@ +--- a/src/libcrypto.c ++++ b/src/libcrypto.c +@@ -43,10 +43,12 @@ + #include + #include + #include ++#include "libcrypto-compat.h" + + #ifdef HAVE_OPENSSL_AES_H + #define HAS_AES + #include ++#include + #endif + #ifdef HAVE_OPENSSL_BLOWFISH_H + #define HAS_BLOWFISH +@@ -133,18 +135,20 @@ static const EVP_MD *nid_to_evpmd(int ni + void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen) + { + const EVP_MD *evp_md = nid_to_evpmd(nid); +- EVP_MD_CTX md; ++ EVP_MD_CTX *md; + +- EVP_DigestInit(&md, evp_md); +- EVP_DigestUpdate(&md, digest, len); +- EVP_DigestFinal(&md, hash, hlen); ++ md = EVP_MD_CTX_new(); ++ EVP_DigestInit(md, evp_md); ++ EVP_DigestUpdate(md, digest, len); ++ EVP_DigestFinal(md, hash, hlen); ++ EVP_MD_CTX_free(md); + } + + EVPCTX evp_init(int nid) + { + const EVP_MD *evp_md = nid_to_evpmd(nid); + +- EVPCTX ctx = malloc(sizeof(EVP_MD_CTX)); ++ EVPCTX ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { + return NULL; + } +@@ -322,32 +326,33 @@ void ssh_mac_final(unsigned char *md, ss + HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) { + HMACCTX ctx = NULL; + +- ctx = malloc(sizeof(*ctx)); ++ ctx = HMAC_CTX_new(); + if (ctx == NULL) { + return NULL; + } + + #ifndef OLD_CRYPTO +- HMAC_CTX_init(ctx); // openssl 0.9.7 requires it. ++ HMAC_CTX_reset(ctx); // openssl 0.9.7 requires it. + #endif + + switch(type) { + case SSH_HMAC_SHA1: +- HMAC_Init(ctx, key, len, EVP_sha1()); ++ HMAC_Init_ex(ctx, key, len, EVP_sha1(), NULL); + break; + case SSH_HMAC_SHA256: +- HMAC_Init(ctx, key, len, EVP_sha256()); ++ HMAC_Init_ex(ctx, key, len, EVP_sha256(), NULL); + break; + case SSH_HMAC_SHA384: +- HMAC_Init(ctx, key, len, EVP_sha384()); ++ HMAC_Init_ex(ctx, key, len, EVP_sha384(), NULL); + break; + case SSH_HMAC_SHA512: +- HMAC_Init(ctx, key, len, EVP_sha512()); ++ HMAC_Init_ex(ctx, key, len, EVP_sha512(), NULL); + break; + case SSH_HMAC_MD5: +- HMAC_Init(ctx, key, len, EVP_md5()); ++ HMAC_Init_ex(ctx, key, len, EVP_md5(), NULL); + break; + default: ++ HMAC_CTX_free(ctx); + SAFE_FREE(ctx); + ctx = NULL; + } +@@ -363,7 +368,8 @@ void hmac_final(HMACCTX ctx, unsigned ch + HMAC_Final(ctx,hashmacbuf,len); + + #ifndef OLD_CRYPTO +- HMAC_CTX_cleanup(ctx); ++ HMAC_CTX_free(ctx); ++ ctx = NULL; + #else + HMAC_cleanup(ctx); + #endif +@@ -455,7 +461,11 @@ static void aes_ctr128_encrypt(struct ss + * Same for num, which is being used to store the current offset in blocksize in CTR + * function. + */ ++#if OPENSSL_VERSION_NUMBER < 0x10100000L + AES_ctr128_encrypt(in, out, len, cipher->key, cipher->IV, tmp_buffer, &num); ++#else ++ CRYPTO_ctr128_encrypt(in, out, len, cipher->key, cipher->IV, tmp_buffer, &num, (block128_f)AES_encrypt); ++#endif + } + #endif /* BROKEN_AES_CTR */ + #endif /* HAS_AES */ +--- a/src/pki_crypto.c ++++ b/src/pki_crypto.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include "libcrypto-compat.h" + + #ifdef HAVE_OPENSSL_EC_H + #include +@@ -230,7 +231,10 @@ ssh_key pki_key_dup(const ssh_key key, i + } + + switch (key->type) { +- case SSH_KEYTYPE_DSS: ++ case SSH_KEYTYPE_DSS: { ++ const BIGNUM *p = NULL, *q = NULL, *g = NULL, ++ *pub_key = NULL, *priv_key = NULL; ++ BIGNUM *np, *nq, *ng, *npub_key, *npriv_key; + new->dsa = DSA_new(); + if (new->dsa == NULL) { + goto fail; +@@ -243,36 +247,54 @@ ssh_key pki_key_dup(const ssh_key key, i + * pub_key = public key y = g^x + * priv_key = private key x + */ +- new->dsa->p = BN_dup(key->dsa->p); +- if (new->dsa->p == NULL) { ++ DSA_get0_pqg(key->dsa, &p, &q, &g); ++ np = BN_dup(p); ++ nq = BN_dup(q); ++ ng = BN_dup(g); ++ if (np == NULL || nq == NULL || ng == NULL) { ++ BN_free(np); ++ BN_free(nq); ++ BN_free(ng); + goto fail; + } + +- new->dsa->q = BN_dup(key->dsa->q); +- if (new->dsa->q == NULL) { ++ rc = DSA_set0_pqg(new->dsa, np, nq, ng); ++ if (rc == 0) { ++ BN_free(np); ++ BN_free(nq); ++ BN_free(ng); + goto fail; + } + +- new->dsa->g = BN_dup(key->dsa->g); +- if (new->dsa->g == NULL) { ++ DSA_get0_key(key->dsa, &pub_key, &priv_key); ++ npub_key = BN_dup(pub_key); ++ if (npub_key == NULL) { + goto fail; + } + +- new->dsa->pub_key = BN_dup(key->dsa->pub_key); +- if (new->dsa->pub_key == NULL) { ++ rc = DSA_set0_key(new->dsa, npub_key, NULL); ++ if (rc == 0) { + goto fail; + } + + if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { +- new->dsa->priv_key = BN_dup(key->dsa->priv_key); +- if (new->dsa->priv_key == NULL) { ++ npriv_key = BN_dup(priv_key); ++ if (npriv_key == NULL) { ++ goto fail; ++ } ++ ++ rc = DSA_set0_key(new->dsa, NULL, npriv_key); ++ if (rc == 0) { + goto fail; + } + } + + break; ++ } + case SSH_KEYTYPE_RSA: +- case SSH_KEYTYPE_RSA1: ++ case SSH_KEYTYPE_RSA1: { ++ const BIGNUM *n = NULL, *e = NULL, *d = NULL; ++ BIGNUM *nn, *ne, *nd; + new->rsa = RSA_new(); + if (new->rsa == NULL) { + goto fail; +@@ -288,62 +310,82 @@ ssh_key pki_key_dup(const ssh_key key, i + * dmq1 = d mod (q-1) + * iqmp = q^-1 mod p + */ +- new->rsa->n = BN_dup(key->rsa->n); +- if (new->rsa->n == NULL) { ++ RSA_get0_key(key->rsa, &n, &e, &d); ++ nn = BN_dup(n); ++ ne = BN_dup(e); ++ if (nn == NULL || ne == NULL) { ++ BN_free(nn); ++ BN_free(ne); + goto fail; + } + +- new->rsa->e = BN_dup(key->rsa->e); +- if (new->rsa->e == NULL) { ++ rc = RSA_set0_key(new->rsa, nn, ne, NULL); ++ if (rc == 0) { ++ BN_free(nn); ++ BN_free(ne); + goto fail; + } + + if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { +- new->rsa->d = BN_dup(key->rsa->d); +- if (new->rsa->d == NULL) { ++ const BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL, ++ *dmq1 = NULL, *iqmp = NULL; ++ BIGNUM *np, *nq, *ndmp1, *ndmq1, *niqmp; ++ ++ nd = BN_dup(d); ++ if (nd == NULL) { ++ goto fail; ++ } ++ ++ rc = RSA_set0_key(new->rsa, NULL, NULL, nd); ++ if (rc == 0) { + goto fail; + } + + /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the + * RSA operations are much faster when these values are available. + */ +- if (key->rsa->p != NULL) { +- new->rsa->p = BN_dup(key->rsa->p); +- if (new->rsa->p == NULL) { ++ RSA_get0_factors(key->rsa, &p, &q); ++ if (p != NULL && q != NULL) { /* need to set both of them */ ++ np = BN_dup(p); ++ nq = BN_dup(q); ++ if (np == NULL || nq == NULL) { ++ BN_free(np); ++ BN_free(nq); + goto fail; + } +- } + +- if (key->rsa->q != NULL) { +- new->rsa->q = BN_dup(key->rsa->q); +- if (new->rsa->q == NULL) { ++ rc = RSA_set0_factors(new->rsa, np, nq); ++ if (rc == 0) { ++ BN_free(np); ++ BN_free(nq); + goto fail; + } + } + +- if (key->rsa->dmp1 != NULL) { +- new->rsa->dmp1 = BN_dup(key->rsa->dmp1); +- if (new->rsa->dmp1 == NULL) { ++ RSA_get0_crt_params(key->rsa, &dmp1, &dmq1, &iqmp); ++ if (dmp1 != NULL || dmq1 != NULL || iqmp != NULL) { ++ ndmp1 = BN_dup(dmp1); ++ ndmq1 = BN_dup(dmq1); ++ niqmp = BN_dup(iqmp); ++ if (ndmp1 == NULL || ndmq1 == NULL || niqmp == NULL) { ++ BN_free(ndmp1); ++ BN_free(ndmq1); ++ BN_free(niqmp); + goto fail; + } +- } + +- if (key->rsa->dmq1 != NULL) { +- new->rsa->dmq1 = BN_dup(key->rsa->dmq1); +- if (new->rsa->dmq1 == NULL) { +- goto fail; +- } +- } +- +- if (key->rsa->iqmp != NULL) { +- new->rsa->iqmp = BN_dup(key->rsa->iqmp); +- if (new->rsa->iqmp == NULL) { ++ rc = RSA_set0_crt_params(new->rsa, ndmp1, ndmq1, niqmp); ++ if (rc == 0) { ++ BN_free(ndmp1); ++ BN_free(ndmq1); ++ BN_free(niqmp); + goto fail; + } + } + } + + break; ++ } + case SSH_KEYTYPE_ECDSA: + #ifdef HAVE_OPENSSL_ECC + new->ecdsa_nid = key->ecdsa_nid; +@@ -409,11 +451,30 @@ int pki_key_generate_rsa(ssh_key key, in + + int pki_key_generate_dss(ssh_key key, int parameter){ + int rc; ++#if OPENSSL_VERSION_NUMBER > 0x10100000L ++ key->dsa = DSA_new(); ++ if (key->dsa == NULL) { ++ return SSH_ERROR; ++ } ++ rc = DSA_generate_parameters_ex(key->dsa, ++ parameter, ++ NULL, /* seed */ ++ 0, /* seed_len */ ++ NULL, /* counter_ret */ ++ NULL, /* h_ret */ ++ NULL); /* cb */ ++ if (rc != 1) { ++ DSA_free(key->dsa); ++ key->dsa = NULL; ++ return SSH_ERROR; ++ } ++#else + key->dsa = DSA_generate_parameters(parameter, NULL, 0, NULL, NULL, + NULL, NULL); + if(key->dsa == NULL){ + return SSH_ERROR; + } ++#endif + rc = DSA_generate_key(key->dsa); + if (rc != 1){ + DSA_free(key->dsa); +@@ -466,51 +527,64 @@ int pki_key_compare(const ssh_key k1, + enum ssh_keycmp_e what) + { + switch (k1->type) { +- case SSH_KEYTYPE_DSS: ++ case SSH_KEYTYPE_DSS: { ++ const BIGNUM *p1, *p2, *q1, *q2, *g1, *g2, ++ *pub_key1, *pub_key2, *priv_key1, *priv_key2; + if (DSA_size(k1->dsa) != DSA_size(k2->dsa)) { + return 1; + } +- if (bignum_cmp(k1->dsa->p, k2->dsa->p) != 0) { ++ DSA_get0_pqg(k1->dsa, &p1, &q1, &g1); ++ DSA_get0_pqg(k2->dsa, &p2, &q2, &g2); ++ if (bignum_cmp(p1, p2) != 0) { + return 1; + } +- if (bignum_cmp(k1->dsa->q, k2->dsa->q) != 0) { ++ if (bignum_cmp(q1, q2) != 0) { + return 1; + } +- if (bignum_cmp(k1->dsa->g, k2->dsa->g) != 0) { ++ if (bignum_cmp(g1, g2) != 0) { + return 1; + } +- if (bignum_cmp(k1->dsa->pub_key, k2->dsa->pub_key) != 0) { ++ DSA_get0_key(k1->dsa, &pub_key1, &priv_key1); ++ DSA_get0_key(k2->dsa, &pub_key2, &priv_key2); ++ if (bignum_cmp(pub_key1, pub_key2) != 0) { + return 1; + } + + if (what == SSH_KEY_CMP_PRIVATE) { +- if (bignum_cmp(k1->dsa->priv_key, k2->dsa->priv_key) != 0) { ++ if (bignum_cmp(priv_key1, priv_key2) != 0) { + return 1; + } + } + break; ++ } + case SSH_KEYTYPE_RSA: +- case SSH_KEYTYPE_RSA1: ++ case SSH_KEYTYPE_RSA1: { ++ const BIGNUM *e1, *e2, *n1, *n2, *p1, *p2, *q1, *q2; + if (RSA_size(k1->rsa) != RSA_size(k2->rsa)) { + return 1; + } +- if (bignum_cmp(k1->rsa->e, k2->rsa->e) != 0) { ++ RSA_get0_key(k1->rsa, &n1, &e1, NULL); ++ RSA_get0_key(k2->rsa, &n2, &e2, NULL); ++ if (bignum_cmp(e1, e2) != 0) { + return 1; + } +- if (bignum_cmp(k1->rsa->n, k2->rsa->n) != 0) { ++ if (bignum_cmp(n1, n2) != 0) { + return 1; + } + + if (what == SSH_KEY_CMP_PRIVATE) { +- if (bignum_cmp(k1->rsa->p, k2->rsa->p) != 0) { ++ RSA_get0_factors(k1->rsa, &p1, &q1); ++ RSA_get0_factors(k2->rsa, &p2, &q2); ++ if (bignum_cmp(p1, p2) != 0) { + return 1; + } + +- if (bignum_cmp(k1->rsa->q, k2->rsa->q) != 0) { ++ if (bignum_cmp(q1, q2) != 0) { + return 1; + } + } + break; ++ } + case SSH_KEYTYPE_ECDSA: + #ifdef HAVE_OPENSSL_ECC + { +@@ -586,7 +660,7 @@ ssh_string pki_private_key_to_pem(const + } else { + rc = PEM_write_bio_DSAPrivateKey(mem, + key->dsa, +- NULL, /* cipher */ ++ EVP_aes_128_cbc(), + NULL, /* kstr */ + 0, /* klen */ + NULL, /* auth_fn */ +@@ -611,7 +685,7 @@ ssh_string pki_private_key_to_pem(const + } else { + rc = PEM_write_bio_RSAPrivateKey(mem, + key->rsa, +- NULL, /* cipher */ ++ EVP_aes_128_cbc(), + NULL, /* kstr */ + 0, /* klen */ + NULL, /* auth_fn */ +@@ -621,8 +695,8 @@ ssh_string pki_private_key_to_pem(const + goto err; + } + break; +- case SSH_KEYTYPE_ECDSA: + #ifdef HAVE_ECC ++ case SSH_KEYTYPE_ECDSA: + if (passphrase == NULL) { + struct pem_get_password_struct pgp = { auth_fn, auth_data }; + +@@ -636,7 +710,7 @@ ssh_string pki_private_key_to_pem(const + } else { + rc = PEM_write_bio_ECPrivateKey(mem, + key->ecdsa, +- NULL, /* cipher */ ++ EVP_aes_128_cbc(), + NULL, /* kstr */ + 0, /* klen */ + NULL, /* auth_fn */ +@@ -819,43 +893,65 @@ int pki_pubkey_build_dss(ssh_key key, + ssh_string q, + ssh_string g, + ssh_string pubkey) { ++ int rc; ++ BIGNUM *bp, *bq, *bg, *bpub_key; ++ + key->dsa = DSA_new(); + if (key->dsa == NULL) { + return SSH_ERROR; + } + +- key->dsa->p = make_string_bn(p); +- key->dsa->q = make_string_bn(q); +- key->dsa->g = make_string_bn(g); +- key->dsa->pub_key = make_string_bn(pubkey); +- if (key->dsa->p == NULL || +- key->dsa->q == NULL || +- key->dsa->g == NULL || +- key->dsa->pub_key == NULL) { +- DSA_free(key->dsa); +- return SSH_ERROR; ++ bp = make_string_bn(p); ++ bq = make_string_bn(q); ++ bg = make_string_bn(g); ++ bpub_key = make_string_bn(pubkey); ++ if (bp == NULL || bq == NULL || ++ bg == NULL || bpub_key == NULL) { ++ goto fail; ++ } ++ ++ rc = DSA_set0_pqg(key->dsa, bp, bq, bg); ++ if (rc == 0) { ++ goto fail; ++ } ++ ++ rc = DSA_set0_key(key->dsa, bpub_key, NULL); ++ if (rc == 0) { ++ goto fail; + } + + return SSH_OK; ++fail: ++ DSA_free(key->dsa); ++ return SSH_ERROR; + } + + int pki_pubkey_build_rsa(ssh_key key, + ssh_string e, + ssh_string n) { ++ int rc; ++ BIGNUM *be, *bn; ++ + key->rsa = RSA_new(); + if (key->rsa == NULL) { + return SSH_ERROR; + } + +- key->rsa->e = make_string_bn(e); +- key->rsa->n = make_string_bn(n); +- if (key->rsa->e == NULL || +- key->rsa->n == NULL) { +- RSA_free(key->rsa); +- return SSH_ERROR; ++ be = make_string_bn(e); ++ bn = make_string_bn(n); ++ if (be == NULL || bn == NULL) { ++ goto fail; ++ } ++ ++ rc = RSA_set0_key(key->rsa, bn, be, NULL); ++ if (rc == 0) { ++ goto fail; + } + + return SSH_OK; ++fail: ++ RSA_free(key->rsa); ++ return SSH_ERROR; + } + + ssh_string pki_publickey_to_blob(const ssh_key key) +@@ -889,23 +985,26 @@ ssh_string pki_publickey_to_blob(const s + } + + switch (key->type) { +- case SSH_KEYTYPE_DSS: +- p = make_bignum_string(key->dsa->p); ++ case SSH_KEYTYPE_DSS: { ++ const BIGNUM *bp, *bq, *bg, *bpub_key; ++ DSA_get0_pqg(key->dsa, &bp, &bq, &bg); ++ p = make_bignum_string((BIGNUM *)bp); + if (p == NULL) { + goto fail; + } + +- q = make_bignum_string(key->dsa->q); ++ q = make_bignum_string((BIGNUM *)bq); + if (q == NULL) { + goto fail; + } + +- g = make_bignum_string(key->dsa->g); ++ g = make_bignum_string((BIGNUM *)bg); + if (g == NULL) { + goto fail; + } + +- n = make_bignum_string(key->dsa->pub_key); ++ DSA_get0_key(key->dsa, &bpub_key, NULL); ++ n = make_bignum_string((BIGNUM *)bpub_key); + if (n == NULL) { + goto fail; + } +@@ -937,14 +1036,17 @@ ssh_string pki_publickey_to_blob(const s + n = NULL; + + break; ++ } + case SSH_KEYTYPE_RSA: +- case SSH_KEYTYPE_RSA1: +- e = make_bignum_string(key->rsa->e); ++ case SSH_KEYTYPE_RSA1: { ++ const BIGNUM *be, *bn; ++ RSA_get0_key(key->rsa, &bn, &be, NULL); ++ e = make_bignum_string((BIGNUM *)be); + if (e == NULL) { + goto fail; + } + +- n = make_bignum_string(key->rsa->n); ++ n = make_bignum_string((BIGNUM *)bn); + if (n == NULL) { + goto fail; + } +@@ -964,6 +1066,7 @@ ssh_string pki_publickey_to_blob(const s + n = NULL; + + break; ++ } + case SSH_KEYTYPE_ECDSA: + #ifdef HAVE_OPENSSL_ECC + rc = ssh_buffer_reinit(buffer); +@@ -1065,13 +1168,15 @@ int pki_export_pubkey_rsa1(const ssh_key + char *e; + char *n; + int rsa_size = RSA_size(key->rsa); ++ const BIGNUM *be, *bn; + +- e = bignum_bn2dec(key->rsa->e); ++ RSA_get0_key(key->rsa, &bn, &be, NULL); ++ e = bignum_bn2dec(be); + if (e == NULL) { + return SSH_ERROR; + } + +- n = bignum_bn2dec(key->rsa->n); ++ n = bignum_bn2dec(bn); + if (n == NULL) { + OPENSSL_free(e); + return SSH_ERROR; +@@ -1136,6 +1241,7 @@ static ssh_string pki_dsa_signature_to_b + { + char buffer[40] = { 0 }; + ssh_string sig_blob = NULL; ++ const BIGNUM *pr, *ps; + + ssh_string r; + int r_len, r_offset_in, r_offset_out; +@@ -1143,12 +1249,13 @@ static ssh_string pki_dsa_signature_to_b + ssh_string s; + int s_len, s_offset_in, s_offset_out; + +- r = make_bignum_string(sig->dsa_sig->r); ++ DSA_SIG_get0(sig->dsa_sig, &pr, &ps); ++ r = make_bignum_string((BIGNUM *)pr); + if (r == NULL) { + return NULL; + } + +- s = make_bignum_string(sig->dsa_sig->s); ++ s = make_bignum_string((BIGNUM *)ps); + if (s == NULL) { + ssh_string_free(r); + return NULL; +@@ -1201,13 +1308,15 @@ ssh_string pki_signature_to_blob(const s + ssh_string s; + ssh_buffer b; + int rc; ++ const BIGNUM *pr, *ps; + + b = ssh_buffer_new(); + if (b == NULL) { + return NULL; + } + +- r = make_bignum_string(sig->ecdsa_sig->r); ++ ECDSA_SIG_get0(sig->ecdsa_sig, &pr, &ps); ++ r = make_bignum_string((BIGNUM *)pr); + if (r == NULL) { + ssh_buffer_free(b); + return NULL; +@@ -1219,7 +1328,7 @@ ssh_string pki_signature_to_blob(const s + return NULL; + } + +- s = make_bignum_string(sig->ecdsa_sig->s); ++ s = make_bignum_string((BIGNUM *)ps); + if (s == NULL) { + ssh_buffer_free(b); + return NULL; +@@ -1324,6 +1433,7 @@ ssh_signature pki_signature_from_blob(co + ssh_string s; + size_t len; + int rc; ++ BIGNUM *pr = NULL, *ps = NULL; + + sig = ssh_signature_new(); + if (sig == NULL) { +@@ -1363,9 +1473,9 @@ ssh_signature pki_signature_from_blob(co + } + ssh_string_fill(r, ssh_string_data(sig_blob), 20); + +- sig->dsa_sig->r = make_string_bn(r); ++ pr = make_string_bn(r); + ssh_string_free(r); +- if (sig->dsa_sig->r == NULL) { ++ if (pr == NULL) { + ssh_signature_free(sig); + return NULL; + } +@@ -1377,9 +1487,15 @@ ssh_signature pki_signature_from_blob(co + } + ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20); + +- sig->dsa_sig->s = make_string_bn(s); ++ ps = make_string_bn(s); + ssh_string_free(s); +- if (sig->dsa_sig->s == NULL) { ++ if (ps == NULL) { ++ ssh_signature_free(sig); ++ return NULL; ++ } ++ ++ rc = DSA_SIG_set0(sig->dsa_sig, pr, ps); ++ if (rc == 0) { + ssh_signature_free(sig); + return NULL; + } +@@ -1427,17 +1543,17 @@ ssh_signature pki_signature_from_blob(co + ssh_print_hexa("r", ssh_string_data(r), ssh_string_len(r)); + #endif + +- make_string_bn_inplace(r, sig->ecdsa_sig->r); ++ pr = make_string_bn(r); + ssh_string_burn(r); + ssh_string_free(r); +- if (sig->ecdsa_sig->r == NULL) { ++ if (pr == NULL) { + ssh_buffer_free(b); + ssh_signature_free(sig); + return NULL; + } + + s = buffer_get_ssh_string(b); +- rlen = buffer_get_rest_len(b); ++ rlen = buffer_get_len(b); + ssh_buffer_free(b); + if (s == NULL) { + ssh_signature_free(sig); +@@ -1448,10 +1564,16 @@ ssh_signature pki_signature_from_blob(co + ssh_print_hexa("s", ssh_string_data(s), ssh_string_len(s)); + #endif + +- make_string_bn_inplace(s, sig->ecdsa_sig->s); ++ ps = make_string_bn(s); + ssh_string_burn(s); + ssh_string_free(s); +- if (sig->ecdsa_sig->s == NULL) { ++ if (ps == NULL) { ++ ssh_signature_free(sig); ++ return NULL; ++ } ++ ++ rc = ECDSA_SIG_set0(sig->ecdsa_sig, pr, ps); ++ if (rc == 0) { + ssh_signature_free(sig); + return NULL; + } +@@ -1578,8 +1700,12 @@ ssh_signature pki_do_sign(const ssh_key + } + + #ifdef DEBUG_CRYPTO +- ssh_print_bignum("r", sig->dsa_sig->r); +- ssh_print_bignum("s", sig->dsa_sig->s); ++ { ++ const BIGNUM *pr, *ps; ++ DSA_SIG_get0(sig->dsa_sig, &pr, &ps); ++ ssh_print_bignum("r", (BIGNUM *) pr); ++ ssh_print_bignum("s", (BIGNUM *) ps); ++ } + #endif + + break; +@@ -1601,8 +1727,12 @@ ssh_signature pki_do_sign(const ssh_key + } + + # ifdef DEBUG_CRYPTO +- ssh_print_bignum("r", sig->ecdsa_sig->r); +- ssh_print_bignum("s", sig->ecdsa_sig->s); ++ { ++ const BIGNUM *pr, *ps; ++ ECDSA_SIG_get0(sig->ecdsa_sig, &pr, &ps); ++ ssh_print_bignum("r", (BIGNUM *) pr); ++ ssh_print_bignum("s", (BIGNUM *) ps); ++ } + # endif /* DEBUG_CRYPTO */ + + break; +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -164,6 +164,9 @@ else (WITH_GCRYPT) + ${libssh_SRCS} + pki_crypto.c + ) ++ if(OPENSSL_VERSION VERSION_LESS "1.1.0") ++ set(libssh_SRCS ${libssh_SRCS} libcrypto-compat.c) ++ endif() + endif (WITH_GCRYPT) + + if (WITH_SFTP) +--- /dev/null ++++ b/src/libcrypto-compat.c +@@ -0,0 +1,334 @@ ++/* ++ * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. ++ * ++ * Licensed under the OpenSSL license (the "License"). You may not use ++ * this file except in compliance with the License. You can obtain a copy ++ * in the file LICENSE in the source distribution or at ++ * https://www.openssl.org/source/license.html ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include "libcrypto-compat.h" ++ ++static void *OPENSSL_zalloc(size_t num) ++{ ++ void *ret = OPENSSL_malloc(num); ++ ++ if (ret != NULL) ++ memset(ret, 0, num); ++ return ret; ++} ++ ++int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) ++{ ++ /* If the fields n and e in r are NULL, the corresponding input ++ * parameters MUST be non-NULL for n and e. d may be ++ * left NULL (in case only the public key is used). ++ */ ++ 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; ++} ++ ++int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) ++{ ++ /* If the fields p and q in r are NULL, the corresponding input ++ * parameters MUST be non-NULL. ++ */ ++ 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; ++} ++ ++int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) ++{ ++ /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input ++ * parameters MUST be non-NULL. ++ */ ++ 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; ++} ++ ++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; ++} ++ ++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; ++} ++ ++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; ++} ++ ++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; ++} ++ ++int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) ++{ ++ /* If the fields p, q and g in d are NULL, the corresponding input ++ * parameters MUST be non-NULL. ++ */ ++ 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; ++} ++ ++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; ++} ++ ++int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) ++{ ++ /* If the field pub_key in d is NULL, the corresponding input ++ * parameters MUST be non-NULL. The priv_key field may ++ * be left NULL. ++ */ ++ 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; ++} ++ ++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; ++} ++ ++int DSA_SIG_set0(DSA_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; ++} ++ ++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; ++} ++ ++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; ++} ++ ++EVP_MD_CTX *EVP_MD_CTX_new(void) ++{ ++ return OPENSSL_zalloc(sizeof(EVP_MD_CTX)); ++} ++ ++static void OPENSSL_clear_free(void *str, size_t num) ++{ ++ if (str == NULL) ++ return; ++ if (num) ++ OPENSSL_cleanse(str, num); ++ OPENSSL_free(str); ++} ++ ++/* This call frees resources associated with the context */ ++int EVP_MD_CTX_reset(EVP_MD_CTX *ctx) ++{ ++ if (ctx == NULL) ++ return 1; ++ ++ /* ++ * Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because ++ * sometimes only copies of the context are ever finalised. ++ */ ++ if (ctx->digest && ctx->digest->cleanup ++ && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED)) ++ ctx->digest->cleanup(ctx); ++ if (ctx->digest && ctx->digest->ctx_size && ctx->md_data ++ && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) { ++ OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size); ++ } ++ EVP_PKEY_CTX_free(ctx->pctx); ++#ifndef OPENSSL_NO_ENGINE ++ ENGINE_finish(ctx->engine); ++#endif ++ OPENSSL_cleanse(ctx, sizeof(*ctx)); ++ ++ return 1; ++} ++ ++void EVP_MD_CTX_free(EVP_MD_CTX *ctx) ++{ ++ EVP_MD_CTX_reset(ctx); ++ OPENSSL_free(ctx); ++} ++ ++HMAC_CTX *HMAC_CTX_new(void) ++{ ++ HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX)); ++ ++ if (ctx != NULL) { ++ if (!HMAC_CTX_reset(ctx)) { ++ HMAC_CTX_free(ctx); ++ return NULL; ++ } ++ } ++ return ctx; ++} ++ ++static void hmac_ctx_cleanup(HMAC_CTX *ctx) ++{ ++ EVP_MD_CTX_reset(&ctx->i_ctx); ++ EVP_MD_CTX_reset(&ctx->o_ctx); ++ EVP_MD_CTX_reset(&ctx->md_ctx); ++ ctx->md = NULL; ++ ctx->key_length = 0; ++ OPENSSL_cleanse(ctx->key, sizeof(ctx->key)); ++} ++ ++void HMAC_CTX_free(HMAC_CTX *ctx) ++{ ++ if (ctx != NULL) { ++ hmac_ctx_cleanup(ctx); ++#if OPENSSL_VERSION_NUMBER > 0x10100000L ++ EVP_MD_CTX_free(&ctx->i_ctx); ++ EVP_MD_CTX_free(&ctx->o_ctx); ++ EVP_MD_CTX_free(&ctx->md_ctx); ++#endif ++ OPENSSL_free(ctx); ++ } ++} ++ ++int HMAC_CTX_reset(HMAC_CTX *ctx) ++{ ++ HMAC_CTX_init(ctx); ++ return 1; ++} ++ ++#ifndef HAVE_OPENSSL_EVP_CIPHER_CTX_NEW ++EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) ++{ ++ return OPENSSL_zalloc(sizeof(EVP_CIPHER_CTX)); ++} ++ ++void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) ++{ ++ /* EVP_CIPHER_CTX_reset(ctx); alias */ ++ EVP_CIPHER_CTX_init(ctx); ++ OPENSSL_free(ctx); ++} ++#endif +--- /dev/null ++++ b/src/libcrypto-compat.h +@@ -0,0 +1,42 @@ ++#ifndef LIBCRYPTO_COMPAT_H ++#define LIBCRYPTO_COMPAT_H ++ ++#include ++#if OPENSSL_VERSION_NUMBER < 0x10100000L ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); ++int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); ++int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp); ++void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); ++void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); ++void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp); ++ ++void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); ++int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g); ++void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key); ++int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); ++ ++void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); ++int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s); ++ ++void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); ++int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); ++ ++int EVP_MD_CTX_reset(EVP_MD_CTX *ctx); ++EVP_MD_CTX *EVP_MD_CTX_new(void); ++void EVP_MD_CTX_free(EVP_MD_CTX *ctx); ++ ++HMAC_CTX *HMAC_CTX_new(void); ++int HMAC_CTX_reset(HMAC_CTX *ctx); ++void HMAC_CTX_free(HMAC_CTX *ctx); ++ ++#endif /* OPENSSL_VERSION_NUMBER */ ++ ++#endif /* LIBCRYPTO_COMPAT_H */