diff options
-rw-r--r-- | include/libssh/pki_priv.h | 26 | ||||
-rw-r--r-- | src/pki.c | 173 | ||||
-rw-r--r-- | src/pki_container_openssh.c | 56 | ||||
-rw-r--r-- | src/pki_crypto.c | 150 | ||||
-rw-r--r-- | src/pki_ed25519.c | 22 | ||||
-rw-r--r-- | src/pki_gcrypt.c | 66 | ||||
-rw-r--r-- | src/pki_mbedcrypto.c | 137 |
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, @@ -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) { |