/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 |