]> git.cryptolib.org Git - arm-crypto-lib.git/blob - prf_tls12/prf_tls12.c
now with function
[arm-crypto-lib.git] / prf_tls12 / prf_tls12.c
1 /* prf_tls12.c */
2 /*
3     This file is part of the ARM-Crypto-Lib.
4     Copyright (C) 2009  Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 /*
20  * \file    prf_tls12.c
21  * \author  Daniel Otte
22  * \email   daniel.otte@rub.de
23  * \date    2011-10-06
24  * \license GPLv3 or later
25  *
26  */
27 /* from rfc5246
28
29
30       P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
31                              HMAC_hash(secret, A(2) + seed) +
32                              HMAC_hash(secret, A(3) + seed) + ...
33
34    where + indicates concatenation.
35
36    A() is defined as:
37
38       A(0) = seed
39       A(i) = HMAC_hash(secret, A(i-1))
40
41    P_hash can be iterated as many times as necessary to produce the
42    required quantity of data.  For example, if P_SHA256 is being used to
43    create 80 bytes of data, it will have to be iterated three times
44    (through A(3)), creating 96 bytes of output data; the last 16 bytes
45    of the final iteration will then be discarded, leaving 80 bytes of
46    output data.
47
48    TLS's PRF is created by applying P_hash to the secret as:
49
50       PRF(secret, label, seed) = P_<hash>(secret, label + seed)
51
52 */
53 /* long story short:
54  * P(k,s) = H(k, A(1) | s) | H(k, A(2) | s) | ... | H(k, A(n) | s)
55  * A(0) = s
56  * A(i) = H(k, A(i-1))
57  *
58  * PRF(k,l,s) = P(k, l | s)
59  *
60  */
61
62 /* This implementation is limited to hashfunctions which return a hash value
63  * of a length (in bits) which is divideable by 8.
64  *
65  * Also note that our HMAC implementation may fail on hashfunction which
66  * return a larger hash value then their nativ blocksize
67  *
68  */
69
70 #include <stdint.h>
71 #include <stdlib.h>
72 #include <string.h>
73 #include <crypto/hashfunction_descriptor.h>
74 #include <crypto/hfal-basic.h>
75 #include <crypto/hfal-hmac.h>
76 #include "prf_tls12.h"
77
78 uint8_t prf_tls12_init(prf_tls12_ctx_t* ctx, const hfdesc_t* hash,
79         const void* key, uint16_t keylength_b,
80         const void* seed, uint16_t seedlength_b){
81         hfhmacgen_ctx_t tmp_ctx;
82         ctx->blocklength_b = hfal_hash_getHashsize(hash);
83         ctx->seed_buffer = malloc(ctx->blocklength_b/8+(seedlength_b+7)/8);
84         if(!ctx->seed_buffer){
85                 return 1;
86         }
87         ctx->bufferlength_b = ctx->blocklength_b + seedlength_b;
88         memcpy(ctx->seed_buffer+ctx->blocklength_b/8, seed, seedlength_b/8);
89         if(hfal_hmac_init(hash, &(ctx->mainctx), key, keylength_b)){
90                 return 2;
91         }
92         if(hfal_hmac_ctxcopy(&tmp_ctx, &(ctx->mainctx))){
93                 prf_tls12_free(ctx);
94                 return 3;
95         }
96         hfal_hmac_lastBlock(&tmp_ctx, seed, seedlength_b);
97         hfal_hmac_ctx2mac(ctx->seed_buffer, &tmp_ctx);
98         hfal_hmac_free(&tmp_ctx);
99         return 0;
100 }
101
102 uint8_t prf_tls12_init_w_label(prf_tls12_ctx_t* ctx, const hfdesc_t* hash,
103         const void* key, uint16_t keylength_b,
104         const void* label, uint16_t labellength_B,
105         const void* seed, uint16_t seedlength_b){
106
107         uint8_t buffer[labellength_B+(seedlength_b+7)/8];
108         memcpy(buffer, label, labellength_B);
109         memcpy(buffer+labellength_B, seed, (seedlength_b+7)/8);
110         return prf_tls12_init(ctx, hash, key, keylength_b, buffer, labellength_B*8+seedlength_b);
111 }
112
113
114 void prf_tls12_free(prf_tls12_ctx_t* ctx){
115         free(ctx->seed_buffer);
116         hfal_hmac_free(&(ctx->mainctx));
117 }
118
119 uint8_t prf_tls12_next(void* dest, prf_tls12_ctx_t* ctx){
120         hfhmacgen_ctx_t tmp_ctx;
121         if(hfal_hmac_ctxcopy(&tmp_ctx, &(ctx->mainctx))){
122                 return 1;
123         }
124         hfal_hmac_lastBlock(&tmp_ctx, ctx->seed_buffer, ctx->bufferlength_b);
125         hfal_hmac_ctx2mac(dest, &tmp_ctx);
126         hfal_hmac_free(&tmp_ctx);
127         if(hfal_hmac_ctxcopy(&tmp_ctx, &(ctx->mainctx))){
128                 return 2;
129         }
130         hfal_hmac_lastBlock(&tmp_ctx, ctx->seed_buffer, ctx->blocklength_b);
131         hfal_hmac_ctx2mac(ctx->seed_buffer, &tmp_ctx);
132         hfal_hmac_free(&tmp_ctx);
133         return 0;
134 }
135
136 uint8_t prf_tls12_fill(void* dest, uint16_t length_B, prf_tls12_ctx_t* ctx){
137         uint16_t bs = ctx->blocklength_b/8;
138         while(length_B>=bs){
139                 if(prf_tls12_next(dest, ctx)){
140                         return 1;
141                 }
142                 length_B -= bs;
143                 dest = (uint8_t*)dest + bs;
144         }
145         if(length_B){
146                 uint8_t buffer[bs];
147                 if(prf_tls12_next(buffer, ctx)){
148                         return 2;
149                 }
150                 memcpy(dest, buffer, length_B);
151         }
152         return 0;
153 }