From bdcaf55b906bedb84df1cf0637137f674dd5ce64 Mon Sep 17 00:00:00 2001 From: Anderson Toshiyuki Sasaki Date: Fri, 20 Sep 2019 16:28:03 +0200 Subject: pki: Move common Ed25519 functions to pki_ed25519_common.c This is a preparation to use the Ed25519 implementation from OpenSSL. The function pki_ed25519_sig_to_blob() was renamed to pki_ed25519_signature_to_blob() and pki_ed25519_sig_from_blob() was renamed to pki_signature_from_ed25519_blob() to follow the naming for other algorithms. Signed-off-by: Anderson Toshiyuki Sasaki Reviewed-by: Jakub Jelen --- include/libssh/pki_priv.h | 4 +- src/CMakeLists.txt | 1 + src/pki_crypto.c | 4 +- src/pki_ed25519.c | 184 ------------------------------------- src/pki_ed25519_common.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++ src/pki_gcrypt.c | 4 +- src/pki_mbedcrypto.c | 4 +- 7 files changed, 236 insertions(+), 192 deletions(-) create mode 100644 src/pki_ed25519_common.c diff --git a/include/libssh/pki_priv.h b/include/libssh/pki_priv.h index 39a22cac..24538d8e 100644 --- a/include/libssh/pki_priv.h +++ b/include/libssh/pki_priv.h @@ -148,8 +148,8 @@ int pki_ed25519_key_cmp(const ssh_key k1, enum ssh_keycmp_e what); 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); +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_privkey_build_ed25519(ssh_key key, ssh_string pubkey, ssh_string privkey); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f8d2a2ab..8f2b0337 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -165,6 +165,7 @@ set(libssh_SRCS chachapoly.c config_parser.c token.c + pki_ed25519_common.c ) if (DEFAULT_C_NO_DEPRECATION_FLAGS) diff --git a/src/pki_crypto.c b/src/pki_crypto.c index 3854b119..3f876ee6 100644 --- a/src/pki_crypto.c +++ b/src/pki_crypto.c @@ -1473,7 +1473,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) sig_blob = ssh_string_copy(sig->raw_sig); break; case SSH_KEYTYPE_ED25519: - sig_blob = pki_ed25519_sig_to_blob(sig); + sig_blob = pki_ed25519_signature_to_blob(sig); break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: @@ -1821,7 +1821,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, } break; case SSH_KEYTYPE_ED25519: - rc = pki_ed25519_sig_from_blob(sig, sig_blob); + rc = pki_signature_from_ed25519_blob(sig, sig_blob); if (rc != SSH_OK){ goto error; } diff --git a/src/pki_ed25519.c b/src/pki_ed25519.c index 0eaa4943..fdf94b4e 100644 --- a/src/pki_ed25519.c +++ b/src/pki_ed25519.c @@ -56,28 +56,6 @@ 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, @@ -170,165 +148,3 @@ error: return SSH_ERROR; } -/** - * @internal - * - * @brief Compare ed25519 keys if they are equal. - * - * @param[in] k1 The first key to compare. - * - * @param[in] k2 The second key to compare. - * - * @param[in] what What part or type of the key do you want to compare. - * - * @return 0 if equal, 1 if not. - */ -int pki_ed25519_key_cmp(const ssh_key k1, - const ssh_key k2, - enum ssh_keycmp_e what) -{ - int cmp; - - switch(what) { - case SSH_KEY_CMP_PRIVATE: - if (k1->ed25519_privkey == NULL || k2->ed25519_privkey == NULL) { - return 1; - } - cmp = memcmp(k1->ed25519_privkey, k2->ed25519_privkey, ED25519_SK_LEN); - if (cmp != 0) { - return 1; - } - /* FALL THROUGH */ - case SSH_KEY_CMP_PUBLIC: - if (k1->ed25519_pubkey == NULL || k2->ed25519_pubkey == NULL) { - return 1; - } - cmp = memcmp(k1->ed25519_pubkey, k2->ed25519_pubkey, ED25519_PK_LEN); - if (cmp != 0) { - return 1; - } - } - - return 0; -} - -/** - * @internal - * - * @brief duplicate an ed25519 key - * - * @param[out\ new preinitialized output ssh_ke - * - * @param[in] key key to copy - * - * @return SSH_ERROR on error, SSH_OK on success - */ -int pki_ed25519_key_dup(ssh_key new, const ssh_key key) -{ - if (key->ed25519_privkey == NULL && key->ed25519_pubkey == NULL) { - return SSH_ERROR; - } - - if (key->ed25519_privkey != NULL) { - new->ed25519_privkey = malloc(ED25519_SK_LEN); - if (new->ed25519_privkey == NULL) { - return SSH_ERROR; - } - memcpy(new->ed25519_privkey, key->ed25519_privkey, ED25519_SK_LEN); - } - - if (key->ed25519_pubkey != NULL) { - new->ed25519_pubkey = malloc(ED25519_PK_LEN); - if (new->ed25519_pubkey == NULL) { - SAFE_FREE(new->ed25519_privkey); - return SSH_ERROR; - } - memcpy(new->ed25519_pubkey, key->ed25519_pubkey, ED25519_PK_LEN); - } - - return SSH_OK; -} - -/** - * @internal - * - * @brief outputs an ed25519 public key in a blob buffer. - * - * @param[out] buffer output buffer - * - * @param[in] key key to output - * - * @return SSH_ERROR on error, SSH_OK on success - */ -int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key) -{ - int rc; - - if (key->ed25519_pubkey == NULL){ - return SSH_ERROR; - } - - rc = ssh_buffer_pack(buffer, - "dP", - (uint32_t)ED25519_PK_LEN, - (size_t)ED25519_PK_LEN, key->ed25519_pubkey); - - return rc; -} - -/** - * @internal - * - * @brief output a signature blob from an ed25519 signature - * - * @param[in] sig signature to convert - * - * @return Signature blob in SSH string, or NULL on error - */ -ssh_string pki_ed25519_sig_to_blob(ssh_signature sig) -{ - ssh_string sig_blob; - - if (sig->ed25519_sig == NULL) { - return NULL; - } - - sig_blob = ssh_string_new(ED25519_SIG_LEN); - if (sig_blob == NULL) { - return NULL; - } - ssh_string_fill(sig_blob, sig->ed25519_sig, ED25519_SIG_LEN); - - return sig_blob; -} - -/** - * @internal - * - * @brief Convert a signature blob in an ed25519 signature. - * - * @param[out] sig a preinitialized signature - * - * @param[in] sig_blob a signature blob - * - * @return SSH_ERROR on error, SSH_OK on success - */ -int pki_ed25519_sig_from_blob(ssh_signature sig, ssh_string sig_blob) -{ - size_t len; - - len = ssh_string_len(sig_blob); - if (len != ED25519_SIG_LEN){ - SSH_LOG(SSH_LOG_WARN, "Invalid ssh-ed25519 signature len: %zu", len); - return SSH_ERROR; - } - - sig->ed25519_sig = malloc(ED25519_SIG_LEN); - if (sig->ed25519_sig == NULL){ - return SSH_ERROR; - } - - memcpy(sig->ed25519_sig, ssh_string_data(sig_blob), ED25519_SIG_LEN); - - return SSH_OK; -} diff --git a/src/pki_ed25519_common.c b/src/pki_ed25519_common.c new file mode 100644 index 00000000..25585874 --- /dev/null +++ b/src/pki_ed25519_common.c @@ -0,0 +1,227 @@ +/* + * pki_ed25519_common.c - Common ed25519 functions + * + * This file is part of the SSH Library + * + * Copyright (c) 2014 by Aris Adamantiadis + * + * The SSH Library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the SSH Library; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#include "config.h" + +#include "libssh/pki.h" +#include "libssh/pki_priv.h" +#include "libssh/buffer.h" + +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(2 * ED25519_SK_LEN); + if (key->ed25519_privkey == NULL) { + goto error; + } + + key->ed25519_pubkey = malloc(ED25519_PK_LEN); + if (key->ed25519_pubkey == NULL) { + goto 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; + +error: + SAFE_FREE(key->ed25519_privkey); + SAFE_FREE(key->ed25519_pubkey); + + return SSH_ERROR; +} + +/** + * @internal + * + * @brief Compare ed25519 keys if they are equal. + * + * @param[in] k1 The first key to compare. + * + * @param[in] k2 The second key to compare. + * + * @param[in] what What part or type of the key do you want to compare. + * + * @return 0 if equal, 1 if not. + */ +int pki_ed25519_key_cmp(const ssh_key k1, + const ssh_key k2, + enum ssh_keycmp_e what) +{ + int cmp; + + switch(what) { + case SSH_KEY_CMP_PRIVATE: + if (k1->ed25519_privkey == NULL || k2->ed25519_privkey == NULL) { + return 1; + } + cmp = memcmp(k1->ed25519_privkey, k2->ed25519_privkey, ED25519_SK_LEN); + if (cmp != 0) { + return 1; + } + /* FALL THROUGH */ + case SSH_KEY_CMP_PUBLIC: + if (k1->ed25519_pubkey == NULL || k2->ed25519_pubkey == NULL) { + return 1; + } + cmp = memcmp(k1->ed25519_pubkey, k2->ed25519_pubkey, ED25519_PK_LEN); + if (cmp != 0) { + return 1; + } + } + + return 0; +} + +/** + * @internal + * + * @brief Duplicate an Ed25519 key + * + * @param[out] new Pre-initialized ssh_key structure + * + * @param[in] key Key to copy + * + * @return SSH_ERROR on error, SSH_OK on success + */ +int pki_ed25519_key_dup(ssh_key new, const ssh_key key) +{ + if (key->ed25519_privkey == NULL && key->ed25519_pubkey == NULL) { + return SSH_ERROR; + } + + if (key->ed25519_privkey != NULL) { + new->ed25519_privkey = malloc(ED25519_SK_LEN); + if (new->ed25519_privkey == NULL) { + return SSH_ERROR; + } + memcpy(new->ed25519_privkey, key->ed25519_privkey, ED25519_SK_LEN); + } + + if (key->ed25519_pubkey != NULL) { + new->ed25519_pubkey = malloc(ED25519_PK_LEN); + if (new->ed25519_pubkey == NULL) { + SAFE_FREE(new->ed25519_privkey); + return SSH_ERROR; + } + memcpy(new->ed25519_pubkey, key->ed25519_pubkey, ED25519_PK_LEN); + } + + return SSH_OK; +} + +/** + * @internal + * + * @brief Outputs an Ed25519 public key in a blob buffer. + * + * @param[out] buffer Output buffer + * + * @param[in] key Key to output + * + * @return SSH_ERROR on error, SSH_OK on success + */ +int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key) +{ + int rc; + + if (key->ed25519_pubkey == NULL){ + return SSH_ERROR; + } + + rc = ssh_buffer_pack(buffer, + "dP", + (uint32_t)ED25519_PK_LEN, + (size_t)ED25519_PK_LEN, key->ed25519_pubkey); + + return rc; +} + +/** + * @internal + * + * @brief output a signature blob from an ed25519 signature + * + * @param[in] sig signature to convert + * + * @return Signature blob in SSH string, or NULL on error + */ +ssh_string pki_ed25519_signature_to_blob(ssh_signature sig) +{ + ssh_string sig_blob; + + if (sig->ed25519_sig == NULL) { + return NULL; + } + + sig_blob = ssh_string_new(ED25519_SIG_LEN); + if (sig_blob == NULL) { + return NULL; + } + + ssh_string_fill(sig_blob, sig->ed25519_sig, ED25519_SIG_LEN); + + return sig_blob; +} + +/** + * @internal + * + * @brief Convert a signature blob in an ed25519 signature. + * + * @param[out] sig a preinitialized signature + * + * @param[in] sig_blob a signature blob + * + * @return SSH_ERROR on error, SSH_OK on success + */ +int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob) +{ + size_t len; + + len = ssh_string_len(sig_blob); + if (len != ED25519_SIG_LEN){ + SSH_LOG(SSH_LOG_WARN, "Invalid ssh-ed25519 signature len: %zu", len); + return SSH_ERROR; + } + + sig->ed25519_sig = malloc(ED25519_SIG_LEN); + if (sig->ed25519_sig == NULL){ + return SSH_ERROR; + } + memcpy(sig->ed25519_sig, ssh_string_data(sig_blob), ED25519_SIG_LEN); + + return SSH_OK; +} + diff --git a/src/pki_gcrypt.c b/src/pki_gcrypt.c index 065bf798..8adc8165 100644 --- a/src/pki_gcrypt.c +++ b/src/pki_gcrypt.c @@ -1832,7 +1832,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) gcry_sexp_release(sexp); break; case SSH_KEYTYPE_ED25519: - sig_blob = pki_ed25519_sig_to_blob(sig); + sig_blob = pki_ed25519_signature_to_blob(sig); break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: @@ -1994,7 +1994,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, } break; case SSH_KEYTYPE_ED25519: - rc = pki_ed25519_sig_from_blob(sig, sig_blob); + rc = pki_signature_from_ed25519_blob(sig, sig_blob); if (rc != SSH_OK){ ssh_signature_free(sig); return NULL; diff --git a/src/pki_mbedcrypto.c b/src/pki_mbedcrypto.c index a1ae573e..7236210a 100644 --- a/src/pki_mbedcrypto.c +++ b/src/pki_mbedcrypto.c @@ -837,7 +837,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) break; } case SSH_KEYTYPE_ED25519: - sig_blob = pki_ed25519_sig_to_blob(sig); + sig_blob = pki_ed25519_signature_to_blob(sig); break; default: SSH_LOG(SSH_LOG_WARN, "Unknown signature key type: %s", @@ -1008,7 +1008,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, break; } case SSH_KEYTYPE_ED25519: - rc = pki_ed25519_sig_from_blob(sig, sig_blob); + rc = pki_signature_from_ed25519_blob(sig, sig_blob); if (rc == SSH_ERROR) { ssh_signature_free(sig); return NULL; -- cgit v1.2.3