22 #include <tqptrlist.h>
23 #include <tqcstring.h>
28 #include "ksslcertificate.h"
29 #include "ksslpkcs12.h"
30 #include "ksmimecrypto.h"
35 #define crypt _openssl_crypt
36 #include <openssl/err.h>
42 static const char eot = 0;
44 class KSMIMECryptoPrivate {
51 STACK_OF(X509) *certsToX509(TQPtrList<KSSLCertificate> &certs);
53 KSMIMECrypto::rc signMessage(BIO *clearText,
55 KSSLPKCS12 &privKey, TQPtrList<KSSLCertificate> &certs,
58 KSMIMECrypto::rc encryptMessage(BIO *clearText,
59 BIO *cipherText, KSMIMECrypto::algo algorithm,
60 TQPtrList<KSSLCertificate> &recip);
62 KSMIMECrypto::rc checkSignature(BIO *clearText,
63 BIO *signature,
bool detached,
64 TQPtrList<KSSLCertificate> &recip);
66 KSMIMECrypto::rc decryptMessage(BIO *cipherText,
70 void MemBIOToQByteArray(BIO *src, TQByteArray &dest);
72 KSMIMECrypto::rc sslErrToRc(
void);
76 KSMIMECryptoPrivate::KSMIMECryptoPrivate(
KOpenSSLProxy *kossl): kossl(kossl) {
80 STACK_OF(X509) *KSMIMECryptoPrivate::certsToX509(TQPtrList<KSSLCertificate> &certs) {
81 STACK_OF(X509) *x509 =
reinterpret_cast<STACK_OF(X509)*
>(kossl->OPENSSL_sk_new(NULL));
84 kossl->OPENSSL_sk_push(x509, cert->getCert());
91 KSMIMECrypto::rc KSMIMECryptoPrivate::signMessage(BIO *clearText,
93 KSSLPKCS12 &privKey, TQPtrList<KSSLCertificate> &certs,
96 STACK_OF(X509) *other = NULL;
98 int flags = detached?PKCS7_DETACHED:0;
100 if (certs.count()) other = certsToX509(certs);
103 other, clearText, flags);
105 if (other) kossl->OPENSSL_sk_free(other);
107 if (!p7)
return sslErrToRc();
109 if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
110 rc = KSMIMECrypto::KSC_R_OK;
115 kossl->PKCS7_free(p7);
120 KSMIMECrypto::rc KSMIMECryptoPrivate::encryptMessage(BIO *clearText,
121 BIO *cipherText, KSMIMECrypto::algo algorithm,
122 TQPtrList<KSSLCertificate> &recip) {
123 EVP_CIPHER *cipher = NULL;
126 case KSMIMECrypto::KSC_C_DES3_CBC:
127 cipher = kossl->EVP_des_ede3_cbc();
129 case KSMIMECrypto::KSC_C_RC2_CBC_128:
130 cipher = kossl->EVP_rc2_cbc();
132 case KSMIMECrypto::KSC_C_RC2_CBC_64:
133 cipher = kossl->EVP_rc2_64_cbc();
135 case KSMIMECrypto::KSC_C_DES_CBC:
136 cipher = kossl->EVP_des_cbc();
138 case KSMIMECrypto::KSC_C_RC2_CBC_40:
139 cipher = kossl->EVP_rc2_40_cbc();
142 if (!cipher)
return KSMIMECrypto::KSC_R_NOCIPHER;
144 STACK_OF(X509) *certs = certsToX509(recip);
146 PKCS7 *p7 = kossl->PKCS7_encrypt(certs, clearText, cipher, 0);
148 kossl->OPENSSL_sk_free(certs);
150 if (!p7)
return sslErrToRc();
152 if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
153 rc = KSMIMECrypto::KSC_R_OK;
158 kossl->PKCS7_free(p7);
164 KSMIMECrypto::rc KSMIMECryptoPrivate::checkSignature(BIO *clearText,
165 BIO *signature,
bool detached,
166 TQPtrList<KSSLCertificate> &recip) {
168 PKCS7 *p7 = kossl->d2i_PKCS7_bio(signature, NULL);
169 KSMIMECrypto::rc rc = KSMIMECrypto::KSC_R_OTHER;
171 if (!p7)
return sslErrToRc();
183 X509_STORE *dummystore = kossl->X509_STORE_new();
184 if (kossl->PKCS7_verify(p7, NULL, dummystore, in, out, PKCS7_NOVERIFY)) {
185 STACK_OF(X509) *signers = kossl->PKCS7_get0_signers(p7, 0, PKCS7_NOVERIFY);
186 int num = kossl->OPENSSL_sk_num(signers);
188 for(
int n=0; n<num; n++) {
190 recip.append(signer);
193 kossl->OPENSSL_sk_free(signers);
194 rc = KSMIMECrypto::KSC_R_OK;
199 kossl->X509_STORE_free(dummystore);
200 kossl->PKCS7_free(p7);
206 KSMIMECrypto::rc KSMIMECryptoPrivate::decryptMessage(BIO *cipherText,
210 PKCS7 *p7 = kossl->d2i_PKCS7_bio(cipherText, NULL);
213 if (!p7)
return sslErrToRc();
217 rc = KSMIMECrypto::KSC_R_OK;
222 kossl->PKCS7_free(p7);
228 void KSMIMECryptoPrivate::MemBIOToQByteArray(BIO *src, TQByteArray &dest) {
230 long len = kossl->BIO_get_mem_data(src, &buf);
231 dest.assign(buf, len);
236 void *ptr = kossl->BIO_get_data(src);
237 reinterpret_cast<BUF_MEM *
>(ptr)->data = NULL;
241 KSMIMECrypto::rc KSMIMECryptoPrivate::sslErrToRc(
void) {
242 unsigned long cerr = kossl->ERR_get_error();
246 switch(ERR_GET_REASON(cerr)) {
247 case ERR_R_MALLOC_FAILURE:
248 return KSMIMECrypto::KSC_R_NOMEM;
251 switch(ERR_GET_LIB(cerr)) {
253 switch(ERR_GET_REASON(cerr)) {
254 case PKCS7_R_WRONG_CONTENT_TYPE:
255 case PKCS7_R_NO_CONTENT:
256 case PKCS7_R_NO_SIGNATURES_ON_DATA:
257 return KSMIMECrypto::KSC_R_FORMAT;
259 case PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:
260 case PKCS7_R_DECRYPT_ERROR:
261 return KSMIMECrypto::KSC_R_WRONGKEY;
263 case PKCS7_R_DIGEST_FAILURE:
264 return KSMIMECrypto::KSC_R_VERIFY;
273 kdDebug(7029) <<
"KSMIMECrypto: uncaught error " <<ERR_GET_LIB(cerr)
274 <<
" " <<ERR_GET_REASON(cerr) <<endl;
275 return KSMIMECrypto::KSC_R_OTHER;
280 KSMIMECrypto::KSMIMECrypto() {
283 priv =
new KSMIMECryptoPrivate(kossl);
284 if (!kossl->hasLibCrypto()) kossl = 0L;
291 KSMIMECrypto::~KSMIMECrypto() {
298 KSMIMECrypto::rc KSMIMECrypto::signMessage(
const TQCString &clearText,
299 TQByteArray &cipherText,
301 const TQPtrList<KSSLCertificate> &certs,
304 if (!kossl)
return KSC_R_NO_SSL;
305 BIO *in = kossl->BIO_new_mem_buf((
char *)clearText.data(), clearText.size());
306 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
308 rc rc = priv->signMessage(in, out,
310 const_cast<TQPtrList<KSSLCertificate> &
>(certs),
313 if (!rc) priv->MemBIOToQByteArray(out, cipherText);
315 kossl->BIO_free(out);
325 KSMIMECrypto::rc KSMIMECrypto::checkDetachedSignature(
const TQCString &clearText,
326 const TQByteArray &signature,
327 TQPtrList<KSSLCertificate> &foundCerts) {
329 if (!kossl)
return KSC_R_NO_SSL;
330 BIO *txt = kossl->BIO_new_mem_buf((
char *)clearText.data(), clearText.length());
331 BIO *sig = kossl->BIO_new_mem_buf((
char *)signature.data(), signature.size());
333 rc rc = priv->checkSignature(txt, sig,
true, foundCerts);
335 kossl->BIO_free(sig);
336 kossl->BIO_free(txt);
345 KSMIMECrypto::rc KSMIMECrypto::checkOpaqueSignature(
const TQByteArray &signedText,
346 TQCString &clearText,
347 TQPtrList<KSSLCertificate> &foundCerts) {
349 if (!kossl)
return KSC_R_NO_SSL;
351 BIO *in = kossl->BIO_new_mem_buf((
char *)signedText.data(), signedText.size());
352 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
354 rc rc = priv->checkSignature(out, in,
false, foundCerts);
356 kossl->BIO_write(out, &eot, 1);
357 priv->MemBIOToQByteArray(out, clearText);
359 kossl->BIO_free(out);
369 KSMIMECrypto::rc KSMIMECrypto::encryptMessage(
const TQCString &clearText,
370 TQByteArray &cipherText,
372 const TQPtrList<KSSLCertificate> &recip) {
374 if (!kossl)
return KSC_R_NO_SSL;
376 BIO *in = kossl->BIO_new_mem_buf((
char *)clearText.data(), clearText.size());
377 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
379 rc rc = priv->encryptMessage(in,out,algorithm,
380 const_cast< TQPtrList<KSSLCertificate> &
>(recip));
382 if (!rc) priv->MemBIOToQByteArray(out, cipherText);
384 kossl->BIO_free(out);
394 KSMIMECrypto::rc KSMIMECrypto::decryptMessage(
const TQByteArray &cipherText,
395 TQCString &clearText,
398 if (!kossl)
return KSC_R_NO_SSL;
400 BIO *in = kossl->BIO_new_mem_buf((
char *)cipherText.data(), cipherText.size());
401 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
403 rc rc = priv->decryptMessage(in,out,
406 kossl->BIO_write(out, &eot, 1);
407 priv->MemBIOToQByteArray(out, clearText);
409 kossl->BIO_free(out);
Dynamically load and wrap OpenSSL.
static KOpenSSLProxy * self()
Return an instance of class KOpenSSLProxy * You cannot delete this object.
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.