Coverage Report

Created: 2026-01-10 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rnp/src/librepgp/stream-sig.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2018-2022, [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
#ifndef STREAM_SIG_H_
28
#define STREAM_SIG_H_
29
30
#include <stdint.h>
31
#include <stdbool.h>
32
#include <sys/types.h>
33
#include "rnp.h"
34
#include "stream-common.h"
35
#include "stream-packet.h"
36
#include "sig_subpacket.hpp"
37
#include "sig_material.hpp"
38
39
namespace pgp {
40
namespace pkt {
41
42
class Signature {
43
  private:
44
    pgp_sig_type_t       type_;
45
    std::vector<uint8_t> preferred(sigsub::Type type) const;
46
    void                 set_preferred(const std::vector<uint8_t> &data, sigsub::Type type);
47
    rnp_result_t         parse_v2v3(pgp_packet_body_t &pkt);
48
    rnp_result_t         parse_v4up(pgp_packet_body_t &pkt);
49
    bool                 get_subpkt_len(pgp_packet_body_t &pkt, size_t &len);
50
    bool                 parse_subpackets(uint8_t *buf, size_t len, bool hashed);
51
    static bool          version_supported(pgp_version_t version);
52
53
    const sigsub::RevocationKey *revoker_subpkt() const noexcept;
54
55
  public:
56
    pgp_version_t version;
57
    /* common v3 and v4 fields */
58
    pgp_pubkey_alg_t       palg;
59
    pgp_hash_alg_t         halg;
60
    std::array<uint8_t, 2> lbits{};
61
    std::vector<uint8_t>   hashed_data;
62
    std::vector<uint8_t>   material_buf; /* raw signature material */
63
64
    /* v3 - only fields */
65
    uint32_t creation_time;
66
    KeyID    signer{};
67
68
    /* common v4, v5 and v6 fields */
69
    sigsub::List subpkts;
70
71
#if defined(ENABLE_CRYPTO_REFRESH)
72
    /* v6 - only fields */
73
    std::vector<uint8_t> salt;
74
#endif
75
76
    Signature()
77
3.17M
        : type_(PGP_SIG_BINARY), version(PGP_VUNKNOWN), palg(PGP_PKA_NOTHING),
78
3.17M
          halg(PGP_HASH_UNKNOWN), creation_time(0){};
79
    bool operator==(const Signature &src) const;
80
    bool operator!=(const Signature &src) const;
81
82
    /* @brief Get signature's type */
83
    pgp_sig_type_t
84
    type() const
85
3.43M
    {
86
3.43M
        return type_;
87
3.43M
    };
88
    void
89
    set_type(pgp_sig_type_t atype)
90
0
    {
91
0
        type_ = atype;
92
0
    };
93
94
    bool
95
    is_document() const
96
257k
    {
97
257k
        return (type_ == PGP_SIG_BINARY) || (type_ == PGP_SIG_TEXT);
98
257k
    };
99
100
    /** @brief Calculate the unique signature identifier by hashing signature's fields. */
101
    SigID get_id() const;
102
103
    size_t find_subpkt(uint8_t type, bool hashed = true, size_t skip = 0) const;
104
    size_t find_subpkt(sigsub::Type type, bool hashed = true, size_t skip = 0) const;
105
    /**
106
     * @brief Get v4 and up signature's subpacket of the specified type and hashedness.
107
     * @param stype subpacket type.
108
     * @param hashed whether subpacket must be in hashed area on in any area.
109
     * @return pointer to the subpacket, or nullptr if subpacket was not found.
110
     */
111
    sigsub::Raw *      get_subpkt(uint8_t stype, bool hashed = true);
112
    const sigsub::Raw *get_subpkt(uint8_t stype, bool hashed = true) const;
113
    sigsub::Raw *      get_subpkt(sigsub::Type type, bool hashed = true);
114
    const sigsub::Raw *get_subpkt(sigsub::Type type, bool hashed = true) const;
115
116
    /* @brief Check whether v4 signature has subpacket of the specified type/hashedness */
117
    bool has_subpkt(uint8_t stype, bool hashed = true) const;
118
    /* @brief Check whether signature has signing key id (via v3 field, or v4 key id/key fp
119
     * subpacket) */
120
    bool has_keyid() const;
121
    /**
122
     * @brief Get signer's key id if available. Availability may be checked via has_keyid().
123
     * @return signer's key id if available, or empty (zero-filled) keyid otherwise.
124
     */
125
    KeyID keyid() const noexcept;
126
    /** @brief Set the signer's key id for the signature being populated. Version should be set
127
     *         prior of setting key id. */
128
    void set_keyid(const KeyID &id);
129
    /**
130
     * @brief Check whether signature has valid issuer fingerprint subpacket.
131
     * @return true if there is one, and it can be safely returned via keyfp() method or false
132
     *         otherwise.
133
     */
134
    bool has_keyfp() const;
135
    /**
136
     * @brief Get signing key's fingerprint if it is available. Availability may be checked via
137
     *        has_keyfp() method.
138
     * @return fingerprint (or empty zero-size fp in case it is unavailable)
139
     */
140
    Fingerprint keyfp() const noexcept;
141
142
    /** @brief Set signing key's fingerprint. Works only for signatures with version 4 and up,
143
     *         so version should be set prior to fingerprint. */
144
    void set_keyfp(const Fingerprint &fp);
145
146
    /**
147
     * @brief Get signature's creation time
148
     * @return time in seconds since the Jan 1, 1970 UTC. 0 is the default value and returned
149
     *         even if creation time is not available
150
     */
151
    uint32_t creation() const;
152
153
    /**
154
     * @brief Set signature's creation time
155
     * @param ctime creation time in seconds since the Jan 1, 1970 UTC.
156
     */
157
    void set_creation(uint32_t ctime);
158
159
    /**
160
     * @brief Get the signature's expiration time
161
     * @return expiration time in seconds since the creation time. 0 if signature never
162
     * expires.
163
     */
164
    uint32_t expiration() const;
165
166
    /**
167
     * @brief Set the signature's expiration time
168
     * @param etime expiration time
169
     */
170
    void set_expiration(uint32_t etime);
171
172
    /**
173
     * @brief Get the key expiration time
174
     * @return expiration time in seconds since the creation time. 0 if key never expires.
175
     */
176
    uint32_t key_expiration() const;
177
178
    /**
179
     * @brief Set the key expiration time
180
     * @param etime expiration time
181
     */
182
    void set_key_expiration(uint32_t etime);
183
184
    /**
185
     * @brief Get the key flags
186
     * @return byte of key flags. If there is no corresponding subpackets then 0 is returned.
187
     */
188
    uint8_t key_flags() const;
189
190
    /**
191
     * @brief Set the key flags
192
     * @param flags byte of key flags
193
     */
194
    void set_key_flags(uint8_t flags);
195
196
    /**
197
     * @brief Get the primary user id flag
198
     * @return true if user id is marked as primary or false otherwise
199
     */
200
    bool primary_uid() const;
201
202
    /**
203
     * @brief Set the primary user id flag
204
     * @param primary true if user id should be marked as primary
205
     */
206
    void set_primary_uid(bool primary);
207
208
    /** @brief Get preferred symmetric algorithms if any. If there are no ones then empty
209
     *         vector is returned. */
210
    std::vector<uint8_t> preferred_symm_algs() const;
211
212
    /** @brief Set the preferred symmetric algorithms. If empty vector is passed then
213
     *         corresponding subpacket is deleted. */
214
    void set_preferred_symm_algs(const std::vector<uint8_t> &algs);
215
216
    /** @brief Get preferred hash algorithms if any. If there are no ones then empty vector is
217
     *         returned.*/
218
    std::vector<uint8_t> preferred_hash_algs() const;
219
220
    /** @brief Set the preferred hash algorithms. If empty vector is passed then corresponding
221
     *         subpacket is deleted. */
222
    void set_preferred_hash_algs(const std::vector<uint8_t> &algs);
223
224
    /** @brief Get preferred compression algorithms if any. If there are no ones then empty
225
     *         vector is returned.*/
226
    std::vector<uint8_t> preferred_z_algs() const;
227
228
    /** @brief Set the preferred compression algorithms. If empty vector is passed then
229
     *         corresponding subpacket is deleted. */
230
    void set_preferred_z_algs(const std::vector<uint8_t> &algs);
231
232
#if defined(ENABLE_CRYPTO_REFRESH)
233
    /** @brief Get preferred AEAD algorithms if any. If there are no ones then empty
234
     *         vector is returned.*/
235
    std::vector<uint8_t> preferred_aead_algs() const;
236
237
    /** @brief Set the preferred AEAD algorithms. If empty vector is passed then
238
     *         corresponding subpacket is deleted. */
239
    void set_preferred_aead_algs(const std::vector<uint8_t> &algs);
240
#endif
241
242
    /** @brief Get key server preferences flags. If subpacket is not available then 0 is
243
     *         returned. */
244
    uint8_t key_server_prefs() const;
245
246
    /** @brief Set key server preferences flags. */
247
    void set_key_server_prefs(uint8_t prefs);
248
249
    /** @brief Get preferred key server URI, if available. Otherwise empty string is returned.
250
     */
251
    std::string key_server() const;
252
253
    /** @brief Set preferred key server URI. If it is empty string then subpacket is deleted if
254
     *         it is available. */
255
    void set_key_server(const std::string &uri);
256
257
    /** @brief Get trust level, if available. Otherwise will return 0. See RFC 4880, 5.2.3.14.
258
     *         for the detailed information on trust level and amount.
259
     */
260
    uint8_t trust_level() const;
261
262
    /** @brief Get trust amount, if available. Otherwise will return 0. See RFC 4880, 5.2.3.14.
263
     *         for the detailed information on trust level and amount.
264
     */
265
    uint8_t trust_amount() const;
266
267
    /** @brief Set the trust level and amount. See RFC 4880, 5.2.3.14.
268
     *         for the detailed information on trust level and amount.
269
     */
270
    void set_trust(uint8_t level, uint8_t amount);
271
272
    /** @brief check whether signature is revocable. True by default.
273
     */
274
    bool revocable() const;
275
276
    /** @brief Set the signature's revocability status.
277
     */
278
    void set_revocable(bool status);
279
280
    /** @brief Get the key/subkey revocation reason in humand-readable form. If there is no
281
     *         revocation reason subpacket, then empty string will be returned.
282
     */
283
    std::string revocation_reason() const;
284
285
    /** @brief Get the key/subkey revocation code. If there is no revocation reason subpacket,
286
     *         then PGP_REVOCATION_NO_REASON will be rerturned. See the RFC 4880, 5.2.3.24 for
287
     *         the detailed explanation.
288
     */
289
    pgp_revocation_type_t revocation_code() const;
290
291
    /**
292
     * @brief Check whether signature has revocation reason and code subpacket.
293
     */
294
    bool has_revocation_reason() const;
295
296
    /** @brief Set the revocation reason and code for key/subkey revocation signature. See the
297
     *         RFC 4880, 5.2.3.24 for the detailed explanation.
298
     */
299
    void set_revocation_reason(pgp_revocation_type_t code, const std::string &reason);
300
301
    uint32_t key_get_features() const;
302
303
    /**
304
     * @brief Check whether signer's key supports certain feature(s). Makes sense only for
305
     *        self-signature, for more details see the RFC 4880bis, 5.2.3.25. If there is
306
     *        no corresponding subpacket then false will be returned.
307
     * @param flags one or more flags, combined via bitwise OR operation.
308
     * @return true if key is claimed to support all of the features listed in flags, or false
309
     *         otherwise
310
     */
311
    bool key_has_features(uint32_t flags) const;
312
313
    /**
314
     * @brief Set the features supported by the signer's key, makes sense only for
315
     *        self-signature. For more details see the RFC 4880bis, 5.2.3.25.
316
     * @param flags one or more flags, combined via bitwise OR operation.
317
     */
318
    void set_key_features(uint32_t flags);
319
320
    /** @brief Get signer's user id, if available. Otherwise empty string is returned. See the
321
     *         RFC 4880bis, 5.2.3.23 for details.
322
     */
323
    std::string signer_uid() const;
324
325
    /**
326
     * @brief Set the signer's uid, responsible for the signature creation. See the RFC
327
     *        4880bis, 5.2.3.23 for details.
328
     */
329
    void set_signer_uid(const std::string &uid);
330
331
    /**
332
     * @brief Add notation.
333
     */
334
    void add_notation(const std::string &         name,
335
                      const std::vector<uint8_t> &value,
336
                      bool                        human = true,
337
                      bool                        critical = false);
338
339
    /**
340
     * @brief Add human-readable notation.
341
     */
342
    void add_notation(const std::string &name,
343
                      const std::string &value,
344
                      bool               critical = false);
345
346
    /**
347
     * @brief Set the embedded signature.
348
     * @param esig populated and calculated embedded signature.
349
     */
350
    void set_embedded_sig(const Signature &esig);
351
352
    /**
353
     * @brief Check whether signature includes revocation key subpacket.
354
     */
355
    bool has_revoker() const noexcept;
356
357
    /**
358
     * @brief Get the revocation key fingerprint, if it is available. Otherwise empty
359
     * fingerprint will be returned.
360
     */
361
    Fingerprint revoker() const noexcept;
362
363
    /**
364
     * @brief Set the revocation key.
365
     *
366
     * @param revoker revoker's key packet.
367
     */
368
    void set_revoker(const rnp::Key &revoker, bool sensitive = false);
369
370
    /**
371
     * @brief Add subpacket to v4 and up signature
372
     * @param sub pointer to the subpacket object.
373
     * @param replace replace already existing subpacket of the specified type if any
374
     * @return reference to the subpacket structure or throws an exception
375
     */
376
    void add_subpkt(std::unique_ptr<sigsub::Raw> &&sub, bool replace = true);
377
378
    /**
379
     * @brief Remove signature's subpacket
380
     * @param idx Index of the subpacket in list.
381
     */
382
    void remove_subpkt(size_t idx);
383
384
    /**
385
     * @brief Check whether signature packet matches one-pass signature packet.
386
     * @param onepass reference to the read one-pass signature packet
387
     * @return true if sig corresponds to onepass or false otherwise
388
     */
389
    bool matches_onepass(const pgp_one_pass_sig_t &onepass) const;
390
391
    /**
392
     * @brief Parse signature body (i.e. without checking the packet header).
393
     *
394
     * @param pkt packet body with data.
395
     * @return RNP_SUCCESS or error code if failed. May also throw an exception.
396
     */
397
    rnp_result_t parse(pgp_packet_body_t &pkt);
398
399
    /**
400
     * @brief Parse signature packet from source.
401
     *
402
     * @param src source with data.
403
     * @return RNP_SUCCESS or error code if failed. May also throw an exception.
404
     */
405
    rnp_result_t parse(pgp_source_t &src);
406
407
    /**
408
     * @brief Parse signature material, stored in the signature in raw.
409
     *
410
     * @param material on success parsed material will be stored here.
411
     * @return true on success or false otherwise. May also throw an exception.
412
     */
413
    std::unique_ptr<SigMaterial> parse_material() const;
414
415
    /**
416
     * @brief Write signature to the destination. May throw an exception.
417
     */
418
    void                 write(pgp_dest_t &dst, bool hdr = true) const;
419
    std::vector<uint8_t> write(bool hdr = true) const;
420
421
    /**
422
     * @brief Write the signature material's raw representation. May throw an exception.
423
     *
424
     * @param material populated signature material.
425
     */
426
    void write_material(const SigMaterial &material);
427
428
    /**
429
     * @brief Fill signature's hashed data. This includes all the fields from signature which
430
     * are hashed after the previous document or key fields.
431
     */
432
    void fill_hashed_data();
433
};
434
435
using Signatures = std::vector<Signature>;
436
437
} // namespace pkt
438
} // namespace pgp
439
440
/**
441
 * @brief Hash key packet. Used in signatures and v4 fingerprint calculation.
442
 *        Throws exception on error.
443
 * @param key key packet, must be populated
444
 * @param hash initialized hash context
445
 * @param pgpver for fingerprint calculation, the key version is required,
446
 * otherwise the signature version is required
447
 */
448
void signature_hash_key(const pgp_key_pkt_t &key, rnp::Hash &hash, pgp_version_t pgpver);
449
450
void signature_hash_userid(const pgp_userid_pkt_t &uid, rnp::Hash &hash, pgp_version_t sigver);
451
452
std::unique_ptr<rnp::Hash> signature_hash_certification(const pgp::pkt::Signature &sig,
453
                                                        const pgp_key_pkt_t &      key,
454
                                                        const pgp_userid_pkt_t &   userid);
455
456
std::unique_ptr<rnp::Hash> signature_hash_binding(const pgp::pkt::Signature &sig,
457
                                                  const pgp_key_pkt_t &      key,
458
                                                  const pgp_key_pkt_t &      subkey);
459
460
std::unique_ptr<rnp::Hash> signature_hash_direct(const pgp::pkt::Signature &sig,
461
                                                 const pgp_key_pkt_t &      key);
462
463
/**
464
 * @brief Parse stream with signatures to the signatures list.
465
 *        Can handle binary or armored stream with signatures, including stream with multiple
466
 * armored signatures.
467
 *
468
 * @param src signatures stream, cannot be NULL.
469
 * @param sigs on success parsed signature structures will be put here.
470
 * @return RNP_SUCCESS or error code otherwise.
471
 */
472
rnp_result_t process_pgp_signatures(pgp_source_t &src, pgp::pkt::Signatures &sigs);
473
474
#endif