From: Alberto Leiva Popper Date: Sat, 24 Feb 2024 01:19:18 +0000 (-0600) Subject: Modernize the hash module X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=154742c3fa1bf14f92ac0b42d02ed8d1d5010a05;p=thirdparty%2FFORT-validator.git Modernize the hash module It seems nowadays libcrypto wants us to - perform "explicit [algorithm] fetching," - cache algorithms to improve performance, - and stop hardcoding algorithms in the code (which largely doesn't really apply in our RFC-bound situation). https://www.openssl.org/docs/man3.0/man7/crypto.html#ALGORITHM-FETCHING So fetch explicitely, cache algorithms and try to keep hardcoding at a minimum. Also, the code was seemingly unaware that hash size depends on algorithm, so this was often validated weakly. --- diff --git a/src/asn1/signed_data.c b/src/asn1/signed_data.c index 301ae23d..068d3b5d 100644 --- a/src/asn1/signed_data.c +++ b/src/asn1/signed_data.c @@ -157,8 +157,9 @@ validate_message_digest_attribute(CMSAttributeValue_t *value, if (error) return error; - error = hash_validate_octet_string("sha256", digest, eci->eContent); - if (error) + error = hash_validate(hash_get_sha256(), eci->eContent->buf, + eci->eContent->size, digest->buf, digest->size); + if (error > 0) pr_val_err("The content's hash does not match the Message-Digest Attribute."); ASN_STRUCT_FREE(asn_DEF_MessageDigest, digest); diff --git a/src/crypto/hash.c b/src/crypto/hash.c index a6e05b6a..740621cc 100644 --- a/src/crypto/hash.c +++ b/src/crypto/hash.c @@ -1,59 +1,111 @@ #include "crypto/hash.h" +#include +#include +#include #include #include "alloc.h" -#include "common.h" #include "file.h" #include "log.h" -#include "asn1/oid.h" -static int -get_md(char const *algorithm, EVP_MD const **result) -{ +/* + * TODO (fine) Delete this structure (use md directly) once OpenSSL < 3 support + * is dropped. + */ +struct hash_algorithm { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MD *md; +#else EVP_MD const *md; +#endif + size_t size; + char const *name; +}; + +/* + * EVP_sha256() and EVP_sha1() are now mildly deprecated ("present for + * compatibility with OpenSSL before version 3.0"). + * + * This is because they want to encourage explicit fetching, but also because + * they want us to stop hardcoding the algorithms in the code. + * + * But we're RFC-bound to use these algorithms, so we only want the explicit + * fetching part. (Which is done during hash_setup().) + */ +static struct hash_algorithm sha1; +static struct hash_algorithm sha256; - md = EVP_get_digestbyname(algorithm); - if (md == NULL) { - pr_val_err("Unknown message digest %s", algorithm); - return -EINVAL; +int +hash_setup(void) +{ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + sha1.md = EVP_MD_fetch(NULL, "SHA1", NULL); + if (sha1.md == NULL) + return pr_op_err("This version of libcrypto does not seem to support SHA1."); + sha1.size = EVP_MD_get_size(sha1.md); + sha1.name = EVP_MD_get0_name(sha1.md); + + sha256.md = EVP_MD_fetch(NULL, "SHA256", NULL); + if (sha256.md == NULL) { + EVP_MD_free(sha1.md); + return pr_op_err("This version of libcrypto does not seem to support SHA256."); } + sha256.size = EVP_MD_get_size(sha256.md); + sha256.name = EVP_MD_get0_name(sha256.md); + +#else + sha1.md = EVP_get_digestbyname("sha1"); + if (sha1.md == NULL) + return pr_op_err("This version of libcrypto does not seem to support SHA1."); + sha1.size = EVP_MD_size(sha1.md); + sha1.name = EVP_MD_name(sha1.md); + + sha256.md = EVP_get_digestbyname("sha256"); + if (sha256.md == NULL) + return pr_op_err("This version of libcrypto does not seem to support SHA256."); + sha256.size = EVP_MD_size(sha256.md); + sha256.name = EVP_MD_name(sha256.md); + +#endif - *result = md; return 0; } -static bool -hash_matches(unsigned char const *expected, size_t expected_len, - unsigned char const *actual, unsigned int actual_len) +void +hash_teardown(void) { - return (expected_len == actual_len) - && (memcmp(expected, actual, expected_len) == 0); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MD_free(sha256.md); + EVP_MD_free(sha1.md); +#endif } -static int -hash_file(struct rpki_uri *uri, unsigned char *result, unsigned int *result_len) +struct hash_algorithm const * +hash_get_sha1(void) +{ + return &sha1; +} + +struct hash_algorithm const * +hash_get_sha256(void) { - return hash_local_file(uri_get_local(uri), result, result_len); + return &sha256; } int -hash_local_file(char const *uri, unsigned char *result, - unsigned int *result_len) +hash_file(struct hash_algorithm const *algorithm, char const *filename, + unsigned char *result, size_t *result_size) { - EVP_MD const *md; FILE *file; struct stat stat; unsigned char *buffer; size_t consumed; EVP_MD_CTX *ctx; + unsigned int hash_size; int error; - error = get_md("sha256", &md); - if (error) - return error; - - error = file_open(uri, &file, &stat); + error = file_open(filename, &file, &stat); if (error) return error; @@ -63,7 +115,7 @@ hash_local_file(char const *uri, unsigned char *result, if (ctx == NULL) enomem_panic(); - if (!EVP_DigestInit_ex(ctx, md, NULL)) { + if (!EVP_DigestInit_ex(ctx, algorithm->md, NULL)) { error = val_crypto_err("EVP_DigestInit_ex() failed"); goto end; } @@ -84,8 +136,17 @@ hash_local_file(char const *uri, unsigned char *result, } while (!feof(file)); - if (!EVP_DigestFinal_ex(ctx, result, result_len)) + if (!EVP_DigestFinal_ex(ctx, result, &hash_size)) { error = val_crypto_err("EVP_DigestFinal_ex() failed"); + goto end; + } + if (hash_size != algorithm->size) { + error = pr_op_err("libcrypto returned a %s hash sized %u bytes.", + algorithm->name, hash_size); + } + + if (result_size) + *result_size = hash_size; end: EVP_MD_CTX_free(ctx); @@ -94,144 +155,84 @@ end: return error; } -/** - * Computes the hash of the file @uri, and compares it to @expected (The - * "expected" hash). - * - * Returns: - * 0 if no errors happened and the hashes match, or the hash doesn't match - * but there's an incidence to ignore such error. - * < 0 if there was an error that can't be ignored. - * > 0 if there was an error but it can be ignored (file not found and there's - * an incidence to ignore this). - */ int -hash_validate_mft_file(struct rpki_uri *uri, BIT_STRING_t const *expected) +hash_validate_file(struct hash_algorithm const *algorithm, struct rpki_uri *uri, + unsigned char const *expected, size_t expected_len) { unsigned char actual[EVP_MAX_MD_SIZE]; - unsigned int actual_len; + size_t actual_len; int error; - if (expected->bits_unused != 0) - return pr_val_err("Hash string has unused bits."); - - do { - error = hash_file(uri, actual, &actual_len); - if (!error) - break; - - if (error == EACCES || error == ENOENT) { - if (incidence(INID_MFT_FILE_NOT_FOUND, - "File '%s' listed at manifest doesn't exist.", - uri_val_get_printable(uri))) - return -EINVAL; - - return error; - } - /* Any other error (crypto, enomem, file read) */ - return ENSURE_NEGATIVE(error); - } while (0); - - if (!hash_matches(expected->buf, expected->size, actual, actual_len)) { - return incidence(INID_MFT_FILE_HASH_NOT_MATCH, - "File '%s' does not match its manifest hash.", - uri_val_get_printable(uri)); - } - - return 0; -} - -/** - * Computes the hash of the file @uri, and compares it to @expected HASH of - * @expected_len. Returns 0 if no errors happened and the hashes match. - */ -int -hash_validate_file(struct rpki_uri *uri, unsigned char const *expected, - size_t expected_len) -{ - unsigned char actual[EVP_MAX_MD_SIZE]; - unsigned int actual_len; - int error; - - error = hash_file(uri, actual, &actual_len); + error = hash_file(algorithm, uri_get_local(uri), actual, &actual_len); if (error) return error; - if (!hash_matches(expected, expected_len, actual, actual_len)) { - return pr_val_err("File '%s' does not match its expected hash.", - uri_val_get_printable(uri)); - } + if (expected_len != actual_len) + goto fail; + if (memcmp(expected, actual, expected_len) != 0) + goto fail; return 0; + +fail: + return pr_val_err("File '%s' does not match its expected hash.", + uri_val_get_printable(uri)); } static int -hash_buffer(char const *algorithm, - unsigned char const *content, size_t content_len, - unsigned char *hash, unsigned int *hash_len) +hash_buffer(struct hash_algorithm const *algorithm, + unsigned char const *content, size_t content_len, unsigned char *hash) { - EVP_MD const *md; EVP_MD_CTX *ctx; - int error; - - error = get_md(algorithm, &md); - if (error) - return error; + unsigned int actual_len; ctx = EVP_MD_CTX_new(); if (ctx == NULL) enomem_panic(); - if (!EVP_DigestInit_ex(ctx, md, NULL) - || !EVP_DigestUpdate(ctx, content, content_len) - || !EVP_DigestFinal_ex(ctx, hash, hash_len)) { - error = val_crypto_err("Buffer hashing failed"); + if (!EVP_DigestInit_ex(ctx, algorithm->md, NULL) || + !EVP_DigestUpdate(ctx, content, content_len) || + !EVP_DigestFinal_ex(ctx, hash, &actual_len)) { + EVP_MD_CTX_free(ctx); + return val_crypto_err("Buffer hashing failed"); } EVP_MD_CTX_free(ctx); - return error; + + if (actual_len != algorithm->size) + pr_crit("libcrypto returned a %s hash sized %u bytes.", + algorithm->name, actual_len); + + return 0; } -/* - * Returns 0 if @data's hash is @expected. Returns error code otherwise. - */ int -hash_validate(char const *algorithm, - unsigned char const *expected, size_t expected_len, - unsigned char const *data, size_t data_len) +hash_validate(struct hash_algorithm const *algorithm, unsigned char const *data, + size_t data_len, unsigned char const *expected, size_t expected_len) { unsigned char actual[EVP_MAX_MD_SIZE]; - unsigned int actual_len; int error; - error = hash_buffer(algorithm, data, data_len, actual, &actual_len); + error = hash_buffer(algorithm, data, data_len, actual); if (error) return error; - return hash_matches(expected, expected_len, actual, actual_len) - ? 0 - : -EINVAL; + if (expected_len != algorithm->size) + return EINVAL; + if (memcmp(expected, actual, expected_len) != 0) + return EINVAL; + + return 0; } -int -hash_validate_octet_string(char const *algorithm, - OCTET_STRING_t const *expected, - OCTET_STRING_t const *data) +char const * +hash_get_name(struct hash_algorithm const *algorithm) { - return hash_validate(algorithm, expected->buf, expected->size, - data->buf, data->size); + return algorithm->name; } -/* - * Hash the @str using the specified @algorithm, setting the result at the - * @result buffer and its length at @result_len. - * - * Return 0 on success, any other value means error. - */ -int -hash_str(char const *algorithm, char const *str, unsigned char *result, - unsigned int *result_len) +size_t +hash_get_size(struct hash_algorithm const *algorithm) { - return hash_buffer(algorithm, (unsigned char const *) str, strlen(str), - result, result_len); + return algorithm->size; } diff --git a/src/crypto/hash.h b/src/crypto/hash.h index f27fc336..6426b1a3 100644 --- a/src/crypto/hash.h +++ b/src/crypto/hash.h @@ -1,18 +1,26 @@ #ifndef SRC_HASH_H_ #define SRC_HASH_H_ +#include #include "types/uri.h" -#include "asn1/asn1c/BIT_STRING.h" -int hash_validate_mft_file(struct rpki_uri *uri, BIT_STRING_t const *); -int hash_validate_file(struct rpki_uri *, unsigned char const *, size_t); -int hash_validate(char const *, unsigned char const *, size_t, - unsigned char const *, size_t); -int hash_validate_octet_string(char const *, OCTET_STRING_t const*, - OCTET_STRING_t const *); +struct hash_algorithm; + +int hash_setup(void); +void hash_teardown(void); + +struct hash_algorithm const *hash_get_sha1(void); +struct hash_algorithm const *hash_get_sha256(void); -int hash_local_file(char const *, unsigned char *, unsigned int *); +int hash_file(struct hash_algorithm const *, char const *, unsigned char *, + size_t *); + +int hash_validate_file(struct hash_algorithm const *, struct rpki_uri *, + unsigned char const *, size_t); +int hash_validate(struct hash_algorithm const *, unsigned char const *, size_t, + unsigned char const *, size_t); -int hash_str(char const *, char const *, unsigned char *, unsigned int *); +char const *hash_get_name(struct hash_algorithm const *); +size_t hash_get_size(struct hash_algorithm const *); #endif /* SRC_HASH_H_ */ diff --git a/src/extension.c b/src/extension.c index 11d3e3c3..97cc6c85 100644 --- a/src/extension.c +++ b/src/extension.c @@ -242,7 +242,7 @@ cannot_decode(struct extension_metadata const *meta) * Otherwise returns error code. */ int -validate_public_key_hash(X509 *cert, ASN1_OCTET_STRING *hash) +validate_public_key_hash(X509 *cert, ASN1_OCTET_STRING *hash, char const *hash_name) { X509_PUBKEY *pubkey; const unsigned char *spk; @@ -290,20 +290,16 @@ validate_public_key_hash(X509 *cert, ASN1_OCTET_STRING *hash) if (!ok) return val_crypto_err("X509_PUBKEY_get0_param() returned %d", ok); - /* Hash the SPK, compare SPK hash with the SKI */ - if (hash->length < 0 || SIZE_MAX < hash->length) { - return pr_val_err("%s length (%d) is out of bounds. (0-%zu)", - ext_ski()->name, hash->length, SIZE_MAX); - } + /* FIXME the max limit needs to be a lot less than SIZE_MAX. */ if (spk_len < 0 || SIZE_MAX < spk_len) { - return pr_val_err("Subject Public Key length (%d) is out of bounds. (0-%zu)", + return pr_val_err("The Subject Public Key length (%d) is out of bounds. (0-%zu)", spk_len, SIZE_MAX); } - error = hash_validate("sha1", hash->data, hash->length, spk, spk_len); - if (error) { + error = hash_validate(hash_get_sha1(), spk, spk_len, hash->data, hash->length); + if (error > 0) { pr_val_err("The Subject Public Key's hash does not match the %s.", - ext_ski()->name); + hash_name); } return error; @@ -339,7 +335,7 @@ handle_aki(X509_EXTENSION *ext, void *arg) goto end; } - error = validate_public_key_hash(parent, aki->keyid); + error = validate_public_key_hash(parent, aki->keyid, "AKI"); end: AUTHORITY_KEYID_free(aki); diff --git a/src/extension.h b/src/extension.h index 33a4022d..6dada3b8 100644 --- a/src/extension.h +++ b/src/extension.h @@ -44,7 +44,7 @@ int handle_extensions(struct extension_handler *, STACK_OF(X509_EXTENSION) const *); int cannot_decode(struct extension_metadata const *); -int validate_public_key_hash(X509 *, ASN1_OCTET_STRING *); +int validate_public_key_hash(X509 *, ASN1_OCTET_STRING *, char const *); int handle_aki(X509_EXTENSION *, void *); #endif /* SRC_EXTENSION_H_ */ diff --git a/src/main.c b/src/main.c index 62ac29de..88c56379 100644 --- a/src/main.c +++ b/src/main.c @@ -5,6 +5,7 @@ #include "log.h" #include "nid.h" #include "thread_var.h" +#include "crypto/hash.h" #include "http/http.h" #include "incidence/incidence.h" #include "rtr/rtr.h" @@ -149,9 +150,12 @@ main(int argc, char **argv) error = extension_init(); if (error) goto revert_nid; - error = http_init(); + error = hash_setup(); if (error) goto revert_nid; + error = http_init(); + if (error) + goto revert_hash; error = relax_ng_init(); if (error) @@ -178,6 +182,8 @@ revert_relax_ng: relax_ng_cleanup(); revert_http: http_cleanup(); +revert_hash: + hash_teardown(); revert_nid: nid_destroy(); revert_config: diff --git a/src/object/certificate.c b/src/object/certificate.c index e3194d48..407c6e9f 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -1263,7 +1263,7 @@ handle_ski_ca(X509_EXTENSION *ext, void *arg) if (ski == NULL) return cannot_decode(ext_ski()); - error = validate_public_key_hash(arg, ski); + error = validate_public_key_hash(arg, ski, "SKI"); ASN1_OCTET_STRING_free(ski); return error; @@ -1282,7 +1282,7 @@ handle_ski_ee(X509_EXTENSION *ext, void *arg) return cannot_decode(ext_ski()); args = arg; - error = validate_public_key_hash(args->cert, ski); + error = validate_public_key_hash(args->cert, ski, "SKI"); if (error) goto end; diff --git a/src/object/manifest.c b/src/object/manifest.c index 3d1739d8..4ee6c1c1 100644 --- a/src/object/manifest.c +++ b/src/object/manifest.c @@ -188,6 +188,63 @@ validate_manifest(struct Manifest *manifest) return 0; } +/** + * Computes the hash of the file @uri, and compares it to @expected (The + * "expected" hash). + * + * Returns: + * 0 if no errors happened and the hashes match, or the hash doesn't match + * but there's an incidence to ignore such error. + * < 0 if there was an error that can't be ignored. + * > 0 if there was an error but it can be ignored (file not found and there's + * an incidence to ignore this). + */ +static int +hash_validate_mft_file(struct rpki_uri *uri, BIT_STRING_t const *expected) +{ + struct hash_algorithm const *algorithm; + size_t hash_size; + unsigned char actual[EVP_MAX_MD_SIZE]; + int error; + + algorithm = hash_get_sha256(); + hash_size = hash_get_size(algorithm); + + if (expected->size != hash_size) + return pr_val_err("%s string has bogus size: %zu", + hash_get_name(algorithm), expected->size); + if (expected->bits_unused != 0) + return pr_val_err("Hash string has unused bits."); + + /* + * TODO (#82) This is atrocious. Implement RFC 9286, and probably reuse + * hash_validate_file(). + */ + + error = hash_file(algorithm, uri_get_local(uri), actual, NULL); + if (error) { + if (error == EACCES || error == ENOENT) { + /* FIXME .................. */ + if (incidence(INID_MFT_FILE_NOT_FOUND, + "File '%s' listed at manifest doesn't exist.", + uri_val_get_printable(uri))) + return -EINVAL; + + return error; + } + /* Any other error (crypto, file read) */ + return ENSURE_NEGATIVE(error); + } + + if (memcmp(expected->buf, actual, hash_size) != 0) { + return incidence(INID_MFT_FILE_HASH_NOT_MATCH, + "File '%s' does not match its manifest hash.", + uri_val_get_printable(uri)); + } + + return 0; +} + static int build_rpp(struct Manifest *mft, struct rpki_uri *notif, struct rpki_uri *mft_uri, struct rpp **pp) diff --git a/src/rrdp.c b/src/rrdp.c index a8251b6e..e285335a 100644 --- a/src/rrdp.c +++ b/src/rrdp.c @@ -152,7 +152,8 @@ update_notification_cleanup(struct update_notification *file) static int validate_hash(struct file_metadata *meta) { - return hash_validate_file(meta->uri, meta->hash, meta->hash_len); + return hash_validate_file(hash_get_sha256(), meta->uri, meta->hash, + meta->hash_len); } /* Left trim @from, setting the result at @result pointer */ diff --git a/src/slurm/db_slurm.h b/src/slurm/db_slurm.h index 5dd988fb..2882cd0d 100644 --- a/src/slurm/db_slurm.h +++ b/src/slurm/db_slurm.h @@ -30,8 +30,12 @@ struct slurm_bgpsec { }; struct slurm_file_csum { + /* + * Actual length is SHA256_DIGEST_LENGTH, but the documentation of + * EVP_DigestFinal_ex() doesn't say we can allocate less. + */ unsigned char csum[EVP_MAX_MD_SIZE]; - unsigned int csum_len; + size_t csum_len; SLIST_ENTRY(slurm_file_csum) next; }; diff --git a/src/slurm/slurm_loader.c b/src/slurm/slurm_loader.c index 6562a469..2c0abd04 100644 --- a/src/slurm/slurm_loader.c +++ b/src/slurm/slurm_loader.c @@ -132,7 +132,7 @@ __slurm_load_checksums(char const *location, void *arg) csum = pmalloc(sizeof(struct slurm_file_csum)); - if (hash_local_file(location, csum->csum, &csum->csum_len) != 0) { + if (hash_file(hash_get_sha256(), location, csum->csum, &csum->csum_len) != 0) { free(csum); return pr_op_err("Calculating slurm hash"); } diff --git a/test/Makefile.am b/test/Makefile.am index 6b528020..b9d1a415 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -26,6 +26,7 @@ check_PROGRAMS = address.test check_PROGRAMS += cache.test check_PROGRAMS += db_table.test check_PROGRAMS += deltas_array.test +check_PROGRAMS += hash.test check_PROGRAMS += line_file.test check_PROGRAMS += pb.test check_PROGRAMS += pdu_handler.test @@ -53,6 +54,9 @@ db_table_test_LDADD = ${MY_LDADD} deltas_array_test_SOURCES = rtr/db/deltas_array_test.c deltas_array_test_LDADD = ${MY_LDADD} +hash_test_SOURCES = crypto/hash_test.c +hash_test_LDADD = ${MY_LDADD} + line_file_test_SOURCES = line_file_test.c line_file_test_LDADD = ${MY_LDADD} @@ -93,9 +97,10 @@ xml_test_SOURCES = xml_test.c xml_test_LDADD = ${MY_LDADD} ${XML2_LIBS} EXTRA_DIST = mock.c mock.h -EXTRA_DIST += line_file/core.txt -EXTRA_DIST += line_file/empty.txt -EXTRA_DIST += line_file/error.txt +EXTRA_DIST += resources/lorem-ipsum.txt +EXTRA_DIST += resources/line_file/core.txt +EXTRA_DIST += resources/line_file/empty.txt +EXTRA_DIST += resources/line_file/error.txt EXTRA_DIST += rtr/db/rtr_db_mock.c EXTRA_DIST += tal/lacnic.tal EXTRA_DIST += xml/notification.xml diff --git a/test/crypto/hash_test.c b/test/crypto/hash_test.c new file mode 100644 index 00000000..ac284dba --- /dev/null +++ b/test/crypto/hash_test.c @@ -0,0 +1,110 @@ +#include +#include + +#include "alloc.c" +#include "common.c" +#include "file.c" +#include "mock.c" +#include "data_structure/path_builder.c" +#include "types/uri.c" +#include "crypto/hash.c" + +/* Actually mostly tests libcrypto's sanity, not Fort's. */ +START_TEST(test_hash) +{ + static unsigned char FORT_SHA1[] = { + 0xe5, 0x79, 0x65, 0xf7, 0x36, 0xd2, 0x9d, 0x43, 0xde, 0x05, + 0xf7, 0x02, 0x86, 0xa7, 0xf4, 0xcc, 0x5b, 0x74, 0x8c, 0xa7 + }; + static unsigned char FORT_SHA256[] = { + 0xb6, 0x9f, 0xee, 0xa9, 0xef, 0xa8, 0x61, 0x5c, 0xd4, 0x91, + 0x95, 0x7b, 0x7e, 0xf8, 0x28, 0xef, 0xb4, 0x10, 0xc2, 0xdd, + 0x67, 0x6c, 0xa0, 0x63, 0x75, 0x9a, 0x68, 0x9a, 0xf4, 0xfe, + 0xf9, 0xb1 + }; + + static unsigned char FILE_SHA1[] = { + 0xea, 0x3c, 0xa1, 0xc6, 0xe2, 0x3a, 0x70, 0x1a, 0xe8, 0x97, + 0xec, 0x0b, 0xf0, 0xa2, 0x20, 0x66, 0xe1, 0xf8, 0x8b, 0xb5 + }; + + static unsigned char FILE_SHA256[] = { + 0x00, 0xb8, 0x08, 0xa1, 0x60, 0x5e, 0x13, 0xfe, 0xb6, 0xc5, + 0x71, 0x67, 0x1f, 0xb2, 0x29, 0x2b, 0xa8, 0x7f, 0x0f, 0x28, + 0xed, 0xe3, 0xe0, 0xe3, 0x51, 0xfe, 0xd8, 0xf5, 0x7c, 0xad, + 0x68, 0x06 + }; + + struct hash_algorithm const *ha; + char const *name; + char const *input = "Fort"; + struct rpki_uri uri = { 0 }; + + hash_setup(); + + uri.local = "resources/lorem-ipsum.txt"; + + ha = hash_get_sha1(); + ck_assert_uint_eq(20, hash_get_size(ha)); + name = hash_get_name(ha); + ck_assert(strcasecmp("sha1", name) || strcasecmp("sha-1", name)); + + ck_assert_int_eq(0, hash_validate(ha, (unsigned char *)input, strlen(input), FORT_SHA1, sizeof(FORT_SHA1))); + ck_assert_int_eq(EINVAL, hash_validate(ha, (unsigned char *)input, strlen(input), FORT_SHA1, sizeof(FORT_SHA1) - 1)); + FORT_SHA1[1] = 1; + ck_assert_int_eq(EINVAL, hash_validate(ha, (unsigned char *)input, strlen(input), FORT_SHA1, sizeof(FORT_SHA1))); + + ck_assert_int_eq(0, hash_validate_file(ha, &uri, FILE_SHA1, sizeof(FILE_SHA1))); + ck_assert_int_eq(-EINVAL, hash_validate_file(ha, &uri, FILE_SHA1, sizeof(FILE_SHA1) - 10)); + FILE_SHA1[19] = 0; + ck_assert_int_eq(-EINVAL, hash_validate_file(ha, &uri, FILE_SHA1, sizeof(FILE_SHA1))); + + ha = hash_get_sha256(); + ck_assert_uint_eq(32, hash_get_size(ha)); + name = hash_get_name(ha); + ck_assert(strcasecmp("sha256", name) || strcasecmp("sha-256", name)); + + ck_assert_int_eq(0, hash_validate(ha, (unsigned char *)input, strlen(input), FORT_SHA256, sizeof(FORT_SHA256))); + ck_assert_int_eq(EINVAL, hash_validate(ha, (unsigned char *)input, strlen(input), FORT_SHA256, sizeof(FORT_SHA256) - 6)); + FORT_SHA256[10] = 0; + ck_assert_int_eq(EINVAL, hash_validate(ha, (unsigned char *)input, strlen(input), FORT_SHA256, sizeof(FORT_SHA256))); + + ck_assert_int_eq(0, hash_validate_file(ha, &uri, FILE_SHA256, sizeof(FILE_SHA256))); + ck_assert_int_eq(-EINVAL, hash_validate_file(ha, &uri, FILE_SHA256, sizeof(FILE_SHA256) - 1)); + FILE_SHA256[31] = 10; + ck_assert_int_eq(-EINVAL, hash_validate_file(ha, &uri, FILE_SHA256, sizeof(FILE_SHA256))); + + hash_teardown(); +} +END_TEST + +static Suite * +pdu_suite(void) +{ + Suite *suite; + TCase *core; + + core = tcase_create("hash"); + tcase_add_test(core, test_hash); + + suite = suite_create("hash"); + suite_add_tcase(suite, core); + return suite; +} + +int +main(int argc, char **argv) +{ + Suite *suite; + SRunner *runner; + int tests_failed; + + suite = pdu_suite(); + + runner = srunner_create(suite); + srunner_run_all(runner, CK_NORMAL); + tests_failed = srunner_ntests_failed(runner); + srunner_free(runner); + + return (tests_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/test/line_file_test.c b/test/line_file_test.c index 21a8f047..ff0d00c0 100644 --- a/test/line_file_test.c +++ b/test/line_file_test.c @@ -15,7 +15,7 @@ START_TEST(file_line_normal) size_t SENTENCE_LEN; unsigned int i; - ck_assert_int_eq(lfile_open("line_file/core.txt", &lfile), 0); + ck_assert_int_eq(lfile_open("resources/line_file/core.txt", &lfile), 0); ck_assert_int_eq(lfile_read(lfile, &string), 0); ck_assert_str_eq(string, "This is a normal line."); @@ -60,7 +60,7 @@ START_TEST(file_line_empty) struct line_file *lfile; char *string; - ck_assert_int_eq(lfile_open("line_file/empty.txt", &lfile), 0); + ck_assert_int_eq(lfile_open("resources/line_file/empty.txt", &lfile), 0); ck_assert_int_eq(lfile_read(lfile, &string), 0); ck_assert(string == NULL); @@ -74,7 +74,7 @@ START_TEST(file_line_null_chara) struct line_file *lfile; char *string; - ck_assert_int_eq(lfile_open("line_file/error.txt", &lfile), 0); + ck_assert_int_eq(lfile_open("resources/line_file/error.txt", &lfile), 0); ck_assert_int_eq(lfile_read(lfile, &string), 0); ck_assert_str_eq(string, "This is a normal line."); diff --git a/test/line_file/core.txt b/test/resources/line_file/core.txt similarity index 100% rename from test/line_file/core.txt rename to test/resources/line_file/core.txt diff --git a/test/line_file/empty.txt b/test/resources/line_file/empty.txt similarity index 100% rename from test/line_file/empty.txt rename to test/resources/line_file/empty.txt diff --git a/test/line_file/error.txt b/test/resources/line_file/error.txt similarity index 100% rename from test/line_file/error.txt rename to test/resources/line_file/error.txt diff --git a/test/resources/lorem-ipsum.txt b/test/resources/lorem-ipsum.txt new file mode 100644 index 00000000..8deed24a --- /dev/null +++ b/test/resources/lorem-ipsum.txt @@ -0,0 +1,9 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. In a malesuada neque. Nunc efficitur at leo ac feugiat. Aliquam velit erat, molestie nec nulla vitae, accumsan accumsan ipsum. Nunc mattis quam sit amet turpis sollicitudin fringilla. Sed id ante finibus, finibus erat in, vestibulum lectus. Aenean sed massa ut lacus efficitur sollicitudin. Mauris at imperdiet augue. Maecenas tempus ornare odio, egestas faucibus ante commodo id. Morbi at urna nisl. Phasellus gravida felis non erat ornare, at mattis magna venenatis. In ac lorem vel est euismod finibus. Nam mauris felis, laoreet id eros sed, suscipit gravida justo. In a dictum erat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. + +Ut sagittis nec risus vitae cursus. Mauris id ipsum sem. Sed bibendum mauris orci, eget tincidunt massa vehicula dapibus. Vivamus lobortis tellus et molestie euismod. Integer venenatis diam ut libero dapibus, in dictum tortor dictum. Nulla at ante magna. Vivamus lectus orci, efficitur a semper eget, facilisis eget orci. + +Maecenas venenatis lacus et est pharetra fermentum. Curabitur auctor rhoncus enim. Aliquam ut nisi suscipit, semper enim vitae, viverra quam. Aenean neque turpis, aliquam ut metus ac, tempus porta orci. Nam at nunc eu velit porta sagittis. Quisque ullamcorper diam dolor, sit amet convallis lacus dignissim et. Nullam dictum tortor lectus. + +Curabitur tortor sapien, auctor id laoreet nec, facilisis in mauris. Maecenas tellus nisl, sollicitudin sit amet pulvinar eu, dictum eu ligula. Vivamus vel fringilla turpis, at mattis neque. Aenean venenatis dapibus urna ac pulvinar. Cras ut ante a ipsum volutpat pellentesque. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nulla facilisi. Aliquam ultrices nibh vel turpis laoreet tristique. + +Aliquam in orci sed lectus dapibus mollis sit amet nec ligula. Aliquam nec neque enim. Ut rutrum pulvinar urna a gravida. Ut vulputate tortor vitae risus molestie, quis accumsan sapien elementum. Nulla facilisi. Suspendisse potenti. Nam lacus tortor, condimentum eget eleifend sed, fermentum a lorem. Mauris sit amet quam at eros maximus eleifend vel quis metus. Fusce molestie feugiat orci. Morbi aliquet nec diam vel fermentum. Nullam fermentum eget odio eu dapibus. Praesent varius aliquet ante sit amet vehicula. Aliquam sed enim ut dui malesuada pellentesque eget finibus urna. diff --git a/test/rrdp_test.c b/test/rrdp_test.c index 18ef8368..6e292cb8 100644 --- a/test/rrdp_test.c +++ b/test/rrdp_test.c @@ -22,8 +22,8 @@ MOCK_ABORT_INT(delete_dir_recursive_bottom_up, char const *path) MOCK_ABORT_INT(mkdir_p, char const *path, bool include_basename) MOCK_ABORT_VOID(fnstack_pop, void) MOCK_ABORT_VOID(fnstack_push_uri, struct rpki_uri *uri) -MOCK_ABORT_INT(hash_validate_file, struct rpki_uri *uri, - unsigned char const *expected, size_t expected_len) +MOCK_ABORT_INT(hash_validate_file, struct hash_algorithm const *algorithm, + struct rpki_uri *uri, unsigned char const *expected, size_t expected_len) MOCK_ABORT_INT(relax_ng_parse, const char *path, xml_read_cb cb, void *arg) MOCK_ABORT_PTR(state_retrieve, validation, void) __MOCK_ABORT(tal_get_file_name, char const *, NULL, struct tal *tal)