""" OCB 3 for lilliput ae i """ import lilliput_tbc as ltbc from constants import BLOCK_BITS, BLOCK_BYTES, NONCE_BYTES from enum import Enum from helpers import ArrayToBlockbytesMatrix, BlockbytesMatrixToBytes KEY_BITS = 128 TWEAK_BITS = 192 TWEAKEY_BITS = KEY_BITS + TWEAK_BITS LANE_BITS = 64 LANES = int((TWEAKEY_BITS) / LANE_BITS) KEY_BYTES = int(KEY_BITS / 8) TWEAK_BYTES = int(TWEAK_BITS / 8) TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) def InitParameters(key_bits) : global KEY_BITS global KEY_BYTES global TWEAKEY_BITS global TWEAKEY_BYTES global LANES KEY_BITS = key_bits TWEAKEY_BITS = KEY_BITS + TWEAK_BITS LANES = int((TWEAKEY_BITS) / LANE_BITS) KEY_BYTES = int(KEY_BITS / 8) TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) ############################################################################### def XorState(state1, state2) : state_output = [state1[byte] ^ state2[byte] for byte in range(0, len(state1))] return state_output def Padding10LSB(array, number_bits) : shifted = 0 for byte in range(0, len(array)) : shifted |= (array[byte] << (8 * byte)) shifted = (shifted << (BLOCK_BITS - number_bits)) & 0xffffffffffffffffffffffffffffffff padded = shifted | (0x1 << (BLOCK_BITS - number_bits - 1)) array_padded = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES) : array_padded[byte] = (padded & (0xff << (8 * byte))) >> (8 * byte) return array_padded def LowPart(array, number_bits) : shifted = 0 for byte in range(0, len(array)) : shifted |= (array[byte] << (8 * byte)) mask = 0 for bit in range(0, number_bits) : mask |= (0x1 << bit) lower_part = shifted & mask will_padd = 0 if (number_bits % 8) != 0 : will_padd = 1 lower_part_byte = [0 for byte in range(0, int(number_bits / 8) + will_padd)] for byte in range(0, int(number_bits / 8) + will_padd) : lower_part_byte[byte] = lower_part & 0xff lower_part = lower_part >> 8 return lower_part_byte ############################################################################### def TweakAssociatedData(i, padded) : tweak = [0 for byte in range(0, TWEAK_BYTES)] mask = 0xff for byte in range(0, TWEAK_BYTES - 1) : tweak[byte] = (i & mask) >> (byte * 8) mask = mask << 8 mask = (0xf << (8 * (TWEAK_BYTES - 1))) tweak[TWEAK_BYTES - 1] = (i & mask) >> ((TWEAK_BYTES - 1) * 8) if not padded: tweak[TWEAK_BYTES - 1] |= 0x20 else : tweak[TWEAK_BYTES - 1] |= 0x60 return tweak def BuildAuth(A, key) : Auth = [0 for byte in range(0, BLOCK_BYTES)] l_a = len(A)//BLOCK_BYTES padding_bytes = len(A)%BLOCK_BYTES A = ArrayToBlockbytesMatrix(A) for i in range(0, l_a) : tweak = TweakAssociatedData(i, padded=False) enc = ltbc.LilliputTBCEnc(tweak, key, A[i]) Auth = XorState(Auth, enc) if padding_bytes == 0: return Auth tweak = TweakAssociatedData(l_a, padded=True) ad_padded = Padding10LSB(A[l_a], padding_bytes*8) enc = ltbc.LilliputTBCEnc(tweak, key, ad_padded) Auth = XorState(Auth, enc) return Auth ################################################################################ class _MessageTweak(Enum): BLOCK = 0b000 NO_PADDING = 0b0001 PAD = 0b0100 FINAL = 0b0101 def TweakMessage(N, j, padding): tweak = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(NONCE_BYTES-1, -1, -1) : tweak[byte + (TWEAK_BYTES-NONCE_BYTES)] |= (N[byte] & 0xf0) >> 4 tweak[byte + (TWEAK_BYTES-NONCE_BYTES-1)] |= (N[byte] & 0x0f) << 4 tweak[TWEAK_BYTES-NONCE_BYTES-1] |= ((j >> 64) & 0xf) for byte in range(TWEAK_BYTES-NONCE_BYTES-2, -1, -1) : tweak[byte] = (j >> (8 * byte)) & 0xff tweak[-1] |= padding.value<<4 return tweak def TreatMessageEnc(M, N, key): checksum = [0 for byte in range(0, BLOCK_BYTES)] l = len(M)//BLOCK_BYTES padding_bytes = len(M)%BLOCK_BYTES M = ArrayToBlockbytesMatrix(M) C = [] for j in range(0, l): checksum = XorState(checksum, M[j]) tweak = TweakMessage(N, j, _MessageTweak.BLOCK) C.append(ltbc.LilliputTBCEnc(tweak, key, M[j])) if padding_bytes == 0: tweak = TweakMessage(N, l, _MessageTweak.NO_PADDING) Final = ltbc.LilliputTBCEnc(tweak, key, checksum) else: m_padded = Padding10LSB(M[l], padding_bytes*8) checksum = XorState(checksum, m_padded) tweak = TweakMessage(N, l, _MessageTweak.PAD) pad = ltbc.LilliputTBCEnc(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) lower_part = LowPart(pad, padding_bytes*8) C.append(XorState(M[l], lower_part)) tweak_final = TweakMessage(N, l+1, _MessageTweak.FINAL) Final = ltbc.LilliputTBCEnc(tweak_final, key, checksum) return (Final, C) def TreatMessageDec(C, N, key) : checksum = [0 for byte in range(0, BLOCK_BYTES)] l = len(C)//BLOCK_BYTES padding_bytes = len(C)%BLOCK_BYTES C = ArrayToBlockbytesMatrix(C) M = [] for j in range(0, l): tweak = TweakMessage(N, j, _MessageTweak.BLOCK) M.append(ltbc.LilliputTBCDec(tweak, key, C[j])) checksum = XorState(checksum, M[j]) if padding_bytes == 0: tweak = TweakMessage(N, l, _MessageTweak.NO_PADDING) Final = ltbc.LilliputTBCEnc(tweak, key, checksum) else: tweak = TweakMessage(N, l, _MessageTweak.PAD) pad = ltbc.LilliputTBCEnc(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) lower_part = LowPart(pad, padding_bytes*8) M.append(XorState(C[l], lower_part)) m_padded = Padding10LSB(M[l], padding_bytes*8) checksum = XorState(checksum, m_padded) tweak_final = TweakMessage(N, l+1, _MessageTweak.FINAL) Final = ltbc.LilliputTBCEnc(tweak_final, key, checksum) return (Final, M) ################################################################################ def OCB3Enc(A, M, N, key) : InitParameters(len(key)*8) K = list(key) Auth = BuildAuth(A, K) (Final, C) = TreatMessageEnc(M, N, K) tag = XorState(Auth, Final) return BlockbytesMatrixToBytes(C), bytes(tag) def OCB3Dec(A, C, N, tag, key) : InitParameters(len(key)*8) K = list(key) Auth = BuildAuth(A, K) (Final, M) = TreatMessageDec(C, N, K) tag2 = XorState(Auth, Final) if(tag == tag2) : return BlockbytesMatrixToBytes(M)