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

kio/kssl

  • kio
  • kssl
ksmimecrypto.cc
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 // forward included macros to KOpenSSLProxy
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
48 
49 
50 #ifdef KSSL_HAVE_SSL
51 static const char eot = 0;
52 
53 class KSMIMECryptoPrivate {
54  KOpenSSLProxy *kossl;
55 
56 public:
57  KSMIMECryptoPrivate(KOpenSSLProxy *kossl);
58 
59 
60  STACK_OF(X509) *certsToX509(TQPtrList<KSSLCertificate> &certs);
61 
62  KSMIMECrypto::rc signMessage(BIO *clearText,
63  BIO *cipherText,
64  KSSLPKCS12 &privKey, TQPtrList<KSSLCertificate> &certs,
65  bool detached);
66 
67  KSMIMECrypto::rc encryptMessage(BIO *clearText,
68  BIO *cipherText, KSMIMECrypto::algo algorithm,
69  TQPtrList<KSSLCertificate> &recip);
70 
71  KSMIMECrypto::rc checkSignature(BIO *clearText,
72  BIO *signature, bool detached,
73  TQPtrList<KSSLCertificate> &recip);
74 
75  KSMIMECrypto::rc decryptMessage(BIO *cipherText,
76  BIO *clearText,
77  KSSLPKCS12 &privKey);
78 
79  void MemBIOToQByteArray(BIO *src, TQByteArray &dest);
80 
81  KSMIMECrypto::rc sslErrToRc(void);
82 };
83 
84 
85 KSMIMECryptoPrivate::KSMIMECryptoPrivate(KOpenSSLProxy *kossl): kossl(kossl) {
86 }
87 
88 
89 STACK_OF(X509) *KSMIMECryptoPrivate::certsToX509(TQPtrList<KSSLCertificate> &certs) {
90  STACK_OF(X509) *x509 = reinterpret_cast<STACK_OF(X509)*>(sk_new(NULL));
91  KSSLCertificate *cert = certs.first();
92  while(cert) {
93  sk_X509_push(x509, cert->getCert());
94  cert = certs.next();
95  }
96  return x509;
97 }
98 
99 
100 KSMIMECrypto::rc KSMIMECryptoPrivate::signMessage(BIO *clearText,
101  BIO *cipherText,
102  KSSLPKCS12 &privKey, TQPtrList<KSSLCertificate> &certs,
103  bool detached) {
104 
105  STACK_OF(X509) *other = NULL;
106  KSMIMECrypto::rc rc;
107  int flags = detached?PKCS7_DETACHED:0;
108 
109  if (certs.count()) other = certsToX509(certs);
110 
111  PKCS7 *p7 = kossl->PKCS7_sign(privKey.getCertificate()->getCert(), privKey.getPrivateKey(),
112  other, clearText, flags);
113 
114  if (other) sk_X509_free(other);
115 
116  if (!p7) return sslErrToRc();
117 
118  if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
119  rc = KSMIMECrypto::KSC_R_OK;
120  } else {
121  rc = sslErrToRc();
122  }
123 
124  kossl->PKCS7_free(p7);
125 
126  return rc;
127 }
128 
129 KSMIMECrypto::rc KSMIMECryptoPrivate::encryptMessage(BIO *clearText,
130  BIO *cipherText, KSMIMECrypto::algo algorithm,
131  TQPtrList<KSSLCertificate> &recip) {
132  EVP_CIPHER *cipher = NULL;
133  KSMIMECrypto::rc rc;
134  switch(algorithm) {
135  case KSMIMECrypto::KSC_C_DES3_CBC:
136  cipher = kossl->EVP_des_ede3_cbc();
137  break;
138  case KSMIMECrypto::KSC_C_RC2_CBC_128:
139  cipher = kossl->EVP_rc2_cbc();
140  break;
141  case KSMIMECrypto::KSC_C_RC2_CBC_64:
142  cipher = kossl->EVP_rc2_64_cbc();
143  break;
144  case KSMIMECrypto::KSC_C_DES_CBC:
145  cipher = kossl->EVP_des_cbc();
146  break;
147  case KSMIMECrypto::KSC_C_RC2_CBC_40:
148  cipher = kossl->EVP_rc2_40_cbc();
149  break;
150  }
151  if (!cipher) return KSMIMECrypto::KSC_R_NOCIPHER;
152 
153  STACK_OF(X509) *certs = certsToX509(recip);
154 
155  PKCS7 *p7 = kossl->PKCS7_encrypt(certs, clearText, cipher, 0);
156 
157  sk_X509_free(certs);
158 
159  if (!p7) return sslErrToRc();
160 
161  if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
162  rc = KSMIMECrypto::KSC_R_OK;
163  } else {
164  rc = sslErrToRc();
165  }
166 
167  kossl->PKCS7_free(p7);
168 
169  return rc;
170 }
171 
172 
173 KSMIMECrypto::rc KSMIMECryptoPrivate::checkSignature(BIO *clearText,
174  BIO *signature, bool detached,
175  TQPtrList<KSSLCertificate> &recip) {
176 
177  PKCS7 *p7 = kossl->d2i_PKCS7_bio(signature, NULL);
178  KSMIMECrypto::rc rc = KSMIMECrypto::KSC_R_OTHER;
179 
180  if (!p7) return sslErrToRc();
181 
182  BIO *in;
183  BIO *out;
184  if (detached) {
185  in = clearText;
186  out = NULL;
187  } else {
188  in = NULL;
189  out = clearText;
190  }
191 
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);
196 
197  for(int n=0; n<num; n++) {
198  KSSLCertificate *signer = KSSLCertificate::fromX509(sk_X509_value(signers, n));
199  recip.append(signer);
200  }
201 
202  sk_X509_free(signers);
203  rc = KSMIMECrypto::KSC_R_OK;
204  } else {
205  rc = sslErrToRc();
206  }
207 
208  kossl->X509_STORE_free(dummystore);
209  kossl->PKCS7_free(p7);
210 
211  return rc;
212 }
213 
214 
215 KSMIMECrypto::rc KSMIMECryptoPrivate::decryptMessage(BIO *cipherText,
216  BIO *clearText,
217  KSSLPKCS12 &privKey) {
218 
219  PKCS7 *p7 = kossl->d2i_PKCS7_bio(cipherText, NULL);
220  KSMIMECrypto::rc rc;
221 
222  if (!p7) return sslErrToRc();
223 
224  if (kossl->PKCS7_decrypt(p7, privKey.getPrivateKey(), privKey.getCertificate()->getCert(),
225  clearText, 0)) {
226  rc = KSMIMECrypto::KSC_R_OK;
227  } else {
228  rc = sslErrToRc();
229  }
230 
231  kossl->PKCS7_free(p7);
232 
233  return rc;
234 }
235 
236 
237 void KSMIMECryptoPrivate::MemBIOToQByteArray(BIO *src, TQByteArray &dest) {
238  char *buf;
239  long len = BIO_get_mem_data(src, &buf);
240  dest.assign(buf, len);
241  /* Now this goes quite a bit into openssl internals.
242  We assume that openssl uses malloc() (it does in
243  default config) and rip out the buffer.
244  */
245  reinterpret_cast<BUF_MEM *>(src->ptr)->data = NULL;
246 }
247 
248 
249 KSMIMECrypto::rc KSMIMECryptoPrivate::sslErrToRc(void) {
250  unsigned long cerr = kossl->ERR_get_error();
251 
252  // To be completed and possibly fixed
253 
254  switch(ERR_GET_REASON(cerr)) {
255  case ERR_R_MALLOC_FAILURE:
256  return KSMIMECrypto::KSC_R_NOMEM;
257  }
258 
259  switch(ERR_GET_LIB(cerr)) {
260  case ERR_LIB_PKCS7:
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;
266  break;
267  case PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:
268  case PKCS7_R_DECRYPT_ERROR: // Hmm?
269  return KSMIMECrypto::KSC_R_WRONGKEY;
270  break;
271  case PKCS7_R_DIGEST_FAILURE:
272  return KSMIMECrypto::KSC_R_VERIFY;
273  default:
274  break;
275  }
276  break;
277  default:
278  break;
279  }
280 
281  kdDebug(7029) <<"KSMIMECrypto: uncaught error " <<ERR_GET_LIB(cerr)
282  <<" " <<ERR_GET_REASON(cerr) <<endl;
283  return KSMIMECrypto::KSC_R_OTHER;
284 }
285 #endif
286 
287 
288 KSMIMECrypto::KSMIMECrypto() {
289 #ifdef KSSL_HAVE_SSL
290  kossl = KOpenSSLProxy::self();
291  priv = new KSMIMECryptoPrivate(kossl);
292  if (!kossl->hasLibCrypto()) kossl = 0L;
293 #else
294  kossl = 0L;
295 #endif
296 }
297 
298 
299 KSMIMECrypto::~KSMIMECrypto() {
300 #ifdef KSSL_HAVE_SSL
301  delete priv;
302 #endif
303 }
304 
305 
306 KSMIMECrypto::rc KSMIMECrypto::signMessage(const TQCString &clearText,
307  TQByteArray &cipherText,
308  const KSSLPKCS12 &privKey,
309  const TQPtrList<KSSLCertificate> &certs,
310  bool detached) {
311 #ifdef KSSL_HAVE_SSL
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());
315 
316  rc rc = priv->signMessage(in, out,
317  const_cast<KSSLPKCS12 &>(privKey),
318  const_cast<TQPtrList<KSSLCertificate> &>(certs),
319  detached);
320 
321  if (!rc) priv->MemBIOToQByteArray(out, cipherText);
322 
323  kossl->BIO_free(out);
324  kossl->BIO_free(in);
325 
326  return rc;
327 #else
328  return KSC_R_NO_SSL;
329 #endif
330 }
331 
332 
333 KSMIMECrypto::rc KSMIMECrypto::checkDetachedSignature(const TQCString &clearText,
334  const TQByteArray &signature,
335  TQPtrList<KSSLCertificate> &foundCerts) {
336 #ifdef KSSL_HAVE_SSL
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());
340 
341  rc rc = priv->checkSignature(txt, sig, true, foundCerts);
342 
343  kossl->BIO_free(sig);
344  kossl->BIO_free(txt);
345 
346  return rc;
347 #else
348  return KSC_R_NO_SSL;
349 #endif
350 }
351 
352 
353 KSMIMECrypto::rc KSMIMECrypto::checkOpaqueSignature(const TQByteArray &signedText,
354  TQCString &clearText,
355  TQPtrList<KSSLCertificate> &foundCerts) {
356 #ifdef KSSL_HAVE_SSL
357  if (!kossl) return KSC_R_NO_SSL;
358 
359  BIO *in = kossl->BIO_new_mem_buf((char *)signedText.data(), signedText.size());
360  BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
361 
362  rc rc = priv->checkSignature(out, in, false, foundCerts);
363 
364  kossl->BIO_write(out, &eot, 1);
365  priv->MemBIOToQByteArray(out, clearText);
366 
367  kossl->BIO_free(out);
368  kossl->BIO_free(in);
369 
370  return rc;
371 #else
372  return KSC_R_NO_SSL;
373 #endif
374 }
375 
376 
377 KSMIMECrypto::rc KSMIMECrypto::encryptMessage(const TQCString &clearText,
378  TQByteArray &cipherText,
379  algo algorithm,
380  const TQPtrList<KSSLCertificate> &recip) {
381 #ifdef KSSL_HAVE_SSL
382  if (!kossl) return KSC_R_NO_SSL;
383 
384  BIO *in = kossl->BIO_new_mem_buf((char *)clearText.data(), clearText.size());
385  BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
386 
387  rc rc = priv->encryptMessage(in,out,algorithm,
388  const_cast< TQPtrList<KSSLCertificate> &>(recip));
389 
390  if (!rc) priv->MemBIOToQByteArray(out, cipherText);
391 
392  kossl->BIO_free(out);
393  kossl->BIO_free(in);
394 
395  return rc;
396 #else
397  return KSC_R_NO_SSL;
398 #endif
399 }
400 
401 
402 KSMIMECrypto::rc KSMIMECrypto::decryptMessage(const TQByteArray &cipherText,
403  TQCString &clearText,
404  const KSSLPKCS12 &privKey) {
405 #ifdef KSSL_HAVE_SSL
406  if (!kossl) return KSC_R_NO_SSL;
407 
408  BIO *in = kossl->BIO_new_mem_buf((char *)cipherText.data(), cipherText.size());
409  BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
410 
411  rc rc = priv->decryptMessage(in,out,
412  const_cast<KSSLPKCS12 &>(privKey));
413 
414  kossl->BIO_write(out, &eot, 1);
415  priv->MemBIOToQByteArray(out, clearText);
416 
417  kossl->BIO_free(out);
418  kossl->BIO_free(in);
419 
420  return rc;
421 #else
422  return KSC_R_NO_SSL;
423 #endif
424 }

kio/kssl

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

kio/kssl

Skip menu "kio/kssl"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kio/kssl by doxygen 1.8.3.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |