tech-install archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: HTTPS trust anchors in sysinst



(Please keep me cc'd -- otherwise I may miss your replies.)

> Date: Sat, 26 Aug 2023 09:21:49 -0400
> From: Mouse <mouse%Rodents-Montreal.ORG@localhost>
> 
> > [*] We should _also_ bake a public signature verification key into
> >     the installers that can verify a signature on the sets which can
> >     in turn be made only by TNF -- not by any of the public HTTPS
> >     CAs.  But that's a separate issue that requires more key
> >     management and software verifier setup than we have settled now.
> 
> Once you have that, it seems to me that the use of SSL on either HTTP
> or FTP becomes pointless CPU cycle wasting.  This then leads me to
> wonder two things: (1) is doing SSL a case of the good being the enemy
> of the best (because people will fall into the trap of thinking that
> SSL means "it's secure" without asking "...against what?"[%])? and (2)
> is all this kerfuffle about CA trust anchors effort that would better
> be put into designing and building the right answer?

Enabling HTTPS validation is low-hanging fruit for modern systems in a
modern world to defend against a large class of plausible threats --
namely, MITM on the network between you and cdn.netbsd.org.

The [*] part _also_ defends against a compromised CDN, or against MITM
on the network _combined with_ a compromised root CA.  But the [*]
part takes even more care to make sure we seriously consider other
classes of threats, and don't ship a system that will silently get
permanently wedged on automatic updates.

I am planning to the [*] part but it is not going to be ready for
netbsd-10, whereas HTTPS validation will be -- in base, at least.  So
I'm probing to see how much engineering effort will be needed to make
HTTPS validation happen in the installer too.  See also:

   Or maybe we can decide this isn't worthwhile, and the effort is better
   spent on a lighter-weight signing system for NetBSD distributions...
   (https://mail-index.netbsd.org/tech-install/2023/08/26/msg000698.html)

> Also, if you're doing public-key crypto - for anything - in the
> installers, this will drastically, I am tempted to say
> catastrophically, slow down installation on low-end machines, like a
> MicroVAX-II or Sun-3.  (Of course, NetBSD might be fine with that.  I
> just think it should be at least thought about.)

Can you please do the following tests on any low-end machines of
interest?

1. Run `openssl speed' and share the output.  Running it will take
   several minutes but the time is largely independent of the speed of
   the CPU; it measures how many operations it can do in a fixed time.

2. Build the attached rwverify.c with

	make rwverify DBG=-g\ -O2 LDLIBS=-lcrypto

   Then run it and share the output.

   You can also cross-build it on a more capable machine if you have a
   NetBSD `build.sh release' cross-build handy already, of course:

	make rwverify CC=$TOOLDIR/bin/vax--netbsdelf-gcc \
		DBG=-g\ -O2\ --sysroot=$OBJDIR/destdir.vax \
		LDLIBS=-lcrypto

   Running it will take approximately ten seconds.

3. Download

	https://falcon-sign.info/Falcon-impl-20211101.zip

   (or

	http://www.NetBSD.org/~riastradh/tmp/20230827/Falcon-impl-20211101.zip

   if you insist on avoiding https), build it with make, run
   `./speed', and share the output.

   To build for VAX, you'll need to make sure that -DFALCON_FPEMU=1
   -DFALCON_FPNATIVE=0 is set in CFLAGS.  So to cross-build for VAX,
   you'll need to do this:

	make CC=$TOOLDIR/bin/vax--netbsdelf-gcc \
		CFLAGS=-g\ -O2\ --sysroot=$OBJDIR/destdir.vax\ -DFALCON_FPEMU=1\ -DFALCON_FPNATIVE=0 \
		LD=$TOOLDIR/bin/vax--netbsdelf-gcc \
		LDFLAGS=--sysroot=$OBJDIR/destdir.vax
#include <assert.h>
#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#include <openssl/bn.h>
#include <openssl/err.h>

static void
oerr(int status, const char *fmt, ...)
{
	va_list va;

	fprintf(stderr, "%s: ", getprogname());

	va_start(va, fmt);
	vfprintf(stderr, fmt, va);
	va_end(va);

	fprintf(stderr, ": %s\n", ERR_error_string(ERR_get_error(), NULL));

	exit(status);
}

/*
 * openssl prime -generate -hex -bits 1024 | fold -w 64 | sed -e 's,^,    ",' -e 's,$,",'
 *
 * repeat until:
 * - lsbyte of p is 3
 * - lsbyte of q is 7
 * - p*q > 2^2047
 */
static const char p_hex[] =
    "E29BC82D77D0A11610FAF5CEC23A1FEB05C5274FDBB9C548DCC4460B306C2ABE"
    "99B9287C7AC53FF9DC041C722D9F7288D73AD49495A98DA5255D93B9ADF3DCB0"
    "60FFB8D9ADA3499BA8782BC4B77B25CE0CDF6A47D2F3410BEB5FFC26775DE6A7"
    "0CD74FA2C98667932A9663E29284880F36D6F94E14102D321A4B9D209E1E49C3";
static const char q_hex[] =
    "E8A6EE70C1F10DA317CF5B2B5EB7B5388BD5013C2A4D078C0ADB3CB1B64A87C3"
    "1E9F1B06301E3A288FC0869FD3727604C408AC4D21E941E4B45910B02A3FFB2C"
    "B608C3790994965AC8EA49802A00D40D242E701543117F8B220F6BDF47B2BCEE"
    "371DD93047C35EA734BA66AF94A6E94AC5230C323A9F435073FC73DCA68FF4E7";

/*
 * n = p*q
 */
static const char n_hex[] =
    "cdf0f17da5ff6f30d64bd37863b27bcd0ba20e0b014597517d8ddb7035059959"
    "93f2df5d937a2c8e861047cc8777ff82ade5f0337895466d7855dbdae07f4d9e"
    "79cc85a6479f96989c32ca0571b87df85eb26ca6d88a19522d65adc2de164276"
    "420b1297cd2d448b38f978b837f6139aa0387547cd2c8a2942a6f9650b00e071"
    "c3fa2e9041123969a2e3fca77704bac7874fb56c5c4577cf4406fd0df840fc00"
    "c735bf766d899962e5f1e433bd85ee235676429ebb06b80ed129eb3ff21964e8"
    "cf799c89b6d744e12d422e5ef488caa69b155821ae79967eaa97d5c8c8179c9f"
    "5c8659401975d2579122decd9a80493b356d86fd7a4c475869dbd277318f6af5";

/*
 * openssl rand -hex 32
 */
static const char z_hex[] =
    "7715296787e5fa6f33a383dece71f421de100ef755da8d4785566d927a621ae6";

/*
 * r = KangarooTwelve(z ||
 *         'The Magic Words are Squeamish Ossifrage')[0:4),
 */
static const int r = 0x3;

/*
 * h = KangarooTwelve('\0'*32 ||
 *         'The Magic Words are Squeamish Ossifrage')[0:2047),
 *
 * (note: 2047-bit integer, not 2048-bit integer)
 */
static const char h_hex[] =
    "5bf14befd0c7c1646f66ba6fd75f464b9fe769439f4816a20d8d8d92ea00327f"
    "862f1c7f87250c02c0d2dffdaefd4f5fdeb28fbd97cd86e7da2af4eaabff9087"
    "eade2f5d88e6628fddcc9439d505c6c339db315609509873b40f4504e2c3ef6c"
    "ce96df7fede8a24403566a7d6d0644cb486cf05d3943c74cfc8ec23efc338b21"
    "acbf5fc6261eaa4e1446c5da4350987f9f8e9f1d8fba92744411d04e0ddf6e2e"
    "37a555f3d51865ea2f4e43c6739605757af6880b1d261e02d7bb5ad22b31ff04"
    "1f602166314e360e2d166362e71aa06320b26d10a51e3c2cc6add5dcb2daf3f8"
    "e45bdc5456694adfca42373058d7978a98e068046437dd016efaa80fd75e3515";

/*
 * Standard signature components -- tweaked square root of h modulo n.
 */
static const int e = 1;	/* 1 or -1 */
static const int f = 1;	/* 1 or 2 */
static const char s_hex[] =
    "1ebbb89fcb46a93c951bee64efb1aeb47cf604404d907b36193e9525c13a7a66"
    "87e280b8cd0f134b9de31722fb5ad8f15a22039017effdd948d5cd592a0ba1d4"
    "280589f8242e0891b014dcad060f8721359522fcc874c08ba175645a4784f71c"
    "ba4c91919d578528bde19113aeed301e8b7f009accd2315b0bc360eb8910e864"
    "c627b594316e8b705a84d8c78aebe7eec7d25e8d7def08a5296c7b2d246abb1f"
    "db3cca82463f8dcfad4863ea7ef4b2f8f8cfa318182643b36893659094a7a66b"
    "db3433884cfbacf119231abe15090d966516da47de2fde4a3a972835525487c7"
    "792594d09b6058d8d53262e881d07c44ae0c2415621efebdef99aee51bde520f";

/*
 * Multiplier for reduction-free verification.
 */
static const char t_hex[] =
    "049620497c78b2f064d5a1bfffe5da819d733c976c63c5b3a8e0d65c33d598ab"
    "12664e220c61f53a1031933a40e91cb39ac81aa22f5a4e9d2c5983d27170d853"
    "c35de0cbb99081b039aee92da2e194ac258a0fa95577e6531c9b9aaa55c540e5"
    "88a1b9c976331de6d1353f15ec6b75a31fbc482f6df29393946d217af9362684"
    "fe73c7ef8380ba4aee66af6ca8ad7b5a76e56b6cb3a9806326cebca37bb0db9d"
    "6da5cc48075222ff6da8240bf9a68574456a5fcc8e3c7738a2fadda699f310b0"
    "bb0905f19e05c6a258e0faed653681b87a6cc5991fbe2efcdd37d66a9c6165b0"
    "0bf5ff50d3a3872240a7718b20be0b53cdf940c3d7105e07d9a1e6e9d27dc11c";

static sig_atomic_t alarmed = 0;

static void
sigalrm(int signo)
{
	alarmed = 1;
}

int
main(int argc, char **argv)
{
	BIGNUM *n, *h, *s, *t;
	int n_len, h_len, s_len, t_len;
	int n_off, h_off, s_off, t_off;
	unsigned char *n_bin, *h_bin, *s_bin, *t_bin;
	unsigned timelimit_sec = 10;
	unsigned i = 0;
	struct timespec t0, t1, dt;

	setprogname(argv[0]);

	/* Parse the hex representations once -- slow, unrealistic. */
	n = NULL;
	if (BN_hex2bn(&n, n_hex) == 0)
		oerr(1, "BN_hex2bn n");
	assert(n);
	h = NULL;
	if (BN_hex2bn(&h, h_hex) == 0)
		oerr(1, "BN_hex2bn h");
	assert(h);
	s = NULL;
	if (BN_hex2bn(&s, s_hex) == 0)
		oerr(1, "BN_hex2bn s");
	assert(s);
	t = NULL;
	if (BN_hex2bn(&t, t_hex) == 0)
		oerr(1, "BN_hex2bn t");
	assert(t);

	/* Convert to binary representations -- realistic. */
	n_len = 256;
	assert(n_len >= BN_num_bytes(n));
	n_off = n_len - BN_num_bytes(n);
	if ((n_bin = calloc(1, n_len)) == NULL)
		err(1, "malloc n_bin");

	h_len = 256;
	assert(h_len >= BN_num_bytes(h));
	h_off = h_len - BN_num_bytes(h);
	if ((h_bin = calloc(1, h_len)) == NULL)
		err(1, "malloc h_bin");

	s_len = 256;
	assert(s_len >= BN_num_bytes(s));
	s_off = s_len - BN_num_bytes(s);
	if ((s_bin = calloc(1, s_len)) == NULL)
		err(1, "malloc s_bin");

	t_len = 256;
	assert(t_len >= BN_num_bytes(t));
	t_off = t_len - BN_num_bytes(t);
	if ((t_bin = calloc(1, t_len)) == NULL)
		err(1, "malloc t_bin");

	if (BN_bn2binpad(n, n_bin + n_off, n_len - n_off) == -1)
		oerr(1, "BN_bn2binpad n");
	if (BN_bn2binpad(h, h_bin + h_off, h_len - h_off) == -1)
		oerr(1, "BN_bn2binpad h");
	if (BN_bn2binpad(s, s_bin + s_off, s_len - s_off) == -1)
		oerr(1, "BN_bn2binpad s");
	if (BN_bn2binpad(t, t_bin + t_off, t_len - t_off) == -1)
		oerr(1, "BN_bn2binpad t");

	BN_free(t);
	t = NULL;
	BN_free(s);
	s = NULL;
	BN_free(h);
	h = NULL;
	BN_free(n);
	n = NULL;

	/* Start a timer going. */
	if (signal(SIGALRM, sigalrm) == SIG_ERR)
		err(1, "signal");
	alarm(timelimit_sec);
	if (clock_gettime(CLOCK_MONOTONIC, &t0) == -1)
		err(1, "clock_gettime(CLOCK_MONOTONIC)");

	for (i = 0; !alarmed; i++) {
		BN_CTX *ctx;
		BIGNUM *f_bn, *s2, *fs2, *nt, *fs2_nt;

		/* Allocate a bignum context. */
		if ((ctx = BN_CTX_new()) == NULL)
			oerr(1, "BN_CTX_new");

		/* Push an intermediate bignum frame. */
		BN_CTX_start(ctx);

		if ((n = BN_CTX_get(ctx)) == NULL)
			oerr(1, "BN_CTX_get n");
		if ((h = BN_CTX_get(ctx)) == NULL)
			oerr(1, "BN_CTX_get h");
		if ((s = BN_CTX_get(ctx)) == NULL)
			oerr(1, "BN_CTX_get s");
		if ((t = BN_CTX_get(ctx)) == NULL)
			oerr(1, "BN_CTX_get t");
		if ((f_bn = BN_CTX_get(ctx)) == NULL)
			oerr(1, "BN_CTX_get f");
		if ((s2 = BN_CTX_get(ctx)) == NULL)
			oerr(1, "BN_CTX_get s2");
		if ((fs2 = BN_CTX_get(ctx)) == NULL)
			oerr(1, "BN_CTX_get fs2");
		if ((nt = BN_CTX_get(ctx)) == NULL)
			oerr(1, "BN_CTX_get nt");
		if ((fs2_nt = BN_CTX_get(ctx)) == NULL)
			oerr(1, "BN_CTX_get fs2_nt");

		/* Parse the signature. */
		if (BN_bin2bn(n_bin, n_len, n) == NULL)
			oerr(1, "BN_bin2bn n");
		if (BN_bin2bn(h_bin, h_len, h) == NULL)
			oerr(1, "BN_bin2bn h");
		if (BN_bin2bn(s_bin, s_len, s) == NULL)
			oerr(1, "BN_bin2bn s");
		if (BN_bin2bn(t_bin, t_len, t) == NULL)
			oerr(1, "BN_bin2bn t");
		if (!BN_set_word(f_bn, f))
			oerr(1, "BN_set_word f");

		/* Verify the signature. */
		if (!BN_sqr(s2, s, ctx))
			oerr(1, "BN_sqr s");
		if (!BN_mul(fs2, f_bn, s2, ctx))
			oerr(1, "BN_mul f, s2");
		if (!BN_mul(nt, n, t, ctx))
			oerr(1, "BN_mul n, t");
		switch (e) {
		case 1:
			if (!BN_sub(fs2_nt, fs2, nt))
				oerr(1, "BN_sub fs2, nt");
			if (BN_cmp(h, fs2_nt) != 0)
				errx(42, "verification failure");
			break;
		case -1:
			if (!BN_sub(fs2_nt, nt, fs2))
				oerr(1, "BN_sub nt, fs2");
			if (BN_cmp(h, fs2_nt) != 0)
				errx(42, "verification failure");
			break;
		default:
			err(1, "bad e: %d", e);
		}

		/* Free intermediate bignums. */
		BN_CTX_end(ctx);

		/* Free the bignum context. */
		BN_CTX_free(ctx);
	}
	if (clock_gettime(CLOCK_MONOTONIC, &t1) == -1)
		err(1, "clock_gettime(CLOCK_MONOTONIC)");
	timespecsub(&t1, &t0, &dt);

	/* Print results of the timer. */
	printf("%d verifications in %f sec\n", i,
	    dt.tv_sec + 1e-9*dt.tv_nsec);
	printf("%f v/s\n", i/(dt.tv_sec + 1e-9*dt.tv_nsec));

	fflush(stdout);
	return ferror(stdout);
}


Home | Main Index | Thread Index | Old Index