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
50static const char eot = 0;
52class KSMIMECryptoPrivate {
71 BIO *signature,
bool detached,
78 void MemBIOToQByteArray(BIO *src, QByteArray &dest);
84KSMIMECryptoPrivate::KSMIMECryptoPrivate(
KOpenSSLProxy *kossl): kossl(kossl) {
91 sk_X509_push(x509, cert->
getCert());
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);
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,
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);
234void 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,
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,
319 if (!
rc) priv->MemBIOToQByteArray(out, cipherText);
321 kossl->BIO_free(out);
332 const QByteArray &signature,
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,
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,
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,
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,
412 kossl->BIO_write(out, &eot, 1);
413 priv->MemBIOToQByteArray(out, clearText);
415 kossl->BIO_free(out);
Dynamically load and wrap OpenSSL.
bool hasLibCrypto() const
Return true of libcrypto was found and loaded.
static KOpenSSLProxy * self()
Return an instance of class KOpenSSLProxy * You cannot delete this object.
rc signMessage(const QByteArray &clearText, QByteArray &cipherText, const KSSLPKCS12 &privKey, const QList< KSSLCertificate * > &certs, bool detached)
Sign a message.
rc decryptMessage(const QByteArray &cipherText, QByteArray &clearText, const KSSLPKCS12 &privKey)
Decrypt a message.
rc encryptMessage(const QByteArray &clearText, QByteArray &cipherText, algo algorithm, const QList< KSSLCertificate * > &recip)
Encrypt a message encrypts a message for the given list of recipients and the selected algorithm.
rc checkDetachedSignature(const QByteArray &clearText, const QByteArray &signature, QList< KSSLCertificate * > &foundCerts)
Check a detached message signature Will check if messages matches signature and extract certificates ...
rc checkOpaqueSignature(const QByteArray &signedText, QByteArray &clearText, QList< KSSLCertificate * > &foundCerts)
Check an opaque signed message Will check if signature matches and extract message Does not check cer...
static KSSLCertificate * fromX509(X509 *x5)
Create an X.509 certificate from the internal representation.
EVP_PKEY * getPrivateKey()
Get the private key.
KSSLCertificate * getCertificate()
Get the X.509 certificate.