aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/pki_priv.h26
-rw-r--r--src/pki.c173
-rw-r--r--src/pki_container_openssh.c56
-rw-r--r--src/pki_crypto.c150
-rw-r--r--src/pki_ed25519.c22
-rw-r--r--src/pki_gcrypt.c66
-rw-r--r--src/pki_mbedcrypto.c137
7 files changed, 578 insertions, 52 deletions
diff --git a/include/libssh/pki_priv.h b/include/libssh/pki_priv.h
index fe7e92a8..f8d94616 100644
--- a/include/libssh/pki_priv.h
+++ b/include/libssh/pki_priv.h
@@ -72,6 +72,9 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
const char *passphrase,
ssh_auth_callback auth_fn,
void *auth_data);
+int pki_import_privkey_buffer(enum ssh_keytypes_e type,
+ ssh_buffer buffer,
+ ssh_key *pkey);
/* SSH Public Key Functions */
int pki_pubkey_build_dss(ssh_key key,
@@ -85,6 +88,26 @@ int pki_pubkey_build_rsa(ssh_key key,
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e);
ssh_string pki_publickey_to_blob(const ssh_key key);
+/* SSH Private Key Functions */
+int pki_privkey_build_dss(ssh_key key,
+ ssh_string p,
+ ssh_string q,
+ ssh_string g,
+ ssh_string pubkey,
+ ssh_string privkey);
+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 pki_privkey_build_ecdsa(ssh_key key,
+ int nid,
+ ssh_string e,
+ ssh_string exp);
+ssh_string pki_publickey_to_blob(const ssh_key key);
+
/* SSH Signature Functions */
ssh_string pki_signature_to_blob(const ssh_signature sign);
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
@@ -121,6 +144,9 @@ int pki_ed25519_key_dup(ssh_key new, const ssh_key key);
int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key);
ssh_string pki_ed25519_sig_to_blob(ssh_signature sig);
int pki_ed25519_sig_from_blob(ssh_signature sig, ssh_string sig_blob);
+int pki_privkey_build_ed25519(ssh_key key,
+ ssh_string pubkey,
+ ssh_string privkey);
/* PKI Container OpenSSH */
ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
diff --git a/src/pki.c b/src/pki.c
index aa188767..f819b94d 100644
--- a/src/pki.c
+++ b/src/pki.c
@@ -810,6 +810,179 @@ ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key) {
return privkey;
}
+int pki_import_privkey_buffer(enum ssh_keytypes_e type,
+ ssh_buffer buffer,
+ ssh_key *pkey)
+{
+ ssh_key key = NULL;
+ int rc;
+
+ key = ssh_key_new();
+ if (key == NULL) {
+ return SSH_ERROR;
+ }
+
+ key->type = type;
+ key->type_c = ssh_key_type_to_char(type);
+ key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
+
+ switch (type) {
+ case SSH_KEYTYPE_DSS:
+ {
+ ssh_string p = NULL;
+ ssh_string q = NULL;
+ ssh_string g = NULL;
+ ssh_string pubkey = NULL;
+ ssh_string privkey = NULL;
+
+ rc = ssh_buffer_unpack(buffer, "SSSSS", &p, &q, &g,
+ &pubkey, &privkey);
+ if (rc != SSH_OK) {
+ SSH_LOG(SSH_LOG_WARN, "Unpack error");
+ goto fail;
+ }
+
+ rc = pki_privkey_build_dss(key, p, q, g, pubkey, privkey);
+#ifdef DEBUG_CRYPTO
+ ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
+ ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
+ ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g));
+ ssh_print_hexa("pubkey", ssh_string_data(pubkey),
+ ssh_string_len(pubkey));
+ ssh_print_hexa("privkey", ssh_string_data(privkey),
+ ssh_string_len(privkey));
+#endif
+ ssh_string_burn(p);
+ ssh_string_free(p);
+ ssh_string_burn(q);
+ ssh_string_free(q);
+ ssh_string_burn(g);
+ ssh_string_free(g);
+ ssh_string_burn(pubkey);
+ ssh_string_free(pubkey);
+ ssh_string_burn(privkey);
+ ssh_string_free(privkey);
+ if (rc == SSH_ERROR) {
+ goto fail;
+ }
+ }
+ break;
+ case SSH_KEYTYPE_RSA:
+ {
+ ssh_string n = NULL;
+ ssh_string e = NULL;
+ ssh_string d = NULL;
+ ssh_string iqmp = NULL;
+ ssh_string p = NULL;
+ ssh_string q = NULL;
+
+ rc = ssh_buffer_unpack(buffer, "SSSSSS", &n, &e, &d,
+ &iqmp, &p, &q);
+ if (rc != SSH_OK) {
+ SSH_LOG(SSH_LOG_WARN, "Unpack error");
+ goto fail;
+ }
+
+ rc = pki_privkey_build_rsa(key, n, e, d, iqmp, p, q);
+#ifdef DEBUG_CRYPTO
+ ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n));
+ ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e));
+ ssh_print_hexa("d", ssh_string_data(d), ssh_string_len(d));
+ ssh_print_hexa("iqmp", ssh_string_data(iqmp),
+ ssh_string_len(iqmp));
+ ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
+ ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
+#endif
+ ssh_string_burn(n);
+ ssh_string_free(n);
+ ssh_string_burn(e);
+ ssh_string_free(e);
+ ssh_string_burn(d);
+ ssh_string_free(d);
+ ssh_string_burn(iqmp);
+ ssh_string_free(iqmp);
+ ssh_string_burn(p);
+ ssh_string_free(p);
+ ssh_string_burn(q);
+ ssh_string_free(q);
+ if (rc == SSH_ERROR) {
+ SSH_LOG(SSH_LOG_WARN, "Failed to build RSA private key");
+ goto fail;
+ }
+ }
+ break;
+#ifdef HAVE_ECC
+ case SSH_KEYTYPE_ECDSA:
+ {
+ ssh_string e = NULL;
+ ssh_string exp = NULL;
+ ssh_string i = NULL;
+ int nid;
+
+ rc = ssh_buffer_unpack(buffer, "SSS", &i, &e, &exp);
+ if (rc != SSH_OK) {
+ SSH_LOG(SSH_LOG_WARN, "Unpack error");
+ goto fail;
+ }
+
+ nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
+ ssh_string_free(i);
+ if (nid == -1) {
+ goto fail;
+ }
+
+ rc = pki_privkey_build_ecdsa(key, nid, e, exp);
+ ssh_string_burn(e);
+ ssh_string_free(e);
+ ssh_string_burn(exp);
+ ssh_string_free(exp);
+ if (rc < 0) {
+ SSH_LOG(SSH_LOG_WARN, "Failed to build ECDSA private key");
+ goto fail;
+ }
+
+ /* Update key type */
+ key->type_c = ssh_pki_key_ecdsa_name(key);
+ }
+ break;
+#endif
+ case SSH_KEYTYPE_ED25519:
+ {
+ ssh_string pubkey = NULL, privkey = NULL;
+
+ rc = ssh_buffer_unpack(buffer, "SS", &pubkey, &privkey);
+ if (rc != SSH_OK){
+ SSH_LOG(SSH_LOG_WARN, "Unpack error");
+ goto fail;
+ }
+
+ rc = pki_privkey_build_ed25519(key, pubkey, privkey);
+ ssh_string_burn(privkey);
+ ssh_string_free(privkey);
+ ssh_string_free(pubkey);
+ if (rc != SSH_OK) {
+ SSH_LOG(SSH_LOG_WARN, "Failed to build ed25519 key");
+ goto fail;
+ }
+ }
+ break;
+ case SSH_KEYTYPE_DSS_CERT01:
+ case SSH_KEYTYPE_RSA_CERT01:
+ case SSH_KEYTYPE_RSA1:
+ case SSH_KEYTYPE_UNKNOWN:
+ default:
+ SSH_LOG(SSH_LOG_WARN, "Unknown private key type (%d)", type);
+ goto fail;
+ }
+
+ *pkey = key;
+ return SSH_OK;
+fail:
+ ssh_key_free(key);
+
+ return SSH_ERROR;
+}
+
static int pki_import_pubkey_buffer(ssh_buffer buffer,
enum ssh_keytypes_e type,
ssh_key *pkey) {
diff --git a/src/pki_container_openssh.c b/src/pki_container_openssh.c
index 2c4b6c46..4154b424 100644
--- a/src/pki_container_openssh.c
+++ b/src/pki_container_openssh.c
@@ -60,7 +60,6 @@ static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer,
enum ssh_keytypes_e type;
char *type_s = NULL;
ssh_key key = NULL;
- ssh_string pubkey = NULL, privkey = NULL;
int rc;
if (pkey == NULL) {
@@ -75,57 +74,14 @@ static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer,
type = ssh_key_type_from_name(type_s);
if (type == SSH_KEYTYPE_UNKNOWN) {
- SSH_LOG(SSH_LOG_WARN, "Unknown key type found!");
+ SSH_LOG(SSH_LOG_WARN, "Unknown key type '%s' found!", type_s);
return SSH_ERROR;
}
SAFE_FREE(type_s);
- key = ssh_key_new();
- if (key == NULL) {
- SSH_LOG(SSH_LOG_WARN, "Out of memory");
- return SSH_ERROR;
- }
-
- key->type = type;
- key->type_c = ssh_key_type_to_char(type);
- key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
-
- switch (type) {
- case SSH_KEYTYPE_ED25519:
- rc = ssh_buffer_unpack(key_blob_buffer, "SS", &pubkey, &privkey);
- if (rc != SSH_OK){
- SSH_LOG(SSH_LOG_WARN, "Unpack error");
- goto fail;
- }
- if(ssh_string_len(pubkey) != ED25519_PK_LEN ||
- ssh_string_len(privkey) != ED25519_SK_LEN){
- SSH_LOG(SSH_LOG_WARN, "Invalid ed25519 key len");
- goto fail;
- }
- key->ed25519_privkey = malloc(ED25519_SK_LEN);
- key->ed25519_pubkey = malloc(ED25519_PK_LEN);
- if(key->ed25519_privkey == NULL || key->ed25519_pubkey == NULL){
- goto fail;
- }
- memcpy(key->ed25519_privkey, ssh_string_data(privkey), ED25519_SK_LEN);
- memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_PK_LEN);
- explicit_bzero(ssh_string_data(privkey), ED25519_SK_LEN);
- SAFE_FREE(privkey);
- SAFE_FREE(pubkey);
- break;
- case SSH_KEYTYPE_DSS_CERT01:
- case SSH_KEYTYPE_DSS:
- /* p,q,g,pub_key,priv_key */
- case SSH_KEYTYPE_RSA_CERT01:
- case SSH_KEYTYPE_RSA:
- /* n,e,d,iqmp,p,q */
- case SSH_KEYTYPE_ECDSA:
- /* curve_name, group, privkey */
- SSH_LOG(SSH_LOG_WARN, "Unsupported private key method %s", key->type_c);
- goto fail;
- case SSH_KEYTYPE_RSA1:
- case SSH_KEYTYPE_UNKNOWN:
- SSH_LOG(SSH_LOG_WARN, "Unknown private key protocol %s", key->type_c);
+ rc = pki_import_privkey_buffer(type, key_blob_buffer, &key);
+ if (rc != SSH_OK) {
+ SSH_LOG(SSH_LOG_WARN, "Failed to read key in OpenSSH format");
goto fail;
}
@@ -134,10 +90,6 @@ static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer,
fail:
ssh_key_free(key);
- ssh_string_burn(privkey);
- ssh_string_free(privkey);
- ssh_string_free(pubkey);
-
return SSH_ERROR;
}
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) {
diff --git a/src/pki_ed25519.c b/src/pki_ed25519.c
index 45362c4f..981a74b6 100644
--- a/src/pki_ed25519.c
+++ b/src/pki_ed25519.c
@@ -56,6 +56,28 @@ error:
return SSH_ERROR;
}
+int pki_privkey_build_ed25519(ssh_key key,
+ ssh_string pubkey,
+ ssh_string privkey)
+{
+ if (ssh_string_len(pubkey) != ED25519_PK_LEN ||
+ ssh_string_len(privkey) != ED25519_SK_LEN) {
+ SSH_LOG(SSH_LOG_WARN, "Invalid ed25519 key len");
+ return SSH_ERROR;
+ }
+ key->ed25519_privkey = malloc(ED25519_SK_LEN);
+ key->ed25519_pubkey = malloc(ED25519_PK_LEN);
+ if (key->ed25519_privkey == NULL || key->ed25519_pubkey == NULL) {
+ return SSH_ERROR;
+ }
+ memcpy(key->ed25519_privkey, ssh_string_data(privkey),
+ ED25519_SK_LEN);
+ memcpy(key->ed25519_pubkey, ssh_string_data(pubkey),
+ ED25519_PK_LEN);
+
+ return SSH_OK;
+}
+
int pki_ed25519_sign(const ssh_key privkey,
ssh_signature sig,
const unsigned char *hash,
diff --git a/src/pki_gcrypt.c b/src/pki_gcrypt.c
index a988d805..95499f00 100644
--- a/src/pki_gcrypt.c
+++ b/src/pki_gcrypt.c
@@ -1030,6 +1030,27 @@ 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)
+{
+ gcry_sexp_build(&key->dsa, NULL,
+ "(private-key(dsa(p %b)(q %b)(g %b)(y %b)(x %b)))",
+ ssh_string_len(p), ssh_string_data(p),
+ ssh_string_len(q), ssh_string_data(q),
+ ssh_string_len(g), ssh_string_data(g),
+ ssh_string_len(pubkey), ssh_string_data(pubkey),
+ ssh_string_len(privkey), ssh_string_data(privkey));
+ if (key->dsa == NULL) {
+ return SSH_ERROR;
+ }
+
+ return SSH_OK;
+}
+
int pki_pubkey_build_dss(ssh_key key,
ssh_string p,
ssh_string q,
@@ -1048,6 +1069,32 @@ int pki_pubkey_build_dss(ssh_key key,
return SSH_OK;
}
+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)
+{
+ /* in gcrypt, there is no iqmp (inverse of q mod p) argument,
+ * but it is ipmq (inverse of p mod q) so we need to swap
+ * the p and q arguments */
+ gcry_sexp_build(&key->rsa, NULL,
+ "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))",
+ ssh_string_len(n), ssh_string_data(n),
+ ssh_string_len(e), ssh_string_data(e),
+ ssh_string_len(d), ssh_string_data(d),
+ ssh_string_len(q), ssh_string_data(q),
+ ssh_string_len(p), ssh_string_data(p),
+ ssh_string_len(iqmp), ssh_string_data(iqmp));
+ if (key->rsa == NULL) {
+ return SSH_ERROR;
+ }
+
+ return SSH_OK;
+}
+
int pki_pubkey_build_rsa(ssh_key key,
ssh_string e,
ssh_string n) {
@@ -1063,6 +1110,25 @@ int pki_pubkey_build_rsa(ssh_key key,
}
#ifdef HAVE_GCRYPT_ECC
+int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp)
+{
+ gpg_error_t err;
+
+ key->ecdsa_nid = nid;
+ key->type_c = pki_key_ecdsa_nid_to_name(nid);
+
+ err = gcry_sexp_build(&key->ecdsa, NULL,
+ "(private-key(ecdsa(curve %s)(d %b)(q %b)))",
+ pki_key_ecdsa_nid_to_gcrypt_name(nid),
+ ssh_string_len(exp), ssh_string_data(exp),
+ ssh_string_len(e), ssh_string_data(e));
+ if (err) {
+ return SSH_ERROR;
+ }
+
+ return SSH_OK;
+}
+
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
{
gpg_error_t err;
diff --git a/src/pki_mbedcrypto.c b/src/pki_mbedcrypto.c
index a5954980..26a80be0 100644
--- a/src/pki_mbedcrypto.c
+++ b/src/pki_mbedcrypto.c
@@ -214,6 +214,64 @@ fail:
return NULL;
}
+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)
+{
+ mbedtls_rsa_context *rsa = NULL;
+ const mbedtls_pk_info_t *pk_info = NULL;
+ int rc;
+
+ key->rsa = malloc(sizeof(mbedtls_pk_context));
+ if (key->rsa == NULL) {
+ return SSH_ERROR;
+ }
+
+ mbedtls_pk_init(key->rsa);
+ pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
+ mbedtls_pk_setup(key->rsa, pk_info);
+
+ rc = mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA);
+ if (rc == 0) {
+ goto fail;
+ }
+
+ rsa = mbedtls_pk_rsa(*key->rsa);
+ rc = mbedtls_rsa_import_raw(rsa,
+ ssh_string_data(n), ssh_string_len(n),
+ ssh_string_data(p), ssh_string_len(p),
+ ssh_string_data(q), ssh_string_len(q),
+ ssh_string_data(d), ssh_string_len(d),
+ ssh_string_data(e), ssh_string_len(e));
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARN, "Failed to import private RSA key");
+ goto fail;
+ }
+
+ rc = mbedtls_rsa_complete(rsa);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARN, "Failed to complete private RSA key");
+ goto fail;
+ }
+
+ rc = mbedtls_rsa_check_privkey(rsa);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARN, "Inconsistent private RSA key");
+ goto fail;
+ }
+
+ return SSH_OK;
+
+fail:
+ mbedtls_pk_free(key->rsa);
+ SAFE_FREE(key->rsa);
+ return SSH_ERROR;
+}
+
int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n)
{
mbedtls_rsa_context *rsa = NULL;
@@ -1243,6 +1301,73 @@ static mbedtls_ecp_group_id pki_key_ecdsa_nid_to_mbed_gid(int nid)
return MBEDTLS_ECP_DP_NONE;
}
+int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp)
+{
+ int rc;
+ mbedtls_ecp_keypair keypair;
+ mbedtls_ecp_group group;
+ mbedtls_ecp_point Q;
+
+ key->ecdsa_nid = nid;
+ key->type_c = pki_key_ecdsa_nid_to_name(nid);
+
+ key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
+ if (key->ecdsa == NULL) {
+ return SSH_ERROR;
+ }
+
+ mbedtls_ecdsa_init(key->ecdsa);
+ mbedtls_ecp_keypair_init(&keypair);
+ mbedtls_ecp_group_init(&group);
+ mbedtls_ecp_point_init(&Q);
+
+ rc = mbedtls_ecp_group_load(&group,
+ pki_key_ecdsa_nid_to_mbed_gid(nid));
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_ecp_point_read_binary(&group, &Q, ssh_string_data(e),
+ ssh_string_len(e));
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_ecp_copy(&keypair.Q, &Q);
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_ecp_group_copy(&keypair.grp, &group);
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_mpi_read_binary(&keypair.d, ssh_string_data(exp),
+ ssh_string_len(exp));
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_ecdsa_from_keypair(key->ecdsa, &keypair);
+ if (rc != 0) {
+ goto fail;
+ }
+
+ mbedtls_ecp_point_free(&Q);
+ mbedtls_ecp_group_free(&group);
+ mbedtls_ecp_keypair_free(&keypair);
+ return SSH_OK;
+
+fail:
+ mbedtls_ecdsa_free(key->ecdsa);
+ mbedtls_ecp_point_free(&Q);
+ mbedtls_ecp_group_free(&group);
+ mbedtls_ecp_keypair_free(&keypair);
+ SAFE_FREE(key->ecdsa);
+ return SSH_ERROR;
+}
+
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
{
int rc;
@@ -1347,6 +1472,18 @@ int pki_key_generate_ecdsa(ssh_key key, int parameter)
return SSH_OK;
}
+int pki_privkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g,
+ ssh_string pubkey, ssh_string privkey)
+{
+ (void) key;
+ (void) p;
+ (void) q;
+ (void) g;
+ (void) pubkey;
+ (void) privkey;
+ return SSH_ERROR;
+}
+
int pki_pubkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g,
ssh_string pubkey)
{