Beispiel #1
0
    def __init__(self, matNameP, matrixP, matNameP_inv, matrixP_inv, matNameFL,
                 matrixFL, matNameFL_inv, matrixFL_inv, sboxName, sbox,
                 sboxDim, numberOfSbox, dim, r, mid_r, inVec, outVec):

        self._sbox = AssertSbox(sboxName, sbox, sboxDim, r, numberOfSbox)

        self._matNameFL = matNameFL
        self._matrixFL = matrixFL
        self._matNameFL_inv = matNameFL_inv
        self._matrixFL_inv = matrixFL_inv
        self._matNameP = matNameP
        self._matrixP = matrixP

        self._matNameP_inv = matNameP_inv
        self._matrixP_inv = matrixP_inv

        self._dim = dim
        self._round = r
        self._midRound = mid_r
        self._constrs = []
        self._vars = dict()
        self._inVec = inVec
        self._outVec = outVec

        self._constrs += self._sbox.get_asserts_declares()
Beispiel #2
0
    def __init__(self, matNameFL, matrixFL, matNameFO, matrixFO,
                 matNameFI_zero_extended, matrixFI_zero_extended,
                 matNameFI_truncate, matrixFI_truncate, sboxName9, sbox9,
                 sboxDim9, numberOfSbox9, sboxName7, sbox7, sboxDim7,
                 numberOfSbox7, dim, r, inVec, outVec):

        self._sbox9 = AssertSbox(sboxName9, sbox9, sboxDim9, r, numberOfSbox9)
        self._sbox7 = AssertSbox(sboxName7, sbox7, sboxDim7, r, numberOfSbox7)
        self._sboxDim9 = sboxDim9
        self._sboxDim7 = sboxDim7

        self._matrixNameFL = matNameFL
        self._matrixFL = matrixFL

        self._matrixNameFO = matNameFO
        self._matrixFO = matrixFO
        self._matrixNameFI_zero_extended = matNameFI_zero_extended
        self._matrixFI_zero_extended = matrixFI_zero_extended
        self._matrixNameFI_truncate = matNameFI_truncate
        self._matrixFI_truncate = matrixFI_truncate

        self._dim = dim
        self._round = r
        self._constrs = []
        self._vars = dict()
        self._inVec = inVec
        self._outVec = outVec

        self._constrs += self._sbox9.get_asserts_declares()
        self._constrs += self._sbox7.get_asserts_declares()
Beispiel #3
0
 def __init__(self, matName, matrix, sboxName, sbox, sboxDim, dim, r,
              numberOfSbox, inVec, outVec):
     self.__sbox = AssertSbox(sboxName, sbox, sboxDim, r, numberOfSbox)
     self.__matName = matName
     self.__matrix = matrix
     self.__sboxDim = sboxDim
     self.__dim = dim
     self.__round = r
     self.__constrs = []
     self.__variables = self.__declareVariables()
     self.__afterSboxVariables = self.__declareSboxVariables()
     self.__constrs += self.__sbox.get_asserts_declares()
     self.__gen_round_constrs()
     self.__gen_init_constrs(inVec, outVec)
Beispiel #4
0
    def __init__(self, S0_name, S0, S0_dim, S0_num, S1_name, S1, S1_dim,
                 S1_num, M0_name, M0, M1_name, M1, dim, r, inVec, outVec):

        self._s0 = AssertSbox(S0_name, S0, S0_dim, r, S0_num)
        self._s1 = AssertSbox(S1_name, S1, S1_dim, r, S1_num)

        self._s0dim = S0_dim
        self._s1dim = S1_dim

        self._matrixName_M0 = M0_name
        self._matrix_M0 = M0

        self._matrixName_M1 = M1_name
        self._matrix_M1 = M1

        self._dim = dim
        self._round = r
        self._constrs = []
        self._vars = dict()
        self._inVec = inVec
        self._outVec = outVec

        self._constrs += self._s0.get_asserts_declares()
        self._constrs += self._s1.get_asserts_declares()
Beispiel #5
0
class CLEFIA(object):
    def __init__(self, S0_name, S0, S0_dim, S0_num, S1_name, S1, S1_dim,
                 S1_num, M0_name, M0, M1_name, M1, dim, r, inVec, outVec):

        self._s0 = AssertSbox(S0_name, S0, S0_dim, r, S0_num)
        self._s1 = AssertSbox(S1_name, S1, S1_dim, r, S1_num)

        self._s0dim = S0_dim
        self._s1dim = S1_dim

        self._matrixName_M0 = M0_name
        self._matrix_M0 = M0

        self._matrixName_M1 = M1_name
        self._matrix_M1 = M1

        self._dim = dim
        self._round = r
        self._constrs = []
        self._vars = dict()
        self._inVec = inVec
        self._outVec = outVec

        self._constrs += self._s0.get_asserts_declares()
        self._constrs += self._s1.get_asserts_declares()

    def _declare(self, varName, dim=1):
        return '%s:BITVECTOR(%d);' % (varName, dim)

    def _addConstr(self, asserts):
        self._constrs.append(asserts)

    def _declareV(self, varName, round_dim, one_round_dim):
        self._vars[varName] = [[None for x in range(one_round_dim)]
                               for x in range(round_dim)]
        for r in range(round_dim):
            for p in range(one_round_dim):
                varx = '%s_%d_%d' % (varName, r, p)
                self._vars[varName][r][p] = varx
                self._addConstr(self._declare(varx))

    def _Kxor(self, a0, a1, b):
        s = 'ASSERT '
        s += '~' + a0 + ' | ~' + a1 + '= 0bin1;\n'
        s += 'ASSERT '
        s += a0 + ' | ' + a1 + ' | ~' + b + '= 0bin1;\n'
        s += 'ASSERT '
        s += a0 + ' | ~' + a1 + ' | ' + b + '= 0bin1;\n'
        s += 'ASSERT '
        s += '~' + a0 + ' | ' + a1 + ' | ' + b + '= 0bin1;'

        return s

    def _Kcopy(self, a, b0, b1):
        s = 'ASSERT '
        s += '~' + b0 + ' | ~' + b1 + ' = 0bin1;\n'
        s += 'ASSERT '
        s += a + ' | ' + b0 + ' | ~' + b1 + ' = 0bin1;\n'
        s += 'ASSERT '
        s += a + ' | ' + '~' + b0 + ' | ' + b1 + ' = 0bin1;\n'
        s += 'ASSERT '
        s += '~' + a + ' | ' + b0 + ' | ' + b1 + ' = 0bin1;'

        return s

    def _block_copy(self, inV, outV1, outV2):
        dim = len(inV)
        for i in range(dim):
            self._addConstr(self._Kcopy(inV[i], outV1[i], outV2[i]))

    def _block_xor(self, inV, outV1, outV2):
        dim = len(inV)
        for i in range(dim):
            self._addConstr(self._Kxor(inV[i], outV1[i], outV2[i]))

    def _declareVariables(self):
        self._declareV('CLEFIA_X', self._round + 1, self._dim)
        self._declareV('CLEFIA_F0_IN', self._round, self._dim // 4)
        self._declareV('CLEFIA_F1_IN', self._round, self._dim // 4)
        self._declareV('CLEFIA_F0_S_OUT', self._round, self._dim // 4)
        self._declareV('CLEFIA_F1_S_OUT', self._round, self._dim // 4)
        self._declareV('CLEFIA_F0_OUT', self._round, self._dim // 4)
        self._declareV('CLEFIA_F1_OUT', self._round, self._dim // 4)

    def _F0(self, F0_in, sbox_out, F0_out, r):
        self._constrs.append(
            self._s0.build_constrs(F0_in[0:8], sbox_out[0:8], r, 0))

        self._constrs.append(
            self._s1.build_constrs(F0_in[8:16], sbox_out[8:16], r, 0))

        self._constrs.append(
            self._s0.build_constrs(F0_in[16:24], sbox_out[16:24], r, 1))

        self._constrs.append(
            self._s1.build_constrs(F0_in[24:32], sbox_out[24:32], r, 1))

        m = Matrix(self._matrixName_M0, self._matrix_M0, sbox_out, F0_out, r,
                   0)
        self._constrs += m.get_declares_asserts()

    def _F1(self, F0_in, sbox_out, F0_out, r):
        self._constrs.append(
            self._s1.build_constrs(F0_in[0:8], sbox_out[0:8], r, 2))

        self._constrs.append(
            self._s0.build_constrs(F0_in[8:16], sbox_out[8:16], r, 2))

        self._constrs.append(
            self._s1.build_constrs(F0_in[16:24], sbox_out[16:24], r, 3))

        self._constrs.append(
            self._s0.build_constrs(F0_in[24:32], sbox_out[24:32], r, 3))

        m = Matrix(self._matrixName_M1, self._matrix_M1, sbox_out, F0_out, r,
                   0)
        self._constrs += m.get_declares_asserts()

    def _gen_round_constrs(self):
        for r in range(self._round):
            self._block_copy(self._vars['CLEFIA_X'][r][0:32],
                             self._vars['CLEFIA_F0_IN'][r],
                             self._vars['CLEFIA_X'][r + 1][96:128])
            self._F0(self._vars['CLEFIA_F0_IN'][r],
                     self._vars['CLEFIA_F0_S_OUT'][r],
                     self._vars['CLEFIA_F0_OUT'][r], r)
            self._block_xor(self._vars['CLEFIA_F0_OUT'][r],
                            self._vars['CLEFIA_X'][r][32:64],
                            self._vars['CLEFIA_X'][r + 1][0:32])

            self._block_copy(self._vars['CLEFIA_X'][r][64:96],
                             self._vars['CLEFIA_F1_IN'][r],
                             self._vars['CLEFIA_X'][r + 1][32:64])
            self._F1(self._vars['CLEFIA_F1_IN'][r],
                     self._vars['CLEFIA_F1_S_OUT'][r],
                     self._vars['CLEFIA_F1_OUT'][r], r)
            self._block_xor(self._vars['CLEFIA_F1_OUT'][r],
                            self._vars['CLEFIA_X'][r][96:128],
                            self._vars['CLEFIA_X'][r + 1][64:96])

    def _gen_init_constrs(self):
        for i in range(self._dim):
            if i in self._inVec:
                self._addConstr('ASSERT %s = 0bin1;' %
                                self._vars['CLEFIA_X'][0][i])
            else:
                self._addConstr('ASSERT %s = 0bin0;' %
                                self._vars['CLEFIA_X'][0][i])

        for i in [x for x in range(32)] + [x for x in range(64, 96)]:
            self._addConstr('ASSERT %s = 0bin0;' %
                            self._vars['CLEFIA_X'][self._round][i])

        s = 'ASSERT BVPLUS(10,'
        for i in [x for x in range(32, 64)] + [x for x in range(96, 127)]:
            s += '0bin000000000@%s,' % self._vars['CLEFIA_X'][self._round][i]
        s += '0bin000000000@%s ) = 0bin0000000001;' % self._vars['CLEFIA_X'][
            self._round][127]

        self._constrs.append('QUERY FALSE;')
        #self._constrs.append( 'COUNTEREXAMPLE;')

    def getConstrs(self):
        self._declareVariables()
        self._gen_round_constrs()
        self._gen_init_constrs()

        return self._constrs
Beispiel #6
0
class AES(object):
    def __init__(self, matName, matrix, sboxName, sbox, sboxDim, dim, r,
                 numberOfSbox, inVec, outVec):
        self.__sbox = AssertSbox(sboxName, sbox, sboxDim, r, numberOfSbox)
        self.__matName = matName
        self.__matrix = matrix
        self.__sboxDim = sboxDim
        self.__dim = dim
        self.__round = r
        self.__constrs = []
        self.__variables = self.__declareVariables()
        self.__afterSboxVariables = self.__declareSboxVariables()
        self.__constrs += self.__sbox.get_asserts_declares()
        self.__gen_round_constrs()
        self.__gen_init_constrs(inVec, outVec)

    def __bin(self, num, length):
        return '0bin' + bin(num)[2:].zfill(length)

    def __declareVariables(self):
        # declare the round variables
        variables = [[0 for x in range(self.__dim)]
                     for x in range(self.__round + 1)]
        for r in range(self.__round + 1):
            for p in range(self.__dim):
                s = 'AES_X_%d_%d' % (r, p)
                variables[r][p] = s
                s = '%s:BITVECTOR(1);' % s
                self.__constrs.append(s)
        return variables

    def __declareSboxVariables(self):
        afterSboxVariables = [[0 for x in range(self.__dim)]
                              for x in range(self.__round)]
        for r in range(self.__round):
            for p in range(self.__dim):
                s = 'AES_SBOX_%d_%d' % (r, p)
                afterSboxVariables[r][p] = s
                s = '%s:BITVECTOR(1);' % s
                self.__constrs.append(s)
        return afterSboxVariables

    def __gen_round_constrs(self):
        '''
        constraints for model
        '''

        # pass sbox
        for r in range(self.__round):
            for p in range(int(self.__dim / self.__sboxDim)):
                self.__constrs.append(
                    self.__sbox.build_constrs(
                        self.__variables[r][self.__sboxDim * p:self.__sboxDim *
                                            (p + 1)],
                        self.__afterSboxVariables[r][self.__sboxDim *
                                                     p:self.__sboxDim *
                                                     (p + 1)], r, p), )
        # pass shiftRows and MixColumn
        # 0  1  2  3             0  1  2  3
        # 4  5  6  7   ----->    5  6  7  4
        # 8  9  10 11            10 11 8  9
        # 12 13 14 15            15 12 13 14
            inVec0 = self.__afterSboxVariables[r][0:self.__sboxDim]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 5 : self.__sboxDim * 6 ]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 10: self.__sboxDim * 11]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 15: self.__sboxDim * 16]
            inVec1 = self.__afterSboxVariables[r][self.__sboxDim * 1: self.__sboxDim * 2] \
                    +self.__afterSboxVariables[r][self.__sboxDim * 6: self.__sboxDim * 7]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 11:self.__sboxDim * 12]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 12:self.__sboxDim * 13]
            inVec2 = self.__afterSboxVariables[r][self.__sboxDim * 2 :self.__sboxDim * 3] \
                    +self.__afterSboxVariables[r][self.__sboxDim * 7: self.__sboxDim * 8] \
                    +self.__afterSboxVariables[r][self.__sboxDim * 8 :self.__sboxDim * 9] \
                    +self.__afterSboxVariables[r][self.__sboxDim * 13: self.__sboxDim *14]
            inVec3 = self.__afterSboxVariables[r][self.__sboxDim * 3: self.__sboxDim * 4]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 4:self.__sboxDim * 5] \
                    +self.__afterSboxVariables[r][self.__sboxDim * 9: self.__sboxDim * 10]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 14: self.__sboxDim * 15]

            outVec0 = self.__variables[r+1][self.__sboxDim * 0: self.__sboxDim * 1]\
                  +   self.__variables[r+1][self.__sboxDim * 4: self.__sboxDim * 5]\
                  +   self.__variables[r+1][self.__sboxDim * 8: self.__sboxDim * 9]\
                  +   self.__variables[r+1][self.__sboxDim * 12: self.__sboxDim * 13]
            outVec1 = self.__variables[r+1][self.__sboxDim * 1: self.__sboxDim * 2]\
                  +   self.__variables[r+1][self.__sboxDim * 5: self.__sboxDim * 6]\
                  +   self.__variables[r+1][self.__sboxDim * 9: self.__sboxDim * 10]\
                  +   self.__variables[r+1][self.__sboxDim * 13: self.__sboxDim * 14]
            outVec2 = self.__variables[r+1][self.__sboxDim * 2: self.__sboxDim * 3]\
                  +   self.__variables[r+1][self.__sboxDim * 6: self.__sboxDim * 7]\
                  +   self.__variables[r+1][self.__sboxDim * 10: self.__sboxDim * 11]\
                  +   self.__variables[r+1][self.__sboxDim * 14: self.__sboxDim * 15]
            outVec3 = self.__variables[r+1][self.__sboxDim * 3: self.__sboxDim * 4]\
                  +   self.__variables[r+1][self.__sboxDim * 7: self.__sboxDim * 8]\
                  +   self.__variables[r+1][self.__sboxDim * 11: self.__sboxDim * 12]\
                  +   self.__variables[r+1][self.__sboxDim * 15: self.__sboxDim * 16]

            m = Matrix(self.__matName, self.__matrix, inVec0, outVec0, r, 0)
            self.__constrs += m.get_declares_asserts()

            m = Matrix(self.__matName, self.__matrix, inVec1, outVec1, r, 1)
            self.__constrs += m.get_declares_asserts()

            m = Matrix(self.__matName, self.__matrix, inVec2, outVec2, r, 2)
            self.__constrs += m.get_declares_asserts()

            m = Matrix(self.__matName, self.__matrix, inVec3, outVec3, r, 3)
            self.__constrs += m.get_declares_asserts()

    def __gen_init_constrs(self, constants, tail):
        for i in range(self.__dim):
            if i in constants:
                self.__constrs.append('ASSERT %s = 0bin1;' %
                                      self.__variables[0][i])
            else:
                self.__constrs.append('ASSERT %s = 0bin0;' %
                                      self.__variables[0][i])

        # C_0 + C_1 + ... + C_63 = 0
        s = 'ASSERT BVPLUS(10, 0bin000000000@%s ' % self.__variables[
            self.__round][0]
        for i in range(1, 64):
            s += ', 0bin000000000@%s' % self.__variables[self.__round][i]
        s += ') = 0bin0000000001;'
        self.__constrs.append(s)
        self.__constrs.append('QUERY FALSE;')
        #self.__constrs.append( 'COUNTEREXAMPLE;' )

    def getConstrs(self):
        return self.__constrs
Beispiel #7
0
class AES(object):
    def __init__(self, fname, f, matName, matrix, sboxName, sbox, sboxDim, dim,
                 r, numberOfSbox, inVec, outVec):
        self.__sbox = AssertSbox(sboxName, sbox, sboxDim, r, numberOfSbox)
        self.__firstMatrixName = fname
        self.__firstMatrix = f
        self.__matName = matName
        self.__matrix = matrix
        self.__sboxDim = sboxDim
        self.__dim = dim
        self.__round = r
        self.__constrs = []
        self.__variables = self.__declareVariables()
        self.__afterSboxVariables = self.__declareSboxVariables()
        self.__constrs += self.__sbox.get_asserts_declares()
        self.__gen_round_constrs()
        self.__gen_init_constrs(inVec, outVec)

    def __declareVariables(self):
        # declare the round variables
        variables = [[0 for x in range(self.__dim)]
                     for x in range(self.__round + 1)]
        for r in range(self.__round + 1):
            for p in range(self.__dim):
                s = 'AES_X_%d_%d' % (r, p)
                variables[r][p] = s
                s = '%s:BITVECTOR(1);' % s
                self.__constrs.append(s)
        return variables

    def __declareSboxVariables(self):
        afterSboxVariables = [[0 for x in range(self.__dim)]
                              for x in range(self.__round)]
        for r in range(self.__round):
            for p in range(self.__dim):
                s = 'AES_SBOX_%d_%d' % (r, p)
                afterSboxVariables[r][p] = s
                s = '%s:BITVECTOR(1);' % s
                self.__constrs.append(s)
        return afterSboxVariables

    def __gen_round_constrs(self):
        # pass sbox
        for r in range(self.__round):
            if r == 0:
                # r == 0, apply the first matrix
                inVec0 = self.__variables[r][0 * self.__sboxDim: 1 * self.__sboxDim]\
                       + self.__variables[r][4 * self.__sboxDim: 5 * self.__sboxDim]\
                       + self.__variables[r][8 * self.__sboxDim: 9 * self.__sboxDim]

                inVec1 = self.__variables[r][1 * self.__sboxDim: 2 * self.__sboxDim]\
                       + self.__variables[r][5 * self.__sboxDim: 6 * self.__sboxDim]\
                       + self.__variables[r][9 * self.__sboxDim: 10 * self.__sboxDim]

                inVec2 = self.__variables[r][2 * self.__sboxDim: 3 * self.__sboxDim]\
                       + self.__variables[r][6 * self.__sboxDim: 7 * self.__sboxDim]\
                       + self.__variables[r][10 * self.__sboxDim: 11 * self.__sboxDim]

                inVec3 = self.__variables[r][3 * self.__sboxDim: 4 * self.__sboxDim]\
                       + self.__variables[r][7 * self.__sboxDim: 8 * self.__sboxDim]\
                       + self.__variables[r][11 * self.__sboxDim: 12 * self.__sboxDim]
            else:
                inVec0 = self.__variables[r][0 * self.__sboxDim: 1 * self.__sboxDim]\
                       + self.__variables[r][4 * self.__sboxDim: 5 * self.__sboxDim]\
                       + self.__variables[r][8 * self.__sboxDim: 9 * self.__sboxDim]\
                       + self.__variables[r][12 * self.__sboxDim: 13 * self.__sboxDim]

                inVec1 = self.__variables[r][1 * self.__sboxDim: 2 * self.__sboxDim]\
                       + self.__variables[r][5 * self.__sboxDim: 6 * self.__sboxDim]\
                       + self.__variables[r][9 * self.__sboxDim: 10 * self.__sboxDim]\
                       + self.__variables[r][13 * self.__sboxDim: 14 * self.__sboxDim]

                inVec2 = self.__variables[r][2 * self.__sboxDim: 3 * self.__sboxDim]\
                       + self.__variables[r][6 * self.__sboxDim: 7 * self.__sboxDim]\
                       + self.__variables[r][10 * self.__sboxDim: 11 * self.__sboxDim]\
                       + self.__variables[r][14 * self.__sboxDim: 15 * self.__sboxDim]\

                inVec3 = self.__variables[r][3 * self.__sboxDim: 4 * self.__sboxDim]\
                       + self.__variables[r][7 * self.__sboxDim: 8 * self.__sboxDim]\
                       + self.__variables[r][11 * self.__sboxDim: 12 * self.__sboxDim]\
                       + self.__variables[r][15 * self.__sboxDim: 16 * self.__sboxDim]

            outVec0 = self.__afterSboxVariables[r][0 * self.__sboxDim: 1 * self.__sboxDim]\
                   + self.__afterSboxVariables[r][4 * self.__sboxDim: 5 * self.__sboxDim]\
                   + self.__afterSboxVariables[r][8 * self.__sboxDim: 9 * self.__sboxDim]\
                   + self.__afterSboxVariables[r][12 * self.__sboxDim: 13 * self.__sboxDim]

            outVec1 = self.__afterSboxVariables[r][1 * self.__sboxDim: 2 * self.__sboxDim]\
                   + self.__afterSboxVariables[r][5 * self.__sboxDim: 6 * self.__sboxDim]\
                   + self.__afterSboxVariables[r][9 * self.__sboxDim: 10 * self.__sboxDim]\
                   + self.__afterSboxVariables[r][13 * self.__sboxDim: 14 * self.__sboxDim]

            outVec2 = self.__afterSboxVariables[r][2 * self.__sboxDim: 3 * self.__sboxDim]\
                   + self.__afterSboxVariables[r][6 * self.__sboxDim: 7 * self.__sboxDim]\
                   + self.__afterSboxVariables[r][10 * self.__sboxDim: 11 * self.__sboxDim]\
                   + self.__afterSboxVariables[r][14 * self.__sboxDim: 15 * self.__sboxDim]

            outVec3 = self.__afterSboxVariables[r][3 * self.__sboxDim: 4 * self.__sboxDim]\
                   + self.__afterSboxVariables[r][7 * self.__sboxDim: 8 * self.__sboxDim]\
                   + self.__afterSboxVariables[r][11 * self.__sboxDim: 12 * self.__sboxDim]\
                   + self.__afterSboxVariables[r][15 * self.__sboxDim: 16 * self.__sboxDim]

            if r == 0:
                matName = self.__firstMatrixName
                mat = self.__firstMatrix
                m = NonMatrix(matName, mat, inVec0, outVec0, r, 0)
                self.__constrs += m.get_declares_asserts()

                m = NonMatrix(matName, mat, inVec1, outVec1, r, 1)
                self.__constrs += m.get_declares_asserts()

                m = NonMatrix(matName, mat, inVec2, outVec2, r, 2)
                self.__constrs += m.get_declares_asserts()

                m = NonMatrix(matName, mat, inVec3, outVec3, r, 3)
                self.__constrs += m.get_declares_asserts()
            else:
                matName = self.__matName
                mat = self.__matrix

                m = Matrix(matName, mat, inVec0, outVec0, r, 0)
                self.__constrs += m.get_declares_asserts()

                m = Matrix(matName, mat, inVec1, outVec1, r, 1)
                self.__constrs += m.get_declares_asserts()

                m = Matrix(matName, mat, inVec2, outVec2, r, 2)
                self.__constrs += m.get_declares_asserts()

                m = Matrix(matName, mat, inVec3, outVec3, r, 3)
                self.__constrs += m.get_declares_asserts()

            for p in range(4):
                self.__constrs.append(
                    self.__sbox.build_constrs(
                        self.__afterSboxVariables[r][self.__sboxDim *
                                                     p:self.__sboxDim *
                                                     (p + 1)],
                        self.__variables[r + 1][self.__sboxDim *
                                                p:self.__sboxDim * (p + 1)], r,
                        p), )
            self.__constrs.append(
                self.__sbox.build_constrs(
                    self.__afterSboxVariables[r][self.__sboxDim *
                                                 7:self.__sboxDim * 8],
                    self.__variables[r + 1][self.__sboxDim * 4:self.__sboxDim *
                                            5], r, 4), )
            self.__constrs.append(
                self.__sbox.build_constrs(
                    self.__afterSboxVariables[r][self.__sboxDim *
                                                 4:self.__sboxDim * 5],
                    self.__variables[r + 1][self.__sboxDim * 5:self.__sboxDim *
                                            6], r, 5), )
            self.__constrs.append(
                self.__sbox.build_constrs(
                    self.__afterSboxVariables[r][self.__sboxDim *
                                                 5:self.__sboxDim * 6],
                    self.__variables[r + 1][self.__sboxDim * 6:self.__sboxDim *
                                            7], r, 6), )
            self.__constrs.append(
                self.__sbox.build_constrs(
                    self.__afterSboxVariables[r][self.__sboxDim *
                                                 6:self.__sboxDim * 7],
                    self.__variables[r + 1][self.__sboxDim * 7:self.__sboxDim *
                                            8], r, 7), )

            self.__constrs.append(
                self.__sbox.build_constrs(
                    self.__afterSboxVariables[r][self.__sboxDim *
                                                 10:self.__sboxDim * 11],
                    self.__variables[r + 1][self.__sboxDim * 8:self.__sboxDim *
                                            9], r, 8), )
            self.__constrs.append(
                self.__sbox.build_constrs(
                    self.__afterSboxVariables[r][self.__sboxDim *
                                                 11:self.__sboxDim * 12],
                    self.__variables[r + 1][self.__sboxDim *
                                            12:self.__sboxDim * 13], r, 9), )
            self.__constrs.append(
                self.__sbox.build_constrs(
                    self.__afterSboxVariables[r][self.__sboxDim *
                                                 8:self.__sboxDim * 9],
                    self.__variables[r + 1][self.__sboxDim *
                                            10:self.__sboxDim * 11], r, 10), )
            self.__constrs.append(
                self.__sbox.build_constrs(
                    self.__afterSboxVariables[r][self.__sboxDim *
                                                 9:self.__sboxDim * 10],
                    self.__variables[r + 1][self.__sboxDim *
                                            11:self.__sboxDim * 12], r, 11), )

            self.__constrs.append(
                self.__sbox.build_constrs(
                    self.__afterSboxVariables[r][self.__sboxDim *
                                                 13:self.__sboxDim * 14],
                    self.__variables[r + 1][self.__sboxDim *
                                            12:self.__sboxDim * 13], r, 12), )
            self.__constrs.append(
                self.__sbox.build_constrs(
                    self.__afterSboxVariables[r][self.__sboxDim *
                                                 14:self.__sboxDim * 15],
                    self.__variables[r + 1][self.__sboxDim *
                                            13:self.__sboxDim * 14], r, 13), )
            self.__constrs.append(
                self.__sbox.build_constrs(
                    self.__afterSboxVariables[r][self.__sboxDim *
                                                 15:self.__sboxDim * 16],
                    self.__variables[r + 1][self.__sboxDim *
                                            14:self.__sboxDim * 15], r, 14), )
            self.__constrs.append(
                self.__sbox.build_constrs(
                    self.__afterSboxVariables[r][self.__sboxDim *
                                                 12:self.__sboxDim * 13],
                    self.__variables[r + 1][self.__sboxDim *
                                            15:self.__sboxDim * 16], r, 15), )

    def __gen_init_constrs(self, constants, tail):
        for i in range(self.__dim):
            if i in constants:
                self.__constrs.append('ASSERT %s = 0bin1;' %
                                      self.__variables[0][i])
            else:
                self.__constrs.append('ASSERT %s = 0bin0;' %
                                      self.__variables[0][i])

        s = 'ASSERT BVPLUS(10, 0bin000000000@%s ' % self.__variables[
            self.__round][0]
        for i in range(1, self.__dim):
            s += ', 0bin000000000@%s' % self.__variables[self.__round][i]
        s += ') = 0bin0000000001;'
        self.__constrs.append(s)
        self.__constrs.append('QUERY FALSE;')
        self.__constrs.append('COUNTEREXAMPLE;')

    def getConstrs(self):
        return self.__constrs
class AES(object):
    def __init__(self, firstName, firstMatrix, matName, matrix, sboxName, sbox,
                 sboxDim, dim, r, numberOfSbox, inVec, outVec):
        self.__sbox = AssertSbox(sboxName, sbox, sboxDim, r, numberOfSbox)
        self.__firstName = firstName
        self.__firstMatrix = firstMatrix
        self.__matName = matName
        self.__matrix = matrix
        self.__sboxDim = sboxDim
        self.__dim = dim
        self.__round = r
        self.__constrs = []
        self.__variables = self.__declareVariables()
        self.__var2 = self.__declareVariables2()
        self.__afterSboxVariables = self.__declareSboxVariables()
        self.__constrs += self.__sbox.get_asserts_declares()
        self.__gen_round_constrs()
        self.__gen_init_constrs(inVec, outVec)

    def __declareVariables(self):
        # declare the round variables
        variables = [[0 for x in range(self.__dim)]
                     for x in range(self.__round + 1)]
        for r in range(self.__round + 1):
            for p in range(self.__dim):
                s = 'AES_X_%d_%d' % (r, p)
                variables[r][p] = s
                s = '%s:BITVECTOR(1);' % s
                self.__constrs.append(s)
        return variables

    def __declareVariables2(self):
        # declare the input variables of the distinguishers
        var2 = [0 for x in range(self.__dim)]

        for p in range(self.__dim):
            s = 'AES_SX_%d' % (p)
            var2[p] = s
            s = '%s:BITVECTOR(1);' % s
            self.__constrs.append(s)
        return var2

    def __declareSboxVariables(self):
        afterSboxVariables = [[0 for x in range(self.__dim)]
                              for x in range(self.__round)]
        for r in range(self.__round):
            for p in range(self.__dim):
                s = 'AES_SBOX_%d_%d' % (r, p)
                afterSboxVariables[r][p] = s
                s = '%s:BITVECTOR(1);' % s
                self.__constrs.append(s)
        return afterSboxVariables

    def __gen_round_constrs(self):
        inVec0 = self.__var2[0 * self.__sboxDim: 1 * self.__sboxDim]\
               + self.__var2[4 * self.__sboxDim: 5 * self.__sboxDim]\
               + self.__var2[8 * self.__sboxDim: 9 * self.__sboxDim]

        inVec1 = self.__var2[1 * self.__sboxDim: 2 * self.__sboxDim]\
               + self.__var2[5 * self.__sboxDim: 6 * self.__sboxDim]\
               + self.__var2[9 * self.__sboxDim: 10 * self.__sboxDim]\
               + self.__var2[13 * self.__sboxDim: 14 * self.__sboxDim]

        inVec2 = self.__var2[2 * self.__sboxDim: 3 * self.__sboxDim]\
               + self.__var2[6 * self.__sboxDim: 7 * self.__sboxDim]\
               + self.__var2[10 * self.__sboxDim: 11 * self.__sboxDim]\
               + self.__var2[14 * self.__sboxDim: 15 * self.__sboxDim]

        inVec3 = self.__var2[3 * self.__sboxDim: 4 * self.__sboxDim]\
               + self.__var2[7 * self.__sboxDim: 8 * self.__sboxDim]\
               + self.__var2[11 * self.__sboxDim: 12 * self.__sboxDim]\
               + self.__var2[15 * self.__sboxDim: 16 * self.__sboxDim]

        outVec0 = self.__variables[0][0 * self.__sboxDim: 1 * self.__sboxDim]\
                   + self.__variables[0][4 * self.__sboxDim: 5 * self.__sboxDim]\
                   + self.__variables[0][8 * self.__sboxDim: 9 * self.__sboxDim]\
                   + self.__variables[0][12 * self.__sboxDim: 13 * self.__sboxDim]

        outVec1 = self.__variables[0][1 * self.__sboxDim: 2 * self.__sboxDim]\
                   + self.__variables[0][5 * self.__sboxDim: 6 * self.__sboxDim]\
                   + self.__variables[0][9 * self.__sboxDim: 10 * self.__sboxDim]\
                   + self.__variables[0][13 * self.__sboxDim: 14 * self.__sboxDim]

        outVec2 = self.__variables[0][2 * self.__sboxDim: 3 * self.__sboxDim]\
                   + self.__variables[0][6 * self.__sboxDim: 7 * self.__sboxDim]\
                   + self.__variables[0][10 * self.__sboxDim: 11 * self.__sboxDim]\
                   + self.__variables[0][14 * self.__sboxDim: 15 * self.__sboxDim]

        outVec3 = self.__variables[0][3 * self.__sboxDim: 4 * self.__sboxDim]\
                   + self.__variables[0][7 * self.__sboxDim: 8 * self.__sboxDim]\
                   + self.__variables[0][11 * self.__sboxDim: 12 * self.__sboxDim]\
                   + self.__variables[0][15 * self.__sboxDim: 16 * self.__sboxDim]

        m = NonSquareMatrix(self.__firstName, self.__firstMatrix, inVec0,
                            outVec0, 10, 0)
        self.__constrs += m.get_declares_asserts()

        m = Matrix(self.__matName, self.__matrix, inVec1, outVec1, 10, 1)
        self.__constrs += m.get_declares_asserts()

        m = Matrix(self.__matName, self.__matrix, inVec2, outVec2, 10, 2)
        self.__constrs += m.get_declares_asserts()

        m = Matrix(self.__matName, self.__matrix, inVec3, outVec3, 10, 3)
        self.__constrs += m.get_declares_asserts()

        for r in range(self.__round):
            for p in range(int(self.__dim / self.__sboxDim)):
                self.__constrs.append(
                    self.__sbox.build_constrs(
                        self.__variables[r][self.__sboxDim * p:self.__sboxDim *
                                            (p + 1)],
                        self.__afterSboxVariables[r][self.__sboxDim *
                                                     p:self.__sboxDim *
                                                     (p + 1)], r, p), )
        # pass shiftRows and MixColumn
        # 0  1  2  3             0  1  2  3
        # 4  5  6  7   ----->    5  6  7  4
        # 8  9  10 11            10 11 8  9
        # 12 13 14 15            15 12 13 14
            inVec0 = self.__afterSboxVariables[r][0:self.__sboxDim]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 5 : self.__sboxDim * 6 ]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 10: self.__sboxDim * 11]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 15: self.__sboxDim * 16]
            inVec1 = self.__afterSboxVariables[r][self.__sboxDim * 1: self.__sboxDim * 2] \
                    +self.__afterSboxVariables[r][self.__sboxDim * 6: self.__sboxDim * 7]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 11:self.__sboxDim * 12]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 12:self.__sboxDim * 13]
            inVec2 = self.__afterSboxVariables[r][self.__sboxDim * 2 :self.__sboxDim * 3] \
                    +self.__afterSboxVariables[r][self.__sboxDim * 7: self.__sboxDim * 8] \
                    +self.__afterSboxVariables[r][self.__sboxDim * 8 :self.__sboxDim * 9] \
                    +self.__afterSboxVariables[r][self.__sboxDim * 13: self.__sboxDim *14]
            inVec3 = self.__afterSboxVariables[r][self.__sboxDim * 3: self.__sboxDim * 4]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 4:self.__sboxDim * 5] \
                    +self.__afterSboxVariables[r][self.__sboxDim * 9: self.__sboxDim * 10]\
                    +self.__afterSboxVariables[r][self.__sboxDim * 14: self.__sboxDim * 15]

            outVec0 = self.__variables[r+1][self.__sboxDim * 0: self.__sboxDim * 1]\
                  +   self.__variables[r+1][self.__sboxDim * 4: self.__sboxDim * 5]\
                  +   self.__variables[r+1][self.__sboxDim * 8: self.__sboxDim * 9]\
                  +   self.__variables[r+1][self.__sboxDim * 12: self.__sboxDim * 13]
            outVec1 = self.__variables[r+1][self.__sboxDim * 1: self.__sboxDim * 2]\
                  +   self.__variables[r+1][self.__sboxDim * 5: self.__sboxDim * 6]\
                  +   self.__variables[r+1][self.__sboxDim * 9: self.__sboxDim * 10]\
                  +   self.__variables[r+1][self.__sboxDim * 13: self.__sboxDim * 14]
            outVec2 = self.__variables[r+1][self.__sboxDim * 2: self.__sboxDim * 3]\
                  +   self.__variables[r+1][self.__sboxDim * 6: self.__sboxDim * 7]\
                  +   self.__variables[r+1][self.__sboxDim * 10: self.__sboxDim * 11]\
                  +   self.__variables[r+1][self.__sboxDim * 14: self.__sboxDim * 15]
            outVec3 = self.__variables[r+1][self.__sboxDim * 3: self.__sboxDim * 4]\
                  +   self.__variables[r+1][self.__sboxDim * 7: self.__sboxDim * 8]\
                  +   self.__variables[r+1][self.__sboxDim * 11: self.__sboxDim * 12]\
                  +   self.__variables[r+1][self.__sboxDim * 15: self.__sboxDim * 16]

            m = Matrix(self.__matName, self.__matrix, inVec0, outVec0, r, 0)
            self.__constrs += m.get_declares_asserts()

            m = Matrix(self.__matName, self.__matrix, inVec1, outVec1, r, 1)
            self.__constrs += m.get_declares_asserts()

            m = Matrix(self.__matName, self.__matrix, inVec2, outVec2, r, 2)
            self.__constrs += m.get_declares_asserts()

            m = Matrix(self.__matName, self.__matrix, inVec3, outVec3, r, 3)
            self.__constrs += m.get_declares_asserts()

    def __gen_init_constrs(self, constants, tail):
        for i in range(self.__dim):
            if i in constants:
                self.__constrs.append('ASSERT %s = 0bin1;' % self.__var2[i])
            else:
                self.__constrs.append('ASSERT %s = 0bin0;' % self.__var2[i])

        s = 'ASSERT BVPLUS(10, 0bin000000000@%s ' % self.__variables[
            self.__round][0]
        for i in range(1, self.__dim):
            s += ', 0bin000000000@%s' % self.__variables[self.__round][i]
        s += ') = 0bin0000000001;'
        self.__constrs.append(s)
        self.__constrs.append('QUERY FALSE;')
        self.__constrs.append('COUNTEREXAMPLE;')

    def getConstrs(self):
        return self.__constrs
Beispiel #9
0
class Camellia(object):
    def __init__(self, matNameP, matrixP, matNameP_inv, matrixP_inv, matNameFL,
                 matrixFL, matNameFL_inv, matrixFL_inv, sboxName, sbox,
                 sboxDim, numberOfSbox, dim, r, mid_r, inVec, outVec):

        self._sbox = AssertSbox(sboxName, sbox, sboxDim, r, numberOfSbox)

        self._matNameFL = matNameFL
        self._matrixFL = matrixFL
        self._matNameFL_inv = matNameFL_inv
        self._matrixFL_inv = matrixFL_inv
        self._matNameP = matNameP
        self._matrixP = matrixP

        self._matNameP_inv = matNameP_inv
        self._matrixP_inv = matrixP_inv

        self._dim = dim
        self._round = r
        self._midRound = mid_r
        self._constrs = []
        self._vars = dict()
        self._inVec = inVec
        self._outVec = outVec

        self._constrs += self._sbox.get_asserts_declares()

    def _declare(self, varName, dim=1):
        return '%s:BITVECTOR(%d);' % (varName, dim)

    def _addConstr(self, asserts):
        self._constrs.append(asserts)

    def _declareV(self, varName, round_dim, one_round_dim):
        if round_dim > 0:
            self._vars[varName] = [[None for x in range(one_round_dim)]
                                   for x in range(round_dim)]
            for r in range(round_dim):
                for p in range(one_round_dim):
                    varx = '%s_%d_%d' % (varName, r, p)
                    self._vars[varName][r][p] = varx
                    self._addConstr(self._declare(varx))
        else:
            self._vars[varName] = [None for x in range(one_round_dim)]
            for p in range(one_round_dim):
                varx = '%s_%d' % (varName, p)
                self._vars[varName][p] = varx
                self._addConstr(self._declare(varx))

    def _Kxor(self, a0, a1, b):
        s = 'ASSERT '
        s += '~' + a0 + ' | ~' + a1 + '= 0bin1;\n'
        s += 'ASSERT '
        s += a0 + ' | ' + a1 + ' | ~' + b + '= 0bin1;\n'
        s += 'ASSERT '
        s += a0 + ' | ~' + a1 + ' | ' + b + '= 0bin1;\n'
        s += 'ASSERT '
        s += '~' + a0 + ' | ' + a1 + ' | ' + b + '= 0bin1;'

        return s

    def _Kcopy(self, a, b0, b1):
        s = 'ASSERT '
        s += '~' + b0 + ' | ~' + b1 + ' = 0bin1;\n'
        s += 'ASSERT '
        s += a + ' | ' + b0 + ' | ~' + b1 + ' = 0bin1;\n'
        s += 'ASSERT '
        s += a + ' | ' + '~' + b0 + ' | ' + b1 + ' = 0bin1;\n'
        s += 'ASSERT '
        s += '~' + a + ' | ' + b0 + ' | ' + b1 + ' = 0bin1;'

        return s

    def _block_copy(self, inV, outV1, outV2):
        dim = len(inV)
        for i in range(dim):
            self._addConstr(self._Kcopy(inV[i], outV1[i], outV2[i]))

    def _block_xor(self, inV, outV1, outV2):
        dim = len(inV)
        for i in range(dim):
            self._addConstr(self._Kxor(inV[i], outV1[i], outV2[i]))

    def _declareVariables(self):
        self._declareV('Camellia_KX', self._round + 1, self._dim)
        self._declareV('Camellia_inSbox', self._round, self._dim // 2)
        self._declareV('Camellia_inP', self._round, self._dim // 2)
        self._declareV('Camellia_outP', self._round, self._dim // 2)
        self._declareV('Camellia_inFL', 0, self._dim)

    def _sboxLayer(self, in_sbox, out_sbox, r):
        rot_left(in_sbox, 24, 32)
        rot_left(in_sbox, 48, 56)
        self._constrs.append(
            self._sbox.build_constrs(in_sbox[0:8], out_sbox[0:8], r, 0))
        self._constrs.append(
            self._sbox.build_constrs(in_sbox[8:16], out_sbox[8:16], r, 1))
        self._constrs.append(
            self._sbox.build_constrs(in_sbox[16:24], out_sbox[16:24], r, 2))
        self._constrs.append(
            self._sbox.build_constrs(in_sbox[24:32], out_sbox[24:32], r, 3))
        self._constrs.append(
            self._sbox.build_constrs(in_sbox[32:40], out_sbox[32:40], r, 4))
        self._constrs.append(
            self._sbox.build_constrs(in_sbox[40:48], out_sbox[40:48], r, 5))
        self._constrs.append(
            self._sbox.build_constrs(in_sbox[48:56], out_sbox[48:56], r, 6))
        self._constrs.append(
            self._sbox.build_constrs(in_sbox[56:64], out_sbox[56:64], r, 7))

        rot_right(out_sbox, 16, 24)
        rot_right(out_sbox, 40, 48)

        rot_left(out_sbox, 8, 16)
        rot_left(out_sbox, 32, 40)

    def _FL(self, in_FL, out_FL):
        m = Matrix(self._matNameFL, self._matrixFL, in_FL[0:64], out_FL[0:64],
                   0, 0)
        self._constrs += m.get_declares_asserts()

        m = Matrix(self._matNameFL_inv, self._matrixFL_inv, in_FL[64:128],
                   out_FL[64:128], 0, 0)
        self._constrs += m.get_declares_asserts()

    def _P(self, in_P, out_P, r):
        m = Matrix(self._matNameP, self._matrixP, in_P, out_P, r, 0)
        self._constrs += m.get_declares_asserts()

    def _gen_round_constrs(self):
        for r in range(self._round):
            if r == self._midRound - 1:
                self._block_copy(self._vars['Camellia_KX'][r][0:64],
                                 self._vars['Camellia_inSbox'][r],
                                 self._vars['Camellia_inFL'][64:128])
                self._sboxLayer(self._vars['Camellia_inSbox'][r],
                                self._vars['Camellia_inP'][r], r)
                self._P(self._vars['Camellia_inP'][r],
                        self._vars['Camellia_outP'][r], r)
                self._block_xor(self._vars['Camellia_KX'][r][64:128],
                                self._vars['Camellia_outP'][r],
                                self._vars['Camellia_inFL'][0:64])
                self._FL(self._vars['Camellia_inFL'],
                         self._vars['Camellia_KX'][r + 1])
            else:
                self._block_copy(self._vars['Camellia_KX'][r][0:64],
                                 self._vars['Camellia_inSbox'][r],
                                 self._vars['Camellia_KX'][r + 1][64:128])
                self._sboxLayer(self._vars['Camellia_inSbox'][r],
                                self._vars['Camellia_inP'][r], r)
                self._P(self._vars['Camellia_inP'][r],
                        self._vars['Camellia_outP'][r], r)
                self._block_xor(self._vars['Camellia_KX'][r][64:128],
                                self._vars['Camellia_outP'][r],
                                self._vars['Camellia_KX'][r + 1][0:64])

    def _gen_init_constrs(self):
        '''
        add the initial and stopping rules
        '''
        for i in range(self._dim):
            if i in self._inVec:
                self._addConstr('ASSERT %s = 0bin1;' %
                                self._vars['Camellia_KX'][0][i])
            else:
                self._addConstr('ASSERT %s = 0bin0;' %
                                self._vars['Camellia_KX'][0][i])

        # C_0 + ... + C_6 + C_32 + ... + C_63 = 1
        s = 'ASSERT BVPLUS(10, 0bin000000000@%s ' % self._vars['Camellia_KX'][
            self._round][64]
        for i in range(65, 128):
            s += ', 0bin000000000@%s' % self._vars['Camellia_KX'][
                self._round][i]
        s += ') = 0bin0000000001;'
        self._constrs.append(s)
        self._constrs.append('QUERY FALSE;')

    def getConstrs(self):
        self._declareVariables()
        self._gen_round_constrs()
        self._gen_init_constrs()

        return self._constrs
Beispiel #10
0
class Misty(object):
    def __init__(self, matNameFL, matrixFL, matNameFO, matrixFO,
                 matNameFI_zero_extended, matrixFI_zero_extended,
                 matNameFI_truncate, matrixFI_truncate, sboxName9, sbox9,
                 sboxDim9, numberOfSbox9, sboxName7, sbox7, sboxDim7,
                 numberOfSbox7, dim, r, inVec, outVec):

        self._sbox9 = AssertSbox(sboxName9, sbox9, sboxDim9, r, numberOfSbox9)
        self._sbox7 = AssertSbox(sboxName7, sbox7, sboxDim7, r, numberOfSbox7)
        self._sboxDim9 = sboxDim9
        self._sboxDim7 = sboxDim7

        self._matrixNameFL = matNameFL
        self._matrixFL = matrixFL

        self._matrixNameFO = matNameFO
        self._matrixFO = matrixFO
        self._matrixNameFI_zero_extended = matNameFI_zero_extended
        self._matrixFI_zero_extended = matrixFI_zero_extended
        self._matrixNameFI_truncate = matNameFI_truncate
        self._matrixFI_truncate = matrixFI_truncate

        self._dim = dim
        self._round = r
        self._constrs = []
        self._vars = dict()
        self._inVec = inVec
        self._outVec = outVec

        self._constrs += self._sbox9.get_asserts_declares()
        self._constrs += self._sbox7.get_asserts_declares()

    def _declare(self, varName, dim=1):
        return '%s:BITVECTOR(%d);' % (varName, dim)

    def _addConstr(self, asserts):
        self._constrs.append(asserts)

    def _equal(self, in_var, out_var):
        dim = len(in_var)
        for i in range(dim):
            self._addConstr('ASSERT %s= %s;' % (in_var[i], out_var[i]))

    def _declareV(self, varName, round_dim, one_round_dim):
        self._vars[varName] = [[None for x in range(one_round_dim)]
                               for x in range(round_dim)]
        for r in range(round_dim):
            for p in range(one_round_dim):
                varx = '%s_%d_%d' % (varName, r, p)
                self._vars[varName][r][p] = varx
                self._addConstr(self._declare(varx))

    def _Kxor(self, a0, a1, b):
        s = 'ASSERT '
        s += '~' + a0 + ' | ~' + a1 + '= 0bin1;\n'
        s += 'ASSERT '
        s += a0 + ' | ' + a1 + ' | ~' + b + '= 0bin1;\n'
        s += 'ASSERT '
        s += a0 + ' | ~' + a1 + ' | ' + b + '= 0bin1;\n'
        s += 'ASSERT '
        s += '~' + a0 + ' | ' + a1 + ' | ' + b + '= 0bin1;'

        return s

    def _Kcopy(self, a, b0, b1):
        s = 'ASSERT '
        s += '~' + b0 + ' | ~' + b1 + ' = 0bin1;\n'
        s += 'ASSERT '
        s += a + ' | ' + b0 + ' | ~' + b1 + ' = 0bin1;\n'
        s += 'ASSERT '
        s += a + ' | ' + '~' + b0 + ' | ' + b1 + ' = 0bin1;\n'
        s += 'ASSERT '
        s += '~' + a + ' | ' + b0 + ' | ' + b1 + ' = 0bin1;'

        return s

    def _block_copy(self, inV, outV1, outV2):
        dim = len(inV)
        for i in range(dim):
            self._addConstr(self._Kcopy(inV[i], outV1[i], outV2[i]))

    def _block_xor(self, inV, outV1, outV2):
        dim = len(inV)
        for i in range(dim):
            self._addConstr(self._Kxor(inV[i], outV1[i], outV2[i]))

    def _declareVariables(self):
        self._declareV('MISTY_KX', self._round + 1, self._dim)
        self._declareV('MISTY_FL', self._round // 2 + 1, self._dim)
        self._declareV('MISTY_FO_IN', self._round, self._dim // 2)
        self._declareV('MISTY_FO_OUT', self._round, self._dim // 2)

        self._declareV('MISTY_FO_FIRST', self._round, self._dim // 2)
        self._declareV('MISTY_FO_SECOND', self._round, self._dim // 2)
        self._declareV('MISTY_FO_THIRD', self._round, self._dim // 2)
        self._declareV('MISTY_FO_FOURTH', self._round, self._dim // 2)
        self._declareV('MISTY_FO_FIFTH', self._round, self._dim // 2)

        varName = 'MISTY_FI_FIRST'
        self._vars[varName] = [[[None for x in range(16)] for x in range(3)]
                               for x in range(self._round)]
        for r in range(self._round):
            for q in range(3):
                for p in range(16):
                    varx = '%s_%d_%d_%d' % (varName, r, q, p)
                    self._vars[varName][r][q][p] = varx
                    self._addConstr(self._declare(varx))
        varName = 'MISTY_FI_SECOND'
        self._vars[varName] = [[[None for x in range(16)] for x in range(3)]
                               for x in range(self._round)]
        for r in range(self._round):
            for q in range(3):
                for p in range(16):
                    varx = '%s_%d_%d_%d' % (varName, r, q, p)
                    self._vars[varName][r][q][p] = varx
                    self._addConstr(self._declare(varx))
        varName = 'MISTY_FI_THIRD'
        self._vars[varName] = [[[None for x in range(16)] for x in range(3)]
                               for x in range(self._round)]
        for r in range(self._round):
            for q in range(3):
                for p in range(16):
                    varx = '%s_%d_%d_%d' % (varName, r, q, p)
                    self._vars[varName][r][q][p] = varx
                    self._addConstr(self._declare(varx))
        varName = 'MISTY_FI_FOURTH'
        self._vars[varName] = [[[None for x in range(16)] for x in range(3)]
                               for x in range(self._round)]
        for r in range(self._round):
            for q in range(3):
                for p in range(16):
                    varx = '%s_%d_%d_%d' % (varName, r, q, p)
                    self._vars[varName][r][q][p] = varx
                    self._addConstr(self._declare(varx))
        varName = 'MISTY_FI_FIFTH'
        self._vars[varName] = [[[None for x in range(16)] for x in range(3)]
                               for x in range(self._round)]
        for r in range(self._round):
            for q in range(3):
                for p in range(16):
                    varx = '%s_%d_%d_%d' % (varName, r, q, p)
                    self._vars[varName][r][q][p] = varx
                    self._addConstr(self._declare(varx))

    def _FL(self, in_vars, out_vars, r, p):
        m = Matrix(self._matrixNameFL, self._matrixFL, in_vars, out_vars, r, p)
        self._constrs += m.get_declares_asserts()

    def _FO(self, in_vars, out_vars, r):
        self._FI(in_vars[0:16], self._vars['MISTY_FO_FIRST'][r][0:16], r, 0)
        self._equal(in_vars[16:32], self._vars['MISTY_FO_FIRST'][r][16:32])

        m = Matrix(self._matrixNameFO, self._matrixFO,
                   self._vars['MISTY_FO_FIRST'][r],
                   self._vars['MISTY_FO_SECOND'][r], r, 0)
        self._constrs += m.get_declares_asserts()

        self._FI(self._vars['MISTY_FO_SECOND'][r][0:16],
                 self._vars['MISTY_FO_THIRD'][r][0:16], r, 1)
        self._equal(self._vars['MISTY_FO_SECOND'][r][16:32],
                    self._vars['MISTY_FO_THIRD'][r][16:32])

        m = Matrix(self._matrixNameFO, self._matrixFO,
                   self._vars['MISTY_FO_THIRD'][r],
                   self._vars['MISTY_FO_FOURTH'][r], r, 1)
        self._constrs += m.get_declares_asserts()

        self._FI(self._vars['MISTY_FO_FOURTH'][r][0:16],
                 self._vars['MISTY_FO_FIFTH'][r][0:16], r, 2)
        self._equal(self._vars['MISTY_FO_FOURTH'][r][16:32],
                    self._vars['MISTY_FO_FIFTH'][r][16:32])

        m = Matrix(self._matrixNameFO, self._matrixFO,
                   self._vars['MISTY_FO_FIFTH'][r],
                   self._vars['MISTY_FO_OUT'][r], r, 2)
        self._constrs += m.get_declares_asserts()

    def _FI(self, in_vars, out_vars, r, p):
        self._constrs.append(
            self._sbox9.build_constrs(in_vars[0:9],
                                      self._vars['MISTY_FI_FIRST'][r][p][0:9],
                                      r, 2 * p))
        self._equal(in_vars[9:16], self._vars['MISTY_FI_FIRST'][r][p][9:16])

        m = Matrix(self._matrixNameFI_zero_extended,
                   self._matrixFI_zero_extended,
                   self._vars['MISTY_FI_FIRST'][r][p],
                   self._vars['MISTY_FI_SECOND'][r][p], r, 2 * p)
        self._constrs += m.get_declares_asserts()

        self._constrs.append(
            self._sbox7.build_constrs(self._vars['MISTY_FI_SECOND'][r][p][0:7],
                                      self._vars['MISTY_FI_THIRD'][r][p][0:7],
                                      r, p))
        self._equal(self._vars['MISTY_FI_SECOND'][r][p][7:16],
                    self._vars['MISTY_FI_THIRD'][r][p][7:16])

        m = Matrix(self._matrixNameFI_truncate, self._matrixFI_truncate,
                   self._vars['MISTY_FI_THIRD'][r][p],
                   self._vars['MISTY_FI_FOURTH'][r][p], r, p)
        self._constrs += m.get_declares_asserts()

        self._constrs.append(
            self._sbox9.build_constrs(self._vars['MISTY_FI_FOURTH'][r][p][0:9],
                                      self._vars['MISTY_FI_FIFTH'][r][p][0:9],
                                      r, 2 * p + 1))
        self._equal(self._vars['MISTY_FI_FOURTH'][r][p][9:16],
                    self._vars['MISTY_FI_FIFTH'][r][p][9:16])

        m = Matrix(self._matrixNameFI_zero_extended,
                   self._matrixFI_zero_extended,
                   self._vars['MISTY_FI_FIFTH'][r][p], out_vars, r, 2 * p + 1)
        self._constrs += m.get_declares_asserts()

    def _gen_round_constrs(self):
        for r in range(self._round):
            if r % 2 == 0 and r != 0:
                self._FL(self._vars['MISTY_KX'][r][0:32],
                         self._vars['MISTY_FL'][r // 2][0:32], r, 0)
                self._FL(self._vars['MISTY_KX'][r][32:64],
                         self._vars['MISTY_FL'][r // 2][32:64], r, 1)

                self._block_copy(self._vars['MISTY_FL'][r // 2][0:32],
                                 self._vars['MISTY_FO_IN'][r],
                                 self._vars['MISTY_KX'][r + 1][32:64])
                self._FO(self._vars['MISTY_FO_IN'][r],
                         self._vars['MISTY_FO_OUT'][r], r)

                self._block_xor(self._vars['MISTY_FO_OUT'][r],
                                self._vars['MISTY_FL'][r // 2][32:64],
                                self._vars['MISTY_KX'][r + 1][0:32])
            else:

                self._block_copy(self._vars['MISTY_KX'][r][0:32],
                                 self._vars['MISTY_FO_IN'][r],
                                 self._vars['MISTY_KX'][r + 1][32:64])
                self._FO(self._vars['MISTY_FO_IN'][r],
                         self._vars['MISTY_FO_OUT'][r], r)

                self._block_xor(self._vars['MISTY_FO_OUT'][r],
                                self._vars['MISTY_KX'][r][32:64],
                                self._vars['MISTY_KX'][r + 1][0:32])

    def _gen_init_constrs(self):
        for i in range(self._dim):
            if i in self._inVec:
                self._addConstr('ASSERT %s = 0bin1;' %
                                self._vars['MISTY_KX'][0][i])
            else:
                self._addConstr('ASSERT %s = 0bin0;' %
                                self._vars['MISTY_KX'][0][i])

        for i in range(7, 32):
            self._addConstr('ASSERT %s = 0bin0;' %
                            self._vars['MISTY_KX'][self._round][i])

        s = 'ASSERT BVPLUS(10,'
        for i in range(0, 7):
            s += '0bin000000000@%s,' % self._vars['MISTY_KX'][self._round][i]
        for i in range(32, 63):
            s += '0bin000000000@%s,' % self._vars['MISTY_KX'][self._round][i]

        s += '0bin000000000@%s ) = 0bin0000000001;' % self._vars['MISTY_KX'][
            self._round][63]

        self._constrs.append('QUERY FALSE;')
        #self._constrs.append( 'COUNTEREXAMPLE;')

    def getConstrs(self):
        self._declareVariables()
        self._gen_round_constrs()
        self._gen_init_constrs()

        return self._constrs