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

Last change on this file since 34 was 31, checked in by dmik, 19 years ago

QCA-TLS: Imported original QCA TLS 1.0 sources from Affinix

  • Property svn:keywords set to Id
File size: 28.5 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 r = d2i_RSA_PUBKEY(NULL, (unsigned char **)&p, len);
458 }
459 if(r) {
460 if(pub) {
461 RSA_free(pub);
462 }
463 pub = r;
464 return true;
465 }
466 }
467
468 return false;
469 }
470
471 bool createFromPEM(const char *in, unsigned int len)
472 {
473 BIO *bi;
474
475 // private?
476 bi = BIO_new(BIO_s_mem());
477 BIO_write(bi, in, len);
478 RSA *r = PEM_read_bio_RSAPrivateKey(bi, NULL, NULL, NULL);
479 BIO_free(bi);
480 if(r) {
481 reset();
482 separate(r, &pub, &sec);
483 return true;
484 }
485 else {
486 // public?
487 bi = BIO_new(BIO_s_mem());
488 BIO_write(bi, in, len);
489 r = PEM_read_bio_RSAPublicKey(bi, NULL, NULL, NULL);
490 BIO_free(bi);
491 if(r) {
492 if(pub) {
493 RSA_free(pub);
494 }
495 pub = r;
496 return true;
497 }
498 }
499
500 return false;
501 }
502
503 bool createFromNative(void *in)
504 {
505 reset();
506 separate((RSA *)in, &pub, &sec);
507 return true;
508 }
509
510 bool generate(unsigned int bits)
511 {
512 RSA *r = RSA_generate_key(bits, RSA_F4, NULL, NULL);
513 if(!r)
514 return false;
515 separate(r, &pub, &sec);
516 RSA_free(r);
517 return true;
518 }
519
520 QCA_RSAKeyContext *clone() const
521 {
522 // deep copy
523 RSAKeyContext *c = new RSAKeyContext;
524 if(pub) {
525 ++(pub->references);
526 c->pub = pub; //RSAPublicKey_dup(pub);
527 }
528 if(sec) {
529 ++(sec->references);
530 c->sec = sec; //RSAPrivateKey_dup(sec);
531 }
532 return c;
533 }
534
535 bool toDER(QByteArray *out, bool publicOnly)
536 {
537 if(sec && !publicOnly) {
538 int len = i2d_RSAPrivateKey(sec, NULL);
539 QByteArray buf(len);
540 unsigned char *p;
541 p = (unsigned char *)buf.data();
542 i2d_RSAPrivateKey(sec, &p);
543 *out = buf;
544 return true;
545 }
546 else if(pub) {
547 int len = i2d_RSAPublicKey(pub, NULL);
548 QByteArray buf(len);
549 unsigned char *p;
550 p = (unsigned char *)buf.data();
551 i2d_RSAPublicKey(pub, &p);
552 *out = buf;
553 return true;
554 }
555 else
556 return false;
557 }
558
559 bool toPEM(QByteArray *out, bool publicOnly)
560 {
561 if(sec && !publicOnly) {
562 BIO *bo = BIO_new(BIO_s_mem());
563 PEM_write_bio_RSAPrivateKey(bo, sec, NULL, NULL, 0, NULL, NULL);
564 *out = bio2buf(bo);
565 return true;
566 }
567 else if(pub) {
568 BIO *bo = BIO_new(BIO_s_mem());
569 PEM_write_bio_RSAPublicKey(bo, pub);
570 *out = bio2buf(bo);
571 return true;
572 }
573 else
574 return false;
575
576 }
577
578 bool encrypt(const QByteArray &in, QByteArray *out, bool oaep)
579 {
580 if(!pub)
581 return false;
582
583 int size = RSA_size(pub);
584 int flen = in.size();
585 if(oaep) {
586 if(flen >= size - 41)
587 flen = size - 41;
588 }
589 else {
590 if(flen >= size - 11)
591 flen = size - 11;
592 }
593 QByteArray result(size);
594 unsigned char *from = (unsigned char *)in.data();
595 unsigned char *to = (unsigned char *)result.data();
596 int ret = RSA_public_encrypt(flen, from, to, pub, oaep ? RSA_PKCS1_OAEP_PADDING : RSA_PKCS1_PADDING);
597 if(ret == -1)
598 return false;
599 result.resize(ret);
600
601 *out = result;
602 return true;
603 }
604
605 bool decrypt(const QByteArray &in, QByteArray *out, bool oaep)
606 {
607 if(!sec)
608 return false;
609
610 int size = RSA_size(sec);
611 int flen = in.size();
612 QByteArray result(size);
613 unsigned char *from = (unsigned char *)in.data();
614 unsigned char *to = (unsigned char *)result.data();
615 int ret = RSA_private_decrypt(flen, from, to, sec, oaep ? RSA_PKCS1_OAEP_PADDING : RSA_PKCS1_PADDING);
616 if(ret == -1)
617 return false;
618 result.resize(ret);
619
620 *out = result;
621 return true;
622 }
623
624 RSA *pub, *sec;
625};
626
627static QValueList<QCA_CertProperty> nameToProperties(struct X509_name_st *name)
628{
629 QValueList<QCA_CertProperty> list;
630
631 for(int n = 0; n < X509_NAME_entry_count(name); ++n) {
632 X509_NAME_ENTRY *ne = X509_NAME_get_entry(name, n);
633 QCA_CertProperty p;
634
635 ASN1_OBJECT *ao = X509_NAME_ENTRY_get_object(ne);
636 int nid = OBJ_obj2nid(ao);
637 if(nid == NID_undef)
638 continue;
639 p.var = OBJ_nid2sn(nid);
640
641 ASN1_STRING *as = X509_NAME_ENTRY_get_data(ne);
642 QCString c;
643 c.resize(as->length+1);
644 strncpy(c.data(), (char *)as->data, as->length);
645 p.val = QString::fromLatin1(c);
646 list += p;
647 }
648
649 return list;
650}
651
652// (taken from kdelibs) -- Justin
653//
654// This code is mostly taken from OpenSSL v0.9.5a
655// by Eric Young
656QDateTime ASN1_UTCTIME_QDateTime(ASN1_UTCTIME *tm, int *isGmt)
657{
658 QDateTime qdt;
659 char *v;
660 int gmt=0;
661 int i;
662 int y=0,M=0,d=0,h=0,m=0,s=0;
663 QDate qdate;
664 QTime qtime;
665
666 i = tm->length;
667 v = (char *)tm->data;
668
669 if (i < 10) goto auq_err;
670 if (v[i-1] == 'Z') gmt=1;
671 for (i=0; i<10; i++)
672 if ((v[i] > '9') || (v[i] < '0')) goto auq_err;
673 y = (v[0]-'0')*10+(v[1]-'0');
674 if (y < 50) y+=100;
675 M = (v[2]-'0')*10+(v[3]-'0');
676 if ((M > 12) || (M < 1)) goto auq_err;
677 d = (v[4]-'0')*10+(v[5]-'0');
678 h = (v[6]-'0')*10+(v[7]-'0');
679 m = (v[8]-'0')*10+(v[9]-'0');
680 if ( (v[10] >= '0') && (v[10] <= '9') &&
681 (v[11] >= '0') && (v[11] <= '9'))
682 s = (v[10]-'0')*10+(v[11]-'0');
683
684 // localize the date and display it.
685 qdate.setYMD(y+1900, M, d);
686 qtime.setHMS(h,m,s);
687 qdt.setDate(qdate); qdt.setTime(qtime);
688auq_err:
689 if (isGmt) *isGmt = gmt;
690 return qdt;
691}
692
693// (adapted from kdelibs) -- Justin
694static bool cnMatchesAddress(const QString &_cn, const QString &peerHost)
695{
696 QString cn = _cn.stripWhiteSpace().lower();
697 QRegExp rx;
698
699 // Check for invalid characters
700 if(QRegExp("[^a-zA-Z0-9\\.\\*\\-]").search(cn) >= 0)
701 return false;
702
703 // Domains can legally end with '.'s. We don't need them though.
704 while(cn.endsWith("."))
705 cn.truncate(cn.length()-1);
706
707 // Do not let empty CN's get by!!
708 if(cn.isEmpty())
709 return false;
710
711 // Check for IPv4 address
712 rx.setPattern("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}");
713 if(rx.exactMatch(peerHost))
714 return peerHost == cn;
715
716 // Check for IPv6 address here...
717 rx.setPattern("^\\[.*\\]$");
718 if(rx.exactMatch(peerHost))
719 return peerHost == cn;
720
721 if(cn.contains('*')) {
722 // First make sure that there are at least two valid parts
723 // after the wildcard (*).
724 QStringList parts = QStringList::split('.', cn, false);
725
726 while(parts.count() > 2)
727 parts.remove(parts.begin());
728
729 if(parts.count() != 2) {
730 return false; // we don't allow *.root - that's bad
731 }
732
733 if(parts[0].contains('*') || parts[1].contains('*')) {
734 return false;
735 }
736
737 // RFC2818 says that *.example.com should match against
738 // foo.example.com but not bar.foo.example.com
739 // (ie. they must have the same number of parts)
740 if(QRegExp(cn, false, true).exactMatch(peerHost) &&
741 QStringList::split('.', cn, false).count() ==
742 QStringList::split('.', peerHost, false).count())
743 return true;
744
745 return false;
746 }
747
748 // We must have an exact match in this case (insensitive though)
749 // (note we already did .lower())
750 if(cn == peerHost)
751 return true;
752 return false;
753}
754
755class CertContext : public QCA_CertContext
756{
757public:
758 CertContext()
759 {
760 x = 0;
761 }
762
763 ~CertContext()
764 {
765 reset();
766 }
767
768 QCA_CertContext *clone() const
769 {
770 CertContext *c = new CertContext(*this);
771 if(x) {
772 ++(x->references);
773 c->x = x;
774 }
775 return c;
776 }
777
778 void reset()
779 {
780 if(x) {
781 X509_free(x);
782 x = 0;
783
784 serial = "";
785 v_subject = "";
786 v_issuer = "";
787 cp_subject.clear();
788 cp_issuer.clear();
789 na = QDateTime();
790 nb = QDateTime();
791 }
792 }
793
794 bool isNull() const
795 {
796 return (x ? false: true);
797 }
798
799 bool createFromDER(const char *in, unsigned int len)
800 {
801 unsigned char *p = (unsigned char *)in;
802 X509 *t = d2i_X509(NULL, &p, len);
803 if(!t)
804 return false;
805 fromX509(t);
806 X509_free(t);
807 return true;
808 }
809
810 bool createFromPEM(const char *in, unsigned int len)
811 {
812 BIO *bi = BIO_new(BIO_s_mem());
813 BIO_write(bi, in, len);
814 X509 *t = PEM_read_bio_X509(bi, NULL, NULL, NULL);
815 BIO_free(bi);
816 if(!t)
817 return false;
818 fromX509(t);
819 X509_free(t);
820 return true;
821 }
822
823 bool toDER(QByteArray *out)
824 {
825 int len = i2d_X509(x, NULL);
826 QByteArray buf(len);
827 unsigned char *p = (unsigned char *)buf.data();
828 i2d_X509(x, &p);
829 *out = buf;
830 return true;
831 }
832
833 bool toPEM(QByteArray *out)
834 {
835 BIO *bo = BIO_new(BIO_s_mem());
836 PEM_write_bio_X509(bo, x);
837 *out = bio2buf(bo);
838 return true;
839 }
840
841 void fromX509(X509 *t)
842 {
843 reset();
844 ++(t->references);
845 x = t;
846
847 // serial number
848 ASN1_INTEGER *ai = X509_get_serialNumber(x);
849 if(ai) {
850 char *rep = i2s_ASN1_INTEGER(NULL, ai);
851 serial = rep;
852 OPENSSL_free(rep);
853 }
854
855 // validity dates
856 nb = ASN1_UTCTIME_QDateTime(X509_get_notBefore(x), NULL);
857 na = ASN1_UTCTIME_QDateTime(X509_get_notAfter(x), NULL);
858
859 // extract the subject/issuer strings
860 struct X509_name_st *sn = X509_get_subject_name(x);
861 struct X509_name_st *in = X509_get_issuer_name(x);
862 char buf[1024];
863 X509_NAME_oneline(sn, buf, 1024);
864 v_subject = buf;
865 X509_NAME_oneline(in, buf, 1024);
866 v_issuer = buf;
867
868 // extract the subject/issuer contents
869 cp_subject = nameToProperties(sn);
870 cp_issuer = nameToProperties(in);
871 }
872
873 QString serialNumber() const
874 {
875 return serial;
876 }
877
878 QString subjectString() const
879 {
880 return v_subject;
881 }
882
883 QString issuerString() const
884 {
885 return v_issuer;
886 }
887
888 QValueList<QCA_CertProperty> subject() const
889 {
890 return cp_subject;
891 }
892
893 QValueList<QCA_CertProperty> issuer() const
894 {
895 return cp_issuer;
896 }
897
898 QDateTime notBefore() const
899 {
900 return nb;
901 }
902
903 QDateTime notAfter() const
904 {
905 return na;
906 }
907
908 bool matchesAddress(const QString &realHost) const
909 {
910 QString peerHost = realHost.stripWhiteSpace();
911 while(peerHost.endsWith("."))
912 peerHost.truncate(peerHost.length()-1);
913 peerHost = peerHost.lower();
914
915 QString cn;
916 for(QValueList<QCA_CertProperty>::ConstIterator it = cp_subject.begin(); it != cp_subject.end(); ++it) {
917 if((*it).var == "CN") {
918 cn = (*it).val;
919 break;
920 }
921 }
922 if(cnMatchesAddress(cn, peerHost))
923 return true;
924 return false;
925 }
926
927 X509 *x;
928 QString serial, v_subject, v_issuer;
929 QValueList<QCA_CertProperty> cp_subject, cp_issuer;
930 QDateTime nb, na;
931};
932
933static bool ssl_init = false;
934class TLSContext : public QCA_TLSContext
935{
936public:
937 enum { Good, TryAgain, Bad };
938 enum { Idle, Connect, Accept, Handshake, Active, Closing };
939
940 bool serv;
941 int mode;
942 QByteArray sendQueue, recvQueue;
943
944 CertContext *cert;
945 RSAKeyContext *key;
946
947 SSL *ssl;
948 SSL_METHOD *method;
949 SSL_CTX *context;
950 BIO *rbio, *wbio;
951 CertContext cc;
952 int vr;
953 bool v_eof;
954
955 TLSContext()
956 {
957 if(!ssl_init) {
958 SSL_library_init();
959 SSL_load_error_strings();
960 ssl_init = true;
961 }
962
963 ssl = 0;
964 context = 0;
965 cert = 0;
966 key = 0;
967 }
968
969 ~TLSContext()
970 {
971 reset();
972 }
973
974 void reset()
975 {
976 if(ssl) {
977 SSL_free(ssl);
978 ssl = 0;
979 }
980 if(context) {
981 SSL_CTX_free(context);
982 context = 0;
983 }
984 if(cert) {
985 delete cert;
986 cert = 0;
987 }
988 if(key) {
989 delete key;
990 key = 0;
991 }
992
993 sendQueue.resize(0);
994 recvQueue.resize(0);
995 mode = Idle;
996 cc.reset();
997 vr = QCA::TLS::Unknown;
998 v_eof = false;
999 }
1000
1001 bool eof() const
1002 {
1003 return v_eof;
1004 }
1005
1006 bool startClient(const QPtrList<QCA_CertContext> &store, const QCA_CertContext &_cert, const QCA_RSAKeyContext &_key)
1007 {
1008 reset();
1009 serv = false;
1010 method = SSLv23_client_method();
1011
1012 if(!setup(store, _cert, _key))
1013 return false;
1014
1015 mode = Connect;
1016 return true;
1017 }
1018
1019 bool startServer(const QPtrList<QCA_CertContext> &store, const QCA_CertContext &_cert, const QCA_RSAKeyContext &_key)
1020 {
1021 reset();
1022 serv = true;
1023 method = SSLv23_server_method();
1024
1025 if(!setup(store, _cert, _key))
1026 return false;
1027
1028 mode = Accept;
1029 return true;
1030 }
1031
1032 bool setup(const QPtrList<QCA_CertContext> &list, const QCA_CertContext &_cc, const QCA_RSAKeyContext &kc)
1033 {
1034 context = SSL_CTX_new(method);
1035 if(!context) {
1036 reset();
1037 return false;
1038 }
1039
1040 // load the cert store
1041 if(!list.isEmpty()) {
1042 X509_STORE *store = SSL_CTX_get_cert_store(context);
1043 QPtrListIterator<QCA_CertContext> it(list);
1044 for(CertContext *i; (i = (CertContext *)it.current()); ++it)
1045 X509_STORE_add_cert(store, i->x);
1046 }
1047
1048 ssl = SSL_new(context);
1049 if(!ssl) {
1050 reset();
1051 return false;
1052 }
1053 SSL_set_ssl_method(ssl, method); // can this return error?
1054
1055 // setup the memory bio
1056 rbio = BIO_new(BIO_s_mem());
1057 wbio = BIO_new(BIO_s_mem());
1058
1059 // this passes control of the bios to ssl. we don't need to free them.
1060 SSL_set_bio(ssl, rbio, wbio);
1061
1062 // setup the cert to send
1063 if(!_cc.isNull() && !kc.isNull()) {
1064 cert = static_cast<CertContext*>(_cc.clone());
1065 key = static_cast<RSAKeyContext*>(kc.clone());
1066 if(SSL_use_certificate(ssl, cert->x) != 1) {
1067 reset();
1068 return false;
1069 }
1070 if(SSL_use_RSAPrivateKey(ssl, key->sec) != 1) {
1071 reset();
1072 return false;
1073 }
1074 }
1075
1076 return true;
1077 }
1078
1079 int handshake(const QByteArray &in, QByteArray *out)
1080 {
1081 if(!in.isEmpty())
1082 BIO_write(rbio, in.data(), in.size());
1083
1084 if(mode == Connect) {
1085 int ret = doConnect();
1086 if(ret == Good) {
1087 mode = Handshake;
1088 }
1089 else if(ret == Bad) {
1090 reset();
1091 return Error;
1092 }
1093 }
1094
1095 if(mode == Accept) {
1096 int ret = doAccept();
1097 if(ret == Good) {
1098 getCert();
1099 mode = Active;
1100 }
1101 else if(ret == Bad) {
1102 reset();
1103 return Error;
1104 }
1105 }
1106
1107 if(mode == Handshake) {
1108 int ret = doHandshake();
1109 if(ret == Good) {
1110 getCert();
1111 mode = Active;
1112 }
1113 else if(ret == Bad) {
1114 reset();
1115 return Error;
1116 }
1117 }
1118
1119 // process outgoing
1120 *out = readOutgoing();
1121
1122 if(mode == Active)
1123 return Success;
1124 else
1125 return Continue;
1126 }
1127
1128 int shutdown(const QByteArray &in, QByteArray *out)
1129 {
1130 if(!in.isEmpty())
1131 BIO_write(rbio, in.data(), in.size());
1132
1133 int ret = doShutdown();
1134 if(ret == Bad) {
1135 reset();
1136 return Error;
1137 }
1138
1139 *out = readOutgoing();
1140
1141 if(ret == Good) {
1142 mode = Idle;
1143 return Success;
1144 }
1145 else {
1146 mode = Closing;
1147 return Continue;
1148 }
1149 }
1150
1151 void getCert()
1152 {
1153 // verify the certificate
1154 int code = QCA::TLS::Unknown;
1155 X509 *x = SSL_get_peer_certificate(ssl);
1156 if(x) {
1157 cc.fromX509(x);
1158 X509_free(x);
1159 int ret = SSL_get_verify_result(ssl);
1160 if(ret == X509_V_OK)
1161 code = QCA::TLS::Valid;
1162 else
1163 code = resultToCV(ret);
1164 }
1165 else {
1166 cc.reset();
1167 code = QCA::TLS::NoCert;
1168 }
1169 vr = code;
1170 }
1171
1172 bool encode(const QByteArray &plain, QByteArray *to_net, int *enc)
1173 {
1174 if(mode != Active)
1175 return false;
1176 appendArray(&sendQueue, plain);
1177
1178 int encoded = 0;
1179 if(sendQueue.size() > 0) {
1180 int ret = SSL_write(ssl, sendQueue.data(), sendQueue.size());
1181
1182 enum { Good, Continue, Done, Error };
1183 int m;
1184 if(ret <= 0) {
1185 int x = SSL_get_error(ssl, ret);
1186 if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
1187 m = Continue;
1188 else if(x == SSL_ERROR_ZERO_RETURN)
1189 m = Done;
1190 else
1191 m = Error;
1192 }
1193 else {
1194 m = Good;
1195 encoded = ret;
1196 int newsize = sendQueue.size() - encoded;
1197 char *r = sendQueue.data();
1198 memmove(r, r + encoded, newsize);
1199 sendQueue.resize(newsize);
1200 }
1201
1202 if(m == Done) {
1203 sendQueue.resize(0);
1204 v_eof = true;
1205 return false;
1206 }
1207 if(m == Error) {
1208 sendQueue.resize(0);
1209 return false;
1210 }
1211 }
1212
1213 *to_net = readOutgoing();
1214 *enc = encoded;
1215 return true;
1216 }
1217
1218 bool decode(const QByteArray &from_net, QByteArray *plain, QByteArray *to_net)
1219 {
1220 if(mode != Active)
1221 return false;
1222 if(!from_net.isEmpty())
1223 BIO_write(rbio, from_net.data(), from_net.size());
1224
1225 QByteArray a;
1226 while(!v_eof) {
1227 a.resize(8192);
1228 int ret = SSL_read(ssl, a.data(), a.size());
1229 if(ret > 0) {
1230 if(ret != (int)a.size())
1231 a.resize(ret);
1232 appendArray(&recvQueue, a);
1233 }
1234 else if(ret <= 0) {
1235 int x = SSL_get_error(ssl, ret);
1236 if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
1237 break;
1238 else if(x == SSL_ERROR_ZERO_RETURN)
1239 v_eof = true;
1240 else
1241 return false;
1242 }
1243 }
1244
1245 *plain = recvQueue.copy();
1246 recvQueue.resize(0);
1247
1248 // could be outgoing data also
1249 *to_net = readOutgoing();
1250 return true;
1251 }
1252
1253 QByteArray unprocessed()
1254 {
1255 QByteArray a;
1256 int size = BIO_pending(rbio);
1257 if(size <= 0)
1258 return a;
1259 a.resize(size);
1260
1261 int r = BIO_read(rbio, a.data(), size);
1262 if(r <= 0) {
1263 a.resize(0);
1264 return a;
1265 }
1266 if(r != size)
1267 a.resize(r);
1268 return a;
1269 }
1270
1271 QByteArray readOutgoing()
1272 {
1273 QByteArray a;
1274 int size = BIO_pending(wbio);
1275 if(size <= 0)
1276 return a;
1277 a.resize(size);
1278
1279 int r = BIO_read(wbio, a.data(), size);
1280 if(r <= 0) {
1281 a.resize(0);
1282 return a;
1283 }
1284 if(r != size)
1285 a.resize(r);
1286 return a;
1287 }
1288
1289 int doConnect()
1290 {
1291 int ret = SSL_connect(ssl);
1292 if(ret < 0) {
1293 int x = SSL_get_error(ssl, ret);
1294 if(x == SSL_ERROR_WANT_CONNECT || x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
1295 return TryAgain;
1296 else
1297 return Bad;
1298 }
1299 else if(ret == 0)
1300 return Bad;
1301 return Good;
1302 }
1303
1304 int doAccept()
1305 {
1306 int ret = SSL_accept(ssl);
1307 if(ret < 0) {
1308 int x = SSL_get_error(ssl, ret);
1309 if(x == SSL_ERROR_WANT_CONNECT || x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
1310 return TryAgain;
1311 else
1312 return Bad;
1313 }
1314 else if(ret == 0)
1315 return Bad;
1316 return Good;
1317 }
1318
1319 int doHandshake()
1320 {
1321 int ret = SSL_do_handshake(ssl);
1322 if(ret < 0) {
1323 int x = SSL_get_error(ssl, ret);
1324 if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
1325 return TryAgain;
1326 else
1327 return Bad;
1328 }
1329 else if(ret == 0)
1330 return Bad;
1331 return Good;
1332 }
1333
1334 int doShutdown()
1335 {
1336 int ret = SSL_shutdown(ssl);
1337 if(ret >= 1)
1338 return Good;
1339 else {
1340 if(ret == 0)
1341 return TryAgain;
1342 int x = SSL_get_error(ssl, ret);
1343 if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
1344 return TryAgain;
1345 return Bad;
1346 }
1347 }
1348
1349 QCA_CertContext *peerCertificate() const
1350 {
1351 return cc.clone();
1352 }
1353
1354 int validityResult() const
1355 {
1356 return vr;
1357 }
1358
1359 int resultToCV(int ret) const
1360 {
1361 int rc;
1362
1363 switch(ret) {
1364 case X509_V_ERR_CERT_REJECTED:
1365 rc = QCA::TLS::Rejected;
1366 break;
1367 case X509_V_ERR_CERT_UNTRUSTED:
1368 rc = QCA::TLS::Untrusted;
1369 break;
1370 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
1371 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
1372 case X509_V_ERR_CRL_SIGNATURE_FAILURE:
1373 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
1374 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
1375 rc = QCA::TLS::SignatureFailed;
1376 break;
1377 case X509_V_ERR_INVALID_CA:
1378 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
1379 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
1380 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
1381 rc = QCA::TLS::InvalidCA;
1382 break;
1383 case X509_V_ERR_INVALID_PURPOSE:
1384 rc = QCA::TLS::InvalidPurpose;
1385 break;
1386 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
1387 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
1388 rc = QCA::TLS::SelfSigned;
1389 break;
1390 case X509_V_ERR_CERT_REVOKED:
1391 rc = QCA::TLS::Revoked;
1392 break;
1393 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
1394 rc = QCA::TLS::PathLengthExceeded;
1395 break;
1396 case X509_V_ERR_CERT_NOT_YET_VALID:
1397 case X509_V_ERR_CERT_HAS_EXPIRED:
1398 case X509_V_ERR_CRL_NOT_YET_VALID:
1399 case X509_V_ERR_CRL_HAS_EXPIRED:
1400 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
1401 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
1402 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
1403 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
1404 rc = QCA::TLS::Expired;
1405 break;
1406 case X509_V_ERR_APPLICATION_VERIFICATION:
1407 case X509_V_ERR_OUT_OF_MEM:
1408 case X509_V_ERR_UNABLE_TO_GET_CRL:
1409 case X509_V_ERR_CERT_CHAIN_TOO_LONG:
1410 default:
1411 rc = QCA::TLS::Unknown;
1412 break;
1413 }
1414 return rc;
1415 }
1416};
1417
1418class QCAOpenSSL : public QCAProvider
1419{
1420public:
1421 QCAOpenSSL() {}
1422 ~QCAOpenSSL() {}
1423
1424 void init()
1425 {
1426 }
1427
1428 int qcaVersion() const
1429 {
1430 return QCA_PLUGIN_VERSION;
1431 }
1432
1433 int capabilities() const
1434 {
1435 int caps =
1436 QCA::CAP_SHA1 |
1437 QCA::CAP_MD5 |
1438 QCA::CAP_BlowFish |
1439 QCA::CAP_TripleDES |
1440#ifndef NO_AES
1441 QCA::CAP_AES128 |
1442 QCA::CAP_AES256 |
1443#endif
1444 QCA::CAP_RSA |
1445 QCA::CAP_X509 |
1446 QCA::CAP_TLS;
1447 return caps;
1448 }
1449
1450 void *context(int cap)
1451 {
1452 if(cap == QCA::CAP_SHA1)
1453 return new SHA1Context;
1454 else if(cap == QCA::CAP_MD5)
1455 return new MD5Context;
1456 else if(cap == QCA::CAP_BlowFish)
1457 return new BlowFishContext;
1458 else if(cap == QCA::CAP_TripleDES)
1459 return new TripleDESContext;
1460#ifndef NO_AES
1461 else if(cap == QCA::CAP_AES128)
1462 return new AES128Context;
1463 else if(cap == QCA::CAP_AES256)
1464 return new AES256Context;
1465#endif
1466 else if(cap == QCA::CAP_RSA)
1467 return new RSAKeyContext;
1468 else if(cap == QCA::CAP_X509)
1469 return new CertContext;
1470 else if(cap == QCA::CAP_TLS)
1471 return new TLSContext;
1472 return 0;
1473 }
1474};
1475
1476#ifdef QCA_PLUGIN
1477QCAProvider *createProvider()
1478#else
1479QCAProvider *createProviderTLS()
1480#endif
1481{
1482 return (new QCAOpenSSL);
1483}
Note: See TracBrowser for help on using the repository browser.