From 9949f0d88ab4fde73731824b9500082590c55062 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Thu, 20 Jul 2023 20:13:51 +0200 Subject: [PATCH] feat(crypto): Implement TLS PRF with SHA-256. --- crypto/Makefile | 1 + crypto/tls_prf.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ crypto/tls_prf.h | 33 ++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 crypto/tls_prf.c create mode 100644 crypto/tls_prf.h diff --git a/crypto/Makefile b/crypto/Makefile index c7ff9e6b3..1d83619de 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -123,6 +123,7 @@ SRCS += zkp_context.c SRCS += zkp_ecdsa.c SRCS += zkp_bip340.c SRCS += cardano.c +SRCS += tls_prf.c OBJS = $(SRCS:.c=.o) OBJS += secp256k1-zkp.o diff --git a/crypto/tls_prf.c b/crypto/tls_prf.c new file mode 100644 index 000000000..32b58b613 --- /dev/null +++ b/crypto/tls_prf.c @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2023 Andrew R. Kozlik + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * For a specification of TLS-PRF see + * https://datatracker.ietf.org/doc/html/rfc5246#section-5 + */ + +#include + +#include "hmac.h" +#include "memzero.h" +#include "sha2.h" + +void tls_prf_sha256(const uint8_t *secret, size_t secret_len, + const uint8_t *label, size_t label_len, const uint8_t *seed, + size_t seed_len, uint8_t *output, size_t out_len) { + uint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)] = {0}; + uint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)] = {0}; + uint8_t a[SHA256_DIGEST_LENGTH] = {0}; + uint8_t result[SHA256_DIGEST_LENGTH] = {0}; + SHA256_CTX ctx = {0}; + + // Prepare inner and outer digest. + hmac_sha256_prepare(secret, secret_len, odig, idig); + + // a = HMAC(secret, label + seed) + sha256_Init_ex(&ctx, idig, 8 * SHA256_BLOCK_LENGTH); + sha256_Update(&ctx, label, label_len); + sha256_Update(&ctx, seed, seed_len); + sha256_Final(&ctx, a); + sha256_Init_ex(&ctx, odig, 8 * SHA256_BLOCK_LENGTH); + sha256_Update(&ctx, a, SHA256_DIGEST_LENGTH); + sha256_Final(&ctx, a); + + while (1) { + // result = HMAC(secret, a + label + seed) + sha256_Init_ex(&ctx, idig, 8 * SHA256_BLOCK_LENGTH); + sha256_Update(&ctx, a, SHA256_DIGEST_LENGTH); + sha256_Update(&ctx, label, label_len); + sha256_Update(&ctx, seed, seed_len); + sha256_Final(&ctx, result); + sha256_Init_ex(&ctx, odig, 8 * SHA256_BLOCK_LENGTH); + sha256_Update(&ctx, result, SHA256_DIGEST_LENGTH); + sha256_Final(&ctx, result); + + if (out_len <= SHA256_DIGEST_LENGTH) { + break; + } + + memcpy(output, result, SHA256_DIGEST_LENGTH); + output += SHA256_DIGEST_LENGTH; + out_len -= SHA256_DIGEST_LENGTH; + + // a = HMAC(secret, a) + sha256_Init_ex(&ctx, idig, 8 * SHA256_BLOCK_LENGTH); + sha256_Update(&ctx, a, SHA256_DIGEST_LENGTH); + sha256_Final(&ctx, a); + sha256_Init_ex(&ctx, odig, 8 * SHA256_BLOCK_LENGTH); + sha256_Update(&ctx, a, SHA256_DIGEST_LENGTH); + sha256_Final(&ctx, a); + } + + memcpy(output, result, out_len); + memzero(idig, sizeof(idig)); + memzero(odig, sizeof(odig)); + memzero(a, sizeof(a)); + memzero(result, sizeof(result)); +} diff --git a/crypto/tls_prf.h b/crypto/tls_prf.h new file mode 100644 index 000000000..d97b8fb58 --- /dev/null +++ b/crypto/tls_prf.h @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2023 Andrew R. Kozlik + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT HMAC_SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __TLS_PRF_H__ +#define __TLS_PRF_H__ + +#include +#include "hmac.h" + +void tls_prf_sha256(const uint8_t *secret, size_t secret_len, + const uint8_t *label, size_t label_len, const uint8_t *seed, + size_t seed_len, uint8_t *output, size_t out_len); + +#endif