From b9d6e1eb867eaa431c4c555a7409342805fa2706 Mon Sep 17 00:00:00 2001 From: bg Date: Fri, 7 Oct 2011 04:46:05 +0200 Subject: [PATCH] adding PRF TLSv1.2 --- hfal/hfal-hmac.c | 6 +- hfal/hfal-hmac.h | 2 +- mkfiles/prf_tls12.mk | 14 ++++ prf_tls12/prf_tls12.c | 135 +++++++++++++++++++++++++++++++++ prf_tls12/prf_tls12.h | 48 ++++++++++++ sha1/sha1.c | 4 +- sha256/sha256.c | 3 +- test_src/main-prf_tls12-test.c | 124 ++++++++++++++++++++++++++++++ 8 files changed, 329 insertions(+), 7 deletions(-) create mode 100644 mkfiles/prf_tls12.mk create mode 100644 prf_tls12/prf_tls12.c create mode 100644 prf_tls12/prf_tls12.h create mode 100644 test_src/main-prf_tls12-test.c diff --git a/hfal/hfal-hmac.c b/hfal/hfal-hmac.c index f36b58e..6f5fbf9 100644 --- a/hfal/hfal-hmac.c +++ b/hfal/hfal-hmac.c @@ -69,16 +69,16 @@ uint8_t hfal_hmac_init(const hfdesc_t* hash_descriptor, return 0; } -int hfal_hmac_ctxcopy(hfhmacgen_ctx_t* dest, hfhmacgen_ctx_t* src){ +uint8_t hfal_hmac_ctxcopy(hfhmacgen_ctx_t* dest, hfhmacgen_ctx_t* src){ dest->desc = src->desc; dest->ctx = malloc(dest->desc->ctxsize_B); if(dest->ctx == NULL){ - return -1; + return 1; } memcpy(dest->ctx, src->ctx, dest->desc->ctxsize_B); dest->finctx = malloc(dest->desc->ctxsize_B); if(dest->finctx == NULL){ - return -1; + return 1; } memcpy(dest->finctx, src->finctx, dest->desc->ctxsize_B); return 0; diff --git a/hfal/hfal-hmac.h b/hfal/hfal-hmac.h index 63cb016..4c1c738 100644 --- a/hfal/hfal-hmac.h +++ b/hfal/hfal-hmac.h @@ -29,7 +29,7 @@ typedef struct { } hfhmacgen_ctx_t; uint8_t hfal_hmac_init(const hfdesc_t* hash_descriptor, hfhmacgen_ctx_t* ctx, const void* key, uint16_t keylength_b); -int hfal_hmac_ctxcopy(hfhmacgen_ctx_t* dest, hfhmacgen_ctx_t* src); +uint8_t hfal_hmac_ctxcopy(hfhmacgen_ctx_t* dest, hfhmacgen_ctx_t* src); void hfal_hmac_nextBlock(hfhmacgen_ctx_t* ctx, const void* block); void hfal_hmac_lastBlock(hfhmacgen_ctx_t* ctx, const void* block, uint16_t length_b); void hfal_hmac_ctx2mac(void* dest, hfhmacgen_ctx_t* ctx); diff --git a/mkfiles/prf_tls12.mk b/mkfiles/prf_tls12.mk new file mode 100644 index 0000000..dcf8d62 --- /dev/null +++ b/mkfiles/prf_tls12.mk @@ -0,0 +1,14 @@ +# Makefile for PRF Tlsv1.2 +ALGO_NAME := PRF_TLS12 + +# comment out the following line for removement of PRF TLSv1.2 from the build process +AUX += $(ALGO_NAME) + +$(ALGO_NAME)_DIR := prf_tls12/ +$(ALGO_NAME)_INCDIR := hmac/ sha1/ sha256/ hfal/ +$(ALGO_NAME)_OBJ := prf_tls12.o +$(ALGO_NAME)_TESTBIN := main-prf_tls12-test.o $(CLI_STD) hfal_sha1.o hfal_sha256.o $(HFAL_STD) \ + sha256.o sha1.o hfal-hmac.o + +$(ALGO_NAME)_PERFORMANCE_TEST := performance + diff --git a/prf_tls12/prf_tls12.c b/prf_tls12/prf_tls12.c new file mode 100644 index 0000000..8b84d52 --- /dev/null +++ b/prf_tls12/prf_tls12.c @@ -0,0 +1,135 @@ +/* prf_tls12.c */ +/* + This file is part of the ARM-Crypto-Lib. + Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de) + + 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 . +*/ +/* + * \file prf_tls12.c + * \author Daniel Otte + * \email daniel.otte@rub.de + * \date 2011-10-06 + * \license GPLv3 or later + * + */ +/* from rfc5246 + + + P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + + HMAC_hash(secret, A(2) + seed) + + HMAC_hash(secret, A(3) + seed) + ... + + where + indicates concatenation. + + A() is defined as: + + A(0) = seed + A(i) = HMAC_hash(secret, A(i-1)) + + P_hash can be iterated as many times as necessary to produce the + required quantity of data. For example, if P_SHA256 is being used to + create 80 bytes of data, it will have to be iterated three times + (through A(3)), creating 96 bytes of output data; the last 16 bytes + of the final iteration will then be discarded, leaving 80 bytes of + output data. + + TLS's PRF is created by applying P_hash to the secret as: + + PRF(secret, label, seed) = P_(secret, label + seed) + +*/ +/* long story short: + * P(k,s) = H(k, A(1) | s) | H(k, A(2) | s) | ... | H(k, A(n) | s) + * A(0) = s + * A(i) = H(k, A(i-1)) + * + * PRF(k,l,s) = P(k, l | s) + * + */ + +/* This implementation is limited to hashfunctions which return a hash value + * of a length (in bits) which is divideable by 8. + * + * Also note that our HMAC implementation may fail on hashfunction which + * return a larger hash value then their nativ blocksize + * + */ + +#include +#include +#include +#include +#include +#include +#include "prf_tls12.h" + +uint8_t prf_tls12_init(prf_tls12_ctx_t* ctx, const hfdesc_t* hash, + const void* key, uint16_t keylength_b, + const void* seed, uint16_t seedlength_b){ + hfhmacgen_ctx_t tmp_ctx; + ctx->blocklength_b = hfal_hash_getHashsize(hash); + ctx->seed_buffer = malloc(ctx->blocklength_b/8+(seedlength_b+7)/8); + if(!ctx->seed_buffer){ + return 1; + } + ctx->bufferlength_b = ctx->blocklength_b + seedlength_b; + memcpy(ctx->seed_buffer+ctx->blocklength_b/8, seed, seedlength_b/8); + if(hfal_hmac_init(hash, &(ctx->mainctx), key, keylength_b)){ + return 2; + } + if(hfal_hmac_ctxcopy(&tmp_ctx, &(ctx->mainctx))){ + prf_tls12_free(ctx); + return 3; + } + hfal_hmac_lastBlock(&tmp_ctx, seed, seedlength_b); + hfal_hmac_ctx2mac(ctx->seed_buffer, &tmp_ctx); + hfal_hmac_free(&tmp_ctx); + return 0; +} + +uint8_t prf_tls12_init_w_label(prf_tls12_ctx_t* ctx, const hfdesc_t* hash, + const void* key, uint16_t keylength_b, + const void* label, uint16_t labellength_B, + const void* seed, uint16_t seedlength_b){ + + uint8_t buffer[labellength_B+(seedlength_b+7)/8]; + memcpy(buffer, label, labellength_B); + memcpy(buffer+labellength_B, seed, (seedlength_b+7)/8); + return prf_tls12_init(ctx, hash, key, keylength_b, buffer, labellength_B*8+seedlength_b); +} + + +void prf_tls12_free(prf_tls12_ctx_t* ctx){ + free(ctx->seed_buffer); + hfal_hmac_free(&(ctx->mainctx)); +} + +uint8_t prf_tls12_next(void* dest, prf_tls12_ctx_t* ctx){ + hfhmacgen_ctx_t tmp_ctx; + if(hfal_hmac_ctxcopy(&tmp_ctx, &(ctx->mainctx))){ + return 1; + } + hfal_hmac_lastBlock(&tmp_ctx, ctx->seed_buffer, ctx->bufferlength_b); + hfal_hmac_ctx2mac(dest, &tmp_ctx); + hfal_hmac_free(&tmp_ctx); + if(hfal_hmac_ctxcopy(&tmp_ctx, &(ctx->mainctx))){ + return 2; + } + hfal_hmac_lastBlock(&tmp_ctx, ctx->seed_buffer, ctx->blocklength_b); + hfal_hmac_ctx2mac(ctx->seed_buffer, &tmp_ctx); + hfal_hmac_free(&tmp_ctx); + return 0; +} + diff --git a/prf_tls12/prf_tls12.h b/prf_tls12/prf_tls12.h new file mode 100644 index 0000000..759580d --- /dev/null +++ b/prf_tls12/prf_tls12.h @@ -0,0 +1,48 @@ +/* prf_tls12.h */ +/* + This file is part of the AVR-Crypto-Lib. + Copyright (C) 2011 Daniel Otte (daniel.otte@rub.de) + + 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 . +*/ + +#ifndef PRF_TLS12_H_ +#define PRF_TLS12_H_ + +#include +#include +#include +#include + +typedef struct{ + hfhmacgen_ctx_t mainctx; + uint16_t blocklength_b; + uint16_t bufferlength_b; + uint8_t* seed_buffer; +} prf_tls12_ctx_t; + +uint8_t prf_tls12_init(prf_tls12_ctx_t* ctx, const hfdesc_t* hash, + const void* key, uint16_t keylength_b, + const void* seed, uint16_t seedlength_b); + +uint8_t prf_tls12_init_w_label(prf_tls12_ctx_t* ctx, const hfdesc_t* hash, + const void* key, uint16_t keylength_b, + const void* label, uint16_t labellength_B, + const void* seed, uint16_t seedlength_b); + +void prf_tls12_free(prf_tls12_ctx_t* ctx); +uint8_t prf_tls12_next(void* dest, prf_tls12_ctx_t* ctx); + + +#endif /* PRF_TLS12_H_ */ diff --git a/sha1/sha1.c b/sha1/sha1.c index a8b8812..740fe67 100644 --- a/sha1/sha1.c +++ b/sha1/sha1.c @@ -52,12 +52,12 @@ void sha1_init(sha1_ctx_t *state){ /********************************************************************************************************/ /* some helping functions */ -const +static const uint32_t rotl32(uint32_t n, uint8_t bits){ return ((n<>(32-bits))); } -const +static const uint32_t change_endian32(uint32_t x){ return (((x)<<24) | ((x)>>24) | (((x)& 0x0000ff00)<<8) | (((x)& 0x00ff0000)>>8)); } diff --git a/sha256/sha256.c b/sha256/sha256.c index 83b3a43..c121466 100644 --- a/sha256/sha256.c +++ b/sha256/sha256.c @@ -68,6 +68,7 @@ void sha256_init(sha256_ctx_t *state){ /** * rotate x right by n positions */ +static uint32_t rotr32( uint32_t x, uint8_t n){ return ((x>>n) | (x<<(32-n))); } @@ -76,7 +77,7 @@ uint32_t rotr32( uint32_t x, uint8_t n){ /*************************************************************************/ // #define CHANGE_ENDIAN32(x) (((x)<<24) | ((x)>>24) | (((x)& 0x0000ff00)<<8) | (((x)& 0x00ff0000)>>8)) - +static uint32_t change_endian32(uint32_t x){ return (((x)<<24) | ((x)>>24) | (((x)& 0x0000ff00)<<8) | (((x)& 0x00ff0000)>>8)); } diff --git a/test_src/main-prf_tls12-test.c b/test_src/main-prf_tls12-test.c new file mode 100644 index 0000000..037b379 --- /dev/null +++ b/test_src/main-prf_tls12-test.c @@ -0,0 +1,124 @@ +/* main-prf_tls12-test.c */ +/* + This file is part of the ARM-Crypto-Lib. + Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de) + + 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 . +*/ +/* + * DSA test-suit + * +*/ + +#include "main-test-common.h" +#include "prf_tls12.h" +#include +#include +#include +const char* algo_name = "PRF-TLS1.2"; + +/***************************************************************************** + * additional validation-functions * + *****************************************************************************/ + +/* +# Generating 100 bytes of pseudo-randomness using TLS1.2PRF-SHA256 +Secret (16 bytes): +0000 9b be 43 6b a9 40 f0 17 ..Ck.... +0008 b1 76 52 84 9a 71 db 35 .vR..q.5 + +Seed (16 bytes): +0000 a0 ba 9f 93 6c da 31 18 ....l.1. +0008 27 a6 f7 96 ff d5 19 8c ........ + +Label (10 bytes): +0000 74 65 73 74 20 6c 61 62 test lab +0008 65 6c el + +Output (100 bytes): +0000 e3 f2 29 ba 72 7b e1 7b ....r... +0008 8d 12 26 20 55 7c d4 53 ... U..S +0010 c2 aa b2 1d 07 c3 d4 95 ........ +0018 32 9b 52 d4 e6 1e db 5a 2.R....Z +0020 6b 30 17 91 e9 0d 35 c9 k0....5. +0028 c9 a4 6b 4e 14 ba f9 af ..kN.... +0030 0f a0 22 f7 07 7d ef 17 ........ +0038 ab fd 37 97 c0 56 4b ab ..7..VK. +0040 4f bc 91 66 6e 9d ef 9b O..fn... +0048 97 fc e3 4f 79 67 89 ba ...Oyg.. +0050 a4 80 82 d1 22 ee 42 c5 ......B. +0058 a7 2e 5a 51 10 ff f7 01 ..ZQ.... +0060 87 34 7b 66 .4.f + */ + +const uint8_t test_secret[] = { + 0x9b, 0xbe, 0x43, 0x6b, 0xa9, 0x40, 0xf0, 0x17, + 0xb1, 0x76, 0x52, 0x84, 0x9a, 0x71, 0xdb, 0x35 +}; + +const uint8_t test_seed[] = { + 0xa0, 0xba, 0x9f, 0x93, 0x6c, 0xda, 0x31, 0x18, + 0x27, 0xa6, 0xf7, 0x96, 0xff, 0xd5, 0x19, 0x8c +}; + +const char test_label[] = "test label"; + +void test_prf(const hfdesc_t* hash){ + prf_tls12_ctx_t ctx; + prf_tls12_init_w_label(&ctx, hash, test_secret, 16*8, test_label, strlen(test_label), test_seed, 16*8); + uint8_t buffer[ctx.blocklength_b/8]; + uint16_t i=0; + cli_putstr("\r\n== Testing PRF-TLSv1.2 with "); + cli_putstr(hash->name); + cli_putstr(" ==\r\n"); + do{ + prf_tls12_next(buffer, &ctx); + cli_hexdump_block(buffer, ctx.blocklength_b/8, 4, 8); + i += ctx.blocklength_b/8; + }while(i<100); +} + +void test_sha256(void){ + test_prf(&sha256_desc); +} + +void test_sha1(void){ + test_prf(&sha1_desc); +} +/***************************************************************************** + * main * + *****************************************************************************/ + +const char echo_test_str[] = "echo-test"; +const char test_sha256_str[] = "test-sha256"; +const char test_sha1_str[] = "test-sha1"; +//const char performance_str[] = "performance"; +const char echo_str[] = "echo"; + +cmdlist_entry_t cmdlist[] = { + { test_sha256_str, NULL, test_sha256 }, + { test_sha1_str, NULL, test_sha1 }, +// { performance_str, NULL, testrun_performance_bigint }, + { echo_str, (void*)1, (void_fpt)echo_ctrl }, + { NULL, NULL, NULL } +}; + +int main (void){ + main_setup(); + + for(;;){ + welcome_msg(algo_name); + cmd_interface(cmdlist); + } +} -- 2.39.2