diff --git a/Makefile b/Makefile index 0318045a..de788f92 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ export TOPDIR=$(shell pwd) SUBDIRS=lib widgets view ui OBJECTS=$(patsubst %, %/target.obj, $(SUBDIRS)) INSTDIR=img misc lang doc +CLEANDIRS=lang doc bindir=bin @@ -32,10 +33,13 @@ clean: for x in $(SUBDIRS); do \ $(MAKE) -C $${x} clean; \ done + for x in $(CLEANDIRS); do \ + $(MAKE) -C $${x} clean; \ + done rm -f *~ xca distclean: clean - rm -f Local.mak + rm -f Local.mak conftest conftest.log dist: test ! -z "$(TVERSION)" @@ -52,7 +56,7 @@ dist: tar zcf $(TARGET).tar.gz $(TARGET) && \ (cd $(TARGET) && dpkg-buildpackage -rfakeroot ) #rm -rf ../$(TARGET) - + install: xca $(STRIP) xca install -m 755 -d $(destdir)$(prefix)/$(bindir) diff --git a/Rules.mak b/Rules.mak index be177b9e..b923dcd0 100644 --- a/Rules.mak +++ b/Rules.mak @@ -46,7 +46,7 @@ clean: rm -f *~ *.o *.obj $(DELFILES) distclean: clean - rm -f .depend + rm -f -r .depend .depend: $(SRCS) $(CC) -MM $(CPPFLAGS) $(CFLAGS) $(SRCS) > $@ diff --git a/debian/changelog b/debian/changelog index e3e1b75a..db6c3374 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +xca (0.5.1-1.0) unstable; urgency=low + + * NMU + + -- Mikael Magnusson Tue, 7 Sep 2004 20:01:50 +0200 + xca (0.5.1-1) unstable; urgency=low * support for different languages on WIN platform (Thanks Ilya) @@ -66,7 +72,7 @@ xca (0.4.6) unstable; urgency=low - Support for UTF8 in x509name - Netscape SPKAC support added - -- Christian Hohnstädt Tue, 25 Nov 2003 18:28:02 +0100 + -- Christian Hohnstädt Tue, 25 Nov 2003 18:28:02 +0100 xca (0.4.5) unstable; urgency=low @@ -78,14 +84,14 @@ xca (0.4.5) unstable; urgency=low editable to enter arbitrary key sizes. * [ 765774 ] change password for database - -- Christian Hohnstädt Wed, 13 Aug 2003 22:10:43 +0200 + -- Christian Hohnstädt Wed, 13 Aug 2003 22:10:43 +0200 xca (0.4.4) unstable; urgency=low * [ 783853 ] renewal uses 'notBefore' as 'notAfter' date * [ 783830 ] GeneralizedTime-format breaks browsers - -- Christian Hohnstädt Wed, 6 Aug 2003 18:42:58 +0200 + -- Christian Hohnstädt Wed, 6 Aug 2003 18:42:58 +0200 xca (0.4.3) unstable; urgency=low @@ -99,7 +105,7 @@ xca (0.4.3) unstable; urgency=low * some segmentation faults removed * VPN OIDs added to Ext. Keyusage - -- Christian Hohnstädt Tue, 5 Aug 2003 21:51:20 +0200 + -- Christian Hohnstädt Tue, 5 Aug 2003 21:51:20 +0200 xca (0.4.2) unstable; urgency=low @@ -114,7 +120,7 @@ xca (0.4.2) unstable; urgency=low reconnected. * Authority Key identifier repaired - -- Christian Hohnstädt Sun, 20 Jul 2003 23:38:38 +0200 + -- Christian Hohnstädt Sun, 20 Jul 2003 23:38:38 +0200 xca (0.4.1) unstable; urgency=low @@ -145,7 +151,7 @@ xca (0.4.0) unstable; urgency=low key.xpm will be installed as xca.xpm in pixmaps ([ 763954 ] xca.desktop file) Thanks to Enrico Scholz - -- Christian Hohnstädt Tue, 8 Jul 2003 23:31:37 +0200 + -- Christian Hohnstädt Tue, 8 Jul 2003 23:31:37 +0200 xca (0.3.2) unstable; urgency=low @@ -154,14 +160,14 @@ xca (0.3.2) unstable; urgency=low * Support for PKCS#7 certs (im/export) * small UI changes - -- Christian Hohnstädt Thu, 15 May 2003 00:46:07 +0200 + -- Christian Hohnstädt Thu, 15 May 2003 00:46:07 +0200 xca (0.3.1) unstable; urgency=low * Tool Tips added * CRL handling (import, export, details) added - -- Christian Hohnstädt Thu, 24 Apr 2003 19:29:36 +0200 + -- Christian Hohnstädt Thu, 24 Apr 2003 19:29:36 +0200 xca (0.3.0) unstable; urgency=low @@ -177,7 +183,7 @@ xca (0.3.0) unstable; urgency=low * changes in configure * The wizard invokes the key generation process only if really needed - -- Christian Hohnstädt Wed, 5 Mar 2003 23:56:56 +0100 + -- Christian Hohnstädt Wed, 5 Mar 2003 23:56:56 +0100 xca (0.2.12) unstable; urgency=low @@ -186,7 +192,7 @@ xca (0.2.12) unstable; urgency=low * Several export targets added * Certificate renewal repaired - -- Christian Hohnstädt Mon, 6 Jan 2003 21:40:28 +0100 + -- Christian Hohnstädt Mon, 6 Jan 2003 21:40:28 +0100 xca (0.2.11) unstable; urgency=low @@ -195,7 +201,7 @@ xca (0.2.11) unstable; urgency=low * configure continues even if qt lib is absent. * $HOME/xca is created if it does not exist. - -- Christian Hohnstädt Wed, 4 Dec 2002 21:38:28 +0100 + -- Christian Hohnstädt Wed, 4 Dec 2002 21:38:28 +0100 xca (0.2.10) unstable; urgency=low @@ -207,7 +213,7 @@ xca (0.2.10) unstable; urgency=low * create request from certificate * FreeBSD paths and libs recognized by configure - -- Christian Hohnstädt Wed, 4 Dec 2002 21:34:41 +0100 + -- Christian Hohnstädt Wed, 4 Dec 2002 21:34:41 +0100 xca (0.2.9) unstable; urgency=low @@ -219,7 +225,7 @@ xca (0.2.9) unstable; urgency=low * database transactions activated * exception-handling completed - -- Christian Hohnstädt Mon, 21 Oct 2002 21:05:59 +0200 + -- Christian Hohnstädt Mon, 21 Oct 2002 21:05:59 +0200 xca (0.2.8) unstable; urgency=low @@ -230,14 +236,14 @@ xca (0.2.8) unstable; urgency=low * package-builder do build without printf-debugging * key-use counter works now well - -- Christian Hohnstädt Sun, 13 Oct 2002 23:28:29 +0200 + -- Christian Hohnstädt Sun, 13 Oct 2002 23:28:29 +0200 xca (0.2.7) unstable; urgency=low * segfaults removed * minor wizard changes - -- Christian Hohnstädt Mon, 7 Oct 2002 23:32:19 +0200 + -- Christian Hohnstädt Mon, 7 Oct 2002 23:32:19 +0200 xca (0.2.6) unstable; urgency=low @@ -247,7 +253,7 @@ xca (0.2.6) unstable; urgency=low * signing-template, CRL date and CRL time interval adjustable * Fix for windows filenames - -- Christian Hohnstädt Mon, 30 Sep 2002 22:02:01 +0200 + -- Christian Hohnstädt Mon, 30 Sep 2002 22:02:01 +0200 xca (0.2.5) unstable; urgency=low @@ -260,7 +266,7 @@ xca (0.2.5) unstable; urgency=low * Files for MS Visual C++ added (yes, it compiles on MS Windows) * Windows Installer added (Nullsoft) - -- Christian Hohnstädt Tue, 24 Sep 2002 02:18:51 +0200 + -- Christian Hohnstädt Tue, 24 Sep 2002 02:18:51 +0200 xca (0.2.4) unstable; urgency=low diff --git a/debian/control b/debian/control index 4e91af68..76d2057e 100644 --- a/debian/control +++ b/debian/control @@ -2,16 +2,19 @@ Source: xca Section: x11 Priority: optional Maintainer: Christian Hohnstaedt -Build-Depends: debhelper (>> 3.0.0), libdb3++-dev, libqt-dev, libssl-dev +Build-Depends: debhelper (>> 3.0.0), libdb4.2++-dev | libdb3++-dev, libqt3-mt-dev, libssl-dev, libqt3-compat-headers Standards-Version: 3.6.1.0 Package: xca Architecture: any Depends: ${shlibs:Depends} -Description: A GUI for handling X509 certificates, RSA keys, PKCS#10 Requests and CRLs. - The Program uses a Berkeley db for storage and supports RSA keys, - Certificate signing requests (PKCS#10) and Certificates (X509v3) - The signing of requests, and the creation of selfsigned certificates - is supported. Both can use templates for simplicity. - The PKI structures can be imported and exported in several formats - like PKCS#12, PEM, DER, PKCS#8, PKCS#7. +Description: GUI for handling X509 certificates, RSA keys, PKCS#10 Requests and CRLs + XCA is a GUI for handling X509 certificates, RSA keys, PKCS#10 + Requests and CRLs. The program uses a Berkeley db for storage and + supports RSA keys, Certificate signing requests (PKCS#10) and + Certificates (X509v3) The signing of requests, and the creation of + selfsigned certificates is supported. Both can use templates for + simplicity. The PKI structures can be imported and exported in + several formats like PKCS#12, PEM, DER, PKCS#8, PKCS#7. + . + Homepage: http://www.hohnstaedt.de/xca diff --git a/debian/copyright b/debian/copyright index ebba6737..c3af03af 100644 --- a/debian/copyright +++ b/debian/copyright @@ -17,3 +17,5 @@ mail: christian@hohnstaedt.de http: www.hohnstaedt.de/xca +On Debian systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. diff --git a/debian/docs b/debian/docs index e845566c..98669d6b 100644 --- a/debian/docs +++ b/debian/docs @@ -1 +1,3 @@ README +AUTHORS +CREDITS diff --git a/debian/menu b/debian/menu index 2122d0db..28a475e1 100644 --- a/debian/menu +++ b/debian/menu @@ -1,2 +1,2 @@ -?package(xca):needs=X11 section=Apps/Tools\ - title="xca" command="/usr/bin/xca" +?package(xca):needs="X11" section="Apps/Tools"\ + title="xca" command="/usr/bin/xca" icon="/usr/share/pixmaps/xca.xpm" diff --git a/debian/rules b/debian/rules index 644dc8ab..c17ac443 100755 --- a/debian/rules +++ b/debian/rules @@ -8,19 +8,31 @@ # This is the debhelper compatability version to use. export DH_COMPAT=2 +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif +ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) + INSTALL_PROGRAM += -s +endif + Local.mak: dh_testdir - # Add here commands to configure the package. - # prefix=/usr ./configure - cat debian/debian.mak > Local.mak + prefix=/usr CFLAGS="$(CFLAGS)" QTDIR="/usr/share/qt3" ./configure +# Don't use scripts + -test -f debian/postinst && mv debian/postinst debian/postinst.bak + -test -f debian/postrm && mv debian/postrm debian/postrm.bak build: build-stamp build-stamp: Local.mak dh_testdir - # Add here commands to compile the package. - $(MAKE) -j 4 +# $(MAKE) -j 4 + $(MAKE) touch build-stamp clean: @@ -28,8 +40,9 @@ clean: dh_testroot rm -f build-stamp - # Add here commands to clean up after the build process. -$(MAKE) distclean + -test -f debian/postinst.bak && mv debian/postinst.bak debian/postinst + -test -f debian/postrm.bak && mv debian/postrm.bak debian/postrm dh_clean install: build @@ -38,8 +51,7 @@ install: build dh_clean -k dh_installdirs - # Add here commands to install the package into debian/xca. - $(MAKE) install + $(MAKE) install destdir=$(CURDIR)/debian/tmp # Build architecture-independent files here. binary-indep: build install @@ -49,6 +61,7 @@ binary-indep: build install binary-arch: build install dh_testdir dh_testroot + dh_install --list-missing # dh_installdebconf dh_installdocs # dh_installexamples @@ -59,7 +72,7 @@ binary-arch: build install # dh_installmime # dh_installinit # dh_installcron - dh_installmanpages + dh_installman # dh_installinfo # dh_undocumented dh_installchangelogs diff --git a/doc/Makefile b/doc/Makefile index 31a43b3d..19d64b84 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -18,5 +18,8 @@ install: xca.1.gz install -m 644 xca*.html $(destdir)$(prefix)/share/xca install xca.1.gz $(destdir)$(prefix)/$(mandir)/man1 +clean: + $(RM) xca.1.gz + include $(TOPDIR)/Local.mak diff --git a/lang/Makefile b/lang/Makefile index 115c1e1b..136c9566 100644 --- a/lang/Makefile +++ b/lang/Makefile @@ -1,9 +1,17 @@ +QM_FILES=xca_de.qm xca_es.qm -all: +.SUFFIXES: .ts .qm -install: +.ts.qm: + lrelease $< -qm $@ + +all: $(QM_FILES) + +install: $(QM_FILES) install -m 755 -d $(destdir)$(prefix)/share/xca - install -m 644 lang/xca_??.qm $(destdir)$(prefix)/share/xca || true + install -m 644 $(QM_FILES) $(destdir)$(prefix)/share/xca + +clean: + $(RM) $(QM_FILES) include $(TOPDIR)/Local.mak - diff --git a/lib/pki_crl.cpp b/lib/pki_crl.cpp index 10046a55..49d7391c 100644 --- a/lib/pki_crl.cpp +++ b/lib/pki_crl.cpp @@ -179,8 +179,11 @@ void pki_crl::addV3ext(const x509v3ext &e) void pki_crl::sign(pki_key *key, const EVP_MD *md) { + EVP_PKEY *pkey; if (!key || key->isPubKey()) return; - X509_CRL_sign(crl, key->key, md); + pkey = key->decryptKey(); + X509_CRL_sign(crl, pkey, md); + EVP_PKEY_free(pkey); openssl_error(); } @@ -252,7 +255,7 @@ bool pki_crl::verify(pki_key *key) { bool ret=false; if (crl && crl->crl && key) { - ret = (X509_CRL_verify(crl , key->key) == 1); + ret = (X509_CRL_verify(crl , key->getKey()) == 1); ign_openssl_error(); } return ret ; diff --git a/lib/pki_key.cpp b/lib/pki_key.cpp index cce4ec28..2bf10b3d 100644 --- a/lib/pki_key.cpp +++ b/lib/pki_key.cpp @@ -58,7 +58,7 @@ #include #include -char pki_key::passwd[40]="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; +char pki_key::passwd[40]={0,}; QPixmap *pki_key::icon[2]= { NULL, NULL }; @@ -73,6 +73,8 @@ void pki_key::init(int type) key = EVP_PKEY_new(); key->type = type; class_name = "pki_key"; + encKey = NULL; + encKey_len = 0; } void pki_key::incProgress(int a, int b, void *progress) @@ -81,9 +83,10 @@ void pki_key::incProgress(int a, int b, void *progress) ((QProgressDialog *)progress)->setProgress(++i); } -void pki_key::generate(int bits) +void pki_key::generate(int bits, int type) { - RSA *rsakey=NULL; + RSA *rsakey = NULL; + DSA *dsakey = NULL; QProgressDialog *progress = new QProgressDialog( qApp->tr("Please wait, Key generation is in progress"), qApp->tr("Cancel"),90, 0, 0, true); @@ -91,12 +94,20 @@ void pki_key::generate(int bits) progress->setProgress(0); progress->setCaption(XCA_TITLE); - rsakey = RSA_generate_key(bits, 0x10001, &incProgress, progress); + if (type == EVP_PKEY_RSA) { + rsakey = RSA_generate_key(bits, 0x10001, &incProgress, progress); + if (rsakey) EVP_PKEY_set1_RSA(key, rsakey); + } else if (type == EVP_PKEY_DSA) { + dsakey = DSA_generate_parameters(bits,NULL,0,NULL,NULL,&incProgress, progress); + DSA_generate_key(dsakey); + if(dsakey) EVP_PKEY_set1_DSA(key,dsakey); + } + progress->cancel(); delete progress; - EVP_PKEY_assign_RSA(key, rsakey); - openssl_error(); + openssl_error(); + encryptKey(); } pki_key::pki_key(const pki_key *pk) @@ -107,10 +118,15 @@ pki_key::pki_key(const pki_key *pk) if (pk == NULL) return; key->type = pk->key->type; if (key->type == EVP_PKEY_RSA) { + //rsakey = RSA_dup(pk->key->pkey.rsa); key->pkey.rsa=((RSA *)ASN1_dup( (int (*)())i2d_RSAPrivateKey, (char *(*)())d2i_RSAPrivateKey,(char *)pk->key->pkey.rsa)); } - // TODO add DSA support..... + if (key->type == EVP_PKEY_DSA) { + key->pkey.dsa=((DSA *)ASN1_dup( (int(*)())i2d_DSAPrivateKey, (char *(*)())d2i_DSAPrivateKey,(char *)pk->key->pkey.dsa)); + } + openssl_error(); + encryptKey(); } pki_key::pki_key(const QString name, int type ) @@ -136,9 +152,12 @@ void pki_key::fload(const QString fname) + "\n'" + fname + "'"); pem_password_cb *cb = &MainWindow::passRead; FILE *fp = fopen(fname.latin1(), "r"); - RSA *rsakey = NULL; + RSA *rsakey = NULL, *rsapub = NULL; + EVP_PKEY *evkey = NULL; + if (fp != NULL) { rsakey = PEM_read_RSAPrivateKey(fp, NULL, cb, &p); + if (!rsakey) { ign_openssl_error(); rewind(fp); @@ -147,23 +166,26 @@ void pki_key::fload(const QString fname) if (!rsakey) { ign_openssl_error(); rewind(fp); - rsakey = PEM_read_RSA_PUBKEY(fp, NULL, cb, &p); + rsapub = PEM_read_RSA_PUBKEY(fp, NULL, cb, &p); } - if (!rsakey) { + if (!rsapub) { ign_openssl_error(); rewind(fp); - rsakey = d2i_RSA_PUBKEY_fp(fp, NULL); + rsapub = d2i_RSA_PUBKEY_fp(fp, NULL); } - if (!rsakey) { + if (!rsapub) { ign_openssl_error(); rewind(fp); p.setTitle(tr("Password for PKCS#8 private key")); p.setDescription(tr("Please enter the password to decrypt the PKCS#8 private key.") + "\n'" + fname + "'"); - d2i_PKCS8PrivateKey_fp(fp, &key, cb, &p); + d2i_PKCS8PrivateKey_fp(fp, &evkey, cb, &p); } - else { - EVP_PKEY_assign_RSA(key, rsakey); + if (rsakey) { + encryptKey(); + } + else if (rsapub) { + EVP_PKEY_assign_RSA(key, rsapub); openssl_error(); } setIntName(rmslashdot(fname)); @@ -173,8 +195,37 @@ void pki_key::fload(const QString fname) fclose(fp); } - void pki_key::fromData(unsigned char *p, int size ) +{ + unsigned char *p1; + EVP_PKEY *pkey1; + int version, type; + + p1 = p; + pkey1 = key; + + version = intFromData(&p1); + if (version != 1) { // backward compatibility + oldFromData(p, size); + return; + } + if (key) + EVP_PKEY_free(key); + + type = intFromData(&p1); + + d2i_PublicKey(type, &pkey1, &p1, size); + openssl_error(); + + encKey_len = size - (p1-p) - (2*sizeof(int)); + if (encKey_len) { + encKey = (unsigned char *)OPENSSL_malloc(encKey_len); + memcpy(encKey, p1 ,encKey_len); + } + +} + +void pki_key::oldFromData(unsigned char *p, int size ) { unsigned char *sik, *pdec, *pdec1, *sik1; int outl, decsize; @@ -227,66 +278,124 @@ void pki_key::fromData(unsigned char *p, int size ) openssl_error(); } +EVP_PKEY *pki_key::decryptKey() +{ + unsigned char *p, *p1; + int outl, decsize; + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char ckey[EVP_MAX_KEY_LENGTH]; + + memset(iv, 0, EVP_MAX_IV_LENGTH); + RSA *rsakey; + EVP_PKEY *tmpkey; + EVP_CIPHER_CTX ctx; + const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); + p = (unsigned char *)OPENSSL_malloc(encKey_len); + p1 = p; + openssl_error(); + + memcpy(iv, encKey, 8); /* recover the iv */ + /* generate the key */ + EVP_BytesToKey(cipher, EVP_sha1(), iv, (unsigned char *)passwd, + strlen(passwd), 1, ckey,NULL); + /* we use sha1 as message digest, + * because an md5 version of the password is + * stored in the database... + */ + EVP_CIPHER_CTX_init (&ctx); + EVP_DecryptInit( &ctx, cipher, ckey, iv); + EVP_DecryptUpdate( &ctx, p , &outl, encKey + 8, encKey_len - 8 ); + decsize = outl; + EVP_DecryptFinal( &ctx, encKey + decsize , &outl ); + decsize += outl; + openssl_error(); + if (key->type == EVP_PKEY_RSA) { +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL + rsakey = d2i_RSAPrivateKey(NULL, (const unsigned char **)&p, decsize); +#else + rsakey = d2i_RSAPrivateKey(NULL, &p, decsize); +#endif + openssl_error(); + tmpkey = EVP_PKEY_new(); + if (rsakey) EVP_PKEY_assign_RSA(tmpkey, rsakey); + } + OPENSSL_free(p1); + EVP_CIPHER_CTX_cleanup(&ctx); + openssl_error(); + return tmpkey; +} unsigned char *pki_key::toData(int *size) { - unsigned char *p, *p1, *penc; - int outl, encsize=0; + unsigned char *p, *p1; + int pubsize; + + pubsize = i2d_PublicKey(key, NULL); + *size = pubsize + encKey_len + (2*sizeof(int)); + p = (unsigned char *)OPENSSL_malloc(*size); + openssl_error(); + p1 = p; + intToData(&p1, 1); + intToData(&p1, key->type); + i2d_PublicKey(key, &p1); + openssl_error(); + + memcpy(p1, encKey, encKey_len); + return p; +} + +void pki_key::encryptKey() +{ + int outl, keylen; + EVP_PKEY *pkey1 = NULL; EVP_CIPHER_CTX ctx; const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); - unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char iv[EVP_MAX_IV_LENGTH], *punenc, *punenc1; unsigned char ckey[EVP_MAX_KEY_LENGTH]; + + /* Prepare Encryption */ memset(iv, 0, EVP_MAX_IV_LENGTH); RAND_pseudo_bytes(iv,8); /* Generate a salt */ EVP_BytesToKey(cipher, EVP_sha1(), iv, (unsigned char *)passwd, - strlen(passwd), 1, ckey,NULL); + strlen(passwd), 1, ckey, NULL); EVP_CIPHER_CTX_init (&ctx); - EVP_EncryptInit( &ctx, cipher, ckey, iv); openssl_error(); - //if (key->type == EVP_PKEY_RSA) { - if (true) { - if (isPubKey()) { - *size = i2d_RSA_PUBKEY(key->pkey.rsa, NULL); - p = (unsigned char *)OPENSSL_malloc(*size); - openssl_error(); - penc = (unsigned char *)OPENSSL_malloc(*size + EVP_MAX_KEY_LENGTH + 8); - if (!penc) { - OPENSSL_free(p); - openssl_error(); - } - p1 = p; - memcpy(penc,iv,8); /* store the iv */ - i2d_RSA_PUBKEY(key->pkey.rsa, &p1); - EVP_EncryptUpdate( &ctx, penc + 8, &outl, p, *size ); - encsize = outl; - openssl_error(); - - } - else { - *size = i2d_RSAPrivateKey(key->pkey.rsa, NULL); - openssl_error(); - p = (unsigned char *)OPENSSL_malloc(*size); - openssl_error(); - penc = (unsigned char *)OPENSSL_malloc(*size + EVP_MAX_KEY_LENGTH + 8); - if (!penc) { - OPENSSL_free(p); - openssl_error(); - } - p1 = p; - memcpy(penc, iv, 8); /* store the iv */ - i2d_RSAPrivateKey(key->pkey.rsa, &p1); - EVP_EncryptUpdate( &ctx, penc + 8, &outl, p, *size ); /* store key right after the iv */ - encsize = outl; - openssl_error(); - } - } - EVP_EncryptFinal( &ctx, penc + encsize + 8, &outl ); - encsize += outl ; - OPENSSL_free(p); + + /* reserve space for unencrypted and encrypted key */ + keylen = i2d_PrivateKey(key, NULL); + encKey = (unsigned char *)OPENSSL_malloc(keylen + EVP_MAX_KEY_LENGTH + 8); + punenc = (unsigned char *)OPENSSL_malloc(keylen); + openssl_error(); + punenc1 = punenc; + memcpy(encKey, iv, 8); /* store the iv */ + /* copy the public part */ + i2d_PublicKey(key, &punenc1); + punenc1 = punenc; + d2i_PublicKey(key->type, &pkey1, &punenc1, keylen); + punenc1 = punenc; + openssl_error(); + i2d_PrivateKey(key, &punenc1); + + /* do the encryption */ + /* store key right after the iv */ + EVP_EncryptInit( &ctx, cipher, ckey, iv); + EVP_EncryptUpdate( &ctx, encKey + 8, &outl, punenc, keylen ); + encKey_len = outl; + EVP_EncryptFinal( &ctx, encKey + encKey_len + 8, &outl ); + encKey_len += outl + 8; + + /* Cleanup */ EVP_CIPHER_CTX_cleanup(&ctx); openssl_error(); - *size = encsize + 8; - return penc; + + /* convert rsa/dsa to Pubkey */ + /* punenc is big enough, because it held the privkey before. */ + EVP_PKEY_free(key); + key = pkey1; + openssl_error(); + + OPENSSL_free(punenc); + return; } @@ -295,6 +404,8 @@ pki_key::~pki_key() { if (key) EVP_PKEY_free(key); + if (encKey) + OPENSSL_free(encKey); } @@ -321,16 +432,16 @@ void pki_key::writeKey(const QString fname, const EVP_CIPHER *enc, writePublic(fname, PEM); return; } - FILE *fp = fopen(fname.latin1(),"w"); + FILE *fp = fopen(fname.latin1(), "w"); if (fp != NULL) { - if (key){ - if (PEM) - PEM_write_PrivateKey(fp, key, enc, NULL, 0, cb, &p); - else { - i2d_RSAPrivateKey_fp(fp, key->pkey.rsa); + if (key){ + if (PEM) { + PEM_write_PrivateKey(fp, key, enc, NULL, 0, cb, &p); + } else { + i2d_PrivateKey_fp(fp, key); } - openssl_error(); - } + openssl_error(); + } } else fopen_error(fname); fclose(fp); @@ -341,11 +452,11 @@ void pki_key::writePublic(const QString fname, bool PEM) { FILE *fp = fopen(fname.latin1(),"w"); if (fp != NULL) { - if (key->type == EVP_PKEY_RSA) { - if (PEM) - PEM_write_RSA_PUBKEY(fp, key->pkey.rsa); - else - i2d_RSA_PUBKEY_fp(fp, key->pkey.rsa); + if (key->type == EVP_PKEY_RSA) { + if (PEM) + PEM_write_PUBKEY(fp, key); + else + i2d_PUBKEY_fp(fp, key); openssl_error(); } } @@ -397,18 +508,32 @@ QString pki_key::privEx() { bool pki_key::compare(pki_base *ref) { pki_key *kref = (pki_key *)ref; - if (kref == NULL) return false; - if (kref->key == NULL) return false; - if (kref->key->pkey.rsa->n == NULL) return false; - if (key == NULL) return false; - if (key->pkey.rsa->n == NULL) return false; - if ( - BN_cmp(key->pkey.rsa->n, kref->key->pkey.rsa->n) || - BN_cmp(key->pkey.rsa->e, kref->key->pkey.rsa->e) - ){ - openssl_error(); - return false; - } + if(key->type==EVP_PKEY_RSA) { + if (kref==NULL || kref->key==NULL || kref->key->pkey.rsa->n==NULL) + return false; + if (key == NULL || key->pkey.rsa->n == NULL) + return false; + if ( + BN_cmp(key->pkey.rsa->n, kref->key->pkey.rsa->n) || + BN_cmp(key->pkey.rsa->e, kref->key->pkey.rsa->e) + ){ + openssl_error(); + return false; + } + } else if(key->type==EVP_PKEY_DSA) { + if(kref==NULL || kref->key==NULL || kref->key->pkey.dsa->p==NULL) + return false; + if(key==NULL || key->pkey.rsa->p==NULL) + return false; + if( + BN_cmp(key->pkey.dsa->q,kref->key->pkey.dsa->q) || + BN_cmp(key->pkey.dsa->g,kref->key->pkey.dsa->g) || + BN_cmp(key->pkey.dsa->pub_key,kref->key->pkey.dsa->pub_key) + ){ + openssl_error(); + return false; + } + } openssl_error(); return true; } @@ -416,20 +541,15 @@ bool pki_key::compare(pki_base *ref) bool pki_key::isPubKey() { - if (key == NULL) { - return false; + if (encKey_len == 0 || encKey == NULL) { + return true; } - if (key->pkey.rsa == 0) { - return false; - } - return (key->pkey.rsa->d == NULL); - + return false; } bool pki_key::isPrivKey() { return ! isPubKey(); - } int pki_key::verify() diff --git a/lib/pki_key.h b/lib/pki_key.h index ca19f367..5f753639 100644 --- a/lib/pki_key.h +++ b/lib/pki_key.h @@ -66,22 +66,23 @@ class pki_key: public pki_base { - friend class pki_x509req; - friend class pki_x509; - friend class pki_crl; protected: EVP_PKEY *key; - QString BN2QString(BIGNUM *bn); + unsigned char *encKey; + int encKey_len; int ucount; // usage counter + QString BN2QString(BIGNUM *bn); void init(int type = EVP_PKEY_RSA); static void incProgress(int a, int b, void *progress); + void encryptKey(); public: static QPixmap *icon[2]; static char passwd[MAX_PASS_LENGTH]; static void erasePasswd(); - void generate(int bits); + void generate(int bits, int type = EVP_PKEY_RSA); pki_key(const QString name = "", int type = EVP_PKEY_RSA); pki_key(EVP_PKEY *pkey); + EVP_PKEY *decryptKey(); // copy constructor pki_key::pki_key(const pki_key *pk); /* destructor */ @@ -89,6 +90,7 @@ class pki_key: public pki_base void fload(const QString fname); void fromData(unsigned char *p, int size); + void oldFromData(unsigned char *p, int size); unsigned char *toData(int *size); bool compare(pki_base *ref); QString length(); diff --git a/lib/pki_x509.cpp b/lib/pki_x509.cpp index 58130d8a..5ff24c10 100644 --- a/lib/pki_x509.cpp +++ b/lib/pki_x509.cpp @@ -248,11 +248,15 @@ bool pki_x509::hasSubAltName() void pki_x509::sign(pki_key *signkey, const EVP_MD *digest) { + EVP_PKEY *tkey; if (!signkey) { openssl_error("There is no key for signing !"); } - X509_sign(cert, signkey->key, digest); + tkey=signkey->decryptKey(); + X509_sign(cert, tkey, digest); + EVP_PKEY_free(tkey); openssl_error(); + } @@ -408,7 +412,7 @@ bool pki_x509::verify(pki_x509 *signer) return false; } pki_key *pkey = signer->getPubKey(); - int i = X509_verify(cert,pkey->key); + int i = X509_verify(cert,pkey->getKey()); ign_openssl_error(); if (pkey) delete(pkey); if (i>0) { diff --git a/lib/pki_x509req.cpp b/lib/pki_x509req.cpp index 10951246..0c147a5f 100644 --- a/lib/pki_x509req.cpp +++ b/lib/pki_x509req.cpp @@ -82,6 +82,7 @@ pki_x509req::~pki_x509req() void pki_x509req::createReq(pki_key *key, const x509name &dn, const EVP_MD *md) { + EVP_PKEY *privkey = NULL; if (key->isPubKey()) { openssl_error("key not valid"); return; @@ -91,8 +92,10 @@ void pki_x509req::createReq(pki_key *key, const x509name &dn, const EVP_MD *md) X509_REQ_set_pubkey(request, key->getKey()); setSubject(dn); openssl_error(); - X509_REQ_sign(request,key->getKey(), md); + privkey = key->decryptKey(); + X509_REQ_sign(request, privkey, md); openssl_error(); + EVP_PKEY_free(privkey); } void pki_x509req::fload(const QString fname)