Ejemplo n.º 1
0
static void signature_loopback(void)
{
	GBytes *content = read_file("test/openssl-ca/manifest", NULL);
	GBytes *sig = NULL;
	g_assert_nonnull(content);
	sig = cms_sign(content,
		       r_context()->certpath,
		       r_context()->keypath,
		       NULL);
	g_assert_nonnull(sig);
	g_assert_true(cms_verify(content, sig, NULL));
	((char *)g_bytes_get_data(content, NULL))[0] = 0x00;
	g_assert_false(cms_verify(content, sig, NULL));
	g_bytes_unref(content);
	g_bytes_unref(sig);
}
Ejemplo n.º 2
0
static void signature_verify(void)
{
	GBytes *content = read_file("test/openssl-ca/manifest", NULL);
	GBytes *sig = read_file("test/openssl-ca/manifest-r1.sig", NULL);
	g_assert_nonnull(content);
	g_assert_nonnull(sig);
	g_assert_true(cms_verify(content, sig, NULL));
	g_bytes_unref(content);
	g_bytes_unref(sig);
}
Ejemplo n.º 3
0
/**
 * Verify image using downloaded signature
 *
 * @v image		Image to verify
 * @v signature		Image containing signature
 * @v name		Required common name, or NULL to allow any name
 * @ret rc		Return status code
 */
int imgverify ( struct image *image, struct image *signature,
                const char *name ) {
    size_t len;
    void *data;
    struct cms_signature *sig;
    time_t now;
    int rc;

    /* Mark image as untrusted */
    image_untrust ( image );

    /* Copy signature to internal memory */
    len = signature->len;
    data = malloc ( len );
    if ( ! data ) {
        rc = -ENOMEM;
        goto err_alloc;
    }
    copy_from_user ( data, signature->data, 0, len );

    /* Parse signature */
    if ( ( rc = cms_signature ( data, len, &sig ) ) != 0 )
        goto err_parse;

    /* Free internal copy of signature */
    free ( data );
    data = NULL;

    /* Use signature to verify image */
    now = time ( NULL );
    if ( ( rc = cms_verify ( sig, image->data, image->len,
                             name, now, NULL ) ) != 0 )
        goto err_verify;

    /* Drop reference to signature */
    cms_put ( sig );
    sig = NULL;

    /* Mark image as trusted */
    image_trust ( image );
    syslog ( LOG_NOTICE, "Image \"%s\" signature OK\n", image->name );

    return 0;

err_verify:
    cms_put ( sig );
err_parse:
    free ( data );
err_alloc:
    syslog ( LOG_ERR, "Image \"%s\" signature bad: %s\n",
             image->name, strerror ( rc ) );
    return rc;
}
Ejemplo n.º 4
0
GBytes *cms_sign(GBytes *content, const gchar *certfile, const gchar *keyfile, gchar **interfiles, GError **error)
{
	GError *ierror = NULL;
	BIO *incontent = BIO_new_mem_buf((void *)g_bytes_get_data(content, NULL),
			g_bytes_get_size(content));
	BIO *outsig = BIO_new(BIO_s_mem());
	X509 *signcert = NULL;
	EVP_PKEY *pkey = NULL;
	STACK_OF(X509) *intercerts = NULL;
	CMS_ContentInfo *cms = NULL;
	GBytes *res = NULL;
	int flags = CMS_DETACHED | CMS_BINARY;

	g_return_val_if_fail(content != NULL, NULL);
	g_return_val_if_fail(certfile != NULL, NULL);
	g_return_val_if_fail(keyfile != NULL, NULL);
	g_return_val_if_fail(error == NULL || *error == NULL, NULL);

	signcert = load_cert(certfile, &ierror);
	if (signcert == NULL) {
		g_propagate_error(error, ierror);
		goto out;
	}

	pkey = load_key(keyfile, &ierror);
	if (pkey == NULL) {
		g_propagate_error(error, ierror);
		goto out;
	}

	intercerts = sk_X509_new_null();

	for (gchar **intercertpath = interfiles; intercertpath && *intercertpath != NULL; intercertpath++) {

		X509 *intercert = load_cert(*intercertpath, &ierror);
		if (intercert == NULL) {
			g_propagate_error(error, ierror);
			goto out;
		}

		sk_X509_push(intercerts, intercert);
	}

	cms = CMS_sign(signcert, pkey, intercerts, incontent, flags);
	if (cms == NULL) {
		unsigned long err;
		const gchar *data;
		int errflags;
		err = ERR_get_error_line_data(NULL, NULL, &data, &errflags);
		g_set_error(
				error,
				R_SIGNATURE_ERROR,
				R_SIGNATURE_ERROR_INVALID,
				"failed to create signature: %s", (errflags & ERR_TXT_STRING) ? data : ERR_error_string(err, NULL));
		goto out;
	}
	if (!i2d_CMS_bio(outsig, cms)) {
		g_set_error_literal(
				error,
				R_SIGNATURE_ERROR,
				R_SIGNATURE_ERROR_SERIALIZE_SIG,
				"failed to serialize signature");
		goto out;
	}

	res = bytes_from_bio(outsig);

	if (!res) {
		g_set_error_literal(
				error,
				R_SIGNATURE_ERROR,
				R_SIGNATURE_ERROR_UNKNOWN,
				"Read zero bytes");
		goto out;
	}

	/* keyring was given, perform verification to obtain trust chain */
	if (r_context()->config->keyring_path) {
		g_autoptr(CMS_ContentInfo) vcms = NULL;
		g_autoptr(X509_STORE) store = NULL;
		STACK_OF(X509) *verified_chain = NULL;

		g_message("Keyring given, doing signature verification");
		if (!cms_verify(content, res, &vcms, &store, &ierror)) {
			g_propagate_error(error, ierror);
			res = NULL;
			goto out;
		}

		if (!cms_get_cert_chain(vcms, store, &verified_chain, &ierror)) {
			g_propagate_error(error, ierror);
			res = NULL;
			goto out;
		}

		for (int i = 0; i < sk_X509_num(verified_chain); i++) {
			const ASN1_TIME *expiry_time;
			struct tm *next_month;
			time_t now;
			time_t comp;
			time(&now);

			next_month = gmtime(&now);
			next_month->tm_mon += 1;
			if (next_month->tm_mon == 12)
				next_month->tm_mon = 0;
			comp = timegm(next_month);

			expiry_time = X509_get0_notAfter(sk_X509_value(verified_chain, i));

			/* Check if expiry time is within last month */
			if (X509_cmp_current_time(expiry_time) == 1 && X509_cmp_time(expiry_time, &comp) == -1) {
				char buf[BUFSIZ];
				X509_NAME_oneline(X509_get_subject_name(sk_X509_value(verified_chain, i)),
						buf, sizeof buf);
				g_warning("Certificate %d (%s) will exipre in less than a month!", i + 1, buf);
			}
		}

		sk_X509_pop_free(verified_chain, X509_free);
	} else {
		g_message("No keyring given, skipping signature verification");
	}
out:
	ERR_print_errors_fp(stdout);
	BIO_free_all(incontent);
	BIO_free_all(outsig);
	return res;
}