Exported gnutls_cpuid() and gnutls_have_cpuid().
[gnutls:gnutls.git] / lib / accelerated / x86 / aes-padlock.c
1 /*
2  * Copyright (C) 2011 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
8  * The GnuTLS 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 3 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 /*
24  * The following code is an implementation of the AES-128-CBC cipher
25  * using VIA Padlock instruction set. 
26  */
27
28 #include <gnutls_errors.h>
29 #include <gnutls_int.h>
30 #include <gnutls/crypto.h>
31 #include <gnutls_errors.h>
32 #include <aes-x86.h>
33 #include <x86.h>
34 #ifdef HAVE_LIBNETTLE
35 #include <nettle/aes.h>         /* for key generation in 192 and 256 bits */
36 #include <sha-padlock.h>
37 #endif
38 #include <aes-padlock.h>
39
40 static int
41 aes_cipher_init (gnutls_cipher_algorithm_t algorithm, void **_ctx, int enc)
42 {
43   /* we use key size to distinguish */
44   if (algorithm != GNUTLS_CIPHER_AES_128_CBC
45       && algorithm != GNUTLS_CIPHER_AES_192_CBC
46       && algorithm != GNUTLS_CIPHER_AES_256_CBC)
47     return GNUTLS_E_INVALID_REQUEST;
48
49   *_ctx = gnutls_calloc (1, sizeof (struct padlock_ctx));
50   if (*_ctx == NULL)
51     {
52       gnutls_assert ();
53       return GNUTLS_E_MEMORY_ERROR;
54     }
55
56   ((struct padlock_ctx *) (*_ctx))->enc = enc;
57   return 0;
58 }
59
60 int
61 padlock_aes_cipher_setkey (void *_ctx, const void *userkey, size_t keysize)
62 {
63   struct padlock_ctx *ctx = _ctx;
64   struct padlock_cipher_data *pce;
65 #ifdef HAVE_LIBNETTLE
66   struct aes_ctx nc;
67 #endif
68
69   memset (_ctx, 0, sizeof (struct padlock_cipher_data));
70
71   pce = ALIGN16 (&ctx->expanded_key);
72
73   pce->cword.b.encdec = (ctx->enc == 0);
74
75   switch (keysize)
76     {
77     case 16:
78       pce->cword.b.ksize = 0;
79       pce->cword.b.rounds = 10;
80       memcpy (pce->ks.rd_key, userkey, 16);
81       pce->cword.b.keygen = 0;
82       break;
83 #ifdef HAVE_LIBNETTLE
84     case 24:
85       pce->cword.b.ksize = 1;
86       pce->cword.b.rounds = 12;
87       goto common_24_32;
88     case 32:
89       pce->cword.b.ksize = 2;
90       pce->cword.b.rounds = 14;
91     common_24_32:
92       /* expand key using nettle */
93       if (ctx->enc)
94         aes_set_encrypt_key (&nc, keysize, userkey);
95       else
96         aes_set_decrypt_key (&nc, keysize, userkey);
97
98       memcpy (pce->ks.rd_key, nc.keys, sizeof (nc.keys));
99       pce->ks.rounds = nc.nrounds;
100
101       pce->cword.b.keygen = 1;
102       break;
103 #endif
104     default:
105       return gnutls_assert_val (GNUTLS_E_ENCRYPTION_FAILED);
106     }
107
108   padlock_reload_key ();
109
110   return 0;
111 }
112
113 static int
114 aes_setiv (void *_ctx, const void *iv, size_t iv_size)
115 {
116   struct padlock_ctx *ctx = _ctx;
117   struct padlock_cipher_data *pce;
118
119   pce = ALIGN16 (&ctx->expanded_key);
120
121   memcpy (pce->iv, iv, 16);
122
123   return 0;
124 }
125
126 static int
127 padlock_aes_cbc_encrypt (void *_ctx, const void *src, size_t src_size,
128                          void *dst, size_t dst_size)
129 {
130   struct padlock_ctx *ctx = _ctx;
131   struct padlock_cipher_data *pce;
132
133   pce = ALIGN16 (&ctx->expanded_key);
134
135   padlock_cbc_encrypt (dst, src, pce, src_size);
136
137   return 0;
138 }
139
140
141 static int
142 padlock_aes_cbc_decrypt (void *_ctx, const void *src, size_t src_size,
143                          void *dst, size_t dst_size)
144 {
145   struct padlock_ctx *ctx = _ctx;
146   struct padlock_cipher_data *pcd;
147
148   pcd = ALIGN16 (&ctx->expanded_key);
149
150   padlock_cbc_encrypt (dst, src, pcd, src_size);
151
152   return 0;
153 }
154
155 static void
156 aes_deinit (void *_ctx)
157 {
158   gnutls_free (_ctx);
159 }
160
161 static const gnutls_crypto_cipher_st aes_padlock_struct = {
162   .init = aes_cipher_init,
163   .setkey = padlock_aes_cipher_setkey,
164   .setiv = aes_setiv,
165   .encrypt = padlock_aes_cbc_encrypt,
166   .decrypt = padlock_aes_cbc_decrypt,
167   .deinit = aes_deinit,
168 };
169
170 static int
171 check_padlock (void)
172 {
173   unsigned int edx = padlock_capability ();
174
175   return ((edx & (0x3 << 6)) == (0x3 << 6));
176 }
177
178 static int
179 check_phe (void)
180 {
181   unsigned int edx = padlock_capability ();
182
183   return ((edx & (0x3 << 10)) == (0x3 << 10));
184 }
185
186 /* We are actually checking for SHA512 */
187 static int
188 check_phe_sha512 (void)
189 {
190   unsigned int edx = padlock_capability ();
191
192   return ((edx & (0x3 << 25)) == (0x3 << 25));
193 }
194
195 static int
196 check_phe_partial (void)
197 {
198   const char* text = "test and test";
199   uint32_t iv[5] = { 0x67452301UL, 0xEFCDAB89UL,
200        0x98BADCFEUL, 0x10325476UL, 0xC3D2E1F0UL };
201
202   padlock_sha1_blocks (iv, text, sizeof(text)-1);
203   padlock_sha1_blocks (iv, text, sizeof(text)-1);
204
205   if (iv[0] == 0x9096E2D8UL && iv[1] == 0xA33074EEUL &&
206       iv[2] == 0xCDBEE447UL && iv[3] == 0xEC7979D2UL &&
207       iv[4] == 0x9D3FF5CFUL)
208       return 1;
209   else
210     return 0;
211 }
212
213 static unsigned
214 check_via (void)
215 {
216   unsigned int a, b, c, d;
217   gnutls_cpuid (0, &a, &b, &c, &d);
218
219   if ((memcmp (&b, "Cent", 4) == 0 &&
220        memcmp (&d, "aurH", 4) == 0 && memcmp (&c, "auls", 4) == 0))
221     {
222       return 1;
223     }
224
225   return 0;
226 }
227
228 void
229 register_padlock_crypto (void)
230 {
231   int ret, phe;
232
233   if (check_via () == 0)
234     return;
235   if (check_padlock ())
236     {
237       _gnutls_debug_log ("Padlock AES accelerator was detected\n");
238       ret =
239         gnutls_crypto_single_cipher_register
240         (GNUTLS_CIPHER_AES_128_CBC, 80, &aes_padlock_struct);
241       if (ret < 0)
242         {
243           gnutls_assert ();
244         }
245
246       /* register GCM ciphers */
247       ret =
248         gnutls_crypto_single_cipher_register
249         (GNUTLS_CIPHER_AES_128_GCM, 80, &aes_gcm_padlock_struct);
250       if (ret < 0)
251         {
252           gnutls_assert ();
253         }
254 #ifdef HAVE_LIBNETTLE
255       ret =
256         gnutls_crypto_single_cipher_register (GNUTLS_CIPHER_AES_192_CBC,
257                                               80, &aes_padlock_struct);
258       if (ret < 0)
259         {
260           gnutls_assert ();
261         }
262
263       ret =
264         gnutls_crypto_single_cipher_register (GNUTLS_CIPHER_AES_256_CBC,
265                                               80, &aes_padlock_struct);
266       if (ret < 0)
267         {
268           gnutls_assert ();
269         }
270
271       ret =
272         gnutls_crypto_single_cipher_register (GNUTLS_CIPHER_AES_256_GCM,
273                                               80, &aes_gcm_padlock_struct);
274       if (ret < 0)
275         {
276           gnutls_assert ();
277         }
278
279 #endif
280     }
281
282 #ifdef HAVE_LIBNETTLE
283   phe = check_phe ();
284
285   if (check_phe_partial () && phe)
286     {
287       _gnutls_debug_log ("Padlock SHA1 and SHA256 (partial) accelerator was detected\n");
288       if (check_phe_sha512 ())
289         {
290           _gnutls_debug_log ("Padlock SHA512 (partial) accelerator was detected\n");
291           ret =
292             gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA384,
293                                                   80,
294                                                   &sha_padlock_nano_struct);
295           if (ret < 0)
296             {
297               gnutls_assert ();
298             }
299
300           ret =
301             gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA512,
302                                                   80,
303                                                   &sha_padlock_nano_struct);
304           if (ret < 0)
305             {
306               gnutls_assert ();
307             }
308
309           ret =
310             gnutls_crypto_single_mac_register (GNUTLS_MAC_SHA384,
311                                                80,
312                                                &hmac_sha_padlock_nano_struct);
313           if (ret < 0)
314             {
315               gnutls_assert ();
316             }
317
318           ret =
319             gnutls_crypto_single_mac_register (GNUTLS_MAC_SHA512,
320                                                80,
321                                                &hmac_sha_padlock_nano_struct);
322           if (ret < 0)
323             {
324               gnutls_assert ();
325             }
326         }
327
328       ret =
329         gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA1,
330                                               80, &sha_padlock_nano_struct);
331       if (ret < 0)
332         {
333           gnutls_assert ();
334         }
335
336       ret =
337         gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA224,
338                                               80, &sha_padlock_nano_struct);
339       if (ret < 0)
340         {
341           gnutls_assert ();
342         }
343
344       ret =
345         gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA256,
346                                               80, &sha_padlock_nano_struct);
347       if (ret < 0)
348         {
349           gnutls_assert ();
350         }
351
352       ret =
353         gnutls_crypto_single_mac_register (GNUTLS_MAC_SHA1,
354                                            80, &hmac_sha_padlock_nano_struct);
355       if (ret < 0)
356         {
357           gnutls_assert ();
358         }
359
360       /* we don't register MAC_SHA224 because it is not used by TLS */
361
362       ret =
363         gnutls_crypto_single_mac_register (GNUTLS_MAC_SHA256,
364                                            80, &hmac_sha_padlock_nano_struct);
365       if (ret < 0)
366         {
367           gnutls_assert ();
368         }
369     }
370   else if (phe)
371     {
372       /* Original padlock PHE. Does not support incremental operations.
373        */
374       _gnutls_debug_log ("Padlock SHA1 and SHA256 accelerator was detected\n");
375       ret =
376         gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA1,
377                                               80, &sha_padlock_struct);
378       if (ret < 0)
379         {
380           gnutls_assert ();
381         }
382
383       ret =
384         gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA256,
385                                               80, &sha_padlock_struct);
386       if (ret < 0)
387         {
388           gnutls_assert ();
389         }
390
391       ret =
392         gnutls_crypto_single_mac_register (GNUTLS_MAC_SHA1,
393                                            80, &hmac_sha_padlock_struct);
394       if (ret < 0)
395         {
396           gnutls_assert ();
397         }
398
399       ret =
400         gnutls_crypto_single_mac_register (GNUTLS_MAC_SHA256,
401                                            80, &hmac_sha_padlock_struct);
402       if (ret < 0)
403         {
404           gnutls_assert ();
405         }
406     }
407 #endif
408
409   return;
410 }