diff --git a/NEWS b/NEWS index b37393e5b..772853d4e 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ SoftHSM develop * Issue #186: Reinitializing a token will now keep the token, but all token objects are deleted, the user PIN is removed and the token label is updated. +* Issue #190: Support for OpenSSL 1.1.0. * Issue #198: Calling C_GetSlotList with NULL_PTR will make sure that there is always a slot with an uninitialized token available. * Issue #199: The token serial number will be used when setting the slot diff --git a/m4/acx_openssl.m4 b/m4/acx_openssl.m4 index d42e131eb..684860d25 100644 --- a/m4/acx_openssl.m4 +++ b/m4/acx_openssl.m4 @@ -23,7 +23,7 @@ AC_DEFUN([ACX_OPENSSL],[ LIBS="$LIBS $OPENSSL_LIBS" AC_CHECK_HEADERS([openssl/ssl.h],,[AC_MSG_ERROR([Can't find OpenSSL headers])]) - AC_CHECK_LIB(crypto, BN_init,,[AC_MSG_ERROR([Can't find OpenSSL library])]) + AC_CHECK_LIB(crypto, BN_new,,[AC_MSG_ERROR([Can't find OpenSSL library])]) AC_MSG_CHECKING([for OpenSSL version]) CHECK_OPENSSL_VERSION=m4_format(0x%02x%02x%02x000L, $1, $2, $3) diff --git a/m4/acx_openssl_ecc.m4 b/m4/acx_openssl_ecc.m4 index 2bc2f7801..bb7ffdc5c 100644 --- a/m4/acx_openssl_ecc.m4 +++ b/m4/acx_openssl_ecc.m4 @@ -14,19 +14,20 @@ AC_DEFUN([ACX_OPENSSL_ECC],[ #include int main() { - EC_KEY *ec256, *ec384; + EC_KEY *ec256, *ec384, *ec521; ec256 = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); ec384 = EC_KEY_new_by_curve_name(NID_secp384r1); - if (ec256 == NULL || ec384 == NULL) + ec521 = EC_KEY_new_by_curve_name(NID_secp521r1); + if (ec256 == NULL || ec384 == NULL || ec521 == NULL) return 1; return 0; } ]]) ],[ - AC_MSG_RESULT([Found P256 and P384]) + AC_MSG_RESULT([Found P256, P384, and P521]) ],[ - AC_MSG_RESULT([Cannot find P256 or P384]) + AC_MSG_RESULT([Cannot find P256, P384, or P521]) AC_MSG_ERROR([OpenSSL library has no ECC support]) ],[]) AC_LANG_POP([C]) diff --git a/m4/acx_openssl_gost.m4 b/m4/acx_openssl_gost.m4 index 2ca0f7e39..273be1ee1 100644 --- a/m4/acx_openssl_gost.m4 +++ b/m4/acx_openssl_gost.m4 @@ -10,28 +10,52 @@ AC_DEFUN([ACX_OPENSSL_GOST],[ AC_LANG_PUSH([C]) AC_RUN_IFELSE([ AC_LANG_SOURCE([[ - #include #include + #include + #include int main() { - ENGINE *e; - EC_KEY *ek; + ENGINE* eg; + const EVP_MD* EVP_GOST_34_11; - ek = NULL; - OPENSSL_config(NULL); + /* Initialise OpenSSL */ + OpenSSL_add_all_algorithms(); - e = ENGINE_by_id("gost"); - if (e == NULL) + /* Load engines */ + #if OPENSSL_VERSION_NUMBER < 0x10100000L + ENGINE_load_builtin_engines(); + #else + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN | OPENSSL_INIT_LOAD_CONFIG, NULL); + #endif + + /* Initialise the GOST engine */ + eg = ENGINE_by_id("gost"); + if (eg == NULL) + return 1; + if (ENGINE_init(eg) <= 0) return 1; - if (ENGINE_init(e) <= 0) + + /* better than digest_gost */ + EVP_GOST_34_11 = ENGINE_get_digest(eg, NID_id_GostR3411_94); + if (EVP_GOST_34_11 == NULL) return 1; + + /* from the openssl.cnf */ + if (ENGINE_register_pkey_asn1_meths(eg) <= 0) + return 1; + if (ENGINE_ctrl_cmd_string(eg, + "CRYPT_PARAMS", + "id-Gost28147-89-CryptoPro-A-ParamSet", + 0) <= 0) + return 1; + return 0; } ]]) ],[ AC_MSG_RESULT([Found GOST engine]) ],[ - AC_MSG_RESULT([Cannot GOST engine]) + AC_MSG_RESULT([Cannot find GOST engine]) AC_MSG_ERROR([OpenSSL library has no GOST support]) ],[]) AC_LANG_POP([C]) diff --git a/src/bin/keyconv/Makefile.am b/src/bin/keyconv/Makefile.am index 21360f10c..1e6ce39e7 100644 --- a/src/bin/keyconv/Makefile.am +++ b/src/bin/keyconv/Makefile.am @@ -1,6 +1,7 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in -AM_CPPFLAGS = @CRYPTO_INCLUDES@ +AM_CPPFLAGS = @CRYPTO_INCLUDES@ \ + -I$(srcdir)/../../lib/crypto dist_man_MANS = softhsm2-keyconv.1 @@ -12,7 +13,8 @@ softhsm2_keyconv_LDADD = @CRYPTO_LIBS@ # Compile with OpenSSL support if WITH_OPENSSL -softhsm2_keyconv_SOURCES += softhsm2-keyconv-ossl.cpp +softhsm2_keyconv_SOURCES += softhsm2-keyconv-ossl.cpp \ + ../../lib/crypto/OSSLComp.cpp endif # Compile with Botan support diff --git a/src/bin/keyconv/softhsm2-keyconv-ossl.cpp b/src/bin/keyconv/softhsm2-keyconv-ossl.cpp index 47671979b..a5cd8eb47 100644 --- a/src/bin/keyconv/softhsm2-keyconv-ossl.cpp +++ b/src/bin/keyconv/softhsm2-keyconv-ossl.cpp @@ -33,6 +33,7 @@ #include #define KEYCONV_OSSL #include "softhsm2-keyconv.h" +#include "OSSLComp.h" #include #include @@ -95,14 +96,17 @@ int save_rsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey) } rsa = RSA_new(); - rsa->p = BN_bin2bn((unsigned char*)pkey[TAG_PRIME1].big, pkey[TAG_PRIME1].size, NULL); - rsa->q = BN_bin2bn((unsigned char*)pkey[TAG_PRIME2].big, pkey[TAG_PRIME2].size, NULL); - rsa->d = BN_bin2bn((unsigned char*)pkey[TAG_PRIVEXP].big, pkey[TAG_PRIVEXP].size, NULL); - rsa->n = BN_bin2bn((unsigned char*)pkey[TAG_MODULUS].big, pkey[TAG_MODULUS].size, NULL); - rsa->e = BN_bin2bn((unsigned char*)pkey[TAG_PUBEXP].big, pkey[TAG_PUBEXP].size, NULL); - rsa->dmp1 = BN_bin2bn((unsigned char*)pkey[TAG_EXP1].big, pkey[TAG_EXP1].size, NULL); - rsa->dmq1 = BN_bin2bn((unsigned char*)pkey[TAG_EXP2].big, pkey[TAG_EXP2].size, NULL); - rsa->iqmp = BN_bin2bn((unsigned char*)pkey[TAG_COEFF].big, pkey[TAG_COEFF].size, NULL); + BIGNUM* bn_p = BN_bin2bn((unsigned char*)pkey[TAG_PRIME1].big, pkey[TAG_PRIME1].size, NULL); + BIGNUM* bn_q = BN_bin2bn((unsigned char*)pkey[TAG_PRIME2].big, pkey[TAG_PRIME2].size, NULL); + BIGNUM* bn_d = BN_bin2bn((unsigned char*)pkey[TAG_PRIVEXP].big, pkey[TAG_PRIVEXP].size, NULL); + BIGNUM* bn_n = BN_bin2bn((unsigned char*)pkey[TAG_MODULUS].big, pkey[TAG_MODULUS].size, NULL); + BIGNUM* bn_e = BN_bin2bn((unsigned char*)pkey[TAG_PUBEXP].big, pkey[TAG_PUBEXP].size, NULL); + BIGNUM* bn_dmp1 = BN_bin2bn((unsigned char*)pkey[TAG_EXP1].big, pkey[TAG_EXP1].size, NULL); + BIGNUM* bn_dmq1 = BN_bin2bn((unsigned char*)pkey[TAG_EXP2].big, pkey[TAG_EXP2].size, NULL); + BIGNUM* bn_iqmp = BN_bin2bn((unsigned char*)pkey[TAG_COEFF].big, pkey[TAG_COEFF].size, NULL); + RSA_set0_factors(rsa, bn_p, bn_q); + RSA_set0_crt_params(rsa, bn_dmp1, bn_dmq1, bn_iqmp); + RSA_set0_key(rsa, bn_n, bn_e, bn_d); ossl_pkey = EVP_PKEY_new(); @@ -188,11 +192,15 @@ int save_dsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey) } dsa = DSA_new(); - dsa->p = BN_bin2bn((unsigned char*)pkey[TAG_PRIME].big, pkey[TAG_PRIME].size, NULL); - dsa->q = BN_bin2bn((unsigned char*)pkey[TAG_SUBPRIME].big, pkey[TAG_SUBPRIME].size, NULL); - dsa->g = BN_bin2bn((unsigned char*)pkey[TAG_BASE].big, pkey[TAG_BASE].size, NULL); - dsa->priv_key = BN_bin2bn((unsigned char*)pkey[TAG_PRIVVAL].big, pkey[TAG_PRIVVAL].size, NULL); - dsa->pub_key = BN_bin2bn((unsigned char*)pkey[TAG_PUBVAL].big, pkey[TAG_PUBVAL].size, NULL); + BIGNUM* bn_p = BN_bin2bn((unsigned char*)pkey[TAG_PRIME].big, pkey[TAG_PRIME].size, NULL); + BIGNUM* bn_q = BN_bin2bn((unsigned char*)pkey[TAG_SUBPRIME].big, pkey[TAG_SUBPRIME].size, NULL); + BIGNUM* bn_g = BN_bin2bn((unsigned char*)pkey[TAG_BASE].big, pkey[TAG_BASE].size, NULL); + BIGNUM* bn_priv_key = BN_bin2bn((unsigned char*)pkey[TAG_PRIVVAL].big, pkey[TAG_PRIVVAL].size, NULL); + BIGNUM* bn_pub_key = BN_bin2bn((unsigned char*)pkey[TAG_PUBVAL].big, pkey[TAG_PUBVAL].size, NULL); + + DSA_set0_pqg(dsa, bn_p, bn_q, bn_g); + DSA_set0_key(dsa, bn_pub_key, bn_priv_key); + ossl_pkey = EVP_PKEY_new(); // Convert DSA to EVP_PKEY diff --git a/src/bin/util/Makefile.am b/src/bin/util/Makefile.am index 54315e927..2a0490431 100644 --- a/src/bin/util/Makefile.am +++ b/src/bin/util/Makefile.am @@ -27,7 +27,8 @@ softhsm2_util_LDADD = @CRYPTO_LIBS@ \ # Compile with support of OpenSSL if WITH_OPENSSL -softhsm2_util_SOURCES += softhsm2-util-ossl.cpp +softhsm2_util_SOURCES += softhsm2-util-ossl.cpp \ + ../../lib/crypto/OSSLComp.cpp endif # Compile with support of Botan diff --git a/src/bin/util/softhsm2-util-ossl.cpp b/src/bin/util/softhsm2-util-ossl.cpp index eaec9cec9..154f14dae 100644 --- a/src/bin/util/softhsm2-util-ossl.cpp +++ b/src/bin/util/softhsm2-util-ossl.cpp @@ -34,6 +34,7 @@ #define UTIL_OSSL #include "softhsm2-util.h" #include "softhsm2-util-ossl.h" +#include "OSSLComp.h" #include #include @@ -94,7 +95,7 @@ int crypto_import_key_pair EC_KEY* ecdsa = NULL; #endif - switch (EVP_PKEY_type(pkey->type)) + switch (EVP_PKEY_type(EVP_PKEY_id(pkey))) { case EVP_PKEY_RSA: rsa = EVP_PKEY_get1_RSA(pkey); @@ -193,13 +194,6 @@ EVP_PKEY* crypto_read_file(char* filePath, char* filePIN) } } - if (p8inf->broken) - { - fprintf(stderr, "ERROR: Broken key encoding.\n"); - PKCS8_PRIV_KEY_INFO_free(p8inf); - return NULL; - } - // Convert the PKCS#8 to OpenSSL pkey = EVP_PKCS82PKEY(p8inf); PKCS8_PRIV_KEY_INFO_free(p8inf); @@ -310,14 +304,26 @@ rsa_key_material_t* crypto_malloc_rsa(RSA* rsa) return NULL; } - keyMat->sizeE = BN_num_bytes(rsa->e); - keyMat->sizeN = BN_num_bytes(rsa->n); - keyMat->sizeD = BN_num_bytes(rsa->d); - keyMat->sizeP = BN_num_bytes(rsa->p); - keyMat->sizeQ = BN_num_bytes(rsa->q); - keyMat->sizeDMP1 = BN_num_bytes(rsa->dmp1); - keyMat->sizeDMQ1 = BN_num_bytes(rsa->dmq1); - keyMat->sizeIQMP = BN_num_bytes(rsa->iqmp); + const BIGNUM* bn_e = NULL; + const BIGNUM* bn_n = NULL; + const BIGNUM* bn_d = NULL; + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_q = NULL; + const BIGNUM* bn_dmp1 = NULL; + const BIGNUM* bn_dmq1 = NULL; + const BIGNUM* bn_iqmp = NULL; + RSA_get0_factors(rsa, &bn_p, &bn_q); + RSA_get0_crt_params(rsa, &bn_dmp1, &bn_dmq1, &bn_iqmp); + RSA_get0_key(rsa, &bn_n, &bn_e, &bn_d); + + keyMat->sizeE = BN_num_bytes(bn_e); + keyMat->sizeN = BN_num_bytes(bn_n); + keyMat->sizeD = BN_num_bytes(bn_d); + keyMat->sizeP = BN_num_bytes(bn_p); + keyMat->sizeQ = BN_num_bytes(bn_q); + keyMat->sizeDMP1 = BN_num_bytes(bn_dmp1); + keyMat->sizeDMQ1 = BN_num_bytes(bn_dmq1); + keyMat->sizeIQMP = BN_num_bytes(bn_iqmp); keyMat->bigE = (CK_VOID_PTR)malloc(keyMat->sizeE); keyMat->bigN = (CK_VOID_PTR)malloc(keyMat->sizeN); @@ -344,14 +350,14 @@ rsa_key_material_t* crypto_malloc_rsa(RSA* rsa) return NULL; } - BN_bn2bin(rsa->e, (unsigned char*)keyMat->bigE); - BN_bn2bin(rsa->n, (unsigned char*)keyMat->bigN); - BN_bn2bin(rsa->d, (unsigned char*)keyMat->bigD); - BN_bn2bin(rsa->p, (unsigned char*)keyMat->bigP); - BN_bn2bin(rsa->q, (unsigned char*)keyMat->bigQ); - BN_bn2bin(rsa->dmp1, (unsigned char*)keyMat->bigDMP1); - BN_bn2bin(rsa->dmq1, (unsigned char*)keyMat->bigDMQ1); - BN_bn2bin(rsa->iqmp, (unsigned char*)keyMat->bigIQMP); + BN_bn2bin(bn_e, (unsigned char*)keyMat->bigE); + BN_bn2bin(bn_n, (unsigned char*)keyMat->bigN); + BN_bn2bin(bn_d, (unsigned char*)keyMat->bigD); + BN_bn2bin(bn_p, (unsigned char*)keyMat->bigP); + BN_bn2bin(bn_q, (unsigned char*)keyMat->bigQ); + BN_bn2bin(bn_dmp1, (unsigned char*)keyMat->bigDMP1); + BN_bn2bin(bn_dmq1, (unsigned char*)keyMat->bigDMQ1); + BN_bn2bin(bn_iqmp, (unsigned char*)keyMat->bigIQMP); return keyMat; } @@ -467,11 +473,19 @@ dsa_key_material_t* crypto_malloc_dsa(DSA* dsa) return NULL; } - keyMat->sizeP = BN_num_bytes(dsa->p); - keyMat->sizeQ = BN_num_bytes(dsa->q); - keyMat->sizeG = BN_num_bytes(dsa->g); - keyMat->sizeX = BN_num_bytes(dsa->priv_key); - keyMat->sizeY = BN_num_bytes(dsa->pub_key); + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_q = NULL; + const BIGNUM* bn_g = NULL; + const BIGNUM* bn_priv_key = NULL; + const BIGNUM* bn_pub_key = NULL; + DSA_get0_pqg(dsa, &bn_p, &bn_q, &bn_g); + DSA_get0_key(dsa, &bn_pub_key, &bn_priv_key); + + keyMat->sizeP = BN_num_bytes(bn_p); + keyMat->sizeQ = BN_num_bytes(bn_q); + keyMat->sizeG = BN_num_bytes(bn_g); + keyMat->sizeX = BN_num_bytes(bn_priv_key); + keyMat->sizeY = BN_num_bytes(bn_pub_key); keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP); keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ); @@ -485,11 +499,11 @@ dsa_key_material_t* crypto_malloc_dsa(DSA* dsa) return NULL; } - BN_bn2bin(dsa->p, (unsigned char*)keyMat->bigP); - BN_bn2bin(dsa->q, (unsigned char*)keyMat->bigQ); - BN_bn2bin(dsa->g, (unsigned char*)keyMat->bigG); - BN_bn2bin(dsa->priv_key, (unsigned char*)keyMat->bigX); - BN_bn2bin(dsa->pub_key, (unsigned char*)keyMat->bigY); + BN_bn2bin(bn_p, (unsigned char*)keyMat->bigP); + BN_bn2bin(bn_q, (unsigned char*)keyMat->bigQ); + BN_bn2bin(bn_g, (unsigned char*)keyMat->bigG); + BN_bn2bin(bn_priv_key, (unsigned char*)keyMat->bigX); + BN_bn2bin(bn_pub_key, (unsigned char*)keyMat->bigY); return keyMat; } diff --git a/src/lib/crypto/Makefile.am b/src/lib/crypto/Makefile.am index 31ff4596d..a2c875e84 100644 --- a/src/lib/crypto/Makefile.am +++ b/src/lib/crypto/Makefile.am @@ -39,6 +39,7 @@ EXTRA_DIST = $(srcdir)/*.h $(srcdir)/*.cpp # Compile with support of OpenSSL if WITH_OPENSSL libsofthsm_crypto_la_SOURCES += OSSLAES.cpp \ + OSSLComp.cpp \ OSSLCryptoFactory.cpp \ OSSLDES.cpp \ OSSLDH.cpp \ diff --git a/src/lib/crypto/OSSLAES.cpp b/src/lib/crypto/OSSLAES.cpp index d35aadd56..ba53bce56 100644 --- a/src/lib/crypto/OSSLAES.cpp +++ b/src/lib/crypto/OSSLAES.cpp @@ -156,13 +156,12 @@ bool OSSLAES::wrapUnwrapKey(const SymmetricKey* key, const SymWrap::Type mode, c } // Allocate the EVP context - EVP_CIPHER_CTX* pWrapCTX = (EVP_CIPHER_CTX*) salloc(sizeof(EVP_CIPHER_CTX)); + EVP_CIPHER_CTX* pWrapCTX = EVP_CIPHER_CTX_new(); if (pWrapCTX == NULL) { ERROR_MSG("Failed to allocate space for EVP_CIPHER_CTX"); return false; } - EVP_CIPHER_CTX_init(pWrapCTX); EVP_CIPHER_CTX_set_flags(pWrapCTX, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); int rv = EVP_CipherInit_ex(pWrapCTX, cipher, NULL, (unsigned char*) key->getKeyBits().const_byte_str(), NULL, wrap); @@ -173,8 +172,7 @@ bool OSSLAES::wrapUnwrapKey(const SymmetricKey* key, const SymWrap::Type mode, c { ERROR_MSG("Failed to initialise EVP cipher %swrap operation", prefix); - EVP_CIPHER_CTX_cleanup(pWrapCTX); - sfree(pWrapCTX); + EVP_CIPHER_CTX_free(pWrapCTX); return false; } @@ -191,10 +189,10 @@ bool OSSLAES::wrapUnwrapKey(const SymmetricKey* key, const SymWrap::Type mode, c { ERROR_MSG("Failed EVP %swrap operation", prefix); - EVP_CIPHER_CTX_cleanup(pWrapCTX); - sfree(pWrapCTX); + EVP_CIPHER_CTX_free(pWrapCTX); return false; } + EVP_CIPHER_CTX_free(pWrapCTX); outLen += curBlockLen; out.resize(outLen); return true; diff --git a/src/lib/crypto/OSSLComp.cpp b/src/lib/crypto/OSSLComp.cpp new file mode 100644 index 000000000..31333f6c2 --- /dev/null +++ b/src/lib/crypto/OSSLComp.cpp @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2016 SURFnet bv + * All rights reserved. + * + * 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. + */ + +/***************************************************************************** + OSSLUtil.cpp + + Adding OpenSSL forward-compatible code as suggested by OpenSSL + *****************************************************************************/ + +#include "config.h" +#include "OSSLComp.h" +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#ifdef WITH_ECC +#include +#endif +#include + +#include + +// EVP digest routines +EVP_MD_CTX *EVP_MD_CTX_new(void) +{ + EVP_MD_CTX *ctx = (EVP_MD_CTX*)OPENSSL_malloc(sizeof *ctx); + + if (ctx) + EVP_MD_CTX_init(ctx); + + return ctx; +} + +void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +{ + if (ctx) + { + EVP_MD_CTX_cleanup(ctx); + OPENSSL_free(ctx); + } +} + +// HMAC routines +HMAC_CTX *HMAC_CTX_new(void) +{ + HMAC_CTX *ctx = (HMAC_CTX*)OPENSSL_malloc(sizeof(*ctx)); + if (ctx == NULL) return NULL; + + HMAC_CTX_init(ctx); + + return ctx; +} + +void HMAC_CTX_free(HMAC_CTX *ctx) +{ + if (ctx == NULL) return; + + HMAC_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} + +// DH routines +void DH_get0_pqg(const DH *dh, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) +{ + if (p != NULL) + *p = dh->p; + if (q != NULL) + *q = dh->q; + if (g != NULL) + *g = dh->g; +} + +int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + /* If the fields p and g in d are NULL, the corresponding input + * parameters MUST be non-NULL. q may remain NULL. + */ + if ((dh->p == NULL && p == NULL) + || (dh->g == NULL && g == NULL)) + return 0; + + if (p != NULL) + { + BN_free(dh->p); + dh->p = p; + } + if (q != NULL) + { + BN_free(dh->q); + dh->q = q; + } + if (g != NULL) + { + BN_free(dh->g); + dh->g = g; + } + + if (q != NULL) + { + dh->length = BN_num_bits(q); + } + + return 1; +} + +void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) +{ + if (pub_key != NULL) + *pub_key = dh->pub_key; + if (priv_key != NULL) + *priv_key = dh->priv_key; +} + +int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) +{ + /* If the field pub_key in dh is NULL, the corresponding input + * parameters MUST be non-NULL. The priv_key field may + * be left NULL. + */ + if (dh->pub_key == NULL && pub_key == NULL) + return 0; + + if (pub_key != NULL) + { + BN_free(dh->pub_key); + dh->pub_key = pub_key; + } + if (priv_key != NULL) + { + BN_free(dh->priv_key); + dh->priv_key = priv_key; + } + + return 1; +} + +long DH_get_length(const DH *dh) +{ + return dh->length; +} + +int DH_set_length(DH *dh, long length) +{ + dh->length = length; + + return 1; +} + +// DSA routines +void DSA_get0_pqg(const DSA *d, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) +{ + if (p != NULL) + *p = d->p; + if (q != NULL) + *q = d->q; + if (g != NULL) + *g = d->g; +} + +int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + /* If the fields p, q and g in d are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((d->p == NULL && p == NULL) + || (d->q == NULL && q == NULL) + || (d->g == NULL && g == NULL)) + return 0; + + if (p != NULL) + { + BN_free(d->p); + d->p = p; + } + if (q != NULL) + { + BN_free(d->q); + d->q = q; + } + if (g != NULL) + { + BN_free(d->g); + d->g = g; + } + + return 1; +} + +void DSA_get0_key(const DSA *d, + const BIGNUM **pub_key, const BIGNUM **priv_key) +{ + if (pub_key != NULL) + *pub_key = d->pub_key; + if (priv_key != NULL) + *priv_key = d->priv_key; +} + +int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) +{ + /* If the field pub_key in d is NULL, the corresponding input + * parameters MUST be non-NULL. The priv_key field may + * be left NULL. + */ + if (d->pub_key == NULL && pub_key == NULL) + return 0; + + if (pub_key != NULL) + { + BN_free(d->pub_key); + d->pub_key = pub_key; + } + if (priv_key != NULL) + { + BN_free(d->priv_key); + d->priv_key = priv_key; + } + + return 1; +} + +// DSA_SIG routines +void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +{ + if (pr != NULL) + *pr = sig->r; + if (ps != NULL) + *ps = sig->s; +} + +int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + if (r == NULL || s == NULL) + return 0; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + return 1; +} + +// ECDSA_SIG routines +#ifdef WITH_ECC +void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +{ + if (pr != NULL) + *pr = sig->r; + if (ps != NULL) + *ps = sig->s; +} + +int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + if (r == NULL || s == NULL) + return 0; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + + return 1; +} +#endif + +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) +{ + /* If the fields n and e in r are NULL, the corresponding input + * parameters MUST be non-NULL for n and e. d may be + * left NULL (in case only the public key is used). + */ + if ((r->n == NULL && n == NULL) + || (r->e == NULL && e == NULL)) + return 0; + + if (n != NULL) + { + BN_free(r->n); + r->n = n; + } + if (e != NULL) + { + BN_free(r->e); + r->e = e; + } + if (d != NULL) + { + BN_free(r->d); + r->d = d; + } + + return 1; +} + +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) +{ + /* If the fields p and q in r are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((r->p == NULL && p == NULL) + || (r->q == NULL && q == NULL)) + return 0; + + if (p != NULL) + { + BN_free(r->p); + r->p = p; + } + if (q != NULL) + { + BN_free(r->q); + r->q = q; + } + + return 1; +} + +int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) +{ + /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((r->dmp1 == NULL && dmp1 == NULL) + || (r->dmq1 == NULL && dmq1 == NULL) + || (r->iqmp == NULL && iqmp == NULL)) + return 0; + + if (dmp1 != NULL) + { + BN_free(r->dmp1); + r->dmp1 = dmp1; + } + if (dmq1 != NULL) + { + BN_free(r->dmq1); + r->dmq1 = dmq1; + } + if (iqmp != NULL) + { + BN_free(r->iqmp); + r->iqmp = iqmp; + } + + return 1; +} + +void RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) +{ + if (n != NULL) + *n = r->n; + if (e != NULL) + *e = r->e; + if (d != NULL) + *d = r->d; +} + +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) +{ + if (p != NULL) + *p = r->p; + if (q != NULL) + *q = r->q; +} + +void RSA_get0_crt_params(const RSA *r, + const BIGNUM **dmp1, const BIGNUM **dmq1, + const BIGNUM **iqmp) +{ + if (dmp1 != NULL) + *dmp1 = r->dmp1; + if (dmq1 != NULL) + *dmq1 = r->dmq1; + if (iqmp != NULL) + *iqmp = r->iqmp; +} + +#endif diff --git a/src/lib/crypto/OSSLComp.h b/src/lib/crypto/OSSLComp.h new file mode 100644 index 000000000..71d6c2112 --- /dev/null +++ b/src/lib/crypto/OSSLComp.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016 SURFnet bv + * All rights reserved. + * + * 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. + */ + +/***************************************************************************** + OSSLComp.h + + Adding OpenSSL forward-compatible code as suggested by OpenSSL + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLCOMP_H +#define _SOFTHSM_V2_OSSLCOMP_H + +#include "config.h" +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +#include +#include +#include +#include +#ifdef WITH_ECC +#include +#endif +#include + +// EVP digest routines +EVP_MD_CTX *EVP_MD_CTX_new(void); +void EVP_MD_CTX_free(EVP_MD_CTX *ctx); + +// HMAC routines +HMAC_CTX *HMAC_CTX_new(void); +void HMAC_CTX_free(HMAC_CTX *ctx); + +// DH routines +void DH_get0_pqg(const DH *dh, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); +int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); +void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key); +int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); +long DH_get_length(const DH *dh); +int DH_set_length(DH *dh, long length); + +// DSA routines +void DSA_get0_pqg(const DSA *d, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); +int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g); +void DSA_get0_key(const DSA *d, + const BIGNUM **pub_key, const BIGNUM **priv_key); +int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); + +// DSA_SIG routines +void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); +int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s); + +// ECDSA_SIG routines +#ifdef WITH_ECC +void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); +int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); +#endif + +// RSA routines +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); +int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp); +void RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); +void RSA_get0_crt_params(const RSA *r, + const BIGNUM **dmp1, const BIGNUM **dmq1, + const BIGNUM **iqmp); + +#endif + +#endif // !_SOFTHSM_V2_OSSLCOMP_H diff --git a/src/lib/crypto/OSSLCryptoFactory.cpp b/src/lib/crypto/OSSLCryptoFactory.cpp index 3aa8dcdbd..202412fcd 100644 --- a/src/lib/crypto/OSSLCryptoFactory.cpp +++ b/src/lib/crypto/OSSLCryptoFactory.cpp @@ -60,7 +60,9 @@ #endif #include #include +#include #include +#include #include #include #ifdef WITH_GOST @@ -146,7 +148,12 @@ OSSLCryptoFactory::OSSLCryptoFactory() #ifdef WITH_GOST // Load engines +#if OPENSSL_VERSION_NUMBER < 0x10100000L ENGINE_load_builtin_engines(); +#else + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN | + OPENSSL_INIT_LOAD_CONFIG, NULL); +#endif // Initialise the GOST engine eg = ENGINE_by_id("gost"); diff --git a/src/lib/crypto/OSSLDH.cpp b/src/lib/crypto/OSSLDH.cpp index 3b03fb2ed..ee61733cc 100644 --- a/src/lib/crypto/OSSLDH.cpp +++ b/src/lib/crypto/OSSLDH.cpp @@ -35,6 +35,7 @@ #include "OSSLDH.h" #include "CryptoFactory.h" #include "DHParameters.h" +#include "OSSLComp.h" #include "OSSLDHKeyPair.h" #include "OSSLUtil.h" #include @@ -127,7 +128,6 @@ bool OSSLDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters // Generate the key-pair DH* dh = DH_new(); - if (dh == NULL) { ERROR_MSG("Failed to instantiate OpenSSL DH object"); @@ -135,22 +135,25 @@ bool OSSLDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters return false; } - if (dh->p != NULL) - BN_clear_free(dh->p); - dh->p = OSSL::byteString2bn(params->getP()); - if (dh->g != NULL) - BN_clear_free(dh->g); - dh->g = OSSL::byteString2bn(params->getG()); + BIGNUM* bn_p = OSSL::byteString2bn(params->getP()); + BIGNUM* bn_g = OSSL::byteString2bn(params->getG()); - // PKCS#3: 2^(l-1) <= x < 2^l - if (params->getXBitLength() > 0) + if (!DH_set0_pqg(dh, bn_p, NULL, bn_g)) { - if (dh->priv_key == NULL) - dh->priv_key = BN_new(); + ERROR_MSG("DH set pqg failed (0x%08X)", ERR_get_error()); + + BN_free(bn_p); + BN_free(bn_g); + DH_free(dh); + + return false; + } - if (BN_rand(dh->priv_key, params->getXBitLength(), 0, 0) != 1) + if (params->getXBitLength() > 0) + { + if (!DH_set_length(dh, params->getXBitLength())) { - ERROR_MSG("DH private key generation failed (0x%08X)", ERR_get_error()); + ERROR_MSG("DH set length failed (0x%08X)", ERR_get_error()); DH_free(dh); @@ -194,7 +197,15 @@ bool OSSLDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, Priv // Get keys DH *pub = ((OSSLDHPublicKey *)publicKey)->getOSSLKey(); DH *priv = ((OSSLDHPrivateKey *)privateKey)->getOSSLKey(); - if (pub == NULL || pub->pub_key == NULL || priv == NULL) + if (pub == NULL || priv == NULL) + { + ERROR_MSG("Failed to get OpenSSL DH keys"); + + return false; + } + const BIGNUM* bn_pub_key = NULL; + DH_get0_key(pub, &bn_pub_key, NULL); + if (bn_pub_key == NULL) { ERROR_MSG("Failed to get OpenSSL DH keys"); @@ -206,7 +217,7 @@ bool OSSLDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, Priv int size = DH_size(priv); secret.wipe(size); derivedSecret.wipe(size); - int keySize = DH_compute_key(&derivedSecret[0], pub->pub_key, priv); + int keySize = DH_compute_key(&derivedSecret[0], bn_pub_key, priv); if (keySize <= 0) { @@ -262,20 +273,32 @@ bool OSSLDH::generateParameters(AsymmetricParameters** ppParams, void* parameter return false; } - DH* dh = DH_generate_parameters(bitLen, 2, NULL, NULL); - + DH* dh = DH_new(); if (dh == NULL) + { + ERROR_MSG("Failed to create DH object"); + + return false; + } + + if (!DH_generate_parameters_ex(dh, bitLen, 2, NULL)) { ERROR_MSG("Failed to generate %d bit DH parameters", bitLen); + DH_free(dh); + return false; } // Store the DH parameters DHParameters* params = new DHParameters(); - ByteString p = OSSL::bn2ByteString(dh->p); params->setP(p); - ByteString g = OSSL::bn2ByteString(dh->g); params->setG(g); + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_g = NULL; + + DH_get0_pqg(dh, &bn_p, NULL, &bn_g); + ByteString p = OSSL::bn2ByteString(bn_p); params->setP(p); + ByteString g = OSSL::bn2ByteString(bn_g); params->setG(g); *ppParams = params; diff --git a/src/lib/crypto/OSSLDHPrivateKey.cpp b/src/lib/crypto/OSSLDHPrivateKey.cpp index 7e5c31802..4c1b9c3a9 100644 --- a/src/lib/crypto/OSSLDHPrivateKey.cpp +++ b/src/lib/crypto/OSSLDHPrivateKey.cpp @@ -32,27 +32,25 @@ #include "config.h" #include "log.h" +#include "OSSLComp.h" #include "OSSLDHPrivateKey.h" #include "OSSLUtil.h" #include #include +#ifdef WITH_FIPS +#include +#endif #include // Constructors OSSLDHPrivateKey::OSSLDHPrivateKey() { - dh = DH_new(); - - // Use the OpenSSL implementation and not any engine - DH_set_method(dh, DH_get_default_method()); + dh = NULL; } OSSLDHPrivateKey::OSSLDHPrivateKey(const DH* inDH) { - dh = DH_new(); - - // Use the OpenSSL implementation and not any engine - DH_set_method(dh, DH_OpenSSL()); + dh = NULL; setFromOSSL(inDH); } @@ -69,19 +67,26 @@ OSSLDHPrivateKey::~OSSLDHPrivateKey() // Set from OpenSSL representation void OSSLDHPrivateKey::setFromOSSL(const DH* inDH) { - if (inDH->p) + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_g = NULL; + const BIGNUM* bn_priv_key = NULL; + + DH_get0_pqg(inDH, &bn_p, NULL, &bn_g); + DH_get0_key(inDH, NULL, &bn_priv_key); + + if (bn_p) { - ByteString inP = OSSL::bn2ByteString(inDH->p); + ByteString inP = OSSL::bn2ByteString(bn_p); setP(inP); } - if (inDH->g) + if (bn_g) { - ByteString inG = OSSL::bn2ByteString(inDH->g); + ByteString inG = OSSL::bn2ByteString(bn_g); setG(inG); } - if (inDH->priv_key) + if (bn_priv_key) { - ByteString inX = OSSL::bn2ByteString(inDH->priv_key); + ByteString inX = OSSL::bn2ByteString(bn_priv_key); setX(inX); } } @@ -97,13 +102,11 @@ void OSSLDHPrivateKey::setX(const ByteString& inX) { DHPrivateKey::setX(inX); - if (dh->priv_key) + if (dh) { - BN_clear_free(dh->priv_key); - dh->priv_key = NULL; + DH_free(dh); + dh = NULL; } - - dh->priv_key = OSSL::byteString2bn(inX); } @@ -112,32 +115,29 @@ void OSSLDHPrivateKey::setP(const ByteString& inP) { DHPrivateKey::setP(inP); - if (dh->p) + if (dh) { - BN_clear_free(dh->p); - dh->p = NULL; + DH_free(dh); + dh = NULL; } - - dh->p = OSSL::byteString2bn(inP); } void OSSLDHPrivateKey::setG(const ByteString& inG) { DHPrivateKey::setG(inG); - if (dh->g) + if (dh) { - BN_clear_free(dh->g); - dh->g = NULL; + DH_free(dh); + dh = NULL; } - - dh->g = OSSL::byteString2bn(inG); } // Encode into PKCS#8 DER ByteString OSSLDHPrivateKey::PKCS8Encode() { ByteString der; + if (dh == NULL) createOSSLKey(); if (dh == NULL) return der; EVP_PKEY* pkey = EVP_PKEY_new(); if (pkey == NULL) return der; @@ -185,6 +185,55 @@ bool OSSLDHPrivateKey::PKCS8Decode(const ByteString& ber) // Retrieve the OpenSSL representation of the key DH* OSSLDHPrivateKey::getOSSLKey() { + if (dh == NULL) createOSSLKey(); + return dh; } +// Create the OpenSSL representation of the key +void OSSLDHPrivateKey::createOSSLKey() +{ + if (dh != NULL) return; + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) + { + ERROR_MSG("Could not create BN_CTX"); + return; + } + + dh = DH_new(); + if (dh == NULL) + { + ERROR_MSG("Could not create DH object"); + return; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +#ifdef WITH_FIPS + if (FIPS_mode()) + DH_set_method(dh, FIPS_dh_openssl()); + else + DH_set_method(dh, DH_OpenSSL()); +#else + DH_set_method(dh, DH_OpenSSL()); +#endif + +#else + DH_set_method(dh, DH_OpenSSL()); +#endif + + BIGNUM* bn_p = OSSL::byteString2bn(p); + BIGNUM* bn_g = OSSL::byteString2bn(g); + BIGNUM* bn_priv_key = OSSL::byteString2bn(x); + BIGNUM* bn_pub_key = BN_new(); + + BN_mod_exp(bn_pub_key, bn_g, bn_priv_key, bn_p, ctx); + BN_CTX_free(ctx); + + DH_set0_pqg(dh, bn_p, NULL, bn_g); + DH_set0_key(dh, bn_pub_key, bn_priv_key); +} + diff --git a/src/lib/crypto/OSSLDHPrivateKey.h b/src/lib/crypto/OSSLDHPrivateKey.h index a0d760b53..2cf85992a 100644 --- a/src/lib/crypto/OSSLDHPrivateKey.h +++ b/src/lib/crypto/OSSLDHPrivateKey.h @@ -76,6 +76,9 @@ class OSSLDHPrivateKey : public DHPrivateKey private: // The internal OpenSSL representation DH* dh; + + // Create the OpenSSL representation of the key + void createOSSLKey(); }; #endif // !_SOFTHSM_V2_OSSLDHPRIVATEKEY_H diff --git a/src/lib/crypto/OSSLDHPublicKey.cpp b/src/lib/crypto/OSSLDHPublicKey.cpp index ca23b23f9..78820e178 100644 --- a/src/lib/crypto/OSSLDHPublicKey.cpp +++ b/src/lib/crypto/OSSLDHPublicKey.cpp @@ -32,26 +32,24 @@ #include "config.h" #include "log.h" +#include "OSSLComp.h" #include "OSSLDHPublicKey.h" #include "OSSLUtil.h" #include +#ifdef WITH_FIPS +#include +#endif #include // Constructors OSSLDHPublicKey::OSSLDHPublicKey() { - dh = DH_new(); - - // Use the OpenSSL implementation and not any engine - DH_set_method(dh, DH_get_default_method()); + dh = NULL; } OSSLDHPublicKey::OSSLDHPublicKey(const DH* inDH) { - dh = DH_new(); - - // Use the OpenSSL implementation and not any engine - DH_set_method(dh, DH_OpenSSL()); + dh = NULL; setFromOSSL(inDH); } @@ -68,19 +66,26 @@ OSSLDHPublicKey::~OSSLDHPublicKey() // Set from OpenSSL representation void OSSLDHPublicKey::setFromOSSL(const DH* inDH) { - if (inDH->p) + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_g = NULL; + const BIGNUM* bn_pub_key = NULL; + + DH_get0_pqg(inDH, &bn_p, NULL, &bn_g); + DH_get0_key(inDH, &bn_pub_key, NULL); + + if (bn_p) { - ByteString inP = OSSL::bn2ByteString(inDH->p); + ByteString inP = OSSL::bn2ByteString(bn_p); setP(inP); } - if (inDH->g) + if (bn_g) { - ByteString inG = OSSL::bn2ByteString(inDH->g); + ByteString inG = OSSL::bn2ByteString(bn_g); setG(inG); } - if (inDH->pub_key) + if (bn_pub_key) { - ByteString inY = OSSL::bn2ByteString(inDH->pub_key); + ByteString inY = OSSL::bn2ByteString(bn_pub_key); setY(inY); } } @@ -96,44 +101,75 @@ void OSSLDHPublicKey::setP(const ByteString& inP) { DHPublicKey::setP(inP); - if (dh->p) + if (dh) { - BN_clear_free(dh->p); - dh->p = NULL; + DH_free(dh); + dh = NULL; } - - dh->p = OSSL::byteString2bn(inP); } void OSSLDHPublicKey::setG(const ByteString& inG) { DHPublicKey::setG(inG); - if (dh->g) + if (dh) { - BN_clear_free(dh->g); - dh->g = NULL; + DH_free(dh); + dh = NULL; } - - dh->g = OSSL::byteString2bn(inG); } void OSSLDHPublicKey::setY(const ByteString& inY) { DHPublicKey::setY(inY); - if (dh->pub_key) + if (dh) { - BN_clear_free(dh->pub_key); - dh->pub_key = NULL; + DH_free(dh); + dh = NULL; } - - dh->pub_key = OSSL::byteString2bn(inY); } // Retrieve the OpenSSL representation of the key DH* OSSLDHPublicKey::getOSSLKey() { + if (dh == NULL) createOSSLKey(); + return dh; } +// Create the OpenSSL representation of the key +void OSSLDHPublicKey::createOSSLKey() +{ + if (dh != NULL) return; + + dh = DH_new(); + if (dh == NULL) + { + ERROR_MSG("Could not create DH object"); + return; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +#ifdef WITH_FIPS + if (FIPS_mode()) + DH_set_method(dh, FIPS_dh_openssl()); + else + DH_set_method(dh, DH_OpenSSL()); +#else + DH_set_method(dh, DH_OpenSSL()); +#endif + +#else + DH_set_method(dh, DH_OpenSSL()); +#endif + + BIGNUM* bn_p = OSSL::byteString2bn(p); + BIGNUM* bn_g = OSSL::byteString2bn(g); + BIGNUM* bn_pub_key = OSSL::byteString2bn(y); + + DH_set0_pqg(dh, bn_p, NULL, bn_g); + DH_set0_key(dh, bn_pub_key, NULL); +} diff --git a/src/lib/crypto/OSSLDHPublicKey.h b/src/lib/crypto/OSSLDHPublicKey.h index 7950f0864..9f5eed87c 100644 --- a/src/lib/crypto/OSSLDHPublicKey.h +++ b/src/lib/crypto/OSSLDHPublicKey.h @@ -68,6 +68,9 @@ class OSSLDHPublicKey : public DHPublicKey private: // The internal OpenSSL representation DH* dh; + + // Create the OpenSSL representation of the key + void createOSSLKey(); }; #endif // !_SOFTHSM_V2_OSSLDHPUBLICKEY_H diff --git a/src/lib/crypto/OSSLDSA.cpp b/src/lib/crypto/OSSLDSA.cpp index a1bde8d94..06b5d5016 100644 --- a/src/lib/crypto/OSSLDSA.cpp +++ b/src/lib/crypto/OSSLDSA.cpp @@ -36,6 +36,7 @@ #include "CryptoFactory.h" #include "DSAParameters.h" #include "OSSLDSAKeyPair.h" +#include "OSSLComp.h" #include "OSSLUtil.h" #include #include @@ -86,8 +87,11 @@ bool OSSLDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, if (sig == NULL) return false; // Store the 2 values with padding - BN_bn2bin(sig->r, &signature[sigLen / 2 - BN_num_bytes(sig->r)]); - BN_bn2bin(sig->s, &signature[sigLen - BN_num_bytes(sig->s)]); + const BIGNUM* bn_r = NULL; + const BIGNUM* bn_s = NULL; + DSA_SIG_get0(sig, &bn_r, &bn_s); + BN_bn2bin(bn_r, &signature[sigLen / 2 - BN_num_bytes(bn_r)]); + BN_bn2bin(bn_s, &signature[sigLen - BN_num_bytes(bn_s)]); DSA_SIG_free(sig); return true; } @@ -222,8 +226,11 @@ bool OSSLDSA::signFinal(ByteString& signature) if (sig == NULL) return false; // Store the 2 values with padding - BN_bn2bin(sig->r, &signature[sigLen / 2 - BN_num_bytes(sig->r)]); - BN_bn2bin(sig->s, &signature[sigLen - BN_num_bytes(sig->s)]); + const BIGNUM* bn_r = NULL; + const BIGNUM* bn_s = NULL; + DSA_SIG_get0(sig, &bn_r, &bn_s); + BN_bn2bin(bn_r, &signature[sigLen / 2 - BN_num_bytes(bn_r)]); + BN_bn2bin(bn_s, &signature[sigLen - BN_num_bytes(bn_s)]); DSA_SIG_free(sig); return true; } @@ -254,9 +261,10 @@ bool OSSLDSA::verify(PublicKey* publicKey, const ByteString& originalData, if (sig == NULL) return false; const unsigned char *s = signature.const_byte_str(); - sig->r = BN_bin2bn(s, sigLen / 2, NULL); - sig->s = BN_bin2bn(s + sigLen / 2, sigLen / 2, NULL); - if (sig->r == NULL || sig->s == NULL) + BIGNUM* bn_r = BN_bin2bn(s, sigLen / 2, NULL); + BIGNUM* bn_s = BN_bin2bn(s + sigLen / 2, sigLen / 2, NULL); + if (bn_r == NULL || bn_s == NULL || + !DSA_SIG_set0(sig, bn_r, bn_s)) { DSA_SIG_free(sig); return false; @@ -405,9 +413,10 @@ bool OSSLDSA::verifyFinal(const ByteString& signature) if (sig == NULL) return false; const unsigned char *s = signature.const_byte_str(); - sig->r = BN_bin2bn(s, sigLen / 2, NULL); - sig->s = BN_bin2bn(s + sigLen / 2, sigLen / 2, NULL); - if (sig->r == NULL || sig->s == NULL) + BIGNUM* bn_r = BN_bin2bn(s, sigLen / 2, NULL); + BIGNUM* bn_s = BN_bin2bn(s + sigLen / 2, sigLen / 2, NULL); + if (bn_r == NULL || bn_s == NULL || + !DSA_SIG_set0(sig, bn_r, bn_s)) { DSA_SIG_free(sig); return false; @@ -465,7 +474,6 @@ bool OSSLDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameter // Generate the key-pair DSA* dsa = DSA_new(); - if (dsa == NULL) { ERROR_MSG("Failed to instantiate OpenSSL DSA object"); @@ -476,9 +484,10 @@ bool OSSLDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameter // Use the OpenSSL implementation and not any engine DSA_set_method(dsa, DSA_get_default_method()); - dsa->p = OSSL::byteString2bn(params->getP()); - dsa->q = OSSL::byteString2bn(params->getQ()); - dsa->g = OSSL::byteString2bn(params->getG()); + BIGNUM* bn_p = OSSL::byteString2bn(params->getP()); + BIGNUM* bn_q = OSSL::byteString2bn(params->getQ()); + BIGNUM* bn_g = OSSL::byteString2bn(params->getG()); + DSA_set0_pqg(dsa, bn_p, bn_q, bn_g); if (DSA_generate_key(dsa) != 1) { @@ -534,9 +543,10 @@ bool OSSLDSA::generateParameters(AsymmetricParameters** ppParams, void* paramete return false; } - DSA* dsa = DSA_generate_parameters(bitLen, NULL, 0, NULL, NULL, NULL, NULL); + DSA* dsa = DSA_new(); - if (dsa == NULL) + if (dsa == NULL || + !DSA_generate_parameters_ex(dsa, bitLen, NULL, 0, NULL, NULL, NULL)) { ERROR_MSG("Failed to generate %d bit DSA parameters", bitLen); @@ -546,9 +556,14 @@ bool OSSLDSA::generateParameters(AsymmetricParameters** ppParams, void* paramete // Store the DSA parameters DSAParameters* params = new DSAParameters(); - ByteString p = OSSL::bn2ByteString(dsa->p); params->setP(p); - ByteString q = OSSL::bn2ByteString(dsa->q); params->setQ(q); - ByteString g = OSSL::bn2ByteString(dsa->g); params->setG(g); + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_q = NULL; + const BIGNUM* bn_g = NULL; + DSA_get0_pqg(dsa, &bn_p, &bn_q, &bn_g); + + ByteString p = OSSL::bn2ByteString(bn_p); params->setP(p); + ByteString q = OSSL::bn2ByteString(bn_q); params->setQ(q); + ByteString g = OSSL::bn2ByteString(bn_g); params->setG(g); *ppParams = params; diff --git a/src/lib/crypto/OSSLDSAPrivateKey.cpp b/src/lib/crypto/OSSLDSAPrivateKey.cpp index cea029cbf..2192fad3c 100644 --- a/src/lib/crypto/OSSLDSAPrivateKey.cpp +++ b/src/lib/crypto/OSSLDSAPrivateKey.cpp @@ -32,27 +32,25 @@ #include "config.h" #include "log.h" +#include "OSSLComp.h" #include "OSSLDSAPrivateKey.h" #include "OSSLUtil.h" #include #include +#ifdef WITH_FIPS +#include +#endif #include // Constructors OSSLDSAPrivateKey::OSSLDSAPrivateKey() { - dsa = DSA_new(); - - // Use the OpenSSL implementation and not any engine - DSA_set_method(dsa, DSA_get_default_method()); + dsa = NULL; } OSSLDSAPrivateKey::OSSLDSAPrivateKey(const DSA* inDSA) { - dsa = DSA_new(); - - // Use the OpenSSL implementation and not any engine - DSA_set_method(dsa, DSA_OpenSSL()); + dsa = NULL; setFromOSSL(inDSA); } @@ -69,24 +67,32 @@ OSSLDSAPrivateKey::~OSSLDSAPrivateKey() // Set from OpenSSL representation void OSSLDSAPrivateKey::setFromOSSL(const DSA* inDSA) { - if (inDSA->p) + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_q = NULL; + const BIGNUM* bn_g = NULL; + const BIGNUM* bn_priv_key = NULL; + + DSA_get0_pqg(inDSA, &bn_p, &bn_q, &bn_g); + DSA_get0_key(inDSA, NULL, &bn_priv_key); + + if (bn_p) { - ByteString inP = OSSL::bn2ByteString(inDSA->p); + ByteString inP = OSSL::bn2ByteString(bn_p); setP(inP); } - if (inDSA->q) + if (bn_q) { - ByteString inQ = OSSL::bn2ByteString(inDSA->q); + ByteString inQ = OSSL::bn2ByteString(bn_q); setQ(inQ); } - if (inDSA->g) + if (bn_g) { - ByteString inG = OSSL::bn2ByteString(inDSA->g); + ByteString inG = OSSL::bn2ByteString(bn_g); setG(inG); } - if (inDSA->priv_key) + if (bn_priv_key) { - ByteString inX = OSSL::bn2ByteString(inDSA->priv_key); + ByteString inX = OSSL::bn2ByteString(bn_priv_key); setX(inX); } } @@ -102,13 +108,11 @@ void OSSLDSAPrivateKey::setX(const ByteString& inX) { DSAPrivateKey::setX(inX); - if (dsa->priv_key) + if (dsa) { - BN_clear_free(dsa->priv_key); - dsa->priv_key = NULL; + DSA_free(dsa); + dsa = NULL; } - - dsa->priv_key = OSSL::byteString2bn(inX); } @@ -117,45 +121,40 @@ void OSSLDSAPrivateKey::setP(const ByteString& inP) { DSAPrivateKey::setP(inP); - if (dsa->p) + if (dsa) { - BN_clear_free(dsa->p); - dsa->p = NULL; + DSA_free(dsa); + dsa = NULL; } - - dsa->p = OSSL::byteString2bn(inP); } void OSSLDSAPrivateKey::setQ(const ByteString& inQ) { DSAPrivateKey::setQ(inQ); - if (dsa->q) + if (dsa) { - BN_clear_free(dsa->q); - dsa->q = NULL; + DSA_free(dsa); + dsa = NULL; } - - dsa->q = OSSL::byteString2bn(inQ); } void OSSLDSAPrivateKey::setG(const ByteString& inG) { DSAPrivateKey::setG(inG); - if (dsa->g) + if (dsa) { - BN_clear_free(dsa->g); - dsa->g = NULL; + DSA_free(dsa); + dsa = NULL; } - - dsa->g = OSSL::byteString2bn(inG); } // Encode into PKCS#8 DER ByteString OSSLDSAPrivateKey::PKCS8Encode() { ByteString der; + if (dsa == NULL) createOSSLKey(); if (dsa == NULL) return der; EVP_PKEY* pkey = EVP_PKEY_new(); if (pkey == NULL) return der; @@ -203,6 +202,55 @@ bool OSSLDSAPrivateKey::PKCS8Decode(const ByteString& ber) // Retrieve the OpenSSL representation of the key DSA* OSSLDSAPrivateKey::getOSSLKey() { + if (dsa == NULL) createOSSLKey(); + return dsa; } +// Create the OpenSSL representation of the key +void OSSLDSAPrivateKey::createOSSLKey() +{ + if (dsa != NULL) return; + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) + { + ERROR_MSG("Could not create BN_CTX"); + return; + } + + dsa = DSA_new(); + if (dsa == NULL) + { + ERROR_MSG("Could not create DSA object"); + return; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +#ifdef WITH_FIPS + if (FIPS_mode()) + DSA_set_method(dsa, FIPS_dsa_openssl()); + else + DSA_set_method(dsa, DSA_OpenSSL()); +#else + DSA_set_method(dsa, DSA_OpenSSL()); +#endif + +#else + DSA_set_method(dsa, DSA_OpenSSL()); +#endif + + BIGNUM* bn_p = OSSL::byteString2bn(p); + BIGNUM* bn_q = OSSL::byteString2bn(q); + BIGNUM* bn_g = OSSL::byteString2bn(g); + BIGNUM* bn_priv_key = OSSL::byteString2bn(x); + BIGNUM* bn_pub_key = BN_new(); + + BN_mod_exp(bn_pub_key, bn_g, bn_priv_key, bn_p, ctx); + BN_CTX_free(ctx); + + DSA_set0_pqg(dsa, bn_p, bn_q, bn_g); + DSA_set0_key(dsa, bn_pub_key, bn_priv_key); +} diff --git a/src/lib/crypto/OSSLDSAPrivateKey.h b/src/lib/crypto/OSSLDSAPrivateKey.h index 557f0b41c..0e7a9efec 100644 --- a/src/lib/crypto/OSSLDSAPrivateKey.h +++ b/src/lib/crypto/OSSLDSAPrivateKey.h @@ -77,6 +77,9 @@ class OSSLDSAPrivateKey : public DSAPrivateKey private: // The internal OpenSSL representation DSA* dsa; + + // Create the OpenSSL representation of the key + void createOSSLKey(); }; #endif // !_SOFTHSM_V2_OSSLDSAPRIVATEKEY_H diff --git a/src/lib/crypto/OSSLDSAPublicKey.cpp b/src/lib/crypto/OSSLDSAPublicKey.cpp index a1ef14052..71ec3bfb4 100644 --- a/src/lib/crypto/OSSLDSAPublicKey.cpp +++ b/src/lib/crypto/OSSLDSAPublicKey.cpp @@ -33,25 +33,23 @@ #include "config.h" #include "log.h" #include "OSSLDSAPublicKey.h" +#include "OSSLComp.h" #include "OSSLUtil.h" #include +#ifdef WITH_FIPS +#include +#endif #include // Constructors OSSLDSAPublicKey::OSSLDSAPublicKey() { - dsa = DSA_new(); - - // Use the OpenSSL implementation and not any engine - DSA_set_method(dsa, DSA_get_default_method()); + dsa = NULL; } OSSLDSAPublicKey::OSSLDSAPublicKey(const DSA* inDSA) { - dsa = DSA_new(); - - // Use the OpenSSL implementation and not any engine - DSA_set_method(dsa, DSA_OpenSSL()); + dsa = NULL; setFromOSSL(inDSA); } @@ -68,24 +66,32 @@ OSSLDSAPublicKey::~OSSLDSAPublicKey() // Set from OpenSSL representation void OSSLDSAPublicKey::setFromOSSL(const DSA* inDSA) { - if (inDSA->p) + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_q = NULL; + const BIGNUM* bn_g = NULL; + const BIGNUM* bn_pub_key = NULL; + + DSA_get0_pqg(inDSA, &bn_p, &bn_q, &bn_g); + DSA_get0_key(inDSA, &bn_pub_key, NULL); + + if (bn_p) { - ByteString inP = OSSL::bn2ByteString(inDSA->p); + ByteString inP = OSSL::bn2ByteString(bn_p); setP(inP); } - if (inDSA->q) + if (bn_q) { - ByteString inQ = OSSL::bn2ByteString(inDSA->q); + ByteString inQ = OSSL::bn2ByteString(bn_q); setQ(inQ); } - if (inDSA->g) + if (bn_g) { - ByteString inG = OSSL::bn2ByteString(inDSA->g); + ByteString inG = OSSL::bn2ByteString(bn_g); setG(inG); } - if (inDSA->pub_key) + if (bn_pub_key) { - ByteString inY = OSSL::bn2ByteString(inDSA->pub_key); + ByteString inY = OSSL::bn2ByteString(bn_pub_key); setY(inY); } } @@ -101,57 +107,87 @@ void OSSLDSAPublicKey::setP(const ByteString& inP) { DSAPublicKey::setP(inP); - if (dsa->p) + if (dsa) { - BN_clear_free(dsa->p); - dsa->p = NULL; + DSA_free(dsa); + dsa = NULL; } - - dsa->p = OSSL::byteString2bn(inP); } void OSSLDSAPublicKey::setQ(const ByteString& inQ) { DSAPublicKey::setQ(inQ); - if (dsa->q) + if (dsa) { - BN_clear_free(dsa->q); - dsa->q = NULL; + DSA_free(dsa); + dsa = NULL; } - - dsa->q = OSSL::byteString2bn(inQ); } void OSSLDSAPublicKey::setG(const ByteString& inG) { DSAPublicKey::setG(inG); - if (dsa->g) + if (dsa) { - BN_clear_free(dsa->g); - dsa->g = NULL; + DSA_free(dsa); + dsa = NULL; } - - dsa->g = OSSL::byteString2bn(inG); } void OSSLDSAPublicKey::setY(const ByteString& inY) { DSAPublicKey::setY(inY); - if (dsa->pub_key) + if (dsa) { - BN_clear_free(dsa->pub_key); - dsa->pub_key = NULL; + DSA_free(dsa); + dsa = NULL; } - - dsa->pub_key = OSSL::byteString2bn(inY); } // Retrieve the OpenSSL representation of the key DSA* OSSLDSAPublicKey::getOSSLKey() { + if (dsa == NULL) createOSSLKey(); + return dsa; } +// Create the OpenSSL representation of the key +void OSSLDSAPublicKey::createOSSLKey() +{ + if (dsa != NULL) return; + + dsa = DSA_new(); + if (dsa == NULL) + { + ERROR_MSG("Could not create DSA object"); + return; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +#ifdef WITH_FIPS + if (FIPS_mode()) + DSA_set_method(dsa, FIPS_dsa_openssl()); + else + DSA_set_method(dsa, DSA_OpenSSL()); +#else + DSA_set_method(dsa, DSA_OpenSSL()); +#endif + +#else + DSA_set_method(dsa, DSA_OpenSSL()); +#endif + + BIGNUM* bn_p = OSSL::byteString2bn(p); + BIGNUM* bn_q = OSSL::byteString2bn(q); + BIGNUM* bn_g = OSSL::byteString2bn(g); + BIGNUM* bn_pub_key = OSSL::byteString2bn(y); + + DSA_set0_pqg(dsa, bn_p, bn_q, bn_g); + DSA_set0_key(dsa, bn_pub_key, NULL); +} diff --git a/src/lib/crypto/OSSLDSAPublicKey.h b/src/lib/crypto/OSSLDSAPublicKey.h index 3f66f2a62..b30d05cd2 100644 --- a/src/lib/crypto/OSSLDSAPublicKey.h +++ b/src/lib/crypto/OSSLDSAPublicKey.h @@ -69,6 +69,9 @@ class OSSLDSAPublicKey : public DSAPublicKey private: // The internal OpenSSL representation DSA* dsa; + + // Create the OpenSSL representation of the key + void createOSSLKey(); }; #endif // !_SOFTHSM_V2_OSSLDSAPUBLICKEY_H diff --git a/src/lib/crypto/OSSLECDH.cpp b/src/lib/crypto/OSSLECDH.cpp index 2428186a7..9afbf38fe 100644 --- a/src/lib/crypto/OSSLECDH.cpp +++ b/src/lib/crypto/OSSLECDH.cpp @@ -42,6 +42,9 @@ #include #include #include +#ifdef WITH_FIPS +#include +#endif // Signing functions bool OSSLECDH::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/, @@ -184,8 +187,28 @@ bool OSSLECDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, Pr } // Use the OpenSSL implementation and not any engine - ECDH_set_method(pub, ECDH_get_default_method()); - ECDH_set_method(priv, ECDH_get_default_method()); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +#ifdef WITH_FIPS + if (FIPS_mode()) + { + ECDH_set_method(pub, FIPS_ecdh_openssl()); + ECDH_set_method(priv, FIPS_ecdh_openssl()); + } + else + { + ECDH_set_method(pub, ECDH_OpenSSL()); + ECDH_set_method(priv, ECDH_OpenSSL()); + } +#else + ECDH_set_method(pub, ECDH_OpenSSL()); + ECDH_set_method(priv, ECDH_OpenSSL()); +#endif + +#else + EC_KEY_set_method(pub, EC_KEY_OpenSSL()); + EC_KEY_set_method(priv, EC_KEY_OpenSSL()); +#endif // Derive the secret ByteString secret, derivedSecret; diff --git a/src/lib/crypto/OSSLECDSA.cpp b/src/lib/crypto/OSSLECDSA.cpp index 648e035ae..80d23865d 100644 --- a/src/lib/crypto/OSSLECDSA.cpp +++ b/src/lib/crypto/OSSLECDSA.cpp @@ -37,11 +37,15 @@ #include "CryptoFactory.h" #include "ECParameters.h" #include "OSSLECKeyPair.h" +#include "OSSLComp.h" #include "OSSLUtil.h" #include #include #include #include +#ifdef WITH_FIPS +#include +#endif #include // Signing functions @@ -74,7 +78,20 @@ bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, } // Use the OpenSSL implementation and not any engine - ECDSA_set_method(eckey, ECDSA_get_default_method()); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +#ifdef WITH_FIPS + if (FIPS_mode()) + ECDSA_set_method(eckey, FIPS_ecdsa_openssl()); + else + ECDSA_set_method(eckey, ECDSA_OpenSSL()); +#else + ECDSA_set_method(eckey, ECDSA_OpenSSL()); +#endif + +#else + EC_KEY_set_method(eckey, EC_KEY_OpenSSL()); +#endif // Perform the signature operation size_t len = pk->getOrderLength(); @@ -92,8 +109,11 @@ bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, return false; } // Store the 2 values with padding - BN_bn2bin(sig->r, &signature[len - BN_num_bytes(sig->r)]); - BN_bn2bin(sig->s, &signature[2 * len - BN_num_bytes(sig->s)]); + const BIGNUM* bn_r = NULL; + const BIGNUM* bn_s = NULL; + ECDSA_SIG_get0(sig, &bn_r, &bn_s); + BN_bn2bin(bn_r, &signature[len - BN_num_bytes(bn_r)]); + BN_bn2bin(bn_s, &signature[2 * len - BN_num_bytes(bn_s)]); ECDSA_SIG_free(sig); return true; } @@ -150,7 +170,20 @@ bool OSSLECDSA::verify(PublicKey* publicKey, const ByteString& originalData, } // Use the OpenSSL implementation and not any engine - ECDSA_set_method(eckey, ECDSA_get_default_method()); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +#ifdef WITH_FIPS + if (FIPS_mode()) + ECDSA_set_method(eckey, FIPS_ecdsa_openssl()); + else + ECDSA_set_method(eckey, ECDSA_OpenSSL()); +#else + ECDSA_set_method(eckey, ECDSA_OpenSSL()); +#endif + +#else + EC_KEY_set_method(eckey, EC_KEY_OpenSSL()); +#endif // Perform the verify operation size_t len = pk->getOrderLength(); @@ -170,14 +203,11 @@ bool OSSLECDSA::verify(PublicKey* publicKey, const ByteString& originalData, ERROR_MSG("Could not create an ECDSA_SIG object"); return false; } - if (sig->r != NULL) - BN_clear_free(sig->r); const unsigned char *s = signature.const_byte_str(); - sig->r = BN_bin2bn(s, len, NULL); - if (sig->s != NULL) - BN_clear_free(sig->s); - sig->s = BN_bin2bn(s + len, len, NULL); - if (sig->r == NULL || sig->s == NULL) + BIGNUM* bn_r = BN_bin2bn(s, len, NULL); + BIGNUM* bn_s = BN_bin2bn(s + len, len, NULL); + if (bn_r == NULL || bn_s == NULL || + !ECDSA_SIG_set0(sig, bn_r, bn_s)) { ERROR_MSG("Could not add data to the ECDSA_SIG object"); ECDSA_SIG_free(sig); @@ -258,7 +288,6 @@ bool OSSLECDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParamet // Generate the key-pair EC_KEY* eckey = EC_KEY_new(); - if (eckey == NULL) { ERROR_MSG("Failed to instantiate OpenSSL ECDSA object"); diff --git a/src/lib/crypto/OSSLEVPHashAlgorithm.cpp b/src/lib/crypto/OSSLEVPHashAlgorithm.cpp index 139ebe3e5..a1b4f7356 100644 --- a/src/lib/crypto/OSSLEVPHashAlgorithm.cpp +++ b/src/lib/crypto/OSSLEVPHashAlgorithm.cpp @@ -32,11 +32,12 @@ #include "config.h" #include "OSSLEVPHashAlgorithm.h" +#include "OSSLComp.h" // Destructor OSSLEVPHashAlgorithm::~OSSLEVPHashAlgorithm() { - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); } // Hashing functions @@ -48,14 +49,21 @@ bool OSSLEVPHashAlgorithm::hashInit() } // Initialize the context - EVP_MD_CTX_init(&curCTX); + curCTX = EVP_MD_CTX_new(); + if (curCTX == NULL) + { + ERROR_MSG("Failed to allocate space for EVP_MD_CTX"); + + return false; + } // Initialize EVP digesting - if (!EVP_DigestInit_ex(&curCTX, getEVPHash(), NULL)) + if (!EVP_DigestInit_ex(curCTX, getEVPHash(), NULL)) { ERROR_MSG("EVP_DigestInit failed"); - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; ByteString dummy; HashAlgorithm::hashFinal(dummy); @@ -79,11 +87,12 @@ bool OSSLEVPHashAlgorithm::hashUpdate(const ByteString& data) return true; } - if (!EVP_DigestUpdate(&curCTX, (unsigned char*) data.const_byte_str(), data.size())) + if (!EVP_DigestUpdate(curCTX, (unsigned char*) data.const_byte_str(), data.size())) { ERROR_MSG("EVP_DigestUpdate failed"); - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; ByteString dummy; HashAlgorithm::hashFinal(dummy); @@ -104,18 +113,20 @@ bool OSSLEVPHashAlgorithm::hashFinal(ByteString& hashedData) hashedData.resize(EVP_MD_size(getEVPHash())); unsigned int outLen = hashedData.size(); - if (!EVP_DigestFinal_ex(&curCTX, &hashedData[0], &outLen)) + if (!EVP_DigestFinal_ex(curCTX, &hashedData[0], &outLen)) { ERROR_MSG("EVP_DigestFinal failed"); - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; return false; } hashedData.resize(outLen); - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; return true; } diff --git a/src/lib/crypto/OSSLEVPHashAlgorithm.h b/src/lib/crypto/OSSLEVPHashAlgorithm.h index 13b29c909..1775df29f 100644 --- a/src/lib/crypto/OSSLEVPHashAlgorithm.h +++ b/src/lib/crypto/OSSLEVPHashAlgorithm.h @@ -42,7 +42,7 @@ class OSSLEVPHashAlgorithm : public HashAlgorithm public: // Base constructors OSSLEVPHashAlgorithm() : HashAlgorithm() { - EVP_MD_CTX_init(&curCTX); + curCTX = NULL; } // Destructor @@ -59,7 +59,7 @@ class OSSLEVPHashAlgorithm : public HashAlgorithm private: // Current hashing context - EVP_MD_CTX curCTX; + EVP_MD_CTX* curCTX; }; #endif // !_SOFTHSM_V2_OSSLEVPHASHALGORITHM_H diff --git a/src/lib/crypto/OSSLEVPMacAlgorithm.cpp b/src/lib/crypto/OSSLEVPMacAlgorithm.cpp index 32a65cac0..960b341fd 100644 --- a/src/lib/crypto/OSSLEVPMacAlgorithm.cpp +++ b/src/lib/crypto/OSSLEVPMacAlgorithm.cpp @@ -34,11 +34,12 @@ #include "config.h" #include "OSSLEVPMacAlgorithm.h" +#include "OSSLComp.h" // Destructor OSSLEVPMacAlgorithm::~OSSLEVPMacAlgorithm() { - HMAC_CTX_cleanup(&curCTX); + HMAC_CTX_free(curCTX); } // Signing functions @@ -51,14 +52,21 @@ bool OSSLEVPMacAlgorithm::signInit(const SymmetricKey* key) } // Initialize the context - HMAC_CTX_init(&curCTX); + curCTX = HMAC_CTX_new(); + if (curCTX == NULL) + { + ERROR_MSG("Failed to allocate space for HMAC_CTX"); + + return false; + } // Initialize EVP signing - if (!HMAC_Init(&curCTX, key->getKeyBits().const_byte_str(), key->getKeyBits().size(), getEVPHash())) + if (!HMAC_Init_ex(curCTX, key->getKeyBits().const_byte_str(), key->getKeyBits().size(), getEVPHash(), NULL)) { ERROR_MSG("HMAC_Init failed"); - HMAC_CTX_cleanup(&curCTX); + HMAC_CTX_free(curCTX); + curCTX = NULL; ByteString dummy; MacAlgorithm::signFinal(dummy); @@ -79,11 +87,12 @@ bool OSSLEVPMacAlgorithm::signUpdate(const ByteString& dataToSign) // The GOST implementation in OpenSSL will segfault if we update with zero length. if (dataToSign.size() == 0) return true; - if (!HMAC_Update(&curCTX, dataToSign.const_byte_str(), dataToSign.size())) + if (!HMAC_Update(curCTX, dataToSign.const_byte_str(), dataToSign.size())) { ERROR_MSG("HMAC_Update failed"); - HMAC_CTX_cleanup(&curCTX); + HMAC_CTX_free(curCTX); + curCTX = NULL; ByteString dummy; MacAlgorithm::signFinal(dummy); @@ -104,18 +113,20 @@ bool OSSLEVPMacAlgorithm::signFinal(ByteString& signature) signature.resize(EVP_MD_size(getEVPHash())); unsigned int outLen = signature.size(); - if (!HMAC_Final(&curCTX, &signature[0], &outLen)) + if (!HMAC_Final(curCTX, &signature[0], &outLen)) { ERROR_MSG("HMAC_Final failed"); - HMAC_CTX_cleanup(&curCTX); + HMAC_CTX_free(curCTX); + curCTX = NULL; return false; } signature.resize(outLen); - HMAC_CTX_cleanup(&curCTX); + HMAC_CTX_free(curCTX); + curCTX = NULL; return true; } @@ -130,14 +141,21 @@ bool OSSLEVPMacAlgorithm::verifyInit(const SymmetricKey* key) } // Initialize the context - HMAC_CTX_init(&curCTX); + curCTX = HMAC_CTX_new(); + if (curCTX == NULL) + { + ERROR_MSG("Failed to allocate space for HMAC_CTX"); + + return false; + } // Initialize EVP signing - if (!HMAC_Init(&curCTX, key->getKeyBits().const_byte_str(), key->getKeyBits().size(), getEVPHash())) + if (!HMAC_Init_ex(curCTX, key->getKeyBits().const_byte_str(), key->getKeyBits().size(), getEVPHash(), NULL)) { ERROR_MSG("HMAC_Init failed"); - HMAC_CTX_cleanup(&curCTX); + HMAC_CTX_free(curCTX); + curCTX = NULL; ByteString dummy; MacAlgorithm::verifyFinal(dummy); @@ -158,11 +176,12 @@ bool OSSLEVPMacAlgorithm::verifyUpdate(const ByteString& originalData) // The GOST implementation in OpenSSL will segfault if we update with zero length. if (originalData.size() == 0) return true; - if (!HMAC_Update(&curCTX, originalData.const_byte_str(), originalData.size())) + if (!HMAC_Update(curCTX, originalData.const_byte_str(), originalData.size())) { ERROR_MSG("HMAC_Update failed"); - HMAC_CTX_cleanup(&curCTX); + HMAC_CTX_free(curCTX); + curCTX = NULL; ByteString dummy; MacAlgorithm::verifyFinal(dummy); @@ -184,16 +203,18 @@ bool OSSLEVPMacAlgorithm::verifyFinal(ByteString& signature) unsigned int outLen = EVP_MD_size(getEVPHash()); macResult.resize(outLen); - if (!HMAC_Final(&curCTX, &macResult[0], &outLen)) + if (!HMAC_Final(curCTX, &macResult[0], &outLen)) { ERROR_MSG("HMAC_Final failed"); - HMAC_CTX_cleanup(&curCTX); + HMAC_CTX_free(curCTX); + curCTX = NULL; return false; } - HMAC_CTX_cleanup(&curCTX); + HMAC_CTX_free(curCTX); + curCTX = NULL; return macResult == signature; } diff --git a/src/lib/crypto/OSSLEVPMacAlgorithm.h b/src/lib/crypto/OSSLEVPMacAlgorithm.h index 0afbe64be..69e3f18b8 100644 --- a/src/lib/crypto/OSSLEVPMacAlgorithm.h +++ b/src/lib/crypto/OSSLEVPMacAlgorithm.h @@ -45,7 +45,7 @@ class OSSLEVPMacAlgorithm : public MacAlgorithm public: // Constructor OSSLEVPMacAlgorithm() { - HMAC_CTX_init(&curCTX); + curCTX = NULL; }; // Destructor @@ -70,7 +70,7 @@ class OSSLEVPMacAlgorithm : public MacAlgorithm private: // The current context - HMAC_CTX curCTX; + HMAC_CTX* curCTX; }; #endif // !_SOFTHSM_V2_OSSLEVPMACALGORITHM_H diff --git a/src/lib/crypto/OSSLEVPSymmetricAlgorithm.cpp b/src/lib/crypto/OSSLEVPSymmetricAlgorithm.cpp index ab0a5c17c..08dbd15f4 100644 --- a/src/lib/crypto/OSSLEVPSymmetricAlgorithm.cpp +++ b/src/lib/crypto/OSSLEVPSymmetricAlgorithm.cpp @@ -45,10 +45,7 @@ OSSLEVPSymmetricAlgorithm::OSSLEVPSymmetricAlgorithm() // Destructor OSSLEVPSymmetricAlgorithm::~OSSLEVPSymmetricAlgorithm() { - if (pCurCTX != NULL) - { - sfree(pCurCTX); - } + EVP_CIPHER_CTX_free(pCurCTX); } // Encryption functions @@ -96,7 +93,7 @@ bool OSSLEVPSymmetricAlgorithm::encryptInit(const SymmetricKey* key, const SymMo } // Allocate the EVP context - pCurCTX = (EVP_CIPHER_CTX*) salloc(sizeof(EVP_CIPHER_CTX)); + pCurCTX = EVP_CIPHER_CTX_new(); if (pCurCTX == NULL) { @@ -114,8 +111,7 @@ bool OSSLEVPSymmetricAlgorithm::encryptInit(const SymmetricKey* key, const SymMo { ERROR_MSG("Failed to initialise EVP encrypt operation"); - EVP_CIPHER_CTX_cleanup(pCurCTX); - sfree(pCurCTX); + EVP_CIPHER_CTX_free(pCurCTX); pCurCTX = NULL; ByteString dummy; @@ -133,12 +129,8 @@ bool OSSLEVPSymmetricAlgorithm::encryptUpdate(const ByteString& data, ByteString { if (!SymmetricAlgorithm::encryptUpdate(data, encryptedData)) { - if (pCurCTX != NULL) - { - EVP_CIPHER_CTX_cleanup(pCurCTX); - sfree(pCurCTX); - pCurCTX = NULL; - } + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; return false; } @@ -158,8 +150,7 @@ bool OSSLEVPSymmetricAlgorithm::encryptUpdate(const ByteString& data, ByteString { ERROR_MSG("EVP_EncryptUpdate failed"); - EVP_CIPHER_CTX_cleanup(pCurCTX); - sfree(pCurCTX); + EVP_CIPHER_CTX_free(pCurCTX); pCurCTX = NULL; ByteString dummy; @@ -179,12 +170,8 @@ bool OSSLEVPSymmetricAlgorithm::encryptFinal(ByteString& encryptedData) { if (!SymmetricAlgorithm::encryptFinal(encryptedData)) { - if (pCurCTX != NULL) - { - EVP_CIPHER_CTX_cleanup(pCurCTX); - sfree(pCurCTX); - pCurCTX = NULL; - } + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; return false; } @@ -198,8 +185,7 @@ bool OSSLEVPSymmetricAlgorithm::encryptFinal(ByteString& encryptedData) { ERROR_MSG("EVP_EncryptFinal failed"); - EVP_CIPHER_CTX_cleanup(pCurCTX); - sfree(pCurCTX); + EVP_CIPHER_CTX_free(pCurCTX); pCurCTX = NULL; return false; @@ -208,8 +194,7 @@ bool OSSLEVPSymmetricAlgorithm::encryptFinal(ByteString& encryptedData) // Resize the output block encryptedData.resize(outLen); - EVP_CIPHER_CTX_cleanup(pCurCTX); - sfree(pCurCTX); + EVP_CIPHER_CTX_free(pCurCTX); pCurCTX = NULL; return true; @@ -260,7 +245,7 @@ bool OSSLEVPSymmetricAlgorithm::decryptInit(const SymmetricKey* key, const SymMo } // Allocate the EVP context - pCurCTX = (EVP_CIPHER_CTX*) salloc(sizeof(EVP_CIPHER_CTX)); + pCurCTX = EVP_CIPHER_CTX_new(); if (pCurCTX == NULL) { @@ -278,8 +263,7 @@ bool OSSLEVPSymmetricAlgorithm::decryptInit(const SymmetricKey* key, const SymMo { ERROR_MSG("Failed to initialise EVP decrypt operation"); - EVP_CIPHER_CTX_cleanup(pCurCTX); - sfree(pCurCTX); + EVP_CIPHER_CTX_free(pCurCTX); pCurCTX = NULL; ByteString dummy; @@ -297,12 +281,8 @@ bool OSSLEVPSymmetricAlgorithm::decryptUpdate(const ByteString& encryptedData, B { if (!SymmetricAlgorithm::decryptUpdate(encryptedData, data)) { - if (pCurCTX != NULL) - { - EVP_CIPHER_CTX_cleanup(pCurCTX); - sfree(pCurCTX); - pCurCTX = NULL; - } + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; return false; } @@ -318,8 +298,7 @@ bool OSSLEVPSymmetricAlgorithm::decryptUpdate(const ByteString& encryptedData, B { ERROR_MSG("EVP_DecryptUpdate failed"); - EVP_CIPHER_CTX_cleanup(pCurCTX); - sfree(pCurCTX); + EVP_CIPHER_CTX_free(pCurCTX); pCurCTX = NULL; ByteString dummy; @@ -341,12 +320,8 @@ bool OSSLEVPSymmetricAlgorithm::decryptFinal(ByteString& data) { if (!SymmetricAlgorithm::decryptFinal(data)) { - if (pCurCTX != NULL) - { - EVP_CIPHER_CTX_cleanup(pCurCTX); - sfree(pCurCTX); - pCurCTX = NULL; - } + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; return false; } @@ -361,8 +336,7 @@ bool OSSLEVPSymmetricAlgorithm::decryptFinal(ByteString& data) { ERROR_MSG("EVP_DecryptFinal failed (0x%08X)", rv); - EVP_CIPHER_CTX_cleanup(pCurCTX); - sfree(pCurCTX); + EVP_CIPHER_CTX_free(pCurCTX); pCurCTX = NULL; return false; @@ -371,8 +345,7 @@ bool OSSLEVPSymmetricAlgorithm::decryptFinal(ByteString& data) // Resize the output block data.resize(outLen); - EVP_CIPHER_CTX_cleanup(pCurCTX); - sfree(pCurCTX); + EVP_CIPHER_CTX_free(pCurCTX); pCurCTX = NULL; return true; diff --git a/src/lib/crypto/OSSLGOST.cpp b/src/lib/crypto/OSSLGOST.cpp index 34d627e31..4f34d45d4 100644 --- a/src/lib/crypto/OSSLGOST.cpp +++ b/src/lib/crypto/OSSLGOST.cpp @@ -39,6 +39,7 @@ #include "OSSLGOSTKeyPair.h" #include "OSSLGOSTPrivateKey.h" #include "OSSLGOSTPublicKey.h" +#include "OSSLComp.h" #include #include #include @@ -48,7 +49,7 @@ // Destructor OSSLGOST::~OSSLGOST() { - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); } // Signing functions @@ -153,14 +154,24 @@ bool OSSLGOST::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, return false; } - EVP_MD_CTX_init(&curCTX); + curCTX = EVP_MD_CTX_new(); + if (curCTX == NULL) + { + ERROR_MSG("Failed to allocate space for EVP_MD_CTX"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } const EVP_MD* md = OSSLCryptoFactory::i()->EVP_GOST_34_11; - if (!EVP_DigestInit_ex(&curCTX, md, NULL)) + if (!EVP_DigestInit_ex(curCTX, md, NULL)) { ERROR_MSG("EVP_DigestInit_ex failed"); - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); @@ -178,11 +189,12 @@ bool OSSLGOST::signUpdate(const ByteString& dataToSign) return false; } - if (!EVP_DigestUpdate(&curCTX, dataToSign.const_byte_str(), dataToSign.size())) + if (!EVP_DigestUpdate(curCTX, dataToSign.const_byte_str(), dataToSign.size())) { ERROR_MSG("EVP_DigestUpdate failed"); - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; ByteString dummy; AsymmetricAlgorithm::signFinal(dummy); @@ -211,25 +223,28 @@ bool OSSLGOST::signFinal(ByteString& signature) { ERROR_MSG("Could not get the OpenSSL private key"); - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; return false; } signature.resize(EVP_PKEY_size(pkey)); outLen = signature.size(); - if (!EVP_SignFinal(&curCTX, &signature[0], &outLen, pkey)) + if (!EVP_SignFinal(curCTX, &signature[0], &outLen, pkey)) { ERROR_MSG("EVP_SignFinal failed"); - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; return false; } signature.resize(outLen); - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; return true; } @@ -323,14 +338,24 @@ bool OSSLGOST::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, return false; } - EVP_MD_CTX_init(&curCTX); + curCTX = EVP_MD_CTX_new(); + if (curCTX == NULL) + { + ERROR_MSG("Failed to allocate space for EVP_MD_CTX"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } const EVP_MD* md = OSSLCryptoFactory::i()->EVP_GOST_34_11; - if (!EVP_DigestInit_ex(&curCTX, md, NULL)) + if (!EVP_DigestInit_ex(curCTX, md, NULL)) { ERROR_MSG("EVP_DigestInit_ex failed"); - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); @@ -348,11 +373,12 @@ bool OSSLGOST::verifyUpdate(const ByteString& originalData) return false; } - if (!EVP_DigestUpdate(&curCTX, originalData.const_byte_str(), originalData.size())) + if (!EVP_DigestUpdate(curCTX, originalData.const_byte_str(), originalData.size())) { ERROR_MSG("EVP_DigestUpdate failed"); - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); @@ -381,13 +407,15 @@ bool OSSLGOST::verifyFinal(const ByteString& signature) { ERROR_MSG("Could not get the OpenSSL public key"); - EVP_MD_CTX_cleanup(&curCTX); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; return false; } - ret = EVP_VerifyFinal(&curCTX, signature.const_byte_str(), signature.size(), pkey); - EVP_MD_CTX_cleanup(&curCTX); + ret = EVP_VerifyFinal(curCTX, signature.const_byte_str(), signature.size(), pkey); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; if (ret != 1) { if (ret < 0) diff --git a/src/lib/crypto/OSSLGOST.h b/src/lib/crypto/OSSLGOST.h index 2d3a2d4b3..ad399f18c 100644 --- a/src/lib/crypto/OSSLGOST.h +++ b/src/lib/crypto/OSSLGOST.h @@ -42,7 +42,7 @@ class OSSLGOST : public AsymmetricAlgorithm public: // Constructor OSSLGOST() : AsymmetricAlgorithm() { - EVP_MD_CTX_init(&curCTX); + curCTX = NULL; } // Destructor @@ -79,7 +79,7 @@ class OSSLGOST : public AsymmetricAlgorithm virtual AsymmetricParameters* newParameters(); private: - EVP_MD_CTX curCTX; + EVP_MD_CTX* curCTX; }; #endif // !_SOFTHSM_V2_OSSLGOST_H diff --git a/src/lib/crypto/OSSLRSA.cpp b/src/lib/crypto/OSSLRSA.cpp index bad99841f..91b6466c6 100644 --- a/src/lib/crypto/OSSLRSA.cpp +++ b/src/lib/crypto/OSSLRSA.cpp @@ -33,6 +33,7 @@ #include "config.h" #include "log.h" #include "OSSLRSA.h" +#include "OSSLUtil.h" #include "CryptoFactory.h" #include "RSAParameters.h" #include "OSSLRSAKeyPair.h" @@ -513,21 +514,23 @@ bool OSSLRSA::signFinal(ByteString& signature) } bool rv; + int result; if (isPSS) { ByteString em; em.resize(pk->getN().size()); - rv = (RSA_padding_add_PKCS1_PSS(pk->getOSSLKey(), &em[0], &digest[0], + result = (RSA_padding_add_PKCS1_PSS(pk->getOSSLKey(), &em[0], &digest[0], hash, sLen) == 1); - if (!rv) + if (!result) { ERROR_MSG("RSA PSS padding failed (0x%08X)", ERR_get_error()); + rv = false; } else { - int result = RSA_private_encrypt(em.size(), &em[0], &signature[0], + result = RSA_private_encrypt(em.size(), &em[0], &signature[0], pk->getOSSLKey(), RSA_NO_PADDING); if (result >= 0) { @@ -536,15 +539,24 @@ bool OSSLRSA::signFinal(ByteString& signature) } else { - rv = false; ERROR_MSG("RSA private encrypt failed (0x%08X)", ERR_get_error()); + rv = false; } } } else { - rv = (RSA_sign(type, &digest[0], digest.size(), &signature[0], - &sigLen, pk->getOSSLKey()) == 1); + result = RSA_sign(type, &digest[0], digest.size(), &signature[0], + &sigLen, pk->getOSSLKey()); + if (result > 0) + { + rv = true; + } + else + { + ERROR_MSG("RSA sign failed (0x%08X)", ERR_get_error()); + rv = false; + } } RSA_blinding_off(rsa); @@ -1180,15 +1192,26 @@ bool OSSLRSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameter } // Generate the key-pair - RSA* rsa = RSA_generate_key(params->getBitLength(), e, NULL, NULL); + RSA* rsa = RSA_new(); + if (rsa == NULL) + { + ERROR_MSG("Failed to instantiate OpenSSL RSA object"); + + return false; + } + + BIGNUM* bn_e = OSSL::byteString2bn(params->getE()); // Check if the key was successfully generated - if (rsa == NULL) + if (!RSA_generate_key_ex(rsa, params->getBitLength(), bn_e, NULL)) { ERROR_MSG("RSA key generation failed (0x%08X)", ERR_get_error()); + BN_free(bn_e); + RSA_free(rsa); return false; } + BN_free(bn_e); // Create an asymmetric key-pair object to return OSSLRSAKeyPair* kp = new OSSLRSAKeyPair(); diff --git a/src/lib/crypto/OSSLRSAPrivateKey.cpp b/src/lib/crypto/OSSLRSAPrivateKey.cpp index 254731de4..976801be0 100644 --- a/src/lib/crypto/OSSLRSAPrivateKey.cpp +++ b/src/lib/crypto/OSSLRSAPrivateKey.cpp @@ -32,27 +32,25 @@ #include "config.h" #include "log.h" +#include "OSSLComp.h" #include "OSSLRSAPrivateKey.h" #include "OSSLUtil.h" #include #include +#ifdef WITH_FIPS +#include +#endif #include // Constructors OSSLRSAPrivateKey::OSSLRSAPrivateKey() { - rsa = RSA_new(); - - // Use the OpenSSL implementation and not any engine - RSA_set_method(rsa, RSA_get_default_method()); + rsa = NULL; } OSSLRSAPrivateKey::OSSLRSAPrivateKey(const RSA* inRSA) { - rsa = RSA_new(); - - // Use the OpenSSL implementation and not any engine - RSA_set_method(rsa, RSA_PKCS1_SSLeay()); + rsa = NULL; setFromOSSL(inRSA); } @@ -69,46 +67,59 @@ OSSLRSAPrivateKey::~OSSLRSAPrivateKey() // Set from OpenSSL representation void OSSLRSAPrivateKey::setFromOSSL(const RSA* inRSA) { - if (inRSA->p) + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_q = NULL; + const BIGNUM* bn_dmp1 = NULL; + const BIGNUM* bn_dmq1 = NULL; + const BIGNUM* bn_iqmp = NULL; + const BIGNUM* bn_n = NULL; + const BIGNUM* bn_e = NULL; + const BIGNUM* bn_d = NULL; + + RSA_get0_factors(inRSA, &bn_p, &bn_q); + RSA_get0_crt_params(inRSA, &bn_dmp1, &bn_dmq1, &bn_iqmp); + RSA_get0_key(inRSA, &bn_n, &bn_e, &bn_d); + + if (bn_p) { - ByteString inP = OSSL::bn2ByteString(inRSA->p); + ByteString inP = OSSL::bn2ByteString(bn_p); setP(inP); } - if (inRSA->q) + if (bn_q) { - ByteString inQ = OSSL::bn2ByteString(inRSA->q); + ByteString inQ = OSSL::bn2ByteString(bn_q); setQ(inQ); } - if (inRSA->dmp1) + if (bn_dmp1) { - ByteString inDP1 = OSSL::bn2ByteString(inRSA->dmp1); + ByteString inDP1 = OSSL::bn2ByteString(bn_dmp1); setDP1(inDP1); } - if (inRSA->dmq1) + if (bn_dmq1) { - ByteString inDQ1 = OSSL::bn2ByteString(inRSA->dmq1); + ByteString inDQ1 = OSSL::bn2ByteString(bn_dmq1); setDQ1(inDQ1); } - if (inRSA->iqmp) + if (bn_iqmp) { - ByteString inPQ = OSSL::bn2ByteString(inRSA->iqmp); + ByteString inPQ = OSSL::bn2ByteString(bn_iqmp); setPQ(inPQ); } - if (inRSA->d) - { - ByteString inD = OSSL::bn2ByteString(inRSA->d); - setD(inD); - } - if (inRSA->n) + if (bn_n) { - ByteString inN = OSSL::bn2ByteString(inRSA->n); + ByteString inN = OSSL::bn2ByteString(bn_n); setN(inN); } - if (inRSA->e) + if (bn_e) { - ByteString inE = OSSL::bn2ByteString(inRSA->e); + ByteString inE = OSSL::bn2ByteString(bn_e); setE(inE); } + if (bn_d) + { + ByteString inD = OSSL::bn2ByteString(bn_d); + setD(inD); + } } // Check if the key is of the given type @@ -122,78 +133,66 @@ void OSSLRSAPrivateKey::setP(const ByteString& inP) { RSAPrivateKey::setP(inP); - if (rsa->p) + if (rsa) { - BN_clear_free(rsa->p); - rsa->p = NULL; + RSA_free(rsa); + rsa = NULL; } - - rsa->p = OSSL::byteString2bn(inP); } void OSSLRSAPrivateKey::setQ(const ByteString& inQ) { RSAPrivateKey::setQ(inQ); - if (rsa->q) + if (rsa) { - BN_clear_free(rsa->q); - rsa->q = NULL; + RSA_free(rsa); + rsa = NULL; } - - rsa->q = OSSL::byteString2bn(inQ); } void OSSLRSAPrivateKey::setPQ(const ByteString& inPQ) { RSAPrivateKey::setPQ(inPQ); - if (rsa->iqmp) + if (rsa) { - BN_clear_free(rsa->iqmp); - rsa->iqmp = NULL; + RSA_free(rsa); + rsa = NULL; } - - rsa->iqmp = OSSL::byteString2bn(inPQ); } void OSSLRSAPrivateKey::setDP1(const ByteString& inDP1) { RSAPrivateKey::setDP1(inDP1); - if (rsa->dmp1) + if (rsa) { - BN_clear_free(rsa->dmp1); - rsa->dmp1 = NULL; + RSA_free(rsa); + rsa = NULL; } - - rsa->dmp1 = OSSL::byteString2bn(inDP1); } void OSSLRSAPrivateKey::setDQ1(const ByteString& inDQ1) { RSAPrivateKey::setDQ1(inDQ1); - if (rsa->dmq1) + if (rsa) { - BN_clear_free(rsa->dmq1); - rsa->dmq1 = NULL; + RSA_free(rsa); + rsa = NULL; } - - rsa->dmq1 = OSSL::byteString2bn(inDQ1); } void OSSLRSAPrivateKey::setD(const ByteString& inD) { RSAPrivateKey::setD(inD); - if (rsa->d) + if (rsa) { - BN_clear_free(rsa->d); - rsa->d = NULL; + RSA_free(rsa); + rsa = NULL; } - - rsa->d = OSSL::byteString2bn(inD); } @@ -202,32 +201,29 @@ void OSSLRSAPrivateKey::setN(const ByteString& inN) { RSAPrivateKey::setN(inN); - if (rsa->n) + if (rsa) { - BN_clear_free(rsa->n); - rsa->n = NULL; + RSA_free(rsa); + rsa = NULL; } - - rsa->n = OSSL::byteString2bn(inN); } void OSSLRSAPrivateKey::setE(const ByteString& inE) { RSAPrivateKey::setE(inE); - if (rsa->e) + if (rsa) { - BN_clear_free(rsa->e); - rsa->e = NULL; + RSA_free(rsa); + rsa = NULL; } - - rsa->e = OSSL::byteString2bn(inE); } // Encode into PKCS#8 DER ByteString OSSLRSAPrivateKey::PKCS8Encode() { ByteString der; + if (rsa == NULL) createOSSLKey(); if (rsa == NULL) return der; EVP_PKEY* pkey = EVP_PKEY_new(); if (pkey == NULL) return der; @@ -275,6 +271,50 @@ bool OSSLRSAPrivateKey::PKCS8Decode(const ByteString& ber) // Retrieve the OpenSSL representation of the key RSA* OSSLRSAPrivateKey::getOSSLKey() { + if (rsa == NULL) createOSSLKey(); + return rsa; } +// Create the OpenSSL representation of the key +void OSSLRSAPrivateKey::createOSSLKey() +{ + if (rsa != NULL) return; + + rsa = RSA_new(); + if (rsa == NULL) + { + ERROR_MSG("Could not create RSA object"); + return; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +#ifdef OPENSSL_FIPS + if (FIPS_mode()) + RSA_set_method(rsa, FIPS_rsa_pkcs1_ssleay()); + else + RSA_set_method(rsa, RSA_PKCS1_SSLeay()); +#else + RSA_set_method(rsa, RSA_PKCS1_SSLeay()); +#endif + +#else + RSA_set_method(rsa, RSA_PKCS1_OpenSSL()); +#endif + + BIGNUM* bn_p = OSSL::byteString2bn(p); + BIGNUM* bn_q = OSSL::byteString2bn(q); + BIGNUM* bn_dmp1 = OSSL::byteString2bn(dp1); + BIGNUM* bn_dmq1 = OSSL::byteString2bn(dq1); + BIGNUM* bn_iqmp = OSSL::byteString2bn(pq); + BIGNUM* bn_n = OSSL::byteString2bn(n); + BIGNUM* bn_e = OSSL::byteString2bn(e); + BIGNUM* bn_d = OSSL::byteString2bn(d); + + RSA_set0_factors(rsa, bn_p, bn_q); + RSA_set0_crt_params(rsa, bn_dmp1, bn_dmq1, bn_iqmp); + RSA_set0_key(rsa, bn_n, bn_e, bn_d); +} + diff --git a/src/lib/crypto/OSSLRSAPrivateKey.h b/src/lib/crypto/OSSLRSAPrivateKey.h index ebfde61f1..bb876d508 100644 --- a/src/lib/crypto/OSSLRSAPrivateKey.h +++ b/src/lib/crypto/OSSLRSAPrivateKey.h @@ -81,6 +81,9 @@ class OSSLRSAPrivateKey : public RSAPrivateKey private: // The internal OpenSSL representation RSA* rsa; + + // Create the OpenSSL representation of the key + void createOSSLKey(); }; #endif // !_SOFTHSM_V2_OSSLRSAPRIVATEKEY_H diff --git a/src/lib/crypto/OSSLRSAPublicKey.cpp b/src/lib/crypto/OSSLRSAPublicKey.cpp index 858362dd9..711773e72 100644 --- a/src/lib/crypto/OSSLRSAPublicKey.cpp +++ b/src/lib/crypto/OSSLRSAPublicKey.cpp @@ -32,6 +32,7 @@ #include "config.h" #include "log.h" +#include "OSSLComp.h" #include "OSSLRSAPublicKey.h" #include "OSSLUtil.h" #include @@ -40,18 +41,12 @@ // Constructors OSSLRSAPublicKey::OSSLRSAPublicKey() { - rsa = RSA_new(); - - // Use the OpenSSL implementation and not any engine - RSA_set_method(rsa, RSA_get_default_method()); + rsa = NULL; } OSSLRSAPublicKey::OSSLRSAPublicKey(const RSA* inRSA) { - rsa = RSA_new(); - - // Use the OpenSSL implementation and not any engine - RSA_set_method(rsa, RSA_PKCS1_SSLeay()); + rsa = NULL; setFromOSSL(inRSA); } @@ -74,14 +69,19 @@ bool OSSLRSAPublicKey::isOfType(const char* inType) // Set from OpenSSL representation void OSSLRSAPublicKey::setFromOSSL(const RSA* inRSA) { - if (inRSA->n) + const BIGNUM* bn_n = NULL; + const BIGNUM* bn_e = NULL; + + RSA_get0_key(inRSA, &bn_n, &bn_e, NULL); + + if (bn_n) { - ByteString inN = OSSL::bn2ByteString(inRSA->n); + ByteString inN = OSSL::bn2ByteString(bn_n); setN(inN); } - if (inRSA->e) + if (bn_e) { - ByteString inE = OSSL::bn2ByteString(inRSA->e); + ByteString inE = OSSL::bn2ByteString(bn_e); setE(inE); } } @@ -91,31 +91,62 @@ void OSSLRSAPublicKey::setN(const ByteString& inN) { RSAPublicKey::setN(inN); - if (rsa->n) + if (rsa) { - BN_clear_free(rsa->n); - rsa->n = NULL; + RSA_free(rsa); + rsa = NULL; } - - rsa->n = OSSL::byteString2bn(inN); } void OSSLRSAPublicKey::setE(const ByteString& inE) { RSAPublicKey::setE(inE); - if (rsa->e) + if (rsa) { - BN_clear_free(rsa->e); - rsa->e = NULL; + RSA_free(rsa); + rsa = NULL; } - - rsa->e = OSSL::byteString2bn(inE); } // Retrieve the OpenSSL representation of the key RSA* OSSLRSAPublicKey::getOSSLKey() { + if (rsa == NULL) createOSSLKey(); + return rsa; } +// Create the OpenSSL representation of the key +void OSSLRSAPublicKey::createOSSLKey() +{ + if (rsa != NULL) return; + + rsa = RSA_new(); + if (rsa == NULL) + { + ERROR_MSG("Could not create RSA object"); + return; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +#ifdef OPENSSL_FIPS + if (FIPS_mode()) + RSA_set_method(rsa, FIPS_rsa_pkcs1_ssleay()); + else + RSA_set_method(rsa, RSA_PKCS1_SSLeay()); +#else + RSA_set_method(rsa, RSA_PKCS1_SSLeay()); +#endif + +#else + RSA_set_method(rsa, RSA_PKCS1_OpenSSL()); +#endif + + BIGNUM* bn_n = OSSL::byteString2bn(n); + BIGNUM* bn_e = OSSL::byteString2bn(e); + + RSA_set0_key(rsa, bn_n, bn_e, NULL); +} diff --git a/src/lib/crypto/OSSLRSAPublicKey.h b/src/lib/crypto/OSSLRSAPublicKey.h index dd3c3f4d4..98f99f204 100644 --- a/src/lib/crypto/OSSLRSAPublicKey.h +++ b/src/lib/crypto/OSSLRSAPublicKey.h @@ -67,6 +67,9 @@ class OSSLRSAPublicKey : public RSAPublicKey private: // The internal OpenSSL representation RSA* rsa; + + // Create the OpenSSL representation of the key + void createOSSLKey(); }; #endif // !_SOFTHSM_V2_OSSLRSAPUBLICKEY_H diff --git a/src/lib/crypto/OSSLUtil.cpp b/src/lib/crypto/OSSLUtil.cpp index 61472ffbc..3a3134062 100644 --- a/src/lib/crypto/OSSLUtil.cpp +++ b/src/lib/crypto/OSSLUtil.cpp @@ -52,6 +52,8 @@ ByteString OSSL::bn2ByteString(const BIGNUM* bn) // Convert a ByteString to an OpenSSL BIGNUM BIGNUM* OSSL::byteString2bn(const ByteString& byteString) { + if (byteString.size() == 0) return NULL; + return BN_bin2bn(byteString.const_byte_str(), byteString.size(), NULL); }