Imported Upstream version 1.16.0
[platform/upstream/gpgme.git] / lang / cpp / src / key.cpp
1 /*
2   key.cpp - wraps a gpgme key
3   Copyright (C) 2003, 2005 Klarälvdalens Datakonsult AB
4
5   This file is part of GPGME++.
6
7   GPGME++ is free software; you can redistribute it and/or
8   modify it under the terms of the GNU Library General Public
9   License as published by the Free Software Foundation; either
10   version 2 of the License, or (at your option) any later version.
11
12   GPGME++ is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU Library General Public License for more details.
16
17   You should have received a copy of the GNU Library General Public License
18   along with GPGME++; see the file COPYING.LIB.  If not, write to the
19   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20   Boston, MA 02110-1301, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24  #include "config.h"
25 #endif
26
27 #include <key.h>
28
29 #include "util.h"
30 #include "tofuinfo.h"
31 #include "context.h"
32 #include "engineinfo.h"
33
34 #include <gpgme.h>
35
36 #include <string.h>
37 #include <strings.h>
38 #include <cassert>
39 #include <istream>
40 #include <iterator>
41
42 const GpgME::Key::Null GpgME::Key::null;
43
44 namespace GpgME
45 {
46
47 Key::Key() : key() {}
48
49 Key::Key(const Null &) : key() {}
50
51 Key::Key(const shared_gpgme_key_t &k) : key(k) {}
52
53 Key::Key(gpgme_key_t k, bool ref)
54     : key(k
55           ? shared_gpgme_key_t(k, &gpgme_key_unref)
56           : shared_gpgme_key_t())
57 {
58     if (ref && impl()) {
59         gpgme_key_ref(impl());
60     }
61 }
62
63 UserID Key::userID(unsigned int index) const
64 {
65     return UserID(key, index);
66 }
67
68 Subkey Key::subkey(unsigned int index) const
69 {
70     return Subkey(key, index);
71 }
72
73 unsigned int Key::numUserIDs() const
74 {
75     if (!key) {
76         return 0;
77     }
78     unsigned int count = 0;
79     for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
80         ++count;
81     }
82     return count;
83 }
84
85 unsigned int Key::numSubkeys() const
86 {
87     if (!key) {
88         return 0;
89     }
90     unsigned int count = 0;
91     for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
92         ++count;
93     }
94     return count;
95 }
96
97 std::vector<UserID> Key::userIDs() const
98 {
99     if (!key) {
100         return std::vector<UserID>();
101     }
102
103     std::vector<UserID> v;
104     v.reserve(numUserIDs());
105     for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
106         v.push_back(UserID(key, uid));
107     }
108     return v;
109 }
110
111 std::vector<Subkey> Key::subkeys() const
112 {
113     if (!key) {
114         return std::vector<Subkey>();
115     }
116
117     std::vector<Subkey> v;
118     v.reserve(numSubkeys());
119     for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
120         v.push_back(Subkey(key, subkey));
121     }
122     return v;
123 }
124
125 Key::OwnerTrust Key::ownerTrust() const
126 {
127     if (!key) {
128         return Unknown;
129     }
130     switch (key->owner_trust) {
131     default:
132     case GPGME_VALIDITY_UNKNOWN:   return Unknown;
133     case GPGME_VALIDITY_UNDEFINED: return Undefined;
134     case GPGME_VALIDITY_NEVER:     return Never;
135     case GPGME_VALIDITY_MARGINAL:  return Marginal;
136     case GPGME_VALIDITY_FULL:     return Full;
137     case GPGME_VALIDITY_ULTIMATE: return Ultimate;
138     }
139 }
140 char Key::ownerTrustAsString() const
141 {
142     if (!key) {
143         return '?';
144     }
145     switch (key->owner_trust) {
146     default:
147     case GPGME_VALIDITY_UNKNOWN:   return '?';
148     case GPGME_VALIDITY_UNDEFINED: return 'q';
149     case GPGME_VALIDITY_NEVER:     return 'n';
150     case GPGME_VALIDITY_MARGINAL:  return 'm';
151     case GPGME_VALIDITY_FULL:     return 'f';
152     case GPGME_VALIDITY_ULTIMATE: return 'u';
153     }
154 }
155
156 Protocol Key::protocol() const
157 {
158     if (!key) {
159         return UnknownProtocol;
160     }
161     switch (key->protocol) {
162     case GPGME_PROTOCOL_CMS:     return CMS;
163     case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
164     default:                     return UnknownProtocol;
165     }
166 }
167
168 const char *Key::protocolAsString() const
169 {
170     return key ? gpgme_get_protocol_name(key->protocol) : nullptr ;
171 }
172
173 bool Key::isRevoked() const
174 {
175     return key && key->revoked;
176 }
177
178 bool Key::isExpired() const
179 {
180     return key && key->expired;
181 }
182
183 bool Key::isDisabled() const
184 {
185     return key && key->disabled;
186 }
187
188 bool Key::isInvalid() const
189 {
190     return key && key->invalid;
191 }
192
193 bool Key::hasSecret() const
194 {
195     return key && key->secret;
196 }
197
198 bool Key::isRoot() const
199 {
200     return key && key->subkeys && key->subkeys->fpr && key->chain_id &&
201            strcasecmp(key->subkeys->fpr, key->chain_id) == 0;
202 }
203
204 bool Key::canEncrypt() const
205 {
206     return key && key->can_encrypt;
207 }
208
209 bool Key::canSign() const
210 {
211 #ifndef GPGME_CAN_SIGN_ON_SECRET_OPENPGP_KEYLISTING_NOT_BROKEN
212     if (key && key->protocol == GPGME_PROTOCOL_OpenPGP) {
213         return true;
214     }
215 #endif
216     return canReallySign();
217 }
218
219 bool Key::canReallySign() const
220 {
221     return key && key->can_sign;
222 }
223
224 bool Key::canCertify() const
225 {
226     return key && key->can_certify;
227 }
228
229 bool Key::canAuthenticate() const
230 {
231     return key && key->can_authenticate;
232 }
233
234 bool Key::isQualified() const
235 {
236     return key && key->is_qualified;
237 }
238
239 bool Key::isDeVs() const
240 {
241     if (!key) {
242         return false;
243     }
244     if (!key->subkeys || !key->subkeys->is_de_vs) {
245         return false;
246     }
247     for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
248         if (!subkey->is_de_vs) {
249             return false;
250         }
251     }
252     return true;
253 }
254
255 const char *Key::issuerSerial() const
256 {
257     return key ? key->issuer_serial : nullptr ;
258 }
259 const char *Key::issuerName() const
260 {
261     return key ? key->issuer_name : nullptr ;
262 }
263 const char *Key::chainID() const
264 {
265     return key ? key->chain_id : nullptr ;
266 }
267
268 const char *Key::keyID() const
269 {
270     return key && key->subkeys ? key->subkeys->keyid : nullptr ;
271 }
272
273 const char *Key::shortKeyID() const
274 {
275     if (!key || !key->subkeys || !key->subkeys->keyid) {
276         return nullptr;
277     }
278     const int len = strlen(key->subkeys->keyid);
279     if (len > 8) {
280         return key->subkeys->keyid + len - 8; // return the last 8 bytes (in hex notation)
281     } else {
282         return key->subkeys->keyid;
283     }
284 }
285
286 const char *Key::primaryFingerprint() const
287 {
288     if (!key) {
289         return nullptr;
290     }
291     if (key->fpr) {
292         /* Return what gpgme thinks is the primary fingerprint */
293         return key->fpr;
294     }
295     if (key->subkeys) {
296         /* Return the first subkeys fingerprint */
297         return key->subkeys->fpr;
298     }
299     return nullptr;
300 }
301
302 unsigned int Key::keyListMode() const
303 {
304     return key ? convert_from_gpgme_keylist_mode_t(key->keylist_mode) : 0;
305 }
306
307 const Key &Key::mergeWith(const Key &other)
308 {
309     // ### incomplete. Just merges has* and can*, nothing else atm
310     // ### detach also missing
311
312     if (!this->primaryFingerprint() ||
313             !other.primaryFingerprint() ||
314             strcasecmp(this->primaryFingerprint(), other.primaryFingerprint()) != 0) {
315         return *this; // only merge the Key object which describe the same key
316     }
317
318     const gpgme_key_t me = impl();
319     const gpgme_key_t him = other.impl();
320
321     if (!me || !him) {
322         return *this;
323     }
324
325     me->revoked          |= him->revoked;
326     me->expired          |= him->expired;
327     me->disabled         |= him->disabled;
328     me->invalid          |= him->invalid;
329     me->can_encrypt      |= him->can_encrypt;
330     me->can_sign         |= him->can_sign;
331     me->can_certify      |= him->can_certify;
332     me->secret           |= him->secret;
333     me->can_authenticate |= him->can_authenticate;
334     me->is_qualified     |= him->is_qualified;
335     me->keylist_mode     |= him->keylist_mode;
336
337     // make sure the gpgme_sub_key_t::is_cardkey flag isn't lost:
338     for (gpgme_sub_key_t mysk = me->subkeys ; mysk ; mysk = mysk->next) {
339         for (gpgme_sub_key_t hissk = him->subkeys ; hissk ; hissk = hissk->next) {
340             if (strcmp(mysk->fpr, hissk->fpr) == 0) {
341                 mysk->is_cardkey |= hissk->is_cardkey;
342                 mysk->secret |= hissk->secret;
343                 if (hissk->keygrip && !mysk->keygrip) {
344                     mysk->keygrip = strdup(hissk->keygrip);
345                 }
346                 break;
347             }
348         }
349     }
350
351     return *this;
352 }
353
354 void Key::update()
355 {
356     if (isNull() || !primaryFingerprint()) {
357         return;
358     }
359     auto ctx = Context::createForProtocol(protocol());
360     if (!ctx) {
361         return;
362     }
363     ctx->setKeyListMode(KeyListMode::Local |
364                         KeyListMode::Signatures |
365                         KeyListMode::SignatureNotations |
366                         KeyListMode::Validate |
367                         KeyListMode::WithTofu |
368                         KeyListMode::WithKeygrip |
369                         KeyListMode::WithSecret);
370     Error err;
371     Key newKey;
372     if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.0") {
373         newKey = ctx->key(primaryFingerprint(), err, true);
374         // Not secret so we get the information from the pubring.
375         if (newKey.isNull()) {
376             newKey = ctx->key(primaryFingerprint(), err, false);
377         }
378     } else {
379         newKey = ctx->key(primaryFingerprint(), err, false);
380     }
381     delete ctx;
382     if (err) {
383         return;
384     }
385     swap(newKey);
386 }
387
388 // static
389 Key Key::locate(const char *mbox)
390 {
391     if (!mbox) {
392         return Key();
393     }
394
395     auto ctx = Context::createForProtocol(OpenPGP);
396     if (!ctx) {
397         return Key();
398     }
399
400     ctx->setKeyListMode (Extern | Local);
401
402     Error e = ctx->startKeyListing (mbox);
403     auto ret = ctx->nextKey (e);
404     delete ctx;
405
406     return ret;
407 }
408
409 //
410 //
411 // class Subkey
412 //
413 //
414
415 static gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx)
416 {
417     if (key) {
418         for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx) {
419             if (idx == 0) {
420                 return s;
421             }
422         }
423     }
424     return nullptr;
425 }
426
427 static gpgme_sub_key_t verify_subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey)
428 {
429     if (key) {
430         for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next) {
431             if (s == subkey) {
432                 return subkey;
433             }
434         }
435     }
436     return nullptr;
437 }
438
439 Subkey::Subkey() : key(), subkey(nullptr) {}
440
441 Subkey::Subkey(const shared_gpgme_key_t &k, unsigned int idx)
442     : key(k), subkey(find_subkey(k, idx))
443 {
444
445 }
446
447 Subkey::Subkey(const shared_gpgme_key_t &k, gpgme_sub_key_t sk)
448     : key(k), subkey(verify_subkey(k, sk))
449 {
450
451 }
452
453 Key Subkey::parent() const
454 {
455     return Key(key);
456 }
457
458 const char *Subkey::keyID() const
459 {
460     return subkey ? subkey->keyid : nullptr ;
461 }
462
463 const char *Subkey::fingerprint() const
464 {
465     return subkey ? subkey->fpr : nullptr ;
466 }
467
468 Subkey::PubkeyAlgo Subkey::publicKeyAlgorithm() const
469 {
470     return subkey ? static_cast<PubkeyAlgo>(subkey->pubkey_algo) : AlgoUnknown;
471 }
472
473 const char *Subkey::publicKeyAlgorithmAsString() const
474 {
475     return gpgme_pubkey_algo_name(subkey ? subkey->pubkey_algo : (gpgme_pubkey_algo_t)0);
476 }
477
478 /* static */
479 const char *Subkey::publicKeyAlgorithmAsString(PubkeyAlgo algo)
480 {
481     if (algo == AlgoUnknown) {
482         return NULL;
483     }
484     return gpgme_pubkey_algo_name(static_cast<gpgme_pubkey_algo_t>(algo));
485 }
486
487 std::string Subkey::algoName() const
488 {
489     char *gpgmeStr;
490     if (subkey && (gpgmeStr = gpgme_pubkey_algo_string(subkey))) {
491         std::string ret = std::string(gpgmeStr);
492         gpgme_free(gpgmeStr);
493         return ret;
494     }
495     return std::string();
496 }
497
498 bool Subkey::canEncrypt() const
499 {
500     return subkey && subkey->can_encrypt;
501 }
502
503 bool Subkey::canSign() const
504 {
505     return subkey && subkey->can_sign;
506 }
507
508 bool Subkey::canCertify() const
509 {
510     return subkey && subkey->can_certify;
511 }
512
513 bool Subkey::canAuthenticate() const
514 {
515     return subkey && subkey->can_authenticate;
516 }
517
518 bool Subkey::isQualified() const
519 {
520     return subkey && subkey->is_qualified;
521 }
522
523 bool Subkey::isDeVs() const
524 {
525     return subkey && subkey->is_de_vs;
526 }
527
528 bool Subkey::isCardKey() const
529 {
530     return subkey && subkey->is_cardkey;
531 }
532
533 const char *Subkey::cardSerialNumber() const
534 {
535     return subkey ? subkey->card_number : nullptr;
536 }
537
538 const char *Subkey::keyGrip() const
539 {
540     return subkey ? subkey->keygrip : nullptr;
541 }
542
543 bool Subkey::isSecret() const
544 {
545     return subkey && subkey->secret;
546 }
547
548 unsigned int Subkey::length() const
549 {
550     return subkey ? subkey->length : 0 ;
551 }
552
553 time_t Subkey::creationTime() const
554 {
555     return static_cast<time_t>(subkey ? subkey->timestamp : 0);
556 }
557
558 time_t Subkey::expirationTime() const
559 {
560     return static_cast<time_t>(subkey ? subkey->expires : 0);
561 }
562
563 bool Subkey::neverExpires() const
564 {
565     return expirationTime() == time_t(0);
566 }
567
568 bool Subkey::isRevoked() const
569 {
570     return subkey && subkey->revoked;
571 }
572
573 bool Subkey::isInvalid() const
574 {
575     return subkey && subkey->invalid;
576 }
577
578 bool Subkey::isExpired() const
579 {
580     return subkey && subkey->expired;
581 }
582
583 bool Subkey::isDisabled() const
584 {
585     return subkey && subkey->disabled;
586 }
587
588 //
589 //
590 // class UserID
591 //
592 //
593
594 static gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx)
595 {
596     if (key) {
597         for (gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx) {
598             if (idx == 0) {
599                 return u;
600             }
601         }
602     }
603     return nullptr;
604 }
605
606 static gpgme_user_id_t verify_uid(const shared_gpgme_key_t &key, gpgme_user_id_t uid)
607 {
608     if (key) {
609         for (gpgme_user_id_t u = key->uids ; u ; u = u->next) {
610             if (u == uid) {
611                 return uid;
612             }
613         }
614     }
615     return nullptr;
616 }
617
618 UserID::UserID() : key(), uid(nullptr) {}
619
620 UserID::UserID(const shared_gpgme_key_t &k, gpgme_user_id_t u)
621     : key(k), uid(verify_uid(k, u))
622 {
623
624 }
625
626 UserID::UserID(const shared_gpgme_key_t &k, unsigned int idx)
627     : key(k), uid(find_uid(k, idx))
628 {
629
630 }
631
632 Key UserID::parent() const
633 {
634     return Key(key);
635 }
636
637 UserID::Signature UserID::signature(unsigned int index) const
638 {
639     return Signature(key, uid, index);
640 }
641
642 unsigned int UserID::numSignatures() const
643 {
644     if (!uid) {
645         return 0;
646     }
647     unsigned int count = 0;
648     for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
649         ++count;
650     }
651     return count;
652 }
653
654 std::vector<UserID::Signature> UserID::signatures() const
655 {
656     if (!uid) {
657         return std::vector<Signature>();
658     }
659
660     std::vector<Signature> v;
661     v.reserve(numSignatures());
662     for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
663         v.push_back(Signature(key, uid, sig));
664     }
665     return v;
666 }
667
668 const char *UserID::id() const
669 {
670     return uid ? uid->uid : nullptr ;
671 }
672
673 const char *UserID::name() const
674 {
675     return uid ? uid->name : nullptr ;
676 }
677
678 const char *UserID::email() const
679 {
680     return uid ? uid->email : nullptr ;
681 }
682
683 const char *UserID::comment() const
684 {
685     return uid ? uid->comment : nullptr ;
686 }
687
688 const char *UserID::uidhash() const
689 {
690     return uid ? uid->uidhash : nullptr ;
691 }
692
693 UserID::Validity UserID::validity() const
694 {
695     if (!uid) {
696         return Unknown;
697     }
698     switch (uid->validity) {
699     default:
700     case GPGME_VALIDITY_UNKNOWN:   return Unknown;
701     case GPGME_VALIDITY_UNDEFINED: return Undefined;
702     case GPGME_VALIDITY_NEVER:     return Never;
703     case GPGME_VALIDITY_MARGINAL:  return Marginal;
704     case GPGME_VALIDITY_FULL:      return Full;
705     case GPGME_VALIDITY_ULTIMATE:  return Ultimate;
706     }
707 }
708
709 char UserID::validityAsString() const
710 {
711     if (!uid) {
712         return '?';
713     }
714     switch (uid->validity) {
715     default:
716     case GPGME_VALIDITY_UNKNOWN:   return '?';
717     case GPGME_VALIDITY_UNDEFINED: return 'q';
718     case GPGME_VALIDITY_NEVER:     return 'n';
719     case GPGME_VALIDITY_MARGINAL:  return 'm';
720     case GPGME_VALIDITY_FULL:      return 'f';
721     case GPGME_VALIDITY_ULTIMATE:  return 'u';
722     }
723 }
724
725 bool UserID::isRevoked() const
726 {
727     return uid && uid->revoked;
728 }
729
730 bool UserID::isInvalid() const
731 {
732     return uid && uid->invalid;
733 }
734
735 TofuInfo UserID::tofuInfo() const
736 {
737     if (!uid) {
738         return TofuInfo();
739     }
740     return TofuInfo(uid->tofu);
741 }
742
743 static gpgme_key_sig_t find_last_valid_sig_for_keyid (gpgme_user_id_t uid,
744                                                       const char *keyid)
745 {
746     if (!keyid) {
747         return nullptr;
748     }
749     gpgme_key_sig_t ret = NULL;
750     for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
751         if (s->keyid && !strcmp(keyid, s->keyid)) {
752             if (!s->expired && !s->revoked && !s->invalid && !s->status) {
753                 if (!ret) {
754                     ret = s;
755                 } else if (ret && ret->timestamp <= s->timestamp) {
756                     /* Equals because when the timestamps are the same we prefer
757                        the last in the list */
758                     ret = s;
759                 }
760             }
761         }
762     }
763     return ret;
764 }
765
766 const char *UserID::remark(const Key &remarker, Error &err) const
767 {
768     if (!uid || remarker.isNull()) {
769         err = Error::fromCode(GPG_ERR_GENERAL);
770         return nullptr;
771     }
772
773     if (key->protocol != GPGME_PROTOCOL_OpenPGP) {
774         return nullptr;
775     }
776
777     if (!(key->keylist_mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS) ||
778         !(key->keylist_mode & GPGME_KEYLIST_MODE_SIGS)) {
779         err = Error::fromCode(GPG_ERR_NO_DATA);
780         return nullptr;
781     }
782
783     gpgme_key_sig_t s = find_last_valid_sig_for_keyid(uid, remarker.keyID());
784
785     if (!s) {
786         return nullptr;
787     }
788
789     for (gpgme_sig_notation_t n = s->notations; n ; n = n->next) {
790         if (n->name && !strcmp(n->name, "rem@gnupg.org")) {
791             return n->value;
792         }
793     }
794     return nullptr;
795 }
796
797 std::vector<std::string> UserID::remarks(std::vector<Key> keys, Error &err) const
798 {
799     std::vector<std::string> ret;
800
801     for (const auto &key: keys) {
802         const char *rem = remark(key, err);
803         if (err) {
804             return ret;
805         }
806         if (rem) {
807             ret.push_back(rem);
808         }
809     }
810     return ret;
811 }
812
813 //
814 //
815 // class Signature
816 //
817 //
818
819 static gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx)
820 {
821     if (uid) {
822         for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx) {
823             if (idx == 0) {
824                 return s;
825             }
826         }
827     }
828     return nullptr;
829 }
830
831 static gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig)
832 {
833     if (uid) {
834         for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
835             if (s == sig) {
836                 return sig;
837             }
838         }
839     }
840     return nullptr;
841 }
842
843 static int signature_index(gpgme_user_id_t uid, gpgme_key_sig_t sig)
844 {
845     if (uid) {
846         int i = 0;
847         for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, ++i) {
848             if (s == sig) {
849                 return i;
850             }
851         }
852     }
853     return -1;
854 }
855
856 UserID::Signature::Signature() : key(), uid(nullptr), sig(nullptr) {}
857
858 UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx)
859     : key(k), uid(verify_uid(k, u)), sig(find_signature(uid, idx))
860 {
861 }
862
863 UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, gpgme_key_sig_t s)
864     : key(k), uid(verify_uid(k, u)), sig(verify_signature(uid, s))
865 {
866 }
867
868 bool UserID::Signature::operator<(const Signature &other)
869 {
870     // kept for binary compatibility
871     return static_cast<const UserID::Signature *>(this)->operator<(other);
872 }
873
874 bool UserID::Signature::operator<(const Signature &other) const
875 {
876     // based on cmp_signodes() in g10/keylist.c
877
878     // both signatures must belong to the same user ID
879     assert(uid == other.uid);
880
881     // self-signatures are ordered first
882     const char *primaryKeyId = parent().parent().keyID();
883     const bool thisIsSelfSignature = strcmp(signerKeyID(), primaryKeyId) == 0;
884     const bool otherIsSelfSignature = strcmp(other.signerKeyID(), primaryKeyId) == 0;
885     if (thisIsSelfSignature && !otherIsSelfSignature) {
886         return true;
887     }
888     if (otherIsSelfSignature && !thisIsSelfSignature) {
889         return false;
890     }
891
892     // then sort by signer key ID (which are or course the same for self-sigs)
893     const int keyIdComparison = strcmp(signerKeyID(), other.signerKeyID());
894     if (keyIdComparison < 0) {
895         return true;
896     }
897     if (keyIdComparison > 0) {
898         return false;
899     }
900
901     // followed by creation time
902     if (creationTime() < other.creationTime()) {
903         return true;
904     }
905     if (creationTime() > other.creationTime()) {
906         return false;
907     }
908
909     // followed by the class in a way that a rev comes first
910     if (certClass() < other.certClass()) {
911         return true;
912     }
913     if (certClass() > other.certClass()) {
914         return false;
915     }
916
917     // to make the sort stable we compare the indexes of the signatures as last resort
918     return signature_index(uid, sig) < signature_index(uid, other.sig);
919 }
920
921 UserID UserID::Signature::parent() const
922 {
923     return UserID(key, uid);
924 }
925
926 const char *UserID::Signature::signerKeyID() const
927 {
928     return sig ? sig->keyid : nullptr ;
929 }
930
931 const char *UserID::Signature::algorithmAsString() const
932 {
933     return gpgme_pubkey_algo_name(sig ? sig->pubkey_algo : (gpgme_pubkey_algo_t)0);
934 }
935
936 unsigned int UserID::Signature::algorithm() const
937 {
938     return sig ? sig->pubkey_algo : 0 ;
939 }
940
941 time_t UserID::Signature::creationTime() const
942 {
943     return static_cast<time_t>(sig ? sig->timestamp : 0);
944 }
945
946 time_t UserID::Signature::expirationTime() const
947 {
948     return static_cast<time_t>(sig ? sig->expires : 0);
949 }
950
951 bool UserID::Signature::neverExpires() const
952 {
953     return expirationTime() == time_t(0);
954 }
955
956 bool UserID::Signature::isRevokation() const
957 {
958     return sig && sig->revoked;
959 }
960
961 bool UserID::Signature::isInvalid() const
962 {
963     return sig && sig->invalid;
964 }
965
966 bool UserID::Signature::isExpired() const
967 {
968     return sig && sig->expired;
969 }
970
971 bool UserID::Signature::isExportable() const
972 {
973     return sig && sig->exportable;
974 }
975
976 const char *UserID::Signature::signerUserID() const
977 {
978     return sig ? sig->uid : nullptr ;
979 }
980
981 const char *UserID::Signature::signerName() const
982 {
983     return sig ? sig->name : nullptr ;
984 }
985
986 const char *UserID::Signature::signerEmail() const
987 {
988     return sig ? sig->email : nullptr ;
989 }
990
991 const char *UserID::Signature::signerComment() const
992 {
993     return sig ? sig->comment : nullptr ;
994 }
995
996 unsigned int UserID::Signature::certClass() const
997 {
998     return sig ? sig->sig_class : 0 ;
999 }
1000
1001 UserID::Signature::Status UserID::Signature::status() const
1002 {
1003     if (!sig) {
1004         return GeneralError;
1005     }
1006
1007     switch (gpgme_err_code(sig->status)) {
1008     case GPG_ERR_NO_ERROR:      return NoError;
1009     case GPG_ERR_SIG_EXPIRED:   return SigExpired;
1010     case GPG_ERR_KEY_EXPIRED:   return KeyExpired;
1011     case GPG_ERR_BAD_SIGNATURE: return BadSignature;
1012     case GPG_ERR_NO_PUBKEY:     return NoPublicKey;
1013     default:
1014     case GPG_ERR_GENERAL:       return GeneralError;
1015     }
1016 }
1017
1018 std::string UserID::Signature::statusAsString() const
1019 {
1020     if (!sig) {
1021         return std::string();
1022     }
1023     char buf[ 1024 ];
1024     gpgme_strerror_r(sig->status, buf, sizeof buf);
1025     buf[ sizeof buf - 1 ] = '\0';
1026     return std::string(buf);
1027 }
1028
1029 GpgME::Notation UserID::Signature::notation(unsigned int idx) const
1030 {
1031     if (!sig) {
1032         return GpgME::Notation();
1033     }
1034     for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
1035         if (nota->name) {
1036             if (idx-- == 0) {
1037                 return GpgME::Notation(nota);
1038             }
1039         }
1040     }
1041     return GpgME::Notation();
1042 }
1043
1044 unsigned int UserID::Signature::numNotations() const
1045 {
1046     if (!sig) {
1047         return 0;
1048     }
1049     unsigned int count = 0;
1050     for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
1051         if (nota->name) {
1052             ++count; // others are policy URLs...
1053         }
1054     }
1055     return count;
1056 }
1057
1058 std::vector<Notation> UserID::Signature::notations() const
1059 {
1060     if (!sig) {
1061         return std::vector<GpgME::Notation>();
1062     }
1063     std::vector<GpgME::Notation> v;
1064     v.reserve(numNotations());
1065     for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
1066         if (nota->name) {
1067             v.push_back(GpgME::Notation(nota));
1068         }
1069     }
1070     return v;
1071 }
1072
1073 const char *UserID::Signature::policyURL() const
1074 {
1075     if (!sig) {
1076         return nullptr;
1077     }
1078     for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
1079         if (!nota->name) {
1080             return nota->value;
1081         }
1082     }
1083     return nullptr;
1084 }
1085
1086 bool UserID::Signature::isTrustSignature() const
1087 {
1088     return sig && sig->trust_depth > 0;
1089 }
1090
1091 TrustSignatureTrust UserID::Signature::trustValue() const
1092 {
1093     if (!sig || !isTrustSignature()) {
1094         return TrustSignatureTrust::None;
1095     }
1096     return sig->trust_value >= 120 ? TrustSignatureTrust::Complete : TrustSignatureTrust::Partial;
1097 }
1098
1099 unsigned int UserID::Signature::trustDepth() const
1100 {
1101     return sig ? sig->trust_depth : 0;
1102 }
1103
1104 const char *UserID::Signature::trustScope() const
1105 {
1106     return sig ? sig->trust_scope : nullptr;
1107 }
1108
1109 std::string UserID::addrSpecFromString(const char *userid)
1110 {
1111     if (!userid) {
1112         return std::string();
1113     }
1114     char *normalized = gpgme_addrspec_from_uid (userid);
1115     if (normalized) {
1116         std::string ret(normalized);
1117         gpgme_free(normalized);
1118         return ret;
1119     }
1120     return std::string();
1121 }
1122
1123 std::string UserID::addrSpec() const
1124 {
1125     if (!uid || !uid->address) {
1126         return std::string();
1127     }
1128
1129     return uid->address;
1130 }
1131
1132 Error UserID::revoke()
1133 {
1134     if (isNull()) {
1135         return Error::fromCode(GPG_ERR_GENERAL);
1136     }
1137     auto ctx = Context::createForProtocol(parent().protocol());
1138     if (!ctx) {
1139         return Error::fromCode(GPG_ERR_INV_ENGINE);
1140     }
1141     Error ret = ctx->revUid(key, id());
1142     delete ctx;
1143     return ret;
1144 }
1145
1146 static Key::Origin gpgme_origin_to_pp_origin (const unsigned int origin)
1147 {
1148     switch (origin) {
1149         case GPGME_KEYORG_KS:
1150             return Key::OriginKS;
1151         case GPGME_KEYORG_DANE:
1152             return Key::OriginDane;
1153         case GPGME_KEYORG_WKD:
1154             return Key::OriginWKD;
1155         case GPGME_KEYORG_URL:
1156             return Key::OriginURL;
1157         case GPGME_KEYORG_FILE:
1158             return Key::OriginFile;
1159         case GPGME_KEYORG_SELF:
1160             return Key::OriginSelf;
1161         case GPGME_KEYORG_OTHER:
1162             return Key::OriginOther;
1163         case GPGME_KEYORG_UNKNOWN:
1164         default:
1165             return Key::OriginUnknown;
1166     }
1167 }
1168
1169 Key::Origin UserID::origin() const
1170 {
1171     if (isNull()) {
1172         return Key::OriginUnknown;
1173     }
1174     return gpgme_origin_to_pp_origin(uid->origin);
1175 }
1176
1177 time_t UserID::lastUpdate() const
1178 {
1179     return static_cast<time_t>(uid ? uid->last_update : 0);
1180 }
1181
1182 Error Key::addUid(const char *uid)
1183 {
1184     if (isNull()) {
1185         return Error::fromCode(GPG_ERR_GENERAL);
1186     }
1187     auto ctx = Context::createForProtocol(protocol());
1188     if (!ctx) {
1189         return Error::fromCode(GPG_ERR_INV_ENGINE);
1190     }
1191     Error ret = ctx->addUid(key, uid);
1192     delete ctx;
1193     return ret;
1194 }
1195
1196 Key::Origin Key::origin() const
1197 {
1198     if (isNull()) {
1199         return OriginUnknown;
1200     }
1201     return gpgme_origin_to_pp_origin(key->origin);
1202 }
1203
1204 time_t Key::lastUpdate() const
1205 {
1206     return static_cast<time_t>(key ? key->last_update : 0);
1207 }
1208
1209 bool Key::isBad() const
1210 {
1211     return isNull() || isRevoked() || isExpired() || isDisabled() || isInvalid();
1212 }
1213
1214 bool Subkey::isBad() const
1215 {
1216     return isNull() || isRevoked() || isExpired() || isDisabled() || isInvalid();
1217 }
1218
1219 bool UserID::isBad() const
1220 {
1221     return isNull() || isRevoked() || isInvalid();
1222 }
1223
1224 bool UserID::Signature::isBad() const
1225 {
1226     return isNull() || isExpired() || isInvalid();
1227 }
1228
1229 std::ostream &operator<<(std::ostream &os, const UserID &uid)
1230 {
1231     os << "GpgME::UserID(";
1232     if (!uid.isNull()) {
1233         os << "\n name:      " << protect(uid.name())
1234            << "\n email:     " << protect(uid.email())
1235            << "\n mbox:      " << uid.addrSpec()
1236            << "\n comment:   " << protect(uid.comment())
1237            << "\n validity:  " << uid.validityAsString()
1238            << "\n revoked:   " << uid.isRevoked()
1239            << "\n invalid:   " << uid.isInvalid()
1240            << "\n numsigs:   " << uid.numSignatures()
1241            << "\n origin:    " << uid.origin()
1242            << "\n updated:   " << uid.lastUpdate()
1243            << "\n tofuinfo:\n" << uid.tofuInfo();
1244     }
1245     return os << ')';
1246 }
1247
1248 std::ostream &operator<<(std::ostream &os, const Subkey &subkey)
1249 {
1250     os << "GpgME::Subkey(";
1251     if (!subkey.isNull()) {
1252         os << "\n fingerprint:   " << protect(subkey.fingerprint())
1253            << "\n creationTime:  " << subkey.creationTime()
1254            << "\n expirationTime:" << subkey.expirationTime()
1255            << "\n isRevoked:     " << subkey.isRevoked()
1256            << "\n isExpired:     " << subkey.isExpired()
1257            << "\n isInvalid:     " << subkey.isRevoked()
1258            << "\n isDisabled:    " << subkey.isInvalid()
1259            << "\n canSign:       " << subkey.canSign()
1260            << "\n canEncrypt:    " << subkey.canEncrypt()
1261            << "\n canCertify:    " << subkey.canCertify()
1262            << "\n canAuth:       " << subkey.canAuthenticate();
1263     }
1264     return os << ')';
1265 }
1266
1267 std::ostream &operator<<(std::ostream &os, const Key &key)
1268 {
1269     os << "GpgME::Key(";
1270     if (!key.isNull()) {
1271         os << "\n protocol:   " << protect(key.protocolAsString())
1272            << "\n ownertrust: " << key.ownerTrustAsString()
1273            << "\n issuer:     " << protect(key.issuerName())
1274            << "\n fingerprint:" << protect(key.primaryFingerprint())
1275            << "\n listmode:   " << key.keyListMode()
1276            << "\n canSign:    " << key.canReallySign()
1277            << "\n canEncrypt: " << key.canEncrypt()
1278            << "\n canCertify: " << key.canCertify()
1279            << "\n canAuth:    " << key.canAuthenticate()
1280            << "\n origin:     " << key.origin()
1281            << "\n updated:    " << key.lastUpdate()
1282            << "\n uids:\n";
1283         const std::vector<UserID> uids = key.userIDs();
1284         std::copy(uids.begin(), uids.end(),
1285                   std::ostream_iterator<UserID>(os, "\n"));
1286         const std::vector<Subkey> subkeys = key.subkeys();
1287         std::copy(subkeys.begin(), subkeys.end(),
1288                   std::ostream_iterator<Subkey>(os, "\n"));
1289     }
1290     return os << ')';
1291 }
1292
1293 } // namespace GpgME