lib:crypto: Include only the required header files
[gd/samba-autobuild/.git] / lib / crypto / aes_ccm_128.c
1 /*
2    AES-CCM-128 (rfc 3610)
3
4    Copyright (C) Stefan Metzmacher 2012
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "replace.h"
21 #include "lib/crypto/aes.h"
22 #include "lib/crypto/aes_ccm_128.h"
23 #include "lib/util/byteorder.h"
24
25 #define M_ ((AES_CCM_128_M - 2) / 2)
26 #define L_ (AES_CCM_128_L - 1)
27
28 void aes_ccm_128_init(struct aes_ccm_128_context *ctx,
29                       const uint8_t K[AES_BLOCK_SIZE],
30                       const uint8_t N[AES_CCM_128_NONCE_SIZE],
31                       size_t a_total, size_t m_total)
32 {
33         ZERO_STRUCTP(ctx);
34
35         AES_set_encrypt_key(K, 128, &ctx->aes_key);
36         memcpy(ctx->nonce, N, AES_CCM_128_NONCE_SIZE);
37         ctx->a_remain = a_total;
38         ctx->m_remain = m_total;
39
40         /*
41          * prepare B_0
42          */
43         ctx->B_i[0]  = L_;
44         ctx->B_i[0] += 8 * M_;
45         if (a_total > 0) {
46                 ctx->B_i[0] += 64;
47         }
48         memcpy(&ctx->B_i[1], ctx->nonce, AES_CCM_128_NONCE_SIZE);
49         RSIVAL(ctx->B_i, (AES_BLOCK_SIZE - AES_CCM_128_L), m_total);
50
51         /*
52          * prepare X_1
53          */
54         AES_encrypt(ctx->B_i, ctx->X_i, &ctx->aes_key);
55
56         /*
57          * prepare B_1
58          */
59         ZERO_STRUCT(ctx->B_i);
60         if (a_total >= UINT32_MAX) {
61                 RSSVAL(ctx->B_i, 0, 0xFFFF);
62                 RSBVAL(ctx->B_i, 2, (uint64_t)a_total);
63                 ctx->B_i_ofs = 10;
64         } else if (a_total >= 0xFF00) {
65                 RSSVAL(ctx->B_i, 0, 0xFFFE);
66                 RSIVAL(ctx->B_i, 2, a_total);
67                 ctx->B_i_ofs = 6;
68         } else if (a_total > 0) {
69                 RSSVAL(ctx->B_i, 0, a_total);
70                 ctx->B_i_ofs = 2;
71         }
72
73         /*
74          * prepare A_i
75          */
76         ctx->A_i[0]  = L_;
77         memcpy(&ctx->A_i[1], ctx->nonce, AES_CCM_128_NONCE_SIZE);
78
79         ctx->S_i_ofs = AES_BLOCK_SIZE;
80 }
81
82 void aes_ccm_128_update(struct aes_ccm_128_context *ctx,
83                         const uint8_t *v, size_t v_len)
84 {
85         size_t *remain;
86
87         if (v_len == 0) {
88                 return;
89         }
90
91         if (ctx->a_remain > 0) {
92                 remain = &ctx->a_remain;
93         } else {
94                 remain = &ctx->m_remain;
95         }
96
97         if (unlikely(v_len > *remain)) {
98                 abort();
99         }
100
101         if (ctx->B_i_ofs > 0) {
102                 size_t n = MIN(AES_BLOCK_SIZE - ctx->B_i_ofs, v_len);
103
104                 memcpy(&ctx->B_i[ctx->B_i_ofs], v, n);
105                 v += n;
106                 v_len -= n;
107                 ctx->B_i_ofs += n;
108                 *remain -= n;
109         }
110
111         if ((ctx->B_i_ofs == AES_BLOCK_SIZE) || (*remain == 0)) {
112                 aes_block_xor(ctx->X_i, ctx->B_i, ctx->B_i);
113                 AES_encrypt(ctx->B_i, ctx->X_i, &ctx->aes_key);
114                 ctx->B_i_ofs = 0;
115         }
116
117         while (v_len >= AES_BLOCK_SIZE) {
118                 aes_block_xor(ctx->X_i, v, ctx->B_i);
119                 AES_encrypt(ctx->B_i, ctx->X_i, &ctx->aes_key);
120                 v += AES_BLOCK_SIZE;
121                 v_len -= AES_BLOCK_SIZE;
122                 *remain -= AES_BLOCK_SIZE;
123         }
124
125         if (v_len > 0) {
126                 ZERO_STRUCT(ctx->B_i);
127                 memcpy(ctx->B_i, v, v_len);
128                 ctx->B_i_ofs += v_len;
129                 *remain -= v_len;
130                 v = NULL;
131                 v_len = 0;
132         }
133
134         if (*remain > 0) {
135                 return;
136         }
137
138         if (ctx->B_i_ofs > 0) {
139                 aes_block_xor(ctx->X_i, ctx->B_i, ctx->B_i);
140                 AES_encrypt(ctx->B_i, ctx->X_i, &ctx->aes_key);
141                 ctx->B_i_ofs = 0;
142         }
143 }
144
145 static inline void aes_ccm_128_S_i(struct aes_ccm_128_context *ctx,
146                                    uint8_t S_i[AES_BLOCK_SIZE],
147                                    size_t i)
148 {
149         RSIVAL(ctx->A_i, (AES_BLOCK_SIZE - AES_CCM_128_L), i);
150         AES_encrypt(ctx->A_i, S_i, &ctx->aes_key);
151 }
152
153 void aes_ccm_128_crypt(struct aes_ccm_128_context *ctx,
154                        uint8_t *m, size_t m_len)
155 {
156         while (m_len > 0) {
157                 if (ctx->S_i_ofs == AES_BLOCK_SIZE) {
158                         ctx->S_i_ctr += 1;
159                         aes_ccm_128_S_i(ctx, ctx->S_i, ctx->S_i_ctr);
160                         ctx->S_i_ofs = 0;
161                 }
162
163                 if (likely(ctx->S_i_ofs == 0 && m_len >= AES_BLOCK_SIZE)) {
164                         aes_block_xor(m, ctx->S_i, m);
165                         m += AES_BLOCK_SIZE;
166                         m_len -= AES_BLOCK_SIZE;
167                         ctx->S_i_ctr += 1;
168                         aes_ccm_128_S_i(ctx, ctx->S_i, ctx->S_i_ctr);
169                         continue;
170                 }
171
172                 m[0] ^= ctx->S_i[ctx->S_i_ofs];
173                 m += 1;
174                 m_len -= 1;
175                 ctx->S_i_ofs += 1;
176         }
177 }
178
179 void aes_ccm_128_digest(struct aes_ccm_128_context *ctx,
180                         uint8_t digest[AES_BLOCK_SIZE])
181 {
182         if (unlikely(ctx->a_remain != 0)) {
183                 abort();
184         }
185         if (unlikely(ctx->m_remain != 0)) {
186                 abort();
187         }
188
189         /* prepare S_0 */
190         aes_ccm_128_S_i(ctx, ctx->S_i, 0);
191
192         /*
193          * note X_i is T here
194          */
195         aes_block_xor(ctx->X_i, ctx->S_i, digest);
196
197         ZERO_STRUCTP(ctx);
198 }