Fix Wycheproof tests for params
This commit is contained in:
parent
a6208487e4
commit
61d9652b2e
@ -60,9 +60,148 @@ hexparse(const char *s, uint8_t *out, size_t *outlen)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct testcase {
|
||||||
|
uint8_t *key;
|
||||||
|
size_t keylen;
|
||||||
|
size_t keylenarg;
|
||||||
|
uint8_t *iv;
|
||||||
|
size_t ivlen;
|
||||||
|
size_t ivlenarg;
|
||||||
|
uint8_t *tag;
|
||||||
|
size_t taglen;
|
||||||
|
size_t taglenarg;
|
||||||
|
uint8_t *aad;
|
||||||
|
size_t aadlen;
|
||||||
|
uint8_t *msg;
|
||||||
|
size_t msglen;
|
||||||
|
uint8_t *ct;
|
||||||
|
size_t ctlen;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
aead_poly1305_runner(const struct lc_aead_impl *impl, const struct testcase *c,
|
||||||
|
const void *params, int verbose)
|
||||||
|
{
|
||||||
|
uint8_t *buf, *encout, *decout;
|
||||||
|
size_t aeadlen, encoutlen, decoutlen;
|
||||||
|
|
||||||
|
if (!lc_aead_seal(impl, NULL, &encoutlen, params, c->aad, c->aadlen,
|
||||||
|
c->msg, c->msglen))
|
||||||
|
return 0;
|
||||||
|
encout = malloc(encoutlen);
|
||||||
|
if (encout == NULL)
|
||||||
|
err(1, "out of memory");
|
||||||
|
if (!lc_aead_seal(impl, encout, &encoutlen, params, c->aad, c->aadlen,
|
||||||
|
c->msg, c->msglen))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (c->ctlen != encoutlen - LC_POLY1305_TAGLEN ||
|
||||||
|
!lc_ct_cmp(encout, c->ct, c->ctlen)) {
|
||||||
|
if (verbose) {
|
||||||
|
fprintf(stderr, "ct (%zu, %zu)\n", c->ctlen,
|
||||||
|
encoutlen - LC_POLY1305_TAGLEN);
|
||||||
|
lc_hexdump_fp(stderr, c->msg, c->msglen);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
lc_hexdump_fp(stderr, c->ct, c->ctlen);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
lc_hexdump_fp(stderr, encout,
|
||||||
|
encoutlen - LC_POLY1305_TAGLEN);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (c->taglenarg != LC_POLY1305_TAGLEN ||
|
||||||
|
!lc_ct_cmp(encout + c->ctlen, c->tag, LC_POLY1305_TAGLEN)) {
|
||||||
|
if (verbose) {
|
||||||
|
fprintf(stderr, "tag (%zu, %zu)\n", c->taglenarg,
|
||||||
|
(size_t)LC_POLY1305_TAGLEN);
|
||||||
|
lc_hexdump_fp(stderr, c->tag, c->taglen);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
lc_hexdump_fp(stderr, encout + c->ctlen,
|
||||||
|
LC_POLY1305_TAGLEN);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decryption. */
|
||||||
|
|
||||||
|
aeadlen = c->msglen + c->taglen;
|
||||||
|
buf = malloc(aeadlen);
|
||||||
|
if (buf == NULL)
|
||||||
|
err(1, "out of memory");
|
||||||
|
memcpy(buf, c->ct, c->ctlen);
|
||||||
|
memcpy(buf + c->ctlen, c->tag, c->taglen);
|
||||||
|
|
||||||
|
if (!lc_aead_open(impl, NULL, &decoutlen, params, c->aad, c->aadlen,
|
||||||
|
buf, aeadlen))
|
||||||
|
return 0;
|
||||||
|
decout = malloc(decoutlen);
|
||||||
|
if (decout == NULL)
|
||||||
|
err(1, "out of memory");
|
||||||
|
if (!lc_aead_open(impl, decout, &decoutlen, params, c->aad, c->aadlen,
|
||||||
|
buf, aeadlen))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (c->msglen != decoutlen || !lc_ct_cmp(decout, c->msg, c->msglen)) {
|
||||||
|
if (verbose) {
|
||||||
|
fprintf(stderr, "ct (%zu, %zu)\n", c->msglen,
|
||||||
|
decoutlen);
|
||||||
|
lc_hexdump_fp(stderr, c->msg, c->msglen);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
lc_hexdump_fp(stderr, c->ct, c->ctlen);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
lc_hexdump_fp(stderr, decout, decoutlen);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Tag isn't checked, as it's already validated by lc_aead_open. */
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
chacha20_poly1305_runner(const struct testcase *c, int verbose)
|
||||||
|
{
|
||||||
|
struct lc_chacha20_poly1305_params params;
|
||||||
|
|
||||||
|
if (c->keylenarg != LC_CHACHA20_KEYLEN ||
|
||||||
|
c->keylen != LC_CHACHA20_KEYLEN)
|
||||||
|
return 0;
|
||||||
|
memcpy(params.key, c->key, LC_CHACHA20_KEYLEN);
|
||||||
|
|
||||||
|
if (c->ivlenarg != LC_CHACHA20_NONCELEN ||
|
||||||
|
c->ivlen != LC_CHACHA20_NONCELEN)
|
||||||
|
return 0;
|
||||||
|
memcpy(params.nonce, c->iv, LC_CHACHA20_NONCELEN);
|
||||||
|
|
||||||
|
return aead_poly1305_runner(lc_aead_impl_chacha20_poly1305(), c,
|
||||||
|
¶ms, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
xchacha20_poly1305_runner(const struct testcase *c, int verbose)
|
||||||
|
{
|
||||||
|
struct lc_xchacha20_poly1305_params params;
|
||||||
|
|
||||||
|
if (c->keylenarg != LC_XCHACHA20_KEYLEN ||
|
||||||
|
c->keylen != LC_XCHACHA20_KEYLEN)
|
||||||
|
return 0;
|
||||||
|
memcpy(params.key, c->key, LC_XCHACHA20_KEYLEN);
|
||||||
|
|
||||||
|
if (c->ivlenarg != LC_XCHACHA20_NONCELEN ||
|
||||||
|
c->ivlen != LC_XCHACHA20_NONCELEN)
|
||||||
|
return 0;
|
||||||
|
memcpy(params.nonce, c->iv, LC_XCHACHA20_NONCELEN);
|
||||||
|
|
||||||
|
return aead_poly1305_runner(lc_aead_impl_xchacha20_poly1305(), c,
|
||||||
|
¶ms, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
struct kwimpl {
|
struct kwimpl {
|
||||||
const char *kw;
|
const char *kw;
|
||||||
const struct lc_aead_impl *(*impl)(void);
|
int (*runner)(const struct testcase *, int);
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -74,19 +213,19 @@ kwimpl_cmp(const void *k0, const void *h0)
|
|||||||
return strcmp(k, h->kw);
|
return strcmp(k, h->kw);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct lc_aead_impl *
|
static int
|
||||||
kw2impl(const char *s)
|
(*kw2impl(const char *s))(const struct testcase *, int)
|
||||||
{
|
{
|
||||||
static const struct kwimpl tbl[] = {
|
static const struct kwimpl tbl[] = {
|
||||||
{ "CHACHA20-POLY1305", &lc_aead_impl_chacha20_poly1305 },
|
{ "CHACHA20-POLY1305", &chacha20_poly1305_runner },
|
||||||
{ "XCHACHA20-POLY1305", &lc_aead_impl_xchacha20_poly1305 },
|
{ "XCHACHA20-POLY1305", &xchacha20_poly1305_runner },
|
||||||
};
|
};
|
||||||
struct kwimpl *match;
|
struct kwimpl *match;
|
||||||
|
|
||||||
match = bsearch(s, tbl, nelems(tbl), sizeof(struct kwimpl),
|
match = bsearch(s, tbl, nelems(tbl), sizeof(struct kwimpl),
|
||||||
&kwimpl_cmp);
|
&kwimpl_cmp);
|
||||||
|
|
||||||
return match != NULL ? match->impl() : NULL;
|
return match != NULL ? match->runner : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -99,13 +238,10 @@ usage(void)
|
|||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
const struct lc_aead_impl *impl;
|
int (*runner)(const struct testcase *, int);
|
||||||
uint8_t *aad, *ct, *iv, *key, *msg, *tag, *encout, *decout,
|
|
||||||
*buf;
|
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
size_t aadlen, ctlen, ivlen, keylen, msglen, taglen;
|
struct testcase c;
|
||||||
size_t ivlenarg, keylenarg, taglenarg;
|
size_t l;
|
||||||
size_t l, encoutlen, decoutlen;
|
|
||||||
int aflag, cflag, Iflag, iflag, Kflag, kflag, mflag,
|
int aflag, cflag, Iflag, iflag, Kflag, kflag, mflag,
|
||||||
Tflag, tflag;
|
Tflag, tflag;
|
||||||
int ch, verbose;
|
int ch, verbose;
|
||||||
@ -113,8 +249,8 @@ main(int argc, char *argv[])
|
|||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
impl = kw2impl(argv[1]);
|
runner = kw2impl(argv[1]);
|
||||||
if (impl == NULL)
|
if (runner == NULL)
|
||||||
errx(1, "unsupported algorithm: %s", argv[1]);
|
errx(1, "unsupported algorithm: %s", argv[1]);
|
||||||
|
|
||||||
optind = 2;
|
optind = 2;
|
||||||
@ -125,97 +261,97 @@ main(int argc, char *argv[])
|
|||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'a':
|
case 'a':
|
||||||
aflag = 1;
|
aflag = 1;
|
||||||
(void)hexparse(optarg, NULL, &aadlen);
|
(void)hexparse(optarg, NULL, &c.aadlen);
|
||||||
if (aadlen != 0) {
|
if (c.aadlen != 0) {
|
||||||
aad = malloc(aadlen);
|
c.aad = malloc(c.aadlen);
|
||||||
if (aad == NULL)
|
if (c.aad == NULL)
|
||||||
err(1, "out of memory");
|
err(1, "out of memory");
|
||||||
} else
|
} else
|
||||||
aad = NULL;
|
c.aad = NULL;
|
||||||
if (!hexparse(optarg, aad, &l) || l != aadlen)
|
if (!hexparse(optarg, c.aad, &l) || l != c.aadlen)
|
||||||
errx(1, "invalid hex string: %s", optarg);
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
cflag = 1;
|
cflag = 1;
|
||||||
(void)hexparse(optarg, NULL, &ctlen);
|
(void)hexparse(optarg, NULL, &c.ctlen);
|
||||||
if (ctlen != 0) {
|
if (c.ctlen != 0) {
|
||||||
ct = malloc(ctlen);
|
c.ct = malloc(c.ctlen);
|
||||||
if (ct == NULL)
|
if (c.ct == NULL)
|
||||||
err(1, "out of memory");
|
err(1, "out of memory");
|
||||||
} else
|
} else
|
||||||
ct = NULL;
|
c.ct = NULL;
|
||||||
if (!hexparse(optarg, ct, &l) || l != ctlen)
|
if (!hexparse(optarg, c.ct, &l) || l != c.ctlen)
|
||||||
errx(1, "invalid hex string: %s", optarg);
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
Iflag = 1;
|
Iflag = 1;
|
||||||
ivlenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
c.ivlenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
errx(1, "ivlen is %s: %s", errstr, optarg);
|
errx(1, "ivlen is %s: %s", errstr, optarg);
|
||||||
ivlenarg /= 8;
|
c.ivlenarg /= 8;
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
iflag = 1;
|
iflag = 1;
|
||||||
(void)hexparse(optarg, NULL, &ivlen);
|
(void)hexparse(optarg, NULL, &c.ivlen);
|
||||||
if (ivlen != 0) {
|
if (c.ivlen != 0) {
|
||||||
iv = malloc(ivlen);
|
c.iv = malloc(c.ivlen);
|
||||||
if (iv == NULL)
|
if (c.iv == NULL)
|
||||||
err(1, "out of memory");
|
err(1, "out of memory");
|
||||||
} else
|
} else
|
||||||
iv = NULL;
|
c.iv = NULL;
|
||||||
if (!hexparse(optarg, iv, &l) || l != ivlen)
|
if (!hexparse(optarg, c.iv, &l) || l != c.ivlen)
|
||||||
errx(1, "invalid hex string: %s", optarg);
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
break;
|
break;
|
||||||
case 'K':
|
case 'K':
|
||||||
Kflag = 1;
|
Kflag = 1;
|
||||||
keylenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
c.keylenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
errx(1, "keylen is %s: %s", errstr, optarg);
|
errx(1, "keylen is %s: %s", errstr, optarg);
|
||||||
if (keylenarg % 8 != 0)
|
if (c.keylenarg % 8 != 0)
|
||||||
errx(1, "unsupport K value: %zu", keylenarg);
|
errx(1, "unsupport K value: %zu", c.keylenarg);
|
||||||
keylenarg /= 8;
|
c.keylenarg /= 8;
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
kflag = 1;
|
kflag = 1;
|
||||||
(void)hexparse(optarg, NULL, &keylen);
|
(void)hexparse(optarg, NULL, &c.keylen);
|
||||||
if (keylen != 0) {
|
if (c.keylen != 0) {
|
||||||
key = malloc(keylen);
|
c.key = malloc(c.keylen);
|
||||||
if (key == NULL)
|
if (c.key == NULL)
|
||||||
err(1, "out of memory");
|
err(1, "out of memory");
|
||||||
} else
|
} else
|
||||||
key = NULL;
|
c.key = NULL;
|
||||||
if (!hexparse(optarg, key, &l) || l != keylen)
|
if (!hexparse(optarg, c.key, &l) || l != c.keylen)
|
||||||
errx(1, "invalid hex string: %s", optarg);
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
mflag = 1;
|
mflag = 1;
|
||||||
(void)hexparse(optarg, NULL, &msglen);
|
(void)hexparse(optarg, NULL, &c.msglen);
|
||||||
if (msglen != 0) {
|
if (c.msglen != 0) {
|
||||||
msg = malloc(msglen);
|
c.msg = malloc(c.msglen);
|
||||||
if (msg == NULL)
|
if (c.msg == NULL)
|
||||||
err(1, "out of memory");
|
err(1, "out of memory");
|
||||||
} else
|
} else
|
||||||
msg = NULL;
|
c.msg = NULL;
|
||||||
if (!hexparse(optarg, msg, &l) || l != msglen)
|
if (!hexparse(optarg, c.msg, &l) || l != c.msglen)
|
||||||
errx(1, "invalid hex string: %s", optarg);
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
Tflag = 1;
|
Tflag = 1;
|
||||||
taglenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
c.taglenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
errx(1, "taglen is %s: %s", errstr, optarg);
|
errx(1, "taglen is %s: %s", errstr, optarg);
|
||||||
taglenarg /= 8;
|
c.taglenarg /= 8;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
tflag = 1;
|
tflag = 1;
|
||||||
(void)hexparse(optarg, NULL, &taglen);
|
(void)hexparse(optarg, NULL, &c.taglen);
|
||||||
if (taglen != 0) {
|
if (c.taglen != 0) {
|
||||||
tag = malloc(taglen);
|
c.tag = malloc(c.taglen);
|
||||||
if (tag == NULL)
|
if (c.tag == NULL)
|
||||||
err(1, "out of memory");
|
err(1, "out of memory");
|
||||||
} else
|
} else
|
||||||
tag = NULL;
|
c.tag = NULL;
|
||||||
if (!hexparse(optarg, tag, &l) || l != taglen)
|
if (!hexparse(optarg, c.tag, &l) || l != c.taglen)
|
||||||
errx(1, "invalid hex string: %s", optarg);
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
@ -233,90 +369,11 @@ main(int argc, char *argv[])
|
|||||||
Tflag && tflag))
|
Tflag && tflag))
|
||||||
errx(1, "missing required arguments");
|
errx(1, "missing required arguments");
|
||||||
|
|
||||||
/* Encryption. */
|
if (runner(&c, verbose)) {
|
||||||
|
|
||||||
if (!lc_aead_seal(impl, NULL, &encoutlen, key, keylenarg, iv, ivlenarg,
|
|
||||||
aad, aadlen, msg, msglen)) {
|
|
||||||
puts("invalid");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
encout = malloc(encoutlen);
|
|
||||||
if (encout == NULL)
|
|
||||||
err(1, "out of memory");
|
|
||||||
if (!lc_aead_seal(impl, encout, &encoutlen, key, keylenarg, iv,
|
|
||||||
ivlenarg, aad, aadlen, msg, msglen)) {
|
|
||||||
puts("invalid");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctlen != encoutlen - LC_POLY1305_TAGLEN ||
|
|
||||||
!lc_ct_cmp(encout, ct, ctlen)) {
|
|
||||||
if (verbose) {
|
|
||||||
fprintf(stderr, "ct (%zu, %zu)\n", ctlen,
|
|
||||||
encoutlen - LC_POLY1305_TAGLEN);
|
|
||||||
lc_hexdump_fp(stderr, msg, msglen);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
lc_hexdump_fp(stderr, ct, ctlen);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
lc_hexdump_fp(stderr, encout,
|
|
||||||
encoutlen - LC_POLY1305_TAGLEN);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
puts("invalid");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (taglenarg != LC_POLY1305_TAGLEN ||
|
|
||||||
!lc_ct_cmp(encout + ctlen, tag, LC_POLY1305_TAGLEN)) {
|
|
||||||
if (verbose) {
|
|
||||||
fprintf(stderr, "tag (%zu, %zu)\n", taglenarg,
|
|
||||||
(size_t)LC_POLY1305_TAGLEN);
|
|
||||||
lc_hexdump_fp(stderr, tag, taglen);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
lc_hexdump_fp(stderr, encout + ctlen,
|
|
||||||
LC_POLY1305_TAGLEN);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
puts("invalid");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decryption. */
|
|
||||||
|
|
||||||
buf = malloc(msglen + taglen);
|
|
||||||
if (buf == NULL)
|
|
||||||
err(1, "out of memory");
|
|
||||||
memcpy(buf, ct, ctlen);
|
|
||||||
memcpy(buf + ctlen, tag, taglen);
|
|
||||||
|
|
||||||
if (!lc_aead_open(impl, NULL, &decoutlen, key, keylenarg, iv, ivlenarg,
|
|
||||||
aad, aadlen, buf, ctlen + taglen)) {
|
|
||||||
puts("invalid");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
decout = malloc(decoutlen);
|
|
||||||
if (encout == NULL)
|
|
||||||
err(1, "out of memory");
|
|
||||||
if (!lc_aead_open(impl, decout, &decoutlen, key, keylenarg, iv,
|
|
||||||
ivlenarg, aad, aadlen, buf, ctlen + taglen)) {
|
|
||||||
puts("invalid");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msglen != decoutlen || !lc_ct_cmp(decout, msg, msglen)) {
|
|
||||||
if (verbose) {
|
|
||||||
fprintf(stderr, "ct (%zu, %zu)\n", msglen, decoutlen);
|
|
||||||
lc_hexdump_fp(stderr, msg, msglen);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
lc_hexdump_fp(stderr, ct, ctlen);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
lc_hexdump_fp(stderr, decout, decoutlen);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
puts("invalid");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* Tag isn't checked, as it's already validated by lc_aead_open. */
|
|
||||||
|
|
||||||
puts("valid");
|
puts("valid");
|
||||||
return 0;
|
return 0;
|
||||||
|
} else {
|
||||||
|
puts("invalid");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
207
wycheproof_mac.c
207
wycheproof_mac.c
@ -60,9 +60,97 @@ hexparse(const char *s, uint8_t *out, size_t *outlen)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct testcase {
|
||||||
|
uint8_t *key;
|
||||||
|
size_t keylen;
|
||||||
|
size_t keylenarg;
|
||||||
|
uint8_t *tag;
|
||||||
|
size_t taglen;
|
||||||
|
size_t taglenarg;
|
||||||
|
uint8_t *msg;
|
||||||
|
size_t msglen;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
hmac_sha2_runner(const struct lc_auth_impl *impl, const struct testcase *c,
|
||||||
|
int verbose)
|
||||||
|
{
|
||||||
|
struct lc_hmac_params params;
|
||||||
|
struct lc_auth_ctx *ctx;
|
||||||
|
uint8_t *buf;
|
||||||
|
size_t olen;
|
||||||
|
|
||||||
|
if (c->keylen != c->keylenarg)
|
||||||
|
return 0;
|
||||||
|
params.key = c->key;
|
||||||
|
params.keylen = c->keylen;
|
||||||
|
|
||||||
|
ctx = lc_auth_ctx_new(impl);
|
||||||
|
if (ctx == NULL)
|
||||||
|
errx(1, "can't allocate ctx");
|
||||||
|
|
||||||
|
if (!lc_auth_init(ctx, ¶ms) ||
|
||||||
|
!lc_auth_update(ctx, c->msg, c->msglen) ||
|
||||||
|
!lc_auth_final(ctx, NULL, &olen))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
buf = malloc(olen);
|
||||||
|
if (buf == NULL)
|
||||||
|
err(1, "out of memory");
|
||||||
|
|
||||||
|
if (!lc_auth_final(ctx, buf, &olen))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests include truncated output. Skip checking olen as it'll always
|
||||||
|
* be the full-length hash.
|
||||||
|
*/
|
||||||
|
if (c->taglen != c->taglenarg ||
|
||||||
|
!lc_ct_cmp(buf, c->tag, c->taglen)) {
|
||||||
|
if (verbose) {
|
||||||
|
fprintf(stderr, "tag (%zu, %zu, %zu)\n", c->taglen,
|
||||||
|
c->taglenarg, olen);
|
||||||
|
lc_hexdump_fp(stderr, c->tag, c->taglen);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
lc_hexdump_fp(stderr, buf, olen);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
lc_auth_ctx_free(ctx);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hmac_sha224_runner(const struct testcase *c, int verbose)
|
||||||
|
{
|
||||||
|
return hmac_sha2_runner(lc_auth_impl_hmac_sha224(), c, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hmac_sha256_runner(const struct testcase *c, int verbose)
|
||||||
|
{
|
||||||
|
return hmac_sha2_runner(lc_auth_impl_hmac_sha256(), c, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hmac_sha384_runner(const struct testcase *c, int verbose)
|
||||||
|
{
|
||||||
|
return hmac_sha2_runner(lc_auth_impl_hmac_sha384(), c, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hmac_sha512_runner(const struct testcase *c, int verbose)
|
||||||
|
{
|
||||||
|
return hmac_sha2_runner(lc_auth_impl_hmac_sha512(), c, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
struct kwimpl {
|
struct kwimpl {
|
||||||
const char *kw;
|
const char *kw;
|
||||||
const struct lc_auth_impl *(*impl)(void);
|
int (*runner)(const struct testcase *, int);
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -74,22 +162,22 @@ kwimpl_cmp(const void *k0, const void *h0)
|
|||||||
return strcmp(k, h->kw);
|
return strcmp(k, h->kw);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct lc_auth_impl *
|
static int
|
||||||
kw2impl(const char *s)
|
(*kw2impl(const char *s))(const struct testcase *, int)
|
||||||
{
|
{
|
||||||
/* Needs to be sorted. */
|
/* Needs to be sorted. */
|
||||||
static const struct kwimpl tbl[] = {
|
static const struct kwimpl tbl[] = {
|
||||||
{ "HMACSHA224", &lc_auth_impl_hmac_sha224 },
|
{ "HMACSHA224", &hmac_sha224_runner },
|
||||||
{ "HMACSHA256", &lc_auth_impl_hmac_sha256 },
|
{ "HMACSHA256", &hmac_sha256_runner },
|
||||||
{ "HMACSHA384", &lc_auth_impl_hmac_sha384 },
|
{ "HMACSHA384", &hmac_sha384_runner },
|
||||||
{ "HMACSHA512", &lc_auth_impl_hmac_sha512 },
|
{ "HMACSHA512", &hmac_sha512_runner },
|
||||||
};
|
};
|
||||||
struct kwimpl *match;
|
struct kwimpl *match;
|
||||||
|
|
||||||
match = bsearch(s, tbl, nelems(tbl), sizeof(struct kwimpl),
|
match = bsearch(s, tbl, nelems(tbl), sizeof(struct kwimpl),
|
||||||
&kwimpl_cmp);
|
&kwimpl_cmp);
|
||||||
|
|
||||||
return match != NULL ? match->impl() : NULL;
|
return match != NULL ? match->runner : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -102,21 +190,18 @@ usage(void)
|
|||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
const struct lc_auth_impl *impl;
|
int (*runner)(const struct testcase *, int);
|
||||||
struct lc_auth_ctx *ctx;
|
|
||||||
uint8_t *key, *msg, *tag, *buf;
|
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
size_t keylen, msglen, taglen;
|
struct testcase c;
|
||||||
size_t keylenarg, taglenarg;
|
size_t l;
|
||||||
size_t l, olen;
|
|
||||||
int Kflag, kflag, mflag, Tflag, tflag;
|
int Kflag, kflag, mflag, Tflag, tflag;
|
||||||
int ch, verbose;
|
int ch, verbose;
|
||||||
|
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
impl = kw2impl(argv[1]);
|
runner = kw2impl(argv[1]);
|
||||||
if (impl == NULL)
|
if (runner == NULL)
|
||||||
errx(1, "unsupported algorithm: %s", argv[1]);
|
errx(1, "unsupported algorithm: %s", argv[1]);
|
||||||
|
|
||||||
optind = 2;
|
optind = 2;
|
||||||
@ -126,54 +211,54 @@ main(int argc, char *argv[])
|
|||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'K':
|
case 'K':
|
||||||
Kflag = 1;
|
Kflag = 1;
|
||||||
keylenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
c.keylenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
errx(1, "keylen is %s: %s", errstr, optarg);
|
errx(1, "keylen is %s: %s", errstr, optarg);
|
||||||
if (keylenarg % 8 != 0)
|
if (c.keylenarg % 8 != 0)
|
||||||
errx(1, "unsupport K value: %zu", keylenarg);
|
errx(1, "unsupport K value: %zu", c.keylenarg);
|
||||||
keylenarg /= 8;
|
c.keylenarg /= 8;
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
kflag = 1;
|
kflag = 1;
|
||||||
(void)hexparse(optarg, NULL, &keylen);
|
(void)hexparse(optarg, NULL, &c.keylen);
|
||||||
if (keylen != 0) {
|
if (c.keylen != 0) {
|
||||||
key = malloc(keylen);
|
c.key = malloc(c.keylen);
|
||||||
if (key == NULL)
|
if (c.key == NULL)
|
||||||
err(1, "out of memory");
|
err(1, "out of memory");
|
||||||
} else
|
} else
|
||||||
key = NULL;
|
c.key = NULL;
|
||||||
if (!hexparse(optarg, key, &l) || l != keylen)
|
if (!hexparse(optarg, c.key, &l) || l != c.keylen)
|
||||||
errx(1, "invalid hex string: %s", optarg);
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
mflag = 1;
|
mflag = 1;
|
||||||
(void)hexparse(optarg, NULL, &msglen);
|
(void)hexparse(optarg, NULL, &c.msglen);
|
||||||
if (msglen != 0) {
|
if (c.msglen != 0) {
|
||||||
msg = malloc(msglen);
|
c.msg = malloc(c.msglen);
|
||||||
if (msg == NULL)
|
if (c.msg == NULL)
|
||||||
err(1, "out of memory");
|
err(1, "out of memory");
|
||||||
} else
|
} else
|
||||||
msg = NULL;
|
c.msg = NULL;
|
||||||
if (!hexparse(optarg, msg, &l) || l != msglen)
|
if (!hexparse(optarg, c.msg, &l) || l != c.msglen)
|
||||||
errx(1, "invalid hex string: %s", optarg);
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
Tflag = 1;
|
Tflag = 1;
|
||||||
taglenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
c.taglenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
errx(1, "taglen is %s: %s", errstr, optarg);
|
errx(1, "taglen is %s: %s", errstr, optarg);
|
||||||
taglenarg /= 8;
|
c.taglenarg /= 8;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
tflag = 1;
|
tflag = 1;
|
||||||
(void)hexparse(optarg, NULL, &taglen);
|
(void)hexparse(optarg, NULL, &c.taglen);
|
||||||
if (taglen != 0) {
|
if (c.taglen != 0) {
|
||||||
tag = malloc(taglen);
|
c.tag = malloc(c.taglen);
|
||||||
if (tag == NULL)
|
if (c.tag == NULL)
|
||||||
err(1, "out of memory");
|
err(1, "out of memory");
|
||||||
} else
|
} else
|
||||||
tag = NULL;
|
c.tag = NULL;
|
||||||
if (!hexparse(optarg, tag, &l) || l != taglen)
|
if (!hexparse(optarg, c.tag, &l) || l != c.taglen)
|
||||||
errx(1, "invalid hex string: %s", optarg);
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
@ -190,46 +275,14 @@ main(int argc, char *argv[])
|
|||||||
if (!(Kflag && kflag && mflag && Tflag && tflag))
|
if (!(Kflag && kflag && mflag && Tflag && tflag))
|
||||||
errx(1, "missing required arguments");
|
errx(1, "missing required arguments");
|
||||||
|
|
||||||
ctx = lc_auth_ctx_new(impl);
|
if (runner(&c, verbose)) {
|
||||||
if (ctx == NULL)
|
puts("valid");
|
||||||
errx(1, "can't allocate ctx");
|
return 0;
|
||||||
if (!lc_auth_init(ctx, key, keylenarg) ||
|
} else {
|
||||||
!lc_auth_update(ctx, msg, msglen) ||
|
|
||||||
!lc_auth_final(ctx, NULL, &olen)) {
|
|
||||||
puts("invalid");
|
puts("invalid");
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = malloc(olen);
|
|
||||||
if (buf == NULL)
|
|
||||||
err(1, "out of memory");
|
|
||||||
|
|
||||||
if (!lc_auth_final(ctx, buf, &olen)) {
|
|
||||||
puts("invalid");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Tests include truncated output. Skip checking olen as it'll always
|
|
||||||
* be the full-length hash.
|
|
||||||
*/
|
|
||||||
if (taglen != taglenarg ||
|
|
||||||
!lc_ct_cmp(buf, tag, taglen)) {
|
|
||||||
if (verbose) {
|
|
||||||
fprintf(stderr, "tag (%zu, %zu, %zu)\n", taglen,
|
|
||||||
taglenarg, olen);
|
|
||||||
lc_hexdump_fp(stderr, tag, taglen);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
lc_hexdump_fp(stderr, buf, olen);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
puts("invalid");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
lc_auth_ctx_free(ctx);
|
|
||||||
|
|
||||||
puts("valid");
|
puts("valid");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user