00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include <qptrlist.h>
00023
#include <qcstring.h>
00024
#include <qstring.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
00042
#define sk_new kossl->sk_new
00043
#define sk_free kossl->sk_free
00044
#define sk_push kossl->sk_push
00045
#define sk_value kossl->sk_value
00046
#define sk_num kossl->sk_num
00047
#define BIO_ctrl kossl->BIO_ctrl
00048
00049
00050
#ifdef KSSL_HAVE_SSL
00051
static const char eot = 0;
00052
00053
class KSMIMECryptoPrivate {
00054
KOpenSSLProxy *kossl;
00055
00056
public:
00057 KSMIMECryptoPrivate(
KOpenSSLProxy *kossl);
00058
00059
00060 STACK_OF(X509) *certsToX509(
QPtrList<KSSLCertificate> &certs);
00061
00062 KSMIMECrypto::rc signMessage(BIO *clearText,
00063 BIO *cipherText,
00064
KSSLPKCS12 &privKey,
QPtrList<KSSLCertificate> &certs,
00065
bool detached);
00066
00067 KSMIMECrypto::rc encryptMessage(BIO *clearText,
00068 BIO *cipherText, KSMIMECrypto::algo algorithm,
00069
QPtrList<KSSLCertificate> &recip);
00070
00071 KSMIMECrypto::rc checkSignature(BIO *clearText,
00072 BIO *signature,
bool detached,
00073
QPtrList<KSSLCertificate> &recip);
00074
00075 KSMIMECrypto::rc decryptMessage(BIO *cipherText,
00076 BIO *clearText,
00077
KSSLPKCS12 &privKey);
00078
00079
void MemBIOToQByteArray(BIO *src,
QByteArray &dest);
00080
00081 KSMIMECrypto::rc sslErrToRc(
void);
00082 };
00083
00084
00085 KSMIMECryptoPrivate::KSMIMECryptoPrivate(
KOpenSSLProxy *kossl): kossl(kossl) {
00086 }
00087
00088
00089 STACK_OF(X509) *KSMIMECryptoPrivate::certsToX509(
QPtrList<KSSLCertificate> &certs) {
00090 STACK_OF(X509) *x509 = sk_new(NULL);
00091
KSSLCertificate *cert = certs.first();
00092
while(cert) {
00093 sk_X509_push(x509, cert->
getCert());
00094 cert = certs.next();
00095 }
00096
return x509;
00097 }
00098
00099
00100 KSMIMECrypto::rc KSMIMECryptoPrivate::signMessage(BIO *clearText,
00101 BIO *cipherText,
00102
KSSLPKCS12 &privKey,
QPtrList<KSSLCertificate> &certs,
00103
bool detached) {
00104
00105 STACK_OF(X509) *other = NULL;
00106 KSMIMECrypto::rc rc;
00107
int flags = detached?PKCS7_DETACHED:0;
00108
00109
if (certs.count()) other = certsToX509(certs);
00110
00111 PKCS7 *p7 = kossl->PKCS7_sign(privKey.
getCertificate()->
getCert(), privKey.
getPrivateKey(),
00112 other, clearText, flags);
00113
00114
if (other) sk_X509_free(other);
00115
00116
if (!p7)
return sslErrToRc();
00117
00118
if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
00119 rc = KSMIMECrypto::KSC_R_OK;
00120 }
else {
00121 rc = sslErrToRc();
00122 }
00123
00124 kossl->PKCS7_free(p7);
00125
00126
return rc;
00127 }
00128
00129 KSMIMECrypto::rc KSMIMECryptoPrivate::encryptMessage(BIO *clearText,
00130 BIO *cipherText, KSMIMECrypto::algo algorithm,
00131
QPtrList<KSSLCertificate> &recip) {
00132 EVP_CIPHER *cipher = NULL;
00133 KSMIMECrypto::rc rc;
00134
switch(algorithm) {
00135
case KSMIMECrypto::KSC_C_DES3_CBC:
00136 cipher = kossl->EVP_des_ede3_cbc();
00137
break;
00138
case KSMIMECrypto::KSC_C_RC2_CBC_128:
00139 cipher = kossl->EVP_rc2_cbc();
00140
break;
00141
case KSMIMECrypto::KSC_C_RC2_CBC_64:
00142 cipher = kossl->EVP_rc2_64_cbc();
00143
break;
00144
case KSMIMECrypto::KSC_C_DES_CBC:
00145 cipher = kossl->EVP_des_cbc();
00146
break;
00147
case KSMIMECrypto::KSC_C_RC2_CBC_40:
00148 cipher = kossl->EVP_rc2_40_cbc();
00149
break;
00150 }
00151
if (!cipher)
return KSMIMECrypto::KSC_R_NOCIPHER;
00152
00153 STACK_OF(X509) *certs = certsToX509(recip);
00154
00155 PKCS7 *p7 = kossl->PKCS7_encrypt(certs, clearText, cipher, 0);
00156
00157 sk_X509_free(certs);
00158
00159
if (!p7)
return sslErrToRc();
00160
00161
if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
00162 rc = KSMIMECrypto::KSC_R_OK;
00163 }
else {
00164 rc = sslErrToRc();
00165 }
00166
00167 kossl->PKCS7_free(p7);
00168
00169
return rc;
00170 }
00171
00172
00173 KSMIMECrypto::rc KSMIMECryptoPrivate::checkSignature(BIO *clearText,
00174 BIO *signature,
bool detached,
00175
QPtrList<KSSLCertificate> &recip) {
00176
00177 PKCS7 *p7 = kossl->d2i_PKCS7_bio(signature, NULL);
00178 KSMIMECrypto::rc rc = KSMIMECrypto::KSC_R_OTHER;
00179
00180
if (!p7)
return sslErrToRc();
00181
00182 BIO *in;
00183 BIO *out;
00184
if (detached) {
00185 in = clearText;
00186 out = NULL;
00187 }
else {
00188 in = NULL;
00189 out = clearText;
00190 }
00191
00192 X509_STORE *dummystore = kossl->X509_STORE_new();
00193
if (kossl->PKCS7_verify(p7, NULL, dummystore, in, out, PKCS7_NOVERIFY)) {
00194 STACK_OF(X509) *signers = kossl->PKCS7_get0_signers(p7, 0, PKCS7_NOVERIFY);
00195
int num = sk_X509_num(signers);
00196
00197
for(
int n=0; n<num; n++) {
00198
KSSLCertificate *signer =
KSSLCertificate::fromX509(sk_X509_value(signers, n));
00199 recip.append(signer);
00200 }
00201
00202 sk_X509_free(signers);
00203 rc = KSMIMECrypto::KSC_R_OK;
00204 }
else {
00205 rc = sslErrToRc();
00206 }
00207
00208 kossl->X509_STORE_free(dummystore);
00209 kossl->PKCS7_free(p7);
00210
00211
return rc;
00212 }
00213
00214
00215 KSMIMECrypto::rc KSMIMECryptoPrivate::decryptMessage(BIO *cipherText,
00216 BIO *clearText,
00217
KSSLPKCS12 &privKey) {
00218
00219 PKCS7 *p7 = kossl->d2i_PKCS7_bio(cipherText, NULL);
00220 KSMIMECrypto::rc rc;
00221
00222
if (!p7)
return sslErrToRc();
00223
00224
if (kossl->PKCS7_decrypt(p7, privKey.
getPrivateKey(), privKey.
getCertificate()->
getCert(),
00225 clearText, 0)) {
00226 rc = KSMIMECrypto::KSC_R_OK;
00227 }
else {
00228 rc = sslErrToRc();
00229 }
00230
00231 kossl->PKCS7_free(p7);
00232
00233
return rc;
00234 }
00235
00236
00237
void KSMIMECryptoPrivate::MemBIOToQByteArray(BIO *src,
QByteArray &dest) {
00238
char *buf;
00239
long len = BIO_get_mem_data(src, &buf);
00240 dest.assign(buf, len);
00241
00242
00243
00244
00245 reinterpret_cast<BUF_MEM *>(src->ptr)->data = NULL;
00246 }
00247
00248
00249 KSMIMECrypto::rc KSMIMECryptoPrivate::sslErrToRc(
void) {
00250
unsigned long cerr = kossl->ERR_get_error();
00251
00252
00253
00254
switch(ERR_GET_REASON(cerr)) {
00255
case ERR_R_MALLOC_FAILURE:
00256
return KSMIMECrypto::KSC_R_NOMEM;
00257 }
00258
00259
switch(ERR_GET_LIB(cerr)) {
00260
case ERR_LIB_PKCS7:
00261
switch(ERR_GET_REASON(cerr)) {
00262
case PKCS7_R_WRONG_CONTENT_TYPE:
00263
case PKCS7_R_NO_CONTENT:
00264
case PKCS7_R_NO_SIGNATURES_ON_DATA:
00265
return KSMIMECrypto::KSC_R_FORMAT;
00266
break;
00267
case PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:
00268
case PKCS7_R_DECRYPT_ERROR:
00269
return KSMIMECrypto::KSC_R_WRONGKEY;
00270
break;
00271
case PKCS7_R_DIGEST_FAILURE:
00272
return KSMIMECrypto::KSC_R_VERIFY;
00273
default:
00274
break;
00275 }
00276
break;
00277
default:
00278
break;
00279 }
00280
00281
kdDebug(7029) <<
"KSMIMECrypto: uncaught error " <<ERR_GET_LIB(cerr)
00282 <<
" " <<ERR_GET_REASON(cerr) <<
endl;
00283
return KSMIMECrypto::KSC_R_OTHER;
00284 }
00285
#endif
00286
00287
00288 KSMIMECrypto::KSMIMECrypto() {
00289
#ifdef KSSL_HAVE_SSL
00290
kossl =
KOpenSSLProxy::self();
00291 priv =
new KSMIMECryptoPrivate(kossl);
00292
if (!kossl->hasLibCrypto()) kossl = 0L;
00293
#else
00294
kossl = 0L;
00295
#endif
00296
}
00297
00298
00299 KSMIMECrypto::~KSMIMECrypto() {
00300
#ifdef KSSL_HAVE_SSL
00301
delete priv;
00302
#endif
00303
}
00304
00305
00306 KSMIMECrypto::rc KSMIMECrypto::signMessage(
const QCString &clearText,
00307
QByteArray &cipherText,
00308
const KSSLPKCS12 &privKey,
00309
const QPtrList<KSSLCertificate> &certs,
00310
bool detached) {
00311
#ifdef KSSL_HAVE_SSL
00312
if (!kossl)
return KSC_R_NO_SSL;
00313 BIO *in = kossl->BIO_new_mem_buf((
char *)clearText.data(), clearText.size());
00314 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
00315
00316 rc rc = priv->signMessage(in, out,
00317 const_cast<KSSLPKCS12 &>(privKey),
00318
const_cast<
QPtrList<KSSLCertificate> &>(certs),
00319 detached);
00320
00321
if (!rc) priv->MemBIOToQByteArray(out, cipherText);
00322
00323 kossl->BIO_free(out);
00324 kossl->BIO_free(in);
00325
00326
return rc;
00327
#else
00328
return KSC_R_NO_SSL;
00329
#endif
00330
}
00331
00332
00333 KSMIMECrypto::rc KSMIMECrypto::checkDetachedSignature(
const QCString &clearText,
00334
const QByteArray &signature,
00335
QPtrList<KSSLCertificate> &foundCerts) {
00336
#ifdef KSSL_HAVE_SSL
00337
if (!kossl)
return KSC_R_NO_SSL;
00338 BIO *txt = kossl->BIO_new_mem_buf((
char *)clearText.data(), clearText.length());
00339 BIO *sig = kossl->BIO_new_mem_buf((
char *)signature.data(), signature.size());
00340
00341 rc rc = priv->checkSignature(txt, sig,
true, foundCerts);
00342
00343 kossl->BIO_free(sig);
00344 kossl->BIO_free(txt);
00345
00346
return rc;
00347
#else
00348
return KSC_R_NO_SSL;
00349
#endif
00350
}
00351
00352
00353 KSMIMECrypto::rc KSMIMECrypto::checkOpaqueSignature(
const QByteArray &signedText,
00354
QCString &clearText,
00355
QPtrList<KSSLCertificate> &foundCerts) {
00356
#ifdef KSSL_HAVE_SSL
00357
if (!kossl)
return KSC_R_NO_SSL;
00358
00359 BIO *in = kossl->BIO_new_mem_buf((
char *)signedText.data(), signedText.size());
00360 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
00361
00362 rc rc = priv->checkSignature(out, in,
false, foundCerts);
00363
00364 kossl->BIO_write(out, &eot, 1);
00365 priv->MemBIOToQByteArray(out, clearText);
00366
00367 kossl->BIO_free(out);
00368 kossl->BIO_free(in);
00369
00370
return rc;
00371
#else
00372
return KSC_R_NO_SSL;
00373
#endif
00374
}
00375
00376
00377 KSMIMECrypto::rc KSMIMECrypto::encryptMessage(
const QCString &clearText,
00378
QByteArray &cipherText,
00379 algo algorithm,
00380
const QPtrList<KSSLCertificate> &recip) {
00381
#ifdef KSSL_HAVE_SSL
00382
if (!kossl)
return KSC_R_NO_SSL;
00383
00384 BIO *in = kossl->BIO_new_mem_buf((
char *)clearText.data(), clearText.size());
00385 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
00386
00387 rc rc = priv->encryptMessage(in,out,algorithm,
00388
const_cast<
QPtrList<KSSLCertificate> &>(recip));
00389
00390
if (!rc) priv->MemBIOToQByteArray(out, cipherText);
00391
00392 kossl->BIO_free(out);
00393 kossl->BIO_free(in);
00394
00395
return rc;
00396
#else
00397
return KSC_R_NO_SSL;
00398
#endif
00399
}
00400
00401
00402 KSMIMECrypto::rc KSMIMECrypto::decryptMessage(
const QByteArray &cipherText,
00403
QCString &clearText,
00404
const KSSLPKCS12 &privKey) {
00405
#ifdef KSSL_HAVE_SSL
00406
if (!kossl)
return KSC_R_NO_SSL;
00407
00408 BIO *in = kossl->BIO_new_mem_buf((
char *)cipherText.data(), cipherText.size());
00409 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
00410
00411 rc rc = priv->decryptMessage(in,out,
00412 const_cast<KSSLPKCS12 &>(privKey));
00413
00414 kossl->BIO_write(out, &eot, 1);
00415 priv->MemBIOToQByteArray(out, clearText);
00416
00417 kossl->BIO_free(out);
00418 kossl->BIO_free(in);
00419
00420
return rc;
00421
#else
00422
return KSC_R_NO_SSL;
00423
#endif
00424
}