bin_PROGRAMS = rpki_validator
rpki_validator_SOURCES = main.c
+
rpki_validator_SOURCES += common.h
-rpki_validator_SOURCES += content_info.h content_info.c
rpki_validator_SOURCES += file.h file.c
-rpki_validator_SOURCES += oid.h oid.c
-rpki_validator_SOURCES += signed_data.h signed_data.c
+rpki_validator_SOURCES += asn1/content_info.h asn1/content_info.c
+rpki_validator_SOURCES += asn1/decode.h asn1/decode.c
+rpki_validator_SOURCES += asn1/oid.h asn1/oid.c
+rpki_validator_SOURCES += asn1/roa.h asn1/roa.c
+rpki_validator_SOURCES += asn1/signed_data.h asn1/signed_data.c
rpki_validator_CFLAGS = -pedantic -Wall -std=gnu11 -O0 -g ${OPENSSL_CFLAGS}
rpki_validator_LDADD = ${OPENSSL_LIBS}
--- /dev/null
+#include "content_info.h"
+
+#include <err.h>
+#include <errno.h>
+#include <libcmscodec/ContentType.h>
+#include "file.h"
+#include "oid.h"
+#include "asn1/decode.h"
+
+static int
+validate(struct ContentInfo *info)
+{
+ struct oid_arcs arcs;
+ int error;
+
+ /* rfc6488#section-2 */
+ /* rfc6488#section-3.1.a */
+ error = oid2arcs(&info->contentType, &arcs);
+ if (error)
+ return error;
+
+ if (!ARCS_EQUAL_OIDS(&arcs, SIGNED_DATA_OID)) {
+ fprintf(stderr, "Incorrect content-type.");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+decode(struct file_contents *fc, struct ContentInfo **result)
+{
+ struct ContentInfo *cinfo;
+ int error;
+
+ error = asn1_decode_fc(fc, &asn_DEF_ContentInfo, (void **) &cinfo);
+ if (error)
+ return error;
+
+ error = validate(cinfo);
+ if (error) {
+ content_info_free(cinfo);
+ return error;
+ }
+
+ *result = cinfo;
+ return 0;
+}
+
+int
+content_info_load(const char *file_name, struct ContentInfo **result)
+{
+ struct file_contents fc;
+ int error;
+
+ error = file_load(file_name, &fc);
+ if (error)
+ return error;
+
+ error = decode(&fc, result);
+
+ file_free(&fc);
+ return error;
+}
+
+void
+content_info_free(struct ContentInfo *info)
+{
+ ASN_STRUCT_FREE(asn_DEF_ContentInfo, info);
+}
--- /dev/null
+#include "decode.h"
+
+#include <err.h>
+#include <errno.h>
+#include "common.h"
+
+static int
+validate(asn_TYPE_descriptor_t *descriptor, void *result)
+{
+ char error_msg[256];
+ size_t error_msg_size;
+ int error;
+
+ /* The lib's inbuilt validations. (Probably not much.) */
+ error_msg_size = sizeof(error_msg);
+ error = asn_check_constraints(descriptor, result, error_msg,
+ &error_msg_size);
+ if (error == -1) {
+ warnx("Error validating ASN.1 object: %s", error_msg);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int
+asn1_decode(const void *buffer, size_t buffer_size,
+ asn_TYPE_descriptor_t *descriptor, void **result)
+{
+ asn_dec_rval_t rval;
+ int error;
+
+ *result = NULL;
+
+ rval = ber_decode(0, descriptor, result, buffer, buffer_size);
+ if (rval.code != RC_OK) {
+ warnx("Error decoding ASN.1 object: %d", rval.code);
+ /* Must free partial object according to API contracts. */
+ ASN_STRUCT_FREE(*descriptor, *result);
+ return -EINVAL;
+ }
+
+ error = validate(descriptor, *result);
+ if (error) {
+ ASN_STRUCT_FREE(*descriptor, *result);
+ return error;
+ }
+
+ return 0;
+}
+
+int
+asn1_decode_any(ANY_t *any, asn_TYPE_descriptor_t *descriptor, void **result)
+{
+ return asn1_decode(any->buf, any->size, descriptor, result);
+}
+
+int
+asn1_decode_octet_string(OCTET_STRING_t *string,
+ asn_TYPE_descriptor_t *descriptor, void **result)
+{
+ return asn1_decode(string->buf, string->size, descriptor, result);
+}
+
+int
+asn1_decode_fc(struct file_contents *fc, asn_TYPE_descriptor_t *descriptor,
+ void **result)
+{
+ return asn1_decode(fc->buffer, fc->buffer_size, descriptor, result);
+}
--- /dev/null
+#ifndef SRC_ASN1_DECODE_H_
+#define SRC_ASN1_DECODE_H_
+
+#include <libcmscodec/ANY.h>
+#include <libcmscodec/constr_TYPE.h>
+#include "file.h"
+
+/* TODO use this more. */
+int asn1_decode(const void *, size_t, asn_TYPE_descriptor_t *, void **);
+int asn1_decode_any(ANY_t *, asn_TYPE_descriptor_t *, void **);
+int asn1_decode_octet_string(OCTET_STRING_t *, asn_TYPE_descriptor_t *, void **);
+int asn1_decode_fc(struct file_contents *, asn_TYPE_descriptor_t *, void **);
+
+#endif /* SRC_ASN1_DECODE_H_ */
--- /dev/null
+#include "oid.h"
+
+#include <errno.h>
+#include "common.h"
+#include "asn1/decode.h"
+
+#define MAX_ARCS 9
+
+void
+free_arcs(struct oid_arcs *arcs)
+{
+ free(arcs->arcs);
+}
+
+/*
+ * Wrapper for OBJECT_IDENTIFIER_get_arcs().
+ *
+ * Callers must free @result.
+ */
+int
+oid2arcs(OBJECT_IDENTIFIER_t *oid, struct oid_arcs *result)
+{
+ ssize_t count, count2;
+
+ result->arcs = malloc(MAX_ARCS * sizeof(asn_oid_arc_t));
+ if (result->arcs == NULL)
+ return -ENOMEM;
+
+ count = OBJECT_IDENTIFIER_get_arcs(oid, result->arcs, MAX_ARCS);
+ if (count < 0) {
+ free(result->arcs);
+ return count;
+ }
+
+ result->count = count;
+
+ /* If necessary, reallocate arcs array and try again. */
+ if (count > MAX_ARCS) {
+ result->arcs = realloc(result->arcs, count * sizeof(asn_oid_arc_t));
+ if (!result->arcs)
+ return -ENOMEM;
+ count2 = OBJECT_IDENTIFIER_get_arcs(oid, result->arcs, count);
+ if (count != count2) {
+ free(result->arcs);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+/* Callers must free @result. */
+int
+any2arcs(ANY_t *any, struct oid_arcs *result)
+{
+ OBJECT_IDENTIFIER_t *oid;
+ int error;
+
+ error = asn1_decode_any(any, &asn_DEF_OBJECT_IDENTIFIER,
+ (void **) &oid);
+ if (error)
+ return error;
+
+ error = oid2arcs(oid, result);
+ ASN_STRUCT_FREE(asn_DEF_OBJECT_IDENTIFIER, oid);
+ return error;
+}
+
+static bool __arcs_equal(asn_oid_arc_t const *a, size_t a_count,
+ asn_oid_arc_t const *b, size_t b_count)
+{
+ long int i;
+
+ if (a_count != b_count)
+ return false;
+
+ /* Most OIDs start with the same numbers, so iterate backwards. */
+ for (i = a_count - 1; i >= 0; i--) {
+ if (a[i] != b[i])
+ return false;
+ }
+
+ return true;
+}
+
+bool arcs_equal(struct oid_arcs *a, struct oid_arcs *b)
+{
+ return __arcs_equal(a->arcs, a->count, b->arcs, b->count);
+}
+
+bool arcs_equal_oids(struct oid_arcs *arcs, asn_oid_arc_t const *oids,
+ size_t oids_len)
+{
+ return __arcs_equal(arcs->arcs, arcs->count, oids, oids_len);
+}
+
+void
+oid_print(OBJECT_IDENTIFIER_t *oid)
+{
+ asn_fprint(stdout, &asn_DEF_OBJECT_IDENTIFIER, oid);
+}
--- /dev/null
+#ifndef SRC_OID_H_
+#define SRC_OID_H_
+
+#include <stdbool.h>
+#include <libcmscodec/AlgorithmIdentifier.h>
+#include "common.h"
+
+/* These objects are expected to live on the stack. */
+struct oid_arcs {
+ asn_oid_arc_t *arcs;
+ size_t count;
+};
+
+void free_arcs(struct oid_arcs *);
+
+typedef asn_oid_arc_t OID[];
+
+/* Please update MAX_ARCS if you add an OID that has more arcs. */
+static const OID SIGNED_DATA_OID = { 1, 2, 840, 113549, 1, 7, 2 };
+static const OID CONTENT_TYPE_ATTR_OID = { 1, 2, 840, 113549, 1, 9, 3 };
+static const OID MESSAGE_DIGEST_ATTR_OID = { 1, 2, 840, 113549, 1, 9, 4 };
+static const OID SIGNING_TIME_ATTR_OID = { 1, 2, 840, 113549, 1, 9, 5 };
+static const OID BINARY_SIGNING_TIME_ATTR_OID = { 1, 2, 840, 113549, 1, 9, 16,
+ 2, 46 };
+static const OID ROA_OID = { 1, 2, 840, 113549, 1, 9, 16, 1, 24 };
+static const OID OID_SHA224 = { 2, 16, 840, 1, 101, 3, 4, 2, 4 };
+static const OID OID_SHA256 = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
+static const OID OID_SHA384 = { 2, 16, 840, 1, 101, 3, 4, 2, 2 };
+static const OID OID_SHA512 = { 2, 16, 840, 1, 101, 3, 4, 2, 3 };
+
+int oid2arcs(OBJECT_IDENTIFIER_t *, struct oid_arcs *);
+int any2arcs(ANY_t *, struct oid_arcs *);
+
+bool arcs_equal(struct oid_arcs *, struct oid_arcs *);
+/* Use ARCS_EQUAL_OID() instead. */
+bool arcs_equal_oids(struct oid_arcs *, asn_oid_arc_t const *, size_t);
+
+/*
+ * a is supposed to be a OBJECT_IDENTIFIER_t (from libcmscodec.)
+ * b is supposed to be an OID.
+ */
+#define ARCS_EQUAL_OIDS(a, b) arcs_equal_oids(a, b, ARRAY_LEN(b))
+
+void oid_print(OBJECT_IDENTIFIER_t *oid);
+
+#endif /* SRC_OID_H_ */
--- /dev/null
+#include "roa.h"
+
+#include <err.h>
+#include <errno.h>
+#include <stdbool.h>
+#include "oid.h"
+#include "asn1/decode.h"
+#include "asn1/signed_data.h"
+
+static int
+validate_eContentType(struct SignedData *sdata)
+{
+ struct oid_arcs arcs;
+ bool equals;
+ int error;
+
+ error = oid2arcs(&sdata->encapContentInfo.eContentType, &arcs);
+ if (error)
+ return error;
+ equals = ARCS_EQUAL_OIDS(&arcs, ROA_OID);
+ free_arcs(&arcs);
+ if (!equals) {
+ warnx("SignedObject lacks the OID of a ROA.");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+validate_content_type(struct SignedData *sdata)
+{
+ OBJECT_IDENTIFIER_t *ctype;
+ struct oid_arcs arcs;
+ bool equals;
+ int error;
+
+ error = get_content_type_attr(sdata, &ctype);
+ if (error)
+ return error;
+ error = oid2arcs(ctype, &arcs);
+ ASN_STRUCT_FREE(asn_DEF_OBJECT_IDENTIFIER, ctype);
+ if (error)
+ return error;
+ equals = ARCS_EQUAL_OIDS(&arcs, ROA_OID);
+ free_arcs(&arcs);
+ if (!equals) {
+ warnx("SignedObject's content type doesn't match its encapContentInfo's eContent.");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+validate_roa(struct RouteOriginAttestation *roa)
+{
+ struct ROAIPAddressFamily *family;
+ struct ROAIPAddress *addr;
+ int b; /* block counter */
+ int a; /* address counter */
+
+ /* rfc6482#section-3.1 */
+ if (roa->version != 0) {
+ warnx("ROA's version (%ld) is not zero.", roa->version);
+ return -EINVAL;
+ }
+
+ /* rfc6482#section-3.2 */
+ if (roa->ipAddrBlocks.list.array == NULL)
+ return -EINVAL;
+
+ for (b = 0; b < roa->ipAddrBlocks.list.count; b++) {
+ family = roa->ipAddrBlocks.list.array[0];
+ if (family == NULL)
+ return -EINVAL;
+
+ if (family->addressFamily.size != 2)
+ return -EINVAL;
+ if (family->addressFamily.buf[0] != 0)
+ return -EINVAL;
+ if (family->addressFamily.buf[1] != 1
+ && family->addressFamily.buf[1] != 2)
+ return -EINVAL;
+
+ if (family->addresses.list.array == NULL)
+ return -EINVAL;
+ for (a = 0; a < family->addresses.list.count; a++) {
+ addr = family->addresses.list.array[a];
+ /*
+ * TODO I don't understand where the prefix length is.
+ * The bit string's size is measured in bytes...
+ */
+ printf("%ld\n", addr->maxLength
+ ? (*addr->maxLength)
+ : -1);
+ }
+ }
+
+ return 0;
+}
+
+int
+roa_decode(struct SignedData *sdata, struct RouteOriginAttestation **result)
+{
+ struct RouteOriginAttestation *roa;
+ int error;
+
+ /* rfc6482#section-2: eContentType */
+ error = validate_eContentType(sdata);
+ if (error)
+ return error;
+
+ /* rfc6482#section-2: content-type */
+ error = validate_content_type(sdata);
+ if (error)
+ return error;
+
+ error = asn1_decode_octet_string(sdata->encapContentInfo.eContent,
+ &asn_DEF_RouteOriginAttestation, (void **) &roa);
+ if (error)
+ return -EINVAL;
+
+ error = validate_roa(roa);
+ if (error) {
+ ASN_STRUCT_FREE(asn_DEF_RouteOriginAttestation, roa);
+ return error;
+ }
+
+ *result = roa;
+ return 0;
+}
+
+void roa_free(struct RouteOriginAttestation *roa)
+{
+ ASN_STRUCT_FREE(asn_DEF_RouteOriginAttestation, roa);
+}
--- /dev/null
+#ifndef SRC_ROA_H_
+#define SRC_ROA_H_
+
+#include <libcmscodec/RouteOriginAttestation.h>
+#include <libcmscodec/SignedData.h>
+
+int roa_decode(struct SignedData *, struct RouteOriginAttestation **);
+void roa_free(struct RouteOriginAttestation *);
+
+#endif /* SRC_ROA_H_ */
#include <errno.h>
#include <libcmscodec/ContentType.h>
#include "oid.h"
+#include "asn1/decode.h"
/* TODO more consistent and informative error/warning messages.*/
+/*
+ * The correctness of this function depends on @MAX_ARCS being faithful to all
+ * the known OIDs declared *in the project*.
+ */
+static int
+is_digest_algorithm(AlgorithmIdentifier_t *aid, bool *result)
+{
+ struct oid_arcs arcs;
+ int error;
+
+ error = oid2arcs(&aid->algorithm, &arcs);
+ if (error)
+ return error;
+
+ *result = ARCS_EQUAL_OIDS(&arcs, OID_SHA224)
+ || ARCS_EQUAL_OIDS(&arcs, OID_SHA256)
+ || ARCS_EQUAL_OIDS(&arcs, OID_SHA384)
+ || ARCS_EQUAL_OIDS(&arcs, OID_SHA512);
+
+ free_arcs(&arcs);
+ return 0;
+}
+
static int
validate_content_type_attribute(CMSAttributeValue_t *value,
EncapsulatedContentInfo_t *eci)
{
- /* TODO need to decode value. */
+ struct oid_arcs attrValue_arcs;
+ struct oid_arcs EncapContentInfo_arcs;
+ int error;
- /* eci->eContentType*/
+ /* rfc6488#section-3.1.h */
- return 0;
+ error = any2arcs(value, &attrValue_arcs);
+ if (error)
+ return error;
+
+ error = oid2arcs(&eci->eContentType, &EncapContentInfo_arcs);
+ if (error) {
+ free_arcs(&attrValue_arcs);
+ return error;
+ }
+
+ if (!arcs_equal(&attrValue_arcs, &EncapContentInfo_arcs)) {
+ warnx("The eContentType in the EncapsulatedContentInfo does not match the attrValues in the content-type attribute.");
+ error = -EINVAL;
+ }
+
+ free_arcs(&EncapContentInfo_arcs);
+ free_arcs(&attrValue_arcs);
+ return error;
}
static int
{
struct CMSAttribute *attr;
struct CMSAttribute__attrValues *attrs;
+ struct oid_arcs attrType;
unsigned int i;
bool content_type_found = false;
bool message_digest_found = false;
return -EINVAL;
}
- if (OID_EQUALS(&attr->attrType, CONTENT_TYPE_ATTR_OID)) {
+ error = oid2arcs(&attr->attrType, &attrType);
+ if (error)
+ return error;
+
+ if (ARCS_EQUAL_OIDS(&attrType, CONTENT_TYPE_ATTR_OID)) {
if (content_type_found) {
warnx("Multiple ContentTypes found.");
- return -EINVAL;
+ goto illegal_attrType;
}
error = validate_content_type_attribute(attr->attrValues.list.array[0], eci);
content_type_found = true;
- } else if (OID_EQUALS(&attr->attrType, MESSAGE_DIGEST_ATTR_OID)) {
+ } else if (ARCS_EQUAL_OIDS(&attrType, MESSAGE_DIGEST_ATTR_OID)) {
if (message_digest_found) {
warnx("Multiple MessageDigests found.");
- return -EINVAL;
+ goto illegal_attrType;
}
error = validate_message_digest_attribute(attr->attrValues.list.array[0]);
message_digest_found = true;
- } else if (OID_EQUALS(&attr->attrType, SIGNING_TIME_ATTR_OID)) {
+ } else if (ARCS_EQUAL_OIDS(&attrType, SIGNING_TIME_ATTR_OID)) {
if (signing_time_found) {
warnx("Multiple SigningTimes found.");
- return -EINVAL;
+ goto illegal_attrType;
}
error = 0; /* No validations needed for now. */
signing_time_found = true;
- } else if (OID_EQUALS(&attr->attrType, BINARY_SIGNING_TIME_ATTR_OID)) {
+ } else if (ARCS_EQUAL_OIDS(&attrType, BINARY_SIGNING_TIME_ATTR_OID)) {
if (binary_signing_time_found) {
warnx("Multiple BinarySigningTimes found.");
- return -EINVAL;
+ goto illegal_attrType;
}
error = 0; /* No validations needed for now. */
binary_signing_time_found = true;
} else {
+ /* rfc6488#section-3.1.g */
warnx("Illegal attrType OID in SignerInfo.");
- return -EINVAL;
+ goto illegal_attrType;
}
+ free_arcs(&attrType);
+
if (error)
return error;
}
+ /* rfc6488#section-3.1.f */
if (!content_type_found) {
warnx("SignerInfo lacks a ContentType attribute.");
return -EINVAL;
}
return 0;
+
+illegal_attrType:
+ free_arcs(&attrType);
+ return -EINVAL;
}
static int
validate(struct SignedData *sdata)
{
- char error_msg[256];
- size_t error_msg_size;
- int error;
struct SignerInfo *sinfo;
-
- /* The lib's inbuilt validations. (Probably not much.) */
- error_msg_size = sizeof(error_msg);
- error = asn_check_constraints(&asn_DEF_SignedData, sdata, error_msg,
- &error_msg_size);
- if (error == -1) {
- warnx("Error validating SignedData object: %s", error_msg);
- return -EINVAL;
- }
+ bool is_digest;
+ int error;
/* rfc6488#section-2.1 */
if (sdata->signerInfos.list.count != 1) {
}
/* rfc6488#section-2.1.1 */
+ /* rfc6488#section-3.1.b */
if (sdata->version != 3) {
warnx("The SignedData version is only allowed to be 3. (Was %ld.)",
sdata->version);
}
/* rfc6488#section-2.1.2 */
+ /* rfc6488#section-3.1.j 1/2 */
if (sdata->digestAlgorithms.list.count != 1) {
warnx("The SignedData's digestAlgorithms set is supposed to have only one element. (%d given.)",
sdata->digestAlgorithms.list.count);
* AlgorithmIdentifier instead. There's no API.
* This seems to work fine.
*/
- if (!is_digest_algorithm((DigestAlgorithmIdentifier_t *) sdata->digestAlgorithms.list.array[0])) {
+ error = is_digest_algorithm((AlgorithmIdentifier_t *) sdata->digestAlgorithms.list.array[0],
+ &is_digest);
+ if (error)
+ return error;
+ if (!is_digest) {
warnx("The SignedData's digestAlgorithm OID is not listed in RFC 5754.");
return -EINVAL;
}
/* section-2.1.3 */
- /* TODO need a callback for specific signed object types */
+ /* Specific sub-validations will be performed later by calling code. */
/* rfc6488#section-2.1.4 */
+ /* rfc6488#section-3.1.c TODO missing half of the requirement. */
if (sdata->certificates == NULL) {
warnx("The SignedData does not contain certificates.");
return -EINVAL;
}
/* rfc6488#section-2.1.5 */
+ /* rfc6488#section-3.1.d */
if (sdata->crls != NULL && sdata->crls->list.count > 0) {
warnx("The SignedData contains at least one crls.");
return -EINVAL;
}
/* rfc6488#section-2.1.6.1 */
+ /* rfc6488#section-3.1.e */
sinfo = sdata->signerInfos.list.array[0];
if (sinfo == NULL) {
warnx("The SignerInfo object is NULL.");
*/
/* rfc6488#section-2.1.6.3 */
- if (!is_digest_algorithm((AlgorithmIdentifier_t *) &sinfo->digestAlgorithm)) {
+ /* rfc6488#section-3.1.j 2/2 */
+ error = is_digest_algorithm((AlgorithmIdentifier_t *) &sinfo->digestAlgorithm,
+ &is_digest);
+ if (error)
+ return error;
+ if (!is_digest) {
warnx("The SignerInfo digestAlgorithm OID is not listed in RFC 5754.");
return -EINVAL;
}
return error;
/* rfc6488#section-2.1.6.5 */
+ /* rfc6488#section-3.1.k */
/*
* RFC 6485 was obsoleted by 7935. 7935 simply refers to 5652.
*
/* Again, nothing to do for now. */
/* rfc6488#section-2.1.6.7 */
+ /* rfc6488#section-3.1.i */
if (sinfo->unsignedAttrs != NULL && sinfo->unsignedAttrs->list.count > 0) {
warnx("SignerInfo has at least one unsignedAttr.");
return -EINVAL;
}
- /* TODO section 3 */
+ /* rfc6488#section-3.2 TODO */
+ /* rfc6488#section-3.3 TODO */
return 0;
}
int
signed_data_decode(ANY_t *coded, struct SignedData **result)
{
- struct SignedData *sdata = NULL;
- asn_dec_rval_t rval;
+ struct SignedData *sdata;
int error;
- rval = ber_decode(0, &asn_DEF_SignedData, (void **) &sdata, coded->buf,
- coded->size);
- if (rval.code != RC_OK) {
- warnx("Error decoding signed data object: %d", rval.code);
- /* Must free partial signed data according to API contracts. */
- signed_data_free(sdata);
- return -EINVAL;
- }
+ /* rfc6488#section-3.1.l TODO this is BER, not guaranteed to be DER. */
+ error = asn1_decode_any(coded, &asn_DEF_SignedData, (void **) &sdata);
+ if (error)
+ return error;
error = validate(sdata);
if (error) {
void
signed_data_free(struct SignedData *sdata)
{
- asn_DEF_SignedData.op->free_struct(&asn_DEF_SignedData, sdata,
- ASFM_FREE_EVERYTHING);
+ ASN_STRUCT_FREE(asn_DEF_SignedData, sdata);
+}
+
+/* Caller must free *@result. */
+int
+get_content_type_attr(struct SignedData *sdata, OBJECT_IDENTIFIER_t **result)
+{
+ struct SignedAttributes *signedAttrs;
+ struct CMSAttribute *attr;
+ int i;
+ int error;
+ struct oid_arcs arcs;
+ bool equal;
+
+ if (sdata == NULL)
+ return -EINVAL;
+ if (sdata->signerInfos.list.array == NULL)
+ return -EINVAL;
+ if (sdata->signerInfos.list.array[0] == NULL)
+ return -EINVAL;
+
+ signedAttrs = sdata->signerInfos.list.array[0]->signedAttrs;
+ if (signedAttrs->list.array == NULL)
+ return -EINVAL;
+
+ for (i = 0; i < signedAttrs->list.count; i++) {
+ attr = signedAttrs->list.array[i];
+ if (!attr)
+ return -EINVAL;
+ error = oid2arcs(&attr->attrType, &arcs);
+ if (error)
+ return -EINVAL;
+ equal = ARCS_EQUAL_OIDS(&arcs, CONTENT_TYPE_ATTR_OID);
+ free_arcs(&arcs);
+ if (equal) {
+ if (attr->attrValues.list.array == NULL)
+ return -EINVAL;
+ if (attr->attrValues.list.array[0] == NULL)
+ return -EINVAL;
+ return asn1_decode_any(attr->attrValues.list.array[0],
+ &asn_DEF_OBJECT_IDENTIFIER, (void **) result);
+ }
+ }
+
+ return -EINVAL;
}
#include <libcmscodec/SignedData.h>
-int signed_data_decode(ANY_t *coded, struct SignedData **result);
-void signed_data_free(struct SignedData *sdata);
+int signed_data_decode(ANY_t *, struct SignedData **);
+void signed_data_free(struct SignedData *);
+
+int get_content_type_attr(struct SignedData *, OBJECT_IDENTIFIER_t **);
#endif /* SRC_SIGNED_DATA_H_ */
#include <string.h>
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
+#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
#define warnxerror0(error, msg) \
warnx(msg ": %s", strerror(error))
#define warnxerrno(msg, ...) \
warnxerror(errno, msg, ##__VA_ARGS__)
+#define pr_debug0(msg) printf("Debug: " msg "\n");
#define pr_debug(msg, ...) printf("Debug: " msg "\n", ##__VA_ARGS__);
#endif /* SRC_RTR_COMMON_H_ */
+++ /dev/null
-#include "content_info.h"
-
-#include <err.h>
-#include <errno.h>
-#include <libcmscodec/ContentType.h>
-#include "common.h"
-#include "file.h"
-
-static void
-content_type_print(FILE *stream, asn_oid_arc_t *arcs, unsigned int arc_count)
-{
- unsigned int i;
-
- for (i = 0; i < arc_count; i++) {
- fprintf(stream, "%u", arcs[i]);
- if (i != arc_count - 1)
- fprintf(stream, ".");
- }
-}
-
-int
-content_type_validate(ContentType_t *ctype)
-{
- asn_oid_arc_t expected[] = { 1, 2, 840, 113549, 1, 7, 2 };
- asn_oid_arc_t actual[ARRAY_SIZE(expected)];
- const unsigned int SLOTS = ARRAY_SIZE(expected);
- ssize_t result;
- unsigned int i;
-
- result = OBJECT_IDENTIFIER_get_arcs(ctype, actual, SLOTS);
- if (result != SLOTS)
- goto failure;
-
- for (i = 0; i < SLOTS; i++) {
- if (expected[i] != actual[i])
- goto failure;
- }
-
- return 0;
-
-failure:
- fprintf(stderr, "Incorrect content-type; expected ");
- content_type_print(stderr, expected, SLOTS);
- fprintf(stderr, ", got ");
- content_type_print(stderr, actual, (result < SLOTS) ? result : SLOTS);
- fprintf(stderr, ".\n");
- return -EINVAL;
-}
-
-static int
-validate(struct ContentInfo *info)
-{
- char error_msg[256];
- size_t error_msg_size;
- int error;
-
- error_msg_size = sizeof(error_msg);
- error = asn_check_constraints(&asn_DEF_ContentInfo, info, error_msg,
- &error_msg_size);
- if (error == -1) {
- warnx("Error validating content info object: %s", error_msg);
- return -EINVAL;
- }
-
- return content_type_validate(&info->contentType);
-}
-
-static int
-decode(struct file_contents *fc, struct ContentInfo **result)
-{
- struct ContentInfo *info = NULL;
- asn_dec_rval_t rval;
- int error;
-
- rval = ber_decode(0, &asn_DEF_ContentInfo, (void **) &info, fc->buffer,
- fc->buffer_size);
- if (rval.code != RC_OK) {
- warnx("Error decoding content info object: %d", rval.code);
- /* Must free partial content info according to API contracts. */
- content_info_free(info);
- return -EINVAL;
- }
-
- error = validate(info);
- if (error) {
- content_info_free(info);
- return error;
- }
-
- *result = info;
- return 0;
-}
-
-int
-content_info_load(const char *file_name, struct ContentInfo **result)
-{
- struct file_contents fc;
- int error;
-
- error = file_load(file_name, &fc);
- if (error)
- return error;
-
- error = decode(&fc, result);
-
- file_free(&fc);
- return error;
-}
-
-void
-content_info_free(struct ContentInfo *info)
-{
- asn_DEF_ContentInfo.op->free_struct(&asn_DEF_ContentInfo, info,
- ASFM_FREE_EVERYTHING);
-}
-#include "content_info.h"
-#include "signed_data.h"
+#include <errno.h>
-const char *FILE_NAME = "/home/ydahhrk/rpki-cache/repository/"
- "ca.rg.net/rpki/RGnet/IZt-j9P0XqJjzM2Xi4RZKS60gOc.roa";
+#include "common.h"
+#include "asn1/content_info.h"
+#include "asn1/roa.h"
+#include "asn1/signed_data.h"
int
-main(void)
+main(int argc, char **argv)
{
struct ContentInfo *cinfo;
struct SignedData *sdata;
+ struct RouteOriginAttestation *roa;
int error;
- error = content_info_load(FILE_NAME, &cinfo);
+ if (argc < 2) {
+ pr_debug0("argc < 2");
+ return -EINVAL;
+ }
+
+ error = content_info_load(argv[1], &cinfo);
if (error)
return error;
return error;
}
-// asn_fprint(stdout, &asn_DEF_ContentInfo, cinfo);
-// printf("---------------------------------------------\n");
-// asn_fprint(stdout, &asn_DEF_SignedData, sdata);
+ error = roa_decode(sdata, &roa);
+ if (error) {
+ signed_data_free(sdata);
+ content_info_free(cinfo);
+ return error;
+ }
+
+ asn_fprint(stdout, &asn_DEF_RouteOriginAttestation, roa);
+ roa_free(roa);
signed_data_free(sdata);
content_info_free(cinfo);
return 0;
+++ /dev/null
-#include "oid.h"
-
-#include <errno.h>
-#include "common.h"
-
-#define MAX_ARCS 9
-
-/* Please update MAX_ARCS if you add an OID that has more arcs. */
-static asn_oid_arc_t OID_SHA224[] = { 2, 16, 840, 1, 101, 3, 4, 2, 4 };
-static asn_oid_arc_t OID_SHA256[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
-static asn_oid_arc_t OID_SHA384[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 };
-static asn_oid_arc_t OID_SHA512[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 };
-
-/*
- * @a_oid is the original OID that's being tested.
- * @a_arcs must be a stack-allocated array of size @len.
- * @b_arcs is the expected array of arcs that needs to be compared to @a_oid.
- * Its length must be @len.
- */
-bool
-oid_equals(OBJECT_IDENTIFIER_t *const actual_oid,
- asn_oid_arc_t const *expected_arcs,
- size_t len)
-{
- asn_oid_arc_t actual_arcs[MAX_ARCS];
- ssize_t count;
- long int i;
-
- count = OBJECT_IDENTIFIER_get_arcs(actual_oid, actual_arcs, len);
- if (count != len)
- return false;
-
- /* Most OIDs start with the same numbers, so iterate backwards. */
- for (i = len - 1; i >= 0; i--) {
- if (actual_arcs[i] != expected_arcs[i])
- return false;
- }
-
- return true;
-}
-
-void
-oid_print(OBJECT_IDENTIFIER_t *oid)
-{
- asn_fprint(stdout, &asn_DEF_OBJECT_IDENTIFIER, oid);
-}
-
-bool
-is_digest_algorithm(AlgorithmIdentifier_t *algorithm)
-{
- return OID_EQUALS(&algorithm->algorithm, OID_SHA224)
- || OID_EQUALS(&algorithm->algorithm, OID_SHA256)
- || OID_EQUALS(&algorithm->algorithm, OID_SHA384)
- || OID_EQUALS(&algorithm->algorithm, OID_SHA512);
-}
+++ /dev/null
-#ifndef SRC_OID_H_
-#define SRC_OID_H_
-
-#include <stdbool.h>
-#include "libcmscodec/AlgorithmIdentifier.h"
-
-#include "common.h"
-
-typedef asn_oid_arc_t OID[];
-
-/* Please update MAX_ARCS if you add an OID that has more arcs. */
-static const OID CONTENT_TYPE_ATTR_OID = {
- 1, 2, 840, 113549, 1, 9, 3
-};
-static const OID MESSAGE_DIGEST_ATTR_OID = {
- 1, 2, 840, 113549, 1, 9, 4
-};
-static const OID SIGNING_TIME_ATTR_OID = {
- 1, 2, 840, 113549, 1, 9, 5
-};
-static const OID BINARY_SIGNING_TIME_ATTR_OID = {
- 1, 2, 840, 113549, 1, 9, 16, 2, 46
-};
-
-/* Use OID_EQUALS() instead. */
-bool oid_equals(OBJECT_IDENTIFIER_t *const actual_oid,
- asn_oid_arc_t const *expected_arcs, size_t len);
-
-/*
- * a is supposed to be a OBJECT_IDENTIFIER_t (from libcmscodec.)
- * b is supposed to be an OID (from the typedef above.)
- */
-#define OID_EQUALS(a, b) oid_equals(a, b, ARRAY_SIZE(b))
-
-void oid_print(OBJECT_IDENTIFIER_t *oid);
-
-bool is_digest_algorithm(AlgorithmIdentifier_t *algorithm);
-
-#endif /* SRC_OID_H_ */
uri = SLIST_NEXT(uri, next);
ck_assert(uri == NULL);
- ck_assert_uint_eq(ARRAY_SIZE(decoded), tal->spki_size);
- for (i = 0; i < ARRAY_SIZE(decoded); i++)
+ ck_assert_uint_eq(ARRAY_LEN(decoded), tal->spki_size);
+ for (i = 0; i < ARRAY_LEN(decoded); i++)
ck_assert_uint_eq(tal->spki[i], decoded[i]);
tal_destroy(tal);