23 #include <QtCore/QList>
24 #include <QtCore/QString>
34 #define crypt _openssl_crypt
35 #include <openssl/err.h>
41 #define sk_new kossl->sk_new
42 #define sk_free kossl->sk_free
43 #define sk_push kossl->sk_push
44 #define sk_value kossl->sk_value
45 #define sk_num kossl->sk_num
46 #define BIO_ctrl kossl->BIO_ctrl
50 static const char eot = 0;
52 class KSMIMECryptoPrivate {
59 STACK_OF(X509) *certsToX509(
const QList<KSSLCertificate *> &certs);
63 KSSLPKCS12 &privKey, QList<KSSLCertificate *> &certs,
68 QList<KSSLCertificate *> &recip);
71 BIO *signature,
bool detached,
72 QList<KSSLCertificate *> &recip);
78 void MemBIOToQByteArray(BIO *src, QByteArray &dest);
84 KSMIMECryptoPrivate::KSMIMECryptoPrivate(
KOpenSSLProxy *kossl): kossl(kossl) {
88 STACK_OF(X509) *KSMIMECryptoPrivate::certsToX509(
const QList<KSSLCertificate *> &certs) {
91 sk_X509_push(x509, cert->
getCert());
99 KSSLPKCS12 &privKey, QList<KSSLCertificate *> &certs,
104 int flags = detached?PKCS7_DETACHED:0;
106 if (certs.count()) other = certsToX509(certs);
109 other, clearText, flags);
111 if (other) sk_X509_free(other);
113 if (!p7)
return sslErrToRc();
115 if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
121 kossl->PKCS7_free(p7);
128 QList<KSSLCertificate *> &recip) {
129 EVP_CIPHER *cipher = NULL;
133 cipher = kossl->EVP_des_ede3_cbc();
136 cipher = kossl->EVP_rc2_cbc();
139 cipher = kossl->EVP_rc2_64_cbc();
142 cipher = kossl->EVP_des_cbc();
145 cipher = kossl->EVP_rc2_40_cbc();
150 STACK_OF(X509) *certs = certsToX509(recip);
152 PKCS7 *p7 = kossl->PKCS7_encrypt(certs, clearText, cipher, 0);
156 if (!p7)
return sslErrToRc();
158 if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
164 kossl->PKCS7_free(p7);
171 BIO *signature,
bool detached,
172 QList<KSSLCertificate *> &recip) {
174 PKCS7 *p7 = kossl->d2i_PKCS7_bio(signature, NULL);
177 if (!p7)
return sslErrToRc();
189 X509_STORE *dummystore = kossl->X509_STORE_new();
190 if (kossl->PKCS7_verify(p7, NULL, dummystore, in, out, PKCS7_NOVERIFY)) {
191 STACK_OF(X509) *signers = kossl->PKCS7_get0_signers(p7, 0, PKCS7_NOVERIFY);
192 int num = sk_X509_num(signers);
194 for(
int n=0; n<num; n++) {
196 recip.append(signer);
199 sk_X509_free(signers);
205 kossl->X509_STORE_free(dummystore);
206 kossl->PKCS7_free(p7);
216 PKCS7 *p7 = kossl->d2i_PKCS7_bio(cipherText, NULL);
219 if (!p7)
return sslErrToRc();
228 kossl->PKCS7_free(p7);
234 void KSMIMECryptoPrivate::MemBIOToQByteArray(BIO *src, QByteArray &dest) {
236 long len = BIO_get_mem_data(src, &buf);
237 dest = QByteArray(buf, len);
242 reinterpret_cast<BUF_MEM *
>(src->ptr)->data = NULL;
247 unsigned long cerr = kossl->ERR_get_error();
251 switch(ERR_GET_REASON(cerr)) {
252 case ERR_R_MALLOC_FAILURE:
256 switch(ERR_GET_LIB(cerr)) {
258 switch(ERR_GET_REASON(cerr)) {
259 case PKCS7_R_WRONG_CONTENT_TYPE:
260 case PKCS7_R_NO_CONTENT:
261 case PKCS7_R_NO_SIGNATURES_ON_DATA:
264 case PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:
265 case PKCS7_R_DECRYPT_ERROR:
268 case PKCS7_R_DIGEST_FAILURE:
278 kDebug(7029) <<
"KSMIMECrypto: uncaught error " <<ERR_GET_LIB(cerr)
279 <<
" " <<ERR_GET_REASON(cerr) <<endl;
288 priv =
new KSMIMECryptoPrivate(kossl);
305 QByteArray &cipherText,
307 const QList<KSSLCertificate *> &certs,
311 BIO *in = kossl->BIO_new_mem_buf((
char *)clearText.data(), clearText.size());
312 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
314 rc rc = priv->signMessage(in, out,
315 const_cast<KSSLPKCS12 &>(privKey),
316 const_cast<QList<KSSLCertificate *> &
>(certs),
319 if (!rc) priv->MemBIOToQByteArray(out, cipherText);
321 kossl->BIO_free(out);
332 const QByteArray &signature,
333 QList<KSSLCertificate *> &foundCerts) {
336 BIO *txt = kossl->BIO_new_mem_buf((
char *)clearText.data(), clearText.length());
337 BIO *sig = kossl->BIO_new_mem_buf((
char *)signature.data(), signature.size());
339 rc rc = priv->checkSignature(txt, sig,
true, foundCerts);
341 kossl->BIO_free(sig);
342 kossl->BIO_free(txt);
352 QByteArray &clearText,
353 QList<KSSLCertificate *> &foundCerts) {
357 BIO *in = kossl->BIO_new_mem_buf((
char *)signedText.data(), signedText.size());
358 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
360 rc rc = priv->checkSignature(out, in,
false, foundCerts);
362 kossl->BIO_write(out, &eot, 1);
363 priv->MemBIOToQByteArray(out, clearText);
365 kossl->BIO_free(out);
376 QByteArray &cipherText,
378 const QList<KSSLCertificate *> &recip) {
382 BIO *in = kossl->BIO_new_mem_buf((
char *)clearText.data(), clearText.size());
383 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
385 rc rc = priv->encryptMessage(in,out,algorithm,
386 const_cast< QList<KSSLCertificate *> &
>(recip));
388 if (!rc) priv->MemBIOToQByteArray(out, cipherText);
390 kossl->BIO_free(out);
401 QByteArray &clearText,
406 BIO *in = kossl->BIO_new_mem_buf((
char *)cipherText.data(), cipherText.size());
407 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
409 rc rc = priv->decryptMessage(in,out,
410 const_cast<KSSLPKCS12 &>(privKey));
412 kossl->BIO_write(out, &eot, 1);
413 priv->MemBIOToQByteArray(out, clearText);
415 kossl->BIO_free(out);