• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KIO

  • sources
  • kde-4.12
  • kdelibs
  • kio
  • kssl
ksmimecrypto.cpp
Go to the documentation of this file.
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 #include "ksmimecrypto.h"
22 
23 #include <QtCore/QList>
24 #include <QtCore/QString>
25 #include <kdebug.h>
26 
27 #include "kopenssl.h"
28 #include "ksslcertificate.h"
29 #include "ksslpkcs12.h"
30 
31 // this hack provided by Malte Starostik to avoid glibc/openssl bug
32 // on some systems
33 #ifdef KSSL_HAVE_SSL
34 #define crypt _openssl_crypt
35 #include <openssl/err.h>
36 #undef crypt
37 #endif
38 
39 
40 // forward included macros to KOpenSSLProxy
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
47 
48 
49 #ifdef KSSL_HAVE_SSL
50 static const char eot = 0;
51 
52 class KSMIMECryptoPrivate {
53  KOpenSSLProxy *kossl;
54 
55 public:
56  KSMIMECryptoPrivate(KOpenSSLProxy *kossl);
57 
58 
59  STACK_OF(X509) *certsToX509(const QList<KSSLCertificate *> &certs);
60 
61  KSMIMECrypto::rc signMessage(BIO *clearText,
62  BIO *cipherText,
63  KSSLPKCS12 &privKey, QList<KSSLCertificate *> &certs,
64  bool detached);
65 
66  KSMIMECrypto::rc encryptMessage(BIO *clearText,
67  BIO *cipherText, KSMIMECrypto::algo algorithm,
68  QList<KSSLCertificate *> &recip);
69 
70  KSMIMECrypto::rc checkSignature(BIO *clearText,
71  BIO *signature, bool detached,
72  QList<KSSLCertificate *> &recip);
73 
74  KSMIMECrypto::rc decryptMessage(BIO *cipherText,
75  BIO *clearText,
76  KSSLPKCS12 &privKey);
77 
78  void MemBIOToQByteArray(BIO *src, QByteArray &dest);
79 
80  KSMIMECrypto::rc sslErrToRc(void);
81 };
82 
83 
84 KSMIMECryptoPrivate::KSMIMECryptoPrivate(KOpenSSLProxy *kossl): kossl(kossl) {
85 }
86 
87 
88 STACK_OF(X509) *KSMIMECryptoPrivate::certsToX509(const QList<KSSLCertificate *> &certs) {
89  STACK_OF(X509) *x509 = sk_new(NULL);
90  foreach(KSSLCertificate *cert, certs) {
91  sk_X509_push(x509, cert->getCert());
92  }
93  return x509;
94 }
95 
96 
97 KSMIMECrypto::rc KSMIMECryptoPrivate::signMessage(BIO *clearText,
98  BIO *cipherText,
99  KSSLPKCS12 &privKey, QList<KSSLCertificate *> &certs,
100  bool detached) {
101 
102  STACK_OF(X509) *other = NULL;
103  KSMIMECrypto::rc rc;
104  int flags = detached?PKCS7_DETACHED:0;
105 
106  if (certs.count()) other = certsToX509(certs);
107 
108  PKCS7 *p7 = kossl->PKCS7_sign(privKey.getCertificate()->getCert(), privKey.getPrivateKey(),
109  other, clearText, flags);
110 
111  if (other) sk_X509_free(other);
112 
113  if (!p7) return sslErrToRc();
114 
115  if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
116  rc = KSMIMECrypto::KSC_R_OK;
117  } else {
118  rc = sslErrToRc();
119  }
120 
121  kossl->PKCS7_free(p7);
122 
123  return rc;
124 }
125 
126 KSMIMECrypto::rc KSMIMECryptoPrivate::encryptMessage(BIO *clearText,
127  BIO *cipherText, KSMIMECrypto::algo algorithm,
128  QList<KSSLCertificate *> &recip) {
129  EVP_CIPHER *cipher = NULL;
130  KSMIMECrypto::rc rc;
131  switch(algorithm) {
132  case KSMIMECrypto::KSC_C_DES3_CBC:
133  cipher = kossl->EVP_des_ede3_cbc();
134  break;
135  case KSMIMECrypto::KSC_C_RC2_CBC_128:
136  cipher = kossl->EVP_rc2_cbc();
137  break;
138  case KSMIMECrypto::KSC_C_RC2_CBC_64:
139  cipher = kossl->EVP_rc2_64_cbc();
140  break;
141  case KSMIMECrypto::KSC_C_DES_CBC:
142  cipher = kossl->EVP_des_cbc();
143  break;
144  case KSMIMECrypto::KSC_C_RC2_CBC_40:
145  cipher = kossl->EVP_rc2_40_cbc();
146  break;
147  }
148  if (!cipher) return KSMIMECrypto::KSC_R_NOCIPHER;
149 
150  STACK_OF(X509) *certs = certsToX509(recip);
151 
152  PKCS7 *p7 = kossl->PKCS7_encrypt(certs, clearText, cipher, 0);
153 
154  sk_X509_free(certs);
155 
156  if (!p7) return sslErrToRc();
157 
158  if (kossl->i2d_PKCS7_bio(cipherText, p7)) {
159  rc = KSMIMECrypto::KSC_R_OK;
160  } else {
161  rc = sslErrToRc();
162  }
163 
164  kossl->PKCS7_free(p7);
165 
166  return rc;
167 }
168 
169 
170 KSMIMECrypto::rc KSMIMECryptoPrivate::checkSignature(BIO *clearText,
171  BIO *signature, bool detached,
172  QList<KSSLCertificate *> &recip) {
173 
174  PKCS7 *p7 = kossl->d2i_PKCS7_bio(signature, NULL);
175  KSMIMECrypto::rc rc = KSMIMECrypto::KSC_R_OTHER;
176 
177  if (!p7) return sslErrToRc();
178 
179  BIO *in;
180  BIO *out;
181  if (detached) {
182  in = clearText;
183  out = NULL;
184  } else {
185  in = NULL;
186  out = clearText;
187  }
188 
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);
193 
194  for(int n=0; n<num; n++) {
195  KSSLCertificate *signer = KSSLCertificate::fromX509(sk_X509_value(signers, n));
196  recip.append(signer);
197  }
198 
199  sk_X509_free(signers);
200  rc = KSMIMECrypto::KSC_R_OK;
201  } else {
202  rc = sslErrToRc();
203  }
204 
205  kossl->X509_STORE_free(dummystore);
206  kossl->PKCS7_free(p7);
207 
208  return rc;
209 }
210 
211 
212 KSMIMECrypto::rc KSMIMECryptoPrivate::decryptMessage(BIO *cipherText,
213  BIO *clearText,
214  KSSLPKCS12 &privKey) {
215 
216  PKCS7 *p7 = kossl->d2i_PKCS7_bio(cipherText, NULL);
217  KSMIMECrypto::rc rc;
218 
219  if (!p7) return sslErrToRc();
220 
221  if (kossl->PKCS7_decrypt(p7, privKey.getPrivateKey(), privKey.getCertificate()->getCert(),
222  clearText, 0)) {
223  rc = KSMIMECrypto::KSC_R_OK;
224  } else {
225  rc = sslErrToRc();
226  }
227 
228  kossl->PKCS7_free(p7);
229 
230  return rc;
231 }
232 
233 
234 void KSMIMECryptoPrivate::MemBIOToQByteArray(BIO *src, QByteArray &dest) {
235  char *buf;
236  long len = BIO_get_mem_data(src, &buf);
237  dest = QByteArray(buf, len);
238  /* Now this goes quite a bit into openssl internals.
239  We assume that openssl uses malloc() (it does in
240  default config) and rip out the buffer.
241  */
242  reinterpret_cast<BUF_MEM *>(src->ptr)->data = NULL;
243 }
244 
245 
246 KSMIMECrypto::rc KSMIMECryptoPrivate::sslErrToRc(void) {
247  unsigned long cerr = kossl->ERR_get_error();
248 
249  // To be completed and possibly fixed
250 
251  switch(ERR_GET_REASON(cerr)) {
252  case ERR_R_MALLOC_FAILURE:
253  return KSMIMECrypto::KSC_R_NOMEM;
254  }
255 
256  switch(ERR_GET_LIB(cerr)) {
257  case ERR_LIB_PKCS7:
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:
262  return KSMIMECrypto::KSC_R_FORMAT;
263  break;
264  case PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:
265  case PKCS7_R_DECRYPT_ERROR: // Hmm?
266  return KSMIMECrypto::KSC_R_WRONGKEY;
267  break;
268  case PKCS7_R_DIGEST_FAILURE:
269  return KSMIMECrypto::KSC_R_VERIFY;
270  default:
271  break;
272  }
273  break;
274  default:
275  break;
276  }
277 
278  kDebug(7029) <<"KSMIMECrypto: uncaught error " <<ERR_GET_LIB(cerr)
279  <<" " <<ERR_GET_REASON(cerr) <<endl;
280  return KSMIMECrypto::KSC_R_OTHER;
281 }
282 #endif
283 
284 
285 KSMIMECrypto::KSMIMECrypto() {
286 #ifdef KSSL_HAVE_SSL
287  kossl = KOpenSSLProxy::self();
288  priv = new KSMIMECryptoPrivate(kossl);
289  if (!kossl->hasLibCrypto()) kossl = 0L;
290 #else
291  kossl = 0L;
292  priv = 0L;
293 #endif
294 }
295 
296 
297 KSMIMECrypto::~KSMIMECrypto() {
298 #ifdef KSSL_HAVE_SSL
299  delete priv;
300 #endif
301 }
302 
303 
304 KSMIMECrypto::rc KSMIMECrypto::signMessage(const QByteArray &clearText,
305  QByteArray &cipherText,
306  const KSSLPKCS12 &privKey,
307  const QList<KSSLCertificate *> &certs,
308  bool detached) {
309 #ifdef KSSL_HAVE_SSL
310  if (!kossl) return KSC_R_NO_SSL;
311  BIO *in = kossl->BIO_new_mem_buf((char *)clearText.data(), clearText.size());
312  BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
313 
314  rc rc = priv->signMessage(in, out,
315  const_cast<KSSLPKCS12 &>(privKey),
316  const_cast<QList<KSSLCertificate *> &>(certs),
317  detached);
318 
319  if (!rc) priv->MemBIOToQByteArray(out, cipherText);
320 
321  kossl->BIO_free(out);
322  kossl->BIO_free(in);
323 
324  return rc;
325 #else
326  return KSC_R_NO_SSL;
327 #endif
328 }
329 
330 
331 KSMIMECrypto::rc KSMIMECrypto::checkDetachedSignature(const QByteArray &clearText,
332  const QByteArray &signature,
333  QList<KSSLCertificate *> &foundCerts) {
334 #ifdef KSSL_HAVE_SSL
335  if (!kossl) return KSC_R_NO_SSL;
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());
338 
339  rc rc = priv->checkSignature(txt, sig, true, foundCerts);
340 
341  kossl->BIO_free(sig);
342  kossl->BIO_free(txt);
343 
344  return rc;
345 #else
346  return KSC_R_NO_SSL;
347 #endif
348 }
349 
350 
351 KSMIMECrypto::rc KSMIMECrypto::checkOpaqueSignature(const QByteArray &signedText,
352  QByteArray &clearText,
353  QList<KSSLCertificate *> &foundCerts) {
354 #ifdef KSSL_HAVE_SSL
355  if (!kossl) return KSC_R_NO_SSL;
356 
357  BIO *in = kossl->BIO_new_mem_buf((char *)signedText.data(), signedText.size());
358  BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
359 
360  rc rc = priv->checkSignature(out, in, false, foundCerts);
361 
362  kossl->BIO_write(out, &eot, 1);
363  priv->MemBIOToQByteArray(out, clearText);
364 
365  kossl->BIO_free(out);
366  kossl->BIO_free(in);
367 
368  return rc;
369 #else
370  return KSC_R_NO_SSL;
371 #endif
372 }
373 
374 
375 KSMIMECrypto::rc KSMIMECrypto::encryptMessage(const QByteArray &clearText,
376  QByteArray &cipherText,
377  algo algorithm,
378  const QList<KSSLCertificate *> &recip) {
379 #ifdef KSSL_HAVE_SSL
380  if (!kossl) return KSC_R_NO_SSL;
381 
382  BIO *in = kossl->BIO_new_mem_buf((char *)clearText.data(), clearText.size());
383  BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
384 
385  rc rc = priv->encryptMessage(in,out,algorithm,
386  const_cast< QList<KSSLCertificate *> &>(recip));
387 
388  if (!rc) priv->MemBIOToQByteArray(out, cipherText);
389 
390  kossl->BIO_free(out);
391  kossl->BIO_free(in);
392 
393  return rc;
394 #else
395  return KSC_R_NO_SSL;
396 #endif
397 }
398 
399 
400 KSMIMECrypto::rc KSMIMECrypto::decryptMessage(const QByteArray &cipherText,
401  QByteArray &clearText,
402  const KSSLPKCS12 &privKey) {
403 #ifdef KSSL_HAVE_SSL
404  if (!kossl) return KSC_R_NO_SSL;
405 
406  BIO *in = kossl->BIO_new_mem_buf((char *)cipherText.data(), cipherText.size());
407  BIO *out = kossl->BIO_new(kossl->BIO_s_mem());
408 
409  rc rc = priv->decryptMessage(in,out,
410  const_cast<KSSLPKCS12 &>(privKey));
411 
412  kossl->BIO_write(out, &eot, 1);
413  priv->MemBIOToQByteArray(out, clearText);
414 
415  kossl->BIO_free(out);
416  kossl->BIO_free(in);
417 
418  return rc;
419 #else
420  return KSC_R_NO_SSL;
421 #endif
422 }
KSMIMECrypto::algo
algo
Definition: ksmimecrypto.h:37
kdebug.h
KSMIMECrypto::KSC_C_DES_CBC
Definition: ksmimecrypto.h:40
ksslcertificate.h
KSMIMECrypto::KSC_R_NOCIPHER
Definition: ksmimecrypto.h:46
KSMIMECrypto::KSMIMECrypto
KSMIMECrypto()
Definition: ksmimecrypto.cpp:285
KOpenSSLProxy::hasLibCrypto
bool hasLibCrypto() const
Return true of libcrypto was found and loaded.
Definition: kopenssl.cpp:229
KSSLCertificate
KDE X.509 Certificate.
Definition: ksslcertificate.h:74
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KSMIMECrypto::KSC_R_NOMEM
Definition: ksmimecrypto.h:47
KSMIMECrypto::KSC_R_VERIFY
Definition: ksmimecrypto.h:50
KOpenSSLProxy
Dynamically load and wrap OpenSSL.
Definition: kopenssl.h:65
KSSLPKCS12
KDE PKCS#12 Certificate.
Definition: ksslpkcs12.h:63
KSSLCertificate::getCert
X509 * getCert()
Definition: ksslcertificate.cpp:569
STACK_OF
#define STACK_OF(x)
Definition: ksslpkcs12.h:46
KSMIMECrypto::decryptMessage
rc decryptMessage(const QByteArray &cipherText, QByteArray &clearText, const KSSLPKCS12 &privKey)
Decrypt a message.
Definition: ksmimecrypto.cpp:400
KSMIMECrypto::KSC_R_OTHER
Definition: ksmimecrypto.h:44
KSMIMECrypto::KSC_C_DES3_CBC
Definition: ksmimecrypto.h:37
KSMIMECrypto::KSC_R_FORMAT
Definition: ksmimecrypto.h:48
ksmimecrypto.h
KSSLCertificate::fromX509
static KSSLCertificate * fromX509(X509 *x5)
Create an X.509 certificate from the internal representation.
Definition: ksslcertificate.cpp:133
KSMIMECrypto::~KSMIMECrypto
~KSMIMECrypto()
Definition: ksmimecrypto.cpp:297
KSMIMECrypto::rc
rc
Definition: ksmimecrypto.h:43
KSSLPKCS12::getPrivateKey
EVP_PKEY * getPrivateKey()
Get the private key.
Definition: ksslpkcs12.cpp:185
KSMIMECrypto::signMessage
rc signMessage(const QByteArray &clearText, QByteArray &cipherText, const KSSLPKCS12 &privKey, const QList< KSSLCertificate * > &certs, bool detached)
Sign a message.
Definition: ksmimecrypto.cpp:304
KSMIMECrypto::KSC_C_RC2_CBC_128
Definition: ksmimecrypto.h:38
KSMIMECrypto::KSC_R_NO_SSL
Definition: ksmimecrypto.h:45
KSMIMECrypto::KSC_C_RC2_CBC_40
Definition: ksmimecrypto.h:41
KSMIMECrypto::KSC_C_RC2_CBC_64
Definition: ksmimecrypto.h:39
KSMIMECrypto::checkDetachedSignature
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 ...
Definition: ksmimecrypto.cpp:331
ksslpkcs12.h
kopenssl.h
KSSLPKCS12::getCertificate
KSSLCertificate * getCertificate()
Get the X.509 certificate.
Definition: ksslpkcs12.cpp:190
sk_new
#define sk_new
Definition: ksmimecrypto.cpp:41
KSMIMECrypto::encryptMessage
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...
Definition: ksmimecrypto.cpp:375
KSMIMECrypto::KSC_R_OK
Definition: ksmimecrypto.h:43
KSMIMECrypto::checkOpaqueSignature
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...
Definition: ksmimecrypto.cpp:351
KOpenSSLProxy::self
static KOpenSSLProxy * self()
Return an instance of class KOpenSSLProxy * You cannot delete this object.
Definition: kopenssl.cpp:678
KSMIMECrypto::KSC_R_WRONGKEY
Definition: ksmimecrypto.h:49
QList
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:50:02 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal