Add KDF interface and HKDF implementation
This commit is contained in:
parent
cef67c9f09
commit
5eb28b420d
@ -3,6 +3,7 @@ LC_SRCS+= auth.c auth_hmac.c auth_poly1305.c
|
||||
LC_SRCS+= cipher.c cipher_chacha20.c
|
||||
LC_SRCS+= hash.c hash_sha224_sha256.c hash_sha384_sha512.c
|
||||
LC_SRCS+= impl_chacha20.c impl_poly1305.c impl_sha256.c impl_sha512.c
|
||||
LC_SRCS+= kdf.c kdf_hkdf.c
|
||||
LC_SRCS+= ct.c util.c
|
||||
|
||||
WARNINGS= Yes
|
||||
|
11
README
11
README
@ -52,6 +52,12 @@ ECC
|
||||
- [ ] Ed25519 (EdDSA)
|
||||
- [ ] X25519 (ECDH)
|
||||
|
||||
KDF
|
||||
---
|
||||
|
||||
- [x] HKDF
|
||||
|
||||
|
||||
Nice-to-haves
|
||||
=============
|
||||
|
||||
@ -85,8 +91,3 @@ AEAD
|
||||
- [ ] Camellia-GCM
|
||||
- [ ] Salsa20-Poly1305 (no Wycherproof test vector suite)
|
||||
- [ ] XSalsa20-Poly1305 (no Wycherproof test vector suite)
|
||||
|
||||
KDF
|
||||
---
|
||||
|
||||
- [ ] HKDF
|
||||
|
@ -27,6 +27,7 @@
|
||||
/* Authentitcation. */
|
||||
|
||||
#define HMAC_BLOCKLEN_MAX LC_SHA512_BLOCKLEN
|
||||
#define HMAC_HASHLEN_MAX LC_SHA512_HASHLEN
|
||||
|
||||
#define POLY1305_TAGLEN_WORDS (LC_POLY1305_TAGLEN / sizeof(uint32_t))
|
||||
|
||||
@ -108,6 +109,12 @@ struct lc_hash_impl {
|
||||
size_t hashlen;
|
||||
};
|
||||
|
||||
struct lc_kdf_impl {
|
||||
int (*kdf)(uint8_t *, size_t *, void *, size_t);
|
||||
|
||||
size_t argsz;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* *_ctx binds an *_impl with an state, effectively representing an instance of a
|
||||
|
25
kdf.c
Normal file
25
kdf.c
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
int
|
||||
lc_kdf(const struct lc_kdf_impl *impl, uint8_t *out, size_t *outlen,
|
||||
void *initargs, size_t len)
|
||||
{
|
||||
return impl->kdf(out, outlen, initargs, len);
|
||||
}
|
109
kdf_hkdf.c
Normal file
109
kdf_hkdf.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
static uint8_t zeros[HMAC_HASHLEN_MAX];
|
||||
|
||||
|
||||
static int
|
||||
hkdf_kdf(uint8_t *out, size_t *outlen, void *initparams, size_t len)
|
||||
{
|
||||
struct lc_hkdf_params *params = initparams;
|
||||
struct lc_hmac_params hmacparams;
|
||||
uint8_t prk[HMAC_HASHLEN_MAX];
|
||||
uint8_t t[HMAC_HASHLEN_MAX], tn[HMAC_HASHLEN_MAX];
|
||||
size_t hashlen, olen;
|
||||
uint8_t ctr;
|
||||
|
||||
/* Only accept HMAC as auth_impl. */
|
||||
if (params->hmac == NULL ||
|
||||
params->hmac->impl != lc_auth_impl_hmac())
|
||||
return 0;
|
||||
|
||||
hashlen = params->hash->impl->hashlen;
|
||||
|
||||
/* XXX *outlen = 0 ? */
|
||||
if (len > hashlen * 255)
|
||||
return 0;
|
||||
|
||||
if (out == NULL) {
|
||||
*outlen = len;
|
||||
return 1;
|
||||
}
|
||||
*outlen = 0;
|
||||
|
||||
hmacparams.hash = params->hash;
|
||||
if (params->saltlen == 0) {
|
||||
hmacparams.key = zeros;
|
||||
hmacparams.keylen = hashlen;
|
||||
} else {
|
||||
hmacparams.key = params->salt;
|
||||
hmacparams.keylen = params->saltlen;
|
||||
}
|
||||
|
||||
if (!lc_auth(params->hmac->impl, prk, &olen, &hmacparams, params->ikm,
|
||||
params->ikmlen))
|
||||
return 0;
|
||||
|
||||
hmacparams.key = prk;
|
||||
hmacparams.keylen = olen;
|
||||
olen = 0;
|
||||
ctr = 1;
|
||||
while (len >= hashlen) {
|
||||
memcpy(t, tn, olen);
|
||||
if (!lc_auth_init(params->hmac, &hmacparams) ||
|
||||
!lc_auth_update(params->hmac, t, olen) ||
|
||||
!lc_auth_update(params->hmac, params->info,
|
||||
params->infolen) ||
|
||||
!lc_auth_update(params->hmac, &ctr, sizeof(ctr)) ||
|
||||
!lc_auth_final(params->hmac, tn, &olen))
|
||||
return 0;
|
||||
ctr++;
|
||||
|
||||
memcpy(out, tn, hashlen);
|
||||
*outlen += hashlen;
|
||||
out += hashlen;
|
||||
len -= hashlen;
|
||||
}
|
||||
|
||||
memcpy(t, tn, olen);
|
||||
if (!lc_auth_init(params->hmac, &hmacparams) ||
|
||||
!lc_auth_update(params->hmac, t, olen) ||
|
||||
!lc_auth_update(params->hmac, params->info, params->infolen) ||
|
||||
!lc_auth_update(params->hmac, &ctr, sizeof(ctr)) ||
|
||||
!lc_auth_final(params->hmac, tn, &olen))
|
||||
return 0;
|
||||
|
||||
memcpy(out, tn, len);
|
||||
*outlen += len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
const struct lc_kdf_impl *
|
||||
lc_kdf_impl_hkdf(void)
|
||||
{
|
||||
static struct lc_kdf_impl hkdf_impl = {
|
||||
.kdf = &hkdf_kdf,
|
||||
};
|
||||
|
||||
return &hkdf_impl;
|
||||
}
|
25
lilcrypto.h
25
lilcrypto.h
@ -69,6 +69,8 @@ struct lc_cipher_impl;
|
||||
struct lc_hash_ctx;
|
||||
struct lc_hash_impl;
|
||||
|
||||
struct lc_kdf_impl;
|
||||
|
||||
/*
|
||||
* Parameters.
|
||||
*/
|
||||
@ -111,6 +113,19 @@ struct lc_xchacha20_poly1305_params {
|
||||
uint8_t nonce[LC_XCHACHA20_NONCELEN];
|
||||
};
|
||||
|
||||
/* KDF. */
|
||||
|
||||
struct lc_hkdf_params {
|
||||
struct lc_hash_ctx *hash;
|
||||
struct lc_auth_ctx *hmac;
|
||||
uint8_t *ikm;
|
||||
size_t ikmlen;
|
||||
uint8_t *info;
|
||||
size_t infolen;
|
||||
uint8_t *salt;
|
||||
size_t saltlen;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Constant-time operations.
|
||||
@ -194,6 +209,16 @@ const struct lc_aead_impl *lc_aead_impl_chacha20_poly1305(void);
|
||||
const struct lc_aead_impl *lc_aead_impl_xchacha20_poly1305(void);
|
||||
|
||||
|
||||
/*
|
||||
* Key derivation functions.
|
||||
*/
|
||||
|
||||
int lc_kdf(const struct lc_kdf_impl *, uint8_t *, size_t *, void *,
|
||||
size_t);
|
||||
|
||||
const struct lc_kdf_impl *lc_kdf_impl_hkdf(void);
|
||||
|
||||
|
||||
/*
|
||||
* Utilities.
|
||||
*/
|
||||
|
@ -1,19 +1,21 @@
|
||||
.PATH: ${.CURDIR}/..
|
||||
|
||||
AEAD= wycheproof_aead
|
||||
HKDF= wycheproof_hkdf
|
||||
MAC= wycheproof_mac
|
||||
|
||||
PROGS= ${AEAD} ${MAC}
|
||||
PROGS= ${AEAD} ${HKDF} ${MAC}
|
||||
NOMAN= noman
|
||||
|
||||
SRCS_wycheproof_aead= wycheproof_aead.c
|
||||
SRCS_wycheproof_hkdf= wycheproof_hkdf.c
|
||||
SRCS_wycheproof_mac= wycheproof_mac.c
|
||||
|
||||
DPADD+= ${.CURDIR}/../lib/obj/liblilcrypto.a
|
||||
LDADD+= ${.CURDIR}/../lib/obj/liblilcrypto.a
|
||||
|
||||
|
||||
tests: all tests-aead tests-mac
|
||||
tests: all tests-aead tests-hkdf tests-mac
|
||||
|
||||
tests-aead:
|
||||
.ifndef WYCHEPROOF_DIR
|
||||
@ -27,6 +29,22 @@ tests-aead:
|
||||
${WYCHEPROOF_DIR}/testvectors_v1/xchacha20_poly1305_test.json
|
||||
.endfor
|
||||
|
||||
tests-hkdf:
|
||||
.ifndef WYCHEPROOF_DIR
|
||||
@echo Undefined WYCHEPROOF_DIR; false
|
||||
.endif
|
||||
.for p in ${HKDF}
|
||||
perl ${.CURDIR}/hkdf.pl ${TESTOPTS} -x ./${p} \
|
||||
${WYCHEPROOF_DIR}/testvectors/hkdf_sha256_test.json \
|
||||
${WYCHEPROOF_DIR}/testvectors_v1/hkdf_sha256_test.json \
|
||||
${WYCHEPROOF_DIR}/testvectors/hkdf_sha384_test.json \
|
||||
${WYCHEPROOF_DIR}/testvectors_v1/hkdf_sha384_test.json \
|
||||
${WYCHEPROOF_DIR}/testvectors/hkdf_sha512_test.json \
|
||||
${WYCHEPROOF_DIR}/testvectors_v1/hkdf_sha512_test.json
|
||||
.endfor
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
tests-mac:
|
||||
.ifndef WYCHEPROOF_DIR
|
||||
@echo Undefined WYCHEPROOF_DIR; false
|
||||
|
69
wycheproof/hkdf.pl
Normal file
69
wycheproof/hkdf.pl
Normal file
@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env perl
|
||||
use v5.38;;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Getopt::Std;
|
||||
use JSON::PP;
|
||||
|
||||
my $progname = $0 =~ s@.*/@@r;
|
||||
|
||||
sub slurp ($fh) { local $/; <$fh> }
|
||||
|
||||
sub usage ()
|
||||
{
|
||||
say STDERR "Usage: $progname [-Cv] -x runner json_file ",
|
||||
"[json_files ...]";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
sub main ()
|
||||
{
|
||||
my %opts;
|
||||
my $rc = 0;
|
||||
|
||||
getopts("Cvx:", \%opts) && @ARGV > 0 or usage;
|
||||
usage unless defined $opts{"x"};
|
||||
|
||||
for my $f (@ARGV) {
|
||||
open(my $fh, "<", $f) or die "open failed: $!";
|
||||
|
||||
my $json = decode_json(slurp($fh));
|
||||
for my $testgroup ($json->{testGroups}->@*) {
|
||||
for my $test ($testgroup->{tests}->@*) {
|
||||
my @args;
|
||||
|
||||
push(@args, $json->{algorithm});
|
||||
push(@args, "-i", $test->{info});
|
||||
push(@args, "-K", $testgroup->{keySize});
|
||||
push(@args, "-k", $test->{ikm});
|
||||
push(@args, "-o", $test->{okm});
|
||||
push(@args, "-s", $test->{salt});
|
||||
push(@args, "-z", $test->{size});
|
||||
push(@args, "-v") if $opts{"v"};
|
||||
|
||||
open(my $th, "-|", $opts{"x"}, @args) or die;
|
||||
my $result = slurp($th);
|
||||
close($th);
|
||||
|
||||
chomp($result);
|
||||
if ($result ne $test->{result}) {
|
||||
$rc = 1;
|
||||
say STDERR "case $test->{tcId}: ",
|
||||
"expected $test->{result}: ",
|
||||
"$test->{comment} [",
|
||||
join(",", $test->{flags}->@*),
|
||||
"]";
|
||||
exit 1 unless $opts{"C"};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close($fh);
|
||||
}
|
||||
|
||||
say "ALL TESTS PASSED!" if $rc == 0;
|
||||
return $rc;
|
||||
}
|
||||
|
||||
exit main;
|
308
wycheproof_hkdf.c
Normal file
308
wycheproof_hkdf.c
Normal file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lilcrypto.h"
|
||||
|
||||
|
||||
#define nelems(_a) (sizeof((_a)) / sizeof((_a)[0]))
|
||||
|
||||
|
||||
struct testcase {
|
||||
uint8_t *ikm;
|
||||
size_t ikmlen;
|
||||
size_t ikmlenarg;
|
||||
uint8_t *info;
|
||||
size_t infolen;
|
||||
uint8_t *okm;
|
||||
size_t okmlen;
|
||||
uint8_t *salt;
|
||||
size_t saltlen;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct kwrunner {
|
||||
const char *kw;
|
||||
int (*runner)(const struct testcase *, int);
|
||||
};
|
||||
|
||||
|
||||
static int hkdf_sha2_runner(const struct lc_hash_impl *,
|
||||
const struct testcase *, int);
|
||||
static int hkdf_sha224_runner(const struct testcase *, int);
|
||||
static int hkdf_sha256_runner(const struct testcase *, int);
|
||||
static int hkdf_sha384_runner(const struct testcase *, int);
|
||||
static int hkdf_sha512_runner(const struct testcase *, int);
|
||||
|
||||
|
||||
static inline uint8_t
|
||||
hex2num(char s)
|
||||
{
|
||||
return s >= 'A' ? 10 + (s >= 'a' ? s - 'a' : s - 'A') : s - '0';
|
||||
}
|
||||
|
||||
static int
|
||||
hexparse(const char *s, uint8_t *out, size_t *outlen)
|
||||
{
|
||||
size_t l;
|
||||
|
||||
l = strlen(s);
|
||||
if (l % 2 != 0)
|
||||
return 0;
|
||||
|
||||
if (out == NULL) {
|
||||
*outlen = l / 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
*outlen = 0;
|
||||
while (*s != '\0') {
|
||||
if (!isxdigit(s[0]) || !isxdigit(s[1]))
|
||||
return 0;
|
||||
*out++ = (hex2num(s[0]) << 4) | hex2num(s[1]);
|
||||
(*outlen)++;
|
||||
s += 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
kwrunner_cmp(const void *k0, const void *h0)
|
||||
{
|
||||
const struct kwrunner *h = h0;
|
||||
const char *k = k0;
|
||||
|
||||
return strcmp(k, h->kw);
|
||||
}
|
||||
|
||||
static int
|
||||
(*kw2runner(const char *s))(const struct testcase *, int)
|
||||
{
|
||||
/* Needs to be sorted. */
|
||||
static const struct kwrunner tbl[] = {
|
||||
{ "HKDF-SHA-224", &hkdf_sha224_runner },
|
||||
{ "HKDF-SHA-256", &hkdf_sha256_runner },
|
||||
{ "HKDF-SHA-384", &hkdf_sha384_runner },
|
||||
{ "HKDF-SHA-512", &hkdf_sha512_runner },
|
||||
};
|
||||
struct kwrunner *match;
|
||||
|
||||
match = bsearch(s, tbl, nelems(tbl), sizeof(struct kwrunner),
|
||||
&kwrunner_cmp);
|
||||
|
||||
return match != NULL ? match->runner : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [options]\n", getprogname());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int (*runner)(const struct testcase *, int);
|
||||
const char *errstr;
|
||||
struct testcase c;
|
||||
size_t l;
|
||||
int iflag, Kflag, kflag, oflag, sflag, zflag;
|
||||
int ch, verbose;
|
||||
|
||||
if (argc < 2)
|
||||
usage();
|
||||
|
||||
runner = kw2runner(argv[1]);
|
||||
if (runner == NULL)
|
||||
errx(1, "unsupported algorithm: %s", argv[1]);
|
||||
|
||||
optind = 2;
|
||||
iflag = Kflag = kflag = oflag = sflag = zflag = 0;
|
||||
verbose = 0;
|
||||
while ((ch = getopt(argc, argv, "i:K:k:o:s:vz:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'i':
|
||||
iflag = 1;
|
||||
(void)hexparse(optarg, NULL, &c.infolen);
|
||||
if (c.infolen != 0) {
|
||||
c.info = malloc(c.infolen);
|
||||
if (c.info == NULL)
|
||||
err(1, "out of memory");
|
||||
} else
|
||||
c.info = NULL;
|
||||
if (!hexparse(optarg, c.info, &l) || l != c.infolen)
|
||||
errx(1, "invalid hex string: %s", optarg);
|
||||
break;
|
||||
case 'K':
|
||||
Kflag = 1;
|
||||
c.ikmlenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
errx(1, "keylen is %s: %s", errstr, optarg);
|
||||
if (c.ikmlenarg % 8 != 0)
|
||||
errx(1, "unsupport K value: %zu", c.ikmlenarg);
|
||||
c.ikmlenarg /= 8;
|
||||
break;
|
||||
case 'k':
|
||||
kflag = 1;
|
||||
(void)hexparse(optarg, NULL, &c.ikmlen);
|
||||
if (c.ikmlen != 0) {
|
||||
c.ikm = malloc(c.ikmlen);
|
||||
if (c.ikm == NULL)
|
||||
err(1, "out of memory");
|
||||
} else
|
||||
c.ikm = NULL;
|
||||
if (!hexparse(optarg, c.ikm, &l) || l != c.ikmlen)
|
||||
errx(1, "invalid hex string: %s", optarg);
|
||||
break;
|
||||
case 'o':
|
||||
oflag = 1;
|
||||
(void)hexparse(optarg, NULL, &c.okmlen);
|
||||
if (c.okmlen != 0) {
|
||||
c.okm = malloc(c.okmlen);
|
||||
if (c.okm == NULL)
|
||||
err(1, "out of memory");
|
||||
} else
|
||||
c.okm = NULL;
|
||||
if (!hexparse(optarg, c.okm, &l) || l != c.okmlen)
|
||||
errx(1, "invalid hex string: %s", optarg);
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
(void)hexparse(optarg, NULL, &c.saltlen);
|
||||
if (c.saltlen != 0) {
|
||||
c.salt = malloc(c.saltlen);
|
||||
if (c.salt == NULL)
|
||||
err(1, "out of memory");
|
||||
} else
|
||||
c.salt = NULL;
|
||||
if (!hexparse(optarg, c.salt, &l) || l != c.saltlen)
|
||||
errx(1, "invalid hex string: %s", optarg);
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'z':
|
||||
zflag = 1;
|
||||
c.size = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
errx(1, "taglen is %s: %s", errstr, optarg);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!(iflag && Kflag && kflag && oflag && sflag && zflag))
|
||||
errx(1, "missing required arguments");
|
||||
|
||||
if (runner(&c, verbose)) {
|
||||
puts("valid");
|
||||
return 0;
|
||||
} else {
|
||||
puts("invalid");
|
||||
return 0;
|
||||
}
|
||||
|
||||
puts("valid");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hkdf_sha2_runner(const struct lc_hash_impl *impl, const struct testcase *c,
|
||||
int verbose)
|
||||
{
|
||||
struct lc_hkdf_params params;
|
||||
uint8_t *buf;
|
||||
size_t olen;
|
||||
|
||||
if (c->ikmlen != c->ikmlenarg)
|
||||
return 0;
|
||||
params.ikm = c->ikm;
|
||||
params.ikmlen = c->ikmlen;
|
||||
params.info = c->info;
|
||||
params.infolen = c->infolen;
|
||||
params.salt = c->salt;
|
||||
params.saltlen = c->saltlen;
|
||||
|
||||
params.hash = lc_hash_ctx_new(impl);
|
||||
if (params.hash == NULL)
|
||||
return 0;
|
||||
params.hmac = lc_auth_ctx_new(lc_auth_impl_hmac());
|
||||
if (params.hmac == NULL)
|
||||
return 0;
|
||||
|
||||
buf = malloc(c->size);
|
||||
if (buf == NULL)
|
||||
err(1, "out of memory");
|
||||
|
||||
if (!lc_kdf(lc_kdf_impl_hkdf(), buf, &olen, ¶ms, c->size))
|
||||
return 0;
|
||||
|
||||
if (c->okmlen != olen ||
|
||||
!lc_ct_cmp(buf, c->okm, olen)) {
|
||||
if (verbose) {
|
||||
fprintf(stderr, "okmlen (%zu, %zu)\n", c->okmlen,
|
||||
olen);
|
||||
lc_hexdump_fp(stderr, c->okm, c->okmlen);
|
||||
fprintf(stderr, "\n");
|
||||
lc_hexdump_fp(stderr, buf, olen);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
lc_hash_ctx_free(params.hash);
|
||||
lc_auth_ctx_free(params.hmac);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
hkdf_sha224_runner(const struct testcase *c, int verbose)
|
||||
{
|
||||
return hkdf_sha2_runner(lc_hash_impl_sha224(), c, verbose);
|
||||
}
|
||||
|
||||
static int
|
||||
hkdf_sha256_runner(const struct testcase *c, int verbose)
|
||||
{
|
||||
return hkdf_sha2_runner(lc_hash_impl_sha256(), c, verbose);
|
||||
}
|
||||
|
||||
static int
|
||||
hkdf_sha384_runner(const struct testcase *c, int verbose)
|
||||
{
|
||||
return hkdf_sha2_runner(lc_hash_impl_sha384(), c, verbose);
|
||||
}
|
||||
|
||||
static int
|
||||
hkdf_sha512_runner(const struct testcase *c, int verbose)
|
||||
{
|
||||
return hkdf_sha2_runner(lc_hash_impl_sha512(), c, verbose);
|
||||
}
|
Loading…
Reference in New Issue
Block a user