• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/kssl
 

tdeio/kssl

ksmimecrypto.cc

00001 /* This file is part of the KDE project
00002  *
00003  * Copyright (C) 2003 Stefan Rompf <sux@loplof.de>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public License
00016  * along with this library; see the file COPYING.LIB.  If not, write to
00017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 
00021 
00022 #include <tqptrlist.h>
00023 #include <tqcstring.h>
00024 #include <tqstring.h>
00025 #include <kdebug.h>
00026 
00027 #include "kopenssl.h"
00028 #include "ksslcertificate.h"
00029 #include "ksslpkcs12.h"
00030 #include "ksmimecrypto.h"
00031 
00032 // this hack provided by Malte Starostik to avoid glibc/openssl bug
00033 // on some systems
00034 #ifdef KSSL_HAVE_SSL
00035 #define crypt _openssl_crypt
00036 #include <openssl/err.h>
00037 #undef crypt
00038 #endif
00039 
00040 
00041 #ifdef KSSL_HAVE_SSL
00042 static const char eot = 0;
00043 
00044 class KSMIMECryptoPrivate {
00045     KOpenSSLProxy *kossl;
00046 
00047 public:
00048     KSMIMECryptoPrivate(KOpenSSLProxy *kossl);
00049 
00050 
00051     STACK_OF(X509) *certsToX509(TQPtrList<KSSLCertificate> &certs);
00052 
00053     KSMIMECrypto::rc signMessage(BIO *clearText,
00054                  BIO *cipherText,
00055                  KSSLPKCS12 &privKey, TQPtrList<KSSLCertificate> &certs,
00056                  bool detached);
00057 
00058     KSMIMECrypto::rc encryptMessage(BIO *clearText,
00059                     BIO *cipherText, KSMIMECrypto::algo algorithm,
00060                     TQPtrList<KSSLCertificate> &recip);
00061 
00062     KSMIMECrypto::rc checkSignature(BIO *clearText,
00063                     BIO *signature, bool detached,
00064                     TQPtrList<KSSLCertificate> &recip);
00065     
00066     KSMIMECrypto::rc decryptMessage(BIO *cipherText,
00067                     BIO *clearText,
00068                     KSSLPKCS12 &privKey);
00069     
00070     void MemBIOToQByteArray(BIO *src, TQByteArray &dest);
00071 
00072     KSMIMECrypto::rc sslErrToRc(void);
00073 };
00074 
00075 
00076 KSMIMECryptoPrivate::KSMIMECryptoPrivate(KOpenSSLProxy *kossl): kossl(kossl) {
00077 }
00078 
00079 
00080 STACK_OF(X509) *KSMIMECryptoPrivate::certsToX509(TQPtrList<KSSLCertificate> &certs) {
00081     STACK_OF(X509) *x509 = reinterpret_cast<STACK_OF(X509)*>(kossl->OPENSSL_sk_new(NULL));
00082     KSSLCertificate *cert = certs.first();
00083     while(cert) {
00084     kossl->OPENSSL_sk_push(x509, cert->getCert());
00085     cert = certs.next();
00086     }
00087     return x509;
00088 }
00089 
00090 
00091 KSMIMECrypto::rc KSMIMECryptoPrivate::signMessage(BIO *clearText,
00092                           BIO *cipherText,
00093                           KSSLPKCS12 &privKey, TQPtrList<KSSLCertificate> &certs,
00094                           bool detached) {
00095 
00096     STACK_OF(X509) *other = NULL;
00097     KSMIMECrypto::rc rc;
00098     int flags = detached?PKCS7_DETACHED:0;
00099 
00100     if (certs.count()) other = certsToX509(certs);
00101 
00102     PKCS7 *p7 = kossl->PKCS7_sign(privKey.getCertificate()->getCert(), privKey.getPrivateKey(),
00103                   other, clearText, flags);
00104 
00105     if (other) kossl->OPENSSL_sk_free(other);
00106 
00107     if (!p7) return sslErrToRc();
00108 
00109     if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
00110     rc = KSMIMECrypto::KSC_R_OK;
00111     } else {
00112     rc = sslErrToRc();
00113     }
00114 
00115     kossl->PKCS7_free(p7);
00116 
00117     return rc;
00118 }
00119 
00120 KSMIMECrypto::rc KSMIMECryptoPrivate::encryptMessage(BIO *clearText,
00121                              BIO *cipherText, KSMIMECrypto::algo algorithm,
00122                              TQPtrList<KSSLCertificate> &recip) {
00123     EVP_CIPHER *cipher = NULL;
00124     KSMIMECrypto::rc rc;
00125     switch(algorithm) {
00126     case KSMIMECrypto::KSC_C_DES3_CBC:
00127         cipher = kossl->EVP_des_ede3_cbc();
00128         break;
00129     case KSMIMECrypto::KSC_C_RC2_CBC_128:
00130         cipher = kossl->EVP_rc2_cbc();
00131         break;
00132     case KSMIMECrypto::KSC_C_RC2_CBC_64:
00133         cipher = kossl->EVP_rc2_64_cbc();
00134         break;
00135     case KSMIMECrypto::KSC_C_DES_CBC:
00136         cipher = kossl->EVP_des_cbc();
00137         break;
00138     case KSMIMECrypto::KSC_C_RC2_CBC_40:
00139         cipher = kossl->EVP_rc2_40_cbc();
00140         break;
00141     }
00142     if (!cipher) return KSMIMECrypto::KSC_R_NOCIPHER;
00143 
00144     STACK_OF(X509) *certs = certsToX509(recip);
00145 
00146     PKCS7 *p7 = kossl->PKCS7_encrypt(certs, clearText, cipher, 0);
00147 
00148     kossl->OPENSSL_sk_free(certs);
00149 
00150     if (!p7) return sslErrToRc();
00151 
00152     if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
00153     rc = KSMIMECrypto::KSC_R_OK;
00154     } else {
00155     rc = sslErrToRc();
00156     }
00157 
00158     kossl->PKCS7_free(p7);
00159 
00160     return rc;
00161 }
00162 
00163 
00164 KSMIMECrypto::rc KSMIMECryptoPrivate::checkSignature(BIO *clearText,
00165                              BIO *signature, bool detached,
00166                              TQPtrList<KSSLCertificate> &recip) {
00167     
00168     PKCS7 *p7 = kossl->d2i_PKCS7_bio(signature, NULL);
00169     KSMIMECrypto::rc rc = KSMIMECrypto::KSC_R_OTHER;
00170 
00171     if (!p7) return sslErrToRc();
00172 
00173     BIO *in;
00174     BIO *out;
00175     if (detached) {
00176     in = clearText;
00177     out = NULL;
00178     } else {
00179     in = NULL;
00180     out = clearText;
00181     }
00182 
00183     X509_STORE *dummystore = kossl->X509_STORE_new();
00184     if (kossl->PKCS7_verify(p7, NULL, dummystore, in, out, PKCS7_NOVERIFY)) {
00185     STACK_OF(X509) *signers = kossl->PKCS7_get0_signers(p7, 0, PKCS7_NOVERIFY);
00186     int num = kossl->OPENSSL_sk_num(signers);
00187 
00188     for(int n=0; n<num; n++) {
00189         KSSLCertificate *signer = KSSLCertificate::fromX509(reinterpret_cast<X509*>(kossl->OPENSSL_sk_value(signers, n)));
00190         recip.append(signer);
00191     }
00192 
00193     kossl->OPENSSL_sk_free(signers);
00194     rc = KSMIMECrypto::KSC_R_OK;
00195     } else {
00196     rc = sslErrToRc();
00197     }
00198 
00199     kossl->X509_STORE_free(dummystore);
00200     kossl->PKCS7_free(p7);
00201 
00202     return rc;
00203 }
00204 
00205 
00206 KSMIMECrypto::rc KSMIMECryptoPrivate::decryptMessage(BIO *cipherText,
00207                              BIO *clearText,
00208                              KSSLPKCS12 &privKey) {
00209     
00210     PKCS7 *p7 = kossl->d2i_PKCS7_bio(cipherText, NULL);
00211     KSMIMECrypto::rc rc;
00212 
00213     if (!p7) return sslErrToRc();
00214 
00215     if (kossl->PKCS7_decrypt(p7, privKey.getPrivateKey(), privKey.getCertificate()->getCert(), 
00216                  clearText, 0)) {
00217     rc = KSMIMECrypto::KSC_R_OK;
00218     } else {
00219     rc = sslErrToRc();
00220     }
00221 
00222     kossl->PKCS7_free(p7);
00223 
00224     return rc;
00225 }
00226 
00227 
00228 void KSMIMECryptoPrivate::MemBIOToQByteArray(BIO *src, TQByteArray &dest) {
00229     char *buf;
00230     long len = kossl->BIO_get_mem_data(src, &buf);
00231     dest.assign(buf, len);
00232     /* Now this goes quite a bit into openssl internals.
00233        We assume that openssl uses malloc() (it does in
00234        default config) and rip out the buffer.
00235     */
00236     void *ptr = kossl->BIO_get_data(src);
00237     reinterpret_cast<BUF_MEM *>(ptr)->data = NULL;
00238 }
00239 
00240     
00241 KSMIMECrypto::rc KSMIMECryptoPrivate::sslErrToRc(void) {
00242     unsigned long cerr = kossl->ERR_get_error();
00243 
00244     // To be completed and possibly fixed
00245 
00246     switch(ERR_GET_REASON(cerr)) {
00247     case ERR_R_MALLOC_FAILURE:
00248         return KSMIMECrypto::KSC_R_NOMEM;
00249     }
00250 
00251     switch(ERR_GET_LIB(cerr)) {
00252     case ERR_LIB_PKCS7:
00253         switch(ERR_GET_REASON(cerr)) {  
00254         case PKCS7_R_WRONG_CONTENT_TYPE:
00255         case PKCS7_R_NO_CONTENT:
00256         case PKCS7_R_NO_SIGNATURES_ON_DATA:
00257             return KSMIMECrypto::KSC_R_FORMAT;
00258             break;
00259         case PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:
00260         case PKCS7_R_DECRYPT_ERROR: // Hmm?
00261             return KSMIMECrypto::KSC_R_WRONGKEY;
00262             break;
00263         case PKCS7_R_DIGEST_FAILURE:
00264             return KSMIMECrypto::KSC_R_VERIFY;
00265         default:
00266             break;
00267         }
00268         break;
00269     default:
00270         break;
00271     }
00272 
00273     kdDebug(7029) <<"KSMIMECrypto: uncaught error " <<ERR_GET_LIB(cerr)
00274           <<" " <<ERR_GET_REASON(cerr) <<endl;
00275     return KSMIMECrypto::KSC_R_OTHER;
00276 }    
00277 #endif
00278 
00279 
00280 KSMIMECrypto::KSMIMECrypto() {
00281 #ifdef KSSL_HAVE_SSL
00282     kossl = KOpenSSLProxy::self();
00283     priv = new KSMIMECryptoPrivate(kossl);
00284     if (!kossl->hasLibCrypto()) kossl = 0L;
00285 #else
00286     kossl = 0L;
00287 #endif
00288 }
00289 
00290 
00291 KSMIMECrypto::~KSMIMECrypto() {
00292 #ifdef KSSL_HAVE_SSL
00293     delete priv;
00294 #endif
00295 }
00296 
00297 
00298 KSMIMECrypto::rc KSMIMECrypto::signMessage(const TQCString &clearText,
00299                        TQByteArray &cipherText,
00300                        const KSSLPKCS12 &privKey,
00301                        const TQPtrList<KSSLCertificate> &certs,
00302                        bool detached) {
00303 #ifdef KSSL_HAVE_SSL
00304     if (!kossl) return KSC_R_NO_SSL;
00305     BIO *in = kossl->BIO_new_mem_buf((char *)clearText.data(), clearText.size());
00306     BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
00307 
00308     rc rc = priv->signMessage(in, out,
00309                   const_cast<KSSLPKCS12 &>(privKey),
00310                   const_cast<TQPtrList<KSSLCertificate> &>(certs),
00311                   detached);
00312 
00313     if (!rc) priv->MemBIOToQByteArray(out, cipherText);
00314 
00315     kossl->BIO_free(out);
00316     kossl->BIO_free(in);
00317 
00318     return rc;
00319 #else
00320     return KSC_R_NO_SSL;
00321 #endif
00322 }
00323 
00324 
00325 KSMIMECrypto::rc KSMIMECrypto::checkDetachedSignature(const TQCString &clearText,
00326                               const TQByteArray &signature,
00327                               TQPtrList<KSSLCertificate> &foundCerts) {
00328 #ifdef KSSL_HAVE_SSL
00329     if (!kossl) return KSC_R_NO_SSL;
00330     BIO *txt = kossl->BIO_new_mem_buf((char *)clearText.data(), clearText.length());
00331     BIO *sig = kossl->BIO_new_mem_buf((char *)signature.data(), signature.size());
00332 
00333     rc rc = priv->checkSignature(txt, sig, true, foundCerts);
00334 
00335     kossl->BIO_free(sig);
00336     kossl->BIO_free(txt);
00337 
00338     return rc;
00339 #else
00340     return KSC_R_NO_SSL;
00341 #endif
00342 }
00343 
00344 
00345 KSMIMECrypto::rc KSMIMECrypto::checkOpaqueSignature(const TQByteArray &signedText,
00346                             TQCString &clearText,
00347                             TQPtrList<KSSLCertificate> &foundCerts) {
00348 #ifdef KSSL_HAVE_SSL
00349     if (!kossl) return KSC_R_NO_SSL;
00350 
00351     BIO *in = kossl->BIO_new_mem_buf((char *)signedText.data(), signedText.size());
00352     BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
00353    
00354     rc rc = priv->checkSignature(out, in, false, foundCerts);
00355 
00356     kossl->BIO_write(out, &eot, 1);
00357     priv->MemBIOToQByteArray(out, clearText);
00358 
00359     kossl->BIO_free(out);
00360     kossl->BIO_free(in);
00361 
00362     return rc;
00363 #else
00364     return KSC_R_NO_SSL;
00365 #endif
00366 }
00367 
00368 
00369 KSMIMECrypto::rc KSMIMECrypto::encryptMessage(const TQCString &clearText,
00370                           TQByteArray &cipherText,
00371                           algo algorithm,
00372                           const TQPtrList<KSSLCertificate> &recip) {
00373 #ifdef KSSL_HAVE_SSL
00374     if (!kossl) return KSC_R_NO_SSL;
00375 
00376     BIO *in = kossl->BIO_new_mem_buf((char *)clearText.data(), clearText.size());
00377     BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
00378 
00379     rc rc = priv->encryptMessage(in,out,algorithm,
00380                  const_cast< TQPtrList<KSSLCertificate> &>(recip));
00381 
00382     if (!rc) priv->MemBIOToQByteArray(out, cipherText);
00383 
00384     kossl->BIO_free(out);
00385     kossl->BIO_free(in);
00386 
00387     return rc;
00388 #else
00389     return KSC_R_NO_SSL;
00390 #endif
00391 }
00392 
00393 
00394 KSMIMECrypto::rc KSMIMECrypto::decryptMessage(const TQByteArray &cipherText,
00395                           TQCString &clearText,
00396                           const KSSLPKCS12 &privKey) {
00397 #ifdef KSSL_HAVE_SSL
00398     if (!kossl) return KSC_R_NO_SSL;
00399 
00400     BIO *in = kossl->BIO_new_mem_buf((char *)cipherText.data(), cipherText.size());
00401     BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
00402 
00403     rc rc = priv->decryptMessage(in,out,
00404                  const_cast<KSSLPKCS12 &>(privKey));
00405 
00406     kossl->BIO_write(out, &eot, 1);
00407     priv->MemBIOToQByteArray(out, clearText);
00408 
00409     kossl->BIO_free(out);
00410     kossl->BIO_free(in);
00411 
00412     return rc;
00413 #else
00414     return KSC_R_NO_SSL;
00415 #endif
00416 }
00417 

tdeio/kssl

Skip menu "tdeio/kssl"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

tdeio/kssl

Skip menu "tdeio/kssl"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/kssl by doxygen 1.7.1
This website is maintained by Timothy Pearson.