source: qca-tls/trunk/qca-tls.cpp@ 124

Last change on this file since 124 was 35, checked in by dmik, 19 years ago

QCA-TLS: Use 'const unsigned char' when OSSL_097 is defined.

  • Property svn:keywords set to Id
File size: 28.7 KB
Line 
1/*
2 * qca-tls.cpp - TLS plugin for QCA
3 * Copyright (C) 2003 Justin Karneges
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 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 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include"qca-tls.h"
22
23#include<qregexp.h>
24
25#include<openssl/sha.h>
26#include<openssl/md5.h>
27#include<openssl/evp.h>
28#include<openssl/bio.h>
29#include<openssl/pem.h>
30#include<openssl/rsa.h>
31#include<openssl/x509.h>
32#include<openssl/x509v3.h>
33#include<openssl/ssl.h>
34#include<openssl/err.h>
35#include<openssl/rand.h>
36
37#ifndef OSSL_097
38#define NO_AES
39#endif
40
41static QByteArray lib_randomArray(int size)
42{
43 if(RAND_status() == 0) {
44 srand(time(NULL));
45 char buf[128];
46 for(int n = 0; n < 128; ++n)
47 buf[n] = rand();
48 RAND_seed(buf, 128);
49 }
50 QByteArray a(size);
51 RAND_bytes((unsigned char *)a.data(), a.size());
52 return a;
53}
54
55static bool lib_generateKeyIV(const EVP_CIPHER *_type, const QByteArray &data, const QByteArray &salt, QByteArray *key, QByteArray *iv, int keysize=-1)
56{
57 QByteArray k, i;
58 unsigned char *kp = 0;
59 unsigned char *ip = 0;
60 EVP_CIPHER type = *_type;
61 if(keysize != -1)
62 type.key_len = keysize;
63 if(key) {
64 k.resize(type.key_len);
65 kp = (unsigned char *)k.data();
66 }
67 if(iv) {
68 i.resize(type.iv_len);
69 ip = (unsigned char *)i.data();
70 }
71 if(!EVP_BytesToKey(&type, EVP_sha1(), (unsigned char *)salt.data(), (unsigned char *)data.data(), data.size(), 1, kp, ip))
72 return false;
73 if(key)
74 *key = k;
75 if(iv)
76 *iv = i;
77 return true;
78}
79
80static void appendArray(QByteArray *a, const QByteArray &b)
81{
82 int oldsize = a->size();
83 a->resize(oldsize + b.size());
84 memcpy(a->data() + oldsize, b.data(), b.size());
85}
86
87static QByteArray bio2buf(BIO *b)
88{
89 QByteArray buf;
90 while(1) {
91 char block[1024];
92 int ret = BIO_read(b, block, 1024);
93 int oldsize = buf.size();
94 buf.resize(oldsize + ret);
95 memcpy(buf.data() + oldsize, block, ret);
96 if(ret != 1024)
97 break;
98 }
99 BIO_free(b);
100 return buf;
101}
102
103class SHA1Context : public QCA_HashContext
104{
105public:
106 SHA1Context()
107 {
108 reset();
109 }
110
111 QCA_HashContext *clone()
112 {
113 return new SHA1Context(*this);
114 }
115
116 void reset()
117 {
118 SHA1_Init(&c);
119 }
120
121 void update(const char *in, unsigned int len)
122 {
123 SHA1_Update(&c, in, len);
124 }
125
126 void final(QByteArray *out)
127 {
128 QByteArray buf(20);
129 SHA1_Final((unsigned char *)buf.data(), &c);
130 *out = buf;
131 }
132
133 SHA_CTX c;
134};
135
136class MD5Context : public QCA_HashContext
137{
138public:
139 MD5Context()
140 {
141 reset();
142 }
143
144 QCA_HashContext *clone()
145 {
146 return new MD5Context(*this);
147 }
148
149 void reset()
150 {
151 MD5_Init(&c);
152 }
153
154 void update(const char *in, unsigned int len)
155 {
156 MD5_Update(&c, in, len);
157 }
158
159 void final(QByteArray *out)
160 {
161 QByteArray buf(16);
162 MD5_Final((unsigned char *)buf.data(), &c);
163 *out = buf;
164 }
165
166 MD5_CTX c;
167};
168
169class EVPCipherContext : public QCA_CipherContext
170{
171public:
172 EVPCipherContext()
173 {
174 type = 0;
175 }
176
177 virtual ~EVPCipherContext()
178 {
179 if(type) {
180 EVP_CIPHER_CTX_cleanup(&c);
181 type = 0;
182 }
183 }
184
185 QCA_CipherContext *clone()
186 {
187 EVPCipherContext *cc = cloneSelf();
188 cc->r = r.copy();
189 return cc;
190 }
191
192 virtual EVPCipherContext *cloneSelf() const=0;
193 virtual const EVP_CIPHER *getType(int mode) const=0;
194
195 int keySize() { return getType(QCA::CBC)->key_len; }
196 int blockSize() { return getType(QCA::CBC)->block_size; }
197
198 bool generateKey(char *out, int keysize)
199 {
200 QByteArray a;
201 if(!lib_generateKeyIV(getType(QCA::CBC), lib_randomArray(128), lib_randomArray(2), &a, 0, keysize))
202 return false;
203 memcpy(out, a.data(), a.size());
204 return true;
205 }
206
207 bool generateIV(char *out)
208 {
209 QByteArray a;
210 if(!lib_generateKeyIV(getType(QCA::CBC), lib_randomArray(128), lib_randomArray(2), 0, &a))
211 return false;
212 memcpy(out, a.data(), a.size());
213 return true;
214 }
215
216 bool setup(int _dir, int mode, const char *key, int keysize, const char *iv, bool _pad)
217 {
218 dir = _dir;
219 pad = _pad;
220 type = getType(mode);
221 r.resize(0);
222 EVP_CIPHER_CTX_init(&c);
223
224 if(dir == QCA::Encrypt) {
225 if(!EVP_EncryptInit(&c, type, NULL, NULL))
226 return false;
227 if(keysize != type->key_len)
228 EVP_CIPHER_CTX_set_key_length(&c, keysize);
229 if(!EVP_EncryptInit(&c, NULL, (unsigned char *)key, (unsigned char *)iv))
230 return false;
231 }
232 else {
233 if(!EVP_DecryptInit(&c, type, NULL, NULL))
234 return false;
235 if(keysize != type->key_len)
236 EVP_CIPHER_CTX_set_key_length(&c, keysize);
237 if(!EVP_DecryptInit(&c, NULL, (unsigned char *)key, (unsigned char *)iv))
238 return false;
239 }
240 return true;
241 }
242
243 bool update(const char *in, unsigned int len)
244 {
245 QByteArray result(len + type->block_size);
246 int olen;
247 if(dir == QCA::Encrypt || !pad) {
248 if(!EVP_EncryptUpdate(&c, (unsigned char *)result.data(), &olen, (unsigned char *)in, len))
249 return false;
250 }
251 else {
252 if(!EVP_DecryptUpdate(&c, (unsigned char *)result.data(), &olen, (unsigned char *)in, len))
253 return false;
254 }
255 result.resize(olen);
256 appendArray(&r, result);
257 return true;
258 }
259
260 bool final(QByteArray *out)
261 {
262 if(pad) {
263 QByteArray result(type->block_size);
264 int olen;
265 if(dir == QCA::Encrypt) {
266 if(!EVP_EncryptFinal(&c, (unsigned char *)result.data(), &olen))
267 return false;
268 }
269 else {
270 if(!EVP_DecryptFinal(&c, (unsigned char *)result.data(), &olen))
271 return false;
272 }
273 result.resize(olen);
274 appendArray(&r, result);
275 }
276
277 *out = r.copy();
278 r.resize(0);
279 return true;
280 }
281
282 EVP_CIPHER_CTX c;
283 const EVP_CIPHER *type;
284 QByteArray r;
285 int dir;
286 bool pad;
287};
288
289class BlowFishContext : public EVPCipherContext
290{
291public:
292 EVPCipherContext *cloneSelf() const { return new BlowFishContext(*this); }
293 const EVP_CIPHER *getType(int mode) const
294 {
295 if(mode == QCA::CBC)
296 return EVP_bf_cbc();
297 else if(mode == QCA::CFB)
298 return EVP_bf_cfb();
299 else
300 return 0;
301 }
302};
303
304class TripleDESContext : public EVPCipherContext
305{
306public:
307 EVPCipherContext *cloneSelf() const { return new TripleDESContext(*this); }
308 const EVP_CIPHER *getType(int mode) const
309 {
310 if(mode == QCA::CBC)
311 return EVP_des_ede3_cbc();
312 else if(mode == QCA::CFB)
313 return EVP_des_ede3_cfb();
314 else
315 return 0;
316 }
317};
318
319#ifndef NO_AES
320class AES128Context : public EVPCipherContext
321{
322public:
323 EVPCipherContext *cloneSelf() const { return new AES128Context(*this); }
324 const EVP_CIPHER *getType(int mode) const
325 {
326 if(mode == QCA::CBC)
327 return EVP_aes_128_cbc();
328 else if(mode == QCA::CFB)
329 return EVP_aes_128_cfb();
330 else
331 return 0;
332 }
333};
334
335class AES256Context : public EVPCipherContext
336{
337public:
338 EVPCipherContext *cloneSelf() const { return new AES256Context(*this); }
339 const EVP_CIPHER *getType(int mode) const
340 {
341 if(mode == QCA::CBC)
342 return EVP_aes_256_cbc();
343 else if(mode == QCA::CFB)
344 return EVP_aes_256_cfb();
345 else
346 return 0;
347 }
348};
349#endif
350
351class RSAKeyContext : public QCA_RSAKeyContext
352{
353public:
354 RSAKeyContext()
355 {
356 pub = 0;
357 sec = 0;
358 }
359
360 ~RSAKeyContext()
361 {
362 reset();
363 }
364
365 void reset()
366 {
367 if(pub) {
368 RSA_free(pub);
369 pub = 0;
370 }
371 if(sec) {
372 RSA_free(sec);
373 sec = 0;
374 }
375 }
376
377 void separate(RSA *r, RSA **_pub, RSA **_sec)
378 {
379 // public
380 unsigned char *buf, *p;
381 int len = i2d_RSAPublicKey(r, NULL);
382 if(len > 0) {
383 buf = (unsigned char *)malloc(len);
384 p = buf;
385 i2d_RSAPublicKey(r, &p);
386 p = buf;
387#ifdef OSSL_097
388 *_pub = d2i_RSAPublicKey(NULL, (const unsigned char **)&p, len);
389#else
390 *_pub = d2i_RSAPublicKey(NULL, (unsigned char **)&p, len);
391#endif
392 free(buf);
393 }
394
395 len = i2d_RSAPrivateKey(r, NULL);
396 if(len > 0) {
397 buf = (unsigned char *)malloc(len);
398 p = buf;
399 i2d_RSAPrivateKey(r, &p);
400 p = buf;
401#ifdef OSSL_097
402 *_sec = d2i_RSAPrivateKey(NULL, (const unsigned char **)&p, len);
403#else
404 *_sec = d2i_RSAPrivateKey(NULL, (unsigned char **)&p, len);
405#endif
406 free(buf);
407 }
408 }
409
410 bool isNull() const
411 {
412 if(!pub && !sec)
413 return true;
414 return false;
415 }
416
417 bool havePublic() const
418 {
419 return pub ? true : false;
420 }
421
422 bool havePrivate() const
423 {
424 return sec ? true : false;
425 }
426
427 bool createFromDER(const char *in, unsigned int len)
428 {
429 RSA *r;
430 void *p;
431
432 // private?
433 p = (void *)in;
434#ifdef OSSL_097
435 r = d2i_RSAPrivateKey(NULL, (const unsigned char **)&p, len);
436#else
437 r = d2i_RSAPrivateKey(NULL, (unsigned char **)&p, len);
438#endif
439 if(r) {
440 reset();
441
442 // private means both, I think, so separate them
443 separate(r, &pub, &sec);
444 return true;
445 }
446 else {
447 // public?
448 p = (void *)in;
449#ifdef OSSL_097
450 r = d2i_RSAPublicKey(NULL, (const unsigned char **)&p, len);
451#else
452 r = d2i_RSAPublicKey(NULL, (unsigned char **)&p, len);
453#endif
454 if(!r) {
455 // try this other public function, for whatever reason
456 p = (void *)in;
457#ifdef OSSL_097
458 r = d2i_RSA_PUBKEY(NULL, (const unsigned char **)&p, len);
459#else
460 r = d2i_RSA_PUBKEY(NULL, (unsigned char **)&p, len);
461#endif
462 }
463 if(r) {
464 if(pub) {
465 RSA_free(pub);
466 }
467 pub = r;
468 return true;
469 }
470 }
471
472 return false;
473 }
474
475 bool createFromPEM(const char *in, unsigned int len)
476 {
477 BIO *bi;
478
479 // private?
480 bi = BIO_new(BIO_s_mem());
481 BIO_write(bi, in, len);
482 RSA *r = PEM_read_bio_RSAPrivateKey(bi, NULL, NULL, NULL);
483 BIO_free(bi);
484 if(r) {
485 reset();
486 separate(r, &pub, &sec);
487 return true;
488 }
489 else {
490 // public?
491 bi = BIO_new(BIO_s_mem());
492 BIO_write(bi, in, len);
493 r = PEM_read_bio_RSAPublicKey(bi, NULL, NULL, NULL);
494 BIO_free(bi);
495 if(r) {
496 if(pub) {
497 RSA_free(pub);
498 }
499 pub = r;
500 return true;
501 }
502 }
503
504 return false;
505 }
506
507 bool createFromNative(void *in)
508 {
509 reset();
510 separate((RSA *)in, &pub, &sec);
511 return true;
512 }
513
514 bool generate(unsigned int bits)
515 {
516 RSA *r = RSA_generate_key(bits, RSA_F4, NULL, NULL);
517 if(!r)
518 return false;
519 separate(r, &pub, &sec);
520 RSA_free(r);
521 return true;
522 }
523
524 QCA_RSAKeyContext *clone() const
525 {
526 // deep copy
527 RSAKeyContext *c = new RSAKeyContext;
528 if(pub) {
529 ++(pub->references);
530 c->pub = pub; //RSAPublicKey_dup(pub);
531 }
532 if(sec) {
533 ++(sec->references);
534 c->sec = sec; //RSAPrivateKey_dup(sec);
535 }
536 return c;
537 }
538
539 bool toDER(QByteArray *out, bool publicOnly)
540 {
541 if(sec && !publicOnly) {
542 int len = i2d_RSAPrivateKey(sec, NULL);
543 QByteArray buf(len);
544 unsigned char *p;
545 p = (unsigned char *)buf.data();
546 i2d_RSAPrivateKey(sec, &p);
547 *out = buf;
548 return true;
549 }
550 else if(pub) {
551 int len = i2d_RSAPublicKey(pub, NULL);
552 QByteArray buf(len);
553 unsigned char *p;
554 p = (unsigned char *)buf.data();
555 i2d_RSAPublicKey(pub, &p);
556 *out = buf;
557 return true;
558 }
559 else
560 return false;
561 }
562
563 bool toPEM(QByteArray *out, bool publicOnly)
564 {
565 if(sec && !publicOnly) {
566 BIO *bo = BIO_new(BIO_s_mem());
567 PEM_write_bio_RSAPrivateKey(bo, sec, NULL, NULL, 0, NULL, NULL);
568 *out = bio2buf(bo);
569 return true;
570 }
571 else if(pub) {
572 BIO *bo = BIO_new(BIO_s_mem());
573 PEM_write_bio_RSAPublicKey(bo, pub);
574 *out = bio2buf(bo);
575 return true;
576 }
577 else
578 return false;
579
580 }
581
582 bool encrypt(const QByteArray &in, QByteArray *out, bool oaep)
583 {
584 if(!pub)
585 return false;
586
587 int size = RSA_size(pub);
588 int flen = in.size();
589 if(oaep) {
590 if(flen >= size - 41)
591 flen = size - 41;
592 }
593 else {
594 if(flen >= size - 11)
595 flen = size - 11;
596 }
597 QByteArray result(size);
598 unsigned char *from = (unsigned char *)in.data();
599 unsigned char *to = (unsigned char *)result.data();
600 int ret = RSA_public_encrypt(flen, from, to, pub, oaep ? RSA_PKCS1_OAEP_PADDING : RSA_PKCS1_PADDING);
601 if(ret == -1)
602 return false;
603 result.resize(ret);
604
605 *out = result;
606 return true;
607 }
608
609 bool decrypt(const QByteArray &in, QByteArray *out, bool oaep)
610 {
611 if(!sec)
612 return false;
613
614 int size = RSA_size(sec);
615 int flen = in.size();
616 QByteArray result(size);
617 unsigned char *from = (unsigned char *)in.data();
618 unsigned char *to = (unsigned char *)result.data();
619 int ret = RSA_private_decrypt(flen, from, to, sec, oaep ? RSA_PKCS1_OAEP_PADDING : RSA_PKCS1_PADDING);
620 if(ret == -1)
621 return false;
622 result.resize(ret);
623
624 *out = result;
625 return true;
626 }
627
628 RSA *pub, *sec;
629};
630
631static QValueList<QCA_CertProperty> nameToProperties(struct X509_name_st *name)
632{
633 QValueList<QCA_CertProperty> list;
634
635 for(int n = 0; n < X509_NAME_entry_count(name); ++n) {
636 X509_NAME_ENTRY *ne = X509_NAME_get_entry(name, n);
637 QCA_CertProperty p;
638
639 ASN1_OBJECT *ao = X509_NAME_ENTRY_get_object(ne);
640 int nid = OBJ_obj2nid(ao);
641 if(nid == NID_undef)
642 continue;
643 p.var = OBJ_nid2sn(nid);
644
645 ASN1_STRING *as = X509_NAME_ENTRY_get_data(ne);
646 QCString c;
647 c.resize(as->length+1);
648 strncpy(c.data(), (char *)as->data, as->length);
649 p.val = QString::fromLatin1(c);
650 list += p;
651 }
652
653 return list;
654}
655
656// (taken from kdelibs) -- Justin
657//
658// This code is mostly taken from OpenSSL v0.9.5a
659// by Eric Young
660QDateTime ASN1_UTCTIME_QDateTime(ASN1_UTCTIME *tm, int *isGmt)
661{
662 QDateTime qdt;
663 char *v;
664 int gmt=0;
665 int i;
666 int y=0,M=0,d=0,h=0,m=0,s=0;
667 QDate qdate;
668 QTime qtime;
669
670 i = tm->length;
671 v = (char *)tm->data;
672
673 if (i < 10) goto auq_err;
674 if (v[i-1] == 'Z') gmt=1;
675 for (i=0; i<10; i++)
676 if ((v[i] > '9') || (v[i] < '0')) goto auq_err;
677 y = (v[0]-'0')*10+(v[1]-'0');
678 if (y < 50) y+=100;
679 M = (v[2]-'0')*10+(v[3]-'0');
680 if ((M > 12) || (M < 1)) goto auq_err;
681 d = (v[4]-'0')*10+(v[5]-'0');
682 h = (v[6]-'0')*10+(v[7]-'0');
683 m = (v[8]-'0')*10+(v[9]-'0');
684 if ( (v[10] >= '0') && (v[10] <= '9') &&
685 (v[11] >= '0') && (v[11] <= '9'))
686 s = (v[10]-'0')*10+(v[11]-'0');
687
688 // localize the date and display it.
689 qdate.setYMD(y+1900, M, d);
690 qtime.setHMS(h,m,s);
691 qdt.setDate(qdate); qdt.setTime(qtime);
692auq_err:
693 if (isGmt) *isGmt = gmt;
694 return qdt;
695}
696
697// (adapted from kdelibs) -- Justin
698static bool cnMatchesAddress(const QString &_cn, const QString &peerHost)
699{
700 QString cn = _cn.stripWhiteSpace().lower();
701 QRegExp rx;
702
703 // Check for invalid characters
704 if(QRegExp("[^a-zA-Z0-9\\.\\*\\-]").search(cn) >= 0)
705 return false;
706
707 // Domains can legally end with '.'s. We don't need them though.
708 while(cn.endsWith("."))
709 cn.truncate(cn.length()-1);
710
711 // Do not let empty CN's get by!!
712 if(cn.isEmpty())
713 return false;
714
715 // Check for IPv4 address
716 rx.setPattern("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}");
717 if(rx.exactMatch(peerHost))
718 return peerHost == cn;
719
720 // Check for IPv6 address here...
721 rx.setPattern("^\\[.*\\]$");
722 if(rx.exactMatch(peerHost))
723 return peerHost == cn;
724
725 if(cn.contains('*')) {
726 // First make sure that there are at least two valid parts
727 // after the wildcard (*).
728 QStringList parts = QStringList::split('.', cn, false);
729
730 while(parts.count() > 2)
731 parts.remove(parts.begin());
732
733 if(parts.count() != 2) {
734 return false; // we don't allow *.root - that's bad
735 }
736
737 if(parts[0].contains('*') || parts[1].contains('*')) {
738 return false;
739 }
740
741 // RFC2818 says that *.example.com should match against
742 // foo.example.com but not bar.foo.example.com
743 // (ie. they must have the same number of parts)
744 if(QRegExp(cn, false, true).exactMatch(peerHost) &&
745 QStringList::split('.', cn, false).count() ==
746 QStringList::split('.', peerHost, false).count())
747 return true;
748
749 return false;
750 }
751
752 // We must have an exact match in this case (insensitive though)
753 // (note we already did .lower())
754 if(cn == peerHost)
755 return true;
756 return false;
757}
758
759class CertContext : public QCA_CertContext
760{
761public:
762 CertContext()
763 {
764 x = 0;
765 }
766
767 ~CertContext()
768 {
769 reset();
770 }
771
772 QCA_CertContext *clone() const
773 {
774 CertContext *c = new CertContext(*this);
775 if(x) {
776 ++(x->references);
777 c->x = x;
778 }
779 return c;
780 }
781
782 void reset()
783 {
784 if(x) {
785 X509_free(x);
786 x = 0;
787
788 serial = "";
789 v_subject = "";
790 v_issuer = "";
791 cp_subject.clear();
792 cp_issuer.clear();
793 na = QDateTime();
794 nb = QDateTime();
795 }
796 }
797
798 bool isNull() const
799 {
800 return (x ? false: true);
801 }
802
803 bool createFromDER(const char *in, unsigned int len)
804 {
805#ifdef OSSL_097
806 const unsigned char *p = (const unsigned char *)in;
807#else
808 unsigned char *p = (unsigned char *)in;
809#endif
810 X509 *t = d2i_X509(NULL, &p, len);
811 if(!t)
812 return false;
813 fromX509(t);
814 X509_free(t);
815 return true;
816 }
817
818 bool createFromPEM(const char *in, unsigned int len)
819 {
820 BIO *bi = BIO_new(BIO_s_mem());
821 BIO_write(bi, in, len);
822 X509 *t = PEM_read_bio_X509(bi, NULL, NULL, NULL);
823 BIO_free(bi);
824 if(!t)
825 return false;
826 fromX509(t);
827 X509_free(t);
828 return true;
829 }
830
831 bool toDER(QByteArray *out)
832 {
833 int len = i2d_X509(x, NULL);
834 QByteArray buf(len);
835 unsigned char *p = (unsigned char *)buf.data();
836 i2d_X509(x, &p);
837 *out = buf;
838 return true;
839 }
840
841 bool toPEM(QByteArray *out)
842 {
843 BIO *bo = BIO_new(BIO_s_mem());
844 PEM_write_bio_X509(bo, x);
845 *out = bio2buf(bo);
846 return true;
847 }
848
849 void fromX509(X509 *t)
850 {
851 reset();
852 ++(t->references);
853 x = t;
854
855 // serial number
856 ASN1_INTEGER *ai = X509_get_serialNumber(x);
857 if(ai) {
858 char *rep = i2s_ASN1_INTEGER(NULL, ai);
859 serial = rep;
860 OPENSSL_free(rep);
861 }
862
863 // validity dates
864 nb = ASN1_UTCTIME_QDateTime(X509_get_notBefore(x), NULL);
865 na = ASN1_UTCTIME_QDateTime(X509_get_notAfter(x), NULL);
866
867 // extract the subject/issuer strings
868 struct X509_name_st *sn = X509_get_subject_name(x);
869 struct X509_name_st *in = X509_get_issuer_name(x);
870 char buf[1024];
871 X509_NAME_oneline(sn, buf, 1024);
872 v_subject = buf;
873 X509_NAME_oneline(in, buf, 1024);
874 v_issuer = buf;
875
876 // extract the subject/issuer contents
877 cp_subject = nameToProperties(sn);
878 cp_issuer = nameToProperties(in);
879 }
880
881 QString serialNumber() const
882 {
883 return serial;
884 }
885
886 QString subjectString() const
887 {
888 return v_subject;
889 }
890
891 QString issuerString() const
892 {
893 return v_issuer;
894 }
895
896 QValueList<QCA_CertProperty> subject() const
897 {
898 return cp_subject;
899 }
900
901 QValueList<QCA_CertProperty> issuer() const
902 {
903 return cp_issuer;
904 }
905
906 QDateTime notBefore() const
907 {
908 return nb;
909 }
910
911 QDateTime notAfter() const
912 {
913 return na;
914 }
915
916 bool matchesAddress(const QString &realHost) const
917 {
918 QString peerHost = realHost.stripWhiteSpace();
919 while(peerHost.endsWith("."))
920 peerHost.truncate(peerHost.length()-1);
921 peerHost = peerHost.lower();
922
923 QString cn;
924 for(QValueList<QCA_CertProperty>::ConstIterator it = cp_subject.begin(); it != cp_subject.end(); ++it) {
925 if((*it).var == "CN") {
926 cn = (*it).val;
927 break;
928 }
929 }
930 if(cnMatchesAddress(cn, peerHost))
931 return true;
932 return false;
933 }
934
935 X509 *x;
936 QString serial, v_subject, v_issuer;
937 QValueList<QCA_CertProperty> cp_subject, cp_issuer;
938 QDateTime nb, na;
939};
940
941static bool ssl_init = false;
942class TLSContext : public QCA_TLSContext
943{
944public:
945 enum { Good, TryAgain, Bad };
946 enum { Idle, Connect, Accept, Handshake, Active, Closing };
947
948 bool serv;
949 int mode;
950 QByteArray sendQueue, recvQueue;
951
952 CertContext *cert;
953 RSAKeyContext *key;
954
955 SSL *ssl;
956 SSL_METHOD *method;
957 SSL_CTX *context;
958 BIO *rbio, *wbio;
959 CertContext cc;
960 int vr;
961 bool v_eof;
962
963 TLSContext()
964 {
965 if(!ssl_init) {
966 SSL_library_init();
967 SSL_load_error_strings();
968 ssl_init = true;
969 }
970
971 ssl = 0;
972 context = 0;
973 cert = 0;
974 key = 0;
975 }
976
977 ~TLSContext()
978 {
979 reset();
980 }
981
982 void reset()
983 {
984 if(ssl) {
985 SSL_free(ssl);
986 ssl = 0;
987 }
988 if(context) {
989 SSL_CTX_free(context);
990 context = 0;
991 }
992 if(cert) {
993 delete cert;
994 cert = 0;
995 }
996 if(key) {
997 delete key;
998 key = 0;
999 }
1000
1001 sendQueue.resize(0);
1002 recvQueue.resize(0);
1003 mode = Idle;
1004 cc.reset();
1005 vr = QCA::TLS::Unknown;
1006 v_eof = false;
1007 }
1008
1009 bool eof() const
1010 {
1011 return v_eof;
1012 }
1013
1014 bool startClient(const QPtrList<QCA_CertContext> &store, const QCA_CertContext &_cert, const QCA_RSAKeyContext &_key)
1015 {
1016 reset();
1017 serv = false;
1018 method = SSLv23_client_method();
1019
1020 if(!setup(store, _cert, _key))
1021 return false;
1022
1023 mode = Connect;
1024 return true;
1025 }
1026
1027 bool startServer(const QPtrList<QCA_CertContext> &store, const QCA_CertContext &_cert, const QCA_RSAKeyContext &_key)
1028 {
1029 reset();
1030 serv = true;
1031 method = SSLv23_server_method();
1032
1033 if(!setup(store, _cert, _key))
1034 return false;
1035
1036 mode = Accept;
1037 return true;
1038 }
1039
1040 bool setup(const QPtrList<QCA_CertContext> &list, const QCA_CertContext &_cc, const QCA_RSAKeyContext &kc)
1041 {
1042 context = SSL_CTX_new(method);
1043 if(!context) {
1044 reset();
1045 return false;
1046 }
1047
1048 // load the cert store
1049 if(!list.isEmpty()) {
1050 X509_STORE *store = SSL_CTX_get_cert_store(context);
1051 QPtrListIterator<QCA_CertContext> it(list);
1052 for(CertContext *i; (i = (CertContext *)it.current()); ++it)
1053 X509_STORE_add_cert(store, i->x);
1054 }
1055
1056 ssl = SSL_new(context);
1057 if(!ssl) {
1058 reset();
1059 return false;
1060 }
1061 SSL_set_ssl_method(ssl, method); // can this return error?
1062
1063 // setup the memory bio
1064 rbio = BIO_new(BIO_s_mem());
1065 wbio = BIO_new(BIO_s_mem());
1066
1067 // this passes control of the bios to ssl. we don't need to free them.
1068 SSL_set_bio(ssl, rbio, wbio);
1069
1070 // setup the cert to send
1071 if(!_cc.isNull() && !kc.isNull()) {
1072 cert = static_cast<CertContext*>(_cc.clone());
1073 key = static_cast<RSAKeyContext*>(kc.clone());
1074 if(SSL_use_certificate(ssl, cert->x) != 1) {
1075 reset();
1076 return false;
1077 }
1078 if(SSL_use_RSAPrivateKey(ssl, key->sec) != 1) {
1079 reset();
1080 return false;
1081 }
1082 }
1083
1084 return true;
1085 }
1086
1087 int handshake(const QByteArray &in, QByteArray *out)
1088 {
1089 if(!in.isEmpty())
1090 BIO_write(rbio, in.data(), in.size());
1091
1092 if(mode == Connect) {
1093 int ret = doConnect();
1094 if(ret == Good) {
1095 mode = Handshake;
1096 }
1097 else if(ret == Bad) {
1098 reset();
1099 return Error;
1100 }
1101 }
1102
1103 if(mode == Accept) {
1104 int ret = doAccept();
1105 if(ret == Good) {
1106 getCert();
1107 mode = Active;
1108 }
1109 else if(ret == Bad) {
1110 reset();
1111 return Error;
1112 }
1113 }
1114
1115 if(mode == Handshake) {
1116 int ret = doHandshake();
1117 if(ret == Good) {
1118 getCert();
1119 mode = Active;
1120 }
1121 else if(ret == Bad) {
1122 reset();
1123 return Error;
1124 }
1125 }
1126
1127 // process outgoing
1128 *out = readOutgoing();
1129
1130 if(mode == Active)
1131 return Success;
1132 else
1133 return Continue;
1134 }
1135
1136 int shutdown(const QByteArray &in, QByteArray *out)
1137 {
1138 if(!in.isEmpty())
1139 BIO_write(rbio, in.data(), in.size());
1140
1141 int ret = doShutdown();
1142 if(ret == Bad) {
1143 reset();
1144 return Error;
1145 }
1146
1147 *out = readOutgoing();
1148
1149 if(ret == Good) {
1150 mode = Idle;
1151 return Success;
1152 }
1153 else {
1154 mode = Closing;
1155 return Continue;
1156 }
1157 }
1158
1159 void getCert()
1160 {
1161 // verify the certificate
1162 int code = QCA::TLS::Unknown;
1163 X509 *x = SSL_get_peer_certificate(ssl);
1164 if(x) {
1165 cc.fromX509(x);
1166 X509_free(x);
1167 int ret = SSL_get_verify_result(ssl);
1168 if(ret == X509_V_OK)
1169 code = QCA::TLS::Valid;
1170 else
1171 code = resultToCV(ret);
1172 }
1173 else {
1174 cc.reset();
1175 code = QCA::TLS::NoCert;
1176 }
1177 vr = code;
1178 }
1179
1180 bool encode(const QByteArray &plain, QByteArray *to_net, int *enc)
1181 {
1182 if(mode != Active)
1183 return false;
1184 appendArray(&sendQueue, plain);
1185
1186 int encoded = 0;
1187 if(sendQueue.size() > 0) {
1188 int ret = SSL_write(ssl, sendQueue.data(), sendQueue.size());
1189
1190 enum { Good, Continue, Done, Error };
1191 int m;
1192 if(ret <= 0) {
1193 int x = SSL_get_error(ssl, ret);
1194 if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
1195 m = Continue;
1196 else if(x == SSL_ERROR_ZERO_RETURN)
1197 m = Done;
1198 else
1199 m = Error;
1200 }
1201 else {
1202 m = Good;
1203 encoded = ret;
1204 int newsize = sendQueue.size() - encoded;
1205 char *r = sendQueue.data();
1206 memmove(r, r + encoded, newsize);
1207 sendQueue.resize(newsize);
1208 }
1209
1210 if(m == Done) {
1211 sendQueue.resize(0);
1212 v_eof = true;
1213 return false;
1214 }
1215 if(m == Error) {
1216 sendQueue.resize(0);
1217 return false;
1218 }
1219 }
1220
1221 *to_net = readOutgoing();
1222 *enc = encoded;
1223 return true;
1224 }
1225
1226 bool decode(const QByteArray &from_net, QByteArray *plain, QByteArray *to_net)
1227 {
1228 if(mode != Active)
1229 return false;
1230 if(!from_net.isEmpty())
1231 BIO_write(rbio, from_net.data(), from_net.size());
1232
1233 QByteArray a;
1234 while(!v_eof) {
1235 a.resize(8192);
1236 int ret = SSL_read(ssl, a.data(), a.size());
1237 if(ret > 0) {
1238 if(ret != (int)a.size())
1239 a.resize(ret);
1240 appendArray(&recvQueue, a);
1241 }
1242 else if(ret <= 0) {
1243 int x = SSL_get_error(ssl, ret);
1244 if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
1245 break;
1246 else if(x == SSL_ERROR_ZERO_RETURN)
1247 v_eof = true;
1248 else
1249 return false;
1250 }
1251 }
1252
1253 *plain = recvQueue.copy();
1254 recvQueue.resize(0);
1255
1256 // could be outgoing data also
1257 *to_net = readOutgoing();
1258 return true;
1259 }
1260
1261 QByteArray unprocessed()
1262 {
1263 QByteArray a;
1264 int size = BIO_pending(rbio);
1265 if(size <= 0)
1266 return a;
1267 a.resize(size);
1268
1269 int r = BIO_read(rbio, a.data(), size);
1270 if(r <= 0) {
1271 a.resize(0);
1272 return a;
1273 }
1274 if(r != size)
1275 a.resize(r);
1276 return a;
1277 }
1278
1279 QByteArray readOutgoing()
1280 {
1281 QByteArray a;
1282 int size = BIO_pending(wbio);
1283 if(size <= 0)
1284 return a;
1285 a.resize(size);
1286
1287 int r = BIO_read(wbio, a.data(), size);
1288 if(r <= 0) {
1289 a.resize(0);
1290 return a;
1291 }
1292 if(r != size)
1293 a.resize(r);
1294 return a;
1295 }
1296
1297 int doConnect()
1298 {
1299 int ret = SSL_connect(ssl);
1300 if(ret < 0) {
1301 int x = SSL_get_error(ssl, ret);
1302 if(x == SSL_ERROR_WANT_CONNECT || x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
1303 return TryAgain;
1304 else
1305 return Bad;
1306 }
1307 else if(ret == 0)
1308 return Bad;
1309 return Good;
1310 }
1311
1312 int doAccept()
1313 {
1314 int ret = SSL_accept(ssl);
1315 if(ret < 0) {
1316 int x = SSL_get_error(ssl, ret);
1317 if(x == SSL_ERROR_WANT_CONNECT || x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
1318 return TryAgain;
1319 else
1320 return Bad;
1321 }
1322 else if(ret == 0)
1323 return Bad;
1324 return Good;
1325 }
1326
1327 int doHandshake()
1328 {
1329 int ret = SSL_do_handshake(ssl);
1330 if(ret < 0) {
1331 int x = SSL_get_error(ssl, ret);
1332 if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
1333 return TryAgain;
1334 else
1335 return Bad;
1336 }
1337 else if(ret == 0)
1338 return Bad;
1339 return Good;
1340 }
1341
1342 int doShutdown()
1343 {
1344 int ret = SSL_shutdown(ssl);
1345 if(ret >= 1)
1346 return Good;
1347 else {
1348 if(ret == 0)
1349 return TryAgain;
1350 int x = SSL_get_error(ssl, ret);
1351 if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
1352 return TryAgain;
1353 return Bad;
1354 }
1355 }
1356
1357 QCA_CertContext *peerCertificate() const
1358 {
1359 return cc.clone();
1360 }
1361
1362 int validityResult() const
1363 {
1364 return vr;
1365 }
1366
1367 int resultToCV(int ret) const
1368 {
1369 int rc;
1370
1371 switch(ret) {
1372 case X509_V_ERR_CERT_REJECTED:
1373 rc = QCA::TLS::Rejected;
1374 break;
1375 case X509_V_ERR_CERT_UNTRUSTED:
1376 rc = QCA::TLS::Untrusted;
1377 break;
1378 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
1379 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
1380 case X509_V_ERR_CRL_SIGNATURE_FAILURE:
1381 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
1382 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
1383 rc = QCA::TLS::SignatureFailed;
1384 break;
1385 case X509_V_ERR_INVALID_CA:
1386 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
1387 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
1388 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
1389 rc = QCA::TLS::InvalidCA;
1390 break;
1391 case X509_V_ERR_INVALID_PURPOSE:
1392 rc = QCA::TLS::InvalidPurpose;
1393 break;
1394 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
1395 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
1396 rc = QCA::TLS::SelfSigned;
1397 break;
1398 case X509_V_ERR_CERT_REVOKED:
1399 rc = QCA::TLS::Revoked;
1400 break;
1401 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
1402 rc = QCA::TLS::PathLengthExceeded;
1403 break;
1404 case X509_V_ERR_CERT_NOT_YET_VALID:
1405 case X509_V_ERR_CERT_HAS_EXPIRED:
1406 case X509_V_ERR_CRL_NOT_YET_VALID:
1407 case X509_V_ERR_CRL_HAS_EXPIRED:
1408 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
1409 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
1410 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
1411 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
1412 rc = QCA::TLS::Expired;
1413 break;
1414 case X509_V_ERR_APPLICATION_VERIFICATION:
1415 case X509_V_ERR_OUT_OF_MEM:
1416 case X509_V_ERR_UNABLE_TO_GET_CRL:
1417 case X509_V_ERR_CERT_CHAIN_TOO_LONG:
1418 default:
1419 rc = QCA::TLS::Unknown;
1420 break;
1421 }
1422 return rc;
1423 }
1424};
1425
1426class QCAOpenSSL : public QCAProvider
1427{
1428public:
1429 QCAOpenSSL() {}
1430 ~QCAOpenSSL() {}
1431
1432 void init()
1433 {
1434 }
1435
1436 int qcaVersion() const
1437 {
1438 return QCA_PLUGIN_VERSION;
1439 }
1440
1441 int capabilities() const
1442 {
1443 int caps =
1444 QCA::CAP_SHA1 |
1445 QCA::CAP_MD5 |
1446 QCA::CAP_BlowFish |
1447 QCA::CAP_TripleDES |
1448#ifndef NO_AES
1449 QCA::CAP_AES128 |
1450 QCA::CAP_AES256 |
1451#endif
1452 QCA::CAP_RSA |
1453 QCA::CAP_X509 |
1454 QCA::CAP_TLS;
1455 return caps;
1456 }
1457
1458 void *context(int cap)
1459 {
1460 if(cap == QCA::CAP_SHA1)
1461 return new SHA1Context;
1462 else if(cap == QCA::CAP_MD5)
1463 return new MD5Context;
1464 else if(cap == QCA::CAP_BlowFish)
1465 return new BlowFishContext;
1466 else if(cap == QCA::CAP_TripleDES)
1467 return new TripleDESContext;
1468#ifndef NO_AES
1469 else if(cap == QCA::CAP_AES128)
1470 return new AES128Context;
1471 else if(cap == QCA::CAP_AES256)
1472 return new AES256Context;
1473#endif
1474 else if(cap == QCA::CAP_RSA)
1475 return new RSAKeyContext;
1476 else if(cap == QCA::CAP_X509)
1477 return new CertContext;
1478 else if(cap == QCA::CAP_TLS)
1479 return new TLSContext;
1480 return 0;
1481 }
1482};
1483
1484#ifdef QCA_PLUGIN
1485QCAProvider *createProvider()
1486#else
1487QCAProvider *createProviderTLS()
1488#endif
1489{
1490 return (new QCAOpenSSL);
1491}
Note: See TracBrowser for help on using the repository browser.