aboutsummaryrefslogtreecommitdiff
path: root/src/libcrypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcrypto.c')
-rw-r--r--src/libcrypto.c1010
1 files changed, 512 insertions, 498 deletions
diff --git a/src/libcrypto.c b/src/libcrypto.c
index 96abec14..f45ffa96 100644
--- a/src/libcrypto.c
+++ b/src/libcrypto.c
@@ -26,26 +26,31 @@
#include <string.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
-#endif
+#endif /* HAVE_SYS_TIME_H */
#include "libssh/priv.h"
#include "libssh/session.h"
#include "libssh/crypto.h"
#include "libssh/wrapper.h"
#include "libssh/libcrypto.h"
-#if defined(HAVE_OPENSSL_EVP_CHACHA20) && defined(HAVE_OPENSSL_EVP_POLY1305)
+#include "libssh/pki.h"
+#ifdef HAVE_OPENSSL_EVP_CHACHA20
#include "libssh/bytearray.h"
#include "libssh/chacha20-poly1305-common.h"
#endif
#ifdef HAVE_LIBCRYPTO
+#include <openssl/opensslv.h>
#include <openssl/sha.h>
#include <openssl/md5.h>
-#include <openssl/dsa.h>
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
#include <openssl/rsa.h>
#include <openssl/hmac.h>
-#include <openssl/opensslv.h>
+#else
+#include <openssl/param_build.h>
+#include <openssl/core_names.h>
+#endif /* OPENSSL_VERSION_NUMBER */
#include <openssl/rand.h>
#include <openssl/engine.h>
@@ -54,11 +59,11 @@
#ifdef HAVE_OPENSSL_AES_H
#define HAS_AES
#include <openssl/aes.h>
-#endif
+#endif /* HAVE_OPENSSL_AES_H */
#ifdef HAVE_OPENSSL_DES_H
#define HAS_DES
#include <openssl/des.h>
-#endif
+#endif /* HAVE_OPENSSL_DES_H */
#if (defined(HAVE_VALGRIND_VALGRIND_H) && defined(HAVE_OPENSSL_IA32CAP_LOC))
#include <valgrind/valgrind.h>
@@ -67,18 +72,19 @@
#include "libssh/crypto.h"
-#ifdef HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID
+#ifdef HAVE_OPENSSL_EVP_KDF_CTX
#include <openssl/kdf.h>
-#endif
-
-#ifdef HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT
-#include <openssl/modes.h>
-#endif
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/param_build.h>
+#include <openssl/core_names.h>
+#endif /* OPENSSL_VERSION_NUMBER */
+#endif /* HAVE_OPENSSL_EVP_KDF_CTX */
#include "libssh/crypto.h"
static int libcrypto_initialized = 0;
+
void ssh_reseed(void){
#ifndef _WIN32
struct timeval tv;
@@ -87,270 +93,42 @@ void ssh_reseed(void){
#endif
}
-/**
- * @brief Get random bytes
- *
- * Make sure to always check the return code of this function!
- *
- * @param[in] where The buffer to fill with random bytes
- *
- * @param[in] len The size of the buffer to fill.
- *
- * @param[in] strong Use a strong or private RNG source.
- *
- * @return 1 on success, 0 on error.
- */
-int ssh_get_random(void *where, int len, int strong)
-{
-#ifdef HAVE_OPENSSL_RAND_PRIV_BYTES
- if (strong) {
- /* Returns -1 when not supported, 0 on error, 1 on success */
- return !!RAND_priv_bytes(where, len);
- }
-#else
- (void)strong;
-#endif /* HAVE_RAND_PRIV_BYTES */
-
- /* Returns -1 when not supported, 0 on error, 1 on success */
- return !!RAND_bytes(where, len);
-}
+#ifndef WITH_PKCS11_PROVIDER
+static ENGINE *engine = NULL;
-SHACTX sha1_init(void)
+ENGINE *pki_get_engine(void)
{
- int rc;
- SHACTX c = EVP_MD_CTX_create();
- if (c == NULL) {
- return NULL;
- }
- EVP_MD_CTX_init(c);
- rc = EVP_DigestInit_ex(c, EVP_sha1(), NULL);
- if (rc == 0) {
- EVP_MD_CTX_destroy(c);
- c = NULL;
- }
- return c;
-}
-
-void sha1_update(SHACTX c, const void *data, unsigned long len)
-{
- EVP_DigestUpdate(c, data, len);
-}
+ int ok;
-void sha1_final(unsigned char *md, SHACTX c)
-{
- unsigned int mdlen = 0;
-
- EVP_DigestFinal(c, md, &mdlen);
- EVP_MD_CTX_destroy(c);
-}
-
-void sha1(const unsigned char *digest, int len, unsigned char *hash)
-{
- SHACTX c = sha1_init();
- if (c != NULL) {
- sha1_update(c, digest, len);
- sha1_final(hash, c);
- }
-}
+ if (engine == NULL) {
+ ENGINE_load_builtin_engines();
-#ifdef HAVE_OPENSSL_ECC
-static const EVP_MD *nid_to_evpmd(int nid)
-{
- switch (nid) {
- case NID_X9_62_prime256v1:
- return EVP_sha256();
- case NID_secp384r1:
- return EVP_sha384();
- case NID_secp521r1:
- return EVP_sha512();
- default:
+ engine = ENGINE_by_id("pkcs11");
+ if (engine == NULL) {
+ SSH_LOG(SSH_LOG_TRACE,
+ "Could not load the engine: %s",
+ ERR_error_string(ERR_get_error(), NULL));
return NULL;
- }
-
- return NULL;
-}
-
-void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen)
-{
- const EVP_MD *evp_md = nid_to_evpmd(nid);
- EVP_MD_CTX *md = EVP_MD_CTX_new();
-
- EVP_DigestInit(md, evp_md);
- EVP_DigestUpdate(md, digest, len);
- EVP_DigestFinal(md, hash, hlen);
- EVP_MD_CTX_free(md);
-}
-
-EVPCTX evp_init(int nid)
-{
- const EVP_MD *evp_md = nid_to_evpmd(nid);
-
- EVPCTX ctx = EVP_MD_CTX_new();
- if (ctx == NULL) {
- return NULL;
- }
-
- EVP_DigestInit(ctx, evp_md);
-
- return ctx;
-}
-
-void evp_update(EVPCTX ctx, const void *data, unsigned long len)
-{
- EVP_DigestUpdate(ctx, data, len);
-}
-
-void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
-{
- EVP_DigestFinal(ctx, md, mdlen);
- EVP_MD_CTX_free(ctx);
-}
-#endif
-
-SHA256CTX sha256_init(void)
-{
- int rc;
- SHA256CTX c = EVP_MD_CTX_create();
- if (c == NULL) {
- return NULL;
- }
- EVP_MD_CTX_init(c);
- rc = EVP_DigestInit_ex(c, EVP_sha256(), NULL);
- if (rc == 0) {
- EVP_MD_CTX_destroy(c);
- c = NULL;
- }
- return c;
-}
-
-void sha256_update(SHA256CTX c, const void *data, unsigned long len)
-{
- EVP_DigestUpdate(c, data, len);
-}
-
-void sha256_final(unsigned char *md, SHA256CTX c)
-{
- unsigned int mdlen = 0;
-
- EVP_DigestFinal(c, md, &mdlen);
- EVP_MD_CTX_destroy(c);
-}
-
-void sha256(const unsigned char *digest, int len, unsigned char *hash)
-{
- SHA256CTX c = sha256_init();
- if (c != NULL) {
- sha256_update(c, digest, len);
- sha256_final(hash, c);
- }
-}
-
-SHA384CTX sha384_init(void)
-{
- int rc;
- SHA384CTX c = EVP_MD_CTX_create();
- if (c == NULL) {
- return NULL;
- }
- EVP_MD_CTX_init(c);
- rc = EVP_DigestInit_ex(c, EVP_sha384(), NULL);
- if (rc == 0) {
- EVP_MD_CTX_destroy(c);
- c = NULL;
- }
- return c;
-}
-
-void sha384_update(SHA384CTX c, const void *data, unsigned long len)
-{
- EVP_DigestUpdate(c, data, len);
-}
-
-void sha384_final(unsigned char *md, SHA384CTX c)
-{
- unsigned int mdlen = 0;
-
- EVP_DigestFinal(c, md, &mdlen);
- EVP_MD_CTX_destroy(c);
-}
-
-void sha384(const unsigned char *digest, int len, unsigned char *hash)
-{
- SHA384CTX c = sha384_init();
- if (c != NULL) {
- sha384_update(c, digest, len);
- sha384_final(hash, c);
- }
-}
-
-SHA512CTX sha512_init(void)
-{
- int rc = 0;
- SHA512CTX c = EVP_MD_CTX_create();
- if (c == NULL) {
- return NULL;
- }
- EVP_MD_CTX_init(c);
- rc = EVP_DigestInit_ex(c, EVP_sha512(), NULL);
- if (rc == 0) {
- EVP_MD_CTX_destroy(c);
- c = NULL;
- }
- return c;
-}
-
-void sha512_update(SHA512CTX c, const void *data, unsigned long len)
-{
- EVP_DigestUpdate(c, data, len);
-}
-
-void sha512_final(unsigned char *md, SHA512CTX c)
-{
- unsigned int mdlen = 0;
-
- EVP_DigestFinal(c, md, &mdlen);
- EVP_MD_CTX_destroy(c);
-}
-
-void sha512(const unsigned char *digest, int len, unsigned char *hash)
-{
- SHA512CTX c = sha512_init();
- if (c != NULL) {
- sha512_update(c, digest, len);
- sha512_final(hash, c);
- }
-}
+ }
+ SSH_LOG(SSH_LOG_DEBUG, "Engine loaded successfully");
+
+ ok = ENGINE_init(engine);
+ if (!ok) {
+ SSH_LOG(SSH_LOG_TRACE,
+ "Could not initialize the engine: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ ENGINE_free(engine);
+ return NULL;
+ }
-MD5CTX md5_init(void)
-{
- int rc;
- MD5CTX c = EVP_MD_CTX_create();
- if (c == NULL) {
- return NULL;
- }
- EVP_MD_CTX_init(c);
- rc = EVP_DigestInit_ex(c, EVP_md5(), NULL);
- if(rc == 0) {
- EVP_MD_CTX_destroy(c);
- c = NULL;
+ SSH_LOG(SSH_LOG_DEBUG, "Engine init success");
}
- return c;
-}
-
-void md5_update(MD5CTX c, const void *data, unsigned long len)
-{
- EVP_DigestUpdate(c, data, len);
-}
-
-void md5_final(unsigned char *md, MD5CTX c)
-{
- unsigned int mdlen = 0;
-
- EVP_DigestFinal(c, md, &mdlen);
- EVP_MD_CTX_destroy(c);
+ return engine;
}
+#endif /* WITH_PKCS11_PROVIDER */
-#ifdef HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID
+#ifdef HAVE_OPENSSL_EVP_KDF_CTX
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
static const EVP_MD *sshkdf_digest_to_md(enum ssh_kdf_digest digest_type)
{
switch (digest_type) {
@@ -365,19 +143,50 @@ static const EVP_MD *sshkdf_digest_to_md(enum ssh_kdf_digest digest_type)
}
return NULL;
}
+#else
+static const char *sshkdf_digest_to_md(enum ssh_kdf_digest digest_type)
+{
+ switch (digest_type) {
+ case SSH_KDF_SHA1:
+ return SN_sha1;
+ case SSH_KDF_SHA256:
+ return SN_sha256;
+ case SSH_KDF_SHA384:
+ return SN_sha384;
+ case SSH_KDF_SHA512:
+ return SN_sha512;
+ }
+ return NULL;
+}
+#endif /* OPENSSL_VERSION_NUMBER */
int ssh_kdf(struct ssh_crypto_struct *crypto,
unsigned char *key, size_t key_len,
- int key_type, unsigned char *output,
+ uint8_t key_type, unsigned char *output,
size_t requested_len)
{
+ int rc = -1;
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
EVP_KDF_CTX *ctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF);
- int rc;
+#else
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SSHKDF", NULL);
+ EVP_KDF_CTX *ctx = EVP_KDF_CTX_new(kdf);
+ OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new();
+ OSSL_PARAM *params = NULL;
+ const char *md = sshkdf_digest_to_md(crypto->digest_type);
+
+ EVP_KDF_free(kdf);
+ if (param_bld == NULL) {
+ EVP_KDF_CTX_free(ctx);
+ return -1;
+ }
+#endif /* OPENSSL_VERSION_NUMBER */
if (ctx == NULL) {
- return -1;
+ goto out;
}
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD,
sshkdf_digest_to_md(crypto->digest_type));
if (rc != 1) {
@@ -397,7 +206,7 @@ int ssh_kdf(struct ssh_crypto_struct *crypto,
goto out;
}
rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID,
- crypto->session_id, crypto->digest_len);
+ crypto->session_id, crypto->session_id_len);
if (rc != 1) {
goto out;
}
@@ -405,8 +214,60 @@ int ssh_kdf(struct ssh_crypto_struct *crypto,
if (rc != 1) {
goto out;
}
+#else
+ rc = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_DIGEST,
+ md, strlen(md));
+ if (rc != 1) {
+ rc = -1;
+ goto out;
+ }
+ rc = OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_KEY,
+ key, key_len);
+ if (rc != 1) {
+ rc = -1;
+ goto out;
+ }
+ rc = OSSL_PARAM_BLD_push_octet_string(param_bld,
+ OSSL_KDF_PARAM_SSHKDF_XCGHASH,
+ crypto->secret_hash,
+ crypto->digest_len);
+ if (rc != 1) {
+ rc = -1;
+ goto out;
+ }
+ rc = OSSL_PARAM_BLD_push_octet_string(param_bld,
+ OSSL_KDF_PARAM_SSHKDF_SESSION_ID,
+ crypto->session_id,
+ crypto->session_id_len);
+ if (rc != 1) {
+ rc = -1;
+ goto out;
+ }
+ rc = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_SSHKDF_TYPE,
+ (const char*)&key_type, 1);
+ if (rc != 1) {
+ rc = -1;
+ goto out;
+ }
+
+ params = OSSL_PARAM_BLD_to_param(param_bld);
+ if (params == NULL) {
+ rc = -1;
+ goto out;
+ }
+
+ rc = EVP_KDF_derive(ctx, output, requested_len, params);
+ if (rc != 1) {
+ rc = -1;
+ goto out;
+ }
+#endif /* OPENSSL_VERSION_NUMBER */
out:
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ OSSL_PARAM_BLD_free(param_bld);
+ OSSL_PARAM_free(params);
+#endif
EVP_KDF_CTX_free(ctx);
if (rc < 0) {
return rc;
@@ -417,64 +278,83 @@ out:
#else
int ssh_kdf(struct ssh_crypto_struct *crypto,
unsigned char *key, size_t key_len,
- int key_type, unsigned char *output,
+ uint8_t key_type, unsigned char *output,
size_t requested_len)
{
return sshkdf_derive_key(crypto, key, key_len,
key_type, output, requested_len);
}
-#endif
+#endif /* HAVE_OPENSSL_EVP_KDF_CTX */
-HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) {
- HMACCTX ctx = NULL;
+HMACCTX hmac_init(const void *key, size_t len, enum ssh_hmac_e type)
+{
+ HMACCTX ctx = NULL;
+ EVP_PKEY *pkey = NULL;
+ int rc = -1;
- ctx = HMAC_CTX_new();
- if (ctx == NULL) {
- return NULL;
- }
+ ctx = EVP_MD_CTX_new();
+ if (ctx == NULL) {
+ return NULL;
+ }
+ pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, len);
+ if (pkey == NULL) {
+ goto error;
+ }
- switch(type) {
+ switch (type) {
case SSH_HMAC_SHA1:
- HMAC_Init_ex(ctx, key, len, EVP_sha1(), NULL);
- break;
+ rc = EVP_DigestSignInit(ctx, NULL, EVP_sha1(), NULL, pkey);
+ break;
case SSH_HMAC_SHA256:
- HMAC_Init_ex(ctx, key, len, EVP_sha256(), NULL);
- break;
+ rc = EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, pkey);
+ break;
case SSH_HMAC_SHA512:
- HMAC_Init_ex(ctx, key, len, EVP_sha512(), NULL);
- break;
+ rc = EVP_DigestSignInit(ctx, NULL, EVP_sha512(), NULL, pkey);
+ break;
case SSH_HMAC_MD5:
- HMAC_Init_ex(ctx, key, len, EVP_md5(), NULL);
- break;
+ rc = EVP_DigestSignInit(ctx, NULL, EVP_md5(), NULL, pkey);
+ break;
default:
- HMAC_CTX_free(ctx);
- ctx = NULL;
- }
+ rc = -1;
+ break;
+ }
+
+ EVP_PKEY_free(pkey);
+ if (rc != 1) {
+ goto error;
+ }
+ return ctx;
- return ctx;
+error:
+ EVP_MD_CTX_free(ctx);
+ return NULL;
}
-void hmac_update(HMACCTX ctx, const void *data, unsigned long len) {
- HMAC_Update(ctx, data, len);
+int hmac_update(HMACCTX ctx, const void *data, size_t len)
+{
+ return EVP_DigestSignUpdate(ctx, data, len);
}
-void hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, unsigned int *len) {
- HMAC_Final(ctx,hashmacbuf,len);
+int hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, size_t *len)
+{
+ size_t res = *len;
+ int rc;
+ rc = EVP_DigestSignFinal(ctx, hashmacbuf, &res);
+ EVP_MD_CTX_free(ctx);
+ if (rc == 1) {
+ *len = res;
+ }
-#if OPENSSL_VERSION_NUMBER > 0x10100000L
- HMAC_CTX_free(ctx);
- ctx = NULL;
-#else
- HMAC_cleanup(ctx);
- SAFE_FREE(ctx);
- ctx = NULL;
-#endif
+ return rc;
}
-static void evp_cipher_init(struct ssh_cipher_struct *cipher) {
+static void evp_cipher_init(struct ssh_cipher_struct *cipher)
+{
if (cipher->ctx == NULL) {
cipher->ctx = EVP_CIPHER_CTX_new();
+ } else {
+ EVP_CIPHER_CTX_init(cipher->ctx);
}
switch(cipher->ciphertype){
@@ -487,7 +367,6 @@ static void evp_cipher_init(struct ssh_cipher_struct *cipher) {
case SSH_AES256_CBC:
cipher->cipher = EVP_aes_256_cbc();
break;
-#ifdef HAVE_OPENSSL_EVP_AES_CTR
case SSH_AES128_CTR:
cipher->cipher = EVP_aes_128_ctr();
break;
@@ -497,26 +376,12 @@ static void evp_cipher_init(struct ssh_cipher_struct *cipher) {
case SSH_AES256_CTR:
cipher->cipher = EVP_aes_256_ctr();
break;
-#else
- case SSH_AES128_CTR:
- case SSH_AES192_CTR:
- case SSH_AES256_CTR:
- SSH_LOG(SSH_LOG_WARNING, "This cipher is not available in evp_cipher_init");
- break;
-#endif
-#ifdef HAVE_OPENSSL_EVP_AES_GCM
case SSH_AEAD_AES128_GCM:
cipher->cipher = EVP_aes_128_gcm();
break;
case SSH_AEAD_AES256_GCM:
cipher->cipher = EVP_aes_256_gcm();
break;
-#else
- case SSH_AEAD_AES128_GCM:
- case SSH_AEAD_AES256_GCM:
- SSH_LOG(SSH_LOG_WARNING, "This cipher is not available in evp_cipher_init");
- break;
-#endif /* HAVE_OPENSSL_EVP_AES_GCM */
case SSH_3DES_CBC:
cipher->cipher = EVP_des_ede3_cbc();
break;
@@ -525,12 +390,12 @@ static void evp_cipher_init(struct ssh_cipher_struct *cipher) {
cipher->cipher = EVP_bf_cbc();
break;
/* ciphers not using EVP */
-#endif
+#endif /* WITH_BLOWFISH_CIPHER */
case SSH_AEAD_CHACHA20_POLY1305:
- SSH_LOG(SSH_LOG_WARNING, "The ChaCha cipher cannot be handled here");
+ SSH_LOG(SSH_LOG_TRACE, "The ChaCha cipher cannot be handled here");
break;
case SSH_NO_CIPHER:
- SSH_LOG(SSH_LOG_WARNING, "No valid ciphertype found");
+ SSH_LOG(SSH_LOG_TRACE, "No valid ciphertype found");
break;
}
}
@@ -541,15 +406,13 @@ static int evp_cipher_set_encrypt_key(struct ssh_cipher_struct *cipher,
int rc;
evp_cipher_init(cipher);
- EVP_CIPHER_CTX_reset(cipher->ctx);
rc = EVP_EncryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV);
if (rc != 1){
- SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptInit_ex failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptInit_ex failed");
return SSH_ERROR;
}
-#ifdef HAVE_OPENSSL_EVP_AES_GCM
/* For AES-GCM we need to set IV in specific way */
if (cipher->ciphertype == SSH_AEAD_AES128_GCM ||
cipher->ciphertype == SSH_AEAD_AES256_GCM) {
@@ -558,11 +421,10 @@ static int evp_cipher_set_encrypt_key(struct ssh_cipher_struct *cipher,
-1,
(uint8_t *)IV);
if (rc != 1) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_SET_IV_FIXED failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_SET_IV_FIXED failed");
return SSH_ERROR;
}
}
-#endif /* HAVE_OPENSSL_EVP_AES_GCM */
EVP_CIPHER_CTX_set_padding(cipher->ctx, 0);
@@ -574,15 +436,13 @@ static int evp_cipher_set_decrypt_key(struct ssh_cipher_struct *cipher,
int rc;
evp_cipher_init(cipher);
- EVP_CIPHER_CTX_reset(cipher->ctx);
rc = EVP_DecryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV);
if (rc != 1){
- SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptInit_ex failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_DecryptInit_ex failed");
return SSH_ERROR;
}
-#ifdef HAVE_OPENSSL_EVP_AES_GCM
/* For AES-GCM we need to set IV in specific way */
if (cipher->ciphertype == SSH_AEAD_AES128_GCM ||
cipher->ciphertype == SSH_AEAD_AES256_GCM) {
@@ -591,11 +451,10 @@ static int evp_cipher_set_decrypt_key(struct ssh_cipher_struct *cipher,
-1,
(uint8_t *)IV);
if (rc != 1) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_SET_IV_FIXED failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_SET_IV_FIXED failed");
return SSH_ERROR;
}
}
-#endif /* HAVE_OPENSSL_EVP_AES_GCM */
EVP_CIPHER_CTX_set_padding(cipher->ctx, 0);
@@ -617,11 +476,11 @@ static void evp_cipher_encrypt(struct ssh_cipher_struct *cipher,
(unsigned char *)in,
(int)len);
if (rc != 1){
- SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptUpdate failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptUpdate failed");
return;
}
if (outlen != (int)len){
- SSH_LOG(SSH_LOG_WARNING,
+ SSH_LOG(SSH_LOG_DEBUG,
"EVP_EncryptUpdate: output size %d for %zu in",
outlen,
len);
@@ -643,11 +502,11 @@ static void evp_cipher_decrypt(struct ssh_cipher_struct *cipher,
(unsigned char *)in,
(int)len);
if (rc != 1){
- SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptUpdate failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_DecryptUpdate failed");
return;
}
if (outlen != (int)len){
- SSH_LOG(SSH_LOG_WARNING,
+ SSH_LOG(SSH_LOG_DEBUG,
"EVP_DecryptUpdate: output size %d for %zu in",
outlen,
len);
@@ -661,68 +520,6 @@ static void evp_cipher_cleanup(struct ssh_cipher_struct *cipher) {
}
}
-#ifndef HAVE_OPENSSL_EVP_AES_CTR
-/* Some OS (osx, OpenIndiana, ...) have no support for CTR ciphers in EVP_aes */
-
-struct ssh_aes_key_schedule {
- AES_KEY key;
- uint8_t IV[AES_BLOCK_SIZE];
-};
-
-static int aes_ctr_set_key(struct ssh_cipher_struct *cipher, void *key,
- void *IV) {
- int rc;
-
- if (cipher->aes_key == NULL) {
- cipher->aes_key = malloc(sizeof (struct ssh_aes_key_schedule));
- }
- if (cipher->aes_key == NULL) {
- return SSH_ERROR;
- }
- ZERO_STRUCTP(cipher->aes_key);
- /* CTR doesn't need a decryption key */
- rc = AES_set_encrypt_key(key, cipher->keysize, &cipher->aes_key->key);
- if (rc < 0) {
- SAFE_FREE(cipher->aes_key);
- return SSH_ERROR;
- }
- memcpy(cipher->aes_key->IV, IV, AES_BLOCK_SIZE);
- return SSH_OK;
-}
-
-static void
-aes_ctr_encrypt(struct ssh_cipher_struct *cipher,
- void *in,
- void *out,
- size_t len)
-{
- unsigned char tmp_buffer[AES_BLOCK_SIZE];
- unsigned int num=0;
- /* Some things are special with ctr128 :
- * In this case, tmp_buffer is not being used, because it is used to store temporary data
- * when an encryption is made on lengths that are not multiple of blocksize.
- * Same for num, which is being used to store the current offset in blocksize in CTR
- * function.
- */
-#ifdef HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT
- CRYPTO_ctr128_encrypt(in, out, len, &cipher->aes_key->key, cipher->aes_key->IV, tmp_buffer, &num, (block128_f)AES_encrypt);
-#else
- AES_ctr128_encrypt(in, out, len, &cipher->aes_key->key, cipher->aes_key->IV, tmp_buffer, &num);
-#endif /* HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT */
-}
-
-static void aes_ctr_cleanup(struct ssh_cipher_struct *cipher){
- if (cipher != NULL) {
- if (cipher->aes_key != NULL) {
- explicit_bzero(cipher->aes_key, sizeof(*cipher->aes_key));
- }
- SAFE_FREE(cipher->aes_key);
- }
-}
-
-#endif /* HAVE_OPENSSL_EVP_AES_CTR */
-
-#ifdef HAVE_OPENSSL_EVP_AES_GCM
static int
evp_cipher_aead_get_length(struct ssh_cipher_struct *cipher,
void *in,
@@ -764,7 +561,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher,
1,
lastiv);
if (rc == 0) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_IV_GEN failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_IV_GEN failed");
return;
}
@@ -776,7 +573,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher,
(int)aadlen);
outlen = tmplen;
if (rc == 0 || outlen != aadlen) {
- SSH_LOG(SSH_LOG_WARNING, "Failed to pass authenticated data");
+ SSH_LOG(SSH_LOG_TRACE, "Failed to pass authenticated data");
return;
}
memcpy(out, in, aadlen);
@@ -789,7 +586,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher,
(int)len - aadlen);
outlen = tmplen;
if (rc != 1 || outlen != (int)len - aadlen) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptUpdate failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptUpdate failed");
return;
}
@@ -798,7 +595,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher,
NULL,
&tmplen);
if (rc < 0) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptFinal failed: Failed to create a tag");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptFinal failed: Failed to create a tag");
return;
}
@@ -807,7 +604,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher,
authlen,
(unsigned char *)tag);
if (rc != 1) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_GET_TAG failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_GET_TAG failed");
return;
}
}
@@ -835,7 +632,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher,
1,
lastiv);
if (rc == 0) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_IV_GEN failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_IV_GEN failed");
return SSH_ERROR;
}
@@ -845,7 +642,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher,
authlen,
(unsigned char *)complete_packet + aadlen + encrypted_size);
if (rc == 0) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_SET_TAG failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_SET_TAG failed");
return SSH_ERROR;
}
@@ -856,7 +653,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher,
(unsigned char *)complete_packet,
(int)aadlen);
if (rc == 0) {
- SSH_LOG(SSH_LOG_WARNING, "Failed to pass authenticated data");
+ SSH_LOG(SSH_LOG_TRACE, "Failed to pass authenticated data");
return SSH_ERROR;
}
/* Do not copy the length to the target buffer, because it is already processed */
@@ -867,14 +664,14 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher,
(unsigned char *)out,
&outlen,
(unsigned char *)complete_packet + aadlen,
- encrypted_size /* already substracted aadlen*/);
+ encrypted_size /* already subtracted aadlen */);
if (rc != 1) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptUpdate failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_DecryptUpdate failed");
return SSH_ERROR;
}
if (outlen != (int)encrypted_size) {
- SSH_LOG(SSH_LOG_WARNING,
+ SSH_LOG(SSH_LOG_TRACE,
"EVP_DecryptUpdate: output size %d for %zd in",
outlen,
encrypted_size);
@@ -886,28 +683,31 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher,
NULL,
&outlen);
if (rc < 0) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptFinal failed: Failed authentication");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_DecryptFinal failed: Failed authentication");
return SSH_ERROR;
}
return SSH_OK;
}
-#endif /* HAVE_OPENSSL_EVP_AES_GCM */
-
-#if defined(HAVE_OPENSSL_EVP_CHACHA20) && defined(HAVE_OPENSSL_EVP_POLY1305)
+#ifdef HAVE_OPENSSL_EVP_CHACHA20
struct chacha20_poly1305_keysched {
/* cipher handle used for encrypting the packets */
EVP_CIPHER_CTX *main_evp;
/* cipher handle used for encrypting the length field */
EVP_CIPHER_CTX *header_evp;
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
/* mac handle used for authenticating the packets */
EVP_PKEY_CTX *pctx;
/* Poly1305 key */
EVP_PKEY *key;
/* MD context for digesting data in poly1305 */
EVP_MD_CTX *mctx;
+#else
+ /* MAC context used to do poly1305 */
+ EVP_MAC_CTX *mctx;
+#endif /* OPENSSL_VERSION_NUMBER */
};
static void
@@ -925,11 +725,16 @@ chacha20_poly1305_cleanup(struct ssh_cipher_struct *cipher)
ctx->main_evp = NULL;
EVP_CIPHER_CTX_free(ctx->header_evp);
ctx->header_evp = NULL;
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
/* ctx->pctx is freed as part of MD context */
EVP_PKEY_free(ctx->key);
ctx->key = NULL;
EVP_MD_CTX_free(ctx->mctx);
ctx->mctx = NULL;
+#else
+ EVP_MAC_CTX_free(ctx->mctx);
+ ctx->mctx = NULL;
+#endif /* OPENSSL_VERSION_NUMBER */
SAFE_FREE(cipher->chacha20_schedule);
}
@@ -942,6 +747,9 @@ chacha20_poly1305_set_key(struct ssh_cipher_struct *cipher,
struct chacha20_poly1305_keysched *ctx = NULL;
uint8_t *u8key = key;
int ret = SSH_ERROR, rv;
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_MAC *mac = NULL;
+#endif
if (cipher->chacha20_schedule == NULL) {
ctx = calloc(1, sizeof(*ctx));
@@ -957,38 +765,54 @@ chacha20_poly1305_set_key(struct ssh_cipher_struct *cipher,
/* K2 uses the first half of the key */
ctx->main_evp = EVP_CIPHER_CTX_new();
if (ctx->main_evp == NULL) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CIPHER_CTX_new failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CIPHER_CTX_new failed");
goto out;
}
rv = EVP_EncryptInit_ex(ctx->main_evp, EVP_chacha20(), NULL, u8key, NULL);
if (rv != 1) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CipherInit failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CipherInit failed");
goto out;
}
/* K1 uses the second half of the key */
ctx->header_evp = EVP_CIPHER_CTX_new();
if (ctx->header_evp == NULL) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CIPHER_CTX_new failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CIPHER_CTX_new failed");
goto out;
}
ret = EVP_EncryptInit_ex(ctx->header_evp, EVP_chacha20(), NULL,
u8key + CHACHA20_KEYLEN, NULL);
if (ret != 1) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CipherInit failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CipherInit failed");
goto out;
}
/* The Poly1305 key initialization is delayed to the time we know
* the actual key for packet so we do not need to create a bogus keys
*/
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
ctx->mctx = EVP_MD_CTX_new();
if (ctx->mctx == NULL) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_MD_CTX_new failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_MD_CTX_new failed");
return SSH_ERROR;
}
+#else
+ mac = EVP_MAC_fetch(NULL, "poly1305", NULL);
+ if (mac == NULL) {
+ SSH_LOG(SSH_LOG_TRACE, "EVP_MAC_fetch failed");
+ goto out;
+ }
+ ctx->mctx = EVP_MAC_CTX_new(mac);
+ if (ctx->mctx == NULL) {
+ SSH_LOG(SSH_LOG_TRACE, "EVP_MAC_CTX_new failed");
+ goto out;
+ }
+#endif /* OPENSSL_VERSION_NUMBER */
ret = SSH_OK;
out:
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_MAC_free(mac);
+#endif
if (ret != SSH_OK) {
chacha20_poly1305_cleanup(cipher);
}
@@ -1017,13 +841,13 @@ chacha20_poly1305_set_iv(struct ssh_cipher_struct *cipher,
ret = EVP_CipherInit_ex(ctx->header_evp, NULL, NULL, NULL, seqbuf, do_encrypt);
if (ret != 1) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CipherInit_ex(header_evp) failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CipherInit_ex(header_evp) failed");
return SSH_ERROR;
}
ret = EVP_CipherInit_ex(ctx->main_evp, NULL, NULL, NULL, seqbuf, do_encrypt);
if (ret != 1) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CipherInit_ex(main_evp) failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CipherInit_ex(main_evp) failed");
return SSH_ERROR;
}
@@ -1052,7 +876,7 @@ chacha20_poly1305_packet_setup(struct ssh_cipher_struct *cipher,
rv = EVP_CipherUpdate(ctx->main_evp, poly_key, &len,
(unsigned char *)zero_block, sizeof(zero_block));
if (rv != 1 || len != CHACHA20_BLOCKSIZE) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptUpdate failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptUpdate failed");
goto out;
}
#ifdef DEBUG_CRYPTO
@@ -1060,17 +884,18 @@ chacha20_poly1305_packet_setup(struct ssh_cipher_struct *cipher,
#endif /* DEBUG_CRYPTO */
/* Set the Poly1305 key */
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
if (ctx->key == NULL) {
/* Poly1305 Initialization needs to know the actual key */
ctx->key = EVP_PKEY_new_mac_key(EVP_PKEY_POLY1305, NULL,
poly_key, POLY1305_KEYLEN);
if (ctx->key == NULL) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_PKEY_new_mac_key failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_PKEY_new_mac_key failed");
goto out;
}
rv = EVP_DigestSignInit(ctx->mctx, &ctx->pctx, NULL, NULL, ctx->key);
if (rv != 1) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_DigestSignInit failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_DigestSignInit failed");
goto out;
}
} else {
@@ -1079,10 +904,17 @@ chacha20_poly1305_packet_setup(struct ssh_cipher_struct *cipher,
EVP_PKEY_CTRL_SET_MAC_KEY,
POLY1305_KEYLEN, (void *)poly_key);
if (rv <= 0) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_PKEY_CTX_ctrl failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_PKEY_CTX_ctrl failed");
goto out;
}
}
+#else
+ rv = EVP_MAC_init(ctx->mctx, poly_key, POLY1305_KEYLEN, NULL);
+ if (rv != 1) {
+ SSH_LOG(SSH_LOG_TRACE, "EVP_MAC_init failed");
+ goto out;
+ }
+#endif /* OPENSSL_VERSION_NUMBER */
ret = SSH_OK;
out:
@@ -1116,7 +948,7 @@ chacha20_poly1305_aead_decrypt_length(struct ssh_cipher_struct *cipher,
rv = EVP_CipherUpdate(ctx->header_evp, out, &outlen, in, len);
if (rv != 1 || outlen != sizeof(uint32_t)) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CipherUpdate failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CipherUpdate failed");
return SSH_ERROR;
}
@@ -1126,7 +958,7 @@ chacha20_poly1305_aead_decrypt_length(struct ssh_cipher_struct *cipher,
rv = EVP_CipherFinal_ex(ctx->header_evp, out + outlen, &outlen);
if (rv != 1 || outlen != 0) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CipherFinal_ex failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CipherFinal_ex failed");
return SSH_ERROR;
}
@@ -1151,7 +983,7 @@ chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher,
/* Prepare the Poly1305 key */
rv = chacha20_poly1305_packet_setup(cipher, seq, 0);
if (rv != SSH_OK) {
- SSH_LOG(SSH_LOG_WARNING, "Failed to setup packet");
+ SSH_LOG(SSH_LOG_TRACE, "Failed to setup packet");
goto out;
}
@@ -1160,25 +992,40 @@ chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher,
#endif /* DEBUG_CRYPTO */
/* Calculate MAC of received data */
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
rv = EVP_DigestSignUpdate(ctx->mctx, complete_packet,
encrypted_size + sizeof(uint32_t));
if (rv != 1) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_DigestSignUpdate failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_DigestSignUpdate failed");
goto out;
}
rv = EVP_DigestSignFinal(ctx->mctx, tag, &taglen);
if (rv != 1) {
- SSH_LOG(SSH_LOG_WARNING, "poly1305 verify error");
+ SSH_LOG(SSH_LOG_TRACE, "poly1305 verify error");
+ goto out;
+ }
+#else
+ rv = EVP_MAC_update(ctx->mctx, complete_packet,
+ encrypted_size + sizeof(uint32_t));
+ if (rv != 1) {
+ SSH_LOG(SSH_LOG_TRACE, "EVP_MAC_update failed");
goto out;
}
+ rv = EVP_MAC_final(ctx->mctx, tag, &taglen, POLY1305_TAGLEN);
+ if (rv != 1) {
+ SSH_LOG(SSH_LOG_TRACE, "EVP_MAC_final failed");
+ goto out;
+ }
+#endif /* OPENSSL_VERSION_NUMBER */
+
#ifdef DEBUG_CRYPTO
ssh_log_hexdump("calculated mac", tag, POLY1305_TAGLEN);
#endif /* DEBUG_CRYPTO */
/* Verify the calculated MAC matches the attached MAC */
- cmp = memcmp(tag, mac, POLY1305_TAGLEN);
+ cmp = CRYPTO_memcmp(tag, mac, POLY1305_TAGLEN);
if (cmp != 0) {
/* mac error */
SSH_LOG(SSH_LOG_PACKET, "poly1305 verify error");
@@ -1190,13 +1037,13 @@ chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher,
(uint8_t *)complete_packet + sizeof(uint32_t),
encrypted_size);
if (rv != 1) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CipherUpdate failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CipherUpdate failed");
goto out;
}
rv = EVP_CipherFinal_ex(ctx->main_evp, out + len, &len);
if (rv != 1 || len != 0) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CipherFinal_ex failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CipherFinal_ex failed");
goto out;
}
@@ -1221,7 +1068,7 @@ chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
/* Prepare the Poly1305 key */
ret = chacha20_poly1305_packet_setup(cipher, seq, 1);
if (ret != SSH_OK) {
- SSH_LOG(SSH_LOG_WARNING, "Failed to setup packet");
+ SSH_LOG(SSH_LOG_TRACE, "Failed to setup packet");
return;
}
@@ -1236,7 +1083,7 @@ chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
(unsigned char *)&in_packet->length,
sizeof(uint32_t));
if (ret != 1 || outlen != sizeof(uint32_t)) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CipherUpdate failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CipherUpdate failed");
return;
}
#ifdef DEBUG_CRYPTO
@@ -1245,7 +1092,7 @@ chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
#endif /* DEBUG_CRYPTO */
ret = EVP_CipherFinal_ex(ctx->header_evp, (uint8_t *)out + outlen, &outlen);
if (ret != 1 || outlen != 0) {
- SSH_LOG(SSH_LOG_PACKET, "EVP_EncryptFinal_ex failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptFinal_ex failed");
return;
}
@@ -1257,23 +1104,37 @@ chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
in_packet->payload,
len - sizeof(uint32_t));
if (ret != 1) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_CipherUpdate failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_CipherUpdate failed");
return;
}
/* step 4, compute the MAC */
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
ret = EVP_DigestSignUpdate(ctx->mctx, out_packet, len);
if (ret <= 0) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_DigestSignUpdate failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_DigestSignUpdate failed");
return;
}
ret = EVP_DigestSignFinal(ctx->mctx, tag, &taglen);
if (ret <= 0) {
- SSH_LOG(SSH_LOG_WARNING, "EVP_DigestSignFinal failed");
+ SSH_LOG(SSH_LOG_TRACE, "EVP_DigestSignFinal failed");
return;
}
+#else
+ ret = EVP_MAC_update(ctx->mctx, (void*)out_packet, len);
+ if (ret != 1) {
+ SSH_LOG(SSH_LOG_TRACE, "EVP_MAC_update failed");
+ return;
+ }
+
+ ret = EVP_MAC_final(ctx->mctx, tag, &taglen, POLY1305_TAGLEN);
+ if (ret != 1) {
+ SSH_LOG(SSH_LOG_TRACE, "EVP_MAC_final failed");
+ return;
+ }
+#endif /* OPENSSL_VERSION_NUMBER */
}
-#endif /* defined(HAVE_OPENSSL_EVP_CHACHA20) && defined(HAVE_OPENSSL_EVP_POLY1305) */
+#endif /* HAVE_OPENSSL_EVP_CHACHA20 */
#ifdef WITH_INSECURE_NONE
static void
@@ -1302,13 +1163,8 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
.decrypt = evp_cipher_decrypt,
.cleanup = evp_cipher_cleanup
},
-#endif
+#endif /* WITH_BLOWFISH_CIPHER */
#ifdef HAS_AES
-#ifndef BROKEN_AES_CTR
-/* OpenSSL until 0.9.7c has a broken AES_ctr128_encrypt implementation which
- * increments the counter from 2^64 instead of 1. It's better not to use it
- */
-#ifdef HAVE_OPENSSL_EVP_AES_CTR
{
.name = "aes128-ctr",
.blocksize = AES_BLOCK_SIZE,
@@ -1342,42 +1198,6 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
.decrypt = evp_cipher_decrypt,
.cleanup = evp_cipher_cleanup
},
-#else /* HAVE_OPENSSL_EVP_AES_CTR */
- {
- .name = "aes128-ctr",
- .blocksize = AES_BLOCK_SIZE,
- .ciphertype = SSH_AES128_CTR,
- .keysize = 128,
- .set_encrypt_key = aes_ctr_set_key,
- .set_decrypt_key = aes_ctr_set_key,
- .encrypt = aes_ctr_encrypt,
- .decrypt = aes_ctr_encrypt,
- .cleanup = aes_ctr_cleanup
- },
- {
- .name = "aes192-ctr",
- .blocksize = AES_BLOCK_SIZE,
- .ciphertype = SSH_AES192_CTR,
- .keysize = 192,
- .set_encrypt_key = aes_ctr_set_key,
- .set_decrypt_key = aes_ctr_set_key,
- .encrypt = aes_ctr_encrypt,
- .decrypt = aes_ctr_encrypt,
- .cleanup = aes_ctr_cleanup
- },
- {
- .name = "aes256-ctr",
- .blocksize = AES_BLOCK_SIZE,
- .ciphertype = SSH_AES256_CTR,
- .keysize = 256,
- .set_encrypt_key = aes_ctr_set_key,
- .set_decrypt_key = aes_ctr_set_key,
- .encrypt = aes_ctr_encrypt,
- .decrypt = aes_ctr_encrypt,
- .cleanup = aes_ctr_cleanup
- },
-#endif /* HAVE_OPENSSL_EVP_AES_CTR */
-#endif /* BROKEN_AES_CTR */
{
.name = "aes128-cbc",
.blocksize = AES_BLOCK_SIZE,
@@ -1411,7 +1231,6 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
.decrypt = evp_cipher_decrypt,
.cleanup = evp_cipher_cleanup
},
-#ifdef HAVE_OPENSSL_EVP_AES_GCM
{
.name = "aes128-gcm@openssh.com",
.blocksize = AES_BLOCK_SIZE,
@@ -1440,7 +1259,6 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
.aead_decrypt = evp_cipher_aead_decrypt,
.cleanup = evp_cipher_cleanup
},
-#endif /* HAVE_OPENSSL_EVP_AES_GCM */
#endif /* HAS_AES */
#ifdef HAS_DES
{
@@ -1456,7 +1274,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
},
#endif /* HAS_DES */
{
-#if defined(HAVE_OPENSSL_EVP_CHACHA20) && defined(HAVE_OPENSSL_EVP_POLY1305)
+#ifdef HAVE_OPENSSL_EVP_CHACHA20
.ciphertype = SSH_AEAD_CHACHA20_POLY1305,
.name = "chacha20-poly1305@openssh.com",
.blocksize = CHACHA20_BLOCKSIZE/8,
@@ -1472,7 +1290,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
.cleanup = chacha20_poly1305_cleanup
#else
.name = "chacha20-poly1305@openssh.com"
-#endif /* defined(HAVE_OPENSSL_EVP_CHACHA20) && defined(HAVE_OPENSSL_EVP_POLY1305) */
+#endif /* HAVE_OPENSSL_EVP_CHACHA20 */
},
#ifdef WITH_INSECURE_NONE
{
@@ -1499,13 +1317,15 @@ struct ssh_cipher_struct *ssh_get_ciphertab(void)
*/
int ssh_crypto_init(void)
{
- UNUSED_VAR(size_t i);
+#ifndef HAVE_OPENSSL_EVP_CHACHA20
+ size_t i;
+#endif
if (libcrypto_initialized) {
return SSH_OK;
}
if (OpenSSL_version_num() != OPENSSL_VERSION_NUMBER){
- SSH_LOG(SSH_LOG_WARNING, "libssh compiled with %s "
+ SSH_LOG(SSH_LOG_DEBUG, "libssh compiled with %s "
"headers, currently running with %s.",
OPENSSL_VERSION_TEXT,
OpenSSL_version(OpenSSL_version_num())
@@ -1521,12 +1341,9 @@ int ssh_crypto_init(void)
/* Bit #57 denotes AES-NI instruction set extension */
OPENSSL_ia32cap &= ~(1LL << 57);
}
-#endif
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
- OpenSSL_add_all_algorithms();
-#endif
+#endif /* CAN_DISABLE_AESNI */
-#if !defined(HAVE_OPENSSL_EVP_CHACHA20) || !defined(HAVE_OPENSSL_EVP_POLY1305)
+#ifndef HAVE_OPENSSL_EVP_CHACHA20
for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
int cmp;
@@ -1538,7 +1355,7 @@ int ssh_crypto_init(void)
break;
}
}
-#endif /* !defined(HAVE_OPENSSL_EVP_CHACHA20) || !defined(HAVE_OPENSSL_EVP_POLY1305) */
+#endif /* HAVE_OPENSSL_EVP_CHACHA20 */
libcrypto_initialized = 1;
@@ -1555,13 +1372,210 @@ void ssh_crypto_finalize(void)
return;
}
- ENGINE_cleanup();
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
- EVP_cleanup();
- CRYPTO_cleanup_all_ex_data();
+/* TODO this should finalize engine if it was started, but during atexit calls,
+ * we are crashing. AFAIK this is related to the dlopened pkcs11 modules calling
+ * the crypto cleanups earlier. */
+#if 0
+ if (engine != NULL) {
+ ENGINE_finish(engine);
+ ENGINE_free(engine);
+ engine = NULL;
+ }
#endif
libcrypto_initialized = 0;
}
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+/**
+ * @internal
+ * @brief Create EVP_PKEY from parameters
+ *
+ * @param[in] name Algorithm to use. For more info see manpage of EVP_PKEY_CTX_new_from_name
+ *
+ * @param[in] param_bld Constructed param builder for the pkey
+ *
+ * @param[out] pkey Created EVP_PKEY variable
+ *
+ * @param[in] selection Reference selections at man EVP_PKEY_FROMDATA
+ *
+ * @return 0 on success, -1 on error
+ */
+int evp_build_pkey(const char* name, OSSL_PARAM_BLD *param_bld,
+ EVP_PKEY **pkey, int selection)
+{
+ int rc;
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, name, NULL);
+ OSSL_PARAM *params = NULL;
+
+ if (ctx == NULL) {
+ return -1;
+ }
+
+ params = OSSL_PARAM_BLD_to_param(param_bld);
+ if (params == NULL) {
+ EVP_PKEY_CTX_free(ctx);
+ return -1;
+ }
+
+ rc = EVP_PKEY_fromdata_init(ctx);
+ if (rc != 1) {
+ OSSL_PARAM_free(params);
+ EVP_PKEY_CTX_free(ctx);
+ return -1;
+ }
+
+ rc = EVP_PKEY_fromdata(ctx, pkey, selection, params);
+ if (rc != 1) {
+ SSH_LOG(SSH_LOG_WARNING,
+ "Failed to import private key: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ OSSL_PARAM_free(params);
+ EVP_PKEY_CTX_free(ctx);
+ return -1;
+ }
+
+ OSSL_PARAM_free(params);
+ EVP_PKEY_CTX_free(ctx);
+
+ return SSH_OK;
+}
+
+/**
+ * @brief creates a copy of EVP_PKEY
+ *
+ * @param[in] name Algorithm to use. For more info see manpage of
+ * EVP_PKEY_CTX_new_from_name
+ *
+ * @param[in] key Key being duplicated from
+ *
+ * @param[in] demote Same as at pki_key_dup, only the public
+ * part of the key gets duplicated if true
+ *
+ * @param[out] new_key The key where the duplicate is saved
+ *
+ * @return 0 on success, -1 on error
+ */
+static int
+evp_dup_pkey(const char *name, const ssh_key key, int demote, ssh_key new_key)
+{
+ int rc;
+ EVP_PKEY_CTX *ctx = NULL;
+ OSSL_PARAM *params = NULL;
+
+ /* The simple case -- just reference the existing key */
+ if (!demote || (key->flags & SSH_KEY_FLAG_PRIVATE) == 0) {
+ rc = EVP_PKEY_up_ref(key->key);
+ if (rc != 1) {
+ return -1;
+ }
+ new_key->key = key->key;
+ return SSH_OK;
+ }
+
+ /* demote == 1 */
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, name, NULL);
+ if (ctx == NULL) {
+ return -1;
+ }
+
+ rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, &params);
+ if (rc != 1) {
+ EVP_PKEY_CTX_free(ctx);
+ return -1;
+ }
+
+ if (strcmp(name, "EC") == 0) {
+ OSSL_PARAM *locate_param = NULL;
+ /* For ECC keys provided by engine or provider, we need to have the
+ * explicit public part available, otherwise the key will not be
+ * usable */
+ locate_param = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY);
+ if (locate_param == NULL) {
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ return -1;
+ }
+ }
+ rc = EVP_PKEY_fromdata_init(ctx);
+ if (rc != 1) {
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ return -1;
+ }
+
+ rc = EVP_PKEY_fromdata(ctx, &(new_key->key), EVP_PKEY_PUBLIC_KEY, params);
+ if (rc != 1) {
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ return -1;
+ }
+
+ OSSL_PARAM_free(params);
+ EVP_PKEY_CTX_free(ctx);
+
+ return SSH_OK;
+}
+
+int evp_dup_rsa_pkey(const ssh_key key, ssh_key new_key, int demote)
+{
+ return evp_dup_pkey("RSA", key, demote, new_key);
+}
+
+int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new_key, int demote)
+{
+ return evp_dup_pkey("EC", key, demote, new_key);
+}
+#endif /* OPENSSL_VERSION_NUMBER */
+
+ssh_string
+pki_key_make_ecpoint_string(const EC_GROUP *g, const EC_POINT *p)
+{
+ ssh_string s = NULL;
+ size_t len;
+
+ len = EC_POINT_point2oct(g,
+ p,
+ POINT_CONVERSION_UNCOMPRESSED,
+ NULL,
+ 0,
+ NULL);
+ if (len == 0) {
+ return NULL;
+ }
+
+ s = ssh_string_new(len);
+ if (s == NULL) {
+ return NULL;
+ }
+
+ len = EC_POINT_point2oct(g,
+ p,
+ POINT_CONVERSION_UNCOMPRESSED,
+ ssh_string_data(s),
+ ssh_string_len(s),
+ NULL);
+ if (len != ssh_string_len(s)) {
+ SSH_STRING_FREE(s);
+ return NULL;
+ }
+
+ return s;
+}
+
+int pki_key_ecgroup_name_to_nid(const char *group)
+{
+ if (strcmp(group, NISTP256) == 0 ||
+ strcmp(group, "secp256r1") == 0 ||
+ strcmp(group, "prime256v1") == 0) {
+ return NID_X9_62_prime256v1;
+ } else if (strcmp(group, NISTP384) == 0 ||
+ strcmp(group, "secp384r1") == 0) {
+ return NID_secp384r1;
+ } else if (strcmp(group, NISTP521) == 0 ||
+ strcmp(group, "secp521r1") == 0) {
+ return NID_secp521r1;
+ }
+ return -1;
+}
#endif /* LIBCRYPTO */