\
list->array[list->len - 1] = *elem; \
return 0; \
- } \
- \
- static int \
- name##_foreach(struct name *list, \
- int (*cb)(elem_type const *, void *), \
- void *arg) \
- { \
- unsigned int i; \
- int error; \
- \
- for (i = 0; i < list->len; i++) { \
- error = cb(&list->array[i], arg); \
- if (error) \
- return error; \
- } \
- \
- return 0; \
}
+#define ARRAYLIST_FOREACH(list, cursor) for ( \
+ cursor = (list)->array; \
+ (cursor - ((typeof(cursor)) ((list)->array))) < (list)->len; \
+ cursor++ \
+)
+
#endif /* SRC_ARRAY_LIST_H_ */
#define STDOUT stdout
#define STDERR stderr
-#define INDENT_MAX 10
static unsigned int indent;
static void
pr_indent(FILE *stream)
{
- unsigned int __indent = indent;
unsigned int i;
-
-// if (__indent > INDENT_MAX)
-// __indent = INDENT_MAX;
-
- for (i = 0; i < __indent; i++)
+ for (i = 0; i < indent; i++)
fprintf(stream, " ");
}
add_rpki_oids(void)
{
NID_rpkiManifest = OBJ_create("1.3.6.1.5.5.7.48.10",
- "id-ad-rpkiManifest (RFC 6487)",
- "Resource Public Key Infrastructure (RPKI) manifest access method");
+ "rpkiManifest",
+ "RPKI Manifest (RFC 6487)");
printf("rpkiManifest registered. Its nid is %d.\n", NID_rpkiManifest);
NID_signedObject = OBJ_create("1.3.6.1.5.5.7.48.11",
- "id-ad-signedObject (RFC 6487)",
- /* TODO */ "");
+ "signedObject",
+ "RPKI Signed Object (RFC 6487)");
printf("signedObject registered. Its nid is %d.\n", NID_signedObject);
NID_rpkiNotify = OBJ_create("1.3.6.1.5.5.7.48.13",
- "id-ad-rpkiNotify (RFC 8182)",
- /* TODO */ "Blah blah");
+ "rpkiNotify",
+ "RPKI Update Notification File (RFC 8182)");
printf("rpkiNotify registered. Its nid is %d.\n", NID_rpkiNotify);
}
* key." (RFC 7730)
*
* A "hard error" is any other error.
- *
- * TODO this will probably need an update after the merge.
*/
struct validation *state;
int error;
- /* TODO this probably needs the state... */
error = download_files(uri);
if (error)
return 0;
static int
validate_serial_number(X509 *cert)
{
- /* TODO (field) implement this properly. */
-
+ struct validation *state;
BIGNUM *number;
+ int error;
+
+ state = state_retrieve();
+ if (state == NULL)
+ return -EINVAL;
number = ASN1_INTEGER_to_BN(X509_get0_serialNumber(cert), NULL);
- if (number == NULL) {
- crypto_err("Could not parse certificate serial number");
- return 0;
- }
+ if (number == NULL)
+ return crypto_err("Could not parse certificate serial number");
+#ifdef DEBUG
pr_debug_prefix();
fprintf(stdout, "serial Number: ");
BN_print_fp(stdout, number);
fprintf(stdout, "\n");
- BN_free(number);
+#endif
- return 0;
+ error = validation_store_serial_number(state, number);
+ if (error)
+ BN_free(number);
+
+ return error;
}
static int
struct uris roas; /* Route Origin Attestations */
};
-struct foreach_args {
- struct rpp *pp;
- STACK_OF(X509_CRL) *crls;
-};
-
struct rpp *
rpp_create(void)
{
return error;
}
-static int
-traverse_ca_certs(struct rpki_uri const *uri, void *arg)
-{
- struct foreach_args *args = arg;
- return certificate_traverse(args->pp, uri, args->crls, false);
-}
-
-static int
-print_roa(struct rpki_uri const *uri, void *arg)
-{
- struct foreach_args *args = arg;
- handle_roa(uri, args->pp, args->crls);
- return 0;
-}
-
struct rpki_uri const *
rpp_get_crl(struct rpp const *pp)
{
* TODO is the stack supposed to have only the CRLs of this layer,
* or all of them?
*/
- struct foreach_args args;
+ STACK_OF(X509_CRL) *crls;
+ struct rpki_uri *uri;
int error;
- args.pp = pp;
- args.crls = sk_X509_CRL_new_null();
- if (args.crls == NULL)
+ crls = sk_X509_CRL_new_null();
+ if (crls == NULL)
return pr_enomem();
- error = add_crl_to_stack(pp, args.crls);
+ error = add_crl_to_stack(pp, crls);
if (error)
goto end;
/* Use CRL stack to validate certificates, and also traverse them. */
- error = uris_foreach(&pp->certs, traverse_ca_certs, &args);
- if (error)
- goto end;
+ ARRAYLIST_FOREACH(&pp->certs, uri) {
+ /* TODO should we really goto end? */
+ error = certificate_traverse(pp, uri, crls, false);
+ if (error)
+ goto end;
+ }
/* Use valid address ranges to print ROAs that match them. */
- error = uris_foreach(&pp->roas, print_roa, &args);
+ ARRAYLIST_FOREACH(&pp->roas, uri)
+ handle_roa(uri, pp, crls);
end:
- sk_X509_CRL_pop_free(args.crls, X509_CRL_free);
+ sk_X509_CRL_pop_free(crls, X509_CRL_free);
return error;
}
#include <errno.h>
#include <sys/queue.h>
+#include "array_list.h"
#include "log.h"
#include "thread_var.h"
#include "object/certificate.h"
+ARRAY_LIST(serial_numbers, BIGNUM *)
+
/**
* Cached certificate data.
*/
struct certificate {
struct rpki_uri uri;
struct resources *resources;
+ /*
+ * Serial numbers of the children.
+ * This is an unsorted array list for two reasons: Certificates usually
+ * don't have many children, and I'm running out of time.
+ */
+ struct serial_numbers serials;
/** Used by certstack. Points to the next stacked certificate. */
SLIST_ENTRY(certificate) next;
return error;
}
+static void
+serial_cleanup(BIGNUM **serial)
+{
+ BN_free(*serial);
+}
+
void
validation_destroy(struct validation *state)
{
cert = SLIST_FIRST(&state->certs);
SLIST_REMOVE_HEAD(&state->certs, next);
resources_destroy(cert->resources);
+ serial_numbers_cleanup(&cert->serials, serial_cleanup);
free(cert);
c++;
}
}
cert->uri = *cert_uri;
+ error = serial_numbers_init(&cert->serials);
+ if (error)
+ goto end2;
cert->resources = resources_create();
if (cert->resources == NULL) {
error = pr_enomem();
- goto end2;
+ goto end3;
}
error = certificate_get_resources(x509, cert->resources);
if (error)
- goto end3;
+ goto end4;
/*
* rfc7730#section-2.2
*/
if (is_ta && resources_empty(cert->resources)) {
error = pr_err("Trust Anchor certificate does not define any number resources.");
- goto end3;
+ goto end4;
}
ok = sk_X509_push(state->trusted, x509);
if (ok <= 0) {
error = crypto_err(
"Couldn't add certificate to trusted stack: %d", ok);
- goto end3;
+ goto end4;
}
SLIST_INSERT_HEAD(&state->certs, cert, next);
return 0;
-end3: resources_destroy(cert->resources);
+end4: resources_destroy(cert->resources);
+end3: serial_numbers_cleanup(&cert->serials, serial_cleanup);
end2: free(cert);
end1: return error;
}
return pr_crit("Attempted to pop empty certificate stack (2)");
SLIST_REMOVE_HEAD(&state->certs, next);
resources_destroy(cert->resources);
+ serial_numbers_cleanup(&cert->serials, serial_cleanup);
free(cert);
return 0;
struct certificate *cert = SLIST_FIRST(&state->certs);
return (cert != NULL) ? cert->resources : NULL;
}
+
+int
+validation_store_serial_number(struct validation *state, BIGNUM *number)
+{
+ struct certificate *cert;
+ BIGNUM **cursor;
+ BIGNUM *duplicate;
+ int error;
+
+ cert = SLIST_FIRST(&state->certs);
+ if (cert == NULL)
+ return 0; /* The TA lacks siblings, so serial is unique. */
+
+ ARRAYLIST_FOREACH(&cert->serials, cursor)
+ if (BN_cmp(*cursor, number) == 0)
+ return pr_err("Serial number is not unique.");
+
+ duplicate = BN_dup(number);
+ if (duplicate == NULL)
+ return crypto_err("Could not duplicate a BIGNUM");
+
+ error = serial_numbers_add(&cert->serials, &duplicate);
+ if (error)
+ BN_free(duplicate);
+
+ return error;
+}
struct resources *validation_peek_resource(struct validation *);
+int validation_store_serial_number(struct validation *, BIGNUM *);
+
#endif /* SRC_STATE_H_ */