This file is part of MXE. See LICENSE.md for licensing information. Contains ad hoc patches for cross building. changes from v2.1.3 to d58e20e for openssl 1.1 support remove at next update diff -urN qca-2.1.3/CMakeLists.txt KDE-qca-d58e20e/CMakeLists.txt --- qca-2.1.3/CMakeLists.txt 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/CMakeLists.txt 2018-01-05 06:02:38.000000000 +1100 @@ -15,13 +15,12 @@ endif() set(QCA_LIB_MAJOR_VERSION "2") -set(QCA_LIB_MINOR_VERSION "1") -set(QCA_LIB_PATCH_VERSION "3") +set(QCA_LIB_MINOR_VERSION "2") +set(QCA_LIB_PATCH_VERSION "0") -# Do not automatically link Qt executables to qtmain target on Windows. -# QCA exucatables use console mode only. Not need to link against -# qtmain.lib. -cmake_policy(SET CMP0020 OLD) +if(POLICY CMP0042) + cmake_policy(SET CMP0042 OLD) +endif() option(BUILD_TESTS "Create test" ON) option(BUILD_TOOLS "Compile mozcerts and qcatool" ON) @@ -47,6 +46,9 @@ option(QT4_BUILD "Force building with Qt4 even if Qt5 is found") if (NOT QT4_BUILD) + # Do not automatically link Qt executables to qtmain target on Windows. + # QCA exucatables use console mode only. Not need to link against qtmain.lib. + set(Qt5_NO_LINK_QTMAIN ON) find_package(Qt5Core QUIET) mark_as_advanced(Qt5Core_DIR) endif() @@ -67,6 +69,9 @@ else() set(QT_MIN_VERSION "4.7.0") set(QT_USE_IMPORTED_TARGETS ON) + # Do not automatically link Qt executables to qtmain target on Windows. + # QCA exucatables use console mode only. Not need to link against qtmain.lib. + set(QT4_NO_LINK_QTMAIN ON) if(BUILD_TESTS) find_package(Qt4 REQUIRED QtCore QtNetwork QtTest) else(BUILD_TESTS) diff -urN qca-2.1.3/Doxyfile.in KDE-qca-d58e20e/Doxyfile.in --- qca-2.1.3/Doxyfile.in 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/Doxyfile.in 2018-01-05 06:02:38.000000000 +1100 @@ -1070,7 +1070,7 @@ # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. -EXPAND_AS_DEFINED = QCA_EXPORT +EXPAND_AS_DEFINED = QCA_EXPORT QCA_NOEXCEPT # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone diff -urN qca-2.1.3/cmake/modules/FindCoreFoundation.cmake KDE-qca-d58e20e/cmake/modules/FindCoreFoundation.cmake --- qca-2.1.3/cmake/modules/FindCoreFoundation.cmake 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/cmake/modules/FindCoreFoundation.cmake 1970-01-01 10:00:00.000000000 +1000 @@ -1,13 +0,0 @@ -# Copyright (c) 2014, Samuel Gaist, -# -# Redistribution and use is allowed according to the terms of the BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. - -INCLUDE(CMakeFindFrameworks) - -CMAKE_FIND_FRAMEWORKS(CoreFoundation) - -if (CoreFoundation_FRAMEWORKS) - set(COREFOUNDATION_LIBRARY "-framework CoreFoundation" CACHE FILEPATH "CoreFoundation framework" FORCE) - set(COREFOUNDATION_FOUND 1) -endif (CoreFoundation_FRAMEWORKS) diff -urN qca-2.1.3/include/QtCrypto/qca_basic.h KDE-qca-d58e20e/include/QtCrypto/qca_basic.h --- qca-2.1.3/include/QtCrypto/qca_basic.h 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/include/QtCrypto/qca_basic.h 2018-01-05 06:02:38.000000000 +1100 @@ -2,6 +2,7 @@ * qca_basic.h - Qt Cryptographic Architecture * Copyright (C) 2003-2007 Justin Karneges * Copyright (C) 2004-2007 Brad Hards + * Copyright (C) 2013-2016 Ivan Romanov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -583,6 +584,7 @@ \ingroup UserAPI */ + class QCA_EXPORT Cipher : public Algorithm, public Filter { public: @@ -599,7 +601,9 @@ CFB, ///< operate in %Cipher FeedBack mode ECB, ///< operate in Electronic Code Book mode OFB, ///< operate in Output FeedBack Mode - CTR ///< operate in CounTer Mode + CTR, ///< operate in CounTer Mode + GCM, ///< operate in Galois Counter Mode + CCM ///< operate in Counter with CBC-MAC }; /** @@ -637,6 +641,28 @@ const QString &provider = QString()); /** + Standard constructor + + \param type the name of the cipher specialisation to use (e.g. + "aes128") + \param mode the operating Mode to use (e.g. QCA::Cipher::CBC) + \param pad the type of Padding to use + \param dir the Direction that this Cipher should use (Encode for + encryption, Decode for decryption) + \param key the SymmetricKey array that is the key + \param iv the InitializationVector to use (not used for ECB mode) + \param tag the AuthTag to use (only for GCM and CCM modes) + \param provider the name of the Provider to use + + \note Padding only applies to CBC and ECB modes. CFB and OFB + ciphertext is always the length of the plaintext. + */ + Cipher(const QString &type, Mode mode, Padding pad, + Direction dir, const SymmetricKey &key, + const InitializationVector &iv, const AuthTag &tag, + const QString &provider = QString()); + + /** Standard copy constructor \param from the Cipher to copy state from @@ -700,6 +726,11 @@ int blockSize() const; /** + return the authentication tag for the cipher object + */ + AuthTag tag() const; + + /** reset the cipher object, to allow re-use */ virtual void clear(); @@ -742,6 +773,22 @@ void setup(Direction dir, const SymmetricKey &key, const InitializationVector &iv = InitializationVector()); /** + Reset / reconfigure the Cipher + + You can use this to re-use an existing Cipher, rather than creating + a new object with a slightly different configuration. + + \param dir the Direction that this Cipher should use (Encode for + encryption, Decode for decryption) + \param key the SymmetricKey array that is the key + \param iv the InitializationVector to use (not used for ECB Mode) + \param tag the AuthTag to use (only for GCM and CCM modes) + + \note You should not leave iv empty for any Mode except ECB. + */ + void setup(Direction dir, const SymmetricKey &key, const InitializationVector &iv, const AuthTag &tag); + + /** Construct a Cipher type string \param cipherType the name of the algorithm (eg AES128, DES) @@ -751,7 +798,6 @@ QCA::PCKS7) */ static QString withAlgorithms(const QString &cipherType, Mode modeType, Padding paddingType); - private: class Private; Private *d; diff -urN qca-2.1.3/include/QtCrypto/qca_core.h KDE-qca-d58e20e/include/QtCrypto/qca_core.h --- qca-2.1.3/include/QtCrypto/qca_core.h 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/include/QtCrypto/qca_core.h 2018-01-05 06:02:38.000000000 +1100 @@ -2,6 +2,7 @@ * qca_core.h - Qt Cryptographic Architecture * Copyright (C) 2003-2007 Justin Karneges * Copyright (C) 2004,2005 Brad Hards + * Copyright (C) 2014-2016 Ivan Romanov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -491,8 +492,8 @@ */ #define QCA_logTextMessage(message, severity) \ do { \ - register QCA::Logger::Severity s = severity; \ - register QCA::Logger *l = QCA::logger (); \ + QCA::Logger::Severity s = severity; \ + QCA::Logger *l = QCA::logger (); \ if (s <= l->level ()) { \ l->logTextMessage (message, s); \ } \ @@ -510,8 +511,8 @@ */ #define QCA_logBinaryMessage(blob, severity) \ do { \ - register QCA::Logger::Severity s = severity; \ - register QCA::Logger *l = QCA::logger (); \ + QCA::Logger::Severity s = severity; \ + QCA::Logger *l = QCA::logger (); \ if (s <= l->level ()) { \ l->logBinaryMessage (blob, s); \ } \ @@ -619,6 +620,32 @@ QCA_EXPORT QByteArray hexToArray(const QString &hexString); /** + Convert a byte array to printable base64 + representation. + + This is a convenience function to convert an arbitrary + QByteArray to a printable representation. + + \param array the array to be converted + \return a printable representation +*/ +QCA_EXPORT QString arrayToBase64(const QByteArray &array); + +/** + Convert a QString containing a base64 representation + of a byte array into a QByteArray + + This is a convenience function to convert a printable + representation into a QByteArray - effectively the inverse + of QCA::arrayToBase64. + + \param base64String the string containing a printable + representation to be converted + \return the equivalent QByteArray +*/ +QCA_EXPORT QByteArray base64ToArray(const QString &base64String); + +/** \class Initializer qca_core.h QtCrypto Convenience method for initialising and cleaning up %QCA @@ -1295,6 +1322,43 @@ }; /** + \class AuthTag qca_core.h QtCrypto + + Container for authentication tag + + \ingroup UserAPI +*/ +class QCA_EXPORT AuthTag : public SecureArray +{ +public: + /** + Construct an empty authentication tag + */ + AuthTag(); + + /** + Construct an empty authentication tag of the specified size + + \param size the length of the authentication tag, in bytes + */ + AuthTag(int size); + + /** + Construct an authentication tag from a provided byte array + + \param a the byte array to copy + */ + AuthTag(const SecureArray &a); + + /** + Construct an authentication tag from a provided byte array + + \param a the byte array to copy + */ + AuthTag(const QByteArray &a); +}; + +/** \class Event qca_core.h QtCrypto An asynchronous event diff -urN qca-2.1.3/include/QtCrypto/qcaprovider.h KDE-qca-d58e20e/include/QtCrypto/qcaprovider.h --- qca-2.1.3/include/QtCrypto/qcaprovider.h 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/include/QtCrypto/qcaprovider.h 2018-01-05 06:02:38.000000000 +1100 @@ -234,8 +234,9 @@ \param dir the direction for the cipher (encryption/decryption) \param key the symmetric key to use for the cipher \param iv the initialization vector to use for the cipher (not used in ECB mode) + \param tag the AuthTag to use (only for GCM and CCM modes) */ - virtual void setup(Direction dir, const SymmetricKey &key, const InitializationVector &iv) = 0; + virtual void setup(Direction dir, const SymmetricKey &key, const InitializationVector &iv, const AuthTag &tag) = 0; /** Returns the KeyLength for this cipher @@ -248,6 +249,11 @@ virtual int blockSize() const = 0; /** + Returns the authentication tag for this cipher + */ + virtual AuthTag tag() const = 0; + + /** Process a chunk of data. Returns true if successful. \param in the input data to process diff -urN qca-2.1.3/plugins/qca-botan/qca-botan.cpp KDE-qca-d58e20e/plugins/qca-botan/qca-botan.cpp --- qca-2.1.3/plugins/qca-botan/qca-botan.cpp 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/plugins/qca-botan/qca-botan.cpp 2018-01-05 06:02:38.000000000 +1100 @@ -263,8 +263,10 @@ void setup(QCA::Direction dir, const QCA::SymmetricKey &key, - const QCA::InitializationVector &iv) + const QCA::InitializationVector &iv, + const QCA::AuthTag &tag) { + Q_UNUSED(tag); try { m_dir = dir; Botan::SymmetricKey keyCopy((Botan::byte*)key.data(), key.size()); @@ -305,6 +307,12 @@ return Botan::block_size_of(m_algoName); } + QCA::AuthTag tag() const + { + // For future implementation + return QCA::AuthTag(); + } + bool update(const QCA::SecureArray &in, QCA::SecureArray *out) { m_crypter->write((Botan::byte*)in.data(), in.size()); diff -urN qca-2.1.3/plugins/qca-gcrypt/qca-gcrypt.cpp KDE-qca-d58e20e/plugins/qca-gcrypt/qca-gcrypt.cpp --- qca-2.1.3/plugins/qca-gcrypt/qca-gcrypt.cpp 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/plugins/qca-gcrypt/qca-gcrypt.cpp 2018-01-05 06:02:38.000000000 +1100 @@ -163,8 +163,10 @@ void setup(QCA::Direction dir, const QCA::SymmetricKey &key, - const QCA::InitializationVector &iv) + const QCA::InitializationVector &iv, + const QCA::AuthTag &tag) { + Q_UNUSED(tag); m_direction = dir; err = gcry_cipher_open( &context, m_cryptoAlgorithm, m_mode, 0 ); check_error( "gcry_cipher_open", err ); @@ -195,6 +197,12 @@ return blockSize; } + QCA::AuthTag tag() const + { + // For future implementation + return QCA::AuthTag(); + } + bool update(const QCA::SecureArray &in, QCA::SecureArray *out) { QCA::SecureArray result( in.size() ); diff -urN qca-2.1.3/plugins/qca-gnupg/CMakeLists.txt KDE-qca-d58e20e/plugins/qca-gnupg/CMakeLists.txt --- qca-2.1.3/plugins/qca-gnupg/CMakeLists.txt 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/plugins/qca-gnupg/CMakeLists.txt 2018-01-05 06:02:38.000000000 +1100 @@ -21,6 +21,23 @@ gpgproc/gpgproc.cpp ) +set(QCA_GNUPG_HEADERS + gpgaction.h + ringwatch.h + gpgop.h + gpgop_p.h + lineconverter.h + mypgpkeycontext.h + mykeystoreentry.h + mykeystorelist.h + gpgproc/gpgproc_p.h + gpgproc/sprocess.h + gpgproc/gpgproc.h + utils.h + mymessagecontext.h + myopenpgpcontext.h +) + my_automoc(QCA_GNUPG_MOC_SOURCES) qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgop.h) @@ -33,7 +50,7 @@ qt4_wrap_cpp(EXTRA_GNUPG_SOURCES mymessagecontext.h) qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgaction.h) -add_library(qca-gnupg ${PLUGIN_TYPE} ${QCA_GNUPG_MOC_SOURCES} ${QCA_GNUPG_NONMOC_SOURCES} ${EXTRA_GNUPG_SOURCES}) +add_library(qca-gnupg ${PLUGIN_TYPE} ${QCA_GNUPG_MOC_SOURCES} ${QCA_GNUPG_NONMOC_SOURCES} ${EXTRA_GNUPG_SOURCES} ${QCA_GNUPG_HEADERS}) if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE") set_property(TARGET qca-gnupg PROPERTY SUFFIX ".dylib") diff -urN qca-2.1.3/plugins/qca-nss/qca-nss.cpp KDE-qca-d58e20e/plugins/qca-nss/qca-nss.cpp --- qca-2.1.3/plugins/qca-nss/qca-nss.cpp 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/plugins/qca-nss/qca-nss.cpp 2018-01-05 06:02:38.000000000 +1100 @@ -304,10 +304,12 @@ { } - void setup( QCA::Direction dir, - const QCA::SymmetricKey &key, - const QCA::InitializationVector &iv ) + void setup(QCA::Direction dir, + const QCA::SymmetricKey &key, + const QCA::InitializationVector &iv, + const QCA::AuthTag &tag) { + Q_UNUSED(tag); /* Get a slot to use for the crypto operations */ m_slot = PK11_GetBestSlot( m_cipherMechanism, NULL ); if (!m_slot) @@ -365,6 +367,12 @@ return PK11_GetBlockSize( m_cipherMechanism, m_params); } + QCA::AuthTag tag() const + { + // For future implementation + return QCA::AuthTag(); + } + bool update( const QCA::SecureArray &in, QCA::SecureArray *out ) { out->resize(in.size()+blockSize()); diff -urN qca-2.1.3/plugins/qca-ossl/CMakeLists.txt KDE-qca-d58e20e/plugins/qca-ossl/CMakeLists.txt --- qca-2.1.3/plugins/qca-ossl/CMakeLists.txt 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/plugins/qca-ossl/CMakeLists.txt 2018-01-05 06:02:38.000000000 +1100 @@ -25,6 +25,20 @@ message(WARNING "qca-ossl will be compiled without AES CTR mode encryption support") endif(HAVE_OPENSSL_AES_CTR) + check_function_exists(EVP_aes_128_gcm HAVE_OPENSSL_AES_GCM) + if(HAVE_OPENSSL_AES_GCM) + add_definitions(-DHAVE_OPENSSL_AES_GCM) + else() + message(WARNING "qca-ossl will be compiled without AES GCM mode encryption support") + endif() + + check_function_exists(EVP_aes_128_ccm HAVE_OPENSSL_AES_CCM) + if(HAVE_OPENSSL_AES_CCM) + add_definitions(-DHAVE_OPENSSL_AES_CCM) + else() + message(WARNING "qca-ossl will be compiled without AES CCM mode encryption support") + endif() + check_function_exists(EVP_sha HAVE_OPENSSL_SHA0) if(HAVE_OPENSSL_SHA0) add_definitions(-DHAVE_OPENSSL_SHA0) diff -urN qca-2.1.3/plugins/qca-ossl/ossl110-compat.h KDE-qca-d58e20e/plugins/qca-ossl/ossl110-compat.h --- qca-2.1.3/plugins/qca-ossl/ossl110-compat.h 1970-01-01 10:00:00.000000000 +1000 +++ KDE-qca-d58e20e/plugins/qca-ossl/ossl110-compat.h 2018-01-05 06:02:38.000000000 +1100 @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2017 Gabriel Souza Franco + * + * This 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. + * + * This 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#ifndef OSSL110COMPAT_H +#define OSSL110COMPAT_H + +#include +#include +#include +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define RSA_F_RSA_METH_DUP 161 + +static void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +{ + if (pr) + *pr = sig->r; + if (ps) + *ps = sig->s; +} + +static int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + if (!sig) return 0; + sig->r = r; + sig->s = s; + return 1; +} + +static void DSA_get0_pqg(const DSA *dsa, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) +{ + if (p) + *p = dsa->p; + if (q) + *q = dsa->q; + if (g) + *g = dsa->g; +} + +static int DSA_set0_pqg(DSA *dsa, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + if (!dsa) return 0; + dsa->p = p; + dsa->q = q; + dsa->g = g; + return 1; +} + +static void RSA_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) +{ + if (n) + *n = rsa->n; + if (e) + *e = rsa->e; + if (d) + *d = rsa->d; +} + +static int RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d) +{ + if (!rsa) return 0; + rsa->n = n; + rsa->e = e; + rsa->d = d; + return 1; +} + +static void RSA_get0_factors(const RSA *rsa, const BIGNUM **p, const BIGNUM **q) +{ + if (p) + *p = rsa->p; + if (q) + *q = rsa->q; +} + +static int RSA_set0_factors(RSA *rsa, BIGNUM *p, BIGNUM *q) +{ + if (!rsa) return 0; + rsa->p = p; + rsa->q = q; + return 1; +} + +static void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) +{ + if (p) + *p = dh->p; + if (q) + *q = dh->q; + if (g) + *g = dh->g; +} + +static int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + if (!dh) return 0; + dh->p = p; + dh->q = q; + dh->g = g; + return 1; +} + +static void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) +{ + if (pub_key) + *pub_key = dh->pub_key; + if (priv_key) + *priv_key = dh->priv_key; +} + +static int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) +{ + if (!dh) return 0; + dh->pub_key = pub_key; + dh->priv_key = priv_key; + return 1; +} + +static void DSA_get0_key(const DSA *dsa, const BIGNUM **pub_key, const BIGNUM **priv_key) +{ + if (pub_key) + *pub_key = dsa->pub_key; + if (priv_key) + *priv_key = dsa->priv_key; +} + +static int DSA_set0_key(DSA *dsa, BIGNUM *pub_key, BIGNUM *priv_key) +{ + if (!dsa) return 0; + dsa->pub_key = pub_key; + dsa->priv_key = priv_key; + return 1; +} + +static void X509_SIG_getm(const X509_SIG *sig, X509_ALGOR **palg, ASN1_OCTET_STRING **pdigest) +{ + if (palg) + *palg = sig->algor; + if (pdigest) + *pdigest = sig->digest; +} + +static void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig, const X509_ALGOR **palg) +{ + if (psig) + *psig = req->signature; + if (palg) + *palg = req->sig_alg; +} + +static void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, const X509_ALGOR **palg) +{ + if (psig) + *psig = crl->signature; + if (palg) + *palg = crl->sig_alg; +} + +static RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth) +{ + if (!meth) + return NULL; + + RSA_METHOD *_meth = (RSA_METHOD *) OPENSSL_malloc(sizeof(*_meth)); + + if (!_meth) + { + RSAerr(RSA_F_RSA_METH_DUP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memcpy(_meth, meth, sizeof(*_meth)); + _meth->name = strdup(meth->name); + if (!_meth->name) { + OPENSSL_free(_meth); + RSAerr(RSA_F_RSA_METH_DUP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + return _meth; +} + +static int RSA_meth_set_priv_enc(RSA_METHOD *rsa, int (*priv_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding)) +{ + if (!rsa) return 0; + rsa->rsa_priv_enc = priv_enc; + return 1; +} + +static int RSA_meth_set_priv_dec(RSA_METHOD *rsa, int (*priv_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding)) +{ + if (!rsa) return 0; + rsa->rsa_priv_dec = priv_dec; + return 1; +} + +static int RSA_meth_set_sign(RSA_METHOD *meth, int (*sign) (int type, const unsigned char *m, + unsigned int m_length, unsigned char *sigret, unsigned int *siglen, const RSA *rsa)) +{ + if (!meth) return 0; + meth->rsa_sign = sign; + return 1; +} + +static int RSA_meth_set_verify(RSA_METHOD *meth, int (*verify) (int dtype, const unsigned char *m, + unsigned int m_length, const unsigned char *sigbuf, unsigned int siglen, const RSA *rsa)) +{ + if (!meth) return 0; + meth->rsa_verify = verify; + return 1; +} + +static int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa)) +{ + if (!meth) return 0; + meth->finish = finish; + return 1; +} + +static HMAC_CTX *HMAC_CTX_new() +{ + HMAC_CTX *ctx = (HMAC_CTX *) OPENSSL_malloc(sizeof(HMAC_CTX)); + if (ctx) + HMAC_CTX_init(ctx); + return ctx; +} + +static void HMAC_CTX_free(HMAC_CTX *ctx) +{ + if (!ctx) + return; + HMAC_CTX_cleanup(ctx); + EVP_MD_CTX_cleanup(&ctx->i_ctx); + EVP_MD_CTX_cleanup(&ctx->o_ctx); + EVP_MD_CTX_cleanup(&ctx->md_ctx); + OPENSSL_free(ctx); +} + +#define ASN1_STRING_get0_data(...) (const unsigned char*)ASN1_STRING_data(__VA_ARGS__) + +#define EVP_MD_CTX_new(...) EVP_MD_CTX_create(__VA_ARGS__) +#define EVP_MD_CTX_free(...) EVP_MD_CTX_destroy(__VA_ARGS__) + +#define EVP_PKEY_up_ref(pkey) CRYPTO_add(&(pkey)->references, 1, CRYPTO_LOCK_EVP_PKEY) +#define X509_up_ref(cert) CRYPTO_add(&(cert)->references, 1, CRYPTO_LOCK_X509) +#define X509_CRL_up_ref(crl) CRYPTO_add(&(crl)->references, 1, CRYPTO_LOCK_X509_CRL) + +#define EVP_PKEY_id(pky) (pky)->type +#define EVP_PKEY_get0_DSA(pky) (pky)->pkey.dsa +#define EVP_PKEY_get0_RSA(pky) (pky)->pkey.rsa +#define EVP_PKEY_get0_DH(pky) (pky)->pkey.dh + +#define X509_CRL_get0_lastUpdate X509_CRL_get_lastUpdate +#define X509_CRL_get0_nextUpdate X509_CRL_get_nextUpdate + +#define X509_REQ_get_signature_nid(req) OBJ_obj2nid((req)->sig_alg->algorithm) +#define X509_CRL_get_signature_nid(crl) OBJ_obj2nid((crl)->sig_alg->algorithm) + +#define X509_REVOKED_get0_serialNumber(rev) (rev)->serialNumber +#define X509_REVOKED_get0_revocationDate(rev) (rev)->revocationDate + +#endif // OPENSSL_VERSION_NUMBER < 0x10100000L + +#endif // OSSL110COMPAT_H diff -urN qca-2.1.3/plugins/qca-ossl/qca-ossl.cpp KDE-qca-d58e20e/plugins/qca-ossl/qca-ossl.cpp --- qca-2.1.3/plugins/qca-ossl/qca-ossl.cpp 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/plugins/qca-ossl/qca-ossl.cpp 2018-01-05 06:02:38.000000000 +1100 @@ -1,6 +1,8 @@ /* * Copyright (C) 2004-2007 Justin Karneges * Copyright (C) 2004-2006 Brad Hards + * Copyright (C) 2013-2016 Ivan Romanov + * Copyright (C) 2017 Fabian Vogt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -38,6 +40,8 @@ #include #include +#include "ossl110-compat.h" + #ifndef OSSL_097 // comment this out if you'd rather use openssl 0.9.6 #define OSSL_097 @@ -52,6 +56,16 @@ ((_STACK*) (1 ? p : (type*)0)) #endif +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + #define OSSL_110 +#endif + +// OpenSSL 1.1.0 compatibility macros +#ifdef OSSL_110 +#define M_ASN1_IA5STRING_new() ASN1_IA5STRING_new() +#define RSA_F_RSA_EAY_PRIVATE_DECRYPT RSA_F_RSA_OSSL_PRIVATE_DECRYPT +#endif + using namespace QCA; namespace opensslQCAPlugin { @@ -93,7 +107,7 @@ return buf; } -static BigInteger bn2bi(BIGNUM *n) +static BigInteger bn2bi(const BIGNUM *n) { SecureArray buf(BN_num_bytes(n) + 1); buf[0] = 0; // positive @@ -109,7 +123,7 @@ // take lowest bytes of BIGNUM to fit // pad with high byte zeroes to fit -static SecureArray bn2fixedbuf(BIGNUM *n, int size) +static SecureArray bn2fixedbuf(const BIGNUM *n, int size) { SecureArray buf(BN_num_bytes(n)); BN_bn2bin(n, (unsigned char *)buf.data()); @@ -127,8 +141,11 @@ const unsigned char *inp = (const unsigned char *)in.data(); d2i_DSA_SIG(&sig, &inp, in.size()); - SecureArray part_r = bn2fixedbuf(sig->r, 20); - SecureArray part_s = bn2fixedbuf(sig->s, 20); + const BIGNUM *bnr, *bns; + DSA_SIG_get0(sig, &bnr, &bns); + + SecureArray part_r = bn2fixedbuf(bnr, 20); + SecureArray part_s = bn2fixedbuf(bns, 20); SecureArray result; result.append(part_r); result.append(part_s); @@ -143,12 +160,16 @@ return SecureArray(); DSA_SIG *sig = DSA_SIG_new(); - SecureArray part_r(20); - SecureArray part_s(20); + SecureArray part_r(20); BIGNUM *bnr; + SecureArray part_s(20); BIGNUM *bns; memcpy(part_r.data(), in.data(), 20); memcpy(part_s.data(), in.data() + 20, 20); - sig->r = BN_bin2bn((const unsigned char *)part_r.data(), part_r.size(), NULL); - sig->s = BN_bin2bn((const unsigned char *)part_s.data(), part_s.size(), NULL); + bnr = BN_bin2bn((const unsigned char *)part_r.data(), part_r.size(), NULL); + bns = BN_bin2bn((const unsigned char *)part_s.data(), part_s.size(), NULL); + + if(DSA_SIG_set0(sig, bnr, bns) == 0) + return SecureArray(); + // Not documented what happens in the failure case, free bnr and bns? int len = i2d_DSA_SIG(sig, NULL); SecureArray result(len); @@ -1004,29 +1025,39 @@ opensslHashContext(const EVP_MD *algorithm, Provider *p, const QString &type) : HashContext(p, type) { m_algorithm = algorithm; - EVP_DigestInit( &m_context, m_algorithm ); + m_context = EVP_MD_CTX_new(); + EVP_DigestInit( m_context, m_algorithm ); + } + + opensslHashContext(const opensslHashContext &other) + : HashContext(other) + { + m_algorithm = other.m_algorithm; + m_context = EVP_MD_CTX_new(); + EVP_MD_CTX_copy_ex(m_context, other.m_context); } ~opensslHashContext() { - EVP_MD_CTX_cleanup(&m_context); + EVP_MD_CTX_free(m_context); } void clear() { - EVP_MD_CTX_cleanup(&m_context); - EVP_DigestInit( &m_context, m_algorithm ); + EVP_MD_CTX_free(m_context); + m_context = EVP_MD_CTX_new(); + EVP_DigestInit( m_context, m_algorithm ); } void update(const MemoryRegion &a) { - EVP_DigestUpdate( &m_context, (unsigned char*)a.data(), a.size() ); + EVP_DigestUpdate( m_context, (unsigned char*)a.data(), a.size() ); } MemoryRegion final() { SecureArray a( EVP_MD_size( m_algorithm ) ); - EVP_DigestFinal( &m_context, (unsigned char*)a.data(), 0 ); + EVP_DigestFinal( m_context, (unsigned char*)a.data(), 0 ); return a; } @@ -1037,7 +1068,7 @@ protected: const EVP_MD *m_algorithm; - EVP_MD_CTX m_context; + EVP_MD_CTX *m_context; }; @@ -1047,7 +1078,21 @@ opensslPbkdf1Context(const EVP_MD *algorithm, Provider *p, const QString &type) : KDFContext(p, type) { m_algorithm = algorithm; - EVP_DigestInit( &m_context, m_algorithm ); + m_context = EVP_MD_CTX_new(); + EVP_DigestInit( m_context, m_algorithm ); + } + + opensslPbkdf1Context(const opensslPbkdf1Context &other) + : KDFContext(other) + { + m_algorithm = other.m_algorithm; + m_context = EVP_MD_CTX_new(); + EVP_MD_CTX_copy(m_context, other.m_context); + } + + ~opensslPbkdf1Context() + { + EVP_MD_CTX_free(m_context); } Provider::Context *clone() const @@ -1081,16 +1126,16 @@ DK = Tc<0..dkLen-1> */ // calculate T_1 - EVP_DigestUpdate( &m_context, (unsigned char*)secret.data(), secret.size() ); - EVP_DigestUpdate( &m_context, (unsigned char*)salt.data(), salt.size() ); + EVP_DigestUpdate( m_context, (unsigned char*)secret.data(), secret.size() ); + EVP_DigestUpdate( m_context, (unsigned char*)salt.data(), salt.size() ); SecureArray a( EVP_MD_size( m_algorithm ) ); - EVP_DigestFinal( &m_context, (unsigned char*)a.data(), 0 ); + EVP_DigestFinal( m_context, (unsigned char*)a.data(), 0 ); // calculate T_2 up to T_c for ( unsigned int i = 2; i <= iterationCount; ++i ) { - EVP_DigestInit( &m_context, m_algorithm ); - EVP_DigestUpdate( &m_context, (unsigned char*)a.data(), a.size() ); - EVP_DigestFinal( &m_context, (unsigned char*)a.data(), 0 ); + EVP_DigestInit( m_context, m_algorithm ); + EVP_DigestUpdate( m_context, (unsigned char*)a.data(), a.size() ); + EVP_DigestFinal( m_context, (unsigned char*)a.data(), 0 ); } // shrink a to become DK, of the required length @@ -1136,19 +1181,19 @@ DK = Tc<0..dkLen-1> */ // calculate T_1 - EVP_DigestUpdate( &m_context, (unsigned char*)secret.data(), secret.size() ); - EVP_DigestUpdate( &m_context, (unsigned char*)salt.data(), salt.size() ); + EVP_DigestUpdate( m_context, (unsigned char*)secret.data(), secret.size() ); + EVP_DigestUpdate( m_context, (unsigned char*)salt.data(), salt.size() ); SecureArray a( EVP_MD_size( m_algorithm ) ); - EVP_DigestFinal( &m_context, (unsigned char*)a.data(), 0 ); + EVP_DigestFinal( m_context, (unsigned char*)a.data(), 0 ); // calculate T_2 up to T_c *iterationCount = 2 - 1; // <- Have to remove 1, unless it computes one timer.start(); // ^ time more than the base function // ^ with the same iterationCount while (timer.elapsed() < msecInterval) { - EVP_DigestInit( &m_context, m_algorithm ); - EVP_DigestUpdate( &m_context, (unsigned char*)a.data(), a.size() ); - EVP_DigestFinal( &m_context, (unsigned char*)a.data(), 0 ); + EVP_DigestInit( m_context, m_algorithm ); + EVP_DigestUpdate( m_context, (unsigned char*)a.data(), a.size() ); + EVP_DigestFinal( m_context, (unsigned char*)a.data(), 0 ); ++(*iterationCount); } @@ -1163,7 +1208,7 @@ protected: const EVP_MD *m_algorithm; - EVP_MD_CTX m_context; + EVP_MD_CTX *m_context; }; class opensslPbkdf2Context : public KDFContext @@ -1231,12 +1276,28 @@ opensslHMACContext(const EVP_MD *algorithm, Provider *p, const QString &type) : MACContext(p, type) { m_algorithm = algorithm; - HMAC_CTX_init( &m_context ); + m_context = HMAC_CTX_new(); +#ifndef OSSL_110 + HMAC_CTX_init( m_context ); +#endif + } + + opensslHMACContext(const opensslHMACContext &other) + : MACContext(other) + { + m_algorithm = other.m_algorithm; + m_context = HMAC_CTX_new(); + HMAC_CTX_copy(m_context, other.m_context); + } + + ~opensslHMACContext() + { + HMAC_CTX_free(m_context); } void setup(const SymmetricKey &key) { - HMAC_Init_ex( &m_context, key.data(), key.size(), m_algorithm, 0 ); + HMAC_Init_ex( m_context, key.data(), key.size(), m_algorithm, 0 ); } KeyLength keyLength() const @@ -1246,14 +1307,18 @@ void update(const MemoryRegion &a) { - HMAC_Update( &m_context, (unsigned char *)a.data(), a.size() ); + HMAC_Update( m_context, (unsigned char *)a.data(), a.size() ); } void final(MemoryRegion *out) { SecureArray sa( EVP_MD_size( m_algorithm ), 0 ); - HMAC_Final(&m_context, (unsigned char *)sa.data(), 0 ); - HMAC_CTX_cleanup(&m_context); + HMAC_Final(m_context, (unsigned char *)sa.data(), 0 ); +#ifdef OSSL_110 + HMAC_CTX_reset(m_context); +#else + HMAC_CTX_cleanup(m_context); +#endif *out = sa; } @@ -1263,7 +1328,7 @@ } protected: - HMAC_CTX m_context; + HMAC_CTX *m_context; const EVP_MD *m_algorithm; }; @@ -1277,7 +1342,7 @@ public: enum State { Idle, SignActive, SignError, VerifyActive, VerifyError }; EVP_PKEY *pkey; - EVP_MD_CTX mdctx; + EVP_MD_CTX *mdctx; State state; bool raw_type; SecureArray raw; @@ -1287,19 +1352,23 @@ pkey = 0; raw_type = false; state = Idle; + mdctx = EVP_MD_CTX_new(); } EVPKey(const EVPKey &from) { pkey = from.pkey; - CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); + EVP_PKEY_up_ref(pkey); raw_type = false; state = Idle; + mdctx = EVP_MD_CTX_new(); + EVP_MD_CTX_copy(mdctx, from.mdctx); } ~EVPKey() { reset(); + EVP_MD_CTX_free(mdctx); } void reset() @@ -1322,8 +1391,8 @@ else { raw_type = false; - EVP_MD_CTX_init(&mdctx); - if(!EVP_SignInit_ex(&mdctx, type, NULL)) + EVP_MD_CTX_init(mdctx); + if(!EVP_SignInit_ex(mdctx, type, NULL)) state = SignError; } } @@ -1339,8 +1408,8 @@ else { raw_type = false; - EVP_MD_CTX_init(&mdctx); - if(!EVP_VerifyInit_ex(&mdctx, type, NULL)) + EVP_MD_CTX_init(mdctx); + if(!EVP_VerifyInit_ex(mdctx, type, NULL)) state = VerifyError; } } @@ -1352,7 +1421,7 @@ if (raw_type) raw += in; else - if(!EVP_SignUpdate(&mdctx, in.data(), (unsigned int)in.size())) + if(!EVP_SignUpdate(mdctx, in.data(), (unsigned int)in.size())) state = SignError; } else if(state == VerifyActive) @@ -1360,7 +1429,7 @@ if (raw_type) raw += in; else - if(!EVP_VerifyUpdate(&mdctx, in.data(), (unsigned int)in.size())) + if(!EVP_VerifyUpdate(mdctx, in.data(), (unsigned int)in.size())) state = VerifyError; } } @@ -1373,17 +1442,20 @@ unsigned int len = out.size(); if (raw_type) { - if (pkey->type == EVP_PKEY_RSA) + int type = EVP_PKEY_id(pkey); + + if (type == EVP_PKEY_RSA) { + RSA *rsa = EVP_PKEY_get0_RSA(pkey); if(RSA_private_encrypt (raw.size(), (unsigned char *)raw.data(), - (unsigned char *)out.data(), pkey->pkey.rsa, + (unsigned char *)out.data(), rsa, RSA_PKCS1_PADDING) == -1) { state = SignError; return SecureArray (); } } - else if (pkey->type == EVP_PKEY_DSA) + else if (type == EVP_PKEY_DSA) { state = SignError; return SecureArray (); @@ -1395,7 +1467,7 @@ } } else { - if(!EVP_SignFinal(&mdctx, (unsigned char *)out.data(), &len, pkey)) + if(!EVP_SignFinal(mdctx, (unsigned char *)out.data(), &len, pkey)) { state = SignError; return SecureArray(); @@ -1418,16 +1490,19 @@ SecureArray out(EVP_PKEY_size(pkey)); int len = 0; - if (pkey->type == EVP_PKEY_RSA) { + int type = EVP_PKEY_id(pkey); + + if (type == EVP_PKEY_RSA) { + RSA *rsa = EVP_PKEY_get0_RSA(pkey); if((len = RSA_public_decrypt (sig.size(), (unsigned char *)sig.data(), - (unsigned char *)out.data (), pkey->pkey.rsa, + (unsigned char *)out.data (), rsa, RSA_PKCS1_PADDING)) == -1) { state = VerifyError; return false; } } - else if (pkey->type == EVP_PKEY_DSA) + else if (type == EVP_PKEY_DSA) { state = VerifyError; return false; @@ -1447,7 +1522,7 @@ } else { - if(EVP_VerifyFinal(&mdctx, (unsigned char *)sig.data(), (unsigned int)sig.size(), pkey) != 1) + if(EVP_VerifyFinal(mdctx, (unsigned char *)sig.data(), (unsigned int)sig.size(), pkey) != 1) { state = VerifyError; return false; @@ -1561,9 +1636,11 @@ return false; if(ret_counter != counter) return false; - params->p = bn2bi(dsa->p); - params->q = bn2bi(dsa->q); - params->g = bn2bi(dsa->g); + const BIGNUM *bnp, *bnq, *bng; + DSA_get0_pqg(dsa, &bnp, &bnq, &bng); + params->p = bn2bi(bnp); + params->q = bn2bi(bnq); + params->g = bn2bi(bng); DSA_free(dsa); return true; } @@ -1826,10 +1903,11 @@ return; // extract the public key into DER format - int len = i2d_RSAPublicKey(evp.pkey->pkey.rsa, NULL); + RSA *rsa_pkey = EVP_PKEY_get0_RSA(evp.pkey); + int len = i2d_RSAPublicKey(rsa_pkey, NULL); SecureArray result(len); unsigned char *p = (unsigned char *)result.data(); - i2d_RSAPublicKey(evp.pkey->pkey.rsa, &p); + i2d_RSAPublicKey(rsa_pkey, &p); p = (unsigned char *)result.data(); // put the DER public key back into openssl @@ -1852,7 +1930,7 @@ virtual int maximumEncryptSize(EncryptionAlgorithm alg) const { - RSA *rsa = evp.pkey->pkey.rsa; + RSA *rsa = EVP_PKEY_get0_RSA(evp.pkey); int size = 0; switch(alg) { @@ -1867,7 +1945,7 @@ virtual SecureArray encrypt(const SecureArray &in, EncryptionAlgorithm alg) { - RSA *rsa = evp.pkey->pkey.rsa; + RSA *rsa = EVP_PKEY_get0_RSA(evp.pkey); SecureArray buf = in; int max = maximumEncryptSize(alg); @@ -1900,7 +1978,7 @@ virtual bool decrypt(const SecureArray &in, SecureArray *out, EncryptionAlgorithm alg) { - RSA *rsa = evp.pkey->pkey.rsa; + RSA *rsa = EVP_PKEY_get0_RSA(evp.pkey); SecureArray result(RSA_size(rsa)); int pad; @@ -2021,14 +2099,10 @@ evp.reset(); RSA *rsa = RSA_new(); - rsa->n = bi2bn(n); - rsa->e = bi2bn(e); - rsa->p = bi2bn(p); - rsa->q = bi2bn(q); - rsa->d = bi2bn(d); - - if(!rsa->n || !rsa->e || !rsa->p || !rsa->q || !rsa->d) + if(RSA_set0_key(rsa, bi2bn(n), bi2bn(e), bi2bn(d)) == 0 + || RSA_set0_factors(rsa, bi2bn(p), bi2bn(q)) == 0) { + // Free BIGNUMS? RSA_free(rsa); return; } @@ -2036,7 +2110,7 @@ // When private key has no Public Exponent (e) or Private Exponent (d) // need to disable blinding. Otherwise decryption will be broken. // http://www.mail-archive.com/openssl-users@openssl.org/msg63530.html - if(BN_is_zero(rsa->e) || BN_is_zero(rsa->d)) + if(e == BigInteger(0) || d == BigInteger(0)) RSA_blinding_off(rsa); evp.pkey = EVP_PKEY_new(); @@ -2049,10 +2123,7 @@ evp.reset(); RSA *rsa = RSA_new(); - rsa->n = bi2bn(n); - rsa->e = bi2bn(e); - - if(!rsa->n || !rsa->e) + if(RSA_set0_key(rsa, bi2bn(n), bi2bn(e), NULL) == 0) { RSA_free(rsa); return; @@ -2065,27 +2136,42 @@ virtual BigInteger n() const { - return bn2bi(evp.pkey->pkey.rsa->n); + RSA *rsa = EVP_PKEY_get0_RSA(evp.pkey); + const BIGNUM *bnn; + RSA_get0_key(rsa, &bnn, NULL, NULL); + return bn2bi(bnn); } virtual BigInteger e() const { - return bn2bi(evp.pkey->pkey.rsa->e); + RSA *rsa = EVP_PKEY_get0_RSA(evp.pkey); + const BIGNUM *bne; + RSA_get0_key(rsa, NULL, &bne, NULL); + return bn2bi(bne); } virtual BigInteger p() const { - return bn2bi(evp.pkey->pkey.rsa->p); + RSA *rsa = EVP_PKEY_get0_RSA(evp.pkey); + const BIGNUM *bnp; + RSA_get0_factors(rsa, &bnp, NULL); + return bn2bi(bnp); } virtual BigInteger q() const { - return bn2bi(evp.pkey->pkey.rsa->q); + RSA *rsa = EVP_PKEY_get0_RSA(evp.pkey); + const BIGNUM *bnq; + RSA_get0_factors(rsa, NULL, &bnq); + return bn2bi(bnq); } virtual BigInteger d() const { - return bn2bi(evp.pkey->pkey.rsa->d); + RSA *rsa = EVP_PKEY_get0_RSA(evp.pkey); + const BIGNUM *bnd; + RSA_get0_key(rsa, NULL, NULL, &bnd); + return bn2bi(bnd); } private slots: @@ -2134,10 +2220,12 @@ virtual void run() { DSA *dsa = DSA_new(); - dsa->p = bi2bn(domain.p()); - dsa->q = bi2bn(domain.q()); - dsa->g = bi2bn(domain.g()); - if(!DSA_generate_key(dsa)) + BIGNUM *pne = bi2bn(domain.p()), + *qne = bi2bn(domain.q()), + *gne = bi2bn(domain.g()); + + if(!DSA_set0_pqg(dsa, pne, qne, gne) + || !DSA_generate_key(dsa)) { DSA_free(dsa); return; @@ -2212,10 +2300,11 @@ return; // extract the public key into DER format - int len = i2d_DSAPublicKey(evp.pkey->pkey.dsa, NULL); + DSA *dsa_pkey = EVP_PKEY_get0_DSA(evp.pkey); + int len = i2d_DSAPublicKey(dsa_pkey, NULL); SecureArray result(len); unsigned char *p = (unsigned char *)result.data(); - i2d_DSAPublicKey(evp.pkey->pkey.dsa, &p); + i2d_DSAPublicKey(dsa_pkey, &p); p = (unsigned char *)result.data(); // put the DER public key back into openssl @@ -2244,7 +2333,7 @@ else transformsig = false; - evp.startSign(EVP_dss1()); + evp.startSign(EVP_sha1()); } virtual void startVerify(SignatureAlgorithm, SignatureFormat format) @@ -2255,7 +2344,7 @@ else transformsig = false; - evp.startVerify(EVP_dss1()); + evp.startVerify(EVP_sha1()); } virtual void update(const MemoryRegion &in) @@ -2305,13 +2394,14 @@ evp.reset(); DSA *dsa = DSA_new(); - dsa->p = bi2bn(domain.p()); - dsa->q = bi2bn(domain.q()); - dsa->g = bi2bn(domain.g()); - dsa->pub_key = bi2bn(y); - dsa->priv_key = bi2bn(x); + BIGNUM *bnp = bi2bn(domain.p()); + BIGNUM *bnq = bi2bn(domain.q()); + BIGNUM *bng = bi2bn(domain.g()); + BIGNUM *bnpub_key = bi2bn(y); + BIGNUM *bnpriv_key = bi2bn(x); - if(!dsa->p || !dsa->q || !dsa->g || !dsa->pub_key || !dsa->priv_key) + if(!DSA_set0_pqg(dsa, bnp, bnq, bng) + || !DSA_set0_key(dsa, bnpub_key, bnpriv_key)) { DSA_free(dsa); return; @@ -2327,12 +2417,13 @@ evp.reset(); DSA *dsa = DSA_new(); - dsa->p = bi2bn(domain.p()); - dsa->q = bi2bn(domain.q()); - dsa->g = bi2bn(domain.g()); - dsa->pub_key = bi2bn(y); + BIGNUM *bnp = bi2bn(domain.p()); + BIGNUM *bnq = bi2bn(domain.q()); + BIGNUM *bng = bi2bn(domain.g()); + BIGNUM *bnpub_key = bi2bn(y); - if(!dsa->p || !dsa->q || !dsa->g || !dsa->pub_key) + if(!DSA_set0_pqg(dsa, bnp, bnq, bng) + || !DSA_set0_key(dsa, bnpub_key, NULL)) { DSA_free(dsa); return; @@ -2345,17 +2436,26 @@ virtual DLGroup domain() const { - return DLGroup(bn2bi(evp.pkey->pkey.dsa->p), bn2bi(evp.pkey->pkey.dsa->q), bn2bi(evp.pkey->pkey.dsa->g)); + DSA *dsa = EVP_PKEY_get0_DSA(evp.pkey); + const BIGNUM *bnp, *bnq, *bng; + DSA_get0_pqg(dsa, &bnp, &bnq, &bng); + return DLGroup(bn2bi(bnp), bn2bi(bnq), bn2bi(bng)); } virtual BigInteger y() const { - return bn2bi(evp.pkey->pkey.dsa->pub_key); + DSA *dsa = EVP_PKEY_get0_DSA(evp.pkey); + const BIGNUM *bnpub_key; + DSA_get0_key(dsa, &bnpub_key, NULL); + return bn2bi(bnpub_key); } virtual BigInteger x() const { - return bn2bi(evp.pkey->pkey.dsa->priv_key); + DSA *dsa = EVP_PKEY_get0_DSA(evp.pkey); + const BIGNUM *bnpriv_key; + DSA_get0_key(dsa, NULL, &bnpriv_key); + return bn2bi(bnpriv_key); } private slots: @@ -2404,9 +2504,10 @@ virtual void run() { DH *dh = DH_new(); - dh->p = bi2bn(domain.p()); - dh->g = bi2bn(domain.g()); - if(!DH_generate_key(dh)) + BIGNUM *bnp = bi2bn(domain.p()); + BIGNUM *bng = bi2bn(domain.g()); + if(!DH_set0_pqg(dh, bnp, NULL, bng) + || !DH_generate_key(dh)) { DH_free(dh); return; @@ -2478,11 +2579,14 @@ if(!sec) return; - DH *orig = evp.pkey->pkey.dh; + DH *orig = EVP_PKEY_get0_DH(evp.pkey); DH *dh = DH_new(); - dh->p = BN_dup(orig->p); - dh->g = BN_dup(orig->g); - dh->pub_key = BN_dup(orig->pub_key); + const BIGNUM *bnp, *bng, *bnpub_key; + DH_get0_pqg(orig, &bnp, NULL, &bng); + DH_get0_key(orig, &bnpub_key, NULL); + + DH_set0_key(dh, BN_dup(bnpub_key), NULL); + DH_set0_pqg(dh, BN_dup(bnp), NULL, BN_dup(bng)); evp.reset(); @@ -2498,10 +2602,13 @@ virtual SymmetricKey deriveKey(const PKeyBase &theirs) { - DH *dh = evp.pkey->pkey.dh; - DH *them = static_cast(&theirs)->evp.pkey->pkey.dh; + DH *dh = EVP_PKEY_get0_DH(evp.pkey); + DH *them = EVP_PKEY_get0_DH(static_cast(&theirs)->evp.pkey); + const BIGNUM *bnpub_key; + DH_get0_key(them, &bnpub_key, NULL); + SecureArray result(DH_size(dh)); - int ret = DH_compute_key((unsigned char *)result.data(), them->pub_key, dh); + int ret = DH_compute_key((unsigned char *)result.data(), bnpub_key, dh); if(ret <= 0) return SymmetricKey(); result.resize(ret); @@ -2531,12 +2638,13 @@ evp.reset(); DH *dh = DH_new(); - dh->p = bi2bn(domain.p()); - dh->g = bi2bn(domain.g()); - dh->pub_key = bi2bn(y); - dh->priv_key = bi2bn(x); + BIGNUM *bnp = bi2bn(domain.p()); + BIGNUM *bng = bi2bn(domain.g()); + BIGNUM *bnpub_key = bi2bn(y); + BIGNUM *bnpriv_key = bi2bn(x); - if(!dh->p || !dh->g || !dh->pub_key || !dh->priv_key) + if(!DH_set0_key(dh, bnpub_key, bnpriv_key) + || !DH_set0_pqg(dh, bnp, NULL, bng)) { DH_free(dh); return; @@ -2552,11 +2660,12 @@ evp.reset(); DH *dh = DH_new(); - dh->p = bi2bn(domain.p()); - dh->g = bi2bn(domain.g()); - dh->pub_key = bi2bn(y); + BIGNUM *bnp = bi2bn(domain.p()); + BIGNUM *bng = bi2bn(domain.g()); + BIGNUM *bnpub_key = bi2bn(y); - if(!dh->p || !dh->g || !dh->pub_key) + if(!DH_set0_key(dh, bnpub_key, NULL) + || !DH_set0_pqg(dh, bnp, NULL, bng)) { DH_free(dh); return; @@ -2569,17 +2678,26 @@ virtual DLGroup domain() const { - return DLGroup(bn2bi(evp.pkey->pkey.dh->p), bn2bi(evp.pkey->pkey.dh->g)); + DH *dh = EVP_PKEY_get0_DH(evp.pkey); + const BIGNUM *bnp, *bng; + DH_get0_pqg(dh, &bnp, NULL, &bng); + return DLGroup(bn2bi(bnp), bn2bi(bng)); } virtual BigInteger y() const { - return bn2bi(evp.pkey->pkey.dh->pub_key); + DH *dh = EVP_PKEY_get0_DH(evp.pkey); + const BIGNUM *bnpub_key; + DH_get0_key(dh, &bnpub_key, NULL); + return bn2bi(bnpub_key); } virtual BigInteger x() const { - return bn2bi(evp.pkey->pkey.dh->priv_key); + DH *dh = EVP_PKEY_get0_DH(evp.pkey); + const BIGNUM *bnpriv_key; + DH_get0_key(dh, NULL, &bnpriv_key); + return bn2bi(bnpriv_key); } private slots: @@ -2618,10 +2736,14 @@ { key = _key; RSA_set_method(rsa, rsa_method()); +#ifndef OSSL_110 rsa->flags |= RSA_FLAG_SIGN_VER; +#endif RSA_set_app_data(rsa, this); - rsa->n = bi2bn(_key.n()); - rsa->e = bi2bn(_key.e()); + BIGNUM *bnn = bi2bn(_key.n()); + BIGNUM *bne = bi2bn(_key.e()); + + RSA_set0_key(rsa, bnn, bne, NULL); } RSA_METHOD *rsa_method() @@ -2630,12 +2752,16 @@ if(!ops) { - ops = new RSA_METHOD(*RSA_get_default_method()); - ops->rsa_priv_enc = 0;//pkcs11_rsa_encrypt; - ops->rsa_priv_dec = rsa_priv_dec; - ops->rsa_sign = rsa_sign; - ops->rsa_verify = 0;//pkcs11_rsa_verify; - ops->finish = rsa_finish; + ops = RSA_meth_dup(RSA_get_default_method()); + RSA_meth_set_priv_enc(ops, NULL); //pkcs11_rsa_encrypt + RSA_meth_set_priv_dec(ops, rsa_priv_dec); //pkcs11_rsa_encrypt +#ifdef OSSL_110 + RSA_meth_set_sign(ops, NULL); +#else + RSA_meth_set_sign(ops, rsa_sign); +#endif + RSA_meth_set_verify(ops, NULL); //pkcs11_rsa_verify + RSA_meth_set_finish(ops, rsa_finish); } return ops; } @@ -2675,6 +2801,7 @@ return -1; } +#ifndef OSSL_110 static int rsa_sign(int type, const unsigned char *m, unsigned int m_len, unsigned char *sigret, unsigned int *siglen, const RSA *rsa) { QCA_RSA_METHOD *self = (QCA_RSA_METHOD *)RSA_get_app_data(rsa); @@ -2691,7 +2818,6 @@ } else { - // make X509 packet X509_SIG sig; ASN1_TYPE parameter; @@ -2765,6 +2891,7 @@ return 1; } +#endif static int rsa_finish(RSA *rsa) { @@ -2866,21 +2993,22 @@ PKeyBase *pkeyToBase(EVP_PKEY *pkey, bool sec) const { PKeyBase *nk = 0; - if(pkey->type == EVP_PKEY_RSA) + int pkey_type = EVP_PKEY_type(EVP_PKEY_id(pkey)); + if(pkey_type == EVP_PKEY_RSA) { RSAKey *c = new RSAKey(provider()); c->evp.pkey = pkey; c->sec = sec; nk = c; } - else if(pkey->type == EVP_PKEY_DSA) + else if(pkey_type == EVP_PKEY_DSA) { DSAKey *c = new DSAKey(provider()); c->evp.pkey = pkey; c->sec = sec; nk = c; } - else if(pkey->type == EVP_PKEY_DH) + else if(pkey_type == EVP_PKEY_DH) { DHKey *c = new DHKey(provider()); c->evp.pkey = pkey; @@ -2898,8 +3026,10 @@ { EVP_PKEY *pkey = get_pkey(); + int pkey_type = EVP_PKEY_type(EVP_PKEY_id(pkey)); + // OpenSSL does not have DH import/export support - if(pkey->type == EVP_PKEY_DH) + if(pkey_type == EVP_PKEY_DH) return QByteArray(); BIO *bo = BIO_new(BIO_s_mem()); @@ -2912,8 +3042,10 @@ { EVP_PKEY *pkey = get_pkey(); + int pkey_type = EVP_PKEY_type(EVP_PKEY_id(pkey)); + // OpenSSL does not have DH import/export support - if(pkey->type == EVP_PKEY_DH) + if(pkey_type == EVP_PKEY_DH) return QString(); BIO *bo = BIO_new(BIO_s_mem()); @@ -2978,9 +3110,10 @@ return SecureArray(); EVP_PKEY *pkey = get_pkey(); + int pkey_type = EVP_PKEY_type(EVP_PKEY_id(pkey)); // OpenSSL does not have DH import/export support - if(pkey->type == EVP_PKEY_DH) + if(pkey_type == EVP_PKEY_DH) return SecureArray(); BIO *bo = BIO_new(BIO_s_mem()); @@ -3007,9 +3140,10 @@ return QString(); EVP_PKEY *pkey = get_pkey(); + int pkey_type = EVP_PKEY_type(EVP_PKEY_id(pkey)); // OpenSSL does not have DH import/export support - if(pkey->type == EVP_PKEY_DH) + if(pkey_type == EVP_PKEY_DH) return QString(); BIO *bo = BIO_new(BIO_s_mem()); @@ -3110,11 +3244,18 @@ crl = from.crl; if(cert) - CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(cert); if(req) + { +#ifdef OSSL_110 + // Not exposed, so copy + req = X509_REQ_dup(req); +#else CRYPTO_add(&req->references, 1, CRYPTO_LOCK_X509_REQ); +#endif + } if(crl) - CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL); + X509_CRL_up_ref(crl); } return *this; @@ -3220,7 +3361,7 @@ // // This code is mostly taken from OpenSSL v0.9.5a // by Eric Young -QDateTime ASN1_UTCTIME_QDateTime(ASN1_UTCTIME *tm, int *isGmt) +QDateTime ASN1_UTCTIME_QDateTime(const ASN1_UTCTIME *tm, int *isGmt) { QDateTime qdt; char *v; @@ -3318,7 +3459,7 @@ void fromX509(X509 *x) { - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x); item.cert = x; make_props(); } @@ -3349,7 +3490,7 @@ if(priv.key()->type() == PKey::RSA) md = EVP_sha1(); else if(priv.key()->type() == PKey::DSA) - md = EVP_dss1(); + md = EVP_sha1(); else return false; @@ -3480,7 +3621,7 @@ const MyCertContext *our_cc = this; X509 *x = our_cc->item.cert; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x); sk_X509_push(untrusted_list, x); const MyCertContext *other_cc = static_cast(other); @@ -3595,14 +3736,21 @@ p.policies = get_cert_policies(ex); } - if (x->signature) +#ifdef OSSL_110 + const +#endif + ASN1_BIT_STRING *signature; + + X509_get0_signature(&signature, NULL, x); + if(signature) { - p.sig = QByteArray(x->signature->length, 0); - for (int i=0; i< x->signature->length; i++) - p.sig[i] = x->signature->data[i]; + p.sig = QByteArray(signature->length, 0); + for (int i=0; i< signature->length; i++) + p.sig[i] = signature->data[i]; } - switch( OBJ_obj2nid(x->cert_info->signature->algorithm) ) + + switch( X509_get_signature_nid(x) ) { case NID_sha1WithRSAEncryption: p.sigalgo = QCA::EMSA3_SHA1; @@ -3634,7 +3782,7 @@ p.sigalgo = QCA::EMSA3_SHA512; break; default: - qDebug() << "Unknown signature value: " << OBJ_obj2nid(x->cert_info->signature->algorithm); + qDebug() << "Unknown signature value: " << X509_get_signature_nid(x); p.sigalgo = QCA::SignatureUnknown; } @@ -3751,7 +3899,7 @@ if(privateKey -> key()->type() == PKey::RSA) md = EVP_sha1(); else if(privateKey -> key()->type() == PKey::DSA) - md = EVP_dss1(); + md = EVP_sha1(); else return 0; @@ -3934,7 +4082,7 @@ if(priv.key()->type() == PKey::RSA) md = EVP_sha1(); else if(priv.key()->type() == PKey::DSA) - md = EVP_dss1(); + md = EVP_sha1(); else return false; @@ -4095,14 +4243,17 @@ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); - if (x->signature) + const ASN1_BIT_STRING *signature; + + X509_REQ_get0_signature(x, &signature, NULL); + if(signature) { - p.sig = QByteArray(x->signature->length, 0); - for (int i=0; i< x->signature->length; i++) - p.sig[i] = x->signature->data[i]; + p.sig = QByteArray(signature->length, 0); + for (int i=0; i< signature->length; i++) + p.sig[i] = signature->data[i]; } - switch( OBJ_obj2nid(x->sig_alg->algorithm) ) + switch( X509_REQ_get_signature_nid(x) ) { case NID_sha1WithRSAEncryption: p.sigalgo = QCA::EMSA3_SHA1; @@ -4122,7 +4273,7 @@ p.sigalgo = QCA::EMSA1_SHA1; break; default: - qDebug() << "Unknown signature value: " << OBJ_obj2nid(x->sig_alg->algorithm); + qDebug() << "Unknown signature value: " << X509_REQ_get_signature_nid(x); p.sigalgo = QCA::SignatureUnknown; } @@ -4186,7 +4337,7 @@ void fromX509(X509_CRL *x) { - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL); + X509_CRL_up_ref(x); item.crl = x; make_props(); } @@ -4231,15 +4382,15 @@ issuer = get_cert_name(X509_CRL_get_issuer(x)); - p.thisUpdate = ASN1_UTCTIME_QDateTime(X509_CRL_get_lastUpdate(x), NULL); - p.nextUpdate = ASN1_UTCTIME_QDateTime(X509_CRL_get_nextUpdate(x), NULL); + p.thisUpdate = ASN1_UTCTIME_QDateTime(X509_CRL_get0_lastUpdate(x), NULL); + p.nextUpdate = ASN1_UTCTIME_QDateTime(X509_CRL_get0_nextUpdate(x), NULL); STACK_OF(X509_REVOKED)* revokeStack = X509_CRL_get_REVOKED(x); for (int i = 0; i < sk_X509_REVOKED_num(revokeStack); ++i) { X509_REVOKED *rev = sk_X509_REVOKED_value(revokeStack, i); - BigInteger serial = bn2bi(ASN1_INTEGER_to_BN(rev->serialNumber, NULL)); - QDateTime time = ASN1_UTCTIME_QDateTime( rev->revocationDate, NULL); + BigInteger serial = bn2bi(ASN1_INTEGER_to_BN(X509_REVOKED_get0_serialNumber(rev), NULL)); + QDateTime time = ASN1_UTCTIME_QDateTime( X509_REVOKED_get0_revocationDate(rev), NULL); QCA::CRLEntry::Reason reason = QCA::CRLEntry::Unspecified; int pos = X509_REVOKED_get_ext_by_NID(rev, NID_crl_reason, -1); if (pos != -1) { @@ -4288,13 +4439,18 @@ p.revoked.append(thisEntry); } - if (x->signature) + const ASN1_BIT_STRING *signature; + + X509_CRL_get0_signature(x, &signature, NULL); + if(signature) { - p.sig = QByteArray(x->signature->length, 0); - for (int i=0; i< x->signature->length; i++) - p.sig[i] = x->signature->data[i]; + p.sig = QByteArray(signature->length, 0); + for (int i=0; i< signature->length; i++) + p.sig[i] = signature->data[i]; } - switch( OBJ_obj2nid(x->sig_alg->algorithm) ) + + + switch( X509_CRL_get_signature_nid(x) ) { case NID_sha1WithRSAEncryption: p.sigalgo = QCA::EMSA3_SHA1; @@ -4326,7 +4482,7 @@ p.sigalgo = QCA::EMSA3_SHA512; break; default: - qWarning() << "Unknown signature value: " << OBJ_obj2nid(x->sig_alg->algorithm); + qWarning() << "Unknown signature value: " << X509_CRL_get_signature_nid(x); p.sigalgo = QCA::SignatureUnknown; } @@ -4487,21 +4643,21 @@ { const MyCertContext *cc = static_cast(trusted[n]); X509 *x = cc->item.cert; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x); sk_X509_push(trusted_list, x); } for(n = 0; n < untrusted.count(); ++n) { const MyCertContext *cc = static_cast(untrusted[n]); X509 *x = cc->item.cert; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x); sk_X509_push(untrusted_list, x); } for(n = 0; n < crls.count(); ++n) { const MyCRLContext *cc = static_cast(crls[n]); X509_CRL *x = cc->item.crl; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL); + X509_CRL_up_ref(x); crl_list.append(x); } @@ -4526,7 +4682,7 @@ int ret = X509_verify_cert(ctx); int err = -1; if(!ret) - err = ctx->error; + err = X509_STORE_CTX_get_error(ctx); // cleanup X509_STORE_CTX_free(ctx); @@ -4560,21 +4716,21 @@ { const MyCertContext *cc = static_cast(trusted[n]); X509 *x = cc->item.cert; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x); sk_X509_push(trusted_list, x); } for(n = 1; n < chain.count(); ++n) { const MyCertContext *cc = static_cast(chain[n]); X509 *x = cc->item.cert; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x); sk_X509_push(untrusted_list, x); } for(n = 0; n < crls.count(); ++n) { const MyCRLContext *cc = static_cast(crls[n]); X509_CRL *x = cc->item.crl; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL); + X509_CRL_up_ref(x); crl_list.append(x); } @@ -4599,7 +4755,7 @@ int ret = X509_verify_cert(ctx); int err = -1; if(!ret) - err = ctx->error; + err = X509_STORE_CTX_get_error(ctx); // grab the chain, which may not be fully populated STACK_OF(X509) *xchain = X509_STORE_CTX_get_chain(ctx); @@ -4663,7 +4819,7 @@ for(int n = 1; n < chain.count(); ++n) { X509 *x = static_cast(chain[n])->item.cert; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x); sk_X509_push(ca, x); } } @@ -5398,7 +5554,7 @@ OpenSSL_add_ssl_algorithms(); SSL_CTX *ctx = 0; switch (version) { -#ifndef OPENSSL_NO_SSL2 +#if !defined(OPENSSL_NO_SSL2) && !defined(OSSL_110) case TLS::SSL_v2: ctx = SSL_CTX_new(SSLv2_client_method()); break; @@ -5429,8 +5585,8 @@ STACK_OF(SSL_CIPHER) *sk = SSL_get_ciphers(ssl); QStringList cipherList; for(int i = 0; i < sk_SSL_CIPHER_num(sk); ++i) { - SSL_CIPHER *thisCipher = sk_SSL_CIPHER_value(sk, i); - cipherList += cipherIDtoString(version, thisCipher->id); + const SSL_CIPHER *thisCipher = sk_SSL_CIPHER_value(sk, i); + cipherList += cipherIDtoString(version, SSL_CIPHER_get_id(thisCipher)); } SSL_free(ssl); @@ -5807,13 +5963,15 @@ { SessionInfo sessInfo; - sessInfo.isCompressed = (0 != SSL_SESSION_get_compress_id(ssl->session)); + SSL_SESSION *session = SSL_get0_session(ssl); + sessInfo.isCompressed = (0 != SSL_SESSION_get_compress_id(session)); + int ssl_version = SSL_version(ssl); - if (ssl->version == TLS1_VERSION) + if (ssl_version == TLS1_VERSION) sessInfo.version = TLS::TLS_v1; - else if (ssl->version == SSL3_VERSION) + else if (ssl_version == SSL3_VERSION) sessInfo.version = TLS::SSL_v3; - else if (ssl->version == SSL2_VERSION) + else if (ssl_version == SSL2_VERSION) sessInfo.version = TLS::SSL_v2; else { qDebug("unexpected version response"); @@ -5821,7 +5979,7 @@ } sessInfo.cipherSuite = cipherIDtoString( sessInfo.version, - SSL_get_current_cipher(ssl)->id); + SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))); sessInfo.cipherMaxBits = SSL_get_cipher_bits(ssl, &(sessInfo.cipherBits)); @@ -6393,7 +6551,7 @@ for(int n = 0; n < nonroots.count(); ++n) { X509 *x = static_cast(nonroots[n].context())->item.cert; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x); sk_X509_push(other_certs, x); } @@ -6435,7 +6593,7 @@ other_certs = sk_X509_new_null(); X509 *x = static_cast(target.context())->item.cert; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x); sk_X509_push(other_certs, x); bi = BIO_new(BIO_s_mem()); @@ -6498,7 +6656,7 @@ for(int n = 0; n < untrusted_list.count(); ++n) { X509 *x = static_cast(untrusted_list[n].context())->item.cert; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x); sk_X509_push(other_certs, x); } @@ -6749,40 +6907,64 @@ opensslCipherContext(const EVP_CIPHER *algorithm, const int pad, Provider *p, const QString &type) : CipherContext(p, type) { m_cryptoAlgorithm = algorithm; - EVP_CIPHER_CTX_init(&m_context); + m_context = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX_init(m_context); m_pad = pad; m_type = type; } + opensslCipherContext(const opensslCipherContext &other) + : CipherContext(other) + { + m_cryptoAlgorithm = other.m_cryptoAlgorithm; + m_context = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX_copy(m_context, other.m_context); + m_direction = other.m_direction; + m_pad = other.m_pad; + m_type = other.m_type; + m_tag = other.m_tag; + } + ~opensslCipherContext() { - EVP_CIPHER_CTX_cleanup(&m_context); + EVP_CIPHER_CTX_cleanup(m_context); + EVP_CIPHER_CTX_free(m_context); } void setup(Direction dir, const SymmetricKey &key, - const InitializationVector &iv) + const InitializationVector &iv, + const AuthTag &tag) { + m_tag = tag; m_direction = dir; if ( ( m_cryptoAlgorithm == EVP_des_ede3() ) && (key.size() == 16) ) { // this is really a two key version of triple DES. m_cryptoAlgorithm = EVP_des_ede(); } if (Encode == m_direction) { - EVP_EncryptInit_ex(&m_context, m_cryptoAlgorithm, 0, 0, 0); - EVP_CIPHER_CTX_set_key_length(&m_context, key.size()); - EVP_EncryptInit_ex(&m_context, 0, 0, + EVP_EncryptInit_ex(m_context, m_cryptoAlgorithm, 0, 0, 0); + EVP_CIPHER_CTX_set_key_length(m_context, key.size()); + if (m_type.endsWith("gcm") || m_type.endsWith("ccm")) { + int parameter = m_type.endsWith("gcm") ? EVP_CTRL_GCM_SET_IVLEN : EVP_CTRL_CCM_SET_IVLEN; + EVP_CIPHER_CTX_ctrl(m_context, parameter, iv.size(), NULL); + } + EVP_EncryptInit_ex(m_context, 0, 0, (const unsigned char*)(key.data()), (const unsigned char*)(iv.data())); } else { - EVP_DecryptInit_ex(&m_context, m_cryptoAlgorithm, 0, 0, 0); - EVP_CIPHER_CTX_set_key_length(&m_context, key.size()); - EVP_DecryptInit_ex(&m_context, 0, 0, + EVP_DecryptInit_ex(m_context, m_cryptoAlgorithm, 0, 0, 0); + EVP_CIPHER_CTX_set_key_length(m_context, key.size()); + if (m_type.endsWith("gcm") || m_type.endsWith("ccm")) { + int parameter = m_type.endsWith("gcm") ? EVP_CTRL_GCM_SET_IVLEN : EVP_CTRL_CCM_SET_IVLEN; + EVP_CIPHER_CTX_ctrl(m_context, parameter, iv.size(), NULL); + } + EVP_DecryptInit_ex(m_context, 0, 0, (const unsigned char*)(key.data()), (const unsigned char*)(iv.data())); } - EVP_CIPHER_CTX_set_padding(&m_context, m_pad); + EVP_CIPHER_CTX_set_padding(m_context, m_pad); } Provider::Context *clone() const @@ -6792,9 +6974,14 @@ int blockSize() const { - return EVP_CIPHER_CTX_block_size(&m_context); + return EVP_CIPHER_CTX_block_size(m_context); } + AuthTag tag() const + { + return m_tag; + } + bool update(const SecureArray &in, SecureArray *out) { // This works around a problem in OpenSSL, where it asserts if @@ -6805,7 +6992,7 @@ out->resize(in.size()+blockSize()); int resultLength; if (Encode == m_direction) { - if (0 == EVP_EncryptUpdate(&m_context, + if (0 == EVP_EncryptUpdate(m_context, (unsigned char*)out->data(), &resultLength, (unsigned char*)in.data(), @@ -6813,7 +7000,7 @@ return false; } } else { - if (0 == EVP_DecryptUpdate(&m_context, + if (0 == EVP_DecryptUpdate(m_context, (unsigned char*)out->data(), &resultLength, (unsigned char*)in.data(), @@ -6830,13 +7017,25 @@ out->resize(blockSize()); int resultLength; if (Encode == m_direction) { - if (0 == EVP_EncryptFinal_ex(&m_context, + if (0 == EVP_EncryptFinal_ex(m_context, (unsigned char*)out->data(), &resultLength)) { return false; } + if (m_tag.size() && (m_type.endsWith("gcm") || m_type.endsWith("ccm"))) { + int parameter = m_type.endsWith("gcm") ? EVP_CTRL_GCM_GET_TAG : EVP_CTRL_CCM_GET_TAG; + if (0 == EVP_CIPHER_CTX_ctrl(m_context, parameter, m_tag.size(), (unsigned char*)m_tag.data())) { + return false; + } + } } else { - if (0 == EVP_DecryptFinal_ex(&m_context, + if (m_tag.size() && (m_type.endsWith("gcm") || m_type.endsWith("ccm"))) { + int parameter = m_type.endsWith("gcm") ? EVP_CTRL_GCM_SET_TAG : EVP_CTRL_CCM_SET_TAG; + if (0 == EVP_CIPHER_CTX_ctrl(m_context, parameter, m_tag.size(), m_tag.data())) { + return false; + } + } + if (0 == EVP_DecryptFinal_ex(m_context, (unsigned char*)out->data(), &resultLength)) { return false; @@ -6871,11 +7070,12 @@ protected: - EVP_CIPHER_CTX m_context; + EVP_CIPHER_CTX *m_context; const EVP_CIPHER *m_cryptoAlgorithm; Direction m_direction; int m_pad; QString m_type; + AuthTag m_tag; }; static QStringList all_hash_types() @@ -6922,6 +7122,12 @@ #ifdef HAVE_OPENSSL_AES_CTR list += "aes128-ctr"; #endif +#ifdef HAVE_OPENSSL_AES_GCM + list += "aes128-gcm"; +#endif +#ifdef HAVE_OPENSSL_AES_CCM + list += "aes128-ccm"; +#endif list += "aes192-ecb"; list += "aes192-cfb"; list += "aes192-cbc"; @@ -6930,6 +7136,12 @@ #ifdef HAVE_OPENSSL_AES_CTR list += "aes192-ctr"; #endif +#ifdef HAVE_OPENSSL_AES_GCM + list += "aes192-gcm"; +#endif +#ifdef HAVE_OPENSSL_AES_CCM + list += "aes192-ccm"; +#endif list += "aes256-ecb"; list += "aes256-cbc"; list += "aes256-cbc-pkcs7"; @@ -6938,6 +7150,12 @@ #ifdef HAVE_OPENSSL_AES_CTR list += "aes256-ctr"; #endif +#ifdef HAVE_OPENSSL_AES_GCM + list += "aes256-gcm"; +#endif +#ifdef HAVE_OPENSSL_AES_CCM + list += "aes256-ccm"; +#endif list += "blowfish-ecb"; list += "blowfish-cbc-pkcs7"; list += "blowfish-cbc"; @@ -7217,6 +7435,14 @@ else if ( type == "aes128-ctr" ) return new opensslCipherContext( EVP_aes_128_ctr(), 0, this, type); #endif +#ifdef HAVE_OPENSSL_AES_GCM + else if ( type == "aes128-gcm" ) + return new opensslCipherContext( EVP_aes_128_gcm(), 0, this, type); +#endif +#ifdef HAVE_OPENSSL_AES_CCM + else if ( type == "aes128-ccm" ) + return new opensslCipherContext( EVP_aes_128_ccm(), 0, this, type); +#endif else if ( type == "aes192-ecb" ) return new opensslCipherContext( EVP_aes_192_ecb(), 0, this, type); else if ( type == "aes192-cfb" ) @@ -7231,6 +7457,14 @@ else if ( type == "aes192-ctr" ) return new opensslCipherContext( EVP_aes_192_ctr(), 0, this, type); #endif +#ifdef HAVE_OPENSSL_AES_GCM + else if ( type == "aes192-gcm" ) + return new opensslCipherContext( EVP_aes_192_gcm(), 0, this, type); +#endif +#ifdef HAVE_OPENSSL_AES_CCM + else if ( type == "aes192-ccm" ) + return new opensslCipherContext( EVP_aes_192_ccm(), 0, this, type); +#endif else if ( type == "aes256-ecb" ) return new opensslCipherContext( EVP_aes_256_ecb(), 0, this, type); else if ( type == "aes256-cfb" ) @@ -7245,6 +7479,14 @@ else if ( type == "aes256-ctr" ) return new opensslCipherContext( EVP_aes_256_ctr(), 0, this, type); #endif +#ifdef HAVE_OPENSSL_AES_GCM + else if ( type == "aes256-gcm" ) + return new opensslCipherContext( EVP_aes_256_gcm(), 0, this, type); +#endif +#ifdef HAVE_OPENSSL_AES_CCM + else if ( type == "aes256-ccm" ) + return new opensslCipherContext( EVP_aes_256_ccm(), 0, this, type); +#endif else if ( type == "blowfish-ecb" ) return new opensslCipherContext( EVP_bf_ecb(), 0, this, type); else if ( type == "blowfish-cfb" ) diff -urN qca-2.1.3/src/CMakeLists.txt KDE-qca-d58e20e/src/CMakeLists.txt --- qca-2.1.3/src/CMakeLists.txt 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/src/CMakeLists.txt 2018-01-05 06:02:38.000000000 +1100 @@ -148,9 +148,15 @@ endif(WIN32) if(APPLE) - set(COREFOUNDATION_LIBRARY "-framework CoreFoundation") - set(COREFOUNDATION_LIBRARY_SECURITY "-framework Security") - TARGET_LINK_LIBRARIES(${QCA_LIB_NAME} ${COREFOUNDATION_LIBRARY} ${COREFOUNDATION_LIBRARY_SECURITY}) + set(COREFOUNDATION_LIBRARY "-framework CoreFoundation") + set(COREFOUNDATION_LIBRARY_SECURITY "-framework Security") + TARGET_LINK_LIBRARIES(${QCA_LIB_NAME} ${COREFOUNDATION_LIBRARY} ${COREFOUNDATION_LIBRARY_SECURITY}) + + if(OSX_FRAMEWORK AND NOT USE_RELATIVE_PATHS) + set_target_properties(${QCA_LIB_NAME} PROPERTIES + INSTALL_NAME_DIR "${QCA_LIBRARY_INSTALL_DIR}" + ) + endif() endif(APPLE) if(NOT ANDROID) diff -urN qca-2.1.3/src/botantools/botan/alloc_mmap/mmap_mem.cpp KDE-qca-d58e20e/src/botantools/botan/alloc_mmap/mmap_mem.cpp --- qca-2.1.3/src/botantools/botan/alloc_mmap/mmap_mem.cpp 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/src/botantools/botan/alloc_mmap/mmap_mem.cpp 2018-01-05 06:02:38.000000000 +1100 @@ -107,7 +107,7 @@ umask(old_umask); } - ~TemporaryFile() + ~TemporaryFile() QCA_NOEXCEPT(false) { delete[] filepath; if(fd != -1 && close(fd) == -1) diff -urN qca-2.1.3/src/botantools/botan/botan/allocate.h KDE-qca-d58e20e/src/botantools/botan/botan/allocate.h --- qca-2.1.3/src/botantools/botan/botan/allocate.h 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/src/botantools/botan/botan/allocate.h 2018-01-05 06:02:38.000000000 +1100 @@ -40,6 +40,12 @@ #include namespace QCA { // WRAPNS_LINE +#if __cplusplus >= 201103L +#define QCA_NOEXCEPT(x) noexcept(x) +#else +#define QCA_NOEXCEPT(x) +#endif + namespace Botan { /************************************************* @@ -58,7 +64,7 @@ virtual void init() {} virtual void destroy() {} - virtual ~Allocator() {} + virtual ~Allocator() QCA_NOEXCEPT(false) {} }; /************************************************* diff -urN qca-2.1.3/src/botantools/botan/botan/mem_pool.h KDE-qca-d58e20e/src/botantools/botan/botan/mem_pool.h --- qca-2.1.3/src/botantools/botan/botan/mem_pool.h 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/src/botantools/botan/botan/mem_pool.h 2018-01-05 06:02:38.000000000 +1100 @@ -63,7 +63,7 @@ void destroy(); Pooling_Allocator(u32bit, bool); - ~Pooling_Allocator(); + ~Pooling_Allocator() QCA_NOEXCEPT(false); private: void get_more_core(u32bit); byte* allocate_blocks(u32bit); diff -urN qca-2.1.3/src/botantools/botan/mem_pool.cpp KDE-qca-d58e20e/src/botantools/botan/mem_pool.cpp --- qca-2.1.3/src/botantools/botan/mem_pool.cpp 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/src/botantools/botan/mem_pool.cpp 2018-01-05 06:02:38.000000000 +1100 @@ -171,7 +171,7 @@ /************************************************* * Pooling_Allocator Destructor * *************************************************/ -Pooling_Allocator::~Pooling_Allocator() +Pooling_Allocator::~Pooling_Allocator() QCA_NOEXCEPT(false) { delete mutex; if(blocks.size()) diff -urN qca-2.1.3/src/qca_basic.cpp KDE-qca-d58e20e/src/qca_basic.cpp --- qca-2.1.3/src/qca_basic.cpp 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/src/qca_basic.cpp 2018-01-05 06:02:38.000000000 +1100 @@ -262,6 +262,7 @@ Direction dir; SymmetricKey key; InitializationVector iv; + AuthTag tag; bool ok, done; }; @@ -280,6 +281,19 @@ setup(dir, key, iv); } +Cipher::Cipher(const QString &type, Cipher::Mode mode, Cipher::Padding pad, Direction dir, const SymmetricKey &key, const InitializationVector &iv, const AuthTag &tag, const QString &provider) + : Algorithm(withAlgorithms(type, mode, pad), provider) +{ + d = new Private; + d->type = type; + d->mode = mode; + d->pad = pad; + d->tag = tag; + if(!key.isEmpty()) + setup(dir, key, iv, tag); +} + + Cipher::Cipher(const Cipher &from) :Algorithm(from), Filter(from) { @@ -339,10 +353,15 @@ return static_cast(context())->blockSize(); } +AuthTag Cipher::tag() const +{ + return static_cast(context())->tag(); +} + void Cipher::clear() { d->done = false; - static_cast(context())->setup(d->dir, d->key, d->iv); + static_cast(context())->setup(d->dir, d->key, d->iv, d->tag); } MemoryRegion Cipher::update(const MemoryRegion &a) @@ -371,9 +390,15 @@ void Cipher::setup(Direction dir, const SymmetricKey &key, const InitializationVector &iv) { + setup(dir, key, iv, AuthTag()); +} + +void Cipher::setup(Direction dir, const SymmetricKey &key, const InitializationVector &iv, const AuthTag &tag) +{ d->dir = dir; d->key = key; d->iv = iv; + d->tag = tag; clear(); } @@ -396,6 +421,12 @@ case CTR: mode = "ctr"; break; + case GCM: + mode = "gcm"; + break; + case CCM: + mode = "ccm"; + break; default: Q_ASSERT(0); } diff -urN qca-2.1.3/src/qca_core.cpp KDE-qca-d58e20e/src/qca_core.cpp --- qca-2.1.3/src/qca_core.cpp 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/src/qca_core.cpp 2018-01-05 06:02:38.000000000 +1100 @@ -1,6 +1,7 @@ /* * Copyright (C) 2003-2008 Justin Karneges * Copyright (C) 2004,2005 Brad Hards + * Copyright (C) 2014-2016 Ivan Romanov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -812,6 +813,16 @@ return Hex().stringToArray(str).toByteArray(); } +QString arrayToBase64(const QByteArray &a) +{ + return Base64().arrayToString(a); +} + +QByteArray base64ToArray(const QString &base64String) +{ + return Base64().stringToArray(base64String).toByteArray(); +} + static Provider *getProviderForType(const QString &type, const QString &provider) { Provider *p = 0; @@ -1511,6 +1522,28 @@ } //---------------------------------------------------------------------------- +// AuthTag +//---------------------------------------------------------------------------- +AuthTag::AuthTag() +{ +} + +AuthTag::AuthTag(int size) +{ + resize(size); +} + +AuthTag::AuthTag(const SecureArray &a) +{ + set(a); +} + +AuthTag::AuthTag(const QByteArray &a) +{ + set(SecureArray(a)); +} + +//---------------------------------------------------------------------------- // Event //---------------------------------------------------------------------------- class Event::Private : public QSharedData diff -urN qca-2.1.3/src/support/console.cpp KDE-qca-d58e20e/src/support/console.cpp --- qca-2.1.3/src/support/console.cpp 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/src/support/console.cpp 2018-01-05 06:02:38.000000000 +1100 @@ -857,7 +857,7 @@ return false; } - if(c == '\b' || c == 0x7f) + if(c == '\b' || c.unicode() == 0x7f) { if(at > 0) { diff -urN qca-2.1.3/unittest/base64unittest/base64unittest.cpp KDE-qca-d58e20e/unittest/base64unittest/base64unittest.cpp --- qca-2.1.3/unittest/base64unittest/base64unittest.cpp 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/unittest/base64unittest/base64unittest.cpp 2018-01-05 06:02:38.000000000 +1100 @@ -120,6 +120,9 @@ QCOMPARE( base64Object.encodeString(raw), encoded ); QCOMPARE( base64Object.decodeString(encoded), raw ); + + QCOMPARE( QCA::arrayToBase64(raw.toUtf8()), encoded ); + QCOMPARE( QLatin1String(QCA::base64ToArray(encoded)), raw ); } QTEST_MAIN(Base64UnitTest) diff -urN qca-2.1.3/unittest/cipherunittest/CMakeLists.txt KDE-qca-d58e20e/unittest/cipherunittest/CMakeLists.txt --- qca-2.1.3/unittest/cipherunittest/CMakeLists.txt 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/unittest/cipherunittest/CMakeLists.txt 2018-01-05 06:02:38.000000000 +1100 @@ -5,7 +5,7 @@ qt4_wrap_cpp(EXTRA_SRCS cipherunittest.h) -add_executable(cipherunittest ${cipherunittest_bin_SRCS} ${EXTRA_SRCS}) +add_executable(cipherunittest ${cipherunittest_bin_SRCS} ${EXTRA_SRCS} ${cipherunittest_bin_HDRS}) target_link_qca_test_libraries(cipherunittest) diff -urN qca-2.1.3/unittest/cipherunittest/cipherunittest.cpp KDE-qca-d58e20e/unittest/cipherunittest/cipherunittest.cpp --- qca-2.1.3/unittest/cipherunittest/cipherunittest.cpp 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/unittest/cipherunittest/cipherunittest.cpp 2018-01-05 06:02:38.000000000 +1100 @@ -1,5 +1,6 @@ /** * Copyright (C) 2004-2007 Brad Hards + * Copyright (C) 2013-2016 Ivan Romanov * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -496,6 +497,103 @@ } } +void CipherUnitTest::aes128_gcm_data() +{ + QTest::addColumn("plainText"); + QTest::addColumn("payload"); + QTest::addColumn("tag"); + QTest::addColumn("keyText"); + QTest::addColumn("ivText"); + + QTest::newRow("short") << QString("6f6820526f6d656d6f21") + << QString("a9f2558b9a74e6fc551f") + << QString("f8ebf75f108c6f74e6fe49035d268d43") + << QString("1f491f8ddf4856ae4bff9039d418175a") + << QString("f85f8aad39164daf64a12ad9b3fc8a3a"); + + QTest::newRow("long") << QString("54484520515549434b2042524f574e20464f58204a554d504544204f56455220544845204c415a5920444f472753204241434b2031323334353637383930") + << QString("04e321a8870b6b9cd6846239c27a63fb41d0a7b8994f1514c066f0427fa9ed6707ea6e3b4f161fdff0eb5fc087ed3827b569cd72456c697b5a3a62c9e767") + << QString("b0ad4aa545ea25fc3117cbed955ff155") + << QString("56341f2b431d3b0dbad787db003f2215") + << QString("bfcd3a7252f7f199bf788df8cf61032a"); + + + QTest::newRow("wrongtag") << QString("6f6820526f6d656d6f21") + << QString("a9f2558b9a74e6fc551f") + << QString("f8ebf75f108c6f74e6fe49035d268d44") + << QString("1f491f8ddf4856ae4bff9039d418175a") + << QString("f85f8aad39164daf64a12ad9b3fc8a3a"); +} + +void CipherUnitTest::aes128_gcm() +{ + QStringList providersToTest; + providersToTest.append("qca-ossl"); + providersToTest.append("qca-gcrypt"); + providersToTest.append("qca-botan"); + providersToTest.append("qca-nss"); + + foreach (const QString &provider, providersToTest) { + if (!QCA::isSupported( "aes128-gcm", provider)) + QWARN(QString("AES128 GCM not supported for " + provider).toLocal8Bit()); + else { + QFETCH(QString, plainText); + QFETCH(QString, payload); + QFETCH(QString, tag); + QFETCH(QString, keyText); + QFETCH(QString, ivText); + + QCA::SymmetricKey key(QCA::hexToArray(keyText)); + QCA::InitializationVector iv(QCA::hexToArray(ivText)); + QCA::AuthTag authTag(16); + QCA::Cipher forwardCipher(QString("aes128"), + QCA::Cipher::GCM, + QCA::Cipher::NoPadding, + QCA::Encode, + key, + iv, + authTag, + provider); + QString update = QCA::arrayToHex(forwardCipher.update(QCA::hexToArray(plainText)).toByteArray()); + QVERIFY(forwardCipher.ok()); + update += QCA::arrayToHex(forwardCipher.final().toByteArray()); + authTag = forwardCipher.tag(); + QEXPECT_FAIL("wrongtag", "It's OK", Continue); + QCOMPARE(QCA::arrayToHex(authTag.toByteArray()), tag); + QCOMPARE(update, payload); + QVERIFY(forwardCipher.ok()); + + QCA::Cipher reverseCipher(QString( "aes128"), + QCA::Cipher::GCM, + QCA::Cipher::NoPadding, + QCA::Decode, + key, + iv, + QCA::AuthTag(QCA::hexToArray(tag)), + provider); + + update = QCA::arrayToHex(reverseCipher.update(QCA::hexToArray(payload)).toByteArray()); + QVERIFY(reverseCipher.ok()); + QCOMPARE(update, plainText.left(update.size())); + update += QCA::arrayToHex(reverseCipher.final().toByteArray()); + QEXPECT_FAIL("wrongtag", "It's OK", Continue); + QCOMPARE(update, plainText); + QEXPECT_FAIL("wrongtag", "It's OK", Continue); + QVERIFY(reverseCipher.ok()); + } + } +} + +void CipherUnitTest::aes128_ccm_data() +{ + +} + +void CipherUnitTest::aes128_ccm() +{ + // For future implementation +} + void CipherUnitTest::aes192_data() { QTest::addColumn("plainText"); @@ -950,6 +1048,104 @@ } } +void CipherUnitTest::aes192_gcm_data() +{ + QTest::addColumn("plainText"); + QTest::addColumn("payload"); + QTest::addColumn("tag"); + QTest::addColumn("keyText"); + QTest::addColumn("ivText"); + + QTest::newRow("short") << QString("6f6820526f6d656d6f21") + << QString("01ca25ff74121917f397") + << QString("b90e97706d8eacbabc0be5e0a671b4e4") + << QString("7ecb21a647fae54a0996ad281ab0c1a00cb905d9e2eb3b82") + << QString("f85f8aad39164daf64a12ad9b3fc8a3a"); + + QTest::newRow("long") << QString("54484520515549434b2042524f574e20464f58204a554d504544204f56455220544845204c415a5920444f472753204241434b2031323334353637383930") + << QString("4c1c5874877f0bee6efd450ec341b1c591e1e100da40bd4744e1035ed0ed0fb458f8efdb7c4b0b2101e29c950c56dc2489c2febec2d7062da28b9a033173") + << QString("af3ea1b7f275ea1e4d4e1fdce63f83fe") + << QString("7ecb21a647fae54a0996ad281ab0c1a00cb905d9e2eb3b82") + << QString("bfcd3a7252f7f199bf788df8cf61032a"); + + + QTest::newRow("wrongtag") << QString("6f6820526f6d656d6f21") + << QString("773c3d06b94727c04afc") + << QString("c558aca7f19050db49d94d99119277af") + << QString("7ecb21a647fae54a0996ad281ab0c1a00cb905d9e2eb3b82") + << QString("bfcd3a7252f7f199bf788df8cf61032a"); +} + +void CipherUnitTest::aes192_gcm() +{ + QStringList providersToTest; + providersToTest.append("qca-ossl"); + providersToTest.append("qca-gcrypt"); + providersToTest.append("qca-botan"); + providersToTest.append("qca-nss"); + + foreach (const QString &provider, providersToTest) { + if (!QCA::isSupported( "aes192-gcm", provider)) + QWARN(QString("AES128 GCM not supported for " + provider).toLocal8Bit()); + else { + QFETCH(QString, plainText); + QFETCH(QString, payload); + QFETCH(QString, tag); + QFETCH(QString, keyText); + QFETCH(QString, ivText); + + QCA::SymmetricKey key(QCA::hexToArray(keyText)); + QCA::InitializationVector iv(QCA::hexToArray(ivText)); + QCA::AuthTag authTag(16); + QCA::Cipher forwardCipher(QString("aes192"), + QCA::Cipher::GCM, + QCA::Cipher::NoPadding, + QCA::Encode, + key, + iv, + authTag, + provider); + QString update = QCA::arrayToHex(forwardCipher.update(QCA::hexToArray(plainText)).toByteArray()); + QVERIFY(forwardCipher.ok()); + update += QCA::arrayToHex(forwardCipher.final().toByteArray()); + authTag = forwardCipher.tag(); + QEXPECT_FAIL("wrongtag", "It's OK", Continue); + QCOMPARE(QCA::arrayToHex(authTag.toByteArray()), tag); + QCOMPARE(update, payload); + QVERIFY(forwardCipher.ok()); + + QCA::Cipher reverseCipher(QString( "aes192"), + QCA::Cipher::GCM, + QCA::Cipher::NoPadding, + QCA::Decode, + key, + iv, + QCA::AuthTag(QCA::hexToArray(tag)), + provider); + + update = QCA::arrayToHex(reverseCipher.update(QCA::hexToArray(payload)).toByteArray()); + QVERIFY(reverseCipher.ok()); + QCOMPARE(update, plainText.left(update.size())); + update += QCA::arrayToHex(reverseCipher.final().toByteArray()); + QEXPECT_FAIL("wrongtag", "It's OK", Continue); + QCOMPARE(update, plainText); + QEXPECT_FAIL("wrongtag", "It's OK", Continue); + QVERIFY(reverseCipher.ok()); + } + } +} + + +void CipherUnitTest::aes192_ccm_data() +{ + +} + +void CipherUnitTest::aes192_ccm() +{ + // For future implementation +} + void CipherUnitTest::aes256_data() { QTest::addColumn("plainText"); @@ -1442,6 +1638,103 @@ } } +void CipherUnitTest::aes256_gcm_data() +{ + QTest::addColumn("plainText"); + QTest::addColumn("payload"); + QTest::addColumn("tag"); + QTest::addColumn("keyText"); + QTest::addColumn("ivText"); + + QTest::newRow("short") << QString("6f6820526f6d656d6f21") + << QString("4ce2f4df041252820847") + << QString("1c570805832dfe7babc1b386c26bcd04") + << QString("3fa609690bf07a81a75839b0a4c0add774f54eb804d4f02df488691910298b04") + << QString("f85f8aad39164daf64a12ad9b3fc8a3a"); + + QTest::newRow("long") << QString("54484520515549434b2042524f574e20464f58204a554d504544204f56455220544845204c415a5920444f472753204241434b2031323334353637383930") + << QString("e516c267146d6cfd3af3300e24aba7ac23ab3c5cb4765937a6c0156e454cae357e14f4c0dfb0def9624f4f70de90ad2bc9cd555171c4551c26b6346922ed") + << QString("f59aac31ab9dace3fcc693e114dd6610") + << QString("3fa609690bf07a81a75839b0a4c0add774f54eb804d4f02df488691910298b04") + << QString("bfcd3a7252f7f199bf788df8cf61032a"); + + + QTest::newRow("wrongtag") << QString("6f6820526f6d656d6f21") + << QString("4ce2f4df041252820847") + << QString("1c570805833dfe7babc1b386c26bcd04") + << QString("3fa609690bf07a81a75839b0a4c0add774f54eb804d4f02df488691910298b04") + << QString("f85f8aad39164daf64a12ad9b3fc8a3a"); +} + +void CipherUnitTest::aes256_gcm() +{ + QStringList providersToTest; + providersToTest.append("qca-ossl"); + providersToTest.append("qca-gcrypt"); + providersToTest.append("qca-botan"); + providersToTest.append("qca-nss"); + + foreach (const QString &provider, providersToTest) { + if (!QCA::isSupported( "aes256-gcm", provider)) + QWARN(QString("AES256 GCM not supported for " + provider).toLocal8Bit()); + else { + QFETCH(QString, plainText); + QFETCH(QString, payload); + QFETCH(QString, tag); + QFETCH(QString, keyText); + QFETCH(QString, ivText); + + QCA::SymmetricKey key(QCA::hexToArray(keyText)); + QCA::InitializationVector iv(QCA::hexToArray(ivText)); + QCA::AuthTag authTag(16); + QCA::Cipher forwardCipher(QString("aes256"), + QCA::Cipher::GCM, + QCA::Cipher::NoPadding, + QCA::Encode, + key, + iv, + authTag, + provider); + QString update = QCA::arrayToHex(forwardCipher.update(QCA::hexToArray(plainText)).toByteArray()); + QVERIFY(forwardCipher.ok()); + update += QCA::arrayToHex(forwardCipher.final().toByteArray()); + authTag = forwardCipher.tag(); + QEXPECT_FAIL("wrongtag", "It's OK", Continue); + QCOMPARE(QCA::arrayToHex(authTag.toByteArray()), tag); + QCOMPARE(update, payload); + QVERIFY(forwardCipher.ok()); + + QCA::Cipher reverseCipher(QString( "aes256"), + QCA::Cipher::GCM, + QCA::Cipher::NoPadding, + QCA::Decode, + key, + iv, + QCA::AuthTag(QCA::hexToArray(tag)), + provider); + + update = QCA::arrayToHex(reverseCipher.update(QCA::hexToArray(payload)).toByteArray()); + QVERIFY(reverseCipher.ok()); + QCOMPARE(update, plainText.left(update.size())); + update += QCA::arrayToHex(reverseCipher.final().toByteArray()); + QEXPECT_FAIL("wrongtag", "It's OK", Continue); + QCOMPARE(update, plainText); + QEXPECT_FAIL("wrongtag", "It's OK", Continue); + QVERIFY(reverseCipher.ok()); + } + } +} + +void CipherUnitTest::aes256_ccm_data() +{ + +} + +void CipherUnitTest::aes256_ccm() +{ + // For future implementation +} + void CipherUnitTest::tripleDES_data() { QTest::addColumn("plainText"); diff -urN qca-2.1.3/unittest/cipherunittest/cipherunittest.h KDE-qca-d58e20e/unittest/cipherunittest/cipherunittest.h --- qca-2.1.3/unittest/cipherunittest/cipherunittest.h 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/unittest/cipherunittest/cipherunittest.h 2018-01-05 06:02:38.000000000 +1100 @@ -1,3 +1,29 @@ +/** + * Copyright (C) 2004-2007 Brad Hards + * Copyright (C) 2013-2016 Ivan Romanov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #ifndef CIPHERUNITTEST_H #define CIPHERUNITTEST_H @@ -23,6 +49,10 @@ void aes128_ofb(); void aes128_ctr_data(); void aes128_ctr(); + void aes128_gcm_data(); + void aes128_gcm(); + void aes128_ccm_data(); + void aes128_ccm(); void aes192_data(); void aes192(); @@ -36,6 +66,10 @@ void aes192_ofb(); void aes192_ctr_data(); void aes192_ctr(); + void aes192_gcm_data(); + void aes192_gcm(); + void aes192_ccm_data(); + void aes192_ccm(); void aes256_data(); void aes256(); @@ -49,6 +83,10 @@ void aes256_ofb(); void aes256_ctr_data(); void aes256_ctr(); + void aes256_gcm_data(); + void aes256_gcm(); + void aes256_ccm_data(); + void aes256_ccm(); void tripleDES_data(); void tripleDES(); diff -urN qca-2.1.3/unittest/tls/tlsunittest.cpp KDE-qca-d58e20e/unittest/tls/tlsunittest.cpp --- qca-2.1.3/unittest/tls/tlsunittest.cpp 2017-02-06 23:29:44.000000000 +1100 +++ KDE-qca-d58e20e/unittest/tls/tlsunittest.cpp 2018-01-05 06:02:38.000000000 +1100 @@ -60,18 +60,22 @@ QCA::TLS *tls = new QCA::TLS(QCA::TLS::Stream, 0, "qca-ossl"); QStringList cipherList = tls->supportedCipherSuites(QCA::TLS::TLS_v1); QVERIFY( cipherList.contains("TLS_DHE_RSA_WITH_AES_256_CBC_SHA") ); - QVERIFY( cipherList.contains("TLS_DHE_DSS_WITH_AES_256_CBC_SHA") ); QVERIFY( cipherList.contains("TLS_RSA_WITH_AES_256_CBC_SHA") ); - QVERIFY( cipherList.contains("TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA") ); - QVERIFY( cipherList.contains("TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA") ); - QVERIFY( cipherList.contains("TLS_RSA_WITH_3DES_EDE_CBC_SHA") ); QVERIFY( cipherList.contains("TLS_DHE_RSA_WITH_AES_128_CBC_SHA") ); - QVERIFY( cipherList.contains("TLS_DHE_DSS_WITH_AES_128_CBC_SHA") ); - QVERIFY( cipherList.contains("TLS_RSA_WITH_AES_128_CBC_SHA") ); - QVERIFY( cipherList.contains("TLS_RSA_WITH_RC4_128_SHA") ); - // Fedora 22 has no TLS_RSA_WITH_RC4_128_MD5 + // openSUSE TW OpenSSL 1.1 does not have this + // QVERIFY( cipherList.contains("TLS_DHE_DSS_WITH_AES_256_CBC_SHA") ); + // QVERIFY( cipherList.contains("TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA") ); + // QVERIFY( cipherList.contains("TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA") ); + // QVERIFY( cipherList.contains("TLS_RSA_WITH_3DES_EDE_CBC_SHA") ); + // QVERIFY( cipherList.contains("TLS_RSA_WITH_AES_128_CBC_SHA") ); + // QVERIFY( cipherList.contains("TLS_DHE_DSS_WITH_AES_128_CBC_SHA") ); + + // Fedora 26 openssl has no this cipher suites. + // QVERIFY( cipherList.contains("TLS_RSA_WITH_RC4_128_SHA") ); // QVERIFY( cipherList.contains("TLS_RSA_WITH_RC4_128_MD5") ); + // QVERIFY( cipherList.contains("SSL_RSA_WITH_RC4_128_SHA") ); + // QVERIFY( cipherList.contains("SSL_RSA_WITH_RC4_128_MD5") ); // Fedora 20 openssl has no this cipher suites. // I just believe that F20 has the most strict patent rules @@ -87,20 +91,17 @@ // QVERIFY( cipherList.contains("TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5") ); // QVERIFY( cipherList.contains("TLS_RSA_EXPORT_WITH_RC4_40_MD5") ); - cipherList = tls->supportedCipherSuites(QCA::TLS::SSL_v3); - QVERIFY( cipherList.contains("SSL_DHE_RSA_WITH_AES_256_CBC_SHA") ); - QVERIFY( cipherList.contains("SSL_DHE_DSS_WITH_AES_256_CBC_SHA") ); - QVERIFY( cipherList.contains("SSL_RSA_WITH_AES_256_CBC_SHA") ); - QVERIFY( cipherList.contains("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA") ); - QVERIFY( cipherList.contains("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA") ); - QVERIFY( cipherList.contains("SSL_RSA_WITH_3DES_EDE_CBC_SHA") ); - QVERIFY( cipherList.contains("SSL_DHE_RSA_WITH_AES_128_CBC_SHA") ); - QVERIFY( cipherList.contains("SSL_DHE_DSS_WITH_AES_128_CBC_SHA") ); - QVERIFY( cipherList.contains("SSL_RSA_WITH_AES_128_CBC_SHA") ); - QVERIFY( cipherList.contains("SSL_RSA_WITH_RC4_128_SHA") ); - - // Fedora 22 has no SSL_RSA_WITH_RC4_128_MD5 - // QVERIFY( cipherList.contains("SSL_RSA_WITH_RC4_128_MD5") ); + // OpenSSL 1.1 in openSUSE TW has it disabled by default + // cipherList = tls->supportedCipherSuites(QCA::TLS::SSL_v3); + // QVERIFY( cipherList.contains("SSL_DHE_RSA_WITH_AES_256_CBC_SHA") ); + // QVERIFY( cipherList.contains("SSL_DHE_DSS_WITH_AES_256_CBC_SHA") ); + // QVERIFY( cipherList.contains("SSL_RSA_WITH_AES_256_CBC_SHA") ); + // QVERIFY( cipherList.contains("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA") ); + // QVERIFY( cipherList.contains("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA") ); + // QVERIFY( cipherList.contains("SSL_RSA_WITH_3DES_EDE_CBC_SHA") ); + // QVERIFY( cipherList.contains("SSL_DHE_RSA_WITH_AES_128_CBC_SHA") ); + // QVERIFY( cipherList.contains("SSL_DHE_DSS_WITH_AES_128_CBC_SHA") ); + // QVERIFY( cipherList.contains("SSL_RSA_WITH_AES_128_CBC_SHA") ); // QVERIFY( cipherList.contains("SSL_DHE_RSA_WITH_DES_CBC_SHA") ); // QVERIFY( cipherList.contains("SSL_DHE_DSS_WITH_DES_CBC_SHA") );