Add a return value to prf_t.allocate_bytes()
[strongswan.git] / src / libstrongswan / plugins / sha1 / sha1_prf.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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 "sha1_prf.h"
17 #include "sha1_hasher.h"
18
19 #include <arpa/inet.h>
20
21 typedef struct private_sha1_prf_t private_sha1_prf_t;
22 typedef struct private_sha1_hasher_t private_sha1_hasher_t;
23
24 /**
25 * Private data structure with hasing context.
26 */
27 struct private_sha1_hasher_t {
28 /**
29 * Public interface for this hasher.
30 */
31 sha1_hasher_t public;
32
33 /*
34 * State of the hasher. From sha1_hasher.c, do not change it!
35 */
36 u_int32_t state[5];
37 u_int32_t count[2];
38 u_int8_t buffer[64];
39 };
40
41 /**
42 * Private data structure with keyed prf context.
43 */
44 struct private_sha1_prf_t {
45
46 /**
47 * public prf interface
48 */
49 sha1_prf_t public;
50
51 /**
52 * internal used hasher
53 */
54 private_sha1_hasher_t *hasher;
55 };
56
57 /**
58 * From sha1_hasher.c
59 */
60 extern void SHA1Update(private_sha1_hasher_t* this, u_int8_t *data, u_int32_t len);
61
62 METHOD(prf_t, get_bytes, bool,
63 private_sha1_prf_t *this, chunk_t seed, u_int8_t *bytes)
64 {
65 u_int32_t *hash = (u_int32_t*)bytes;
66
67 SHA1Update(this->hasher, seed.ptr, seed.len);
68
69 hash[0] = htonl(this->hasher->state[0]);
70 hash[1] = htonl(this->hasher->state[1]);
71 hash[2] = htonl(this->hasher->state[2]);
72 hash[3] = htonl(this->hasher->state[3]);
73 hash[4] = htonl(this->hasher->state[4]);
74
75 return TRUE;
76 }
77
78 METHOD(prf_t, get_block_size, size_t,
79 private_sha1_prf_t *this)
80 {
81 return HASH_SIZE_SHA1;
82 }
83
84 METHOD(prf_t, allocate_bytes, bool,
85 private_sha1_prf_t *this, chunk_t seed, chunk_t *chunk)
86 {
87 *chunk = chunk_alloc(HASH_SIZE_SHA1);
88 return get_bytes(this, seed, chunk->ptr);
89 }
90
91 METHOD(prf_t, get_key_size, size_t,
92 private_sha1_prf_t *this)
93 {
94 return sizeof(this->hasher->state);
95 }
96
97 METHOD(prf_t, set_key, void,
98 private_sha1_prf_t *this, chunk_t key)
99 {
100 int i, rounds;
101 u_int32_t *iv = (u_int32_t*)key.ptr;
102
103 this->hasher->public.hasher_interface.reset(&this->hasher->public.hasher_interface);
104 rounds = min(key.len/sizeof(u_int32_t), sizeof(this->hasher->state));
105 for (i = 0; i < rounds; i++)
106 {
107 this->hasher->state[i] ^= htonl(iv[i]);
108 }
109 }
110
111 METHOD(prf_t, destroy, void,
112 private_sha1_prf_t *this)
113 {
114 this->hasher->public.hasher_interface.destroy(&this->hasher->public.hasher_interface);
115 free(this);
116 }
117
118 /**
119 * see header
120 */
121 sha1_prf_t *sha1_prf_create(pseudo_random_function_t algo)
122 {
123 private_sha1_prf_t *this;
124
125 if (algo != PRF_KEYED_SHA1)
126 {
127 return NULL;
128 }
129
130 INIT(this,
131 .public = {
132 .prf_interface = {
133 .get_bytes = _get_bytes,
134 .allocate_bytes = _allocate_bytes,
135 .get_block_size = _get_block_size,
136 .get_key_size = _get_key_size,
137 .set_key = _set_key,
138 .destroy = _destroy,
139 },
140 },
141 .hasher = (private_sha1_hasher_t*)sha1_hasher_create(HASH_SHA1),
142 );
143
144 return &this->public;
145 }
146