pki_crypto: Use OpenSSL for Ed25519 signatures
Use OpenSSL to generate and verify Ed25519 signatures, if supported. Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com>
Этот коммит содержится в:
родитель
bdcaf55b90
Коммит
2a2c1c98bf
@ -30,7 +30,15 @@
|
||||
#endif
|
||||
|
||||
#include "libssh/crypto.h"
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* If using OpenSSL implementation, define the signature lenght which would be
|
||||
* defined in libssh/ed25519.h otherwise */
|
||||
#define ED25519_SIG_LEN 64
|
||||
#else
|
||||
#include "libssh/ed25519.h"
|
||||
#endif
|
||||
/* This definition is used for both OpenSSL and internal implementations */
|
||||
#define ED25519_KEY_LEN 32
|
||||
|
||||
#define MAX_PUBKEY_SIZE 0x100000 /* 1M */
|
||||
#define MAX_PRIVKEY_SIZE 0x400000 /* 4M */
|
||||
@ -61,8 +69,13 @@ struct ssh_key_struct {
|
||||
void *ecdsa;
|
||||
# endif /* HAVE_OPENSSL_EC_H */
|
||||
#endif /* HAVE_LIBGCRYPT */
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
uint8_t *ed25519_pubkey;
|
||||
uint8_t *ed25519_privkey;
|
||||
#else
|
||||
ed25519_pubkey *ed25519_pubkey;
|
||||
ed25519_privkey *ed25519_privkey;
|
||||
#endif
|
||||
void *cert;
|
||||
enum ssh_keytypes_e cert_type;
|
||||
};
|
||||
@ -79,7 +92,9 @@ struct ssh_signature_struct {
|
||||
ssh_string rsa_sig;
|
||||
struct mbedtls_ecdsa_sig ecdsa_sig;
|
||||
#endif /* HAVE_LIBGCRYPT */
|
||||
#ifndef HAVE_OPENSSL_ED25519
|
||||
ed25519_signature *ed25519_sig;
|
||||
#endif
|
||||
ssh_string raw_sig;
|
||||
};
|
||||
|
||||
|
@ -146,7 +146,6 @@ set(libssh_SRCS
|
||||
pcap.c
|
||||
pki.c
|
||||
pki_container_openssh.c
|
||||
pki_ed25519.c
|
||||
poll.c
|
||||
session.c
|
||||
scp.c
|
||||
@ -202,6 +201,7 @@ if (WITH_GCRYPT)
|
||||
pki_gcrypt.c
|
||||
ecdh_gcrypt.c
|
||||
dh_key.c
|
||||
pki_ed25519.c
|
||||
)
|
||||
elseif (WITH_MBEDTLS)
|
||||
set(libssh_SRCS
|
||||
@ -212,6 +212,7 @@ elseif (WITH_MBEDTLS)
|
||||
pki_mbedcrypto.c
|
||||
ecdh_mbedcrypto.c
|
||||
dh_key.c
|
||||
pki_ed25519.c
|
||||
)
|
||||
else (WITH_GCRYPT)
|
||||
set(libssh_SRCS
|
||||
@ -222,6 +223,12 @@ else (WITH_GCRYPT)
|
||||
libcrypto.c
|
||||
dh_crypto.c
|
||||
)
|
||||
if (NOT HAVE_OPENSSL_ED25519)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
pki_ed25519.c
|
||||
)
|
||||
endif (NOT HAVE_OPENSSL_ED25519)
|
||||
if(OPENSSL_VERSION VERSION_LESS "1.1.0")
|
||||
set(libssh_SRCS ${libssh_SRCS} libcrypto-compat.c)
|
||||
endif()
|
||||
|
24
src/pki.c
24
src/pki.c
@ -162,7 +162,14 @@ void ssh_key_clean (ssh_key key){
|
||||
}
|
||||
#endif
|
||||
if (key->ed25519_privkey != NULL){
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* In OpenSSL implementation the private key is only the private
|
||||
* original seed. In the internal implementation the private key is the
|
||||
* concatenation of the original private seed with the public key.*/
|
||||
explicit_bzero(key->ed25519_privkey, ED25519_KEY_LEN);
|
||||
#else
|
||||
explicit_bzero(key->ed25519_privkey, sizeof(ed25519_privkey));
|
||||
#endif
|
||||
SAFE_FREE(key->ed25519_privkey);
|
||||
}
|
||||
SAFE_FREE(key->ed25519_pubkey);
|
||||
@ -679,7 +686,10 @@ void ssh_signature_free(ssh_signature sig)
|
||||
#endif
|
||||
break;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
#ifndef HAVE_OPENSSL_ED25519
|
||||
/* When using OpenSSL, the signature is stored in sig->raw_sig */
|
||||
SAFE_FREE(sig->ed25519_sig);
|
||||
#endif
|
||||
break;
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
case SSH_KEYTYPE_RSA_CERT01:
|
||||
@ -1321,21 +1331,21 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
{
|
||||
ssh_string pubkey = ssh_buffer_get_ssh_string(buffer);
|
||||
if (ssh_string_len(pubkey) != ED25519_PK_LEN) {
|
||||
if (ssh_string_len(pubkey) != ED25519_KEY_LEN) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid public key length");
|
||||
ssh_string_burn(pubkey);
|
||||
ssh_string_free(pubkey);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
key->ed25519_pubkey = malloc(ED25519_PK_LEN);
|
||||
key->ed25519_pubkey = malloc(ED25519_KEY_LEN);
|
||||
if (key->ed25519_pubkey == NULL) {
|
||||
ssh_string_burn(pubkey);
|
||||
ssh_string_free(pubkey);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_PK_LEN);
|
||||
memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_KEY_LEN);
|
||||
ssh_string_burn(pubkey);
|
||||
ssh_string_free(pubkey);
|
||||
}
|
||||
@ -2259,7 +2269,7 @@ int ssh_pki_signature_verify(ssh_session session,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = pki_signature_verify(session, sig, key, input, input_len);
|
||||
rc = pki_verify_data_signature(sig, key, input, input_len);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -2283,12 +2293,6 @@ ssh_signature pki_do_sign(const ssh_key privkey,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (privkey->type == SSH_KEYTYPE_ED25519 ||
|
||||
privkey->type == SSH_KEYTYPE_ED25519_CERT01)
|
||||
{
|
||||
return pki_do_sign_hash(privkey, input, input_len, SSH_DIGEST_AUTO);
|
||||
}
|
||||
|
||||
return pki_sign_data(privkey, hash_type, input, input_len);
|
||||
}
|
||||
|
||||
|
@ -415,12 +415,13 @@ static int pki_openssh_export_privkey_blob(const ssh_key privkey,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
rc = ssh_buffer_pack(buffer,
|
||||
"sdPdP",
|
||||
"sdPdPP",
|
||||
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);
|
||||
(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;
|
||||
}
|
||||
|
||||
|
190
src/pki_crypto.c
190
src/pki_crypto.c
@ -821,7 +821,11 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
|
||||
BIO *mem = NULL;
|
||||
DSA *dsa = NULL;
|
||||
RSA *rsa = NULL;
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
uint8_t *ed25519 = NULL;
|
||||
#else
|
||||
ed25519_privkey *ed25519 = NULL;
|
||||
#endif
|
||||
ssh_key key = NULL;
|
||||
enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN;
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
@ -1880,15 +1884,7 @@ int pki_signature_verify(ssh_session session,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* For ed25519 keys, verify using the input directly */
|
||||
if (key->type == SSH_KEYTYPE_ED25519 ||
|
||||
key->type == SSH_KEYTYPE_ED25519_CERT01)
|
||||
{
|
||||
rc = pki_ed25519_verify(key, sig, input, input_len);
|
||||
} else {
|
||||
/* For the other key types, calculate the hash and verify the signature */
|
||||
rc = pki_verify_data_signature(sig, key, input, input_len);
|
||||
}
|
||||
rc = pki_verify_data_signature(sig, key, input, input_len);
|
||||
|
||||
if (rc != SSH_OK){
|
||||
ssh_set_error(session,
|
||||
@ -1918,6 +1914,8 @@ static const EVP_MD *pki_digest_to_md(enum ssh_digest_e hash_type)
|
||||
md = EVP_sha1();
|
||||
break;
|
||||
case SSH_DIGEST_AUTO:
|
||||
md = NULL;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown hash algorithm for type: %d",
|
||||
hash_type);
|
||||
@ -1931,12 +1929,6 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key)
|
||||
{
|
||||
EVP_PKEY *pkey = NULL;
|
||||
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch(key->type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
@ -1944,6 +1936,12 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key)
|
||||
SSH_LOG(SSH_LOG_TRACE, "NULL key->dsa");
|
||||
goto error;
|
||||
}
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EVP_PKEY_set1_DSA(pkey, key->dsa);
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
@ -1953,6 +1951,12 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key)
|
||||
SSH_LOG(SSH_LOG_TRACE, "NULL key->rsa");
|
||||
goto error;
|
||||
}
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EVP_PKEY_set1_RSA(pkey, key->rsa);
|
||||
break;
|
||||
case SSH_KEYTYPE_ECDSA_P256:
|
||||
@ -1966,12 +1970,46 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key)
|
||||
SSH_LOG(SSH_LOG_TRACE, "NULL key->ecdsa");
|
||||
goto error;
|
||||
}
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
|
||||
break;
|
||||
# endif
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
/* Not supported yet. This type requires the use of EVP_DigestSign*()
|
||||
* API and ECX keys. There is no EVP_set1_ECX_KEY() or equivalent yet. */
|
||||
case SSH_KEYTYPE_ED25519_CERT01:
|
||||
# if defined(HAVE_OPENSSL_ED25519)
|
||||
if (ssh_key_is_private(key)) {
|
||||
if (key->ed25519_privkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "NULL key->ed25519_privkey");
|
||||
goto error;
|
||||
}
|
||||
/* In OpenSSL, the input is the private key seed only, which means
|
||||
* the first half of the SSH private key (the second half is the
|
||||
* public key). Both keys have the same length (32 bytes) */
|
||||
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
|
||||
(const uint8_t *)key->ed25519_privkey,
|
||||
ED25519_KEY_LEN);
|
||||
} else {
|
||||
if (key->ed25519_pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "NULL key->ed25519_pubkey");
|
||||
goto error;
|
||||
}
|
||||
pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL,
|
||||
(const uint8_t *)key->ed25519_pubkey,
|
||||
ED25519_KEY_LEN);
|
||||
}
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create ed25519 EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown private key algorithm for type: %d",
|
||||
@ -2027,10 +2065,20 @@ ssh_signature pki_sign_data(const ssh_key privkey,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef HAVE_OPENSSL_ED25519
|
||||
if (privkey->type == SSH_KEYTYPE_ED25519 ||
|
||||
privkey->type == SSH_KEYTYPE_ED25519_CERT01)
|
||||
{
|
||||
return pki_do_sign_hash(privkey, input, input_len, hash_type);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set hash algorithm to be used */
|
||||
md = pki_digest_to_md(hash_type);
|
||||
if (md == NULL) {
|
||||
return NULL;
|
||||
if (hash_type != SSH_DIGEST_AUTO) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup private key EVP_PKEY */
|
||||
@ -2160,7 +2208,11 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
int evp_rc;
|
||||
|
||||
if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL ||
|
||||
signature == NULL || signature->raw_sig == NULL)
|
||||
signature == NULL || (signature->raw_sig == NULL
|
||||
#ifndef HAVE_OPENSSL_ED25519
|
||||
&& signature->ed25519_sig == NULL
|
||||
#endif
|
||||
))
|
||||
{
|
||||
SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to "
|
||||
"pki_verify_data_signature()");
|
||||
@ -2173,6 +2225,14 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifndef HAVE_OPENSSL_ED25519
|
||||
if (pubkey->type == SSH_KEYTYPE_ED25519 ||
|
||||
pubkey->type == SSH_KEYTYPE_ED25519_CERT01)
|
||||
{
|
||||
return pki_ed25519_verify(pubkey, signature, input, input_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the signature to be verified */
|
||||
raw_sig_data = ssh_string_data(signature->raw_sig);
|
||||
raw_sig_len = ssh_string_len(signature->raw_sig);
|
||||
@ -2183,7 +2243,9 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
/* Set hash algorithm to be used */
|
||||
md = pki_digest_to_md(signature->hash_type);
|
||||
if (md == NULL) {
|
||||
return SSH_ERROR;
|
||||
if (signature->hash_type != SSH_DIGEST_AUTO) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup public key EVP_PKEY */
|
||||
@ -2243,6 +2305,92 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
int pki_key_generate_ed25519(ssh_key key)
|
||||
{
|
||||
int evp_rc;
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
size_t privkey_len = ED25519_KEY_LEN;
|
||||
size_t pubkey_len = ED25519_KEY_LEN;
|
||||
|
||||
if (key == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);
|
||||
if (pctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create ed25519 EVP_PKEY_CTX: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto error;
|
||||
}
|
||||
|
||||
evp_rc = EVP_PKEY_keygen_init(pctx);
|
||||
if (evp_rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize ed25519 key generation: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto error;
|
||||
}
|
||||
|
||||
evp_rc = EVP_PKEY_keygen(pctx, &pkey);
|
||||
if (evp_rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to generate ed25519 key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto error;
|
||||
}
|
||||
|
||||
key->ed25519_privkey = malloc(ED25519_KEY_LEN);
|
||||
if (key->ed25519_privkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to allocate memory for ed25519 private key");
|
||||
goto error;
|
||||
}
|
||||
|
||||
key->ed25519_pubkey = malloc(ED25519_KEY_LEN);
|
||||
if (key->ed25519_pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to allocate memory for ed25519 public key");
|
||||
goto error;
|
||||
}
|
||||
|
||||
evp_rc = EVP_PKEY_get_raw_private_key(pkey, (uint8_t *)key->ed25519_privkey,
|
||||
&privkey_len);
|
||||
if (evp_rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get ed25519 raw private key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto error;
|
||||
}
|
||||
|
||||
evp_rc = EVP_PKEY_get_raw_public_key(pkey, (uint8_t *)key->ed25519_pubkey,
|
||||
&pubkey_len);
|
||||
if (evp_rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get ed25519 raw public key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto error;
|
||||
}
|
||||
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
return SSH_OK;
|
||||
|
||||
error:
|
||||
if (pctx != NULL) {
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
}
|
||||
if (pkey != NULL) {
|
||||
EVP_PKEY_free(pkey);
|
||||
}
|
||||
SAFE_FREE(key->ed25519_privkey);
|
||||
SAFE_FREE(key->ed25519_pubkey);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
#else
|
||||
ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
@ -2275,4 +2423,6 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
|
||||
return sig;
|
||||
}
|
||||
#endif /* HAVE_OPENSSL_ED25519 */
|
||||
|
||||
#endif /* _PKI_CRYPTO_H */
|
||||
|
@ -31,27 +31,40 @@ 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)
|
||||
if (ssh_string_len(pubkey) != ED25519_KEY_LEN ||
|
||||
ssh_string_len(privkey) != (2 * ED25519_KEY_LEN))
|
||||
{
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid ed25519 key len");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
key->ed25519_privkey = malloc(2 * ED25519_SK_LEN);
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* In OpenSSL implementation, the private key is the original private seed,
|
||||
* without the public key. */
|
||||
key->ed25519_privkey = malloc(ED25519_KEY_LEN);
|
||||
#else
|
||||
/* In the internal implementation, the private key is the concatenation of
|
||||
* the private seed with the public key. */
|
||||
key->ed25519_privkey = malloc(2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
if (key->ed25519_privkey == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
key->ed25519_pubkey = malloc(ED25519_PK_LEN);
|
||||
key->ed25519_pubkey = malloc(ED25519_KEY_LEN);
|
||||
if (key->ed25519_pubkey == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
memcpy(key->ed25519_privkey, ssh_string_data(privkey),
|
||||
ED25519_SK_LEN);
|
||||
ED25519_KEY_LEN);
|
||||
#else
|
||||
memcpy(key->ed25519_privkey, ssh_string_data(privkey),
|
||||
2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
memcpy(key->ed25519_pubkey, ssh_string_data(pubkey),
|
||||
ED25519_PK_LEN);
|
||||
ED25519_KEY_LEN);
|
||||
|
||||
return SSH_OK;
|
||||
|
||||
@ -86,7 +99,16 @@ int pki_ed25519_key_cmp(const ssh_key k1,
|
||||
if (k1->ed25519_privkey == NULL || k2->ed25519_privkey == NULL) {
|
||||
return 1;
|
||||
}
|
||||
cmp = memcmp(k1->ed25519_privkey, k2->ed25519_privkey, ED25519_SK_LEN);
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* In OpenSSL implementation, the private key is the original private
|
||||
* seed, without the public key. */
|
||||
cmp = memcmp(k1->ed25519_privkey, k2->ed25519_privkey, ED25519_KEY_LEN);
|
||||
#else
|
||||
/* In the internal implementation, the private key is the concatenation
|
||||
* of the private seed with the public key. */
|
||||
cmp = memcmp(k1->ed25519_privkey, k2->ed25519_privkey,
|
||||
2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
if (cmp != 0) {
|
||||
return 1;
|
||||
}
|
||||
@ -95,7 +117,7 @@ int pki_ed25519_key_cmp(const ssh_key k1,
|
||||
if (k1->ed25519_pubkey == NULL || k2->ed25519_pubkey == NULL) {
|
||||
return 1;
|
||||
}
|
||||
cmp = memcmp(k1->ed25519_pubkey, k2->ed25519_pubkey, ED25519_PK_LEN);
|
||||
cmp = memcmp(k1->ed25519_pubkey, k2->ed25519_pubkey, ED25519_KEY_LEN);
|
||||
if (cmp != 0) {
|
||||
return 1;
|
||||
}
|
||||
@ -122,20 +144,32 @@ int pki_ed25519_key_dup(ssh_key new, const ssh_key key)
|
||||
}
|
||||
|
||||
if (key->ed25519_privkey != NULL) {
|
||||
new->ed25519_privkey = malloc(ED25519_SK_LEN);
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* In OpenSSL implementation, the private key is the original private
|
||||
* seed, without the public key. */
|
||||
new->ed25519_privkey = malloc(ED25519_KEY_LEN);
|
||||
#else
|
||||
/* In the internal implementation, the private key is the concatenation
|
||||
* of the private seed with the public key. */
|
||||
new->ed25519_privkey = malloc(2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
if (new->ed25519_privkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(new->ed25519_privkey, key->ed25519_privkey, ED25519_SK_LEN);
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
memcpy(new->ed25519_privkey, key->ed25519_privkey, ED25519_KEY_LEN);
|
||||
#else
|
||||
memcpy(new->ed25519_privkey, key->ed25519_privkey, 2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (key->ed25519_pubkey != NULL) {
|
||||
new->ed25519_pubkey = malloc(ED25519_PK_LEN);
|
||||
new->ed25519_pubkey = malloc(ED25519_KEY_LEN);
|
||||
if (new->ed25519_pubkey == NULL) {
|
||||
SAFE_FREE(new->ed25519_privkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(new->ed25519_pubkey, key->ed25519_pubkey, ED25519_PK_LEN);
|
||||
memcpy(new->ed25519_pubkey, key->ed25519_pubkey, ED25519_KEY_LEN);
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
@ -162,8 +196,8 @@ int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key)
|
||||
|
||||
rc = ssh_buffer_pack(buffer,
|
||||
"dP",
|
||||
(uint32_t)ED25519_PK_LEN,
|
||||
(size_t)ED25519_PK_LEN, key->ed25519_pubkey);
|
||||
(uint32_t)ED25519_KEY_LEN,
|
||||
(size_t)ED25519_KEY_LEN, key->ed25519_pubkey);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -181,16 +215,31 @@ ssh_string pki_ed25519_signature_to_blob(ssh_signature sig)
|
||||
{
|
||||
ssh_string sig_blob;
|
||||
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* When using the OpenSSL implementation, the signature is stored in raw_sig
|
||||
* which is shared by all algorithms.*/
|
||||
if (sig->raw_sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
/* When using the internal implementation, the signature is stored in an
|
||||
* algorithm specific field. */
|
||||
if (sig->ed25519_sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
sig_blob = ssh_string_new(ED25519_SIG_LEN);
|
||||
if (sig_blob == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
ssh_string_fill(sig_blob, ssh_string_data(sig->raw_sig),
|
||||
ssh_string_len(sig->raw_sig));
|
||||
#else
|
||||
ssh_string_fill(sig_blob, sig->ed25519_sig, ED25519_SIG_LEN);
|
||||
#endif
|
||||
|
||||
return sig_blob;
|
||||
}
|
||||
@ -216,11 +265,15 @@ int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob)
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
sig->raw_sig = ssh_string_copy(sig_blob);
|
||||
#else
|
||||
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);
|
||||
#endif
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
@ -422,8 +422,16 @@ static void torture_pki_ed25519_generate_key(void **state)
|
||||
enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN;
|
||||
const char *type_char = NULL;
|
||||
ssh_session session=ssh_new();
|
||||
uint8_t *raw_sig_data = NULL;
|
||||
(void) state;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
assert_non_null(session);
|
||||
|
||||
rc = ssh_pki_generate(SSH_KEYTYPE_ED25519, 256, &key);
|
||||
assert_true(rc == SSH_OK);
|
||||
assert_non_null(key);
|
||||
@ -440,7 +448,13 @@ static void torture_pki_ed25519_generate_key(void **state)
|
||||
assert_true(strcmp(type_char, "ssh-ed25519") == 0);
|
||||
|
||||
/* try an invalid signature */
|
||||
(*sign->ed25519_sig)[3]^= 0xff;
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
raw_sig_data = ssh_string_data(sign->raw_sig);
|
||||
#else
|
||||
raw_sig_data = (uint8_t *)sign->ed25519_sig;
|
||||
#endif
|
||||
assert_non_null(raw_sig_data);
|
||||
(raw_sig_data)[3]^= 0xff;
|
||||
rc = pki_signature_verify(session, sign, pubkey, HASH, 20);
|
||||
assert_true(rc == SSH_ERROR);
|
||||
|
||||
@ -459,6 +473,13 @@ static void torture_pki_ed25519_cert_verify(void **state)
|
||||
ssh_session session=ssh_new();
|
||||
(void) state;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
assert_non_null(session);
|
||||
|
||||
rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY,
|
||||
NULL,
|
||||
NULL,
|
||||
@ -599,10 +620,12 @@ static void torture_pki_ed25519_sign(void **state)
|
||||
const char *keystring = NULL;
|
||||
int rc;
|
||||
|
||||
(void)state;
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
sig = ssh_signature_new();
|
||||
assert_non_null(sig);
|
||||
(void)state;
|
||||
|
||||
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0);
|
||||
rc = ssh_pki_import_privkey_base64(keystring,
|
||||
@ -613,9 +636,8 @@ static void torture_pki_ed25519_sign(void **state)
|
||||
assert_true(rc == SSH_OK);
|
||||
assert_non_null(privkey);
|
||||
|
||||
sig->type = SSH_KEYTYPE_ED25519;
|
||||
rc = pki_ed25519_sign(privkey, sig, HASH, sizeof(HASH));
|
||||
assert_true(rc == SSH_OK);
|
||||
sig = pki_do_sign(privkey, HASH, sizeof(HASH), SSH_DIGEST_AUTO);
|
||||
assert_non_null(sig);
|
||||
|
||||
blob = pki_signature_to_blob(sig);
|
||||
assert_non_null(blob);
|
||||
@ -632,12 +654,22 @@ static void torture_pki_ed25519_sign(void **state)
|
||||
static void torture_pki_ed25519_verify(void **state){
|
||||
ssh_key pubkey = NULL;
|
||||
ssh_signature sig = NULL;
|
||||
ssh_session session = NULL;
|
||||
ssh_string blob = ssh_string_new(ED25519_SIG_LEN);
|
||||
char *pkey_ptr = strdup(strchr(torture_get_testkey_pub(SSH_KEYTYPE_ED25519), ' ') + 1);
|
||||
char *ptr = NULL;
|
||||
uint8_t *raw_sig_data = NULL;
|
||||
int rc;
|
||||
(void) state;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
session = ssh_new();
|
||||
assert_non_null(session);
|
||||
|
||||
/* remove trailing comment */
|
||||
ptr = strchr(pkey_ptr, ' ');
|
||||
if(ptr != NULL){
|
||||
@ -651,20 +683,32 @@ static void torture_pki_ed25519_verify(void **state){
|
||||
sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519, SSH_DIGEST_AUTO);
|
||||
assert_non_null(sig);
|
||||
|
||||
rc = pki_ed25519_verify(pubkey, sig, HASH, sizeof(HASH));
|
||||
rc = pki_signature_verify(session, sig, pubkey, HASH, sizeof(HASH));
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
/* Alter signature and expect verification error */
|
||||
#if defined(HAVE_OPENSSL_ED25519)
|
||||
raw_sig_data = ssh_string_data(sig->raw_sig);
|
||||
#else
|
||||
raw_sig_data = (uint8_t *)sig->ed25519_sig;
|
||||
#endif
|
||||
assert_non_null(raw_sig_data);
|
||||
(raw_sig_data)[3]^= 0xff;
|
||||
rc = pki_signature_verify(session, sig, pubkey, HASH, sizeof(HASH));
|
||||
assert_true(rc == SSH_ERROR);
|
||||
|
||||
ssh_signature_free(sig);
|
||||
/* alter signature and expect false result */
|
||||
|
||||
SSH_KEY_FREE(pubkey);
|
||||
SSH_STRING_FREE(blob);
|
||||
free(pkey_ptr);
|
||||
ssh_free(session);
|
||||
}
|
||||
|
||||
static void torture_pki_ed25519_verify_bad(void **state){
|
||||
ssh_key pubkey = NULL;
|
||||
ssh_signature sig = NULL;
|
||||
ssh_session session = NULL;
|
||||
ssh_string blob = ssh_string_new(ED25519_SIG_LEN);
|
||||
char *pkey_ptr = strdup(strchr(torture_get_testkey_pub(SSH_KEYTYPE_ED25519), ' ') + 1);
|
||||
char *ptr = NULL;
|
||||
@ -672,6 +716,14 @@ static void torture_pki_ed25519_verify_bad(void **state){
|
||||
int i;
|
||||
(void) state;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
session = ssh_new();
|
||||
assert_non_null(session);
|
||||
|
||||
/* remove trailing comment */
|
||||
ptr = strchr(pkey_ptr, ' ');
|
||||
if(ptr != NULL){
|
||||
@ -689,7 +741,7 @@ static void torture_pki_ed25519_verify_bad(void **state){
|
||||
sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519, SSH_DIGEST_AUTO);
|
||||
assert_non_null(sig);
|
||||
|
||||
rc = pki_ed25519_verify(pubkey, sig, HASH, sizeof(HASH));
|
||||
rc = pki_signature_verify(session, sig, pubkey, HASH, sizeof(HASH));
|
||||
assert_true(rc == SSH_ERROR);
|
||||
ssh_signature_free(sig);
|
||||
|
||||
@ -697,6 +749,7 @@ static void torture_pki_ed25519_verify_bad(void **state){
|
||||
SSH_KEY_FREE(pubkey);
|
||||
SSH_STRING_FREE(blob);
|
||||
free(pkey_ptr);
|
||||
ssh_free(session);
|
||||
}
|
||||
|
||||
static void torture_pki_ed25519_import_privkey_base64_passphrase(void **state)
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user