Added Appro's SSSE3 SHA implementations
[gnutls:gnutls.git] / lib / accelerated / x86 / hmac-x86.c
1 /*
2  * Copyright (C) 2008, 2010-2012 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GNUTLS.
7  *
8  * The GNUTLS library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>
20  *
21  */
22
23 /* This file provides the backend hash/mac implementation for
24  * VIA Padlock hardware acceleration.
25  */
26
27 #include <gnutls_int.h>
28 #include <gnutls_hash_int.h>
29 #include <gnutls_errors.h>
30 #include <nettle/sha.h>
31 #include <nettle/hmac.h>
32 #include <nettle/macros.h>
33 #include <aes-x86.h>
34 #include <sha-x86.h>
35 #include <algorithms.h>
36
37 #ifdef HAVE_LIBNETTLE
38
39 typedef void (*update_func) (void *, unsigned, const uint8_t *);
40 typedef void (*digest_func) (void *, unsigned, uint8_t *);
41 typedef void (*set_key_func) (void *, unsigned, const uint8_t *);
42
43 struct x86_hmac_ctx {
44         union {
45                 struct hmac_sha1_ctx sha1;
46                 struct hmac_sha224_ctx sha224;
47                 struct hmac_sha256_ctx sha256;
48 #ifdef ENABLE_SHA512
49                 struct hmac_sha384_ctx sha384;
50                 struct hmac_sha512_ctx sha512;
51 #endif
52         } ctx;
53
54         void *ctx_ptr;
55         gnutls_mac_algorithm_t algo;
56         size_t length;
57         update_func update;
58         digest_func digest;
59         set_key_func setkey;
60 };
61
62 static void
63 x86_hmac_sha1_set_key(struct hmac_sha1_ctx *ctx,
64                           unsigned key_length, const uint8_t * key)
65 {
66         HMAC_SET_KEY(ctx, &x86_sha1, key_length, key);
67 }
68
69 static void
70 x86_hmac_sha1_update(struct hmac_sha1_ctx *ctx,
71                          unsigned length, const uint8_t * data)
72 {
73         x86_sha1_update(&ctx->state, length, data);
74 }
75
76 static void
77 x86_hmac_sha1_digest(struct hmac_sha1_ctx *ctx,
78                          unsigned length, uint8_t * digest)
79 {
80         HMAC_DIGEST(ctx, &x86_sha1, length, digest);
81 }
82
83 static void
84 x86_hmac_sha256_set_key(struct hmac_sha256_ctx *ctx,
85                             unsigned key_length, const uint8_t * key)
86 {
87         HMAC_SET_KEY(ctx, &x86_sha256, key_length, key);
88 }
89
90 static void
91 x86_hmac_sha256_update(struct hmac_sha256_ctx *ctx,
92                            unsigned length, const uint8_t * data)
93 {
94         x86_sha256_update(&ctx->state, length, data);
95 }
96
97 static void
98 x86_hmac_sha256_digest(struct hmac_sha256_ctx *ctx,
99                            unsigned length, uint8_t * digest)
100 {
101         HMAC_DIGEST(ctx, &x86_sha256, length, digest);
102 }
103
104 static void
105 x86_hmac_sha224_set_key(struct hmac_sha224_ctx *ctx,
106                             unsigned key_length, const uint8_t * key)
107 {
108         HMAC_SET_KEY(ctx, &x86_sha224, key_length, key);
109 }
110
111 static void
112 x86_hmac_sha224_digest(struct hmac_sha224_ctx *ctx,
113                            unsigned length, uint8_t * digest)
114 {
115         HMAC_DIGEST(ctx, &x86_sha224, length, digest);
116 }
117
118 #ifdef ENABLE_SHA512
119 static void
120 x86_hmac_sha384_set_key(struct hmac_sha384_ctx *ctx,
121                             unsigned key_length, const uint8_t * key)
122 {
123         HMAC_SET_KEY(ctx, &x86_sha384, key_length, key);
124 }
125
126 static void
127 x86_hmac_sha384_digest(struct hmac_sha384_ctx *ctx,
128                            unsigned length, uint8_t * digest)
129 {
130         HMAC_DIGEST(ctx, &x86_sha384, length, digest);
131 }
132
133 static void
134 x86_hmac_sha512_set_key(struct hmac_sha512_ctx *ctx,
135                             unsigned key_length, const uint8_t * key)
136 {
137         HMAC_SET_KEY(ctx, &x86_sha512, key_length, key);
138 }
139
140 static void
141 x86_hmac_sha512_update(struct hmac_sha512_ctx *ctx,
142                            unsigned length, const uint8_t * data)
143 {
144         x86_sha512_update(&ctx->state, length, data);
145 }
146
147 static void
148 x86_hmac_sha512_digest(struct hmac_sha512_ctx *ctx,
149                            unsigned length, uint8_t * digest)
150 {
151         HMAC_DIGEST(ctx, &x86_sha512, length, digest);
152 }
153 #endif
154
155 static int
156 _hmac_ctx_init(gnutls_mac_algorithm_t algo, struct x86_hmac_ctx *ctx)
157 {
158         switch (algo) {
159         case GNUTLS_MAC_SHA1:
160                 ctx->update = (update_func) x86_hmac_sha1_update;
161                 ctx->digest = (digest_func) x86_hmac_sha1_digest;
162                 ctx->setkey = (set_key_func) x86_hmac_sha1_set_key;
163                 ctx->ctx_ptr = &ctx->ctx.sha1;
164                 ctx->length = SHA1_DIGEST_SIZE;
165                 break;
166         case GNUTLS_MAC_SHA224:
167                 ctx->update = (update_func) x86_hmac_sha256_update;
168                 ctx->digest = (digest_func) x86_hmac_sha224_digest;
169                 ctx->setkey = (set_key_func) x86_hmac_sha224_set_key;
170                 ctx->ctx_ptr = &ctx->ctx.sha224;
171                 ctx->length = SHA224_DIGEST_SIZE;
172                 break;
173         case GNUTLS_MAC_SHA256:
174                 ctx->update = (update_func) x86_hmac_sha256_update;
175                 ctx->digest = (digest_func) x86_hmac_sha256_digest;
176                 ctx->setkey = (set_key_func) x86_hmac_sha256_set_key;
177                 ctx->ctx_ptr = &ctx->ctx.sha256;
178                 ctx->length = SHA256_DIGEST_SIZE;
179                 break;
180 #ifdef ENABLE_SHA512
181         case GNUTLS_MAC_SHA384:
182                 ctx->update = (update_func) x86_hmac_sha512_update;
183                 ctx->digest = (digest_func) x86_hmac_sha384_digest;
184                 ctx->setkey = (set_key_func) x86_hmac_sha384_set_key;
185                 ctx->ctx_ptr = &ctx->ctx.sha384;
186                 ctx->length = SHA384_DIGEST_SIZE;
187                 break;
188         case GNUTLS_MAC_SHA512:
189                 ctx->update = (update_func) x86_hmac_sha512_update;
190                 ctx->digest = (digest_func) x86_hmac_sha512_digest;
191                 ctx->setkey = (set_key_func) x86_hmac_sha512_set_key;
192                 ctx->ctx_ptr = &ctx->ctx.sha512;
193                 ctx->length = SHA512_DIGEST_SIZE;
194                 break;
195 #endif
196         default:
197                 gnutls_assert();
198                 return GNUTLS_E_INVALID_REQUEST;
199         }
200
201         return 0;
202 }
203
204
205 static int wrap_x86_hmac_init(gnutls_mac_algorithm_t algo, void **_ctx)
206 {
207         struct x86_hmac_ctx *ctx;
208         int ret;
209
210         ctx = gnutls_calloc(1, sizeof(struct x86_hmac_ctx));
211         if (ctx == NULL) {
212                 gnutls_assert();
213                 return GNUTLS_E_MEMORY_ERROR;
214         }
215
216         ctx->algo = algo;
217
218         ret = _hmac_ctx_init(algo, ctx);
219         if (ret < 0)
220                 return gnutls_assert_val(ret);
221
222         *_ctx = ctx;
223
224         return 0;
225 }
226
227 static int
228 wrap_x86_hmac_setkey(void *_ctx, const void *key, size_t keylen)
229 {
230         struct x86_hmac_ctx *ctx = _ctx;
231
232         ctx->setkey(ctx->ctx_ptr, keylen, key);
233
234         return GNUTLS_E_SUCCESS;
235 }
236
237 static int
238 wrap_x86_hmac_update(void *_ctx, const void *text, size_t textsize)
239 {
240         struct x86_hmac_ctx *ctx = _ctx;
241
242         ctx->update(ctx->ctx_ptr, textsize, text);
243
244         return GNUTLS_E_SUCCESS;
245 }
246
247 static int
248 wrap_x86_hmac_output(void *src_ctx, void *digest, size_t digestsize)
249 {
250         struct x86_hmac_ctx *ctx;
251         ctx = src_ctx;
252
253         if (digestsize < ctx->length) {
254                 gnutls_assert();
255                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
256         }
257
258         ctx->digest(ctx->ctx_ptr, digestsize, digest);
259
260         return 0;
261 }
262
263 static void wrap_x86_hmac_deinit(void *hd)
264 {
265         gnutls_free(hd);
266 }
267
268 static int wrap_x86_hmac_fast(gnutls_mac_algorithm_t algo,
269                                 const void *nonce, size_t nonce_size,
270                                 const void *key, size_t key_size,
271                                 const void *text, size_t text_size,
272                                 void *digest)
273 {
274         struct x86_hmac_ctx ctx;
275         int ret;
276
277         ret = _hmac_ctx_init(algo, &ctx);
278         if (ret < 0)
279                 return gnutls_assert_val(ret);
280
281         ctx.setkey(&ctx, key_size, key);
282         ctx.update(&ctx, text_size, text);
283         ctx.digest(&ctx, ctx.length, digest);
284         
285         zeroize_temp_key(&ctx, sizeof(ctx));
286
287         return 0;
288 }
289
290 const gnutls_crypto_mac_st hmac_sha_x86_struct = {
291         .init = wrap_x86_hmac_init,
292         .setkey = wrap_x86_hmac_setkey,
293         .setnonce = NULL,
294         .hash = wrap_x86_hmac_update,
295         .output = wrap_x86_hmac_output,
296         .deinit = wrap_x86_hmac_deinit,
297         .fast = wrap_x86_hmac_fast,
298 };
299
300 #endif                          /* HAVE_LIBNETTLE */