• 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
42static const char eot = 0;
43
44class KSMIMECryptoPrivate {
45 KOpenSSLProxy *kossl;
46
47public:
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
76KSMIMECryptoPrivate::KSMIMECryptoPrivate(KOpenSSLProxy *kossl): kossl(kossl) {
77}
78
79
80STACK_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
91KSMIMECrypto::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
120KSMIMECrypto::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
164KSMIMECrypto::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
206KSMIMECrypto::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
228void 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
241KSMIMECrypto::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
280KSMIMECrypto::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
291KSMIMECrypto::~KSMIMECrypto() {
292#ifdef KSSL_HAVE_SSL
293 delete priv;
294#endif
295}
296
297
298KSMIMECrypto::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
325KSMIMECrypto::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
345KSMIMECrypto::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
369KSMIMECrypto::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
394KSMIMECrypto::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
KOpenSSLProxy
Dynamically load and wrap OpenSSL.
Definition: kopenssl.h:76
KOpenSSLProxy::self
static KOpenSSLProxy * self()
Return an instance of class KOpenSSLProxy * You cannot delete this object.
Definition: kopenssl.cpp:749
KSSLCertificate
KDE X.509 Certificate.
Definition: ksslcertificate.h:77
KSSLCertificate::fromX509
static KSSLCertificate * fromX509(X509 *x5)
Create an X.509 certificate from the internal representation.
Definition: ksslcertificate.cpp:139
KSSLPKCS12
KDE PKCS#12 Certificate.
Definition: ksslpkcs12.h:61
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

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
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/kssl by doxygen 1.9.4
This website is maintained by Timothy Pearson.