1/***********************************************************************
2**
3** Debug output functions for Skein hashing.
4**
5** Source code author: Doug Whiting, 2008.
6**
7** This algorithm and source code is released to the public domain.
8**
9************************************************************************/
10#include <stdio.h>
11
12#ifdef SKEIN_DEBUG  /* only instantiate this code if SKEIN_DEBUG is on */
13#include "skein.h"
14
15static const char INDENT[] =  "    ";  /* how much to indent on new line */
16
17uint_t skein_DebugFlag = 0;  /* off by default. Must be set externally */
18
19static void Show64_step(size_t cnt,const u64b_t *X,size_t step)
20    {
21    size_t i,j;
22    for (i=j=0;i < cnt;i++,j+=step)
23        {
24        if (i % 4 ==  0) printf(INDENT);
25        printf(" %08X.%08X ",(uint_32t)(X[j] >> 32),(uint_32t)X[j]);
26        if (i % 4 ==  3 || i==cnt-1) printf("\n");
27        fflush(stdout);
28        }
29    }
30
31#define Show64(cnt,X) Show64_step(cnt,X,1)
32
33static void Show64_flag(size_t cnt,const u64b_t *X)
34    {
35    size_t xptr = (size_t) X;
36    size_t step = (xptr & 1) ? 2 : 1;
37    if (step != 1)
38        {
39        X = (const u64b_t *) (xptr & ~1);
40        }
41    Show64_step(cnt,X,step);
42    }
43
44static void Show08(size_t cnt,const u08b_t *b)
45    {
46    size_t i;
47    for (i=0;i < cnt;i++)
48        {
49        if (i %16 ==  0) printf(INDENT);
50        else if (i % 4 == 0) printf(" ");
51        printf(" %02X",b[i]);
52        if (i %16 == 15 || i==cnt-1) printf("\n");
53        fflush(stdout);
54        }
55    }
56
57static const char *AlgoHeader(uint_t bits)
58    {
59    if (skein_DebugFlag & SKEIN_DEBUG_THREEFISH)
60        switch (bits)
61            {
62            case  256:  return ":Threefish-256: ";
63            case  512:  return ":Threefish-512: ";
64            case 1024:  return ":Threefish-1024:";
65            }
66    else
67        switch (bits)
68            {
69            case  256:  return ":Skein-256: ";
70            case  512:  return ":Skein-512: ";
71            case 1024:  return ":Skein-1024:";
72            }
73    return NULL;
74    }
75
76void Skein_Show_Final(uint_t bits,const Skein_Ctxt_Hdr_t *h,size_t cnt,const u08b_t *outPtr)
77    {
78    if (skein_DebugFlag & SKEIN_DEBUG_CONFIG || ((h->T[1] & SKEIN_T1_BLK_TYPE_MASK) != SKEIN_T1_BLK_TYPE_CFG))
79    if (skein_DebugFlag & SKEIN_DEBUG_FINAL)
80        {
81        printf("\n%s Final output=\n",AlgoHeader(bits));
82        Show08(cnt,outPtr);
83        printf("    ++++++++++\n");
84        fflush(stdout);
85        }
86    }
87
88/* show state after a round (or "pseudo-round") */
89void Skein_Show_Round(uint_t bits,const Skein_Ctxt_Hdr_t *h,size_t r,const u64b_t *X)
90    {
91    static uint_t injectNum=0;  /* not multi-thread safe! */
92
93    if (skein_DebugFlag & SKEIN_DEBUG_CONFIG || ((h->T[1] & SKEIN_T1_BLK_TYPE_MASK) != SKEIN_T1_BLK_TYPE_CFG))
94    if (skein_DebugFlag)
95        {
96        if (r >= SKEIN_RND_SPECIAL)
97            {       /* a key injection (or feedforward) point */
98            injectNum = (r == SKEIN_RND_KEY_INITIAL) ? 0 : injectNum+1;
99            if (  skein_DebugFlag & SKEIN_DEBUG_INJECT ||
100                ((skein_DebugFlag & SKEIN_DEBUG_FINAL) && r == SKEIN_RND_FEED_FWD))
101                {
102                printf("\n%s",AlgoHeader(bits));
103                switch (r)
104                    {
105                    case SKEIN_RND_KEY_INITIAL:
106                        printf(" [state after initial key injection]");
107                        break;
108                    case SKEIN_RND_KEY_INJECT:
109                        printf(" [state after key injection #%02d]",injectNum);
110                        break;
111                    case SKEIN_RND_FEED_FWD:
112                        printf(" [state after plaintext feedforward]");
113                        injectNum = 0;
114                        break;
115                    }
116                printf("=\n");
117                Show64(bits/64,X);
118                if (r== SKEIN_RND_FEED_FWD)
119                    printf("    ----------\n");
120                }
121            }
122        else if (skein_DebugFlag & SKEIN_DEBUG_ROUNDS)
123            {
124            uint_t j;
125            u64b_t p[SKEIN_MAX_STATE_WORDS];
126            const u08b_t *perm;
127            const static u08b_t PERM_256 [4][ 4] = { { 0,1,2,3 }, { 0,3,2,1 }, { 0,1,2,3 }, { 0,3,2,1 } };
128            const static u08b_t PERM_512 [4][ 8] = { { 0,1,2,3,4,5,6,7 },
129                                                     { 2,1,4,7,6,5,0,3 },
130                                                     { 4,1,6,3,0,5,2,7 },
131                                                     { 6,1,0,7,2,5,4,3 }
132                                                   };
133            const static u08b_t PERM_1024[4][16] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 },
134                                                     { 0, 9, 2,13, 6,11, 4,15,10, 7,12, 3,14, 5, 8, 1 },
135                                                     { 0, 7, 2, 5, 4, 3, 6, 1,12,15,14,13, 8,11,10, 9 },
136                                                     { 0,15, 2,11, 6,13, 4, 9,14, 1, 8, 5,10, 3,12, 7 }
137                                                   };
138
139            if ((skein_DebugFlag & SKEIN_DEBUG_PERMUTE) && (r & 3))
140                {
141                printf("\n%s [state after round %2d (permuted)]=\n",AlgoHeader(bits),(int)r);
142                switch (bits)
143                    {
144                    case  256: perm = PERM_256 [r&3];   break;
145                    case  512: perm = PERM_512 [r&3];   break;
146                    default:   perm = PERM_1024[r&3];   break;
147                    }
148                for (j=0;j<bits/64;j++)
149                    p[j] = X[perm[j]];
150                Show64(bits/64,p);
151                }
152            else
153                {
154                printf("\n%s [state after round %2d]=\n",AlgoHeader(bits),(int)r);
155                Show64(bits/64,X);
156                }
157            }
158        }
159    }
160
161/* show state after a round (or "pseudo-round"), given a list of pointers */
162void Skein_Show_R_Ptr(uint_t bits,const Skein_Ctxt_Hdr_t *h,size_t r,const u64b_t *X_ptr[])
163    {
164    uint_t i;
165    u64b_t X[SKEIN_MAX_STATE_WORDS];
166
167    for (i=0;i<bits/64;i++)     /* copy over the words */
168        X[i] = X_ptr[i][0];
169    Skein_Show_Round(bits,h,r,X);
170    }
171
172
173/* show the state at the start of a block */
174void Skein_Show_Block(uint_t bits,const Skein_Ctxt_Hdr_t *h,const u64b_t *X,const u08b_t *blkPtr,
175                      const u64b_t *wPtr, const u64b_t *ksPtr, const u64b_t *tsPtr)
176    {
177    uint_t n;
178    if (skein_DebugFlag & SKEIN_DEBUG_CONFIG || ((h->T[1] & SKEIN_T1_BLK_TYPE_MASK) != SKEIN_T1_BLK_TYPE_CFG))
179    if (skein_DebugFlag)
180        {
181        if (skein_DebugFlag & SKEIN_DEBUG_HDR)
182            {
183            printf("\n%s Block: outBits=%4d. T0=%06X.",AlgoHeader(bits),(uint_t) h->hashBitLen,(uint_t)h->T[0]);
184            printf(" Type=");
185            n = (uint_t) ((h->T[1] & SKEIN_T1_BLK_TYPE_MASK) >> SKEIN_T1_POS_BLK_TYPE);
186            switch (n)
187                {
188                case SKEIN_BLK_TYPE_KEY:  printf("KEY. ");  break;
189                case SKEIN_BLK_TYPE_CFG:  printf("CFG. ");  break;
190                case SKEIN_BLK_TYPE_PERS: printf("PERS.");  break;
191                case SKEIN_BLK_TYPE_PK :  printf("PK.  ");  break;
192                case SKEIN_BLK_TYPE_KDF:  printf("KDF. ");  break;
193                case SKEIN_BLK_TYPE_MSG:  printf("MSG. ");  break;
194                case SKEIN_BLK_TYPE_OUT:  printf("OUT. ");  break;
195                default:    printf("0x%02X.",n); break;
196                }
197            printf(" Flags=");
198            printf((h->T[1] & SKEIN_T1_FLAG_FIRST)   ? " First":"      ");
199            printf((h->T[1] & SKEIN_T1_FLAG_FINAL)   ? " Final":"      ");
200            printf((h->T[1] & SKEIN_T1_FLAG_BIT_PAD) ? " Pad"  :"    ");
201            n = (uint_t) ((h->T[1] & SKEIN_T1_TREE_LVL_MASK) >> SKEIN_T1_POS_TREE_LVL);
202            if (n)
203                printf("  TreeLevel = %02X",n);
204            printf("\n");
205            fflush(stdout);
206            }
207        if (skein_DebugFlag & SKEIN_DEBUG_TWEAK)
208            {
209            printf("  Tweak:\n");
210            Show64(2,h->T);
211            }
212        if (skein_DebugFlag & SKEIN_DEBUG_STATE)
213            {
214            printf("  %s words:\n",(skein_DebugFlag & SKEIN_DEBUG_THREEFISH)?"Key":"State");
215            Show64(bits/64,X);
216            }
217        if (skein_DebugFlag & SKEIN_DEBUG_KEYSCHED)
218            {
219            printf("  Tweak schedule:\n");
220            Show64_flag(3,tsPtr);
221            printf("  Key   schedule:\n");
222            Show64_flag((bits/64)+1,ksPtr);
223            }
224        if (skein_DebugFlag & SKEIN_DEBUG_INPUT_64)
225            {
226            printf("  Input block (words):\n");
227            Show64(bits/64,wPtr);
228            }
229        if (skein_DebugFlag & SKEIN_DEBUG_INPUT_08)
230            {
231            printf("  Input block (bytes):\n");
232            Show08(bits/8,blkPtr);
233            }
234        }
235    }
236
237void Skein_Show_Key(uint_t bits,const Skein_Ctxt_Hdr_t *h,const u08b_t *key,size_t keyBytes)
238    {
239    if (keyBytes)
240    if (skein_DebugFlag & SKEIN_DEBUG_CONFIG || ((h->T[1] & SKEIN_T1_BLK_TYPE_MASK) != SKEIN_T1_BLK_TYPE_CFG))
241    if (skein_DebugFlag & SKEIN_DEBUG_KEY)
242        {
243        printf("\n%s MAC key = %4u bytes\n",AlgoHeader(bits),(unsigned) keyBytes);
244        Show08(keyBytes,key);
245        }
246    }
247#endif
248