HashReturn Keccak_HashUpdate(Keccak_HashInstance *instance, const BitSequence *data, DataLength databitlen) { if ((databitlen % 8) == 0) return Keccak_SpongeAbsorb(&instance->sponge, data, databitlen/8); else { HashReturn ret = Keccak_SpongeAbsorb(&instance->sponge, data, databitlen/8); if (ret == SUCCESS) { // The last partial byte is assumed to be aligned on the least significant bits unsigned char lastByte = data[databitlen/8]; // Concatenate the last few bits provided here with those of the suffix unsigned short delimitedLastBytes = (unsigned short)lastByte | ((unsigned short)instance->delimitedSuffix << (databitlen % 8)); if ((delimitedLastBytes & 0xFF00) == 0x0000) { instance->delimitedSuffix = delimitedLastBytes & 0xFF; } else { unsigned char oneByte[1]; oneByte[0] = delimitedLastBytes & 0xFF; ret = Keccak_SpongeAbsorb(&instance->sponge, oneByte, 1); instance->delimitedSuffix = (delimitedLastBytes >> 8) & 0xFF; } } return ret; }
void displaySpongeIntermediateValuesOne(const unsigned char *message, unsigned int messageLength, unsigned int rate, unsigned int capacity) { Keccak_SpongeInstance sponge; unsigned char output[512]; unsigned char *messageInternal; messageInternal = malloc((messageLength+7)/8); alignLastByteOnLSB(message, messageInternal, messageLength); displayBytes(1, "Input message (last byte aligned on MSB)", message, (messageLength+7)/8); displayBits(2, "Input message (in bits)", message, messageLength, 1); displayBits(2, "Input message (in bits, after the formal bit reordering)", messageInternal, messageLength, 0); displayBytes(2, "Input message (last byte aligned on LSB)", messageInternal, (messageLength+7)/8); Keccak_SpongeInitialize(&sponge, rate, capacity); displayStateAsBytes(1, "Initial state", sponge.state); Keccak_SpongeAbsorb(&sponge, messageInternal, messageLength/8); if ((messageLength % 8) != 0) Keccak_SpongeAbsorbLastFewBits(&sponge, messageInternal[messageLength/8] | (1 << (messageLength % 8))); Keccak_SpongeSqueeze(&sponge, output, sizeof(output)); free(messageInternal); }
void testSponge(FILE *f, unsigned int rate, unsigned int capacity, int usingQueue) { #define inputByteSize 512 #define outputByteSize 512 unsigned char input[inputByteSize]; unsigned char output[outputByteSize]; unsigned char acc[outputByteSize]; unsigned int inputBitLength, offset, size; int result; Keccak_SpongeInstance sponge; // Acumulated test vector memset(acc, 0x00, sizeof(acc)); for(inputBitLength = 0; inputBitLength <= (inputByteSize*8); inputBitLength += (inputBitLength < 1600) ? 1 : 8) { unsigned int i; unsigned int inputByteLengthCeiling = (inputBitLength + 7) / 8; for(i=0; i<inputByteLengthCeiling; i++) input[i] = inputBitLength - i; if ((inputBitLength % 8) != 0) input[inputByteLengthCeiling-1] &= (1 << (inputBitLength % 8)) - 1; result = Keccak_SpongeInitialize(&sponge, rate, capacity); if (usingQueue) { for(offset = 0; offset < inputBitLength/8; offset += size) { unsigned int p = (inputBitLength/8)%11; // vary sizes if (p < 1) size = 1; // byte per byte else if (p < 5) size = (rand() % 20); // small random else if (p < 9) size = (rand() % 200); // big random else size = ((rand() % (inputBitLength/8 - offset)) + 1); // converging random if (size > (inputBitLength/8 - offset)) size = inputBitLength/8 - offset; result = Keccak_SpongeAbsorb(&sponge, input + offset, size); } } else result = Keccak_SpongeAbsorb(&sponge, input, inputBitLength/8); if ((inputBitLength % 8) != 0) result = Keccak_SpongeAbsorbLastFewBits(&sponge, input[inputByteLengthCeiling-1] | (1 << (inputBitLength % 8))); if (usingQueue) { unsigned char filler = 0xAA + inputBitLength; memset(output, filler, sizeof(output)); for(offset = 0; offset < outputByteSize; offset += size) { unsigned int p = (inputBitLength/8)%11; // vary sizes if (p < 1) size = 1; // byte per byte else if (p < 5) size = (rand() % 20); // small random else if (p < 9) size = (rand() % 200); // big random else size = ((rand() % (outputByteSize - offset)) + 1); // converging random if (size > (outputByteSize - offset)) size = outputByteSize - offset; result = Keccak_SpongeSqueeze(&sponge, output + offset, size); for(i = offset + size; i<sizeof(output); i++) if (output[i] != filler) { printf("Out of range data written!\n"); abort(); } } } else result = Keccak_SpongeSqueeze(&sponge, output, outputByteSize); for (i = 0; i < outputByteSize; i++) acc[i] ^= output[i]; } fprintf(f, "Keccak[r=%d, c=%d]: ", rate, capacity); for(offset=0; offset<outputByteSize; offset++) fprintf(f, "%02x ", acc[offset]); fprintf(f, "\n\n"); #undef inputByteSize #undef outputByteSize }