Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of wolfSSL by
poly1305.c
00001 /* poly1305.c 00002 * 00003 * Copyright (C) 2006-2016 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 /* 00023 * Based off the public domain implementations by Andrew Moon 00024 * and Daniel J. Bernstein 00025 */ 00026 00027 #ifdef HAVE_CONFIG_H 00028 #include <config.h> 00029 #endif 00030 00031 #include <wolfssl/wolfcrypt/settings.h> 00032 00033 #ifdef HAVE_POLY1305 00034 #include <wolfssl/wolfcrypt/poly1305.h> 00035 #include <wolfssl/wolfcrypt/error-crypt.h> 00036 #include <wolfssl/wolfcrypt/logging.h> 00037 #ifdef NO_INLINE 00038 #include <wolfssl/wolfcrypt/misc.h> 00039 #else 00040 #define WOLFSSL_MISC_INCLUDED 00041 #include <wolfcrypt/src/misc.c> 00042 #endif 00043 #ifdef CHACHA_AEAD_TEST 00044 #include <stdio.h> 00045 #endif 00046 00047 #ifdef _MSC_VER 00048 /* 4127 warning constant while(1) */ 00049 #pragma warning(disable: 4127) 00050 #endif 00051 00052 #if defined(POLY130564) 00053 00054 #if defined(_MSC_VER) 00055 #define POLY1305_NOINLINE __declspec(noinline) 00056 #elif defined(__GNUC__) 00057 #define POLY1305_NOINLINE __attribute__((noinline)) 00058 #else 00059 #define POLY1305_NOINLINE 00060 #endif 00061 00062 #if defined(_MSC_VER) 00063 #include <intrin.h> 00064 00065 typedef struct word128 { 00066 word64 lo; 00067 word64 hi; 00068 } word128; 00069 00070 #define MUL(out, x, y) out.lo = _umul128((x), (y), &out.hi) 00071 #define ADD(out, in) { word64 t = out.lo; out.lo += in.lo; \ 00072 out.hi += (out.lo < t) + in.hi; } 00073 #define ADDLO(out, in) { word64 t = out.lo; out.lo += in; \ 00074 out.hi += (out.lo < t); } 00075 #define SHR(in, shift) (__shiftright128(in.lo, in.hi, (shift))) 00076 #define LO(in) (in.lo) 00077 00078 #elif defined(__GNUC__) 00079 #if defined(__SIZEOF_INT128__) 00080 typedef unsigned __int128 word128; 00081 #else 00082 typedef unsigned word128 __attribute__((mode(TI))); 00083 #endif 00084 00085 #define MUL(out, x, y) out = ((word128)x * y) 00086 #define ADD(out, in) out += in 00087 #define ADDLO(out, in) out += in 00088 #define SHR(in, shift) (word64)(in >> (shift)) 00089 #define LO(in) (word64)(in) 00090 #endif 00091 00092 static word64 U8TO64(const byte* p) { 00093 return 00094 (((word64)(p[0] & 0xff) ) | 00095 ((word64)(p[1] & 0xff) << 8) | 00096 ((word64)(p[2] & 0xff) << 16) | 00097 ((word64)(p[3] & 0xff) << 24) | 00098 ((word64)(p[4] & 0xff) << 32) | 00099 ((word64)(p[5] & 0xff) << 40) | 00100 ((word64)(p[6] & 0xff) << 48) | 00101 ((word64)(p[7] & 0xff) << 56)); 00102 } 00103 00104 static void U64TO8(byte* p, word64 v) { 00105 p[0] = (v ) & 0xff; 00106 p[1] = (v >> 8) & 0xff; 00107 p[2] = (v >> 16) & 0xff; 00108 p[3] = (v >> 24) & 0xff; 00109 p[4] = (v >> 32) & 0xff; 00110 p[5] = (v >> 40) & 0xff; 00111 p[6] = (v >> 48) & 0xff; 00112 p[7] = (v >> 56) & 0xff; 00113 } 00114 00115 #else /* if not 64 bit then use 32 bit */ 00116 00117 static word32 U8TO32(const byte *p) { 00118 return 00119 (((word32)(p[0] & 0xff) ) | 00120 ((word32)(p[1] & 0xff) << 8) | 00121 ((word32)(p[2] & 0xff) << 16) | 00122 ((word32)(p[3] & 0xff) << 24)); 00123 } 00124 00125 static void U32TO8(byte *p, word32 v) { 00126 p[0] = (v ) & 0xff; 00127 p[1] = (v >> 8) & 0xff; 00128 p[2] = (v >> 16) & 0xff; 00129 p[3] = (v >> 24) & 0xff; 00130 } 00131 #endif 00132 00133 00134 static void U32TO64(word32 v, byte* p) { 00135 XMEMSET(p, 0, 8); 00136 p[0] = (v & 0xFF); 00137 p[1] = (v >> 8) & 0xFF; 00138 p[2] = (v >> 16) & 0xFF; 00139 p[3] = (v >> 24) & 0xFF; 00140 } 00141 00142 00143 static void poly1305_blocks(Poly1305* ctx, const unsigned char *m, 00144 size_t bytes) { 00145 00146 #ifdef POLY130564 00147 00148 const word64 hibit = (ctx->final) ? 0 : ((word64)1 << 40); /* 1 << 128 */ 00149 word64 r0,r1,r2; 00150 word64 s1,s2; 00151 word64 h0,h1,h2; 00152 word64 c; 00153 word128 d0,d1,d2,d; 00154 00155 #else 00156 00157 const word32 hibit = (ctx->final) ? 0 : (1 << 24); /* 1 << 128 */ 00158 word32 r0,r1,r2,r3,r4; 00159 word32 s1,s2,s3,s4; 00160 word32 h0,h1,h2,h3,h4; 00161 word64 d0,d1,d2,d3,d4; 00162 word32 c; 00163 00164 #endif 00165 00166 #ifdef POLY130564 00167 00168 r0 = ctx->r[0]; 00169 r1 = ctx->r[1]; 00170 r2 = ctx->r[2]; 00171 00172 h0 = ctx->h[0]; 00173 h1 = ctx->h[1]; 00174 h2 = ctx->h[2]; 00175 00176 s1 = r1 * (5 << 2); 00177 s2 = r2 * (5 << 2); 00178 00179 while (bytes >= POLY1305_BLOCK_SIZE) { 00180 word64 t0,t1; 00181 00182 /* h += m[i] */ 00183 t0 = U8TO64(&m[0]); 00184 t1 = U8TO64(&m[8]); 00185 00186 h0 += (( t0 ) & 0xfffffffffff); 00187 h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff); 00188 h2 += (((t1 >> 24) ) & 0x3ffffffffff) | hibit; 00189 00190 /* h *= r */ 00191 MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d); 00192 MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d); 00193 MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d); 00194 00195 /* (partial) h %= p */ 00196 c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff; 00197 ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff; 00198 ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff; 00199 h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff; 00200 h1 += c; 00201 00202 m += POLY1305_BLOCK_SIZE; 00203 bytes -= POLY1305_BLOCK_SIZE; 00204 } 00205 00206 ctx->h[0] = h0; 00207 ctx->h[1] = h1; 00208 ctx->h[2] = h2; 00209 00210 #else /* if not 64 bit then use 32 bit */ 00211 00212 r0 = ctx->r[0]; 00213 r1 = ctx->r[1]; 00214 r2 = ctx->r[2]; 00215 r3 = ctx->r[3]; 00216 r4 = ctx->r[4]; 00217 00218 s1 = r1 * 5; 00219 s2 = r2 * 5; 00220 s3 = r3 * 5; 00221 s4 = r4 * 5; 00222 00223 h0 = ctx->h[0]; 00224 h1 = ctx->h[1]; 00225 h2 = ctx->h[2]; 00226 h3 = ctx->h[3]; 00227 h4 = ctx->h[4]; 00228 00229 while (bytes >= POLY1305_BLOCK_SIZE) { 00230 /* h += m[i] */ 00231 h0 += (U8TO32(m+ 0) ) & 0x3ffffff; 00232 h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff; 00233 h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff; 00234 h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff; 00235 h4 += (U8TO32(m+12) >> 8) | hibit; 00236 00237 /* h *= r */ 00238 d0 = ((word64)h0 * r0) + ((word64)h1 * s4) + ((word64)h2 * s3) + 00239 ((word64)h3 * s2) + ((word64)h4 * s1); 00240 d1 = ((word64)h0 * r1) + ((word64)h1 * r0) + ((word64)h2 * s4) + 00241 ((word64)h3 * s3) + ((word64)h4 * s2); 00242 d2 = ((word64)h0 * r2) + ((word64)h1 * r1) + ((word64)h2 * r0) + 00243 ((word64)h3 * s4) + ((word64)h4 * s3); 00244 d3 = ((word64)h0 * r3) + ((word64)h1 * r2) + ((word64)h2 * r1) + 00245 ((word64)h3 * r0) + ((word64)h4 * s4); 00246 d4 = ((word64)h0 * r4) + ((word64)h1 * r3) + ((word64)h2 * r2) + 00247 ((word64)h3 * r1) + ((word64)h4 * r0); 00248 00249 /* (partial) h %= p */ 00250 c = (word32)(d0 >> 26); h0 = (word32)d0 & 0x3ffffff; 00251 d1 += c; c = (word32)(d1 >> 26); h1 = (word32)d1 & 0x3ffffff; 00252 d2 += c; c = (word32)(d2 >> 26); h2 = (word32)d2 & 0x3ffffff; 00253 d3 += c; c = (word32)(d3 >> 26); h3 = (word32)d3 & 0x3ffffff; 00254 d4 += c; c = (word32)(d4 >> 26); h4 = (word32)d4 & 0x3ffffff; 00255 h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; 00256 h1 += c; 00257 00258 m += POLY1305_BLOCK_SIZE; 00259 bytes -= POLY1305_BLOCK_SIZE; 00260 } 00261 00262 ctx->h[0] = h0; 00263 ctx->h[1] = h1; 00264 ctx->h[2] = h2; 00265 ctx->h[3] = h3; 00266 ctx->h[4] = h4; 00267 00268 #endif /* end of 64 bit cpu blocks or 32 bit cpu */ 00269 } 00270 00271 00272 int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) { 00273 00274 #if defined(POLY130564) 00275 word64 t0,t1; 00276 #endif 00277 00278 #ifdef CHACHA_AEAD_TEST 00279 word32 k; 00280 printf("Poly key used:\n"); 00281 for (k = 0; k < keySz; k++) { 00282 printf("%02x", key[k]); 00283 if ((k+1) % 8 == 0) 00284 printf("\n"); 00285 } 00286 printf("\n"); 00287 #endif 00288 00289 if (keySz != 32 || ctx == NULL) 00290 return BAD_FUNC_ARG; 00291 00292 #if defined(POLY130564) 00293 00294 /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ 00295 t0 = U8TO64(key + 0); 00296 t1 = U8TO64(key + 8); 00297 00298 ctx->r[0] = ( t0 ) & 0xffc0fffffff; 00299 ctx->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff; 00300 ctx->r[2] = ((t1 >> 24) ) & 0x00ffffffc0f; 00301 00302 /* h (accumulator) = 0 */ 00303 ctx->h[0] = 0; 00304 ctx->h[1] = 0; 00305 ctx->h[2] = 0; 00306 00307 /* save pad for later */ 00308 ctx->pad[0] = U8TO64(key + 16); 00309 ctx->pad[1] = U8TO64(key + 24); 00310 00311 #else /* if not 64 bit then use 32 bit */ 00312 00313 /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ 00314 ctx->r[0] = (U8TO32(key + 0) ) & 0x3ffffff; 00315 ctx->r[1] = (U8TO32(key + 3) >> 2) & 0x3ffff03; 00316 ctx->r[2] = (U8TO32(key + 6) >> 4) & 0x3ffc0ff; 00317 ctx->r[3] = (U8TO32(key + 9) >> 6) & 0x3f03fff; 00318 ctx->r[4] = (U8TO32(key + 12) >> 8) & 0x00fffff; 00319 00320 /* h = 0 */ 00321 ctx->h[0] = 0; 00322 ctx->h[1] = 0; 00323 ctx->h[2] = 0; 00324 ctx->h[3] = 0; 00325 ctx->h[4] = 0; 00326 00327 /* save pad for later */ 00328 ctx->pad[0] = U8TO32(key + 16); 00329 ctx->pad[1] = U8TO32(key + 20); 00330 ctx->pad[2] = U8TO32(key + 24); 00331 ctx->pad[3] = U8TO32(key + 28); 00332 00333 #endif 00334 00335 ctx->leftover = 0; 00336 ctx->final = 0; 00337 00338 return 0; 00339 } 00340 00341 00342 int wc_Poly1305Final(Poly1305* ctx, byte* mac) { 00343 00344 #if defined(POLY130564) 00345 00346 word64 h0,h1,h2,c; 00347 word64 g0,g1,g2; 00348 word64 t0,t1; 00349 00350 #else 00351 00352 word32 h0,h1,h2,h3,h4,c; 00353 word32 g0,g1,g2,g3,g4; 00354 word64 f; 00355 word32 mask; 00356 00357 #endif 00358 00359 if (ctx == NULL) 00360 return BAD_FUNC_ARG; 00361 00362 #if defined(POLY130564) 00363 00364 /* process the remaining block */ 00365 if (ctx->leftover) { 00366 size_t i = ctx->leftover; 00367 ctx->buffer[i] = 1; 00368 for (i = i + 1; i < POLY1305_BLOCK_SIZE; i++) 00369 ctx->buffer[i] = 0; 00370 ctx->final = 1; 00371 poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE); 00372 } 00373 00374 /* fully carry h */ 00375 h0 = ctx->h[0]; 00376 h1 = ctx->h[1]; 00377 h2 = ctx->h[2]; 00378 00379 c = (h1 >> 44); h1 &= 0xfffffffffff; 00380 h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; 00381 h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; 00382 h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff; 00383 h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; 00384 h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; 00385 h1 += c; 00386 00387 /* compute h + -p */ 00388 g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff; 00389 g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff; 00390 g2 = h2 + c - ((word64)1 << 42); 00391 00392 /* select h if h < p, or h + -p if h >= p */ 00393 c = (g2 >> ((sizeof(word64) * 8) - 1)) - 1; 00394 g0 &= c; 00395 g1 &= c; 00396 g2 &= c; 00397 c = ~c; 00398 h0 = (h0 & c) | g0; 00399 h1 = (h1 & c) | g1; 00400 h2 = (h2 & c) | g2; 00401 00402 /* h = (h + pad) */ 00403 t0 = ctx->pad[0]; 00404 t1 = ctx->pad[1]; 00405 00406 h0 += (( t0 ) & 0xfffffffffff) ; 00407 c = (h0 >> 44); h0 &= 0xfffffffffff; 00408 h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; 00409 c = (h1 >> 44); h1 &= 0xfffffffffff; 00410 h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c; 00411 h2 &= 0x3ffffffffff; 00412 00413 /* mac = h % (2^128) */ 00414 h0 = ((h0 ) | (h1 << 44)); 00415 h1 = ((h1 >> 20) | (h2 << 24)); 00416 00417 U64TO8(mac + 0, h0); 00418 U64TO8(mac + 8, h1); 00419 00420 /* zero out the state */ 00421 ctx->h[0] = 0; 00422 ctx->h[1] = 0; 00423 ctx->h[2] = 0; 00424 ctx->r[0] = 0; 00425 ctx->r[1] = 0; 00426 ctx->r[2] = 0; 00427 ctx->pad[0] = 0; 00428 ctx->pad[1] = 0; 00429 00430 #else /* if not 64 bit then use 32 bit */ 00431 00432 /* process the remaining block */ 00433 if (ctx->leftover) { 00434 size_t i = ctx->leftover; 00435 ctx->buffer[i++] = 1; 00436 for (; i < POLY1305_BLOCK_SIZE; i++) 00437 ctx->buffer[i] = 0; 00438 ctx->final = 1; 00439 poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE); 00440 } 00441 00442 /* fully carry h */ 00443 h0 = ctx->h[0]; 00444 h1 = ctx->h[1]; 00445 h2 = ctx->h[2]; 00446 h3 = ctx->h[3]; 00447 h4 = ctx->h[4]; 00448 00449 c = h1 >> 26; h1 = h1 & 0x3ffffff; 00450 h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; 00451 h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; 00452 h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; 00453 h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; 00454 h1 += c; 00455 00456 /* compute h + -p */ 00457 g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; 00458 g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; 00459 g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; 00460 g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; 00461 g4 = h4 + c - (1 << 26); 00462 00463 /* select h if h < p, or h + -p if h >= p */ 00464 mask = (g4 >> ((sizeof(word32) * 8) - 1)) - 1; 00465 g0 &= mask; 00466 g1 &= mask; 00467 g2 &= mask; 00468 g3 &= mask; 00469 g4 &= mask; 00470 mask = ~mask; 00471 h0 = (h0 & mask) | g0; 00472 h1 = (h1 & mask) | g1; 00473 h2 = (h2 & mask) | g2; 00474 h3 = (h3 & mask) | g3; 00475 h4 = (h4 & mask) | g4; 00476 00477 /* h = h % (2^128) */ 00478 h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; 00479 h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; 00480 h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; 00481 h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; 00482 00483 /* mac = (h + pad) % (2^128) */ 00484 f = (word64)h0 + ctx->pad[0] ; h0 = (word32)f; 00485 f = (word64)h1 + ctx->pad[1] + (f >> 32); h1 = (word32)f; 00486 f = (word64)h2 + ctx->pad[2] + (f >> 32); h2 = (word32)f; 00487 f = (word64)h3 + ctx->pad[3] + (f >> 32); h3 = (word32)f; 00488 00489 U32TO8(mac + 0, h0); 00490 U32TO8(mac + 4, h1); 00491 U32TO8(mac + 8, h2); 00492 U32TO8(mac + 12, h3); 00493 00494 /* zero out the state */ 00495 ctx->h[0] = 0; 00496 ctx->h[1] = 0; 00497 ctx->h[2] = 0; 00498 ctx->h[3] = 0; 00499 ctx->h[4] = 0; 00500 ctx->r[0] = 0; 00501 ctx->r[1] = 0; 00502 ctx->r[2] = 0; 00503 ctx->r[3] = 0; 00504 ctx->r[4] = 0; 00505 ctx->pad[0] = 0; 00506 ctx->pad[1] = 0; 00507 ctx->pad[2] = 0; 00508 ctx->pad[3] = 0; 00509 00510 #endif 00511 00512 return 0; 00513 } 00514 00515 00516 int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) { 00517 00518 size_t i; 00519 00520 #ifdef CHACHA_AEAD_TEST 00521 word32 k; 00522 printf("Raw input to poly:\n"); 00523 for (k = 0; k < bytes; k++) { 00524 printf("%02x", m[k]); 00525 if ((k+1) % 16 == 0) 00526 printf("\n"); 00527 } 00528 printf("\n"); 00529 #endif 00530 00531 if (ctx == NULL) 00532 return BAD_FUNC_ARG; 00533 00534 /* handle leftover */ 00535 if (ctx->leftover) { 00536 size_t want = (POLY1305_BLOCK_SIZE - ctx->leftover); 00537 if (want > bytes) 00538 want = bytes; 00539 for (i = 0; i < want; i++) 00540 ctx->buffer[ctx->leftover + i] = m[i]; 00541 bytes -= (word32)want; 00542 m += want; 00543 ctx->leftover += want; 00544 if (ctx->leftover < POLY1305_BLOCK_SIZE) 00545 return 0; 00546 poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE); 00547 ctx->leftover = 0; 00548 } 00549 00550 /* process full blocks */ 00551 if (bytes >= POLY1305_BLOCK_SIZE) { 00552 size_t want = (bytes & ~(POLY1305_BLOCK_SIZE - 1)); 00553 poly1305_blocks(ctx, m, want); 00554 m += want; 00555 bytes -= (word32)want; 00556 } 00557 00558 /* store leftover */ 00559 if (bytes) { 00560 for (i = 0; i < bytes; i++) 00561 ctx->buffer[ctx->leftover + i] = m[i]; 00562 ctx->leftover += bytes; 00563 } 00564 return 0; 00565 } 00566 00567 00568 /* Takes in an initialized Poly1305 struct that has a key loaded and creates 00569 a MAC (tag) using recent TLS AEAD padding scheme. 00570 ctx : Initialized Poly1305 struct to use 00571 additional : Additional data to use 00572 addSz : Size of additional buffer 00573 input : Input buffer to create tag from 00574 sz : Size of input buffer 00575 tag : Buffer to hold created tag 00576 tagSz : Size of input tag buffer (must be at least 00577 WC_POLY1305_MAC_SZ(16)) 00578 */ 00579 int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, 00580 byte* input, word32 sz, byte* tag, word32 tagSz) 00581 { 00582 int ret; 00583 byte padding[WC_POLY1305_PAD_SZ - 1]; 00584 word32 paddingLen; 00585 byte little64[8]; 00586 00587 XMEMSET(padding, 0, sizeof(padding)); 00588 00589 /* sanity check on arguments */ 00590 if (ctx == NULL || input == NULL || tag == NULL || 00591 tagSz < WC_POLY1305_MAC_SZ) { 00592 return BAD_FUNC_ARG; 00593 } 00594 00595 /* additional allowed to be 0 */ 00596 if (addSz > 0) { 00597 if (additional == NULL) 00598 return BAD_FUNC_ARG; 00599 00600 /* additional data plus padding */ 00601 if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) { 00602 return ret; 00603 } 00604 paddingLen = -((int)addSz) & (WC_POLY1305_PAD_SZ - 1); 00605 if (paddingLen) { 00606 if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { 00607 return ret; 00608 } 00609 } 00610 } 00611 00612 /* input plus padding */ 00613 if ((ret = wc_Poly1305Update(ctx, input, sz)) != 0) { 00614 return ret; 00615 } 00616 paddingLen = -((int)sz) & (WC_POLY1305_PAD_SZ - 1); 00617 if (paddingLen) { 00618 if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { 00619 return ret; 00620 } 00621 } 00622 00623 /* size of additional data and input as little endian 64 bit types */ 00624 U32TO64(addSz, little64); 00625 ret = wc_Poly1305Update(ctx, little64, sizeof(little64)); 00626 if (ret) 00627 { 00628 return ret; 00629 } 00630 00631 U32TO64(sz, little64); 00632 ret = wc_Poly1305Update(ctx, little64, sizeof(little64)); 00633 if (ret) 00634 { 00635 return ret; 00636 } 00637 00638 /* Finalize the auth tag */ 00639 ret = wc_Poly1305Final(ctx, tag); 00640 00641 return ret; 00642 00643 } 00644 #endif /* HAVE_POLY1305 */ 00645 00646
Generated on Tue Jul 12 2022 23:30:59 by
1.7.2
