upstream commit

more and better key tests

test signatures and verification
test certificate generation
flesh out nested cert test

removes most of the XXX todo markers
This commit is contained in:
djm@openbsd.org 2015-01-18 19:54:46 +00:00 committed by Damien Miller
parent 589e69fd82
commit 3a2b09d147
2 changed files with 167 additions and 12 deletions

View File

@ -1,5 +1,5 @@
#!/bin/sh
# $OpenBSD: mktestdata.sh,v 1.3 2014/07/22 23:57:40 dtucker Exp $
# $OpenBSD: mktestdata.sh,v 1.4 2015/01/18 19:54:46 djm Exp $
PW=mekmitasdigoat
@ -187,4 +187,6 @@ ssh-keygen -Bf dsa_2 | awk '{print $2}' > dsa_2.fp.bb
ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb
ssh-keygen -Bf ed25519_2 | awk '{print $2}' > ed25519_2.fp.bb
# XXX Extend ssh-keygen to do detached signatures (better to test/fuzz against)
echo "$PW" > pw

View File

@ -1,4 +1,4 @@
/* $OpenBSD: test_sshkey.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */
/* $OpenBSD: test_sshkey.c,v 1.2 2015/01/18 19:54:46 djm Exp $ */
/*
* Regress test for sshkey.h key management API
*
@ -36,6 +36,20 @@
void sshkey_tests(void);
static void
put_opt(struct sshbuf *b, const char *name, const char *value)
{
struct sshbuf *sect;
sect = sshbuf_new();
ASSERT_PTR_NE(sect, NULL);
ASSERT_INT_EQ(sshbuf_put_cstring(b, name), 0);
if (value != NULL)
ASSERT_INT_EQ(sshbuf_put_cstring(sect, value), 0);
ASSERT_INT_EQ(sshbuf_put_stringb(b, sect), 0);
sshbuf_free(sect);
}
static void
build_cert(struct sshbuf *b, const struct sshkey *k, const char *type,
const struct sshkey *sign_key, const struct sshkey *ca_key)
@ -45,6 +59,7 @@ build_cert(struct sshbuf *b, const struct sshkey *k, const char *type,
size_t siglen;
ca_buf = sshbuf_new();
ASSERT_PTR_NE(ca_buf, NULL);
ASSERT_INT_EQ(sshkey_to_blob_buf(ca_key, ca_buf), 0);
/*
@ -52,18 +67,23 @@ build_cert(struct sshbuf *b, const struct sshkey *k, const char *type,
* the type string. This is a bit of a hack :/
*/
pk = sshbuf_new();
ASSERT_PTR_NE(pk, NULL);
ASSERT_INT_EQ(sshkey_plain_to_blob_buf(k, pk), 0);
ASSERT_INT_EQ(sshbuf_skip_string(pk), 0);
principals = sshbuf_new();
ASSERT_PTR_NE(principals, NULL);
ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gsamsa"), 0);
ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gregor"), 0);
critopts = sshbuf_new();
/* XXX fill this in */
ASSERT_PTR_NE(critopts, NULL);
put_opt(critopts, "force-command", "/usr/local/bin/nethack");
put_opt(critopts, "source-address", "192.168.0.0/24,127.0.0.1,::1");
exts = sshbuf_new();
/* XXX fill this in */
ASSERT_PTR_NE(exts, NULL);
put_opt(critopts, "permit-X11-forwarding", NULL);
ASSERT_INT_EQ(sshbuf_put_cstring(b, type), 0);
ASSERT_INT_EQ(sshbuf_put_cstring(b, "noncenoncenonce!"), 0); /* nonce */
@ -90,6 +110,67 @@ build_cert(struct sshbuf *b, const struct sshkey *k, const char *type,
sshbuf_free(pk);
}
static void
signature_test(struct sshkey *k, struct sshkey *bad, const u_char *d, size_t l)
{
size_t len;
u_char *sig;
ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, 0), 0);
ASSERT_SIZE_T_GT(len, 8);
ASSERT_PTR_NE(sig, NULL);
ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, 0), 0);
ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, 0), 0);
/* Fuzz test is more comprehensive, this is just a smoke test */
sig[len - 5] ^= 0x10;
ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, 0), 0);
free(sig);
}
static void
banana(u_char *s, size_t l)
{
size_t o;
const u_char the_banana[] = { 'b', 'a', 'n', 'a', 'n', 'a' };
for (o = 0; o < l; o += sizeof(the_banana)) {
if (l - o < sizeof(the_banana)) {
memcpy(s + o, "nanananana", l - o);
break;
}
memcpy(s + o, banana, sizeof(the_banana));
}
}
static void
signature_tests(struct sshkey *k, struct sshkey *bad)
{
u_char i, buf[2049];
size_t lens[] = {
1, 2, 7, 8, 9, 15, 16, 17, 31, 32, 33, 127, 128, 129,
255, 256, 257, 1023, 1024, 1025, 2047, 2048, 2049
};
for (i = 0; i < (sizeof(lens)/sizeof(lens[0])); i++) {
test_subtest_info("%s key, banana length %zu",
sshkey_type(k), lens[i]);
banana(buf, lens[i]);
signature_test(k, bad, buf, lens[i]);
}
}
static struct sshkey *
get_private(const char *n)
{
struct sshbuf *b;
struct sshkey *ret;
b = load_file(n);
ASSERT_INT_EQ(sshkey_parse_private_fileblob(b, "", n, &ret, NULL), 0);
sshbuf_free(b);
return ret;
}
void
sshkey_tests(void)
{
@ -332,26 +413,98 @@ sshkey_tests(void)
#endif
sshkey_free(kf);
/* XXX certify test */
/* XXX sign test */
/* XXX verify test */
TEST_START("certify key");
ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_1.pub"),
&k1, NULL), 0);
k2 = get_private("ed25519_2");
ASSERT_INT_EQ(sshkey_to_certified(k1, 0), 0);
ASSERT_PTR_NE(k1->cert, NULL);
k1->cert->type = SSH2_CERT_TYPE_USER;
k1->cert->serial = 1234;
k1->cert->key_id = strdup("estragon");
ASSERT_PTR_NE(k1->cert->key_id, NULL);
k1->cert->principals = calloc(4, sizeof(*k1->cert->principals));
ASSERT_PTR_NE(k1->cert->principals, NULL);
k1->cert->principals[0] = strdup("estragon");
k1->cert->principals[1] = strdup("vladimir");
k1->cert->principals[2] = strdup("pozzo");
k1->cert->principals[3] = strdup("lucky");
ASSERT_PTR_NE(k1->cert->principals[0], NULL);
ASSERT_PTR_NE(k1->cert->principals[1], NULL);
ASSERT_PTR_NE(k1->cert->principals[2], NULL);
ASSERT_PTR_NE(k1->cert->principals[3], NULL);
k1->cert->valid_after = 0;
k1->cert->valid_before = (u_int64_t)-1;
k1->cert->critical = sshbuf_new();
ASSERT_PTR_NE(k1->cert->critical, NULL);
k1->cert->extensions = sshbuf_new();
ASSERT_PTR_NE(k1->cert->extensions, NULL);
put_opt(k1->cert->critical, "force-command", "/usr/bin/true");
put_opt(k1->cert->critical, "source-address", "127.0.0.1");
put_opt(k1->cert->extensions, "permit-X11-forwarding", NULL);
put_opt(k1->cert->extensions, "permit-agent-forwarding", NULL);
ASSERT_INT_EQ(sshkey_from_private(k2, &k1->cert->signature_key), 0);
ASSERT_INT_EQ(sshkey_certify(k1, k2), 0);
b = sshbuf_new();
ASSERT_PTR_NE(b, NULL);
ASSERT_INT_EQ(sshkey_to_blob_buf(k1, b), 0);
ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k3), 0);
sshkey_free(k1);
sshkey_free(k2);
sshkey_free(k3);
sshbuf_reset(b);
TEST_DONE();
TEST_START("sign and verify RSA");
k1 = get_private("rsa_1");
ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_2.pub"), &k2,
NULL), 0);
signature_tests(k1, k2);
sshkey_free(k1);
sshkey_free(k2);
TEST_DONE();
TEST_START("sign and verify DSA");
k1 = get_private("dsa_1");
ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_2.pub"), &k2,
NULL), 0);
signature_tests(k1, k2);
sshkey_free(k1);
sshkey_free(k2);
TEST_DONE();
TEST_START("sign and verify ECDSA");
k1 = get_private("ecdsa_1");
ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_2.pub"), &k2,
NULL), 0);
signature_tests(k1, k2);
sshkey_free(k1);
sshkey_free(k2);
TEST_DONE();
TEST_START("sign and verify ED25519");
k1 = get_private("ed25519_1");
ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_2.pub"), &k2,
NULL), 0);
signature_tests(k1, k2);
sshkey_free(k1);
sshkey_free(k2);
TEST_DONE();
TEST_START("nested certificate");
ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0);
ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2,
NULL), 0);
b = load_file("rsa_2");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(b, "", "rsa_1",
&k3, NULL), 0);
sshbuf_reset(b);
k3 = get_private("ed25519_2");
build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1);
ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4),
SSH_ERR_KEY_CERT_INVALID_SIGN_KEY);
ASSERT_PTR_EQ(k4, NULL);
sshbuf_free(b);
sshkey_free(k1);
sshkey_free(k2);
sshkey_free(k3);
sshbuf_free(b);
TEST_DONE();
}