Download raw body.
rpki-client: last but not least... convert ccr
This converts most of ccr.c to opaque ASN1_STRING
There already is a base64 encoding helper. Hoist that to the top, rename
it and add hex and copy helpers to remove quite a bit of duplication.
While the copy helper could be used in a couple of places outside of ccr,
the precise length check isn't ideal for an extern.h API but required
here.
The rest is straightforward. It leaves a write to abs->flags in ccr.c which
will need another new API: https://github.com/openssl/openssl/issues/29185
Index: ccr.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/ccr.c,v
diff -u -p -r1.29 ccr.c
--- ccr.c 3 Dec 2025 10:21:53 -0000 1.29
+++ ccr.c 3 Dec 2025 10:45:02 -0000
@@ -190,6 +190,35 @@ ASN1_SEQUENCE(RouterKey) = {
IMPLEMENT_ASN1_FUNCTIONS(RouterKey);
+static char *
+hex_encode_asn1_string(const ASN1_STRING *str)
+{
+ return hex_encode(ASN1_STRING_get0_data(str), ASN1_STRING_length(str));
+}
+
+static int
+base64_encode_asn1_string(const ASN1_OCTET_STRING *astr, char **out)
+{
+ const unsigned char *data = ASN1_STRING_get0_data(astr);
+ int length = ASN1_STRING_length(astr);
+
+ return base64_encode(data, length, out) == 0;
+}
+
+static int
+copy_asn1_string(const ASN1_STRING *astr, unsigned char *buf, size_t len)
+{
+ const unsigned char *data = ASN1_STRING_get0_data(astr);
+ int length = ASN1_STRING_length(astr);
+
+ if (length < 0 || (size_t)length != len)
+ return 0;
+
+ memcpy(buf, data, length);
+
+ return 1;
+}
+
static void
hash_asn1_item(ASN1_OCTET_STRING *astr, const ASN1_ITEM *it, void *val)
{
@@ -219,7 +248,7 @@ validate_asn1_hash(const char *fn, const
goto out;
}
- hex = hex_encode(hash->data, hash->length);
+ hex = hex_encode_asn1_string(hash);
out:
ASN1_OCTET_STRING_free(astr);
return hex;
@@ -316,12 +345,6 @@ append_cached_manifest(STACK_OF(Manifest
errx(1, "sk_ManifestInstance_push");
}
-static int
-base64_encode_asn1str(const ASN1_OCTET_STRING *astr, char **out)
-{
- return base64_encode(astr->data, astr->length, out) == 0;
-}
-
static ManifestState *
generate_manifeststate(struct validation_data *vd)
{
@@ -346,8 +369,8 @@ generate_manifeststate(struct validation
hash_asn1_item(ms->hash, ASN1_ITEM_rptr(ManifestInstances), ms->mis);
- if (!base64_encode_asn1str(ms->hash, &ccr->mfts_hash))
- errx(1, "base64_encode_asn1str");
+ if (!base64_encode_asn1_string(ms->hash, &ccr->mfts_hash))
+ errx(1, "base64_encode_asn1_string");
return ms;
}
@@ -440,8 +463,8 @@ generate_roapayloadstate(struct validati
hash_asn1_item(vrps->hash, ASN1_ITEM_rptr(ROAPayloadSets), vrps->rps);
- if (!base64_encode_asn1str(vrps->hash, &ccr->vrps_hash))
- errx(1, "base64_encode_asn1str");
+ if (!base64_encode_asn1_string(vrps->hash, &ccr->vrps_hash))
+ errx(1, "base64_encode_asn1_string");
return vrps;
}
@@ -491,8 +514,8 @@ generate_aspapayloadstate(struct validat
hash_asn1_item(vaps->hash, ASN1_ITEM_rptr(ASPAPayloadSets), vaps->aps);
- if (!base64_encode_asn1str(vaps->hash, &ccr->vaps_hash))
- errx(1, "base64_encode_asn1str");
+ if (!base64_encode_asn1_string(vaps->hash, &ccr->vaps_hash))
+ errx(1, "base64_encode_asn1_string");
return vaps;
}
@@ -528,8 +551,8 @@ generate_trustanchorstate(struct validat
hash_asn1_item(tas->hash, ASN1_ITEM_rptr(SubjectKeyIdentifiers),
tas->skis);
- if (!base64_encode_asn1str(tas->hash, &vd->ccr.tas_hash))
- errx(1, "base64_encode_asn1str");
+ if (!base64_encode_asn1_string(tas->hash, &vd->ccr.tas_hash))
+ errx(1, "base64_encode_asn1_string");
return tas;
}
@@ -593,8 +616,8 @@ generate_routerkeystate(struct validatio
hash_asn1_item(rks->hash, ASN1_ITEM_rptr(RouterKeySets), rks->rksets);
- if (!base64_encode_asn1str(rks->hash, &vd->ccr.brks_hash))
- errx(1, "base64_encode_asn1str");
+ if (!base64_encode_asn1_string(rks->hash, &vd->ccr.brks_hash))
+ errx(1, "base64_encode_asn1_string");
return rks;
}
@@ -981,11 +1004,11 @@ parse_mft_instances(const char *fn, stru
mi = sk_ManifestInstance_value(mis, i);
- if (mi->hash->length != sizeof(ccr_mft->hash)) {
+ if (!copy_asn1_string(mi->hash,
+ ccr_mft->hash, sizeof(ccr_mft->hash))) {
warnx("%s: manifest instance #%d corrupted", fn, i);
goto out;
}
- memcpy(ccr_mft->hash, mi->hash->data, mi->hash->length);
if (prev != NULL) {
if (ccr_mft_cmp(ccr_mft, prev) <= 0) {
@@ -994,11 +1017,11 @@ parse_mft_instances(const char *fn, stru
}
}
- if (mi->aki->length != sizeof(ccr_mft->aki)) {
+ if (!copy_asn1_string(mi->aki,
+ ccr_mft->aki, sizeof(ccr_mft->aki))) {
warnx("%s: manifest instance #%d corrupted", fn, i);
goto out;
}
- memcpy(ccr_mft->aki, mi->aki->data, mi->aki->length);
if (!ASN1_INTEGER_get_uint64(&size, mi->size)) {
warnx("%s: manifest instance #%d corrupted", fn, i);
@@ -1039,12 +1062,11 @@ parse_mft_instances(const char *fn, stru
err(1, NULL);
s = sk_SubjectKeyIdentifier_value(mi->subordinates, j);
- if (s->length != sizeof(sub->ski)) {
+ if (!copy_asn1_string(s, sub->ski, sizeof(sub->ski))) {
warnx("%s: manifest instance #%d corrupted",
- fn, j);
+ fn, i);
goto out;
}
- memcpy(sub->ski, s->data, sizeof(sub->ski));
SLIST_INSERT_HEAD(&ccr_mft->subordinates, sub, entry);
sub = NULL;
}
@@ -1391,13 +1413,11 @@ parse_tas_skis(const char *fn, struct cc
ski = sk_SubjectKeyIdentifier_value(skis, i);
- if (ski->length != sizeof(cts->keyid)) {
+ if (!copy_asn1_string(ski, cts->keyid, sizeof(cts->keyid))) {
warnx("%s: TAS SKI #%d corrupted", fn, i);
goto out;
}
- memcpy(cts->keyid, ski->data, ski->length);
-
if (prev != NULL) {
if (ccr_tas_ski_cmp(cts, prev) <= 0) {
warnx("%s: misordered TrustAnchorState", fn);
@@ -1463,12 +1483,12 @@ parse_routerkeys(const char *fn, struct
rk = sk_RouterKey_value(routerkeys, i);
- if (rk->ski->length != SHA_DIGEST_LENGTH) {
+ if (ASN1_STRING_length(rk->ski) != SHA_DIGEST_LENGTH) {
warnx("%s: AS%d RouterKey SKI corrupted", fn, asid);
goto out;
}
- brk->ski = hex_encode(rk->ski->data, rk->ski->length);
+ brk->ski = hex_encode_asn1_string(rk->ski);
der = NULL;
if ((der_len = i2d_X509_PUBKEY(rk->spki, &der)) <= 0) {
rpki-client: last but not least... convert ccr