1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-11-30 13:01:23 +03:00

pki_crypto: Use getters and setters for opaque keys and signatures

This is for OpenSSL 1.1.0 support.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
Jakub Jelen
2016-11-02 17:02:58 +01:00
committed by Andreas Schneider
parent 5d2e9ee66e
commit 3341f49a49

View File

@@ -31,6 +31,7 @@
#include <openssl/dsa.h> #include <openssl/dsa.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include "libcrypto-compat.h"
#ifdef HAVE_OPENSSL_EC_H #ifdef HAVE_OPENSSL_EC_H
#include <openssl/ec.h> #include <openssl/ec.h>
@@ -230,7 +231,10 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
} }
switch (key->type) { 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(); new->dsa = DSA_new();
if (new->dsa == NULL) { if (new->dsa == NULL) {
goto fail; goto fail;
@@ -243,36 +247,54 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
* pub_key = public key y = g^x * pub_key = public key y = g^x
* priv_key = private key x * priv_key = private key x
*/ */
new->dsa->p = BN_dup(key->dsa->p); DSA_get0_pqg(key->dsa, &p, &q, &g);
if (new->dsa->p == NULL) { 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; goto fail;
} }
new->dsa->q = BN_dup(key->dsa->q); rc = DSA_set0_pqg(new->dsa, np, nq, ng);
if (new->dsa->q == NULL) { if (rc == 0) {
BN_free(np);
BN_free(nq);
BN_free(ng);
goto fail; goto fail;
} }
new->dsa->g = BN_dup(key->dsa->g); DSA_get0_key(key->dsa, &pub_key, &priv_key);
if (new->dsa->g == NULL) { npub_key = BN_dup(pub_key);
if (npub_key == NULL) {
goto fail; goto fail;
} }
new->dsa->pub_key = BN_dup(key->dsa->pub_key); rc = DSA_set0_key(new->dsa, npub_key, NULL);
if (new->dsa->pub_key == NULL) { if (rc == 0) {
goto fail; goto fail;
} }
if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) {
new->dsa->priv_key = BN_dup(key->dsa->priv_key); npriv_key = BN_dup(priv_key);
if (new->dsa->priv_key == NULL) { if (npriv_key == NULL) {
goto fail;
}
rc = DSA_set0_key(new->dsa, NULL, npriv_key);
if (rc == 0) {
goto fail; goto fail;
} }
} }
break; break;
}
case SSH_KEYTYPE_RSA: 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(); new->rsa = RSA_new();
if (new->rsa == NULL) { if (new->rsa == NULL) {
goto fail; goto fail;
@@ -288,62 +310,82 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
* dmq1 = d mod (q-1) * dmq1 = d mod (q-1)
* iqmp = q^-1 mod p * iqmp = q^-1 mod p
*/ */
new->rsa->n = BN_dup(key->rsa->n); RSA_get0_key(key->rsa, &n, &e, &d);
if (new->rsa->n == NULL) { nn = BN_dup(n);
ne = BN_dup(e);
if (nn == NULL || ne == NULL) {
BN_free(nn);
BN_free(ne);
goto fail; goto fail;
} }
new->rsa->e = BN_dup(key->rsa->e); rc = RSA_set0_key(new->rsa, nn, ne, NULL);
if (new->rsa->e == NULL) { if (rc == 0) {
BN_free(nn);
BN_free(ne);
goto fail; goto fail;
} }
if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) {
new->rsa->d = BN_dup(key->rsa->d); const BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL,
if (new->rsa->d == 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; goto fail;
} }
/* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the
* RSA operations are much faster when these values are available. * RSA operations are much faster when these values are available.
*/ */
if (key->rsa->p != NULL) { RSA_get0_factors(key->rsa, &p, &q);
new->rsa->p = BN_dup(key->rsa->p); if (p != NULL && q != NULL) { /* need to set both of them */
if (new->rsa->p == NULL) { np = BN_dup(p);
nq = BN_dup(q);
if (np == NULL || nq == NULL) {
BN_free(np);
BN_free(nq);
goto fail;
}
rc = RSA_set0_factors(new->rsa, np, nq);
if (rc == 0) {
BN_free(np);
BN_free(nq);
goto fail; goto fail;
} }
} }
if (key->rsa->q != NULL) { RSA_get0_crt_params(key->rsa, &dmp1, &dmq1, &iqmp);
new->rsa->q = BN_dup(key->rsa->q); if (dmp1 != NULL || dmq1 != NULL || iqmp != NULL) {
if (new->rsa->q == 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; goto fail;
} }
}
if (key->rsa->dmp1 != NULL) { rc = RSA_set0_crt_params(new->rsa, ndmp1, ndmq1, niqmp);
new->rsa->dmp1 = BN_dup(key->rsa->dmp1); if (rc == 0) {
if (new->rsa->dmp1 == NULL) { BN_free(ndmp1);
goto fail; BN_free(ndmq1);
} BN_free(niqmp);
}
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) {
goto fail; goto fail;
} }
} }
} }
break; break;
}
case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_OPENSSL_ECC #ifdef HAVE_OPENSSL_ECC
new->ecdsa_nid = key->ecdsa_nid; new->ecdsa_nid = key->ecdsa_nid;
@@ -466,51 +508,64 @@ int pki_key_compare(const ssh_key k1,
enum ssh_keycmp_e what) enum ssh_keycmp_e what)
{ {
switch (k1->type) { 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)) { if (DSA_size(k1->dsa) != DSA_size(k2->dsa)) {
return 1; 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; return 1;
} }
if (bignum_cmp(k1->dsa->q, k2->dsa->q) != 0) { if (bignum_cmp(q1, q2) != 0) {
return 1; return 1;
} }
if (bignum_cmp(k1->dsa->g, k2->dsa->g) != 0) { if (bignum_cmp(g1, g2) != 0) {
return 1; 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; return 1;
} }
if (what == SSH_KEY_CMP_PRIVATE) { 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; return 1;
} }
} }
break; break;
}
case SSH_KEYTYPE_RSA: 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)) { if (RSA_size(k1->rsa) != RSA_size(k2->rsa)) {
return 1; 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; return 1;
} }
if (bignum_cmp(k1->rsa->n, k2->rsa->n) != 0) { if (bignum_cmp(n1, n2) != 0) {
return 1; return 1;
} }
if (what == SSH_KEY_CMP_PRIVATE) { 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; return 1;
} }
if (bignum_cmp(k1->rsa->q, k2->rsa->q) != 0) { if (bignum_cmp(q1, q2) != 0) {
return 1; return 1;
} }
} }
break; break;
}
case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_OPENSSL_ECC #ifdef HAVE_OPENSSL_ECC
{ {
@@ -826,43 +881,65 @@ int pki_pubkey_build_dss(ssh_key key,
ssh_string q, ssh_string q,
ssh_string g, ssh_string g,
ssh_string pubkey) { ssh_string pubkey) {
int rc;
BIGNUM *bp, *bq, *bg, *bpub_key;
key->dsa = DSA_new(); key->dsa = DSA_new();
if (key->dsa == NULL) { if (key->dsa == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }
key->dsa->p = ssh_make_string_bn(p); bp = ssh_make_string_bn(p);
key->dsa->q = ssh_make_string_bn(q); bq = ssh_make_string_bn(q);
key->dsa->g = ssh_make_string_bn(g); bg = ssh_make_string_bn(g);
key->dsa->pub_key = ssh_make_string_bn(pubkey); bpub_key = ssh_make_string_bn(pubkey);
if (key->dsa->p == NULL || if (bp == NULL || bq == NULL ||
key->dsa->q == NULL || bg == NULL || bpub_key == NULL) {
key->dsa->g == NULL || goto fail;
key->dsa->pub_key == NULL) { }
DSA_free(key->dsa);
return SSH_ERROR; 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; return SSH_OK;
fail:
DSA_free(key->dsa);
return SSH_ERROR;
} }
int pki_pubkey_build_rsa(ssh_key key, int pki_pubkey_build_rsa(ssh_key key,
ssh_string e, ssh_string e,
ssh_string n) { ssh_string n) {
int rc;
BIGNUM *be, *bn;
key->rsa = RSA_new(); key->rsa = RSA_new();
if (key->rsa == NULL) { if (key->rsa == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }
key->rsa->e = ssh_make_string_bn(e); be = ssh_make_string_bn(e);
key->rsa->n = ssh_make_string_bn(n); bn = ssh_make_string_bn(n);
if (key->rsa->e == NULL || if (be == NULL || bn == NULL) {
key->rsa->n == NULL) { goto fail;
RSA_free(key->rsa); }
return SSH_ERROR;
rc = RSA_set0_key(key->rsa, bn, be, NULL);
if (rc == 0) {
goto fail;
} }
return SSH_OK; return SSH_OK;
fail:
RSA_free(key->rsa);
return SSH_ERROR;
} }
ssh_string pki_publickey_to_blob(const ssh_key key) ssh_string pki_publickey_to_blob(const ssh_key key)
@@ -905,23 +982,26 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
} }
switch (key->type) { switch (key->type) {
case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS: {
p = ssh_make_bignum_string(key->dsa->p); const BIGNUM *bp, *bq, *bg, *bpub_key;
DSA_get0_pqg(key->dsa, &bp, &bq, &bg);
p = ssh_make_bignum_string((BIGNUM *)bp);
if (p == NULL) { if (p == NULL) {
goto fail; goto fail;
} }
q = ssh_make_bignum_string(key->dsa->q); q = ssh_make_bignum_string((BIGNUM *)bq);
if (q == NULL) { if (q == NULL) {
goto fail; goto fail;
} }
g = ssh_make_bignum_string(key->dsa->g); g = ssh_make_bignum_string((BIGNUM *)bg);
if (g == NULL) { if (g == NULL) {
goto fail; goto fail;
} }
n = ssh_make_bignum_string(key->dsa->pub_key); DSA_get0_key(key->dsa, &bpub_key, NULL);
n = ssh_make_bignum_string((BIGNUM *)bpub_key);
if (n == NULL) { if (n == NULL) {
goto fail; goto fail;
} }
@@ -953,14 +1033,17 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
n = NULL; n = NULL;
break; break;
}
case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_RSA1: {
e = ssh_make_bignum_string(key->rsa->e); const BIGNUM *be, *bn;
RSA_get0_key(key->rsa, &bn, &be, NULL);
e = ssh_make_bignum_string((BIGNUM *)be);
if (e == NULL) { if (e == NULL) {
goto fail; goto fail;
} }
n = ssh_make_bignum_string(key->rsa->n); n = ssh_make_bignum_string((BIGNUM *)bn);
if (n == NULL) { if (n == NULL) {
goto fail; goto fail;
} }
@@ -980,6 +1063,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
n = NULL; n = NULL;
break; break;
}
case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_OPENSSL_ECC #ifdef HAVE_OPENSSL_ECC
rc = ssh_buffer_reinit(buffer); rc = ssh_buffer_reinit(buffer);
@@ -1082,13 +1166,15 @@ int pki_export_pubkey_rsa1(const ssh_key key,
char *e; char *e;
char *n; char *n;
int rsa_size = RSA_size(key->rsa); 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) { if (e == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }
n = bignum_bn2dec(key->rsa->n); n = bignum_bn2dec(bn);
if (n == NULL) { if (n == NULL) {
OPENSSL_free(e); OPENSSL_free(e);
return SSH_ERROR; return SSH_ERROR;
@@ -1153,6 +1239,7 @@ static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
{ {
char buffer[40] = { 0 }; char buffer[40] = { 0 };
ssh_string sig_blob = NULL; ssh_string sig_blob = NULL;
const BIGNUM *pr, *ps;
ssh_string r; ssh_string r;
int r_len, r_offset_in, r_offset_out; int r_len, r_offset_in, r_offset_out;
@@ -1160,12 +1247,13 @@ static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
ssh_string s; ssh_string s;
int s_len, s_offset_in, s_offset_out; int s_len, s_offset_in, s_offset_out;
r = ssh_make_bignum_string(sig->dsa_sig->r); DSA_SIG_get0(sig->dsa_sig, &pr, &ps);
r = ssh_make_bignum_string((BIGNUM *)pr);
if (r == NULL) { if (r == NULL) {
return NULL; return NULL;
} }
s = ssh_make_bignum_string(sig->dsa_sig->s); s = ssh_make_bignum_string((BIGNUM *)ps);
if (s == NULL) { if (s == NULL) {
ssh_string_free(r); ssh_string_free(r);
return NULL; return NULL;
@@ -1218,13 +1306,15 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
ssh_string s; ssh_string s;
ssh_buffer b; ssh_buffer b;
int rc; int rc;
const BIGNUM *pr, *ps;
b = ssh_buffer_new(); b = ssh_buffer_new();
if (b == NULL) { if (b == NULL) {
return NULL; return NULL;
} }
r = ssh_make_bignum_string(sig->ecdsa_sig->r); ECDSA_SIG_get0(sig->ecdsa_sig, &pr, &ps);
r = ssh_make_bignum_string((BIGNUM *)pr);
if (r == NULL) { if (r == NULL) {
ssh_buffer_free(b); ssh_buffer_free(b);
return NULL; return NULL;
@@ -1236,7 +1326,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
return NULL; return NULL;
} }
s = ssh_make_bignum_string(sig->ecdsa_sig->s); s = ssh_make_bignum_string((BIGNUM *)ps);
if (s == NULL) { if (s == NULL) {
ssh_buffer_free(b); ssh_buffer_free(b);
return NULL; return NULL;
@@ -1345,6 +1435,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
ssh_string s; ssh_string s;
size_t len; size_t len;
int rc; int rc;
BIGNUM *pr = NULL, *ps = NULL;
sig = ssh_signature_new(); sig = ssh_signature_new();
if (sig == NULL) { if (sig == NULL) {
@@ -1385,9 +1476,9 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
} }
ssh_string_fill(r, ssh_string_data(sig_blob), 20); ssh_string_fill(r, ssh_string_data(sig_blob), 20);
sig->dsa_sig->r = ssh_make_string_bn(r); pr = ssh_make_string_bn(r);
ssh_string_free(r); ssh_string_free(r);
if (sig->dsa_sig->r == NULL) { if (pr == NULL) {
ssh_signature_free(sig); ssh_signature_free(sig);
return NULL; return NULL;
} }
@@ -1399,9 +1490,15 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
} }
ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20); ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20);
sig->dsa_sig->s = ssh_make_string_bn(s); ps = ssh_make_string_bn(s);
ssh_string_free(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); ssh_signature_free(sig);
return NULL; return NULL;
} }
@@ -1449,10 +1546,10 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
ssh_print_hexa("r", ssh_string_data(r), ssh_string_len(r)); ssh_print_hexa("r", ssh_string_data(r), ssh_string_len(r));
#endif #endif
ssh_make_string_bn_inplace(r, sig->ecdsa_sig->r); pr = ssh_make_string_bn(r);
ssh_string_burn(r); ssh_string_burn(r);
ssh_string_free(r); ssh_string_free(r);
if (sig->ecdsa_sig->r == NULL) { if (pr == NULL) {
ssh_buffer_free(b); ssh_buffer_free(b);
ssh_signature_free(sig); ssh_signature_free(sig);
return NULL; return NULL;
@@ -1470,10 +1567,16 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
ssh_print_hexa("s", ssh_string_data(s), ssh_string_len(s)); ssh_print_hexa("s", ssh_string_data(s), ssh_string_len(s));
#endif #endif
ssh_make_string_bn_inplace(s, sig->ecdsa_sig->s); ps = ssh_make_string_bn(s);
ssh_string_burn(s); ssh_string_burn(s);
ssh_string_free(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); ssh_signature_free(sig);
return NULL; return NULL;
} }
@@ -1601,8 +1704,12 @@ ssh_signature pki_do_sign(const ssh_key privkey,
} }
#ifdef DEBUG_CRYPTO #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 #endif
break; break;
@@ -1624,8 +1731,12 @@ ssh_signature pki_do_sign(const ssh_key privkey,
} }
# ifdef DEBUG_CRYPTO # 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 */ # endif /* DEBUG_CRYPTO */
break; break;