]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/plugins/padlock/padlock_sha1_hasher.c
Add a return value to hasher_t.allocate_hash()
[thirdparty/strongswan.git] / src / libstrongswan / plugins / padlock / padlock_sha1_hasher.c
1 /*
2 * Copyright (C) 2008 Thomas Kallenberg
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <string.h>
18 #include <arpa/inet.h>
19 #include <byteswap.h>
20
21 #include "padlock_sha1_hasher.h"
22
23 #define PADLOCK_ALIGN __attribute__ ((__aligned__(16)))
24
25 typedef struct private_padlock_sha1_hasher_t private_padlock_sha1_hasher_t;
26
27 /**
28 * Private data structure with hasing context.
29 */
30 struct private_padlock_sha1_hasher_t {
31 /**
32 * Public interface for this hasher.
33 */
34 padlock_sha1_hasher_t public;
35
36 /**
37 * data collected to hash
38 */
39 chunk_t data;
40 };
41
42 /**
43 * Invoke the actual padlock sha1() operation
44 */
45 static void padlock_sha1(int len, u_char *in, u_char *out)
46 {
47 /* rep xsha1 */
48 asm volatile (
49 ".byte 0xf3, 0x0f, 0xa6, 0xc8"
50 : "+S"(in), "+D"(out)
51 : "c"(len), "a"(0));
52 }
53
54 /**
55 * sha1() a buffer of data into digest
56 */
57 static void sha1(chunk_t data, u_int32_t *digest)
58 {
59 u_int32_t hash[128] PADLOCK_ALIGN;
60
61 hash[0] = 0x67452301;
62 hash[1] = 0xefcdab89;
63 hash[2] = 0x98badcfe;
64 hash[3] = 0x10325476;
65 hash[4] = 0xc3d2e1f0;
66
67 padlock_sha1(data.len, data.ptr, (u_char*)hash);
68
69 digest[0] = bswap_32(hash[0]);
70 digest[1] = bswap_32(hash[1]);
71 digest[2] = bswap_32(hash[2]);
72 digest[3] = bswap_32(hash[3]);
73 digest[4] = bswap_32(hash[4]);
74 }
75
76 /**
77 * append data to the to-be-hashed buffer
78 */
79 static void append_data(private_padlock_sha1_hasher_t *this, chunk_t data)
80 {
81 this->data.ptr = realloc(this->data.ptr, this->data.len + data.len);
82 memcpy(this->data.ptr + this->data.len, data.ptr, data.len);
83 this->data.len += data.len;
84 }
85
86 METHOD(hasher_t, reset, void,
87 private_padlock_sha1_hasher_t *this)
88 {
89 chunk_free(&this->data);
90 }
91
92 METHOD(hasher_t, get_hash, bool,
93 private_padlock_sha1_hasher_t *this, chunk_t chunk, u_int8_t *hash)
94 {
95 if (hash)
96 {
97 if (this->data.len)
98 {
99 append_data(this, chunk);
100 sha1(this->data, (u_int32_t*)hash);
101 }
102 else
103 { /* hash directly if no previous data found */
104 sha1(chunk, (u_int32_t*)hash);
105 }
106 reset(this);
107 }
108 else
109 {
110 append_data(this, chunk);
111 }
112 return TRUE;
113 }
114
115 METHOD(hasher_t, allocate_hash, bool,
116 private_padlock_sha1_hasher_t *this, chunk_t chunk, chunk_t *hash)
117 {
118 if (hash)
119 {
120 *hash = chunk_alloc(HASH_SIZE_SHA1);
121 return get_hash(this, chunk, hash->ptr);
122 }
123 return get_hash(this, chunk, NULL);
124 }
125
126 METHOD(hasher_t, get_hash_size, size_t,
127 private_padlock_sha1_hasher_t *this)
128 {
129 return HASH_SIZE_SHA1;
130 }
131
132 METHOD(hasher_t, destroy, void,
133 private_padlock_sha1_hasher_t *this)
134 {
135 free(this->data.ptr);
136 free(this);
137 }
138
139 /*
140 * Described in header.
141 */
142 padlock_sha1_hasher_t *padlock_sha1_hasher_create(hash_algorithm_t algo)
143 {
144 private_padlock_sha1_hasher_t *this;
145
146 if (algo != HASH_SHA1)
147 {
148 return NULL;
149 }
150 INIT(this,
151 .public = {
152 .hasher = {
153 .get_hash = _get_hash,
154 .allocate_hash = _allocate_hash,
155 .get_hash_size = _get_hash_size,
156 .reset = _reset,
157 .destroy = _destroy,
158 },
159 },
160 );
161 return &this->public;
162 }