]>
Commit | Line | Data |
---|---|---|
ab6908f1 MW |
1 | /** |
2 | * @file prf_plus.c | |
3 | * | |
8277be60 | 4 | * @brief Implementation of prf_plus_t. |
ab6908f1 MW |
5 | * |
6 | */ | |
7 | ||
8 | /* | |
9 | * Copyright (C) 2005 Jan Hutter, Martin Willi | |
10 | * Hochschule fuer Technik Rapperswil | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by the | |
14 | * Free Software Foundation; either version 2 of the License, or (at your | |
15 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, but | |
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
19 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
20 | * for more details. | |
21 | */ | |
22 | ||
5113680f | 23 | #include <string.h> |
ab6908f1 MW |
24 | |
25 | #include "prf_plus.h" | |
26 | ||
021c2322 | 27 | #include <definitions.h> |
ab6908f1 | 28 | |
5796aa16 MW |
29 | typedef struct private_prf_plus_t private_prf_plus_t; |
30 | ||
ab6908f1 MW |
31 | /** |
32 | * Private data of an prf_plus_t object. | |
33 | * | |
34 | */ | |
5796aa16 | 35 | struct private_prf_plus_t { |
ab6908f1 | 36 | /** |
1e7d52a6 | 37 | * Public interface of prf_plus_t. |
ab6908f1 MW |
38 | */ |
39 | prf_plus_t public; | |
40 | ||
41 | /** | |
1e7d52a6 | 42 | * PRF to use. |
ab6908f1 MW |
43 | */ |
44 | prf_t *prf; | |
45 | ||
46 | /** | |
1e7d52a6 | 47 | * Initial seed. |
ab6908f1 MW |
48 | */ |
49 | chunk_t seed; | |
50 | ||
51 | /** | |
1e7d52a6 | 52 | * Buffer to store current PRF result. |
ab6908f1 MW |
53 | */ |
54 | chunk_t buffer; | |
55 | ||
56 | /** | |
1e7d52a6 | 57 | * Already given out bytes in current buffer. |
ab6908f1 MW |
58 | */ |
59 | size_t given_out; | |
60 | ||
61 | /** | |
1e7d52a6 | 62 | * Octet which will be appended to the seed. |
ab6908f1 MW |
63 | */ |
64 | u_int8_t appending_octet; | |
65 | }; | |
66 | ||
ab6908f1 | 67 | /** |
1e7d52a6 | 68 | * Implementation of prf_plus_t.get_bytes. |
ab6908f1 | 69 | */ |
d048df5c | 70 | static void get_bytes(private_prf_plus_t *this, size_t length, u_int8_t *buffer) |
ab6908f1 MW |
71 | { |
72 | chunk_t appending_chunk; | |
73 | size_t bytes_in_round; | |
29b8cafc | 74 | size_t total_bytes_written = 0; |
ab6908f1 MW |
75 | |
76 | appending_chunk.ptr = &(this->appending_octet); | |
77 | appending_chunk.len = 1; | |
78 | ||
62adf1e0 | 79 | while (length > 0) |
ab6908f1 MW |
80 | { /* still more to do... */ |
81 | if (this->buffer.len == this->given_out) | |
82 | { /* no bytes left in buffer, get next*/ | |
83 | this->prf->get_bytes(this->prf, this->buffer, NULL); | |
84 | this->prf->get_bytes(this->prf, this->seed, NULL); | |
85 | this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr); | |
86 | this->given_out = 0; | |
87 | this->appending_octet++; | |
88 | } | |
89 | /* how many bytes can we write in this round ? */ | |
90 | bytes_in_round = min(length, this->buffer.len - this->given_out); | |
91 | /* copy bytes from buffer with offset */ | |
29b8cafc | 92 | memcpy(buffer + total_bytes_written, this->buffer.ptr + this->given_out, bytes_in_round); |
ab6908f1 MW |
93 | |
94 | length -= bytes_in_round; | |
95 | this->given_out += bytes_in_round; | |
29b8cafc | 96 | total_bytes_written += bytes_in_round; |
ab6908f1 | 97 | } |
ab6908f1 MW |
98 | } |
99 | ||
100 | /** | |
1e7d52a6 | 101 | * Implementation of prf_plus_t.allocate_bytes. |
ab6908f1 | 102 | */ |
d048df5c | 103 | static void allocate_bytes(private_prf_plus_t *this, size_t length, chunk_t *chunk) |
ab6908f1 | 104 | { |
5113680f | 105 | chunk->ptr = malloc(length); |
ab6908f1 | 106 | chunk->len = length; |
d048df5c | 107 | this->public.get_bytes(&(this->public), length, chunk->ptr); |
ab6908f1 MW |
108 | } |
109 | ||
110 | /** | |
1e7d52a6 | 111 | * Implementation of prf_plus_t.destroy. |
ab6908f1 | 112 | */ |
d048df5c | 113 | static void destroy(private_prf_plus_t *this) |
ab6908f1 | 114 | { |
5113680f MW |
115 | free(this->buffer.ptr); |
116 | free(this->seed.ptr); | |
117 | free(this); | |
ab6908f1 MW |
118 | } |
119 | ||
120 | /* | |
1e7d52a6 | 121 | * Description in header. |
ab6908f1 MW |
122 | */ |
123 | prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed) | |
124 | { | |
125 | private_prf_plus_t *this; | |
126 | chunk_t appending_chunk; | |
127 | ||
5113680f | 128 | this = malloc_thing(private_prf_plus_t); |
d048df5c | 129 | |
ab6908f1 | 130 | /* set public methods */ |
d048df5c MW |
131 | this->public.get_bytes = (void (*)(prf_plus_t *,size_t,u_int8_t*))get_bytes; |
132 | this->public.allocate_bytes = (void (*)(prf_plus_t *,size_t,chunk_t*))allocate_bytes; | |
133 | this->public.destroy = (void (*)(prf_plus_t *))destroy; | |
ab6908f1 MW |
134 | |
135 | /* take over prf */ | |
136 | this->prf = prf; | |
137 | ||
138 | /* allocate buffer for prf output */ | |
139 | this->buffer.len = prf->get_block_size(prf); | |
5113680f | 140 | this->buffer.ptr = malloc(this->buffer.len); |
d048df5c | 141 | |
ab6908f1 MW |
142 | this->appending_octet = 0x01; |
143 | ||
144 | /* clone seed */ | |
5113680f | 145 | this->seed.ptr = clalloc(seed.ptr, seed.len); |
ab6908f1 | 146 | this->seed.len = seed.len; |
d048df5c | 147 | |
ab6908f1 MW |
148 | /* do the first run */ |
149 | appending_chunk.ptr = &(this->appending_octet); | |
150 | appending_chunk.len = 1; | |
151 | this->prf->get_bytes(this->prf, this->seed, NULL); | |
152 | this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr); | |
153 | this->given_out = 0; | |
154 | this->appending_octet++; | |
155 | ||
156 | return &(this->public); | |
157 | } |