def compute_logical(vec, X, Y, ctx, use_esf): nbits = X.nbits e = imm(1) for i in range(nbits): e *= X.eval(vec, i, use_esf) + Y.eval(vec, i, use_esf) + imm(1) simplify_inplace(e) return e
def test_N(nbits, X, n): ret = imm(1) for i in range(nbits): if ((n >> i) & 1) == 1: ret *= X[i] else: ret *= X[i] + imm(1) simplify_inplace(ret) return ret
def matrix_v(i, j): if i == j: return imm(1) if i < j: return imm(0) if i > j: mask = (~((1 << (j)) - 1)) & self.max_uint mask2 = ((1 << (i)) - 1) & self.max_uint mask &= mask2 return imm((n & mask) == mask)
def sub_Y(self, X, Y): carry = imm(0) ret = Vector(self.nbits) if self.use_esf: for i in range(0, self.nbits): ret[i] = simplify_inplace(X[i]+Y[i]+carry) carry = esf(2, [X[i]+imm(1), Y[i], carry]) else: for i in range(0, self.nbits): sum_XY = simplify_inplace(X[i]+Y[i]) ret[i] = simplify_inplace(sum_XY+carry) carry = simplify_inplace((X[i]+imm(1))*Y[i] + (carry * (sum_XY+imm(1)))) return ret
def evaluate_expr(E, nbits, map_): # keys of map_ can be mba variables or symbols # => an mba variable must map to an integer # => a symbol must map to an expression keys = [] values = [] for k,v in six.iteritems(map_): # TOFIX: not a clean test if hasattr(k, "vec"): if not isinstance(v, six.integer_types): raise ValueError("an MBAVariable must map to an integer value!") keys.extend(k.vec) values.extend(imm((v>>i)&1) for i in range(k.nbits)) elif isinstance(k, Expr): if not k.is_sym(): raise ValueError("only symbols or MBAVariable can be a key") if not isinstance(v, Expr): raise ValueError("a symbol can only be mapped to an expression") keys.append(k) values.append(v) E = expand_esf(E) simplify_inplace(E) subs_exprs_inplace(E, keys, values) simplify_inplace(E) try: return E.get_int_be() except RuntimeError: return E
def __identify(app, in_name): # TODO: identify number of independant inputs NL = app.nl().vector() M = app.matrix() nbits_in = M.ncols() nbits_out = M.nlines() if nbits_in != nbits_out: raise ValueError("do not yet support application with a different\ number of input and output bits!") mba = MBA(nbits_in) var_in = mba.var(in_name) if NL != Vector(len(NL)): return _identify_nonaffine(app, var_in) C = EX.ExprCst(mba.from_vec(app.cst()).to_cst(), nbits_out) if M == Matrix(nbits_out, nbits_in): # This is just a constant return C ret = EX.ExprBV(var_in) matrix_empty = 0 # Find empty columns in the matrix. for j in range(nbits_in): is_zero = reduce(operator.and_, (M.at(i, j) == imm(0) for i in range(nbits_out)), True) if is_zero: matrix_empty |= 1 << j matrix_and_mask = (~matrix_empty) % (2**nbits_out) if matrix_empty != 0: ret = EX.ExprAnd(ret, EX.ExprCst(matrix_and_mask, nbits_out)) if mba.from_vec(M * var_in.vec) ^ (var_in & matrix_empty) == var_in: # This is a XOR return EX.ExprXor(ret, C) raise ValueError("unable to identify an expression")
def or_n(self, X, n): ret = Vector(self.nbits) for i in range(self.nbits): if n & (1 << i): ret[i] = imm(1) else: ret[i] = X[i] return ret
def iadd_lshifted_Y(self, X, Y, offset): if self.use_esf: self.iadd_Y(X, self.lshift_n(Y, offset)) simplify_inplace(X) return carry = imm(0) for i in range(0, self.nbits): if i < offset: Yi = imm(0) else: Yi = Y[i - offset] Xi = X[i] mul_XY = simplify_inplace(Xi * Yi) Xi += Yi simplify_inplace(Xi) carry_new = simplify_inplace(mul_XY + (carry * Xi)) Xi += carry simplify_inplace(Xi) carry = carry_new
def solve(self, X): nbits = len(X.vec) idx_base = X[0].sym_idx() for I0 in self.I0s: I0.difference_update(self.I1) if (len(I0) == 0): return [] self.I0s = [I0 for I0 in self.I0s if len(I0) > 0] fix1 = Vector(X.vec) for idx in self.I1: idx = self.__idx(idx, idx_base, nbits) fix1[idx] = imm(1) if (len(self.I0s) == 0): return [fix1] ret = [] def iter_zeros(idxes, I0s): if len(I0s) == 0: yield idxes return for i,I0 in enumerate(I0s): if I0.isdisjoint(idxes): next_I0 = I0 next_idx = i break else: yield idxes return for idx in next_I0: new_idxes = idxes + [idx] for z in iter_zeros(new_idxes, I0s[next_idx+1:]): yield z for idxes in iter_zeros([], self.I0s): new = Vector(fix1) for idx in idxes: new[self.__idx(idx, idx_base, nbits)] = imm(0) ret.append(new) return ret
def compute(self, vec, i, args, ctx, use_esf): if ((self.mask >> i) & 1) == 1: return imm(1) args = list(args) ret = esf(1, args) for i in range(2, len(args) + 1): ret += esf(i, args) if not use_esf: expand_esf_inplace(ret) simplify_inplace(ret) return ret
def compute_binop_(vec, i, X, Y, CC, use_esf): carry = CC.carry sum_args = simplify_inplace(X + Y) ret = simplify_inplace(sum_args + carry) carry = esf(2, [X + imm(1), Y, carry]) if not use_esf: expand_esf_inplace(carry) carry = simplify_inplace(carry) CC.carry = carry return ret
def iadd_Y(self, X, Y): carry = imm(0) ret = Vector(self.nbits) if self.use_esf: for i in range(0, self.nbits): new_carry = esf(2, [X[i], Y[i], carry]) X[i] += simplify_inplace(Y[i] + carry) carry = new_carry else: for i in range(0, self.nbits): sum_XY = simplify_inplace(X[i] + Y[i]) new_carry = simplify_inplace(X[i] * Y[i] + (carry * sum_XY)) X[i] = sum_XY + carry carry = new_carry return ret
def permut2expr(self, P, X): ret = Vector(self.nbits) v0 = P[0] nbits_in = (len(P) - 1).bit_length() for k, v in enumerate(P[1:]): v ^= v0 if v == 0: continue k += 1 test = test_N(nbits_in, X, k) for i in range(self.nbits): if ((v >> i) & 1) == 1: ret[i] += test for i in range(self.nbits): ret[i] += imm((v0 >> i) & 1) simplify_inplace(ret) return ret
def eval(self, vec, i, ctx, args, use_esf): return imm((self.n >> i) & 1)
def compute_logical(vec, X, Y, ctx, use_esf): return simplify_inplace( ExprCmpEq.compute_logical(vec, X, Y, ctx, use_esf) + imm(1))
def __init__(self, nbits): self.cache = [CtxUninitialized] * nbits self.last_bit = -1 self.carry = imm(0)
def eval(self, vec, i, ctx, args, use_esf): if (i >= self.arg_nbits): return imm(0) return args[0].eval(vec, i, use_esf)
def eval(self, vec, i, ctx, args, use_esf): if i >= self.nbits - self.n: return imm(False) return args[0].eval(vec, i + self.n, use_esf)
def compute(self, vec, i, args, ctx, use_esf): if ((self.mask >> i) & 1) == 0: return imm(0) return reduce(lambda x, y: x * y, args)
def compute(self, vec, i, args, ctx, use_esf): return sum(args, imm(0))
def eval(self, vec, i, ctx, args, use_esf): return args[0].eval(vec, i, use_esf) + imm(True)
def f(i, j): if i != j: return imm(0) return X[i]
def from_bytes(self, s): ret = Vector(self.nbits) for i, c in enumerate(six.iterbytes(s)): for j in range(8): ret[i * 8 + j] = imm((c >> j) & 1) return ret