Implement signature verification

This patch adds functionality for the swupd client to do signature
verification on the MoM, which ensures a root of trust for the rest
of the update by guaranteeing the authenticity of the MoM and content
it includes.

As we focus now on just verifying the signed MoM, a number of functions now
become static to src/signature.c.

By default MoM signature verification is disabled.  Configure
--enable-signature-verification to enable it.  When enabled the default
cert for verification is /usr/share/clear/update-ca/ClearLinuxRoot.pem, as
specified by concatenation of SWUPDCERT onto UPDATE_CA_CERTS_PATH.  The
SWUPDCERT can be overridden via configure --with-swupdcert=some.pem.

When signature verification is enabled, and the MoM's signature does _NOT_
verify, currently only a warning is presented but the swupd operation
continues.  In the future signature verification will become mandatory.
We first need to sort out a few details with mixer to insure the right
thing happens there.

Signed-off-by: Tim Pepper <timothy.c.pepper@linux.intel.com>
Signed-off-by: Tudor Marcu <tudor.marcu@intel.com>
This commit is contained in:
Tim Pepper
2016-06-24 15:12:28 -07:00
parent a384265d88
commit 97f46edd52
9 changed files with 406 additions and 222 deletions
+1 -1
View File
@@ -90,7 +90,7 @@ swupd_sig_verifytest_LDADD = $(SWUPD_CORE_LIBS)
noinst_HEADERS = $(top_srcdir)/include/*
swupdcertsdir = @swupdcertsdir@
swupdcertsdir = @update_ca_certs_path@
SWUPD_CERTS = certs/157753a5.0 \
certs/425b0f6b.0 \
certs/425b0f6b.key \
+19 -9
View File
@@ -11,11 +11,7 @@ AM_SILENT_RULES([yes])
AC_PROG_CC
AM_PROG_CC_C_O
AC_LANG(C)
AC_ARG_WITH([swupdcertsdir],
[AS_HELP_STRING([--with-swupdcertsdir=DIR], [swupdcertsdir files])],
[swupdcertsdir=$withval],
[swupdcertsdir="/usr/share/clear/update-ca"])
AC_SUBST([swupdcertsdir], [$swupdcertsdir])
AC_CONFIG_HEADERS([config.h])
PKG_CHECK_MODULES([bsdiff], [bsdiff])
PKG_CHECK_MODULES([lzma], [liblzma])
@@ -29,6 +25,19 @@ AS_IF([test "x$enable_bzip2" != "xno" ],
AC_CHECK_LIB([bz2], [BZ2_bzBuffToBuffCompress], [], [AC_MSG_ERROR([the libbz2 library is missing])])],
[AC_DEFINE(SWUPD_WITHOUT_BZIP2,1,[Do not use bzip2 compression])]
)
AC_ARG_ENABLE(
[signature-verification],
[AS_HELP_STRING([--enable-signature-verification], [Enable signature check (disabled by default)])],
[AC_DEFINE([SIGNATURES], [], [Enable signature check as default])]
)
if test "$enable_signature_verification" = "yes" ; then
AC_ARG_WITH([swupdcert],
[AS_HELP_STRING([--with-swupdcert=FILE], [swupd verification cert])],
[AC_DEFINE_UNQUOTED([SWUPDCERT], ["$withval"], [swupd verification cert])],
[AC_DEFINE([SWUPDCERT], ["ClearLinuxRoot.pem"], [swupd verification cert])])
fi
AC_ARG_ENABLE(
[tests],
@@ -83,12 +92,13 @@ AS_IF([test "$enable_tests" != "no"], [
AM_CONDITIONAL([ENABLE_TESTS], [test "$enable_tests" != "no"])
PKG_CHECK_MODULES([curl], [libcurl])
PKG_CHECK_MODULES([openssl], [libcrypto >= 0.9.8])
PKG_CHECK_MODULES([openssl], [libcrypto >= 1.0.2])
AC_CHECK_LIB([pthread], [pthread_create])
AC_CHECK_PROGS(TAR, tar)
# default to Linux rootfs build
enable_linux_rootfs_build="yes"
certs_path="/usr/share/clear/update-ca"
# document all options for build variants
## (1) build variants
@@ -103,7 +113,6 @@ AH_TEMPLATE([LOG_DIR],[Directory for swupd log files])
AH_TEMPLATE([LOCK_DIR],[Directory for lock file])
AH_TEMPLATE([BUNDLES_DIR],[Directory to use for bundles])
AH_TEMPLATE([UPDATE_CA_CERTS_PATH],[Location of CA certificates])
AH_TEMPLATE([SIGNATURE_CA_CERT],[CA certificate to use])
AH_TEMPLATE([MOTD_FILE],[motd file path])
if test "$enable_linux_rootfs_build" = "yes"; then
@@ -113,13 +122,14 @@ if test "$enable_linux_rootfs_build" = "yes"; then
AC_DEFINE([LOG_DIR],["/var/log/swupd"])
AC_DEFINE([LOCK_DIR],["/run/lock"])
AC_DEFINE([BUNDLES_DIR],["/usr/share/clear/bundles"])
AC_DEFINE([UPDATE_CA_CERTS_PATH],["/usr/share/clear/update-ca"])
AC_DEFINE([SIGNATURE_CA_CERT],["test-do-not-ship-R0-0.pem"])
AC_DEFINE_UNQUOTED([UPDATE_CA_CERTS_PATH],["$certs_path"])
AC_DEFINE([MOTD_FILE],["/usr/lib/motd.d/001-new-release"])
else
AC_MSG_ERROR([Unknown build variant])
fi
AC_SUBST([update_ca_certs_path], ["$certs_path"])
AC_CONFIG_FILES([Makefile data/check-update.service data/check-update.timer])
AC_REQUIRE_AUX_FILE([tap-driver.sh])
AC_OUTPUT
+1 -27
View File
@@ -3,26 +3,6 @@
#include <stdbool.h>
/*
* Initialize this module.
* @param ca_cert_filename - the file containing the CA certificate
* @return true <=> no error
*/
bool signature_initialize(const char *ca_cert_filename);
/*
* Terminate usage of this module, free resources.
*/
void signature_terminate(void);
/*
* Verify data file contents against a purported signature.
* @param data_filename - the file containing the data
* @param sig_filename - the file containing the signature
* @return true <=> no error
*/
bool signature_verify(const char *data_filename, const char *sig_filename);
/*
* The given data file has already been downloaded from the given URL.
* Download the corresponding signature file, and verify the data against the signature.
@@ -30,12 +10,6 @@ bool signature_verify(const char *data_filename, const char *sig_filename);
* @param data_url - the URL from which the data came
* @param data_filename - the file containing the data
*/
bool signature_download_and_verify(const char *data_url, const char *data_filename);
/*
* Delete the signature file corresponding to given data file.
* @param data_filename - the file containing the data
*/
void signature_delete(const char *data_filename);
bool download_and_verify_signature(const char *data_url, const char *data_filename);
#endif /* SIGNATURE_H_ */
+21 -19
View File
@@ -428,7 +428,7 @@ static int try_delta_manifest_download(int current, int new, char *component, st
struct stat buf;
if (strcmp(component, "MoM") == 0) {
#warning "need to crypto validate MoM and allow delta"
// We don't do MoM deltas.
return -1;
}
@@ -459,16 +459,9 @@ static int try_delta_manifest_download(int current, int new, char *component, st
unlink(deltafile);
goto out;
}
if (!signature_download_and_verify(url, deltafile)) {
ret = -1;
unlink(deltafile);
goto out;
}
}
/* Now apply the manifest delta */
string_or_die(&newfile, "%s/%i/Manifest.%s", state_dir, new, component);
ret = apply_bsdiff_delta(original, newfile, deltafile);
@@ -480,7 +473,6 @@ static int try_delta_manifest_download(int current, int new, char *component, st
}
unlink(deltafile);
signature_delete(deltafile);
out:
free(original);
@@ -494,7 +486,7 @@ out:
/* TODO: This should deal with nested manifests better */
static int retrieve_manifests(int current, int version, char *component, struct file *file)
{
char *url;
char *url = NULL;
char *filename;
char *dir;
int ret = 0;
@@ -503,17 +495,19 @@ static int retrieve_manifests(int current, int version, char *component, struct
string_or_die(&filename, "%s/%i/Manifest.%s.tar", state_dir, version, component);
if (stat(filename, &sb) == 0) {
return 0;
ret = 0;
goto out;
}
if (!check_network()) {
return -ENOSWUPDSERVER;
ret = -ENOSWUPDSERVER;
goto out;
}
string_or_die(&dir, "%s/%i", state_dir, version);
ret = mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if ((ret != 0) && (errno != EEXIST)) {
return ret;
goto out;
}
free(dir);
@@ -532,11 +526,6 @@ static int retrieve_manifests(int current, int version, char *component, struct
goto out;
}
if (!signature_download_and_verify(url, filename)) {
unlink(filename);
goto out;
}
string_or_die(&tar, TAR_COMMAND " -C %s/%i -xf %s/%i/Manifest.%s.tar 2> /dev/null",
state_dir, version, state_dir, version, component);
@@ -588,6 +577,8 @@ struct manifest *load_mom(int version)
{
struct manifest *manifest = NULL;
int ret = 0;
char *filename;
char *url;
ret = retrieve_manifests(version, version, "MoM", NULL);
if (ret != 0) {
@@ -595,14 +586,25 @@ struct manifest *load_mom(int version)
return NULL;
}
string_or_die(&filename, "%s/%i/Manifest.MoM", state_dir, version);
string_or_die(&url, "%s/%i/Manifest.MoM", content_url, version);
if (!download_and_verify_signature(url, filename)) {
printf("WARNING!!! FAILED TO VERIFY SIGNATURE OF Manifest.MoM\n");
}
free(filename);
free(url);
manifest = manifest_from_file(version, "MoM");
if (manifest == NULL) {
printf("Failed to load %d MoM manifest\n", version);
return NULL;
goto out;
}
return manifest;
out:
return NULL;
}
/* Loads the MANIFEST for bundle associated with FILE at VERSION, referenced by
-7
View File
@@ -66,13 +66,6 @@ static int download_pack(int oldversion, int newversion, char *module)
return err;
}
if (!signature_download_and_verify(url, filename)) {
free(url);
unlink(filename);
free(filename);
return -1;
}
free(url);
printf("Extracting pack.\n");
+362 -141
View File
@@ -17,6 +17,8 @@
*
* Authors:
* Tom Keel <thomas.keel@intel.com>
* Tudor Marcu <tudor.marcu@intel.com>
* Tim Pepper <timothy.c.pepper@linux.intel.com>
*
*/
@@ -24,198 +26,417 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/crypto.h>
#include "config.h"
#include "signature.h"
#include "swupd.h"
/*
* Implementation flavors:
* FAKE ..... do nothing, always return success
* FORGIVE .. do everything, always return success
* REAL ..... do everything, return the real status
*/
#define IMPL_FAKE 0
#define IMPL_FORGIVE 1
#define IMPL_REAL 2
#ifdef SIGNATURES
#warning "TODO pick signing scheme"
#if defined(SWUPD_LINUX_ROOTFS)
#define IMPL IMPL_FAKE
#endif
#define CERTNAME UPDATE_CA_CERTS_PATH"/"SWUPDCERT
#if IMPL != IMPL_FAKE
static bool validate_certificate(void);
static int verify_callback(int, X509_STORE_CTX *);
static bool get_pubkey();
static X509_STORE *create_store(const char *, const char *, const char *);
FILE *fp_pubkey = NULL;
static EVP_PKEY *pkey = NULL;
static X509 *cert = NULL;
static X509_STORE *store = NULL;
static STACK_OF(X509) *x509_stack = NULL;
//TODO: static char *chain = NULL;
static char *crl = NULL;
static char *VERIF_FAIL = "Signature verification failed";
static char *XSTORE_FAIL = "XSTORE creation failed";
static bool initialized = false;
static X509_STORE *x509_store = NULL;
bool signature_initialize(const char *ca_cert_filename)
/* This function must be called before trying to sign any file.
* It loads string for errors, and ciphers are auto-loaded by OpenSSL now.
* If this function fails it may be because the certificate cannot
* be validated.
*
* returns: true if can initialize and validate certificates, otherwise false */
static bool initialize_signature(void)
{
if (initialized) {
ERR_load_crypto_strings();
ERR_load_PKCS7_strings();
if (!get_pubkey()) {
goto fail;
}
if (!validate_certificate()) {
goto fail;
}
/* Push our trust cert(s) to the stack, which is a set of certificates
* in which to search for the signer's cert. */
x509_stack = sk_X509_new_null();
if (!x509_stack) {
goto fail;
}
sk_X509_push(x509_stack, cert);
return true;
fail:
return false;
}
/* Delete the memory used for string errors as well as memory allocated for
* certificates and private keys. */
static void terminate_signature(void)
{
//TODO: once implemented, must free chain
//TODO: once implemented, must free crl
if (store) {
X509_STORE_free(store);
store = NULL;
}
if (x509_stack) {
sk_X509_pop_free(x509_stack, X509_free);
x509_stack = NULL;
}
ERR_free_strings();
if (pkey) {
EVP_PKEY_free(pkey);
pkey = NULL;
}
EVP_cleanup();
if (fp_pubkey) {
fclose(fp_pubkey);
}
if (cert) {
cert = NULL;
}
ERR_remove_thread_state(NULL);
CRYPTO_cleanup_all_ex_data();
}
/* Verifies that the file and the signature exists, and does a signature
* check afterwards.
*
* returns: true if able to validate the signature, false otherwise */
static bool verify_signature(const char *data_filename, const char *sig_filename)
{
int ret;
struct stat st;
int data_fd;
size_t data_len;
unsigned char *data = NULL;
BIO *data_BIO;
int sig_fd;
size_t sig_len;
unsigned char *sig = NULL;
BIO *sig_BIO;
PKCS7 *p7;
BIO *verify_BIO;
if (!initialize_signature()) {
terminate_signature();
return false;
}
//this function has issues: EVP_add_digest(EVP_sha256());
OpenSSL_add_all_digests();
/* get the signature */
sig_fd = open(sig_filename, O_RDONLY);
if (sig_fd == -1) {
fprintf(stderr, "Failed open %s\n", sig_filename);
terminate_signature();
return false;
}
if (fstat(sig_fd, &st) != 0) {
fprintf(stderr, "Failed to stat %s file\n", sig_filename);
close(sig_fd);
terminate_signature();
return false;
}
sig_len = st.st_size;
sig = mmap(NULL, sig_len, PROT_READ, MAP_PRIVATE, sig_fd, 0);
if (sig == MAP_FAILED) {
fprintf(stderr, "Failed to mmap %s signature\n", sig_filename);
close(sig_fd);
terminate_signature();
return false;
}
sig_BIO = BIO_new_mem_buf(sig, sig_len);
if (!sig_BIO) {
fprintf(stderr, "Failed to read %s signature into BIO\n", sig_filename);
ERR_print_errors_fp(stderr);
munmap(sig, sig_len);
close(sig_fd);
terminate_signature();
return false;
}
/* the signature is in DER format, so d2i it into verification pkcs7 form */
p7 = d2i_PKCS7_bio(sig_BIO, NULL);
if (p7 == NULL) {
fprintf(stderr, "NULL PKCS7 File\n");
ERR_print_errors_fp(stderr);
munmap(sig, sig_len);
close(sig_fd);
BIO_free(sig_BIO);
terminate_signature();
return false;
}
/* get the data to be verified */
data_fd = open(data_filename, O_RDONLY);
if (data_fd == -1) {
fprintf(stderr, "Failed open %s\n", data_filename);
munmap(sig, sig_len);
close(sig_fd);
BIO_free(sig_BIO);
PKCS7_free(p7);
terminate_signature();
return false;
}
if (fstat(data_fd, &st) != 0) {
fprintf(stderr, "Failed to stat %s\n", data_filename);
munmap(sig, sig_len);
close(sig_fd);
close(data_fd);
BIO_free(sig_BIO);
PKCS7_free(p7);
terminate_signature();
return false;
}
data_len = st.st_size;
data = mmap(NULL, data_len, PROT_READ, MAP_PRIVATE, data_fd, 0);
if (data == MAP_FAILED) {
fprintf(stderr, "Failed to mmap %s\n", data_filename);
munmap(sig, sig_len);
close(sig_fd);
close(data_fd);
BIO_free(sig_BIO);
PKCS7_free(p7);
terminate_signature();
return false;
}
data_BIO = BIO_new_mem_buf(data, data_len);
if (!data_BIO) {
fprintf(stderr, "Failed to read %s into BIO\n", data_filename);
ERR_print_errors_fp(stderr);
munmap(sig, sig_len);
close(sig_fd);
munmap(data, data_len);
close(data_fd);
BIO_free(sig_BIO);
PKCS7_free(p7);
terminate_signature();
return false;
}
/* munge the signature and data into a verifiable format */
verify_BIO = PKCS7_dataInit(p7, data_BIO);
if (!verify_BIO) {
fprintf(stderr, "Failed PKCS7_dataInit()\n");
ERR_print_errors_fp(stderr);
munmap(sig, sig_len);
close(sig_fd);
munmap(data, data_len);
close(data_fd);
BIO_free(sig_BIO);
BIO_free(data_BIO);
PKCS7_free(p7);
terminate_signature();
return false;
}
/* Verify the signature, outdata can be NULL because we don't use it */
ret = PKCS7_verify(p7, x509_stack, store, verify_BIO, NULL, 0);
munmap(sig, sig_len);
close(sig_fd);
munmap(data, data_len);
close(data_fd);
BIO_free(sig_BIO);
BIO_free(data_BIO);
BIO_free(verify_BIO);
PKCS7_free(p7);
ERR_print_errors_fp(stderr);
terminate_signature();
if (ret == 1) {
printf("Signature check succeeded.\n");
return true;
}
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
x509_store = create_store(ca_cert_filename, NULL, NULL);
if (x509_store == NULL) {
ERR_free_strings(); // undoes ERR_load_crypto_strings
EVP_cleanup(); // undoes OpenSSL_add_all_algorithms
return false || (IMPL == IMPL_FORGIVE);
fprintf(stderr, "Signature check failed!\n");
return false;
}
/* Make sure the certificate exists and extract the public key from it.
*
* returns: true if it can get the public key, false otherwise */
static bool get_pubkey(void)
{
fp_pubkey = fopen(CERTNAME, "r");
if (!fp_pubkey) {
fprintf(stderr, "Failed fopen %s\n", CERTNAME);
goto error;
}
cert = PEM_read_X509(fp_pubkey, NULL, NULL, NULL);
if (!cert) {
fprintf(stderr, "Failed PEM_read_X509() for %s\n", CERTNAME);
fclose(fp_pubkey);
goto error;
}
pkey = X509_get_pubkey(cert);
if (!pkey) {
fprintf(stderr, "Failed X509_get_pubkey() for %s\n", CERTNAME);
fclose(fp_pubkey);
X509_free(cert);
goto error;
}
initialized = true;
return true;
error:
ERR_print_errors_fp(stderr);
return false;
}
void signature_terminate(void)
/* This function makes sure the certificate is still valid by not having any
* compromised certificates in the chain.
* If there is no Certificate Revocation List (CRL) it may be that the private
* keys have not been compromised or the CRL has not been generated by the
* Certificate Authority (CA)
*
* returns: true if certificate is valid, false otherwise */
static bool validate_certificate(void)
{
if (initialized) {
X509_STORE_free(x509_store); // undocumented...
ERR_free_strings(); // undoes ERR_load_crypto_strings
EVP_cleanup(); // undoes OpenSSL_add_all_algorithms
initialized = false;
}
}
X509_LOOKUP *lookup = NULL;
X509_STORE_CTX *verify_ctx = NULL;
bool signature_verify(const char *data_filename, const char *sig_filename)
{
BIO *bio_data = NULL;
BIO *bio_sig = NULL;
PKCS7 *pkcs7 = NULL;
int ret;
bool result = false;
/* TODO: CRL and Chains are not required for the current setup, but we may
* implement them in the future
if (!crl) {
printf("No certificate revocation list provided\n");
}
if (!chain) {
printf("No certificate chain provided\n");
}
*/
if (!initialized) {
return false || (IMPL == IMPL_FORGIVE);
/* create the cert store and set the verify callback */
if (!(store = X509_STORE_new())) {
fprintf(stderr, "Failed X509_STORE_new() for %s\n", CERTNAME);
goto error;
}
bio_data = BIO_new_file(data_filename, "r"); // i.e. fopen
if (bio_data == NULL) {
goto exit;
}
bio_sig = BIO_new_file(sig_filename, "r"); // i.e. fopen
if (bio_sig == NULL) {
goto exit;
}
pkcs7 = PEM_read_bio_PKCS7(bio_sig, NULL, NULL, NULL);
if (pkcs7 == NULL) {
goto exit;
}
ret = PKCS7_verify(pkcs7, NULL, x509_store, bio_data, NULL, 0);
if (ret != 1) {
goto exit;
}
result = true;
exit:
/*
* The free functions below tolerate NULL arguments.
* The documentation doesn't really say so, but both testing and
* examination of openssl source code confirm that such is the case.
*/
PKCS7_free(pkcs7); // undocumented...
BIO_free(bio_sig); // i.e. fclose
BIO_free(bio_data); // i.e. fclose
return result || (IMPL == IMPL_FORGIVE);
}
static X509_STORE *create_store(const char *ca_filename, const char *ca_dirname,
const char *crl_filename)
{
X509_STORE *store = X509_STORE_new();
X509_STORE_set_verify_cb_func(store, verify_callback);
if (!store) {
return NULL;
/* Add the certificates to be verified to the store */
if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()))) {
fprintf(stderr, "Failed X509_STORE_add_lookup() for %s\n", CERTNAME);
goto error;
}
if (X509_STORE_load_locations(store, ca_filename, ca_dirname) != 1) {
goto err;
/* Load the our Root cert, which can be in either DER or PEM format */
if (!X509_load_cert_file(lookup, CERTNAME, X509_FILETYPE_PEM)) {
fprintf(stderr, "Failed X509_load_cert_file() for %s\n", CERTNAME);
goto error;
}
if (X509_STORE_set_default_paths(store) != 1) {
goto err;
}
if (crl_filename) {
X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
if (!lookup) {
goto err;
}
if (X509_load_crl_file(lookup, crl_filename, X509_FILETYPE_PEM) != 1) {
goto err;
if (crl) {
if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) ||
(X509_load_crl_file(lookup, crl, X509_FILETYPE_PEM) != 1)) {
fprintf(stderr, "Failed X509 crl init for %s\n", CERTNAME);
goto error;
}
/* set the flags of the store so that CLRs are consulted */
X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
}
return store;
err:
X509_STORE_free(x509_store);
return NULL;
/* create a verification context and initialize it */
if (!(verify_ctx = X509_STORE_CTX_new())) {
fprintf(stderr, "Failed X509_STORE_CTX_new() for %s\n", CERTNAME);
goto error;
}
if (X509_STORE_CTX_init(verify_ctx, store, cert, NULL) != 1) {
fprintf(stderr, "Failed X509_STORE_CTX_init() for %s\n", CERTNAME);
goto error;
}
/* Specify which cert to validate in the verify context.
* This is required because we may add multiple certs to the X509 store,
* but we want to validate a specific one out of the group/chain. */
X509_STORE_CTX_set_cert(verify_ctx, cert);
/* verify the certificate */
if (X509_verify_cert(verify_ctx) != 1) {
fprintf(stderr, "Failed X509_verify_cert() for %s\n", CERTNAME);
goto error;
}
X509_STORE_CTX_free(verify_ctx);
/* Certificate verified correctly */
return true;
error:
ERR_print_errors_fp(stderr);
if (store) {
X509_STORE_free(store);
}
if (lookup) {
X509_LOOKUP_free(lookup);
}
return false;
}
bool signature_download_and_verify(const char *data_url, const char *data_filename)
int verify_callback(int ok, X509_STORE_CTX *stor)
{
if (!ok) {
fprintf(stderr, "Error: %s\n",
X509_verify_cert_error_string(stor->error));
}
return ok;
}
/* Downloads the corresponding signature filename from the
* swupd server.
*
* returns: true if signature was downloaded, false otherwise
*/
bool download_and_verify_signature(const char *data_url, const char *data_filename)
{
char *sig_url;
char *sig_filename;
int ret;
bool result;
string_or_die(&sig_url, "%s.signed", data_url);
string_or_die(&sig_url, "%s.sig", data_url);
string_or_die(&sig_filename, "%s.signed", data_filename);
string_or_die(&sig_filename, "%s.sig", data_filename);
ret = swupd_curl_get_file(sig_url, sig_filename, NULL, NULL, false);
if (ret) {
result = false;
} else {
result = signature_verify(data_filename, sig_filename);
}
if (!result) {
unlink(sig_filename);
result = verify_signature(data_filename, sig_filename);
}
free(sig_filename);
free(sig_url);
return result || (IMPL == IMPL_FORGIVE);
return result;
}
void signature_delete(const char *data_filename)
{
char *sig_filename;
string_or_die(&sig_filename, "%s.signed", data_filename);
unlink(sig_filename);
free(sig_filename);
}
#else // IMPL == IMPL_FAKE
bool signature_initialize(const char UNUSED_PARAM *ca_cert_filename)
#else
bool download_and_verify_signature(const char UNUSED_PARAM *data_url, const char UNUSED_PARAM *data_filename)
{
return true;
}
void signature_terminate(void)
{
}
bool signature_verify(const char UNUSED_PARAM *data_filename, const char UNUSED_PARAM *sig_filename)
{
return true;
}
bool signature_download_and_verify(const char UNUSED_PARAM *data_url, const char UNUSED_PARAM *data_filename)
{
return true;
}
void signature_delete(const char UNUSED_PARAM *data_filename)
{
}
#endif // IMPL == IMPL_FAKE
#endif
-5
View File
@@ -242,10 +242,6 @@ int main_update()
printf("Update started.\n");
read_subscriptions_alt();
if (!signature_initialize(UPDATE_CA_CERTS_PATH "/" SIGNATURE_CA_CERT)) {
goto clean_curl;
}
/* Step 1: get versions */
ret = check_versions(&current_version, &server_version, path_prefix);
@@ -402,7 +398,6 @@ clean_exit:
free_manifest(server_manifest);
clean_curl:
signature_terminate();
swupd_curl_cleanup();
free_subscriptions();
free_globals();
+1 -5
View File
@@ -641,10 +641,6 @@ int verify_main(int argc, char **argv)
* FIXME: We need a command line option to override this in case the
* certificate is hosed and the admin knows it and wants to recover.
*/
if (!signature_initialize(UPDATE_CA_CERTS_PATH "/" SIGNATURE_CA_CERT)) {
printf("Can't initialize the SSL certificates\n");
goto brick_the_system_and_clean_curl;
}
ret = rm_staging_dir_contents("download");
if (ret != 0) {
@@ -658,7 +654,7 @@ int verify_main(int argc, char **argv)
* is not available, or if there is a server error and a manifest is
* not provided.
*/
printf("Unable to download %d Manifest.MoM\n", version);
printf("Unable to download/verify %d Manifest.MoM\n", version);
ret = EXIT_FAILURE;
/* No repair is possible without a manifest, nor is accurate reporting
+1 -8
View File
@@ -46,19 +46,12 @@ int main(int argc, char **argv)
usage(argv[0]);
}
if (!signature_initialize(argv[3])) {
fprintf(stderr, "Can't initialize!\n");
exit(-1);
}
if (signature_verify(argv[1], argv[2])) {
if (download_and_verify_signature(argv[1], argv[2])) {
fprintf(stderr, "Verification successful!\n");
} else {
fprintf(stderr, "Verification failed!\n");
}
signature_terminate();
return 0;
}