From: Alberto Leiva Popper Date: Thu, 27 Sep 2018 21:56:50 +0000 (-0500) Subject: Implement about 40% of RFC 6486 (Manifests) X-Git-Tag: v0.0.2~125 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d5a070b3095c3a87d12af3ca516ed2e17a43d59f;p=thirdparty%2FFORT-validator.git Implement about 40% of RFC 6486 (Manifests) --- diff --git a/configure.ac b/configure.ac index f01b3f71..75070bb9 100644 --- a/configure.ac +++ b/configure.ac @@ -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. diff --git a/src/Makefile.am b/src/Makefile.am index 54878e0f..042c7e7c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 index 00000000..8e4d802e --- /dev/null +++ b/src/asn1/manifest.c @@ -0,0 +1,187 @@ +#include "asn1/manifest.h" + +#include +#include +#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 index 00000000..48434cee --- /dev/null +++ b/src/asn1/manifest.h @@ -0,0 +1,10 @@ +#ifndef SRC_ASN1_MANIFEST_H_ +#define SRC_ASN1_MANIFEST_H_ + +#include +#include + +int manifest_decode(struct SignedData *sdata, struct Manifest **mf); +void manifest_free(struct Manifest *mf); + +#endif /* SRC_ASN1_MANIFEST_H_ */ diff --git a/src/asn1/oid.h b/src/asn1/oid.h index c14c5adb..187bc0b5 100644 --- a/src/asn1/oid.h +++ b/src/asn1/oid.h @@ -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 }; diff --git a/src/file.c b/src/file.c index ea4d9004..3f3047b8 100644 --- a/src/file.c +++ b/src/file.c @@ -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"); diff --git a/src/main.c b/src/main.c index 2cc95662..3ec6c27e 100644 --- a/src/main.c +++ b/src/main.c @@ -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; +}