mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-11-29 01:03:57 +03:00
pki: New API functions exporting (also ed25519 keys in different formats)
This also adds an fallback to OpenSSH file format in non-OpenSSL backends and OpenSSH-compatible private key export for writing OpenSSH private keys. Signed-off-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
@@ -686,6 +686,12 @@ typedef int (*ssh_auth_callback) (const char *prompt, char *buf, size_t len,
|
|||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
enum ssh_file_format_e {
|
||||||
|
SSH_FILE_FORMAT_DEFAULT = 0,
|
||||||
|
SSH_FILE_FORMAT_OPENSSH,
|
||||||
|
SSH_FILE_FORMAT_PEM,
|
||||||
|
};
|
||||||
|
|
||||||
LIBSSH_API ssh_key ssh_key_new(void);
|
LIBSSH_API ssh_key ssh_key_new(void);
|
||||||
#define SSH_KEY_FREE(x) \
|
#define SSH_KEY_FREE(x) \
|
||||||
do { if ((x) != NULL) { ssh_key_free(x); x = NULL; } } while(0)
|
do { if ((x) != NULL) { ssh_key_free(x); x = NULL; } } while(0)
|
||||||
@@ -712,6 +718,13 @@ LIBSSH_API int ssh_pki_export_privkey_base64(const ssh_key privkey,
|
|||||||
ssh_auth_callback auth_fn,
|
ssh_auth_callback auth_fn,
|
||||||
void *auth_data,
|
void *auth_data,
|
||||||
char **b64_key);
|
char **b64_key);
|
||||||
|
LIBSSH_API int
|
||||||
|
ssh_pki_export_privkey_base64_format(const ssh_key privkey,
|
||||||
|
const char *passphrase,
|
||||||
|
ssh_auth_callback auth_fn,
|
||||||
|
void *auth_data,
|
||||||
|
char **b64_key,
|
||||||
|
enum ssh_file_format_e format);
|
||||||
LIBSSH_API int ssh_pki_import_privkey_file(const char *filename,
|
LIBSSH_API int ssh_pki_import_privkey_file(const char *filename,
|
||||||
const char *passphrase,
|
const char *passphrase,
|
||||||
ssh_auth_callback auth_fn,
|
ssh_auth_callback auth_fn,
|
||||||
@@ -722,6 +735,13 @@ LIBSSH_API int ssh_pki_export_privkey_file(const ssh_key privkey,
|
|||||||
ssh_auth_callback auth_fn,
|
ssh_auth_callback auth_fn,
|
||||||
void *auth_data,
|
void *auth_data,
|
||||||
const char *filename);
|
const char *filename);
|
||||||
|
LIBSSH_API int
|
||||||
|
ssh_pki_export_privkey_file_format(const ssh_key privkey,
|
||||||
|
const char *passphrase,
|
||||||
|
ssh_auth_callback auth_fn,
|
||||||
|
void *auth_data,
|
||||||
|
const char *filename,
|
||||||
|
enum ssh_file_format_e format);
|
||||||
|
|
||||||
LIBSSH_API int ssh_pki_copy_cert_to_privkey(const ssh_key cert_key,
|
LIBSSH_API int ssh_pki_copy_cert_to_privkey(const ssh_key cert_key,
|
||||||
ssh_key privkey);
|
ssh_key privkey);
|
||||||
|
|||||||
@@ -153,6 +153,10 @@ int ssh_pki_import_pubkey_blob(const ssh_string key_blob,
|
|||||||
int ssh_pki_import_cert_blob(const ssh_string cert_blob,
|
int ssh_pki_import_cert_blob(const ssh_string cert_blob,
|
||||||
ssh_key *pkey);
|
ssh_key *pkey);
|
||||||
|
|
||||||
|
/* SSH Private Key Functions */
|
||||||
|
int ssh_pki_export_privkey_blob(const ssh_key key,
|
||||||
|
ssh_string *pblob);
|
||||||
|
|
||||||
|
|
||||||
/* SSH Signing Functions */
|
/* SSH Signing Functions */
|
||||||
ssh_string ssh_pki_do_sign(ssh_session session, ssh_buffer sigbuf,
|
ssh_string ssh_pki_do_sign(ssh_session session, ssh_buffer sigbuf,
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ int pki_pubkey_build_rsa(ssh_key key,
|
|||||||
ssh_string e,
|
ssh_string e,
|
||||||
ssh_string n);
|
ssh_string n);
|
||||||
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e);
|
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e);
|
||||||
ssh_string pki_publickey_to_blob(const ssh_key key);
|
ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type);
|
||||||
|
|
||||||
/* SSH Private Key Functions */
|
/* SSH Private Key Functions */
|
||||||
int pki_privkey_build_rsa(ssh_key key,
|
int pki_privkey_build_rsa(ssh_key key,
|
||||||
@@ -106,7 +106,6 @@ int pki_privkey_build_ecdsa(ssh_key key,
|
|||||||
int nid,
|
int nid,
|
||||||
ssh_string e,
|
ssh_string e,
|
||||||
ssh_string exp);
|
ssh_string exp);
|
||||||
ssh_string pki_publickey_to_blob(const ssh_key key);
|
|
||||||
|
|
||||||
/* SSH Signature Functions */
|
/* SSH Signature Functions */
|
||||||
ssh_signature pki_sign_data(const ssh_key privkey,
|
ssh_signature pki_sign_data(const ssh_key privkey,
|
||||||
@@ -143,6 +142,7 @@ int pki_ed25519_key_cmp(const ssh_key k1,
|
|||||||
enum ssh_keycmp_e what);
|
enum ssh_keycmp_e what);
|
||||||
int pki_ed25519_key_dup(ssh_key new_key, const ssh_key key);
|
int pki_ed25519_key_dup(ssh_key new_key, const ssh_key key);
|
||||||
int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key);
|
int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key);
|
||||||
|
int pki_ed25519_private_key_to_blob(ssh_buffer buffer, const ssh_key privkey);
|
||||||
ssh_string pki_ed25519_signature_to_blob(ssh_signature sig);
|
ssh_string pki_ed25519_signature_to_blob(ssh_signature sig);
|
||||||
int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob);
|
int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob);
|
||||||
int pki_privkey_build_ed25519(ssh_key key,
|
int pki_privkey_build_ed25519(ssh_key key,
|
||||||
|
|||||||
@@ -469,5 +469,7 @@ LIBSSH_AFTER_4_9_0
|
|||||||
sftp_aio_free;
|
sftp_aio_free;
|
||||||
sftp_aio_wait_read;
|
sftp_aio_wait_read;
|
||||||
sftp_aio_wait_write;
|
sftp_aio_wait_write;
|
||||||
|
ssh_pki_export_privkey_base64_format;
|
||||||
|
ssh_pki_export_privkey_file_format;
|
||||||
} LIBSSH_4_9_0;
|
} LIBSSH_4_9_0;
|
||||||
|
|
||||||
|
|||||||
232
src/pki.c
232
src/pki.c
@@ -836,6 +836,88 @@ int ssh_pki_import_privkey_base64(const char *b64_key,
|
|||||||
|
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert a private key to a base64 encoded key in given format
|
||||||
|
*
|
||||||
|
* @param[in] privkey The private key to export.
|
||||||
|
*
|
||||||
|
* @param[in] passphrase The passphrase to use to encrypt the key with or
|
||||||
|
* NULL. An empty string means no passphrase.
|
||||||
|
*
|
||||||
|
* @param[in] auth_fn An auth function you may want to use or NULL.
|
||||||
|
*
|
||||||
|
* @param[in] auth_data Private data passed to the auth function.
|
||||||
|
*
|
||||||
|
* @param[out] b64_key A pointer to store the allocated base64 encoded key. You
|
||||||
|
* need to free the buffer using ssh_string_from_char().
|
||||||
|
*
|
||||||
|
* @param[in] format The file format (OpenSSH, PEM, or default)
|
||||||
|
*
|
||||||
|
* @return SSH_OK on success, SSH_ERROR on error.
|
||||||
|
*
|
||||||
|
* @see ssh_string_free_char()
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ssh_pki_export_privkey_base64_format(const ssh_key privkey,
|
||||||
|
const char *passphrase,
|
||||||
|
ssh_auth_callback auth_fn,
|
||||||
|
void *auth_data,
|
||||||
|
char **b64_key,
|
||||||
|
enum ssh_file_format_e format)
|
||||||
|
{
|
||||||
|
ssh_string blob = NULL;
|
||||||
|
char *b64 = NULL;
|
||||||
|
|
||||||
|
if (privkey == NULL || !ssh_key_is_private(privkey)) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The PEM export is supported only with OpenSSL. We fall back to
|
||||||
|
* OpenSSH key format elsewhere */
|
||||||
|
if (format == SSH_FILE_FORMAT_DEFAULT) {
|
||||||
|
#ifdef HAVE_LIBCRYPTO
|
||||||
|
if (privkey->type != SSH_KEYTYPE_ED25519) {
|
||||||
|
format = SSH_FILE_FORMAT_PEM;
|
||||||
|
} else {
|
||||||
|
#else
|
||||||
|
if (1) {
|
||||||
|
#endif /* HAVE_LIBCRYPTO */
|
||||||
|
format = SSH_FILE_FORMAT_OPENSSH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (format) {
|
||||||
|
case SSH_FILE_FORMAT_DEFAULT:
|
||||||
|
case SSH_FILE_FORMAT_PEM:
|
||||||
|
blob = pki_private_key_to_pem(privkey,
|
||||||
|
passphrase,
|
||||||
|
auth_fn,
|
||||||
|
auth_data);
|
||||||
|
break;
|
||||||
|
case SSH_FILE_FORMAT_OPENSSH:
|
||||||
|
blob = ssh_pki_openssh_privkey_export(privkey,
|
||||||
|
passphrase,
|
||||||
|
auth_fn,
|
||||||
|
auth_data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (blob == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
b64 = strndup(ssh_string_data(blob), ssh_string_len(blob));
|
||||||
|
SSH_STRING_FREE(blob);
|
||||||
|
if (b64 == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*b64_key = b64;
|
||||||
|
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert a private key to a pem base64 encoded key, or OpenSSH format for
|
* @brief Convert a private key to a pem base64 encoded key, or OpenSSH format for
|
||||||
* keytype ssh-ed25519
|
* keytype ssh-ed25519
|
||||||
@@ -862,39 +944,16 @@ int ssh_pki_export_privkey_base64(const ssh_key privkey,
|
|||||||
void *auth_data,
|
void *auth_data,
|
||||||
char **b64_key)
|
char **b64_key)
|
||||||
{
|
{
|
||||||
ssh_string blob = NULL;
|
return ssh_pki_export_privkey_base64_format(privkey,
|
||||||
char *b64 = NULL;
|
|
||||||
|
|
||||||
if (privkey == NULL || !ssh_key_is_private(privkey)) {
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (privkey->type == SSH_KEYTYPE_ED25519){
|
|
||||||
blob = ssh_pki_openssh_privkey_export(privkey,
|
|
||||||
passphrase,
|
passphrase,
|
||||||
auth_fn,
|
auth_fn,
|
||||||
auth_data);
|
auth_data,
|
||||||
} else {
|
b64_key,
|
||||||
blob = pki_private_key_to_pem(privkey,
|
SSH_FILE_FORMAT_DEFAULT);
|
||||||
passphrase,
|
|
||||||
auth_fn,
|
|
||||||
auth_data);
|
|
||||||
}
|
|
||||||
if (blob == NULL) {
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
b64 = strndup(ssh_string_data(blob), ssh_string_len(blob));
|
|
||||||
SSH_STRING_FREE(blob);
|
|
||||||
if (b64 == NULL) {
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
*b64_key = b64;
|
|
||||||
|
|
||||||
return SSH_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Import a private key from a file or a PKCS #11 device.
|
* @brief Import a private key from a file or a PKCS #11 device.
|
||||||
*
|
*
|
||||||
@@ -1002,8 +1061,7 @@ int ssh_pki_import_privkey_file(const char *filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Export a private key to a pem file on disk, or OpenSSH format for
|
* @brief Export a private key to a file in format specified in the argument
|
||||||
* keytype ssh-ed25519
|
|
||||||
*
|
*
|
||||||
* @param[in] privkey The private key to export.
|
* @param[in] privkey The private key to export.
|
||||||
*
|
*
|
||||||
@@ -1016,16 +1074,21 @@ int ssh_pki_import_privkey_file(const char *filename,
|
|||||||
*
|
*
|
||||||
* @param[in] filename The path where to store the pem file.
|
* @param[in] filename The path where to store the pem file.
|
||||||
*
|
*
|
||||||
|
* @param[in] format The file format (OpenSSH, PEM, or default)
|
||||||
|
*
|
||||||
* @return SSH_OK on success, SSH_ERROR on error.
|
* @return SSH_OK on success, SSH_ERROR on error.
|
||||||
*/
|
*/
|
||||||
int ssh_pki_export_privkey_file(const ssh_key privkey,
|
|
||||||
|
int
|
||||||
|
ssh_pki_export_privkey_file_format(const ssh_key privkey,
|
||||||
const char *passphrase,
|
const char *passphrase,
|
||||||
ssh_auth_callback auth_fn,
|
ssh_auth_callback auth_fn,
|
||||||
void *auth_data,
|
void *auth_data,
|
||||||
const char *filename)
|
const char *filename,
|
||||||
|
enum ssh_file_format_e format)
|
||||||
{
|
{
|
||||||
ssh_string blob;
|
ssh_string blob = NULL;
|
||||||
FILE *fp;
|
FILE *fp = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (privkey == NULL || !ssh_key_is_private(privkey)) {
|
if (privkey == NULL || !ssh_key_is_private(privkey)) {
|
||||||
@@ -1040,16 +1103,34 @@ int ssh_pki_export_privkey_file(const ssh_key privkey,
|
|||||||
return SSH_EOF;
|
return SSH_EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (privkey->type == SSH_KEYTYPE_ED25519){
|
/* The PEM export is supported only with OpenSSL. We fall back to
|
||||||
blob = ssh_pki_openssh_privkey_export(privkey,
|
* OpenSSH key format elsewhere */
|
||||||
passphrase,
|
if (format == SSH_FILE_FORMAT_DEFAULT) {
|
||||||
auth_fn,
|
#ifdef HAVE_LIBCRYPTO
|
||||||
auth_data);
|
if (privkey->type != SSH_KEYTYPE_ED25519) {
|
||||||
|
format = SSH_FILE_FORMAT_PEM;
|
||||||
} else {
|
} else {
|
||||||
|
#else
|
||||||
|
if (1) {
|
||||||
|
#endif /* HAVE_LIBCRYPTO */
|
||||||
|
format = SSH_FILE_FORMAT_OPENSSH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (format) {
|
||||||
|
case SSH_FILE_FORMAT_DEFAULT:
|
||||||
|
case SSH_FILE_FORMAT_PEM:
|
||||||
blob = pki_private_key_to_pem(privkey,
|
blob = pki_private_key_to_pem(privkey,
|
||||||
passphrase,
|
passphrase,
|
||||||
auth_fn,
|
auth_fn,
|
||||||
auth_data);
|
auth_data);
|
||||||
|
break;
|
||||||
|
case SSH_FILE_FORMAT_OPENSSH:
|
||||||
|
blob = ssh_pki_openssh_privkey_export(privkey,
|
||||||
|
passphrase,
|
||||||
|
auth_fn,
|
||||||
|
auth_data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (blob == NULL) {
|
if (blob == NULL) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -1068,6 +1149,38 @@ int ssh_pki_export_privkey_file(const ssh_key privkey,
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Export a private key to a pem file on disk, or OpenSSH format for
|
||||||
|
* keytype ssh-ed25519
|
||||||
|
*
|
||||||
|
* @param[in] privkey The private key to export.
|
||||||
|
*
|
||||||
|
* @param[in] passphrase The passphrase to use to encrypt the key with or
|
||||||
|
* NULL. An empty string means no passphrase.
|
||||||
|
*
|
||||||
|
* @param[in] auth_fn An auth function you may want to use or NULL.
|
||||||
|
*
|
||||||
|
* @param[in] auth_data Private data passed to the auth function.
|
||||||
|
*
|
||||||
|
* @param[in] filename The path where to store the pem file.
|
||||||
|
*
|
||||||
|
* @return SSH_OK on success, SSH_ERROR on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ssh_pki_export_privkey_file(const ssh_key privkey,
|
||||||
|
const char *passphrase,
|
||||||
|
ssh_auth_callback auth_fn,
|
||||||
|
void *auth_data,
|
||||||
|
const char *filename)
|
||||||
|
{
|
||||||
|
return ssh_pki_export_privkey_file_format(privkey,
|
||||||
|
passphrase,
|
||||||
|
auth_fn,
|
||||||
|
auth_data,
|
||||||
|
filename,
|
||||||
|
SSH_FILE_FORMAT_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
/* temporary function to migrate seamlessly to ssh_key */
|
/* temporary function to migrate seamlessly to ssh_key */
|
||||||
ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key)
|
ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key)
|
||||||
{
|
{
|
||||||
@@ -2035,7 +2148,42 @@ int ssh_pki_export_pubkey_blob(const ssh_key key,
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
blob = pki_publickey_to_blob(key);
|
blob = pki_key_to_blob(key, SSH_KEY_PUBLIC);
|
||||||
|
if (blob == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pblob = blob;
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @brief Create a key_blob from a private key.
|
||||||
|
*
|
||||||
|
* The "key_blob" is encoded as per draft-miller-ssh-agent-08 section 4.2
|
||||||
|
* "Adding keys to the agent" for any of the supported key types.
|
||||||
|
*
|
||||||
|
* @param[in] key A private key to create the private ssh_string from.
|
||||||
|
*
|
||||||
|
* @param[out] pblob A pointer to store the newly allocated key blob. You
|
||||||
|
* need to free it using ssh_string_free().
|
||||||
|
*
|
||||||
|
* @return SSH_OK on success, SSH_ERROR otherwise.
|
||||||
|
*
|
||||||
|
* @see ssh_string_free()
|
||||||
|
*/
|
||||||
|
int ssh_pki_export_privkey_blob(const ssh_key key,
|
||||||
|
ssh_string *pblob)
|
||||||
|
{
|
||||||
|
ssh_string blob;
|
||||||
|
|
||||||
|
if (key == NULL) {
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
blob = pki_key_to_blob(key, SSH_KEY_PRIVATE);
|
||||||
if (blob == NULL) {
|
if (blob == NULL) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -2066,7 +2214,7 @@ int ssh_pki_export_pubkey_base64(const ssh_key key,
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
key_blob = pki_publickey_to_blob(key);
|
key_blob = pki_key_to_blob(key, SSH_KEY_PUBLIC);
|
||||||
if (key_blob == NULL) {
|
if (key_blob == NULL) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -394,37 +394,6 @@ ssh_key ssh_pki_openssh_pubkey_import(const char *text_key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** @internal
|
|
||||||
* @brief exports a private key to a string blob.
|
|
||||||
* @param[in] privkey private key to convert
|
|
||||||
* @param[out] buffer buffer to write the blob in.
|
|
||||||
* @returns SSH_OK on success
|
|
||||||
* @warning only supports ed25519 key type at the moment.
|
|
||||||
*/
|
|
||||||
static int pki_openssh_export_privkey_blob(const ssh_key privkey,
|
|
||||||
ssh_buffer buffer)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (privkey->type != SSH_KEYTYPE_ED25519) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE, "Type %s not supported", privkey->type_c);
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
if (privkey->ed25519_privkey == NULL ||
|
|
||||||
privkey->ed25519_pubkey == NULL) {
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
rc = ssh_buffer_pack(buffer,
|
|
||||||
"sdPdPP",
|
|
||||||
privkey->type_c,
|
|
||||||
(uint32_t)ED25519_KEY_LEN,
|
|
||||||
(size_t)ED25519_KEY_LEN, privkey->ed25519_pubkey,
|
|
||||||
(uint32_t)(2 * ED25519_KEY_LEN),
|
|
||||||
(size_t)ED25519_KEY_LEN, privkey->ed25519_privkey,
|
|
||||||
(size_t)ED25519_KEY_LEN, privkey->ed25519_pubkey);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
* @brief encrypts an ed25519 private key blob
|
* @brief encrypts an ed25519 private key blob
|
||||||
*
|
*
|
||||||
@@ -536,8 +505,8 @@ ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
|
|||||||
ssh_auth_callback auth_fn,
|
ssh_auth_callback auth_fn,
|
||||||
void *auth_data)
|
void *auth_data)
|
||||||
{
|
{
|
||||||
ssh_buffer buffer;
|
ssh_buffer buffer = NULL;
|
||||||
ssh_string str = NULL;
|
ssh_string str = NULL, blob = NULL;
|
||||||
ssh_string pubkey_s=NULL;
|
ssh_string pubkey_s=NULL;
|
||||||
ssh_buffer privkey_buffer = NULL;
|
ssh_buffer privkey_buffer = NULL;
|
||||||
uint32_t rnd;
|
uint32_t rnd;
|
||||||
@@ -554,17 +523,13 @@ ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
|
|||||||
if (privkey == NULL) {
|
if (privkey == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (privkey->type != SSH_KEYTYPE_ED25519){
|
|
||||||
SSH_LOG(SSH_LOG_TRACE, "Unsupported key type %s", privkey->type_c);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (passphrase != NULL || auth_fn != NULL){
|
if (passphrase != NULL || auth_fn != NULL){
|
||||||
SSH_LOG(SSH_LOG_DEBUG, "Enabling encryption for private key export");
|
SSH_LOG(SSH_LOG_DEBUG, "Enabling encryption for private key export");
|
||||||
to_encrypt = 1;
|
to_encrypt = 1;
|
||||||
}
|
}
|
||||||
buffer = ssh_buffer_new();
|
buffer = ssh_buffer_new();
|
||||||
pubkey_s = pki_publickey_to_blob(privkey);
|
rc = ssh_pki_export_pubkey_blob(privkey, &pubkey_s);
|
||||||
if(buffer == NULL || pubkey_s == NULL){
|
if (buffer == NULL || rc != SSH_OK) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,22 +543,17 @@ ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* checkint1 & 2 */
|
rc = ssh_pki_export_privkey_blob(privkey, &blob);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_pack(privkey_buffer,
|
rc = ssh_buffer_pack(privkey_buffer,
|
||||||
"dd",
|
"ddPs",
|
||||||
|
rnd, /* checkint 1 & 2 */
|
||||||
rnd,
|
rnd,
|
||||||
rnd);
|
ssh_string_len(blob), ssh_string_data(blob),
|
||||||
if (rc == SSH_ERROR){
|
"" /* comment */);
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = pki_openssh_export_privkey_blob(privkey, privkey_buffer);
|
|
||||||
if (rc == SSH_ERROR){
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* comment */
|
|
||||||
rc = ssh_buffer_pack(privkey_buffer, "s", "" /* comment */);
|
|
||||||
if (rc == SSH_ERROR){
|
if (rc == SSH_ERROR){
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -710,6 +670,8 @@ ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
|
|||||||
}
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
ssh_string_burn(blob);
|
||||||
|
ssh_string_free(blob);
|
||||||
if (privkey_buffer != NULL) {
|
if (privkey_buffer != NULL) {
|
||||||
void *bufptr = ssh_buffer_get(privkey_buffer);
|
void *bufptr = ssh_buffer_get(privkey_buffer);
|
||||||
explicit_bzero(bufptr, ssh_buffer_get_len(privkey_buffer));
|
explicit_bzero(bufptr, ssh_buffer_get_len(privkey_buffer));
|
||||||
|
|||||||
216
src/pki_crypto.c
216
src/pki_crypto.c
@@ -1309,18 +1309,9 @@ fail:
|
|||||||
|
|
||||||
rc = evp_build_pkey("RSA", param_bld, &(key->key), EVP_PKEY_KEYPAIR);
|
rc = evp_build_pkey("RSA", param_bld, &(key->key), EVP_PKEY_KEYPAIR);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
rc = SSH_ERROR;
|
SSH_LOG(SSH_LOG_WARNING,
|
||||||
goto fail;
|
"Failed to import private key: %s\n",
|
||||||
}
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
|
||||||
rc = EVP_PKEY_set_bn_param(key->key, OSSL_PKEY_PARAM_RSA_FACTOR1, bp);
|
|
||||||
if (rc != 1) {
|
|
||||||
rc = SSH_ERROR;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = EVP_PKEY_set_bn_param(key->key, OSSL_PKEY_PARAM_RSA_FACTOR2, bq);
|
|
||||||
if (rc != 1) {
|
|
||||||
rc = SSH_ERROR;
|
rc = SSH_ERROR;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -1412,7 +1403,7 @@ fail:
|
|||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string pki_publickey_to_blob(const ssh_key key)
|
ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
||||||
{
|
{
|
||||||
ssh_buffer buffer;
|
ssh_buffer buffer;
|
||||||
ssh_string type_s;
|
ssh_string type_s;
|
||||||
@@ -1422,10 +1413,13 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
|||||||
ssh_string p = NULL;
|
ssh_string p = NULL;
|
||||||
ssh_string g = NULL;
|
ssh_string g = NULL;
|
||||||
ssh_string q = NULL;
|
ssh_string q = NULL;
|
||||||
|
ssh_string d = NULL;
|
||||||
|
ssh_string iqmp = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
BIGNUM *bp = NULL, *bq = NULL, *bg = NULL, *bpub_key = NULL,
|
BIGNUM *bp = NULL, *bq = NULL, *bg = NULL, *bpub_key = NULL,
|
||||||
*bn = NULL, *be = NULL;
|
*bn = NULL, *be = NULL,
|
||||||
|
*bd = NULL, *biqmp = NULL;
|
||||||
OSSL_PARAM *params = NULL;
|
OSSL_PARAM *params = NULL;
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
|
||||||
@@ -1460,7 +1454,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
|||||||
case SSH_KEYTYPE_RSA:
|
case SSH_KEYTYPE_RSA:
|
||||||
case SSH_KEYTYPE_RSA1: {
|
case SSH_KEYTYPE_RSA1: {
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||||
const BIGNUM *be, *bn;
|
const BIGNUM *be = NULL, *bn = NULL;
|
||||||
const RSA *key_rsa = EVP_PKEY_get0_RSA(key->key);
|
const RSA *key_rsa = EVP_PKEY_get0_RSA(key->key);
|
||||||
RSA_get0_key(key_rsa, &bn, &be, NULL);
|
RSA_get0_key(key_rsa, &bn, &be, NULL);
|
||||||
#else
|
#else
|
||||||
@@ -1498,13 +1492,133 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssh_buffer_add_ssh_string(buffer, e) < 0) {
|
if (type == SSH_KEY_PUBLIC) {
|
||||||
|
/* The N and E parts are swapped in the public key export ! */
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, e);
|
||||||
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (ssh_buffer_add_ssh_string(buffer, n) < 0) {
|
rc = ssh_buffer_add_ssh_string(buffer, n);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
} else if (type == SSH_KEY_PRIVATE) {
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||||
|
const BIGNUM *bd, *biqmp, *bp, *bq;
|
||||||
|
RSA_get0_key(key_rsa, NULL, NULL, &bd);
|
||||||
|
RSA_get0_factors(key_rsa, &bp, &bq);
|
||||||
|
RSA_get0_crt_params(key_rsa, NULL, NULL, &biqmp);
|
||||||
|
#else
|
||||||
|
rc = EVP_PKEY_todata(key->key, EVP_PKEY_KEYPAIR, ¶ms);
|
||||||
|
if (rc != 1) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D);
|
||||||
|
if (out_param == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "RSA: No param D has been found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = OSSL_PARAM_get_BN(out_param, &bd);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR1);
|
||||||
|
if (out_param == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "RSA: No param P has been found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = OSSL_PARAM_get_BN(out_param, &bp);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR2);
|
||||||
|
if (out_param == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "RSA: No param Q has been found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = OSSL_PARAM_get_BN(out_param, &bq);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT1);
|
||||||
|
if (out_param == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "RSA: No param IQMP has been found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = OSSL_PARAM_get_BN(out_param, &biqmp);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, n);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, e);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = ssh_make_bignum_string((BIGNUM *)bd);
|
||||||
|
if (d == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
iqmp = ssh_make_bignum_string((BIGNUM *)biqmp);
|
||||||
|
if (iqmp == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ssh_make_bignum_string((BIGNUM *)bp);
|
||||||
|
if (p == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
q = ssh_make_bignum_string((BIGNUM *)bq);
|
||||||
|
if (q == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, d);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, iqmp);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, p);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, q);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_string_burn(d);
|
||||||
|
SSH_STRING_FREE(d);
|
||||||
|
d = NULL;
|
||||||
|
ssh_string_burn(iqmp);
|
||||||
|
SSH_STRING_FREE(iqmp);
|
||||||
|
iqmp = NULL;
|
||||||
|
ssh_string_burn(p);
|
||||||
|
SSH_STRING_FREE(p);
|
||||||
|
p = NULL;
|
||||||
|
ssh_string_burn(q);
|
||||||
|
SSH_STRING_FREE(q);
|
||||||
|
q = NULL;
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
|
bignum_safe_free(bd);
|
||||||
|
bignum_safe_free(biqmp);
|
||||||
|
bignum_safe_free(bp);
|
||||||
|
bignum_safe_free(bq);
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
}
|
||||||
ssh_string_burn(e);
|
ssh_string_burn(e);
|
||||||
SSH_STRING_FREE(e);
|
SSH_STRING_FREE(e);
|
||||||
e = NULL;
|
e = NULL;
|
||||||
@@ -1520,14 +1634,24 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
|||||||
}
|
}
|
||||||
case SSH_KEYTYPE_ED25519:
|
case SSH_KEYTYPE_ED25519:
|
||||||
case SSH_KEYTYPE_SK_ED25519:
|
case SSH_KEYTYPE_SK_ED25519:
|
||||||
|
if (type == SSH_KEY_PUBLIC) {
|
||||||
rc = pki_ed25519_public_key_to_blob(buffer, key);
|
rc = pki_ed25519_public_key_to_blob(buffer, key);
|
||||||
if (rc == SSH_ERROR){
|
if (rc == SSH_ERROR){
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (key->type == SSH_KEYTYPE_SK_ED25519 &&
|
/* public key can contain certificate sk information */
|
||||||
ssh_buffer_add_ssh_string(buffer, key->sk_application) < 0) {
|
if (key->type == SSH_KEYTYPE_SK_ED25519) {
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
||||||
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = pki_ed25519_private_key_to_blob(buffer, key);
|
||||||
|
if (rc == SSH_ERROR){
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SSH_KEYTYPE_ECDSA_P256:
|
case SSH_KEYTYPE_ECDSA_P256:
|
||||||
case SSH_KEYTYPE_ECDSA_P384:
|
case SSH_KEYTYPE_ECDSA_P384:
|
||||||
@@ -1544,6 +1668,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
|||||||
#else
|
#else
|
||||||
const EC_GROUP *group = NULL;
|
const EC_GROUP *group = NULL;
|
||||||
const EC_POINT *point = NULL;
|
const EC_POINT *point = NULL;
|
||||||
|
const BIGNUM *exp = NULL;
|
||||||
EC_KEY *ec = NULL;
|
EC_KEY *ec = NULL;
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
|
||||||
@@ -1628,15 +1753,52 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
|||||||
ssh_string_burn(e);
|
ssh_string_burn(e);
|
||||||
SSH_STRING_FREE(e);
|
SSH_STRING_FREE(e);
|
||||||
e = NULL;
|
e = NULL;
|
||||||
|
if (type == SSH_KEY_PRIVATE) {
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
OSSL_PARAM_free(params);
|
rc = EVP_PKEY_todata(key->key, EVP_PKEY_KEYPAIR, ¶ms);
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
if (rc < 0) {
|
||||||
|
|
||||||
if (key->type == SSH_KEYTYPE_SK_ECDSA &&
|
|
||||||
ssh_buffer_add_ssh_string(buffer, key->sk_application) < 0) {
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
locate_param = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PRIV_KEY);
|
||||||
|
rc = OSSL_PARAM_get_BN(locate_param, &bd);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
d = ssh_make_bignum_string((BIGNUM *)bd);
|
||||||
|
if (d == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (ssh_buffer_add_ssh_string(buffer, d) < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
exp = EC_KEY_get0_private_key(ec);
|
||||||
|
if (exp == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
d = ssh_make_bignum_string((BIGNUM *)exp);
|
||||||
|
if (d == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, d);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
ssh_string_burn(d);
|
||||||
|
SSH_STRING_FREE(d);
|
||||||
|
d = NULL;
|
||||||
|
} else if (key->type == SSH_KEYTYPE_SK_ECDSA) {
|
||||||
|
/* public key can contain certificate sk information */
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
|
OSSL_PARAM_free(params);
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_OPENSSL_ECC */
|
#endif /* HAVE_OPENSSL_ECC */
|
||||||
@@ -1672,6 +1834,10 @@ fail:
|
|||||||
SSH_STRING_FREE(q);
|
SSH_STRING_FREE(q);
|
||||||
ssh_string_burn(n);
|
ssh_string_burn(n);
|
||||||
SSH_STRING_FREE(n);
|
SSH_STRING_FREE(n);
|
||||||
|
ssh_string_burn(d);
|
||||||
|
SSH_STRING_FREE(d);
|
||||||
|
ssh_string_burn(iqmp);
|
||||||
|
SSH_STRING_FREE(iqmp);
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
bignum_safe_free(bp);
|
bignum_safe_free(bp);
|
||||||
bignum_safe_free(bq);
|
bignum_safe_free(bq);
|
||||||
@@ -1679,6 +1845,8 @@ fail:
|
|||||||
bignum_safe_free(bpub_key);
|
bignum_safe_free(bpub_key);
|
||||||
bignum_safe_free(bn);
|
bignum_safe_free(bn);
|
||||||
bignum_safe_free(be);
|
bignum_safe_free(be);
|
||||||
|
bignum_safe_free(bd);
|
||||||
|
bignum_safe_free(biqmp);
|
||||||
OSSL_PARAM_free(params);
|
OSSL_PARAM_free(params);
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
|
||||||
|
|||||||
@@ -206,6 +206,34 @@ int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief exports a ed25519 private key to a string blob.
|
||||||
|
* @param[in] privkey private key to convert
|
||||||
|
* @param[out] buffer buffer to write the blob in.
|
||||||
|
* @returns SSH_OK on success
|
||||||
|
*/
|
||||||
|
int pki_ed25519_private_key_to_blob(ssh_buffer buffer, const ssh_key privkey)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (privkey->type != SSH_KEYTYPE_ED25519) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "Type %s not supported", privkey->type_c);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
if (privkey->ed25519_privkey == NULL ||
|
||||||
|
privkey->ed25519_pubkey == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_pack(buffer,
|
||||||
|
"dPdPP",
|
||||||
|
(uint32_t)ED25519_KEY_LEN,
|
||||||
|
(size_t)ED25519_KEY_LEN, privkey->ed25519_pubkey,
|
||||||
|
(uint32_t)(2 * ED25519_KEY_LEN),
|
||||||
|
(size_t)ED25519_KEY_LEN, privkey->ed25519_privkey,
|
||||||
|
(size_t)ED25519_KEY_LEN, privkey->ed25519_pubkey);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*
|
*
|
||||||
|
|||||||
121
src/pki_gcrypt.c
121
src/pki_gcrypt.c
@@ -1366,16 +1366,18 @@ int pki_key_compare(const ssh_key k1,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string pki_publickey_to_blob(const ssh_key key)
|
ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
||||||
{
|
{
|
||||||
ssh_buffer buffer;
|
ssh_buffer buffer;
|
||||||
ssh_string type_s;
|
ssh_string type_s;
|
||||||
ssh_string str = NULL;
|
ssh_string str = NULL;
|
||||||
ssh_string e = NULL;
|
ssh_string e = NULL;
|
||||||
ssh_string n = NULL;
|
ssh_string n = NULL;
|
||||||
|
ssh_string d = NULL;
|
||||||
ssh_string p = NULL;
|
ssh_string p = NULL;
|
||||||
ssh_string g = NULL;
|
ssh_string g = NULL;
|
||||||
ssh_string q = NULL;
|
ssh_string q = NULL;
|
||||||
|
ssh_string u = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
buffer = ssh_buffer_new();
|
buffer = ssh_buffer_new();
|
||||||
@@ -1423,6 +1425,8 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == SSH_KEY_PUBLIC) {
|
||||||
|
/* The N and E parts are swapped in the public key export ! */
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, e);
|
rc = ssh_buffer_add_ssh_string(buffer, e);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -1431,23 +1435,99 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
|||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
} else if (type == SSH_KEY_PRIVATE) {
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, n);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, e);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = ssh_sexp_extract_mpi(key->rsa,
|
||||||
|
"d",
|
||||||
|
GCRYMPI_FMT_USG,
|
||||||
|
GCRYMPI_FMT_STD);
|
||||||
|
if (d == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ssh_sexp_extract_mpi(key->rsa,
|
||||||
|
"p",
|
||||||
|
GCRYMPI_FMT_USG,
|
||||||
|
GCRYMPI_FMT_STD);
|
||||||
|
if (p == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
q = ssh_sexp_extract_mpi(key->rsa,
|
||||||
|
"q",
|
||||||
|
GCRYMPI_FMT_USG,
|
||||||
|
GCRYMPI_FMT_STD);
|
||||||
|
if (q == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
u = ssh_sexp_extract_mpi(key->rsa,
|
||||||
|
"u",
|
||||||
|
GCRYMPI_FMT_USG,
|
||||||
|
GCRYMPI_FMT_STD);
|
||||||
|
if (u == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, d);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, u);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
/* Swap the P and Q as the iqmp in gcrypt is ipmq ... */
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, q);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, p);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
ssh_string_burn(d);
|
||||||
|
SSH_STRING_FREE(d);
|
||||||
|
ssh_string_burn(p);
|
||||||
|
SSH_STRING_FREE(p);
|
||||||
|
ssh_string_burn(q);
|
||||||
|
SSH_STRING_FREE(q);
|
||||||
|
ssh_string_burn(u);
|
||||||
|
SSH_STRING_FREE(u);
|
||||||
|
}
|
||||||
ssh_string_burn(e);
|
ssh_string_burn(e);
|
||||||
SSH_STRING_FREE(e);
|
SSH_STRING_FREE(e);
|
||||||
ssh_string_burn(n);
|
ssh_string_burn(n);
|
||||||
SSH_STRING_FREE(n);
|
SSH_STRING_FREE(n);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SSH_KEYTYPE_ED25519:
|
case SSH_KEYTYPE_ED25519:
|
||||||
case SSH_KEYTYPE_SK_ED25519:
|
case SSH_KEYTYPE_SK_ED25519:
|
||||||
|
if (type == SSH_KEY_PUBLIC) {
|
||||||
rc = pki_ed25519_public_key_to_blob(buffer, key);
|
rc = pki_ed25519_public_key_to_blob(buffer, key);
|
||||||
if (rc != SSH_OK){
|
if (rc == SSH_ERROR) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (key->type == SSH_KEYTYPE_SK_ED25519 &&
|
/* public key can contain certificate sk information */
|
||||||
ssh_buffer_add_ssh_string(buffer, key->sk_application) < 0) {
|
if (key->type == SSH_KEYTYPE_SK_ED25519) {
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
||||||
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = pki_ed25519_private_key_to_blob(buffer, key);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SSH_KEYTYPE_ECDSA_P256:
|
case SSH_KEYTYPE_ECDSA_P256:
|
||||||
case SSH_KEYTYPE_ECDSA_P384:
|
case SSH_KEYTYPE_ECDSA_P384:
|
||||||
@@ -1457,22 +1537,19 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
|||||||
type_s = ssh_string_from_char(
|
type_s = ssh_string_from_char(
|
||||||
pki_key_ecdsa_nid_to_char(key->ecdsa_nid));
|
pki_key_ecdsa_nid_to_char(key->ecdsa_nid));
|
||||||
if (type_s == NULL) {
|
if (type_s == NULL) {
|
||||||
SSH_BUFFER_FREE(buffer);
|
goto fail;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, type_s);
|
rc = ssh_buffer_add_ssh_string(buffer, type_s);
|
||||||
SSH_STRING_FREE(type_s);
|
SSH_STRING_FREE(type_s);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
SSH_BUFFER_FREE(buffer);
|
goto fail;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e = ssh_sexp_extract_mpi(key->ecdsa, "q", GCRYMPI_FMT_STD,
|
e = ssh_sexp_extract_mpi(key->ecdsa, "q", GCRYMPI_FMT_STD,
|
||||||
GCRYMPI_FMT_STD);
|
GCRYMPI_FMT_STD);
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
SSH_BUFFER_FREE(buffer);
|
goto fail;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, e);
|
rc = ssh_buffer_add_ssh_string(buffer, e);
|
||||||
@@ -1484,11 +1561,29 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
|||||||
SSH_STRING_FREE(e);
|
SSH_STRING_FREE(e);
|
||||||
e = NULL;
|
e = NULL;
|
||||||
|
|
||||||
if (key->type == SSH_KEYTYPE_SK_ECDSA &&
|
if (type == SSH_KEY_PRIVATE) {
|
||||||
ssh_buffer_add_ssh_string(buffer, key->sk_application) < 0) {
|
d = ssh_sexp_extract_mpi(key->ecdsa, "d", GCRYMPI_FMT_STD,
|
||||||
|
GCRYMPI_FMT_STD);
|
||||||
|
if (d == NULL) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, d);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_string_burn(d);
|
||||||
|
SSH_STRING_FREE(d);
|
||||||
|
d = NULL;
|
||||||
|
} else if (key->type == SSH_KEYTYPE_SK_ECDSA) {
|
||||||
|
/* public key can contain certificate sk information */
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case SSH_KEYTYPE_RSA1:
|
case SSH_KEYTYPE_RSA1:
|
||||||
|
|||||||
@@ -878,7 +878,7 @@ static const char* pki_key_ecdsa_nid_to_char(int nid)
|
|||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string pki_publickey_to_blob(const ssh_key key)
|
ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
||||||
{
|
{
|
||||||
ssh_buffer buffer = NULL;
|
ssh_buffer buffer = NULL;
|
||||||
ssh_string type_s = NULL;
|
ssh_string type_s = NULL;
|
||||||
@@ -888,6 +888,10 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
|||||||
#if MBEDTLS_VERSION_MAJOR > 2
|
#if MBEDTLS_VERSION_MAJOR > 2
|
||||||
mbedtls_mpi E;
|
mbedtls_mpi E;
|
||||||
mbedtls_mpi N;
|
mbedtls_mpi N;
|
||||||
|
mbedtls_mpi D;
|
||||||
|
mbedtls_mpi IQMP;
|
||||||
|
mbedtls_mpi P;
|
||||||
|
mbedtls_mpi Q;
|
||||||
#endif
|
#endif
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@@ -961,21 +965,124 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ssh_buffer_add_ssh_string(buffer, e) < 0) {
|
if (type == SSH_KEY_PUBLIC) {
|
||||||
|
/* The N and E parts are swapped in the public key export ! */
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, e);
|
||||||
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssh_buffer_add_ssh_string(buffer, n) < 0) {
|
rc = ssh_buffer_add_ssh_string(buffer, n);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
} else if (type == SSH_KEY_PRIVATE) {
|
||||||
|
ssh_string p = NULL;
|
||||||
|
ssh_string q = NULL;
|
||||||
|
ssh_string d = NULL;
|
||||||
|
ssh_string iqmp = NULL;
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, n);
|
||||||
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, e);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MBEDTLS_VERSION_MAJOR > 2
|
||||||
|
rc = mbedtls_rsa_export(rsa, NULL, &P, &Q, &D, NULL);
|
||||||
|
if (rc != 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ssh_make_bignum_string(&P);
|
||||||
|
if (p == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
q = ssh_make_bignum_string(&Q);
|
||||||
|
if (q == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = ssh_make_bignum_string(&D);
|
||||||
|
if (d == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = mbedtls_rsa_export_crt(rsa, NULL, NULL, &IQMP)
|
||||||
|
if (rc != 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
iqmp = ssh_make_bignum_string(&IQMP);
|
||||||
|
if (iqmp == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
p = ssh_make_bignum_string(&rsa->P);
|
||||||
|
if (p == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
q = ssh_make_bignum_string(&rsa->Q);
|
||||||
|
if (q == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = ssh_make_bignum_string(&rsa->D);
|
||||||
|
if (d == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
iqmp = ssh_make_bignum_string(&rsa->QP);
|
||||||
|
if (iqmp == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, d);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, iqmp);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, p);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, q);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_string_burn(d);
|
||||||
|
SSH_STRING_FREE(d);
|
||||||
|
d = NULL;
|
||||||
|
ssh_string_burn(iqmp);
|
||||||
|
SSH_STRING_FREE(iqmp);
|
||||||
|
iqmp = NULL;
|
||||||
|
ssh_string_burn(p);
|
||||||
|
SSH_STRING_FREE(p);
|
||||||
|
p = NULL;
|
||||||
|
ssh_string_burn(q);
|
||||||
|
SSH_STRING_FREE(q);
|
||||||
|
q = NULL;
|
||||||
|
}
|
||||||
ssh_string_burn(e);
|
ssh_string_burn(e);
|
||||||
SSH_STRING_FREE(e);
|
SSH_STRING_FREE(e);
|
||||||
e = NULL;
|
e = NULL;
|
||||||
ssh_string_burn(n);
|
ssh_string_burn(n);
|
||||||
SSH_STRING_FREE(n);
|
SSH_STRING_FREE(n);
|
||||||
n = NULL;
|
n = NULL;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SSH_KEYTYPE_ECDSA_P256:
|
case SSH_KEYTYPE_ECDSA_P256:
|
||||||
@@ -1013,22 +1120,52 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
|||||||
SSH_STRING_FREE(e);
|
SSH_STRING_FREE(e);
|
||||||
e = NULL;
|
e = NULL;
|
||||||
|
|
||||||
if (key->type == SSH_KEYTYPE_SK_ECDSA &&
|
if (type == SSH_KEY_PRIVATE) {
|
||||||
ssh_buffer_add_ssh_string(buffer, key->sk_application) < 0) {
|
ssh_string d = NULL;
|
||||||
|
d = ssh_make_bignum_string(&key->ecdsa->MBEDTLS_PRIVATE(d));
|
||||||
|
|
||||||
|
if (d == NULL) {
|
||||||
|
SSH_BUFFER_FREE(buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, d);
|
||||||
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssh_string_burn(d);
|
||||||
|
SSH_STRING_FREE(d);
|
||||||
|
d = NULL;
|
||||||
|
} else if (key->type == SSH_KEYTYPE_SK_ECDSA) {
|
||||||
|
/* public key can contain certificate sk information */
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SSH_KEYTYPE_ED25519:
|
case SSH_KEYTYPE_ED25519:
|
||||||
case SSH_KEYTYPE_SK_ED25519:
|
case SSH_KEYTYPE_SK_ED25519:
|
||||||
|
if (type == SSH_KEY_PUBLIC) {
|
||||||
rc = pki_ed25519_public_key_to_blob(buffer, key);
|
rc = pki_ed25519_public_key_to_blob(buffer, key);
|
||||||
if (rc != SSH_OK) {
|
if (rc == SSH_ERROR) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (key->type == SSH_KEYTYPE_SK_ED25519 &&
|
/* public key can contain certificate sk information */
|
||||||
ssh_buffer_add_ssh_string(buffer, key->sk_application) < 0) {
|
if (key->type == SSH_KEYTYPE_SK_ED25519) {
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
||||||
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = pki_ed25519_private_key_to_blob(buffer, key);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|||||||
Reference in New Issue
Block a user