Skip to content

Commit

Permalink
Reuse code and replace some manually handled memory management
Browse files Browse the repository at this point in the history
Signed-off-by: Raul Metsma <[email protected]>
  • Loading branch information
metsma committed Feb 19, 2025
1 parent 407aad0 commit beffd79
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 91 deletions.
8 changes: 3 additions & 5 deletions cdoc/CDoc1Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ CDoc1Writer::~CDoc1Writer()

bool CDoc1Writer::Private::writeRecipient(XMLWriter *xmlw, const std::vector<uint8_t> &recipient, const libcdoc::Crypto::Key& transportKey)
{
auto peerCert = make_unique_ptr<X509_free>(libcdoc::Crypto::toX509(recipient));
auto peerCert = libcdoc::Crypto::toX509(recipient);
if(!peerCert)
return false;
std::string cn = [&]{
Expand Down Expand Up @@ -129,9 +129,7 @@ bool CDoc1Writer::Private::writeRecipient(XMLWriter *xmlw, const std::vector<uin

std::string oid(50, 0);
oid.resize(size_t(OBJ_obj2txt(&oid[0], int(oid.size()), OBJ_nid2obj(curveName), 1)));
std::vector<uint8_t> SsDer(size_t(i2d_PublicKey(pkey.get(), nullptr)), 0);
uint8_t *p = SsDer.data();
i2d_PublicKey(pkey.get(), &p);
std::vector<uint8_t> SsDer = Crypto::toPublicKeyDer(pkey.get());

std::string encryptionMethod(libcdoc::Crypto::KWAES256_MTH);
std::string concatDigest = libcdoc::Crypto::SHA384_MTH;
Expand Down Expand Up @@ -287,7 +285,7 @@ libcdoc::result_t
CDoc1Writer::addFile(const std::string& name, size_t size)
{
d->files.push_back({name, size, {}});
return libcdoc::NOT_IMPLEMENTED;
return libcdoc::OK;
}

libcdoc::result_t
Expand Down
108 changes: 42 additions & 66 deletions cdoc/Certificate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,24 @@ namespace libcdoc {
static std::string
getName(const std::vector<uint8_t>& cert, int NID)
{
X509 *peerCert = Crypto::toX509(cert);
if(!peerCert) return {};
std::string cn = [&]{
std::string cn;
X509_NAME *name = X509_get_subject_name(peerCert);
if(!name)
return cn;
int pos = X509_NAME_get_index_by_NID(name, NID, -1);
if(pos == -1)
return cn;
X509_NAME_ENTRY *e = X509_NAME_get_entry(name, pos);
if(!e)
return cn;
char *data = nullptr;
int size = ASN1_STRING_to_UTF8((uint8_t**)&data, X509_NAME_ENTRY_get_data(e));

cn.assign(data, size_t(size));
OPENSSL_free(data);
return cn;
}();
X509_free(peerCert);
return cn;
std::string cn;
auto peerCert = Crypto::toX509(cert);
if(!peerCert)
return cn;
X509_NAME *name = X509_get_subject_name(peerCert.get());
if(!name)
return cn;
int pos = X509_NAME_get_index_by_NID(name, NID, -1);
if(pos == -1)
return cn;
X509_NAME_ENTRY *e = X509_NAME_get_entry(name, pos);
if(!e)
return cn;
char *data = nullptr;
int size = ASN1_STRING_to_UTF8((uint8_t**)&data, X509_NAME_ENTRY_get_data(e));
cn.assign(data, size_t(size));
OPENSSL_free(data);
return cn;
}

std::string
Expand All @@ -74,77 +70,59 @@ Certificate::getSerialNumber() const
return getName(cert, NID_serialNumber);
}

static void *
extension(X509 *x509, int nid )
{
return X509_get_ext_d2i(x509, nid, nullptr, nullptr);
}


std::vector<std::string>
Certificate::policies() const
{
constexpr int PolicyBufferLen = 50;
std::vector<std::string> list;

X509 *peerCert = Crypto::toX509(cert);
if(!peerCert) return {};
auto peerCert = Crypto::toX509(cert);
if(!peerCert)
return list;

stack_st_POLICYINFO *cp = (stack_st_POLICYINFO *) extension(peerCert, NID_certificate_policies);
if(!cp) {
X509_free(peerCert);
return {};
}
auto cp = make_unique_cast<CERTIFICATEPOLICIES_free>(X509_get_ext_d2i(
peerCert.get(), NID_certificate_policies, nullptr, nullptr));
if(!cp)
return list;

std::vector<std::string> list;
for(int i = 0; i < sk_POLICYINFO_num(cp); i++) {
POLICYINFO *pi = sk_POLICYINFO_value(cp, i);
for(int i = 0; i < sk_POLICYINFO_num(cp.get()); i++) {
POLICYINFO *pi = sk_POLICYINFO_value(cp.get(), i);
char buf[PolicyBufferLen + 1]{};
int len = OBJ_obj2txt(buf, PolicyBufferLen, pi->policyid, 1);
if(len != NID_undef) {
list.push_back(std::string(buf));
}
}

CERTIFICATEPOLICIES_free((CERTIFICATEPOLICIES *) cp);
X509_free(peerCert);
if(len != NID_undef) {
list.push_back(std::string(buf));
}
}

return list;
return list;
}

std::vector<uint8_t>
Certificate::getPublicKey() const
{
X509 *x509 = Crypto::toX509(cert);
if(!x509) return {};

EVP_PKEY *pkey = X509_get0_pubkey(x509);
int plen = i2d_PublicKey(pkey, nullptr);
std::vector<uint8_t> pdata(plen);
uint8_t *pptr = pdata.data();
i2d_PublicKey(pkey, &pptr);

X509_free(x509);

return pdata;
if(auto x509 = Crypto::toX509(cert))
return Crypto::toPublicKeyDer(X509_get0_pubkey(x509.get()));
return {};
}

Certificate::Algorithm
Certificate::getAlgorithm() const
{
X509 *x509 = Crypto::toX509(cert);
if(!x509) return {};
auto x509 = Crypto::toX509(cert);
if(!x509)
return {};

EVP_PKEY *pkey = X509_get0_pubkey(x509);
EVP_PKEY *pkey = X509_get0_pubkey(x509.get());
int alg = EVP_PKEY_get_base_id(pkey);

X509_free(x509);

return (alg == EVP_PKEY_RSA) ? Algorithm::RSA : Algorithm::ECC;
}

std::vector<uint8_t> Certificate::getDigest()
{
X509* x509 = Crypto::toX509(cert);
auto x509 = Crypto::toX509(cert);
if(!x509)
return {};

Expand All @@ -153,7 +131,7 @@ std::vector<uint8_t> Certificate::getDigest()
std::vector<uint8_t> digest(EVP_MAX_MD_SIZE);
unsigned int digest_len = 0;

if (X509_digest(x509, digest_type, digest.data(), &digest_len))
if (X509_digest(x509.get(), digest_type, digest.data(), &digest_len))
{
digest.resize(digest_len);
}
Expand All @@ -162,8 +140,6 @@ std::vector<uint8_t> Certificate::getDigest()
digest.clear();
}

X509_free(x509);

return digest;
}

Expand Down
7 changes: 3 additions & 4 deletions cdoc/Crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,8 +529,7 @@ Crypto::toPublicKeyDer(EVP_PKEY *key)
{
if(!key) return {};
std::vector<uint8_t> der(i2d_PublicKey(key, nullptr), 0);
auto *p = der.data();
if(i2d_PublicKey(key, &p) != der.size())
if(auto *p = der.data(); i2d_PublicKey(key, &p) != der.size())
{
LOG_SSL_ERROR("i2d_PublicKey");
der.clear();
Expand Down Expand Up @@ -562,10 +561,10 @@ Crypto::xor_data(std::vector<uint8_t>& dst, const std::vector<uint8_t> &lhs, con
return OK;
}

X509* Crypto::toX509(const std::vector<uint8_t> &data)
unique_free_t<X509> Crypto::toX509(const std::vector<uint8_t> &data)
{
const uint8_t *p = data.data();
X509* x509 = d2i_X509(nullptr, &p, int(data.size()));
auto x509 = make_unique_ptr(d2i_X509(nullptr, &p, int(data.size())), X509_free);
if (!x509)
{
LOG_SSL_ERROR("d2i_X509");
Expand Down
2 changes: 1 addition & 1 deletion cdoc/Crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class Crypto
static std::vector<uint8_t> random(uint32_t len = 32);
static int xor_data(std::vector<uint8_t>& dst, const std::vector<uint8_t> &lhs, const std::vector<uint8_t> &rhs);

static X509* toX509(const std::vector<uint8_t> &data);
static unique_free_t<X509> toX509(const std::vector<uint8_t> &data);

static bool isError(int retval, const char* funcName, const char* file, int line)
{
Expand Down
20 changes: 9 additions & 11 deletions cdoc/NetworkBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@
#include "Crypto.h"
#include "CryptoBackend.h"
#include "Utils.h"
#include "utils/memory.h"

#define OPENSSL_SUPPRESS_DEPRECATED

#include <openssl/bio.h>
#include <openssl/http.h>
#include "openssl/ssl.h"
#include <openssl/ssl.h>

#include "json.hpp"

Expand Down Expand Up @@ -54,7 +55,7 @@ static ECDSA_SIG* ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const B
static int rsa_sign(int type, const unsigned char *m, unsigned int m_len, unsigned char *sigret, unsigned int *siglen, const ::RSA *rsa);

struct Private {
X509 *x509 = nullptr;
libcdoc::unique_free_t<X509> x509{nullptr, X509_free};
EVP_PKEY *pkey = nullptr;

RSA_METHOD *rsamethod = nullptr;
Expand All @@ -64,7 +65,7 @@ struct Private {
if (client_cert.empty()) return;
x509 = libcdoc::Crypto::toX509(client_cert);
if (!x509) return;
pkey = EVP_PKEY_dup(X509_get0_pubkey(x509));
pkey = X509_get_pubkey(x509.get());
if (!pkey) return;
int id = EVP_PKEY_get_id(pkey);
if (id == EVP_PKEY_EC) {
Expand All @@ -91,7 +92,6 @@ struct Private {
}

~Private() {
if (x509) X509_free(x509);
if (pkey) EVP_PKEY_free(pkey);
if (rsamethod) RSA_meth_free(rsamethod);
if (ecmethod) EC_KEY_METHOD_free(ecmethod);
Expand Down Expand Up @@ -124,10 +124,9 @@ libcdoc::NetworkBackend::sendKey (CapsuleInfo& dst, const std::string& url, cons
X509_STORE *store = SSL_CTX_get_cert_store(ctx);
X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST | X509_V_FLAG_PARTIAL_CHAIN);
for (const std::vector<uint8_t>& c : certs) {
X509 *x509 = Crypto::toX509(c);
auto x509 = Crypto::toX509(c);
if (!x509) return CRYPTO_ERROR;
X509_STORE_add_cert(store, x509);
X509_free(x509);
X509_STORE_add_cert(store, x509.get());
}
cli.enable_server_certificate_verification(true);
cli.enable_server_hostname_verification(true);
Expand Down Expand Up @@ -186,7 +185,7 @@ libcdoc::NetworkBackend::fetchKey (std::vector<uint8_t>& dst, const std::string&
std::unique_ptr<Private> d = std::make_unique<Private>(this, cert);
if (!cert.empty() && (!d->x509 || !d->pkey)) return CRYPTO_ERROR;

httplib::SSLClient cli(host, port, d->x509, d->pkey);
httplib::SSLClient cli(host, port, d->x509.get(), d->pkey);

std::vector<std::vector<uint8_t>> certs;
getPeerTLSCertificates(certs);
Expand All @@ -196,10 +195,9 @@ libcdoc::NetworkBackend::fetchKey (std::vector<uint8_t>& dst, const std::string&
X509_STORE *store = SSL_CTX_get_cert_store(ctx);
X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST | X509_V_FLAG_PARTIAL_CHAIN);
for (const std::vector<uint8_t>& c : certs) {
X509 *x509 = Crypto::toX509(c);
auto x509 = Crypto::toX509(c);
if (!x509) return CRYPTO_ERROR;
X509_STORE_add_cert(store, x509);
X509_free(x509);
X509_STORE_add_cert(store, x509.get());
}
cli.enable_server_certificate_verification(true);
cli.enable_server_hostname_verification(true);
Expand Down
5 changes: 1 addition & 4 deletions cdoc/PKCS11Backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,10 +385,7 @@ libcdoc::PKCS11Backend::getPublicKey(std::vector<uint8_t>& val, bool& rsa, int s
EC_KEY_set_public_key(key, pub_key_point);
EVP_PKEY *evp_pkey = EVP_PKEY_new();
EVP_PKEY_assign_EC_KEY(evp_pkey, key);
int plen = i2d_PublicKey(evp_pkey, nullptr);
val.resize(plen);
uint8_t *pptr = val.data();
i2d_PublicKey(evp_pkey, &pptr);
val = Crypto::toPublicKeyDer(evp_pkey);
EVP_PKEY_free(evp_pkey);
EC_POINT_free(pub_key_point);
EC_GROUP_free(group);
Expand Down

0 comments on commit beffd79

Please sign in to comment.