xca/lib/pki_pkcs7.cpp
Christian Hohnstaedt 8726c8b96d Improve item loading. Inspired by #153
If Loading the item results in an openssl error,
even if the item is not empty, discard it.
Otherwise loading it from the database later on will fail.

Improve "autoIntName()"
2020-01-06 19:35:11 +01:00

197 lines
3.7 KiB
C++

/* vi: set sw=4 ts=4:
*
* Copyright (C) 2001 - 2010 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include "pki_pkcs7.h"
#include "func.h"
#include "exception.h"
pki_pkcs7::pki_pkcs7(const QString name)
:pki_base(name)
{
p7 = PKCS7_new();
PKCS7_set_type(p7, NID_pkcs7_signed);
PKCS7_content_new(p7, NID_pkcs7_data);
}
pki_pkcs7::~pki_pkcs7()
{
if (p7)
PKCS7_free(p7);
}
void pki_pkcs7::encryptFile(pki_x509 *crt, QString filename)
{
BIO *bio = NULL;
bio = BIO_new_file(QString2filename(filename), "r");
openssl_error();
encryptBio(crt, bio);
BIO_free(bio);
}
void pki_pkcs7::encryptBio(pki_x509 *crt, BIO *bio)
{
STACK_OF(X509) *certstack;
if (!crt)
return;
certstack = sk_X509_new_null();
sk_X509_push(certstack, crt->getCert());
openssl_error();
if (p7)
PKCS7_free(p7);
p7 = PKCS7_encrypt(certstack, bio, EVP_des_ede3_cbc(), PKCS7_BINARY);
openssl_error();
sk_X509_free(certstack);
}
void pki_pkcs7::signBio(pki_x509 *crt, BIO *bio)
{
pki_key *privkey;
EVP_PKEY *pk;
STACK_OF(X509) *certstack;
if (!crt)
return;
privkey = crt->getRefKey();
if (!privkey)
throw errorEx("No private key for signing found", getClassName());
certstack = sk_X509_new_null();
pki_x509 *signer = crt->getSigner();
if (signer == crt)
signer = NULL;
while (signer != NULL ) {
sk_X509_push(certstack, signer->getCert());
openssl_error();
if (signer == signer->getSigner() )
signer = NULL;
else
signer = signer->getSigner();
}
if (p7)
PKCS7_free(p7);
pk = privkey->decryptKey();
p7 = PKCS7_sign(crt->getCert(), pk, certstack, bio, PKCS7_BINARY);
EVP_PKEY_free(pk);
openssl_error();
sk_X509_free(certstack);
}
void pki_pkcs7::signFile(pki_x509 *crt, QString filename)
{
BIO *bio;
if (!crt)
return;
bio = BIO_new_file(QString2filename(filename), "r");
openssl_error();
signBio(crt, bio);
BIO_free(bio);
}
void pki_pkcs7::signCert(pki_x509 *crt, pki_x509 *contCert)
{
BIO *bio;
if (!crt)
return;
bio = BIO_new(BIO_s_mem());
openssl_error();
i2d_X509_bio(bio, contCert->getCert());
signBio(crt, bio);
BIO_free(bio);
}
void pki_pkcs7::writeP7(XFile &file, bool PEM) const
{
if (!p7)
return;
if (PEM)
PEM_write_PKCS7(file.fp(), p7);
else
i2d_PKCS7_fp(file.fp(), p7);
openssl_error();
}
pki_x509 *pki_pkcs7::getCert(int x)
{
pki_x509 *cert;
cert = new pki_x509(X509_dup(sk_X509_value(getCertStack(), x)));
openssl_error();
cert->autoIntName(getIntName());
cert->pkiSource = imported;
return cert;
}
int pki_pkcs7::numCert()
{
int n= sk_X509_num(getCertStack());
openssl_error();
return n;
}
void pki_pkcs7::fromPEM_BIO(BIO *bio, QString name)
{
PKCS7 *_p7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
openssl_error(name);
if (p7)
PKCS7_free(p7);
p7 = _p7;
autoIntName(name);
}
void pki_pkcs7::fload(const QString fname)
{
PKCS7 *_p7;
XFile file(fname);
file.open_read();
_p7 = PEM_read_PKCS7(file.fp(), NULL, NULL, NULL);
if (!_p7) {
ign_openssl_error();
file.retry_read();
_p7 = d2i_PKCS7_fp(file.fp(), NULL);
}
if (ign_openssl_error()) {
if (_p7)
PKCS7_free(_p7);
throw errorEx(tr("Unable to load the PKCS#7 file %1. Tried PEM and DER format.").arg(fname));
}
if (p7)
PKCS7_free(p7);
p7 = _p7;
}
STACK_OF(X509) *pki_pkcs7::getCertStack()
{
int i;
STACK_OF(X509) *certstack = NULL;
if (p7 == NULL)
return NULL;
i = OBJ_obj2nid(p7->type);
switch (i) {
case NID_pkcs7_signed:
certstack = p7->d.sign->cert;
break;
case NID_pkcs7_signedAndEnveloped:
certstack = p7->d.signed_and_enveloped->cert;
break;
default:
break;
}
openssl_error();
return certstack;
}
void pki_pkcs7::addCert(pki_x509 *crt)
{
if (p7 == NULL || crt == NULL)
return;
PKCS7_add_certificate(p7, crt->getCert());
openssl_error();
}