aboutsummaryrefslogtreecommitdiff
path: root/src/pki_crypto.c
diff options
context:
space:
mode:
authorJakub Jelen <jjelen@redhat.com>2018-09-06 17:53:19 +0200
committerAndreas Schneider <asn@cryptomilk.org>2018-09-18 09:53:49 +0200
commit39102224b25c937bd07cb61eccf12f0aec62e159 (patch)
treec92a5a72626ffa63c4ed46306d5c6ce7f178294d /src/pki_crypto.c
parente365aed6d2cf829d55e6f0c26203a8e66976cf28 (diff)
downloadlibssh-39102224b25c937bd07cb61eccf12f0aec62e159.tar.gz
libssh-39102224b25c937bd07cb61eccf12f0aec62e159.tar.xz
libssh-39102224b25c937bd07cb61eccf12f0aec62e159.zip
pki: Allow reading keys in new OpenSSH format
This implements reading the OpenSSH key format accross the cryptographic backends. Most of the code is shared and moved to pki.c, just the building of the keys is implemented in pki_privkey_build_*() functions. Signed-off-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Diffstat (limited to 'src/pki_crypto.c')
-rw-r--r--src/pki_crypto.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/src/pki_crypto.c b/src/pki_crypto.c
index 8cf029a6..a90b6d00 100644
--- a/src/pki_crypto.c
+++ b/src/pki_crypto.c
@@ -172,6 +172,61 @@ static ssh_string make_ecpoint_string(const EC_GROUP *g,
return s;
}
+int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp)
+{
+ EC_POINT *p = NULL;
+ const EC_GROUP *g = NULL;
+ int ok;
+ BIGNUM *bexp = NULL;
+
+ key->ecdsa_nid = nid;
+ key->type_c = pki_key_ecdsa_nid_to_name(nid);
+
+ key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid);
+ if (key->ecdsa == NULL) {
+ return -1;
+ }
+
+ g = EC_KEY_get0_group(key->ecdsa);
+
+ p = EC_POINT_new(g);
+ if (p == NULL) {
+ return -1;
+ }
+
+ ok = EC_POINT_oct2point(g,
+ p,
+ ssh_string_data(e),
+ ssh_string_len(e),
+ NULL);
+ if (!ok) {
+ EC_POINT_free(p);
+ return -1;
+ }
+
+ /* EC_KEY_set_public_key duplicates p */
+ ok = EC_KEY_set_public_key(key->ecdsa, p);
+ EC_POINT_free(p);
+ if (!ok) {
+ return -1;
+ }
+
+ bexp = ssh_make_string_bn(exp);
+ if (bexp == NULL) {
+ EC_KEY_free(key->ecdsa);
+ return -1;
+ }
+ /* EC_KEY_set_private_key duplicates exp */
+ ok = EC_KEY_set_private_key(key->ecdsa, bexp);
+ BN_free(bexp);
+ if (!ok) {
+ EC_KEY_free(key->ecdsa);
+ return -1;
+ }
+
+ return 0;
+}
+
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
{
EC_POINT *p = NULL;
@@ -896,6 +951,49 @@ fail:
return NULL;
}
+int pki_privkey_build_dss(ssh_key key,
+ ssh_string p,
+ ssh_string q,
+ ssh_string g,
+ ssh_string pubkey,
+ ssh_string privkey)
+{
+ int rc;
+ BIGNUM *bp, *bq, *bg, *bpub_key, *bpriv_key;
+
+ key->dsa = DSA_new();
+ if (key->dsa == NULL) {
+ return SSH_ERROR;
+ }
+
+ bp = ssh_make_string_bn(p);
+ bq = ssh_make_string_bn(q);
+ bg = ssh_make_string_bn(g);
+ bpub_key = ssh_make_string_bn(pubkey);
+ bpriv_key = ssh_make_string_bn(privkey);
+ if (bp == NULL || bq == NULL ||
+ bg == NULL || bpub_key == NULL) {
+ goto fail;
+ }
+
+ /* Memory management of bp, qq and bg is transfered to DSA object */
+ rc = DSA_set0_pqg(key->dsa, bp, bq, bg);
+ if (rc == 0) {
+ goto fail;
+ }
+
+ /* Memory management of bpub_key and bpriv_key is transfered to DSA object */
+ rc = DSA_set0_key(key->dsa, bpub_key, bpriv_key);
+ if (rc == 0) {
+ goto fail;
+ }
+
+ return SSH_OK;
+fail:
+ DSA_free(key->dsa);
+ return SSH_ERROR;
+}
+
int pki_pubkey_build_dss(ssh_key key,
ssh_string p,
ssh_string q,
@@ -936,6 +1034,58 @@ fail:
return SSH_ERROR;
}
+int pki_privkey_build_rsa(ssh_key key,
+ ssh_string n,
+ ssh_string e,
+ ssh_string d,
+ ssh_string iqmp,
+ ssh_string p,
+ ssh_string q)
+{
+ int rc;
+ BIGNUM *be, *bn, *bd/*, *biqmp*/, *bp, *bq;
+
+ key->rsa = RSA_new();
+ if (key->rsa == NULL) {
+ return SSH_ERROR;
+ }
+
+ bn = ssh_make_string_bn(n);
+ be = ssh_make_string_bn(e);
+ bd = ssh_make_string_bn(d);
+ /*biqmp = ssh_make_string_bn(iqmp);*/
+ bp = ssh_make_string_bn(p);
+ bq = ssh_make_string_bn(q);
+ if (be == NULL || bn == NULL || bd == NULL ||
+ /*biqmp == NULL ||*/ bp == NULL || bq == NULL) {
+ goto fail;
+ }
+
+ /* Memory management of be, bn and bd is transfered to RSA object */
+ rc = RSA_set0_key(key->rsa, bn, be, bd);
+ if (rc == 0) {
+ goto fail;
+ }
+
+ /* Memory management of bp and bq is transfered to RSA object */
+ rc = RSA_set0_factors(key->rsa, bp, bq);
+ 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.
+ * https://www.openssl.org/docs/man1.0.2/crypto/rsa.html
+ */
+ /* RSA_set0_crt_params(key->rsa, biqmp, NULL, NULL);
+ TODO calculate missing crt_params */
+
+ return SSH_OK;
+fail:
+ RSA_free(key->rsa);
+ return SSH_ERROR;
+}
+
int pki_pubkey_build_rsa(ssh_key key,
ssh_string e,
ssh_string n) {