1/*
2 * Copyright (C) 2003-2007 Justin Karneges <justin@affinix.com>
3 * Copyright (C) 2004,2005 Brad Hards <bradh@frogmouth.net>
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., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include "qca_publickey.h"
23
24#include "qcaprovider.h"
25
26#include <QFile>
27#include <QTextStream>
28
29namespace QCA {
30
31Provider::Context *getContext(const QString &type, const QString &provider);
32Provider::Context *getContext(const QString &type, Provider *p);
33
34bool stringToFile(const QString &fileName, const QString &content)
35{
36 QFile f(fileName);
37 if (!f.open(flags: QFile::WriteOnly))
38 return false;
39 QTextStream ts(&f);
40 ts << content;
41 return true;
42}
43
44bool stringFromFile(const QString &fileName, QString *s)
45{
46 QFile f(fileName);
47 if (!f.open(flags: QFile::ReadOnly))
48 return false;
49 QTextStream ts(&f);
50 *s = ts.readAll();
51 return true;
52}
53
54bool arrayToFile(const QString &fileName, const QByteArray &content)
55{
56 QFile f(fileName);
57 if (!f.open(flags: QFile::WriteOnly))
58 return false;
59 f.write(data: content.data(), len: content.size());
60 return true;
61}
62
63bool arrayFromFile(const QString &fileName, QByteArray *a)
64{
65 QFile f(fileName);
66 if (!f.open(flags: QFile::ReadOnly))
67 return false;
68 *a = f.readAll();
69 return true;
70}
71
72bool ask_passphrase(const QString &fname, void *ptr, SecureArray *answer)
73{
74 PasswordAsker asker;
75 asker.ask(pstyle: Event::StylePassphrase, fileName: fname, ptr);
76 asker.waitForResponse();
77 if (!asker.accepted())
78 return false;
79 *answer = asker.password();
80 return true;
81}
82
83ProviderList allProviders()
84{
85 ProviderList pl = providers();
86 pl += defaultProvider();
87 return pl;
88}
89
90Provider *providerForName(const QString &name)
91{
92 ProviderList pl = allProviders();
93 for (int n = 0; n < pl.count(); ++n) {
94 if (pl[n]->name() == name)
95 return pl[n];
96 }
97 return nullptr;
98}
99
100bool use_asker_fallback(ConvertResult r)
101{
102 // FIXME: we should only do this if we get ErrorPassphrase?
103 // if(r == ErrorPassphrase)
104 if (r != ConvertGood)
105 return true;
106 return false;
107}
108
109class Getter_GroupSet
110{
111public:
112 static QList<DLGroupSet> getList(Provider *p)
113 {
114 QList<DLGroupSet> list;
115 const DLGroupContext *c = static_cast<const DLGroupContext *>(getContext(QStringLiteral("dlgroup"), p));
116 if (!c)
117 return list;
118 list = c->supportedGroupSets();
119 delete c;
120 return list;
121 }
122};
123
124class Getter_PBE
125{
126public:
127 static QList<PBEAlgorithm> getList(Provider *p)
128 {
129 QList<PBEAlgorithm> list;
130 const PKeyContext *c = static_cast<const PKeyContext *>(getContext(QStringLiteral("pkey"), p));
131 if (!c)
132 return list;
133 list = c->supportedPBEAlgorithms();
134 delete c;
135 return list;
136 }
137};
138
139class Getter_Type
140{
141public:
142 static QList<PKey::Type> getList(Provider *p)
143 {
144 QList<PKey::Type> list;
145 const PKeyContext *c = static_cast<const PKeyContext *>(getContext(QStringLiteral("pkey"), p));
146 if (!c)
147 return list;
148 list = c->supportedTypes();
149 delete c;
150 return list;
151 }
152};
153
154class Getter_IOType
155{
156public:
157 static QList<PKey::Type> getList(Provider *p)
158 {
159 QList<PKey::Type> list;
160 const PKeyContext *c = static_cast<const PKeyContext *>(getContext(QStringLiteral("pkey"), p));
161 if (!c)
162 return list;
163 list = c->supportedIOTypes();
164 delete c;
165 return list;
166 }
167};
168
169template<typename I> class Getter_PublicKey
170{
171public:
172 // DER
173 static ConvertResult fromData(PKeyContext *c, const QByteArray &in)
174 {
175 return c->publicFromDER(a: in);
176 }
177
178 // PEM
179 static ConvertResult fromData(PKeyContext *c, const QString &in)
180 {
181 return c->publicFromPEM(s: in);
182 }
183
184 static PublicKey getKey(Provider *p, const I &in, const SecureArray &, ConvertResult *result)
185 {
186 PublicKey k;
187 PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p));
188 if (!c) {
189 if (result)
190 *result = ErrorDecode;
191 return k;
192 }
193 ConvertResult r = fromData(c, in);
194 if (result)
195 *result = r;
196 if (r == ConvertGood)
197 k.change(c);
198 else
199 delete c;
200 return k;
201 }
202};
203
204template<typename I> class Getter_PrivateKey
205{
206public:
207 // DER
208 static ConvertResult fromData(PKeyContext *c, const SecureArray &in, const SecureArray &passphrase)
209 {
210 return c->privateFromDER(a: in, passphrase);
211 }
212
213 // PEM
214 static ConvertResult fromData(PKeyContext *c, const QString &in, const SecureArray &passphrase)
215 {
216 return c->privateFromPEM(s: in, passphrase);
217 }
218
219 static PrivateKey getKey(Provider *p, const I &in, const SecureArray &passphrase, ConvertResult *result)
220 {
221 PrivateKey k;
222 PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p));
223 if (!c) {
224 if (result)
225 *result = ErrorDecode;
226 return k;
227 }
228 ConvertResult r = fromData(c, in, passphrase);
229 if (result)
230 *result = r;
231 if (r == ConvertGood)
232 k.change(c);
233 else
234 delete c;
235 return k;
236 }
237};
238
239Provider *providerForGroupSet(DLGroupSet set)
240{
241 ProviderList pl = allProviders();
242 for (int n = 0; n < pl.count(); ++n) {
243 if (Getter_GroupSet::getList(p: pl[n]).contains(t: set))
244 return pl[n];
245 }
246 return nullptr;
247}
248
249Provider *providerForPBE(PBEAlgorithm alg, PKey::Type ioType, const PKeyContext *prefer = nullptr)
250{
251 Provider *preferProvider = nullptr;
252 if (prefer) {
253 preferProvider = prefer->provider();
254 if (prefer->supportedPBEAlgorithms().contains(t: alg) && prefer->supportedIOTypes().contains(t: ioType))
255 return preferProvider;
256 }
257
258 ProviderList pl = allProviders();
259 for (int n = 0; n < pl.count(); ++n) {
260 if (preferProvider && pl[n] == preferProvider)
261 continue;
262
263 if (Getter_PBE::getList(p: pl[n]).contains(t: alg) && Getter_IOType::getList(p: pl[n]).contains(t: ioType))
264 return pl[n];
265 }
266 return nullptr;
267}
268
269Provider *providerForIOType(PKey::Type type, const PKeyContext *prefer = nullptr)
270{
271 Provider *preferProvider = nullptr;
272 if (prefer) {
273 preferProvider = prefer->provider();
274 if (prefer && prefer->supportedIOTypes().contains(t: type))
275 return preferProvider;
276 }
277
278 ProviderList pl = allProviders();
279 for (int n = 0; n < pl.count(); ++n) {
280 if (preferProvider && pl[n] == preferProvider)
281 continue;
282
283 if (Getter_IOType::getList(p: pl[n]).contains(t: type))
284 return pl[n];
285 }
286 return nullptr;
287}
288
289template<typename T, typename G> QList<T> getList(const QString &provider)
290{
291 QList<T> list;
292
293 // single
294 if (!provider.isEmpty()) {
295 Provider *p = providerForName(name: provider);
296 if (p)
297 list = G::getList(p);
298 }
299 // all
300 else {
301 ProviderList pl = allProviders();
302 for (int n = 0; n < pl.count(); ++n) {
303 const QList<T> other = G::getList(pl[n]);
304 for (int k = 0; k < other.count(); ++k) {
305 // only add what we don't have in the list
306 if (!list.contains(other[k]))
307 list += other[k];
308 }
309 }
310 }
311
312 return list;
313}
314
315template<typename T, typename G, typename I>
316T getKey(const QString &provider, const I &in, const SecureArray &passphrase, ConvertResult *result)
317{
318 T k;
319
320 // single
321 if (!provider.isEmpty()) {
322 Provider *p = providerForName(name: provider);
323 if (!p)
324 return k;
325 k = G::getKey(p, in, passphrase, result);
326 }
327 // all
328 else {
329 ProviderList pl = allProviders();
330 for (int n = 0; n < pl.count(); ++n) {
331 ConvertResult r;
332 k = G::getKey(pl[n], in, passphrase, &r);
333 if (result)
334 *result = r;
335 if (!k.isNull())
336 break;
337 if (r == ErrorPassphrase) // don't loop if we get this
338 break;
339 }
340 }
341
342 return k;
343}
344
345PBEAlgorithm get_pbe_default()
346{
347 return PBES2_TripleDES_SHA1;
348}
349
350static PrivateKey get_privatekey_der(const SecureArray &der,
351 const QString &fileName,
352 void *ptr,
353 const SecureArray &passphrase,
354 ConvertResult *result,
355 const QString &provider)
356{
357 PrivateKey out;
358 ConvertResult r;
359 out = getKey<PrivateKey, Getter_PrivateKey<SecureArray>, SecureArray>(provider, in: der, passphrase, result: &r);
360
361 // error converting without passphrase? maybe a passphrase is needed
362 if (use_asker_fallback(r) && passphrase.isEmpty()) {
363 SecureArray pass;
364 if (ask_passphrase(fname: fileName, ptr, answer: &pass))
365 out = getKey<PrivateKey, Getter_PrivateKey<SecureArray>, SecureArray>(provider, in: der, passphrase: pass, result: &r);
366 }
367 if (result)
368 *result = r;
369 return out;
370}
371
372static PrivateKey get_privatekey_pem(const QString &pem,
373 const QString &fileName,
374 void *ptr,
375 const SecureArray &passphrase,
376 ConvertResult *result,
377 const QString &provider)
378{
379 PrivateKey out;
380 ConvertResult r;
381 out = getKey<PrivateKey, Getter_PrivateKey<QString>, QString>(provider, in: pem, passphrase, result: &r);
382
383 // error converting without passphrase? maybe a passphrase is needed
384 if (use_asker_fallback(r) && passphrase.isEmpty()) {
385 SecureArray pass;
386 if (ask_passphrase(fname: fileName, ptr, answer: &pass))
387 out = getKey<PrivateKey, Getter_PrivateKey<QString>, QString>(provider, in: pem, passphrase: pass, result: &r);
388 }
389 if (result)
390 *result = r;
391 return out;
392}
393
394//----------------------------------------------------------------------------
395// Global
396//----------------------------------------------------------------------------
397
398// adapted from Botan
399static const unsigned char pkcs_sha1[] =
400 {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14};
401
402static const unsigned char pkcs_md5[] =
403 {0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
404
405static const unsigned char pkcs_md2[] =
406 {0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10};
407
408static const unsigned char pkcs_ripemd160[] =
409 {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14};
410
411QByteArray get_hash_id(const QString &name)
412{
413 if (name == QLatin1String("sha1"))
414 return QByteArray::fromRawData(data: (const char *)pkcs_sha1, size: sizeof(pkcs_sha1));
415 else if (name == QLatin1String("md5"))
416 return QByteArray::fromRawData(data: (const char *)pkcs_md5, size: sizeof(pkcs_md5));
417 else if (name == QLatin1String("md2"))
418 return QByteArray::fromRawData(data: (const char *)pkcs_md2, size: sizeof(pkcs_md2));
419 else if (name == QLatin1String("ripemd160"))
420 return QByteArray::fromRawData(data: (const char *)pkcs_ripemd160, size: sizeof(pkcs_ripemd160));
421 else
422 return QByteArray();
423}
424
425QByteArray emsa3Encode(const QString &hashName, const QByteArray &digest, int size)
426{
427 const QByteArray hash_id = get_hash_id(name: hashName);
428 if (hash_id.isEmpty())
429 return QByteArray();
430
431 // logic adapted from Botan
432 const int basesize = hash_id.size() + digest.size() + 2;
433 if (size == -1)
434 size = basesize + 1; // default to 1-byte pad
435 int padlen = size - basesize;
436 if (padlen < 1)
437 return QByteArray();
438
439 QByteArray out(size, (char)0xff); // pad with 0xff
440 out[0] = 0x01;
441 out[padlen + 1] = 0x00;
442 int at = padlen + 2;
443 memcpy(dest: out.data() + at, src: hash_id.data(), n: hash_id.size());
444 at += hash_id.size();
445 memcpy(dest: out.data() + at, src: digest.data(), n: digest.size());
446 return out;
447}
448
449//----------------------------------------------------------------------------
450// DLGroup
451//----------------------------------------------------------------------------
452class DLGroup::Private
453{
454public:
455 BigInteger p, q, g;
456
457 Private(const BigInteger &p1, const BigInteger &q1, const BigInteger &g1)
458 : p(p1)
459 , q(q1)
460 , g(g1)
461 {
462 }
463};
464
465DLGroup::DLGroup()
466{
467 d = nullptr;
468}
469
470DLGroup::DLGroup(const BigInteger &p, const BigInteger &q, const BigInteger &g)
471{
472 d = new Private(p, q, g);
473}
474
475DLGroup::DLGroup(const BigInteger &p, const BigInteger &g)
476{
477 d = new Private(p, 0, g);
478}
479
480DLGroup::DLGroup(const DLGroup &from)
481{
482 d = nullptr;
483 *this = from;
484}
485
486DLGroup::~DLGroup()
487{
488 delete d;
489}
490
491DLGroup &DLGroup::operator=(const DLGroup &from)
492{
493 delete d;
494 d = nullptr;
495
496 if (from.d)
497 d = new Private(*from.d);
498
499 return *this;
500}
501
502QList<DLGroupSet> DLGroup::supportedGroupSets(const QString &provider)
503{
504 return getList<DLGroupSet, Getter_GroupSet>(provider);
505}
506
507bool DLGroup::isNull() const
508{
509 return (d ? false : true);
510}
511
512BigInteger DLGroup::p() const
513{
514 Q_ASSERT(d);
515 return d->p;
516}
517
518BigInteger DLGroup::q() const
519{
520 Q_ASSERT(d);
521 return d->q;
522}
523
524BigInteger DLGroup::g() const
525{
526 Q_ASSERT(d);
527 return d->g;
528}
529
530//----------------------------------------------------------------------------
531// PKey
532//----------------------------------------------------------------------------
533class PKey::Private
534{
535public:
536};
537
538PKey::PKey()
539{
540 d = new Private;
541}
542
543PKey::PKey(const QString &type, const QString &provider)
544 : Algorithm(type, provider)
545{
546 d = new Private;
547}
548
549PKey::PKey(const PKey &from)
550 : Algorithm(from)
551{
552 d = new Private;
553 *this = from;
554}
555
556PKey::~PKey()
557{
558 delete d;
559}
560
561PKey &PKey::operator=(const PKey &from)
562{
563 Algorithm::operator=(from);
564 *d = *from.d;
565 return *this;
566}
567
568void PKey::set(const PKey &k)
569{
570 *this = k;
571}
572
573void PKey::assignToPublic(PKey *dest) const
574{
575 dest->set(*this);
576
577 // converting private to public
578 if (dest->isPrivate())
579 static_cast<PKeyContext *>(dest->context())->key()->convertToPublic();
580}
581
582void PKey::assignToPrivate(PKey *dest) const
583{
584 dest->set(*this);
585}
586
587QList<PKey::Type> PKey::supportedTypes(const QString &provider)
588{
589 return getList<Type, Getter_Type>(provider);
590}
591
592QList<PKey::Type> PKey::supportedIOTypes(const QString &provider)
593{
594 return getList<Type, Getter_IOType>(provider);
595}
596
597bool PKey::isNull() const
598{
599 return (!context() ? true : false);
600}
601
602PKey::Type PKey::type() const
603{
604 if (isNull())
605 return RSA; // some default so we don't explode
606 return static_cast<const PKeyContext *>(context())->key()->type();
607}
608
609int PKey::bitSize() const
610{
611 return static_cast<const PKeyContext *>(context())->key()->bits();
612}
613
614bool PKey::isRSA() const
615{
616 return (type() == RSA);
617}
618
619bool PKey::isDSA() const
620{
621 return (type() == DSA);
622}
623
624bool PKey::isDH() const
625{
626 return (type() == DH);
627}
628
629bool PKey::isPublic() const
630{
631 if (isNull())
632 return false;
633 return !isPrivate();
634}
635
636bool PKey::isPrivate() const
637{
638 if (isNull())
639 return false;
640 return static_cast<const PKeyContext *>(context())->key()->isPrivate();
641}
642
643bool PKey::canExport() const
644{
645 return static_cast<const PKeyContext *>(context())->key()->canExport();
646}
647
648bool PKey::canKeyAgree() const
649{
650 return isDH();
651}
652
653PublicKey PKey::toPublicKey() const
654{
655 PublicKey k;
656 if (!isNull())
657 assignToPublic(dest: &k);
658 return k;
659}
660
661PrivateKey PKey::toPrivateKey() const
662{
663 PrivateKey k;
664 if (!isNull() && isPrivate())
665 assignToPrivate(dest: &k);
666 return k;
667}
668
669RSAPublicKey PKey::toRSAPublicKey() const
670{
671 RSAPublicKey k;
672 if (!isNull() && isRSA())
673 assignToPublic(dest: &k);
674 return k;
675}
676
677RSAPrivateKey PKey::toRSAPrivateKey() const
678{
679 RSAPrivateKey k;
680 if (!isNull() && isRSA() && isPrivate())
681 assignToPrivate(dest: &k);
682 return k;
683}
684
685DSAPublicKey PKey::toDSAPublicKey() const
686{
687 DSAPublicKey k;
688 if (!isNull() && isDSA())
689 assignToPublic(dest: &k);
690 return k;
691}
692
693DSAPrivateKey PKey::toDSAPrivateKey() const
694{
695 DSAPrivateKey k;
696 if (!isNull() && isDSA() && isPrivate())
697 assignToPrivate(dest: &k);
698 return k;
699}
700
701DHPublicKey PKey::toDHPublicKey() const
702{
703 DHPublicKey k;
704 if (!isNull() && isDH())
705 assignToPublic(dest: &k);
706 return k;
707}
708
709DHPrivateKey PKey::toDHPrivateKey() const
710{
711 DHPrivateKey k;
712 if (!isNull() && isDH() && isPrivate())
713 assignToPrivate(dest: &k);
714 return k;
715}
716
717bool PKey::operator==(const PKey &a) const
718{
719 if (isNull() || a.isNull() || type() != a.type())
720 return false;
721
722 if (a.isPrivate())
723 return (toPrivateKey().toDER() == a.toPrivateKey().toDER());
724 else
725 return (toPublicKey().toDER() == a.toPublicKey().toDER());
726}
727
728bool PKey::operator!=(const PKey &a) const
729{
730 return !(*this == a);
731}
732
733//----------------------------------------------------------------------------
734// PublicKey
735//----------------------------------------------------------------------------
736PublicKey::PublicKey()
737{
738}
739
740PublicKey::PublicKey(const QString &type, const QString &provider)
741 : PKey(type, provider)
742{
743}
744
745PublicKey::PublicKey(const PrivateKey &k)
746{
747 set(k.toPublicKey());
748}
749
750PublicKey::PublicKey(const QString &fileName)
751{
752 *this = fromPEMFile(fileName, result: nullptr, provider: QString());
753}
754
755PublicKey::PublicKey(const PublicKey &from)
756 : PKey(from)
757{
758}
759
760PublicKey::~PublicKey()
761{
762}
763
764PublicKey &PublicKey::operator=(const PublicKey &from)
765{
766 PKey::operator=(from);
767 return *this;
768}
769
770RSAPublicKey PublicKey::toRSA() const
771{
772 return toRSAPublicKey();
773}
774
775DSAPublicKey PublicKey::toDSA() const
776{
777 return toDSAPublicKey();
778}
779
780DHPublicKey PublicKey::toDH() const
781{
782 return toDHPublicKey();
783}
784
785bool PublicKey::canEncrypt() const
786{
787 return isRSA();
788}
789
790bool PublicKey::canDecrypt() const
791{
792 return isRSA();
793}
794
795bool PublicKey::canVerify() const
796{
797 return (isRSA() || isDSA());
798}
799
800int PublicKey::maximumEncryptSize(EncryptionAlgorithm alg) const
801{
802 const PKeyContext *ctx = qobject_cast<const PKeyContext *>(object: context());
803 if (ctx)
804 return ctx->key()->maximumEncryptSize(alg);
805 else
806 return -1;
807}
808
809SecureArray PublicKey::encrypt(const SecureArray &a, EncryptionAlgorithm alg)
810{
811 PKeyContext *ctx = qobject_cast<PKeyContext *>(object: context());
812 if (ctx)
813 return ctx->key()->encrypt(in: a, alg);
814 else
815 return SecureArray();
816}
817
818bool PublicKey::decrypt(const SecureArray &in, SecureArray *out, EncryptionAlgorithm alg)
819{
820 PKeyContext *ctx = qobject_cast<PKeyContext *>(object: context());
821 if (ctx)
822 return ctx->key()->decrypt(in, out, alg);
823 else
824 return false;
825}
826
827void PublicKey::startVerify(SignatureAlgorithm alg, SignatureFormat format)
828{
829 if (isDSA() && format == DefaultFormat)
830 format = IEEE_1363;
831 PKeyContext *ctx = qobject_cast<PKeyContext *>(object: context());
832 if (ctx)
833 ctx->key()->startVerify(alg, format);
834}
835
836void PublicKey::update(const MemoryRegion &a)
837{
838 PKeyContext *ctx = qobject_cast<PKeyContext *>(object: context());
839 if (ctx) {
840 ctx->key()->update(in: a);
841 }
842}
843
844bool PublicKey::validSignature(const QByteArray &sig)
845{
846 PKeyContext *ctx = qobject_cast<PKeyContext *>(object: context());
847 if (ctx)
848 return ctx->key()->endVerify(sig);
849 return false;
850}
851
852bool PublicKey::verifyMessage(const MemoryRegion &a,
853 const QByteArray &sig,
854 SignatureAlgorithm alg,
855 SignatureFormat format)
856{
857 startVerify(alg, format);
858 update(a);
859 return validSignature(sig);
860}
861
862QByteArray PublicKey::toDER() const
863{
864 QByteArray out;
865 const PKeyContext *cur = static_cast<const PKeyContext *>(context());
866 Provider *p = providerForIOType(type: type(), prefer: cur);
867 if (!p)
868 return out;
869 if (cur->provider() == p) {
870 out = cur->publicToDER();
871 } else {
872 PKeyContext *pk = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p));
873 if (pk && pk->importKey(key: cur->key()))
874 out = pk->publicToDER();
875 delete pk;
876 }
877 return out;
878}
879
880QString PublicKey::toPEM() const
881{
882 QString out;
883 const PKeyContext *cur = static_cast<const PKeyContext *>(context());
884 if (!cur)
885 return out;
886 Provider *p = providerForIOType(type: type(), prefer: cur);
887 if (!p)
888 return out;
889 if (cur->provider() == p) {
890 out = cur->publicToPEM();
891 } else {
892 PKeyContext *pk = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p));
893 if (pk && pk->importKey(key: cur->key()))
894 out = pk->publicToPEM();
895 delete pk;
896 }
897 return out;
898}
899
900bool PublicKey::toPEMFile(const QString &fileName) const
901{
902 return stringToFile(fileName, content: toPEM());
903}
904
905PublicKey PublicKey::fromDER(const QByteArray &a, ConvertResult *result, const QString &provider)
906{
907 return getKey<PublicKey, Getter_PublicKey<QByteArray>, QByteArray>(provider, in: a, passphrase: SecureArray(), result);
908}
909
910PublicKey PublicKey::fromPEM(const QString &s, ConvertResult *result, const QString &provider)
911{
912 return getKey<PublicKey, Getter_PublicKey<QString>, QString>(provider, in: s, passphrase: SecureArray(), result);
913}
914
915PublicKey PublicKey::fromPEMFile(const QString &fileName, ConvertResult *result, const QString &provider)
916{
917 QString pem;
918 if (!stringFromFile(fileName, s: &pem)) {
919 if (result)
920 *result = ErrorFile;
921 return PublicKey();
922 }
923 return fromPEM(s: pem, result, provider);
924}
925
926//----------------------------------------------------------------------------
927// PrivateKey
928//----------------------------------------------------------------------------
929PrivateKey::PrivateKey()
930{
931}
932
933PrivateKey::PrivateKey(const QString &type, const QString &provider)
934 : PKey(type, provider)
935{
936}
937
938PrivateKey::PrivateKey(const QString &fileName, const SecureArray &passphrase)
939{
940 *this = fromPEMFile(fileName, passphrase, result: nullptr, provider: QString());
941}
942
943PrivateKey::PrivateKey(const PrivateKey &from)
944 : PKey(from)
945{
946}
947
948PrivateKey::~PrivateKey()
949{
950}
951
952PrivateKey &PrivateKey::operator=(const PrivateKey &from)
953{
954 PKey::operator=(from);
955 return *this;
956}
957
958RSAPrivateKey PrivateKey::toRSA() const
959{
960 return toRSAPrivateKey();
961}
962
963DSAPrivateKey PrivateKey::toDSA() const
964{
965 return toDSAPrivateKey();
966}
967
968DHPrivateKey PrivateKey::toDH() const
969{
970 return toDHPrivateKey();
971}
972
973bool PrivateKey::canDecrypt() const
974{
975 return isRSA();
976}
977
978bool PrivateKey::canEncrypt() const
979{
980 return isRSA();
981}
982
983bool PrivateKey::canSign() const
984{
985 return (isRSA() || isDSA());
986}
987
988int PrivateKey::maximumEncryptSize(EncryptionAlgorithm alg) const
989{
990 return static_cast<const PKeyContext *>(context())->key()->maximumEncryptSize(alg);
991}
992
993bool PrivateKey::decrypt(const SecureArray &in, SecureArray *out, EncryptionAlgorithm alg)
994{
995 return static_cast<PKeyContext *>(context())->key()->decrypt(in, out, alg);
996}
997
998SecureArray PrivateKey::encrypt(const SecureArray &a, EncryptionAlgorithm alg)
999{
1000 return static_cast<PKeyContext *>(context())->key()->encrypt(in: a, alg);
1001}
1002
1003void PrivateKey::startSign(SignatureAlgorithm alg, SignatureFormat format)
1004{
1005 if (isDSA() && format == DefaultFormat)
1006 format = IEEE_1363;
1007 static_cast<PKeyContext *>(context())->key()->startSign(alg, format);
1008}
1009
1010void PrivateKey::update(const MemoryRegion &a)
1011{
1012 static_cast<PKeyContext *>(context())->key()->update(in: a);
1013}
1014
1015QByteArray PrivateKey::signature()
1016{
1017 return static_cast<PKeyContext *>(context())->key()->endSign();
1018}
1019
1020QByteArray PrivateKey::signMessage(const MemoryRegion &a, SignatureAlgorithm alg, SignatureFormat format)
1021{
1022 startSign(alg, format);
1023 update(a);
1024 return signature();
1025}
1026
1027SymmetricKey PrivateKey::deriveKey(const PublicKey &theirs)
1028{
1029 const PKeyContext *theirContext = static_cast<const PKeyContext *>(theirs.context());
1030 return static_cast<PKeyContext *>(context())->key()->deriveKey(theirs: *(theirContext->key()));
1031}
1032
1033QList<PBEAlgorithm> PrivateKey::supportedPBEAlgorithms(const QString &provider)
1034{
1035 return getList<PBEAlgorithm, Getter_PBE>(provider);
1036}
1037
1038SecureArray PrivateKey::toDER(const SecureArray &passphrase, PBEAlgorithm pbe) const
1039{
1040 SecureArray out;
1041 if (pbe == PBEDefault)
1042 pbe = get_pbe_default();
1043 const PKeyContext *cur = static_cast<const PKeyContext *>(context());
1044 Provider *p = providerForPBE(alg: pbe, ioType: type(), prefer: cur);
1045 if (!p)
1046 return out;
1047 if (cur->provider() == p) {
1048 out = cur->privateToDER(passphrase, pbe);
1049 } else {
1050 PKeyContext *pk = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p));
1051 if (pk->importKey(key: cur->key()))
1052 out = pk->privateToDER(passphrase, pbe);
1053 delete pk;
1054 }
1055 return out;
1056}
1057
1058QString PrivateKey::toPEM(const SecureArray &passphrase, PBEAlgorithm pbe) const
1059{
1060 QString out;
1061 if (pbe == PBEDefault)
1062 pbe = get_pbe_default();
1063 const PKeyContext *cur = static_cast<const PKeyContext *>(context());
1064 Provider *p = providerForPBE(alg: pbe, ioType: type(), prefer: cur);
1065 if (!p)
1066 return out;
1067 if (cur->provider() == p) {
1068 out = cur->privateToPEM(passphrase, pbe);
1069 } else {
1070 PKeyContext *pk = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p));
1071 if (pk->importKey(key: cur->key()))
1072 out = pk->privateToPEM(passphrase, pbe);
1073 delete pk;
1074 }
1075 return out;
1076}
1077
1078bool PrivateKey::toPEMFile(const QString &fileName, const SecureArray &passphrase, PBEAlgorithm pbe) const
1079{
1080 return stringToFile(fileName, content: toPEM(passphrase, pbe));
1081}
1082
1083PrivateKey
1084PrivateKey::fromDER(const SecureArray &a, const SecureArray &passphrase, ConvertResult *result, const QString &provider)
1085{
1086 return get_privatekey_der(der: a, fileName: QString(), ptr: (void *)&a, passphrase, result, provider);
1087}
1088
1089PrivateKey
1090PrivateKey::fromPEM(const QString &s, const SecureArray &passphrase, ConvertResult *result, const QString &provider)
1091{
1092 return get_privatekey_pem(pem: s, fileName: QString(), ptr: (void *)&s, passphrase, result, provider);
1093}
1094
1095PrivateKey PrivateKey::fromPEMFile(const QString &fileName,
1096 const SecureArray &passphrase,
1097 ConvertResult *result,
1098 const QString &provider)
1099{
1100 QString pem;
1101 if (!stringFromFile(fileName, s: &pem)) {
1102 if (result)
1103 *result = ErrorFile;
1104 return PrivateKey();
1105 }
1106 return get_privatekey_pem(pem, fileName, ptr: nullptr, passphrase, result, provider);
1107}
1108
1109//----------------------------------------------------------------------------
1110// KeyGenerator
1111//----------------------------------------------------------------------------
1112class KeyGenerator::Private : public QObject
1113{
1114 Q_OBJECT
1115public:
1116 KeyGenerator *parent;
1117 bool blocking, wasBlocking;
1118 PrivateKey key;
1119 DLGroup group;
1120
1121 PKeyBase *k;
1122 PKeyContext *dest;
1123 DLGroupContext *dc;
1124
1125 Private(KeyGenerator *_parent)
1126 : QObject(_parent)
1127 , parent(_parent)
1128 {
1129 k = nullptr;
1130 dest = nullptr;
1131 dc = nullptr;
1132 }
1133
1134 ~Private() override
1135 {
1136 delete k;
1137 delete dest;
1138 delete dc;
1139 }
1140
1141public Q_SLOTS:
1142 void done()
1143 {
1144 if (!k->isNull()) {
1145 if (!wasBlocking) {
1146 k->setParent(nullptr);
1147 k->moveToThread(thread: nullptr);
1148 }
1149 dest->setKey(k);
1150 k = nullptr;
1151
1152 key.change(c: dest);
1153 dest = nullptr;
1154 } else {
1155 delete k;
1156 k = nullptr;
1157 delete dest;
1158 dest = nullptr;
1159 }
1160
1161 if (!wasBlocking)
1162 emit parent->finished();
1163 }
1164
1165 void done_group()
1166 {
1167 if (!dc->isNull()) {
1168 BigInteger p, q, g;
1169 dc->getResult(p: &p, q: &q, g: &g);
1170 group = DLGroup(p, q, g);
1171 }
1172 delete dc;
1173 dc = nullptr;
1174
1175 if (!wasBlocking)
1176 emit parent->finished();
1177 }
1178};
1179
1180KeyGenerator::KeyGenerator(QObject *parent)
1181 : QObject(parent)
1182{
1183 d = new Private(this);
1184 d->blocking = true;
1185}
1186
1187KeyGenerator::~KeyGenerator()
1188{
1189 delete d;
1190}
1191
1192bool KeyGenerator::blockingEnabled() const
1193{
1194 return d->blocking;
1195}
1196
1197void KeyGenerator::setBlockingEnabled(bool b)
1198{
1199 d->blocking = b;
1200}
1201
1202bool KeyGenerator::isBusy() const
1203{
1204 return (d->k ? true : false);
1205}
1206
1207PrivateKey KeyGenerator::createRSA(int bits, int exp, const QString &provider)
1208{
1209 if (isBusy())
1210 return PrivateKey();
1211
1212 d->key = PrivateKey();
1213 d->wasBlocking = d->blocking;
1214 d->k = static_cast<RSAContext *>(getContext(QStringLiteral("rsa"), provider));
1215 if (!d->k)
1216 return PrivateKey();
1217 d->dest = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p: d->k->provider()));
1218
1219 if (!d->blocking) {
1220 d->k->moveToThread(thread: thread());
1221 d->k->setParent(d);
1222 connect(sender: d->k, signal: &RSAContext::finished, context: d, slot: &Private::done);
1223 static_cast<RSAContext *>(d->k)->createPrivate(bits, exp, block: false);
1224 } else {
1225 static_cast<RSAContext *>(d->k)->createPrivate(bits, exp, block: true);
1226 d->done();
1227 }
1228
1229 return d->key;
1230}
1231
1232PrivateKey KeyGenerator::createDSA(const DLGroup &domain, const QString &provider)
1233{
1234 if (isBusy())
1235 return PrivateKey();
1236
1237 d->key = PrivateKey();
1238 d->wasBlocking = d->blocking;
1239 d->k = static_cast<DSAContext *>(getContext(QStringLiteral("dsa"), provider));
1240 d->dest = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p: d->k->provider()));
1241
1242 if (!d->blocking) {
1243 d->k->moveToThread(thread: thread());
1244 d->k->setParent(d);
1245 connect(sender: d->k, signal: &DSAContext::finished, context: d, slot: &Private::done);
1246 static_cast<DSAContext *>(d->k)->createPrivate(domain, block: false);
1247 } else {
1248 static_cast<DSAContext *>(d->k)->createPrivate(domain, block: true);
1249 d->done();
1250 }
1251
1252 return d->key;
1253}
1254
1255PrivateKey KeyGenerator::createDH(const DLGroup &domain, const QString &provider)
1256{
1257 if (isBusy())
1258 return PrivateKey();
1259
1260 d->key = PrivateKey();
1261 d->wasBlocking = d->blocking;
1262 d->k = static_cast<DHContext *>(getContext(QStringLiteral("dh"), provider));
1263 d->dest = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p: d->k->provider()));
1264
1265 if (!d->blocking) {
1266 d->k->moveToThread(thread: thread());
1267 d->k->setParent(d);
1268 connect(sender: d->k, signal: &DHContext::finished, context: d, slot: &Private::done);
1269 static_cast<DHContext *>(d->k)->createPrivate(domain, block: false);
1270 } else {
1271 static_cast<DHContext *>(d->k)->createPrivate(domain, block: true);
1272 d->done();
1273 }
1274
1275 return d->key;
1276}
1277
1278PrivateKey KeyGenerator::key() const
1279{
1280 return d->key;
1281}
1282
1283DLGroup KeyGenerator::createDLGroup(QCA::DLGroupSet set, const QString &provider)
1284{
1285 if (isBusy())
1286 return DLGroup();
1287
1288 Provider *p;
1289 if (!provider.isEmpty())
1290 p = providerForName(name: provider);
1291 else
1292 p = providerForGroupSet(set);
1293
1294 d->dc = static_cast<DLGroupContext *>(getContext(QStringLiteral("dlgroup"), p));
1295 d->group = DLGroup();
1296
1297 if (d->dc) {
1298 d->wasBlocking = d->blocking;
1299 if (!d->blocking) {
1300 connect(sender: d->dc, signal: &DLGroupContext ::finished, context: d, slot: &Private::done_group);
1301 d->dc->fetchGroup(set, block: false);
1302 } else {
1303 d->dc->fetchGroup(set, block: true);
1304 d->done_group();
1305 }
1306 }
1307
1308 return d->group;
1309}
1310
1311DLGroup KeyGenerator::dlGroup() const
1312{
1313 return d->group;
1314}
1315
1316//----------------------------------------------------------------------------
1317// RSAPublicKey
1318//----------------------------------------------------------------------------
1319RSAPublicKey::RSAPublicKey()
1320{
1321}
1322
1323RSAPublicKey::RSAPublicKey(const BigInteger &n, const BigInteger &e, const QString &provider)
1324{
1325 RSAContext *k = static_cast<RSAContext *>(getContext(QStringLiteral("rsa"), provider));
1326 k->createPublic(n, e);
1327 PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p: k->provider()));
1328 c->setKey(k);
1329 change(c);
1330}
1331
1332RSAPublicKey::RSAPublicKey(const RSAPrivateKey &k)
1333 : PublicKey(k)
1334{
1335}
1336
1337BigInteger RSAPublicKey::n() const
1338{
1339 return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->n();
1340}
1341
1342BigInteger RSAPublicKey::e() const
1343{
1344 return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->e();
1345}
1346
1347//----------------------------------------------------------------------------
1348// RSAPrivateKey
1349//----------------------------------------------------------------------------
1350RSAPrivateKey::RSAPrivateKey()
1351{
1352}
1353
1354RSAPrivateKey::RSAPrivateKey(const BigInteger &n,
1355 const BigInteger &e,
1356 const BigInteger &p,
1357 const BigInteger &q,
1358 const BigInteger &d,
1359 const QString &provider)
1360{
1361 RSAContext *k = static_cast<RSAContext *>(getContext(QStringLiteral("rsa"), provider));
1362 k->createPrivate(n, e, p, q, d);
1363 PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p: k->provider()));
1364 c->setKey(k);
1365 change(c);
1366}
1367
1368BigInteger RSAPrivateKey::n() const
1369{
1370 return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->n();
1371}
1372
1373BigInteger RSAPrivateKey::e() const
1374{
1375 return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->e();
1376}
1377
1378BigInteger RSAPrivateKey::p() const
1379{
1380 return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->p();
1381}
1382
1383BigInteger RSAPrivateKey::q() const
1384{
1385 return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->q();
1386}
1387
1388BigInteger RSAPrivateKey::d() const
1389{
1390 return static_cast<const RSAContext *>(static_cast<const PKeyContext *>(context())->key())->d();
1391}
1392
1393//----------------------------------------------------------------------------
1394// DSAPublicKey
1395//----------------------------------------------------------------------------
1396DSAPublicKey::DSAPublicKey()
1397{
1398}
1399
1400DSAPublicKey::DSAPublicKey(const DLGroup &domain, const BigInteger &y, const QString &provider)
1401{
1402 DSAContext *k = static_cast<DSAContext *>(getContext(QStringLiteral("dsa"), provider));
1403 k->createPublic(domain, y);
1404 PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p: k->provider()));
1405 c->setKey(k);
1406 change(c);
1407}
1408
1409DSAPublicKey::DSAPublicKey(const DSAPrivateKey &k)
1410 : PublicKey(k)
1411{
1412}
1413
1414DLGroup DSAPublicKey::domain() const
1415{
1416 return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->domain();
1417}
1418
1419BigInteger DSAPublicKey::y() const
1420{
1421 return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->y();
1422}
1423
1424//----------------------------------------------------------------------------
1425// DSAPrivateKey
1426//----------------------------------------------------------------------------
1427DSAPrivateKey::DSAPrivateKey()
1428{
1429}
1430
1431DSAPrivateKey::DSAPrivateKey(const DLGroup &domain, const BigInteger &y, const BigInteger &x, const QString &provider)
1432{
1433 DSAContext *k = static_cast<DSAContext *>(getContext(QStringLiteral("dsa"), provider));
1434 k->createPrivate(domain, y, x);
1435 PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p: k->provider()));
1436 c->setKey(k);
1437 change(c);
1438}
1439
1440DLGroup DSAPrivateKey::domain() const
1441{
1442 return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->domain();
1443}
1444
1445BigInteger DSAPrivateKey::y() const
1446{
1447 return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->y();
1448}
1449
1450BigInteger DSAPrivateKey::x() const
1451{
1452 return static_cast<const DSAContext *>(static_cast<const PKeyContext *>(context())->key())->x();
1453}
1454
1455//----------------------------------------------------------------------------
1456// DHPublicKey
1457//----------------------------------------------------------------------------
1458DHPublicKey::DHPublicKey()
1459{
1460}
1461
1462DHPublicKey::DHPublicKey(const DLGroup &domain, const BigInteger &y, const QString &provider)
1463{
1464 DHContext *k = static_cast<DHContext *>(getContext(QStringLiteral("dh"), provider));
1465 k->createPublic(domain, y);
1466 PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p: k->provider()));
1467 c->setKey(k);
1468 change(c);
1469}
1470
1471DHPublicKey::DHPublicKey(const DHPrivateKey &k)
1472 : PublicKey(k)
1473{
1474}
1475
1476DLGroup DHPublicKey::domain() const
1477{
1478 return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->domain();
1479}
1480
1481BigInteger DHPublicKey::y() const
1482{
1483 return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->y();
1484}
1485
1486//----------------------------------------------------------------------------
1487// DHPrivateKey
1488//----------------------------------------------------------------------------
1489DHPrivateKey::DHPrivateKey()
1490{
1491}
1492
1493DHPrivateKey::DHPrivateKey(const DLGroup &domain, const BigInteger &y, const BigInteger &x, const QString &provider)
1494{
1495 DHContext *k = static_cast<DHContext *>(getContext(QStringLiteral("dh"), provider));
1496 k->createPrivate(domain, y, x);
1497 PKeyContext *c = static_cast<PKeyContext *>(getContext(QStringLiteral("pkey"), p: k->provider()));
1498 c->setKey(k);
1499 change(c);
1500}
1501
1502DLGroup DHPrivateKey::domain() const
1503{
1504 return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->domain();
1505}
1506
1507BigInteger DHPrivateKey::y() const
1508{
1509 return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->y();
1510}
1511
1512BigInteger DHPrivateKey::x() const
1513{
1514 return static_cast<const DHContext *>(static_cast<const PKeyContext *>(context())->key())->x();
1515}
1516
1517}
1518
1519#include "qca_publickey.moc"
1520

source code of qca/src/qca_publickey.cpp