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