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

KIO

  • 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
50static const char eot = 0;
51
52class KSMIMECryptoPrivate {
53 KOpenSSLProxy *kossl;
54
55public:
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
84KSMIMECryptoPrivate::KSMIMECryptoPrivate(KOpenSSLProxy *kossl): kossl(kossl) {
85}
86
87
88STACK_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
97KSMIMECrypto::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
126KSMIMECrypto::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
170KSMIMECrypto::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
212KSMIMECrypto::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
234void 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
246KSMIMECrypto::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
285KSMIMECrypto::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
297KSMIMECrypto::~KSMIMECrypto() {
298#ifdef KSSL_HAVE_SSL
299 delete priv;
300#endif
301}
302
303
304KSMIMECrypto::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
331KSMIMECrypto::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
351KSMIMECrypto::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
375KSMIMECrypto::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
400KSMIMECrypto::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}
KOpenSSLProxy
Dynamically load and wrap OpenSSL.
Definition: kopenssl.h:65
KOpenSSLProxy::hasLibCrypto
bool hasLibCrypto() const
Return true of libcrypto was found and loaded.
Definition: kopenssl.cpp:246
KOpenSSLProxy::self
static KOpenSSLProxy * self()
Return an instance of class KOpenSSLProxy * You cannot delete this object.
Definition: kopenssl.cpp:722
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::decryptMessage
rc decryptMessage(const QByteArray &cipherText, QByteArray &clearText, const KSSLPKCS12 &privKey)
Decrypt a message.
Definition: ksmimecrypto.cpp:400
KSMIMECrypto::rc
rc
Definition: ksmimecrypto.h:43
KSMIMECrypto::KSC_R_OTHER
@ KSC_R_OTHER
Definition: ksmimecrypto.h:44
KSMIMECrypto::KSC_R_VERIFY
@ KSC_R_VERIFY
Definition: ksmimecrypto.h:50
KSMIMECrypto::KSC_R_WRONGKEY
@ KSC_R_WRONGKEY
Definition: ksmimecrypto.h:49
KSMIMECrypto::KSC_R_NO_SSL
@ KSC_R_NO_SSL
Definition: ksmimecrypto.h:45
KSMIMECrypto::KSC_R_OK
@ KSC_R_OK
Definition: ksmimecrypto.h:43
KSMIMECrypto::KSC_R_NOMEM
@ KSC_R_NOMEM
Definition: ksmimecrypto.h:47
KSMIMECrypto::KSC_R_NOCIPHER
@ KSC_R_NOCIPHER
Definition: ksmimecrypto.h:46
KSMIMECrypto::KSC_R_FORMAT
@ KSC_R_FORMAT
Definition: ksmimecrypto.h:48
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::~KSMIMECrypto
~KSMIMECrypto()
Definition: ksmimecrypto.cpp:297
KSMIMECrypto::algo
algo
Definition: ksmimecrypto.h:37
KSMIMECrypto::KSC_C_RC2_CBC_128
@ KSC_C_RC2_CBC_128
Definition: ksmimecrypto.h:38
KSMIMECrypto::KSC_C_RC2_CBC_64
@ KSC_C_RC2_CBC_64
Definition: ksmimecrypto.h:39
KSMIMECrypto::KSC_C_RC2_CBC_40
@ KSC_C_RC2_CBC_40
Definition: ksmimecrypto.h:41
KSMIMECrypto::KSC_C_DES3_CBC
@ KSC_C_DES3_CBC
Definition: ksmimecrypto.h:37
KSMIMECrypto::KSC_C_DES_CBC
@ KSC_C_DES_CBC
Definition: ksmimecrypto.h:40
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
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
KSMIMECrypto::KSMIMECrypto
KSMIMECrypto()
Definition: ksmimecrypto.cpp:285
KSSLCertificate
KDE X.509 Certificate.
Definition: ksslcertificate.h:75
KSSLCertificate::getCert
X509 * getCert()
Definition: ksslcertificate.cpp:580
KSSLCertificate::fromX509
static KSSLCertificate * fromX509(X509 *x5)
Create an X.509 certificate from the internal representation.
Definition: ksslcertificate.cpp:133
KSSLPKCS12
KDE PKCS#12 Certificate.
Definition: ksslpkcs12.h:63
KSSLPKCS12::getPrivateKey
EVP_PKEY * getPrivateKey()
Get the private key.
Definition: ksslpkcs12.cpp:185
KSSLPKCS12::getCertificate
KSSLCertificate * getCertificate()
Get the X.509 certificate.
Definition: ksslpkcs12.cpp:190
QList
kDebug
#define kDebug
kdebug.h
kopenssl.h
sk_new
#define sk_new
Definition: ksmimecrypto.cpp:41
ksmimecrypto.h
ksslcertificate.h
ksslpkcs12.h
STACK_OF
#define STACK_OF(x)
Definition: ksslpkcs12.h:46
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 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-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 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
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
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