From 1739747e7bc8b1a7fe15f3203944c3c593a6b58d Mon Sep 17 00:00:00 2001 From: chris2511 Date: Wed, 14 May 2003 12:16:12 +0000 Subject: [PATCH] Support for PKCS#7 files completed. Extension *.p7b added Certificate stack export in PKCS7 format added BUG #737031 solved --- ExportCert.cpp | 6 +++-- ExportCert_UI.ui | 1 + MainWindow.h | 1 + MainWindowX509.cpp | 66 +++++++++++++++++++++++++++++++++++++++------- lib/db_x509.cpp | 12 +++++++++ lib/db_x509.h | 5 ++-- lib/pki_pkcs7.cpp | 58 +++++++++++++++++++++++++++++----------- lib/pki_pkcs7.h | 3 ++- 8 files changed, 122 insertions(+), 30 deletions(-) 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; };