[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] add mbedtls crypto support
[Thread Prev] | [Thread Next]
- Subject: [PATCH] add mbedtls crypto support
- From: Juraj Vijtiuk <juraj.vijtiuk@xxxxxxxxxx>
- Reply-to: libssh@xxxxxxxxxx
- Date: Tue, 8 Aug 2017 16:29:45 +0200
- To: libssh@xxxxxxxxxx
- Cc: luka.perkov@xxxxxxxxxx, davor.popovic@xxxxxxxxxx, juraj.vijtiuk@xxxxxxxxxx
This patch adds support for mbedTLS as a crypto backend for libssh.
mbedTLS is an SSL/TLS library that has been designed to mainly be used
in embedded systems. It is loosely coupled and has a low memory
footprint. mbedTLS also provides a cryptography library (libmbedcrypto)
that can be used without the TLS modules.
Signed-off-by: Juraj Vijtiuk <juraj.vijtiuk@xxxxxxxxxx>
---
v1:
* The patch has been tested with a Debug and MinSizeRel build, with
libssh unit tests, client tests and the pkd tests.
* All the tests have been run with valgrind's memcheck, drd and helgrind
tools.
* The examples/samplessh client works when built with the patch.
* The patch is unfortunately quite big, since several new files had to
be added.
* DSA is disabled at compile time, since mbedTLS doesn't support DSA
* Patch review and feedback would be appreciated, and if any issues or
suggestions appear, I'm willing to work on them.
---
CMakeLists.txt | 11 +-
ConfigureChecks.cmake | 13 +-
DefineOptions.cmake | 1 +
cmake/Modules/FindMbedTLS.cmake | 104 +++
config.h.cmake | 6 +
include/libssh/bignum.h | 1 +
include/libssh/bind.h | 4 +
include/libssh/crypto.h | 6 +
include/libssh/ecdh.h | 4 +
include/libssh/keys.h | 4 +
include/libssh/libmbedcrypto.h | 111 +++
include/libssh/libssh.h | 4 +
include/libssh/pki.h | 6 +
include/libssh/pki_priv.h | 6 +
include/libssh/server.h | 2 +
include/libssh/session.h | 2 +
include/libssh/wrapper.h | 1 +
src/CMakeLists.txt | 19 +
src/auth.c | 4 +
src/bignum.c | 12 +
src/bind.c | 22 +-
src/curve25519.c | 8 +
src/dh.c | 29 +
src/ecdh_mbedcrypto.c | 265 ++++++++
src/kex.c | 12 +
src/known_hosts.c | 6 +
src/legacy.c | 26 +
src/libcrypto-compat.c | 2 +
src/libcrypto.c | 6 +-
src/libmbedcrypto.c | 1109 ++++++++++++++++++++++++++++++
src/mbedcrypto_missing.c | 126 ++++
src/misc.c | 58 +-
src/options.c | 16 +-
src/pki.c | 67 +-
src/pki_container_openssh.c | 2 +
src/pki_crypto.c | 2 +
src/pki_mbedcrypto.c | 1300 ++++++++++++++++++++++++++++++++++++
src/server.c | 4 +
src/session.c | 4 +
src/threads.c | 32 +
src/wrapper.c | 8 +-
tests/client/torture_knownhosts.c | 14 +
tests/pkd/pkd_daemon.c | 2 +
tests/pkd/pkd_daemon.h | 2 +
tests/pkd/pkd_hello.c | 99 +++
tests/pkd/pkd_keyutil.c | 8 +
tests/pkd/pkd_keyutil.h | 10 +
tests/test_ssh_bind_accept_fd.c | 8 +
tests/torture.c | 22 +
tests/unittests/torture_keyfiles.c | 18 +
tests/unittests/torture_misc.c | 142 ++++
tests/unittests/torture_options.c | 8 +
tests/unittests/torture_pki.c | 53 +-
53 files changed, 3765 insertions(+), 46 deletions(-)
create mode 100644 cmake/Modules/FindMbedTLS.cmake
create mode 100644 include/libssh/libmbedcrypto.h
create mode 100644 src/ecdh_mbedcrypto.c
create mode 100644 src/libmbedcrypto.c
create mode 100644 src/mbedcrypto_missing.c
create mode 100644 src/pki_mbedcrypto.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 30b1025c..a496a5b3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -49,12 +49,20 @@ if (WITH_GCRYPT)
if (NOT GCRYPT_FOUND)
message(FATAL_ERROR "Could not find GCrypt")
endif (NOT GCRYPT_FOUND)
+elseif(WITH_MBEDTLS)
+ find_package(MbedTLS REQUIRED)
+ if (NOT MBEDTLS_FOUND)
+ message(FATAL_ERROR "Could not find mbedTLS")
+ endif (NOT MBEDTLS_FOUND)
else (WITH_GCRYPT)
find_package(OpenSSL)
if (NOT OPENSSL_FOUND)
find_package(GCrypt)
if (NOT GCRYPT_FOUND)
- message(FATAL_ERROR "Could not find OpenSSL or GCrypt")
+ find_package(MbedTLS)
+ if (NOT MBEDTLS_FOUND)
+ message(FATAL_ERROR "Could not find OpenSSL, GCrypt or mbedTLS")
+ endif (NOT MBEDTLS_FOUND)
endif (NOT GCRYPT_FOUND)
endif (NOT OPENSSL_FOUND)
endif(WITH_GCRYPT)
@@ -150,6 +158,7 @@ message(STATUS "********** ${PROJECT_NAME} build options : **********")
message(STATUS "zlib support: ${WITH_ZLIB}")
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
+message(STATUS "libmbedTLS support: ${WITH_MBEDTLS}")
message(STATUS "libnacl support: ${WITH_NACL}")
message(STATUS "SSH-1 support: ${WITH_SSH1}")
message(STATUS "SFTP support: ${WITH_SFTP}")
diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index f5645807..a814b5eb 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -124,7 +124,7 @@ if (CMAKE_HAVE_PTHREAD_H)
set(HAVE_PTHREAD_H 1)
endif (CMAKE_HAVE_PTHREAD_H)
-if (NOT WITH_GCRYPT)
+if (NOT WITH_GCRYPT AND NOT WITH_MBEDTLS)
if (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H)
set(HAVE_OPENSSL_ECC 1)
endif (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H)
@@ -132,7 +132,11 @@ if (NOT WITH_GCRYPT)
if (HAVE_OPENSSL_ECC)
set(HAVE_ECC 1)
endif (HAVE_OPENSSL_ECC)
-endif (NOT WITH_GCRYPT)
+endif ()
+
+if (NOT WITH_MBEDTLS)
+ set(HAVE_DSA 1)
+endif()
# FUNCTIONS
@@ -223,6 +227,11 @@ if (GCRYPT_FOUND)
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
endif (GCRYPT_FOUND)
+if (MBEDTLS_FOUND)
+ set(HAVE_LIBMBEDCRYPTO 1)
+ set(HAVE_ECC 1)
+endif (MBEDTLS_FOUND)
+
if (CMAKE_USE_PTHREADS_INIT)
set(HAVE_PTHREAD 1)
endif (CMAKE_USE_PTHREADS_INIT)
diff --git a/DefineOptions.cmake b/DefineOptions.cmake
index ab7819a5..c7d0b820 100644
--- a/DefineOptions.cmake
+++ b/DefineOptions.cmake
@@ -7,6 +7,7 @@ option(WITH_STATIC_LIB "Build with a static library" OFF)
option(WITH_DEBUG_CRYPTO "Build with cryto debug output" OFF)
option(WITH_DEBUG_CALLTRACE "Build with calltrace debug output" ON)
option(WITH_GCRYPT "Compile against libgcrypt" OFF)
+option(WITH_MBEDTLS "Compile against libmbedtls" OFF)
option(WITH_PCAP "Compile with Pcap generation support" ON)
option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
option(WITH_TESTING "Build with unit tests" OFF)
diff --git a/cmake/Modules/FindMbedTLS.cmake b/cmake/Modules/FindMbedTLS.cmake
new file mode 100644
index 00000000..baec8adc
--- /dev/null
+++ b/cmake/Modules/FindMbedTLS.cmake
@@ -0,0 +1,104 @@
+# - Try to find mbedTLS
+# Once done this will define
+#
+# MBEDTLS_FOUND - system has mbedTLS
+# MBEDTLS_INCLUDE_DIRS - the mbedTLS include directory
+# MBEDTLS_LIBRARIES - Link these to use mbedTLS
+# MBEDTLS_DEFINITIONS - Compiler switches required for using mbedTLS
+#=============================================================================
+# Copyright (c) 2017 Sartura d.o.o.
+#
+# Author: Juraj Vijtiuk <juraj.vijtiuk@xxxxxxxxxx>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+#
+
+
+set(_MBEDTLS_ROOT_HINTS
+ $ENV{MBEDTLS_ROOT_DIR}
+ ${MBEDTLS_ROOT_DIR})
+
+set(_MBEDTLS_ROOT_PATHS
+ "$ENV{PROGRAMFILES}/libmbedtls")
+
+set(_MBEDTLS_ROOT_HINTS_AND_PATHS
+ HINTS ${_MBEDTLS_ROOT_HINTS}
+ PATHS ${_MBEDTLS_ROOT_PATHS})
+
+
+find_path(MBEDTLS_INCLUDE_DIR
+ NAMES
+ mbedtls/config.h
+ HINTS
+ ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
+ PATH_SUFFIXES
+ include
+)
+
+find_library(MBEDTLS_SSL_LIBRARY
+ NAMES
+ mbedtls
+ HINTS
+ ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
+ PATH_SUFFIXES
+ lib
+
+)
+
+find_library(MBEDTLS_CRYPTO_LIBRARY
+ NAMES
+ mbedcrypto
+ HINTS
+ ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
+ PATH_SUFFIXES
+ lib
+)
+
+find_library(MBEDTLS_X509_LIBRARY
+ NAMES
+ mbedx509
+ HINTS
+ ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
+ PATH_SUFFIXES
+ lib
+)
+
+set(MBEDTLS_LIBRARIES ${MBEDTLS_SSL_LIBRARY} ${MBEDTLS_CRYPTO_LIBRARY}
+ ${MBEDTLS_X509_LIBRARY})
+
+if (MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")
+ file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" _mbedtls_version_str REGEX
+ "^#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"[0-9]+.[0-9]+.[0-9]+\"")
+
+ string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+.[0-9]+.[0-9]+).*"
+ "\\1" MBEDTLS_VERSION "${_mbedtls_version_str}")
+endif ()
+
+include(FindPackageHandleStandardArgs)
+if (MBEDTLS_VERSION)
+ find_package_handle_standard_args(MbedTLS
+ REQUIRED_VARS
+ MBEDTLS_INCLUDE_DIR
+ MBEDTLS_LIBRARIES
+ VERSION_VAR
+ MBEDTLS_VERSION
+ FAIL_MESSAGE
+ "Could NOT find mbedTLS, try to set the path to mbedTLS root folder
+ in the system variable MBEDTLS_ROOT_DIR"
+ )
+else (MBEDTLS_VERSION)
+ find_package_handle_standard_args(MBedTLS
+ "Could NOT find mbedTLS, try to set the path to mbedLS root folder in
+ the system variable MBEDTLS_ROOT_DIR"
+ MBEDTLS_INCLUDE_DIR
+ MBEDTLS_LIBRARIES)
+endif (MBEDTLS_VERSION)
+
+# show the MBEDTLS_INCLUDE_DIRS and MBEDTLS_LIBRARIES variables only in the advanced view
+mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARIES)
diff --git a/config.h.cmake b/config.h.cmake
index 3f34f09b..e183c6c7 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -80,6 +80,9 @@
/* Define to 1 if you have eliptic curve cryptography */
#cmakedefine HAVE_ECC 1
+/* Define to 1 if you have DSA */
+#cmakedefine HAVE_DSA 1
+
/*************************** FUNCTIONS ***************************/
/* Define to 1 if you have the `EVP_aes128_ctr' function. */
@@ -159,6 +162,9 @@
/* Define to 1 if you have the `gcrypt' library (-lgcrypt). */
#cmakedefine HAVE_LIBGCRYPT 1
+/* Define to 1 if you have the 'mbedTLS' library (-lmbedtls). */
+#cmakedefine HAVE_LIBMBEDCRYPTO 1
+
/* Define to 1 if you have the `pthread' library (-lpthread). */
#cmakedefine HAVE_PTHREAD 1
diff --git a/include/libssh/bignum.h b/include/libssh/bignum.h
index 71970e3e..32727050 100644
--- a/include/libssh/bignum.h
+++ b/include/libssh/bignum.h
@@ -23,6 +23,7 @@
#include "libssh/libcrypto.h"
#include "libssh/libgcrypt.h"
+#include "libssh/libmbedcrypto.h"
bignum ssh_make_string_bn(ssh_string string);
void ssh_make_string_bn_inplace(ssh_string string, bignum bnout);
diff --git a/include/libssh/bind.h b/include/libssh/bind.h
index edbc7b77..6f4425c9 100644
--- a/include/libssh/bind.h
+++ b/include/libssh/bind.h
@@ -34,11 +34,15 @@ struct ssh_bind_struct {
char *wanted_methods[10];
char *banner;
char *ecdsakey;
+#ifdef HAVE_DSA
char *dsakey;
+#endif
char *rsakey;
char *ed25519key;
ssh_key ecdsa;
+#ifdef HAVE_DSA
ssh_key dsa;
+#endif
ssh_key rsa;
ssh_key ed25519;
char *bindaddr;
diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h
index 4c79c8ca..9e602028 100644
--- a/include/libssh/crypto.h
+++ b/include/libssh/crypto.h
@@ -80,6 +80,8 @@ struct ssh_crypto_struct {
EC_KEY *ecdh_privkey;
#elif defined HAVE_GCRYPT_ECC
gcry_sexp_t ecdh_privkey;
+#elif defined HAVE_LIBMBEDCRYPTO
+ mbedtls_ecp_keypair *ecdh_privkey;
#endif
ssh_string ecdh_client_pubkey;
ssh_string ecdh_server_pubkey;
@@ -131,6 +133,10 @@ struct ssh_cipher_struct {
struct ssh_aes_key_schedule *aes_key;
const EVP_CIPHER *cipher;
EVP_CIPHER_CTX *ctx;
+#elif defined HAVE_LIBMBEDCRYPTO
+ mbedtls_cipher_context_t encrypt_ctx;
+ mbedtls_cipher_context_t decrypt_ctx;
+ mbedtls_cipher_type_t type;
#endif
unsigned int keysize; /* bytes of key used. != keylen */
/* sets the new key for immediate use */
diff --git a/include/libssh/ecdh.h b/include/libssh/ecdh.h
index 9f94d69c..66659b85 100644
--- a/include/libssh/ecdh.h
+++ b/include/libssh/ecdh.h
@@ -37,6 +37,10 @@
#define HAVE_ECDH 1
#endif
+#ifdef HAVE_LIBMBEDCRYPTO
+#define HAVE_ECDH 1
+#endif
+
/* Common functions. */
int ssh_client_ecdh_reply(ssh_session session, ssh_buffer packet);
diff --git a/include/libssh/keys.h b/include/libssh/keys.h
index 6f08e070..e3603c42 100644
--- a/include/libssh/keys.h
+++ b/include/libssh/keys.h
@@ -34,6 +34,8 @@ struct ssh_public_key_struct {
#elif HAVE_LIBCRYPTO
DSA *dsa_pub;
RSA *rsa_pub;
+#elif HAVE_LIBMBEDCRYPTO
+ mbedtls_pk_context *rsa_pub;
#endif
};
@@ -45,6 +47,8 @@ struct ssh_private_key_struct {
#elif defined HAVE_LIBCRYPTO
DSA *dsa_priv;
RSA *rsa_priv;
+#elif HAVE_LIBMBEDCRYPTO
+ mbedtls_pk_context *rsa_priv;
#endif
};
diff --git a/include/libssh/libmbedcrypto.h b/include/libssh/libmbedcrypto.h
new file mode 100644
index 00000000..7cc1bbb0
--- /dev/null
+++ b/include/libssh/libmbedcrypto.h
@@ -0,0 +1,111 @@
+/*
+ * This file is part of the SSH Library
+ *
+ * Copyright (c) 2017 Sartura d.o.o.
+ *
+ * Author: Juraj Vijtiuk <juraj.vijtiuk@xxxxxxxxxx>
+ *
+ * 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.
+ */
+
+#ifndef LIBMBEDCRYPTO_H_
+#define LIBMBEDCRYPTO_H_
+
+#include "config.h"
+
+#ifdef HAVE_LIBMBEDCRYPTO
+
+#include <mbedtls/md.h>
+#include <mbedtls/bignum.h>
+#include <mbedtls/pk.h>
+#include <mbedtls/cipher.h>
+#include <mbedtls/entropy.h>
+#include <mbedtls/ctr_drbg.h>
+
+typedef mbedtls_md_context_t *SHACTX;
+typedef mbedtls_md_context_t *SHA256CTX;
+typedef mbedtls_md_context_t *SHA384CTX;
+typedef mbedtls_md_context_t *SHA512CTX;
+typedef mbedtls_md_context_t *MD5CTX;
+typedef mbedtls_md_context_t *HMACCTX;
+typedef mbedtls_md_context_t *EVPCTX;
+
+#define SHA_DIGEST_LENGTH 20
+#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
+#define MD5_DIGEST_LEN 16
+#define SHA256_DIGEST_LENGTH 32
+#define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH
+#define SHA384_DIGEST_LENGTH 48
+#define SHA384_DIGEST_LEN SHA384_DIGEST_LENGTH
+#define SHA512_DIGEST_LENGTH 64
+#define SHA512_DIGEST_LEN SHA512_DIGEST_LENGTH
+
+#ifndef EVP_MAX_MD_SIZE
+#define EVP_MAX_MD_SIZE 64
+#endif
+
+#define EVP_DIGEST_LEN EVP_MAX_MD_SIZE
+
+typedef mbedtls_mpi *bignum;
+
+/* Constants for curves */
+#define NID_mbedtls_nistp256 0
+#define NID_mbedtls_nistp384 1
+#define NID_mbedtls_nistp521 2
+
+struct mbedtls_ecdsa_sig {
+ bignum r;
+ bignum s;
+};
+
+bignum ssh_mbedcry_bn_new(void);
+void ssh_mbedcry_bn_free(bignum num);
+char *ssh_mbedcry_bn2num(bignum num, int radix);
+int ssh_mbedcry_rand(bignum rnd, int bits, int top, int bottom);
+int ssh_mbedcry_is_bit_set(bignum num, size_t pos);
+
+#define bignum_new() ssh_mbedcry_bn_new()
+#define bignum_free(num) ssh_mbedcry_bn_free(num);
+#define bignum_set_word(bn, n) mbedtls_mpi_lset(bn, n) /* TODO fix
+ overflow/underflow */
+#define bignum_bin2bn(data, datalen, bn) mbedtls_mpi_read_binary(bn, data, \
+ datalen)
+#define bignum_bn2dec(num) ssh_mbedcry_bn2num(num, 10)
+#define bignum_dec2bn(data, bn) mbedtls_mpi_read_string(bn, 10, data)
+#define bignum_bn2hex(num) ssh_mbedcry_bn2num(num, 16)
+#define bignum_rand(rnd, bits, top, bottom) ssh_mbedcry_rand(rnd, bits, \
+ top, bottom)
+#define bignum_mod_exp(dest, generator, exp, modulo, ctx) \
+ mbedtls_mpi_exp_mod(dest, generator, exp, modulo, NULL)
+#define bignum_num_bytes(num) mbedtls_mpi_size(num)
+#define bignum_num_bits(num) mbedtls_mpi_bitlen(num)
+#define bignum_is_bit_set(num, bit) ssh_mbedcry_is_bit_set(num, bit)
+#define bignum_bn2bin(num, ptr) mbedtls_mpi_write_binary(num, ptr, \
+ mbedtls_mpi_size(num))
+#define bignum_cmp(num1, num2) mbedtls_mpi_cmp_mpi(num1, num2)
+
+mbedtls_entropy_context ssh_mbedtls_entropy;
+mbedtls_ctr_drbg_context ssh_mbedtls_ctr_drbg;
+
+void ssh_mbedtls_init(void);
+void ssh_mbedtls_cleanup(void);
+int ssh_mbedtls_random(void *where, int len, int strong);
+
+ssh_string make_ecpoint_string(const mbedtls_ecp_group *g, const
+ mbedtls_ecp_point *p);
+
+#endif /* HAVE_LIBMBEDCRYPTO */
+#endif /* LIBMBEDCRYPTO_H_ */
diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h
index 504a645a..d8757406 100644
--- a/include/libssh/libssh.h
+++ b/include/libssh/libssh.h
@@ -253,12 +253,16 @@ enum ssh_error_types_e {
/* some types for keys */
enum ssh_keytypes_e{
SSH_KEYTYPE_UNKNOWN=0,
+#ifdef HAVE_DSA
SSH_KEYTYPE_DSS=1,
+#endif
SSH_KEYTYPE_RSA,
SSH_KEYTYPE_RSA1,
SSH_KEYTYPE_ECDSA,
SSH_KEYTYPE_ED25519,
+#ifdef HAVE_DSA
SSH_KEYTYPE_DSS_CERT01,
+#endif
SSH_KEYTYPE_RSA_CERT01
};
diff --git a/include/libssh/pki.h b/include/libssh/pki.h
index e0e30f1a..46ce6457 100644
--- a/include/libssh/pki.h
+++ b/include/libssh/pki.h
@@ -48,6 +48,9 @@ struct ssh_key_struct {
gcry_sexp_t dsa;
gcry_sexp_t rsa;
gcry_sexp_t ecdsa;
+#elif HAVE_LIBMBEDCRYPTO
+ mbedtls_pk_context *rsa;
+ mbedtls_ecdsa_context *ecdsa;
#elif HAVE_LIBCRYPTO
DSA *dsa;
RSA *rsa;
@@ -78,6 +81,9 @@ struct ssh_signature_struct {
# else
void *ecdsa_sig;
# endif
+#elif defined HAVE_LIBMBEDCRYPTO
+ ssh_string rsa_sig;
+ struct mbedtls_ecdsa_sig ecdsa_sig;
#endif
ed25519_signature *ed25519_sig;
};
diff --git a/include/libssh/pki_priv.h b/include/libssh/pki_priv.h
index 9a8857dc..7dfd49aa 100644
--- a/include/libssh/pki_priv.h
+++ b/include/libssh/pki_priv.h
@@ -34,8 +34,10 @@ int bcrypt_pbkdf(const char *pass,
#define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----"
#define RSA_HEADER_END "-----END RSA PRIVATE KEY-----"
+#ifdef HAVE_DSA
#define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----"
#define DSA_HEADER_END "-----END DSA PRIVATE KEY-----"
+#endif
#define ECDSA_HEADER_BEGIN "-----BEGIN EC PRIVATE KEY-----"
#define ECDSA_HEADER_END "-----END EC PRIVATE KEY-----"
#define OPENSSH_HEADER_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----"
@@ -49,7 +51,9 @@ const char *pki_key_ecdsa_nid_to_name(int nid);
/* SSH Key Functions */
ssh_key pki_key_dup(const ssh_key key, int demote);
int pki_key_generate_rsa(ssh_key key, int parameter);
+#ifdef HAVE_DSA
int pki_key_generate_dss(ssh_key key, int parameter);
+#endif
int pki_key_generate_ecdsa(ssh_key key, int parameter);
int pki_key_generate_ed25519(ssh_key key);
@@ -70,11 +74,13 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
void *auth_data);
/* SSH Public Key Functions */
+#ifdef HAVE_DSA
int pki_pubkey_build_dss(ssh_key key,
ssh_string p,
ssh_string q,
ssh_string g,
ssh_string pubkey);
+#endif
int pki_pubkey_build_rsa(ssh_key key,
ssh_string e,
ssh_string n);
diff --git a/include/libssh/server.h b/include/libssh/server.h
index c2132de1..b76b95b3 100644
--- a/include/libssh/server.h
+++ b/include/libssh/server.h
@@ -40,7 +40,9 @@ enum ssh_bind_options_e {
SSH_BIND_OPTIONS_BINDPORT,
SSH_BIND_OPTIONS_BINDPORT_STR,
SSH_BIND_OPTIONS_HOSTKEY,
+#ifdef HAVE_DSA
SSH_BIND_OPTIONS_DSAKEY,
+#endif
SSH_BIND_OPTIONS_RSAKEY,
SSH_BIND_OPTIONS_BANNER,
SSH_BIND_OPTIONS_LOG_VERBOSITY,
diff --git a/include/libssh/session.h b/include/libssh/session.h
index 60d78578..3357f7f3 100644
--- a/include/libssh/session.h
+++ b/include/libssh/session.h
@@ -154,7 +154,9 @@ struct ssh_session_struct {
/* server host keys */
struct {
ssh_key rsa_key;
+#ifdef HAVE_DSA
ssh_key dsa_key;
+#endif
ssh_key ecdsa_key;
ssh_key ed25519_key;
/* The type of host key wanted by client */
diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h
index cdd72d6d..6b6cf0b1 100644
--- a/include/libssh/wrapper.h
+++ b/include/libssh/wrapper.h
@@ -25,6 +25,7 @@
#include "libssh/libssh.h"
#include "libssh/libcrypto.h"
#include "libssh/libgcrypt.h"
+#include "libssh/libmbedcrypto.h"
enum ssh_mac_e {
SSH_MAC_SHA1=1,
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e5a93538..da87313e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -39,6 +39,17 @@ if (OPENSSL_CRYPTO_LIBRARY)
)
endif (OPENSSL_CRYPTO_LIBRARY)
+if (MBEDTLS_CRYPTO_LIBRARY)
+ set(LIBSSH_PRIVATE_INCLUDE_DIRS
+ ${LIBSSH_PRIVATE_INCLUDE_DIRS}
+ ${MBEDTLS_INCLUDE_DIR}
+ )
+ set(LIBSSH_LINK_LIBRARIES
+ ${LIBSSH_LINK_LIBRARIES}
+ ${MBEDTLS_CRYPTO_LIBRARY}
+ )
+endif (MBEDTLS_CRYPTO_LIBRARY)
+
if (GCRYPT_LIBRARY)
set(LIBSSH_PRIVATE_INCLUDE_DIRS
${LIBSSH_PRIVATE_INCLUDE_DIRS}
@@ -160,6 +171,14 @@ if (WITH_GCRYPT)
pki_gcrypt.c
ecdh_gcrypt.c
)
+elseif (WITH_MBEDTLS)
+ set(libssh_SRCS
+ ${libssh_SRCS}
+ libmbedcrypto.c
+ mbedcrypto_missing.c
+ pki_mbedcrypto.c
+ ecdh_mbedcrypto.c
+ )
else (WITH_GCRYPT)
set(libssh_SRCS
${libssh_SRCS}
diff --git a/src/auth.c b/src/auth.c
index 8a686dc2..c92e3073 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -1206,12 +1206,16 @@ int ssh_userauth_agent_pubkey(ssh_session session,
key->type = publickey->type;
key->type_c = ssh_key_type_to_char(key->type);
key->flags = SSH_KEY_FLAG_PUBLIC;
+#ifdef HAVE_DSA
key->dsa = publickey->dsa_pub;
+#endif
key->rsa = publickey->rsa_pub;
rc = ssh_userauth_agent_publickey(session, username, key);
+#ifdef HAVE_DSA
key->dsa = NULL;
+#endif
key->rsa = NULL;
ssh_key_free(key);
diff --git a/src/bignum.c b/src/bignum.c
index fd6cf954..93e67e7d 100644
--- a/src/bignum.c
+++ b/src/bignum.c
@@ -58,6 +58,8 @@ ssh_string ssh_make_bignum_string(bignum num) {
bignum_bn2bin(num, len, ptr->data + pad);
#elif HAVE_LIBCRYPTO
bignum_bn2bin(num, ptr->data + pad);
+#elif HAVE_LIBMBEDCRYPTO
+ bignum_bn2bin(num, ptr->data + pad);
#endif
return ptr;
@@ -76,6 +78,9 @@ bignum ssh_make_string_bn(ssh_string string){
bignum_bin2bn(string->data, len, &bn);
#elif defined HAVE_LIBCRYPTO
bn = bignum_bin2bn(string->data, len, NULL);
+#elif defined HAVE_LIBMBEDCRYPTO
+ bn = bignum_new();
+ bignum_bin2bn(string->data, len, bn);
#endif
return bn;
@@ -89,6 +94,8 @@ void ssh_make_string_bn_inplace(ssh_string string, bignum bnout) {
(void) bnout;
#elif defined HAVE_LIBCRYPTO
bignum_bin2bn(string->data, len, bnout);
+#elif defined HAVE_LIBMBEDCRYPTO
+ bignum_bin2bn(string->data, len, bnout);
#endif
}
@@ -100,6 +107,9 @@ void ssh_print_bignum(const char *which, const bignum num) {
#elif defined HAVE_LIBCRYPTO
char *hex = NULL;
hex = bignum_bn2hex(num);
+#elif defined HAVE_LIBMBEDCRYPTO
+ char *hex = NULL;
+ hex = bignum_bn2hex(num);
#endif
fprintf(stderr, "%s value: ", which);
fprintf(stderr, "%s\n", (hex == NULL) ? "(null)" : (char *) hex);
@@ -107,5 +117,7 @@ void ssh_print_bignum(const char *which, const bignum num) {
SAFE_FREE(hex);
#elif defined HAVE_LIBCRYPTO
OPENSSL_free(hex);
+#elif defined HAVE_LIBMBEDCRYPTO
+ SAFE_FREE(hex);
#endif
}
diff --git a/src/bind.c b/src/bind.c
index fa5f8d57..2b41fe18 100644
--- a/src/bind.c
+++ b/src/bind.c
@@ -148,7 +148,9 @@ static int ssh_bind_import_keys(ssh_bind sshbind) {
int rc;
if (sshbind->ecdsakey == NULL &&
+#ifdef HAVE_DSA
sshbind->dsakey == NULL &&
+#endif
sshbind->rsakey == NULL) {
ssh_set_error(sshbind, SSH_FATAL,
"ECDSA, DSA, or RSA host key file must be set");
@@ -178,6 +180,7 @@ static int ssh_bind_import_keys(ssh_bind sshbind) {
}
#endif
+#ifdef HAVE_DSA
if (sshbind->dsa == NULL && sshbind->dsakey != NULL) {
rc = ssh_pki_import_privkey_file(sshbind->dsakey,
NULL,
@@ -199,6 +202,7 @@ static int ssh_bind_import_keys(ssh_bind sshbind) {
return SSH_ERROR;
}
}
+#endif
if (sshbind->rsa == NULL && sshbind->rsakey != NULL) {
rc = ssh_pki_import_privkey_file(sshbind->rsakey,
@@ -235,7 +239,11 @@ int ssh_bind_listen(ssh_bind sshbind) {
return -1;
}
- if (sshbind->rsa == NULL && sshbind->dsa == NULL && sshbind->ecdsa == NULL) {
+ if (sshbind->rsa == NULL &&
+#ifdef HAVE_DSA
+ sshbind->dsa == NULL &&
+#endif
+ sshbind->ecdsa == NULL) {
rc = ssh_bind_import_keys(sshbind);
if (rc != SSH_OK) {
return SSH_ERROR;
@@ -250,8 +258,10 @@ int ssh_bind_listen(ssh_bind sshbind) {
fd = bind_socket(sshbind, host, sshbind->bindport);
if (fd == SSH_INVALID_SOCKET) {
+#ifdef HAVE_DSA
ssh_key_free(sshbind->dsa);
sshbind->dsa = NULL;
+#endif
ssh_key_free(sshbind->rsa);
sshbind->rsa = NULL;
return -1;
@@ -262,8 +272,10 @@ int ssh_bind_listen(ssh_bind sshbind) {
"Listening to socket %d: %s",
fd, strerror(errno));
CLOSE_SOCKET(fd);
+#ifdef HAVE_DSA
ssh_key_free(sshbind->dsa);
sshbind->dsa = NULL;
+#endif
ssh_key_free(sshbind->rsa);
sshbind->rsa = NULL;
return -1;
@@ -360,13 +372,17 @@ void ssh_bind_free(ssh_bind sshbind){
SAFE_FREE(sshbind->banner);
SAFE_FREE(sshbind->bindaddr);
+#ifdef HAVE_DSA
SAFE_FREE(sshbind->dsakey);
+#endif
SAFE_FREE(sshbind->rsakey);
SAFE_FREE(sshbind->ecdsakey);
SAFE_FREE(sshbind->ed25519key);
+#ifdef HAVE_DSA
ssh_key_free(sshbind->dsa);
sshbind->dsa = NULL;
+#endif
ssh_key_free(sshbind->rsa);
sshbind->rsa = NULL;
ssh_key_free(sshbind->ecdsa);
@@ -433,7 +449,9 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
* only using ssh_bind_accept_fd to manage sockets ourselves.
*/
if (sshbind->rsa == NULL &&
+#ifdef HAVE_DSA
sshbind->dsa == NULL &&
+#endif
sshbind->ecdsa == NULL) {
rc = ssh_bind_import_keys(sshbind);
if (rc != SSH_OK) {
@@ -450,6 +468,7 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
}
}
#endif
+#ifdef HAVE_DSA
if (sshbind->dsa) {
session->srv.dsa_key = ssh_key_dup(sshbind->dsa);
if (session->srv.dsa_key == NULL) {
@@ -457,6 +476,7 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
return SSH_ERROR;
}
}
+#endif
if (sshbind->rsa) {
session->srv.rsa_key = ssh_key_dup(sshbind->rsa);
if (session->srv.rsa_key == NULL) {
diff --git a/src/curve25519.c b/src/curve25519.c
index 77fab2d2..6d9a409c 100644
--- a/src/curve25519.c
+++ b/src/curve25519.c
@@ -78,6 +78,12 @@ static int ssh_curve25519_build_k(ssh_session session) {
if (session->next_crypto->k == NULL) {
return SSH_ERROR;
}
+#elif defined HAVE_LIBMBEDCRYPTO
+ session->next_crypto->k = bignum_new();
+
+ if (session->next_crypto->k == NULL) {
+ return SSH_ERROR;
+ }
#endif
if (session->server)
@@ -91,6 +97,8 @@ static int ssh_curve25519_build_k(ssh_session session) {
bignum_bin2bn(k, CURVE25519_PUBKEY_SIZE, &session->next_crypto->k);
#elif defined HAVE_LIBCRYPTO
bignum_bin2bn(k, CURVE25519_PUBKEY_SIZE, session->next_crypto->k);
+#elif defined HAVE_LIBMBEDCRYPTO
+ bignum_bin2bn(k, CURVE25519_PUBKEY_SIZE, session->next_crypto->k);
#endif
#ifdef DEBUG_CRYPTO
diff --git a/src/dh.c b/src/dh.c
index c54bb9f1..b547d6f8 100644
--- a/src/dh.c
+++ b/src/dh.c
@@ -136,6 +136,8 @@ int ssh_get_random(void *where, int len, int strong){
} else {
return RAND_pseudo_bytes(where,len);
}
+#elif defined HAVE_LIBMBEDCRYPTO
+ return ssh_mbedtls_random(where, len, strong);
#endif
/* never reached */
@@ -155,6 +157,8 @@ int ssh_crypto_init(void) {
gcry_control(GCRYCTL_INIT_SECMEM, 4096);
gcry_control(GCRYCTL_INITIALIZATION_FINISHED,0);
}
+#elif HAVE_LIBMBEDCRYPTO
+ ssh_mbedtls_init();
#endif
g = bignum_new();
@@ -199,7 +203,12 @@ int ssh_crypto_init(void) {
bignum_bin2bn(p_group14_value, P_GROUP14_LEN, p_group14);
OpenSSL_add_all_algorithms();
+#elif defined HAVE_LIBMBEDCRYPTO
+ p_group1 = bignum_new();
+ bignum_bin2bn(p_group1_value, P_GROUP1_LEN, p_group1);
+ p_group14 = bignum_new();
+ bignum_bin2bn(p_group14_value, P_GROUP14_LEN, p_group14);
#endif
ssh_crypto_initialized = 1;
@@ -221,6 +230,8 @@ void ssh_crypto_finalize(void) {
#elif defined HAVE_LIBCRYPTO
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
+#elif defined HAVE_LIBMBEDTLS
+ ssh_mbedtls_cleanup();
#endif
ssh_crypto_initialized=0;
}
@@ -242,6 +253,8 @@ int ssh_dh_generate_x(ssh_session session) {
bignum_rand(session->next_crypto->x, keysize);
#elif defined HAVE_LIBCRYPTO
bignum_rand(session->next_crypto->x, keysize, -1, 0);
+#elif defined HAVE_LIBMBEDCRYPTO
+ bignum_rand(session->next_crypto->x, keysize, -1, 0);
#endif
/* not harder than this */
@@ -269,6 +282,8 @@ int ssh_dh_generate_y(ssh_session session) {
bignum_rand(session->next_crypto->y, keysize);
#elif defined HAVE_LIBCRYPTO
bignum_rand(session->next_crypto->y, keysize, -1, 0);
+#elif defined HAVE_LIBMBEDCRYPTO
+ bignum_rand(session->next_crypto->y, keysize, -1, 0);
#endif
/* not harder than this */
@@ -302,6 +317,9 @@ int ssh_dh_generate_e(ssh_session session) {
#elif defined HAVE_LIBCRYPTO
bignum_mod_exp(session->next_crypto->e, g, session->next_crypto->x,
select_p(session->next_crypto->kex_type), ctx);
+#elif defined HAVE_LIBMBEDCRYPTO
+ bignum_mod_exp(session->next_crypto->e, g, session->next_crypto->x,
+ select_p(session->next_crypto->kex_type), NULL);
#endif
#ifdef DEBUG_CRYPTO
@@ -337,6 +355,9 @@ int ssh_dh_generate_f(ssh_session session) {
#elif defined HAVE_LIBCRYPTO
bignum_mod_exp(session->next_crypto->f, g, session->next_crypto->y,
select_p(session->next_crypto->kex_type), ctx);
+#elif defined HAVE_LIBMBEDCRYPTO
+ bignum_mod_exp(session->next_crypto->f, g, session->next_crypto->y,
+ select_p(session->next_crypto->kex_type), NULL);
#endif
#ifdef DEBUG_CRYPTO
@@ -423,6 +444,14 @@ int ssh_dh_build_k(ssh_session session) {
bignum_mod_exp(session->next_crypto->k, session->next_crypto->e,
session->next_crypto->y, select_p(session->next_crypto->kex_type), ctx);
}
+#elif defined HAVE_LIBMBEDCRYPTO
+ if (session->client) {
+ bignum_mod_exp(session->next_crypto->k, session->next_crypto->f,
+ session->next_crypto->x, select_p(session->next_crypto->kex_type), NULL);
+ } else {
+ bignum_mod_exp(session->next_crypto->k, session->next_crypto->e,
+ session->next_crypto->y, select_p(session->next_crypto->kex_type), NULL);
+ }
#endif
#ifdef DEBUG_CRYPTO
diff --git a/src/ecdh_mbedcrypto.c b/src/ecdh_mbedcrypto.c
new file mode 100644
index 00000000..344260c5
--- /dev/null
+++ b/src/ecdh_mbedcrypto.c
@@ -0,0 +1,265 @@
+/*
+ * This file is part of the SSH Library
+ *
+ * Copyright (c) 2017 Sartura d.o.o.
+ *
+ * Author: Juraj Vijtiuk <juraj.vijtiuk@xxxxxxxxxx>
+ *
+ * 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/session.h"
+#include "libssh/ecdh.h"
+#include "libssh/buffer.h"
+#include "libssh/ssh2.h"
+#include "libssh/dh.h"
+#include "libssh/pki.h"
+#include "libssh/bignum.h"
+#include "libssh/libmbedcrypto.h"
+
+#include <mbedtls/ecdh.h>
+#include <mbedtls/ecp.h>
+
+#ifdef HAVE_ECDH
+int ssh_client_ecdh_init(ssh_session session)
+{
+ ssh_string client_pubkey = NULL;
+ mbedtls_ecp_group grp;
+ int rc;
+
+ rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT);
+ if (rc < 0) {
+ return SSH_ERROR;
+ }
+
+ session->next_crypto->ecdh_privkey = malloc(sizeof(mbedtls_ecp_keypair));
+ if (session->next_crypto->ecdh_privkey == NULL) {
+ return SSH_ERROR;
+ }
+
+ mbedtls_ecp_keypair_init(session->next_crypto->ecdh_privkey);
+ mbedtls_ecp_group_init(&grp);
+
+ rc = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
+ if (rc != 0) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ rc = mbedtls_ecp_gen_keypair(&grp, &session->next_crypto->ecdh_privkey->d,
+ &session->next_crypto->ecdh_privkey->Q, mbedtls_ctr_drbg_random,
+ &ssh_mbedtls_ctr_drbg);
+
+ if (rc != 0) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ client_pubkey = make_ecpoint_string(&grp,
+ &session->next_crypto->ecdh_privkey->Q);
+ if (client_pubkey == NULL) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ rc = ssh_buffer_add_ssh_string(session->out_buffer, client_pubkey);
+ if (rc < 0) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ session->next_crypto->ecdh_client_pubkey = client_pubkey;
+ client_pubkey = NULL;
+
+ rc = ssh_packet_send(session);
+
+out:
+ mbedtls_ecp_group_free(&grp);
+ if (client_pubkey != NULL) {
+ ssh_string_free(client_pubkey);
+ }
+
+ return rc;
+}
+
+int ecdh_build_k(ssh_session session)
+{
+ mbedtls_ecp_group grp;
+ mbedtls_ecp_point pubkey;
+ int rc;
+
+ mbedtls_ecp_group_init(&grp);
+ mbedtls_ecp_point_init(&pubkey);
+
+ rc = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
+ if (rc != 0) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ if (session->server) {
+ rc = mbedtls_ecp_point_read_binary(&grp, &pubkey,
+ ssh_string_data(session->next_crypto->ecdh_client_pubkey),
+ ssh_string_len(session->next_crypto->ecdh_client_pubkey));
+ } else {
+ rc = mbedtls_ecp_point_read_binary(&grp, &pubkey,
+ ssh_string_data(session->next_crypto->ecdh_server_pubkey),
+ ssh_string_len(session->next_crypto->ecdh_server_pubkey));
+ }
+
+ if (rc != 0) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ session->next_crypto->k = malloc(sizeof(mbedtls_mpi));
+ if (session->next_crypto->k == NULL) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ mbedtls_mpi_init(session->next_crypto->k);
+
+ rc = mbedtls_ecdh_compute_shared(&grp, session->next_crypto->k, &pubkey,
+ &session->next_crypto->ecdh_privkey->d, mbedtls_ctr_drbg_random,
+ &ssh_mbedtls_ctr_drbg);
+ if (rc != 0) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+out:
+ mbedtls_ecp_keypair_free(session->next_crypto->ecdh_privkey);
+ SAFE_FREE(session->next_crypto->ecdh_privkey);
+ mbedtls_ecp_group_free(&grp);
+ mbedtls_ecp_point_free(&pubkey);
+ return rc;
+}
+
+#ifdef WITH_SERVER
+int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet)
+{
+ ssh_string q_c_string;
+ ssh_string q_s_string;
+ mbedtls_ecp_group grp;
+ ssh_key privkey;
+ ssh_string sig_blob = NULL;
+ int rc;
+
+ q_c_string = ssh_buffer_get_ssh_string(packet);
+ if (q_c_string == NULL) {
+ ssh_set_error(session, SSH_FATAL, "No Q_C ECC point in packet");
+ return SSH_ERROR;
+ }
+
+ session->next_crypto->ecdh_privkey = malloc(sizeof(mbedtls_ecp_keypair));
+ if (session->next_crypto->ecdh_privkey == NULL) {
+ return SSH_ERROR;
+ }
+
+ session->next_crypto->ecdh_client_pubkey = q_c_string;
+
+ mbedtls_ecp_group_init(&grp);
+ mbedtls_ecp_keypair_init(session->next_crypto->ecdh_privkey);
+
+ rc = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
+ if (rc != 0) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ rc = mbedtls_ecp_gen_keypair(&grp, &session->next_crypto->ecdh_privkey->d,
+ &session->next_crypto->ecdh_privkey->Q, mbedtls_ctr_drbg_random,
+ &ssh_mbedtls_ctr_drbg);
+ if (rc != 0) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ q_s_string = make_ecpoint_string(&grp, &session->next_crypto->ecdh_privkey->Q);
+ if (q_s_string == NULL) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ session->next_crypto->ecdh_server_pubkey = q_s_string;
+
+ /* build k and session_id */
+ rc = ecdh_build_k(session);
+ if (rc != SSH_OK) {
+ ssh_set_error(session, SSH_FATAL, "Cannot build k number");
+ goto out;
+ }
+
+ /* privkey is not allocated */
+ rc = ssh_get_key_params(session, &privkey);
+ if (rc == SSH_ERROR) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ rc = ssh_make_sessionid(session);
+ if (rc != SSH_OK) {
+ ssh_set_error(session, SSH_FATAL, "Could not create a session id");
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
+ if (sig_blob == NULL) {
+ ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ rc = ssh_buffer_pack(session->out_buffer, "bSSS",
+ SSH2_MSG_KEXDH_REPLY, session->next_crypto->server_pubkey,
+ q_s_string,
+ sig_blob);
+
+ ssh_string_free(sig_blob);
+
+ if (rc != SSH_OK) {
+ ssh_set_error_oom(session);
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent");
+ rc = ssh_packet_send(session);
+ if (rc != SSH_OK) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
+ if (rc < 0) {
+ rc = SSH_ERROR;
+ goto out;
+ }
+
+ session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
+ rc = ssh_packet_send(session);
+ SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
+
+out:
+ mbedtls_ecp_group_free(&grp);
+ return rc;
+}
+
+#endif /* WITH_SERVER */
+#endif
diff --git a/src/kex.c b/src/kex.c
index f34728c7..5f222147 100644
--- a/src/kex.c
+++ b/src/kex.c
@@ -43,6 +43,12 @@
# define DES "3des-cbc"
# define DES_SUPPORTED "3des-cbc,des-cbc-ssh1"
+#elif defined HAVE_LIBMBEDCRYPTO
+# define BLOWFISH "blowfish-cbc,"
+# define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,"
+# define DES "3des-cbc"
+# define DES_SUPPORTED "3des-cbc,des-cbc-ssh1"
+
#elif defined(HAVE_LIBCRYPTO)
# ifdef HAVE_OPENSSL_BLOWFISH_H
@@ -81,7 +87,11 @@
#define ECDH "ecdh-sha2-nistp256,"
#define HOSTKEYS "ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,ssh-dss"
#else
+#ifdef HAVE_DSA
#define HOSTKEYS "ssh-ed25519,ssh-rsa,ssh-dss"
+#else
+#define HOSTKEYS "ssh-ed25519,ssh-rsa"
+#endif
#define ECDH ""
#endif
@@ -495,7 +505,9 @@ static char *ssh_client_select_hostkeys(ssh_session session){
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp256",
"ssh-rsa",
+#ifdef HAVE_DSA
"ssh-dss",
+#endif
"ssh-rsa1",
NULL
};
diff --git a/src/known_hosts.c b/src/known_hosts.c
index 2f66cc27..354da176 100644
--- a/src/known_hosts.c
+++ b/src/known_hosts.c
@@ -220,7 +220,11 @@ static int check_public_key(ssh_session session, char **tokens) {
for (i = 2; i < 4; i++) { /* e, then n */
tmpbn = NULL;
+#ifdef HAVE_LIBMBEDCRYPTO
+ bignum_dec2bn(tokens[i], tmpbn);
+#else
bignum_dec2bn(tokens[i], &tmpbn);
+#endif
if (tmpbn == NULL) {
ssh_buffer_free(pubkey_buffer);
return -1;
@@ -242,6 +246,8 @@ static int check_public_key(ssh_session session, char **tokens) {
bignum_bn2bin(tmpbn, len, ssh_string_data(tmpstring));
#elif defined HAVE_LIBCRYPTO
bignum_bn2bin(tmpbn, ssh_string_data(tmpstring));
+#elif defined HAVE_LIBMBEDCRYPTO
+ bignum_bn2bin(tmpbn, ssh_string_data(tmpstring));
#endif
bignum_free(tmpbn);
if (ssh_buffer_add_ssh_string(pubkey_buffer, tmpstring) < 0) {
diff --git a/src/legacy.c b/src/legacy.c
index 3f09992c..7f43f59c 100644
--- a/src/legacy.c
+++ b/src/legacy.c
@@ -82,11 +82,15 @@ int ssh_userauth_pubkey(ssh_session session,
key->type = privatekey->type;
key->type_c = ssh_key_type_to_char(key->type);
key->flags = SSH_KEY_FLAG_PRIVATE|SSH_KEY_FLAG_PUBLIC;
+#ifdef HAVE_DSA
key->dsa = privatekey->dsa_priv;
+#endif
key->rsa = privatekey->rsa_priv;
rc = ssh_userauth_publickey(session, username, key);
+#ifdef HAVE_DSA
key->dsa = NULL;
+#endif
key->rsa = NULL;
ssh_key_free(key);
@@ -349,6 +353,7 @@ void publickey_free(ssh_public_key key) {
}
switch(key->type) {
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS:
#ifdef HAVE_LIBGCRYPT
gcry_sexp_release(key->dsa_pub);
@@ -356,12 +361,16 @@ void publickey_free(ssh_public_key key) {
DSA_free(key->dsa_pub);
#endif
break;
+#endif
case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1:
#ifdef HAVE_LIBGCRYPT
gcry_sexp_release(key->rsa_pub);
#elif defined HAVE_LIBCRYPTO
RSA_free(key->rsa_pub);
+#elif defined HAVE_LIBMBEDCRYPTO
+ mbedtls_pk_free(key->rsa_pub);
+ SAFE_FREE(key->rsa_pub);
#endif
break;
default:
@@ -384,11 +393,15 @@ ssh_public_key publickey_from_privatekey(ssh_private_key prv) {
privkey->type = prv->type;
privkey->type_c = ssh_key_type_to_char(privkey->type);
privkey->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
+#ifdef HAVE_DSA
privkey->dsa = prv->dsa_priv;
+#endif
privkey->rsa = prv->rsa_priv;
rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey);
+#ifdef HAVE_DSA
privkey->dsa = NULL;
+#endif
privkey->rsa = NULL;
ssh_key_free(privkey);
if (rc < 0) {
@@ -435,10 +448,14 @@ ssh_private_key privatekey_from_file(ssh_session session,
}
privkey->type = key->type;
+#ifdef HAVE_DSA
privkey->dsa_priv = key->dsa;
+#endif
privkey->rsa_priv = key->rsa;
+#ifdef HAVE_DSA
key->dsa = NULL;
+#endif
key->rsa = NULL;
ssh_key_free(key);
@@ -463,6 +480,9 @@ void privatekey_free(ssh_private_key prv) {
#elif defined HAVE_LIBCRYPTO
DSA_free(prv->dsa_priv);
RSA_free(prv->rsa_priv);
+#elif defined HAVE_LIBMBEDCRYPTO
+ mbedtls_pk_free(prv->rsa_priv);
+ SAFE_FREE(prv->rsa_priv);
#endif
memset(prv, 0, sizeof(struct ssh_private_key_struct));
SAFE_FREE(prv);
@@ -524,8 +544,10 @@ ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s) {
pubkey->type = key->type;
pubkey->type_c = key->type_c;
+#ifdef HAVE_DSA
pubkey->dsa_pub = key->dsa;
key->dsa = NULL;
+#endif
pubkey->rsa_pub = key->rsa;
key->rsa = NULL;
@@ -547,7 +569,9 @@ ssh_string publickey_to_string(ssh_public_key pubkey) {
key->type = pubkey->type;
key->type_c = pubkey->type_c;
+#ifdef HAVE_DSA
key->dsa = pubkey->dsa_pub;
+#endif
key->rsa = pubkey->rsa_pub;
rc = ssh_pki_export_pubkey_blob(key, &key_blob);
@@ -555,7 +579,9 @@ ssh_string publickey_to_string(ssh_public_key pubkey) {
key_blob = NULL;
}
+#ifdef HAVE_DSA
key->dsa = NULL;
+#endif
key->rsa = NULL;
ssh_key_free(key);
diff --git a/src/libcrypto-compat.c b/src/libcrypto-compat.c
index 3e1bc71a..45dffbb4 100644
--- a/src/libcrypto-compat.c
+++ b/src/libcrypto-compat.c
@@ -304,9 +304,11 @@ void HMAC_CTX_free(HMAC_CTX *ctx)
{
if (ctx != NULL) {
hmac_ctx_cleanup(ctx);
+#if OPENSSL_VERSION_NUMBER > 0x10100000L
EVP_MD_CTX_free(&ctx->i_ctx);
EVP_MD_CTX_free(&ctx->o_ctx);
EVP_MD_CTX_free(&ctx->md_ctx);
+#endif
OPENSSL_free(ctx);
}
}
diff --git a/src/libcrypto.c b/src/libcrypto.c
index 867bf227..59c99568 100644
--- a/src/libcrypto.c
+++ b/src/libcrypto.c
@@ -422,7 +422,8 @@ void hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, unsigned int *len) {
HMAC_Final(ctx,hashmacbuf,len);
#ifndef OLD_CRYPTO
- HMAC_CTX_reset(ctx);
+ HMAC_CTX_free(ctx);
+ ctx = NULL;
#else
HMAC_cleanup(ctx);
#endif
@@ -552,7 +553,10 @@ static void evp_cipher_decrypt(struct ssh_cipher_struct *cipher,
}
static void evp_cipher_cleanup(struct ssh_cipher_struct *cipher) {
+ if (cipher->ctx != NULL) {
EVP_CIPHER_CTX_cleanup(cipher->ctx);
+ EVP_CIPHER_CTX_free(cipher->ctx);
+ }
}
#ifndef HAVE_OPENSSL_EVP_AES_CTR
diff --git a/src/libmbedcrypto.c b/src/libmbedcrypto.c
new file mode 100644
index 00000000..c89033fb
--- /dev/null
+++ b/src/libmbedcrypto.c
@@ -0,0 +1,1109 @@
+/*
+ * This file is part of the SSH Library
+ *
+ * Copyright (c) 2017 Sartura d.o.o.
+ *
+ * Author: Juraj Vijtiuk <juraj.vijtiuk@xxxxxxxxxx>
+ *
+ * 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 "libssh/wrapper.h"
+#include "libssh/crypto.h"
+#include "libssh/priv.h"
+
+#ifdef HAVE_LIBMBEDCRYPTO
+#include <mbedtls/md.h>
+
+struct ssh_mac_ctx_struct {
+ enum ssh_mac_e mac_type;
+ mbedtls_md_context_t ctx;
+};
+
+void ssh_reseed(void)
+{
+}
+
+SHACTX sha1_init(void)
+{
+ SHACTX ctx;
+ int rc;
+ const mbedtls_md_info_t *md_info =
+ mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
+
+ if (md_info == NULL) {
+ return NULL;
+ }
+
+ ctx = malloc(sizeof(mbedtls_md_context_t));
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ mbedtls_md_init(ctx);
+
+ rc = mbedtls_md_setup(ctx, md_info, 0);
+ if (rc != 0) {
+ return NULL;
+ }
+
+ rc = mbedtls_md_starts(ctx);
+ if (rc != 0) {
+ return NULL;
+ }
+
+ return ctx;
+}
+
+void sha1_update(SHACTX c, const void *data, unsigned long len)
+{
+ mbedtls_md_update(c, data, len);
+}
+
+void sha1_final(unsigned char *md, SHACTX c)
+{
+ mbedtls_md_finish(c, md);
+ mbedtls_md_free(c);
+ SAFE_FREE(c);
+}
+
+void sha1(unsigned char *digest, int len, unsigned char *hash)
+{
+ const mbedtls_md_info_t *md_info =
+ mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
+ if (md_info != NULL) {
+ mbedtls_md(md_info, digest, len, hash);
+ }
+}
+
+static mbedtls_md_type_t nid_to_md_algo(int nid)
+{
+ switch (nid) {
+ case NID_mbedtls_nistp256:
+ return MBEDTLS_MD_SHA256;
+ case NID_mbedtls_nistp384:
+ return MBEDTLS_MD_SHA384;
+ case NID_mbedtls_nistp521:
+ return MBEDTLS_MD_SHA512;
+ }
+ return MBEDTLS_MD_NONE;
+}
+
+void evp(int nid, unsigned char *digest, int len,
+ unsigned char *hash, unsigned int *hlen)
+{
+ mbedtls_md_type_t algo = nid_to_md_algo(nid);
+ const mbedtls_md_info_t *md_info =
+ mbedtls_md_info_from_type(algo);
+
+
+ if (md_info != NULL) {
+ *hlen = mbedtls_md_get_size(md_info);
+ mbedtls_md(md_info, digest, len, hash);
+ }
+}
+
+EVPCTX evp_init(int nid)
+{
+ EVPCTX ctx;
+ int rc;
+ mbedtls_md_type_t algo = nid_to_md_algo(nid);
+ const mbedtls_md_info_t *md_info =
+ mbedtls_md_info_from_type(algo);
+
+ if (md_info == NULL) {
+ return NULL;
+ }
+
+ ctx = malloc(sizeof(mbedtls_md_context_t));
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ mbedtls_md_init(ctx);
+
+ rc = mbedtls_md_setup(ctx, md_info, 0);
+ if (rc != 0) {
+ return NULL;
+ }
+
+ rc = mbedtls_md_starts(ctx);
+ if (rc != 0) {
+ return NULL;
+ }
+
+ return ctx;
+}
+
+void evp_update(EVPCTX ctx, const void *data, unsigned long len)
+{
+ mbedtls_md_update(ctx, data, len);
+}
+
+void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
+{
+ *mdlen = mbedtls_md_get_size(ctx->md_info);
+ mbedtls_md_hmac_finish(ctx, md);
+ mbedtls_md_free(ctx);
+ SAFE_FREE(ctx);
+}
+
+SHA256CTX sha256_init(void)
+{
+ SHA256CTX ctx;
+ int rc;
+ const mbedtls_md_info_t *md_info =
+ mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+
+ if (md_info == NULL) {
+ return NULL;
+ }
+
+ ctx = malloc(sizeof(mbedtls_md_context_t));
+ if(ctx == NULL) {
+ return NULL;
+ }
+
+ mbedtls_md_init(ctx);
+
+ rc = mbedtls_md_setup(ctx, md_info, 0);
+ if (rc != 0) {
+ return NULL;
+ }
+
+ rc = mbedtls_md_starts(ctx);
+ if (rc != 0) {
+ return NULL;
+ }
+
+ return ctx;
+}
+
+void sha256_update(SHA256CTX c, const void *data, unsigned long len)
+{
+ mbedtls_md_update(c, data, len);
+}
+
+void sha256_final(unsigned char *md, SHA256CTX c)
+{
+ mbedtls_md_finish(c, md);
+ mbedtls_md_free(c);
+ SAFE_FREE(c);
+}
+
+void sha256(unsigned char *digest, int len, unsigned char *hash)
+{
+ const mbedtls_md_info_t *md_info =
+ mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+ if (md_info != NULL) {
+ mbedtls_md(md_info, digest, len, hash);
+ }
+}
+
+SHA384CTX sha384_init(void)
+{
+ SHA384CTX ctx;
+ int rc;
+ const mbedtls_md_info_t *md_info =
+ mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
+
+ if (md_info == NULL) {
+ return NULL;
+ }
+
+ ctx = malloc(sizeof(mbedtls_md_context_t));
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ mbedtls_md_init(ctx);
+
+ rc = mbedtls_md_setup(ctx, md_info, 0);
+ if (rc != 0) {
+ return NULL;
+ }
+
+ rc = mbedtls_md_starts(ctx);
+ if (rc != 0) {
+ return NULL;
+ }
+
+ return ctx;
+}
+
+void sha384_update(SHA384CTX c, const void *data, unsigned long len)
+{
+ mbedtls_md_update(c, data, len);
+}
+
+void sha384_final(unsigned char *md, SHA384CTX c)
+{
+ mbedtls_md_finish(c, md);
+ mbedtls_md_free(c);
+ SAFE_FREE(c);
+}
+
+void sha384(unsigned char *digest, int len, unsigned char *hash)
+{
+ const mbedtls_md_info_t *md_info =
+ mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
+ if (md_info != NULL) {
+ mbedtls_md(md_info, digest, len, hash);
+ }
+}
+
+SHA512CTX sha512_init(void)
+{
+ SHA512CTX ctx;
+ int rc;
+ const mbedtls_md_info_t *md_info =
+ mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
+ if (md_info == NULL) {
+ return NULL;
+ }
+
+ ctx = malloc(sizeof(mbedtls_md_context_t));
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ mbedtls_md_init(ctx);
+
+ rc = mbedtls_md_setup(ctx, md_info, 0);
+ if (rc != 0) {
+ return NULL;
+ }
+
+ rc = mbedtls_md_starts(ctx);
+ if (rc != 0) {
+ return NULL;
+ }
+
+ return ctx;
+}
+
+void sha512_update(SHA512CTX c, const void *data, unsigned long len)
+{
+ mbedtls_md_update(c, data, len);
+}
+
+void sha512_final(unsigned char *md, SHA512CTX c)
+{
+ mbedtls_md_finish(c, md);
+ mbedtls_md_free(c);
+ SAFE_FREE(c);
+}
+
+void sha512(unsigned char *digest, int len, unsigned char *hash)
+{
+ const mbedtls_md_info_t *md_info =
+ mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
+ if (md_info != NULL) {
+ mbedtls_md(md_info, digest, len, hash);
+ }
+}
+
+MD5CTX md5_init(void)
+{
+ MD5CTX ctx;
+ int rc;
+ const mbedtls_md_info_t *md_info =
+ mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
+ if (md_info == NULL) {
+ return NULL;
+ }
+
+ ctx = malloc(sizeof(mbedtls_md_context_t));
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ mbedtls_md_init(ctx);
+
+ rc = mbedtls_md_setup(ctx, md_info, 0);
+ if (rc != 0) {
+ return NULL;
+ }
+
+ rc = mbedtls_md_starts(ctx);
+ if (rc != 0) {
+ return NULL;
+ }
+
+ return ctx;
+}
+
+
+void md5_update(MD5CTX c, const void *data, unsigned long len) {
+ mbedtls_md_update(c, data, len);
+}
+
+void md5_final(unsigned char *md, MD5CTX c)
+{
+ mbedtls_md_finish(c, md);
+ mbedtls_md_free(c);
+ SAFE_FREE(c);
+}
+
+ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type)
+{
+ ssh_mac_ctx ctx = malloc(sizeof (struct ssh_mac_ctx_struct));
+ const mbedtls_md_info_t *md_info;
+ int rc;
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ ctx->mac_type=type;
+ switch(type) {
+ case SSH_MAC_SHA1:
+ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
+ break;
+ case SSH_MAC_SHA256:
+ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+ break;
+ case SSH_MAC_SHA384:
+ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
+ break;
+ case SSH_MAC_SHA512:
+ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
+ break;
+ default:
+ goto error;
+ }
+
+ if (md_info == NULL) {
+ goto error;
+ }
+
+ mbedtls_md_init(&ctx->ctx);
+
+ rc = mbedtls_md_setup(&ctx->ctx, md_info, 0);
+ if (rc != 0) {
+ goto error;
+ }
+
+ rc = mbedtls_md_starts(&ctx->ctx);
+ if (rc != 0) {
+ goto error;
+ }
+
+ return ctx;
+
+error:
+ SAFE_FREE(ctx);
+ return NULL;
+}
+
+void ssh_mac_update(ssh_mac_ctx ctx, const void *data, unsigned long len)
+{
+ mbedtls_md_update(&ctx->ctx, data, len);
+}
+
+void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx)
+{
+ mbedtls_md_finish(&ctx->ctx, md);
+ mbedtls_md_free(&ctx->ctx);
+ SAFE_FREE(ctx);
+}
+
+HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type)
+{
+ HMACCTX ctx = NULL;
+ const mbedtls_md_info_t *md_info;
+ int rc;
+
+ ctx = malloc(sizeof(mbedtls_md_context_t));
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ switch (type) {
+ case SSH_HMAC_SHA1:
+ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
+ break;
+ case SSH_HMAC_SHA256:
+ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+ break;
+ case SSH_HMAC_SHA384:
+ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
+ break;
+ case SSH_HMAC_SHA512:
+ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
+ break;
+ default:
+ goto error;
+ }
+
+ mbedtls_md_init(ctx);
+
+ if (md_info == NULL) {
+ goto error;
+ }
+
+ rc = mbedtls_md_setup(ctx, md_info, 1);
+ if (rc != 0) {
+ goto error;
+ }
+
+ rc = mbedtls_md_hmac_starts(ctx, key, len);
+ if (rc != 0) {
+ goto error;
+ }
+
+ return ctx;
+
+error:
+ mbedtls_md_free(ctx);
+ SAFE_FREE(ctx);
+ return NULL;
+}
+
+void hmac_update(HMACCTX c, const void *data, unsigned long len)
+{
+ mbedtls_md_hmac_update(c, data, len);
+}
+
+void hmac_final(HMACCTX c, unsigned char *hashmacbuf, unsigned int *len)
+{
+ *len = mbedtls_md_get_size(c->md_info);
+ mbedtls_md_hmac_finish(c, hashmacbuf);
+ mbedtls_md_free(c);
+ SAFE_FREE(c);
+}
+
+static int cipher_set_encrypt_key(struct ssh_cipher_struct *cipher, void *key,
+ void *IV)
+{
+
+ const mbedtls_cipher_info_t *cipher_info;
+ int rc;
+
+ mbedtls_cipher_init(&cipher->encrypt_ctx);
+ cipher_info = mbedtls_cipher_info_from_type(cipher->type);
+
+ rc = mbedtls_cipher_setup(&cipher->encrypt_ctx, cipher_info);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setup failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_setkey(&cipher->encrypt_ctx, key,
+ cipher_info->key_bitlen,
+ MBEDTLS_ENCRYPT);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_set_iv(&cipher->encrypt_ctx, IV, cipher_info->iv_size);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_reset(&cipher->encrypt_ctx);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed");
+ goto error;
+ }
+
+ return SSH_OK;
+error:
+ mbedtls_cipher_free(&cipher->encrypt_ctx);
+ return SSH_ERROR;
+}
+
+static int cipher_set_encrypt_key_cbc(struct ssh_cipher_struct *cipher, void *key,
+ void *IV)
+{
+
+ const mbedtls_cipher_info_t *cipher_info;
+ int rc;
+
+ mbedtls_cipher_init(&cipher->encrypt_ctx);
+ cipher_info = mbedtls_cipher_info_from_type(cipher->type);
+
+ rc = mbedtls_cipher_setup(&cipher->encrypt_ctx, cipher_info);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setup failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_setkey(&cipher->encrypt_ctx, key,
+ cipher_info->key_bitlen,
+ MBEDTLS_ENCRYPT);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_set_iv(&cipher->encrypt_ctx, IV, cipher_info->iv_size);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed");
+ goto error;
+ }
+
+ /* libssh only encypts and decrypts packets that are multiples of a block
+ * size, and no padding is used */
+ rc = mbedtls_cipher_set_padding_mode(&cipher->encrypt_ctx,
+ MBEDTLS_PADDING_NONE);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_padding_mode failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_reset(&cipher->encrypt_ctx);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed");
+ goto error;
+ }
+
+ return SSH_OK;
+error:
+ mbedtls_cipher_free(&cipher->encrypt_ctx);
+ return SSH_ERROR;
+}
+
+static int cipher_set_decrypt_key(struct ssh_cipher_struct *cipher, void *key,
+ void *IV)
+{
+ const mbedtls_cipher_info_t *cipher_info;
+ int rc;
+
+ mbedtls_cipher_init(&cipher->decrypt_ctx);
+ cipher_info = mbedtls_cipher_info_from_type(cipher->type);
+
+ rc = mbedtls_cipher_setup(&cipher->decrypt_ctx, cipher_info);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_setkey(&cipher->decrypt_ctx, key,
+ cipher_info->key_bitlen,
+ MBEDTLS_DECRYPT);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_set_iv(&cipher->decrypt_ctx, IV, cipher_info->iv_size);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed");
+ goto error;
+ }
+
+ mbedtls_cipher_reset(&cipher->decrypt_ctx);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed");
+ goto error;
+ }
+
+ return SSH_OK;
+error:
+ mbedtls_cipher_free(&cipher->decrypt_ctx);
+ return SSH_ERROR;
+}
+
+static int cipher_set_decrypt_key_cbc(struct ssh_cipher_struct *cipher, void *key,
+ void *IV)
+{
+ const mbedtls_cipher_info_t *cipher_info;
+ int rc;
+
+ mbedtls_cipher_init(&cipher->decrypt_ctx);
+ cipher_info = mbedtls_cipher_info_from_type(cipher->type);
+
+ rc = mbedtls_cipher_setup(&cipher->decrypt_ctx, cipher_info);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_setkey(&cipher->decrypt_ctx, key,
+ cipher_info->key_bitlen,
+ MBEDTLS_DECRYPT);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_set_iv(&cipher->decrypt_ctx, IV, cipher_info->iv_size);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_set_padding_mode(&cipher->decrypt_ctx,
+ MBEDTLS_PADDING_NONE);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_padding_mode failed");
+ goto error;
+ }
+
+ mbedtls_cipher_reset(&cipher->decrypt_ctx);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed");
+ goto error;
+ }
+
+ return SSH_OK;
+error:
+ mbedtls_cipher_free(&cipher->decrypt_ctx);
+ return SSH_ERROR;
+}
+
+static void cipher_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
+ unsigned long len)
+{
+ size_t outlen = 0;
+ size_t total_len = 0;
+ int rc = 0;
+ rc = mbedtls_cipher_update(&cipher->encrypt_ctx, in, len, out, &outlen);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during encryption");
+ return;
+ }
+
+ total_len += outlen;
+
+ if (total_len == len) {
+ return;
+ }
+
+ rc = mbedtls_cipher_finish(&cipher->encrypt_ctx, (unsigned char *) out + outlen,
+ &outlen);
+
+ total_len += outlen;
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_finish failed during encryption");
+ return;
+ }
+
+ if (total_len != len) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu",
+ outlen, len);
+ return;
+ }
+
+}
+
+static void cipher_encrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out,
+ unsigned long len)
+{
+ size_t outlen = 0;
+ int rc = 0;
+ rc = mbedtls_cipher_update(&cipher->encrypt_ctx, in, len, out, &outlen);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during encryption");
+ return;
+ }
+
+ if (outlen != len) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu",
+ outlen, len);
+ return;
+ }
+
+}
+
+static void cipher_decrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
+ unsigned long len)
+{
+ size_t outlen = 0;
+ int rc = 0;
+ size_t total_len = 0;
+
+ rc = mbedtls_cipher_update(&cipher->decrypt_ctx, in, len, out, &outlen);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during decryption");
+ return;
+ }
+
+ total_len += outlen;
+
+ if (total_len == len) {
+ return;
+ }
+
+ rc = mbedtls_cipher_finish(&cipher->decrypt_ctx, (unsigned char *) out +
+ outlen, &outlen);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed during decryption");
+ return;
+ }
+
+ total_len += outlen;
+
+ if (total_len != len) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu",
+ outlen, len);
+ return;
+ }
+
+}
+
+static void cipher_decrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out,
+ unsigned long len)
+{
+ size_t outlen = 0;
+ int rc = 0;
+ rc = mbedtls_cipher_update(&cipher->decrypt_ctx, in, len, out, &outlen);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during decryption");
+ return;
+ }
+
+ /* MbedTLS caches the last block when decrypting with cbc.
+ * By calling finish the block is flushed to out, however the unprocessed
+ * data counter is not reset.
+ * Calling mbedtls_cipher_reset resets the unprocessed data counter.
+ */
+ if (outlen == 0) {
+ rc = mbedtls_cipher_finish(&cipher->decrypt_ctx, out, &outlen);
+ } else if (outlen == len) {
+ return;
+ } else {
+ rc = mbedtls_cipher_finish(&cipher->decrypt_ctx, (unsigned char *) out +
+ outlen , &outlen);
+ }
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_finish failed during decryption");
+ return;
+ }
+
+ rc = mbedtls_cipher_reset(&cipher->decrypt_ctx);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed during decryption");
+ return;
+ }
+
+ if (outlen != len) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu",
+ outlen, len);
+ return;
+ }
+
+}
+
+static void cipher_cleanup(struct ssh_cipher_struct *cipher)
+{
+ mbedtls_cipher_free(&cipher->encrypt_ctx);
+ mbedtls_cipher_free(&cipher->decrypt_ctx);
+}
+
+static int des3_set_encrypt_key(struct ssh_cipher_struct *cipher, void *key,
+ void *IV)
+{
+ const mbedtls_cipher_info_t *cipher_info;
+ unsigned char *des3_key = NULL;
+ size_t des_key_size = 0;
+ int rc;
+
+ mbedtls_cipher_init(&cipher->encrypt_ctx);
+ cipher_info = mbedtls_cipher_info_from_type(cipher->type);
+
+ rc = mbedtls_cipher_setup(&cipher->encrypt_ctx, cipher_info);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setup failed");
+ goto error;
+ }
+
+ des3_key = malloc(cipher_info->key_bitlen / 8);
+ if (des3_key == NULL) {
+ SSH_LOG(SSH_LOG_WARNING, "error allocating memory for key");
+ goto error;
+ }
+
+ des_key_size = cipher_info->key_bitlen / (8 * 3);
+ memcpy(des3_key, key, des_key_size);
+ memcpy(des3_key + des_key_size, (unsigned char * )key + des_key_size,
+ des_key_size);
+ memcpy(des3_key + 2 * des_key_size,
+ (unsigned char *) key + 2 * des_key_size, des_key_size);
+
+ rc = mbedtls_cipher_setkey(&cipher->encrypt_ctx, des3_key,
+ cipher_info->key_bitlen,
+ MBEDTLS_ENCRYPT);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_set_iv(&cipher->encrypt_ctx, IV, cipher_info->iv_size);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_reset(&cipher->encrypt_ctx);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed");
+ goto error;
+ }
+
+ SAFE_FREE(des3_key);
+ return SSH_OK;
+error:
+ mbedtls_cipher_free(&cipher->encrypt_ctx);
+ if (des3_key != NULL) {
+ SAFE_FREE(des3_key);
+ }
+ return SSH_ERROR;
+}
+
+static int des3_set_decrypt_key(struct ssh_cipher_struct *cipher, void *key,
+ void *IV)
+{
+ const mbedtls_cipher_info_t *cipher_info;
+ unsigned char *des3_key = NULL;
+ size_t des_key_size = 0;
+ int rc;
+
+ mbedtls_cipher_init(&cipher->decrypt_ctx);
+ cipher_info = mbedtls_cipher_info_from_type(cipher->type);
+
+ rc = mbedtls_cipher_setup(&cipher->decrypt_ctx, cipher_info);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setup failed");
+ goto error;
+ }
+
+ des3_key = malloc(cipher_info->key_bitlen / 8);
+ if (des3_key == NULL) {
+ SSH_LOG(SSH_LOG_WARNING, "error allocating memory for key");
+ goto error;
+ }
+
+ des_key_size = cipher_info->key_bitlen / (8 * 3);
+ memcpy(des3_key, key, des_key_size);
+ memcpy(des3_key + des_key_size, (unsigned char *) key + des_key_size,
+ des_key_size);
+ memcpy(des3_key + 2 * des_key_size,
+ (unsigned char *) key + 2 * des_key_size,
+ des_key_size);
+
+ rc = mbedtls_cipher_setkey(&cipher->decrypt_ctx, des3_key,
+ cipher_info->key_bitlen,
+ MBEDTLS_DECRYPT);
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_set_iv(&cipher->decrypt_ctx, IV, cipher_info->iv_size);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed");
+ goto error;
+ }
+
+ rc = mbedtls_cipher_reset(&cipher->decrypt_ctx);
+
+ if (rc != 0) {
+ SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed");
+ goto error;
+ }
+
+ SAFE_FREE(des3_key);
+ return SSH_OK;
+error:
+ mbedtls_cipher_free(&cipher->decrypt_ctx);
+ if (des3_key != NULL) {
+ SAFE_FREE(des3_key);
+ }
+ return SSH_ERROR;
+}
+
+static struct ssh_cipher_struct ssh_ciphertab[] = {
+ {
+ .name = "blowfish-cbc",
+ .blocksize = 8,
+ .keysize = 128,
+ .type = MBEDTLS_CIPHER_BLOWFISH_CBC,
+ .set_encrypt_key = cipher_set_encrypt_key_cbc,
+ .set_decrypt_key = cipher_set_decrypt_key_cbc,
+ .encrypt = cipher_encrypt_cbc,
+ .decrypt = cipher_decrypt_cbc,
+ .cleanup = cipher_cleanup
+ },
+ {
+ .name = "aes128-ctr",
+ .blocksize = 16,
+ .keysize = 128,
+ .type = MBEDTLS_CIPHER_AES_128_CTR,
+ .set_encrypt_key = cipher_set_encrypt_key,
+ .set_decrypt_key = cipher_set_decrypt_key,
+ .encrypt = cipher_encrypt,
+ .decrypt = cipher_decrypt,
+ .cleanup = cipher_cleanup
+ },
+ {
+ .name = "aes192-ctr",
+ .blocksize = 16,
+ .keysize = 192,
+ .type = MBEDTLS_CIPHER_AES_192_CTR,
+ .set_encrypt_key = cipher_set_encrypt_key,
+ .set_decrypt_key = cipher_set_decrypt_key,
+ .encrypt = cipher_encrypt,
+ .decrypt = cipher_decrypt,
+ .cleanup = cipher_cleanup
+ },
+ {
+ .name = "aes256-ctr",
+ .blocksize = 16,
+ .keysize = 256,
+ .type = MBEDTLS_CIPHER_AES_256_CTR,
+ .set_encrypt_key = cipher_set_encrypt_key,
+ .set_decrypt_key = cipher_set_decrypt_key,
+ .encrypt = cipher_encrypt,
+ .decrypt = cipher_decrypt,
+ .cleanup = cipher_cleanup
+ },
+ {
+ .name = "aes128-cbc",
+ .blocksize = 16,
+ .keysize = 128,
+ .type = MBEDTLS_CIPHER_AES_128_CBC,
+ .set_encrypt_key = cipher_set_encrypt_key_cbc,
+ .set_decrypt_key = cipher_set_decrypt_key_cbc,
+ .encrypt = cipher_encrypt_cbc,
+ .decrypt = cipher_decrypt_cbc,
+ .cleanup = cipher_cleanup
+ },
+ {
+ .name = "aes192-cbc",
+ .blocksize = 16,
+ .keysize = 192,
+ .type = MBEDTLS_CIPHER_AES_192_CBC,
+ .set_encrypt_key = cipher_set_encrypt_key_cbc,
+ .set_decrypt_key = cipher_set_decrypt_key_cbc,
+ .encrypt = cipher_encrypt_cbc,
+ .decrypt = cipher_decrypt_cbc,
+ .cleanup = cipher_cleanup
+ },
+ {
+ .name = "aes256-cbc",
+ .blocksize = 16,
+ .keysize = 256,
+ .type = MBEDTLS_CIPHER_AES_256_CBC,
+ .set_encrypt_key = cipher_set_encrypt_key_cbc,
+ .set_decrypt_key = cipher_set_decrypt_key_cbc,
+ .encrypt = cipher_encrypt_cbc,
+ .decrypt = cipher_decrypt_cbc,
+ .cleanup = cipher_cleanup
+ },
+ {
+ .name = "3des-cbc",
+ .blocksize = 8,
+ .keysize = 192,
+ .type = MBEDTLS_CIPHER_DES_EDE3_CBC,
+ .set_encrypt_key = cipher_set_encrypt_key_cbc,
+ .set_decrypt_key = cipher_set_decrypt_key_cbc,
+ .encrypt = cipher_encrypt_cbc,
+ .decrypt = cipher_decrypt_cbc,
+ .cleanup = cipher_cleanup
+ },
+ {
+ .name = "3des-cbc-ssh1",
+ .blocksize = 8,
+ .keysize = 192,
+ .type = MBEDTLS_CIPHER_DES_CBC,
+ .set_encrypt_key = des3_set_encrypt_key,
+ .set_decrypt_key = des3_set_decrypt_key,
+ .encrypt = cipher_encrypt_cbc,
+ .decrypt = cipher_decrypt_cbc,
+ .cleanup = cipher_cleanup
+ },
+ {
+ .name = "des-cbc-ssh1",
+ .blocksize = 8,
+ .keysize = 64,
+ .type = MBEDTLS_CIPHER_DES_CBC,
+ .set_encrypt_key = cipher_set_encrypt_key_cbc,
+ .set_decrypt_key = cipher_set_decrypt_key_cbc,
+ .encrypt = cipher_encrypt_cbc,
+ .decrypt = cipher_decrypt_cbc,
+ },
+ {
+ .name = NULL,
+ .blocksize = 0,
+ .keysize = 0,
+ .set_encrypt_key = NULL,
+ .set_decrypt_key = NULL,
+ .encrypt = NULL,
+ .decrypt = NULL,
+ .cleanup = NULL
+ }
+};
+
+struct ssh_cipher_struct *ssh_get_ciphertab(void)
+{
+ return ssh_ciphertab;
+}
+
+void ssh_mbedtls_init(void)
+{
+ int rc;
+
+ mbedtls_entropy_init(&ssh_mbedtls_entropy);
+ mbedtls_ctr_drbg_init(&ssh_mbedtls_ctr_drbg);
+
+ rc = mbedtls_ctr_drbg_seed(&ssh_mbedtls_ctr_drbg, mbedtls_entropy_func,
+ &ssh_mbedtls_entropy, NULL, 0);
+ if (rc != 0) {
+ mbedtls_ctr_drbg_free(&ssh_mbedtls_ctr_drbg);
+ }
+}
+
+int ssh_mbedtls_random(void *where, int len, int strong)
+{
+ int rc = 0;
+ if (strong) {
+ mbedtls_ctr_drbg_set_prediction_resistance(&ssh_mbedtls_ctr_drbg,
+ MBEDTLS_CTR_DRBG_PR_ON);
+ rc = mbedtls_ctr_drbg_random(&ssh_mbedtls_ctr_drbg, where, len);
+ mbedtls_ctr_drbg_set_prediction_resistance(&ssh_mbedtls_ctr_drbg,
+ MBEDTLS_CTR_DRBG_PR_OFF);
+ } else {
+ rc = mbedtls_ctr_drbg_random(&ssh_mbedtls_ctr_drbg, where, len);
+ }
+
+ return !rc;
+}
+
+void ssh_mbedtls_cleanup(void)
+{
+ mbedtls_ctr_drbg_free(&ssh_mbedtls_ctr_drbg);
+ mbedtls_entropy_free(&ssh_mbedtls_entropy);
+}
+
+#endif /* HAVE_LIBMBEDCRYPTO */
diff --git a/src/mbedcrypto_missing.c b/src/mbedcrypto_missing.c
new file mode 100644
index 00000000..ceb404b2
--- /dev/null
+++ b/src/mbedcrypto_missing.c
@@ -0,0 +1,126 @@
+/*
+ * This file is part of the SSH Library
+ *
+ * Copyright (c) 2017 Sartura d.o.o.
+ *
+ * Author: Juraj Vijtiuk <juraj.vijtiuk@xxxxxxxxxx>
+ *
+ * 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 "libssh/priv.h"
+#include "libssh/libmbedcrypto.h"
+
+#ifdef HAVE_LIBMBEDCRYPTO
+bignum ssh_mbedcry_bn_new(void)
+{
+ bignum bn;
+
+ bn = malloc(sizeof(mbedtls_mpi));
+ if (bn) {
+ mbedtls_mpi_init(bn);
+ }
+
+ return bn;
+}
+
+void ssh_mbedcry_bn_free(bignum bn)
+{
+ mbedtls_mpi_free(bn);
+ SAFE_FREE(bn);
+}
+
+char *ssh_mbedcry_bn2num(bignum num, int radix)
+{
+ char *buf = NULL;
+ size_t olen;
+ int rc;
+
+ rc = mbedtls_mpi_write_string(num, radix, buf, 0, &olen);
+ if (rc != 0) {
+ return NULL;
+ }
+
+ buf = malloc(olen);
+ if (!buf) {
+ return NULL;
+ }
+
+ rc = mbedtls_mpi_write_string(num, radix, buf, olen, &olen);
+ if (rc != 0) {
+ SAFE_FREE(buf);
+ return NULL;
+ }
+
+ return buf;
+}
+
+int ssh_mbedcry_rand(bignum rnd, int bits, int top, int bottom)
+{
+ size_t len;
+ int rc;
+ int i;
+
+ if (bits <= 0) {
+ return 0;
+ }
+
+ len = bits / 8 + 1;
+ rc = mbedtls_mpi_fill_random(rnd, len, mbedtls_ctr_drbg_random,
+ &ssh_mbedtls_ctr_drbg);
+ if (rc != 0) {
+ return 0;
+ }
+
+ for (i = len * 8 - 1; i >= bits; i--) {
+ rc = mbedtls_mpi_set_bit(rnd, i, 0);
+ if (rc != 0) {
+ return 0;
+ }
+ }
+
+ if (top == 0) {
+ rc = mbedtls_mpi_set_bit(rnd, bits - 1, 0);
+ }
+
+ if (top == 1) {
+ if (bits < 2) {
+ return 0;
+ }
+
+ rc = mbedtls_mpi_set_bit(rnd, bits - 2, 0);
+ if (rc != 0) {
+ return 0;
+ }
+ }
+
+ if (bottom) {
+ rc = mbedtls_mpi_set_bit(rnd, 0, 1);
+ if (rc != 0) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int ssh_mbedcry_is_bit_set(bignum num, size_t pos)
+{
+ int bit;
+ bit = mbedtls_mpi_get_bit(num, pos);
+ return bit;
+}
+#endif
diff --git a/src/misc.c b/src/misc.c
index 1e09a25d..ad560bda 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -35,6 +35,7 @@
#endif /* _WIN32 */
+#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
@@ -81,6 +82,12 @@
#define CRYPTO_STRING ""
#endif
+#ifdef HAVE_LIBMBEDCRYPTO
+#define MBED_STRING "/mbedtls"
+#else
+#define MBED_STRING ""
+#endif
+
#ifdef WITH_ZLIB
#define ZLIB_STRING "/zlib"
#else
@@ -348,7 +355,7 @@ char *ssh_hostport(const char *host, int port){
*/
const char *ssh_version(int req_version) {
if (req_version <= LIBSSH_VERSION_INT) {
- return SSH_STRINGIFY(LIBSSH_VERSION) GCRYPT_STRING CRYPTO_STRING
+ return SSH_STRINGIFY(LIBSSH_VERSION) GCRYPT_STRING CRYPTO_STRING MBED_STRING
ZLIB_STRING;
}
@@ -780,8 +787,7 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) {
/**
* @internal
*
- * @brief Analyze the SSH banner to find out if we have a SSHv1 or SSHv2
- * server.
+ * @brief Analyze the SSH banner to extract version information.
*
* @param session The session to analyze the banner from.
* @param server 0 means we are a client, 1 a server.
@@ -790,7 +796,7 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) {
*
* @return 0 on success, < 0 on error.
*
- * @see ssh_get_banner()
+ * @see ssh_get_issue_banner()
*/
int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2) {
const char *banner;
@@ -824,7 +830,7 @@ int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2) {
SSH_LOG(SSH_LOG_RARE, "Analyzing banner: %s", banner);
- switch(banner[4]) {
+ switch (banner[4]) {
case '1':
*ssh1 = 1;
if (strlen(banner) > 6) {
@@ -844,9 +850,12 @@ int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2) {
return -1;
}
+ /* Make a best-effort to extract OpenSSH version numbers. */
openssh = strstr(banner, "OpenSSH");
if (openssh != NULL) {
- unsigned int major, minor;
+ char *tmp = NULL;
+ unsigned long int major = 0UL;
+ unsigned long int minor = 0UL;
/*
* The banner is typical:
@@ -854,30 +863,33 @@ int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2) {
* 012345678901234567890
*/
if (strlen(openssh) > 9) {
- major = strtoul(openssh + 8, (char **) NULL, 10);
- if (major < 1 || major > 100) {
- ssh_set_error(session,
- SSH_FATAL,
- "Invalid major version number: %s",
- banner);
- return -1;
+ major = strtoul(openssh + 8, &tmp, 10);
+ if ((tmp == (openssh + 8)) ||
+ ((errno == ERANGE) && (major == ULONG_MAX)) ||
+ ((errno != 0) && (major == 0)) ||
+ ((major < 1) || (major > 100))) {
+ /* invalid major */
+ goto done;
}
- minor = strtoul(openssh + 10, (char **) NULL, 10);
- if (minor > 100) {
- ssh_set_error(session,
- SSH_FATAL,
- "Invalid minor version number: %s",
- banner);
- return -1;
+
+ minor = strtoul(openssh + 10, &tmp, 10);
+ if ((tmp == (openssh + 10)) ||
+ ((errno == ERANGE) && (major == ULONG_MAX)) ||
+ ((errno != 0) && (major == 0)) ||
+ (minor > 100)) {
+ /* invalid minor */
+ goto done;
}
- session->openssh = SSH_VERSION_INT(major, minor, 0);
+
+ session->openssh = SSH_VERSION_INT(((int) major), ((int) minor), 0);
+
SSH_LOG(SSH_LOG_RARE,
- "We are talking to an OpenSSH client version: %d.%d (%x)",
+ "We are talking to an OpenSSH client version: %lu.%lu (%x)",
major, minor, session->openssh);
}
}
-
+done:
return 0;
}
diff --git a/src/options.c b/src/options.c
index 68c11053..e73f7529 100644
--- a/src/options.c
+++ b/src/options.c
@@ -1031,7 +1031,9 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
int argc = *argcptr;
int debuglevel = 0;
int usersa = 0;
+#ifdef HAVE_DSA
int usedss = 0;
+#endif
int compress = 0;
int cont = 1;
int current = 0;
@@ -1063,9 +1065,11 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
case 'r':
usersa++;
break;
+#ifdef HAVE_DSA
case 'd':
usedss++;
break;
+#endif
case 'c':
cipher = optarg;
break;
@@ -1128,7 +1132,11 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
optind++;
}
- if (usersa && usedss) {
+ if (usersa
+#ifdef HAVE_DSA
+ && usedss
+#endif
+ ) {
ssh_set_error(session, SSH_FATAL, "Either RSA or DSS must be chosen");
cont = 0;
}
@@ -1426,10 +1434,12 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
}
key_type = ssh_key_type(key);
switch (key_type) {
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS:
bind_key_loc = &sshbind->dsa;
bind_key_path_loc = &sshbind->dsakey;
break;
+#endif
case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_ECC
bind_key_loc = &sshbind->ecdsa;
@@ -1483,9 +1493,11 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
key_type = ssh_key_type(key);
switch (key_type) {
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS:
bind_key_loc = &sshbind->dsa;
break;
+#endif
case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_ECC
bind_key_loc = &sshbind->ecdsa;
@@ -1581,12 +1593,14 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
ssh_set_log_level(i & 0xffff);
}
break;
+#ifdef HAVE_DSA
case SSH_BIND_OPTIONS_DSAKEY:
rc = ssh_bind_set_key(sshbind, &sshbind->dsakey, value);
if (rc < 0) {
return -1;
}
break;
+#endif
case SSH_BIND_OPTIONS_RSAKEY:
rc = ssh_bind_set_key(sshbind, &sshbind->rsakey, value);
if (rc < 0) {
diff --git a/src/pki.c b/src/pki.c
index 91f972b1..94720d98 100644
--- a/src/pki.c
+++ b/src/pki.c
@@ -65,9 +65,11 @@
#include "libssh/agent.h"
enum ssh_keytypes_e pki_privatekey_type_from_string(const char *privkey) {
+#ifdef HAVE_DSA
if (strncmp(privkey, DSA_HEADER_BEGIN, strlen(DSA_HEADER_BEGIN)) == 0) {
return SSH_KEYTYPE_DSS;
}
+#endif
if (strncmp(privkey, RSA_HEADER_BEGIN, strlen(RSA_HEADER_BEGIN)) == 0) {
return SSH_KEYTYPE_RSA;
@@ -138,6 +140,16 @@ void ssh_key_clean (ssh_key key){
#ifdef HAVE_OPENSSL_ECC
if(key->ecdsa) EC_KEY_free(key->ecdsa);
#endif /* HAVE_OPENSSL_ECC */
+#elif defined HAVE_LIBMBEDCRYPTO
+ if (key->rsa != NULL) {
+ mbedtls_pk_free(key->rsa);
+ SAFE_FREE(key->rsa);
+ }
+
+ if (key->ecdsa != NULL) {
+ mbedtls_ecdsa_free(key->ecdsa);
+ SAFE_FREE(key->ecdsa);
+ }
#endif
if (key->ed25519_privkey != NULL){
BURN_BUFFER(key->ed25519_privkey, sizeof(ed25519_privkey));
@@ -152,7 +164,9 @@ void ssh_key_clean (ssh_key key){
key->type=SSH_KEYTYPE_UNKNOWN;
key->ecdsa_nid = 0;
key->type_c=NULL;
+#ifdef HAVE_DSA
key->dsa = NULL;
+#endif
key->rsa = NULL;
key->ecdsa = NULL;
}
@@ -190,8 +204,10 @@ enum ssh_keytypes_e ssh_key_type(const ssh_key key){
*/
const char *ssh_key_type_to_char(enum ssh_keytypes_e type) {
switch (type) {
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS:
return "ssh-dss";
+#endif
case SSH_KEYTYPE_RSA:
return "ssh-rsa";
case SSH_KEYTYPE_RSA1:
@@ -200,8 +216,10 @@ const char *ssh_key_type_to_char(enum ssh_keytypes_e type) {
return "ssh-ecdsa";
case SSH_KEYTYPE_ED25519:
return "ssh-ed25519";
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS_CERT01:
return "ssh-dss-cert-v01@xxxxxxxxxxx";
+#endif
case SSH_KEYTYPE_RSA_CERT01:
return "ssh-rsa-cert-v01@xxxxxxxxxxx";
case SSH_KEYTYPE_UNKNOWN:
@@ -228,14 +246,18 @@ enum ssh_keytypes_e ssh_key_type_from_name(const char *name) {
return SSH_KEYTYPE_RSA1;
} else if (strcmp(name, "rsa") == 0) {
return SSH_KEYTYPE_RSA;
+#ifdef HAVE_DSA
} else if (strcmp(name, "dsa") == 0) {
return SSH_KEYTYPE_DSS;
+#endif
} else if (strcmp(name, "ssh-rsa1") == 0) {
return SSH_KEYTYPE_RSA1;
} else if (strcmp(name, "ssh-rsa") == 0) {
return SSH_KEYTYPE_RSA;
+#ifdef HAVE_DSA
} else if (strcmp(name, "ssh-dss") == 0) {
return SSH_KEYTYPE_DSS;
+#endif
} else if (strcmp(name, "ssh-ecdsa") == 0
|| strcmp(name, "ecdsa") == 0
|| strcmp(name, "ecdsa-sha2-nistp256") == 0
@@ -244,8 +266,10 @@ enum ssh_keytypes_e ssh_key_type_from_name(const char *name) {
return SSH_KEYTYPE_ECDSA;
} else if (strcmp(name, "ssh-ed25519") == 0){
return SSH_KEYTYPE_ED25519;
+#ifdef HAVE_DSA
} else if (strcmp(name, "ssh-dss-cert-v01@xxxxxxxxxxx") == 0) {
return SSH_KEYTYPE_DSS_CERT01;
+#endif
} else if (strcmp(name, "ssh-rsa-cert-v01@xxxxxxxxxxx") == 0) {
return SSH_KEYTYPE_RSA_CERT01;
}
@@ -341,6 +365,7 @@ void ssh_signature_free(ssh_signature sig)
}
switch(sig->type) {
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS:
#ifdef HAVE_LIBGCRYPT
gcry_sexp_release(sig->dsa_sig);
@@ -348,12 +373,15 @@ void ssh_signature_free(ssh_signature sig)
DSA_SIG_free(sig->dsa_sig);
#endif
break;
+#endif
case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1:
#ifdef HAVE_LIBGCRYPT
gcry_sexp_release(sig->rsa_sig);
#elif defined HAVE_LIBCRYPTO
SAFE_FREE(sig->rsa_sig);
+#elif defined HAVE_LIBMBEDCRYPTO
+ SAFE_FREE(sig->rsa_sig);
#endif
break;
case SSH_KEYTYPE_ECDSA:
@@ -361,12 +389,17 @@ void ssh_signature_free(ssh_signature sig)
gcry_sexp_release(sig->ecdsa_sig);
#elif defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_ECC)
ECDSA_SIG_free(sig->ecdsa_sig);
+#elif defined HAVE_LIBMBEDCRYPTO
+ bignum_free(sig->ecdsa_sig.r);
+ bignum_free(sig->ecdsa_sig.s);
#endif
break;
case SSH_KEYTYPE_ED25519:
SAFE_FREE(sig->ed25519_sig);
break;
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS_CERT01:
+#endif
case SSH_KEYTYPE_RSA_CERT01:
case SSH_KEYTYPE_UNKNOWN:
break;
@@ -624,8 +657,10 @@ ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key) {
pub->type = tmp->type;
pub->type_c = tmp->type_c;
+#ifdef HAVE_DSA
pub->dsa_pub = tmp->dsa;
tmp->dsa = NULL;
+#endif
pub->rsa_pub = tmp->rsa;
tmp->rsa = NULL;
@@ -644,7 +679,9 @@ ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key) {
}
privkey->type = key->type;
+#ifdef HAVE_DSA
privkey->dsa_priv = key->dsa;
+#endif
privkey->rsa_priv = key->rsa;
return privkey;
@@ -666,6 +703,7 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
key->flags = SSH_KEY_FLAG_PUBLIC;
switch (type) {
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS:
{
ssh_string p;
@@ -724,6 +762,7 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
}
}
break;
+#endif
case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1:
{
@@ -813,8 +852,10 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
ssh_string_free(pubkey);
}
break;
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS_CERT01:
case SSH_KEYTYPE_RSA_CERT01:
+#endif
case SSH_KEYTYPE_UNKNOWN:
default:
SSH_LOG(SSH_LOG_WARN, "Unknown public key protocol %d", type);
@@ -918,8 +959,11 @@ int ssh_pki_import_pubkey_base64(const char *b64_key,
}
ssh_string_free(type_s);
- if (type == SSH_KEYTYPE_RSA_CERT01 ||
- type == SSH_KEYTYPE_DSS_CERT01) {
+ if (type == SSH_KEYTYPE_RSA_CERT01
+#ifdef HAVE_DSA
+ || type == SSH_KEYTYPE_DSS_CERT01
+#endif
+ ) {
rc = pki_import_cert_buffer(buffer, type, pkey);
} else {
rc = pki_import_pubkey_buffer(buffer, type, pkey);
@@ -981,8 +1025,11 @@ int ssh_pki_import_pubkey_blob(const ssh_string key_blob,
}
ssh_string_free(type_s);
- if (type == SSH_KEYTYPE_RSA_CERT01 ||
- type == SSH_KEYTYPE_DSS_CERT01) {
+ if (type == SSH_KEYTYPE_RSA_CERT01
+#ifdef HAVE_DSA
+ || type == SSH_KEYTYPE_DSS_CERT01
+#endif
+ ) {
rc = pki_import_cert_buffer(buffer, type, pkey);
} else {
rc = pki_import_pubkey_buffer(buffer, type, pkey);
@@ -1181,11 +1228,13 @@ int ssh_pki_generate(enum ssh_keytypes_e type, int parameter,
if(rc == SSH_ERROR)
goto error;
break;
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS:
rc = pki_key_generate_dss(key, parameter);
if(rc == SSH_ERROR)
goto error;
break;
+#endif
case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_ECC
rc = pki_key_generate_ecdsa(key, parameter);
@@ -1203,7 +1252,9 @@ int ssh_pki_generate(enum ssh_keytypes_e type, int parameter,
goto error;
}
break;
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS_CERT01:
+#endif
case SSH_KEYTYPE_RSA_CERT01:
case SSH_KEYTYPE_UNKNOWN:
goto error;
@@ -1581,9 +1632,13 @@ int ssh_pki_signature_verify_blob(ssh_session session,
sha1(digest, dlen, hash);
#ifdef DEBUG_CRYPTO
- ssh_print_hexa(key->type == SSH_KEYTYPE_DSS
+ ssh_print_hexa(
+#ifdef HAVE_DSA
+ key->type == SSH_KEYTYPE_DSS
? "Hash to be verified with DSA"
- : "Hash to be verified with RSA",
+ :
+#endif
+ "Hash to be verified with RSA",
hash,
SHA_DIGEST_LEN);
#endif
diff --git a/src/pki_container_openssh.c b/src/pki_container_openssh.c
index 551a7f03..33b309c2 100644
--- a/src/pki_container_openssh.c
+++ b/src/pki_container_openssh.c
@@ -113,9 +113,11 @@ static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer,
SAFE_FREE(privkey);
SAFE_FREE(pubkey);
break;
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS_CERT01:
case SSH_KEYTYPE_DSS:
/* p,q,g,pub_key,priv_key */
+#endif
case SSH_KEYTYPE_RSA_CERT01:
case SSH_KEYTYPE_RSA:
/* n,e,d,iqmp,p,q */
diff --git a/src/pki_crypto.c b/src/pki_crypto.c
index 70ac6854..40407d65 100644
--- a/src/pki_crypto.c
+++ b/src/pki_crypto.c
@@ -982,6 +982,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
}
switch (key->type) {
+#ifndef HAVE_LIBMBEDCRYPTO
case SSH_KEYTYPE_DSS: {
const BIGNUM *bp, *bq, *bg, *bpub_key;
DSA_get0_pqg(key->dsa, &bp, &bq, &bg);
@@ -1034,6 +1035,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
break;
}
+#endif
case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1: {
const BIGNUM *be, *bn;
diff --git a/src/pki_mbedcrypto.c b/src/pki_mbedcrypto.c
new file mode 100644
index 00000000..9ab34a4b
--- /dev/null
+++ b/src/pki_mbedcrypto.c
@@ -0,0 +1,1300 @@
+/*
+<<<<<<< HEAD
+ * This file is part of the SSH Library
+ *
+ * Copyright (c) 2017 Sartura d.o.o.
+ *
+ * Author: Juraj Vijtiuk <juraj.vijtiuk@xxxxxxxxxx>
+ *
+ * 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"
+
+#ifdef HAVE_LIBMBEDCRYPTO
+#include <mbedtls/pk.h>
+#include <mbedtls/error.h>
+
+#include "libssh/priv.h"
+#include "libssh/pki.h"
+#include "libssh/pki_priv.h"
+#include "libssh/buffer.h"
+#include "libssh/bignum.h"
+
+#define MAX_PASSPHRASE_SIZE 1024
+#define MAX_KEY_SIZE 32
+
+ssh_string pki_private_key_to_pem(const ssh_key key, const char *passphrase,
+ ssh_auth_callback auth_fn, void *auth_data)
+{
+ (void) key;
+ (void) passphrase;
+ (void) auth_fn;
+ (void) auth_data; return NULL;
+}
+
+static int pki_key_ecdsa_to_nid(mbedtls_ecdsa_context *ecdsa)
+{
+ mbedtls_ecp_group_id id;
+
+ id = ecdsa->grp.id;
+ if (id == MBEDTLS_ECP_DP_SECP256R1) {
+ return NID_mbedtls_nistp256;
+ } else if (id == MBEDTLS_ECP_DP_SECP384R1) {
+ return NID_mbedtls_nistp384;
+ } else if (id == MBEDTLS_ECP_DP_SECP521R1) {
+ return NID_mbedtls_nistp521;
+ }
+
+ return -1;
+}
+
+ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase,
+ ssh_auth_callback auth_fn, void *auth_data)
+{
+ ssh_key key = NULL;
+ mbedtls_pk_context *rsa = NULL;
+ mbedtls_pk_context *ecdsa = NULL;
+ ed25519_privkey *ed25519 = NULL;
+ enum ssh_keytypes_e type;
+ int valid;
+ /* mbedtls pk_parse_key expects strlen to count the 0 byte */
+ size_t b64len = strlen(b64_key) + 1;
+ unsigned char tmp[MAX_PASSPHRASE_SIZE] = {0};
+
+ if (ssh_init() < 0) {
+ return NULL;
+ }
+
+ type = pki_privatekey_type_from_string(b64_key);
+ if (type == SSH_KEYTYPE_UNKNOWN) {
+ SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key.");
+ return NULL;
+ }
+
+ switch (type) {
+ case SSH_KEYTYPE_RSA:
+ case SSH_KEYTYPE_RSA1:
+ rsa = malloc(sizeof(mbedtls_pk_context));
+ if (rsa == NULL) {
+ return NULL;
+ }
+
+ mbedtls_pk_init(rsa);
+
+ if (passphrase == NULL) {
+ if (auth_fn) {
+ valid = auth_fn("Passphrase for private key:", (char *) tmp,
+ MAX_PASSPHRASE_SIZE, 0, 0, auth_data);
+ if (valid < 0) {
+ return NULL;
+ }
+ /* TODO fix signedness and strlen */
+ valid = mbedtls_pk_parse_key(rsa,
+ (const unsigned char *) b64_key,
+ b64len, tmp,
+ strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE));
+ } else {
+ valid = mbedtls_pk_parse_key(rsa,
+ (const unsigned char *) b64_key,
+ b64len, NULL,
+ 0);
+ }
+ } else {
+ valid = mbedtls_pk_parse_key(rsa,
+ (const unsigned char *) b64_key, b64len,
+ (const unsigned char *) passphrase,
+ strnlen(passphrase, MAX_PASSPHRASE_SIZE));
+ }
+
+ if (valid != 0) {
+ char error_buf[100];
+ mbedtls_strerror(valid, error_buf, 100);
+ SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf);
+ goto fail;
+ }
+ break;
+ case SSH_KEYTYPE_ECDSA:
+ ecdsa = malloc(sizeof(mbedtls_pk_context));
+ if (ecdsa == NULL) {
+ return NULL;
+ }
+
+ mbedtls_pk_init(ecdsa);
+
+ if (passphrase == NULL) {
+ if (auth_fn) {
+ valid = auth_fn("Passphrase for private key:", (char *) tmp,
+ MAX_PASSPHRASE_SIZE, 0, 0, auth_data);
+ if (valid < 0) {
+ return NULL;
+ }
+ valid = mbedtls_pk_parse_key(ecdsa,
+ (const unsigned char *) b64_key,
+ b64len, tmp,
+ strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE));
+ } else {
+ valid = mbedtls_pk_parse_key(ecdsa,
+ (const unsigned char *) b64_key,
+ b64len, NULL,
+ 0);
+ }
+ } else {
+ valid = mbedtls_pk_parse_key(ecdsa,
+ (const unsigned char *) b64_key, b64len,
+ (const unsigned char *) passphrase,
+ strnlen(passphrase, MAX_PASSPHRASE_SIZE));
+ }
+
+ if (valid != 0) {
+ char error_buf[100];
+ mbedtls_strerror(valid, error_buf, 100);
+ SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf);
+ goto fail;
+ }
+ break;
+ case SSH_KEYTYPE_ED25519:
+ /* Cannot open ed25519 keys with libmbedcrypto */
+ default:
+ SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d",
+ type);
+ return NULL;
+ }
+
+ key = ssh_key_new();
+ if (key == NULL) {
+ goto fail;
+ }
+
+ key->type = type;
+ key->type_c = ssh_key_type_to_char(type);
+ key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
+ key->rsa = rsa;
+ if (ecdsa != NULL) {
+ mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*ecdsa);
+
+ key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
+ if (key->ecdsa == NULL) {
+ goto fail;
+ }
+
+ mbedtls_ecdsa_init(key->ecdsa);
+ mbedtls_ecdsa_from_keypair(key->ecdsa, keypair);
+ mbedtls_pk_free(ecdsa);
+ SAFE_FREE(ecdsa);
+ } else {
+ key->ecdsa = NULL;
+ }
+ key->ed25519_privkey = ed25519;
+ rsa = NULL;
+ ecdsa = NULL;
+ if (key->type == SSH_KEYTYPE_ECDSA) {
+ key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa);
+ key->type_c = pki_key_ecdsa_nid_to_name(key->ecdsa_nid);
+ }
+
+ return key;
+fail:
+ ssh_key_free(key);
+ if (rsa) {
+ mbedtls_pk_free(rsa);
+ SAFE_FREE(rsa);
+ }
+ if (ecdsa) {
+ mbedtls_pk_free(ecdsa);
+ SAFE_FREE(ecdsa);
+ }
+ return NULL;
+}
+
+int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n)
+{
+ mbedtls_rsa_context *rsa;
+ const mbedtls_pk_info_t *pk_info;
+ int rc;
+
+ key->rsa = malloc(sizeof(mbedtls_pk_context));
+ if (key->rsa == NULL) {
+ return SSH_ERROR;
+ }
+
+ mbedtls_pk_init(key->rsa);
+ pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
+ mbedtls_pk_setup(key->rsa, pk_info);
+
+ if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA)) {
+ rsa = mbedtls_pk_rsa(*key->rsa);
+ rc = mbedtls_mpi_read_binary(&rsa->N, ssh_string_data(n),
+ ssh_string_len(n));
+ if (rc != 0) {
+ return SSH_ERROR;
+ }
+ rc = mbedtls_mpi_read_binary(&rsa->E, ssh_string_data(e),
+ ssh_string_len(e));
+ if (rc != 0) {
+ return SSH_ERROR;
+ }
+
+ rsa->len = (mbedtls_mpi_bitlen(&rsa->N) + 7) >> 3;
+ } else {
+ return SSH_ERROR;
+ }
+
+ return SSH_OK;
+}
+
+ssh_key pki_key_dup(const ssh_key key, int demote)
+{
+ ssh_key new;
+ int rc;
+ const mbedtls_pk_info_t *pk_info;
+
+
+ new = ssh_key_new();
+ if (new == NULL) {
+ return NULL;
+ }
+
+ new->type = key->type;
+ new->type_c = key->type_c;
+ if (demote) {
+ new->flags = SSH_KEY_FLAG_PUBLIC;
+ } else {
+ new->flags = key->flags;
+ }
+
+
+ switch(key->type) {
+ case SSH_KEYTYPE_RSA:
+ case SSH_KEYTYPE_RSA1: {
+ mbedtls_rsa_context *rsa, *new_rsa;
+
+ new->rsa = malloc(sizeof(mbedtls_pk_context));
+ if (new->rsa == NULL) {
+ return NULL;
+ }
+
+ mbedtls_pk_init(new->rsa);
+ pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
+ mbedtls_pk_setup(new->rsa, pk_info);
+
+ if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA) &&
+ mbedtls_pk_can_do(new->rsa, MBEDTLS_PK_RSA)) {
+ rsa = mbedtls_pk_rsa(*key->rsa);
+ new_rsa = mbedtls_pk_rsa(*new->rsa);
+
+ rc = mbedtls_mpi_copy(&new_rsa->N, &rsa->N);
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_mpi_copy(&new_rsa->E, &rsa->E);
+ if (rc != 0) {
+ goto fail;
+ }
+ new_rsa->len = (mbedtls_mpi_bitlen(&new_rsa->N) + 7) >> 3;
+
+ if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) {
+ rc = mbedtls_mpi_copy(&new_rsa->D, &rsa->D);
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_mpi_copy(&new_rsa->P, &rsa->P);
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_mpi_copy(&new_rsa->Q, &rsa->Q);
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_mpi_copy(&new_rsa->DP, &rsa->DP);
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_mpi_copy(&new_rsa->DQ, &rsa->DQ);
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_mpi_copy(&new_rsa->QP, &rsa->QP);
+ if (rc != 0) {
+ goto fail;
+ }
+ }
+ } else {
+ goto fail;
+ }
+
+ break;
+ }
+ case SSH_KEYTYPE_ECDSA:
+ new->ecdsa_nid = key->ecdsa_nid;
+
+ new->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
+
+ if (new->ecdsa == NULL) {
+ return NULL;
+ }
+
+ mbedtls_ecdsa_init(new->ecdsa);
+
+ if (demote && ssh_key_is_private(key)) {
+ rc = mbedtls_ecp_copy(&new->ecdsa->Q, &key->ecdsa->Q);
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_ecp_group_copy(&new->ecdsa->grp, &key->ecdsa->grp);
+ if (rc != 0) {
+ goto fail;
+ }
+ } else {
+ mbedtls_ecdsa_from_keypair(new->ecdsa, key->ecdsa);
+ }
+
+ break;
+ case SSH_KEYTYPE_ED25519:
+ rc = pki_ed25519_key_dup(new, key);
+ if (rc != SSH_OK) {
+ goto fail;
+ }
+ break;
+ default:
+ ssh_key_free(new);
+ return NULL;
+ }
+
+ return new;
+fail:
+ ssh_key_free(new);
+ return NULL;
+}
+
+int pki_key_generate_rsa(ssh_key key, int parameter)
+{
+ int rc;
+ const mbedtls_pk_info_t *info;
+
+ key->rsa = malloc(sizeof(mbedtls_pk_context));
+ if (key->rsa == NULL) {
+ return SSH_ERROR;
+ }
+
+ mbedtls_pk_init(key->rsa);
+
+ info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
+ rc = mbedtls_pk_setup(key->rsa, info);
+ if (rc != 0) {
+ return SSH_ERROR;
+ }
+
+ if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA)) {
+ rc = mbedtls_rsa_gen_key(mbedtls_pk_rsa(*key->rsa), mbedtls_ctr_drbg_random,
+ &ssh_mbedtls_ctr_drbg, parameter, 65537);
+ if (rc != 0) {
+ mbedtls_pk_free(key->rsa);
+ return SSH_ERROR;
+ }
+ }
+
+ return SSH_OK;
+}
+
+int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what)
+{
+ switch (k1->type) {
+ case SSH_KEYTYPE_RSA:
+ case SSH_KEYTYPE_RSA1: {
+ mbedtls_rsa_context *rsa1, *rsa2;
+ if (mbedtls_pk_can_do(k1->rsa, MBEDTLS_PK_RSA) &&
+ mbedtls_pk_can_do(k2->rsa, MBEDTLS_PK_RSA)) {
+ if (mbedtls_pk_get_type(k1->rsa) != mbedtls_pk_get_type(k2->rsa) ||
+ mbedtls_pk_get_bitlen(k1->rsa) !=
+ mbedtls_pk_get_bitlen(k2->rsa)) {
+ return 1;
+ }
+
+ rsa1 = mbedtls_pk_rsa(*k1->rsa);
+ rsa2 = mbedtls_pk_rsa(*k2->rsa);
+ if (mbedtls_mpi_cmp_mpi(&rsa1->N, &rsa2->N) != 0) {
+ return 1;
+ }
+
+ if (mbedtls_mpi_cmp_mpi(&rsa1->E, &rsa2->E) != 0) {
+ return 1;
+ }
+
+ if (what == SSH_KEY_CMP_PRIVATE) {
+ if (mbedtls_mpi_cmp_mpi(&rsa1->P, &rsa2->P) != 0) {
+ return 1;
+ }
+
+ if (mbedtls_mpi_cmp_mpi(&rsa1->Q, &rsa2->Q) != 0) {
+ return 1;
+ }
+ }
+ }
+ break;
+ }
+ case SSH_KEYTYPE_ECDSA:
+ /* mbedTLS can't compare ecdsa keys */
+ return 1;
+ case SSH_KEYTYPE_ED25519:
+ /* ed25519 keys handled globally */
+ return 0;
+ default:
+ return 1;
+ }
+
+ return 0;
+}
+
+ssh_string make_ecpoint_string(const mbedtls_ecp_group *g, const
+ mbedtls_ecp_point *p)
+{
+ ssh_string s;
+ size_t len = 1;
+ int rc;
+
+ s = ssh_string_new(len);
+ if (s == NULL) {
+ return NULL;
+ }
+
+ /* mbedtls_ecp_point_write_binary has no way of signaling how big the
+ * destination buffer has to be. Therefore we increase the buffer length
+ * as long as the buffer is too small. */
+ rc = mbedtls_ecp_point_write_binary(g, p, MBEDTLS_ECP_PF_UNCOMPRESSED,
+ &len, ssh_string_data(s), ssh_string_len(s));
+ while (rc == MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) {
+ ssh_string_free(s);
+ len *= 2;
+
+ s = ssh_string_new(len);
+ if (s == NULL) {
+ return NULL;
+ }
+
+ rc = mbedtls_ecp_point_write_binary(g, p, MBEDTLS_ECP_PF_UNCOMPRESSED,
+ &len, ssh_string_data(s), ssh_string_len(s));
+ }
+
+ if (rc == MBEDTLS_ERR_ECP_BAD_INPUT_DATA) {
+ ssh_string_free(s);
+ return NULL;
+ }
+
+ ssh_string_free(s);
+ s = ssh_string_new(len);
+ if (s == NULL) {
+ return NULL;
+ }
+
+ rc = mbedtls_ecp_point_write_binary(g, p, MBEDTLS_ECP_PF_UNCOMPRESSED,
+ &len, ssh_string_data(s), ssh_string_len(s));
+
+ if (rc != 0) {
+ ssh_string_free(s);
+ return NULL;
+ }
+
+ if (len != ssh_string_len(s)) {
+ ssh_string_free(s);
+ return NULL;
+ }
+
+ return s;
+}
+
+static const char* pki_key_ecdsa_nid_to_char(int nid)
+{
+ switch (nid) {
+ case NID_mbedtls_nistp256:
+ return "nistp256";
+ case NID_mbedtls_nistp384:
+ return "nistp384";
+ case NID_mbedtls_nistp521:
+ return "nistp521";
+ default:
+ break;
+ }
+
+ return "unknown";
+}
+
+ssh_string pki_publickey_to_blob(const ssh_key key)
+{
+ ssh_buffer buffer;
+ ssh_string type_s;
+ ssh_string e = NULL;
+ ssh_string n = NULL;
+ ssh_string str = NULL;
+ int rc;
+
+ buffer = ssh_buffer_new();
+ if (buffer == NULL) {
+ return NULL;
+ }
+
+ if (key->cert != NULL) {
+ rc = ssh_buffer_add_buffer(buffer, key->cert);
+ if (rc < 0) {
+ ssh_buffer_free(buffer);
+ return NULL;
+ }
+
+ goto makestring;
+ }
+
+ type_s = ssh_string_from_char(key->type_c);
+ if (type_s == NULL) {
+ ssh_buffer_free(buffer);
+ return NULL;
+ }
+
+ rc = ssh_buffer_add_ssh_string(buffer, type_s);
+ ssh_string_free(type_s);
+ if (rc < 0) {
+ ssh_buffer_free(buffer);
+ return NULL;
+ }
+
+ switch (key->type) {
+ case SSH_KEYTYPE_RSA:
+ case SSH_KEYTYPE_RSA1: {
+ mbedtls_rsa_context *rsa;
+ if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA) == 0) {
+ ssh_buffer_free(buffer);
+ return NULL;
+ }
+
+ rsa = mbedtls_pk_rsa(*key->rsa);
+
+ e = ssh_make_bignum_string(&rsa->E);
+ if (e == NULL) {
+ goto fail;
+ }
+
+ n = ssh_make_bignum_string(&rsa->N);
+ if (n == NULL) {
+ goto fail;
+ }
+
+ if (ssh_buffer_add_ssh_string(buffer, e) < 0) {
+ goto fail;
+ }
+
+ if (ssh_buffer_add_ssh_string(buffer, n) < 0) {
+ goto fail;
+ }
+
+ ssh_string_burn(e);
+ ssh_string_free(e);
+ e = NULL;
+ ssh_string_burn(n);
+ ssh_string_free(n);
+ n = NULL;
+
+ break;
+ }
+ case SSH_KEYTYPE_ECDSA:
+ rc = ssh_buffer_reinit(buffer);
+ if (rc < 0) {
+ ssh_buffer_free(buffer);
+ return NULL;
+ }
+
+ type_s =
+ ssh_string_from_char(pki_key_ecdsa_nid_to_name(key->ecdsa_nid));
+ if (type_s == NULL) {
+ ssh_buffer_free(buffer);
+ return NULL;
+ }
+
+ rc = ssh_buffer_add_ssh_string(buffer, type_s);
+ ssh_string_free(type_s);
+ if (rc < 0) {
+ ssh_buffer_free(buffer);
+ return NULL;
+ }
+
+ type_s =
+ ssh_string_from_char(pki_key_ecdsa_nid_to_char(key->ecdsa_nid));
+ if (type_s == NULL) {
+ ssh_buffer_free(buffer);
+ return NULL;
+ }
+
+ rc = ssh_buffer_add_ssh_string(buffer, type_s);
+ ssh_string_free(type_s);
+ if (rc < 0) {
+ ssh_buffer_free(buffer);
+ return NULL;
+ }
+
+ e = make_ecpoint_string(&key->ecdsa->grp, &key->ecdsa->Q);
+
+ if (e == NULL) {
+ ssh_buffer_free(buffer);
+ return NULL;
+ }
+
+ rc = ssh_buffer_add_ssh_string(buffer, e);
+ if (rc < 0) {
+ goto fail;
+ }
+
+ ssh_string_burn(e);
+ ssh_string_free(e);
+ e = NULL;
+
+ break;
+ case SSH_KEYTYPE_ED25519:
+ rc = pki_ed25519_public_key_to_blob(buffer, key);
+ if (rc != SSH_OK) {
+ goto fail;
+ }
+ break;
+ default:
+ goto fail;
+ }
+makestring:
+ str = ssh_string_new(ssh_buffer_get_len(buffer));
+ if (str == NULL) {
+ goto fail;
+ }
+
+ rc = ssh_string_fill(str, ssh_buffer_get(buffer),
+ ssh_buffer_get_len(buffer));
+ if (rc < 0) {
+ goto fail;
+ }
+
+ ssh_buffer_free(buffer);
+ return str;
+fail:
+ ssh_buffer_free(buffer);
+ ssh_string_burn(str);
+ ssh_string_free(str);
+ ssh_string_burn(e);
+ ssh_string_free(e);
+ ssh_string_burn(n);
+ ssh_string_free(n);
+
+ return NULL;
+}
+
+int pki_export_pubkey_rsa1(const ssh_key key, const char *host, char *rsa1,
+ size_t rsa1_len)
+{
+ char *e;
+ char *n;
+ int rsa_size = mbedtls_pk_get_bitlen(key->rsa);
+ mbedtls_rsa_context *rsa;
+
+ if (!mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA)) {
+ return SSH_ERROR;
+ }
+
+ rsa = mbedtls_pk_rsa(*key->rsa);
+
+ n = bignum_bn2dec(&rsa->N);
+ if (n == NULL) {
+ return SSH_ERROR;
+ }
+
+ e = bignum_bn2dec(&rsa->E);
+ if (e == NULL) {
+ return SSH_ERROR;
+ }
+
+ snprintf(rsa1, rsa1_len, "%s %d %s %s\n",
+ host, rsa_size << 3, e, n);
+
+ SAFE_FREE(e);
+ SAFE_FREE(n);
+ return SSH_OK;
+}
+
+ssh_string pki_signature_to_blob(const ssh_signature sig)
+{
+ ssh_string sig_blob = NULL;
+
+ switch(sig->type) {
+ case SSH_KEYTYPE_RSA:
+ case SSH_KEYTYPE_RSA1:
+ sig_blob = ssh_string_copy(sig->rsa_sig);
+ break;
+ case SSH_KEYTYPE_ECDSA: {
+ ssh_string r;
+ ssh_string s;
+ ssh_buffer b;
+ int rc;
+
+ b = ssh_buffer_new();
+ if (b == NULL) {
+ return NULL;
+ }
+
+ r = ssh_make_bignum_string(sig->ecdsa_sig.r);
+ if (r == NULL) {
+ ssh_buffer_free(b);
+ return NULL;
+ }
+
+ rc = ssh_buffer_add_ssh_string(b, r);
+ ssh_string_free(r);
+ if (rc < 0) {
+ ssh_buffer_free(b);
+ return NULL;
+ }
+
+ s = ssh_make_bignum_string(sig->ecdsa_sig.s);
+ if (s == NULL) {
+ ssh_buffer_free(b);
+ return NULL;
+ }
+
+ rc = ssh_buffer_add_ssh_string(b, s);
+ ssh_string_free(s);
+ if (rc < 0) {
+ ssh_buffer_free(b);
+ return NULL;
+ }
+
+ sig_blob = ssh_string_new(ssh_buffer_get_len(b));
+ if (sig_blob == NULL) {
+ ssh_buffer_free(b);
+ return NULL;
+ }
+
+ ssh_string_fill(sig_blob, ssh_buffer_get(b), ssh_buffer_get_len(b));
+ ssh_buffer_free(b);
+ break;
+ }
+ case SSH_KEYTYPE_ED25519:
+ sig_blob = pki_ed25519_sig_to_blob(sig);
+ break;
+ default:
+ SSH_LOG(SSH_LOG_WARN, "Unknown signature key type: %s",
+ sig->type_c);
+ return NULL;
+ }
+
+ return sig_blob;
+}
+
+static ssh_signature pki_signature_from_rsa_blob(const ssh_key pubkey, const
+ ssh_string sig_blob, ssh_signature sig)
+{
+ size_t pad_len = 0;
+ char *blob_orig;
+ char *blob_padded_data;
+ ssh_string sig_blob_padded;
+
+ size_t rsalen = 0;
+ size_t len = ssh_string_len(sig_blob);
+
+ if (pubkey->rsa == NULL) {
+ SSH_LOG(SSH_LOG_WARN, "Pubkey RSA field NULL");
+ goto errout;
+ }
+
+ rsalen = mbedtls_pk_get_bitlen(pubkey->rsa) / 8;
+ if (len > rsalen) {
+ SSH_LOG(SSH_LOG_WARN,
+ "Signature is too big: %lu > %lu",
+ (unsigned long) len,
+ (unsigned long) rsalen);
+ goto errout;
+ }
+#ifdef DEBUG_CRYPTO
+ SSH_LOG(SSH_LOG_WARN, "RSA signature len: %lu", (unsigned long)len);
+ ssh_print_hexa("RSA signature", ssh_string_data(sig_blob), len);
+#endif
+
+ if (len == rsalen) {
+ sig->rsa_sig = ssh_string_copy(sig_blob);
+ } else {
+ SSH_LOG(SSH_LOG_DEBUG, "RSA signature len %lu < %lu",
+ (unsigned long) len,
+ (unsigned long) rsalen);
+ pad_len = rsalen - len;
+
+ sig_blob_padded = ssh_string_new(rsalen);
+ if (sig_blob_padded == NULL) {
+ goto errout;
+ }
+
+ blob_padded_data = (char *) ssh_string_data(sig_blob_padded);
+ blob_orig = (char *) ssh_string_data(sig_blob);
+
+ BURN_BUFFER(blob_padded_data, pad_len);
+ memcpy(blob_padded_data + pad_len, blob_orig, len);
+
+ sig->rsa_sig = sig_blob_padded;
+ }
+
+ return sig;
+
+errout:
+ ssh_signature_free(sig);
+ return NULL;
+}
+ssh_signature pki_signature_from_blob(const ssh_key pubkey, const ssh_string
+ sig_blob, enum ssh_keytypes_e type)
+{
+ ssh_signature sig;
+ int rc;
+
+ sig = ssh_signature_new();
+ if (sig == NULL) {
+ return NULL;
+ }
+
+ sig->type = type;
+ sig->type_c = ssh_key_type_to_char(type);
+
+ switch(type) {
+ case SSH_KEYTYPE_RSA:
+ case SSH_KEYTYPE_RSA1:
+ sig = pki_signature_from_rsa_blob(pubkey, sig_blob, sig);
+ break;
+ case SSH_KEYTYPE_ECDSA: {
+ ssh_buffer b;
+ ssh_string r;
+ ssh_string s;
+ size_t rlen;
+
+ b = ssh_buffer_new();
+ if (b == NULL) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+ rc = ssh_buffer_add_data(b, ssh_string_data(sig_blob),
+ ssh_string_len(sig_blob));
+
+ if (rc < 0) {
+ ssh_buffer_free(b);
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+ r = ssh_buffer_get_ssh_string(b);
+ if (r == NULL) {
+ ssh_buffer_free(b);
+ ssh_signature_free(sig);
+ return NULL;
+ }
+#ifdef DEBUG_CRYPTO
+ ssh_print_hexa("r", ssh_string_data(r), ssh_string_len(r));
+#endif
+ sig->ecdsa_sig.r = ssh_make_string_bn(r);
+ ssh_string_burn(r);
+ ssh_string_free(r);
+ if (sig->ecdsa_sig.r == NULL) {
+ ssh_buffer_free(b);
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+ s = ssh_buffer_get_ssh_string(b);
+ rlen = ssh_buffer_get_len(b);
+ ssh_buffer_free(b);
+ if (s == NULL) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+#ifdef DEBUG_CRYPTO
+ ssh_print_hexa("s", ssh_string_data(s), ssh_string_len(s));
+#endif
+ sig->ecdsa_sig.s = ssh_make_string_bn(s);
+ ssh_string_burn(s);
+ ssh_string_free(s);
+ if (sig->ecdsa_sig.s == NULL) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+ if (rlen != 0) {
+ SSH_LOG(SSH_LOG_WARN, "Signature has remaining bytes in inner "
+ "sigblob: %lu",
+ (unsigned long)rlen);
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+ break;
+ }
+ case SSH_KEYTYPE_ED25519:
+ rc = pki_ed25519_sig_from_blob(sig, sig_blob);
+ if (rc == SSH_ERROR) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+ break;
+ default:
+ SSH_LOG(SSH_LOG_WARN, "Unknown signature type");
+ return NULL;
+ }
+
+ return sig;
+}
+
+int pki_signature_verify(ssh_session session, const ssh_signature sig, const
+ ssh_key key, const unsigned char *hash, size_t hlen)
+{
+ int rc;
+
+ switch (key->type) {
+ case SSH_KEYTYPE_RSA:
+ case SSH_KEYTYPE_RSA1:
+ rc = mbedtls_pk_verify(key->rsa, MBEDTLS_MD_SHA1, hash, hlen,
+ ssh_string_data(sig->rsa_sig),
+ ssh_string_len(sig->rsa_sig));
+ if (rc != 0) {
+ char error_buf[100];
+ mbedtls_strerror(rc, error_buf, 100);
+ ssh_set_error(session, SSH_FATAL, "RSA error: %s", error_buf);
+ return SSH_ERROR;
+ }
+ break;
+ case SSH_KEYTYPE_ECDSA:
+ rc = mbedtls_ecdsa_verify(&key->ecdsa->grp, hash, hlen,
+ &key->ecdsa->Q, sig->ecdsa_sig.r, sig->ecdsa_sig.s);
+ if (rc != 0) {
+ char error_buf[100];
+ mbedtls_strerror(rc, error_buf, 100);
+ ssh_set_error(session, SSH_FATAL, "RSA error: %s", error_buf);
+ return SSH_ERROR;
+
+ }
+ break;
+ case SSH_KEYTYPE_ED25519:
+ rc = pki_ed25519_verify(key, sig, hash, hlen);
+ if (rc != SSH_OK) {
+ ssh_set_error(session, SSH_FATAL,
+ "ed25519 signature verification error");
+ return SSH_ERROR;
+ }
+ break;
+ default:
+ ssh_set_error(session, SSH_FATAL, "Unknown public key type");
+ return SSH_ERROR;
+ }
+
+ return SSH_OK;
+}
+
+static ssh_string rsa_do_sign(const unsigned char *digest, int dlen,
+ mbedtls_pk_context *privkey)
+{
+ ssh_string sig_blob;
+ unsigned char *sig;
+ size_t slen;
+ int ok;
+
+ sig = malloc(mbedtls_pk_get_bitlen(privkey) / 8);
+ if (sig == NULL) {
+ return NULL;
+ }
+
+ ok = mbedtls_pk_sign(privkey, MBEDTLS_MD_SHA1, digest, dlen, sig, &slen,
+ mbedtls_ctr_drbg_random, &ssh_mbedtls_ctr_drbg);
+
+ if (ok != 0) {
+ SAFE_FREE(sig);
+ return NULL;
+ }
+
+ sig_blob = ssh_string_new(slen);
+ if (sig_blob == NULL) {
+ SAFE_FREE(sig);
+ return NULL;
+ }
+
+ ssh_string_fill(sig_blob, sig, slen);
+ memset(sig, 'd', slen);
+ SAFE_FREE(sig);
+
+ return sig_blob;
+}
+
+
+ssh_signature pki_do_sign(const ssh_key privkey, const unsigned char *hash,
+ size_t hlen)
+{
+ ssh_signature sig;
+ int rc;
+
+ sig = ssh_signature_new();
+ if (sig == NULL) {
+ return NULL;
+ }
+
+ sig->type = privkey->type;
+ sig->type_c = privkey->type_c;
+
+ switch(privkey->type) {
+ case SSH_KEYTYPE_RSA:
+ case SSH_KEYTYPE_RSA1:
+ sig->rsa_sig = rsa_do_sign(hash, hlen, privkey->rsa);
+ if (sig->rsa_sig == NULL) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+ break;
+ case SSH_KEYTYPE_ECDSA:
+ sig->ecdsa_sig.r = bignum_new();
+ if (sig->ecdsa_sig.r == NULL) {
+ return NULL;
+ }
+
+ sig->ecdsa_sig.s = bignum_new();
+ if (sig->ecdsa_sig.s == NULL) {
+ bignum_free(sig->ecdsa_sig.r);
+ return NULL;
+ }
+
+ rc = mbedtls_ecdsa_sign(&privkey->ecdsa->grp, sig->ecdsa_sig.r,
+ sig->ecdsa_sig.s, &privkey->ecdsa->d, hash, hlen,
+ mbedtls_ctr_drbg_random, &ssh_mbedtls_ctr_drbg);
+ if (rc != 0) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+ break;
+ case SSH_KEYTYPE_ED25519:
+ rc = pki_ed25519_sign(privkey, sig, hash, hlen);
+ if (rc != SSH_OK) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+ break;
+ default:
+ ssh_signature_free(sig);
+ return NULL;
+
+ }
+
+ return sig;
+}
+
+#ifdef WITH_SERVER
+ssh_signature pki_do_sign_sessionid(const ssh_key key, const unsigned char
+ *hash, size_t hlen)
+{
+ ssh_signature sig;
+ int rc;
+
+ sig = ssh_signature_new();
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->type = key->type;
+ sig->type_c = key->type_c;
+
+ switch (key->type) {
+ case SSH_KEYTYPE_RSA:
+ case SSH_KEYTYPE_RSA1:
+ sig->rsa_sig = rsa_do_sign(hash, hlen, key->rsa);
+ if (sig->rsa_sig == NULL) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+ break;
+ case SSH_KEYTYPE_ECDSA:
+ sig->ecdsa_sig.r = bignum_new();
+ if (sig->ecdsa_sig.r == NULL) {
+ return NULL;
+ }
+
+ sig->ecdsa_sig.s = bignum_new();
+ if (sig->ecdsa_sig.s == NULL) {
+ bignum_free(sig->ecdsa_sig.r);
+ return NULL;
+ }
+
+ rc = mbedtls_ecdsa_sign(&key->ecdsa->grp, sig->ecdsa_sig.r,
+ sig->ecdsa_sig.s, &key->ecdsa->d, hash, hlen,
+ mbedtls_ctr_drbg_random, &ssh_mbedtls_ctr_drbg);
+ if (rc != 0) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+ break;
+ case SSH_KEYTYPE_ED25519:
+ /* ED25519 handled in caller */
+ default:
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+ return sig;
+}
+#endif /* WITH_SERVER */
+
+const char *pki_key_ecdsa_nid_to_name(int nid)
+{
+ switch (nid) {
+ case NID_mbedtls_nistp256:
+ return "ecdsa-sha2-nistp256";
+ case NID_mbedtls_nistp384:
+ return "ecdsa-sha2-nistp384";
+ case NID_mbedtls_nistp521:
+ return "ecdsa-sha2-nistp521";
+ default:
+ break;
+ }
+
+ return "unknown";
+}
+
+int pki_key_ecdsa_nid_from_name(const char *name)
+{
+ if (strcmp(name, "nistp256") == 0) {
+ return NID_mbedtls_nistp256;
+ } else if (strcmp(name, "nistp384") == 0) {
+ return NID_mbedtls_nistp384;
+ } else if (strcmp(name, "nistp521") == 0) {
+ return NID_mbedtls_nistp521;
+ }
+
+ return -1;
+}
+
+static mbedtls_ecp_group_id pki_key_ecdsa_nid_to_mbed_gid(int nid)
+{
+ switch (nid) {
+ case NID_mbedtls_nistp256:
+ return MBEDTLS_ECP_DP_SECP256R1;
+ case NID_mbedtls_nistp384:
+ return MBEDTLS_ECP_DP_SECP384R1;
+ case NID_mbedtls_nistp521:
+ return MBEDTLS_ECP_DP_SECP521R1;
+ }
+
+ return MBEDTLS_ECP_DP_NONE;
+}
+
+int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
+{
+ int rc;
+ mbedtls_ecp_keypair keypair;
+ mbedtls_ecp_group group;
+ mbedtls_ecp_point Q;
+
+ key->ecdsa_nid = nid;
+ key->type_c = pki_key_ecdsa_nid_to_name(nid);
+
+ key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
+ if (key->ecdsa == NULL) {
+ return SSH_ERROR;
+ }
+
+ mbedtls_ecdsa_init(key->ecdsa);
+ mbedtls_ecp_keypair_init(&keypair);
+ mbedtls_ecp_group_init(&group);
+ mbedtls_ecp_point_init(&Q);
+
+ rc = mbedtls_ecp_group_load(&group,
+ pki_key_ecdsa_nid_to_mbed_gid(nid));
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_ecp_point_read_binary(&group, &Q, ssh_string_data(e),
+ ssh_string_len(e));
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_ecp_copy(&keypair.Q, &Q);
+ if (rc != 0) {
+ goto fail;
+ }
+
+ rc = mbedtls_ecp_group_copy(&keypair.grp, &group);
+ if (rc != 0) {
+ goto fail;
+ }
+
+ mbedtls_mpi_init(&keypair.d);
+
+ rc = mbedtls_ecdsa_from_keypair(key->ecdsa, &keypair);
+ if (rc != 0) {
+ goto fail;
+ }
+
+ mbedtls_ecp_point_free(&Q);
+ mbedtls_ecp_group_free(&group);
+ mbedtls_ecp_keypair_free(&keypair);
+ return SSH_OK;
+fail:
+ mbedtls_ecdsa_free(key->ecdsa);
+ mbedtls_ecp_point_free(&Q);
+ mbedtls_ecp_group_free(&group);
+ mbedtls_ecp_keypair_free(&keypair);
+ SAFE_FREE(key->ecdsa);
+ return SSH_ERROR;
+}
+
+int pki_key_generate_ecdsa(ssh_key key, int parameter)
+{
+ int nid;
+ int ok;
+
+ switch (parameter) {
+ case 384:
+ nid = NID_mbedtls_nistp384;
+ break;
+ case 512:
+ nid = NID_mbedtls_nistp521;
+ break;
+ case 256:
+ default:
+ nid = NID_mbedtls_nistp256;
+ break;
+ }
+
+ key->ecdsa_nid = nid;
+ key->type = SSH_KEYTYPE_ECDSA;
+ key->type_c = pki_key_ecdsa_nid_to_name(nid);
+
+ key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
+ if (key->ecdsa == NULL) {
+ return SSH_ERROR;
+ }
+
+ mbedtls_ecdsa_init(key->ecdsa);
+
+ ok = mbedtls_ecdsa_genkey(key->ecdsa, pki_key_ecdsa_nid_to_mbed_gid(nid),
+ mbedtls_ctr_drbg_random, &ssh_mbedtls_ctr_drbg);
+
+ if (ok != 0) {
+ mbedtls_ecdsa_free(key->ecdsa);
+ SAFE_FREE(key->ecdsa);
+ }
+
+ return SSH_OK;
+}
+#endif /* HAVE_LIBMBEDCRYPTO */
diff --git a/src/server.c b/src/server.c
index 3c1ee74c..321ed78c 100644
--- a/src/server.c
+++ b/src/server.c
@@ -107,6 +107,7 @@ static int server_set_kex(ssh_session session) {
",%s", session->srv.ecdsa_key->type_c);
}
#endif
+#ifdef HAVE_DSA
if (session->srv.dsa_key != NULL) {
len = strlen(hostkeys);
keytype = ssh_key_type(session->srv.dsa_key);
@@ -114,6 +115,7 @@ static int server_set_kex(ssh_session session) {
snprintf(hostkeys + len, sizeof(hostkeys) - len,
",%s", ssh_key_type_to_char(keytype));
}
+#endif
if (session->srv.rsa_key != NULL) {
len = strlen(hostkeys);
keytype = ssh_key_type(session->srv.rsa_key);
@@ -225,9 +227,11 @@ int ssh_get_key_params(ssh_session session, ssh_key *privkey){
int rc;
switch(session->srv.hostkey) {
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS:
*privkey = session->srv.dsa_key;
break;
+#endif
case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1:
*privkey = session->srv.rsa_key;
diff --git a/src/session.c b/src/session.c
index 01773c52..f17d37c3 100644
--- a/src/session.c
+++ b/src/session.c
@@ -147,6 +147,7 @@ ssh_session ssh_new(void) {
goto err;
}
+#ifdef HAVE_DSA
id = strdup("%d/id_dsa");
if (id == NULL) {
goto err;
@@ -155,6 +156,7 @@ ssh_session ssh_new(void) {
if (rc == SSH_ERROR) {
goto err;
}
+#endif
id = strdup("%d/identity");
if (id == NULL) {
@@ -237,8 +239,10 @@ void ssh_free(ssh_session session) {
ssh_agent_free(session->agent);
#endif /* _WIN32 */
+#ifdef HAVE_DSA
ssh_key_free(session->srv.dsa_key);
session->srv.dsa_key = NULL;
+#endif
ssh_key_free(session->srv.rsa_key);
session->srv.rsa_key = NULL;
ssh_key_free(session->srv.ecdsa_key);
diff --git a/src/threads.c b/src/threads.c
index 062c3b84..b85ac756 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -33,6 +33,10 @@
#include "libssh/crypto.h"
#include "libssh/threads.h"
+#ifdef HAVE_LIBMBEDCRYPTO
+#include <mbedtls/threading.h>
+#endif
+
static int threads_noop (void **lock){
(void)lock;
return 0;
@@ -100,6 +104,28 @@ static int libgcrypt_thread_init(void){
return SSH_OK;
}
#endif /* GCRYPT_VERSION_NUMBER */
+#elif defined HAVE_LIBMBEDCRYPTO
+static int libmbedcrypto_thread_init(void)
+{
+ if (user_callbacks == NULL) {
+ return SSH_ERROR;
+ }
+
+ if (user_callbacks == &ssh_threads_noop) {
+ return SSH_OK;
+ }
+#ifdef MBEDTLS_THREADING_ALT
+ else {
+ mbedtls_threading_set_alt(user_callbacks->mutex_init,
+ user_callbacks->mutex_destroy, user_callbacks->mutex_lock,
+ user_callbacks->mutex_unlock);
+ }
+#elif defined MBEDTLS_THREADING_PTHREAD
+ return SSH_OK;
+#else
+ return SSH_ERROR;
+#endif
+}
#else /* HAVE_LIBGCRYPT */
/* Libcrypto specific stuff */
@@ -181,6 +207,8 @@ int ssh_threads_init(void){
/* Then initialize the crypto libraries threading callbacks */
#ifdef HAVE_LIBGCRYPT
ret = libgcrypt_thread_init();
+#elif HAVE_LIBMBEDCRYPTO
+ ret = libmbedcrypto_thread_init();
#else /* Libcrypto */
ret = libcrypto_thread_init();
#endif
@@ -191,6 +219,10 @@ int ssh_threads_init(void){
void ssh_threads_finalize(void){
#ifdef HAVE_LIBGCRYPT
+#elif HAVE_LIBMBEDCRYPTO
+#ifdef MBEDTLS_THREADING_ALT
+ mbedtls_threading_free_alt();
+#endif
#else
libcrypto_thread_finalize();
#endif
diff --git a/src/wrapper.c b/src/wrapper.c
index 877b807b..8ee04b49 100644
--- a/src/wrapper.c
+++ b/src/wrapper.c
@@ -113,21 +113,17 @@ void ssh_cipher_clear(struct ssh_cipher_struct *cipher){
}
#ifdef HAVE_LIBGCRYPT
- if(cipher->key) {
+ if (cipher->key) {
for (i = 0; i < (cipher->keylen / sizeof(gcry_cipher_hd_t)); i++) {
gcry_cipher_close(cipher->key[i]);
}
SAFE_FREE(cipher->key);
}
#endif
- if (cipher->ctx != NULL) {
+
if (cipher->cleanup != NULL) {
cipher->cleanup(cipher);
}
-#ifdef HAVE_LIBCRYPTO
- EVP_CIPHER_CTX_free(cipher->ctx);
-#endif
- }
}
static void cipher_free(struct ssh_cipher_struct *cipher) {
diff --git a/tests/client/torture_knownhosts.c b/tests/client/torture_knownhosts.c
index 00aa8269..014347df 100644
--- a/tests/client/torture_knownhosts.c
+++ b/tests/client/torture_knownhosts.c
@@ -38,6 +38,7 @@
"YgIytryNn7LLiwYfoSxvWigFrTTZsrVtCOYyNgklmffpGdzuC43wdANvTewfI9G" \
"o71r8EXmEc228CrYPmb8Scv3mpXFK/BosohSGkPlEHu9lf3YjnknBicDaVtJOYp" \
"wnXJPjZo2EhG79HxDRpjJHH"
+#ifdef HAVE_DSA
#define BADDSA "AAAAB3NzaC1kc3MAAACBAITDKqGQ5aC5wHySG6ZdL1+BVBY2nLP5vzw3i3pvZfP" \
"yNUS0UCwrt5pajsMvDRGXXebTJhWVonDnv8tpSgiuIBXMZrma8CU1KCFGRzwb/n8" \
"cc5tJmIphlOUTrObjBmsRz7u1eZmoaddXC9ask6BNnt0DmhzYi2esL3mbardy8IN" \
@@ -48,6 +49,7 @@
"EcxqLVllrNEvd2EGD9p16BYO2yaalYon8im59PtOcul2ay5XQ6rVDQ2T0pgNUpsI" \
"h0dSi8VJXI1wes5HTyLsv9VBmU1uCXUUvufoQKfF/OcSH0ufcCpnd62g1/adZcy2" \
"WJg=="
+#endif
static int sshd_setup(void **state)
{
@@ -185,6 +187,7 @@ static void torture_knownhosts_fail(void **state) {
assert_int_equal(rc, SSH_SERVER_KNOWN_CHANGED);
}
+#ifdef HAVE_DSA
static void torture_knownhosts_other(void **state) {
struct torture_state *s = *state;
ssh_session session = s->ssh.session;
@@ -270,6 +273,7 @@ static void torture_knownhosts_other_auto(void **state) {
/* session will be freed by session_teardown() */
}
+#endif
static void torture_knownhosts_conflict(void **state) {
struct torture_state *s = *state;
@@ -296,7 +300,9 @@ static void torture_knownhosts_conflict(void **state) {
file = fopen(known_hosts_file, "w");
assert_true(file != NULL);
fprintf(file, "127.0.0.10 ssh-rsa %s\n", BADRSA);
+#ifdef HAVE_DSA
fprintf(file, "127.0.0.10 ssh-dss %s\n", BADDSA);
+#endif
fclose(file);
rc = ssh_connect(session);
@@ -354,15 +360,21 @@ static void torture_knownhosts_precheck(void **state) {
file = fopen(known_hosts_file, "w");
assert_true(file != NULL);
fprintf(file, "127.0.0.10 ssh-rsa %s\n", BADRSA);
+#ifdef HAVE_DSA
fprintf(file, "127.0.0.10 ssh-dss %s\n", BADDSA);
+#endif
fclose(file);
kex = ssh_knownhosts_algorithms(session);
assert_true(kex != NULL);
assert_string_equal(kex[0],"ssh-rsa");
+#ifdef HAVE_DSA
assert_string_equal(kex[1],"ssh-dss");
assert_true(kex[2]==NULL);
free(kex[1]);
+#else
+ assert_true(kex[1]==NULL);
+#endif
free(kex[0]);
free(kex);
}
@@ -376,12 +388,14 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_knownhosts_fail,
session_setup,
session_teardown),
+#ifdef HAVE_DSA
cmocka_unit_test_setup_teardown(torture_knownhosts_other,
session_setup,
session_teardown),
cmocka_unit_test_setup_teardown(torture_knownhosts_other_auto,
session_setup,
session_teardown),
+#endif
cmocka_unit_test_setup_teardown(torture_knownhosts_conflict,
session_setup,
session_teardown),
diff --git a/tests/pkd/pkd_daemon.c b/tests/pkd/pkd_daemon.c
index 61582b5a..a72f53f8 100644
--- a/tests/pkd/pkd_daemon.c
+++ b/tests/pkd/pkd_daemon.c
@@ -253,8 +253,10 @@ static int pkd_exec_hello(int fd, struct pkd_daemon_args *args) {
if (type == PKD_RSA) {
opts = SSH_BIND_OPTIONS_RSAKEY;
+#ifdef HAVE_DSA
} else if (type == PKD_DSA) {
opts = SSH_BIND_OPTIONS_DSAKEY;
+#endif
} else if (type == PKD_ECDSA) {
opts = SSH_BIND_OPTIONS_ECDSAKEY;
} else {
diff --git a/tests/pkd/pkd_daemon.h b/tests/pkd/pkd_daemon.h
index c42573c1..cc5aa43f 100644
--- a/tests/pkd/pkd_daemon.h
+++ b/tests/pkd/pkd_daemon.h
@@ -10,7 +10,9 @@
enum pkd_hostkey_type_e {
PKD_RSA,
+#ifdef HAVE_DSA
PKD_DSA,
+#endif
PKD_ECDSA
};
diff --git a/tests/pkd/pkd_hello.c b/tests/pkd/pkd_hello.c
index fe7c2276..aac33fcf 100644
--- a/tests/pkd/pkd_hello.c
+++ b/tests/pkd/pkd_hello.c
@@ -139,12 +139,14 @@ static int torture_pkd_setup_rsa(void **state) {
return 0;
}
+#ifdef HAVE_DSA
static int torture_pkd_setup_dsa(void **state) {
setup_dsa_key();
*state = (void *) torture_pkd_setup(PKD_DSA, LIBSSH_DSA_TESTKEY);
return 0;
}
+#endif
static int torture_pkd_setup_ecdsa_256(void **state) {
setup_ecdsa_keys();
@@ -171,6 +173,7 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
* Test matrices: f(clientname, testname, ssh-command, setup-function, teardown-function).
*/
+#ifdef HAVE_DSA
#define PKDTESTS_DEFAULT(f, client, cmd) \
/* Default passes by server key type. */ \
f(client, rsa_default, cmd, setup_rsa, teardown) \
@@ -178,7 +181,16 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, ecdsa_256_default, cmd, setup_ecdsa_256, teardown) \
f(client, ecdsa_384_default, cmd, setup_ecdsa_384, teardown) \
f(client, ecdsa_521_default, cmd, setup_ecdsa_521, teardown)
+#else
+#define PKDTESTS_DEFAULT(f, client, cmd) \
+ /* Default passes by server key type. */ \
+ f(client, rsa_default, cmd, setup_rsa, teardown) \
+ f(client, ecdsa_256_default, cmd, setup_ecdsa_256, teardown) \
+ f(client, ecdsa_384_default, cmd, setup_ecdsa_384, teardown) \
+ f(client, ecdsa_521_default, cmd, setup_ecdsa_521, teardown)
+#endif
+#ifdef HAVE_DSA
#define PKDTESTS_KEX(f, client, kexcmd) \
/* Kex algorithms. */ \
f(client, rsa_curve25519_sha256, kexcmd("curve25519-sha256@xxxxxxxxxx"), setup_rsa, teardown) \
@@ -201,7 +213,28 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, ecdsa_521_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256 "), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_521, teardown)
+#else
+#define PKDTESTS_KEX(f, client, kexcmd) \
+ /* Kex algorithms. */ \
+ f(client, rsa_curve25519_sha256, kexcmd("curve25519-sha256@xxxxxxxxxx"), setup_rsa, teardown) \
+ f(client, rsa_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256 "), setup_rsa, teardown) \
+ f(client, rsa_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_rsa, teardown) \
+ f(client, rsa_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_rsa, teardown) \
+ f(client, ecdsa_256_curve25519_sha256, kexcmd("curve25519-sha256@xxxxxxxxxx"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_256_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256 "), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_256_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_256_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_384_curve25519_sha256, kexcmd("curve25519-sha256@xxxxxxxxxx"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_384_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256 "), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_384_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_384_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_521_curve25519_sha256, kexcmd("curve25519-sha256@xxxxxxxxxx"), setup_ecdsa_521, teardown) \
+ f(client, ecdsa_521_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256 "), setup_ecdsa_521, teardown) \
+ f(client, ecdsa_521_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_521, teardown) \
+ f(client, ecdsa_521_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_521, teardown)
+#endif
+#ifdef HAVE_DSA
#define PKDTESTS_CIPHER(f, client, ciphercmd) \
/* Ciphers. */ \
f(client, rsa_3des_cbc, ciphercmd("3des-cbc"), setup_rsa, teardown) \
@@ -234,7 +267,36 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, ecdsa_521_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_aes256_ctr, ciphercmd("aes256-ctr"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_blowfish_cbc, ciphercmd("blowfish-cbc"), setup_ecdsa_521, teardown)
+#else
+#define PKDTESTS_CIPHER(f, client, ciphercmd) \
+ /* Ciphers. */ \
+ f(client, rsa_3des_cbc, ciphercmd("3des-cbc"), setup_rsa, teardown) \
+ f(client, rsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_rsa, teardown) \
+ f(client, rsa_aes128_ctr, ciphercmd("aes128-ctr"), setup_rsa, teardown) \
+ f(client, rsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_rsa, teardown) \
+ f(client, rsa_aes256_ctr, ciphercmd("aes256-ctr"), setup_rsa, teardown) \
+ f(client, rsa_blowfish_cbc, ciphercmd("blowfish-cbc"), setup_rsa, teardown) \
+ f(client, ecdsa_256_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_256_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_256_aes128_ctr, ciphercmd("aes128-ctr"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_256_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_256_aes256_ctr, ciphercmd("aes256-ctr"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_256_blowfish_cbc, ciphercmd("blowfish-cbc"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_384_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_384_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_384_aes128_ctr, ciphercmd("aes128-ctr"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_384_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_384_aes256_ctr, ciphercmd("aes256-ctr"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_384_blowfish_cbc, ciphercmd("blowfish-cbc"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_521_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_521, teardown) \
+ f(client, ecdsa_521_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_521, teardown) \
+ f(client, ecdsa_521_aes128_ctr, ciphercmd("aes128-ctr"), setup_ecdsa_521, teardown) \
+ f(client, ecdsa_521_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_521, teardown) \
+ f(client, ecdsa_521_aes256_ctr, ciphercmd("aes256-ctr"), setup_ecdsa_521, teardown) \
+ f(client, ecdsa_521_blowfish_cbc, ciphercmd("blowfish-cbc"), setup_ecdsa_521, teardown)
+#endif
+#ifdef HAVE_DSA
#define PKDTESTS_CIPHER_AES192(f, client, ciphercmd) \
/* Ciphers. */ \
f(client, rsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_rsa, teardown) \
@@ -247,7 +309,20 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, ecdsa_384_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_384, teardown) \
f(client, ecdsa_521_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_521, teardown)
+#else
+#define PKDTESTS_CIPHER_AES192(f, client, ciphercmd) \
+ /* Ciphers. */ \
+ f(client, rsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_rsa, teardown) \
+ f(client, rsa_aes192_ctr, ciphercmd("aes192-ctr"), setup_rsa, teardown) \
+ f(client, ecdsa_256_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_256_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_384_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_384_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_521_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_521, teardown) \
+ f(client, ecdsa_521_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_521, teardown)
+#endif
+#ifdef HAVE_DSA
#define PKDTESTS_MAC(f, client, maccmd) \
/* MACs. */ \
f(client, rsa_hmac_sha1, maccmd("hmac-sha1"), setup_rsa, teardown) \
@@ -265,6 +340,22 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, ecdsa_256_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_ecdsa_256, teardown) \
f(client, ecdsa_384_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_ecdsa_384, teardown) \
f(client, ecdsa_521_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_ecdsa_521, teardown)
+#else
+#define PKDTESTS_MAC(f, client, maccmd) \
+ /* MACs. */ \
+ f(client, rsa_hmac_sha1, maccmd("hmac-sha1"), setup_rsa, teardown) \
+ f(client, ecdsa_256_hmac_sha1, maccmd("hmac-sha1"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_384_hmac_sha1, maccmd("hmac-sha1"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_521_hmac_sha1, maccmd("hmac-sha1"), setup_ecdsa_521, teardown) \
+ f(client, rsa_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_rsa, teardown) \
+ f(client, ecdsa_256_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_384_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_521_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ecdsa_521, teardown) \
+ f(client, rsa_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_rsa, teardown) \
+ f(client, ecdsa_256_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_ecdsa_256, teardown) \
+ f(client, ecdsa_384_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_ecdsa_384, teardown) \
+ f(client, ecdsa_521_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_ecdsa_521, teardown)
+#endif
static void torture_pkd_client_noop(void **state) {
struct pkd_state *pstate = (struct pkd_state *) (*state);
@@ -311,6 +402,7 @@ static void torture_pkd_runtest(const char *testname,
* Actual test functions are emitted here.
*/
+#ifdef HAVE_DSA
#define CLIENT_ID_FILE OPENSSH_DSA_TESTKEY
PKDTESTS_DEFAULT(emit_keytest, openssh_dsa, OPENSSH_CMD)
PKDTESTS_KEX(emit_keytest, openssh_dsa, OPENSSH_KEX_CMD)
@@ -318,6 +410,7 @@ PKDTESTS_CIPHER(emit_keytest, openssh_dsa, OPENSSH_CIPHER_CMD)
PKDTESTS_CIPHER_AES192(emit_keytest, openssh_dsa, OPENSSH_CIPHER_CMD)
PKDTESTS_MAC(emit_keytest, openssh_dsa, OPENSSH_MAC_CMD)
#undef CLIENT_ID_FILE
+#endif
#define CLIENT_ID_FILE OPENSSH_RSA_TESTKEY
PKDTESTS_DEFAULT(emit_keytest, openssh_rsa, OPENSSH_CMD)
@@ -376,11 +469,13 @@ struct {
const struct CMUnitTest test[3]; /* requires setup + test + teardown */
} testmap[] = {
/* OpenSSH */
+#ifdef HAVE_DSA
PKDTESTS_DEFAULT(emit_testmap, openssh_dsa, OPENSSH_CMD)
PKDTESTS_KEX(emit_testmap, openssh_dsa, OPENSSH_KEX_CMD)
PKDTESTS_CIPHER(emit_testmap, openssh_dsa, OPENSSH_CIPHER_CMD)
PKDTESTS_CIPHER_AES192(emit_testmap, openssh_dsa, OPENSSH_CIPHER_CMD)
PKDTESTS_MAC(emit_testmap, openssh_dsa, OPENSSH_MAC_CMD)
+#endif
PKDTESTS_DEFAULT(emit_testmap, openssh_rsa, OPENSSH_CMD)
PKDTESTS_KEX(emit_testmap, openssh_rsa, OPENSSH_KEX_CMD)
@@ -418,11 +513,13 @@ static int pkd_run_tests(void) {
int tindex = 0;
const struct CMUnitTest openssh_tests[] = {
+#ifdef HAVE_DSA
PKDTESTS_DEFAULT(emit_unit_test_comma, openssh_dsa, OPENSSH_CMD)
PKDTESTS_KEX(emit_unit_test_comma, openssh_dsa, OPENSSH_KEX_CMD)
PKDTESTS_CIPHER(emit_unit_test_comma, openssh_dsa, OPENSSH_CIPHER_CMD)
PKDTESTS_CIPHER_AES192(emit_unit_test_comma, openssh_dsa, OPENSSH_CIPHER_CMD)
PKDTESTS_MAC(emit_unit_test_comma, openssh_dsa, OPENSSH_MAC_CMD)
+#endif
PKDTESTS_DEFAULT(emit_unit_test_comma, openssh_rsa, OPENSSH_CMD)
PKDTESTS_KEX(emit_unit_test_comma, openssh_rsa, OPENSSH_KEX_CMD)
@@ -508,7 +605,9 @@ static int pkd_run_tests(void) {
/* Clean up any server keys that were generated. */
cleanup_rsa_key();
+#ifdef HAVE_DSA
cleanup_dsa_key();
+#endif
cleanup_ecdsa_keys();
return rc;
diff --git a/tests/pkd/pkd_keyutil.c b/tests/pkd/pkd_keyutil.c
index e1e1ecb8..7cb2ed48 100644
--- a/tests/pkd/pkd_keyutil.c
+++ b/tests/pkd/pkd_keyutil.c
@@ -27,6 +27,7 @@ void setup_rsa_key() {
assert_int_equal(rc, 0);
}
+#ifdef HAVE_DSA
void setup_dsa_key() {
int rc = 0;
if (access(LIBSSH_DSA_TESTKEY, F_OK) != 0) {
@@ -35,6 +36,7 @@ void setup_dsa_key() {
}
assert_int_equal(rc, 0);
}
+#endif
void setup_ecdsa_keys() {
int rc = 0;
@@ -65,9 +67,11 @@ void cleanup_rsa_key() {
cleanup_key(LIBSSH_RSA_TESTKEY, LIBSSH_RSA_TESTKEY ".pub");
}
+#ifdef HAVE_DSA
void cleanup_dsa_key() {
cleanup_key(LIBSSH_DSA_TESTKEY, LIBSSH_DSA_TESTKEY ".pub");
}
+#endif
void cleanup_ecdsa_keys() {
cleanup_key(LIBSSH_ECDSA_256_TESTKEY, LIBSSH_ECDSA_256_TESTKEY ".pub");
@@ -78,11 +82,13 @@ void cleanup_ecdsa_keys() {
void setup_openssh_client_keys() {
int rc = 0;
+#ifdef HAVE_DSA
if (access(OPENSSH_DSA_TESTKEY, F_OK) != 0) {
rc = system_checked(OPENSSH_KEYGEN " -t dsa -q -N \"\" -f "
OPENSSH_DSA_TESTKEY);
}
assert_int_equal(rc, 0);
+#endif
if (access(OPENSSH_RSA_TESTKEY, F_OK) != 0) {
rc = system_checked(OPENSSH_KEYGEN " -t rsa -q -N \"\" -f "
@@ -116,7 +122,9 @@ void setup_openssh_client_keys() {
}
void cleanup_openssh_client_keys() {
+#ifdef HAVE_DSA
cleanup_key(OPENSSH_DSA_TESTKEY, OPENSSH_DSA_TESTKEY ".pub");
+#endif
cleanup_key(OPENSSH_RSA_TESTKEY, OPENSSH_RSA_TESTKEY ".pub");
cleanup_key(OPENSSH_ECDSA256_TESTKEY, OPENSSH_ECDSA256_TESTKEY ".pub");
cleanup_key(OPENSSH_ECDSA384_TESTKEY, OPENSSH_ECDSA384_TESTKEY ".pub");
diff --git a/tests/pkd/pkd_keyutil.h b/tests/pkd/pkd_keyutil.h
index 8e9de009..3d0ae5a7 100644
--- a/tests/pkd/pkd_keyutil.h
+++ b/tests/pkd/pkd_keyutil.h
@@ -7,22 +7,32 @@
#ifndef __PKD_KEYUTIL_H__
#define __PKD_KEYUTIL_H__
+#include "config.h"
+
/* Server keys. */
+#ifdef HAVE_DSA
#define LIBSSH_DSA_TESTKEY "libssh_testkey.id_dsa"
+#endif
#define LIBSSH_RSA_TESTKEY "libssh_testkey.id_rsa"
#define LIBSSH_ECDSA_256_TESTKEY "libssh_testkey.id_ecdsa256"
#define LIBSSH_ECDSA_384_TESTKEY "libssh_testkey.id_ecdsa384"
#define LIBSSH_ECDSA_521_TESTKEY "libssh_testkey.id_ecdsa521"
+#ifdef HAVE_DSA
void setup_dsa_key(void);
+#endif
void setup_rsa_key(void);
void setup_ecdsa_keys(void);
+#ifdef HAVE_DSA
void cleanup_dsa_key(void);
+#endif
void cleanup_rsa_key(void);
void cleanup_ecdsa_keys(void);
/* Client keys. */
+#ifdef HAVE_DSA
#define OPENSSH_DSA_TESTKEY "openssh_testkey.id_dsa"
+#endif
#define OPENSSH_RSA_TESTKEY "openssh_testkey.id_rsa"
#define OPENSSH_ECDSA256_TESTKEY "openssh_testkey.id_ecdsa256"
#define OPENSSH_ECDSA384_TESTKEY "openssh_testkey.id_ecdsa384"
diff --git a/tests/test_ssh_bind_accept_fd.c b/tests/test_ssh_bind_accept_fd.c
index 7611cf4c..5aa8211a 100644
--- a/tests/test_ssh_bind_accept_fd.c
+++ b/tests/test_ssh_bind_accept_fd.c
@@ -73,10 +73,18 @@ void ssh_server() {
errx(1, "ssh_bind_new");
}
+#ifdef HAVE_DSA
+ /*TODO mbedtls this is probably required */
if (ssh_bind_options_set(bind, SSH_BIND_OPTIONS_DSAKEY,
options.server_keyfile) != SSH_OK) {
errx(1, "ssh_bind_options_set(SSH_BIND_OPTIONS_DSAKEY");
}
+#else
+ if (ssh_bind_options_set(bind, SSH_BIND_OPTIONS_RSAKEY,
+ options.server_keyfile) != SSH_OK) {
+ errx(1, "ssh_bind_options_set(SSH_BIND_OPTIONS_RSAKEY");
+ }
+#endif
session = ssh_new();
if (!session) {
diff --git a/tests/torture.c b/tests/torture.c
index 545fc2e3..7a23ec51 100644
--- a/tests/torture.c
+++ b/tests/torture.c
@@ -113,6 +113,7 @@ static const char torture_rsa_testkey_cert[] =
"neB6OdgTpKFsmgPZVtqrvhjw+b5T8a4W4iWSl+6wg6gowAm "
"rsa_privkey.pub\n";
+#ifdef HAVE_DSA
static const char torture_dsa_testkey[] =
"-----BEGIN DSA PRIVATE KEY-----\n"
"MIIBuwIBAAKBgQCUyvVPEkn3UnZDjzCzSzSHpTltzr0Ec+1mz/JACjHMBJ9C/W/P\n"
@@ -167,6 +168,7 @@ static const char torture_dsa_testkey_cert[] =
"4mMXgzaLViFtcwah6wHGlW0UPQMvrq/RqigAkyUszSccfibkIXJ+wGAgsRYhVAMwME"
"JqPZ6GHOEIjLBKUegsclHb7Pk0YO8Auaw== "
"aris@aris-air\n";
+#endif
static const char torture_rsa_testkey_pp[] =
"-----BEGIN RSA PRIVATE KEY-----\n"
@@ -200,6 +202,7 @@ static const char torture_rsa_testkey_pp[] =
"JSvUyxoaZUjQkT7iF94HsF+FVVJdI55UjgnMiZ0d5vKffWyTHYcYHkFYaSloAMWN\n"
"-----END RSA PRIVATE KEY-----\n";
+#ifdef HAVE_DSA
static const char torture_dsa_testkey_pp[] =
"-----BEGIN DSA PRIVATE KEY-----\n"
"Proc-Type: 4,ENCRYPTED\n"
@@ -216,6 +219,7 @@ static const char torture_dsa_testkey_pp[] =
"HTSuHZ7edjoWqwnl/vkc3+nG//IEj8LqAacx0i4krDcQpGuQ6BnPfwPFco2NQQpw\n"
"wHBOL6HrOnD+gGs6DUFwzA==\n"
"-----END DSA PRIVATE KEY-----\n";
+#endif
static const char torture_ecdsa256_testkey[] =
"-----BEGIN EC PRIVATE KEY-----\n"
@@ -571,9 +575,11 @@ ssh_bind torture_ssh_bind(const char *addr,
}
switch (key_type) {
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS:
opts = SSH_BIND_OPTIONS_DSAKEY;
break;
+#endif
case SSH_KEYTYPE_RSA:
opts = SSH_BIND_OPTIONS_RSAKEY;
break;
@@ -694,6 +700,7 @@ static const char *torture_get_testkey_internal(enum ssh_keytypes_e type,
int pubkey)
{
switch (type) {
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS:
if (pubkey) {
return torture_dsa_testkey_pub;
@@ -701,6 +708,7 @@ static const char *torture_get_testkey_internal(enum ssh_keytypes_e type,
return torture_dsa_testkey_pp;
}
return torture_dsa_testkey;
+#endif
case SSH_KEYTYPE_RSA:
if (pubkey) {
return torture_rsa_testkey_pub;
@@ -738,8 +746,10 @@ static const char *torture_get_testkey_internal(enum ssh_keytypes_e type,
return torture_ed25519_testkey_pp;
}
return torture_ed25519_testkey;
+#ifdef HAVE_DSA
case SSH_KEYTYPE_DSS_CERT01:
return torture_dsa_testkey_cert;
+#endif
case SSH_KEYTYPE_RSA_CERT01:
return torture_rsa_testkey_cert;
case SSH_KEYTYPE_RSA1:
@@ -859,7 +869,9 @@ void torture_setup_socket_dir(void **state)
static void torture_setup_create_sshd_config(void **state)
{
struct torture_state *s = *state;
+#ifdef HAVE_DSA
char dsa_hostkey[1024];
+#endif
char rsa_hostkey[1024];
char ecdsa_hostkey[1024];
char trusted_ca_pubkey[1024];
@@ -879,7 +891,9 @@ static void torture_setup_create_sshd_config(void **state)
const char config_string[]=
"Port 22\n"
"ListenAddress 127.0.0.10\n"
+#ifdef HAVE_DSA
"HostKey %s\n"
+#endif
"HostKey %s\n"
"HostKey %s\n"
"\n"
@@ -898,7 +912,11 @@ static void torture_setup_create_sshd_config(void **state)
"UsePAM yes\n"
"\n"
#if (OPENSSH_VERSION_MAJOR == 6 && OPENSSH_VERSION_MINOR >= 7) || (OPENSSH_VERSION_MAJOR >= 7)
+#ifdef HAVE_DSA
"HostKeyAlgorithms +ssh-dss\n"
+#else
+ "HostKeyAlgorithms +ssh-rsa\n"
+#endif
"Ciphers +3des-cbc,aes128-cbc,aes192-cbc,aes256-cbc,blowfish-cbc\n"
"KexAlgorithms +diffie-hellman-group1-sha1"
#else
@@ -932,11 +950,13 @@ static void torture_setup_create_sshd_config(void **state)
rc = mkdir(sshd_path, 0755);
assert_return_code(rc, errno);
+#ifdef HAVE_DSA
snprintf(dsa_hostkey,
sizeof(dsa_hostkey),
"%s/sshd/ssh_host_dsa_key",
s->socket_dir);
torture_write_file(dsa_hostkey, torture_get_testkey(SSH_KEYTYPE_DSS, 0, 0));
+#endif
snprintf(rsa_hostkey,
sizeof(rsa_hostkey),
@@ -973,7 +993,9 @@ static void torture_setup_create_sshd_config(void **state)
snprintf(sshd_config, sizeof(sshd_config),
config_string,
+#ifdef HAVE_DSA
dsa_hostkey,
+#endif
rsa_hostkey,
ecdsa_hostkey,
trusted_ca_pubkey,
diff --git a/tests/unittests/torture_keyfiles.c b/tests/unittests/torture_keyfiles.c
index e5f054f9..6573711b 100644
--- a/tests/unittests/torture_keyfiles.c
+++ b/tests/unittests/torture_keyfiles.c
@@ -4,7 +4,9 @@
#include "legacy.c"
#define LIBSSH_RSA_TESTKEY "libssh_testkey.id_rsa"
+#ifdef HAVE_DSA
#define LIBSSH_DSA_TESTKEY "libssh_testkey.id_dsa"
+#endif
static int setup_rsa_key(void **state)
{
@@ -24,6 +26,7 @@ static int setup_rsa_key(void **state)
return 0;
}
+#ifdef HAVE_DSA
static int setup_dsa_key(void **state)
{
ssh_session session;
@@ -41,6 +44,7 @@ static int setup_dsa_key(void **state)
return 0;
}
+#endif
static int setup_both_keys(void **state) {
int rc;
@@ -49,9 +53,11 @@ static int setup_both_keys(void **state) {
if (rc != 0) {
return rc;
}
+#ifdef HAVE_DSA
ssh_free(*state);
rc = setup_dsa_key(state);
+#endif
return rc;
}
@@ -65,10 +71,12 @@ static int setup_both_keys_passphrase(void **state)
torture_write_file(LIBSSH_RSA_TESTKEY ".pub",
torture_get_testkey_pub(SSH_KEYTYPE_RSA, 0));
+#ifdef HAVE_DSA
torture_write_file(LIBSSH_DSA_TESTKEY,
torture_get_testkey(SSH_KEYTYPE_DSS, 0, 1));
torture_write_file(LIBSSH_DSA_TESTKEY ".pub",
torture_get_testkey_pub(SSH_KEYTYPE_DSS, 0));
+#endif
session = ssh_new();
*state = session;
@@ -78,8 +86,10 @@ static int setup_both_keys_passphrase(void **state)
static int teardown(void **state)
{
+#ifdef HAVE_DSA
unlink(LIBSSH_DSA_TESTKEY);
unlink(LIBSSH_DSA_TESTKEY ".pub");
+#endif
unlink(LIBSSH_RSA_TESTKEY);
unlink(LIBSSH_RSA_TESTKEY ".pub");
@@ -214,12 +224,14 @@ static void torture_privatekey_from_file(void **state) {
key = NULL;
}
+#ifdef HAVE_DSA
key = privatekey_from_file(session, LIBSSH_DSA_TESTKEY, SSH_KEYTYPE_DSS, NULL);
assert_true(key != NULL);
if (key != NULL) {
privatekey_free(key);
key = NULL;
}
+#endif
/* Test the automatic type discovery */
key = privatekey_from_file(session, LIBSSH_RSA_TESTKEY, 0, NULL);
@@ -229,12 +241,14 @@ static void torture_privatekey_from_file(void **state) {
key = NULL;
}
+#ifdef HAVE_DSA
key = privatekey_from_file(session, LIBSSH_DSA_TESTKEY, 0, NULL);
assert_true(key != NULL);
if (key != NULL) {
privatekey_free(key);
key = NULL;
}
+#endif
}
/**
@@ -251,12 +265,14 @@ static void torture_privatekey_from_file_passphrase(void **state) {
key = NULL;
}
+#ifdef HAVE_DSA
key = privatekey_from_file(session, LIBSSH_DSA_TESTKEY, SSH_KEYTYPE_DSS, TORTURE_TESTKEY_PASSWORD);
assert_true(key != NULL);
if (key != NULL) {
privatekey_free(key);
key = NULL;
}
+#endif
/* Test the automatic type discovery */
key = privatekey_from_file(session, LIBSSH_RSA_TESTKEY, 0, TORTURE_TESTKEY_PASSWORD);
@@ -266,12 +282,14 @@ static void torture_privatekey_from_file_passphrase(void **state) {
key = NULL;
}
+#ifdef HAVE_DSA
key = privatekey_from_file(session, LIBSSH_DSA_TESTKEY, 0, TORTURE_TESTKEY_PASSWORD);
assert_true(key != NULL);
if (key != NULL) {
privatekey_free(key);
key = NULL;
}
+#endif
}
int torture_run_tests(void) {
diff --git a/tests/unittests/torture_misc.c b/tests/unittests/torture_misc.c
index bc16dfb0..1d0e0f5c 100644
--- a/tests/unittests/torture_misc.c
+++ b/tests/unittests/torture_misc.c
@@ -205,6 +205,147 @@ static void torture_timeout_update(void **state){
assert_int_equal(ssh_timeout_update(&ts,-1),-1);
}
+static void torture_ssh_analyze_banner(void **state) {
+ int rc = 0;
+ int ssh1 = 0;
+ int ssh2 = 0;
+ ssh_session session = NULL;
+ (void) state;
+
+#define reset_banner_test() \
+ do { \
+ rc = 0; \
+ ssh1 = 0; \
+ ssh2 = 0; \
+ ssh_free(session); \
+ session = ssh_new(); \
+ assert_non_null(session); \
+ } while (0)
+
+#define assert_banner_rejected(is_server) \
+ do { \
+ rc = ssh_analyze_banner(session, is_server, &ssh1, &ssh2); \
+ assert_int_not_equal(0, rc); \
+ } while (0);
+
+#define assert_client_banner_rejected(banner) \
+ do { \
+ reset_banner_test(); \
+ session->clientbanner = strdup(banner); \
+ assert_non_null(session->clientbanner); \
+ assert_banner_rejected(1 /*server*/); \
+ SAFE_FREE(session->clientbanner); \
+ } while (0)
+
+#define assert_server_banner_rejected(banner) \
+ do { \
+ reset_banner_test(); \
+ session->serverbanner = strdup(banner); \
+ assert_non_null(session->serverbanner); \
+ assert_banner_rejected(0 /*client*/); \
+ SAFE_FREE(session->serverbanner); \
+ } while (0)
+
+#define assert_banner_accepted(is_server, expected_ssh1, expected_ssh2) \
+ do { \
+ rc = ssh_analyze_banner(session, is_server, &ssh1, &ssh2); \
+ assert_int_equal(0, rc); \
+ assert_int_equal(expected_ssh1, ssh1); \
+ assert_int_equal(expected_ssh2, ssh2); \
+ } while (0)
+
+#define assert_client_banner_accepted(banner, e1, e2) \
+ do { \
+ reset_banner_test(); \
+ session->clientbanner = strdup(banner); \
+ assert_non_null(session->clientbanner); \
+ assert_banner_accepted(1 /*server*/, e1, e2); \
+ SAFE_FREE(session->clientbanner); \
+ } while (0)
+
+#define assert_server_banner_accepted(banner, e1, e2) \
+ do { \
+ reset_banner_test(); \
+ session->serverbanner = strdup(banner); \
+ assert_non_null(session->serverbanner); \
+ assert_banner_accepted(0 /*client*/, e1, e2); \
+ SAFE_FREE(session->serverbanner); \
+ } while (0)
+
+ /* no banner is set */
+ reset_banner_test();
+ assert_banner_rejected(0 /*client*/);
+ reset_banner_test();
+ assert_banner_rejected(1 /*server*/);
+
+ /* banner is too short */
+ assert_client_banner_rejected("abc");
+ assert_server_banner_rejected("abc");
+
+ /* banner doesn't start "SSH-" */
+ assert_client_banner_rejected("abc-2.0");
+ assert_server_banner_rejected("abc-2.0");
+
+ /* SSH v1 */
+ assert_client_banner_accepted("SSH-1.0", 1, 0);
+ assert_server_banner_accepted("SSH-1.0", 1, 0);
+
+ /* SSH v1.9 gets counted as both v1 and v2 */
+ assert_client_banner_accepted("SSH-1.9", 1, 1);
+ assert_server_banner_accepted("SSH-1.9", 1, 1);
+
+ /* SSH v2 */
+ assert_client_banner_accepted("SSH-2.0", 0, 1);
+ assert_server_banner_accepted("SSH-2.0", 0, 1);
+
+ /* OpenSSH banners: too short to extract major and minor versions */
+ assert_client_banner_accepted("SSH-2.0-OpenSSH", 0, 1);
+ assert_int_equal(0, session->openssh);
+ assert_server_banner_accepted("SSH-2.0-OpenSSH", 0, 1);
+ assert_int_equal(0, session->openssh);
+
+ /* OpenSSH banners: big enough to extract major and minor versions */
+ assert_client_banner_accepted("SSH-2.0-OpenSSH_5.9p1", 0, 1);
+ assert_int_equal(SSH_VERSION_INT(5, 9, 0), session->openssh);
+ assert_server_banner_accepted("SSH-2.0-OpenSSH_5.9p1", 0, 1);
+ assert_int_equal(SSH_VERSION_INT(5, 9, 0), session->openssh);
+
+ assert_client_banner_accepted("SSH-2.0-OpenSSH_1.99", 0, 1);
+ assert_int_equal(SSH_VERSION_INT(1, 99, 0), session->openssh);
+ assert_server_banner_accepted("SSH-2.0-OpenSSH_1.99", 0, 1);
+ assert_int_equal(SSH_VERSION_INT(1, 99, 0), session->openssh);
+
+ /* OpenSSH banners: major, minor version limits result in zero */
+ assert_client_banner_accepted("SSH-2.0-OpenSSH_0.99p1", 0, 1);
+ assert_int_equal(0, session->openssh);
+ assert_server_banner_accepted("SSH-2.0-OpenSSH_0.99p1", 0, 1);
+ assert_int_equal(0, session->openssh);
+ assert_client_banner_accepted("SSH-2.0-OpenSSH_1.101p1", 0, 1);
+ assert_int_equal(0, session->openssh);
+ assert_server_banner_accepted("SSH-2.0-OpenSSH_1.101p1", 0, 1);
+ assert_int_equal(0, session->openssh);
+
+ /* OpenSSH banners: bogus major results in zero */
+ assert_client_banner_accepted("SSH-2.0-OpenSSH_X.9p1", 0, 1);
+ assert_int_equal(0, session->openssh);
+ assert_server_banner_accepted("SSH-2.0-OpenSSH_X.9p1", 0, 1);
+ assert_int_equal(0, session->openssh);
+
+ /* OpenSSH banners: bogus minor results in zero */
+ assert_server_banner_accepted("SSH-2.0-OpenSSH_5.Yp1", 0, 1);
+ assert_int_equal(0, session->openssh);
+ assert_client_banner_accepted("SSH-2.0-OpenSSH_5.Yp1", 0, 1);
+ assert_int_equal(0, session->openssh);
+
+ /* OpenSSH banners: ssh-keyscan(1) */
+ assert_client_banner_accepted("SSH-2.0-OpenSSH-keyscan", 0, 1);
+ assert_int_equal(0, session->openssh);
+ assert_server_banner_accepted("SSH-2.0-OpenSSH-keyscan", 0, 1);
+ assert_int_equal(0, session->openssh);
+
+ ssh_free(session);
+}
+
int torture_run_tests(void) {
int rc;
struct CMUnitTest tests[] = {
@@ -221,6 +362,7 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_path_expand_known_hosts, setup, teardown),
cmocka_unit_test(torture_timeout_elapsed),
cmocka_unit_test(torture_timeout_update),
+ cmocka_unit_test(torture_ssh_analyze_banner),
};
ssh_init();
diff --git a/tests/unittests/torture_options.c b/tests/unittests/torture_options.c
index 820e607d..296b3f1b 100644
--- a/tests/unittests/torture_options.c
+++ b/tests/unittests/torture_options.c
@@ -200,6 +200,7 @@ static void torture_options_proxycommand(void **state) {
}
+#ifdef WITH_SERVER
/* sshbind options */
static int sshbind_setup(void **state)
{
@@ -233,6 +234,7 @@ static void torture_bind_options_import_key(void **state)
ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key);
assert_int_equal(rc, 0);
+#ifdef HAVE_DSA
/* set dsa key */
base64_key = torture_get_testkey(SSH_KEYTYPE_DSS, 0, 0);
ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
@@ -243,7 +245,9 @@ static void torture_bind_options_import_key(void **state)
ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key);
assert_int_equal(rc, 0);
+#endif
}
+#endif /* WITH_SERVER */
int torture_run_tests(void) {
@@ -261,14 +265,18 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_options_proxycommand, setup, teardown),
};
+#ifdef WITH_SERVER
struct CMUnitTest sshbind_tests[] = {
cmocka_unit_test_setup_teardown(torture_bind_options_import_key, sshbind_setup, sshbind_teardown),
};
+#endif /* WITH_SERVER */
ssh_init();
torture_filter_tests(tests);
rc = cmocka_run_group_tests(tests, NULL, NULL);
+#ifdef WITH_SERVER
rc += cmocka_run_group_tests(sshbind_tests, NULL, NULL);
+#endif /* WITH_SERVER */
ssh_finalize();
return rc;
}
diff --git a/tests/unittests/torture_pki.c b/tests/unittests/torture_pki.c
index 8e6e2b63..0b21a569 100644
--- a/tests/unittests/torture_pki.c
+++ b/tests/unittests/torture_pki.c
@@ -6,7 +6,9 @@
#include <fcntl.h>
#define LIBSSH_RSA_TESTKEY "libssh_testkey.id_rsa"
+#ifdef HAVE_DSA
#define LIBSSH_DSA_TESTKEY "libssh_testkey.id_dsa"
+#endif
#define LIBSSH_ECDSA_TESTKEY "libssh_testkey.id_ecdsa"
#define LIBSSH_ED25519_TESTKEY "libssh_testkey.id_ed25519"
@@ -30,6 +32,7 @@ static int setup_rsa_key(void **state)
return 0;
}
+#ifdef HAVE_DSA
static int setup_dsa_key(void **state) {
(void) state; /* unused */
@@ -46,6 +49,7 @@ static int setup_dsa_key(void **state) {
return 0;
}
+#endif
#ifdef HAVE_ECC
static int setup_ecdsa_key(void **state, int ecdsa_bits) {
@@ -101,7 +105,9 @@ static int setup_both_keys(void **state) {
(void) state; /* unused */
setup_rsa_key(state);
+#ifdef HAVE_DSA
setup_dsa_key(state);
+#endif
return 0;
}
@@ -109,9 +115,11 @@ static int setup_both_keys(void **state) {
static int teardown(void **state) {
(void) state; /* unused */
+#ifdef HAVE_DSA
unlink(LIBSSH_DSA_TESTKEY);
unlink(LIBSSH_DSA_TESTKEY ".pub");
unlink(LIBSSH_DSA_TESTKEY "-cert.pub");
+#endif
unlink(LIBSSH_RSA_TESTKEY);
unlink(LIBSSH_RSA_TESTKEY ".pub");
@@ -279,6 +287,7 @@ static void torture_pki_import_privkey_base64_NULL_str(void **state) {
ssh_key_free(key);
}
+#ifdef HAVE_DSA
static void torture_pki_import_privkey_base64_DSA(void **state) {
int rc;
ssh_key key;
@@ -295,6 +304,7 @@ static void torture_pki_import_privkey_base64_DSA(void **state) {
ssh_key_free(key);
}
+#endif
#ifdef HAVE_ECC
static void torture_pki_import_privkey_base64_ECDSA(void **state) {
@@ -347,6 +357,8 @@ static void torture_pki_import_privkey_base64_passphrase(void **state) {
NULL,
&key);
assert_true(rc == -1);
+ ssh_key_free(key);
+ key = NULL;
#ifndef HAVE_LIBCRYPTO
/* test if it returns -1 if passphrase is NULL */
@@ -357,7 +369,10 @@ static void torture_pki_import_privkey_base64_passphrase(void **state) {
NULL,
&key);
assert_true(rc == -1);
+ ssh_key_free(key);
+ key = NULL;
#endif
+#ifdef HAVE_DSA
/* same for DSA */
@@ -382,7 +397,6 @@ static void torture_pki_import_privkey_base64_passphrase(void **state) {
&key);
assert_true(rc == -1);
-#ifndef HAVE_LIBCRYPTO
/* test if it returns -1 if passphrase is NULL */
/* libcrypto asks for a passphrase, so skip this test */
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_DSS, 0, 1),
@@ -391,10 +405,8 @@ static void torture_pki_import_privkey_base64_passphrase(void **state) {
NULL,
&key);
assert_true(rc == -1);
-#endif
-
+# endif
/* same for ED25519 */
-
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_ED25519, 0, 1),
passphrase,
NULL,
@@ -415,7 +427,6 @@ static void torture_pki_import_privkey_base64_passphrase(void **state) {
NULL,
&key);
assert_true(rc == -1);
-
}
static void torture_pki_import_privkey_base64_ed25519(void **state){
@@ -472,6 +483,7 @@ static void torture_pki_pki_publickey_from_privatekey_RSA(void **state) {
ssh_key_free(pubkey);
}
+#ifdef HAVE_DSA
static void torture_pki_pki_publickey_from_privatekey_DSA(void **state) {
int rc;
ssh_key key;
@@ -496,6 +508,7 @@ static void torture_pki_pki_publickey_from_privatekey_DSA(void **state) {
ssh_key_free(key);
ssh_key_free(pubkey);
}
+#endif
static void torture_pki_pki_publickey_from_privatekey_ed25519(void **state){
int rc;
@@ -619,6 +632,7 @@ static void torture_pki_import_cert_file_rsa(void **state) {
ssh_key_free(cert);
}
+#ifdef HAVE_DSA
static void torture_pki_import_cert_file_dsa(void **state) {
int rc;
ssh_key cert;
@@ -674,6 +688,7 @@ static void torture_pki_publickey_dsa_base64(void **state)
free(key_buf);
ssh_key_free(key);
}
+#endif
#ifdef HAVE_ECC
static void torture_pki_publickey_ecdsa_base64(void **state)
@@ -827,6 +842,7 @@ static void torture_generate_pubkey_from_privkey_rsa(void **state) {
ssh_key_free(pubkey);
}
+#ifdef HAVE_DSA
static void torture_generate_pubkey_from_privkey_dsa(void **state) {
char pubkey_generated[4096] = {0};
ssh_key privkey;
@@ -865,6 +881,7 @@ static void torture_generate_pubkey_from_privkey_dsa(void **state) {
ssh_key_free(privkey);
ssh_key_free(pubkey);
}
+#endif
static void torture_generate_pubkey_from_privkey_ed25519(void **state){
char pubkey_generated[4096] = {0};
@@ -995,6 +1012,7 @@ static void torture_pki_duplicate_key_rsa(void **state)
ssh_string_free_char(b64_key_gen);
}
+#ifdef HAVE_DSA
static void torture_pki_duplicate_key_dsa(void **state)
{
int rc;
@@ -1040,6 +1058,7 @@ static void torture_pki_duplicate_key_dsa(void **state)
ssh_string_free_char(b64_key);
ssh_string_free_char(b64_key_gen);
}
+#endif
#ifdef HAVE_ECC
static void torture_pki_duplicate_key_ecdsa(void **state)
@@ -1078,8 +1097,11 @@ static void torture_pki_duplicate_key_ecdsa(void **state)
assert_string_equal(b64_key, b64_key_gen);
+#ifndef HAVE_LIBMBEDCRYPTO
+ /* libmbedcrypto can't compare ecdsa keys */
rc = ssh_key_cmp(privkey, privkey_dup, SSH_KEY_CMP_PRIVATE);
assert_true(rc == 0);
+#endif
ssh_key_free(pubkey);
ssh_key_free(privkey);
@@ -1210,6 +1232,7 @@ static void torture_pki_generate_key_rsa1(void **state)
ssh_free(session);
}
+#ifdef HAVE_DSA
static void torture_pki_generate_key_dsa(void **state)
{
int rc;
@@ -1253,6 +1276,7 @@ static void torture_pki_generate_key_dsa(void **state)
ssh_free(session);
}
+#endif
#ifdef HAVE_ECC
static void torture_pki_generate_key_ecdsa(void **state)
@@ -1476,6 +1500,8 @@ static void torture_pki_write_privkey_ecdsa(void **state)
#endif
#endif /* HAVE_LIBCRYPTO */
+#ifdef HAVE_DSA
+/* TODO mbedtls check if rsa can be used instead of dsa */
static void torture_pki_write_privkey_ed25519(void **state){
ssh_key origkey;
ssh_key privkey;
@@ -1541,6 +1567,7 @@ static void torture_pki_write_privkey_ed25519(void **state){
ssh_key_free(origkey);
ssh_key_free(privkey);
}
+#endif
#ifdef HAVE_ECC
static void torture_pki_ecdsa_name(void **state, const char *expected_name)
@@ -1593,9 +1620,11 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_pki_import_privkey_base64_RSA,
setup_rsa_key,
teardown),
+#ifdef HAVE_DSA
cmocka_unit_test_setup_teardown(torture_pki_import_privkey_base64_DSA,
setup_dsa_key,
teardown),
+#endif
#ifdef HAVE_ECC
cmocka_unit_test_setup_teardown(torture_pki_import_privkey_base64_ECDSA,
setup_ecdsa_key_256,
@@ -1615,9 +1644,11 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_pki_pki_publickey_from_privatekey_RSA,
setup_rsa_key,
teardown),
+#ifdef HAVE_DSA
cmocka_unit_test_setup_teardown(torture_pki_pki_publickey_from_privatekey_DSA,
setup_dsa_key,
teardown),
+#endif
#ifdef HAVE_ECC
cmocka_unit_test_setup_teardown(torture_pki_publickey_from_privatekey_ECDSA,
setup_ecdsa_key_256,
@@ -1648,6 +1679,7 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_pki_import_cert_file_rsa,
setup_rsa_key,
teardown),
+#ifdef HAVE_DSA
cmocka_unit_test_setup_teardown(torture_pki_import_cert_file_dsa,
setup_dsa_key,
teardown),
@@ -1656,6 +1688,7 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_pki_publickey_dsa_base64,
setup_dsa_key,
teardown),
+#endif
cmocka_unit_test_setup_teardown(torture_pki_publickey_rsa_base64,
setup_rsa_key,
teardown),
@@ -1673,9 +1706,11 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_pki_publickey_ed25519_base64,
setup_ed25519_key,
teardown),
+#ifdef HAVE_DSA
cmocka_unit_test_setup_teardown(torture_generate_pubkey_from_privkey_dsa,
setup_dsa_key,
teardown),
+#endif
cmocka_unit_test_setup_teardown(torture_generate_pubkey_from_privkey_rsa,
setup_rsa_key,
teardown),
@@ -1696,9 +1731,11 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_pki_duplicate_key_rsa,
setup_rsa_key,
teardown),
+#ifdef HAVE_DSA
cmocka_unit_test_setup_teardown(torture_pki_duplicate_key_dsa,
setup_dsa_key,
teardown),
+#endif
#ifdef HAVE_ECC
cmocka_unit_test_setup_teardown(torture_pki_duplicate_key_ecdsa,
setup_ecdsa_key_256,
@@ -1710,12 +1747,16 @@ int torture_run_tests(void) {
setup_ecdsa_key_521,
teardown),
#endif
+#ifdef HAVE_DSA
cmocka_unit_test_setup_teardown(torture_pki_duplicate_key_dsa,
setup_dsa_key,
teardown),
+#endif
cmocka_unit_test(torture_pki_generate_key_rsa),
cmocka_unit_test(torture_pki_generate_key_rsa1),
+#ifdef HAVE_DSA
cmocka_unit_test(torture_pki_generate_key_dsa),
+#endif
#ifdef HAVE_ECC
cmocka_unit_test(torture_pki_generate_key_ecdsa),
#endif
@@ -1739,9 +1780,11 @@ int torture_run_tests(void) {
teardown),
#endif
#endif /* HAVE_LIBCRYPTO */
+#ifdef HAVE_DSA
cmocka_unit_test_setup_teardown(torture_pki_write_privkey_ed25519,
setup_dsa_key,
teardown),
+#endif
#ifdef HAVE_ECC
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_name256,
--
2.11.0
| Re: [PATCH] add mbedtls crypto support | Andreas Schneider <asn@xxxxxxxxxxxxxx> |