Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new OCSP access certificate and use when old is expired #205

Merged
merged 1 commit into from
May 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added etc/798.p12
Binary file not shown.
1 change: 0 additions & 1 deletion etc/digidocpp.conf.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
<!--<param name="verify.serivceUri" lock="false">@SIVA_URL@</param>-->

<!-- OCSP responder url. Used for validating signing certificates and generating BDoc-TM signatures-->
<!--<ocsp issuer="ESTEID-SK 2007">http://ocsp.sk.ee</ocsp>-->
<!--<ocsp issuer="ESTEID-SK 2011">http://ocsp.sk.ee</ocsp>-->
<!--<ocsp issuer="ESTEID-SK 2015">http://ocsp.sk.ee</ocsp>-->
<!--<ocsp issuer="EID-SK 2011">http://ocsp.sk.ee</ocsp>-->
Expand Down
2 changes: 2 additions & 0 deletions libdigidocpp.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<?endif?>
<File Source="$(var.libdigidocpp)\x86\bin\digidoc-tool.exe"/>
<File Source="$(var.libdigidocpp)\x86\etc\digidocpp\878252.p12"/>
<File Source="$(var.libdigidocpp)\x86\etc\digidocpp\798.p12"/>
<File Source="$(var.libdigidocpp)\x86\etc\digidocpp\digidocpp.conf"/>
</Component>
<Component Id="LibrariesDevX86" Guid="{9B16F8D1-11AA-4AF4-B8C2-96B4EC7E79CD}">
Expand Down Expand Up @@ -118,6 +119,7 @@
<?endif?>
<File Source="$(var.libdigidocpp)\x64\bin\digidoc-tool.exe" Id="digidoc_tool.exe_64"/>
<File Source="$(var.libdigidocpp)\x64\etc\digidocpp\878252.p12" Id="_878252.p12_64"/>
<File Source="$(var.libdigidocpp)\x64\etc\digidocpp\798.p12" Id="_798.p12_64"/>
<File Source="$(var.libdigidocpp)\x64\etc\digidocpp\digidocpp.conf" Id="digidocpp.conf_64"/>
</Component>
<Component Id="LibrariesDevX64" Guid="{D992688C-0D4A-4C22-BEF4-582D7FA91731}">
Expand Down
5 changes: 3 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ add_library(digidocpp ${BUILD_TYPE}
${digidocpp_SRCS}
${CMAKE_CURRENT_BINARY_DIR}/digidocpp.conf
${CMAKE_SOURCE_DIR}/etc/878252.p12
${CMAKE_SOURCE_DIR}/etc/798.p12
${SCHEMA_FILES}
${PUBLIC_HEADER}
${CRYPTO_HEADER}
Expand Down Expand Up @@ -257,7 +258,7 @@ set_target_properties(digidocpp PROPERTIES
VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}
SOVERSION 1
PUBLIC_HEADER "${PUBLIC_HEADER}"
RESOURCE "${CMAKE_CURRENT_BINARY_DIR}/digidocpp.conf;${CMAKE_SOURCE_DIR}/etc/878252.p12"
RESOURCE "${CMAKE_CURRENT_BINARY_DIR}/digidocpp.conf;${CMAKE_SOURCE_DIR}/etc/878252.p12;${CMAKE_SOURCE_DIR}/etc/798.p12"
FRAMEWORK_VERSION 1
FRAMEWORK "${FRAMEWORK}"
MACOSX_FRAMEWORK_IDENTIFIER "ee.ria.digidocpp"
Expand Down Expand Up @@ -326,7 +327,7 @@ if(WIN32)
DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL)
endif()

source_group( "Resources" FILES "${CMAKE_CURRENT_BINARY_DIR}/digidocpp.conf;${CMAKE_SOURCE_DIR}/etc/878252.p12" )
source_group( "Resources" FILES "${CMAKE_CURRENT_BINARY_DIR}/digidocpp.conf;${CMAKE_SOURCE_DIR}/etc/878252.p12;${CMAKE_SOURCE_DIR}/etc/798.p12" )
source_group( "Resources\\schemas" FILES ${SCHEMA_FILES} )

if( FRAMEWORK )
Expand Down
35 changes: 26 additions & 9 deletions src/Conf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@

#include "Conf.h"

#include "log.h"
#include "crypto/Digest.h"
#include "crypto/OpenSSLHelpers.h"
#include "crypto/X509Cert.h"
#include "util/File.h"
#include "log.h"
#include "tslcerts.h"
#include "util/File.h"

#include <map>

Expand All @@ -42,9 +43,9 @@ Conf* Conf::INSTANCE = nullptr;
/**
* Configuration parameters
*/
Conf::Conf() {}
Conf::Conf() = default;

Conf::~Conf() {}
Conf::~Conf() = default;

/**
* Return global instance object
Expand Down Expand Up @@ -115,15 +116,13 @@ string Conf::ocsp(const string &issuer) const
{
static const map<string,string> ocsplist = {
//Estonia Live
{"ESTEID-SK 2007", "http://ocsp.sk.ee"},
{"ESTEID-SK 2011", "http://ocsp.sk.ee"},
{"ESTEID-SK 2015", "http://ocsp.sk.ee"},
{"EID-SK 2011", "http://ocsp.sk.ee"},
{"EID-SK 2016", "http://ocsp.sk.ee"},
{"KLASS3-SK 2010", "http://ocsp.sk.ee"},
{"KLASS3-SK 2016", "http://ocsp.sk.ee"},
//Estonia Test
{"TEST of ESTEID-SK 2007", "http://demo.sk.ee/ocsp"},
{"TEST of ESTEID-SK 2011", "http://demo.sk.ee/ocsp"},
{"TEST of ESTEID-SK 2015", "http://demo.sk.ee/ocsp"},
{"TEST of EID-SK 2011", "http://demo.sk.ee/ocsp"},
Expand Down Expand Up @@ -173,7 +172,25 @@ string Conf::proxyPass() const { return string(); }
*
* Used for signing OCSP request
*/
string Conf::PKCS12Cert() const { return File::confPath() + "878252.p12"; }
string Conf::PKCS12Cert() const
{
string oldPath = File::confPath() + "878252.p12";
string newPath = File::confPath() + "798.p12";
static const bool isValid = [&]{
try {
X509 *tmp = nullptr;
EVP_PKEY *key = nullptr;
OpenSSL::parsePKCS12(oldPath, PKCS12Pass(), &key, &tmp);
EVP_PKEY_free(key);
SCOPE(X509, cert, tmp);
return X509Cert(cert.get()).isValid();
} catch(const Exception &e) {
WARN("Failed to parse PKCS12 certificate: %s %s", oldPath.c_str(), e.msg().c_str());
}
return true;
}();
return isValid ? oldPath : newPath;
}

/**
* Gets PKCS12 password.
Expand Down Expand Up @@ -274,9 +291,9 @@ string Conf::verifyServiceUri() const { return SIVA_URL; }
/**
* Version 2 config with new parameters
*/
ConfV2::ConfV2() {}
ConfV2::ConfV2() = default;

ConfV2::~ConfV2() {}
ConfV2::~ConfV2() = default;

/**
* Return global instance object
Expand Down
44 changes: 17 additions & 27 deletions src/crypto/OCSP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,15 @@

#include "OCSP.h"

#include "Container.h"
#include "log.h"
#include "Conf.h"
#include "Container.h"
#include "crypto/OpenSSLHelpers.h"
#include "crypto/X509CertStore.h"
#include "log.h"
#include "util/DateTime.h"

#include <algorithm>

#include <openssl/pkcs12.h>
#include <openssl/ssl.h>
#ifdef WIN32 //hack for win32 build
#undef OCSP_REQUEST
Expand Down Expand Up @@ -102,7 +101,7 @@ OCSP::OCSP(const X509Cert &cert, const X509Cert &issuer, const vector<unsigned c
throw e;
}

OCSP_CERTID *certId = OCSP_cert_to_id(0, cert.handle(), issuer.handle());
OCSP_CERTID *certId = OCSP_cert_to_id(nullptr, cert.handle(), issuer.handle());
SCOPE(OCSP_REQUEST, req, createRequest(certId, nonce,
!Conf::instance()->PKCS12Disable() && url.find("ocsp.sk.ee") != string::npos));
resp.reset(sendRequest(url, req.get(), "format: " + format + " profile: " +
Expand Down Expand Up @@ -147,7 +146,7 @@ OCSP::OCSP(const vector<unsigned char> &data)
if(data.empty())
return;
const unsigned char *p = data.data();
resp.reset(d2i_OCSP_RESPONSE(0, &p, (unsigned int)data.size()), OCSP_RESPONSE_free);
resp.reset(d2i_OCSP_RESPONSE(nullptr, &p, (unsigned int)data.size()), OCSP_RESPONSE_free);
if(resp)
basic.reset(OCSP_response_get1_basic(resp.get()), OCSP_BASICRESP_free);
}
Expand All @@ -165,8 +164,8 @@ bool OCSP::compareResponderCert(const X509Cert &cert) const
{
unsigned char sha1[SHA_DIGEST_LENGTH];
ASN1_BIT_STRING *key = X509_get0_pubkey_bitstr(cert.handle());
return EVP_Digest(key->data, key->length, sha1, nullptr, EVP_sha1(), nullptr) == 1 &&
memcmp(hash->data, &sha1, hash->length) == 0;
return EVP_Digest(key->data, size_t(key->length), sha1, nullptr, EVP_sha1(), nullptr) == 1 &&
memcmp(hash->data, &sha1, size_t(hash->length)) == 0;
}
return false;
}
Expand Down Expand Up @@ -200,7 +199,7 @@ OCSP_REQUEST* OCSP::createRequest(OCSP_CERTID *certId, const vector<unsigned cha
}
else
ASN1_OCTET_STRING_set(st.get(), nonce.data(), int(nonce.size()));
if(!OCSP_REQUEST_add_ext(req.get(), X509_EXTENSION_create_by_NID(0, NID_id_pkix_OCSP_Nonce, 0, st.get()), 0))
if(!OCSP_REQUEST_add_ext(req.get(), X509_EXTENSION_create_by_NID(nullptr, NID_id_pkix_OCSP_Nonce, 0, st.get()), 0))
THROW_OPENSSLEXCEPTION("Failed to add NONCE to OCSP request.");
#endif

Expand All @@ -209,7 +208,7 @@ OCSP_REQUEST* OCSP::createRequest(OCSP_CERTID *certId, const vector<unsigned cha
X509* signCert;
EVP_PKEY* signKey;
#ifdef USE_KEYCHAIN
if(SecIdentityRef identity = SecIdentityCopyPreferred( CFSTR("ocsp.sk.ee"), 0, 0 ))
if(SecIdentityRef identity = SecIdentityCopyPreferred(CFSTR("ocsp.sk.ee"), nullptr, nullptr))
{
SecCertificateRef certref = nullptr;
SecKeyRef keyref = nullptr;
Expand All @@ -224,7 +223,7 @@ OCSP_REQUEST* OCSP::createRequest(OCSP_CERTID *certId, const vector<unsigned cha
if(!certdata)
THROW("Failed to read PKCS12 certificate");
const unsigned char *p = CFDataGetBytePtr(certdata);
signCert = d2i_X509(0, &p, CFDataGetLength(certdata));
signCert = d2i_X509(nullptr, &p, CFDataGetLength(certdata));
CFRelease(certdata);

CFDataRef keydata = nullptr;
Expand All @@ -236,37 +235,28 @@ OCSP_REQUEST* OCSP::createRequest(OCSP_CERTID *certId, const vector<unsigned cha
CFRelease(keyref);
if(!keydata)
THROW("Failed to read PKCS12 key");
SCOPE(BIO, bio, BIO_new_mem_buf((void*)CFDataGetBytePtr(keydata), CFDataGetLength(keydata)));
signKey = d2i_PKCS8PrivateKey_bio(bio.get(), 0, [](char *buf, int bufsiz, int, void *) -> int {
SCOPE(BIO, bio, BIO_new_mem_buf((void*)CFDataGetBytePtr(keydata), int(CFDataGetLength(keydata))));
signKey = d2i_PKCS8PrivateKey_bio(bio.get(), nullptr, [](char *buf, int bufsiz, int, void *) -> int {
static const char password[] = "pass";
int res = strlen(password);
if (res > bufsiz)
res = bufsiz;
memcpy(buf, password, res);
memcpy(buf, password, size_t(res));
return res;
}, 0);
}, nullptr);
CFRelease(keydata);
} else {
#endif
Conf *c = Conf::instance();
SCOPE(BIO, bio, BIO_new_file(c->PKCS12Cert().c_str(), "rb"));
if(!bio)
THROW_OPENSSLEXCEPTION("Failed to open PKCS12 certificate: %s.", c->PKCS12Cert().c_str());
SCOPE(PKCS12, p12, d2i_PKCS12_bio(bio.get(), 0));
if(!p12)
THROW_OPENSSLEXCEPTION("Failed to read PKCS12 certificate: %s.", c->PKCS12Cert().c_str());
if(!PKCS12_parse(p12.get(), c->PKCS12Pass().c_str(), &signKey, &signCert, 0))
THROW_OPENSSLEXCEPTION("Failed to parse PKCS12 certificate.");
else // Hack: clear PKCS12_parse error ERROR: 185073780 - error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch
OpenSSLException();
OpenSSL::parsePKCS12(c->PKCS12Cert(), c->PKCS12Pass(), &signKey, &signCert);
#ifdef USE_KEYCHAIN
}
#endif
if(!signCert)
THROW_OPENSSLEXCEPTION("Failed to parse PKCS12 certificate");
if(!signKey)
THROW_OPENSSLEXCEPTION("Failed to parse PKCS12 key");
if(!OCSP_request_sign(req.get(), signCert, signKey, EVP_sha256(), 0, 0))
if(!OCSP_request_sign(req.get(), signCert, signKey, EVP_sha256(), nullptr, 0))
THROW_OPENSSLEXCEPTION("Failed to sign OCSP request.");
X509_free(signCert);
EVP_PKEY_free(signKey);
Expand Down Expand Up @@ -366,7 +356,7 @@ OCSP_RESPONSE* OCSP::sendRequest(const string &_url, OCSP_REQUEST *req, const st
user_agent += " APP " + appInfo() + " " + useragent;

OCSP_RESPONSE* resp = nullptr;
SCOPE(OCSP_REQ_CTX, rctx, OCSP_sendreq_new(connection.get(), const_cast<char*>(url.c_str()), 0, -1));
SCOPE(OCSP_REQ_CTX, rctx, OCSP_sendreq_new(connection.get(), const_cast<char*>(url.c_str()), nullptr, -1));
if(!rctx)
THROW_OPENSSLEXCEPTION("Failed to set OCSP request headers.");
if(!OCSP_REQ_CTX_add1_header(rctx.get(), "Host", const_cast<char*>(hostname.c_str())))
Expand Down Expand Up @@ -425,7 +415,7 @@ void OCSP::verifyResponse(const X509Cert &cert) const

SCOPE(OCSP_CERTID, certId, OCSP_cert_to_id(0, cert.handle(), issuer.handle()));
int status = -1; int reason = -1;
if(OCSP_resp_find_status(basic.get(), certId.get(), &status, &reason, 0, 0, 0) <= 0)
if(OCSP_resp_find_status(basic.get(), certId.get(), &status, &reason, nullptr, nullptr, nullptr) <= 0)
{
Exception e(EXCEPTION_PARAMS("Certificate status: unknown"));
e.setCode(Exception::CertificateUnknown);
Expand Down
19 changes: 19 additions & 0 deletions src/crypto/OpenSSLHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <sstream>

#include <openssl/err.h>
#include <openssl/pkcs12.h>

namespace digidoc
{
Expand Down Expand Up @@ -75,4 +76,22 @@ class OpenSSLException : public Exception

#define THROW_OPENSSLEXCEPTION(...) THROW_CAUSE(OpenSSLException(), __VA_ARGS__)

class OpenSSL
{
public:
static void parsePKCS12(const std::string &path, const std::string &pass, EVP_PKEY **key, X509 **cert)
{
SCOPE(BIO, bio, BIO_new_file(path.c_str(), "rb"));
if(!bio)
THROW_OPENSSLEXCEPTION("Failed to open PKCS12 certificate: %s.", path.c_str());
SCOPE(PKCS12, p12, d2i_PKCS12_bio(bio.get(), nullptr));
if(!p12)
THROW_OPENSSLEXCEPTION("Failed to read PKCS12 certificate: %s.", path.c_str());
if(!PKCS12_parse(p12.get(), pass.c_str(), key, cert, nullptr))
THROW_OPENSSLEXCEPTION("Failed to parse PKCS12 certificate.");
else // Hack: clear PKCS12_parse error ERROR: 185073780 - error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch
OpenSSLException();
}
};

}
39 changes: 12 additions & 27 deletions src/crypto/PKCS12Signer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,20 @@

#include "PKCS12Signer.h"

#include "log.h"
#include "crypto/Digest.h"
#include "crypto/OpenSSLHelpers.h"
#include "crypto/X509Cert.h"
#include "log.h"

#include <openssl/pkcs12.h>
#include <openssl/x509.h>
using namespace digidoc;
using namespace std;

namespace digidoc
{
class PKCS12SignerPrivate
class PKCS12Signer::Private
{
public:
X509 *cert = nullptr;
EVP_PKEY *key = nullptr;
};
}
using namespace digidoc;
using namespace std;

#if OPENSSL_VERSION_NUMBER < 0x10010000L
static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
Expand All @@ -61,19 +56,9 @@ static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM
* @throws Exception throws exception if the file is not found or wrong password
*/
PKCS12Signer::PKCS12Signer(const string &path, const string &pass)
: d(new PKCS12SignerPrivate)
: d(new Private)
{
SCOPE(BIO, bio, BIO_new_file(path.c_str(), "rb"));
if(!bio)
THROW_CAUSE(OpenSSLException(), "Failed to open PKCS12 certificate: %s.", path.c_str());
SCOPE(PKCS12, p12, d2i_PKCS12_bio(bio.get(), 0));
if(!p12)
THROW_CAUSE(OpenSSLException(), "Failed to read PKCS12 certificate: %s.", path.c_str());

if(!PKCS12_parse(p12.get(), pass.c_str(), &d->key, &d->cert, 0))
THROW_CAUSE(OpenSSLException(), "Failed to parse PKCS12 certificate.");
else // Hack: clear PKCS12_parse error ERROR: 185073780 - error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch
OpenSSLException();
OpenSSL::parsePKCS12(path, pass, &d->key, &d->cert);
}

PKCS12Signer::~PKCS12Signer()
Expand Down Expand Up @@ -102,23 +87,23 @@ vector<unsigned char> PKCS12Signer::sign(const string &method, const vector<unsi
signature.resize(size_t(RSA_size(rsa.get())));
int nid = Digest::toMethod(method);
unsigned int size = (unsigned int)signature.size();
result = RSA_sign(nid, &digest[0], (unsigned int)digest.size(), signature.data(), &size, rsa.get());
result = RSA_sign(nid, digest.data(), (unsigned int)digest.size(), signature.data(), &size, rsa.get());
break;
}
#ifndef OPENSSL_NO_ECDSA
case EVP_PKEY_EC:
{
SCOPE(EC_KEY, ec, EVP_PKEY_get1_EC_KEY(d->key));
SCOPE(ECDSA_SIG, sig, ECDSA_do_sign(&digest[0], (unsigned int)digest.size(), ec.get()));
SCOPE(ECDSA_SIG, sig, ECDSA_do_sign(digest.data(), int(digest.size()), ec.get()));
if(!sig)
break;

unsigned int keyLen = 0;
size_t keyLen = 0;
if(const EC_GROUP *group = EC_KEY_get0_group(ec.get()))
{
BIGNUM *order = BN_new();
if (EC_GROUP_get_order(group, order, nullptr))
keyLen = BN_num_bytes(order);
keyLen = size_t(BN_num_bytes(order));
BN_clear_free(order);
}
if(keyLen == 0)
Expand All @@ -127,9 +112,9 @@ vector<unsigned char> PKCS12Signer::sign(const string &method, const vector<unsi

const BIGNUM *r = nullptr, *s = nullptr;
ECDSA_SIG_get0(sig.get(), &r, &s);
if(BN_bn2bin(r, &signature[keyLen - BN_num_bytes(r)]) <= 0)
if(BN_bn2bin(r, &signature[keyLen - size_t(BN_num_bytes(r))]) <= 0)
THROW("Error copying signature 'r' value to buffer");
if(BN_bn2bin(s, &signature[keyLen*2 - BN_num_bytes(s)]) <= 0)
if(BN_bn2bin(s, &signature[keyLen*2 - size_t(BN_num_bytes(s))]) <= 0)
THROW("Error copying signature 's' value to buffer");

result = 1;
Expand Down
Loading