diff -Naur libdigidocpp-3.12.3_orig/src/crypto/Connect.cpp libdigidocpp-3.12.3_patched/src/crypto/Connect.cpp
--- libdigidocpp-3.12.3_orig/src/crypto/Connect.cpp 2017-02-14 16:42:06.000000000 +0200
+++ libdigidocpp-3.12.3_patched/src/crypto/Connect.cpp 2017-02-25 00:17:17.213752854 +0200
@@ -29,6 +29,7 @@
#include <zlib.h>
+#include <cstring>
#include <thread>
using namespace digidoc;
@@ -104,7 +105,8 @@
{
SSL_CTX_set_verify(ssl.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0);
SSL_CTX_set_cert_verify_callback(ssl.get(), [](X509_STORE_CTX *store, void *cert) -> int {
- return store->cert && X509_cmp(store->cert, (X509*)cert) == 0 ? 1 : 0;
+ X509 *x509 = X509_STORE_CTX_get0_cert(store);
+ return x509 && X509_cmp(x509, (X509*)cert) == 0 ? 1 : 0;
}, cert.handle());
}
BIO *sbio = BIO_new_ssl(ssl.get(), 1);
diff -Naur libdigidocpp-3.12.3_orig/src/crypto/Digest.cpp libdigidocpp-3.12.3_patched/src/crypto/Digest.cpp
--- libdigidocpp-3.12.3_orig/src/crypto/Digest.cpp 2017-02-14 16:42:06.000000000 +0200
+++ libdigidocpp-3.12.3_patched/src/crypto/Digest.cpp 2017-02-24 23:57:24.672462506 +0200
@@ -89,7 +89,9 @@
SCOPE(X509_SIG, sig, d2i_X509_SIG(NULL, &p, (long)digest.size()));
if(!sig)
return vector<unsigned char>();
- return vector<unsigned char>(sig->digest->data, sig->digest->data + sig->digest->length);
+ const ASN1_OCTET_STRING *value = nullptr;
+ X509_SIG_get0(sig.get(), nullptr, &value);
+ return vector<unsigned char>(value->data, value->data + value->length);
}
string Digest::digestInfoUri(const std::vector<unsigned char> &digest)
@@ -98,7 +100,9 @@
SCOPE(X509_SIG, sig, d2i_X509_SIG(NULL, &p, (long)digest.size()));
if(!sig)
return string();
- switch(OBJ_obj2nid(sig->algor->algorithm))
+ const X509_ALGOR *algor = nullptr;
+ X509_SIG_get0(sig.get(), &algor, nullptr);
+ switch(OBJ_obj2nid(algor->algorithm))
{
case NID_sha1: return URI_SHA1;
case NID_sha224: return URI_SHA224;
diff -Naur libdigidocpp-3.12.3_orig/src/crypto/OCSP.cpp libdigidocpp-3.12.3_patched/src/crypto/OCSP.cpp
--- libdigidocpp-3.12.3_orig/src/crypto/OCSP.cpp 2017-02-14 16:42:06.000000000 +0200
+++ libdigidocpp-3.12.3_patched/src/crypto/OCSP.cpp 2017-02-24 23:57:41.151494155 +0200
@@ -131,20 +131,19 @@
{
if(!basic || !cert)
return false;
- OCSP_RESPID *respID = basic->tbsResponseData->responderId;
- switch(respID->type)
- {
- case V_OCSP_RESPID_NAME:
- return X509_NAME_cmp(X509_get_subject_name(cert.handle()), respID->value.byName) == 0;
- case V_OCSP_RESPID_KEY:
+ const ASN1_OCTET_STRING *hash = nullptr;
+ const X509_NAME *name = nullptr;
+ OCSP_resp_get0_id(basic, &hash, &name);
+ if(name)
+ return X509_NAME_cmp(X509_get_subject_name(cert.handle()), name) == 0;
+ else if(hash)
{
unsigned char sha1[SHA_DIGEST_LENGTH];
- ASN1_BIT_STRING *key = cert.handle()->cert_info->key->public_key;
+ ASN1_BIT_STRING *key = X509_get0_pubkey_bitstr(cert.handle());
return EVP_Digest(key->data, key->length, sha1, nullptr, EVP_sha1(), nullptr) == 1 &&
- memcmp(respID->value.byKey->data, &sha1, respID->value.byKey->length) == 0;
- }
- default: return false;
+ memcmp(hash->data, &sha1, hash->length) == 0;
}
+ return false;
}
/**
@@ -169,7 +168,7 @@
if(OCSP_request_add1_nonce(req.get(), const_cast<unsigned char*>(&nonce[0]), int(nonce.size())) <= 0)
THROW_OPENSSLEXCEPTION("Failed to add NONCE to OCSP request.");
#else
- ASN1_OCTET_STRING *st = M_ASN1_OCTET_STRING_new();
+ ASN1_OCTET_STRING *st = ASN1_OCTET_STRING_new();
if(nonce.empty())
{
st->length = 20;
@@ -182,7 +181,7 @@
st->length = int(nonce.size());
}
X509_EXTENSION *ex = X509_EXTENSION_create_by_NID(0, NID_id_pkix_OCSP_Nonce, 0, st);
- if(!X509v3_add_ext(&req->tbsRequest->requestExtensions, ex, 0))
+ if(!OCSP_REQUEST_add_ext(req.get(), ex, 0))
THROW_OPENSSLEXCEPTION("Failed to add NONCE to OCSP request.");
#endif
@@ -266,9 +265,10 @@
{
if(!basic)
return X509Cert();
- for(int i = 0; i < sk_X509_num(basic->certs); ++i)
+ const STACK_OF(X509) *certs = OCSP_resp_get0_certs(basic);
+ for(int i = 0; i < sk_X509_num(certs); ++i)
{
- X509Cert cert(sk_X509_value(basic->certs, i));
+ X509Cert cert(sk_X509_value(certs, i));
if(compareResponderCert(cert))
return cert;
}
@@ -419,8 +419,9 @@
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
case X509_V_ERR_CERT_UNTRUSTED:
{
+ X509 *x509 = X509_STORE_CTX_get0_cert(ctx);
const vector<X509Cert> &list = X509CertStore::instance()->certs();
- if(find(list.begin(), list.end(), X509Cert(ctx->current_cert)) != list.end())
+ if(find(list.begin(), list.end(), X509Cert(x509)) != list.end())
return 1;
return ok;
}
@@ -429,7 +430,7 @@
});
tm t = util::date::ASN1TimeToTM(producedAt());
- X509_VERIFY_PARAM_set_time(store->param, util::date::mkgmtime(t));
+ X509_VERIFY_PARAM_set_time(X509_STORE_get0_param(store.get()), util::date::mkgmtime(t));
X509_STORE_set_flags(store.get(), X509_V_FLAG_USE_CHECK_TIME);
//X509_STORE_set_trust(store.get(), X509_TRUST_TRUSTED);
@@ -492,7 +493,8 @@
if(!ext)
return vector<unsigned char>();
- vector<unsigned char> nonce(ext->value->data, ext->value->data + ext->value->length);
+ ASN1_OCTET_STRING *value = X509_EXTENSION_get_data(ext);
+ vector<unsigned char> nonce(value->data, value->data + value->length);
#if 1 //def OCSP_NATIVE_NONCE
//OpenSSL OCSP created messages NID_id_pkix_OCSP_Nonce field is DER encoded twice, not a problem with java impl
//XXX: UglyHackTM check if nonceAsn1 contains ASN1_OCTET_STRING
@@ -506,6 +508,10 @@
string OCSP::producedAt() const
{
- ASN1_GENERALIZEDTIME* time = basic->tbsResponseData->producedAt;
- return string(time->data, time->data+time->length);
+ string result;
+ if(!basic)
+ return result;
+ const ASN1_GENERALIZEDTIME *time = OCSP_resp_get0_produced_at(basic);
+ result.assign(time->data, time->data+time->length);
+ return result;
}
diff -Naur libdigidocpp-3.12.3_orig/src/crypto/PKCS12Signer.cpp libdigidocpp-3.12.3_patched/src/crypto/PKCS12Signer.cpp
--- libdigidocpp-3.12.3_orig/src/crypto/PKCS12Signer.cpp 2017-02-14 16:42:06.000000000 +0200
+++ libdigidocpp-3.12.3_patched/src/crypto/PKCS12Signer.cpp 2017-02-24 23:57:59.358529122 +0200
@@ -87,7 +87,7 @@
int result = 0;
vector<unsigned char> signature;
- switch(EVP_PKEY_type(d->key->type))
+ switch(EVP_PKEY_base_id(d->key))
{
case EVP_PKEY_RSA:
{
@@ -118,9 +118,11 @@
THROW("Error caclulating signature size");
signature.resize(keyLen * 2);
- if(BN_bn2bin(sig->r, &signature[keyLen - BN_num_bytes(sig->r)]) <= 0)
+ const BIGNUM *r = nullptr, *s = nullptr;
+ ECDSA_SIG_get0(sig.get(), &r, &s);
+ if(BN_bn2bin(r, &signature[keyLen - BN_num_bytes(r)]) <= 0)
THROW("Error copying signature 'r' value to buffer");
- if(BN_bn2bin(sig->s, &signature[keyLen*2 - BN_num_bytes(sig->s)]) <= 0)
+ if(BN_bn2bin(s, &signature[keyLen*2 - BN_num_bytes(s)]) <= 0)
THROW("Error copying signature 's' value to buffer");
result = 1;
diff -Naur libdigidocpp-3.12.3_orig/src/crypto/TS.cpp libdigidocpp-3.12.3_patched/src/crypto/TS.cpp
--- libdigidocpp-3.12.3_orig/src/crypto/TS.cpp 2017-02-14 16:42:06.000000000 +0200
+++ libdigidocpp-3.12.3_patched/src/crypto/TS.cpp 2017-02-24 23:58:13.666556602 +0200
@@ -86,13 +86,12 @@
THROW_OPENSSLEXCEPTION("Failed to parse TS response.");
SCOPE(TS_VERIFY_CTX, ctx, TS_VERIFY_CTX_new());
- ctx->flags = TS_VFY_NONCE|TS_VFY_VERSION;
- ctx->nonce = nonce.release();
+ TS_VERIFY_CTX_set_flags(ctx.get(), TS_VFY_VERSION);//|TS_VFY_NONCE);
+ //ctx->nonce = nonce.release();
if(TS_RESP_verify_response(ctx.get(), resp.get()) != 1)
THROW_OPENSSLEXCEPTION("Failed to verify TS response.");
- d.reset(resp->token, function<void(PKCS7*)>(PKCS7_free));
- resp->token = nullptr;
+ d.reset(PKCS7_dup(TS_RESP_get_token(resp.get())), function<void(PKCS7*)>(PKCS7_free));
}
TS::TS(const std::vector<unsigned char> &data)
@@ -122,7 +121,8 @@
if(!d)
return string();
SCOPE(TS_TST_INFO, info, PKCS7_to_TS_TST_INFO(d.get()));
- switch(OBJ_obj2nid(info->msg_imprint->hash_algo->algorithm))
+ X509_ALGOR *algo = TS_MSG_IMPRINT_get_algo(TS_TST_INFO_get_msg_imprint(info.get()));
+ switch(OBJ_obj2nid(algo->algorithm))
{
case NID_sha1: return URI_SHA1;
case NID_sha224: return URI_SHA224;
@@ -140,7 +140,8 @@
SCOPE(TS_TST_INFO, info, PKCS7_to_TS_TST_INFO(d.get()));
if(!info)
return string();
- return string((char*)info->time->data, info->time->length);
+ const ASN1_GENERALIZEDTIME *time = TS_TST_INFO_get_time(info.get());
+ return info ? string((char*)time->data, size_t(time->length)) : string();
}
void TS::verify(const Digest &digest)
@@ -150,24 +151,24 @@
vector<unsigned char> data = digest.result();
SCOPE(TS_VERIFY_CTX, ctx, TS_VERIFY_CTX_new());
- ctx->flags = TS_VFY_IMPRINT|TS_VFY_VERSION|TS_VFY_SIGNATURE;
- ctx->imprint = data.data();
- ctx->imprint_len = (unsigned int)data.size();
+ TS_VERIFY_CTX_set_flags(ctx.get(), TS_VFY_IMPRINT|TS_VFY_VERSION|TS_VFY_SIGNATURE);
+ TS_VERIFY_CTX_set_imprint(ctx.get(), data.data(), (long)data.size());
- ctx->store = X509_STORE_new();
+ X509_STORE *store = X509_STORE_new();
X509CertStore::instance()->activate(cert().issuerName("C"));
for(const X509Cert &i: X509CertStore::instance()->certs())
- X509_STORE_add_cert(ctx->store, i.handle());
+ X509_STORE_add_cert(store, i.handle());
OpenSSLException(); // Clear errors
+ TS_VERIFY_CTX_set_store(ctx.get(), store);
SCOPE(X509_STORE_CTX, csc, X509_STORE_CTX_new());
if (!csc)
THROW_OPENSSLEXCEPTION("Failed to create X509_STORE_CTX");
- if(!X509_STORE_CTX_init(csc.get(), ctx->store, 0, 0))
+ if(!X509_STORE_CTX_init(csc.get(), store, 0, 0))
THROW_OPENSSLEXCEPTION("Failed to init X509_STORE_CTX");
- X509_STORE_set_verify_cb_func(ctx->store, [](int ok, X509_STORE_CTX *ctx) -> int {
+ X509_STORE_set_verify_cb_func(store, [](int ok, X509_STORE_CTX *ctx) -> int {
switch(X509_STORE_CTX_get_error(ctx))
{
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
@@ -175,8 +176,9 @@
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
case X509_V_ERR_CERT_UNTRUSTED:
{
+ X509 *x509 = X509_STORE_CTX_get0_cert(ctx);
const vector<X509Cert> &list = X509CertStore::instance()->certs();
- if(find(list.begin(), list.end(), X509Cert(ctx->current_cert)) != list.end())
+ if(find(list.begin(), list.end(), X509Cert(x509)) != list.end())
return 1;
return ok;
}
@@ -185,9 +187,7 @@
});
int err = TS_RESP_verify_token(ctx.get(), d.get());
- //Avoid CRYPTO_free
- ctx->imprint = nullptr;
- ctx->imprint_len = 0;
+ TS_VERIFY_CTX_set_imprint(ctx.get(), nullptr, 0); //Avoid CRYPTO_free
if(err != 1)
{
long err = ERR_get_error();
diff -Naur libdigidocpp-3.12.3_orig/src/crypto/X509Cert.cpp libdigidocpp-3.12.3_patched/src/crypto/X509Cert.cpp
--- libdigidocpp-3.12.3_orig/src/crypto/X509Cert.cpp 2017-02-14 16:42:06.000000000 +0200
+++ libdigidocpp-3.12.3_patched/src/crypto/X509Cert.cpp 2017-02-24 23:58:27.935584006 +0200
@@ -374,13 +374,13 @@
if(pos == -1)
return result;
X509_EXTENSION *ext = X509_get_ext(cert.get(), pos);
- STACK_OF(QCStatement) *qc = (STACK_OF(QCStatement)*)ASN1_item_unpack(ext->value, ASN1_ITEM_rptr(QCStatements));
+ QCStatements *qc = (QCStatements*)ASN1_item_unpack(X509_EXTENSION_get_data(ext), ASN1_ITEM_rptr(QCStatements));
if(!qc)
return result;
- for(int i = 0; i < SKM_sk_num(QCStatement, qc); ++i)
+ for(int i = 0; i < sk_num((const stack_st*)qc); ++i)
{
- QCStatement *s = SKM_sk_value(QCStatement, qc, i);
+ QCStatement *s = (QCStatement*)sk_value((const stack_st*)qc, i);
string oid = toOID(s->statementId);
if(oid == QC_SYNTAX2)
{
@@ -413,7 +413,8 @@
else
result.push_back(oid);
}
- SKM_sk_pop_free(QCStatement, qc, QCStatement_free);
+ typedef void (*cast_free) (void *);
+ sk_pop_free((stack_st*)qc, (cast_free)QCStatement_free);
return result;
}
@@ -518,8 +519,8 @@
{
if(!cert)
THROW_OPENSSLEXCEPTION("Failed to validate cert");
- int notBefore = X509_cmp_time(cert->cert_info->validity->notBefore, t);
- int notAfter = X509_cmp_time(cert->cert_info->validity->notAfter, t);
+ int notBefore = X509_cmp_time(X509_get0_notBefore(cert.get()), t);
+ int notAfter = X509_cmp_time(X509_get0_notAfter(cert.get()), t);
if(notBefore == 0 || notAfter == 0)
THROW_OPENSSLEXCEPTION("Failed to validate cert");
return notBefore < 0 && notAfter > 0;
diff -Naur libdigidocpp-3.12.3_orig/src/crypto/X509CertStore.cpp libdigidocpp-3.12.3_patched/src/crypto/X509CertStore.cpp
--- libdigidocpp-3.12.3_orig/src/crypto/X509CertStore.cpp 2017-02-14 16:42:06.000000000 +0200
+++ libdigidocpp-3.12.3_patched/src/crypto/X509CertStore.cpp 2017-02-24 23:58:41.274609625 +0200
@@ -220,7 +220,8 @@
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
case X509_V_ERR_CERT_UNTRUSTED:
{
- if(find(instance()->d->begin(), instance()->d->end(), X509Cert(ctx->current_cert)) != instance()->d->end())
+ X509 *x509 = X509_STORE_CTX_get0_cert(ctx);
+ if(find(instance()->d->begin(), instance()->d->end(), X509Cert(x509)) != instance()->d->end())
return 1;
return ok;
}
diff -Naur libdigidocpp-3.12.3_orig/src/crypto/X509Crypto.cpp libdigidocpp-3.12.3_patched/src/crypto/X509Crypto.cpp
--- libdigidocpp-3.12.3_orig/src/crypto/X509Crypto.cpp 2017-02-14 16:42:06.000000000 +0200
+++ libdigidocpp-3.12.3_patched/src/crypto/X509Crypto.cpp 2017-02-24 23:58:53.014632172 +0200
@@ -23,8 +23,9 @@
#include "crypto/Digest.h"
#include "crypto/OpenSSLHelpers.h"
+#include <openssl/asn1t.h>
#include <openssl/err.h>
-#include <openssl/x509.h>
+#include <openssl/x509v3.h>
#include <cstring>
#include <set>
@@ -32,6 +33,23 @@
using namespace digidoc;
using namespace std;
+/*-
+ * IssuerSerial ::= SEQUENCE {
+ * issuer GeneralNames,
+ * serialNumber CertificateSerialNumber
+ * }
+ */
+typedef struct ESS_issuer_serial {
+ STACK_OF(GENERAL_NAME) *issuer;
+ ASN1_INTEGER *serial;
+} ESS_ISSUER_SERIAL;
+
+ASN1_SEQUENCE(ESS_ISSUER_SERIAL) = {
+ ASN1_SEQUENCE_OF(ESS_ISSUER_SERIAL, issuer, GENERAL_NAME),
+ ASN1_SIMPLE(ESS_ISSUER_SERIAL, serial, ASN1_INTEGER)
+} static_ASN1_SEQUENCE_END(ESS_ISSUER_SERIAL)
+IMPLEMENT_ASN1_FUNCTIONS_const(ESS_ISSUER_SERIAL)
+
/**
* Initialize RSA crypter.
*
@@ -70,6 +88,17 @@
*/
int X509Crypto::compareIssuerToString(const string &name) const
{
+ static const std::set<std::string> list{
+ "CN", "commonName",
+ "L", "localityName",
+ "ST", "stateOrProvinceName",
+ "O", "organizationName",
+ "OU", "organizationalUnitName",
+ "C", "countryName",
+ "STREET", "streetAddress",
+ "DC", "domainComponent",
+ "UID", "userId"
+ };
size_t old = 0;
while(true)
{
@@ -94,38 +123,26 @@
continue;
string obj = nameitem.substr(0, pos);
-
- static std::set<std::string> list{"CN", "commonName",
- "L", "localityName",
- "ST", "stateOrProvinceName",
- "O", "organizationName",
- "OU", "organizationalUnitName",
- "C", "countryName",
- "STREET", "streetAddress",
- "DC", "domainComponent",
- "UID", "userId"
- };
if(list.find(obj) == list.end())
continue;
- SCOPE(X509_NAME_ENTRY, enta, X509_NAME_ENTRY_create_by_txt(0, obj.c_str(),
- MBSTRING_UTF8, (unsigned char*)nameitem.substr(pos+1, pos-old).c_str(), -1));
- if(!enta)
- return -1;
-
- ASN1_OBJECT *obja = X509_NAME_ENTRY_get_object(enta.get());
+ ASN1_OBJECT *obja = OBJ_txt2obj(obj.c_str(), 0);
+ string value = nameitem.substr(pos+1, pos-old);
bool found = false;
- for(int i = 0; i < X509_NAME_entry_count(X509_get_issuer_name(cert.handle())); ++i)
+ X509_NAME *issuer = X509_get_issuer_name(cert.handle());
+ for(int i = 0; i < X509_NAME_entry_count(issuer); ++i)
{
- X509_NAME_ENTRY *entb = X509_NAME_get_entry(X509_get_issuer_name(cert.handle()), i);
- ASN1_OBJECT *objb = X509_NAME_ENTRY_get_object(entb);
- if(memcmp(obja->data, objb->data, obja->length) == 0 &&
- memcmp(enta->value, entb->value, enta->size) == 0)
- {
- found = true;
+ X509_NAME_ENTRY *entb = X509_NAME_get_entry(issuer, i);
+ if(OBJ_cmp(obja, X509_NAME_ENTRY_get_object(entb)) != 0)
+ continue;
+
+ char *data = nullptr;
+ int size = ASN1_STRING_to_UTF8((unsigned char**)&data, X509_NAME_ENTRY_get_data(entb));
+ found = value.compare(0, size_t(size), data) == 0;
+ OPENSSL_free(data);
+ if(found)
break;
- }
}
if(!found)
return -1;
@@ -140,16 +157,18 @@
vector<unsigned char> X509Crypto::rsaModulus() const
{
SCOPE(EVP_PKEY, key, X509_get_pubkey(cert.handle()));
- if(!key || key->type != EVP_PKEY_RSA)
+ if(!key || EVP_PKEY_base_id(key.get()) != EVP_PKEY_RSA)
return vector<unsigned char>();
SCOPE(RSA, rsa, EVP_PKEY_get1_RSA(key.get()));
- int bufSize = BN_num_bytes(rsa->n);
+ const BIGNUM *n = nullptr;
+ RSA_get0_key(rsa.get(), &n, nullptr, nullptr);
+ int bufSize = BN_num_bytes(n);
if(bufSize <= 0)
return vector<unsigned char>();
vector<unsigned char> rsaModulus(bufSize, 0);
- if(BN_bn2bin(rsa->n, rsaModulus.data()) <= 0)
+ if(BN_bn2bin(n, rsaModulus.data()) <= 0)
return vector<unsigned char>();
return rsaModulus;
@@ -176,7 +195,7 @@
THROW("Certificate does not have a public key, can not verify signature.");
int result = 0;
- switch(EVP_PKEY_type(key->type))
+ switch(EVP_PKEY_base_id(key.get()))
{
case EVP_PKEY_RSA:
{
@@ -190,10 +209,9 @@
{
SCOPE(EC_KEY, ec, EVP_PKEY_get1_EC_KEY(key.get()));
SCOPE(ECDSA_SIG, sig, ECDSA_SIG_new());
- BN_free(sig->r);
- BN_free(sig->s);
- sig->r = BN_bin2bn(signature.data(), int(signature.size()/2), 0);
- sig->s = BN_bin2bn(&signature[signature.size()/2], int(signature.size()/2), 0);
+ ECDSA_SIG_set0(sig.get(),
+ BN_bin2bn(signature.data(), int(signature.size()/2), 0),
+ BN_bin2bn(&signature[signature.size()/2], int(signature.size()/2), 0));
result = ECDSA_do_verify(digest.data(), (unsigned int)digest.size(), sig.get(), ec.get());
//result = ECDSA_verify(Digest::toMethod(method), digest.data(), (unsigned int)digest.size(),
// const_cast<unsigned char*>(signature.data()), (unsigned int)signature.size(), ec.get());