From 69c6a41ffb878ef98c9378ed4b1634a404cfaa7f Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 6 May 2024 02:53:35 +0200 Subject: Adding upstream version 2.7.6. Signed-off-by: Daniel Baumann --- src/libknot/cookies.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 src/libknot/cookies.c (limited to 'src/libknot/cookies.c') diff --git a/src/libknot/cookies.c b/src/libknot/cookies.c new file mode 100644 index 0000000..dd024d5 --- /dev/null +++ b/src/libknot/cookies.c @@ -0,0 +1,130 @@ +/* Copyright (C) 2017 CZ.NIC, z.s.p.o. + + 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 . + */ + +#include +#include + +#include "libknot/attribute.h" +#include "libknot/cookies.h" +#include "libknot/errcode.h" +#include "contrib/string.h" +#include "contrib/sockaddr.h" +#include "contrib/openbsd/siphash.h" + +_public_ +int knot_edns_cookie_client_generate(knot_edns_cookie_t *out, + const knot_edns_cookie_params_t *params) +{ + if (out == NULL || params == NULL || params->client_addr == NULL || + params->server_addr == NULL) { + return KNOT_EINVAL; + } + + SIPHASH_CTX ctx; + assert(sizeof(params->secret) == sizeof(SIPHASH_KEY)); + SipHash24_Init(&ctx, (const SIPHASH_KEY *)params->secret); + + size_t addr_len = 0; + void *addr = sockaddr_raw(params->client_addr, &addr_len); + SipHash24_Update(&ctx, addr, addr_len); + + addr_len = 0; + addr = sockaddr_raw(params->server_addr, &addr_len); + SipHash24_Update(&ctx, addr, addr_len); + + uint64_t hash = SipHash24_End(&ctx); + memcpy(out->data, &hash, sizeof(hash)); + out->len = sizeof(hash); + + return KNOT_EOK; +} + +_public_ +int knot_edns_cookie_client_check(const knot_edns_cookie_t *cc, + const knot_edns_cookie_params_t *params) +{ + if (cc == NULL || cc->len != KNOT_EDNS_COOKIE_CLNT_SIZE) { + return KNOT_EINVAL; + } + + knot_edns_cookie_t ref; + int ret = knot_edns_cookie_client_generate(&ref, params); + if (ret != KNOT_EOK) { + return ret; + } + assert(ref.len == KNOT_EDNS_COOKIE_CLNT_SIZE); + + ret = const_time_memcmp(cc->data, ref.data, KNOT_EDNS_COOKIE_CLNT_SIZE); + if (ret != 0) { + return KNOT_EINVAL; + } + + return KNOT_EOK; +} + +_public_ +int knot_edns_cookie_server_generate(knot_edns_cookie_t *out, + const knot_edns_cookie_t *cc, + const knot_edns_cookie_params_t *params) +{ + if (out == NULL || cc == NULL || cc->len != KNOT_EDNS_COOKIE_CLNT_SIZE || + params == NULL || params->client_addr == NULL) { + return KNOT_EINVAL; + } + + SIPHASH_CTX ctx; + assert(sizeof(params->secret) == sizeof(SIPHASH_KEY)); + SipHash24_Init(&ctx, (const SIPHASH_KEY *)params->secret); + + size_t addr_len = 0; + void *addr = sockaddr_raw(params->client_addr, &addr_len); + SipHash24_Update(&ctx, addr, addr_len); + + SipHash24_Update(&ctx, cc->data, cc->len); + + uint64_t hash = SipHash24_End(&ctx); + memcpy(out->data, &hash, sizeof(hash)); + out->len = sizeof(hash); + + return KNOT_EOK; +} + +_public_ +int knot_edns_cookie_server_check(const knot_edns_cookie_t *sc, + const knot_edns_cookie_t *cc, + const knot_edns_cookie_params_t *params) +{ + if (sc == NULL || cc == NULL || params == NULL) { + return KNOT_EINVAL; + } + + knot_edns_cookie_t ref; + int ret = knot_edns_cookie_server_generate(&ref, cc, params); + if (ret != KNOT_EOK) { + return ret; + } + + if (sc->len != ref.len) { + return KNOT_EINVAL; + } + + ret = const_time_memcmp(sc->data, ref.data, sc->len); + if (ret != 0) { + return KNOT_EINVAL; + } + + return KNOT_EOK; +} -- cgit v1.2.3