summaryrefslogtreecommitdiffstats
path: root/comm/third_party/rnp/src/librepgp/stream-packet.h
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/rnp/src/librepgp/stream-packet.h')
-rw-r--r--comm/third_party/rnp/src/librepgp/stream-packet.h323
1 files changed, 323 insertions, 0 deletions
diff --git a/comm/third_party/rnp/src/librepgp/stream-packet.h b/comm/third_party/rnp/src/librepgp/stream-packet.h
new file mode 100644
index 0000000000..f88c96f22d
--- /dev/null
+++ b/comm/third_party/rnp/src/librepgp/stream-packet.h
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2017-2020 [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef STREAM_PACKET_H_
+#define STREAM_PACKET_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include "types.h"
+#include "stream-common.h"
+
+/* maximum size of the 'small' packet */
+#define PGP_MAX_PKT_SIZE 0x100000
+
+/* maximum size of indeterminate-size packet allowed with old length format */
+#define PGP_MAX_OLD_LEN_INDETERMINATE_PKT_SIZE 0x40000000
+
+typedef struct pgp_packet_hdr_t {
+ pgp_pkt_type_t tag; /* packet tag */
+ uint8_t hdr[PGP_MAX_HEADER_SIZE]; /* PGP packet header, needed for AEAD */
+ size_t hdr_len; /* length of the header */
+ size_t pkt_len; /* packet body length if non-partial and non-indeterminate */
+ bool partial; /* partial length packet */
+ bool indeterminate; /* indeterminate length packet */
+} pgp_packet_hdr_t;
+
+/* structure for convenient writing or parsing of non-stream packets */
+typedef struct pgp_packet_body_t {
+ private:
+ pgp_pkt_type_t tag_; /* packet tag */
+ std::vector<uint8_t> data_; /* packet bytes */
+ /* fields below are filled only for parsed packet */
+ uint8_t hdr_[PGP_MAX_HEADER_SIZE]{}; /* packet header bytes */
+ size_t hdr_len_{}; /* number of bytes in hdr */
+ size_t pos_{}; /* current read position in packet data */
+ bool secure_{}; /* contents of the packet are secure so must be wiped in the destructor */
+ public:
+ /** @brief initialize writing of packet body
+ * @param tag tag of the packet
+ **/
+ pgp_packet_body_t(pgp_pkt_type_t tag);
+ /** @brief init packet body (without headers) with memory. Used for easier data parsing.
+ * @param data buffer with packet body part
+ * @param len number of available bytes in mem
+ */
+ pgp_packet_body_t(const uint8_t *data, size_t len);
+
+ pgp_packet_body_t(const pgp_packet_body_t &src) = delete;
+ pgp_packet_body_t(pgp_packet_body_t &&src) = delete;
+ pgp_packet_body_t &operator=(const pgp_packet_body_t &) = delete;
+ pgp_packet_body_t &operator=(pgp_packet_body_t &&) = delete;
+ ~pgp_packet_body_t();
+
+ /** @brief pointer to the data, kept in the packet */
+ uint8_t *data() noexcept;
+ /** @brief number of bytes, kept in the packet (without the header) */
+ size_t size() const noexcept;
+ /** @brief number of bytes left to read */
+ size_t left() const noexcept;
+ /** @brief get next byte from the packet body, populated with read() call.
+ * @param val result will be stored here on success
+ * @return true on success or false otherwise (if end of the packet is reached)
+ **/
+ bool get(uint8_t &val) noexcept;
+ /** @brief get next big-endian uint16 from the packet body, populated with read() call.
+ * @param val result will be stored here on success
+ * @return true on success or false otherwise (if end of the packet is reached)
+ **/
+ bool get(uint16_t &val) noexcept;
+ /** @brief get next big-endian uint32 from the packet body, populated with read() call.
+ * @param val result will be stored here on success
+ * @return true on success or false otherwise (if end of the packet is reached)
+ **/
+ bool get(uint32_t &val) noexcept;
+ /** @brief get some bytes from the packet body, populated with read() call.
+ * @param val packet body bytes will be stored here. Must be capable of storing len bytes.
+ * @param len number of bytes to read
+ * @return true on success or false otherwise (if end of the packet is reached)
+ **/
+ bool get(uint8_t *val, size_t len) noexcept;
+ /** @brief get next keyid from the packet body, populated with read() call.
+ * @param val result will be stored here on success
+ * @return true on success or false otherwise (if end of the packet is reached)
+ **/
+ bool get(pgp_key_id_t &val) noexcept;
+ /** @brief get next mpi from the packet body, populated with read() call.
+ * @param val result will be stored here on success
+ * @return true on success or false otherwise (if end of the packet is reached
+ * or mpi is ill-formed)
+ **/
+ bool get(pgp_mpi_t &val) noexcept;
+ /** @brief Read ECC key curve and convert it to pgp_curve_t */
+ bool get(pgp_curve_t &val) noexcept;
+ /** @brief read s2k from the packet */
+ bool get(pgp_s2k_t &s2k) noexcept;
+ /** @brief append some bytes to the packet body */
+ void add(const void *data, size_t len);
+ /** @brief append single byte to the packet body */
+ void add_byte(uint8_t bt);
+ /** @brief append big endian 16-bit value to the packet body */
+ void add_uint16(uint16_t val);
+ /** @brief append big endian 32-bit value to the packet body */
+ void add_uint32(uint32_t val);
+ /** @brief append keyid to the packet body */
+ void add(const pgp_key_id_t &val);
+ /** @brief add pgp mpi (including header) to the packet body */
+ void add(const pgp_mpi_t &val);
+ /**
+ * @brief add pgp signature subpackets (including their length) to the packet body
+ * @param sig signature, containing subpackets
+ * @param hashed whether write hashed or not hashed subpackets
+ */
+ void add_subpackets(const pgp_signature_t &sig, bool hashed);
+ /** @brief add ec curve description to the packet body */
+ void add(const pgp_curve_t curve);
+ /** @brief add s2k description to the packet body */
+ void add(const pgp_s2k_t &s2k);
+ /** @brief read 'short-length' packet body (including tag and length bytes) from the source
+ * @param src source to read from
+ * @return RNP_SUCCESS or error code if operation failed
+ **/
+ rnp_result_t read(pgp_source_t &src) noexcept;
+ /** @brief write packet header, length and body to the dst
+ * @param dst destination to write to.
+ * @param hdr write packet's header or not
+ **/
+ void write(pgp_dest_t &dst, bool hdr = true) noexcept;
+ /** @brief mark contents as secure, so secure_clear() must be called in the destructor */
+ void mark_secure(bool secure = true) noexcept;
+} pgp_packet_body_t;
+
+/** public-key encrypted session key packet */
+typedef struct pgp_pk_sesskey_t {
+ unsigned version{};
+ pgp_key_id_t key_id{};
+ pgp_pubkey_alg_t alg{};
+ std::vector<uint8_t> material_buf{};
+
+ void write(pgp_dest_t &dst) const;
+ rnp_result_t parse(pgp_source_t &src);
+ /**
+ * @brief Parse encrypted material which is stored in packet in raw.
+ * @param material on success parsed material will be stored here.
+ * @return true on success or false otherwise. May also throw an exception.
+ */
+ bool parse_material(pgp_encrypted_material_t &material) const;
+ /**
+ * @brief Write encrypted material to the material_buf.
+ * @param material populated encrypted material.
+ */
+ void write_material(const pgp_encrypted_material_t &material);
+} pgp_pk_sesskey_t;
+
+/** pkp_sk_sesskey_t */
+typedef struct pgp_sk_sesskey_t {
+ unsigned version{};
+ pgp_symm_alg_t alg{};
+ pgp_s2k_t s2k{};
+ uint8_t enckey[PGP_MAX_KEY_SIZE + PGP_AEAD_MAX_TAG_LEN + 1]{};
+ unsigned enckeylen{};
+ /* v5 specific fields */
+ pgp_aead_alg_t aalg{};
+ uint8_t iv[PGP_MAX_BLOCK_SIZE]{};
+ unsigned ivlen{};
+
+ void write(pgp_dest_t &dst) const;
+ rnp_result_t parse(pgp_source_t &src);
+} pgp_sk_sesskey_t;
+
+/** pgp_one_pass_sig_t */
+typedef struct pgp_one_pass_sig_t {
+ uint8_t version{};
+ pgp_sig_type_t type{};
+ pgp_hash_alg_t halg{};
+ pgp_pubkey_alg_t palg{};
+ pgp_key_id_t keyid{};
+ unsigned nested{};
+
+ void write(pgp_dest_t &dst) const;
+ rnp_result_t parse(pgp_source_t &src);
+} pgp_one_pass_sig_t;
+
+/** Struct to hold userid or userattr packet. We don't parse userattr now, just storing the
+ * binary blob as it is. It may be distinguished by tag field.
+ */
+typedef struct pgp_userid_pkt_t {
+ pgp_pkt_type_t tag;
+ uint8_t * uid;
+ size_t uid_len;
+
+ pgp_userid_pkt_t() : tag(PGP_PKT_RESERVED), uid(NULL), uid_len(0){};
+ pgp_userid_pkt_t(const pgp_userid_pkt_t &src);
+ pgp_userid_pkt_t(pgp_userid_pkt_t &&src);
+ pgp_userid_pkt_t &operator=(pgp_userid_pkt_t &&src);
+ pgp_userid_pkt_t &operator=(const pgp_userid_pkt_t &src);
+ bool operator==(const pgp_userid_pkt_t &src) const;
+ bool operator!=(const pgp_userid_pkt_t &src) const;
+ ~pgp_userid_pkt_t();
+
+ void write(pgp_dest_t &dst) const;
+ rnp_result_t parse(pgp_source_t &src);
+} pgp_userid_pkt_t;
+
+uint16_t read_uint16(const uint8_t *buf);
+
+uint32_t read_uint32(const uint8_t *buf);
+
+void write_uint16(uint8_t *buf, uint16_t val);
+
+/** @brief write new packet length
+ * @param buf pre-allocated buffer, must have 5 bytes
+ * @param len packet length
+ * @return number of bytes, saved in buf
+ **/
+size_t write_packet_len(uint8_t *buf, size_t len);
+
+/** @brief get packet type from the packet header byte
+ * @param ptag first byte of the packet header
+ * @return packet type or -1 if ptag is wrong
+ **/
+int get_packet_type(uint8_t ptag);
+
+/** @brief peek the packet type from the stream
+ * @param src source to peek from
+ * @return packet tag or -1 if read failed or packet header is malformed
+ */
+int stream_pkt_type(pgp_source_t &src);
+
+/** @brief Peek length of the packet header. Returns false on error.
+ * @param src source to read length from
+ * @param hdrlen header length will be put here on success. Cannot be NULL.
+ * @return true on success or false if there is a read error or packet length
+ * is ill-formed
+ **/
+bool stream_pkt_hdr_len(pgp_source_t &src, size_t &hdrlen);
+
+bool stream_old_indeterminate_pkt_len(pgp_source_t *src);
+
+bool stream_partial_pkt_len(pgp_source_t *src);
+
+size_t get_partial_pkt_len(uint8_t blen);
+
+/** @brief Read packet length for fixed-size (say, small) packet. Returns false on error.
+ * Will also read packet tag byte. We do not allow partial length here as well as large
+ * packets (so ignoring possible size_t overflow)
+ *
+ * @param src source to read length from
+ * @param pktlen packet length will be stored here on success. Cannot be NULL.
+ * @return true on success or false if there is read error or packet length is ill-formed
+ **/
+bool stream_read_pkt_len(pgp_source_t *src, size_t *pktlen);
+
+/** @brief Read partial packet chunk length.
+ *
+ * @param src source to read length from
+ * @param clen chunk length will be stored here on success. Cannot be NULL.
+ * @param last will be set to true if chunk is last (i.e. has non-partial length)
+ * @return true on success or false if there is read error or packet length is ill-formed
+ **/
+bool stream_read_partial_chunk_len(pgp_source_t *src, size_t *clen, bool *last);
+
+/** @brief get and parse OpenPGP packet header to the structure.
+ * Note: this will not read but just peek required bytes.
+ *
+ * @param src source to read from
+ * @param hdr header structure
+ * @return RNP_SUCCESS or error code if operation failed
+ **/
+rnp_result_t stream_peek_packet_hdr(pgp_source_t *src, pgp_packet_hdr_t *hdr);
+
+/* Packet handling functions */
+
+/** @brief read OpenPGP packet from the stream, and write its contents to another stream.
+ * @param src source with packet data
+ * @param dst destination to write packet contents. All write failures on dst
+ * will be ignored. Can be NULL if you need just to skip packet.
+ * @return RNP_SUCCESS or error code if operation failed.
+ */
+rnp_result_t stream_read_packet(pgp_source_t *src, pgp_dest_t *dst);
+
+rnp_result_t stream_skip_packet(pgp_source_t *src);
+
+rnp_result_t stream_parse_marker(pgp_source_t &src);
+
+/* Public/Private key or Subkey */
+
+bool is_key_pkt(int tag);
+
+bool is_subkey_pkt(int tag);
+
+bool is_primary_key_pkt(int tag);
+
+bool is_public_key_pkt(int tag);
+
+bool is_secret_key_pkt(int tag);
+
+bool is_rsa_key_alg(pgp_pubkey_alg_t alg);
+
+#endif