diff --git a/ExportCert.cpp b/ExportCert.cpp
index a5bfb224..328e3366 100644
--- a/ExportCert.cpp
+++ b/ExportCert.cpp
@@ -63,7 +63,9 @@ ExportCert::ExportCert(QString fname, bool hasKey, QString dpath,
exportFormat->insertItem("PEM all trusted Certificates");
exportFormat->insertItem("PEM all Certificates");
exportFormat->insertItem("DER");
-// exportFormat->insertItem("Signed PKCS#7");
+ exportFormat->insertItem("PKCS #7");
+ exportFormat->insertItem("PKCS #7 with Certificate chain");
+ exportFormat->insertItem("PKCS #7 all trusted Certificates");
if (hasKey) {
exportFormat->insertItem("PKCS #12");
exportFormat->insertItem("PKCS #12 with Certificate chain");
@@ -98,7 +100,7 @@ void ExportCert::chooseFile()
void ExportCert::formatChanged()
{
CERR("Export format changed");
- char *suffix[] = {"crt", "crt", "crt", "crt", "cer", "p12", "p12"};
+ char *suffix[] = {"crt", "crt", "crt", "crt", "cer", "p7b", "p7b", "p7b", "p12", "p12"};
int selected = exportFormat->currentItem();
QString fn = filename->text();
QString nfn = fn.left(fn.findRev('.')+1) + suffix[selected];
diff --git a/ExportCert_UI.ui b/ExportCert_UI.ui
index ae9942d6..ce9acfd5 100644
--- a/ExportCert_UI.ui
+++ b/ExportCert_UI.ui
@@ -238,6 +238,7 @@
text
DER is a binary format of the Certificate
PEM is a base64 encoded Certificate
+PKCS#7 is an official Certificate exchange format
PKCS#12 is an encrypted official Key-Certificate exchange format
diff --git a/MainWindow.h b/MainWindow.h
index 5dd08cb3..9d6b7987 100644
--- a/MainWindow.h
+++ b/MainWindow.h
@@ -169,6 +169,7 @@ class MainWindow: public MainWindow_UI
bool alterTemp(pki_temp *temp);
void Error(errorEx &err);
void writePKCS12(QString s, bool chain);
+ void writePKCS7(QString s, int type);
void setPath(QFileDialog *dlg);
QString getPath();
void newPath(QFileDialog *dlg);
diff --git a/MainWindowX509.cpp b/MainWindowX509.cpp
index 0090b678..5701329c 100644
--- a/MainWindowX509.cpp
+++ b/MainWindowX509.cpp
@@ -554,9 +554,7 @@ void MainWindow::deleteCert()
void MainWindow::loadCert()
{
QStringList filt;
- filt.append(tr("Certificates ( *.pem *.der *.crt *.cer)"));
- filt.append(tr("PKCS#12 Certificates ( *.p12 )"));
- //filt.append(tr("PKCS#7 Signatures ( *.p7s )"));
+ filt.append(tr("Certificates ( *.pem *.der *.crt *.cer )"));
filt.append(tr("All files ( *.* )"));
QStringList slist;
QString s="";
@@ -591,7 +589,7 @@ void MainWindow::loadPKCS12()
{
pki_pkcs12 *pk12;
QStringList filt;
- filt.append(tr("PKCS#12 Certificates ( *.p12 )"));
+ filt.append(tr("PKCS#12 Certificates ( *.p12 *.pfx )"));
filt.append(tr("All files ( *.* )"));
QStringList slist;
QString s="";
@@ -658,10 +656,10 @@ void MainWindow::insertP12(pki_pkcs12 *pk12)
void MainWindow::loadPKCS7()
{
- pki_pkcs7 *pk7;
+ pki_pkcs7 *pk7 = NULL;
pki_x509 *acert;
QStringList filt;
- filt.append(tr("PKCS#7 data ( *.p7s *.p7m )"));
+ filt.append(tr("PKCS#7 data ( *.p7s *.p7m *.p7b )"));
filt.append(tr("All files ( *.* )"));
QStringList slist;
QString s="";
@@ -680,17 +678,21 @@ void MainWindow::loadPKCS7()
s = QDir::convertSeparators(s);
try {
pk7 = new pki_pkcs7(s.latin1());
+ MARK
pk7->readP7(s.latin1());
+ MARK
for (int i=0; inumCert(); i++) {
acert = pk7->getCert(i);
showDetailsCert(acert, true);
}
- delete pk7;
keys->updateView();
}
catch (errorEx &err) {
Error(err);
}
+ MARK
+ if (pk7) delete pk7;
+ MARK
}
}
@@ -736,6 +738,10 @@ pki_x509 *MainWindow::insertCert(pki_x509 *cert)
return cert;
}
+#define P7_ONLY 0
+#define P7_CHAIN 1
+#define P7_TRUSTED 2
+
void MainWindow::writeCert()
{
QStringList filt;
@@ -779,10 +785,19 @@ void MainWindow::writeCert()
case 4: // DER
crt->writeCert(fname.latin1(),false,false);
break;
- case 5: // P12
+ case 5: // P7 lonely
+ writePKCS7(fname, P7_ONLY);
+ break;
+ case 6: // P12
+ writePKCS7(fname, P7_CHAIN);
+ break;
+ case 7: // P12
+ writePKCS7(fname, P7_TRUSTED);
+ break;
+ case 8: // P12
writePKCS12(fname,false);
break;
- case 6: // P12 + cert chain
+ case 9: // P12 + cert chain
writePKCS12(fname,true);
break;
@@ -829,6 +844,39 @@ void MainWindow::writePKCS12(QString s, bool chain)
}
}
+void MainWindow::writePKCS7(QString s, int type) {
+ pki_pkcs7 *p7 = NULL;
+ QList list;
+ pki_x509 *cert = (pki_x509 *)certs->getSelectedPKI();
+ try {
+ p7 = new pki_pkcs7("");
+ if ( type == P7_CHAIN ) {
+ while (cert != NULL) {
+ p7->addCert(cert);
+ if (cert->getSigner() == cert) cert = NULL;
+ else cert = cert->getSigner();
+ }
+ }
+ if ( type == P7_ONLY ) {
+ p7->addCert(cert);
+ }
+ if (type == P7_TRUSTED) {
+ list = certs->getCerts(true);
+ if (!list.isEmpty()) {
+ for ( cert = list.first(); cert != NULL; cert = list.next() ) {
+ p7->addCert(cert);
+ }
+ }
+ }
+ p7->writeP7(s.latin1(), false);
+ }
+ catch (errorEx &err) {
+ Error(err);
+ }
+ if (p7 != NULL ) delete p7;
+
+}
+
void MainWindow::signP7()
{
QStringList filt;
diff --git a/lib/db_x509.cpp b/lib/db_x509.cpp
index 6110a2d1..03080767 100644
--- a/lib/db_x509.cpp
+++ b/lib/db_x509.cpp
@@ -396,6 +396,18 @@ void db_x509::writeAllCerts(QString fname, bool onlyTrusted)
}
}
+QList db_x509::getCerts(bool onlyTrusted)
+{
+ QList c;
+ c.clear();
+ pki_x509 *cert = NULL;
+ for ( cert = (pki_x509 *)container.first(); cert != 0; cert = (pki_x509 *)container.next() ) {
+ if (onlyTrusted && cert->getTrust() != 2) continue;
+ c.append(cert);
+ }
+ return c;
+}
+
int db_x509::searchSerial(pki_x509 *signer)
{
if (!signer) return 0;
diff --git a/lib/db_x509.h b/lib/db_x509.h
index 25ae1cd4..a7592b62 100644
--- a/lib/db_x509.h
+++ b/lib/db_x509.h
@@ -80,8 +80,9 @@ class db_x509: public db_base
QStringList getSignerDesc();
pki_key * findKey(pki_x509 *cert);
void calcEffTrust();
- QList db_x509::getIssuedCerts(pki_x509 *issuer);
- pki_x509 *db_x509::getBySubject(X509_NAME *xname);
+ QList getIssuedCerts(pki_x509 *issuer);
+ QList getCerts(bool onlyTrusted);
+ pki_x509 *getBySubject(X509_NAME *xname);
int searchSerial(pki_x509 *signer);
void writeAllCerts(QString fname, bool onlyTrusted);
pki_x509 *getByIssSerial(pki_x509 *iss, long serial);
diff --git a/lib/pki_pkcs7.cpp b/lib/pki_pkcs7.cpp
index 78cbd4b0..dd980915 100644
--- a/lib/pki_pkcs7.cpp
+++ b/lib/pki_pkcs7.cpp
@@ -55,8 +55,9 @@
pki_pkcs7::pki_pkcs7(const string d )
:pki_base(d)
{
- p7 = NULL;
- certstack = NULL;
+ p7 = PKCS7_new();
+ PKCS7_set_type(p7, NID_pkcs7_signed);
+ PKCS7_content_new(p7, NID_pkcs7_data);
className = "pki_pkcs7";
}
@@ -64,16 +65,14 @@ pki_pkcs7::pki_pkcs7(const string d )
pki_pkcs7::~pki_pkcs7()
{
if (p7) PKCS7_free(p7);
- if (certstack) sk_X509_free(certstack);
}
void pki_pkcs7::encryptFile(pki_x509 *crt, string filename)
{
BIO *bio = NULL;
+ STACK_OF(X509) *certstack;
if (!crt) return;
bio = BIO_new_file(filename.c_str(), "r");
- openssl_error();
- if (certstack) sk_X509_free(certstack);
certstack = sk_X509_new_null();
sk_X509_push(certstack, crt->getCert());
openssl_error();
@@ -81,29 +80,30 @@ void pki_pkcs7::encryptFile(pki_x509 *crt, string filename)
p7 = PKCS7_encrypt(certstack, bio, EVP_des_ede3_cbc(), PKCS7_BINARY);
openssl_error();
sk_X509_free(certstack);
- certstack = NULL;
}
void pki_pkcs7::signBio(pki_x509 *crt, BIO *bio)
{
pki_key *privkey;
+ STACK_OF(X509) *certstack;
if (!crt) return;
privkey = crt->getKey();
if (!privkey) throw errorEx("No private key for signing found", className);
- if (certstack) sk_X509_free(certstack);
certstack = sk_X509_new_null();
+
pki_x509 *signer = crt->getSigner();
- while (signer != NULL && signer != signer->getSigner()) {
+ if (signer == crt) signer = NULL;
+ while (signer != NULL ) {
+ CERR("SIGNER: "<getDescription())
sk_X509_push(certstack, signer->getCert());
openssl_error();
- signer = signer->getSigner();
- CERR("SIGNER: "<getDescription())
+ if (signer == signer->getSigner() ) signer = NULL;
+ else signer = signer->getSigner();
}
if (p7) PKCS7_free(p7);
p7 = PKCS7_sign(crt->getCert(), privkey->getKey(), certstack, bio, PKCS7_BINARY);
openssl_error();
sk_X509_free(certstack);
- certstack = NULL;
}
@@ -146,17 +146,15 @@ void pki_pkcs7::writeP7(string fname,bool PEM)
}
pki_x509 *pki_pkcs7::getCert(int x) {
- if (!certstack) return NULL;
pki_x509 *cert;
- cert = new pki_x509(X509_dup(sk_X509_value(certstack, x)));
+ cert = new pki_x509(X509_dup(sk_X509_value(getCertStack(), x)));
openssl_error();
cert->setDescription("pk7-import");
return cert;
}
int pki_pkcs7::numCert() {
- if (!certstack) return 0;
- int n= sk_X509_num(certstack);
+ int n= sk_X509_num(getCertStack());
openssl_error();
return n;
}
@@ -169,6 +167,7 @@ void pki_pkcs7::readP7(string fname)
p7 = PEM_read_PKCS7(fp, NULL, NULL, NULL);
if (!p7) {
ign_openssl_error();
+ rewind(fp);
CERR("Fallback to DER encoded PKCS#7");
p7 = d2i_PKCS7_fp(fp, &p7);
}
@@ -176,7 +175,34 @@ void pki_pkcs7::readP7(string fname)
fclose(fp);
openssl_error();
}
- certstack = PKCS7_get0_signers(p7, NULL, 0);
+ else fopen_error(fname);
+}
+
+
+STACK_OF(X509) *pki_pkcs7::getCertStack() {
+ STACK_OF(X509) *certstack = NULL;
+ int i;
+ if (p7 == NULL) return NULL;
+ i = OBJ_obj2nid(p7->type);
+ switch (i) {
+ case NID_pkcs7_signed:
+ certstack = p7->d.sign->cert;
+ CERR("PKCS#7: SIGNED");
+ break;
+ case NID_pkcs7_signedAndEnveloped:
+ certstack = p7->d.signed_and_enveloped->cert;
+ CERR("PKCS#7: SIGNED and ENVELOPED");
+ 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();
}
diff --git a/lib/pki_pkcs7.h b/lib/pki_pkcs7.h
index 785ad8d8..16832469 100644
--- a/lib/pki_pkcs7.h
+++ b/lib/pki_pkcs7.h
@@ -62,7 +62,7 @@ class pki_pkcs7: public pki_base
friend class pki_x509;
protected:
PKCS7 *p7;
- STACK_OF(X509) *certstack;
+ STACK_OF(X509) *getCertStack();
void signBio(pki_x509 *crt, BIO * bio);
public:
pki_pkcs7(const string d);
@@ -75,6 +75,7 @@ class pki_pkcs7: public pki_base
void writeP7(string fname,bool PEM);
void readP7(string fname);
pki_x509 *getCert(int x);
+ void addCert(pki_x509 *crt);
int numCert(); // number of certs;
};