doc: Fix typo.
[libgcrypt.git] / cipher / rijndael-padlock.c
1 /* Padlock accelerated AES for Libgcrypt
2  * Copyright (C) 2000, 2001, 2002, 2003, 2007,
3  *               2008, 2011, 2012 Free Software Foundation, Inc.
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h> /* for memcmp() */
25
26 #include "types.h"  /* for byte and u32 typedefs */
27 #include "g10lib.h"
28 #include "cipher.h"
29 #include "bufhelp.h"
30 #include "cipher-selftest.h"
31 #include "rijndael-internal.h"
32
33 #ifdef USE_PADLOCK
34
35 /* Encrypt or decrypt one block using the padlock engine.  A and B may
36    be the same. */
37 static unsigned int
38 do_padlock (const RIJNDAEL_context *ctx, unsigned char *bx,
39             const unsigned char *ax, int decrypt_flag)
40 {
41   /* BX and AX are not necessary correctly aligned.  Thus we need to
42      copy them here. */
43   unsigned char a[16] __attribute__ ((aligned (16)));
44   unsigned char b[16] __attribute__ ((aligned (16)));
45   unsigned int cword[4] __attribute__ ((aligned (16)));
46   int blocks;
47
48   /* The control word fields are:
49       127:12   11:10 9     8     7     6     5     4     3:0
50       RESERVED KSIZE CRYPT INTER KEYGN CIPHR ALIGN DGEST ROUND  */
51   cword[0] = (ctx->rounds & 15);  /* (The mask is just a safeguard.)  */
52   cword[1] = 0;
53   cword[2] = 0;
54   cword[3] = 0;
55   if (decrypt_flag)
56     cword[0] |= 0x00000200;
57
58   memcpy (a, ax, 16);
59
60   blocks = 1; /* Init counter for just one block.  */
61 #ifdef __x86_64__
62   asm volatile
63     ("pushfq\n\t"          /* Force key reload.  */
64      "popfq\n\t"
65      ".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t" /* REP XCRYPT ECB. */
66      : /* No output */
67      : "S" (a), "D" (b), "d" (cword), "b" (ctx->padlockkey), "c" (blocks)
68      : "cc", "memory"
69      );
70 #else
71   asm volatile
72     ("pushfl\n\t"          /* Force key reload.  */
73      "popfl\n\t"
74      "xchg %3, %%ebx\n\t"  /* Load key.  */
75      ".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t" /* REP XCRYPT ECB. */
76      "xchg %3, %%ebx\n"    /* Restore GOT register.  */
77      : /* No output */
78      : "S" (a), "D" (b), "d" (cword), "r" (ctx->padlockkey), "c" (blocks)
79      : "cc", "memory"
80      );
81 #endif
82
83   memcpy (bx, b, 16);
84
85   return (48 + 15 /* possible padding for alignment */);
86 }
87
88 unsigned int
89 _gcry_aes_padlock_encrypt (const RIJNDAEL_context *ctx,
90                            unsigned char *bx, const unsigned char *ax)
91 {
92   return do_padlock(ctx, bx, ax, 0);
93 }
94
95 unsigned int
96 _gcry_aes_padlock_decrypt (const RIJNDAEL_context *ctx,
97                            unsigned char *bx, const unsigned char *ax)
98 {
99   return do_padlock(ctx, bx, ax, 1);
100 }
101
102 #endif /* USE_PADLOCK */