00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00033
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
00233
00234
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
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:
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