• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/kssl
 

tdeio/kssl

  • tdeio
  • kssl
ksmimecrypto.cpp
1 /* This file is part of the KDE project
2  *
3  * Copyright (C) 2003 Stefan Rompf <sux@loplof.de>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB. If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 
22 #include <tqptrlist.h>
23 #include <tqcstring.h>
24 #include <tqstring.h>
25 #include <kdebug.h>
26 
27 #include "kopenssl.h"
28 #include "ksslcertificate.h"
29 #include "ksslpkcs12.h"
30 #include "ksmimecrypto.h"
31 
32 // this hack provided by Malte Starostik to avoid glibc/openssl bug
33 // on some systems
34 #ifdef KSSL_HAVE_SSL
35 #define crypt _openssl_crypt
36 #include <openssl/err.h>
37 #undef crypt
38 #endif
39 
40 
41 #ifdef KSSL_HAVE_SSL
42 static const char eot = 0;
43 
44 class KSMIMECryptoPrivate {
45  KOpenSSLProxy *kossl;
46 
47 public:
48  KSMIMECryptoPrivate(KOpenSSLProxy *kossl);
49 
50 
51  STACK_OF(X509) *certsToX509(TQPtrList<KSSLCertificate> &certs);
52 
53  KSMIMECrypto::rc signMessage(BIO *clearText,
54  BIO *cipherText,
55  KSSLPKCS12 &privKey, TQPtrList<KSSLCertificate> &certs,
56  bool detached);
57 
58  KSMIMECrypto::rc encryptMessage(BIO *clearText,
59  BIO *cipherText, KSMIMECrypto::algo algorithm,
60  TQPtrList<KSSLCertificate> &recip);
61 
62  KSMIMECrypto::rc checkSignature(BIO *clearText,
63  BIO *signature, bool detached,
64  TQPtrList<KSSLCertificate> &recip);
65 
66  KSMIMECrypto::rc decryptMessage(BIO *cipherText,
67  BIO *clearText,
68  KSSLPKCS12 &privKey);
69 
70  void MemBIOToQByteArray(BIO *src, TQByteArray &dest);
71 
72  KSMIMECrypto::rc sslErrToRc(void);
73 };
74 
75 
76 KSMIMECryptoPrivate::KSMIMECryptoPrivate(KOpenSSLProxy *kossl): kossl(kossl) {
77 }
78 
79 
80 STACK_OF(X509) *KSMIMECryptoPrivate::certsToX509(TQPtrList<KSSLCertificate> &certs) {
81  STACK_OF(X509) *x509 = reinterpret_cast<STACK_OF(X509)*>(kossl->OPENSSL_sk_new(NULL));
82  KSSLCertificate *cert = certs.first();
83  while(cert) {
84  kossl->OPENSSL_sk_push(x509, cert->getCert());
85  cert = certs.next();
86  }
87  return x509;
88 }
89 
90 
91 KSMIMECrypto::rc KSMIMECryptoPrivate::signMessage(BIO *clearText,
92  BIO *cipherText,
93  KSSLPKCS12 &privKey, TQPtrList<KSSLCertificate> &certs,
94  bool detached) {
95 
96  STACK_OF(X509) *other = NULL;
97  KSMIMECrypto::rc rc;
98  int flags = detached?PKCS7_DETACHED:0;
99 
100  if (certs.count()) other = certsToX509(certs);
101 
102  PKCS7 *p7 = kossl->PKCS7_sign(privKey.getCertificate()->getCert(), privKey.getPrivateKey(),
103  other, clearText, flags);
104 
105  if (other) kossl->OPENSSL_sk_free(other);
106 
107  if (!p7) return sslErrToRc();
108 
109  if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
110  rc = KSMIMECrypto::KSC_R_OK;
111  } else {
112  rc = sslErrToRc();
113  }
114 
115  kossl->PKCS7_free(p7);
116 
117  return rc;
118 }
119 
120 KSMIMECrypto::rc KSMIMECryptoPrivate::encryptMessage(BIO *clearText,
121  BIO *cipherText, KSMIMECrypto::algo algorithm,
122  TQPtrList<KSSLCertificate> &recip) {
123  EVP_CIPHER *cipher = NULL;
124  KSMIMECrypto::rc rc;
125  switch(algorithm) {
126  case KSMIMECrypto::KSC_C_DES3_CBC:
127  cipher = kossl->EVP_des_ede3_cbc();
128  break;
129  case KSMIMECrypto::KSC_C_RC2_CBC_128:
130  cipher = kossl->EVP_rc2_cbc();
131  break;
132  case KSMIMECrypto::KSC_C_RC2_CBC_64:
133  cipher = kossl->EVP_rc2_64_cbc();
134  break;
135  case KSMIMECrypto::KSC_C_DES_CBC:
136  cipher = kossl->EVP_des_cbc();
137  break;
138  case KSMIMECrypto::KSC_C_RC2_CBC_40:
139  cipher = kossl->EVP_rc2_40_cbc();
140  break;
141  }
142  if (!cipher) return KSMIMECrypto::KSC_R_NOCIPHER;
143 
144  STACK_OF(X509) *certs = certsToX509(recip);
145 
146  PKCS7 *p7 = kossl->PKCS7_encrypt(certs, clearText, cipher, 0);
147 
148  kossl->OPENSSL_sk_free(certs);
149 
150  if (!p7) return sslErrToRc();
151 
152  if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
153  rc = KSMIMECrypto::KSC_R_OK;
154  } else {
155  rc = sslErrToRc();
156  }
157 
158  kossl->PKCS7_free(p7);
159 
160  return rc;
161 }
162 
163 
164 KSMIMECrypto::rc KSMIMECryptoPrivate::checkSignature(BIO *clearText,
165  BIO *signature, bool detached,
166  TQPtrList<KSSLCertificate> &recip) {
167 
168  PKCS7 *p7 = kossl->d2i_PKCS7_bio(signature, NULL);
169  KSMIMECrypto::rc rc = KSMIMECrypto::KSC_R_OTHER;
170 
171  if (!p7) return sslErrToRc();
172 
173  BIO *in;
174  BIO *out;
175  if (detached) {
176  in = clearText;
177  out = NULL;
178  } else {
179  in = NULL;
180  out = clearText;
181  }
182 
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);
187 
188  for(int n=0; n<num; n++) {
189  KSSLCertificate *signer = KSSLCertificate::fromX509(reinterpret_cast<X509*>(kossl->OPENSSL_sk_value(signers, n)));
190  recip.append(signer);
191  }
192 
193  kossl->OPENSSL_sk_free(signers);
194  rc = KSMIMECrypto::KSC_R_OK;
195  } else {
196  rc = sslErrToRc();
197  }
198 
199  kossl->X509_STORE_free(dummystore);
200  kossl->PKCS7_free(p7);
201 
202  return rc;
203 }
204 
205 
206 KSMIMECrypto::rc KSMIMECryptoPrivate::decryptMessage(BIO *cipherText,
207  BIO *clearText,
208  KSSLPKCS12 &privKey) {
209 
210  PKCS7 *p7 = kossl->d2i_PKCS7_bio(cipherText, NULL);
211  KSMIMECrypto::rc rc;
212 
213  if (!p7) return sslErrToRc();
214 
215  if (kossl->PKCS7_decrypt(p7, privKey.getPrivateKey(), privKey.getCertificate()->getCert(),
216  clearText, 0)) {
217  rc = KSMIMECrypto::KSC_R_OK;
218  } else {
219  rc = sslErrToRc();
220  }
221 
222  kossl->PKCS7_free(p7);
223 
224  return rc;
225 }
226 
227 
228 void KSMIMECryptoPrivate::MemBIOToQByteArray(BIO *src, TQByteArray &dest) {
229  char *buf;
230  long len = kossl->BIO_get_mem_data(src, &buf);
231  dest.assign(buf, len);
232  /* Now this goes quite a bit into openssl internals.
233  We assume that openssl uses malloc() (it does in
234  default config) and rip out the buffer.
235  */
236  void *ptr = kossl->BIO_get_data(src);
237  reinterpret_cast<BUF_MEM *>(ptr)->data = NULL;
238 }
239 
240 
241 KSMIMECrypto::rc KSMIMECryptoPrivate::sslErrToRc(void) {
242  unsigned long cerr = kossl->ERR_get_error();
243 
244  // To be completed and possibly fixed
245 
246  switch(ERR_GET_REASON(cerr)) {
247  case ERR_R_MALLOC_FAILURE:
248  return KSMIMECrypto::KSC_R_NOMEM;
249  }
250 
251  switch(ERR_GET_LIB(cerr)) {
252  case ERR_LIB_PKCS7:
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;
258  break;
259  case PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:
260  case PKCS7_R_DECRYPT_ERROR: // Hmm?
261  return KSMIMECrypto::KSC_R_WRONGKEY;
262  break;
263  case PKCS7_R_DIGEST_FAILURE:
264  return KSMIMECrypto::KSC_R_VERIFY;
265  default:
266  break;
267  }
268  break;
269  default:
270  break;
271  }
272 
273  kdDebug(7029) <<"KSMIMECrypto: uncaught error " <<ERR_GET_LIB(cerr)
274  <<" " <<ERR_GET_REASON(cerr) <<endl;
275  return KSMIMECrypto::KSC_R_OTHER;
276 }
277 #endif
278 
279 
280 KSMIMECrypto::KSMIMECrypto() {
281 #ifdef KSSL_HAVE_SSL
282  kossl = KOpenSSLProxy::self();
283  priv = new KSMIMECryptoPrivate(kossl);
284  if (!kossl->hasLibCrypto()) kossl = 0L;
285 #else
286  kossl = 0L;
287 #endif
288 }
289 
290 
291 KSMIMECrypto::~KSMIMECrypto() {
292 #ifdef KSSL_HAVE_SSL
293  delete priv;
294 #endif
295 }
296 
297 
298 KSMIMECrypto::rc KSMIMECrypto::signMessage(const TQCString &clearText,
299  TQByteArray &cipherText,
300  const KSSLPKCS12 &privKey,
301  const TQPtrList<KSSLCertificate> &certs,
302  bool detached) {
303 #ifdef KSSL_HAVE_SSL
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());
307 
308  rc rc = priv->signMessage(in, out,
309  const_cast<KSSLPKCS12 &>(privKey),
310  const_cast<TQPtrList<KSSLCertificate> &>(certs),
311  detached);
312 
313  if (!rc) priv->MemBIOToQByteArray(out, cipherText);
314 
315  kossl->BIO_free(out);
316  kossl->BIO_free(in);
317 
318  return rc;
319 #else
320  return KSC_R_NO_SSL;
321 #endif
322 }
323 
324 
325 KSMIMECrypto::rc KSMIMECrypto::checkDetachedSignature(const TQCString &clearText,
326  const TQByteArray &signature,
327  TQPtrList<KSSLCertificate> &foundCerts) {
328 #ifdef KSSL_HAVE_SSL
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());
332 
333  rc rc = priv->checkSignature(txt, sig, true, foundCerts);
334 
335  kossl->BIO_free(sig);
336  kossl->BIO_free(txt);
337 
338  return rc;
339 #else
340  return KSC_R_NO_SSL;
341 #endif
342 }
343 
344 
345 KSMIMECrypto::rc KSMIMECrypto::checkOpaqueSignature(const TQByteArray &signedText,
346  TQCString &clearText,
347  TQPtrList<KSSLCertificate> &foundCerts) {
348 #ifdef KSSL_HAVE_SSL
349  if (!kossl) return KSC_R_NO_SSL;
350 
351  BIO *in = kossl->BIO_new_mem_buf((char *)signedText.data(), signedText.size());
352  BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
353 
354  rc rc = priv->checkSignature(out, in, false, foundCerts);
355 
356  kossl->BIO_write(out, &eot, 1);
357  priv->MemBIOToQByteArray(out, clearText);
358 
359  kossl->BIO_free(out);
360  kossl->BIO_free(in);
361 
362  return rc;
363 #else
364  return KSC_R_NO_SSL;
365 #endif
366 }
367 
368 
369 KSMIMECrypto::rc KSMIMECrypto::encryptMessage(const TQCString &clearText,
370  TQByteArray &cipherText,
371  algo algorithm,
372  const TQPtrList<KSSLCertificate> &recip) {
373 #ifdef KSSL_HAVE_SSL
374  if (!kossl) return KSC_R_NO_SSL;
375 
376  BIO *in = kossl->BIO_new_mem_buf((char *)clearText.data(), clearText.size());
377  BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
378 
379  rc rc = priv->encryptMessage(in,out,algorithm,
380  const_cast< TQPtrList<KSSLCertificate> &>(recip));
381 
382  if (!rc) priv->MemBIOToQByteArray(out, cipherText);
383 
384  kossl->BIO_free(out);
385  kossl->BIO_free(in);
386 
387  return rc;
388 #else
389  return KSC_R_NO_SSL;
390 #endif
391 }
392 
393 
394 KSMIMECrypto::rc KSMIMECrypto::decryptMessage(const TQByteArray &cipherText,
395  TQCString &clearText,
396  const KSSLPKCS12 &privKey) {
397 #ifdef KSSL_HAVE_SSL
398  if (!kossl) return KSC_R_NO_SSL;
399 
400  BIO *in = kossl->BIO_new_mem_buf((char *)cipherText.data(), cipherText.size());
401  BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
402 
403  rc rc = priv->decryptMessage(in,out,
404  const_cast<KSSLPKCS12 &>(privKey));
405 
406  kossl->BIO_write(out, &eot, 1);
407  priv->MemBIOToQByteArray(out, clearText);
408 
409  kossl->BIO_free(out);
410  kossl->BIO_free(in);
411 
412  return rc;
413 #else
414  return KSC_R_NO_SSL;
415 #endif
416 }
417 
KSSLCertificate
KDE X.509 Certificate.
Definition: ksslcertificate.h:77
KOpenSSLProxy
Dynamically load and wrap OpenSSL.
Definition: kopenssl.h:76
KSSLPKCS12
KDE PKCS#12 Certificate.
Definition: ksslpkcs12.h:61
KSSLCertificate::fromX509
static KSSLCertificate * fromX509(X509 *x5)
Create an X.509 certificate from the internal representation.
Definition: ksslcertificate.cpp:139
KSSLPKCS12::getPrivateKey
EVP_PKEY * getPrivateKey()
Get the private key.
Definition: ksslpkcs12.cpp:176
KSSLPKCS12::getCertificate
KSSLCertificate * getCertificate()
Get the X.509 certificate.
Definition: ksslpkcs12.cpp:181
KOpenSSLProxy::self
static KOpenSSLProxy * self()
Return an instance of class KOpenSSLProxy * You cannot delete this object.
Definition: kopenssl.cpp:729

tdeio/kssl

Skip menu "tdeio/kssl"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

tdeio/kssl

Skip menu "tdeio/kssl"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/kssl by doxygen 1.8.8
This website is maintained by Timothy Pearson.