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 */
|
/* PKI Container OpenSSH */
|
||||||
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);
|
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_ */
|
#endif /* PKI_PRIV_H_ */
|
||||||
|
19
src/pki.c
19
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.
|
* @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;
|
return SSH_EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (privkey->type == SSH_KEYTYPE_ED25519){
|
||||||
blob = pki_private_key_to_pem(privkey,
|
blob = ssh_pki_openssh_privkey_export(privkey,
|
||||||
passphrase,
|
passphrase,
|
||||||
auth_fn,
|
auth_fn,
|
||||||
auth_data);
|
auth_data);
|
||||||
|
} else {
|
||||||
|
blob = pki_private_key_to_pem(privkey,
|
||||||
|
passphrase,
|
||||||
|
auth_fn,
|
||||||
|
auth_data);
|
||||||
|
}
|
||||||
if (blob == NULL) {
|
if (blob == NULL) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return -1;
|
return -1;
|
||||||
|
@@ -144,10 +144,10 @@ fail:
|
|||||||
* @brief Import a private key in OpenSSH (new) format. This format is
|
* @brief Import a private key in OpenSSH (new) format. This format is
|
||||||
* typically used with ed25519 keys but can be used for others.
|
* 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,
|
const char *passphrase,
|
||||||
ssh_auth_callback auth_fn,
|
ssh_auth_callback auth_fn,
|
||||||
void *auth_data)
|
void *auth_data)
|
||||||
{
|
{
|
||||||
const char *ptr=text_key;
|
const char *ptr=text_key;
|
||||||
const char *end;
|
const char *end;
|
||||||
@@ -249,6 +249,162 @@ error:
|
|||||||
return key;
|
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