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 #define sk_new kossl->sk_new 43 #define sk_free kossl->sk_free 44 #define sk_push kossl->sk_push 45 #define sk_value kossl->sk_value 46 #define sk_num kossl->sk_num 47 #define BIO_ctrl kossl->BIO_ctrl 51 static const char eot = 0;
53 class KSMIMECryptoPrivate {
60 STACK_OF(X509) *certsToX509(TQPtrList<KSSLCertificate> &certs);
62 KSMIMECrypto::rc signMessage(BIO *clearText,
64 KSSLPKCS12 &privKey, TQPtrList<KSSLCertificate> &certs,
67 KSMIMECrypto::rc encryptMessage(BIO *clearText,
68 BIO *cipherText, KSMIMECrypto::algo algorithm,
69 TQPtrList<KSSLCertificate> &recip);
71 KSMIMECrypto::rc checkSignature(BIO *clearText,
72 BIO *signature,
bool detached,
73 TQPtrList<KSSLCertificate> &recip);
75 KSMIMECrypto::rc decryptMessage(BIO *cipherText,
79 void MemBIOToQByteArray(BIO *src, TQByteArray &dest);
81 KSMIMECrypto::rc sslErrToRc(
void);
85 KSMIMECryptoPrivate::KSMIMECryptoPrivate(
KOpenSSLProxy *kossl): kossl(kossl) {
89 STACK_OF(X509) *KSMIMECryptoPrivate::certsToX509(TQPtrList<KSSLCertificate> &certs) {
90 STACK_OF(X509) *x509 =
reinterpret_cast<STACK_OF(X509)*
>(sk_new(NULL));
93 sk_X509_push(x509, cert->getCert());
100 KSMIMECrypto::rc KSMIMECryptoPrivate::signMessage(BIO *clearText,
102 KSSLPKCS12 &privKey, TQPtrList<KSSLCertificate> &certs,
105 STACK_OF(X509) *other = NULL;
107 int flags = detached?PKCS7_DETACHED:0;
109 if (certs.count()) other = certsToX509(certs);
112 other, clearText, flags);
114 if (other) sk_X509_free(other);
116 if (!p7)
return sslErrToRc();
118 if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
119 rc = KSMIMECrypto::KSC_R_OK;
124 kossl->PKCS7_free(p7);
129 KSMIMECrypto::rc KSMIMECryptoPrivate::encryptMessage(BIO *clearText,
130 BIO *cipherText, KSMIMECrypto::algo algorithm,
131 TQPtrList<KSSLCertificate> &recip) {
132 EVP_CIPHER *cipher = NULL;
135 case KSMIMECrypto::KSC_C_DES3_CBC:
136 cipher = kossl->EVP_des_ede3_cbc();
138 case KSMIMECrypto::KSC_C_RC2_CBC_128:
139 cipher = kossl->EVP_rc2_cbc();
141 case KSMIMECrypto::KSC_C_RC2_CBC_64:
142 cipher = kossl->EVP_rc2_64_cbc();
144 case KSMIMECrypto::KSC_C_DES_CBC:
145 cipher = kossl->EVP_des_cbc();
147 case KSMIMECrypto::KSC_C_RC2_CBC_40:
148 cipher = kossl->EVP_rc2_40_cbc();
151 if (!cipher)
return KSMIMECrypto::KSC_R_NOCIPHER;
153 STACK_OF(X509) *certs = certsToX509(recip);
155 PKCS7 *p7 = kossl->PKCS7_encrypt(certs, clearText, cipher, 0);
159 if (!p7)
return sslErrToRc();
161 if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
162 rc = KSMIMECrypto::KSC_R_OK;
167 kossl->PKCS7_free(p7);
173 KSMIMECrypto::rc KSMIMECryptoPrivate::checkSignature(BIO *clearText,
174 BIO *signature,
bool detached,
175 TQPtrList<KSSLCertificate> &recip) {
177 PKCS7 *p7 = kossl->d2i_PKCS7_bio(signature, NULL);
178 KSMIMECrypto::rc rc = KSMIMECrypto::KSC_R_OTHER;
180 if (!p7)
return sslErrToRc();
192 X509_STORE *dummystore = kossl->X509_STORE_new();
193 if (kossl->PKCS7_verify(p7, NULL, dummystore, in, out, PKCS7_NOVERIFY)) {
194 STACK_OF(X509) *signers = kossl->PKCS7_get0_signers(p7, 0, PKCS7_NOVERIFY);
195 int num = sk_X509_num(signers);
197 for(
int n=0; n<num; n++) {
199 recip.append(signer);
202 sk_X509_free(signers);
203 rc = KSMIMECrypto::KSC_R_OK;
208 kossl->X509_STORE_free(dummystore);
209 kossl->PKCS7_free(p7);
215 KSMIMECrypto::rc KSMIMECryptoPrivate::decryptMessage(BIO *cipherText,
219 PKCS7 *p7 = kossl->d2i_PKCS7_bio(cipherText, NULL);
222 if (!p7)
return sslErrToRc();
226 rc = KSMIMECrypto::KSC_R_OK;
231 kossl->PKCS7_free(p7);
237 void KSMIMECryptoPrivate::MemBIOToQByteArray(BIO *src, TQByteArray &dest) {
239 long len = BIO_get_mem_data(src, &buf);
240 dest.assign(buf, len);
245 reinterpret_cast<BUF_MEM *
>(src->ptr)->data = NULL;
249 KSMIMECrypto::rc KSMIMECryptoPrivate::sslErrToRc(
void) {
250 unsigned long cerr = kossl->ERR_get_error();
254 switch(ERR_GET_REASON(cerr)) {
255 case ERR_R_MALLOC_FAILURE:
256 return KSMIMECrypto::KSC_R_NOMEM;
259 switch(ERR_GET_LIB(cerr)) {
261 switch(ERR_GET_REASON(cerr)) {
262 case PKCS7_R_WRONG_CONTENT_TYPE:
263 case PKCS7_R_NO_CONTENT:
264 case PKCS7_R_NO_SIGNATURES_ON_DATA:
265 return KSMIMECrypto::KSC_R_FORMAT;
267 case PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:
268 case PKCS7_R_DECRYPT_ERROR:
269 return KSMIMECrypto::KSC_R_WRONGKEY;
271 case PKCS7_R_DIGEST_FAILURE:
272 return KSMIMECrypto::KSC_R_VERIFY;
281 kdDebug(7029) <<
"KSMIMECrypto: uncaught error " <<ERR_GET_LIB(cerr)
282 <<
" " <<ERR_GET_REASON(cerr) <<endl;
283 return KSMIMECrypto::KSC_R_OTHER;
288 KSMIMECrypto::KSMIMECrypto() {
291 priv =
new KSMIMECryptoPrivate(kossl);
292 if (!kossl->hasLibCrypto()) kossl = 0L;
299 KSMIMECrypto::~KSMIMECrypto() {
306 KSMIMECrypto::rc KSMIMECrypto::signMessage(
const TQCString &clearText,
307 TQByteArray &cipherText,
309 const TQPtrList<KSSLCertificate> &certs,
312 if (!kossl)
return KSC_R_NO_SSL;
313 BIO *in = kossl->BIO_new_mem_buf((
char *)clearText.data(), clearText.size());
314 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
316 rc rc = priv->signMessage(in, out,
317 const_cast<KSSLPKCS12 &>(privKey),
318 const_cast<TQPtrList<KSSLCertificate> &
>(certs),
321 if (!rc) priv->MemBIOToQByteArray(out, cipherText);
323 kossl->BIO_free(out);
333 KSMIMECrypto::rc KSMIMECrypto::checkDetachedSignature(
const TQCString &clearText,
334 const TQByteArray &signature,
335 TQPtrList<KSSLCertificate> &foundCerts) {
337 if (!kossl)
return KSC_R_NO_SSL;
338 BIO *txt = kossl->BIO_new_mem_buf((
char *)clearText.data(), clearText.length());
339 BIO *sig = kossl->BIO_new_mem_buf((
char *)signature.data(), signature.size());
341 rc rc = priv->checkSignature(txt, sig,
true, foundCerts);
343 kossl->BIO_free(sig);
344 kossl->BIO_free(txt);
353 KSMIMECrypto::rc KSMIMECrypto::checkOpaqueSignature(
const TQByteArray &signedText,
354 TQCString &clearText,
355 TQPtrList<KSSLCertificate> &foundCerts) {
357 if (!kossl)
return KSC_R_NO_SSL;
359 BIO *in = kossl->BIO_new_mem_buf((
char *)signedText.data(), signedText.size());
360 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
362 rc rc = priv->checkSignature(out, in,
false, foundCerts);
364 kossl->BIO_write(out, &eot, 1);
365 priv->MemBIOToQByteArray(out, clearText);
367 kossl->BIO_free(out);
377 KSMIMECrypto::rc KSMIMECrypto::encryptMessage(
const TQCString &clearText,
378 TQByteArray &cipherText,
380 const TQPtrList<KSSLCertificate> &recip) {
382 if (!kossl)
return KSC_R_NO_SSL;
384 BIO *in = kossl->BIO_new_mem_buf((
char *)clearText.data(), clearText.size());
385 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
387 rc rc = priv->encryptMessage(in,out,algorithm,
388 const_cast< TQPtrList<KSSLCertificate> &
>(recip));
390 if (!rc) priv->MemBIOToQByteArray(out, cipherText);
392 kossl->BIO_free(out);
402 KSMIMECrypto::rc KSMIMECrypto::decryptMessage(
const TQByteArray &cipherText,
403 TQCString &clearText,
406 if (!kossl)
return KSC_R_NO_SSL;
408 BIO *in = kossl->BIO_new_mem_buf((
char *)cipherText.data(), cipherText.size());
409 BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
411 rc rc = priv->decryptMessage(in,out,
412 const_cast<KSSLPKCS12 &>(privKey));
414 kossl->BIO_write(out, &eot, 1);
415 priv->MemBIOToQByteArray(out, clearText);
417 kossl->BIO_free(out);
Dynamically load and wrap OpenSSL.
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.
static KOpenSSLProxy * self()
Return an instance of class KOpenSSLProxy * You cannot delete this object.