lib/crypto: Detect CommonCrypto and use it if available
[samba.git] / lib / crypto / aes.c
1 /*
2  * Copyright (c) 2003 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #include "replace.h"
35
36 #include "rijndael-alg-fst.h"
37 #include "aes.h"
38
39 int
40 AES_set_encrypt_key(const unsigned char *userkey, const int bits, AES_KEY *key)
41 {
42     key->rounds = rijndaelKeySetupEnc(key->key, userkey, bits);
43     if (key->rounds == 0)
44         return -1;
45     return 0;
46 }
47
48 int
49 AES_set_decrypt_key(const unsigned char *userkey, const int bits, AES_KEY *key)
50 {
51     key->rounds = rijndaelKeySetupDec(key->key, userkey, bits);
52     if (key->rounds == 0)
53         return -1;
54     return 0;
55 }
56
57 void
58 AES_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key)
59 {
60     rijndaelEncrypt(key->key, key->rounds, in, out);
61 }
62
63 void
64 AES_decrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key)
65 {
66     rijndaelDecrypt(key->key, key->rounds, in, out);
67 }
68
69 void
70 AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
71                 unsigned long size, const AES_KEY *key,
72                 unsigned char *iv, int forward_encrypt)
73 {
74     unsigned char tmp[AES_BLOCK_SIZE];
75     int i;
76
77     if (forward_encrypt) {
78         while (size >= AES_BLOCK_SIZE) {
79             for (i = 0; i < AES_BLOCK_SIZE; i++)
80                 tmp[i] = in[i] ^ iv[i];
81             AES_encrypt(tmp, out, key);
82             memcpy(iv, out, AES_BLOCK_SIZE);
83             size -= AES_BLOCK_SIZE;
84             in += AES_BLOCK_SIZE;
85             out += AES_BLOCK_SIZE;
86         }
87         if (size) {
88             for (i = 0; i < size; i++)
89                 tmp[i] = in[i] ^ iv[i];
90             for (i = size; i < AES_BLOCK_SIZE; i++)
91                 tmp[i] = iv[i];
92             AES_encrypt(tmp, out, key);
93             memcpy(iv, out, AES_BLOCK_SIZE);
94         }
95     } else {
96         while (size >= AES_BLOCK_SIZE) {
97             memcpy(tmp, in, AES_BLOCK_SIZE);
98             AES_decrypt(tmp, out, key);
99             for (i = 0; i < AES_BLOCK_SIZE; i++)
100                 out[i] ^= iv[i];
101             memcpy(iv, tmp, AES_BLOCK_SIZE);
102             size -= AES_BLOCK_SIZE;
103             in += AES_BLOCK_SIZE;
104             out += AES_BLOCK_SIZE;
105         }
106         if (size) {
107             memcpy(tmp, in, AES_BLOCK_SIZE);
108             AES_decrypt(tmp, out, key);
109             for (i = 0; i < size; i++)
110                 out[i] ^= iv[i];
111             memcpy(iv, tmp, AES_BLOCK_SIZE);
112         }
113     }
114 }
115
116 void aes_cfb8_encrypt(const uint8_t *in, uint8_t *out,
117                       size_t length, const AES_KEY *key,
118                       uint8_t *iv, int forward)
119 {
120         size_t i;
121
122         for (i=0; i < length; i++) {
123                 uint8_t tiv[AES_BLOCK_SIZE*2];
124
125                 memcpy(tiv, iv, AES_BLOCK_SIZE);
126                 AES_encrypt(iv, iv, key);
127                 if (!forward) {
128                         tiv[AES_BLOCK_SIZE] = in[i];
129                 }
130                 out[i] = in[i] ^ iv[0];
131                 if (forward) {
132                         tiv[AES_BLOCK_SIZE] = out[i];
133                 }
134                 memcpy(iv, tiv+1, AES_BLOCK_SIZE);
135         }
136 }