Coverage Report

Created: 2026-01-17 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rnp/src/lib/key.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2017-2024 [Ribose Inc](https://www.ribose.com).
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without modification,
6
 * are permitted provided that the following conditions are met:
7
 *
8
 * 1.  Redistributions of source code must retain the above copyright notice,
9
 *     this list of conditions and the following disclaimer.
10
 *
11
 * 2.  Redistributions in binary form must reproduce the above copyright notice,
12
 *     this list of conditions and the following disclaimer in the documentation
13
 *     and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#include "key.hpp"
28
#include "utils.h"
29
#include <librekey/key_store_g10.h>
30
#include "crypto/s2k.h"
31
#include "crypto/mem.h"
32
#include "crypto/signatures.h"
33
#include "keygen.hpp"
34
35
#include <librepgp/stream-packet.h>
36
#include <librepgp/stream-key.h>
37
#include <librepgp/stream-sig.h>
38
#include <librepgp/stream-armor.h>
39
40
#include <stdio.h>
41
#include <string.h>
42
#include <stdlib.h>
43
#include <cassert>
44
#include <time.h>
45
#include <algorithm>
46
#include <stdexcept>
47
#include "defaults.h"
48
49
void
50
pgp_validity_t::mark_valid()
51
0
{
52
0
    validated = true;
53
0
    valid = true;
54
0
    expired = false;
55
0
}
56
57
void
58
pgp_validity_t::reset()
59
234
{
60
234
    validated = false;
61
234
    valid = false;
62
234
    expired = false;
63
234
}
64
65
namespace rnp {
66
67
pgp_key_pkt_t *
68
pgp_decrypt_seckey_pgp(const RawPacket &raw, const pgp_key_pkt_t &pubkey, const char *password)
69
0
{
70
0
    try {
71
0
        MemorySource src(raw.data());
72
0
        auto         res = std::unique_ptr<pgp_key_pkt_t>(new pgp_key_pkt_t());
73
0
        if (res->parse(src.src()) || decrypt_secret_key(res.get(), password)) {
74
0
            return NULL;
75
0
        }
76
0
        return res.release();
77
0
    } catch (const std::exception &e) {
78
0
        RNP_LOG("%s", e.what());
79
0
        return NULL;
80
0
    }
81
0
}
82
83
/* Note that this function essentially serves two purposes.
84
 * - In the case of a protected key, it requests a password and
85
 *   uses it to decrypt the key and fill in key->key.seckey.
86
 * - In the case of an unprotected key, it simply re-loads
87
 *   key->key.seckey by parsing the key data in packets[0].
88
 */
89
pgp_key_pkt_t *
90
pgp_decrypt_seckey(const Key &                    key,
91
                   const pgp_password_provider_t &provider,
92
                   const pgp_password_ctx_t &     ctx)
93
0
{
94
    // sanity checks
95
0
    if (!key.is_secret()) {
96
0
        RNP_LOG("invalid args");
97
0
        return NULL;
98
0
    }
99
    // ask the provider for a password
100
0
    secure_array<char, MAX_PASSWORD_LENGTH> password;
101
0
    if (key.is_protected() &&
102
0
        !pgp_request_password(&provider, &ctx, password.data(), password.size())) {
103
0
        return NULL;
104
0
    }
105
    // attempt to decrypt with the provided password
106
0
    switch (key.format) {
107
0
    case KeyFormat::GPG:
108
0
    case KeyFormat::KBX:
109
0
        return pgp_decrypt_seckey_pgp(key.rawpkt(), key.pkt(), password.data());
110
0
    case KeyFormat::G10:
111
0
        return g10_decrypt_seckey(key.rawpkt(), key.pkt(), password.data());
112
0
    default:
113
0
        RNP_LOG("unexpected format: %d", static_cast<int>(key.format));
114
0
        return NULL;
115
0
    }
116
0
}
117
118
bool
119
Key::write_sec_pgp(pgp_dest_t &       dst,
120
                   pgp_key_pkt_t &    seckey,
121
                   const std::string &password,
122
                   RNG &              rng)
123
0
{
124
0
    bool           res = false;
125
0
    pgp_pkt_type_t oldtag = seckey.tag;
126
127
0
    seckey.tag = type();
128
0
    if (encrypt_secret_key(&seckey, password.c_str(), rng)) {
129
0
        goto done;
130
0
    }
131
0
    try {
132
0
        seckey.write(dst);
133
0
        res = !dst.werr;
134
0
    } catch (const std::exception &e) {
135
0
        RNP_LOG("%s", e.what());
136
0
    }
137
0
done:
138
0
    seckey.tag = oldtag;
139
0
    return res;
140
0
}
141
142
bool
143
Key::write_sec_rawpkt(pgp_key_pkt_t &seckey, const std::string &password, SecurityContext &ctx)
144
0
{
145
    // encrypt+write the key in the appropriate format
146
0
    try {
147
0
        MemoryDest memdst;
148
0
        switch (format) {
149
0
        case KeyFormat::GPG:
150
0
        case KeyFormat::KBX:
151
0
            if (!write_sec_pgp(memdst.dst(), seckey, password, ctx.rng)) {
152
0
                RNP_LOG("failed to write secret key");
153
0
                return false;
154
0
            }
155
0
            break;
156
0
        case KeyFormat::G10:
157
0
            if (!g10_write_seckey(&memdst.dst(), &seckey, password.c_str(), ctx)) {
158
0
                RNP_LOG("failed to write g10 secret key");
159
0
                return false;
160
0
            }
161
0
            break;
162
0
        default:
163
0
            RNP_LOG("invalid format");
164
0
            return false;
165
0
        }
166
167
0
        rawpkt_ = RawPacket((uint8_t *) memdst.memory(), memdst.writeb(), type());
168
0
        return true;
169
0
    } catch (const std::exception &e) {
170
0
        RNP_LOG("%s", e.what());
171
0
        return false;
172
0
    }
173
0
}
174
175
static bool
176
update_sig_expiration(pgp::pkt::Signature *      dst,
177
                      const pgp::pkt::Signature *src,
178
                      uint64_t                   create,
179
                      uint32_t                   expiry,
180
                      SecurityContext &          ctx)
181
0
{
182
0
    try {
183
0
        *dst = *src;
184
        // Upgrade old hashes to the more secure one
185
0
        SecurityRule rule(FeatureType::Hash, dst->halg, ctx.profile.def_level());
186
0
        if (ctx.profile.has_rule(
187
0
              FeatureType::Hash, dst->halg, ctx.time(), SecurityAction::Any)) {
188
0
            rule = ctx.profile.get_rule(
189
0
              FeatureType::Hash, dst->halg, ctx.time(), SecurityAction::Any);
190
0
        }
191
192
0
        if (rule.level != SecurityLevel::Default) {
193
0
            RNP_LOG("Warning: Weak hash algorithm, authomatically upgrading to SHA256");
194
0
            dst->halg = PGP_HASH_SHA256;
195
0
        }
196
0
        if (!expiry) {
197
0
            dst->remove_subpkt(dst->find_subpkt(pgp::pkt::sigsub::Type::KeyExpirationTime));
198
0
            ;
199
0
        } else {
200
0
            dst->set_key_expiration(expiry);
201
0
        }
202
0
        dst->set_creation(create);
203
0
        return true;
204
0
    } catch (const std::exception &e) {
205
0
        RNP_LOG("%s", e.what());
206
0
        return false;
207
0
    }
208
0
}
209
210
bool
211
pgp_key_set_expiration(Key *                          key,
212
                       Key *                          seckey,
213
                       uint32_t                       expiry,
214
                       const pgp_password_provider_t &prov,
215
                       SecurityContext &              ctx)
216
0
{
217
0
    if (!key->is_primary()) {
218
0
        RNP_LOG("Not a primary key");
219
0
        return false;
220
0
    }
221
222
0
    pgp::SigIDs sigs;
223
    /* update expiration for the latest direct-key signature and self-signature for each userid
224
     */
225
0
    auto sig = key->latest_selfsig(UserID::None, false);
226
0
    if (sig) {
227
0
        sigs.push_back(sig->sigid);
228
0
    }
229
0
    for (size_t uid = 0; uid < key->uid_count(); uid++) {
230
0
        sig = key->latest_selfsig(uid, false);
231
0
        if (sig) {
232
0
            sigs.push_back(sig->sigid);
233
0
        }
234
0
    }
235
0
    if (sigs.empty()) {
236
0
        RNP_LOG("No valid self-signature(s)");
237
0
        return false;
238
0
    }
239
240
0
    KeyLocker seclock(*seckey);
241
0
    for (const auto &sigid : sigs) {
242
0
        auto &sig = key->get_sig(sigid);
243
        /* update signature and re-sign it */
244
0
        if (!expiry && !sig.sig.has_subpkt(PGP_SIG_SUBPKT_KEY_EXPIRY)) {
245
0
            continue;
246
0
        }
247
248
        /* unlock secret key if needed */
249
0
        if (seckey->is_locked() && !seckey->unlock(prov)) {
250
0
            RNP_LOG("Failed to unlock secret key");
251
0
            return false;
252
0
        }
253
254
0
        pgp::pkt::Signature newsig;
255
0
        auto                oldsigid = sigid;
256
0
        if (!update_sig_expiration(&newsig, &sig.sig, ctx.time(), expiry, ctx)) {
257
0
            return false;
258
0
        }
259
0
        try {
260
0
            if (sig.is_cert()) {
261
0
                if (sig.uid >= key->uid_count()) {
262
0
                    RNP_LOG("uid not found");
263
0
                    return false;
264
0
                }
265
0
                seckey->sign_cert(key->pkt(), key->get_uid(sig.uid).pkt, newsig, ctx);
266
0
            } else {
267
                /* direct-key signature case */
268
0
                seckey->sign_direct(key->pkt(), newsig, ctx);
269
0
            }
270
            /* replace signature, first for secret key since it may be replaced in public */
271
0
            if (seckey->has_sig(oldsigid)) {
272
0
                seckey->replace_sig(oldsigid, newsig);
273
0
            }
274
0
            if (key != seckey) {
275
0
                key->replace_sig(oldsigid, newsig);
276
0
            }
277
0
        } catch (const std::exception &e) {
278
0
            RNP_LOG("failed to calculate or add signature: %s", e.what());
279
0
            return false;
280
0
        }
281
0
    }
282
283
0
    if (!seckey->refresh_data(ctx)) {
284
0
        RNP_LOG("Failed to refresh seckey data.");
285
0
        return false;
286
0
    }
287
0
    if ((key != seckey) && !key->refresh_data(ctx)) {
288
0
        RNP_LOG("Failed to refresh key data.");
289
0
        return false;
290
0
    }
291
0
    return true;
292
0
}
293
294
bool
295
pgp_subkey_set_expiration(Key *                          sub,
296
                          Key *                          primsec,
297
                          Key *                          secsub,
298
                          uint32_t                       expiry,
299
                          const pgp_password_provider_t &prov,
300
                          SecurityContext &              ctx)
301
0
{
302
0
    if (!sub->is_subkey()) {
303
0
        RNP_LOG("Not a subkey");
304
0
        return false;
305
0
    }
306
307
    /* find the latest valid subkey binding */
308
0
    auto subsig = sub->latest_binding(false);
309
0
    if (!subsig) {
310
0
        RNP_LOG("No valid subkey binding");
311
0
        return false;
312
0
    }
313
0
    if (!expiry && !subsig->sig.has_subpkt(PGP_SIG_SUBPKT_KEY_EXPIRY)) {
314
0
        return true;
315
0
    }
316
317
0
    KeyLocker primlock(*primsec);
318
0
    if (primsec->is_locked() && !primsec->unlock(prov)) {
319
0
        RNP_LOG("Failed to unlock primary key");
320
0
        return false;
321
0
    }
322
0
    bool      subsign = secsub->can_sign();
323
0
    KeyLocker sublock(*secsub);
324
0
    if (subsign && secsub->is_locked() && !secsub->unlock(prov)) {
325
0
        RNP_LOG("Failed to unlock subkey");
326
0
        return false;
327
0
    }
328
329
0
    try {
330
        /* update signature and re-sign */
331
0
        pgp::pkt::Signature newsig;
332
0
        auto                oldsigid = subsig->sigid;
333
0
        if (!update_sig_expiration(&newsig, &subsig->sig, ctx.time(), expiry, ctx)) {
334
0
            return false;
335
0
        }
336
0
        primsec->sign_subkey_binding(*secsub, newsig, ctx);
337
        /* replace signature, first for the secret key since it may be replaced in public */
338
0
        if (secsub->has_sig(oldsigid)) {
339
0
            secsub->replace_sig(oldsigid, newsig);
340
0
            if (!secsub->refresh_data(primsec, ctx)) {
341
0
                return false;
342
0
            }
343
0
        }
344
0
        if (sub == secsub) {
345
0
            return true;
346
0
        }
347
0
        sub->replace_sig(oldsigid, newsig);
348
0
        return sub->refresh_data(primsec, ctx);
349
0
    } catch (const std::exception &e) {
350
0
        RNP_LOG("%s", e.what());
351
0
        return false;
352
0
    }
353
0
}
354
355
Key *
356
find_suitable_key(
357
  pgp_op_t op, Key *key, KeyProvider *key_provider, bool no_primary, bool pref_pqc_sub)
358
0
{
359
0
    if (!key || !key_provider) {
360
0
        return NULL;
361
0
    }
362
0
    bool secret = false;
363
0
    switch (op) {
364
0
    case PGP_OP_ENCRYPT:
365
0
        break;
366
0
    case PGP_OP_SIGN:
367
0
    case PGP_OP_CERTIFY:
368
0
        secret = true;
369
0
        break;
370
0
    default:
371
0
        RNP_LOG("Unsupported operation: %d", (int) op);
372
0
        return NULL;
373
0
    }
374
    /* Return if specified primary key fits our needs */
375
0
    if (!no_primary && key->usable_for(op)) {
376
0
        return key;
377
0
    }
378
    /* Check for the case when we need to look up for a secret key */
379
0
    if (!no_primary && secret && key->is_public() && key->usable_for(op, true)) {
380
0
        KeyFingerprintSearch search(key->fp());
381
0
        Key *                sec = key_provider->request_key(search, op, secret);
382
0
        if (sec && sec->usable_for(op)) {
383
0
            return sec;
384
0
        }
385
0
    }
386
    /* Now look up for subkeys */
387
0
    Key *subkey = NULL;
388
0
    for (auto &fp : key->subkey_fps()) {
389
0
        KeyFingerprintSearch search(fp);
390
0
        Key *                cur = key_provider->request_key(search, op, secret);
391
0
        if (!cur || !cur->usable_for(op)) {
392
0
            continue;
393
0
        }
394
0
#if defined(ENABLE_PQC)
395
0
        if (pref_pqc_sub && op == PGP_OP_ENCRYPT) {
396
            /* prefer PQC encryption over non-PQC encryption. Assume non-PQC key is only there
397
             * for backwards compatibility. */
398
0
            if (subkey && subkey->is_pqc_alg() && !cur->is_pqc_alg()) {
399
                /* do not override already found PQC key with non-PQC key */
400
0
                continue;
401
0
            }
402
0
            if (subkey && cur->is_pqc_alg() && !subkey->is_pqc_alg()) {
403
                /* override non-PQC key with PQC key */
404
0
                subkey = cur;
405
0
                continue;
406
0
            }
407
0
        }
408
0
#endif
409
0
        if (!subkey || (cur->creation() > subkey->creation())) {
410
0
            subkey = cur;
411
0
        }
412
0
    }
413
0
    return subkey;
414
0
}
415
416
0
Key::Key(const pgp_key_pkt_t &keypkt) : pkt_(keypkt)
417
0
{
418
0
    if (!is_key_pkt(pkt_.tag) || !pkt_.material->alg()) {
419
0
        throw rnp_exception(RNP_ERROR_BAD_PARAMETERS);
420
0
    }
421
0
    fingerprint_ = pgp::Fingerprint(pkt_);
422
0
    grip_ = pkt_.material->grip();
423
424
    /* parse secret key if not encrypted */
425
0
    if (is_secret_key_pkt(pkt_.tag)) {
426
0
        bool cleartext = pkt_.sec_protection.s2k.usage == PGP_S2KU_NONE;
427
0
        if (cleartext && decrypt_secret_key(&pkt_, NULL)) {
428
0
            RNP_LOG("failed to setup key fields");
429
0
            throw rnp_exception(RNP_ERROR_BAD_PARAMETERS);
430
0
        }
431
        /* decryption resets validity */
432
0
        pkt_.material->set_validity(keypkt.material->validity());
433
0
    }
434
    /* add rawpacket */
435
0
    rawpkt_ = RawPacket(pkt_);
436
0
    format = KeyFormat::GPG;
437
0
}
438
439
0
Key::Key(const pgp_key_pkt_t &pkt, Key &primary) : Key(pkt)
440
0
{
441
0
    primary.link_subkey_fp(*this);
442
0
}
443
444
Key::Key(const Key &src, bool pubonly)
445
117
{
446
    /* Do some checks for g10 keys */
447
117
    if (src.format == KeyFormat::G10) {
448
117
        if (pubonly) {
449
0
            RNP_LOG("attempt to copy public part from g10 key");
450
0
            throw std::invalid_argument("pubonly");
451
0
        }
452
117
    }
453
454
117
    if (pubonly) {
455
0
        pkt_ = pgp_key_pkt_t(src.pkt_, true);
456
0
        rawpkt_ = RawPacket(pkt_);
457
117
    } else {
458
117
        pkt_ = src.pkt_;
459
117
        rawpkt_ = src.rawpkt_;
460
117
    }
461
462
117
    uids_ = src.uids_;
463
117
    sigs_ = src.sigs_;
464
117
    sigs_map_ = src.sigs_map_;
465
117
    keysigs_ = src.keysigs_;
466
117
    subkey_fps_ = src.subkey_fps_;
467
117
    primary_fp_set_ = src.primary_fp_set_;
468
117
    primary_fp_ = src.primary_fp_;
469
117
    expiration_ = src.expiration_;
470
117
    flags_ = src.flags_;
471
117
    fingerprint_ = src.fingerprint_;
472
117
    grip_ = src.grip_;
473
117
    uid0_ = src.uid0_;
474
117
    uid0_set_ = src.uid0_set_;
475
117
    revoked_ = src.revoked_;
476
117
    revocation_ = src.revocation_;
477
117
    revokers_ = src.revokers_;
478
117
    format = src.format;
479
117
    validity_ = src.validity_;
480
117
    valid_till_ = src.valid_till_;
481
117
}
482
483
0
Key::Key(const pgp_transferable_key_t &src) : Key(src.key)
484
0
{
485
    /* add direct-key signatures */
486
0
    for (auto &sig : src.signatures) {
487
0
        add_sig(sig);
488
0
    }
489
490
    /* add userids and their signatures */
491
0
    for (auto &uid : src.userids) {
492
0
        add_uid(uid);
493
0
    }
494
0
}
495
496
0
Key::Key(const pgp_transferable_subkey_t &src, Key *primary) : Key(src.subkey)
497
0
{
498
    /* add subkey binding signatures */
499
0
    for (auto &sig : src.signatures) {
500
0
        add_sig(sig);
501
0
    }
502
503
    /* setup key grips if primary is available */
504
0
    if (primary) {
505
0
        primary->link_subkey_fp(*this);
506
0
    }
507
0
}
508
509
size_t
510
Key::sig_count() const
511
0
{
512
0
    return sigs_.size();
513
0
}
514
515
Signature &
516
Key::get_sig(size_t idx)
517
0
{
518
0
    return get_sig(sigs_.at(idx));
519
0
}
520
521
const Signature &
522
Key::get_sig(size_t idx) const
523
0
{
524
0
    return get_sig(sigs_.at(idx));
525
0
}
526
527
bool
528
Key::has_sig(const pgp::SigID &id) const
529
0
{
530
0
    return sigs_map_.count(id);
531
0
}
532
533
Signature &
534
Key::get_sig(const pgp::SigID &id)
535
0
{
536
0
    if (!has_sig(id)) {
537
0
        throw rnp_exception(RNP_ERROR_BAD_PARAMETERS);
538
0
    }
539
0
    return sigs_map_.at(id);
540
0
}
541
542
const Signature &
543
Key::get_sig(const pgp::SigID &id) const
544
0
{
545
0
    if (!has_sig(id)) {
546
0
        throw rnp_exception(RNP_ERROR_BAD_PARAMETERS);
547
0
    }
548
0
    return sigs_map_.at(id);
549
0
}
550
551
Signature &
552
Key::replace_sig(const pgp::SigID &id, const pgp::pkt::Signature &newsig)
553
0
{
554
    /* save oldsig's uid */
555
0
    size_t uid = get_sig(id).uid;
556
    /* delete first old sig since we may have theoretically the same sigid */
557
0
    auto oldid = id;
558
0
    sigs_map_.erase(oldid);
559
0
    auto &res = sigs_map_.emplace(std::make_pair(newsig.get_id(), newsig)).first->second;
560
0
    res.uid = uid;
561
0
    auto it = std::find(sigs_.begin(), sigs_.end(), oldid);
562
0
    if (it == sigs_.end()) {
563
0
        throw rnp_exception(RNP_ERROR_BAD_STATE);
564
0
    }
565
0
    *it = res.sigid;
566
0
    if (uid == UserID::None) {
567
0
        auto it = std::find(keysigs_.begin(), keysigs_.end(), oldid);
568
0
        if (it == keysigs_.end()) {
569
0
            throw rnp_exception(RNP_ERROR_BAD_STATE);
570
0
        }
571
0
        *it = res.sigid;
572
0
    } else {
573
0
        uids_[uid].replace_sig(oldid, res.sigid);
574
0
    }
575
0
    return res;
576
0
}
577
578
Signature &
579
Key::add_sig(const pgp::pkt::Signature &sig, size_t uid, bool begin)
580
0
{
581
0
    auto sigid = sig.get_id();
582
0
    sigs_map_.erase(sigid);
583
0
    auto &res = sigs_map_.emplace(std::make_pair(sigid, sig)).first->second;
584
0
    res.uid = uid;
585
0
    if (uid == UserID::None) {
586
0
        size_t idx = begin ? 0 : keysigs_.size();
587
0
        sigs_.insert(sigs_.begin() + idx, sigid);
588
0
        keysigs_.insert(keysigs_.begin() + idx, sigid);
589
0
        return res;
590
0
    }
591
592
    /* Calculate correct position in sigs_ */
593
0
    size_t idx = keysigs_.size();
594
0
    for (size_t u = 0; u < uid; u++) {
595
0
        idx += uids_[u].sig_count();
596
0
    }
597
0
    if (!begin) {
598
0
        idx += uids_[uid].sig_count();
599
0
    }
600
0
    sigs_.insert(sigs_.begin() + idx, sigid);
601
0
    uids_[uid].add_sig(sigid, begin);
602
0
    return res;
603
0
}
604
605
bool
606
Key::del_sig(const pgp::SigID &sigid)
607
0
{
608
0
    if (!has_sig(sigid)) {
609
0
        return false;
610
0
    }
611
0
    uint32_t uid = get_sig(sigid).uid;
612
0
    if (uid == UserID::None) {
613
        /* signature over the key itself */
614
0
        auto it = std::find(keysigs_.begin(), keysigs_.end(), sigid);
615
0
        if (it != keysigs_.end()) {
616
0
            keysigs_.erase(it);
617
0
        }
618
0
    } else if (uid < uids_.size()) {
619
        /* userid-related signature */
620
0
        uids_[uid].del_sig(sigid);
621
0
    }
622
0
    auto it = std::find(sigs_.begin(), sigs_.end(), sigid);
623
0
    if (it != sigs_.end()) {
624
0
        sigs_.erase(it);
625
0
    }
626
0
    return sigs_map_.erase(sigid);
627
0
}
628
629
size_t
630
Key::del_sigs(const pgp::SigIDs &sigs)
631
0
{
632
    /* delete actual signatures */
633
0
    size_t res = 0;
634
0
    for (auto &sig : sigs) {
635
0
        res += sigs_map_.erase(sig);
636
0
    }
637
    /* rebuild vectors with signatures order */
638
0
    keysigs_.clear();
639
0
    for (auto &uid : uids_) {
640
0
        uid.clear_sigs();
641
0
    }
642
0
    pgp::SigIDs newsigs;
643
0
    newsigs.reserve(sigs_map_.size());
644
0
    for (auto &sigid : sigs_) {
645
0
        if (!sigs_map_.count(sigid)) {
646
0
            continue;
647
0
        }
648
0
        newsigs.push_back(sigid);
649
0
        uint32_t uid = get_sig(sigid).uid;
650
0
        if (uid == UserID::None) {
651
0
            keysigs_.push_back(sigid);
652
0
        } else {
653
0
            uids_[uid].add_sig(sigid);
654
0
        }
655
0
    }
656
0
    sigs_ = std::move(newsigs);
657
0
    return res;
658
0
}
659
660
size_t
661
Key::keysig_count() const
662
0
{
663
0
    return keysigs_.size();
664
0
}
665
666
Signature &
667
Key::get_keysig(size_t idx)
668
0
{
669
0
    return get_sig(keysigs_.at(idx));
670
0
}
671
672
size_t
673
Key::uid_count() const
674
0
{
675
0
    return uids_.size();
676
0
}
677
678
UserID &
679
Key::get_uid(size_t idx)
680
0
{
681
0
    return uids_.at(idx);
682
0
}
683
684
const UserID &
685
Key::get_uid(size_t idx) const
686
0
{
687
0
    return uids_.at(idx);
688
0
}
689
690
bool
691
Key::has_uid(const std::string &uidstr) const
692
0
{
693
0
    for (auto &userid : uids_) {
694
0
        if (!userid.valid) {
695
0
            continue;
696
0
        }
697
0
        if (userid.str == uidstr) {
698
0
            return true;
699
0
        }
700
0
    }
701
0
    return false;
702
0
}
703
704
uint32_t
705
Key::uid_idx(const pgp_userid_pkt_t &uid) const
706
0
{
707
0
    for (uint32_t idx = 0; idx < uids_.size(); idx++) {
708
0
        if (uids_[idx].pkt == uid) {
709
0
            return idx;
710
0
        }
711
0
    }
712
0
    return UserID::None;
713
0
}
714
715
void
716
Key::del_uid(size_t idx)
717
0
{
718
0
    if (idx >= uids_.size()) {
719
0
        throw std::out_of_range("idx");
720
0
    }
721
722
0
    pgp::SigIDs newsigs;
723
    /* copy sigs which do not belong to uid */
724
0
    newsigs.reserve(sigs_.size());
725
0
    for (auto &id : sigs_) {
726
0
        if (get_sig(id).uid == idx) {
727
0
            sigs_map_.erase(id);
728
0
            continue;
729
0
        }
730
0
        newsigs.push_back(id);
731
0
    }
732
0
    sigs_ = std::move(newsigs);
733
0
    uids_.erase(uids_.begin() + idx);
734
    /* update uids */
735
0
    if (idx == uids_.size()) {
736
0
        return;
737
0
    }
738
0
    for (auto &sig : sigs_map_) {
739
0
        if ((sig.second.uid == UserID::None) || (sig.second.uid <= idx)) {
740
0
            continue;
741
0
        }
742
0
        sig.second.uid--;
743
0
    }
744
0
}
745
746
bool
747
Key::has_primary_uid() const
748
0
{
749
0
    return uid0_set_;
750
0
}
751
752
uint32_t
753
Key::get_primary_uid() const
754
0
{
755
0
    if (!uid0_set_) {
756
0
        throw rnp_exception(RNP_ERROR_BAD_PARAMETERS);
757
0
    }
758
0
    return uid0_;
759
0
}
760
761
UserID &
762
Key::add_uid(const pgp_transferable_userid_t &uid)
763
0
{
764
    /* construct userid */
765
0
    uids_.emplace_back(uid.uid);
766
    /* add certifications */
767
0
    for (auto &sig : uid.signatures) {
768
0
        add_sig(sig, uid_count() - 1);
769
0
    }
770
0
    return uids_.back();
771
0
}
772
773
bool
774
Key::revoked() const
775
0
{
776
0
    return revoked_;
777
0
}
778
779
const Revocation &
780
Key::revocation() const
781
0
{
782
0
    if (!revoked_) {
783
0
        throw rnp_exception(RNP_ERROR_BAD_PARAMETERS);
784
0
    }
785
0
    return revocation_;
786
0
}
787
788
void
789
Key::clear_revokes()
790
0
{
791
0
    revoked_ = false;
792
0
    revocation_ = {};
793
0
    for (auto &uid : uids_) {
794
0
        uid.revoked = false;
795
0
        uid.revocation = {};
796
0
    }
797
0
}
798
799
void
800
Key::add_revoker(const pgp::Fingerprint &revoker)
801
0
{
802
0
    if (std::find(revokers_.begin(), revokers_.end(), revoker) == revokers_.end()) {
803
0
        revokers_.push_back(revoker);
804
0
    }
805
0
}
806
807
bool
808
Key::has_revoker(const pgp::Fingerprint &revoker) const
809
0
{
810
0
    return std::find(revokers_.begin(), revokers_.end(), revoker) != revokers_.end();
811
0
}
812
813
size_t
814
Key::revoker_count() const
815
0
{
816
0
    return revokers_.size();
817
0
}
818
819
const pgp::Fingerprint &
820
Key::get_revoker(size_t idx) const
821
0
{
822
0
    return revokers_.at(idx);
823
0
}
824
825
const pgp_key_pkt_t &
826
Key::pkt() const noexcept
827
0
{
828
0
    return pkt_;
829
0
}
830
831
pgp_key_pkt_t &
832
Key::pkt() noexcept
833
0
{
834
0
    return pkt_;
835
0
}
836
837
void
838
Key::set_pkt(const pgp_key_pkt_t &pkt)
839
117
{
840
117
    pkt_ = pkt;
841
117
}
842
843
const pgp::KeyMaterial *
844
Key::material() const noexcept
845
0
{
846
0
    return pkt_.material.get();
847
0
}
848
849
pgp::KeyMaterial *
850
Key::material() noexcept
851
0
{
852
0
    return pkt_.material.get();
853
0
}
854
855
pgp_pubkey_alg_t
856
Key::alg() const noexcept
857
0
{
858
0
    return pkt_.alg;
859
0
}
860
861
pgp_curve_t
862
Key::curve() const
863
0
{
864
0
    return material() ? material()->curve() : PGP_CURVE_UNKNOWN;
865
0
}
866
867
pgp_version_t
868
Key::version() const noexcept
869
0
{
870
0
    return pkt().version;
871
0
}
872
873
pgp_pkt_type_t
874
Key::type() const noexcept
875
0
{
876
0
    return pkt().tag;
877
0
}
878
879
bool
880
Key::encrypted() const noexcept
881
0
{
882
0
    return is_secret() && material() && !material()->secret();
883
0
}
884
885
uint8_t
886
Key::flags() const noexcept
887
0
{
888
0
    return flags_;
889
0
}
890
891
bool
892
Key::can_sign() const noexcept
893
0
{
894
0
    return flags_ & PGP_KF_SIGN;
895
0
}
896
897
bool
898
Key::can_certify() const noexcept
899
0
{
900
0
    return flags_ & PGP_KF_CERTIFY;
901
0
}
902
903
bool
904
Key::can_encrypt() const noexcept
905
0
{
906
0
    return flags_ & PGP_KF_ENCRYPT;
907
0
}
908
909
bool
910
Key::has_secret() const noexcept
911
0
{
912
0
    if (!is_secret()) {
913
0
        return false;
914
0
    }
915
0
    if ((format == KeyFormat::GPG) && pkt_.sec_data.empty()) {
916
0
        return false;
917
0
    }
918
0
    if (pkt_.sec_protection.s2k.usage == PGP_S2KU_NONE) {
919
0
        return true;
920
0
    }
921
0
    switch (pkt_.sec_protection.s2k.specifier) {
922
0
    case PGP_S2KS_SIMPLE:
923
0
    case PGP_S2KS_SALTED:
924
0
    case PGP_S2KS_ITERATED_AND_SALTED:
925
0
        return true;
926
0
    default:
927
0
        return false;
928
0
    }
929
0
}
930
931
#if defined(ENABLE_PQC)
932
bool
933
Key::is_pqc_alg() const
934
0
{
935
0
    switch (alg()) {
936
0
    case PGP_PKA_KYBER768_X25519:
937
0
        FALLTHROUGH_STATEMENT;
938
0
    case PGP_PKA_KYBER768_P256:
939
0
        FALLTHROUGH_STATEMENT;
940
0
    case PGP_PKA_KYBER1024_P384:
941
0
        FALLTHROUGH_STATEMENT;
942
0
    case PGP_PKA_KYBER768_BP256:
943
0
        FALLTHROUGH_STATEMENT;
944
0
    case PGP_PKA_KYBER1024_BP384:
945
0
        FALLTHROUGH_STATEMENT;
946
0
    case PGP_PKA_DILITHIUM3_ED25519:
947
0
        FALLTHROUGH_STATEMENT;
948
0
    case PGP_PKA_DILITHIUM3_P256:
949
0
        FALLTHROUGH_STATEMENT;
950
0
    case PGP_PKA_DILITHIUM5_P384:
951
0
        FALLTHROUGH_STATEMENT;
952
0
    case PGP_PKA_DILITHIUM3_BP256:
953
0
        FALLTHROUGH_STATEMENT;
954
0
    case PGP_PKA_DILITHIUM5_BP384:
955
0
        FALLTHROUGH_STATEMENT;
956
0
    case PGP_PKA_SPHINCSPLUS_SHA2:
957
0
        FALLTHROUGH_STATEMENT;
958
0
    case PGP_PKA_SPHINCSPLUS_SHAKE:
959
0
        return true;
960
0
    default:
961
0
        return false;
962
0
    }
963
0
}
964
#endif
965
966
bool
967
Key::usable_for(pgp_op_t op, bool if_secret) const
968
0
{
969
0
    switch (op) {
970
0
    case PGP_OP_ADD_SUBKEY:
971
0
        return is_primary() && can_sign() && (if_secret || has_secret());
972
0
    case PGP_OP_SIGN:
973
0
        return can_sign() && valid() && (if_secret || has_secret());
974
0
    case PGP_OP_CERTIFY:
975
0
        return can_certify() && valid() && (if_secret || has_secret());
976
0
    case PGP_OP_DECRYPT:
977
0
        return can_encrypt() && valid() && (if_secret || has_secret());
978
0
    case PGP_OP_UNLOCK:
979
0
    case PGP_OP_PROTECT:
980
0
    case PGP_OP_UNPROTECT:
981
0
        return has_secret();
982
0
    case PGP_OP_VERIFY:
983
0
        return can_sign() && valid();
984
0
    case PGP_OP_ADD_USERID:
985
0
        return is_primary() && can_sign() && (if_secret || has_secret());
986
0
    case PGP_OP_ENCRYPT:
987
0
        return can_encrypt() && valid();
988
0
    default:
989
0
        return false;
990
0
    }
991
0
}
992
993
uint32_t
994
Key::expiration() const noexcept
995
0
{
996
0
    if (pkt_.version >= 4) {
997
0
        return expiration_;
998
0
    }
999
    /* too large value for pkt.v3_days may overflow uint32_t */
1000
0
    if (pkt_.v3_days > (0xffffffffu / 86400)) {
1001
0
        return 0xffffffffu;
1002
0
    }
1003
0
    return (uint32_t) pkt_.v3_days * 86400;
1004
0
}
1005
1006
bool
1007
Key::expired() const noexcept
1008
0
{
1009
0
    return validity_.expired;
1010
0
}
1011
1012
uint32_t
1013
Key::creation() const noexcept
1014
0
{
1015
0
    return pkt_.creation_time;
1016
0
}
1017
1018
bool
1019
Key::is_public() const noexcept
1020
0
{
1021
0
    return is_public_key_pkt(pkt_.tag);
1022
0
}
1023
1024
bool
1025
Key::is_secret() const noexcept
1026
0
{
1027
0
    return is_secret_key_pkt(pkt_.tag);
1028
0
}
1029
1030
bool
1031
Key::is_primary() const noexcept
1032
117
{
1033
117
    return is_primary_key_pkt(pkt_.tag);
1034
117
}
1035
1036
bool
1037
Key::is_subkey() const noexcept
1038
585
{
1039
585
    return is_subkey_pkt(pkt_.tag);
1040
585
}
1041
1042
bool
1043
Key::is_locked() const noexcept
1044
0
{
1045
0
    if (!is_secret()) {
1046
0
        RNP_LOG("key is not a secret key");
1047
0
        return false;
1048
0
    }
1049
0
    return encrypted();
1050
0
}
1051
1052
bool
1053
Key::is_protected() const noexcept
1054
0
{
1055
    // sanity check
1056
0
    if (!is_secret()) {
1057
0
        RNP_LOG("Warning: this is not a secret key");
1058
0
    }
1059
0
    return pkt_.sec_protection.s2k.usage != PGP_S2KU_NONE;
1060
0
}
1061
1062
bool
1063
Key::valid() const noexcept
1064
0
{
1065
0
    return validity_.validated && validity_.valid && !validity_.expired;
1066
0
}
1067
1068
bool
1069
Key::validated() const noexcept
1070
117
{
1071
117
    return validity_.validated;
1072
117
}
1073
1074
uint64_t
1075
Key::valid_till_common(bool expiry) const
1076
0
{
1077
0
    if (!validated()) {
1078
0
        return 0;
1079
0
    }
1080
0
    uint64_t till = expiration() ? (uint64_t) creation() + expiration() : UINT64_MAX;
1081
0
    if (valid()) {
1082
0
        return till;
1083
0
    }
1084
0
    if (revoked()) {
1085
        /* we should not believe to the compromised key at all */
1086
0
        if (revocation_.code == PGP_REVOCATION_COMPROMISED) {
1087
0
            return 0;
1088
0
        }
1089
0
        auto &revsig = get_sig(revocation_.sigid);
1090
0
        if (revsig.sig.creation() > creation()) {
1091
            /* pick less time from revocation time and expiration time */
1092
0
            return std::min((uint64_t) revsig.sig.creation(), till);
1093
0
        }
1094
0
        return 0;
1095
0
    }
1096
    /* if key is not marked as expired then it wasn't valid at all */
1097
0
    return expiry ? till : 0;
1098
0
}
1099
1100
uint64_t
1101
Key::valid_till() const noexcept
1102
0
{
1103
0
    return valid_till_;
1104
0
}
1105
1106
bool
1107
Key::valid_at(uint64_t timestamp) const noexcept
1108
0
{
1109
    /* TODO: consider implementing more sophisticated checks, as key validity time could
1110
     * possibly be non-continuous */
1111
0
    return (timestamp >= creation()) && timestamp && (timestamp <= valid_till());
1112
0
}
1113
1114
const pgp::KeyID &
1115
Key::keyid() const noexcept
1116
0
{
1117
0
    return fingerprint_.keyid();
1118
0
}
1119
1120
const pgp::Fingerprint &
1121
Key::fp() const noexcept
1122
234
{
1123
234
    return fingerprint_;
1124
234
}
1125
1126
const pgp::KeyGrip &
1127
Key::grip() const noexcept
1128
0
{
1129
0
    return grip_;
1130
0
}
1131
1132
const pgp::Fingerprint &
1133
Key::primary_fp() const
1134
0
{
1135
0
    if (!primary_fp_set_) {
1136
0
        throw rnp_exception(RNP_ERROR_BAD_PARAMETERS);
1137
0
    }
1138
0
    return primary_fp_;
1139
0
}
1140
1141
bool
1142
Key::has_primary_fp() const noexcept
1143
0
{
1144
0
    return primary_fp_set_;
1145
0
}
1146
1147
void
1148
Key::unset_primary_fp() noexcept
1149
0
{
1150
0
    primary_fp_set_ = false;
1151
0
    primary_fp_ = {};
1152
0
}
1153
1154
void
1155
Key::link_subkey_fp(Key &subkey)
1156
0
{
1157
0
    if (!is_primary() || !subkey.is_subkey()) {
1158
0
        throw rnp_exception(RNP_ERROR_BAD_PARAMETERS);
1159
0
    }
1160
0
    subkey.primary_fp_ = fp();
1161
0
    subkey.primary_fp_set_ = true;
1162
0
    add_subkey_fp(subkey.fp());
1163
0
}
1164
1165
void
1166
Key::add_subkey_fp(const pgp::Fingerprint &fp)
1167
0
{
1168
0
    if (std::find(subkey_fps_.begin(), subkey_fps_.end(), fp) == subkey_fps_.end()) {
1169
0
        subkey_fps_.push_back(fp);
1170
0
    }
1171
0
}
1172
1173
size_t
1174
Key::subkey_count() const noexcept
1175
117
{
1176
117
    return subkey_fps_.size();
1177
117
}
1178
1179
void
1180
Key::remove_subkey_fp(const pgp::Fingerprint &fp)
1181
0
{
1182
0
    auto it = std::find(subkey_fps_.begin(), subkey_fps_.end(), fp);
1183
0
    if (it != subkey_fps_.end()) {
1184
0
        subkey_fps_.erase(it);
1185
0
    }
1186
0
}
1187
1188
const pgp::Fingerprint &
1189
Key::get_subkey_fp(size_t idx) const
1190
0
{
1191
0
    return subkey_fps_[idx];
1192
0
}
1193
1194
const pgp::Fingerprints &
1195
Key::subkey_fps() const
1196
0
{
1197
0
    return subkey_fps_;
1198
0
}
1199
1200
size_t
1201
Key::rawpkt_count() const
1202
0
{
1203
0
    if (format == KeyFormat::G10) {
1204
0
        return 1;
1205
0
    }
1206
0
    return 1 + uid_count() + sig_count();
1207
0
}
1208
1209
RawPacket &
1210
Key::rawpkt()
1211
0
{
1212
0
    return rawpkt_;
1213
0
}
1214
1215
const RawPacket &
1216
Key::rawpkt() const
1217
0
{
1218
0
    return rawpkt_;
1219
0
}
1220
1221
void
1222
Key::set_rawpkt(const RawPacket &src)
1223
117
{
1224
117
    rawpkt_ = src;
1225
117
}
1226
1227
bool
1228
Key::unlock(const pgp_password_provider_t &provider, pgp_op_t op)
1229
0
{
1230
    // sanity checks
1231
0
    if (!usable_for(PGP_OP_UNLOCK)) {
1232
0
        return false;
1233
0
    }
1234
    // see if it's already unlocked
1235
0
    if (!is_locked()) {
1236
0
        return true;
1237
0
    }
1238
1239
0
    pgp_password_ctx_t ctx(op, this);
1240
0
    pgp_key_pkt_t *    decrypted_seckey = pgp_decrypt_seckey(*this, provider, ctx);
1241
0
    if (!decrypted_seckey) {
1242
0
        return false;
1243
0
    }
1244
1245
    // move the decrypted mpis into the Key
1246
0
    pkt_.material = std::move(decrypted_seckey->material);
1247
0
    delete decrypted_seckey;
1248
0
    return true;
1249
0
}
1250
1251
bool
1252
Key::lock() noexcept
1253
0
{
1254
    // sanity checks
1255
0
    if (!is_secret()) {
1256
0
        RNP_LOG("invalid args");
1257
0
        return false;
1258
0
    }
1259
1260
    // see if it's already locked
1261
0
    if (is_locked()) {
1262
0
        return true;
1263
0
    }
1264
1265
0
    assert(material());
1266
0
    if (material()) {
1267
0
        material()->clear_secret();
1268
0
    }
1269
0
    return true;
1270
0
}
1271
1272
bool
1273
Key::protect(const rnp_key_protection_params_t &protection,
1274
             const pgp_password_provider_t &    password_provider,
1275
             SecurityContext &                  sctx)
1276
0
{
1277
0
    pgp_password_ctx_t ctx(PGP_OP_PROTECT, this);
1278
1279
    // ask the provider for a password
1280
0
    secure_array<char, MAX_PASSWORD_LENGTH> password;
1281
0
    if (!pgp_request_password(&password_provider, &ctx, password.data(), password.size())) {
1282
0
        return false;
1283
0
    }
1284
0
    return protect(pkt_, protection, password.data(), sctx);
1285
0
}
1286
1287
bool
1288
Key::protect(pgp_key_pkt_t &                    decrypted,
1289
             const rnp_key_protection_params_t &protection,
1290
             const std::string &                new_password,
1291
             SecurityContext &                  ctx)
1292
0
{
1293
0
    if (!is_secret()) {
1294
0
        RNP_LOG("Warning: this is not a secret key");
1295
0
        return false;
1296
0
    }
1297
0
    bool ownpkt = &decrypted == &pkt_;
1298
0
    if (!decrypted.material->secret()) {
1299
0
        RNP_LOG("Decrypted secret key must be provided");
1300
0
        return false;
1301
0
    }
1302
1303
    /* force encrypted-and-hashed and iterated-and-salted as it's the only method we support*/
1304
0
    pkt_.sec_protection.s2k.usage = PGP_S2KU_ENCRYPTED_AND_HASHED;
1305
0
    pkt_.sec_protection.s2k.specifier = PGP_S2KS_ITERATED_AND_SALTED;
1306
    /* use default values where needed */
1307
0
    pkt_.sec_protection.symm_alg =
1308
0
      protection.symm_alg ? protection.symm_alg : DEFAULT_PGP_SYMM_ALG;
1309
0
    pkt_.sec_protection.cipher_mode =
1310
0
      protection.cipher_mode ? protection.cipher_mode : DEFAULT_PGP_CIPHER_MODE;
1311
0
    pkt_.sec_protection.s2k.hash_alg =
1312
0
      protection.hash_alg ? protection.hash_alg : DEFAULT_PGP_HASH_ALG;
1313
0
    auto iter = protection.iterations;
1314
0
    if (!iter) {
1315
0
        iter = ctx.s2k_iterations(pkt_.sec_protection.s2k.hash_alg);
1316
0
    }
1317
0
    pkt_.sec_protection.s2k.iterations = pgp_s2k_round_iterations(iter);
1318
0
    if (!ownpkt) {
1319
        /* decrypted is assumed to be temporary variable so we may modify it */
1320
0
        decrypted.sec_protection = pkt_.sec_protection;
1321
0
    }
1322
1323
    /* write the protected key to raw packet */
1324
0
    return write_sec_rawpkt(decrypted, new_password, ctx);
1325
0
}
1326
1327
bool
1328
Key::unprotect(const pgp_password_provider_t &password_provider, SecurityContext &secctx)
1329
0
{
1330
    /* sanity check */
1331
0
    if (!is_secret()) {
1332
0
        RNP_LOG("Warning: this is not a secret key");
1333
0
        return false;
1334
0
    }
1335
    /* already unprotected */
1336
0
    if (!is_protected()) {
1337
0
        return true;
1338
0
    }
1339
    /* simple case */
1340
0
    if (!encrypted()) {
1341
0
        pkt_.sec_protection.s2k.usage = PGP_S2KU_NONE;
1342
0
        return write_sec_rawpkt(pkt_, "", secctx);
1343
0
    }
1344
1345
0
    pgp_password_ctx_t ctx(PGP_OP_UNPROTECT, this);
1346
1347
0
    pgp_key_pkt_t *decrypted_seckey = pgp_decrypt_seckey(*this, password_provider, ctx);
1348
0
    if (!decrypted_seckey) {
1349
0
        return false;
1350
0
    }
1351
0
    decrypted_seckey->sec_protection.s2k.usage = PGP_S2KU_NONE;
1352
0
    if (!write_sec_rawpkt(*decrypted_seckey, "", secctx)) {
1353
0
        delete decrypted_seckey;
1354
0
        return false;
1355
0
    }
1356
0
    pkt_ = std::move(*decrypted_seckey);
1357
    /* current logic is that unprotected key should be additionally unlocked */
1358
0
    assert(material());
1359
0
    if (material()) {
1360
0
        material()->clear_secret();
1361
0
    }
1362
0
    delete decrypted_seckey;
1363
0
    return true;
1364
0
}
1365
1366
void
1367
Key::write(pgp_dest_t &dst) const
1368
0
{
1369
    /* write key rawpacket */
1370
0
    rawpkt_.write(dst);
1371
1372
0
    if (format == KeyFormat::G10) {
1373
0
        return;
1374
0
    }
1375
1376
    /* write signatures on key */
1377
0
    for (auto &sigid : keysigs_) {
1378
0
        get_sig(sigid).raw.write(dst);
1379
0
    }
1380
1381
    /* write uids and their signatures */
1382
0
    for (const auto &uid : uids_) {
1383
0
        uid.rawpkt.write(dst);
1384
0
        for (size_t idx = 0; idx < uid.sig_count(); idx++) {
1385
0
            get_sig(uid.get_sig(idx)).raw.write(dst);
1386
0
        }
1387
0
    }
1388
0
}
1389
1390
void
1391
Key::write_xfer(pgp_dest_t &dst, const KeyStore *keyring) const
1392
0
{
1393
0
    write(dst);
1394
0
    if (dst.werr) {
1395
0
        RNP_LOG("Failed to export primary key");
1396
0
        return;
1397
0
    }
1398
1399
0
    if (!keyring) {
1400
0
        return;
1401
0
    }
1402
1403
    // Export subkeys
1404
0
    for (auto &fp : subkey_fps_) {
1405
0
        const Key *subkey = keyring->get_key(fp);
1406
0
        if (!subkey) {
1407
0
            std::string fphex = bin_to_hex(fp.data(), fp.size(), HexFormat::Lowercase);
1408
0
            RNP_LOG("Warning! Subkey %s not found.", fphex.c_str());
1409
0
            continue;
1410
0
        }
1411
0
        subkey->write(dst);
1412
0
        if (dst.werr) {
1413
0
            RNP_LOG("Error occurred when exporting a subkey");
1414
0
            return;
1415
0
        }
1416
0
    }
1417
0
}
1418
1419
bool
1420
Key::write_autocrypt(pgp_dest_t &dst, Key &sub, uint32_t uid)
1421
0
{
1422
0
    auto cert = latest_uid_selfcert(uid);
1423
0
    if (!cert) {
1424
0
        RNP_LOG("No valid uid certification");
1425
0
        return false;
1426
0
    }
1427
0
    auto binding = sub.latest_binding();
1428
0
    if (!binding) {
1429
0
        RNP_LOG("No valid binding for subkey");
1430
0
        return false;
1431
0
    }
1432
0
    if (is_secret() || sub.is_secret()) {
1433
0
        RNP_LOG("Public key required");
1434
0
        return false;
1435
0
    }
1436
1437
0
    try {
1438
        /* write all or nothing */
1439
0
        MemoryDest memdst;
1440
0
        pkt().write(memdst.dst());
1441
0
        get_uid(uid).pkt.write(memdst.dst());
1442
0
        cert->sig.write(memdst.dst());
1443
0
        sub.pkt().write(memdst.dst());
1444
0
        binding->sig.write(memdst.dst());
1445
0
        dst_write(&dst, memdst.memory(), memdst.writeb());
1446
0
        return !dst.werr;
1447
0
    } catch (const std::exception &e) {
1448
0
        RNP_LOG("%s", e.what());
1449
0
        return false;
1450
0
    }
1451
0
}
1452
1453
std::vector<uint8_t>
1454
Key::write_vec() const
1455
0
{
1456
0
    MemoryDest dst;
1457
0
    write(dst.dst());
1458
0
    return dst.to_vector();
1459
0
}
1460
1461
Signature *
1462
Key::latest_selfsig(uint32_t uid, bool validated)
1463
351
{
1464
351
    uint32_t   latest = 0;
1465
351
    Signature *res = nullptr;
1466
1467
351
    for (auto &sigid : sigs_) {
1468
0
        auto &sig = get_sig(sigid);
1469
0
        if (validated && !sig.validity.valid()) {
1470
0
            continue;
1471
0
        }
1472
0
        bool skip = false;
1473
0
        switch (uid) {
1474
0
        case UserID::None:
1475
0
            skip = (sig.uid != UserID::None) || !is_direct_self(sig);
1476
0
            break;
1477
0
        case UserID::Primary: {
1478
0
            skip = !is_self_cert(sig) ||
1479
0
                   !sig.sig.get_subpkt(pgp::pkt::sigsub::Type::PrimaryUserID) ||
1480
0
                   !sig.sig.primary_uid() || (sig.uid == UserID::None);
1481
0
            break;
1482
0
        }
1483
0
        case UserID::Any:
1484
0
            skip = !is_self_cert(sig) || (sig.uid == UserID::None);
1485
0
            break;
1486
0
        default:
1487
0
            skip = (sig.uid != uid) || !is_self_cert(sig);
1488
0
            break;
1489
0
        }
1490
0
        if (skip) {
1491
0
            continue;
1492
0
        }
1493
1494
0
        uint32_t creation = sig.sig.creation();
1495
0
        if (creation >= latest) {
1496
0
            latest = creation;
1497
0
            res = &sig;
1498
0
        }
1499
0
    }
1500
1501
    /* if there is later self-sig for the same uid without primary flag, then drop res */
1502
351
    if ((uid == UserID::Primary) && res) {
1503
0
        auto overres = latest_selfsig(res->uid, validated);
1504
0
        if (overres && (overres->sig.creation() > res->sig.creation())) {
1505
0
            res = nullptr;
1506
0
        }
1507
0
    }
1508
351
    return res;
1509
351
}
1510
1511
Signature *
1512
Key::latest_binding(bool validated)
1513
0
{
1514
0
    uint32_t   latest = 0;
1515
0
    Signature *res = nullptr;
1516
1517
0
    for (auto &sigid : sigs_) {
1518
0
        auto &sig = get_sig(sigid);
1519
0
        if (validated && !sig.validity.valid()) {
1520
0
            continue;
1521
0
        }
1522
0
        if (!is_binding(sig)) {
1523
0
            continue;
1524
0
        }
1525
1526
0
        uint32_t creation = sig.sig.creation();
1527
0
        if (creation >= latest) {
1528
0
            latest = creation;
1529
0
            res = &sig;
1530
0
        }
1531
0
    }
1532
0
    return res;
1533
0
}
1534
1535
Signature *
1536
Key::latest_uid_selfcert(uint32_t uid)
1537
0
{
1538
0
    uint32_t   latest = 0;
1539
0
    Signature *res = nullptr;
1540
1541
0
    if (uid >= uids_.size()) {
1542
0
        return NULL;
1543
0
    }
1544
1545
0
    for (size_t idx = 0; idx < uids_[uid].sig_count(); idx++) {
1546
0
        auto &sig = get_sig(uids_[uid].get_sig(idx));
1547
0
        if (!sig.validity.valid() || (sig.uid != uid)) {
1548
0
            continue;
1549
0
        }
1550
0
        if (!is_self_cert(sig)) {
1551
0
            continue;
1552
0
        }
1553
1554
0
        uint32_t creation = sig.sig.creation();
1555
0
        if (creation >= latest) {
1556
0
            latest = creation;
1557
0
            res = &sig;
1558
0
        }
1559
0
    }
1560
0
    return res;
1561
0
}
1562
1563
bool
1564
Key::is_signer(const Signature &sig) const
1565
0
{
1566
    /* if we have fingerprint let's check it */
1567
0
    if (sig.sig.has_keyfp()) {
1568
0
        return sig.sig.keyfp() == fp();
1569
0
    }
1570
0
    if (!sig.sig.has_keyid()) {
1571
0
        return false;
1572
0
    }
1573
0
    return keyid() == sig.sig.keyid();
1574
0
}
1575
1576
bool
1577
Key::expired_with(const Signature &sig, uint64_t at) const
1578
0
{
1579
    /* key expiration: absence of subpkt or 0 means it never expires */
1580
0
    uint64_t expiration = sig.sig.key_expiration();
1581
0
    if (!expiration) {
1582
0
        return false;
1583
0
    }
1584
0
    return expiration + creation() < at;
1585
0
}
1586
1587
bool
1588
Key::is_self_cert(const Signature &sig) const
1589
0
{
1590
0
    return is_primary() && sig.is_cert() && is_signer(sig);
1591
0
}
1592
1593
bool
1594
Key::is_direct_self(const Signature &sig) const
1595
0
{
1596
0
    return is_primary() && (sig.sig.type() == PGP_SIG_DIRECT) && is_signer(sig);
1597
0
}
1598
1599
bool
1600
Key::is_revocation(const Signature &sig) const
1601
0
{
1602
0
    return is_primary() ? (sig.sig.type() == PGP_SIG_REV_KEY) :
1603
0
                          (sig.sig.type() == PGP_SIG_REV_SUBKEY);
1604
0
}
1605
1606
bool
1607
Key::is_uid_revocation(const Signature &sig) const
1608
0
{
1609
0
    return is_primary() && (sig.sig.type() == PGP_SIG_REV_CERT);
1610
0
}
1611
1612
bool
1613
Key::is_binding(const Signature &sig) const
1614
0
{
1615
0
    return is_subkey() && (sig.sig.type() == PGP_SIG_SUBKEY);
1616
0
}
1617
1618
void
1619
Key::validate_sig(const Key &key, Signature &sig, const SecurityContext &ctx) const noexcept
1620
0
{
1621
0
    sig.validity.reset();
1622
1623
0
    SignatureInfo sinfo;
1624
0
    sinfo.sig = &sig.sig;
1625
0
    sinfo.signer_valid = true;
1626
0
    sinfo.ignore_expiry = key.is_self_cert(sig) || key.is_binding(sig);
1627
0
    sinfo.ignore_sig_expiry = sig.is_revocation();
1628
1629
0
    pgp_sig_type_t stype = sig.sig.type();
1630
0
    try {
1631
0
        switch (stype) {
1632
0
        case PGP_SIG_BINARY:
1633
0
        case PGP_SIG_TEXT:
1634
0
        case PGP_SIG_STANDALONE:
1635
0
        case PGP_SIG_PRIMARY:
1636
0
            RNP_LOG("Invalid key signature type: %d", (int) stype);
1637
0
            sinfo.validity.add_error(RNP_ERROR_SIG_WRONG_KEY_SIG);
1638
0
            break;
1639
0
        case PGP_CERT_GENERIC:
1640
0
        case PGP_CERT_PERSONA:
1641
0
        case PGP_CERT_CASUAL:
1642
0
        case PGP_CERT_POSITIVE:
1643
0
        case PGP_SIG_REV_CERT: {
1644
0
            if (sig.uid >= key.uid_count()) {
1645
0
                RNP_LOG("Userid not found");
1646
0
                sinfo.validity.add_error(RNP_ERROR_SIG_UID_MISSING);
1647
0
                break;
1648
0
            }
1649
0
            validate_cert(sinfo, key.pkt(), key.get_uid(sig.uid).pkt, ctx);
1650
0
            break;
1651
0
        }
1652
0
        case PGP_SIG_SUBKEY:
1653
0
            if (!is_signer(sig)) {
1654
0
                RNP_LOG("Invalid subkey binding's signer.");
1655
0
                sinfo.validity.add_error(RNP_ERROR_SIG_WRONG_BINDING);
1656
0
                break;
1657
0
            }
1658
0
            validate_binding(sinfo, key, ctx);
1659
0
            break;
1660
0
        case PGP_SIG_DIRECT:
1661
0
            if (!is_signer(sig)) {
1662
0
                RNP_LOG("Invalid direct key signer.");
1663
0
                sinfo.validity.add_error(RNP_ERROR_SIG_WRONG_DIRECT);
1664
0
                break;
1665
0
            }
1666
0
            validate_direct(sinfo, ctx);
1667
0
            break;
1668
0
        case PGP_SIG_REV_KEY:
1669
0
            if (!is_signer(sig)) {
1670
0
                RNP_LOG("Invalid key revocation signer.");
1671
0
                sinfo.validity.add_error(RNP_ERROR_SIG_WRONG_REV);
1672
0
                break;
1673
0
            }
1674
0
            validate_key_rev(sinfo, key.pkt(), ctx);
1675
0
            break;
1676
0
        case PGP_SIG_REV_SUBKEY:
1677
0
            if (!is_signer(sig)) {
1678
0
                RNP_LOG("Invalid subkey revocation's signer.");
1679
0
                sinfo.validity.add_error(RNP_ERROR_SIG_WRONG_REV);
1680
0
                break;
1681
0
            }
1682
0
            validate_sub_rev(sinfo, key.pkt(), ctx);
1683
0
            break;
1684
0
        default:
1685
0
            RNP_LOG("Unsupported key signature type: %d", (int) stype);
1686
0
            sinfo.validity.add_error(RNP_ERROR_SIG_UNSUPPORTED);
1687
0
            break;
1688
0
        }
1689
0
    } catch (const std::exception &e) {
1690
0
        RNP_LOG("Key signature validation failed: %s", e.what());
1691
0
        sinfo.validity.add_error(RNP_ERROR_SIG_ERROR);
1692
0
    }
1693
1694
0
    sinfo.validity.mark_validated();
1695
0
    sig.validity = std::move(sinfo.validity);
1696
0
}
1697
1698
void
1699
Key::validate_sig(SignatureInfo &          sinfo,
1700
                  Hash &                   hash,
1701
                  const SecurityContext &  ctx,
1702
                  const pgp_literal_hdr_t *hdr) const noexcept
1703
0
{
1704
    /* Validate signature itself */
1705
0
    auto res = signature_validate(*sinfo.sig, *pkt_.material, hash, ctx, hdr);
1706
0
    if (!sinfo.signer_valid && !valid_at(sinfo.sig->creation())) {
1707
0
        RNP_LOG("invalid or untrusted key");
1708
0
        res.add_error(RNP_ERROR_SIG_SIGNER_UNTRUSTED);
1709
0
    }
1710
1711
    /* Check signature's expiration time */
1712
0
    uint32_t now = ctx.time();
1713
0
    uint32_t create = sinfo.sig->creation();
1714
0
    uint32_t expiry = sinfo.sig->expiration();
1715
0
    if (create > now) {
1716
        /* signature created later then now */
1717
0
        RNP_LOG("signature created %d seconds in future", (int) (create - now));
1718
0
        if (!sinfo.ignore_sig_expiry) {
1719
0
            res.add_error(RNP_ERROR_SIG_FROM_FUTURE);
1720
0
        }
1721
0
    }
1722
0
    if (create && expiry && (create + expiry < now)) {
1723
        /* signature expired */
1724
0
        RNP_LOG("signature expired");
1725
0
        if (!sinfo.ignore_sig_expiry) {
1726
0
            res.add_error(RNP_ERROR_SIG_EXPIRED);
1727
0
        }
1728
0
    }
1729
1730
    /* check key creation time vs signature creation */
1731
0
    if (creation() > create) {
1732
0
        RNP_LOG("key is newer than signature");
1733
0
        res.add_error(RNP_ERROR_SIG_OLDER_KEY);
1734
0
    }
1735
1736
    /* check whether key was not expired when sig created */
1737
0
    if (!sinfo.ignore_expiry && expiration() && (creation() + expiration() < create)) {
1738
0
        RNP_LOG("signature made after key expiration");
1739
0
        res.add_error(RNP_ERROR_SIG_EXPIRED_KEY);
1740
0
    }
1741
1742
    /* Check signer's fingerprint */
1743
0
    if (sinfo.sig->has_keyfp() && (sinfo.sig->keyfp() != fp())) {
1744
0
        RNP_LOG("issuer fingerprint doesn't match signer's one");
1745
0
        res.add_error(RNP_ERROR_SIG_FP_MISMATCH);
1746
0
    }
1747
1748
    /* Check for unknown critical notations */
1749
0
    for (auto &subpkt : sinfo.sig->subpkts) {
1750
0
        if (!subpkt->critical() || (subpkt->type() != pgp::pkt::sigsub::Type::NotationData)) {
1751
0
            continue;
1752
0
        }
1753
0
        auto &notation = dynamic_cast<pgp::pkt::sigsub::NotationData &>(*subpkt);
1754
0
        RNP_LOG("unknown critical notation: %s", notation.name().c_str());
1755
0
        res.add_error(RNP_ERROR_SIG_UNKNOWN_NOTATION);
1756
0
    }
1757
1758
0
    for (auto &err : res.errors()) {
1759
0
        sinfo.validity.add_error(err);
1760
0
    }
1761
0
    sinfo.validity.mark_validated();
1762
0
}
1763
1764
void
1765
Key::validate_cert(SignatureInfo &         sinfo,
1766
                   const pgp_key_pkt_t &   key,
1767
                   const pgp_userid_pkt_t &uid,
1768
                   const SecurityContext & ctx) const
1769
0
{
1770
0
    auto hash = signature_hash_certification(*sinfo.sig, key, uid);
1771
0
    validate_sig(sinfo, *hash, ctx);
1772
0
}
1773
1774
void
1775
Key::validate_binding(SignatureInfo &        sinfo,
1776
                      const Key &            subkey,
1777
                      const SecurityContext &ctx) const
1778
0
{
1779
0
    if (!is_primary() || !subkey.is_subkey()) {
1780
0
        RNP_LOG("Invalid binding signature key type(s)");
1781
0
        sinfo.validity.add_error(RNP_ERROR_SIG_ERROR);
1782
0
        sinfo.validity.mark_validated();
1783
0
        return;
1784
0
    }
1785
0
    auto hash = signature_hash_binding(*sinfo.sig, pkt(), subkey.pkt());
1786
0
    validate_sig(sinfo, *hash, ctx);
1787
    /* Check whether subkey is capable of signing and return otherwise */
1788
0
    if (!sinfo.validity.valid() || !(sinfo.sig->key_flags() & PGP_KF_SIGN)) {
1789
0
        return;
1790
0
    }
1791
1792
    /* check primary key binding signature if any */
1793
0
    auto sub = dynamic_cast<pgp::pkt::sigsub::EmbeddedSignature *>(
1794
0
      sinfo.sig->get_subpkt(pgp::pkt::sigsub::Type::EmbeddedSignature, false));
1795
0
    if (!sub) {
1796
0
        RNP_LOG("error! no primary key binding signature");
1797
0
        sinfo.validity.add_error(RNP_ERROR_SIG_NO_PRIMARY_BINDING);
1798
0
        return;
1799
0
    }
1800
0
    if (!sub->signature()) {
1801
0
        RNP_LOG("invalid embedded signature subpacket");
1802
0
        sinfo.validity.add_error(RNP_ERROR_SIG_BINDING_PARSE);
1803
0
        return;
1804
0
    }
1805
0
    if (sub->signature()->type() != PGP_SIG_PRIMARY) {
1806
0
        RNP_LOG("invalid primary key binding signature");
1807
0
        sinfo.validity.add_error(RNP_ERROR_SIG_WRONG_BIND_TYPE);
1808
0
        return;
1809
0
    }
1810
0
    if (sub->signature()->version < PGP_V4) {
1811
0
        RNP_LOG("invalid primary key binding signature version");
1812
0
        sinfo.validity.add_error(RNP_ERROR_SIG_WRONG_BIND_TYPE);
1813
0
        return;
1814
0
    }
1815
1816
0
    hash = signature_hash_binding(*sub->signature(), pkt(), subkey.pkt());
1817
0
    SignatureInfo bindinfo;
1818
0
    bindinfo.sig = sub->signature();
1819
0
    bindinfo.signer_valid = true;
1820
0
    bindinfo.ignore_expiry = true;
1821
0
    subkey.validate_sig(bindinfo, *hash, ctx);
1822
0
    if (!bindinfo.validity.valid()) {
1823
0
        sinfo.validity.add_error(RNP_ERROR_SIG_INVALID_BINDING);
1824
0
        for (auto &err : bindinfo.validity.errors()) {
1825
0
            sinfo.validity.add_error(err);
1826
0
        }
1827
0
    }
1828
0
}
1829
1830
void
1831
Key::validate_sub_rev(SignatureInfo &        sinfo,
1832
                      const pgp_key_pkt_t &  subkey,
1833
                      const SecurityContext &ctx) const
1834
0
{
1835
0
    auto hash = signature_hash_binding(*sinfo.sig, pkt(), subkey);
1836
0
    validate_sig(sinfo, *hash, ctx);
1837
0
}
1838
1839
void
1840
Key::validate_direct(SignatureInfo &sinfo, const SecurityContext &ctx) const
1841
0
{
1842
0
    auto hash = signature_hash_direct(*sinfo.sig, pkt());
1843
0
    validate_sig(sinfo, *hash, ctx);
1844
0
}
1845
1846
void
1847
Key::validate_key_rev(SignatureInfo &        sinfo,
1848
                      const pgp_key_pkt_t &  key,
1849
                      const SecurityContext &ctx) const
1850
0
{
1851
0
    auto hash = signature_hash_direct(*sinfo.sig, key);
1852
0
    validate_sig(sinfo, *hash, ctx);
1853
0
}
1854
1855
void
1856
Key::validate_self_signatures(const SecurityContext &ctx)
1857
117
{
1858
117
    for (auto &sigid : sigs_) {
1859
0
        auto &sig = get_sig(sigid);
1860
0
        if (sig.validity.validated()) {
1861
0
            continue;
1862
0
        }
1863
0
        if (!is_signer(sig)) {
1864
0
            continue;
1865
0
        }
1866
1867
0
        if (is_direct_self(sig) || is_self_cert(sig) || is_uid_revocation(sig) ||
1868
0
            is_revocation(sig)) {
1869
0
            validate_sig(*this, sig, ctx);
1870
0
        }
1871
0
    }
1872
117
}
1873
1874
void
1875
Key::validate_self_signatures(Key &primary, const SecurityContext &ctx)
1876
0
{
1877
0
    for (auto &sigid : sigs_) {
1878
0
        auto &sig = get_sig(sigid);
1879
0
        if (sig.validity.validated()) {
1880
0
            continue;
1881
0
        }
1882
1883
0
        if (is_binding(sig) || is_revocation(sig)) {
1884
0
            primary.validate_sig(*this, sig, ctx);
1885
0
        }
1886
0
    }
1887
0
}
1888
1889
bool
1890
Key::validate_desig_revokes(KeyStore &keyring)
1891
117
{
1892
117
    if (revokers_.empty()) {
1893
117
        return false;
1894
117
    }
1895
0
    bool refresh = false;
1896
0
    for (auto &sigid : sigs_) {
1897
0
        auto &sig = get_sig(sigid);
1898
0
        if (!is_revocation(sig) || is_signer(sig)) {
1899
0
            continue;
1900
0
        }
1901
        /* Don't think we should deal with sigs without issuer's fingerprint */
1902
0
        if (!sig.sig.has_keyfp() || !has_revoker(sig.sig.keyfp())) {
1903
0
            continue;
1904
0
        }
1905
        /* If signature was validated and valid, do not re-validate it */
1906
0
        if (sig.validity.valid()) {
1907
0
            continue;
1908
0
        }
1909
1910
0
        auto revoker = keyring.get_signer(sig.sig);
1911
0
        if (!revoker) {
1912
0
            continue;
1913
0
        }
1914
1915
0
        revoker->validate_sig(*this, sig, keyring.secctx);
1916
0
        if (sig.validity.valid()) {
1917
            /* return true only if new valid revocation was added */
1918
0
            refresh = true;
1919
0
        }
1920
0
    }
1921
1922
0
    return refresh;
1923
117
}
1924
1925
void
1926
Key::validate_primary(KeyStore &keyring)
1927
117
{
1928
    /* validate signatures if needed */
1929
117
    validate_self_signatures(keyring.secctx);
1930
1931
    /* consider public key as valid on this level if it is not expired and has at least one
1932
     * valid self-signature, and is not revoked */
1933
117
    validity_.reset();
1934
117
    validity_.validated = true;
1935
117
    bool has_cert = false;
1936
117
    bool has_expired = false;
1937
    /* check whether key is revoked */
1938
117
    for (auto &sigid : sigs_) {
1939
0
        auto &sig = get_sig(sigid);
1940
0
        if (!sig.validity.valid()) {
1941
0
            continue;
1942
0
        }
1943
0
        if (is_revocation(sig)) {
1944
0
            return;
1945
0
        }
1946
0
    }
1947
    /* if we have direct-key signature, then it has higher priority for expiration check */
1948
117
    uint64_t now = keyring.secctx.time();
1949
117
    auto     dirsig = latest_selfsig(UserID::None);
1950
117
    if (dirsig) {
1951
0
        has_expired = expired_with(*dirsig, now);
1952
0
        has_cert = !has_expired;
1953
0
    }
1954
    /* if we have primary uid and it is more restrictive, then use it as well */
1955
117
    Signature *prisig = nullptr;
1956
117
    if (!has_expired && (prisig = latest_selfsig(UserID::Primary))) {
1957
0
        has_expired = expired_with(*prisig, now);
1958
0
        has_cert = !has_expired;
1959
0
    }
1960
    /* if we don't have direct-key sig and primary uid, use the latest self-cert */
1961
117
    Signature *latest = nullptr;
1962
117
    if (!dirsig && !prisig && (latest = latest_selfsig(UserID::Any))) {
1963
0
        has_expired = expired_with(*latest, now);
1964
0
        has_cert = !has_expired;
1965
0
    }
1966
1967
    /* we have at least one non-expiring key self-signature */
1968
117
    if (has_cert) {
1969
0
        validity_.valid = true;
1970
0
        return;
1971
0
    }
1972
    /* we have valid self-signature which expires key */
1973
117
    if (has_expired) {
1974
0
        validity_.expired = true;
1975
0
        return;
1976
0
    }
1977
1978
    /* let's check whether key has at least one valid subkey binding */
1979
117
    for (size_t i = 0; i < subkey_count(); i++) {
1980
0
        Key *sub = keyring.get_subkey(*this, i);
1981
0
        if (!sub) {
1982
0
            continue;
1983
0
        }
1984
0
        sub->validate_self_signatures(*this, keyring.secctx);
1985
0
        auto sig = sub->latest_binding();
1986
0
        if (!sig) {
1987
0
            continue;
1988
0
        }
1989
        /* check whether subkey is expired - then do not mark key as valid */
1990
0
        if (sub->expired_with(*sig, now)) {
1991
0
            continue;
1992
0
        }
1993
0
        validity_.valid = true;
1994
0
        return;
1995
0
    }
1996
117
}
1997
1998
void
1999
Key::validate_subkey(Key *primary, const SecurityContext &ctx)
2000
0
{
2001
    /* consider subkey as valid on this level if it has valid primary key, has at least one
2002
     * non-expired binding signature, and is not revoked. */
2003
0
    validity_.reset();
2004
0
    validity_.validated = true;
2005
0
    if (!primary || (!primary->valid() && !primary->expired())) {
2006
0
        return;
2007
0
    }
2008
    /* validate signatures if needed */
2009
0
    validate_self_signatures(*primary, ctx);
2010
2011
0
    bool has_binding = false;
2012
0
    bool has_expired = false;
2013
0
    for (auto &sigid : sigs_) {
2014
0
        auto &sig = get_sig(sigid);
2015
0
        if (!sig.validity.valid()) {
2016
0
            continue;
2017
0
        }
2018
2019
0
        if (is_binding(sig) && !has_binding) {
2020
            /* check whether subkey is expired */
2021
0
            if (expired_with(sig, ctx.time())) {
2022
0
                has_expired = true;
2023
0
                continue;
2024
0
            }
2025
0
            has_binding = true;
2026
0
        } else if (is_revocation(sig)) {
2027
0
            return;
2028
0
        }
2029
0
    }
2030
0
    validity_.valid = has_binding && primary->valid();
2031
0
    if (!validity_.valid) {
2032
0
        validity_.expired = has_expired;
2033
0
    }
2034
0
}
2035
2036
void
2037
Key::validate(KeyStore &keyring)
2038
117
{
2039
117
    validity_.reset();
2040
117
    if (!is_subkey()) {
2041
117
        validate_primary(keyring);
2042
117
        return;
2043
117
    }
2044
0
    Key *primary = nullptr;
2045
0
    if (has_primary_fp()) {
2046
0
        primary = keyring.get_key(primary_fp());
2047
0
    }
2048
0
    validate_subkey(primary, keyring.secctx);
2049
0
}
2050
2051
void
2052
Key::revalidate(KeyStore &keyring)
2053
117
{
2054
117
    if (is_subkey()) {
2055
0
        Key *primary = keyring.primary_key(*this);
2056
0
        if (primary) {
2057
0
            primary->revalidate(keyring);
2058
0
        } else {
2059
0
            validate_subkey(NULL, keyring.secctx);
2060
0
        }
2061
0
        return;
2062
0
    }
2063
2064
117
    validate_desig_revokes(keyring);
2065
117
    validate(keyring);
2066
117
    if (!refresh_data(keyring.secctx)) {
2067
117
        RNP_LOG("Failed to refresh key data");
2068
117
    }
2069
    /* validate/re-validate all subkeys as well */
2070
117
    for (auto &fp : subkey_fps_) {
2071
0
        Key *subkey = keyring.get_key(fp);
2072
0
        if (subkey) {
2073
0
            subkey->validate_subkey(this, keyring.secctx);
2074
0
            if (!subkey->refresh_data(this, keyring.secctx)) {
2075
0
                RNP_LOG("Failed to refresh subkey data");
2076
0
            }
2077
0
        }
2078
0
    }
2079
117
}
2080
2081
void
2082
Key::mark_valid()
2083
0
{
2084
0
    validity_.mark_valid();
2085
0
    for (auto &sigid : sigs_) {
2086
0
        get_sig(sigid).validity.reset(true);
2087
0
    }
2088
0
}
2089
2090
void
2091
Key::sign_init(RNG &                rng,
2092
               pgp::pkt::Signature &sig,
2093
               pgp_hash_alg_t       hash,
2094
               uint64_t             creation,
2095
               pgp_version_t        version) const
2096
0
{
2097
0
    sig.version = version;
2098
0
    sig.halg = pkt_.material->adjust_hash(hash);
2099
0
    sig.palg = alg();
2100
0
    sig.set_keyfp(fp());
2101
0
    sig.set_creation(creation);
2102
0
    if (version == PGP_V4) {
2103
        // for v6 issuing keys, this MUST NOT be included
2104
0
        sig.set_keyid(keyid());
2105
0
    }
2106
0
#if defined(ENABLE_CRYPTO_REFRESH)
2107
0
    if (version == PGP_V6) {
2108
0
        sig.salt.resize(Hash::size(sig.halg) / 2);
2109
0
        rng.get(sig.salt.data(), sig.salt.size());
2110
0
    }
2111
0
#endif
2112
0
}
2113
2114
void
2115
Key::sign_cert(const pgp_key_pkt_t &   key,
2116
               const pgp_userid_pkt_t &uid,
2117
               pgp::pkt::Signature &   sig,
2118
               SecurityContext &       ctx)
2119
0
{
2120
0
    sig.fill_hashed_data();
2121
0
    auto hash = signature_hash_certification(sig, key, uid);
2122
0
    signature_calculate(sig, *pkt_.material, *hash, ctx);
2123
0
}
2124
2125
void
2126
Key::sign_direct(const pgp_key_pkt_t &key, pgp::pkt::Signature &sig, SecurityContext &ctx)
2127
0
{
2128
0
    sig.fill_hashed_data();
2129
0
    auto hash = signature_hash_direct(sig, key);
2130
0
    signature_calculate(sig, *pkt_.material, *hash, ctx);
2131
0
}
2132
2133
void
2134
Key::sign_binding(const pgp_key_pkt_t &key, pgp::pkt::Signature &sig, SecurityContext &ctx)
2135
0
{
2136
0
    sig.fill_hashed_data();
2137
0
    auto hash = is_primary() ? signature_hash_binding(sig, pkt(), key) :
2138
0
                               signature_hash_binding(sig, key, pkt());
2139
0
    signature_calculate(sig, *pkt_.material, *hash, ctx);
2140
0
}
2141
2142
void
2143
Key::gen_revocation(const Revocation &   rev,
2144
                    pgp_hash_alg_t       hash,
2145
                    const pgp_key_pkt_t &key,
2146
                    pgp::pkt::Signature &sig,
2147
                    SecurityContext &    ctx)
2148
0
{
2149
0
    sign_init(ctx.rng, sig, hash, ctx.time(), key.version);
2150
0
    sig.set_type(is_primary_key_pkt(key.tag) ? PGP_SIG_REV_KEY : PGP_SIG_REV_SUBKEY);
2151
0
    sig.set_revocation_reason(rev.code, rev.reason);
2152
2153
0
    if (is_primary_key_pkt(key.tag)) {
2154
0
        sign_direct(key, sig, ctx);
2155
0
    } else {
2156
0
        sign_binding(key, sig, ctx);
2157
0
    }
2158
0
}
2159
2160
void
2161
Key::sign_subkey_binding(Key &                sub,
2162
                         pgp::pkt::Signature &sig,
2163
                         SecurityContext &    ctx,
2164
                         bool                 subsign)
2165
0
{
2166
0
    if (!is_primary()) {
2167
0
        throw rnp_exception(RNP_ERROR_BAD_PARAMETERS);
2168
0
    }
2169
0
    sign_binding(sub.pkt(), sig, ctx);
2170
    /* add primary key binding subpacket if requested */
2171
0
    if (subsign) {
2172
0
        pgp::pkt::Signature embsig;
2173
0
        sub.sign_init(ctx.rng, embsig, sig.halg, ctx.time(), sub.version());
2174
0
        embsig.set_type(PGP_SIG_PRIMARY);
2175
0
        sub.sign_binding(pkt(), embsig, ctx);
2176
0
        sig.set_embedded_sig(embsig);
2177
0
    }
2178
0
}
2179
2180
#if defined(ENABLE_CRYPTO_REFRESH)
2181
void
2182
Key::add_direct_sig(CertParams &cert, pgp_hash_alg_t hash, SecurityContext &ctx, Key *pubkey)
2183
0
{
2184
    // We only support modifying v4 and newer keys
2185
0
    if (pkt().version < PGP_V4) {
2186
0
        RNP_LOG("adding a direct-key sig to V2/V3 key is not supported");
2187
0
        throw rnp_exception(RNP_ERROR_BAD_STATE);
2188
0
    }
2189
2190
0
    pgp::pkt::Signature sig;
2191
0
    sign_init(ctx.rng, sig, hash, ctx.time(), pkt().version);
2192
0
    sig.set_type(PGP_SIG_DIRECT);
2193
0
    cert.populate(sig);
2194
0
    sign_direct(pkt_, sig, ctx);
2195
2196
0
    add_sig(sig, UserID::None);
2197
0
    refresh_data(ctx);
2198
0
    if (!pubkey) {
2199
0
        return;
2200
0
    }
2201
0
    pubkey->add_sig(sig, UserID::None);
2202
0
    pubkey->refresh_data(ctx);
2203
0
}
2204
#endif
2205
2206
void
2207
Key::add_uid_cert(CertParams &cert, pgp_hash_alg_t hash, SecurityContext &ctx, Key *pubkey)
2208
0
{
2209
0
    if (cert.userid.empty()) {
2210
        /* todo: why not to allow empty uid? */
2211
0
        RNP_LOG("wrong parameters");
2212
0
        throw rnp_exception(RNP_ERROR_BAD_PARAMETERS);
2213
0
    }
2214
    // userids are only valid for primary keys, not subkeys
2215
0
    if (!is_primary()) {
2216
0
        RNP_LOG("cannot add a userid to a subkey");
2217
0
        throw rnp_exception(RNP_ERROR_BAD_STATE);
2218
0
    }
2219
    // see if the key already has this userid
2220
0
    if (has_uid(cert.userid)) {
2221
0
        RNP_LOG("key already has this userid");
2222
0
        throw rnp_exception(RNP_ERROR_BAD_PARAMETERS);
2223
0
    }
2224
    // this isn't really valid for this format
2225
0
    if (format == KeyFormat::G10) {
2226
0
        RNP_LOG("Unsupported key store type");
2227
0
        throw rnp_exception(RNP_ERROR_BAD_STATE);
2228
0
    }
2229
    // We only support modifying v4 and newer keys
2230
0
    if (pkt().version < PGP_V4) {
2231
0
        RNP_LOG("adding a userid to V2/V3 key is not supported");
2232
0
        throw rnp_exception(RNP_ERROR_BAD_STATE);
2233
0
    }
2234
    /* TODO: if key has at least one uid then has_primary_uid() will be always true! */
2235
0
    if (has_primary_uid() && cert.primary) {
2236
0
        RNP_LOG("changing the primary userid is not supported");
2237
0
        throw rnp_exception(RNP_ERROR_BAD_STATE);
2238
0
    }
2239
2240
    /* Fill the transferable userid */
2241
0
    pgp_userid_pkt_t    uid;
2242
0
    pgp::pkt::Signature sig;
2243
0
    sign_init(ctx.rng, sig, hash, ctx.time(), pkt().version);
2244
0
    cert.populate(uid, sig);
2245
0
    try {
2246
0
        sign_cert(pkt_, uid, sig, ctx);
2247
0
    } catch (const std::exception &e) {
2248
0
        RNP_LOG("Failed to certify: %s", e.what());
2249
0
        throw;
2250
0
    }
2251
    /* add uid and signature to the key and pubkey, if non-NULL */
2252
0
    uids_.emplace_back(uid);
2253
0
    add_sig(sig, uid_count() - 1);
2254
0
    refresh_data(ctx);
2255
0
    if (!pubkey) {
2256
0
        return;
2257
0
    }
2258
0
    pubkey->uids_.emplace_back(uid);
2259
0
    pubkey->add_sig(sig, pubkey->uid_count() - 1);
2260
0
    pubkey->refresh_data(ctx);
2261
0
}
2262
2263
void
2264
Key::add_sub_binding(Key &                subsec,
2265
                     Key &                subpub,
2266
                     const BindingParams &binding,
2267
                     pgp_hash_alg_t       hash,
2268
                     SecurityContext &    ctx)
2269
0
{
2270
0
    if (!is_primary()) {
2271
0
        RNP_LOG("must be called on primary key");
2272
0
        throw rnp_exception(RNP_ERROR_BAD_STATE);
2273
0
    }
2274
2275
    /* populate signature */
2276
0
    pgp::pkt::Signature sig;
2277
0
    sign_init(ctx.rng, sig, hash, ctx.time(), version());
2278
0
    sig.set_type(PGP_SIG_SUBKEY);
2279
0
    if (binding.key_expiration) {
2280
0
        sig.set_key_expiration(binding.key_expiration);
2281
0
    }
2282
0
    if (binding.flags) {
2283
0
        sig.set_key_flags(binding.flags);
2284
0
    }
2285
    /* calculate binding */
2286
0
    pgp_key_flags_t realkf = (pgp_key_flags_t) binding.flags;
2287
0
    if (!realkf) {
2288
0
        realkf = pgp_pk_alg_capabilities(subsec.alg());
2289
0
    }
2290
0
    sign_subkey_binding(subsec, sig, ctx, realkf & PGP_KF_SIGN);
2291
    /* add to the secret and public key */
2292
0
    subsec.add_sig(sig);
2293
0
    subpub.add_sig(sig);
2294
0
}
2295
2296
void
2297
Key::refresh_revocations()
2298
0
{
2299
0
    clear_revokes();
2300
0
    for (auto &sigid : sigs_) {
2301
0
        auto &sig = get_sig(sigid);
2302
0
        if (!sig.validity.valid()) {
2303
0
            continue;
2304
0
        }
2305
0
        if (is_revocation(sig)) {
2306
0
            if (revoked_) {
2307
0
                continue;
2308
0
            }
2309
0
            revoked_ = true;
2310
0
            revocation_ = Revocation(sig);
2311
0
            continue;
2312
0
        }
2313
0
        if (is_uid_revocation(sig)) {
2314
0
            if (sig.uid >= uid_count()) {
2315
0
                RNP_LOG("Invalid uid index");
2316
0
                continue;
2317
0
            }
2318
0
            auto &uid = get_uid(sig.uid);
2319
0
            if (uid.revoked) {
2320
0
                continue;
2321
0
            }
2322
0
            uid.revoked = true;
2323
0
            uid.revocation = Revocation(sig);
2324
0
        }
2325
0
    }
2326
0
}
2327
2328
bool
2329
Key::refresh_data(const SecurityContext &ctx)
2330
117
{
2331
117
    if (!is_primary()) {
2332
117
        RNP_LOG("key must be primary");
2333
117
        return false;
2334
117
    }
2335
    /* validate self-signatures if not done yet */
2336
0
    validate_self_signatures(ctx);
2337
    /* key expiration */
2338
0
    expiration_ = 0;
2339
    /* if we have direct-key signature, then it has higher priority */
2340
0
    auto dirsig = latest_selfsig(UserID::None);
2341
0
    if (dirsig) {
2342
0
        expiration_ = dirsig->sig.key_expiration();
2343
0
    }
2344
    /* if we have primary uid and it is more restrictive, then use it as well */
2345
0
    auto prisig = latest_selfsig(UserID::Primary);
2346
0
    if (prisig && prisig->sig.key_expiration() &&
2347
0
        (!expiration_ || (prisig->sig.key_expiration() < expiration_))) {
2348
0
        expiration_ = prisig->sig.key_expiration();
2349
0
    }
2350
    /* if we don't have direct-key sig and primary uid, use the latest self-cert */
2351
0
    auto latest = latest_selfsig(UserID::Any);
2352
0
    if (!dirsig && !prisig && latest) {
2353
0
        expiration_ = latest->sig.key_expiration();
2354
0
    }
2355
    /* key flags: check in direct-key sig first, then primary uid, and then latest */
2356
0
    if (dirsig && dirsig->sig.has_subpkt(PGP_SIG_SUBPKT_KEY_FLAGS)) {
2357
0
        flags_ = dirsig->sig.key_flags();
2358
0
    } else if (prisig && prisig->sig.has_subpkt(PGP_SIG_SUBPKT_KEY_FLAGS)) {
2359
0
        flags_ = prisig->sig.key_flags();
2360
0
    } else if (latest && latest->sig.has_subpkt(PGP_SIG_SUBPKT_KEY_FLAGS)) {
2361
0
        flags_ = latest->sig.key_flags();
2362
0
    } else {
2363
0
        flags_ = pgp_pk_alg_capabilities(alg());
2364
0
    }
2365
    /* designated revokers */
2366
0
    revokers_.clear();
2367
0
    for (auto &sigid : sigs_) {
2368
0
        auto &sig = get_sig(sigid);
2369
        /* pick designated revokers only from direct-key signatures */
2370
0
        if (!sig.validity.valid() || !is_direct_self(sig)) {
2371
0
            continue;
2372
0
        }
2373
0
        if (!sig.sig.has_revoker()) {
2374
0
            continue;
2375
0
        }
2376
0
        add_revoker(sig.sig.revoker());
2377
0
    }
2378
    /* revocation(s) */
2379
0
    refresh_revocations();
2380
    /* valid till */
2381
0
    valid_till_ = valid_till_common(expired());
2382
    /* userid validities */
2383
0
    for (auto &uid : uids_) {
2384
0
        uid.valid = false;
2385
0
    }
2386
0
    for (auto &sigid : sigs_) {
2387
0
        auto &sig = get_sig(sigid);
2388
        /* consider userid as valid if it has at least one non-expired self-sig */
2389
0
        if (!sig.validity.valid() || !sig.is_cert() || !is_signer(sig) ||
2390
0
            sig.expired(ctx.time())) {
2391
0
            continue;
2392
0
        }
2393
0
        if (sig.uid >= uid_count()) {
2394
0
            continue;
2395
0
        }
2396
0
        get_uid(sig.uid).valid = true;
2397
0
    }
2398
    /* check whether uid is revoked */
2399
0
    for (auto &uid : uids_) {
2400
0
        if (uid.revoked) {
2401
0
            uid.valid = false;
2402
0
        }
2403
0
    }
2404
    /* primary userid: use latest one which is not overridden by later non-primary selfsig */
2405
0
    uid0_set_ = false;
2406
0
    if (prisig && get_uid(prisig->uid).valid) {
2407
0
        uid0_ = prisig->uid;
2408
0
        uid0_set_ = true;
2409
0
    }
2410
0
    return true;
2411
117
}
2412
2413
bool
2414
Key::refresh_data(Key *primary, const SecurityContext &ctx)
2415
0
{
2416
    /* validate self-signatures if not done yet */
2417
0
    if (primary) {
2418
0
        validate_self_signatures(*primary, ctx);
2419
0
    }
2420
0
    auto sig = latest_binding(primary);
2421
    /* subkey expiration */
2422
0
    expiration_ = sig ? sig->sig.key_expiration() : 0;
2423
    /* subkey flags */
2424
0
    if (sig && sig->sig.has_subpkt(PGP_SIG_SUBPKT_KEY_FLAGS)) {
2425
0
        flags_ = sig->sig.key_flags();
2426
0
    } else {
2427
0
        flags_ = pgp_pk_alg_capabilities(alg());
2428
0
    }
2429
    /* revocation */
2430
0
    clear_revokes();
2431
0
    for (auto &sigid : sigs_) {
2432
0
        auto &rev = get_sig(sigid);
2433
0
        if (!rev.validity.valid() || !is_revocation(rev)) {
2434
0
            continue;
2435
0
        }
2436
0
        revoked_ = true;
2437
0
        try {
2438
0
            revocation_ = Revocation(rev);
2439
0
        } catch (const std::exception &e) {
2440
0
            RNP_LOG("%s", e.what());
2441
0
            return false;
2442
0
        }
2443
0
        break;
2444
0
    }
2445
    /* valid till */
2446
0
    if (primary) {
2447
0
        valid_till_ =
2448
0
          std::min(primary->valid_till(), valid_till_common(expired() || primary->expired()));
2449
0
    } else {
2450
0
        valid_till_ = valid_till_common(expired());
2451
0
    }
2452
0
    return true;
2453
0
}
2454
2455
void
2456
Key::merge_validity(const pgp_validity_t &src)
2457
0
{
2458
0
    validity_.valid = validity_.valid && src.valid;
2459
    /* We may safely leave validated status only if both merged keys are valid && validated.
2460
     * Otherwise we'll need to revalidate. For instance, one validated but invalid key may add
2461
     * revocation signature, or valid key may add certification to the invalid one. */
2462
0
    validity_.validated = validity_.valid && validity_.validated && src.validated;
2463
    /* if expired is true at least in one case then valid and validated are false */
2464
0
    validity_.expired = false;
2465
0
}
2466
2467
bool
2468
Key::merge(const Key &src)
2469
0
{
2470
0
    assert(!is_subkey());
2471
0
    assert(!src.is_subkey());
2472
2473
    /* if src is secret key then merged key will become secret as well. */
2474
0
    if (src.is_secret() && !is_secret()) {
2475
0
        pkt_ = src.pkt();
2476
0
        rawpkt_ = src.rawpkt();
2477
        /* no subkey processing here - they are separated from the main key */
2478
0
    }
2479
2480
    /* merge direct-key signatures */
2481
0
    for (auto &sigid : src.keysigs_) {
2482
0
        if (has_sig(sigid)) {
2483
0
            continue;
2484
0
        }
2485
0
        add_sig(src.get_sig(sigid).sig);
2486
0
    }
2487
2488
    /* merge user ids and their signatures */
2489
0
    for (auto &srcuid : src.uids_) {
2490
        /* check whether we have this uid and add if needed */
2491
0
        auto uididx = uid_idx(srcuid.pkt);
2492
0
        if (uididx == UserID::None) {
2493
0
            uididx = uid_count();
2494
0
            uids_.emplace_back(srcuid.pkt);
2495
0
        }
2496
        /* add uid signatures */
2497
0
        for (size_t idx = 0; idx < srcuid.sig_count(); idx++) {
2498
0
            auto &sigid = srcuid.get_sig(idx);
2499
0
            if (has_sig(sigid)) {
2500
0
                continue;
2501
0
            }
2502
0
            add_sig(src.get_sig(sigid).sig, uididx);
2503
0
        }
2504
0
    }
2505
2506
    /* Update subkey fingerprints */
2507
0
    for (auto &fp : src.subkey_fps()) {
2508
0
        add_subkey_fp(fp);
2509
0
    }
2510
2511
    /* check whether key was unlocked and assign secret key data */
2512
0
    if (src.is_secret() && !src.is_locked() && (!is_secret() || is_locked())) {
2513
0
        pkt().material = src.pkt().material->clone();
2514
0
    }
2515
    /* copy validity status */
2516
0
    merge_validity(src.validity_);
2517
0
    return true;
2518
0
}
2519
2520
bool
2521
Key::merge(const Key &src, Key *primary)
2522
0
{
2523
0
    assert(is_subkey());
2524
0
    assert(src.is_subkey());
2525
2526
    /* if src is secret key then merged key will become secret as well. */
2527
0
    if (src.is_secret() && !is_secret()) {
2528
0
        pkt_ = src.pkt();
2529
0
        rawpkt_ = src.rawpkt();
2530
0
    }
2531
2532
    /* add subkey binding signatures */
2533
0
    for (auto &sigid : src.keysigs_) {
2534
0
        if (has_sig(sigid)) {
2535
0
            continue;
2536
0
        }
2537
0
        add_sig(src.get_sig(sigid).sig);
2538
0
    }
2539
2540
    /* check whether key was unlocked and assign secret key data */
2541
0
    if (src.is_secret() && !src.is_locked() && (!is_secret() || is_locked())) {
2542
0
        pkt().material = src.pkt().material->clone();
2543
0
    }
2544
    /* copy validity status */
2545
0
    merge_validity(src.validity_);
2546
    /* link subkey fps */
2547
0
    if (primary) {
2548
0
        primary->link_subkey_fp(*this);
2549
0
    }
2550
0
    return true;
2551
0
}
2552
} // namespace rnp
2553
2554
pgp_key_flags_t
2555
pgp_pk_alg_capabilities(pgp_pubkey_alg_t alg)
2556
0
{
2557
0
    switch (alg) {
2558
0
    case PGP_PKA_RSA:
2559
0
        return pgp_key_flags_t(PGP_KF_SIGN | PGP_KF_CERTIFY | PGP_KF_AUTH | PGP_KF_ENCRYPT);
2560
2561
0
    case PGP_PKA_RSA_SIGN_ONLY:
2562
        // deprecated, but still usable
2563
0
        return PGP_KF_SIGN;
2564
2565
0
    case PGP_PKA_RSA_ENCRYPT_ONLY:
2566
        // deprecated, but still usable
2567
0
        return PGP_KF_ENCRYPT;
2568
2569
0
    case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: /* deprecated */
2570
        // These are no longer permitted per the RFC
2571
0
        return PGP_KF_NONE;
2572
2573
0
    case PGP_PKA_DSA:
2574
0
    case PGP_PKA_ECDSA:
2575
0
    case PGP_PKA_EDDSA:
2576
0
        return pgp_key_flags_t(PGP_KF_SIGN | PGP_KF_CERTIFY | PGP_KF_AUTH);
2577
2578
0
#if defined(ENABLE_CRYPTO_REFRESH)
2579
0
    case PGP_PKA_ED25519:
2580
0
        return pgp_key_flags_t(PGP_KF_SIGN | PGP_KF_CERTIFY | PGP_KF_AUTH);
2581
0
    case PGP_PKA_X25519:
2582
0
        return PGP_KF_ENCRYPT;
2583
0
#endif
2584
2585
0
    case PGP_PKA_SM2:
2586
0
        return pgp_key_flags_t(PGP_KF_SIGN | PGP_KF_CERTIFY | PGP_KF_AUTH | PGP_KF_ENCRYPT);
2587
2588
0
    case PGP_PKA_ECDH:
2589
0
    case PGP_PKA_ELGAMAL:
2590
0
        return PGP_KF_ENCRYPT;
2591
2592
0
#if defined(ENABLE_PQC)
2593
0
    case PGP_PKA_KYBER768_X25519:
2594
0
        FALLTHROUGH_STATEMENT;
2595
    // TODO: Add case for PGP_PKA_KYBER1024_X448 with FALLTHROUGH_STATEMENT;
2596
0
    case PGP_PKA_KYBER768_P256:
2597
0
        FALLTHROUGH_STATEMENT;
2598
0
    case PGP_PKA_KYBER1024_P384:
2599
0
        FALLTHROUGH_STATEMENT;
2600
0
    case PGP_PKA_KYBER768_BP256:
2601
0
        FALLTHROUGH_STATEMENT;
2602
0
    case PGP_PKA_KYBER1024_BP384:
2603
0
        return PGP_KF_ENCRYPT;
2604
2605
0
    case PGP_PKA_DILITHIUM3_ED25519:
2606
0
        FALLTHROUGH_STATEMENT;
2607
    // TODO: Add case PGP_PKA_DILITHIUM5_ED448: FALLTHROUGH_STATEMENT;
2608
0
    case PGP_PKA_DILITHIUM3_P256:
2609
0
        FALLTHROUGH_STATEMENT;
2610
0
    case PGP_PKA_DILITHIUM5_P384:
2611
0
        FALLTHROUGH_STATEMENT;
2612
0
    case PGP_PKA_DILITHIUM3_BP256:
2613
0
        FALLTHROUGH_STATEMENT;
2614
0
    case PGP_PKA_DILITHIUM5_BP384:
2615
0
        FALLTHROUGH_STATEMENT;
2616
0
    case PGP_PKA_SPHINCSPLUS_SHA2:
2617
0
        FALLTHROUGH_STATEMENT;
2618
0
    case PGP_PKA_SPHINCSPLUS_SHAKE:
2619
0
        return pgp_key_flags_t(PGP_KF_SIGN | PGP_KF_CERTIFY | PGP_KF_AUTH);
2620
0
#endif
2621
2622
0
    default:
2623
0
        RNP_LOG("unknown pk alg: %d\n", alg);
2624
0
        return PGP_KF_NONE;
2625
0
    }
2626
0
}