int Keccak_DuplexingFeedPartialInput(Keccak_DuplexInstance *instance, const unsigned char *in, unsigned int inByteLen) { const unsigned int rho_max = instance->rate - 2; if ((instance->byteInputIndex+inByteLen)*8 > rho_max) return 1; if ((instance->byteInputIndex == 0) && (inByteLen >= KeccakF_laneInBytes)) { KeccakF_StateXORLanes(instance->state, in, inByteLen/KeccakF_laneInBytes); in += (inByteLen/KeccakF_laneInBytes)*KeccakF_laneInBytes; instance->byteInputIndex += (inByteLen/KeccakF_laneInBytes)*KeccakF_laneInBytes; inByteLen -= (inByteLen/KeccakF_laneInBytes)*KeccakF_laneInBytes; } while(inByteLen > 0) { unsigned int offsetInLane = instance->byteInputIndex % KeccakF_laneInBytes; unsigned int bytesInLane = KeccakF_laneInBytes - offsetInLane; if (bytesInLane > inByteLen) bytesInLane = inByteLen; KeccakF_StateXORBytesInLane(instance->state, instance->byteInputIndex/KeccakF_laneInBytes, in, offsetInLane, bytesInLane); in += bytesInLane; instance->byteInputIndex += bytesInLane; inByteLen -= bytesInLane; } return 0; }
void Ket_StateXORByte( void *state, unsigned int offset, unsigned char data ) { unsigned char localData[1]; localData[0] = data; KeccakF_StateXORBytesInLane(state, offset / KeccakF_laneInBytes, localData, offset % KeccakF_laneInBytes, 1 ); }
void Ket_WrapBlocks( void *state, const unsigned char *plaintext, unsigned char *ciphertext, unsigned int nBlocks ) { unsigned char keystream[Ketje_BlockSize]; unsigned char plaintemp[Ketje_BlockSize]; unsigned char frameAndPaddingBits[1]; frameAndPaddingBits[0] = 0x08 | FRAMEBITS11; while ( nBlocks-- != 0 ) { KeccakF_StateExtractLanes(state, keystream, Ketje_BlockSize / KeccakF_laneInBytes); plaintemp[0] = plaintext[0]; plaintemp[1] = plaintext[1]; #if (KeccakF_width == 400 ) plaintemp[2] = plaintext[2]; plaintemp[3] = plaintext[3]; #endif *(ciphertext++) = *(plaintext++) ^ keystream[0]; *(ciphertext++) = *(plaintext++) ^ keystream[1]; #if (KeccakF_width == 400 ) *(ciphertext++) = *(plaintext++) ^ keystream[2]; *(ciphertext++) = *(plaintext++) ^ keystream[3]; #endif KeccakF_StateXORLanes(state, plaintemp, Ketje_BlockSize / KeccakF_laneInBytes); KeccakF_StateXORBytesInLane(state, Ketje_BlockSize / KeccakF_laneInBytes, frameAndPaddingBits, 0, 1); KeccakP_StatePermute(state, Ket_StepRounds); } }
void Ket_UnwrapBlocks( void *state, const unsigned char *ciphertext, unsigned char *plaintext, unsigned int nBlocks ) { unsigned char tempBlock[Ketje_BlockSize]; unsigned char frameAndPaddingBits[1]; frameAndPaddingBits[0] = 0x08 | FRAMEBITS11; while ( nBlocks-- != 0 ) { KeccakF_StateExtractLanes(state, tempBlock, Ketje_BlockSize / KeccakF_laneInBytes); tempBlock[0] = *(plaintext++) = *(ciphertext++) ^ tempBlock[0]; tempBlock[1] = *(plaintext++) = *(ciphertext++) ^ tempBlock[1]; #if (KeccakF_width == 400 ) tempBlock[2] = *(plaintext++) = *(ciphertext++) ^ tempBlock[2]; tempBlock[3] = *(plaintext++) = *(ciphertext++) ^ tempBlock[3]; #endif KeccakF_StateXORLanes(state, tempBlock, Ketje_BlockSize / KeccakF_laneInBytes); KeccakF_StateXORBytesInLane(state, Ketje_BlockSize / KeccakF_laneInBytes, frameAndPaddingBits, 0, 1); KeccakP_StatePermute(state, Ket_StepRounds); } }
int Keccak_Duplexing(Keccak_DuplexInstance *instance, const unsigned char *sigmaBegin, unsigned int sigmaBeginByteLen, unsigned char *Z, unsigned int ZByteLen, unsigned char delimitedSigmaEnd) { unsigned char delimitedSigmaEnd1[1]; const unsigned int rho_max = instance->rate - 2; if (delimitedSigmaEnd == 0) return 1; if ((instance->byteInputIndex+sigmaBeginByteLen)*8 > rho_max) return 1; if (rho_max - sigmaBeginByteLen*8 < 7) { unsigned int maxBitsInDelimitedSigmaEnd = rho_max - sigmaBeginByteLen*8; if (delimitedSigmaEnd >= (1 << (maxBitsInDelimitedSigmaEnd+1))) return 1; } if (ZByteLen > (instance->rate+7)/8) return 1; // The output length must not be greater than the rate (rounded up to a byte) delimitedSigmaEnd1[0] = delimitedSigmaEnd; // Last few bits, whose delimiter coincides with first bit of padding KeccakF_StateXORBytesInLane(instance->state, (instance->byteInputIndex+sigmaBeginByteLen)/KeccakF_laneInBytes, delimitedSigmaEnd1, (instance->byteInputIndex+sigmaBeginByteLen)%KeccakF_laneInBytes, 1); // Second bit of padding KeccakF_StateComplementBit(instance->state, instance->rate - 1); if (instance->byteInputIndex > 0) { int result = Keccak_DuplexingFeedPartialInput(instance, sigmaBegin, sigmaBeginByteLen); if (result != 0) return result; KeccakF_StatePermute(instance->state); KeccakF_StateExtractLanes(instance->state, Z, ZByteLen/KeccakF_laneInBytes); } else { if ((sigmaBeginByteLen%KeccakF_laneInBytes) > 0) { unsigned int offsetBeyondLane = (sigmaBeginByteLen/KeccakF_laneInBytes)*KeccakF_laneInBytes; unsigned int beyondLaneBytes = sigmaBeginByteLen%KeccakF_laneInBytes; KeccakF_StateXORBytesInLane(instance->state, sigmaBeginByteLen/KeccakF_laneInBytes, sigmaBegin+offsetBeyondLane, 0, beyondLaneBytes); } #ifdef KeccakReference { unsigned char block[KeccakF_width/8]; memcpy(block, sigmaBegin, sigmaBeginByteLen); block[sigmaBeginByteLen] = delimitedSigmaEnd; memset(block+sigmaBeginByteLen+1, 0, ((instance->rate+63)/64)*8-sigmaBeginByteLen-1); block[(instance->rate-1)/8] |= 1 << ((instance->rate-1) % 8); displayBytes(1, "Block to be absorbed (after padding)", block, (instance->rate+7)/8); } #endif KeccakF_StateXORPermuteExtract(instance->state, sigmaBegin, sigmaBeginByteLen/KeccakF_laneInBytes, Z, ZByteLen/KeccakF_laneInBytes); } if ((ZByteLen%KeccakF_laneInBytes) > 0) { unsigned int offsetBeyondLane = (ZByteLen/KeccakF_laneInBytes)*KeccakF_laneInBytes; unsigned int beyondLaneBytes = ZByteLen%KeccakF_laneInBytes; KeccakF_StateExtractBytesInLane(instance->state, ZByteLen/KeccakF_laneInBytes, Z+offsetBeyondLane, 0, beyondLaneBytes); } if (ZByteLen*8 > instance->rate) { unsigned char mask = (1 << (instance->rate % 8)) - 1; Z[ZByteLen-1] &= mask; } instance->byteInputIndex = 0; instance->byteOutputIndex = ZByteLen; return 0; }