]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libtls/tls_prf.c
Add a return value to tls_prf_t.set_key()
[thirdparty/strongswan.git] / src / libtls / tls_prf.c
CommitLineData
149b7e6d
MW
1/*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16#include "tls_prf.h"
17
18typedef struct private_tls_prf12_t private_tls_prf12_t;
19
20/**
21 * Private data of an tls_prf_t object.
22 */
23struct private_tls_prf12_t {
24
25 /**
26 * Public tls_prf_t interface.
27 */
28 tls_prf_t public;
29
30 /**
31 * Underlying primitive PRF
32 */
33 prf_t *prf;
34};
35
e7d98b8c 36METHOD(tls_prf_t, set_key12, bool,
149b7e6d
MW
37 private_tls_prf12_t *this, chunk_t key)
38{
39 this->prf->set_key(this->prf, key);
e7d98b8c 40 return TRUE;
149b7e6d
MW
41}
42
43/**
44 * The P_hash function as in TLS 1.0/1.2
45 */
97b30b93 46static bool p_hash(prf_t *prf, char *label, chunk_t seed, size_t block_size,
149b7e6d
MW
47 size_t bytes, char *out)
48{
49 char buf[block_size], abuf[block_size];
50 chunk_t a;
51
52 /* seed = label + seed */
53 seed = chunk_cata("cc", chunk_create(label, strlen(label)), seed);
54 /* A(0) = seed */
55 a = seed;
56
57 while (TRUE)
58 {
59 /* A(i) = HMAC_hash(secret, A(i-1)) */
60 prf->get_bytes(prf, a, abuf);
61 a = chunk_from_thing(abuf);
62 /* HMAC_hash(secret, A(i) + seed) */
63 prf->get_bytes(prf, a, NULL);
64 prf->get_bytes(prf, seed, buf);
65
66 if (bytes <= block_size)
67 {
68 memcpy(out, buf, bytes);
69 break;
70 }
71 memcpy(out, buf, block_size);
72 out += block_size;
73 bytes -= block_size;
74 }
97b30b93 75 return TRUE;
149b7e6d
MW
76}
77
97b30b93 78METHOD(tls_prf_t, get_bytes12, bool,
149b7e6d
MW
79 private_tls_prf12_t *this, char *label, chunk_t seed,
80 size_t bytes, char *out)
81{
97b30b93
MW
82 return p_hash(this->prf, label, seed, this->prf->get_block_size(this->prf),
83 bytes, out);
149b7e6d
MW
84}
85
86METHOD(tls_prf_t, destroy12, void,
87 private_tls_prf12_t *this)
88{
89 this->prf->destroy(this->prf);
90 free(this);
91}
92
93/**
94 * See header
95 */
96tls_prf_t *tls_prf_create_12(pseudo_random_function_t prf)
97{
98 private_tls_prf12_t *this;
99
100 INIT(this,
101 .public = {
102 .set_key = _set_key12,
103 .get_bytes = _get_bytes12,
104 .destroy = _destroy12,
105 },
106 .prf = lib->crypto->create_prf(lib->crypto, prf),
107 );
108 if (!this->prf)
109 {
110 free(this);
111 return NULL;
112 }
113 return &this->public;
114}
115
116
117typedef struct private_tls_prf10_t private_tls_prf10_t;
118
119/**
120 * Private data of an tls_prf_t object.
121 */
122struct private_tls_prf10_t {
123
124 /**
125 * Public tls_prf_t interface.
126 */
127 tls_prf_t public;
128
129 /**
130 * Underlying MD5 PRF
131 */
132 prf_t *md5;
133
134 /**
135 * Underlying SHA1 PRF
136 */
137 prf_t *sha1;
138};
139
e7d98b8c 140METHOD(tls_prf_t, set_key10, bool,
149b7e6d
MW
141 private_tls_prf10_t *this, chunk_t key)
142{
143 size_t len = key.len / 2 + key.len % 2;
144
145 this->md5->set_key(this->md5, chunk_create(key.ptr, len));
146 this->sha1->set_key(this->sha1, chunk_create(key.ptr + key.len - len, len));
e7d98b8c 147 return TRUE;
149b7e6d
MW
148}
149
97b30b93 150METHOD(tls_prf_t, get_bytes10, bool,
149b7e6d
MW
151 private_tls_prf10_t *this, char *label, chunk_t seed,
152 size_t bytes, char *out)
153{
154 char buf[bytes];
155
97b30b93
MW
156 if (!p_hash(this->md5, label, seed, this->md5->get_block_size(this->md5),
157 bytes, out) ||
158 !p_hash(this->sha1, label, seed, this->sha1->get_block_size(this->sha1),
159 bytes, buf))
160 {
161 return FALSE;
162 }
149b7e6d 163 memxor(out, buf, bytes);
97b30b93 164 return TRUE;
149b7e6d
MW
165}
166
167METHOD(tls_prf_t, destroy10, void,
168 private_tls_prf10_t *this)
169{
170 DESTROY_IF(this->md5);
171 DESTROY_IF(this->sha1);
172 free(this);
173}
174
175/**
176 * See header
177 */
178tls_prf_t *tls_prf_create_10(pseudo_random_function_t prf)
179{
180 private_tls_prf10_t *this;
181
182 INIT(this,
183 .public = {
184 .set_key = _set_key10,
185 .get_bytes = _get_bytes10,
186 .destroy = _destroy10,
187 },
188 .md5 = lib->crypto->create_prf(lib->crypto, PRF_HMAC_MD5),
189 .sha1 = lib->crypto->create_prf(lib->crypto, PRF_HMAC_SHA1),
190 );
191 if (!this->md5 || !this->sha1)
192 {
193 destroy10(this);
194 return NULL;
195 }
196 return &this->public;
197}