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