def theta(self, in0, in1, in2, in3, out0, out1, out2, out3, wordsize): """ Model for the Theta function in NOEKEON """ command = "" in1xorin3 = "BVXOR({0}[31:0], {1}[31:0])".format(in1, in3) in1xorin3lr = rotl(in1xorin3, 8, wordsize) in1xorin3rr = rotr(in1xorin3, 8, wordsize) l = "BVXOR({0}, BVXOR({1}, {2}))".format(in1xorin3lr, in1xorin3, in1xorin3rr) in0xorin2 = "BVXOR({0}[31:0], {1}[31:0])".format(in0, in2) in0xorin2lr = rotl(in0xorin2, 8, wordsize) in0xorin2rr = rotr(in0xorin2, 8, wordsize) r = "BVXOR({0}, BVXOR({1}, {2}))".format(in0xorin2lr, in0xorin2, in0xorin2rr) command += "ASSERT({0}[31:0] = BVXOR({1}[31:0], {2}[31:0]));\n".format( out0, in0, l) command += "ASSERT({0}[31:0] = BVXOR({1}[31:0], {2}[31:0]));\n".format( out1, in1, r) command += "ASSERT({0}[31:0] = BVXOR({1}[31:0], {2}[31:0]));\n".format( out2, in2, l) command += "ASSERT({0}[31:0] = BVXOR({1}[31:0], {2}[31:0]));\n".format( out3, in3, r) return command
def A(self, x_in, y_in, x_out, y_out, w, wordsize): """ Model for the ARX box (round) function of SPARX. A^a denotes a rounds of SPECKEY. """ command = "" #Assert((x_in >>> 7) + y_in = x_out) command += "ASSERT(" command += stpcommands.getStringAdd(rotr(x_in, 7, wordsize), y_in, x_out, wordsize) command += ");\n" #Assert(x_out xor (y_in <<< 2) = y_out) command += "ASSERT(" + y_out + " = " command += "BVXOR(" + x_out + "," command += rotl(y_in, 2, wordsize) command += "));\n" #For weight computation command += "ASSERT({0} = ~".format(w) command += stpcommands.getStringEq(rotr(x_in, 7, wordsize), y_in, x_out) command += ");\n" return command
def setupSpeckRound(self, stp_file, x_in, y_in, x_out, y_out, w, wordsize): """ Model for differential behaviour of one round SPECK """ command = "" #Assert(x_in >>> self.rot_alpha + y_in = x_out) command += "ASSERT(" command += stpcommands.getStringAdd(rotr(x_in, self.rot_alpha, wordsize), y_in, x_out, wordsize) command += ");\n" #Assert(x_out xor (y_in <<< self.rot_beta) = x_in) command += "ASSERT(" + y_out + " = " command += "BVXOR(" + x_out + "," command += rotl(y_in, self.rot_beta, wordsize) command += "));\n" #For weight computation command += "ASSERT({0} = ~".format(w) command += stpcommands.getStringEq(rotr(x_in, self.rot_alpha, wordsize), y_in, x_out) command += ");\n" stp_file.write(command) return
def setupSpeckRound(self, stp_file, x_in, y_in, x_out, y_out, w, wordsize): """ Model for differential behaviour of one round SPECK """ command = "" #Assert(x_in >>> self.rot_alpha + y_in = x_out) command += "ASSERT(" command += stpcommands.getStringAdd( rotr(x_in, self.rot_alpha, wordsize), y_in, x_out, wordsize) command += ");\n" #Assert(x_out xor (y_in <<< self.rot_beta) = x_in) command += "ASSERT(" + y_out + " = " command += "BVXOR(" + x_out + "," command += rotl(y_in, self.rot_beta, wordsize) command += "));\n" #For weight computation command += "ASSERT({0} = ~".format(w) command += stpcommands.getStringEq( rotr(x_in, self.rot_alpha, wordsize), y_in, x_out) command += ");\n" stp_file.write(command) return
def setupSPECKEYRound(self, stp_file, x_in, y_in, x_out, y_out, w, wordsize): """ Model for the ARX box (round) function of SPARX which is the same as SPECKEY. """ command = "" #Assert((x_in >>> 7) + y_in = x_out) command += "ASSERT(" command += stpcommands.getStringAdd(rotr(x_in, 7, wordsize), y_in, x_out, wordsize) command += ");\n" #Assert(x_out xor (y_in <<< 2) = y_out) command += "ASSERT(" + y_out + " = " command += "BVXOR(" + x_out + "," command += rotl(y_in, 2, wordsize) command += "));\n" #For weight computation command += "ASSERT({0} = ~".format(w) command += stpcommands.getStringEq(rotr(x_in, 7, wordsize), y_in, x_out) command += ");\n" stp_file.write(command) return
def setupChasKeyRound(self, stp_file, rnd, v0_in, v1_in, v2_in, v3_in, v0_out, v1_out, v2_out, v3_out, w0, w1, wordsize): """ Half a round of ChasKey a0 = (v1 + v0) <<< 32 a1 = (v1 + v0) ^ (v1 <<< 13) a2 = (v2 + v3) a3 = (v2 + v3) ^ (v3 <<< 16) """ command = "" if (rnd % 2) == 0: rot_one = self.rot_v1_up rot_two = self.rot_v3_up rot_three = self.rot_v0_up else: rot_one = self.rot_v1_down rot_two = self.rot_v3_down rot_three = self.rot_v0_down #Assert intermediate values #Rotate right to get correct output value #v0_out command += "ASSERT(" command += stpcommands.getStringAdd(v2_in, v3_in, v0_out, wordsize) command += ");\n" #v1_out command += "ASSERT({} = BVXOR({}, {}));\n".format( v1_out, rotl(v1_in, rot_one, wordsize), rotr(v2_out, rot_three, wordsize)) #v2_out command += "ASSERT(" command += stpcommands.getStringAdd(v1_in, v0_in, rotr(v2_out, rot_three, wordsize), wordsize) command += ");\n" #v3_out command += "ASSERT({} = BVXOR({}, {}));\n".format( v3_out, rotl(v3_in, rot_two, wordsize), v0_out) # Compute Weights for modular addition # Lipmaa and Moriai command += "ASSERT({0} = ~".format(w0) command += stpcommands.getStringEq(v1_in, v0_in, rotr(v2_out, rot_three, wordsize)) command += ");\n" command += "ASSERT({0} = ~".format(w1) command += stpcommands.getStringEq(v2_in, v3_in, v0_out) command += ");\n" stp_file.write(command) return
def setupChasKeyRound( self, stp_file, rnd, v0_in, v1_in, v2_in, v3_in, v0_out, v1_out, v2_out, v3_out, w0, w1, wordsize ): """ Half a round of ChasKey a0 = (v1 + v0) <<< 32 a1 = (v1 + v0) ^ (v1 <<< 13) a2 = (v2 + v3) a3 = (v2 + v3) ^ (v3 <<< 16) """ command = "" if (rnd % 2) == 0: rot_one = 5 rot_two = 8 else: rot_one = 7 rot_two = 13 # Assert intermediate values # Rotate right to get correct output value # v0_out command += "ASSERT(" command += stpcommands.getStringAdd(v2_in, v3_in, v0_out, wordsize) command += ");\n" # v1_out command += "ASSERT({} = BVXOR({}, {}));\n".format( v1_out, rotl(v1_in, rot_one, wordsize), rotr(v2_out, 16, wordsize) ) # v2_out command += "ASSERT(" command += stpcommands.getStringAdd(v1_in, v0_in, rotr(v2_out, 16, wordsize), wordsize) command += ");\n" # v3_out command += "ASSERT({} = BVXOR({}, {}));\n".format(v3_out, rotl(v3_in, rot_two, wordsize), v0_out) # Compute Weights for modular addition # Lipmaa and Moriai command += "ASSERT({0} = ~".format(w0) command += stpcommands.getStringEq(v1_in, v0_in, rotr(v2_out, 16, wordsize)) command += ");\n" command += "ASSERT({0} = ~".format(w1) command += stpcommands.getStringEq(v2_in, v3_in, v0_out) command += ");\n" stp_file.write(command) return
def setupSimonKey(self, stp_file, k, rounds, wordsize): command = "" for i in range(4, rounds): tmpZ = "BVXOR({}, {})".format(rotr(k[i - 1], 3, wordsize), k[i - 3]) command += "ASSERT({} = ".format(k[i]) command += "BVXOR({}, ".format(tmpZ) command += "BVXOR({}, ".format(rotr(tmpZ, 1, wordsize)) command += "BVXOR({}, ~{}".format(k[i - 3], k[i - 4]) command += "))));\n" stp_file.write(command) return
def setupKeySchedule(self, stp_file, key, tmp_key, rounds, wordsize): command = "" const3 = "0x{}3".format("0"*(wordsize // 4 - 1)) if rounds > 4: for i in range(4, rounds): constz = "0x{}{}".format("0"*(wordsize // 4 - 1), self.CONST_Z[(i - 4) % 62]) tmp = "BVXOR({}, {})".format(rotr(key[i-1], 3, wordsize), key[i-3]) command += "ASSERT({} = BVXOR({}, {}));\n".format( tmp_key[i], tmp, rotr(tmp, 1, wordsize)) command += "ASSERT({} = BVXOR({}, BVXOR({}, BVXOR(~{}, {}))));\n".format( key[i], constz, const3, key[i-4], tmp_key[i]) stp_file.write(command) return
def setupKeySchedule(self, stp_file, key, tmp_key, rounds, wordsize): command = "" const3 = "0x{}3".format("0" * (wordsize // 4 - 1)) if rounds > 4: for i in range(4, rounds): constz = "0x{}{}".format("0" * (wordsize // 4 - 1), self.CONST_Z[(i - 4) % 62]) tmp = "BVXOR({}, {})".format(rotr(key[i - 1], 3, wordsize), key[i - 3]) command += "ASSERT({} = BVXOR({}, {}));\n".format( tmp_key[i], tmp, rotr(tmp, 1, wordsize)) command += "ASSERT({} = BVXOR({}, BVXOR({}, BVXOR(~{}, {}))));\n".format( key[i], constz, const3, key[i - 4], tmp_key[i]) stp_file.write(command) return
def pi2(self, in0, in1, in2, in3, out0, out1, out2, out3, wordsize): """ Model for the Pi2 function in NOEKEON - which is the inverse of pi1 """ command = "" command += "ASSERT({0}[31:0] = {1}[31:0]);\n".format(in0, out0) command += "ASSERT({0}[31:0] = {1}[31:0]);\n".format( rotr(in1, 1, wordsize), out1) command += "ASSERT({0}[31:0] = {1}[31:0]);\n".format( rotr(in2, 5, wordsize), out2) command += "ASSERT({0}[31:0] = {1}[31:0]);\n".format( rotr(in3, 2, wordsize), out3) return command
def getStringForSipRound(self, v0_in, v1_in, v2_in, v3_in, a0, a1, a2, a3, v0_out, v1_out, v2_out, v3_out, w0, w1, w2, w3, wordsize): """ Returns a string representing SipRound in STP. a0 = (v1 + v0) <<< 32 a1 = (v1 + v0) ^ (v1 <<< 13) a2 = (v2 + v3) a3 = (v2 + v3) ^ (v3 <<< 16) v0_out = (a0 + a3) v1_out = (a2 + a1) ^ (a1 <<< 17) v2_out = (a2 + a1) <<< 32 v3_out = (a0 + a3) ^ (a3 <<< 21) """ command = "" #Assert intermediate values #Rotate right to get correct output value #a0 command += "ASSERT(" command += stpcommands.getStringAdd(v1_in, v0_in, rotr(a0, 32, wordsize), wordsize) command += ");\n" #a1 command += "ASSERT({} = BVXOR({}, {}));\n".format( a1, rotl(v1_in, 13, wordsize), rotr(a0, 32, wordsize)) #a2 command += "ASSERT(" command += stpcommands.getStringAdd(v2_in, v3_in, a2, wordsize) command += ");\n" #a3 command += "ASSERT({} = BVXOR({}, {}));\n".format( a3, rotl(v3_in, 16, wordsize), a2) #v0_out command += "ASSERT(" command += stpcommands.getStringAdd(a0, a3, v0_out, wordsize) command += ");\n" #v1_out command += "ASSERT({} = BVXOR({}, {}));\n".format( v1_out, rotl(a1, 17, wordsize), rotr(v2_out, 32, wordsize)) #v2_out command += "ASSERT(" command += stpcommands.getStringAdd(a2, a1, rotr(v2_out, 32, wordsize), wordsize) command += ");\n" #v3_out command += "ASSERT({} = BVXOR({}, {}));\n".format( v3_out, rotl(a3, 21, wordsize), v0_out) # Lipmaa and Moriai command += "ASSERT({0} = ~".format(w0) command += stpcommands.getStringEq(v1_in, v0_in, rotr(a0, 32, wordsize)) command += ");\n" command += "ASSERT({0} = ~".format(w1) command += stpcommands.getStringEq(v2_in, v3_in, a2) command += ");\n" command += "ASSERT({0} = ~".format(w2) command += stpcommands.getStringEq(a0, a3, v0_out) command += ");\n" command += "ASSERT({0} = ~".format(w3) command += stpcommands.getStringEq(a2, a1, rotr(v2_out, 32, wordsize)) command += ");\n" return command
def setupAsconRound(self, stp_file, rnd, s, a, b, c, wordsize, tmp, w, xin, xout, andout): """ Model for one round of Ascon. """ command = "" weight_sum = "" # Linear part in S-box command += "ASSERT({} = BVXOR({}, {}));\n".format( a[0 + 5 * rnd], s[0 + 5 * rnd], s[4 + 5 * rnd]) command += "ASSERT({} = {});\n".format(a[1 + 5 * rnd], s[1 + 5 * rnd]) command += "ASSERT({} = BVXOR({}, {}));\n".format( a[2 + 5 * rnd], s[2 + 5 * rnd], s[1 + 5 * rnd]) command += "ASSERT({} = {});\n".format(a[3 + 5 * rnd], s[3 + 5 * rnd]) command += "ASSERT({} = BVXOR({}, {}));\n".format( a[4 + 5 * rnd], s[4 + 5 * rnd], s[3 + 5 * rnd]) # Model for the S-box for z in range(wordsize): # Construct S-box input command += "ASSERT({}={});\n".format( xin[z + 5 * wordsize * rnd], a[0 + 5 * rnd] + "[{0}:{0}]".format(z) + "@" + a[1 + 5 * rnd] + "[{0}:{0}]".format(z) + "@" + a[2 + 5 * rnd] + "[{0}:{0}]".format(z) + "@" + a[3 + 5 * rnd] + "[{0}:{0}]".format(z) + "@" + a[4 + 5 * rnd] + "[{0}:{0}]".format(z)) # Construct S-box output command += "ASSERT({}={});\n".format( xout[z + 5 * wordsize * rnd], b[0 + 5 * rnd] + "[{0}:{0}]".format(z) + "@" + b[1 + 5 * rnd] + "[{0}:{0}]".format(z) + "@" + b[2 + 5 * rnd] + "[{0}:{0}]".format(z) + "@" + b[3 + 5 * rnd] + "[{0}:{0}]".format(z) + "@" + b[4 + 5 * rnd] + "[{0}:{0}]".format(z)) xin_rotalpha = rotl(xin[z + 5 * wordsize * rnd], 2, 5) xin_rotbeta = rotl(xin[z + 5 * wordsize * rnd], 1, 5) #Deal with dependent inputs varibits = "({0} | {1})".format(xin_rotalpha, xin_rotbeta) doublebits = self.getDoubleBits(xin[z + 5 * wordsize * rnd]) #Check for valid difference firstcheck = "({} & ~{})".format(andout[z + 5 * wordsize * rnd], varibits) secondcheck = "(~BVXOR({}, {}) & {})".format( andout[z + 5 * wordsize * rnd], rotl(andout[z + 5 * wordsize * rnd], 2 - 1, 5), doublebits) thirdcheck = "(IF {0} = 0b{1} THEN BVMOD(5, {0}, 0b00010) ELSE 0b{2}ENDIF)".format( xin[z + 5 * wordsize * rnd], "11111", "00000") command += "ASSERT(({} | {} | {}) = 0b{});\n".format( firstcheck, secondcheck, thirdcheck, "00000") #Assert XORs command += "ASSERT({} = BVXOR({},{}));\n".format( xout[z + 5 * wordsize * rnd], xin[z + 5 * wordsize * rnd], andout[z + 5 * wordsize * rnd]) #Weight computation command += ( "ASSERT({0} = (IF {1} = 0b{4} THEN BVSUB({5},0b{4},0b{6}1)" "ELSE BVXOR({2}, {3}) ENDIF));\n".format( tmp[z + 5 * wordsize * rnd], xin[z + 5 * wordsize * rnd], varibits, doublebits, "1" * 5, 5, "0" * 4)) weight_sum += ("0b{0}@(BVPLUS({1}, {2}[0:0], {2}[1:1], " "{2}[2:2],{2}[3:3], {2}[4:4])),".format( "0" * 11, 5, "0b0000@" + tmp[z + 5 * wordsize * rnd])) command += "ASSERT({}=BVPLUS({},{}));\n".format( w[rnd], 16, weight_sum[:-1]) # Linear after S-box command += "ASSERT({} = BVXOR({}, {}));\n".format( c[0 + 5 * rnd], b[0 + 5 * rnd], b[4 + 5 * rnd]) command += "ASSERT({} = BVXOR({}, {}));\n".format( c[1 + 5 * rnd], b[0 + 5 * rnd], b[1 + 5 * rnd]) command += "ASSERT({} = {});\n".format(c[2 + 5 * rnd], b[2 + 5 * rnd]) command += "ASSERT({} = BVXOR({}, {}));\n".format( c[3 + 5 * rnd], b[2 + 5 * rnd], b[3 + 5 * rnd]) command += "ASSERT({} = {});\n".format(c[4 + 5 * rnd], b[4 + 5 * rnd]) # Linear functions rot_constants = [[19, 28], [61, 39], [1, 6], [10, 17], [7, 41]] for row in range(5): command += "ASSERT({} = BVXOR({}, BVXOR({}, {})));\n".format( s[row + 5 * (rnd + 1)], c[row + 5 * rnd], rotr(c[row + 5 * rnd], rot_constants[row][0], wordsize), rotr(c[row + 5 * rnd], rot_constants[row][1], wordsize), ) stp_file.write(command) return
def setupSimonRound(self, stp_file, x_in, y_in, x_out, y_out, and_out, b, c, abits, w, tmpWeight, sbits, pbits, wordsize): """ Model for linear behaviour of one round SIMON. y[i+1] = x[i] x[i+1] = (x[i] <<< 1) & (x[i] <<< 8) ^ y[i] ^ (x[i] << 2) This is a loop unrolled version of the model presented in http://eprint.iacr.org/2015/145 """ command = "" deltarot = self.rot_alpha - self.rot_beta lout = y_in lin = "BVXOR(BVXOR({}, {}), {})".format( x_in, rotr(lout, self.rot_gamma, wordsize), y_out) #lin = "BVXOR({}, {})".format(x_in, rotr(lout, self.rot_gamma, wordsize)) #Assert(y_out = x_in) command += "ASSERT({} = {});\n".format(x_out, y_in) #Assert for AND linear approximation tmp = "BVXOR(({0} | {1}), {2}) & {2}".format( rotr(lout, self.rot_alpha, wordsize), rotr(lout, self.rot_beta, wordsize), lin) command += "ASSERT({} = 0x{});\n".format(tmp, "0" * (wordsize // 4)) #Assert for y_out # command += "ASSERT({0} = BVXOR({1}, BVXOR({2}, BVXOR({3}, {4}))));\n".format( # y_out, x_in, rotr(lout, self.rot_alpha, wordsize), rotr(lout, self.rot_beta, wordsize), # rotr(x_out, self.rot_gamma, wordsize)) command += "ASSERT({0} = BVXOR({1}, BVXOR({2}, {3})));\n".format( y_out, x_in, rotr(x_out, self.rot_gamma, wordsize), lin) #For weight computation #Compute abits loutRotated = rotr(lout, deltarot, wordsize) command += "ASSERT({} = ({} & {}));\n".format(tmpWeight[0], lout, loutRotated) for i in range(1, wordsize): command += "ASSERT({} = ({} & {}));\n".format( tmpWeight[i], lout, rotr(tmpWeight[i - 1], deltarot, wordsize)) abits = "BVXOR({}, {})".format(lout, tmpWeight[0]) for i in range(1, wordsize): abits = "BVXOR({}, {})".format(tmpWeight[i], abits) #abits = y_in #only use weight #Weight computation #command += "ASSERT({0} = (IF {1} = 0x{3} THEN BVSUB({4},0x{3},0x{5}1) \ # ELSE {2} ENDIF));\n".format( # w, y_in, abits, "f"*(wordsize / 4), # wordsize, "0"*((wordsize / 4) - 1)) command += "ASSERT({} = {});\n".format(w, abits) #Parity Checks command += "ASSERT({} = {});\n".format( sbits[0], rotr( "({} & ~{} & ~{})".format(rotr(lout, deltarot, wordsize), lout, rotr(abits, deltarot, wordsize)), 1, wordsize)) command += "ASSERT({} = {});\n".format( pbits[0], rotl("({} & {})".format(sbits[0], lin), 2 * deltarot, wordsize)) for i in range(1, wordsize): command += "ASSERT({} = {});\n".format( sbits[i], rotl( "({} & {})".format( rotl(sbits[i - 1], deltarot, wordsize), rotr(sbits[i - 1], self.rot_beta, wordsize)), deltarot, wordsize)) command += "ASSERT({} = {});\n".format( pbits[i], rotl("BVXOR({}, {} & {})".format(pbits[i - 1], sbits[i], lin), 2 * deltarot, wordsize)) command += "ASSERT({} = 0x{});\n".format(pbits[wordsize - 1], "0" * (wordsize // 4)) stp_file.write(command) return
def setupAsconRound(self, stp_file, rnd, s, a, b, c, wordsize, tmp, w, xin, xout, andout): """ Model for one round of Ascon. """ command = "" weight_sum = "" # Linear part in S-box command += "ASSERT({} = BVXOR({}, {}));\n".format(a[0 + 5*rnd], s[0 + 5*rnd], s[4 + 5*rnd]) command += "ASSERT({} = {});\n".format(a[1 + 5*rnd], s[1 + 5*rnd]) command += "ASSERT({} = BVXOR({}, {}));\n".format(a[2 + 5*rnd], s[2 + 5*rnd], s[1 + 5*rnd]) command += "ASSERT({} = {});\n".format(a[3 + 5*rnd], s[3 + 5*rnd]) command += "ASSERT({} = BVXOR({}, {}));\n".format(a[4 + 5*rnd], s[4 + 5*rnd], s[3 + 5*rnd]) # Model for the S-box for z in range(wordsize): # Construct S-box input command += "ASSERT({}={});\n".format( xin[z + 5*wordsize*rnd], a[0 + 5*rnd] + "[{0}:{0}]".format(z) + "@" + a[1 + 5*rnd] + "[{0}:{0}]".format(z) + "@" + a[2 + 5*rnd] + "[{0}:{0}]".format(z) + "@" + a[3 + 5*rnd] + "[{0}:{0}]".format(z) + "@" + a[4 + 5*rnd] + "[{0}:{0}]".format(z)) # Construct S-box output command += "ASSERT({}={});\n".format( xout[z + 5*wordsize*rnd], b[0 + 5*rnd] + "[{0}:{0}]".format(z) + "@" + b[1 + 5*rnd] + "[{0}:{0}]".format(z) + "@" + b[2 + 5*rnd] + "[{0}:{0}]".format(z) + "@" + b[3 + 5*rnd] + "[{0}:{0}]".format(z) + "@" + b[4 + 5*rnd] + "[{0}:{0}]".format(z)) xin_rotalpha = rotl(xin[z + 5*wordsize*rnd], 2, 5) xin_rotbeta = rotl(xin[z + 5*wordsize*rnd], 1, 5) #Deal with dependent inputs varibits = "({0} | {1})".format(xin_rotalpha, xin_rotbeta) doublebits = self.getDoubleBits(xin[z + 5*wordsize*rnd]) #Check for valid difference firstcheck = "({} & ~{})".format(andout[z + 5*wordsize*rnd], varibits) secondcheck = "(~BVXOR({}, {}) & {})".format( andout[z + 5*wordsize*rnd], rotl(andout[z + 5*wordsize*rnd], 2 - 1, 5), doublebits) thirdcheck = "(IF {0} = 0b{1} THEN BVMOD(5, {0}, 0b00010) ELSE 0b{2}ENDIF)".format( xin[z + 5*wordsize*rnd], "11111", "00000") command += "ASSERT(({} | {} | {}) = 0b{});\n".format(firstcheck, secondcheck, thirdcheck, "00000") #Assert XORs command += "ASSERT({} = BVXOR({},{}));\n".format( xout[z + 5*wordsize*rnd], xin[z + 5*wordsize*rnd], andout[z + 5*wordsize*rnd]) #Weight computation command += ("ASSERT({0} = (IF {1} = 0b{4} THEN BVSUB({5},0b{4},0b{6}1)" "ELSE BVXOR({2}, {3}) ENDIF));\n".format( tmp[z + 5*wordsize*rnd], xin[z + 5*wordsize*rnd], varibits, doublebits, "1"*5, 5, "0"*4)) weight_sum += ("0b{0}@(BVPLUS({1}, {2}[0:0], {2}[1:1], " "{2}[2:2],{2}[3:3], {2}[4:4])),".format("0"*11, 5, "0b0000@" + tmp[z + 5*wordsize*rnd])) command += "ASSERT({}=BVPLUS({},{}));\n".format(w[rnd], 16, weight_sum[:-1]) # Linear after S-box command += "ASSERT({} = BVXOR({}, {}));\n".format(c[0 + 5*rnd], b[0 + 5*rnd], b[4 + 5*rnd]) command += "ASSERT({} = BVXOR({}, {}));\n".format(c[1 + 5*rnd], b[0 + 5*rnd], b[1 + 5*rnd]) command += "ASSERT({} = {});\n".format(c[2 + 5*rnd], b[2 + 5*rnd]) command += "ASSERT({} = BVXOR({}, {}));\n".format(c[3 + 5*rnd], b[2 + 5*rnd], b[3 + 5*rnd]) command += "ASSERT({} = {});\n".format(c[4 + 5*rnd], b[4 + 5*rnd]) # Linear functions rot_constants = [[19, 28], [61, 39], [1, 6], [10, 17], [7, 41]] for row in range(5): command += "ASSERT({} = BVXOR({}, BVXOR({}, {})));\n".format( s[row + 5 * (rnd + 1)], c[row + 5*rnd], rotr(c[row + 5*rnd], rot_constants[row][0], wordsize), rotr(c[row + 5*rnd], rot_constants[row][1], wordsize), ) stp_file.write(command) return
def getStringForSipRound(self, v0_in, v1_in, v2_in, v3_in, a0, a1, a2, a3, v0_out, v1_out, v2_out, v3_out, w0, w1, w2, w3, wordsize): """ Returns a string representing SipRound in STP. a0 = (v1 + v0) <<< 32 a1 = (v1 + v0) ^ (v1 <<< 13) a2 = (v2 + v3) a3 = (v2 + v3) ^ (v3 <<< 16) v0_out = (a0 + a3) v1_out = (a2 + a1) ^ (a1 <<< 17) v2_out = (a2 + a1) <<< 32 v3_out = (a0 + a3) ^ (a3 <<< 21) """ command = "" #Assert intermediate values #Rotate right to get correct output value #a0 command += "ASSERT(" command += stpcommands.getStringAdd( v1_in, v0_in, rotr(a0, 32, wordsize), wordsize) command += ");\n" #a1 command += "ASSERT({} = BVXOR({}, {}));\n".format( a1, rotl(v1_in, 13, wordsize), rotr(a0, 32, wordsize)) #a2 command += "ASSERT(" command += stpcommands.getStringAdd(v2_in, v3_in, a2, wordsize) command += ");\n" #a3 command += "ASSERT({} = BVXOR({}, {}));\n".format( a3, rotl(v3_in, 16, wordsize), a2) #v0_out command += "ASSERT(" command += stpcommands.getStringAdd(a0, a3, v0_out, wordsize) command += ");\n" #v1_out command += "ASSERT({} = BVXOR({}, {}));\n".format( v1_out, rotl(a1, 17, wordsize), rotr(v2_out, 32, wordsize)) #v2_out command += "ASSERT(" command += stpcommands.getStringAdd( a2, a1, rotr(v2_out, 32, wordsize), wordsize) command += ");\n" #v3_out command += "ASSERT({} = BVXOR({}, {}));\n".format( v3_out, rotl(a3, 21, wordsize), v0_out) # Lipmaa and Moriai command += "ASSERT({0} = ~".format(w0) command += stpcommands.getStringEq( v1_in, v0_in, rotr(a0, 32, wordsize)) command += ");\n" command += "ASSERT({0} = ~".format(w1) command += stpcommands.getStringEq(v2_in, v3_in, a2) command += ");\n" command += "ASSERT({0} = ~".format(w2) command += stpcommands.getStringEq(a0, a3, v0_out) command += ");\n" command += "ASSERT({0} = ~".format(w3) command += stpcommands.getStringEq( a2, a1, rotr(v2_out, 32, wordsize)) command += ");\n" return command
def setupSimonRound(self, stp_file, x_in, y_in, x_out, y_out, and_out, b, c, abits, w, tmpWeight, sbits, pbits, wordsize): """ Model for linear behaviour of one round SIMON. y[i+1] = x[i] x[i+1] = (x[i] <<< 1) & (x[i] <<< 8) ^ y[i] ^ (x[i] << 2) This is a loop unrolled version of the model presented in http://eprint.iacr.org/2015/145 """ command = "" deltarot = self.rot_alpha - self.rot_beta lout = y_in lin = "BVXOR(BVXOR({}, {}), {})".format(x_in, rotr(lout, self.rot_gamma, wordsize), y_out) #lin = "BVXOR({}, {})".format(x_in, rotr(lout, self.rot_gamma, wordsize)) #Assert(y_out = x_in) command += "ASSERT({} = {});\n".format(x_out, y_in) #Assert for AND linear approximation tmp = "BVXOR(({0} | {1}), {2}) & {2}".format( rotr(lout, self.rot_alpha, wordsize), rotr(lout, self.rot_beta, wordsize), lin) command += "ASSERT({} = 0x{});\n".format(tmp, "0"*(wordsize // 4)) #Assert for y_out # command += "ASSERT({0} = BVXOR({1}, BVXOR({2}, BVXOR({3}, {4}))));\n".format( # y_out, x_in, rotr(lout, self.rot_alpha, wordsize), rotr(lout, self.rot_beta, wordsize), # rotr(x_out, self.rot_gamma, wordsize)) command += "ASSERT({0} = BVXOR({1}, BVXOR({2}, {3})));\n".format( y_out, x_in, rotr(x_out, self.rot_gamma, wordsize), lin) #For weight computation #Compute abits loutRotated = rotr(lout, deltarot, wordsize) command += "ASSERT({} = ({} & {}));\n".format(tmpWeight[0], lout, loutRotated) for i in range(1, wordsize): command += "ASSERT({} = ({} & {}));\n".format( tmpWeight[i], lout, rotr(tmpWeight[i - 1], deltarot, wordsize)) abits = "BVXOR({}, {})".format(lout, tmpWeight[0]) for i in range(1, wordsize): abits = "BVXOR({}, {})".format(tmpWeight[i], abits) #abits = y_in #only use weight #Weight computation #command += "ASSERT({0} = (IF {1} = 0x{3} THEN BVSUB({4},0x{3},0x{5}1) \ # ELSE {2} ENDIF));\n".format( # w, y_in, abits, "f"*(wordsize / 4), # wordsize, "0"*((wordsize / 4) - 1)) command += "ASSERT({} = {});\n".format(w, abits) #Parity Checks command += "ASSERT({} = {});\n".format( sbits[0], rotr("({} & ~{} & ~{})".format( rotr(lout, deltarot, wordsize), lout, rotr(abits, deltarot, wordsize)), 1, wordsize)) command += "ASSERT({} = {});\n".format( pbits[0], rotl("({} & {})".format(sbits[0], lin), 2*deltarot, wordsize)) for i in range(1, wordsize): command += "ASSERT({} = {});\n".format( sbits[i], rotl("({} & {})".format( rotl(sbits[i - 1], deltarot, wordsize), rotr(sbits[i-1], self.rot_beta, wordsize)), deltarot, wordsize) ) command += "ASSERT({} = {});\n".format( pbits[i], rotl("BVXOR({}, {} & {})".format( pbits[i - 1], sbits[i], lin), 2*deltarot, wordsize) ) command += "ASSERT({} = 0x{});\n".format(pbits[wordsize - 1], "0"*(wordsize // 4)) stp_file.write(command) return