mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-08-08 19:02:06 +03:00
ed25519: Add support to export OpenSSH container keys
Signed-off-by: Aris Adamantiadis <aris@0xbadc0de.be> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
committed by
Andreas Schneider
parent
119840b0a9
commit
46bc11f977
@@ -112,5 +112,7 @@ int pki_ed25519_sig_from_blob(ssh_signature sig, ssh_string sig_blob);
|
||||
/* PKI Container OpenSSH */
|
||||
ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
const char *passphrase, ssh_auth_callback auth_fn, void *auth_data);
|
||||
ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
|
||||
const char *passphrase, ssh_auth_callback auth_fn, void *auth_data);
|
||||
|
||||
#endif /* PKI_PRIV_H_ */
|
||||
|
11
src/pki.c
11
src/pki.c
@@ -529,7 +529,8 @@ int ssh_pki_import_privkey_file(const char *filename,
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Export a private key to a pam file on disk.
|
||||
* @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.
|
||||
*
|
||||
@@ -565,11 +566,17 @@ int ssh_pki_export_privkey_file(const ssh_key privkey,
|
||||
return SSH_EOF;
|
||||
}
|
||||
|
||||
|
||||
if (privkey->type == SSH_KEYTYPE_ED25519){
|
||||
blob = ssh_pki_openssh_privkey_export(privkey,
|
||||
passphrase,
|
||||
auth_fn,
|
||||
auth_data);
|
||||
} else {
|
||||
blob = pki_private_key_to_pem(privkey,
|
||||
passphrase,
|
||||
auth_fn,
|
||||
auth_data);
|
||||
}
|
||||
if (blob == NULL) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
|
@@ -144,7 +144,7 @@ fail:
|
||||
* @brief Import a private key in OpenSSH (new) format. This format is
|
||||
* typically used with ed25519 keys but can be used for others.
|
||||
*/
|
||||
ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data)
|
||||
@@ -249,6 +249,162 @@ error:
|
||||
return 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_pki_log("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,
|
||||
"sdPdP",
|
||||
privkey->type_c,
|
||||
(uint32_t)ED25519_PK_LEN,
|
||||
(size_t)ED25519_PK_LEN, privkey->ed25519_pubkey,
|
||||
(uint32_t)ED25519_SK_LEN,
|
||||
(size_t)ED25519_SK_LEN, privkey->ed25519_privkey);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* generate an OpenSSH private key (defined in PROTOCOL.key) and output it in text format.
|
||||
* @param privkey[in] private key to export
|
||||
* @returns an SSH string containing the text representation of the exported key.
|
||||
* @warning currently only supports ED25519 key types.
|
||||
*/
|
||||
|
||||
ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data)
|
||||
{
|
||||
ssh_buffer buffer;
|
||||
ssh_string str = NULL;
|
||||
ssh_string pubkey_s=NULL;
|
||||
ssh_buffer privkey_buffer = NULL;
|
||||
uint32_t rnd;
|
||||
unsigned char *b64;
|
||||
uint32_t str_len, len;
|
||||
int rc;
|
||||
|
||||
if (privkey == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (privkey->type != SSH_KEYTYPE_ED25519){
|
||||
ssh_pki_log("Unsupported key type %s", privkey->type_c);
|
||||
return NULL;
|
||||
}
|
||||
buffer = ssh_buffer_new();
|
||||
pubkey_s = pki_publickey_to_blob(privkey);
|
||||
if(buffer == NULL || pubkey_s == NULL){
|
||||
goto error;
|
||||
}
|
||||
ssh_get_random(&rnd, sizeof(rnd), 0);
|
||||
|
||||
privkey_buffer = ssh_buffer_new();
|
||||
if (privkey_buffer == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* checkint1 & 2 */
|
||||
rc = ssh_buffer_pack(privkey_buffer,
|
||||
"dd",
|
||||
rnd,
|
||||
rnd);
|
||||
if (rc == SSH_ERROR){
|
||||
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){
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_pack(buffer,
|
||||
"PsssdSdP",
|
||||
(size_t)strlen(OPENSSH_AUTH_MAGIC) + 1, OPENSSH_AUTH_MAGIC,
|
||||
"none", /* ciphername */
|
||||
"none", /* kdfname */
|
||||
"", /* kdfoptions */
|
||||
(uint32_t)1, /* nkeys */
|
||||
pubkey_s,
|
||||
(uint32_t)ssh_buffer_get_len(privkey_buffer),
|
||||
/* rest of buffer is a string */
|
||||
(size_t)ssh_buffer_get_len(privkey_buffer), ssh_buffer_get_begin(privkey_buffer));
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
b64 = bin_to_base64(ssh_buffer_get_begin(buffer),
|
||||
ssh_buffer_get_len(buffer));
|
||||
if (b64 == NULL){
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* we can reuse the buffer */
|
||||
ssh_buffer_reinit(buffer);
|
||||
rc = ssh_buffer_pack(buffer,
|
||||
"tttttt",
|
||||
OPENSSH_HEADER_BEGIN,
|
||||
"\n",
|
||||
b64,
|
||||
"\n",
|
||||
OPENSSH_HEADER_END,
|
||||
"\n");
|
||||
BURN_BUFFER(b64, strlen((char *)b64));
|
||||
SAFE_FREE(b64);
|
||||
|
||||
if (rc != SSH_OK){
|
||||
goto error;
|
||||
}
|
||||
|
||||
str = ssh_string_new(ssh_buffer_get_len(buffer));
|
||||
if (str == NULL){
|
||||
goto error;
|
||||
}
|
||||
|
||||
str_len = ssh_buffer_get_len(buffer);
|
||||
len = buffer_get_data(buffer, ssh_string_data(str), str_len);
|
||||
if (str_len != len) {
|
||||
ssh_string_free(str);
|
||||
str = NULL;
|
||||
}
|
||||
|
||||
error:
|
||||
if (privkey_buffer != NULL) {
|
||||
void *bufptr = ssh_buffer_get_begin(privkey_buffer);
|
||||
BURN_BUFFER(bufptr, ssh_buffer_get_len(privkey_buffer));
|
||||
ssh_buffer_free(privkey_buffer);
|
||||
}
|
||||
SAFE_FREE(pubkey_s);
|
||||
if (buffer != NULL){
|
||||
ssh_buffer_free(buffer);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
Reference in New Issue
Block a user