1a8e1175bSopenharmony_ci/** 2a8e1175bSopenharmony_ci * \file poly1305.c 3a8e1175bSopenharmony_ci * 4a8e1175bSopenharmony_ci * \brief Poly1305 authentication algorithm. 5a8e1175bSopenharmony_ci * 6a8e1175bSopenharmony_ci * Copyright The Mbed TLS Contributors 7a8e1175bSopenharmony_ci * SPDX-License-Identifier: Apache-2.0 8a8e1175bSopenharmony_ci * 9a8e1175bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); you may 10a8e1175bSopenharmony_ci * not use this file except in compliance with the License. 11a8e1175bSopenharmony_ci * You may obtain a copy of the License at 12a8e1175bSopenharmony_ci * 13a8e1175bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 14a8e1175bSopenharmony_ci * 15a8e1175bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 16a8e1175bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 17a8e1175bSopenharmony_ci * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18a8e1175bSopenharmony_ci * See the License for the specific language governing permissions and 19a8e1175bSopenharmony_ci * limitations under the License. 20a8e1175bSopenharmony_ci */ 21a8e1175bSopenharmony_ci#include "common.h" 22a8e1175bSopenharmony_ci 23a8e1175bSopenharmony_ci#if defined(MBEDTLS_POLY1305_C) 24a8e1175bSopenharmony_ci 25a8e1175bSopenharmony_ci#include "mbedtls/poly1305.h" 26a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h" 27a8e1175bSopenharmony_ci#include "mbedtls/error.h" 28a8e1175bSopenharmony_ci 29a8e1175bSopenharmony_ci#include <string.h> 30a8e1175bSopenharmony_ci 31a8e1175bSopenharmony_ci#include "mbedtls/platform.h" 32a8e1175bSopenharmony_ci 33a8e1175bSopenharmony_ci#if !defined(MBEDTLS_POLY1305_ALT) 34a8e1175bSopenharmony_ci 35a8e1175bSopenharmony_ci#define POLY1305_BLOCK_SIZE_BYTES (16U) 36a8e1175bSopenharmony_ci 37a8e1175bSopenharmony_ci/* 38a8e1175bSopenharmony_ci * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier. 39a8e1175bSopenharmony_ci * However we provided an alternative for platforms without such a multiplier. 40a8e1175bSopenharmony_ci */ 41a8e1175bSopenharmony_ci#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) 42a8e1175bSopenharmony_cistatic uint64_t mul64(uint32_t a, uint32_t b) 43a8e1175bSopenharmony_ci{ 44a8e1175bSopenharmony_ci /* a = al + 2**16 ah, b = bl + 2**16 bh */ 45a8e1175bSopenharmony_ci const uint16_t al = (uint16_t) a; 46a8e1175bSopenharmony_ci const uint16_t bl = (uint16_t) b; 47a8e1175bSopenharmony_ci const uint16_t ah = a >> 16; 48a8e1175bSopenharmony_ci const uint16_t bh = b >> 16; 49a8e1175bSopenharmony_ci 50a8e1175bSopenharmony_ci /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */ 51a8e1175bSopenharmony_ci const uint32_t lo = (uint32_t) al * bl; 52a8e1175bSopenharmony_ci const uint64_t me = (uint64_t) ((uint32_t) ah * bl) + (uint32_t) al * bh; 53a8e1175bSopenharmony_ci const uint32_t hi = (uint32_t) ah * bh; 54a8e1175bSopenharmony_ci 55a8e1175bSopenharmony_ci return lo + (me << 16) + ((uint64_t) hi << 32); 56a8e1175bSopenharmony_ci} 57a8e1175bSopenharmony_ci#else 58a8e1175bSopenharmony_cistatic inline uint64_t mul64(uint32_t a, uint32_t b) 59a8e1175bSopenharmony_ci{ 60a8e1175bSopenharmony_ci return (uint64_t) a * b; 61a8e1175bSopenharmony_ci} 62a8e1175bSopenharmony_ci#endif 63a8e1175bSopenharmony_ci 64a8e1175bSopenharmony_ci 65a8e1175bSopenharmony_ci/** 66a8e1175bSopenharmony_ci * \brief Process blocks with Poly1305. 67a8e1175bSopenharmony_ci * 68a8e1175bSopenharmony_ci * \param ctx The Poly1305 context. 69a8e1175bSopenharmony_ci * \param nblocks Number of blocks to process. Note that this 70a8e1175bSopenharmony_ci * function only processes full blocks. 71a8e1175bSopenharmony_ci * \param input Buffer containing the input block(s). 72a8e1175bSopenharmony_ci * \param needs_padding Set to 0 if the padding bit has already been 73a8e1175bSopenharmony_ci * applied to the input data before calling this 74a8e1175bSopenharmony_ci * function. Otherwise, set this parameter to 1. 75a8e1175bSopenharmony_ci */ 76a8e1175bSopenharmony_cistatic void poly1305_process(mbedtls_poly1305_context *ctx, 77a8e1175bSopenharmony_ci size_t nblocks, 78a8e1175bSopenharmony_ci const unsigned char *input, 79a8e1175bSopenharmony_ci uint32_t needs_padding) 80a8e1175bSopenharmony_ci{ 81a8e1175bSopenharmony_ci uint64_t d0, d1, d2, d3; 82a8e1175bSopenharmony_ci uint32_t acc0, acc1, acc2, acc3, acc4; 83a8e1175bSopenharmony_ci uint32_t r0, r1, r2, r3; 84a8e1175bSopenharmony_ci uint32_t rs1, rs2, rs3; 85a8e1175bSopenharmony_ci size_t offset = 0U; 86a8e1175bSopenharmony_ci size_t i; 87a8e1175bSopenharmony_ci 88a8e1175bSopenharmony_ci r0 = ctx->r[0]; 89a8e1175bSopenharmony_ci r1 = ctx->r[1]; 90a8e1175bSopenharmony_ci r2 = ctx->r[2]; 91a8e1175bSopenharmony_ci r3 = ctx->r[3]; 92a8e1175bSopenharmony_ci 93a8e1175bSopenharmony_ci rs1 = r1 + (r1 >> 2U); 94a8e1175bSopenharmony_ci rs2 = r2 + (r2 >> 2U); 95a8e1175bSopenharmony_ci rs3 = r3 + (r3 >> 2U); 96a8e1175bSopenharmony_ci 97a8e1175bSopenharmony_ci acc0 = ctx->acc[0]; 98a8e1175bSopenharmony_ci acc1 = ctx->acc[1]; 99a8e1175bSopenharmony_ci acc2 = ctx->acc[2]; 100a8e1175bSopenharmony_ci acc3 = ctx->acc[3]; 101a8e1175bSopenharmony_ci acc4 = ctx->acc[4]; 102a8e1175bSopenharmony_ci 103a8e1175bSopenharmony_ci /* Process full blocks */ 104a8e1175bSopenharmony_ci for (i = 0U; i < nblocks; i++) { 105a8e1175bSopenharmony_ci /* The input block is treated as a 128-bit little-endian integer */ 106a8e1175bSopenharmony_ci d0 = MBEDTLS_GET_UINT32_LE(input, offset + 0); 107a8e1175bSopenharmony_ci d1 = MBEDTLS_GET_UINT32_LE(input, offset + 4); 108a8e1175bSopenharmony_ci d2 = MBEDTLS_GET_UINT32_LE(input, offset + 8); 109a8e1175bSopenharmony_ci d3 = MBEDTLS_GET_UINT32_LE(input, offset + 12); 110a8e1175bSopenharmony_ci 111a8e1175bSopenharmony_ci /* Compute: acc += (padded) block as a 130-bit integer */ 112a8e1175bSopenharmony_ci d0 += (uint64_t) acc0; 113a8e1175bSopenharmony_ci d1 += (uint64_t) acc1 + (d0 >> 32U); 114a8e1175bSopenharmony_ci d2 += (uint64_t) acc2 + (d1 >> 32U); 115a8e1175bSopenharmony_ci d3 += (uint64_t) acc3 + (d2 >> 32U); 116a8e1175bSopenharmony_ci acc0 = (uint32_t) d0; 117a8e1175bSopenharmony_ci acc1 = (uint32_t) d1; 118a8e1175bSopenharmony_ci acc2 = (uint32_t) d2; 119a8e1175bSopenharmony_ci acc3 = (uint32_t) d3; 120a8e1175bSopenharmony_ci acc4 += (uint32_t) (d3 >> 32U) + needs_padding; 121a8e1175bSopenharmony_ci 122a8e1175bSopenharmony_ci /* Compute: acc *= r */ 123a8e1175bSopenharmony_ci d0 = mul64(acc0, r0) + 124a8e1175bSopenharmony_ci mul64(acc1, rs3) + 125a8e1175bSopenharmony_ci mul64(acc2, rs2) + 126a8e1175bSopenharmony_ci mul64(acc3, rs1); 127a8e1175bSopenharmony_ci d1 = mul64(acc0, r1) + 128a8e1175bSopenharmony_ci mul64(acc1, r0) + 129a8e1175bSopenharmony_ci mul64(acc2, rs3) + 130a8e1175bSopenharmony_ci mul64(acc3, rs2) + 131a8e1175bSopenharmony_ci mul64(acc4, rs1); 132a8e1175bSopenharmony_ci d2 = mul64(acc0, r2) + 133a8e1175bSopenharmony_ci mul64(acc1, r1) + 134a8e1175bSopenharmony_ci mul64(acc2, r0) + 135a8e1175bSopenharmony_ci mul64(acc3, rs3) + 136a8e1175bSopenharmony_ci mul64(acc4, rs2); 137a8e1175bSopenharmony_ci d3 = mul64(acc0, r3) + 138a8e1175bSopenharmony_ci mul64(acc1, r2) + 139a8e1175bSopenharmony_ci mul64(acc2, r1) + 140a8e1175bSopenharmony_ci mul64(acc3, r0) + 141a8e1175bSopenharmony_ci mul64(acc4, rs3); 142a8e1175bSopenharmony_ci acc4 *= r0; 143a8e1175bSopenharmony_ci 144a8e1175bSopenharmony_ci /* Compute: acc %= (2^130 - 5) (partial remainder) */ 145a8e1175bSopenharmony_ci d1 += (d0 >> 32); 146a8e1175bSopenharmony_ci d2 += (d1 >> 32); 147a8e1175bSopenharmony_ci d3 += (d2 >> 32); 148a8e1175bSopenharmony_ci acc0 = (uint32_t) d0; 149a8e1175bSopenharmony_ci acc1 = (uint32_t) d1; 150a8e1175bSopenharmony_ci acc2 = (uint32_t) d2; 151a8e1175bSopenharmony_ci acc3 = (uint32_t) d3; 152a8e1175bSopenharmony_ci acc4 = (uint32_t) (d3 >> 32) + acc4; 153a8e1175bSopenharmony_ci 154a8e1175bSopenharmony_ci d0 = (uint64_t) acc0 + (acc4 >> 2) + (acc4 & 0xFFFFFFFCU); 155a8e1175bSopenharmony_ci acc4 &= 3U; 156a8e1175bSopenharmony_ci acc0 = (uint32_t) d0; 157a8e1175bSopenharmony_ci d0 = (uint64_t) acc1 + (d0 >> 32U); 158a8e1175bSopenharmony_ci acc1 = (uint32_t) d0; 159a8e1175bSopenharmony_ci d0 = (uint64_t) acc2 + (d0 >> 32U); 160a8e1175bSopenharmony_ci acc2 = (uint32_t) d0; 161a8e1175bSopenharmony_ci d0 = (uint64_t) acc3 + (d0 >> 32U); 162a8e1175bSopenharmony_ci acc3 = (uint32_t) d0; 163a8e1175bSopenharmony_ci d0 = (uint64_t) acc4 + (d0 >> 32U); 164a8e1175bSopenharmony_ci acc4 = (uint32_t) d0; 165a8e1175bSopenharmony_ci 166a8e1175bSopenharmony_ci offset += POLY1305_BLOCK_SIZE_BYTES; 167a8e1175bSopenharmony_ci } 168a8e1175bSopenharmony_ci 169a8e1175bSopenharmony_ci ctx->acc[0] = acc0; 170a8e1175bSopenharmony_ci ctx->acc[1] = acc1; 171a8e1175bSopenharmony_ci ctx->acc[2] = acc2; 172a8e1175bSopenharmony_ci ctx->acc[3] = acc3; 173a8e1175bSopenharmony_ci ctx->acc[4] = acc4; 174a8e1175bSopenharmony_ci} 175a8e1175bSopenharmony_ci 176a8e1175bSopenharmony_ci/** 177a8e1175bSopenharmony_ci * \brief Compute the Poly1305 MAC 178a8e1175bSopenharmony_ci * 179a8e1175bSopenharmony_ci * \param ctx The Poly1305 context. 180a8e1175bSopenharmony_ci * \param mac The buffer to where the MAC is written. Must be 181a8e1175bSopenharmony_ci * big enough to contain the 16-byte MAC. 182a8e1175bSopenharmony_ci */ 183a8e1175bSopenharmony_cistatic void poly1305_compute_mac(const mbedtls_poly1305_context *ctx, 184a8e1175bSopenharmony_ci unsigned char mac[16]) 185a8e1175bSopenharmony_ci{ 186a8e1175bSopenharmony_ci uint64_t d; 187a8e1175bSopenharmony_ci uint32_t g0, g1, g2, g3, g4; 188a8e1175bSopenharmony_ci uint32_t acc0, acc1, acc2, acc3, acc4; 189a8e1175bSopenharmony_ci uint32_t mask; 190a8e1175bSopenharmony_ci uint32_t mask_inv; 191a8e1175bSopenharmony_ci 192a8e1175bSopenharmony_ci acc0 = ctx->acc[0]; 193a8e1175bSopenharmony_ci acc1 = ctx->acc[1]; 194a8e1175bSopenharmony_ci acc2 = ctx->acc[2]; 195a8e1175bSopenharmony_ci acc3 = ctx->acc[3]; 196a8e1175bSopenharmony_ci acc4 = ctx->acc[4]; 197a8e1175bSopenharmony_ci 198a8e1175bSopenharmony_ci /* Before adding 's' we ensure that the accumulator is mod 2^130 - 5. 199a8e1175bSopenharmony_ci * We do this by calculating acc - (2^130 - 5), then checking if 200a8e1175bSopenharmony_ci * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5) 201a8e1175bSopenharmony_ci */ 202a8e1175bSopenharmony_ci 203a8e1175bSopenharmony_ci /* Calculate acc + -(2^130 - 5) */ 204a8e1175bSopenharmony_ci d = ((uint64_t) acc0 + 5U); 205a8e1175bSopenharmony_ci g0 = (uint32_t) d; 206a8e1175bSopenharmony_ci d = ((uint64_t) acc1 + (d >> 32)); 207a8e1175bSopenharmony_ci g1 = (uint32_t) d; 208a8e1175bSopenharmony_ci d = ((uint64_t) acc2 + (d >> 32)); 209a8e1175bSopenharmony_ci g2 = (uint32_t) d; 210a8e1175bSopenharmony_ci d = ((uint64_t) acc3 + (d >> 32)); 211a8e1175bSopenharmony_ci g3 = (uint32_t) d; 212a8e1175bSopenharmony_ci g4 = acc4 + (uint32_t) (d >> 32U); 213a8e1175bSopenharmony_ci 214a8e1175bSopenharmony_ci /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */ 215a8e1175bSopenharmony_ci mask = (uint32_t) 0U - (g4 >> 2U); 216a8e1175bSopenharmony_ci mask_inv = ~mask; 217a8e1175bSopenharmony_ci 218a8e1175bSopenharmony_ci /* If 131st bit is set then acc=g, otherwise, acc is unmodified */ 219a8e1175bSopenharmony_ci acc0 = (acc0 & mask_inv) | (g0 & mask); 220a8e1175bSopenharmony_ci acc1 = (acc1 & mask_inv) | (g1 & mask); 221a8e1175bSopenharmony_ci acc2 = (acc2 & mask_inv) | (g2 & mask); 222a8e1175bSopenharmony_ci acc3 = (acc3 & mask_inv) | (g3 & mask); 223a8e1175bSopenharmony_ci 224a8e1175bSopenharmony_ci /* Add 's' */ 225a8e1175bSopenharmony_ci d = (uint64_t) acc0 + ctx->s[0]; 226a8e1175bSopenharmony_ci acc0 = (uint32_t) d; 227a8e1175bSopenharmony_ci d = (uint64_t) acc1 + ctx->s[1] + (d >> 32U); 228a8e1175bSopenharmony_ci acc1 = (uint32_t) d; 229a8e1175bSopenharmony_ci d = (uint64_t) acc2 + ctx->s[2] + (d >> 32U); 230a8e1175bSopenharmony_ci acc2 = (uint32_t) d; 231a8e1175bSopenharmony_ci acc3 += ctx->s[3] + (uint32_t) (d >> 32U); 232a8e1175bSopenharmony_ci 233a8e1175bSopenharmony_ci /* Compute MAC (128 least significant bits of the accumulator) */ 234a8e1175bSopenharmony_ci MBEDTLS_PUT_UINT32_LE(acc0, mac, 0); 235a8e1175bSopenharmony_ci MBEDTLS_PUT_UINT32_LE(acc1, mac, 4); 236a8e1175bSopenharmony_ci MBEDTLS_PUT_UINT32_LE(acc2, mac, 8); 237a8e1175bSopenharmony_ci MBEDTLS_PUT_UINT32_LE(acc3, mac, 12); 238a8e1175bSopenharmony_ci} 239a8e1175bSopenharmony_ci 240a8e1175bSopenharmony_civoid mbedtls_poly1305_init(mbedtls_poly1305_context *ctx) 241a8e1175bSopenharmony_ci{ 242a8e1175bSopenharmony_ci mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context)); 243a8e1175bSopenharmony_ci} 244a8e1175bSopenharmony_ci 245a8e1175bSopenharmony_civoid mbedtls_poly1305_free(mbedtls_poly1305_context *ctx) 246a8e1175bSopenharmony_ci{ 247a8e1175bSopenharmony_ci if (ctx == NULL) { 248a8e1175bSopenharmony_ci return; 249a8e1175bSopenharmony_ci } 250a8e1175bSopenharmony_ci 251a8e1175bSopenharmony_ci mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context)); 252a8e1175bSopenharmony_ci} 253a8e1175bSopenharmony_ci 254a8e1175bSopenharmony_ciint mbedtls_poly1305_starts(mbedtls_poly1305_context *ctx, 255a8e1175bSopenharmony_ci const unsigned char key[32]) 256a8e1175bSopenharmony_ci{ 257a8e1175bSopenharmony_ci /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ 258a8e1175bSopenharmony_ci ctx->r[0] = MBEDTLS_GET_UINT32_LE(key, 0) & 0x0FFFFFFFU; 259a8e1175bSopenharmony_ci ctx->r[1] = MBEDTLS_GET_UINT32_LE(key, 4) & 0x0FFFFFFCU; 260a8e1175bSopenharmony_ci ctx->r[2] = MBEDTLS_GET_UINT32_LE(key, 8) & 0x0FFFFFFCU; 261a8e1175bSopenharmony_ci ctx->r[3] = MBEDTLS_GET_UINT32_LE(key, 12) & 0x0FFFFFFCU; 262a8e1175bSopenharmony_ci 263a8e1175bSopenharmony_ci ctx->s[0] = MBEDTLS_GET_UINT32_LE(key, 16); 264a8e1175bSopenharmony_ci ctx->s[1] = MBEDTLS_GET_UINT32_LE(key, 20); 265a8e1175bSopenharmony_ci ctx->s[2] = MBEDTLS_GET_UINT32_LE(key, 24); 266a8e1175bSopenharmony_ci ctx->s[3] = MBEDTLS_GET_UINT32_LE(key, 28); 267a8e1175bSopenharmony_ci 268a8e1175bSopenharmony_ci /* Initial accumulator state */ 269a8e1175bSopenharmony_ci ctx->acc[0] = 0U; 270a8e1175bSopenharmony_ci ctx->acc[1] = 0U; 271a8e1175bSopenharmony_ci ctx->acc[2] = 0U; 272a8e1175bSopenharmony_ci ctx->acc[3] = 0U; 273a8e1175bSopenharmony_ci ctx->acc[4] = 0U; 274a8e1175bSopenharmony_ci 275a8e1175bSopenharmony_ci /* Queue initially empty */ 276a8e1175bSopenharmony_ci mbedtls_platform_zeroize(ctx->queue, sizeof(ctx->queue)); 277a8e1175bSopenharmony_ci ctx->queue_len = 0U; 278a8e1175bSopenharmony_ci 279a8e1175bSopenharmony_ci return 0; 280a8e1175bSopenharmony_ci} 281a8e1175bSopenharmony_ci 282a8e1175bSopenharmony_ciint mbedtls_poly1305_update(mbedtls_poly1305_context *ctx, 283a8e1175bSopenharmony_ci const unsigned char *input, 284a8e1175bSopenharmony_ci size_t ilen) 285a8e1175bSopenharmony_ci{ 286a8e1175bSopenharmony_ci size_t offset = 0U; 287a8e1175bSopenharmony_ci size_t remaining = ilen; 288a8e1175bSopenharmony_ci size_t queue_free_len; 289a8e1175bSopenharmony_ci size_t nblocks; 290a8e1175bSopenharmony_ci 291a8e1175bSopenharmony_ci if ((remaining > 0U) && (ctx->queue_len > 0U)) { 292a8e1175bSopenharmony_ci queue_free_len = (POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len); 293a8e1175bSopenharmony_ci 294a8e1175bSopenharmony_ci if (ilen < queue_free_len) { 295a8e1175bSopenharmony_ci /* Not enough data to complete the block. 296a8e1175bSopenharmony_ci * Store this data with the other leftovers. 297a8e1175bSopenharmony_ci */ 298a8e1175bSopenharmony_ci memcpy(&ctx->queue[ctx->queue_len], 299a8e1175bSopenharmony_ci input, 300a8e1175bSopenharmony_ci ilen); 301a8e1175bSopenharmony_ci 302a8e1175bSopenharmony_ci ctx->queue_len += ilen; 303a8e1175bSopenharmony_ci 304a8e1175bSopenharmony_ci remaining = 0U; 305a8e1175bSopenharmony_ci } else { 306a8e1175bSopenharmony_ci /* Enough data to produce a complete block */ 307a8e1175bSopenharmony_ci memcpy(&ctx->queue[ctx->queue_len], 308a8e1175bSopenharmony_ci input, 309a8e1175bSopenharmony_ci queue_free_len); 310a8e1175bSopenharmony_ci 311a8e1175bSopenharmony_ci ctx->queue_len = 0U; 312a8e1175bSopenharmony_ci 313a8e1175bSopenharmony_ci poly1305_process(ctx, 1U, ctx->queue, 1U); /* add padding bit */ 314a8e1175bSopenharmony_ci 315a8e1175bSopenharmony_ci offset += queue_free_len; 316a8e1175bSopenharmony_ci remaining -= queue_free_len; 317a8e1175bSopenharmony_ci } 318a8e1175bSopenharmony_ci } 319a8e1175bSopenharmony_ci 320a8e1175bSopenharmony_ci if (remaining >= POLY1305_BLOCK_SIZE_BYTES) { 321a8e1175bSopenharmony_ci nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES; 322a8e1175bSopenharmony_ci 323a8e1175bSopenharmony_ci poly1305_process(ctx, nblocks, &input[offset], 1U); 324a8e1175bSopenharmony_ci 325a8e1175bSopenharmony_ci offset += nblocks * POLY1305_BLOCK_SIZE_BYTES; 326a8e1175bSopenharmony_ci remaining %= POLY1305_BLOCK_SIZE_BYTES; 327a8e1175bSopenharmony_ci } 328a8e1175bSopenharmony_ci 329a8e1175bSopenharmony_ci if (remaining > 0U) { 330a8e1175bSopenharmony_ci /* Store partial block */ 331a8e1175bSopenharmony_ci ctx->queue_len = remaining; 332a8e1175bSopenharmony_ci memcpy(ctx->queue, &input[offset], remaining); 333a8e1175bSopenharmony_ci } 334a8e1175bSopenharmony_ci 335a8e1175bSopenharmony_ci return 0; 336a8e1175bSopenharmony_ci} 337a8e1175bSopenharmony_ci 338a8e1175bSopenharmony_ciint mbedtls_poly1305_finish(mbedtls_poly1305_context *ctx, 339a8e1175bSopenharmony_ci unsigned char mac[16]) 340a8e1175bSopenharmony_ci{ 341a8e1175bSopenharmony_ci /* Process any leftover data */ 342a8e1175bSopenharmony_ci if (ctx->queue_len > 0U) { 343a8e1175bSopenharmony_ci /* Add padding bit */ 344a8e1175bSopenharmony_ci ctx->queue[ctx->queue_len] = 1U; 345a8e1175bSopenharmony_ci ctx->queue_len++; 346a8e1175bSopenharmony_ci 347a8e1175bSopenharmony_ci /* Pad with zeroes */ 348a8e1175bSopenharmony_ci memset(&ctx->queue[ctx->queue_len], 349a8e1175bSopenharmony_ci 0, 350a8e1175bSopenharmony_ci POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len); 351a8e1175bSopenharmony_ci 352a8e1175bSopenharmony_ci poly1305_process(ctx, 1U, /* Process 1 block */ 353a8e1175bSopenharmony_ci ctx->queue, 0U); /* Already padded above */ 354a8e1175bSopenharmony_ci } 355a8e1175bSopenharmony_ci 356a8e1175bSopenharmony_ci poly1305_compute_mac(ctx, mac); 357a8e1175bSopenharmony_ci 358a8e1175bSopenharmony_ci return 0; 359a8e1175bSopenharmony_ci} 360a8e1175bSopenharmony_ci 361a8e1175bSopenharmony_ciint mbedtls_poly1305_mac(const unsigned char key[32], 362a8e1175bSopenharmony_ci const unsigned char *input, 363a8e1175bSopenharmony_ci size_t ilen, 364a8e1175bSopenharmony_ci unsigned char mac[16]) 365a8e1175bSopenharmony_ci{ 366a8e1175bSopenharmony_ci mbedtls_poly1305_context ctx; 367a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 368a8e1175bSopenharmony_ci 369a8e1175bSopenharmony_ci mbedtls_poly1305_init(&ctx); 370a8e1175bSopenharmony_ci 371a8e1175bSopenharmony_ci ret = mbedtls_poly1305_starts(&ctx, key); 372a8e1175bSopenharmony_ci if (ret != 0) { 373a8e1175bSopenharmony_ci goto cleanup; 374a8e1175bSopenharmony_ci } 375a8e1175bSopenharmony_ci 376a8e1175bSopenharmony_ci ret = mbedtls_poly1305_update(&ctx, input, ilen); 377a8e1175bSopenharmony_ci if (ret != 0) { 378a8e1175bSopenharmony_ci goto cleanup; 379a8e1175bSopenharmony_ci } 380a8e1175bSopenharmony_ci 381a8e1175bSopenharmony_ci ret = mbedtls_poly1305_finish(&ctx, mac); 382a8e1175bSopenharmony_ci 383a8e1175bSopenharmony_cicleanup: 384a8e1175bSopenharmony_ci mbedtls_poly1305_free(&ctx); 385a8e1175bSopenharmony_ci return ret; 386a8e1175bSopenharmony_ci} 387a8e1175bSopenharmony_ci 388a8e1175bSopenharmony_ci#endif /* MBEDTLS_POLY1305_ALT */ 389a8e1175bSopenharmony_ci 390a8e1175bSopenharmony_ci#if defined(MBEDTLS_SELF_TEST) 391a8e1175bSopenharmony_ci 392a8e1175bSopenharmony_cistatic const unsigned char test_keys[2][32] = 393a8e1175bSopenharmony_ci{ 394a8e1175bSopenharmony_ci { 395a8e1175bSopenharmony_ci 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, 396a8e1175bSopenharmony_ci 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, 397a8e1175bSopenharmony_ci 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, 398a8e1175bSopenharmony_ci 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b 399a8e1175bSopenharmony_ci }, 400a8e1175bSopenharmony_ci { 401a8e1175bSopenharmony_ci 0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, 402a8e1175bSopenharmony_ci 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0, 403a8e1175bSopenharmony_ci 0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, 404a8e1175bSopenharmony_ci 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0 405a8e1175bSopenharmony_ci } 406a8e1175bSopenharmony_ci}; 407a8e1175bSopenharmony_ci 408a8e1175bSopenharmony_cistatic const unsigned char test_data[2][127] = 409a8e1175bSopenharmony_ci{ 410a8e1175bSopenharmony_ci { 411a8e1175bSopenharmony_ci 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, 412a8e1175bSopenharmony_ci 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f, 413a8e1175bSopenharmony_ci 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, 414a8e1175bSopenharmony_ci 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, 415a8e1175bSopenharmony_ci 0x75, 0x70 416a8e1175bSopenharmony_ci }, 417a8e1175bSopenharmony_ci { 418a8e1175bSopenharmony_ci 0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, 419a8e1175bSopenharmony_ci 0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, 420a8e1175bSopenharmony_ci 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 421a8e1175bSopenharmony_ci 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f, 422a8e1175bSopenharmony_ci 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, 423a8e1175bSopenharmony_ci 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, 424a8e1175bSopenharmony_ci 0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, 425a8e1175bSopenharmony_ci 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 426a8e1175bSopenharmony_ci 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c, 427a8e1175bSopenharmony_ci 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, 428a8e1175bSopenharmony_ci 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 429a8e1175bSopenharmony_ci 0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, 430a8e1175bSopenharmony_ci 0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 431a8e1175bSopenharmony_ci 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20, 432a8e1175bSopenharmony_ci 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, 433a8e1175bSopenharmony_ci 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e 434a8e1175bSopenharmony_ci } 435a8e1175bSopenharmony_ci}; 436a8e1175bSopenharmony_ci 437a8e1175bSopenharmony_cistatic const size_t test_data_len[2] = 438a8e1175bSopenharmony_ci{ 439a8e1175bSopenharmony_ci 34U, 440a8e1175bSopenharmony_ci 127U 441a8e1175bSopenharmony_ci}; 442a8e1175bSopenharmony_ci 443a8e1175bSopenharmony_cistatic const unsigned char test_mac[2][16] = 444a8e1175bSopenharmony_ci{ 445a8e1175bSopenharmony_ci { 446a8e1175bSopenharmony_ci 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, 447a8e1175bSopenharmony_ci 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9 448a8e1175bSopenharmony_ci }, 449a8e1175bSopenharmony_ci { 450a8e1175bSopenharmony_ci 0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61, 451a8e1175bSopenharmony_ci 0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62 452a8e1175bSopenharmony_ci } 453a8e1175bSopenharmony_ci}; 454a8e1175bSopenharmony_ci 455a8e1175bSopenharmony_ci/* Make sure no other definition is already present. */ 456a8e1175bSopenharmony_ci#undef ASSERT 457a8e1175bSopenharmony_ci 458a8e1175bSopenharmony_ci#define ASSERT(cond, args) \ 459a8e1175bSopenharmony_ci do \ 460a8e1175bSopenharmony_ci { \ 461a8e1175bSopenharmony_ci if (!(cond)) \ 462a8e1175bSopenharmony_ci { \ 463a8e1175bSopenharmony_ci if (verbose != 0) \ 464a8e1175bSopenharmony_ci mbedtls_printf args; \ 465a8e1175bSopenharmony_ci \ 466a8e1175bSopenharmony_ci return -1; \ 467a8e1175bSopenharmony_ci } \ 468a8e1175bSopenharmony_ci } \ 469a8e1175bSopenharmony_ci while (0) 470a8e1175bSopenharmony_ci 471a8e1175bSopenharmony_ciint mbedtls_poly1305_self_test(int verbose) 472a8e1175bSopenharmony_ci{ 473a8e1175bSopenharmony_ci unsigned char mac[16]; 474a8e1175bSopenharmony_ci unsigned i; 475a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 476a8e1175bSopenharmony_ci 477a8e1175bSopenharmony_ci for (i = 0U; i < 2U; i++) { 478a8e1175bSopenharmony_ci if (verbose != 0) { 479a8e1175bSopenharmony_ci mbedtls_printf(" Poly1305 test %u ", i); 480a8e1175bSopenharmony_ci } 481a8e1175bSopenharmony_ci 482a8e1175bSopenharmony_ci ret = mbedtls_poly1305_mac(test_keys[i], 483a8e1175bSopenharmony_ci test_data[i], 484a8e1175bSopenharmony_ci test_data_len[i], 485a8e1175bSopenharmony_ci mac); 486a8e1175bSopenharmony_ci ASSERT(0 == ret, ("error code: %i\n", ret)); 487a8e1175bSopenharmony_ci 488a8e1175bSopenharmony_ci ASSERT(0 == memcmp(mac, test_mac[i], 16U), ("failed (mac)\n")); 489a8e1175bSopenharmony_ci 490a8e1175bSopenharmony_ci if (verbose != 0) { 491a8e1175bSopenharmony_ci mbedtls_printf("passed\n"); 492a8e1175bSopenharmony_ci } 493a8e1175bSopenharmony_ci } 494a8e1175bSopenharmony_ci 495a8e1175bSopenharmony_ci if (verbose != 0) { 496a8e1175bSopenharmony_ci mbedtls_printf("\n"); 497a8e1175bSopenharmony_ci } 498a8e1175bSopenharmony_ci 499a8e1175bSopenharmony_ci return 0; 500a8e1175bSopenharmony_ci} 501a8e1175bSopenharmony_ci 502a8e1175bSopenharmony_ci#endif /* MBEDTLS_SELF_TEST */ 503a8e1175bSopenharmony_ci 504a8e1175bSopenharmony_ci#endif /* MBEDTLS_POLY1305_C */ 505