ECB mode added to the DES plugin
[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 * $Id$
17 */
18
19 #include <string.h>
20 #include <arpa/inet.h>
21 #include <byteswap.h>
22
23 #include "padlock_sha1_hasher.h"
24
25 #define PADLOCK_ALIGN __attribute__ ((__aligned__(16)))
26
27 typedef struct private_padlock_sha1_hasher_t private_padlock_sha1_hasher_t;
28
29 /**
30 * Private data structure with hasing context.
31 */
32 struct private_padlock_sha1_hasher_t {
33 /**
34 * Public interface for this hasher.
35 */
36 padlock_sha1_hasher_t public;
37
38 /**
39 * data collected to hash
40 */
41 chunk_t data;
42 };
43
44 /**
45 * Invoke the actual padlock sha1() operation
46 */
47 static void padlock_sha1(int len, u_char *in, u_char *out)
48 {
49 /* rep xsha1 */
50 asm volatile (
51 ".byte 0xf3, 0x0f, 0xa6, 0xc8"
52 : "+S"(in), "+D"(out)
53 : "c"(len), "a"(0));
54 }
55
56 /**
57 * sha1() a buffer of data into digest
58 */
59 static void sha1(chunk_t data, u_int32_t *digest)
60 {
61 u_int32_t hash[128] PADLOCK_ALIGN;
62
63 hash[0] = 0x67452301;
64 hash[1] = 0xefcdab89;
65 hash[2] = 0x98badcfe;
66 hash[3] = 0x10325476;
67 hash[4] = 0xc3d2e1f0;
68
69 padlock_sha1(data.len, data.ptr, (u_char*)hash);
70
71 digest[0] = bswap_32(hash[0]);
72 digest[1] = bswap_32(hash[1]);
73 digest[2] = bswap_32(hash[2]);
74 digest[3] = bswap_32(hash[3]);
75 digest[4] = bswap_32(hash[4]);
76 }
77
78 /**
79 * append data to the to-be-hashed buffer
80 */
81 static void append_data(private_padlock_sha1_hasher_t *this, chunk_t data)
82 {
83 this->data.ptr = realloc(this->data.ptr, this->data.len + data.len);
84 memcpy(this->data.ptr + this->data.len, data.ptr, data.len);
85 this->data.len += data.len;
86 }
87
88 /**
89 * Implementation of hasher_t.reset.
90 */
91 static void reset(private_padlock_sha1_hasher_t *this)
92 {
93 chunk_free(&this->data);
94 }
95
96 /**
97 * Implementation of hasher_t.get_hash.
98 */
99 static void get_hash(private_padlock_sha1_hasher_t *this, chunk_t chunk,
100 u_int8_t *hash)
101 {
102 if (hash)
103 {
104 if (this->data.len)
105 {
106 append_data(this, chunk);
107 sha1(this->data, (u_int32_t*)hash);
108 }
109 else
110 { /* hash directly if no previous data found */
111 sha1(chunk, (u_int32_t*)hash);
112 }
113 reset(this);
114 }
115 else
116 {
117 append_data(this, chunk);
118 }
119 }
120
121 /**
122 * Implementation of hasher_t.allocate_hash.
123 */
124 static void allocate_hash(private_padlock_sha1_hasher_t *this, chunk_t chunk,
125 chunk_t *hash)
126 {
127 if (hash)
128 {
129 *hash = chunk_alloc(HASH_SIZE_SHA1);
130 get_hash(this, chunk, hash->ptr);
131 }
132 else
133 {
134 get_hash(this, chunk, NULL);
135 }
136 }
137
138 /**
139 * Implementation of hasher_t.get_hash_size.
140 */
141 static size_t get_hash_size(private_padlock_sha1_hasher_t *this)
142 {
143 return HASH_SIZE_SHA1;
144 }
145
146 /**
147 * Implementation of hasher_t.destroy.
148 */
149 static void destroy(private_padlock_sha1_hasher_t *this)
150 {
151 free(this->data.ptr);
152 free(this);
153 }
154
155 /*
156 * Described in header.
157 */
158 padlock_sha1_hasher_t *padlock_sha1_hasher_create(hash_algorithm_t algo)
159 {
160 private_padlock_sha1_hasher_t *this;
161
162 if (algo != HASH_SHA1)
163 {
164 return NULL;
165 }
166
167 this = malloc_thing(private_padlock_sha1_hasher_t);
168 this->public.hasher_interface.get_hash = (void (*) (hasher_t*, chunk_t, u_int8_t*))get_hash;
169 this->public.hasher_interface.allocate_hash = (void (*) (hasher_t*, chunk_t, chunk_t*))allocate_hash;
170 this->public.hasher_interface.get_hash_size = (size_t (*) (hasher_t*))get_hash_size;
171 this->public.hasher_interface.reset = (void (*) (hasher_t*))reset;
172 this->public.hasher_interface.destroy = (void (*) (hasher_t*))destroy;
173
174 this->data = chunk_empty;
175
176 return &(this->public);
177 }