Path: blob/master/sha3/sph_panama.c
1299 views
/* $Id: panama.c 216 2010-06-08 09:46:57Z tp $ */1/*2* PANAMA implementation.3*4* ==========================(LICENSE BEGIN)============================5*6* Copyright (c) 2007-2010 Projet RNRT SAPHIR7*8* Permission is hereby granted, free of charge, to any person obtaining9* a copy of this software and associated documentation files (the10* "Software"), to deal in the Software without restriction, including11* without limitation the rights to use, copy, modify, merge, publish,12* distribute, sublicense, and/or sell copies of the Software, and to13* permit persons to whom the Software is furnished to do so, subject to14* the following conditions:15*16* The above copyright notice and this permission notice shall be17* included in all copies or substantial portions of the Software.18*19* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,20* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF21* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.22* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY23* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,24* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE25* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.26*27* ===========================(LICENSE END)=============================28*29* @author Thomas Pornin <[email protected]>30*/3132#include <stddef.h>33#include <string.h>3435#include "sph_panama.h"3637#define LVAR17(b) sph_u32 \38b ## 0, b ## 1, b ## 2, b ## 3, b ## 4, b ## 5, \39b ## 6, b ## 7, b ## 8, b ## 9, b ## 10, b ## 11, \40b ## 12, b ## 13, b ## 14, b ## 15, b ## 16;4142#define LVARS \43LVAR17(a) \44LVAR17(g) \45LVAR17(p) \46LVAR17(t)4748#define M17(macro) do { \49macro( 0, 1, 2, 4); \50macro( 1, 2, 3, 5); \51macro( 2, 3, 4, 6); \52macro( 3, 4, 5, 7); \53macro( 4, 5, 6, 8); \54macro( 5, 6, 7, 9); \55macro( 6, 7, 8, 10); \56macro( 7, 8, 9, 11); \57macro( 8, 9, 10, 12); \58macro( 9, 10, 11, 13); \59macro(10, 11, 12, 14); \60macro(11, 12, 13, 15); \61macro(12, 13, 14, 16); \62macro(13, 14, 15, 0); \63macro(14, 15, 16, 1); \64macro(15, 16, 0, 2); \65macro(16, 0, 1, 3); \66} while (0)6768#define BUPDATE1(n0, n2) do { \69sc->buffer[ptr24][n0] ^= sc->buffer[ptr31][n2]; \70sc->buffer[ptr31][n2] ^= INW1(n2); \71} while (0)7273#define BUPDATE do { \74BUPDATE1(0, 2); \75BUPDATE1(1, 3); \76BUPDATE1(2, 4); \77BUPDATE1(3, 5); \78BUPDATE1(4, 6); \79BUPDATE1(5, 7); \80BUPDATE1(6, 0); \81BUPDATE1(7, 1); \82} while (0)8384#define RSTATE(n0, n1, n2, n4) (a ## n0 = sc->state[n0])8586#define WSTATE(n0, n1, n2, n4) (sc->state[n0] = a ## n0)8788#define GAMMA(n0, n1, n2, n4) \89(g ## n0 = a ## n0 ^ (a ## n1 | SPH_T32(~a ## n2)))9091#define PI_ALL do { \92p0 = g0; \93p1 = SPH_ROTL32( g7, 1); \94p2 = SPH_ROTL32(g14, 3); \95p3 = SPH_ROTL32( g4, 6); \96p4 = SPH_ROTL32(g11, 10); \97p5 = SPH_ROTL32( g1, 15); \98p6 = SPH_ROTL32( g8, 21); \99p7 = SPH_ROTL32(g15, 28); \100p8 = SPH_ROTL32( g5, 4); \101p9 = SPH_ROTL32(g12, 13); \102p10 = SPH_ROTL32( g2, 23); \103p11 = SPH_ROTL32( g9, 2); \104p12 = SPH_ROTL32(g16, 14); \105p13 = SPH_ROTL32( g6, 27); \106p14 = SPH_ROTL32(g13, 9); \107p15 = SPH_ROTL32( g3, 24); \108p16 = SPH_ROTL32(g10, 8); \109} while (0)110111#define THETA(n0, n1, n2, n4) \112(t ## n0 = p ## n0 ^ p ## n1 ^ p ## n4)113114#define SIGMA_ALL do { \115a0 = t0 ^ 1; \116a1 = t1 ^ INW2(0); \117a2 = t2 ^ INW2(1); \118a3 = t3 ^ INW2(2); \119a4 = t4 ^ INW2(3); \120a5 = t5 ^ INW2(4); \121a6 = t6 ^ INW2(5); \122a7 = t7 ^ INW2(6); \123a8 = t8 ^ INW2(7); \124a9 = t9 ^ sc->buffer[ptr16][0]; \125a10 = t10 ^ sc->buffer[ptr16][1]; \126a11 = t11 ^ sc->buffer[ptr16][2]; \127a12 = t12 ^ sc->buffer[ptr16][3]; \128a13 = t13 ^ sc->buffer[ptr16][4]; \129a14 = t14 ^ sc->buffer[ptr16][5]; \130a15 = t15 ^ sc->buffer[ptr16][6]; \131a16 = t16 ^ sc->buffer[ptr16][7]; \132} while (0)133134#define PANAMA_STEP do { \135unsigned ptr16, ptr24, ptr31; \136\137ptr24 = (ptr0 - 8) & 31; \138ptr31 = (ptr0 - 1) & 31; \139BUPDATE; \140M17(GAMMA); \141PI_ALL; \142M17(THETA); \143ptr16 = ptr0 ^ 16; \144SIGMA_ALL; \145ptr0 = ptr31; \146} while (0)147148/*149* These macros are used to compute150*/151#define INC0 1152#define INC1 2153#define INC2 3154#define INC3 4155#define INC4 5156#define INC5 6157#define INC6 7158#define INC7 8159160/*161* Push data by blocks of 32 bytes. "pbuf" must be 32-bit aligned. Each162* iteration processes 32 data bytes; "num" contains the number of163* iterations.164*/165static void166panama_push(sph_panama_context *sc, const unsigned char *pbuf, size_t num)167{168LVARS169unsigned ptr0;170#if SPH_LITTLE_FAST171#define INW1(i) sph_dec32le_aligned(pbuf + 4 * (i))172#else173sph_u32 X_var[8];174#define INW1(i) X_var[i]175#endif176#define INW2(i) INW1(i)177178M17(RSTATE);179ptr0 = sc->buffer_ptr;180while (num -- > 0) {181#if !SPH_LITTLE_FAST182int i;183184for (i = 0; i < 8; i ++)185X_var[i] = sph_dec32le_aligned(pbuf + 4 * (i));186#endif187PANAMA_STEP;188pbuf = (const unsigned char *)pbuf + 32;189}190M17(WSTATE);191sc->buffer_ptr = ptr0;192193#undef INW1194#undef INW2195}196197/*198* Perform the "pull" operation repeatedly ("num" times). The hash output199* will be extracted from the state afterwards.200*/201static void202panama_pull(sph_panama_context *sc, unsigned num)203{204LVARS205unsigned ptr0;206#define INW1(i) INW_H1(INC ## i)207#define INW_H1(i) INW_H2(i)208#define INW_H2(i) a ## i209#define INW2(i) sc->buffer[ptr4][i]210211M17(RSTATE);212ptr0 = sc->buffer_ptr;213while (num -- > 0) {214unsigned ptr4;215216ptr4 = (ptr0 + 4) & 31;217PANAMA_STEP;218}219M17(WSTATE);220221#undef INW1222#undef INW_H1223#undef INW_H2224#undef INW2225}226227/* see sph_panama.h */228void229sph_panama_init(void *cc)230{231sph_panama_context *sc;232233sc = cc;234/*235* This is not completely conformant, but "it will work236* everywhere". Initial state consists of zeroes everywhere.237* Conceptually, the sph_u32 type may have padding bits which238* must not be set to 0; but such an architecture remains to239* be seen.240*/241sc->data_ptr = 0;242memset(sc->buffer, 0, sizeof sc->buffer);243sc->buffer_ptr = 0;244memset(sc->state, 0, sizeof sc->state);245}246247#ifdef SPH_UPTR248static void249panama_short(void *cc, const void *data, size_t len)250#else251void252sph_panama(void *cc, const void *data, size_t len)253#endif254{255sph_panama_context *sc;256unsigned current;257258sc = cc;259current = sc->data_ptr;260while (len > 0) {261unsigned clen;262263clen = (sizeof sc->data) - current;264if (clen > len)265clen = len;266memcpy(sc->data + current, data, clen);267data = (const unsigned char *)data + clen;268len -= clen;269current += clen;270if (current == sizeof sc->data) {271current = 0;272panama_push(sc, sc->data, 1);273}274}275sc->data_ptr = current;276}277278#ifdef SPH_UPTR279/* see sph_panama.h */280void281sph_panama(void *cc, const void *data, size_t len)282{283sph_panama_context *sc;284unsigned current;285size_t rlen;286287if (len < (2 * sizeof sc->data)) {288panama_short(cc, data, len);289return;290}291sc = cc;292current = sc->data_ptr;293if (current > 0) {294unsigned t;295296t = (sizeof sc->data) - current;297panama_short(sc, data, t);298data = (const unsigned char *)data + t;299len -= t;300}301#if !SPH_UNALIGNED302if (((SPH_UPTR)data & 3) != 0) {303panama_short(sc, data, len);304return;305}306#endif307panama_push(sc, data, len >> 5);308rlen = len & 31;309if (rlen > 0)310memcpy(sc->data,311(const unsigned char *)data + len - rlen, rlen);312sc->data_ptr = rlen;313}314#endif315316/* see sph_panama.h */317void318sph_panama_close(void *cc, void *dst)319{320sph_panama_context *sc;321unsigned current;322int i;323324sc = cc;325current = sc->data_ptr;326sc->data[current ++] = 0x01;327memset(sc->data + current, 0, (sizeof sc->data) - current);328panama_push(sc, sc->data, 1);329panama_pull(sc, 32);330for (i = 0; i < 8; i ++)331sph_enc32le((unsigned char *)dst + 4 * i, sc->state[i + 9]);332sph_panama_init(sc);333}334335336