19 #if defined(HAVE_POLY1305)
30 #define POLY1305_BLOCK_SIZE 16
31 #define POLY1305_PADDED_BLOCK_SIZE (POLY1305_BLOCK_SIZE + 1)
52 static void cx_le_bytes(
const uint8_t *buf,
uint8_t *le_buf,
size_t len)
55 for (i = 0; i < len; i++) {
56 le_buf[i] = buf[len - 1 - i];
60 static cx_err_t cx_poly1305_process(cx_poly1305_context_t *ctx,
67 cx_bn_t acc, r, p, d, res;
68 uint8_t buf[POLY1305_PADDED_BLOCK_SIZE];
71 CX_CHECK(cx_bn_lock(32, 0));
72 CX_CHECK(cx_bn_alloc_init(&p, 32, MODULUS,
sizeof(MODULUS)));
73 CX_CHECK(cx_bn_alloc(&acc, 32));
74 CX_CHECK(cx_bn_alloc(&r, 32));
75 CX_CHECK(cx_bn_alloc(&d, 32));
76 CX_CHECK(cx_bn_alloc(&res, 64));
79 for (i = 0; i < nblocks; i++) {
81 buf[0] = needs_padding;
82 cx_le_bytes(input + offset, buf + 1, POLY1305_BLOCK_SIZE);
83 CX_CHECK(cx_bn_init(d, buf, POLY1305_PADDED_BLOCK_SIZE));
86 U4BE_ENCODE(buf, 1, ctx->acc[3]);
87 U4BE_ENCODE(buf + 4 + 1, 0, ctx->acc[2]);
88 U4BE_ENCODE(buf + 8 + 1, 0, ctx->acc[1]);
89 U4BE_ENCODE(buf + 12 + 1, 0, ctx->acc[0]);
90 CX_CHECK(cx_bn_init(acc, buf,
sizeof(buf)));
93 CX_CHECK(cx_bn_add(acc, acc, d));
95 U4BE_ENCODE(buf, 0, ctx->r[3]);
96 U4BE_ENCODE(buf + 4, 0, ctx->r[2]);
97 U4BE_ENCODE(buf + 8, 0, ctx->r[1]);
98 U4BE_ENCODE(buf + 12, 0, ctx->r[0]);
99 CX_CHECK(cx_bn_init(r, buf, POLY1305_BLOCK_SIZE));
102 CX_CHECK(cx_bn_mul(res, acc, r));
105 CX_CHECK(cx_bn_reduce(acc, res, p));
107 CX_CHECK(cx_bn_export(acc, buf,
sizeof(MODULUS)));
108 ctx->acc[0] = U4BE(buf, 12 + 1);
109 ctx->acc[1] = U4BE(buf, 8 + 1);
110 ctx->acc[2] = U4BE(buf, 4 + 1);
111 ctx->acc[3] = U4BE(buf, 1);
112 ctx->acc[4] = buf[0];
114 offset += POLY1305_BLOCK_SIZE;
122 static cx_err_t cx_poly1305_compute_mac(cx_poly1305_context_t *ctx,
uint8_t *tag)
126 uint8_t buf[POLY1305_PADDED_BLOCK_SIZE];
128 CX_CHECK(cx_bn_lock(32, 0));
129 CX_CHECK(cx_bn_alloc(&acc, 32));
130 CX_CHECK(cx_bn_alloc(&s, 32));
132 buf[0] = (
uint8_t) ctx->acc[4];
133 U4BE_ENCODE(buf, 1, ctx->acc[3]);
134 U4BE_ENCODE(buf + 4 + 1, 0, ctx->acc[2]);
135 U4BE_ENCODE(buf + 8 + 1, 0, ctx->acc[1]);
136 U4BE_ENCODE(buf + 12 + 1, 0, ctx->acc[0]);
137 CX_CHECK(cx_bn_init(acc, buf,
sizeof(buf)));
139 U4BE_ENCODE(buf, 0, ctx->s[3]);
140 U4BE_ENCODE(buf + 4, 0, ctx->s[2]);
141 U4BE_ENCODE(buf + 8, 0, ctx->s[1]);
142 U4BE_ENCODE(buf + 12, 0, ctx->s[0]);
143 CX_CHECK(cx_bn_init(s, buf, POLY1305_BLOCK_SIZE));
146 CX_CHECK(cx_bn_add(acc, acc, s));
149 CX_CHECK(cx_bn_export(acc, buf,
sizeof(MODULUS)));
150 cx_le_bytes(buf + 1, tag, POLY1305_BLOCK_SIZE);
157 void cx_poly1305_init(cx_poly1305_context_t *ctx)
159 memset(ctx, 0,
sizeof(cx_poly1305_context_t));
162 void cx_poly1305_set_key(cx_poly1305_context_t *ctx,
const uint8_t *key)
165 ctx->r[0] = U4LE(key, 0) & 0x0FFFFFFF;
166 ctx->r[1] = U4LE(key, 4) & 0x0FFFFFFC;
167 ctx->r[2] = U4LE(key, 8) & 0x0FFFFFFC;
168 ctx->r[3] = U4LE(key, 12) & 0x0FFFFFFC;
169 ctx->s[0] = U4LE(key, 16);
170 ctx->s[1] = U4LE(key, 20);
171 ctx->s[2] = U4LE(key, 24);
172 ctx->s[3] = U4LE(key, 28);
179 memset(ctx->block, 0,
sizeof(ctx->block));
183 cx_err_t cx_poly1305_update(cx_poly1305_context_t *ctx,
const uint8_t *input,
size_t in_len)
186 size_t remaining = in_len;
187 cx_err_t error = CX_OK;
190 if ((remaining > 0) && (ctx->block_len > 0)) {
191 n = POLY1305_BLOCK_SIZE - ctx->block_len;
196 memcpy(&ctx->block[ctx->block_len], input, in_len);
197 ctx->block_len += in_len;
202 memcpy(&ctx->block[ctx->block_len], input, n);
204 CX_CHECK(cx_poly1305_process(ctx, 1, ctx->block, 1));
210 if (remaining >= POLY1305_BLOCK_SIZE) {
211 n = remaining / POLY1305_BLOCK_SIZE;
212 CX_CHECK(cx_poly1305_process(ctx, n, &input[offset], 1));
213 offset += n * POLY1305_BLOCK_SIZE;
214 remaining %= POLY1305_BLOCK_SIZE;
219 ctx->block_len = remaining;
220 memcpy(ctx->block, &input[offset], remaining);
227 cx_err_t cx_poly1305_finish(cx_poly1305_context_t *ctx,
uint8_t *tag)
232 if (ctx->block_len > 0) {
234 ctx->block[ctx->block_len] = 1;
237 memset(&ctx->block[ctx->block_len], 0, POLY1305_BLOCK_SIZE - ctx->block_len);
238 CX_CHECK(cx_poly1305_process(ctx, 1, ctx->block, 0));
240 CX_CHECK(cx_poly1305_compute_mac(ctx, tag));
249 cx_poly1305_context_t *ctx = &
G_cx.poly1305;
250 cx_poly1305_init(ctx);
251 cx_poly1305_set_key(ctx, key);
252 CX_CHECK(cx_poly1305_update(ctx, input, in_len));
253 CX_CHECK(cx_poly1305_finish(ctx, tag));
256 explicit_bzero(ctx,
sizeof(cx_poly1305_context_t));