]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Implement about 40% of RFC 6486 (Manifests)
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Thu, 27 Sep 2018 21:56:50 +0000 (16:56 -0500)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Thu, 27 Sep 2018 22:06:31 +0000 (17:06 -0500)
configure.ac
src/Makefile.am
src/asn1/manifest.c [new file with mode: 0644]
src/asn1/manifest.h [new file with mode: 0644]
src/asn1/oid.h
src/file.c
src/main.c

index f01b3f71317cdc899b704183b19303fb712d60a3..75070bb96fab0b25530a830832d73485e0f56ecb 100644 (file)
@@ -31,7 +31,6 @@ AC_SEARCH_LIBS([ber_decode], [cmscodec], [],
 )
 
 # Check dependencies.
-#PKG_CHECK_MODULES([OPENSSL], [openssl])
 PKG_CHECK_MODULES([CHECK], [check])
 
 # Spit out the makefiles.
index 54878e0f1f33375b4345b0864ffe9ae6d929db0e..042c7e7c42e411339841dc42cb127ca0888bff2d 100644 (file)
@@ -6,6 +6,7 @@ rpki_validator_SOURCES += common.h
 rpki_validator_SOURCES += file.h file.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/manifest.h asn1/manifest.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
diff --git a/src/asn1/manifest.c b/src/asn1/manifest.c
new file mode 100644 (file)
index 0000000..8e4d802
--- /dev/null
@@ -0,0 +1,187 @@
+#include "asn1/manifest.h"
+
+#include <err.h>
+#include <errno.h>
+#include "asn1/decode.h"
+#include "asn1/oid.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, MANIFEST_OID);
+       free_arcs(&arcs);
+       if (!equals) {
+               warnx("SignedObject lacks the OID of a Manifest.");
+               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, MANIFEST_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_dates(GeneralizedTime_t *this, GeneralizedTime_t *next)
+{
+       const struct asn_TYPE_descriptor_s *def = &asn_DEF_GeneralizedTime;
+       return (GeneralizedTime_compare(def, this, next) < 0) ? 0 : -EINVAL;
+}
+
+static int
+is_hash_algorithm(OBJECT_IDENTIFIER_t *aid, bool *result)
+{
+       struct oid_arcs arcs;
+       int error;
+
+       error = oid2arcs(aid, &arcs);
+       if (error)
+               return error;
+
+       *result = ARCS_EQUAL_OIDS(&arcs, OID_SHA256);
+
+       free_arcs(&arcs);
+       return 0;
+}
+
+int
+validate_manifest(struct Manifest *manifest)
+{
+       int error;
+       bool is_hash;
+
+       /* rfc6486#section-4.2.1 */
+
+       /*
+        * TODO
+        *
+        * If a "one-time-use" EE certificate is employed to verify a manifest,
+        * the EE certificate MUST have a validity period that coincides with
+        * the interval from thisUpdate to nextUpdate, to prevent needless
+        * growth of the CA's CRL.
+        *
+        * If a "sequential-use" EE certificate is employed to verify a
+        * manifest, the EE certificate's validity period needs to be no shorter
+        * than the nextUpdate time of the current manifest.
+        */
+
+       /* rfc6486#section-4.4.2 */
+       if (manifest->version != 0)
+               return -EINVAL;
+
+       /*
+        * TODO "Manifest verifiers MUST be able to handle number values up to
+        * 20 octets."
+        *
+        * What the fuck?
+        */
+       /* manifest->manifestNumber; */
+
+       /*
+        * TODO
+        *
+        * "CRL issuers conforming to this profile MUST encode thisUpdate as
+        * UTCTime for dates through the year 2049.  CRL issuers conforming to
+        * this profile MUST encode thisUpdate as GeneralizedTime for dates in
+        * the year 2050 or later. Conforming applications MUST be able to
+        * process dates that are encoded in either UTCTime or GeneralizedTime."
+        *
+        * WTF man. thisUpdate is defined in the spec as GeneralizedTime;
+        * not as CMSTime. This requirement makes no sense whatsoever.
+        *
+        * Check the errata?
+        */
+       /* manifest->thisUpdate */
+
+       /*
+        * TODO again, same bullshit:
+        *
+        * "CRL issuers conforming to this profile MUST encode nextUpdate as
+        * UTCTime for dates through the year 2049.  CRL issuers conforming to
+        * this profile MUST encode nextUpdate as GeneralizedTime for dates in
+        * the year 2050 or later.  Conforming applications MUST be able to
+        * process dates that are encoded in either UTCTime or GeneralizedTime."
+        */
+       /* manifest->nextUpdate */
+
+       /* rfc6486#section-4.4.3 */
+       error = validate_dates(&manifest->thisUpdate, &manifest->nextUpdate);
+       if (error)
+               return error;
+
+       error = is_hash_algorithm(&manifest->fileHashAlg, &is_hash);
+       if (error)
+               return error;
+       if (!is_hash)
+               return -EINVAL;
+
+       /* fileList needs no validations for now.*/
+
+       return 0;
+}
+
+int manifest_decode(struct SignedData *sdata, struct Manifest **result)
+{
+       struct Manifest *manifest;
+       int error;
+
+       /* rfc6486#section-4.1 */
+       /* rfc6486#section-4.4.1 */
+       error = validate_eContentType(sdata);
+       if (error)
+               return error;
+
+       /* rfc6486#section-4.3 */
+       error = validate_content_type(sdata);
+       if (error)
+               return error;
+
+       error = asn1_decode_octet_string(sdata->encapContentInfo.eContent,
+           &asn_DEF_Manifest, (void **) &manifest);
+       if (error)
+               return -EINVAL;
+
+       error = validate_manifest(manifest);
+       if (error) {
+               ASN_STRUCT_FREE(asn_DEF_Manifest, manifest);
+               return error;
+       }
+
+       *result = manifest;
+       return 0;
+}
+
+void manifest_free(struct Manifest *manifest)
+{
+       ASN_STRUCT_FREE(asn_DEF_Manifest, manifest);
+}
diff --git a/src/asn1/manifest.h b/src/asn1/manifest.h
new file mode 100644 (file)
index 0000000..48434ce
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef SRC_ASN1_MANIFEST_H_
+#define SRC_ASN1_MANIFEST_H_
+
+#include <libcmscodec/Manifest.h>
+#include <libcmscodec/SignedData.h>
+
+int manifest_decode(struct SignedData *sdata, struct Manifest **mf);
+void manifest_free(struct Manifest *mf);
+
+#endif /* SRC_ASN1_MANIFEST_H_ */
index c14c5adbee55a21d77a2949a36b08f6530a28217..187bc0b57c1f3094a3363f0c8cbc00700af9ae54 100644 (file)
@@ -15,14 +15,22 @@ 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. */
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! 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 MANIFEST_OID = { 1, 2, 840, 113549, 1, 9, 16, 1, 26 };
+
 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 };
index ea4d9004a74ed2cc741115dbec4681fb868f9130..3f3047b879ef8e571b4cd7c479adf218c30ceeec 100644 (file)
@@ -34,6 +34,7 @@ file_load(const char *file_name, struct file_contents *fc)
                return errno;
        }
 
+       /* TODO if @file is a directory, this returns a very large integer. */
        error = get_file_size(file, &file_size);
        if (error) {
                warnxerror0(error, "Could not compute file size");
index 2cc956625d220217d79087ceadb4cbf0568e8c76..3ec6c27e1b251f347b7a364039dafd7e0b3c68da 100644 (file)
@@ -2,23 +2,19 @@
 
 #include "common.h"
 #include "asn1/content_info.h"
+#include "asn1/manifest.h"
 #include "asn1/roa.h"
 #include "asn1/signed_data.h"
 
 int
-main(int argc, char **argv)
+try_roa(char *file_name)
 {
        struct ContentInfo *cinfo;
        struct SignedData *sdata;
        struct RouteOriginAttestation *roa;
        int error;
 
-       if (argc < 2) {
-               pr_debug0("argc < 2");
-               return -EINVAL;
-       }
-
-       error = content_info_load(argv[1], &cinfo);
+       error = content_info_load(file_name, &cinfo);
        if (error)
                return error;
 
@@ -42,3 +38,57 @@ main(int argc, char **argv)
        content_info_free(cinfo);
        return 0;
 }
+
+int
+try_manifest(char *file_name)
+{
+       struct ContentInfo *cinfo;
+       struct SignedData *sdata;
+       struct Manifest *manifest;
+       int error;
+
+       error = content_info_load(file_name, &cinfo);
+       if (error)
+               return error;
+
+       error = signed_data_decode(&cinfo->content, &sdata);
+       if (error) {
+               content_info_free(cinfo);
+               return error;
+       }
+
+       error = manifest_decode(sdata, &manifest);
+       if (error) {
+               signed_data_free(sdata);
+               content_info_free(cinfo);
+               return error;
+       }
+
+       asn_fprint(stdout, &asn_DEF_Manifest, manifest);
+
+       manifest_free(manifest);
+       signed_data_free(sdata);
+       content_info_free(cinfo);
+       return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+       int error;
+
+       if (argc < 3) {
+               pr_debug0("argc < 3");
+               return -EINVAL;
+       }
+
+//     error = try_roa(argv[1]);
+//     if (error)
+//             return error;
+
+       error = try_manifest(argv[2]);
+       if (error)
+               return error;
+
+       return 0;
+}