8c00e6a5763ea3a673c8b0d8b8ae4002c64a1b3d
[strongswan.git] / src / libstrongswan / plugins / openssl / openssl_sha1_prf.c
1 /*
2 * Copyright (C) 2010 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 <openssl/opensslconf.h>
17
18 #ifndef OPENSSL_NO_SHA1
19
20 #include "openssl_sha1_prf.h"
21
22 #include <openssl/sha.h>
23
24 typedef struct private_openssl_sha1_prf_t private_openssl_sha1_prf_t;
25
26 /**
27 * Private data of an openssl_sha1_prf_t object.
28 */
29 struct private_openssl_sha1_prf_t {
30
31 /**
32 * Public openssl_sha1_prf_t interface.
33 */
34 openssl_sha1_prf_t public;
35
36 /**
37 * SHA1 context
38 */
39 SHA_CTX ctx;
40 };
41
42 METHOD(prf_t, get_bytes, bool,
43 private_openssl_sha1_prf_t *this, chunk_t seed, u_int8_t *bytes)
44 {
45 SHA1_Update(&this->ctx, seed.ptr, seed.len);
46
47 if (bytes)
48 {
49 u_int32_t *hash = (u_int32_t*)bytes;
50
51 hash[0] = htonl(this->ctx.h0);
52 hash[1] = htonl(this->ctx.h1);
53 hash[2] = htonl(this->ctx.h2);
54 hash[3] = htonl(this->ctx.h3);
55 hash[4] = htonl(this->ctx.h4);
56 }
57
58 return TRUE;
59 }
60
61 METHOD(prf_t, get_block_size, size_t,
62 private_openssl_sha1_prf_t *this)
63 {
64 return HASH_SIZE_SHA1;
65 }
66
67 METHOD(prf_t, allocate_bytes, bool,
68 private_openssl_sha1_prf_t *this, chunk_t seed, chunk_t *chunk)
69 {
70 if (chunk)
71 {
72 *chunk = chunk_alloc(HASH_SIZE_SHA1);
73 return get_bytes(this, seed, chunk->ptr);
74 }
75 return get_bytes(this, seed, NULL);
76 }
77
78 METHOD(prf_t, get_key_size, size_t,
79 private_openssl_sha1_prf_t *this)
80 {
81 return HASH_SIZE_SHA1;
82 }
83
84 METHOD(prf_t, set_key, bool,
85 private_openssl_sha1_prf_t *this, chunk_t key)
86 {
87 SHA1_Init(&this->ctx);
88
89 if (key.len % 4)
90 {
91 return FALSE;
92 }
93 if (key.len >= 4)
94 {
95 this->ctx.h0 ^= untoh32(key.ptr);
96 }
97 if (key.len >= 8)
98 {
99 this->ctx.h1 ^= untoh32(key.ptr + 4);
100 }
101 if (key.len >= 12)
102 {
103 this->ctx.h2 ^= untoh32(key.ptr + 8);
104 }
105 if (key.len >= 16)
106 {
107 this->ctx.h3 ^= untoh32(key.ptr + 12);
108 }
109 if (key.len >= 20)
110 {
111 this->ctx.h4 ^= untoh32(key.ptr + 16);
112 }
113 return TRUE;
114 }
115
116 METHOD(prf_t, destroy, void,
117 private_openssl_sha1_prf_t *this)
118 {
119 free(this);
120 }
121
122 /**
123 * See header
124 */
125 openssl_sha1_prf_t *openssl_sha1_prf_create(pseudo_random_function_t algo)
126 {
127 private_openssl_sha1_prf_t *this;
128
129 if (algo != PRF_KEYED_SHA1)
130 {
131 return NULL;
132 }
133
134 INIT(this,
135 .public = {
136 .prf = {
137 .get_block_size = _get_block_size,
138 .get_bytes = _get_bytes,
139 .allocate_bytes = _allocate_bytes,
140 .get_key_size = _get_key_size,
141 .set_key = _set_key,
142 .destroy = _destroy,
143 },
144 },
145 );
146
147 return &this->public;
148 }
149
150 #endif /* OPENSSL_NO_SHA1 */