]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Certificate serial number uniqueness validation
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Fri, 1 Feb 2019 19:16:06 +0000 (13:16 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Fri, 1 Feb 2019 19:38:30 +0000 (13:38 -0600)
src/array_list.h
src/log.c
src/main.c
src/object/certificate.c
src/rpp.c
src/state.c
src/state.h

index e199414ec338f09be666626017e0d980caad8c8c..213e322a154d47f004c1abdd7fa1e95527dea910 100644 (file)
                                                                        \
                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_ */
index 727a3e56a69accefa24bcdc9df472a4f28bef9c0..a1343da2ef4c748781e8c8064eb0cb8c8759dc21 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -8,19 +8,13 @@
 #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, "  ");
 }
 
index 511faa46d5b13ab45e4b1215bf43cea6dace9f60..5fddc47e3e2789966eff26ecde6d81ff0ccd39d4 100644 (file)
@@ -32,18 +32,18 @@ static void
 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);
 }
 
@@ -66,14 +66,11 @@ handle_tal_uri(struct tal *tal, struct rpki_uri const *uri)
         * 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;
index a952798994c325d37a80f10d16d661d76a33a03b..1c4fbedc1cdc103df00d34b6db23d0d7b29a4aee 100644 (file)
@@ -102,23 +102,30 @@ struct ski_arguments {
 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
index 7f4c5e4851f3614fda55a4f6a9bc2ad29dca147b..23594c3206d539f204bcf239c58f950eabd99c5e 100644 (file)
--- a/src/rpp.c
+++ b/src/rpp.c
@@ -23,11 +23,6 @@ struct rpp {
        struct uris roas; /* Route Origin Attestations */
 };
 
-struct foreach_args {
-       struct rpp *pp;
-       STACK_OF(X509_CRL) *crls;
-};
-
 struct rpp *
 rpp_create(void)
 {
@@ -112,21 +107,6 @@ end:
        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)
 {
@@ -140,26 +120,30 @@ rpp_traverse(struct rpp *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;
 }
index 1f038197f01c46ad43c865a92c60e2c9167672df..c8f559e26ae21422867016f3d8348cc6df3ad043 100644 (file)
@@ -2,16 +2,25 @@
 
 #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;
@@ -131,6 +140,12 @@ abort1:
        return error;
 }
 
+static void
+serial_cleanup(BIGNUM **serial)
+{
+       BN_free(*serial);
+}
+
 void
 validation_destroy(struct validation *state)
 {
@@ -149,6 +164,7 @@ 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++;
        }
@@ -211,15 +227,18 @@ validation_push_cert(struct validation *state, struct rpki_uri const *cert_uri,
        }
 
        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
@@ -230,21 +249,22 @@ validation_push_cert(struct validation *state, struct rpki_uri const *cert_uri,
         */
        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;
 }
@@ -262,6 +282,7 @@ validation_pop_cert(struct validation *state)
                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;
@@ -286,3 +307,30 @@ validation_peek_resource(struct validation *state)
        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;
+}
index 44e4f3fe70623e2e24f3a47b25064c67205b317e..142d3abc1a65584504f09d20902b623d637a1425 100644 (file)
@@ -32,4 +32,6 @@ struct rpki_uri const *validation_peek_cert_uri(struct validation *);
 
 struct resources *validation_peek_resource(struct validation *);
 
+int validation_store_serial_number(struct validation *, BIGNUM *);
+
 #endif /* SRC_STATE_H_ */