From 65a5fb827610ed6b433206be7ecd15f4bec18ced Mon Sep 17 00:00:00 2001 From: Otavio Pontes Date: Thu, 22 Aug 2019 12:24:14 -0700 Subject: [PATCH] signature: Create a helper to verify the signature on files in memory Signed-off-by: Otavio Pontes --- src/signature.c | 157 +++++++++++++++++++++++++++--------------------- src/signature.h | 16 +++++ 2 files changed, 105 insertions(+), 68 deletions(-) diff --git a/src/signature.c b/src/signature.c index 6e4fc515..fa9b919d 100644 --- a/src/signature.c +++ b/src/signature.c @@ -148,50 +148,21 @@ void signature_deinit(void) CRYPTO_cleanup_all_ex_data(); } -/* Verifies that the file and the signature exists, and does a signature check - * afterwards. If any error is to be considered a verify failure, then - * print_errors should be set to true. - * - * returns: true if able to validate the signature, false otherwise */ -bool signature_verify(const char *file, const char *sig_file, bool print_errors) +bool signature_verify_data(const unsigned char *data, size_t data_len, const unsigned char *sig_data, size_t sig_data_len, bool print_errors) + { - int ret; bool result = false; - struct stat st; - char *errorstr = NULL; + int ret; - int data_fd = -1; - size_t data_len; - unsigned char *data = NULL; - BIO *data_BIO = NULL; - - int sig_fd = -1; - size_t sig_len; - unsigned char *sig = NULL; BIO *sig_BIO = NULL; - - PKCS7 *p7 = NULL; + BIO *data_BIO = NULL; BIO *verify_BIO = NULL; + char *errorstr = NULL; + PKCS7 *p7 = NULL; - /* get the signature */ - sig_fd = open(sig_file, O_RDONLY); - if (sig_fd == -1) { - string_or_die(&errorstr, "Failed open %s: %s\n", sig_file, strerror(errno)); - goto error; - } - if (fstat(sig_fd, &st) != 0) { - string_or_die(&errorstr, "Failed to stat %s file\n", sig_file); - goto error; - } - sig_len = st.st_size; - sig = mmap(NULL, sig_len, PROT_READ, MAP_PRIVATE, sig_fd, 0); - if (sig == MAP_FAILED) { - string_or_die(&errorstr, "Failed to mmap %s signature\n", sig_file); - goto error; - } - sig_BIO = BIO_new_mem_buf(sig, sig_len); + sig_BIO = BIO_new_mem_buf(sig_data, sig_data_len); if (!sig_BIO) { - string_or_die(&errorstr, "Failed to read %s signature into BIO\n", sig_file); + string_or_die(&errorstr, "Unable to load signature data into BIO\n"); goto error; } @@ -202,26 +173,9 @@ bool signature_verify(const char *file, const char *sig_file, bool print_errors) goto error; } - /* get the data to be verified */ - - data_fd = open(file, O_RDONLY); - if (data_fd == -1) { - string_or_die(&errorstr, "Failed open %s\n", file); - goto error; - } - if (fstat(data_fd, &st) != 0) { - string_or_die(&errorstr, "Failed to stat %s\n", file); - goto error; - } - data_len = st.st_size; - data = mmap(NULL, data_len, PROT_READ, MAP_PRIVATE, data_fd, 0); - if (data == MAP_FAILED) { - string_or_die(&errorstr, "Failed to mmap %s\n", file); - goto error; - } data_BIO = BIO_new_mem_buf(data, data_len); if (!data_BIO) { - string_or_die(&errorstr, "Failed to read %s into BIO\n", file); + string_or_die(&errorstr, "Unable to load data into BIO\n"); goto error; } @@ -240,6 +194,86 @@ bool signature_verify(const char *file, const char *sig_file, bool print_errors) string_or_die(&errorstr, "Signature check failed!\n"); } +error: + + if (!result && print_errors) { + error("Signature check error\n%s", errorstr); + ERR_print_errors_fp(stderr); + } + + free_string(&errorstr); + + if (sig_BIO) { + BIO_free(sig_BIO); + } + if (data_BIO) { + BIO_free(data_BIO); + } + if (verify_BIO) { + BIO_free(verify_BIO); + } + if (p7) { + PKCS7_free(p7); + } + + return result; +} + +/* Verifies that the file and the signature exists, and does a signature check + * afterwards. If any error is to be considered a verify failure, then + * print_errors should be set to true. + * + * returns: true if able to validate the signature, false otherwise */ +bool signature_verify(const char *file, const char *sig_file, bool print_errors) +{ + struct stat st; + char *errorstr = NULL; + bool result = false; + + int data_fd = -1; + size_t data_len; + unsigned char *data = NULL; + + int sig_fd = -1; + size_t sig_len; + unsigned char *sig = NULL; + + /* get the signature */ + sig_fd = open(sig_file, O_RDONLY); + if (sig_fd == -1) { + string_or_die(&errorstr, "Failed open %s: %s\n", sig_file, strerror(errno)); + goto error; + } + if (fstat(sig_fd, &st) != 0) { + string_or_die(&errorstr, "Failed to stat %s file\n", sig_file); + goto error; + } + sig_len = st.st_size; + sig = mmap(NULL, sig_len, PROT_READ, MAP_PRIVATE, sig_fd, 0); + if (sig == MAP_FAILED) { + string_or_die(&errorstr, "Failed to mmap %s signature\n", sig_file); + goto error; + } + /* get the data to be verified */ + + data_fd = open(file, O_RDONLY); + if (data_fd == -1) { + string_or_die(&errorstr, "Failed open %s\n", file); + goto error; + } + if (fstat(data_fd, &st) != 0) { + string_or_die(&errorstr, "Failed to stat %s\n", file); + goto error; + } + data_len = st.st_size; + data = mmap(NULL, data_len, PROT_READ, MAP_PRIVATE, data_fd, 0); + if (data == MAP_FAILED) { + string_or_die(&errorstr, "Failed to mmap %s\n", file); + goto error; + } + + result = signature_verify_data(data, data_len, sig, sig_len, print_errors); + error: if (!result && print_errors) { error("Signature check error\n%s", errorstr); @@ -260,19 +294,6 @@ error: if (data_fd >= 0) { close(data_fd); } - if (sig_BIO) { - BIO_free(sig_BIO); - } - if (data_BIO) { - BIO_free(data_BIO); - } - if (verify_BIO) { - BIO_free(verify_BIO); - } - if (p7) { - PKCS7_free(p7); - } - return result; } diff --git a/src/signature.h b/src/signature.h index a1fbb213..b6371e14 100644 --- a/src/signature.h +++ b/src/signature.h @@ -41,6 +41,22 @@ void signature_deinit(void); */ bool signature_verify(const char *file, const char *sig_file, bool print_errors); +/** + * Verify signature of a file in memory. + * + * Works like signature_verify(), but instead of pointing to file names + * in disk, the content of the files should be in memory. + * + * @param data Data to be verified + * @param data_len Length of data in bytes + * @param sig Data to be verified + * @param sig_len Length of data in bytes + * @param print_errors if false, errors aren't printed. + * + * @return true if the file is signed with certificate used signature_init() + */ +bool signature_verify_data(const unsigned char *data, size_t data_len, const unsigned char *sig_data, size_t sig_data_len, bool print_errors); + #ifdef __cplusplus } #endif