Commit 79618ab3 authored by Mark Karpilovskij's avatar Mark Karpilovskij Committed by Daniel Salzman

libknot: replace FNV64 with SipHash in cookie hashing

Solved Issue A from the security audit
parent 0dad6544
......@@ -105,7 +105,6 @@ nobase_libknot_la_HEADERS = \
libknot/codes.h \
libknot/consts.h \
libknot/control/control.h \
libknot/cookies/alg-fnv64.h \
libknot/cookies/client.h \
libknot/cookies/server.h \
libknot/descriptor.h \
......@@ -153,7 +152,6 @@ libknot_la_SOURCES = \
libknot/binary.c \
libknot/codes.c \
libknot/control/control.c \
libknot/cookies/alg-fnv64.c \
libknot/cookies/client.c \
libknot/cookies/server.c \
libknot/descriptor.c \
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include "contrib/fnv/fnv.h"
#include "contrib/sockaddr.h"
#include "contrib/wire.h"
#include "libknot/attribute.h"
#include "libknot/cookies/alg-fnv64.h"
#include "libknot/rrtype/opt-cookie.h"
#include "libknot/errcode.h"
/*!
* \brief Update hash value.
*
* \param hash_val Hash value to be updated.
* \param sa Socket address.
*/
static inline void update_hash(Fnv64_t *hash_val, const struct sockaddr *sa)
{
assert(hash_val && sa);
size_t addr_len = 0;
void *addr = sockaddr_raw(sa, &addr_len);
if (addr) {
assert(addr_len);
*hash_val = fnv_64a_buf(addr, addr_len, *hash_val);
}
}
/*!
* \brief Compute client cookie using FNV-64.
*
* \note At least one input address must be provided.
*
* \param input Input parameters.
* \param cc_out Buffer for computed client cookie.
* \param cc_len Buffer size.
*
* \retval non-zero size of written data on successful return
* \retval 0 on error
*/
static uint16_t cc_gen_fnv64(const struct knot_cc_input *input,
uint8_t *cc_out, uint16_t cc_len)
{
if (!knot_cc_input_is_valid(input) ||
!cc_out || cc_len < KNOT_OPT_COOKIE_CLNT) {
return 0;
}
Fnv64_t hash_val = FNV1A_64_INIT;
if (input->clnt_sockaddr) {
update_hash(&hash_val, input->clnt_sockaddr);
}
if (input->srvr_sockaddr) {
update_hash(&hash_val, input->srvr_sockaddr);
}
hash_val = fnv_64a_buf((void *)input->secret_data, input->secret_len,
hash_val);
assert(KNOT_OPT_COOKIE_CLNT == sizeof(hash_val));
cc_len = sizeof(hash_val);
wire_write_u64(cc_out, hash_val);
return cc_len;
}
#define SRVR_FNV64_HASH_SIZE 8
/*!
* \brief Compute server cookie hash using FNV-64.
*
* Server cookie = nonce | FNV-64(client IP | nonce | client cookie | server secret)
*
* \note This function computes only the hash value.
*
* \param input Data to compute cookie from.
* \param hash_out Buffer to write the resulting hash data into.
* \param hash_len Buffer size.
*
* \retval non-zero size of written data on successful return
* \retval 0 on error
*/
static uint16_t sc_gen_fnv64(const struct knot_sc_input *input,
uint8_t *hash_out, uint16_t hash_len)
{
if (!knot_sc_input_is_valid(input) ||
!hash_out || hash_len < SRVR_FNV64_HASH_SIZE) {
return 0;
}
Fnv64_t hash_val = FNV1A_64_INIT;
if (input->srvr_data->clnt_sockaddr) {
update_hash(&hash_val, input->srvr_data->clnt_sockaddr);
}
if (input->nonce && input->nonce_len) {
hash_val = fnv_64a_buf((void *)input->nonce, input->nonce_len, hash_val);
}
hash_val = fnv_64a_buf((void *)input->cc, input->cc_len, hash_val);
hash_val = fnv_64a_buf((void *)input->srvr_data->secret_data,
input->srvr_data->secret_len, hash_val);
assert(SRVR_FNV64_HASH_SIZE == sizeof(hash_val));
hash_len = sizeof(hash_val);
wire_write_u64(hash_out, hash_val);
return hash_len;
}
_public_
const struct knot_cc_alg knot_cc_alg_fnv64 = {
KNOT_OPT_COOKIE_CLNT,
cc_gen_fnv64
};
_public_
const struct knot_sc_alg knot_sc_alg_fnv64 = {
SRVR_FNV64_HASH_SIZE,
sc_gen_fnv64
};
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "libknot/cookies/client.h"
#include "libknot/cookies/server.h"
/*!
* \brief FNV-64 client cookie algorithm.
*/
extern const struct knot_cc_alg knot_cc_alg_fnv64;
/*!
* \brief FNV-64 server hash algorithm.
*
* \note The algorithm expects a nonce value, time stamp and hash value.
*/
extern const struct knot_sc_alg knot_sc_alg_fnv64;
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <string.h>
#include "libknot/attribute.h"
......@@ -21,6 +22,7 @@
#include "libknot/errcode.h"
#include "libknot/rrtype/opt-cookie.h"
#include "contrib/string.h"
#include "contrib/sockaddr.h"
_public_
bool knot_cc_input_is_valid(const struct knot_cc_input *input)
......@@ -30,33 +32,41 @@ bool knot_cc_input_is_valid(const struct knot_cc_input *input)
* client IP address, server IP address and a secret quantity.
*/
return input && (input->clnt_sockaddr || input->srvr_sockaddr) &&
input->secret_data && input->secret_len > 0;
return input && (input->clnt_sockaddr || input->srvr_sockaddr);
}
_public_
int knot_cc_check(const uint8_t *cc, uint16_t cc_len,
const struct knot_cc_input *input,
const struct knot_cc_alg *cc_alg)
static uint64_t generate_client_cookie(const struct knot_cc_input *input)
{
if (!cc || cc_len == 0 || !input ||
!cc_alg || !cc_alg->cc_size || !cc_alg->gen_func) {
return KNOT_EINVAL;
SIPHASH_CTX ctx;
SipHash24_Init(&ctx, &input->secret);
if (input->clnt_sockaddr) {
size_t addr_len = 0;
void *addr = sockaddr_raw(input->clnt_sockaddr, &addr_len);
SipHash24_Update(&ctx, addr, addr_len);
}
if (cc_alg->cc_size > KNOT_OPT_COOKIE_CLNT) {
return KNOT_EINVAL;
if (input->srvr_sockaddr) {
size_t addr_len = 0;
void *addr = sockaddr_raw(input->srvr_sockaddr, &addr_len);
SipHash24_Update(&ctx, addr, addr_len);
}
uint8_t generated_cc[KNOT_OPT_COOKIE_CLNT] = { 0 };
uint16_t generated_cc_len = KNOT_OPT_COOKIE_CLNT;
return SipHash24_End(&ctx);
}
generated_cc_len = cc_alg->gen_func(input, generated_cc, generated_cc_len);
if (generated_cc_len != cc_len) {
_public_
int knot_cc_check(const uint8_t *cc, uint16_t cc_len,
const struct knot_cc_input *input)
{
if (!cc || cc_len != KNOT_OPT_COOKIE_CLNT || !knot_cc_input_is_valid(input)) {
return KNOT_EINVAL;
}
int ret = const_time_memcmp(cc, generated_cc, generated_cc_len);
uint64_t generated_cc = generate_client_cookie(input);
assert(sizeof(generated_cc) == KNOT_OPT_COOKIE_CLNT);
int ret = const_time_memcmp(cc, &generated_cc, KNOT_OPT_COOKIE_CLNT);
if (ret != 0) {
return KNOT_EINVAL;
}
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -20,14 +20,15 @@
#include <stdint.h>
#include <stdlib.h>
#include "contrib/openbsd/siphash.h"
/*!
* \brief Input data needed to compute the client cookie value.
*/
struct knot_cc_input {
const struct sockaddr *clnt_sockaddr; /*!< Client (local) socket address. */
const struct sockaddr *srvr_sockaddr; /*!< Server (remote) socket address. */
const uint8_t *secret_data; /*!< Client secret data. */
size_t secret_len; /*!< Secret data length. */
SIPHASH_KEY secret; /*!< Client secret data. */
};
/*!
......@@ -67,11 +68,9 @@ struct knot_cc_alg {
* \param cc Client cookie that should be checked.
* \param cc_len Client cookie size.
* \param input Client cookie input algorithm parameters.
* \param cc_alg Client cookie algorithm.
*
* \retval KNOT_EOK
* \retval KNOT_EINVAL
*/
int knot_cc_check(const uint8_t *cc, uint16_t cc_len,
const struct knot_cc_input *input,
const struct knot_cc_alg *cc_alg);
const struct knot_cc_input *input);
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <string.h>
#include "libknot/attribute.h"
......@@ -21,6 +22,9 @@
#include "libknot/errcode.h"
#include "libknot/rrtype/opt-cookie.h"
#include "contrib/string.h"
#include "contrib/sockaddr.h"
#define SERVER_HASH_LEN 8
_public_
bool knot_sc_input_is_valid(const struct knot_sc_input *input)
......@@ -30,8 +34,7 @@ bool knot_sc_input_is_valid(const struct knot_sc_input *input)
* source IP address, a secret quantity and request client cookie.
*/
return input && input->cc && input->cc_len > 0 && input->srvr_data &&
input->srvr_data->secret_data && input->srvr_data->secret_len > 0;
return input && input->cc && input->cc_len > 0 && input->srvr_data;
}
_public_
......@@ -55,12 +58,35 @@ int knot_sc_parse(uint16_t nonce_len, const uint8_t *sc, uint16_t sc_len,
return KNOT_EOK;
}
static uint64_t generate_server_cookie(const struct knot_sc_input *input)
{
SIPHASH_CTX ctx;
SipHash24_Init(&ctx, &input->srvr_data->secret);
if (input->srvr_data->clnt_sockaddr) {
size_t addr_len = 0;
void *addr = sockaddr_raw(input->srvr_data->clnt_sockaddr, &addr_len);
if (addr) {
SipHash24_Update(&ctx, addr, addr_len);
}
}
if (input->nonce && input->nonce_len > 0) {
SipHash24_Update(&ctx, input->nonce, input->nonce_len);
}
if (input->cc && input->cc_len == KNOT_OPT_COOKIE_CLNT) {
SipHash24_Update(&ctx, input->cc, input->cc_len);
}
return SipHash24_End(&ctx);
}
_public_
int knot_sc_check(uint16_t nonce_len, const struct knot_dns_cookies *cookies,
const struct knot_sc_private *srvr_data,
const struct knot_sc_alg *sc_alg)
const struct knot_sc_private *srvr_data)
{
if (!cookies || !srvr_data || !sc_alg) {
if (!cookies || !srvr_data) {
return KNOT_EINVAL;
}
......@@ -69,20 +95,15 @@ int knot_sc_check(uint16_t nonce_len, const struct knot_dns_cookies *cookies,
return KNOT_EINVAL;
}
if (!srvr_data->clnt_sockaddr ||
!srvr_data->secret_data || !srvr_data->secret_len) {
if (!srvr_data->clnt_sockaddr) {
return KNOT_EINVAL;
}
if (!sc_alg->hash_size || !sc_alg->hash_func) {
if ((nonce_len + SERVER_HASH_LEN) > KNOT_OPT_COOKIE_SRVR_MAX) {
return KNOT_EINVAL;
}
if ((nonce_len + sc_alg->hash_size) > KNOT_OPT_COOKIE_SRVR_MAX) {
return KNOT_EINVAL;
}
if (cookies->sc_len != (nonce_len + sc_alg->hash_size)) {
if (cookies->sc_len != (nonce_len + SERVER_HASH_LEN)) {
return KNOT_EINVAL;
}
......@@ -94,8 +115,10 @@ int knot_sc_check(uint16_t nonce_len, const struct knot_dns_cookies *cookies,
return ret;
}
uint8_t generated_hash[KNOT_OPT_COOKIE_SRVR_MAX] = { 0 };
uint16_t generated_hash_len = KNOT_OPT_COOKIE_SRVR_MAX;
if (content.hash_len != SERVER_HASH_LEN) {
return KNOT_EINVAL;
}
struct knot_sc_input sc_input = {
.cc = cookies->cc,
.cc_len = cookies->cc_len,
......@@ -104,14 +127,16 @@ int knot_sc_check(uint16_t nonce_len, const struct knot_dns_cookies *cookies,
.srvr_data = srvr_data
};
/* Generate a new hash. */
generated_hash_len = sc_alg->hash_func(&sc_input, generated_hash, generated_hash_len);
if (generated_hash_len == 0) {
if (!knot_sc_input_is_valid(&sc_input)) {
return KNOT_EINVAL;
}
/* Generate a new hash. */
uint64_t generated_hash = generate_server_cookie(&sc_input);
assert(sizeof(generated_hash) == SERVER_HASH_LEN);
/* Compare hashes. */
ret = const_time_memcmp(content.hash, generated_hash, generated_hash_len);
ret = const_time_memcmp(content.hash, &generated_hash, SERVER_HASH_LEN);
if (ret != 0) {
return KNOT_EINVAL;
}
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -20,6 +20,8 @@
#include <stdint.h>
#include <stdlib.h>
#include "contrib/openbsd/siphash.h"
/*!
* \brief Convenience structure holding both, server and client, cookies.
*/
......@@ -38,8 +40,7 @@ struct knot_dns_cookies {
*/
struct knot_sc_private {
const struct sockaddr *clnt_sockaddr; /*!< Client (remote) socket address. */
const uint8_t *secret_data; /*!< Server secret data. */
size_t secret_len; /*!< Secret data length. */
SIPHASH_KEY secret; /*!< Server secret data. */
};
/*!
......@@ -125,11 +126,9 @@ struct knot_sc_alg {
* \param nonce_len Expected nonce data size.
* \param cookies Cookie data.
* \param srvr_data Data known to the server needed for cookie validation.
* \param sc_alg Server cookie algorithm.
*
* \retval KNOT_EOK
* \retval KNOT_EINVAL
*/
int knot_sc_check(uint16_t nonce_len, const struct knot_dns_cookies *cookies,
const struct knot_sc_private *srvr_data,
const struct knot_sc_alg *sc_alg);
const struct knot_sc_private *srvr_data);
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -19,10 +19,12 @@
#include <string.h>
#include <tap/basic.h>
#include "contrib/endian.h"
#include "contrib/openbsd/siphash.h"
#include "contrib/sockaddr.h"
#include "libknot/consts.h"
#include "libknot/cookies/alg-fnv64.h"
#include "libknot/cookies/client.h"
#include "libknot/cookies/client.c"
#include "libknot/errcode.h"
int main(int argc, char *argv[])
......@@ -31,10 +33,13 @@ int main(int argc, char *argv[])
int ret;
const uint8_t secret[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
SIPHASH_KEY secret = {
.k0 = htole64(0xDEADBEEFFACE),
.k1 = htole64(0xFACEDEADBEEF)
};
uint64_t hash;
uint8_t hash[32] = { 0 };
uint16_t hash_len;
struct knot_cc_input cc_in = { 0 };
......@@ -52,118 +57,54 @@ int main(int argc, char *argv[])
/* Client cookie hash algorithm. */
hash_len = sizeof(hash);
hash_len = knot_cc_alg_fnv64.gen_func(NULL, hash, hash_len);
ok(hash_len == 0, "cookies: FNV64 client cookie no input");
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = NULL;
cc_in.srvr_sockaddr = NULL;
cc_in.secret_data = NULL;
cc_in.secret_len = 0;
hash_len = sizeof(hash);
hash_len = knot_cc_alg_fnv64.gen_func(&cc_in, hash, hash_len);
ok(hash_len == 0, "cookies: FNV64 client cookie input no data");
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = (struct sockaddr *)&c4_sa;
cc_in.srvr_sockaddr = (struct sockaddr *)&s4_sa;
cc_in.secret_data = NULL;
cc_in.secret_len = 0;
hash_len = sizeof(hash);
hash_len = knot_cc_alg_fnv64.gen_func(&cc_in, hash, hash_len);
ok(hash_len == 0, "cookies: FNV64 client cookie input no secret");
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = NULL;
cc_in.srvr_sockaddr = NULL;
cc_in.secret_data = secret;
cc_in.secret_len = sizeof(secret);
hash_len = sizeof(hash);
hash_len = knot_cc_alg_fnv64.gen_func(&cc_in, hash, hash_len);
ok(hash_len == 0, "cookies: FNV64 client cookie input no socket");
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = (struct sockaddr *)&c4_sa;
cc_in.srvr_sockaddr = (struct sockaddr *)&s4_sa;
cc_in.secret_data = secret;
cc_in.secret_len = sizeof(secret);
hash_len = 0;
hash_len = knot_cc_alg_fnv64.gen_func(&cc_in, NULL, hash_len);
ok(hash_len == 0, "cookies: FNV64 client cookie output no hash");
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = (struct sockaddr *)&c4_sa;
cc_in.srvr_sockaddr = (struct sockaddr *)&s4_sa;
cc_in.secret_data = secret;
cc_in.secret_len = sizeof(secret);
hash_len = 1;
hash_len = knot_cc_alg_fnv64.gen_func(&cc_in, hash, hash_len);
ok(hash_len == 0, "cookies: FNV64 client cookie hash no space");
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = (struct sockaddr *)&c4_sa;
cc_in.srvr_sockaddr = (struct sockaddr *)&s4_sa;
cc_in.secret_data = secret;
cc_in.secret_len = sizeof(secret);
hash_len = sizeof(hash);
hash_len = knot_cc_alg_fnv64.gen_func(&cc_in, hash, hash_len);
ok(hash_len != 0 && hash_len == knot_cc_alg_fnv64.cc_size, "cookies: FNV64 client cookie output");
cc_in.secret = secret;
hash = generate_client_cookie(&cc_in);
{
uint8_t expected[] = { 0xb1, 0x15, 0xef, 0x03, 0xa8, 0xf9, 0x31, 0x74 };
ok(sizeof(expected) == hash_len && 0 == memcmp(expected, hash, hash_len), "cookies: FNV64 client cookie content");
uint64_t expected = 0xde3832f4f59bf5ab;
ok(hash == expected, "cookies: SipHash client cookie content");
}
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = NULL;
cc_in.srvr_sockaddr = (struct sockaddr *)&s4_sa;
cc_in.secret_data = secret;
cc_in.secret_len = sizeof(secret);
hash_len = sizeof(hash);
hash_len = knot_cc_alg_fnv64.gen_func(&cc_in, hash, hash_len);
ok(hash_len != 0 && hash_len == knot_cc_alg_fnv64.cc_size, "cookies: FNV64 client cookie output");
cc_in.secret = secret;
hash = generate_client_cookie(&cc_in);
{
uint8_t expected[] = { 0xe7, 0x09, 0xdd, 0x43, 0xd2, 0x25, 0x62, 0x7c };
ok(sizeof(expected) == hash_len && 0 == memcmp(expected, hash, hash_len), "cookies: FNV64 client cookie content");
uint64_t expected = 0x6b636ff225a1b340;
ok(hash == expected, "cookies: SipHash client cookie content");
}
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = (struct sockaddr *)&unspec_sa;
cc_in.srvr_sockaddr = (struct sockaddr *)&s4_sa;
cc_in.secret_data = secret;
cc_in.secret_len = sizeof(secret);
hash_len = sizeof(hash);
hash_len = knot_cc_alg_fnv64.gen_func(&cc_in, hash, hash_len);
ok(hash_len != 0 && hash_len == knot_cc_alg_fnv64.cc_size, "cookies: FNV64 client cookie output");
cc_in.secret = secret;
hash = generate_client_cookie(&cc_in);
{
uint8_t expected[] = { 0xe7, 0x09, 0xdd, 0x43, 0xd2, 0x25, 0x62, 0x7c };
ok(sizeof(expected) == hash_len && 0 == memcmp(expected, hash, hash_len), "cookies: FNV64 client cookie content");
uint64_t expected = 0x6b636ff225a1b340;
ok(hash == expected, "cookies: SipHash client cookie content");
}
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = (struct sockaddr *)&c4_sa;
cc_in.srvr_sockaddr = NULL;
cc_in.secret_data = secret;
cc_in.secret_len = sizeof(secret);
hash_len = sizeof(hash);
hash_len = knot_cc_alg_fnv64.gen_func(&cc_in, hash, hash_len);
ok(hash_len != 0 && hash_len == knot_cc_alg_fnv64.cc_size, "cookies: FNV64 client cookie output");
cc_in.secret = secret;
hash = generate_client_cookie(&cc_in);
{
uint8_t expected[] = { 0xaa, 0xe0, 0x98, 0x1b, 0x08, 0xd1, 0xa9, 0x05 };
ok(sizeof(expected) == hash_len && 0 == memcmp(expected, hash, hash_len), "cookies: FNV64 client cookie content");
uint64_t expected = 0xd713ab1a81179bb3;
ok(hash == expected, "cookies: SipHash client cookie content");
}
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = (struct sockaddr *)&c4_sa;
cc_in.srvr_sockaddr = (struct sockaddr *)&unspec_sa;
cc_in.secret_data = secret;
cc_in.secret_len = sizeof(secret);
hash_len = sizeof(hash);
hash_len = knot_cc_alg_fnv64.gen_func(&cc_in, hash, hash_len);
ok(hash_len != 0 && hash_len == knot_cc_alg_fnv64.cc_size, "cookies: FNV64 client cookie output");
cc_in.secret = secret;
hash = generate_client_cookie(&cc_in);
{
uint8_t expected[] = { 0xaa, 0xe0, 0x98, 0x1b, 0x08, 0xd1, 0xa9, 0x05 };
ok(sizeof(expected) == hash_len && 0 == memcmp(expected, hash, hash_len), "cookies: FNV64 client cookie content");
uint64_t expected = 0xd713ab1a81179bb3;
ok(hash == expected, "cookies: SipHash client cookie content");
}
/* Client cookie check. */
......@@ -171,60 +112,45 @@ int main(int argc, char *argv[])
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = (struct sockaddr *)&c6_sa;
cc_in.srvr_sockaddr = (struct sockaddr *)&s6_sa;
cc_in.secret_data = secret;
cc_in.secret_len = sizeof(secret);
cc_in.secret = secret;
{
ret = knot_cc_check(NULL, 0, &cc_in, &knot_cc_alg_fnv64);
is_int(KNOT_EINVAL, ret, "cookies: FNV64 client cookie check no cookie");
ret = knot_cc_check(NULL, 0, &cc_in);
is_int(KNOT_EINVAL, ret, "cookies: SipHash client cookie check no cookie");
}
{
uint8_t cookie[] = { 0xaf, 0xe5, 0x17, 0x94, 0x80, 0xa6, 0x0c, 0x33 };
ret = knot_cc_check(cookie, sizeof(cookie), NULL, &knot_cc_alg_fnv64);
is_int(KNOT_EINVAL, ret, "cookies: FNV64 client cookie check no input");
ret = knot_cc_check(cookie, sizeof(cookie), NULL);
is_int(KNOT_EINVAL, ret, "cookies: SipHash client cookie check no input");
}
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = (struct sockaddr *)&c6_sa;
cc_in.srvr_sockaddr = (struct sockaddr *)&s6_sa;
cc_in.secret_data = secret;
cc_in.secret_len = sizeof(secret);
cc_in.secret = secret;
{
uint8_t cookie[] = { 0xaf, 0xe5, 0x17, 0x94, 0x80, 0xa6, 0x0c, 0x33 };
ret = knot_cc_check(cookie, sizeof(cookie), &cc_in, NULL);
is_int(KNOT_EINVAL, ret, "cookies: FNV64 client cookie check no algorithm");
uint64_t cookie = 0xf99dbd02b69ab3c2;
ret = knot_cc_check((const uint8_t *)&cookie, sizeof(cookie), &cc_in);
is_int(KNOT_EOK, ret, "cookies: SipHash client good cookie check");
}
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = (struct sockaddr *)&c6_sa;
cc_in.srvr_sockaddr = (struct sockaddr *)&s6_sa;
cc_in.secret_data = secret;
cc_in.secret_len = sizeof(secret);
cc_in.secret = secret;
{
uint8_t cookie[] = { 0xaf, 0xe5, 0x17, 0x94, 0x80, 0xa6, 0x0c, 0x33 };
ret = knot_cc_check(cookie, sizeof(cookie), &cc_in, &knot_cc_alg_fnv64);
is_int(KNOT_EOK, ret, "cookies: FNV64 client good cookie check");
}
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = (struct sockaddr *)&c6_sa;
cc_in.srvr_sockaddr = (struct sockaddr *)&s6_sa;
cc_in.secret_data = secret;
cc_in.secret_len = sizeof(secret);
{
uint8_t cookie[] = { 0xaf, 0xe5, 0x17, 0x94, 0x80, 0xa6, 0x0c, 0x33 };
ret = knot_cc_check(cookie, sizeof(cookie) - 1, &cc_in, &knot_cc_alg_fnv64);
is_int(KNOT_EINVAL, ret, "cookies: FNV64 client cookie check invalid length");
uint64_t cookie = 0xf99dbd02b69ab3c2;
ret = knot_cc_check((const uint8_t *)&cookie, sizeof(cookie) - 1, &cc_in);
is_int(KNOT_EINVAL, ret, "cookies: SipHash client cookie check invalid length");
}
memset(&cc_in, 0, sizeof(cc_in));
cc_in.clnt_sockaddr = (struct sockaddr *)&c6_sa;
cc_in.srvr_sockaddr = (struct sockaddr *)&s6_sa;
cc_in.secret_data = secret;
cc_in.secret_len = sizeof(secret);
cc_in.secret = secret;
{
uint8_t cookie[] = { 0xaf, 0xe5, 0x17, 0x94, 0x80, 0xa6, 0x0c, 0x32 };