def test_SearchCh(self): for diff_type in [XorDiff, RXDiff]: for bv_function in [MyFunction]: for option in CH_OPTIONS: btor_ch_found = test_search_ch_skch( bvf_cipher=bv_function, diff_type=diff_type, initial_weight=0, solver_name="btor", rounds=None, der_mode=option.der_mode, search_mode=option.search_mode, check=True, verbose_level=VERBOSE_LEVEL, filename=None) if btor_ch_found is not None: btor_weight = int(btor_ch_found.ch_weight) btor_id = [ value.val for var, value in btor_ch_found.input_diff ] self.assertFalse( BvComp(functools.reduce(Concat, btor_id), 0)) else: btor_weight = math.inf if diff_type == XorDiff: self.assertEqual(0, btor_weight) elif diff_type == RXDiff: if option.der_mode == DerMode.ProbabilityOne: self.assertEqual(math.inf, btor_weight) else: self.assertLessEqual(1, btor_weight) self.assertLessEqual(btor_weight, 3) yices_ch_found = test_search_ch_skch( bvf_cipher=bv_function, diff_type=diff_type, initial_weight=0, solver_name="yices", rounds=None, der_mode=option.der_mode, search_mode=option.search_mode, check=True, verbose_level=1 if VERBOSE_LEVEL >= 2 else 0, filename=None) if yices_ch_found is not None: yices_weight = int(yices_ch_found.ch_weight) yices_id = [ value.val for var, value in yices_ch_found.input_diff ] self.assertFalse( BvComp(functools.reduce(Concat, yices_id), 0)) else: yices_weight = math.inf self.assertEqual(btor_weight, yices_weight)
def has_probability_one(self, output_diff): """Return whether the input diff propagates to the output diff with probability one. >>> from arxpy.bitvector.core import Constant, Variable >>> from arxpy.differential.difference import XorDiff >>> alpha = XorDiff(Constant(0, 16)) >>> f = XDSimonRF(alpha) >>> f.has_probability_one(XorDiff(Constant(0, 16))) 0b1 """ a, b, c = self.op.a, self.op.b, self.op.c n = self.input_diff[0].val.width assert math.gcd(n, a - b) == 1 and a > b and n % 2 == 0 alpha = self.input_diff[0].val Rol = RotateLeft varibits = Rol(alpha, a) | Rol(alpha, b) r = (2 * a - b) % n doublebits = (Rol(alpha, b) & (~Rol(alpha, a)) & Rol(alpha, r)) beta = output_diff.val gamma = beta ^ Rol(alpha, c) case2 = BvComp(Constant(0, n), (gamma & (~varibits)) | ((gamma ^ Rol(gamma, a - b)) & doublebits)) hw = varibits ^ doublebits # no need to PopCount condition = ~BvComp(alpha, ~Constant(0, n)) condition &= case2 condition &= BvComp(hw, Constant(0, hw.width)) return condition
def test_search_Ch(self): diff_type = XorDiff for bvf in BV_FUNCTIONS: if bvf.rounds is None: continue for rounds in range(bvf.rounds, bvf.rounds + 2): bvf.function.set_rounds(rounds) for option in OPTIONS: if bvf.function == PiPermutation and option == ChSearchMode.Optimal: continue btor_ch_found = test_search_ch_skch( bvf_cipher=bvf.function, diff_type=diff_type, initial_weight=0, solver_name="btor", rounds=rounds, der_mode=option.der_mode, search_mode=option.search_mode, check=False if option.search_mode in NoCheckModes else CHECK, verbose_level=VERBOSE_LEVEL, filename=self.filename) if btor_ch_found is not None: btor_weight = int(btor_ch_found.ch_weight) btor_id = [ value.val for var, value in btor_ch_found.input_diff ] self.assertFalse( BvComp(functools.reduce(Concat, btor_id), 0)) else: btor_weight = math.inf yices_ch_found = test_search_ch_skch( bvf_cipher=bvf.function, diff_type=diff_type, initial_weight=0, solver_name="yices", rounds=rounds, der_mode=option.der_mode, search_mode=option.search_mode, check=False, verbose_level=1 if VERBOSE_LEVEL >= 2 else 0, filename=self.filename) if yices_ch_found is not None: yices_weight = int(yices_ch_found.ch_weight) yices_id = [ value.val for var, value in yices_ch_found.input_diff ] self.assertFalse( BvComp(functools.reduce(Concat, yices_id), 0)) else: yices_weight = math.inf self.assertEqual(btor_weight, yices_weight)
def test_SearchSkCh(self): diff_type = XorDiff for cipher in [Cipher1, Cipher2]: cipher.set_rounds(1) for option in SKCH_OPTIONS: btor_ch_found = test_search_ch_skch( bvf_cipher=cipher, diff_type=diff_type, initial_weight=0, solver_name="btor", rounds=1, der_mode=option.der_mode, search_mode=option.search_mode, check=True, verbose_level=VERBOSE_LEVEL, filename=None) if btor_ch_found is not None: btor_weight = int(btor_ch_found.ch_weight) btor_id = [ value.val for var, value in btor_ch_found.input_diff ] self.assertFalse( BvComp(functools.reduce(Concat, btor_id), 0)) else: btor_weight = math.inf self.assertEqual(0, btor_weight) yices_ch_found = test_search_ch_skch( bvf_cipher=cipher, diff_type=diff_type, initial_weight=0, solver_name="yices", rounds=1, der_mode=option.der_mode, search_mode=option.search_mode, check=True, verbose_level=1 if VERBOSE_LEVEL >= 2 else 0, filename=None) if yices_ch_found is not None: yices_weight = int(yices_ch_found.ch_weight) yices_id = [ value.val for var, value in yices_ch_found.input_diff ] self.assertFalse( BvComp(functools.reduce(Concat, yices_id), 0)) else: yices_weight = math.inf self.assertEqual(btor_weight, yices_weight)
def is_possible(self, output_diff): """Return whether the given output `XorDiff` is possible. >>> from arxpy.bitvector.core import Constant, Variable >>> from arxpy.bitvector.context import NotEvaluation >>> from arxpy.bitvector.printing import BvWrapPrinter >>> from arxpy.differential.difference import XorDiff >>> alpha = XorDiff(Constant(0, 16)) >>> f = XDSimonRF(alpha) >>> f.is_possible(XorDiff(Constant(0, 16))) 0b1 >>> u, v = Variable("u", 16), Variable("v", 16) >>> f = XDSimonRF(XorDiff(u)) >>> with NotEvaluation([PopCount]): ... result = f.is_possible(XorDiff(v)) >>> print(BvWrapPrinter().doprint(result)) Ite(0xffff == u, 0b0 == (PopCount(v ^ (u <<< 2))[0]), ==(0x0000, |(~(u <<< 8) & (u <<< 1) & (u <<< 15) & (v ^ (u <<< 2) ^ ((v ^ (u <<< 2)) <<< 7)), ~((u <<< 1) | (u <<< 8)) & (v ^ (u <<< 2)) >>> result.xreplace({u: Constant(0, 16), v: Constant(0, 16)}) 0b1 See `Derivative.is_possible` for more information. """ a, b, c = self.op.a, self.op.b, self.op.c n = self.input_diff[0].val.width assert math.gcd(n, a - b) == 1 and a > b and n % 2 == 0 alpha = self.input_diff[0].val Rol = RotateLeft varibits = Rol(alpha, a) | Rol(alpha, b) r = (2 * a - b) % n doublebits = (Rol(alpha, b) & (~Rol(alpha, a)) & Rol(alpha, r)) beta = output_diff.val gamma = beta ^ Rol(alpha, c) def is_even(x): return BvComp(x[0], Constant(0, 1)) case2 = BvComp(Constant(0, n), (gamma & (~varibits)) | ((gamma ^ Rol(gamma, a - b)) & doublebits)) condition = Ite(BvComp(alpha, ~Constant(0, n)), is_even(PopCount(gamma)), case2) return condition
def weight(self): """Return the weight of the differential. >>> from arxpy.bitvector.core import Constant >>> from arxpy.diffcrypt.difference import DiffVar >>> from arxpy.ciphers.simon32_64 import XDF >>> x, y = DiffVar("x", 16), DiffVar("y", 16) >>> d = XDF(x, y) >>> d.weight() # doctest: +ELLIPSIS Ite(0xffff == x, 0b01111, ((0x00ff & ((0x0f0f & ((0x3333 ... >>> zero = Constant(0, 16) >>> d.weight().xreplace({x: zero, y: zero}) 0b00000 """ a, b = self.op.a, self.op.b n = self.input_diff[0].width alpha = self.input_diff[0] BvRol = RotateLeft varibits = BvRol(alpha, a) | BvRol(alpha, b) doublebits = BvRol(alpha, b) & (~BvRol(alpha, a)) & BvRol( alpha, 2 * a - b) hw = _HammingWeight(varibits ^ doublebits) width = max((n - 1).bit_length(), hw.width) value = Ite(BvComp(alpha, ~Constant(0, n)), Constant(n - 1, width), ZeroExtend(hw, width - hw.width)) return value
def is_possible(self, output_diff): x, y, z = [d.val for d in self.input_diff] w = output_diff.val n = x.width def eq(x, y, z): return (~x ^ y) & (~x ^ z) return BvComp(eq(x, y, z) & (x ^ w), Constant(0, n))
def is_possible(self, output_diff): dx, dy = [d.val for d in self.input_diff] dz = output_diff.val n = dx.width # (dx, dy) = (0, 0) -> dz =(1) bad_case = (~dx) & (~dy) & dz return BvComp(bad_case, Constant(0, n))
def has_probability_one(self, output_diff): dx, dy = [d.val for d in self.input_diff] dz = output_diff.val n = dx.width # (dx, dy) = (0, 0) -> dz =(0) pr1_case = (~dx) & (~dy) & (~dz) return BvComp(pr1_case, ~Constant(0, n))
def has_probability_one(self, output_diff): x, y, z = [d.val for d in self.input_diff] w = output_diff.val n = x.width def eq(x, y, z, w): return (~x ^ y) & (~x ^ z) & (~x ^ w) return BvComp(eq(x, y, z, w), ~Constant(0, n))
def is_possible(self, output_diff): x, y, z = [d.val for d in self.input_diff] w = output_diff.val n = x.width def eq(a, b): return ~a ^ b return BvComp(~x & eq(y, z) & eq(~y, w), Constant(0, n))
def test_bv2pysmt(self): bvx, bvy = Variable("x", 8), Variable("y", 8) psx, psy = bv2pysmt(bvx), bv2pysmt(bvy) self.assertEqual(bv2pysmt(Constant(0, 8)), sc.BV(0, 8)) self.assertEqual(psx, sc.Symbol("x", typing.BVType(8))) self.assertEqual(bv2pysmt(~bvx), sc.BVNot(psx)) self.assertEqual(bv2pysmt(bvx & bvy), sc.BVAnd(psx, psy)) self.assertEqual(bv2pysmt(bvx | bvy), sc.BVOr(psx, psy)) self.assertEqual(bv2pysmt(bvx ^ bvy), sc.BVXor(psx, psy)) self.assertEqual(bv2pysmt(BvComp(bvx, bvy)), sc.Equals(psx, psy)) self.assertEqual(bv2pysmt(BvNot(BvComp(bvx, bvy))), sc.Not(sc.Equals(psx, psy))) self.assertEqual(bv2pysmt(bvx < bvy), sc.BVULT(psx, psy)) self.assertEqual(bv2pysmt(bvx <= bvy), sc.BVULE(psx, psy)) self.assertEqual(bv2pysmt(bvx > bvy), sc.BVUGT(psx, psy)) self.assertEqual(bv2pysmt(bvx >= bvy), sc.BVUGE(psx, psy)) self.assertEqual(bv2pysmt(bvx << bvy), sc.BVLShl(psx, psy)) self.assertEqual(bv2pysmt(bvx >> bvy), sc.BVLShr(psx, psy)) self.assertEqual(bv2pysmt(RotateLeft(bvx, 1)), sc.BVRol(psx, 1)) self.assertEqual(bv2pysmt(RotateRight(bvx, 1)), sc.BVRor(psx, 1)) self.assertEqual(bv2pysmt(bvx[4:2]), sc.BVExtract(psx, 2, 4)) self.assertEqual(bv2pysmt(Concat(bvx, bvy)), sc.BVConcat(psx, psy)) # zeroextend reduces to Concat # self.assertEqual(bv2pysmt(ZeroExtend(bvx, 2)), sc.BVZExt(psx, 2)) self.assertEqual(bv2pysmt(Repeat(bvx, 2)), psx.BVRepeat(2)) self.assertEqual(bv2pysmt(-bvx), sc.BVNeg(psx)) self.assertEqual(bv2pysmt(bvx + bvy), sc.BVAdd(psx, psy)) # bvsum reduces to add # self.assertEqual(bv2pysmt(bvx - bvy), sc.BVSub(psx, psy)) self.assertEqual(bv2pysmt(bvx * bvy), sc.BVMul(psx, psy)) self.assertEqual(bv2pysmt(bvx / bvy), sc.BVUDiv(psx, psy)) self.assertEqual(bv2pysmt(bvx % bvy), sc.BVURem(psx, psy))
def test_pysmt_operations(self, width, x, y): try: from pysmt import shortcuts as sc except ImportError: return modulus = 2 ** width x = x % modulus y = y % modulus bvx = Constant(x, width) bvy = Constant(y, width) psx = sc.BV(x, width) psy = sc.BV(y, width) def eval_pysmt(pysmt_var): return pysmt_var.simplify().constant_value() self.assertEqual(~bvx, eval_pysmt(sc.BVNot(psx))) self.assertEqual(bvx & bvy, eval_pysmt(sc.BVAnd(psx, psy))) self.assertEqual(bvx | bvy, eval_pysmt(sc.BVOr(psx, psy))) self.assertEqual(bvx ^ bvy, eval_pysmt(sc.BVXor(psx, psy))) self.assertEqual(BvComp(bvx, bvy), eval_pysmt(sc.BVComp(psx, psy))) self.assertEqual((bvx < bvy), eval_pysmt(sc.BVULT(psx, psy))) self.assertEqual((bvx <= bvy), eval_pysmt(sc.BVULE(psx, psy))) self.assertEqual((bvx > bvy), eval_pysmt(sc.BVUGT(psx, psy))) self.assertEqual((bvx >= bvy), eval_pysmt(sc.BVUGE(psx, psy))) r = y % bvx.width self.assertEqual(bvx << bvy, eval_pysmt(sc.BVLShl(psx, psy))) self.assertEqual(bvx >> bvy, eval_pysmt(sc.BVLShr(psx, psy))) self.assertEqual(RotateLeft(bvx, r), eval_pysmt(sc.BVRol(psx, r))) self.assertEqual(RotateRight(bvx, r), eval_pysmt(sc.BVRor(psx, r))) bvb = Constant(y % 2, 1) psb = sc.Bool(bool(bvb)) self.assertEqual(Ite(bvb, bvx, bvy), eval_pysmt(sc.Ite(psb, psx, psy))) j = y % bvx.width self.assertEqual(bvx[:j], eval_pysmt(sc.BVExtract(psx, start=j))) self.assertEqual(bvx[j:], eval_pysmt(sc.BVExtract(psx, end=j))) self.assertEqual(Concat(bvx, bvy), eval_pysmt(sc.BVConcat(psx, psy))) self.assertEqual(ZeroExtend(bvx, j), eval_pysmt(sc.BVZExt(psx, j))) self.assertEqual(Repeat(bvx, 1 + j), eval_pysmt(psx.BVRepeat(1 + j))) self.assertEqual(-bvx, eval_pysmt(sc.BVNeg(psx))) self.assertEqual(bvx + bvy, eval_pysmt(sc.BVAdd(psx, psy))) self.assertEqual(bvx - bvy, eval_pysmt(sc.BVSub(psx, psy))) self.assertEqual(bvx * bvy, eval_pysmt(sc.BVMul(psx, psy))) if bvy > 0: self.assertEqual(bvx / bvy, eval_pysmt(sc.BVUDiv(psx, psy))) self.assertEqual(bvx % bvy, eval_pysmt(sc.BVURem(psx, psy)))
def is_valid(self): """Return the bv expression for non-zero propagation probability. >>> from arxpy.bitvector.core import Constant >>> from arxpy.diffcrypt.difference import DiffVar >>> from arxpy.ciphers.simon32_64 import XDF >>> x, y = DiffVar("x", 16), DiffVar("y", 16) >>> d = XDF(x, y) >>> d.is_valid() # doctest: +ELLIPSIS Ite(0xffff == x, 0b0 == (((0x00ff & ((0x0f0f & ((0x3333 ... >>> zero = Constant(0, 16) >>> d.is_valid().xreplace({x: zero, y: zero}) 0b1 """ a, b, c = self.op.a, self.op.b, self.op.c n = self.input_diff[0].width assert gcd(n, a - b) == 1 and a > b and n % 2 == 0 alpha = self.input_diff[0] beta = self.output_diff BvRol = RotateLeft varibits = BvRol(alpha, a) | BvRol(alpha, b) doublebits = BvRol(alpha, b) & (~BvRol(alpha, a)) & BvRol( alpha, 2 * a - b) gamma = beta ^ BvRol(alpha, c) def is_even(x): return BvComp(x[0], Constant(0, 1)) case2 = BvComp(Constant(0, n), (gamma & (~varibits)) | ((gamma ^ BvRol(gamma, a - b)) & doublebits)) condition = Ite(BvComp(alpha, ~Constant(0, n)), is_even(_HammingWeight(gamma)), case2) return condition
def weight(self, output_diff): """Return the weight of a possible output `XorDiff`. >>> from arxpy.bitvector.core import Constant, Variable >>> from arxpy.bitvector.context import NotEvaluation >>> from arxpy.bitvector.printing import BvWrapPrinter >>> from arxpy.bitvector.extraop import PopCount >>> from arxpy.differential.difference import XorDiff >>> alpha = XorDiff(Constant(0, 16)) >>> f = XDSimonRF(alpha) >>> f.weight(XorDiff(Constant(0, 16))) 0b00000 >>> alpha = XorDiff(Variable("u", 16)) >>> f = XDSimonRF(alpha) >>> beta = XorDiff(Variable("v", 16)) >>> with NotEvaluation([PopCount]): ... print(BvWrapPrinter().doprint(f.weight(beta))) Ite(0xffff == u, 0b01111, PopCount((~(u <<< 8) & (u <<< 1) & (u <<< 15)) ^ ((u <<< 1) | (u <<< 8))) See `Derivative.weight` for more information. """ a, b = self.op.a, self.op.b n = self.input_diff[0].val.width alpha = self.input_diff[0].val Rol = RotateLeft varibits = Rol(alpha, a) | Rol(alpha, b) r = (2 * a - b) % n doublebits = (Rol(alpha, b) & (~Rol(alpha, a)) & Rol(alpha, r)) hw = PopCount(varibits ^ doublebits) width = max((n - 1).bit_length(), hw.width) value = Ite(BvComp(alpha, ~Constant(0, n)), Constant(n - 1, width), ZeroExtend(hw, width - hw.width)) return value
def test_SearchRkCh(self): for diff_type in [XorDiff, RXDiff]: for cipher in [Cipher1, Cipher2]: if diff_type == RXDiff and cipher == Cipher2: continue cipher.set_rounds(1) for option in RKCH_OPTIONS: if diff_type == RXDiff and option.enc_der_mode == RkChSearchMode.OptimalFixEncMinKey: continue btor_rkch_found = test_search_related_key_ch( cipher=cipher, diff_type=diff_type, initial_ew=option.initial_ew, initial_kw=option.initial_kw, solver_name="btor", rounds=1, key_der_mode=option.key_der_mode, enc_der_mode=option.enc_der_mode, allow_zero_enc_input_diff=True, search_mode=option.search_mode, check=True, verbose_level=VERBOSE_LEVEL, filename=None) if btor_rkch_found is not None: btor_weight = [ int(btor_rkch_found.key_ch_found.ch_weight), int(btor_rkch_found.enc_ch_found.ch_weight) ] btor_id = [ value.val for var, value in btor_rkch_found.key_ch_found.input_diff ] self.assertFalse( BvComp(functools.reduce(Concat, btor_id), 0)) else: btor_weight = [math.inf, math.inf] if diff_type == XorDiff: self.assertEqual( [option.initial_kw, option.initial_ew], btor_weight) elif diff_type == RXDiff: if option.enc_der_mode == DerMode.ProbabilityOne: self.assertEqual([math.inf, math.inf], btor_weight) elif option.search_mode in [ RkChSearchMode.FirstMinSum, RkChSearchMode.FirstValidKeyMinEnc ]: self.assertEqual([0, 1], btor_weight) yices_rkch_found = test_search_related_key_ch( cipher=cipher, diff_type=diff_type, initial_ew=option.initial_ew, initial_kw=option.initial_kw, solver_name="yices", rounds=1, key_der_mode=option.key_der_mode, enc_der_mode=option.enc_der_mode, allow_zero_enc_input_diff=True, search_mode=option.search_mode, check=True, verbose_level=1 if VERBOSE_LEVEL >= 2 else 0, filename=None) if yices_rkch_found is not None: yices_weight = [ int(yices_rkch_found.key_ch_found.ch_weight), int(yices_rkch_found.enc_ch_found.ch_weight) ] yices_id = [ value.val for var, value in yices_rkch_found.key_ch_found.input_diff ] self.assertFalse( BvComp(functools.reduce(Concat, yices_id), 0)) else: yices_weight = [math.inf, math.inf] if option.search_mode in [ RkChSearchMode.FirstValidKeyMinEnc, RkChSearchMode.OptimalValidKeyMinEnc ]: # ignore key weights self.assertEqual(btor_weight[1], yices_weight[1]) else: self.assertEqual(btor_weight, yices_weight)
def test_search_RkCh(self): diff_type = XorDiff for bc in BLOCK_CIPHERS: if bc.rk_rounds is None: continue for rounds in range(bc.rk_rounds, bc.rk_rounds + 2): bc.cipher.set_rounds(rounds) for option in RK_OPTIONS: btor_rkch_found = test_search_related_key_ch( cipher=bc.cipher, diff_type=diff_type, initial_ew=option.initial_ew, initial_kw=option.initial_kw, solver_name="btor", rounds=rounds, key_der_mode=option.key_der_mode, enc_der_mode=option.enc_der_mode, allow_zero_enc_input_diff=True, search_mode=option.search_mode, check=False if option.search_mode in NoCheckModes else CHECK, verbose_level=VERBOSE_LEVEL, filename=self.filename) if btor_rkch_found is not None: btor_weight = [ int(btor_rkch_found.key_ch_found.ch_weight), int(btor_rkch_found.enc_ch_found.ch_weight) ] btor_id = [ value.val for var, value in btor_rkch_found.key_ch_found.input_diff ] self.assertFalse( BvComp(functools.reduce(Concat, btor_id), 0)) else: btor_weight = [math.inf, math.inf] yices_rkch_found = test_search_related_key_ch( cipher=bc.cipher, diff_type=diff_type, initial_ew=option.initial_ew, initial_kw=option.initial_kw, solver_name="yices", rounds=rounds, key_der_mode=option.key_der_mode, enc_der_mode=option.enc_der_mode, allow_zero_enc_input_diff=True, search_mode=option.search_mode, check=False, verbose_level=1 if VERBOSE_LEVEL >= 2 else 0, filename=self.filename) if yices_rkch_found is not None: yices_weight = [ int(yices_rkch_found.key_ch_found.ch_weight), int(yices_rkch_found.enc_ch_found.ch_weight) ] yices_id = [ value.val for var, value in yices_rkch_found.key_ch_found.input_diff ] self.assertFalse( BvComp(functools.reduce(Concat, yices_id), 0)) else: yices_weight = [math.inf, math.inf] if option.search_mode in [ RkChSearchMode.FirstValidKeyMinEnc, RkChSearchMode.OptimalValidKeyMinEnc ]: # ignore key weights self.assertEqual(btor_weight[1], yices_weight[1]) else: self.assertAlmostEqual(sum(btor_weight), sum(yices_weight))
def is_even(x): return BvComp(x[0], Constant(0, 1))
def test_bv2pysmt(self): bv2pysmt = functools.partial(_bv2pysmt, env=self.env) fm = self.env.formula_manager tm = self.env.type_manager bx, by = Variable("x", 8), Variable("y", 8) b1x, b1y = Variable("x1", 1), Variable("y1", 1) b6x, b6y = Variable("x6", 6), Variable("y6", 6) px, py = bv2pysmt(bx), bv2pysmt(by) p1x, p1y = bv2pysmt(b1x, True), bv2pysmt(b1y, True) p6x, p6y = bv2pysmt(b6x), bv2pysmt(b6y) self.assertEqual(bv2pysmt(Constant(0, 8)), fm.BV(0, 8)) self.assertEqual(px, fm.Symbol("x", tm.BVType(8))) self.assertEqual(p1x, fm.Symbol("x1", tm.BOOL())) self.assertEqual(bv2pysmt(~bx), fm.BVNot(px)) self.assertEqual(bv2pysmt(~b1x, True), fm.Not(p1x)) self.assertEqual(bv2pysmt(bx & by), fm.BVAnd(px, py)) self.assertEqual(bv2pysmt(b1x & b1y, True), fm.And(p1x, p1y)) self.assertEqual(bv2pysmt(bx | by), fm.BVOr(px, py)) self.assertEqual(bv2pysmt(b1x | b1y, True), fm.Or(p1x, p1y)) self.assertEqual(bv2pysmt(bx ^ by), fm.BVXor(px, py)) self.assertEqual(bv2pysmt(b1x ^ b1y, True), fm.Xor(p1x, p1y)) self.assertEqual(bv2pysmt(BvComp(bx, by)), fm.BVComp(px, py)) self.assertEqual(bv2pysmt(BvComp(bx, by), True), fm.Equals(px, py)) self.assertEqual(bv2pysmt(BvNot(BvComp(bx, by))), fm.BVNot(fm.BVComp(px, py))) self.assertEqual(bv2pysmt(BvNot(BvComp(bx, by)), True), fm.Not(fm.Equals(px, py))) self.assertEqual(bv2pysmt(bx < by), fm.BVULT(px, py)) self.assertEqual(bv2pysmt(bx <= by), fm.BVULE(px, py)) self.assertEqual(bv2pysmt(bx > by), fm.BVUGT(px, py)) self.assertEqual(bv2pysmt(bx >= by), fm.BVUGE(px, py)) self.assertEqual(bv2pysmt(bx << by), fm.BVLShl(px, py)) self.assertEqual(bv2pysmt(bx >> by), fm.BVLShr(px, py)) self.assertEqual(bv2pysmt(RotateLeft(bx, 1)), fm.BVRol(px, 1)) self.assertEqual(bv2pysmt(RotateRight(bx, 1)), fm.BVRor(px, 1)) def zext(pysmt_type, offset): # zero_extend reduces to Concat return fm.BVConcat(fm.BV(0, offset), pysmt_type) self.assertEqual( bv2pysmt(b6x << b6y, strict_shift=True), fm.BVExtract(fm.BVLShl(zext(p6x, 2), zext(p6y, 2)), 0, 5)) self.assertEqual( bv2pysmt(RotateRight(b6x, 1), strict_shift=True), fm.BVConcat(fm.BVExtract(p6x, 0, 0), fm.BVExtract(p6x, 1, 5))) self.assertEqual(bv2pysmt(bx[4:2]), fm.BVExtract(px, 2, 4)) self.assertEqual(bv2pysmt(Concat(bx, by)), fm.BVConcat(px, py)) self.assertEqual(bv2pysmt(ZeroExtend(bx, 2)), zext(px, 2)) self.assertEqual(bv2pysmt(Repeat(bx, 2)), px.BVRepeat(2)) self.assertEqual(bv2pysmt(-bx), fm.BVNeg(px)) self.assertEqual(bv2pysmt(bx + by), fm.BVAdd(px, py)) # bv_sum reduces to add self.assertEqual(bv2pysmt(bx - by), fm.BVSub(px, py)) self.assertEqual(bv2pysmt(bx * by), fm.BVMul(px, py)) self.assertEqual(bv2pysmt(bx / by), fm.BVUDiv(px, py)) self.assertEqual(bv2pysmt(bx % by), fm.BVURem(px, py)) # cannot reuse Bool and BV{1} variable with the same name bxx, byy = Variable("xx", 8), Variable("yy", 8) b1xx, b1yy, b1zz = Variable("xx1", 1), Variable("yy1", 1), Variable("zz1", 1) pxx, pyy = bv2pysmt(bxx), bv2pysmt(byy) p1xx, p1yy, p1zz = bv2pysmt(b1xx, False), bv2pysmt(b1yy, True), bv2pysmt( b1zz, True) self.assertEqual(bv2pysmt(Ite(b1xx, bxx, byy)), fm.Ite(fm.Equals(p1xx, fm.BV(1, 1)), pxx, pyy)) self.assertEqual(bv2pysmt(Ite(b1xx, b1yy, b1zz), True), fm.Ite(fm.Equals(p1xx, fm.BV(1, 1)), p1yy, p1zz))