From: Job Snijders Subject: Re: rpki-client: fix printing of ccr hashes in filemode To: Theo Buehler Cc: tech@openbsd.org Date: Tue, 30 Dec 2025 08:36:11 +0000 On Tue, Dec 30, 2025 at 05:30:27AM +0100, Theo Buehler wrote: > On Mon, Dec 29, 2025 at 11:16:18PM +0000, Job Snijders wrote: > > Filemode should print CCR hashes in the same way main(), outputheader(), > > and outputheader_json() do. Use a small helper function to improve > > readability. With this diff hash strings are aligned as follows: > > I think the cleaner approach is changing validate_asn1_hash() to > use base64_encode_asn1_string() instead of hex_encode_asn1_string(). > Then the printing function can just dump the members directly without > reencoding. Ah yes, good suggestion. Index: ccr.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/ccr.c,v diff -u -p -r1.31 ccr.c --- ccr.c 5 Dec 2025 07:26:42 -0000 1.31 +++ ccr.c 30 Dec 2025 08:35:15 -0000 @@ -237,7 +237,7 @@ validate_asn1_hash(const char *fn, const const ASN1_OCTET_STRING *hash, const ASN1_ITEM *it, void *val) { ASN1_OCTET_STRING *astr = NULL; - char *hex = NULL; + char *b64 = NULL; if ((astr = ASN1_OCTET_STRING_new()) == NULL) errx(1, "ASN1_OCTET_STRING_new"); @@ -249,10 +249,12 @@ validate_asn1_hash(const char *fn, const goto out; } - hex = hex_encode_asn1_string(hash); + if (!base64_encode_asn1_string(astr, &b64)) + errx(1, "base64_encode_asn1_string"); + out: ASN1_OCTET_STRING_free(astr); - return hex; + return b64; } static void Index: print.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/print.c,v diff -u -p -r1.71 print.c --- print.c 13 Nov 2025 15:18:53 -0000 1.71 +++ print.c 30 Dec 2025 08:35:15 -0000 @@ -861,21 +861,17 @@ print_ccr_mftstate(struct ccr *ccr) struct ccr_mft *ccr_mft; struct ccr_mft_sub_ski *sub; - if (base64_encode(ccr->mfts_hash, SHA256_DIGEST_LENGTH, &hash) == -1) - errx(1, "base64_encode"); - if (outformats & FORMAT_JSON) { json_do_object("manifest_state", 0); json_do_int("most_recent_update", ccr->most_recent_update); - json_do_string("hash", hash); + json_do_string("hash", ccr->mfts_hash); json_do_array("mft_instances"); } else { - printf("Manifest state hash: %s\n", hash); + printf("Manifest state hash: %s\n", ccr->mfts_hash); printf("Manifest last update: %s\n", time2str(ccr->most_recent_update)); printf("Manifest instances:\n"); } - free(hash); RB_FOREACH(ccr_mft, ccr_mft_tree, &ccr->mfts) { if (base64_encode(ccr_mft->hash, SHA256_DIGEST_LENGTH, &hash) @@ -939,21 +935,17 @@ print_ccr_mftstate(struct ccr *ccr) static void print_ccr_roastate(struct ccr *ccr) { - char buf[64], *hash; + char buf[64]; struct vrp *vrp; - if (base64_encode(ccr->vrps_hash, SHA256_DIGEST_LENGTH, &hash) == -1) - errx(1, "base64_encode"); - if (outformats & FORMAT_JSON) { json_do_object("roapayload_state", 0); - json_do_string("hash", hash); + json_do_string("hash", ccr->vrps_hash); json_do_array("vrps"); } else { - printf("ROA payload state hash: %s\n", hash); + printf("ROA payload state hash: %s\n", ccr->vrps_hash); printf("ROA payload entries:\n"); } - free(hash); RB_FOREACH(vrp, ccr_vrp_tree, &ccr->vrps) { ip_addr_print(&vrp->addr, vrp->afi, buf, sizeof(buf)); @@ -982,22 +974,17 @@ print_ccr_roastate(struct ccr *ccr) static void print_ccr_aspastate(struct ccr *ccr) { - char *hash; struct vap *vap; size_t i; - if (base64_encode(ccr->vaps_hash, SHA256_DIGEST_LENGTH, &hash) == -1) - errx(1, "base64_encode"); - if (outformats & FORMAT_JSON) { json_do_object("aspapayload_state", 0); - json_do_string("hash", hash); + json_do_string("hash", ccr->vaps_hash); json_do_array("vaps"); } else { - printf("ASPA payload state hash: %s\n", hash); + printf("ASPA payload state hash: %s\n", ccr->vaps_hash); printf("ASPA payload entries:\n"); } - free(hash); RB_FOREACH(vap, vap_tree, &ccr->vaps) { if (outformats & FORMAT_JSON) { @@ -1034,24 +1021,19 @@ print_ccr_aspastate(struct ccr *ccr) static void print_ccr_tastate(struct ccr *ccr) { - char *hash, *ski; + char *ski; struct ccr_tas_ski *cts; int i = 0; - if (base64_encode(ccr->tas_hash, SHA256_DIGEST_LENGTH, &hash) == -1) - errx(1, "base64_encode"); - if (outformats & FORMAT_JSON) { json_do_object("trustanchor_state", 0); - json_do_string("hash", hash); + json_do_string("hash", ccr->tas_hash); json_do_array("skis"); } else { - printf("Trust anchor state hash: %s\n", hash); + printf("Trust anchor state hash: %s\n", ccr->tas_hash); printf("Trust anchor keyids: "); } - free(hash); - RB_FOREACH(cts, ccr_tas_tree, &ccr->tas) { ski = hex_encode(cts->keyid, sizeof(cts->keyid)); @@ -1077,15 +1059,11 @@ print_ccr_tastate(struct ccr *ccr) static void print_ccr_rkstate(struct ccr *ccr) { - char *hash; struct brk *brk; - if (base64_encode(ccr->brks_hash, SHA256_DIGEST_LENGTH, &hash) == -1) - errx(1, "base64_encode"); - if (outformats & FORMAT_JSON) { json_do_object("routerkey_state", 0); - json_do_string("hash", hash); + json_do_string("hash", ccr->brks_hash); json_do_array("routerkeys"); RB_FOREACH(brk, brk_tree, &ccr->brks) { json_do_object("brk", 0); @@ -1097,7 +1075,7 @@ print_ccr_rkstate(struct ccr *ccr) json_do_end(); /* routerkeys */ json_do_end(); /* routerkey_state */ } else { - printf("Router key state hash: %s\n", hash); + printf("Router key state hash: %s\n", ccr->brks_hash); printf("Router keys:\n"); RB_FOREACH(brk, brk_tree, &ccr->brks) { printf("%26s", ""); @@ -1106,8 +1084,6 @@ print_ccr_rkstate(struct ccr *ccr) printf("pubkey:%s\n", brk->pubkey); } } - - free(hash); } void