1
0
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:
Aris Adamantiadis
2015-01-20 17:34:21 +01:00
committed by Andreas Schneider
parent 119840b0a9
commit 46bc11f977
3 changed files with 175 additions and 10 deletions

View File

@@ -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_ */

View File

@@ -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 = ssh_pki_openssh_privkey_export(privkey,
passphrase,
auth_fn,
auth_data);
} else {
blob = pki_private_key_to_pem(privkey, blob = pki_private_key_to_pem(privkey,
passphrase, passphrase,
auth_fn, auth_fn,
auth_data); auth_data);
}
if (blob == NULL) { if (blob == NULL) {
fclose(fp); fclose(fp);
return -1; return -1;

View File

@@ -144,7 +144,7 @@ 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)
@@ -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;
}
/** /**
* @} * @}
*/ */