1 /*
2  * Copyright (c) 2018-2020, [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 "config.h"
28 #include <sys/stat.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #else
34 #include "uniwin.h"
35 #endif
36 #include <string.h>
37 #include "time-utils.h"
38 #include "stream-def.h"
39 #include "stream-dump.h"
40 #include "stream-armor.h"
41 #include "stream-packet.h"
42 #include "stream-parse.h"
43 #include "types.h"
44 #include "ctype.h"
45 #include "crypto/symmetric.h"
46 #include "crypto/s2k.h"
47 #include "fingerprint.h"
48 #include "pgp-key.h"
49 #include "list.h"
50 #include "crypto.h"
51 #include "json_utils.h"
52 #include <algorithm>
53 
54 static pgp_map_t packet_tag_map[] = {
55   {PGP_PKT_RESERVED, "Reserved"},
56   {PGP_PKT_PK_SESSION_KEY, "Public-Key Encrypted Session Key"},
57   {PGP_PKT_SIGNATURE, "Signature"},
58   {PGP_PKT_SK_SESSION_KEY, "Symmetric-Key Encrypted Session Key"},
59   {PGP_PKT_ONE_PASS_SIG, "One-Pass Signature"},
60   {PGP_PKT_SECRET_KEY, "Secret Key"},
61   {PGP_PKT_PUBLIC_KEY, "Public Key"},
62   {PGP_PKT_SECRET_SUBKEY, "Secret Subkey"},
63   {PGP_PKT_COMPRESSED, "Compressed Data"},
64   {PGP_PKT_SE_DATA, "Symmetrically Encrypted Data"},
65   {PGP_PKT_MARKER, "Marker"},
66   {PGP_PKT_LITDATA, "Literal Data"},
67   {PGP_PKT_TRUST, "Trust"},
68   {PGP_PKT_USER_ID, "User ID"},
69   {PGP_PKT_PUBLIC_SUBKEY, "Public Subkey"},
70   {PGP_PKT_RESERVED2, "reserved2"},
71   {PGP_PKT_RESERVED3, "reserved3"},
72   {PGP_PKT_USER_ATTR, "User Attribute"},
73   {PGP_PKT_SE_IP_DATA, "Symmetric Encrypted and Integrity Protected Data"},
74   {PGP_PKT_MDC, "Modification Detection Code"},
75   {PGP_PKT_AEAD_ENCRYPTED, "AEAD Encrypted Data Packet"},
76 
77   {0x00, NULL}, /* this is the end-of-array marker */
78 };
79 
80 static pgp_map_t sig_type_map[] = {
81   {PGP_SIG_BINARY, "Signature of a binary document"},
82   {PGP_SIG_TEXT, "Signature of a canonical text document"},
83   {PGP_SIG_STANDALONE, "Standalone signature"},
84   {PGP_CERT_GENERIC, "Generic User ID certification"},
85   {PGP_CERT_PERSONA, "Personal User ID certification"},
86   {PGP_CERT_CASUAL, "Casual User ID certification"},
87   {PGP_CERT_POSITIVE, "Positive User ID certification"},
88   {PGP_SIG_SUBKEY, "Subkey Binding Signature"},
89   {PGP_SIG_PRIMARY, "Primary Key Binding Signature"},
90   {PGP_SIG_DIRECT, "Direct-key signature"},
91   {PGP_SIG_REV_KEY, "Key revocation signature"},
92   {PGP_SIG_REV_SUBKEY, "Subkey revocation signature"},
93   {PGP_SIG_REV_CERT, "Certification revocation signature"},
94   {PGP_SIG_TIMESTAMP, "Timestamp signature"},
95   {PGP_SIG_3RD_PARTY, "Third-Party Confirmation signature"},
96   {0x00, NULL}, /* this is the end-of-array marker */
97 };
98 
99 static pgp_map_t sig_subpkt_type_map[] = {
100   {PGP_SIG_SUBPKT_CREATION_TIME, "signature creation time"},
101   {PGP_SIG_SUBPKT_EXPIRATION_TIME, "signature expiration time"},
102   {PGP_SIG_SUBPKT_EXPORT_CERT, "exportable certification"},
103   {PGP_SIG_SUBPKT_TRUST, "trust signature"},
104   {PGP_SIG_SUBPKT_REGEXP, "regular expression"},
105   {PGP_SIG_SUBPKT_REVOCABLE, "revocable"},
106   {PGP_SIG_SUBPKT_KEY_EXPIRY, "key expiration time"},
107   {PGP_SIG_SUBPKT_PREFERRED_SKA, "preferred symmetric algorithms"},
108   {PGP_SIG_SUBPKT_REVOCATION_KEY, "revocation key"},
109   {PGP_SIG_SUBPKT_ISSUER_KEY_ID, "issuer key ID"},
110   {PGP_SIG_SUBPKT_NOTATION_DATA, "notation data"},
111   {PGP_SIG_SUBPKT_PREFERRED_HASH, "preferred hash algorithms"},
112   {PGP_SIG_SUBPKT_PREF_COMPRESS, "preferred compression algorithms"},
113   {PGP_SIG_SUBPKT_KEYSERV_PREFS, "key server preferences"},
114   {PGP_SIG_SUBPKT_PREF_KEYSERV, "preferred key server"},
115   {PGP_SIG_SUBPKT_PRIMARY_USER_ID, "primary user ID"},
116   {PGP_SIG_SUBPKT_POLICY_URI, "policy URI"},
117   {PGP_SIG_SUBPKT_KEY_FLAGS, "key flags"},
118   {PGP_SIG_SUBPKT_SIGNERS_USER_ID, "signer's user ID"},
119   {PGP_SIG_SUBPKT_REVOCATION_REASON, "reason for revocation"},
120   {PGP_SIG_SUBPKT_FEATURES, "features"},
121   {PGP_SIG_SUBPKT_SIGNATURE_TARGET, "signature target"},
122   {PGP_SIG_SUBPKT_EMBEDDED_SIGNATURE, "embedded signature"},
123   {PGP_SIG_SUBPKT_ISSUER_FPR, "issuer fingerprint"},
124   {PGP_SIG_SUBPKT_PREFERRED_AEAD, "preferred AEAD algorithms"},
125   {0x00, NULL}, /* this is the end-of-array marker */
126 };
127 
128 static pgp_map_t key_type_map[] = {
129   {PGP_PKT_SECRET_KEY, "Secret key"},
130   {PGP_PKT_PUBLIC_KEY, "Public key"},
131   {PGP_PKT_SECRET_SUBKEY, "Secret subkey"},
132   {PGP_PKT_PUBLIC_SUBKEY, "Public subkey"},
133   {0x00, NULL},
134 };
135 
136 static pgp_map_t pubkey_alg_map[] = {
137   {PGP_PKA_RSA, "RSA (Encrypt or Sign)"},
138   {PGP_PKA_RSA_ENCRYPT_ONLY, "RSA (Encrypt-Only)"},
139   {PGP_PKA_RSA_SIGN_ONLY, "RSA (Sign-Only)"},
140   {PGP_PKA_ELGAMAL, "Elgamal (Encrypt-Only)"},
141   {PGP_PKA_DSA, "DSA"},
142   {PGP_PKA_ECDH, "ECDH"},
143   {PGP_PKA_ECDSA, "ECDSA"},
144   {PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN, "Elgamal"},
145   {PGP_PKA_RESERVED_DH, "Reserved for DH (X9.42)"},
146   {PGP_PKA_EDDSA, "EdDSA"},
147   {PGP_PKA_SM2, "SM2"},
148   {0x00, NULL}, /* this is the end-of-array marker */
149 };
150 
151 static pgp_map_t symm_alg_map[] = {
152   {PGP_SA_PLAINTEXT, "Plaintext"},
153   {PGP_SA_IDEA, "IDEA"},
154   {PGP_SA_TRIPLEDES, "TripleDES"},
155   {PGP_SA_CAST5, "CAST5"},
156   {PGP_SA_BLOWFISH, "Blowfish"},
157   {PGP_SA_AES_128, "AES-128"},
158   {PGP_SA_AES_192, "AES-192"},
159   {PGP_SA_AES_256, "AES-256"},
160   {PGP_SA_TWOFISH, "Twofish"},
161   {PGP_SA_CAMELLIA_128, "Camellia-128"},
162   {PGP_SA_CAMELLIA_192, "Camellia-192"},
163   {PGP_SA_CAMELLIA_256, "Camellia-256"},
164   {PGP_SA_SM4, "SM4"},
165   {0x00, NULL}, /* this is the end-of-array marker */
166 };
167 
168 static pgp_map_t hash_alg_map[] = {
169   {PGP_HASH_MD5, "MD5"},
170   {PGP_HASH_SHA1, "SHA1"},
171   {PGP_HASH_RIPEMD, "RIPEMD160"},
172   {PGP_HASH_SHA256, "SHA256"},
173   {PGP_HASH_SHA384, "SHA384"},
174   {PGP_HASH_SHA512, "SHA512"},
175   {PGP_HASH_SHA224, "SHA224"},
176   {PGP_HASH_SM3, "SM3"},
177   {PGP_HASH_SHA3_256, "SHA3-256"},
178   {PGP_HASH_SHA3_512, "SHA3-512"},
179   {0x00, NULL}, /* this is the end-of-array marker */
180 };
181 
182 static pgp_map_t z_alg_map[] = {
183   {PGP_C_NONE, "Uncompressed"},
184   {PGP_C_ZIP, "ZIP"},
185   {PGP_C_ZLIB, "ZLib"},
186   {PGP_C_BZIP2, "BZip2"},
187   {0x00, NULL}, /* this is the end-of-array marker */
188 };
189 
190 static pgp_map_t aead_alg_map[] = {
191   {PGP_AEAD_NONE, "None"},
192   {PGP_AEAD_EAX, "EAX"},
193   {PGP_AEAD_OCB, "OCB"},
194   {0x00, NULL}, /* this is the end-of-array marker */
195 };
196 
197 static pgp_map_t revoc_reason_map[] = {
198   {PGP_REVOCATION_NO_REASON, "No reason"},
199   {PGP_REVOCATION_SUPERSEDED, "Superseded"},
200   {PGP_REVOCATION_COMPROMISED, "Compromised"},
201   {PGP_REVOCATION_RETIRED, "Retired"},
202   {PGP_REVOCATION_NO_LONGER_VALID, "No longer valid"},
203   {0x00, NULL},
204 };
205 
206 typedef struct pgp_dest_indent_param_t {
207     int         level;
208     bool        lstart;
209     pgp_dest_t *writedst;
210 } pgp_dest_indent_param_t;
211 
212 static rnp_result_t
indent_dst_write(pgp_dest_t * dst,const void * buf,size_t len)213 indent_dst_write(pgp_dest_t *dst, const void *buf, size_t len)
214 {
215     pgp_dest_indent_param_t *param = (pgp_dest_indent_param_t *) dst->param;
216     const char *             line = (const char *) buf;
217     char                     indent[4] = {' ', ' ', ' ', ' '};
218 
219     if (!len) {
220         return RNP_SUCCESS;
221     }
222 
223     do {
224         if (param->lstart) {
225             for (int i = 0; i < param->level; i++) {
226                 dst_write(param->writedst, indent, sizeof(indent));
227             }
228             param->lstart = false;
229         }
230 
231         for (size_t i = 0; i < len; i++) {
232             if ((line[i] == '\n') || (i == len - 1)) {
233                 dst_write(param->writedst, line, i + 1);
234                 param->lstart = line[i] == '\n';
235                 line += i + 1;
236                 len -= i + 1;
237                 break;
238             }
239         }
240     } while (len > 0);
241 
242     return RNP_SUCCESS;
243 }
244 
245 static void
indent_dst_close(pgp_dest_t * dst,bool discard)246 indent_dst_close(pgp_dest_t *dst, bool discard)
247 {
248     pgp_dest_indent_param_t *param = (pgp_dest_indent_param_t *) dst->param;
249     if (!param) {
250         return;
251     }
252 
253     free(param);
254 }
255 
256 static rnp_result_t
init_indent_dest(pgp_dest_t * dst,pgp_dest_t * origdst)257 init_indent_dest(pgp_dest_t *dst, pgp_dest_t *origdst)
258 {
259     pgp_dest_indent_param_t *param;
260 
261     if (!init_dst_common(dst, sizeof(*param))) {
262         return RNP_ERROR_OUT_OF_MEMORY;
263     }
264 
265     dst->write = indent_dst_write;
266     dst->close = indent_dst_close;
267     dst->finish = NULL;
268     dst->no_cache = true;
269     param = (pgp_dest_indent_param_t *) dst->param;
270     param->writedst = origdst;
271     param->lstart = true;
272 
273     return RNP_SUCCESS;
274 }
275 
276 static void
indent_dest_increase(pgp_dest_t * dst)277 indent_dest_increase(pgp_dest_t *dst)
278 {
279     pgp_dest_indent_param_t *param = (pgp_dest_indent_param_t *) dst->param;
280     param->level++;
281 }
282 
283 static void
indent_dest_decrease(pgp_dest_t * dst)284 indent_dest_decrease(pgp_dest_t *dst)
285 {
286     pgp_dest_indent_param_t *param = (pgp_dest_indent_param_t *) dst->param;
287     if (param->level > 0) {
288         param->level--;
289     }
290 }
291 
292 static void
indent_dest_set(pgp_dest_t * dst,int level)293 indent_dest_set(pgp_dest_t *dst, int level)
294 {
295     pgp_dest_indent_param_t *param = (pgp_dest_indent_param_t *) dst->param;
296     param->level = level;
297 }
298 
299 static size_t
vsnprinthex(char * str,size_t slen,const uint8_t * buf,size_t buflen)300 vsnprinthex(char *str, size_t slen, const uint8_t *buf, size_t buflen)
301 {
302     static const char *hexes = "0123456789abcdef";
303     size_t             idx = 0;
304 
305     for (size_t i = 0; (i < buflen) && (i < (slen - 1) / 2); i++) {
306         str[idx++] = hexes[buf[i] >> 4];
307         str[idx++] = hexes[buf[i] & 0xf];
308     }
309     str[idx] = '\0';
310     return buflen * 2;
311 }
312 
313 static void
dst_print_mpi(pgp_dest_t * dst,const char * name,pgp_mpi_t * mpi,bool dumpbin)314 dst_print_mpi(pgp_dest_t *dst, const char *name, pgp_mpi_t *mpi, bool dumpbin)
315 {
316     char hex[5000];
317     if (!dumpbin) {
318         dst_printf(dst, "%s: %d bits\n", name, (int) mpi_bits(mpi));
319     } else {
320         vsnprinthex(hex, sizeof(hex), mpi->mpi, mpi->len);
321         dst_printf(dst, "%s: %d bits, %s\n", name, (int) mpi_bits(mpi), hex);
322     }
323 }
324 
325 static void
dst_print_palg(pgp_dest_t * dst,const char * name,pgp_pubkey_alg_t palg)326 dst_print_palg(pgp_dest_t *dst, const char *name, pgp_pubkey_alg_t palg)
327 {
328     const char *palg_name = pgp_str_from_map(palg, pubkey_alg_map);
329     if (!name) {
330         name = "public key algorithm";
331     }
332 
333     dst_printf(dst, "%s: %d (%s)\n", name, (int) palg, palg_name);
334 }
335 
336 static void
dst_print_halg(pgp_dest_t * dst,const char * name,pgp_hash_alg_t halg)337 dst_print_halg(pgp_dest_t *dst, const char *name, pgp_hash_alg_t halg)
338 {
339     const char *halg_name = pgp_str_from_map(halg, hash_alg_map);
340     if (!name) {
341         name = "hash algorithm";
342     }
343 
344     dst_printf(dst, "%s: %d (%s)\n", name, (int) halg, halg_name);
345 }
346 
347 static void
dst_print_salg(pgp_dest_t * dst,const char * name,pgp_symm_alg_t salg)348 dst_print_salg(pgp_dest_t *dst, const char *name, pgp_symm_alg_t salg)
349 {
350     const char *salg_name = pgp_str_from_map(salg, symm_alg_map);
351     if (!name) {
352         name = "symmetric algorithm";
353     }
354 
355     dst_printf(dst, "%s: %d (%s)\n", name, (int) salg, salg_name);
356 }
357 
358 static void
dst_print_aalg(pgp_dest_t * dst,const char * name,pgp_aead_alg_t aalg)359 dst_print_aalg(pgp_dest_t *dst, const char *name, pgp_aead_alg_t aalg)
360 {
361     const char *aalg_name = pgp_str_from_map(aalg, aead_alg_map);
362     if (!name) {
363         name = "aead algorithm";
364     }
365 
366     dst_printf(dst, "%s: %d (%s)\n", name, (int) aalg, aalg_name);
367 }
368 
369 static void
dst_print_zalg(pgp_dest_t * dst,const char * name,pgp_compression_type_t zalg)370 dst_print_zalg(pgp_dest_t *dst, const char *name, pgp_compression_type_t zalg)
371 {
372     const char *zalg_name = pgp_str_from_map(zalg, z_alg_map);
373     if (!name) {
374         name = "compression algorithm";
375     }
376 
377     dst_printf(dst, "%s: %d (%s)\n", name, (int) zalg, zalg_name);
378 }
379 
380 static void
dst_print_raw(pgp_dest_t * dst,const char * name,const void * data,size_t len)381 dst_print_raw(pgp_dest_t *dst, const char *name, const void *data, size_t len)
382 {
383     dst_printf(dst, "%s: ", name);
384     dst_write(dst, data, len);
385     dst_printf(dst, "\n");
386 }
387 
388 static void
dst_print_algs(pgp_dest_t * dst,const char * name,uint8_t * algs,size_t algc,pgp_map_t map[])389 dst_print_algs(pgp_dest_t *dst, const char *name, uint8_t *algs, size_t algc, pgp_map_t map[])
390 {
391     if (!name) {
392         name = "algorithms";
393     }
394 
395     dst_printf(dst, "%s: ", name);
396     for (size_t i = 0; i < algc; i++) {
397         dst_printf(dst, "%s%s", pgp_str_from_map(algs[i], map), i + 1 < algc ? ", " : "");
398     }
399     dst_printf(dst, " (");
400     for (size_t i = 0; i < algc; i++) {
401         dst_printf(dst, "%d%s", (int) algs[i], i + 1 < algc ? ", " : "");
402     }
403     dst_printf(dst, ")\n");
404 }
405 
406 static void
dst_print_sig_type(pgp_dest_t * dst,const char * name,pgp_sig_type_t sigtype)407 dst_print_sig_type(pgp_dest_t *dst, const char *name, pgp_sig_type_t sigtype)
408 {
409     const char *sig_name = pgp_str_from_map(sigtype, sig_type_map);
410     if (!name) {
411         name = "signature type";
412     }
413     dst_printf(dst, "%s: %d (%s)\n", name, (int) sigtype, sig_name);
414 }
415 
416 static void
dst_print_hex(pgp_dest_t * dst,const char * name,const uint8_t * data,size_t len,bool bytes)417 dst_print_hex(pgp_dest_t *dst, const char *name, const uint8_t *data, size_t len, bool bytes)
418 {
419     char hex[512];
420     vsnprinthex(hex, sizeof(hex), data, len);
421     if (bytes) {
422         dst_printf(dst, "%s: 0x%s (%d bytes)\n", name, hex, (int) len);
423     } else {
424         dst_printf(dst, "%s: 0x%s\n", name, hex);
425     }
426 }
427 
428 static void
dst_print_keyid(pgp_dest_t * dst,const char * name,const pgp_key_id_t & keyid)429 dst_print_keyid(pgp_dest_t *dst, const char *name, const pgp_key_id_t &keyid)
430 {
431     if (!name) {
432         name = "key id";
433     }
434     dst_print_hex(dst, name, keyid.data(), keyid.size(), false);
435 }
436 
437 static void
dst_print_s2k(pgp_dest_t * dst,pgp_s2k_t * s2k)438 dst_print_s2k(pgp_dest_t *dst, pgp_s2k_t *s2k)
439 {
440     dst_printf(dst, "s2k specifier: %d\n", (int) s2k->specifier);
441     if ((s2k->specifier == PGP_S2KS_EXPERIMENTAL) && s2k->gpg_ext_num) {
442         dst_printf(dst, "GPG extension num: %d\n", (int) s2k->gpg_ext_num);
443         if (s2k->gpg_ext_num == PGP_S2K_GPG_SMARTCARD) {
444             static_assert(sizeof(s2k->gpg_serial) == 16, "invalid s2k->gpg_serial size");
445             size_t slen = s2k->gpg_serial_len > 16 ? 16 : s2k->gpg_serial_len;
446             dst_print_hex(dst, "card serial number", s2k->gpg_serial, slen, true);
447         }
448         return;
449     }
450     if (s2k->specifier == PGP_S2KS_EXPERIMENTAL) {
451         dst_print_hex(dst,
452                       "Unknown experimental s2k",
453                       s2k->experimental.data(),
454                       s2k->experimental.size(),
455                       true);
456         return;
457     }
458     dst_print_halg(dst, "s2k hash algorithm", s2k->hash_alg);
459     if ((s2k->specifier == PGP_S2KS_SALTED) ||
460         (s2k->specifier == PGP_S2KS_ITERATED_AND_SALTED)) {
461         dst_print_hex(dst, "s2k salt", s2k->salt, PGP_SALT_SIZE, false);
462     }
463     if (s2k->specifier == PGP_S2KS_ITERATED_AND_SALTED) {
464         size_t real_iter = pgp_s2k_decode_iterations(s2k->iterations);
465         dst_printf(dst, "s2k iterations: %zu (encoded as %u)\n", real_iter, s2k->iterations);
466     }
467 }
468 
469 static void
dst_print_time(pgp_dest_t * dst,const char * name,uint32_t time)470 dst_print_time(pgp_dest_t *dst, const char *name, uint32_t time)
471 {
472     char buf[26] = {0};
473     if (!name) {
474         name = "time";
475     }
476     strncpy(buf, rnp_ctime(time), sizeof(buf));
477     buf[24] = '\0';
478     dst_printf(
479       dst, "%s: %zu (%s%s)\n", name, (size_t) time, rnp_y2k38_warning(time) ? ">=" : "", buf);
480 }
481 
482 static void
dst_print_expiration(pgp_dest_t * dst,const char * name,uint32_t seconds)483 dst_print_expiration(pgp_dest_t *dst, const char *name, uint32_t seconds)
484 {
485     if (!name) {
486         name = "expiration";
487     }
488     if (seconds) {
489         int days = seconds / (24 * 60 * 60);
490         dst_printf(dst, "%s: %zu seconds (%d days)\n", name, (size_t) seconds, days);
491     } else {
492         dst_printf(dst, "%s: 0 (never)\n", name);
493     }
494 }
495 
496 #define LINELEN 16
497 
498 static void
dst_hexdump(pgp_dest_t * dst,const uint8_t * src,size_t length)499 dst_hexdump(pgp_dest_t *dst, const uint8_t *src, size_t length)
500 {
501     size_t i;
502     char   line[LINELEN + 1];
503 
504     for (i = 0; i < length; i++) {
505         if (i % LINELEN == 0) {
506             dst_printf(dst, "%.5zu | ", i);
507         }
508         dst_printf(dst, "%.02x ", (uint8_t) src[i]);
509         line[i % LINELEN] = (isprint(src[i])) ? src[i] : '.';
510         if (i % LINELEN == LINELEN - 1) {
511             line[LINELEN] = 0x0;
512             dst_printf(dst, " | %s\n", line);
513         }
514     }
515     if (i % LINELEN != 0) {
516         for (; i % LINELEN != 0; i++) {
517             dst_printf(dst, "   ");
518             line[i % LINELEN] = ' ';
519         }
520         line[LINELEN] = 0x0;
521         dst_printf(dst, " | %s\n", line);
522     }
523 }
524 
525 static rnp_result_t stream_dump_packets_raw(rnp_dump_ctx_t *ctx,
526                                             pgp_source_t *  src,
527                                             pgp_dest_t *    dst);
528 static void         stream_dump_signature_pkt(rnp_dump_ctx_t * ctx,
529                                               pgp_signature_t *sig,
530                                               pgp_dest_t *     dst);
531 
532 static void
signature_dump_subpacket(rnp_dump_ctx_t * ctx,pgp_dest_t * dst,const pgp_sig_subpkt_t & subpkt)533 signature_dump_subpacket(rnp_dump_ctx_t *ctx, pgp_dest_t *dst, const pgp_sig_subpkt_t &subpkt)
534 {
535     const char *sname = pgp_str_from_map(subpkt.type, sig_subpkt_type_map);
536 
537     switch (subpkt.type) {
538     case PGP_SIG_SUBPKT_CREATION_TIME:
539         dst_print_time(dst, sname, subpkt.fields.create);
540         break;
541     case PGP_SIG_SUBPKT_EXPIRATION_TIME:
542         dst_print_expiration(dst, sname, subpkt.fields.expiry);
543         break;
544     case PGP_SIG_SUBPKT_EXPORT_CERT:
545         dst_printf(dst, "%s: %d\n", sname, (int) subpkt.fields.exportable);
546         break;
547     case PGP_SIG_SUBPKT_TRUST:
548         dst_printf(dst,
549                    "%s: amount %d, level %d\n",
550                    sname,
551                    (int) subpkt.fields.trust.amount,
552                    (int) subpkt.fields.trust.level);
553         break;
554     case PGP_SIG_SUBPKT_REGEXP:
555         dst_print_raw(dst, sname, subpkt.fields.regexp.str, subpkt.fields.regexp.len);
556         break;
557     case PGP_SIG_SUBPKT_REVOCABLE:
558         dst_printf(dst, "%s: %d\n", sname, (int) subpkt.fields.revocable);
559         break;
560     case PGP_SIG_SUBPKT_KEY_EXPIRY:
561         dst_print_expiration(dst, sname, subpkt.fields.expiry);
562         break;
563     case PGP_SIG_SUBPKT_PREFERRED_SKA:
564         dst_print_algs(dst,
565                        "preferred symmetric algorithms",
566                        subpkt.fields.preferred.arr,
567                        subpkt.fields.preferred.len,
568                        symm_alg_map);
569         break;
570     case PGP_SIG_SUBPKT_REVOCATION_KEY:
571         dst_printf(dst, "%s\n", sname);
572         dst_printf(dst, "class: %d\n", (int) subpkt.fields.revocation_key.klass);
573         dst_print_palg(dst, NULL, subpkt.fields.revocation_key.pkalg);
574         dst_print_hex(
575           dst, "fingerprint", subpkt.fields.revocation_key.fp, PGP_FINGERPRINT_SIZE, true);
576         break;
577     case PGP_SIG_SUBPKT_ISSUER_KEY_ID:
578         dst_print_hex(dst, sname, subpkt.fields.issuer, PGP_KEY_ID_SIZE, false);
579         break;
580     case PGP_SIG_SUBPKT_NOTATION_DATA:
581         break;
582     case PGP_SIG_SUBPKT_PREFERRED_HASH:
583         dst_print_algs(dst,
584                        "preferred hash algorithms",
585                        subpkt.fields.preferred.arr,
586                        subpkt.fields.preferred.len,
587                        hash_alg_map);
588         break;
589     case PGP_SIG_SUBPKT_PREF_COMPRESS:
590         dst_print_algs(dst,
591                        "preferred compression algorithms",
592                        subpkt.fields.preferred.arr,
593                        subpkt.fields.preferred.len,
594                        z_alg_map);
595         break;
596     case PGP_SIG_SUBPKT_KEYSERV_PREFS:
597         dst_printf(dst, "%s\n", sname);
598         dst_printf(dst, "no-modify: %d\n", (int) subpkt.fields.ks_prefs.no_modify);
599         break;
600     case PGP_SIG_SUBPKT_PREF_KEYSERV:
601         dst_print_raw(
602           dst, sname, subpkt.fields.preferred_ks.uri, subpkt.fields.preferred_ks.len);
603         break;
604     case PGP_SIG_SUBPKT_PRIMARY_USER_ID:
605         dst_printf(dst, "%s: %d\n", sname, (int) subpkt.fields.primary_uid);
606         break;
607     case PGP_SIG_SUBPKT_POLICY_URI:
608         dst_print_raw(dst, sname, subpkt.fields.policy.uri, subpkt.fields.policy.len);
609         break;
610     case PGP_SIG_SUBPKT_KEY_FLAGS: {
611         uint8_t flg = subpkt.fields.key_flags;
612         dst_printf(dst, "%s: 0x%02x ( ", sname, flg);
613         dst_printf(dst, "%s", flg ? "" : "none");
614         dst_printf(dst, "%s", flg & PGP_KF_CERTIFY ? "certify " : "");
615         dst_printf(dst, "%s", flg & PGP_KF_SIGN ? "sign " : "");
616         dst_printf(dst, "%s", flg & PGP_KF_ENCRYPT_COMMS ? "encrypt_comm " : "");
617         dst_printf(dst, "%s", flg & PGP_KF_ENCRYPT_STORAGE ? "encrypt_storage " : "");
618         dst_printf(dst, "%s", flg & PGP_KF_SPLIT ? "split " : "");
619         dst_printf(dst, "%s", flg & PGP_KF_AUTH ? "auth " : "");
620         dst_printf(dst, "%s", flg & PGP_KF_SHARED ? "shared " : "");
621         dst_printf(dst, ")\n");
622         break;
623     }
624     case PGP_SIG_SUBPKT_SIGNERS_USER_ID:
625         dst_print_raw(dst, sname, subpkt.fields.signer.uid, subpkt.fields.signer.len);
626         break;
627     case PGP_SIG_SUBPKT_REVOCATION_REASON: {
628         int         code = subpkt.fields.revocation_reason.code;
629         const char *reason = pgp_str_from_map(code, revoc_reason_map);
630         dst_printf(dst, "%s: %d (%s)\n", sname, code, reason);
631         dst_print_raw(dst,
632                       "message",
633                       subpkt.fields.revocation_reason.str,
634                       subpkt.fields.revocation_reason.len);
635         break;
636     }
637     case PGP_SIG_SUBPKT_FEATURES:
638         dst_printf(dst, "%s: 0x%02x ( ", sname, subpkt.data[0]);
639         dst_printf(dst, "%s", subpkt.fields.features & PGP_KEY_FEATURE_MDC ? "mdc " : "");
640         dst_printf(dst, "%s", subpkt.fields.features & PGP_KEY_FEATURE_AEAD ? "aead " : "");
641         dst_printf(dst, "%s", subpkt.fields.features & PGP_KEY_FEATURE_V5 ? "v5 keys " : "");
642         dst_printf(dst, ")\n");
643         break;
644     case PGP_SIG_SUBPKT_EMBEDDED_SIGNATURE:
645         dst_printf(dst, "%s:\n", sname);
646         stream_dump_signature_pkt(ctx, subpkt.fields.sig, dst);
647         break;
648     case PGP_SIG_SUBPKT_ISSUER_FPR:
649         dst_print_hex(
650           dst, sname, subpkt.fields.issuer_fp.fp, subpkt.fields.issuer_fp.len, true);
651         break;
652     case PGP_SIG_SUBPKT_PREFERRED_AEAD:
653         dst_print_algs(dst,
654                        "preferred aead algorithms",
655                        subpkt.fields.preferred.arr,
656                        subpkt.fields.preferred.len,
657                        aead_alg_map);
658         break;
659     default:
660         if (!ctx->dump_packets) {
661             indent_dest_increase(dst);
662             dst_hexdump(dst, subpkt.data, subpkt.len);
663             indent_dest_decrease(dst);
664         }
665     }
666 }
667 
668 static void
signature_dump_subpackets(rnp_dump_ctx_t * ctx,pgp_dest_t * dst,pgp_signature_t * sig,bool hashed)669 signature_dump_subpackets(rnp_dump_ctx_t * ctx,
670                           pgp_dest_t *     dst,
671                           pgp_signature_t *sig,
672                           bool             hashed)
673 {
674     bool empty = true;
675 
676     for (auto &subpkt : sig->subpkts) {
677         if (subpkt.hashed != hashed) {
678             continue;
679         }
680         empty = false;
681         dst_printf(dst, ":type %d, len %d", (int) subpkt.type, (int) subpkt.len);
682         dst_printf(dst, "%s\n", subpkt.critical ? ", critical" : "");
683         if (ctx->dump_packets) {
684             dst_printf(dst, ":subpacket contents:\n");
685             indent_dest_increase(dst);
686             dst_hexdump(dst, subpkt.data, subpkt.len);
687             indent_dest_decrease(dst);
688         }
689         signature_dump_subpacket(ctx, dst, subpkt);
690     }
691 
692     if (empty) {
693         dst_printf(dst, "none\n");
694     }
695 }
696 
697 static void
stream_dump_signature_pkt(rnp_dump_ctx_t * ctx,pgp_signature_t * sig,pgp_dest_t * dst)698 stream_dump_signature_pkt(rnp_dump_ctx_t *ctx, pgp_signature_t *sig, pgp_dest_t *dst)
699 {
700     indent_dest_increase(dst);
701 
702     dst_printf(dst, "version: %d\n", (int) sig->version);
703     dst_print_sig_type(dst, "type", sig->type());
704     if (sig->version < PGP_V4) {
705         dst_print_time(dst, "creation time", sig->creation_time);
706         dst_print_keyid(dst, "signing key id", sig->signer);
707     }
708     dst_print_palg(dst, NULL, sig->palg);
709     dst_print_halg(dst, NULL, sig->halg);
710 
711     if (sig->version >= PGP_V4) {
712         dst_printf(dst, "hashed subpackets:\n");
713         indent_dest_increase(dst);
714         signature_dump_subpackets(ctx, dst, sig, true);
715         indent_dest_decrease(dst);
716 
717         dst_printf(dst, "unhashed subpackets:\n");
718         indent_dest_increase(dst);
719         signature_dump_subpackets(ctx, dst, sig, false);
720         indent_dest_decrease(dst);
721     }
722 
723     dst_print_hex(dst, "lbits", sig->lbits, sizeof(sig->lbits), false);
724     dst_printf(dst, "signature material:\n");
725     indent_dest_increase(dst);
726 
727     pgp_signature_material_t material = {};
728     try {
729         sig->parse_material(material);
730     } catch (const std::exception &e) {
731         RNP_LOG("%s", e.what());
732         return;
733     }
734     switch (sig->palg) {
735     case PGP_PKA_RSA:
736     case PGP_PKA_RSA_ENCRYPT_ONLY:
737     case PGP_PKA_RSA_SIGN_ONLY:
738         dst_print_mpi(dst, "rsa s", &material.rsa.s, ctx->dump_mpi);
739         break;
740     case PGP_PKA_DSA:
741         dst_print_mpi(dst, "dsa r", &material.dsa.r, ctx->dump_mpi);
742         dst_print_mpi(dst, "dsa s", &material.dsa.s, ctx->dump_mpi);
743         break;
744     case PGP_PKA_EDDSA:
745     case PGP_PKA_ECDSA:
746     case PGP_PKA_SM2:
747     case PGP_PKA_ECDH:
748         dst_print_mpi(dst, "ecc r", &material.ecc.r, ctx->dump_mpi);
749         dst_print_mpi(dst, "ecc s", &material.ecc.s, ctx->dump_mpi);
750         break;
751     case PGP_PKA_ELGAMAL:
752     case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
753         dst_print_mpi(dst, "eg r", &material.eg.r, ctx->dump_mpi);
754         dst_print_mpi(dst, "eg s", &material.eg.s, ctx->dump_mpi);
755         break;
756     default:
757         dst_printf(dst, "unknown algorithm\n");
758     }
759     indent_dest_decrease(dst);
760     indent_dest_decrease(dst);
761 }
762 
763 static void
stream_dump_signature(rnp_dump_ctx_t * ctx,pgp_source_t * src,pgp_dest_t * dst)764 stream_dump_signature(rnp_dump_ctx_t *ctx, pgp_source_t *src, pgp_dest_t *dst)
765 {
766     pgp_signature_t sig;
767     rnp_result_t    ret;
768 
769     dst_printf(dst, "Signature packet\n");
770     try {
771         ret = sig.parse(*src);
772     } catch (const std::exception &e) {
773         RNP_LOG("%s", e.what());
774         ret = RNP_ERROR_GENERIC;
775     }
776     if (ret) {
777         indent_dest_increase(dst);
778         dst_printf(dst, "failed to parse\n");
779         indent_dest_decrease(dst);
780         return;
781     }
782     stream_dump_signature_pkt(ctx, &sig, dst);
783 }
784 
785 static rnp_result_t
stream_dump_key(rnp_dump_ctx_t * ctx,pgp_source_t * src,pgp_dest_t * dst)786 stream_dump_key(rnp_dump_ctx_t *ctx, pgp_source_t *src, pgp_dest_t *dst)
787 {
788     pgp_key_pkt_t     key;
789     rnp_result_t      ret;
790     pgp_fingerprint_t keyfp = {};
791 
792     try {
793         ret = key.parse(*src);
794     } catch (const std::exception &e) {
795         RNP_LOG("%s", e.what());
796         ret = RNP_ERROR_GENERIC;
797     }
798     if (ret) {
799         return ret;
800     }
801 
802     dst_printf(dst, "%s packet\n", pgp_str_from_map(key.tag, key_type_map));
803     indent_dest_increase(dst);
804 
805     dst_printf(dst, "version: %d\n", (int) key.version);
806     dst_print_time(dst, "creation time", key.creation_time);
807     if (key.version < PGP_V4) {
808         dst_printf(dst, "v3 validity days: %d\n", (int) key.v3_days);
809     }
810     dst_print_palg(dst, NULL, key.alg);
811     dst_printf(dst, "public key material:\n");
812     indent_dest_increase(dst);
813 
814     switch (key.alg) {
815     case PGP_PKA_RSA:
816     case PGP_PKA_RSA_ENCRYPT_ONLY:
817     case PGP_PKA_RSA_SIGN_ONLY:
818         dst_print_mpi(dst, "rsa n", &key.material.rsa.n, ctx->dump_mpi);
819         dst_print_mpi(dst, "rsa e", &key.material.rsa.e, ctx->dump_mpi);
820         break;
821     case PGP_PKA_DSA:
822         dst_print_mpi(dst, "dsa p", &key.material.dsa.p, ctx->dump_mpi);
823         dst_print_mpi(dst, "dsa q", &key.material.dsa.q, ctx->dump_mpi);
824         dst_print_mpi(dst, "dsa g", &key.material.dsa.g, ctx->dump_mpi);
825         dst_print_mpi(dst, "dsa y", &key.material.dsa.y, ctx->dump_mpi);
826         break;
827     case PGP_PKA_ELGAMAL:
828     case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
829         dst_print_mpi(dst, "eg p", &key.material.eg.p, ctx->dump_mpi);
830         dst_print_mpi(dst, "eg g", &key.material.eg.g, ctx->dump_mpi);
831         dst_print_mpi(dst, "eg y", &key.material.eg.y, ctx->dump_mpi);
832         break;
833     case PGP_PKA_ECDSA:
834     case PGP_PKA_EDDSA:
835     case PGP_PKA_SM2: {
836         const ec_curve_desc_t *cdesc = get_curve_desc(key.material.ec.curve);
837         dst_print_mpi(dst, "ecc p", &key.material.ec.p, ctx->dump_mpi);
838         dst_printf(dst, "ecc curve: %s\n", cdesc ? cdesc->pgp_name : "unknown");
839         break;
840     }
841     case PGP_PKA_ECDH: {
842         const ec_curve_desc_t *cdesc = get_curve_desc(key.material.ec.curve);
843         dst_print_mpi(dst, "ecdh p", &key.material.ec.p, ctx->dump_mpi);
844         dst_printf(dst, "ecdh curve: %s\n", cdesc ? cdesc->pgp_name : "unknown");
845         dst_print_halg(dst, "ecdh hash algorithm", key.material.ec.kdf_hash_alg);
846         dst_printf(dst, "ecdh key wrap algorithm: %d\n", (int) key.material.ec.key_wrap_alg);
847         break;
848     }
849     default:
850         dst_printf(dst, "unknown public key algorithm\n");
851     }
852     indent_dest_decrease(dst);
853 
854     if (is_secret_key_pkt(key.tag)) {
855         dst_printf(dst, "secret key material:\n");
856         indent_dest_increase(dst);
857 
858         dst_printf(dst, "s2k usage: %d\n", (int) key.sec_protection.s2k.usage);
859         if ((key.sec_protection.s2k.usage == PGP_S2KU_ENCRYPTED) ||
860             (key.sec_protection.s2k.usage == PGP_S2KU_ENCRYPTED_AND_HASHED)) {
861             dst_print_salg(dst, NULL, key.sec_protection.symm_alg);
862             dst_print_s2k(dst, &key.sec_protection.s2k);
863             if (key.sec_protection.s2k.specifier != PGP_S2KS_EXPERIMENTAL) {
864                 size_t bl_size = pgp_block_size(key.sec_protection.symm_alg);
865                 if (bl_size) {
866                     dst_print_hex(dst, "cipher iv", key.sec_protection.iv, bl_size, true);
867                 } else {
868                     dst_printf(dst, "cipher iv: unknown algorithm\n");
869                 }
870             }
871             dst_printf(dst, "encrypted secret key data: %d bytes\n", (int) key.sec_len);
872         }
873 
874         if (!key.sec_protection.s2k.usage) {
875             dst_printf(dst, "cleartext secret key data: %d bytes\n", (int) key.sec_len);
876         }
877         indent_dest_decrease(dst);
878     }
879 
880     pgp_key_id_t keyid = {};
881     if (!pgp_keyid(keyid, key)) {
882         dst_print_hex(dst, "keyid", keyid.data(), keyid.size(), false);
883     } else {
884         dst_printf(dst, "keyid: failed to calculate");
885     }
886 
887     if ((key.version > PGP_V3) && (ctx->dump_grips)) {
888         if (!pgp_fingerprint(keyfp, key)) {
889             dst_print_hex(dst, "fingerprint", keyfp.fingerprint, keyfp.length, false);
890         } else {
891             dst_printf(dst, "fingerprint: failed to calculate");
892         }
893     }
894 
895     if (ctx->dump_grips) {
896         pgp_key_grip_t grip;
897         if (rnp_key_store_get_key_grip(&key.material, grip)) {
898             dst_print_hex(dst, "grip", grip.data(), grip.size(), false);
899         } else {
900             dst_printf(dst, "grip: failed to calculate");
901         }
902     }
903 
904     indent_dest_decrease(dst);
905     return RNP_SUCCESS;
906 }
907 
908 static rnp_result_t
stream_dump_userid(pgp_source_t * src,pgp_dest_t * dst)909 stream_dump_userid(pgp_source_t *src, pgp_dest_t *dst)
910 {
911     pgp_userid_pkt_t uid;
912     rnp_result_t     ret;
913     const char *     utype;
914 
915     try {
916         ret = uid.parse(*src);
917     } catch (const std::exception &e) {
918         ret = RNP_ERROR_GENERIC;
919     }
920     if (ret) {
921         return ret;
922     }
923 
924     switch (uid.tag) {
925     case PGP_PKT_USER_ID:
926         utype = "UserID";
927         break;
928     case PGP_PKT_USER_ATTR:
929         utype = "UserAttr";
930         break;
931     default:
932         utype = "Unknown user id";
933     }
934 
935     dst_printf(dst, "%s packet\n", utype);
936     indent_dest_increase(dst);
937 
938     switch (uid.tag) {
939     case PGP_PKT_USER_ID:
940         dst_printf(dst, "id: ");
941         dst_write(dst, uid.uid, uid.uid_len);
942         dst_printf(dst, "\n");
943         break;
944     case PGP_PKT_USER_ATTR:
945         dst_printf(dst, "id: (%d bytes of data)\n", (int) uid.uid_len);
946         break;
947     default:;
948     }
949 
950     indent_dest_decrease(dst);
951     return RNP_SUCCESS;
952 }
953 
954 static rnp_result_t
stream_dump_pk_session_key(rnp_dump_ctx_t * ctx,pgp_source_t * src,pgp_dest_t * dst)955 stream_dump_pk_session_key(rnp_dump_ctx_t *ctx, pgp_source_t *src, pgp_dest_t *dst)
956 {
957     pgp_pk_sesskey_t         pkey;
958     pgp_encrypted_material_t material;
959     rnp_result_t             ret;
960 
961     try {
962         ret = pkey.parse(*src);
963         if (!pkey.parse_material(material)) {
964             ret = RNP_ERROR_BAD_FORMAT;
965         }
966     } catch (const std::exception &e) {
967         ret = RNP_ERROR_GENERIC;
968     }
969     if (ret) {
970         return ret;
971     }
972 
973     dst_printf(dst, "Public-key encrypted session key packet\n");
974     indent_dest_increase(dst);
975 
976     dst_printf(dst, "version: %d\n", (int) pkey.version);
977     dst_print_keyid(dst, NULL, pkey.key_id);
978     dst_print_palg(dst, NULL, pkey.alg);
979     dst_printf(dst, "encrypted material:\n");
980     indent_dest_increase(dst);
981 
982     switch (pkey.alg) {
983     case PGP_PKA_RSA:
984     case PGP_PKA_RSA_ENCRYPT_ONLY:
985     case PGP_PKA_RSA_SIGN_ONLY:
986         dst_print_mpi(dst, "rsa m", &material.rsa.m, ctx->dump_mpi);
987         break;
988     case PGP_PKA_ELGAMAL:
989     case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
990         dst_print_mpi(dst, "eg g", &material.eg.g, ctx->dump_mpi);
991         dst_print_mpi(dst, "eg m", &material.eg.m, ctx->dump_mpi);
992         break;
993     case PGP_PKA_SM2:
994         dst_print_mpi(dst, "sm2 m", &material.sm2.m, ctx->dump_mpi);
995         break;
996     case PGP_PKA_ECDH:
997         dst_print_mpi(dst, "ecdh p", &material.ecdh.p, ctx->dump_mpi);
998         if (ctx->dump_mpi) {
999             dst_print_hex(dst, "ecdh m", material.ecdh.m, material.ecdh.mlen, true);
1000         } else {
1001             dst_printf(dst, "ecdh m: %d bytes\n", (int) material.ecdh.mlen);
1002         }
1003         break;
1004     default:
1005         dst_printf(dst, "unknown public key algorithm\n");
1006     }
1007 
1008     indent_dest_decrease(dst);
1009     indent_dest_decrease(dst);
1010     return RNP_SUCCESS;
1011 }
1012 
1013 static rnp_result_t
stream_dump_sk_session_key(pgp_source_t * src,pgp_dest_t * dst)1014 stream_dump_sk_session_key(pgp_source_t *src, pgp_dest_t *dst)
1015 {
1016     pgp_sk_sesskey_t skey;
1017     rnp_result_t     ret;
1018 
1019     try {
1020         ret = skey.parse(*src);
1021     } catch (const std::exception &e) {
1022         ret = RNP_ERROR_GENERIC;
1023     }
1024     if (ret) {
1025         return ret;
1026     }
1027 
1028     dst_printf(dst, "Symmetric-key encrypted session key packet\n");
1029     indent_dest_increase(dst);
1030     dst_printf(dst, "version: %d\n", (int) skey.version);
1031     dst_print_salg(dst, NULL, skey.alg);
1032     if (skey.version == PGP_SKSK_V5) {
1033         dst_print_aalg(dst, NULL, skey.aalg);
1034     }
1035     dst_print_s2k(dst, &skey.s2k);
1036     if (skey.version == PGP_SKSK_V5) {
1037         dst_print_hex(dst, "aead iv", skey.iv, skey.ivlen, true);
1038     }
1039     dst_print_hex(dst, "encrypted key", skey.enckey, skey.enckeylen, true);
1040     indent_dest_decrease(dst);
1041 
1042     return RNP_SUCCESS;
1043 }
1044 
1045 static bool
stream_dump_get_aead_hdr(pgp_source_t * src,pgp_aead_hdr_t * hdr)1046 stream_dump_get_aead_hdr(pgp_source_t *src, pgp_aead_hdr_t *hdr)
1047 {
1048     pgp_dest_t encdst = {};
1049     uint8_t    encpkt[64] = {};
1050 
1051     if (init_mem_dest(&encdst, &encpkt, sizeof(encpkt))) {
1052         return false;
1053     }
1054     mem_dest_discard_overflow(&encdst, true);
1055 
1056     if (stream_read_packet(src, &encdst)) {
1057         dst_close(&encdst, false);
1058         return false;
1059     }
1060     size_t len = std::min(encdst.writeb, sizeof(encpkt));
1061     dst_close(&encdst, false);
1062 
1063     pgp_source_t memsrc = {};
1064     if (init_mem_src(&memsrc, encpkt, len, false)) {
1065         return false;
1066     }
1067     bool res = get_aead_src_hdr(&memsrc, hdr);
1068     src_close(&memsrc);
1069     return res;
1070 }
1071 
1072 static rnp_result_t
stream_dump_aead_encrypted(pgp_source_t * src,pgp_dest_t * dst)1073 stream_dump_aead_encrypted(pgp_source_t *src, pgp_dest_t *dst)
1074 {
1075     dst_printf(dst, "AEAD-encrypted data packet\n");
1076 
1077     pgp_aead_hdr_t aead = {};
1078     if (!stream_dump_get_aead_hdr(src, &aead)) {
1079         dst_printf(dst, "ERROR: failed to read AEAD header\n");
1080         return RNP_ERROR_READ;
1081     }
1082 
1083     indent_dest_increase(dst);
1084 
1085     dst_printf(dst, "version: %d\n", (int) aead.version);
1086     dst_print_salg(dst, NULL, aead.ealg);
1087     dst_print_aalg(dst, NULL, aead.aalg);
1088     dst_printf(dst, "chunk size: %d\n", (int) aead.csize);
1089     dst_print_hex(dst, "initialization vector", aead.iv, aead.ivlen, true);
1090 
1091     indent_dest_decrease(dst);
1092     return RNP_SUCCESS;
1093 }
1094 
1095 static rnp_result_t
stream_dump_encrypted(pgp_source_t * src,pgp_dest_t * dst,int tag)1096 stream_dump_encrypted(pgp_source_t *src, pgp_dest_t *dst, int tag)
1097 {
1098     switch (tag) {
1099     case PGP_PKT_SE_DATA:
1100         dst_printf(dst, "Symmetrically-encrypted data packet\n\n");
1101         break;
1102     case PGP_PKT_SE_IP_DATA:
1103         dst_printf(dst, "Symmetrically-encrypted integrity protected data packet\n\n");
1104         break;
1105     case PGP_PKT_AEAD_ENCRYPTED:
1106         return stream_dump_aead_encrypted(src, dst);
1107     default:
1108         dst_printf(dst, "Unknown encrypted data packet\n\n");
1109         break;
1110     }
1111 
1112     return stream_skip_packet(src);
1113 }
1114 
1115 static rnp_result_t
stream_dump_one_pass(pgp_source_t * src,pgp_dest_t * dst)1116 stream_dump_one_pass(pgp_source_t *src, pgp_dest_t *dst)
1117 {
1118     pgp_one_pass_sig_t onepass;
1119     rnp_result_t       ret;
1120 
1121     try {
1122         ret = onepass.parse(*src);
1123     } catch (const std::exception &e) {
1124         ret = RNP_ERROR_GENERIC;
1125     }
1126     if (ret) {
1127         return ret;
1128     }
1129 
1130     dst_printf(dst, "One-pass signature packet\n");
1131     indent_dest_increase(dst);
1132 
1133     dst_printf(dst, "version: %d\n", (int) onepass.version);
1134     dst_print_sig_type(dst, NULL, onepass.type);
1135     dst_print_halg(dst, NULL, onepass.halg);
1136     dst_print_palg(dst, NULL, onepass.palg);
1137     dst_print_keyid(dst, "signing key id", onepass.keyid);
1138     dst_printf(dst, "nested: %d\n", (int) onepass.nested);
1139 
1140     indent_dest_decrease(dst);
1141     return RNP_SUCCESS;
1142 }
1143 
1144 static rnp_result_t
stream_dump_compressed(rnp_dump_ctx_t * ctx,pgp_source_t * src,pgp_dest_t * dst)1145 stream_dump_compressed(rnp_dump_ctx_t *ctx, pgp_source_t *src, pgp_dest_t *dst)
1146 {
1147     pgp_source_t zsrc = {0};
1148     uint8_t      zalg;
1149     rnp_result_t ret;
1150 
1151     if ((ret = init_compressed_src(&zsrc, src))) {
1152         return ret;
1153     }
1154 
1155     dst_printf(dst, "Compressed data packet\n");
1156     indent_dest_increase(dst);
1157 
1158     get_compressed_src_alg(&zsrc, &zalg);
1159     dst_print_zalg(dst, NULL, (pgp_compression_type_t) zalg);
1160     dst_printf(dst, "Decompressed contents:\n");
1161     ret = stream_dump_packets_raw(ctx, &zsrc, dst);
1162 
1163     src_close(&zsrc);
1164     indent_dest_decrease(dst);
1165     return ret;
1166 }
1167 
1168 static rnp_result_t
stream_dump_literal(pgp_source_t * src,pgp_dest_t * dst)1169 stream_dump_literal(pgp_source_t *src, pgp_dest_t *dst)
1170 {
1171     pgp_source_t      lsrc = {0};
1172     pgp_literal_hdr_t lhdr = {0};
1173     rnp_result_t      ret;
1174     uint8_t           readbuf[16384];
1175 
1176     if ((ret = init_literal_src(&lsrc, src))) {
1177         return ret;
1178     }
1179 
1180     dst_printf(dst, "Literal data packet\n");
1181     indent_dest_increase(dst);
1182 
1183     get_literal_src_hdr(&lsrc, &lhdr);
1184     dst_printf(dst, "data format: '%c'\n", lhdr.format);
1185     dst_printf(dst, "filename: %s (len %d)\n", lhdr.fname, (int) lhdr.fname_len);
1186     dst_print_time(dst, "timestamp", lhdr.timestamp);
1187 
1188     ret = RNP_SUCCESS;
1189     while (!src_eof(&lsrc)) {
1190         size_t read = 0;
1191         if (!src_read(&lsrc, readbuf, sizeof(readbuf), &read)) {
1192             ret = RNP_ERROR_READ;
1193             break;
1194         }
1195     }
1196 
1197     dst_printf(dst, "data bytes: %lu\n", (unsigned long) lsrc.readb);
1198     src_close(&lsrc);
1199     indent_dest_decrease(dst);
1200     return ret;
1201 }
1202 
1203 static rnp_result_t
stream_dump_marker(pgp_source_t & src,pgp_dest_t & dst)1204 stream_dump_marker(pgp_source_t &src, pgp_dest_t &dst)
1205 {
1206     dst_printf(&dst, "Marker packet\n");
1207     indent_dest_increase(&dst);
1208     dst_printf(
1209       &dst, "contents: %s\n", stream_parse_marker(src) ? "invalid" : PGP_MARKER_CONTENTS);
1210     indent_dest_decrease(&dst);
1211     return RNP_SUCCESS;
1212 }
1213 
1214 static rnp_result_t
stream_dump_packets_raw(rnp_dump_ctx_t * ctx,pgp_source_t * src,pgp_dest_t * dst)1215 stream_dump_packets_raw(rnp_dump_ctx_t *ctx, pgp_source_t *src, pgp_dest_t *dst)
1216 {
1217     char         msg[1024 + PGP_MAX_HEADER_SIZE] = {0};
1218     char         smsg[128] = {0};
1219     rnp_result_t ret = RNP_ERROR_GENERIC;
1220 
1221     if (src_eof(src)) {
1222         return RNP_SUCCESS;
1223     }
1224 
1225     /* do not allow endless recursion */
1226     if (++ctx->layers > MAXIMUM_NESTING_LEVEL) {
1227         RNP_LOG("Too many OpenPGP nested layers during the dump.");
1228         dst_printf(dst, ":too many OpenPGP packet layers, stopping.");
1229         ret = RNP_SUCCESS;
1230         goto finish;
1231     }
1232 
1233     while (!src_eof(src)) {
1234         pgp_packet_hdr_t hdr = {};
1235         size_t           off = src->readb;
1236         rnp_result_t     hdrret = stream_peek_packet_hdr(src, &hdr);
1237         if (hdrret) {
1238             ret = hdrret;
1239             goto finish;
1240         }
1241 
1242         if (hdr.partial) {
1243             snprintf(msg, sizeof(msg), "partial len");
1244         } else if (hdr.indeterminate) {
1245             snprintf(msg, sizeof(msg), "indeterminate len");
1246         } else {
1247             snprintf(msg, sizeof(msg), "len %zu", hdr.pkt_len);
1248         }
1249         vsnprinthex(smsg, sizeof(smsg), hdr.hdr, hdr.hdr_len);
1250         dst_printf(
1251           dst, ":off %zu: packet header 0x%s (tag %d, %s)\n", off, smsg, hdr.tag, msg);
1252 
1253         if (ctx->dump_packets) {
1254             size_t rlen = hdr.pkt_len + hdr.hdr_len;
1255             bool   part = false;
1256 
1257             if (!hdr.pkt_len || (rlen > 1024 + hdr.hdr_len)) {
1258                 rlen = 1024 + hdr.hdr_len;
1259                 part = true;
1260             }
1261 
1262             dst_printf(dst, ":off %zu: packet contents ", off + hdr.hdr_len);
1263             if (!src_peek(src, msg, rlen, &rlen)) {
1264                 dst_printf(dst, "- failed to read\n");
1265             } else {
1266                 rlen -= hdr.hdr_len;
1267                 if (part || (rlen < hdr.pkt_len)) {
1268                     dst_printf(dst, "(first %d bytes)\n", (int) rlen);
1269                 } else {
1270                     dst_printf(dst, "(%d bytes)\n", (int) rlen);
1271                 }
1272                 indent_dest_increase(dst);
1273                 dst_hexdump(dst, (uint8_t *) msg + hdr.hdr_len, rlen);
1274                 indent_dest_decrease(dst);
1275             }
1276             dst_printf(dst, "\n");
1277         }
1278 
1279         switch (hdr.tag) {
1280         case PGP_PKT_SIGNATURE:
1281             stream_dump_signature(ctx, src, dst);
1282             ret = RNP_SUCCESS;
1283             break;
1284         case PGP_PKT_SECRET_KEY:
1285         case PGP_PKT_PUBLIC_KEY:
1286         case PGP_PKT_SECRET_SUBKEY:
1287         case PGP_PKT_PUBLIC_SUBKEY:
1288             ret = stream_dump_key(ctx, src, dst);
1289             break;
1290         case PGP_PKT_USER_ID:
1291         case PGP_PKT_USER_ATTR:
1292             ret = stream_dump_userid(src, dst);
1293             break;
1294         case PGP_PKT_PK_SESSION_KEY:
1295             ret = stream_dump_pk_session_key(ctx, src, dst);
1296             break;
1297         case PGP_PKT_SK_SESSION_KEY:
1298             ret = stream_dump_sk_session_key(src, dst);
1299             break;
1300         case PGP_PKT_SE_DATA:
1301         case PGP_PKT_SE_IP_DATA:
1302         case PGP_PKT_AEAD_ENCRYPTED:
1303             ret = stream_dump_encrypted(src, dst, hdr.tag);
1304             break;
1305         case PGP_PKT_ONE_PASS_SIG:
1306             ret = stream_dump_one_pass(src, dst);
1307             break;
1308         case PGP_PKT_COMPRESSED:
1309             ret = stream_dump_compressed(ctx, src, dst);
1310             break;
1311         case PGP_PKT_LITDATA:
1312             ret = stream_dump_literal(src, dst);
1313             break;
1314         case PGP_PKT_MARKER:
1315             ret = stream_dump_marker(*src, *dst);
1316             break;
1317         case PGP_PKT_TRUST:
1318         case PGP_PKT_MDC:
1319             dst_printf(dst, "Skipping unhandled pkt: %d\n\n", (int) hdr.tag);
1320             ret = stream_skip_packet(src);
1321             break;
1322         default:
1323             dst_printf(dst, "Skipping Unknown pkt: %d\n\n", (int) hdr.tag);
1324             ret = stream_skip_packet(src);
1325         }
1326 
1327         if (ret) {
1328             RNP_LOG("failed to process packet");
1329             goto finish;
1330         }
1331     }
1332 
1333     ret = RNP_SUCCESS;
1334 finish:
1335     return ret;
1336 }
1337 
1338 static bool
stream_skip_cleartext(pgp_source_t * src)1339 stream_skip_cleartext(pgp_source_t *src)
1340 {
1341     char   buf[4096];
1342     size_t read = 0;
1343     size_t siglen = strlen(ST_SIG_BEGIN);
1344     char * hdrpos;
1345 
1346     while (!src_eof(src)) {
1347         if (!src_peek(src, buf, sizeof(buf) - 1, &read) || (read <= siglen)) {
1348             return false;
1349         }
1350         buf[read] = '\0';
1351 
1352         if ((hdrpos = strstr(buf, ST_SIG_BEGIN))) {
1353             /* +1 here is to skip \n on the beginning of ST_SIG_BEGIN */
1354             src_skip(src, hdrpos - buf + 1);
1355             return true;
1356         }
1357         src_skip(src, read - siglen + 1);
1358     }
1359     return false;
1360 }
1361 
1362 rnp_result_t
stream_dump_packets(rnp_dump_ctx_t * ctx,pgp_source_t * src,pgp_dest_t * dst)1363 stream_dump_packets(rnp_dump_ctx_t *ctx, pgp_source_t *src, pgp_dest_t *dst)
1364 {
1365     pgp_source_t armorsrc = {0};
1366     pgp_dest_t   wrdst = {0};
1367     bool         armored = false;
1368     bool         indent = false;
1369     rnp_result_t ret = RNP_ERROR_GENERIC;
1370 
1371     ctx->layers = 0;
1372     /* check whether source is cleartext - then skip till the signature */
1373     if (is_cleartext_source(src)) {
1374         dst_printf(dst, ":cleartext signed data\n");
1375         if (!stream_skip_cleartext(src)) {
1376             RNP_LOG("malformed cleartext signed data");
1377             ret = RNP_ERROR_BAD_FORMAT;
1378             goto finish;
1379         }
1380     }
1381     /* check whether source is armored */
1382     if (is_armored_source(src)) {
1383         if ((ret = init_armored_src(&armorsrc, src))) {
1384             RNP_LOG("failed to parse armored data");
1385             goto finish;
1386         }
1387         armored = true;
1388         src = &armorsrc;
1389         dst_printf(dst, ":armored input\n");
1390     }
1391 
1392     if (src_eof(src)) {
1393         dst_printf(dst, ":empty input\n");
1394         ret = RNP_SUCCESS;
1395         goto finish;
1396     }
1397 
1398     if ((ret = init_indent_dest(&wrdst, dst))) {
1399         RNP_LOG("failed to init indent dest");
1400         goto finish;
1401     }
1402     indent = true;
1403 
1404     indent_dest_set(&wrdst, 0);
1405 
1406     ret = stream_dump_packets_raw(ctx, src, &wrdst);
1407 
1408 finish:
1409     if (armored) {
1410         src_close(&armorsrc);
1411     }
1412     if (indent) {
1413         dst_close(&wrdst, false);
1414     }
1415     return ret;
1416 }
1417 
1418 static bool
obj_add_intstr_json(json_object * obj,const char * name,int val,pgp_map_t map[])1419 obj_add_intstr_json(json_object *obj, const char *name, int val, pgp_map_t map[])
1420 {
1421     if (!obj_add_field_json(obj, name, json_object_new_int(val))) {
1422         return false;
1423     }
1424     if (!map) {
1425         return true;
1426     }
1427     char        namestr[64] = {0};
1428     const char *str = pgp_str_from_map(val, map);
1429     snprintf(namestr, sizeof(namestr), "%s.str", name);
1430     return obj_add_field_json(obj, namestr, json_object_new_string(str));
1431 }
1432 
1433 static bool
obj_add_mpi_json(json_object * obj,const char * name,const pgp_mpi_t * mpi,bool contents)1434 obj_add_mpi_json(json_object *obj, const char *name, const pgp_mpi_t *mpi, bool contents)
1435 {
1436     char strname[64] = {0};
1437     snprintf(strname, sizeof(strname), "%s.bits", name);
1438     if (!obj_add_field_json(obj, strname, json_object_new_int(mpi_bits(mpi)))) {
1439         return false;
1440     }
1441     if (!contents) {
1442         return true;
1443     }
1444     snprintf(strname, sizeof(strname), "%s.raw", name);
1445     return obj_add_hex_json(obj, strname, mpi->mpi, mpi->len);
1446 }
1447 
1448 static bool
subpacket_obj_add_algs(json_object * obj,const char * name,uint8_t * algs,size_t len,pgp_map_t map[])1449 subpacket_obj_add_algs(
1450   json_object *obj, const char *name, uint8_t *algs, size_t len, pgp_map_t map[])
1451 {
1452     json_object *jso_algs = json_object_new_array();
1453     if (!jso_algs || !obj_add_field_json(obj, name, jso_algs)) {
1454         return false;
1455     }
1456     for (size_t i = 0; i < len; i++) {
1457         if (!array_add_element_json(jso_algs, json_object_new_int(algs[i]))) {
1458             return false;
1459         }
1460     }
1461     if (!map) {
1462         return true;
1463     }
1464 
1465     char strname[64] = {0};
1466     snprintf(strname, sizeof(strname), "%s.str", name);
1467 
1468     jso_algs = json_object_new_array();
1469     if (!jso_algs || !obj_add_field_json(obj, strname, jso_algs)) {
1470         return false;
1471     }
1472     for (size_t i = 0; i < len; i++) {
1473         if (!array_add_element_json(jso_algs,
1474                                     json_object_new_string(pgp_str_from_map(algs[i], map)))) {
1475             return false;
1476         }
1477     }
1478     return true;
1479 }
1480 
1481 static bool
obj_add_s2k_json(json_object * obj,pgp_s2k_t * s2k)1482 obj_add_s2k_json(json_object *obj, pgp_s2k_t *s2k)
1483 {
1484     json_object *s2k_obj = json_object_new_object();
1485     if (!obj_add_field_json(obj, "s2k", s2k_obj)) {
1486         return false;
1487     }
1488     if (!obj_add_field_json(s2k_obj, "specifier", json_object_new_int(s2k->specifier))) {
1489         return false;
1490     }
1491     if ((s2k->specifier == PGP_S2KS_EXPERIMENTAL) && s2k->gpg_ext_num) {
1492         if (!obj_add_field_json(
1493               s2k_obj, "gpg extension", json_object_new_int(s2k->gpg_ext_num))) {
1494             return false;
1495         }
1496         if (s2k->gpg_ext_num == PGP_S2K_GPG_SMARTCARD) {
1497             size_t slen = s2k->gpg_serial_len > 16 ? 16 : s2k->gpg_serial_len;
1498             if (!obj_add_hex_json(s2k_obj, "card serial number", s2k->gpg_serial, slen)) {
1499                 return false;
1500             }
1501         }
1502     }
1503     if (s2k->specifier == PGP_S2KS_EXPERIMENTAL) {
1504         return obj_add_hex_json(
1505           s2k_obj, "unknown experimental", s2k->experimental.data(), s2k->experimental.size());
1506     }
1507     if (!obj_add_intstr_json(s2k_obj, "hash algorithm", s2k->hash_alg, hash_alg_map)) {
1508         return false;
1509     }
1510     if (((s2k->specifier == PGP_S2KS_SALTED) ||
1511          (s2k->specifier == PGP_S2KS_ITERATED_AND_SALTED)) &&
1512         !obj_add_hex_json(s2k_obj, "salt", s2k->salt, PGP_SALT_SIZE)) {
1513         return false;
1514     }
1515     if (s2k->specifier == PGP_S2KS_ITERATED_AND_SALTED) {
1516         size_t real_iter = pgp_s2k_decode_iterations(s2k->iterations);
1517         if (!obj_add_field_json(s2k_obj, "iterations", json_object_new_int(real_iter))) {
1518             return false;
1519         }
1520     }
1521     return true;
1522 }
1523 
1524 static rnp_result_t stream_dump_signature_pkt_json(rnp_dump_ctx_t *       ctx,
1525                                                    const pgp_signature_t *sig,
1526                                                    json_object *          pkt);
1527 
1528 static bool
signature_dump_subpacket_json(rnp_dump_ctx_t * ctx,const pgp_sig_subpkt_t & subpkt,json_object * obj)1529 signature_dump_subpacket_json(rnp_dump_ctx_t *        ctx,
1530                               const pgp_sig_subpkt_t &subpkt,
1531                               json_object *           obj)
1532 {
1533     switch (subpkt.type) {
1534     case PGP_SIG_SUBPKT_CREATION_TIME:
1535         return obj_add_field_json(
1536           obj, "creation time", json_object_new_int64(subpkt.fields.create));
1537     case PGP_SIG_SUBPKT_EXPIRATION_TIME:
1538         return obj_add_field_json(
1539           obj, "expiration time", json_object_new_int64(subpkt.fields.expiry));
1540     case PGP_SIG_SUBPKT_EXPORT_CERT:
1541         return obj_add_field_json(
1542           obj, "exportable", json_object_new_boolean(subpkt.fields.exportable));
1543     case PGP_SIG_SUBPKT_TRUST:
1544         return obj_add_field_json(
1545                  obj, "amount", json_object_new_int(subpkt.fields.trust.amount)) &&
1546                obj_add_field_json(
1547                  obj, "level", json_object_new_int(subpkt.fields.trust.level));
1548     case PGP_SIG_SUBPKT_REGEXP:
1549         return obj_add_field_json(
1550           obj,
1551           "regexp",
1552           json_object_new_string_len(subpkt.fields.regexp.str, subpkt.fields.regexp.len));
1553     case PGP_SIG_SUBPKT_REVOCABLE:
1554         return obj_add_field_json(
1555           obj, "revocable", json_object_new_boolean(subpkt.fields.revocable));
1556     case PGP_SIG_SUBPKT_KEY_EXPIRY:
1557         return obj_add_field_json(
1558           obj, "key expiration", json_object_new_int64(subpkt.fields.expiry));
1559     case PGP_SIG_SUBPKT_PREFERRED_SKA:
1560         return subpacket_obj_add_algs(obj,
1561                                       "algorithms",
1562                                       subpkt.fields.preferred.arr,
1563                                       subpkt.fields.preferred.len,
1564                                       symm_alg_map);
1565     case PGP_SIG_SUBPKT_PREFERRED_HASH:
1566         return subpacket_obj_add_algs(obj,
1567                                       "algorithms",
1568                                       subpkt.fields.preferred.arr,
1569                                       subpkt.fields.preferred.len,
1570                                       hash_alg_map);
1571     case PGP_SIG_SUBPKT_PREF_COMPRESS:
1572         return subpacket_obj_add_algs(obj,
1573                                       "algorithms",
1574                                       subpkt.fields.preferred.arr,
1575                                       subpkt.fields.preferred.len,
1576                                       z_alg_map);
1577     case PGP_SIG_SUBPKT_PREFERRED_AEAD:
1578         return subpacket_obj_add_algs(obj,
1579                                       "algorithms",
1580                                       subpkt.fields.preferred.arr,
1581                                       subpkt.fields.preferred.len,
1582                                       aead_alg_map);
1583     case PGP_SIG_SUBPKT_REVOCATION_KEY:
1584         return obj_add_field_json(
1585                  obj, "class", json_object_new_int(subpkt.fields.revocation_key.klass)) &&
1586                obj_add_field_json(
1587                  obj, "algorithm", json_object_new_int(subpkt.fields.revocation_key.pkalg)) &&
1588                obj_add_hex_json(
1589                  obj, "fingerprint", subpkt.fields.revocation_key.fp, PGP_FINGERPRINT_SIZE);
1590     case PGP_SIG_SUBPKT_ISSUER_KEY_ID:
1591         return obj_add_hex_json(obj, "issuer keyid", subpkt.fields.issuer, PGP_KEY_ID_SIZE);
1592     case PGP_SIG_SUBPKT_KEYSERV_PREFS:
1593         return obj_add_field_json(
1594           obj, "no-modify", json_object_new_boolean(subpkt.fields.ks_prefs.no_modify));
1595     case PGP_SIG_SUBPKT_PREF_KEYSERV:
1596         return obj_add_field_json(obj,
1597                                   "uri",
1598                                   json_object_new_string_len(subpkt.fields.preferred_ks.uri,
1599                                                              subpkt.fields.preferred_ks.len));
1600     case PGP_SIG_SUBPKT_PRIMARY_USER_ID:
1601         return obj_add_field_json(
1602           obj, "primary", json_object_new_boolean(subpkt.fields.primary_uid));
1603     case PGP_SIG_SUBPKT_POLICY_URI:
1604         return obj_add_field_json(
1605           obj,
1606           "uri",
1607           json_object_new_string_len(subpkt.fields.policy.uri, subpkt.fields.policy.len));
1608     case PGP_SIG_SUBPKT_KEY_FLAGS: {
1609         uint8_t flg = subpkt.fields.key_flags;
1610         if (!obj_add_field_json(obj, "flags", json_object_new_int(flg))) {
1611             return false;
1612         }
1613         json_object *jso_flg = json_object_new_array();
1614         if (!jso_flg || !obj_add_field_json(obj, "flags.str", jso_flg)) {
1615             return false;
1616         }
1617         if ((flg & PGP_KF_CERTIFY) &&
1618             !array_add_element_json(jso_flg, json_object_new_string("certify"))) {
1619             return false;
1620         }
1621         if ((flg & PGP_KF_SIGN) &&
1622             !array_add_element_json(jso_flg, json_object_new_string("sign"))) {
1623             return false;
1624         }
1625         if ((flg & PGP_KF_ENCRYPT_COMMS) &&
1626             !array_add_element_json(jso_flg, json_object_new_string("encrypt_comm"))) {
1627             return false;
1628         }
1629         if ((flg & PGP_KF_ENCRYPT_STORAGE) &&
1630             !array_add_element_json(jso_flg, json_object_new_string("encrypt_storage"))) {
1631             return false;
1632         }
1633         if ((flg & PGP_KF_SPLIT) &&
1634             !array_add_element_json(jso_flg, json_object_new_string("split"))) {
1635             return false;
1636         }
1637         if ((flg & PGP_KF_AUTH) &&
1638             !array_add_element_json(jso_flg, json_object_new_string("auth"))) {
1639             return false;
1640         }
1641         if ((flg & PGP_KF_SHARED) &&
1642             !array_add_element_json(jso_flg, json_object_new_string("shared"))) {
1643             return false;
1644         }
1645         return true;
1646     }
1647     case PGP_SIG_SUBPKT_SIGNERS_USER_ID:
1648         return obj_add_field_json(
1649           obj,
1650           "uid",
1651           json_object_new_string_len(subpkt.fields.signer.uid, subpkt.fields.signer.len));
1652     case PGP_SIG_SUBPKT_REVOCATION_REASON: {
1653         if (!obj_add_intstr_json(
1654               obj, "code", subpkt.fields.revocation_reason.code, revoc_reason_map)) {
1655             return false;
1656         }
1657         return obj_add_field_json(
1658           obj,
1659           "message",
1660           json_object_new_string_len(subpkt.fields.revocation_reason.str,
1661                                      subpkt.fields.revocation_reason.len));
1662     }
1663     case PGP_SIG_SUBPKT_FEATURES:
1664         return obj_add_field_json(
1665                  obj,
1666                  "mdc",
1667                  json_object_new_boolean(subpkt.fields.features & PGP_KEY_FEATURE_MDC)) &&
1668                obj_add_field_json(
1669                  obj,
1670                  "aead",
1671                  json_object_new_boolean(subpkt.fields.features & PGP_KEY_FEATURE_AEAD)) &&
1672                obj_add_field_json(
1673                  obj,
1674                  "v5 keys",
1675                  json_object_new_boolean(subpkt.fields.features & PGP_KEY_FEATURE_V5));
1676     case PGP_SIG_SUBPKT_EMBEDDED_SIGNATURE: {
1677         json_object *sig = json_object_new_object();
1678         if (!sig || !obj_add_field_json(obj, "signature", sig)) {
1679             return false;
1680         }
1681         return !stream_dump_signature_pkt_json(ctx, subpkt.fields.sig, sig);
1682     }
1683     case PGP_SIG_SUBPKT_ISSUER_FPR:
1684         return obj_add_hex_json(
1685           obj, "fingerprint", subpkt.fields.issuer_fp.fp, subpkt.fields.issuer_fp.len);
1686     case PGP_SIG_SUBPKT_NOTATION_DATA:
1687     default:
1688         if (!ctx->dump_packets) {
1689             return obj_add_hex_json(obj, "raw", subpkt.data, subpkt.len);
1690         }
1691         return true;
1692     }
1693     return true;
1694 }
1695 
1696 static json_object *
signature_dump_subpackets_json(rnp_dump_ctx_t * ctx,const pgp_signature_t * sig)1697 signature_dump_subpackets_json(rnp_dump_ctx_t *ctx, const pgp_signature_t *sig)
1698 {
1699     json_object *res = json_object_new_array();
1700 
1701     for (auto &subpkt : sig->subpkts) {
1702         json_object *jso_subpkt = json_object_new_object();
1703         if (json_object_array_add(res, jso_subpkt)) {
1704             json_object_put(jso_subpkt);
1705             goto error;
1706         }
1707 
1708         if (!obj_add_intstr_json(jso_subpkt, "type", subpkt.type, sig_subpkt_type_map)) {
1709             goto error;
1710         }
1711         if (!obj_add_field_json(jso_subpkt, "length", json_object_new_int(subpkt.len))) {
1712             goto error;
1713         }
1714         if (!obj_add_field_json(
1715               jso_subpkt, "hashed", json_object_new_boolean(subpkt.hashed))) {
1716             goto error;
1717         }
1718         if (!obj_add_field_json(
1719               jso_subpkt, "critical", json_object_new_boolean(subpkt.critical))) {
1720             goto error;
1721         }
1722 
1723         if (ctx->dump_packets &&
1724             !obj_add_hex_json(jso_subpkt, "raw", subpkt.data, subpkt.len)) {
1725             goto error;
1726         }
1727 
1728         if (!signature_dump_subpacket_json(ctx, subpkt, jso_subpkt)) {
1729             goto error;
1730         }
1731     }
1732 
1733     return res;
1734 error:
1735     json_object_put(res);
1736     return NULL;
1737 }
1738 
1739 static rnp_result_t
stream_dump_signature_pkt_json(rnp_dump_ctx_t * ctx,const pgp_signature_t * sig,json_object * pkt)1740 stream_dump_signature_pkt_json(rnp_dump_ctx_t *       ctx,
1741                                const pgp_signature_t *sig,
1742                                json_object *          pkt)
1743 {
1744     json_object *            material = NULL;
1745     pgp_signature_material_t sigmaterial = {};
1746     rnp_result_t             ret = RNP_ERROR_OUT_OF_MEMORY;
1747 
1748     if (!obj_add_field_json(pkt, "version", json_object_new_int(sig->version))) {
1749         goto done;
1750     }
1751     if (!obj_add_intstr_json(pkt, "type", sig->type(), sig_type_map)) {
1752         goto done;
1753     }
1754 
1755     if (sig->version < PGP_V4) {
1756         if (!obj_add_field_json(
1757               pkt, "creation time", json_object_new_int(sig->creation_time))) {
1758             goto done;
1759         }
1760         if (!obj_add_hex_json(pkt, "signer", sig->signer.data(), sig->signer.size())) {
1761             goto done;
1762         }
1763     }
1764     if (!obj_add_intstr_json(pkt, "algorithm", sig->palg, pubkey_alg_map)) {
1765         goto done;
1766     }
1767     if (!obj_add_intstr_json(pkt, "hash algorithm", sig->halg, hash_alg_map)) {
1768         goto done;
1769     }
1770 
1771     if (sig->version >= PGP_V4) {
1772         json_object *subpkts = signature_dump_subpackets_json(ctx, sig);
1773         if (!subpkts) {
1774             goto done;
1775         }
1776         if (!obj_add_field_json(pkt, "subpackets", subpkts)) {
1777             goto done;
1778         }
1779     }
1780 
1781     if (!obj_add_hex_json(pkt, "lbits", sig->lbits, sizeof(sig->lbits))) {
1782         goto done;
1783     }
1784 
1785     material = json_object_new_object();
1786     if (!material || !obj_add_field_json(pkt, "material", material)) {
1787         goto done;
1788     }
1789 
1790     try {
1791         sig->parse_material(sigmaterial);
1792     } catch (const std::exception &e) {
1793         RNP_LOG("%s", e.what());
1794         return RNP_ERROR_OUT_OF_MEMORY;
1795     }
1796     switch (sig->palg) {
1797     case PGP_PKA_RSA:
1798     case PGP_PKA_RSA_ENCRYPT_ONLY:
1799     case PGP_PKA_RSA_SIGN_ONLY:
1800         if (!obj_add_mpi_json(material, "s", &sigmaterial.rsa.s, ctx->dump_mpi)) {
1801             goto done;
1802         }
1803         break;
1804     case PGP_PKA_DSA:
1805         if (!obj_add_mpi_json(material, "r", &sigmaterial.dsa.r, ctx->dump_mpi) ||
1806             !obj_add_mpi_json(material, "s", &sigmaterial.dsa.s, ctx->dump_mpi)) {
1807             goto done;
1808         }
1809         break;
1810     case PGP_PKA_EDDSA:
1811     case PGP_PKA_ECDSA:
1812     case PGP_PKA_SM2:
1813     case PGP_PKA_ECDH:
1814         if (!obj_add_mpi_json(material, "r", &sigmaterial.ecc.r, ctx->dump_mpi) ||
1815             !obj_add_mpi_json(material, "s", &sigmaterial.ecc.s, ctx->dump_mpi)) {
1816             goto done;
1817         }
1818         break;
1819     case PGP_PKA_ELGAMAL:
1820     case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
1821         if (!obj_add_mpi_json(material, "r", &sigmaterial.eg.r, ctx->dump_mpi) ||
1822             !obj_add_mpi_json(material, "s", &sigmaterial.eg.s, ctx->dump_mpi)) {
1823             goto done;
1824         }
1825         break;
1826     default:
1827         break;
1828     }
1829     ret = RNP_SUCCESS;
1830 done:
1831     return ret;
1832 }
1833 
1834 static rnp_result_t
stream_dump_signature_json(rnp_dump_ctx_t * ctx,pgp_source_t * src,json_object * pkt)1835 stream_dump_signature_json(rnp_dump_ctx_t *ctx, pgp_source_t *src, json_object *pkt)
1836 {
1837     pgp_signature_t sig;
1838     rnp_result_t    ret;
1839     try {
1840         ret = sig.parse(*src);
1841     } catch (const std::exception &e) {
1842         RNP_LOG("%s", e.what());
1843         ret = RNP_ERROR_GENERIC;
1844     }
1845     if (ret) {
1846         return RNP_SUCCESS;
1847     }
1848     return stream_dump_signature_pkt_json(ctx, &sig, pkt);
1849 }
1850 
1851 static rnp_result_t
stream_dump_key_json(rnp_dump_ctx_t * ctx,pgp_source_t * src,json_object * pkt)1852 stream_dump_key_json(rnp_dump_ctx_t *ctx, pgp_source_t *src, json_object *pkt)
1853 {
1854     pgp_key_pkt_t     key;
1855     rnp_result_t      ret;
1856     pgp_key_id_t      keyid = {};
1857     pgp_fingerprint_t keyfp = {};
1858     json_object *     material = NULL;
1859 
1860     try {
1861         ret = key.parse(*src);
1862     } catch (const std::exception &e) {
1863         RNP_LOG("%s", e.what());
1864         ret = RNP_ERROR_GENERIC;
1865     }
1866     if (ret) {
1867         return ret;
1868     }
1869 
1870     ret = RNP_ERROR_OUT_OF_MEMORY;
1871 
1872     if (!obj_add_field_json(pkt, "version", json_object_new_int(key.version))) {
1873         goto done;
1874     }
1875     if (!obj_add_field_json(pkt, "creation time", json_object_new_int64(key.creation_time))) {
1876         goto done;
1877     }
1878     if ((key.version < PGP_V4) &&
1879         !obj_add_field_json(pkt, "v3 days", json_object_new_int(key.v3_days))) {
1880         goto done;
1881     }
1882     if (!obj_add_intstr_json(pkt, "algorithm", key.alg, pubkey_alg_map)) {
1883         goto done;
1884     }
1885 
1886     material = json_object_new_object();
1887     if (!material || !obj_add_field_json(pkt, "material", material)) {
1888         goto done;
1889     }
1890 
1891     switch (key.alg) {
1892     case PGP_PKA_RSA:
1893     case PGP_PKA_RSA_ENCRYPT_ONLY:
1894     case PGP_PKA_RSA_SIGN_ONLY:
1895         if (!obj_add_mpi_json(material, "n", &key.material.rsa.n, ctx->dump_mpi) ||
1896             !obj_add_mpi_json(material, "e", &key.material.rsa.e, ctx->dump_mpi)) {
1897             goto done;
1898         }
1899         break;
1900     case PGP_PKA_DSA:
1901         if (!obj_add_mpi_json(material, "p", &key.material.dsa.p, ctx->dump_mpi) ||
1902             !obj_add_mpi_json(material, "q", &key.material.dsa.q, ctx->dump_mpi) ||
1903             !obj_add_mpi_json(material, "g", &key.material.dsa.g, ctx->dump_mpi) ||
1904             !obj_add_mpi_json(material, "y", &key.material.dsa.y, ctx->dump_mpi)) {
1905             goto done;
1906         }
1907         break;
1908     case PGP_PKA_ELGAMAL:
1909     case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
1910         if (!obj_add_mpi_json(material, "p", &key.material.eg.p, ctx->dump_mpi) ||
1911             !obj_add_mpi_json(material, "g", &key.material.eg.g, ctx->dump_mpi) ||
1912             !obj_add_mpi_json(material, "y", &key.material.eg.y, ctx->dump_mpi)) {
1913             goto done;
1914         }
1915         break;
1916     case PGP_PKA_ECDSA:
1917     case PGP_PKA_EDDSA:
1918     case PGP_PKA_SM2: {
1919         const ec_curve_desc_t *cdesc = get_curve_desc(key.material.ec.curve);
1920         if (!obj_add_mpi_json(material, "p", &key.material.ec.p, ctx->dump_mpi)) {
1921             goto done;
1922         }
1923         if (!obj_add_field_json(material,
1924                                 "curve",
1925                                 json_object_new_string(cdesc ? cdesc->pgp_name : "unknown"))) {
1926             goto done;
1927         }
1928         break;
1929     }
1930     case PGP_PKA_ECDH: {
1931         const ec_curve_desc_t *cdesc = get_curve_desc(key.material.ec.curve);
1932         if (!obj_add_mpi_json(material, "p", &key.material.ec.p, ctx->dump_mpi)) {
1933             goto done;
1934         }
1935         if (!obj_add_field_json(material,
1936                                 "curve",
1937                                 json_object_new_string(cdesc ? cdesc->pgp_name : "unknown"))) {
1938             goto done;
1939         }
1940         if (!obj_add_intstr_json(
1941               material, "hash algorithm", key.material.ec.kdf_hash_alg, hash_alg_map)) {
1942             goto done;
1943         }
1944         if (!obj_add_intstr_json(
1945               material, "key wrap algorithm", key.material.ec.key_wrap_alg, symm_alg_map)) {
1946             goto done;
1947         }
1948         break;
1949     }
1950     default:
1951         break;
1952     }
1953 
1954     if (is_secret_key_pkt(key.tag)) {
1955         if (!obj_add_field_json(
1956               material, "s2k usage", json_object_new_int(key.sec_protection.s2k.usage))) {
1957             goto done;
1958         }
1959         if (!obj_add_s2k_json(material, &key.sec_protection.s2k)) {
1960             goto done;
1961         }
1962         if (key.sec_protection.s2k.usage &&
1963             !obj_add_intstr_json(
1964               material, "symmetric algorithm", key.sec_protection.symm_alg, symm_alg_map)) {
1965             goto done;
1966         }
1967     }
1968 
1969     if (pgp_keyid(keyid, key) || !obj_add_hex_json(pkt, "keyid", keyid.data(), keyid.size())) {
1970         goto done;
1971     }
1972 
1973     if (ctx->dump_grips) {
1974         if (pgp_fingerprint(keyfp, key) ||
1975             !obj_add_hex_json(pkt, "fingerprint", keyfp.fingerprint, keyfp.length)) {
1976             goto done;
1977         }
1978 
1979         pgp_key_grip_t grip;
1980         if (!rnp_key_store_get_key_grip(&key.material, grip) ||
1981             !obj_add_hex_json(pkt, "grip", grip.data(), grip.size())) {
1982             goto done;
1983         }
1984     }
1985     ret = RNP_SUCCESS;
1986 done:
1987     return ret;
1988 }
1989 
1990 static rnp_result_t
stream_dump_userid_json(pgp_source_t * src,json_object * pkt)1991 stream_dump_userid_json(pgp_source_t *src, json_object *pkt)
1992 {
1993     pgp_userid_pkt_t uid;
1994     rnp_result_t     ret;
1995 
1996     try {
1997         ret = uid.parse(*src);
1998     } catch (const std::exception &e) {
1999         ret = RNP_ERROR_GENERIC;
2000     }
2001     if (ret) {
2002         return ret;
2003     }
2004 
2005     switch (uid.tag) {
2006     case PGP_PKT_USER_ID:
2007         if (!obj_add_field_json(
2008               pkt, "userid", json_object_new_string_len((char *) uid.uid, uid.uid_len))) {
2009             return RNP_ERROR_OUT_OF_MEMORY;
2010         }
2011         break;
2012     case PGP_PKT_USER_ATTR:
2013         if (!obj_add_hex_json(pkt, "userattr", uid.uid, uid.uid_len)) {
2014             return RNP_ERROR_OUT_OF_MEMORY;
2015         }
2016         break;
2017     default:;
2018     }
2019     return RNP_SUCCESS;
2020 }
2021 
2022 static rnp_result_t
stream_dump_pk_session_key_json(rnp_dump_ctx_t * ctx,pgp_source_t * src,json_object * pkt)2023 stream_dump_pk_session_key_json(rnp_dump_ctx_t *ctx, pgp_source_t *src, json_object *pkt)
2024 {
2025     pgp_pk_sesskey_t         pkey;
2026     pgp_encrypted_material_t pkmaterial;
2027     rnp_result_t             ret;
2028 
2029     try {
2030         ret = pkey.parse(*src);
2031         if (!pkey.parse_material(pkmaterial)) {
2032             ret = RNP_ERROR_BAD_FORMAT;
2033         }
2034     } catch (const std::exception &e) {
2035         ret = RNP_ERROR_GENERIC;
2036     }
2037     if (ret) {
2038         return ret;
2039     }
2040 
2041     if (!obj_add_field_json(pkt, "version", json_object_new_int(pkey.version)) ||
2042         !obj_add_hex_json(pkt, "keyid", pkey.key_id.data(), pkey.key_id.size()) ||
2043         !obj_add_intstr_json(pkt, "algorithm", pkey.alg, pubkey_alg_map)) {
2044         return RNP_ERROR_OUT_OF_MEMORY;
2045     }
2046 
2047     json_object *material = json_object_new_object();
2048     if (!obj_add_field_json(pkt, "material", material)) {
2049         return RNP_ERROR_OUT_OF_MEMORY;
2050     }
2051 
2052     switch (pkey.alg) {
2053     case PGP_PKA_RSA:
2054     case PGP_PKA_RSA_ENCRYPT_ONLY:
2055     case PGP_PKA_RSA_SIGN_ONLY:
2056         if (!obj_add_mpi_json(material, "m", &pkmaterial.rsa.m, ctx->dump_mpi)) {
2057             return RNP_ERROR_OUT_OF_MEMORY;
2058         }
2059         break;
2060     case PGP_PKA_ELGAMAL:
2061     case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
2062         if (!obj_add_mpi_json(material, "g", &pkmaterial.eg.g, ctx->dump_mpi) ||
2063             !obj_add_mpi_json(material, "m", &pkmaterial.eg.m, ctx->dump_mpi)) {
2064             return RNP_ERROR_OUT_OF_MEMORY;
2065         }
2066         break;
2067     case PGP_PKA_SM2:
2068         if (!obj_add_mpi_json(material, "m", &pkmaterial.sm2.m, ctx->dump_mpi)) {
2069             return RNP_ERROR_OUT_OF_MEMORY;
2070         }
2071         break;
2072     case PGP_PKA_ECDH:
2073         if (!obj_add_mpi_json(material, "p", &pkmaterial.ecdh.p, ctx->dump_mpi) ||
2074             !obj_add_field_json(
2075               material, "m.bytes", json_object_new_int(pkmaterial.ecdh.mlen))) {
2076             return RNP_ERROR_OUT_OF_MEMORY;
2077         }
2078         if (ctx->dump_mpi &&
2079             !obj_add_hex_json(material, "m", pkmaterial.ecdh.m, pkmaterial.ecdh.mlen)) {
2080             return RNP_ERROR_OUT_OF_MEMORY;
2081         }
2082         break;
2083     default:;
2084     }
2085 
2086     return RNP_SUCCESS;
2087 }
2088 
2089 static rnp_result_t
stream_dump_sk_session_key_json(pgp_source_t * src,json_object * pkt)2090 stream_dump_sk_session_key_json(pgp_source_t *src, json_object *pkt)
2091 {
2092     pgp_sk_sesskey_t skey;
2093     rnp_result_t     ret;
2094 
2095     try {
2096         ret = skey.parse(*src);
2097     } catch (const std::exception &e) {
2098         ret = RNP_ERROR_GENERIC;
2099     }
2100     if (ret) {
2101         return ret;
2102     }
2103 
2104     if (!obj_add_field_json(pkt, "version", json_object_new_int(skey.version)) ||
2105         !obj_add_intstr_json(pkt, "algorithm", skey.alg, symm_alg_map)) {
2106         return RNP_ERROR_OUT_OF_MEMORY;
2107     }
2108     if ((skey.version == PGP_SKSK_V5) &&
2109         !obj_add_intstr_json(pkt, "aead algorithm", skey.aalg, aead_alg_map)) {
2110         return RNP_ERROR_OUT_OF_MEMORY;
2111     }
2112     if (!obj_add_s2k_json(pkt, &skey.s2k)) {
2113         return RNP_ERROR_OUT_OF_MEMORY;
2114     }
2115     if ((skey.version == PGP_SKSK_V5) &&
2116         !obj_add_hex_json(pkt, "aead iv", skey.iv, skey.ivlen)) {
2117         return RNP_ERROR_OUT_OF_MEMORY;
2118     }
2119     if (!obj_add_hex_json(pkt, "encrypted key", skey.enckey, skey.enckeylen)) {
2120         return RNP_ERROR_OUT_OF_MEMORY;
2121     }
2122     return RNP_SUCCESS;
2123 }
2124 
2125 static rnp_result_t
stream_dump_encrypted_json(pgp_source_t * src,json_object * pkt,pgp_pkt_type_t tag)2126 stream_dump_encrypted_json(pgp_source_t *src, json_object *pkt, pgp_pkt_type_t tag)
2127 {
2128     if (tag != PGP_PKT_AEAD_ENCRYPTED) {
2129         /* packet header with tag is already in pkt */
2130         return stream_skip_packet(src);
2131     }
2132 
2133     /* dumping AEAD data */
2134     pgp_aead_hdr_t aead = {};
2135     if (!stream_dump_get_aead_hdr(src, &aead)) {
2136         return RNP_ERROR_READ;
2137     }
2138 
2139     if (!obj_add_field_json(pkt, "version", json_object_new_int(aead.version)) ||
2140         !obj_add_intstr_json(pkt, "algorithm", aead.ealg, symm_alg_map) ||
2141         !obj_add_intstr_json(pkt, "aead algorithm", aead.aalg, aead_alg_map) ||
2142         !obj_add_field_json(pkt, "chunk size", json_object_new_int(aead.csize)) ||
2143         !obj_add_hex_json(pkt, "aead iv", aead.iv, aead.ivlen)) {
2144         return RNP_ERROR_OUT_OF_MEMORY;
2145     }
2146 
2147     return RNP_SUCCESS;
2148 }
2149 
2150 static rnp_result_t
stream_dump_one_pass_json(pgp_source_t * src,json_object * pkt)2151 stream_dump_one_pass_json(pgp_source_t *src, json_object *pkt)
2152 {
2153     pgp_one_pass_sig_t onepass;
2154     rnp_result_t       ret;
2155 
2156     try {
2157         ret = onepass.parse(*src);
2158     } catch (const std::exception &e) {
2159         ret = RNP_ERROR_GENERIC;
2160     }
2161     if (ret) {
2162         return ret;
2163     }
2164 
2165     if (!obj_add_field_json(pkt, "version", json_object_new_int(onepass.version))) {
2166         return RNP_ERROR_OUT_OF_MEMORY;
2167     }
2168     if (!obj_add_intstr_json(pkt, "type", onepass.type, sig_type_map)) {
2169         return RNP_ERROR_OUT_OF_MEMORY;
2170     }
2171     if (!obj_add_intstr_json(pkt, "hash algorithm", onepass.halg, hash_alg_map)) {
2172         return RNP_ERROR_OUT_OF_MEMORY;
2173     }
2174     if (!obj_add_intstr_json(pkt, "public key algorithm", onepass.palg, pubkey_alg_map)) {
2175         return RNP_ERROR_OUT_OF_MEMORY;
2176     }
2177     if (!obj_add_hex_json(pkt, "signer", onepass.keyid.data(), onepass.keyid.size())) {
2178         return RNP_ERROR_OUT_OF_MEMORY;
2179     }
2180     if (!obj_add_field_json(pkt, "nested", json_object_new_boolean(onepass.nested))) {
2181         return RNP_ERROR_OUT_OF_MEMORY;
2182     }
2183     return RNP_SUCCESS;
2184 }
2185 
2186 static rnp_result_t
stream_dump_marker_json(pgp_source_t & src,json_object * pkt)2187 stream_dump_marker_json(pgp_source_t &src, json_object *pkt)
2188 {
2189     rnp_result_t ret = stream_parse_marker(src);
2190 
2191     if (!obj_add_field_json(
2192           pkt, "contents", json_object_new_string(ret ? "invalid" : PGP_MARKER_CONTENTS))) {
2193         return RNP_ERROR_OUT_OF_MEMORY;
2194     }
2195     return RNP_SUCCESS;
2196 }
2197 
2198 static rnp_result_t stream_dump_raw_packets_json(rnp_dump_ctx_t *ctx,
2199                                                  pgp_source_t *  src,
2200                                                  json_object **  jso);
2201 
2202 static rnp_result_t
stream_dump_compressed_json(rnp_dump_ctx_t * ctx,pgp_source_t * src,json_object * pkt)2203 stream_dump_compressed_json(rnp_dump_ctx_t *ctx, pgp_source_t *src, json_object *pkt)
2204 {
2205     pgp_source_t zsrc = {0};
2206     uint8_t      zalg;
2207     rnp_result_t ret;
2208     json_object *contents = NULL;
2209 
2210     if ((ret = init_compressed_src(&zsrc, src))) {
2211         return ret;
2212     }
2213 
2214     get_compressed_src_alg(&zsrc, &zalg);
2215     if (!obj_add_intstr_json(pkt, "algorithm", zalg, z_alg_map)) {
2216         ret = RNP_ERROR_OUT_OF_MEMORY;
2217         goto done;
2218     }
2219 
2220     ret = stream_dump_raw_packets_json(ctx, &zsrc, &contents);
2221     if (!ret && !obj_add_field_json(pkt, "contents", contents)) {
2222         json_object_put(contents);
2223         ret = RNP_ERROR_OUT_OF_MEMORY;
2224     }
2225 done:
2226     src_close(&zsrc);
2227     return ret;
2228 }
2229 
2230 static rnp_result_t
stream_dump_literal_json(pgp_source_t * src,json_object * pkt)2231 stream_dump_literal_json(pgp_source_t *src, json_object *pkt)
2232 {
2233     pgp_source_t      lsrc = {0};
2234     pgp_literal_hdr_t lhdr = {0};
2235     rnp_result_t      ret;
2236     uint8_t           readbuf[16384];
2237 
2238     if ((ret = init_literal_src(&lsrc, src))) {
2239         return ret;
2240     }
2241     ret = RNP_ERROR_OUT_OF_MEMORY;
2242     get_literal_src_hdr(&lsrc, &lhdr);
2243     if (!obj_add_field_json(
2244           pkt, "format", json_object_new_string_len((char *) &lhdr.format, 1))) {
2245         goto done;
2246     }
2247     if (!obj_add_field_json(
2248           pkt, "filename", json_object_new_string_len(lhdr.fname, lhdr.fname_len))) {
2249         goto done;
2250     }
2251     if (!obj_add_field_json(pkt, "timestamp", json_object_new_int64(lhdr.timestamp))) {
2252         goto done;
2253     }
2254 
2255     while (!src_eof(&lsrc)) {
2256         size_t read = 0;
2257         if (!src_read(&lsrc, readbuf, sizeof(readbuf), &read)) {
2258             ret = RNP_ERROR_READ;
2259             goto done;
2260         }
2261     }
2262 
2263     if (!obj_add_field_json(pkt, "datalen", json_object_new_int64(lsrc.readb))) {
2264         goto done;
2265     }
2266     ret = RNP_SUCCESS;
2267 done:
2268     src_close(&lsrc);
2269     return ret;
2270 }
2271 
2272 static bool
stream_dump_hdr_json(pgp_source_t * src,pgp_packet_hdr_t * hdr,json_object * pkt)2273 stream_dump_hdr_json(pgp_source_t *src, pgp_packet_hdr_t *hdr, json_object *pkt)
2274 {
2275     rnp_result_t hdrret = stream_peek_packet_hdr(src, hdr);
2276     if (hdrret) {
2277         return false;
2278     }
2279 
2280     json_object *jso_hdr = json_object_new_object();
2281     if (!jso_hdr) {
2282         return false;
2283     }
2284 
2285     if (!obj_add_field_json(jso_hdr, "offset", json_object_new_int64(src->readb))) {
2286         goto error;
2287     }
2288     if (!obj_add_intstr_json(jso_hdr, "tag", hdr->tag, packet_tag_map)) {
2289         goto error;
2290     }
2291     if (!obj_add_hex_json(jso_hdr, "raw", hdr->hdr, hdr->hdr_len)) {
2292         goto error;
2293     }
2294     if (!hdr->partial && !hdr->indeterminate &&
2295         !obj_add_field_json(jso_hdr, "length", json_object_new_int64(hdr->pkt_len))) {
2296         goto error;
2297     }
2298     if (!obj_add_field_json(jso_hdr, "partial", json_object_new_boolean(hdr->partial))) {
2299         goto error;
2300     }
2301     if (!obj_add_field_json(
2302           jso_hdr, "indeterminate", json_object_new_boolean(hdr->indeterminate))) {
2303         goto error;
2304     }
2305     return obj_add_field_json(pkt, "header", jso_hdr);
2306 error:
2307     json_object_put(jso_hdr);
2308     return false;
2309 }
2310 
2311 static rnp_result_t
stream_dump_raw_packets_json(rnp_dump_ctx_t * ctx,pgp_source_t * src,json_object ** jso)2312 stream_dump_raw_packets_json(rnp_dump_ctx_t *ctx, pgp_source_t *src, json_object **jso)
2313 {
2314     json_object *pkts = NULL;
2315     json_object *pkt = NULL;
2316     rnp_result_t ret = RNP_ERROR_GENERIC;
2317 
2318     pkts = json_object_new_array();
2319     if (!pkts) {
2320         return RNP_ERROR_OUT_OF_MEMORY;
2321     }
2322 
2323     if (src_eof(src)) {
2324         ret = RNP_SUCCESS;
2325         goto done;
2326     }
2327 
2328     /* do not allow endless recursion */
2329     if (++ctx->layers > MAXIMUM_NESTING_LEVEL) {
2330         RNP_LOG("Too many OpenPGP nested layers during the dump.");
2331         ret = RNP_SUCCESS;
2332         goto done;
2333     }
2334 
2335     while (!src_eof(src)) {
2336         pgp_packet_hdr_t hdr = {};
2337 
2338         pkt = json_object_new_object();
2339         if (!pkt) {
2340             ret = RNP_ERROR_OUT_OF_MEMORY;
2341             goto done;
2342         }
2343 
2344         if (!stream_dump_hdr_json(src, &hdr, pkt)) {
2345             ret = RNP_ERROR_OUT_OF_MEMORY;
2346             goto done;
2347         }
2348 
2349         if (ctx->dump_packets) {
2350             size_t  rlen = hdr.pkt_len + hdr.hdr_len;
2351             uint8_t buf[2048 + sizeof(hdr.hdr)] = {0};
2352 
2353             if (!hdr.pkt_len || (rlen > 2048 + hdr.hdr_len)) {
2354                 rlen = 2048 + hdr.hdr_len;
2355             }
2356             if (!src_peek(src, buf, rlen, &rlen) || (rlen < hdr.hdr_len)) {
2357                 ret = RNP_ERROR_READ;
2358                 goto done;
2359             }
2360             if (!obj_add_hex_json(pkt, "raw", buf + hdr.hdr_len, rlen - hdr.hdr_len)) {
2361                 ret = RNP_ERROR_OUT_OF_MEMORY;
2362                 goto done;
2363             }
2364         }
2365 
2366         switch (hdr.tag) {
2367         case PGP_PKT_SIGNATURE:
2368             ret = stream_dump_signature_json(ctx, src, pkt);
2369             break;
2370         case PGP_PKT_SECRET_KEY:
2371         case PGP_PKT_PUBLIC_KEY:
2372         case PGP_PKT_SECRET_SUBKEY:
2373         case PGP_PKT_PUBLIC_SUBKEY:
2374             ret = stream_dump_key_json(ctx, src, pkt);
2375             break;
2376         case PGP_PKT_USER_ID:
2377         case PGP_PKT_USER_ATTR:
2378             ret = stream_dump_userid_json(src, pkt);
2379             break;
2380         case PGP_PKT_PK_SESSION_KEY:
2381             ret = stream_dump_pk_session_key_json(ctx, src, pkt);
2382             break;
2383         case PGP_PKT_SK_SESSION_KEY:
2384             ret = stream_dump_sk_session_key_json(src, pkt);
2385             break;
2386         case PGP_PKT_SE_DATA:
2387         case PGP_PKT_SE_IP_DATA:
2388         case PGP_PKT_AEAD_ENCRYPTED:
2389             ret = stream_dump_encrypted_json(src, pkt, hdr.tag);
2390             break;
2391         case PGP_PKT_ONE_PASS_SIG:
2392             ret = stream_dump_one_pass_json(src, pkt);
2393             break;
2394         case PGP_PKT_COMPRESSED:
2395             ret = stream_dump_compressed_json(ctx, src, pkt);
2396             break;
2397         case PGP_PKT_LITDATA:
2398             ret = stream_dump_literal_json(src, pkt);
2399             break;
2400         case PGP_PKT_MARKER:
2401             ret = stream_dump_marker_json(*src, pkt);
2402             break;
2403         case PGP_PKT_TRUST:
2404         case PGP_PKT_MDC:
2405             ret = stream_skip_packet(src);
2406             break;
2407         default:
2408             ret = stream_skip_packet(src);
2409         }
2410 
2411         if (ret) {
2412             RNP_LOG("failed to process packet");
2413             goto done;
2414         }
2415 
2416         if (json_object_array_add(pkts, pkt)) {
2417             ret = RNP_ERROR_OUT_OF_MEMORY;
2418             goto done;
2419         }
2420         pkt = NULL;
2421     }
2422 done:
2423     if (ret) {
2424         json_object_put(pkts);
2425         json_object_put(pkt);
2426         pkts = NULL;
2427     }
2428     *jso = pkts;
2429     return ret;
2430 }
2431 
2432 rnp_result_t
stream_dump_packets_json(rnp_dump_ctx_t * ctx,pgp_source_t * src,json_object ** jso)2433 stream_dump_packets_json(rnp_dump_ctx_t *ctx, pgp_source_t *src, json_object **jso)
2434 {
2435     pgp_source_t armorsrc = {0};
2436     bool         armored = false;
2437     rnp_result_t ret = RNP_ERROR_GENERIC;
2438 
2439     ctx->layers = 0;
2440     /* check whether source is cleartext - then skip till the signature */
2441     if (is_cleartext_source(src)) {
2442         if (!stream_skip_cleartext(src)) {
2443             RNP_LOG("malformed cleartext signed data");
2444             ret = RNP_ERROR_BAD_FORMAT;
2445             goto finish;
2446         }
2447     }
2448     /* check whether source is armored */
2449     if (is_armored_source(src)) {
2450         if ((ret = init_armored_src(&armorsrc, src))) {
2451             RNP_LOG("failed to parse armored data");
2452             goto finish;
2453         }
2454         armored = true;
2455         src = &armorsrc;
2456     }
2457 
2458     if (src_eof(src)) {
2459         ret = RNP_ERROR_NOT_ENOUGH_DATA;
2460         goto finish;
2461     }
2462 
2463     ret = stream_dump_raw_packets_json(ctx, src, jso);
2464 finish:
2465     if (armored) {
2466         src_close(&armorsrc);
2467     }
2468     return ret;
2469 }
2470