X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/b39fadb608dd52cbd6fc8a11001661083d8d078b..ebb0df1d8203932379849c05bf8281b99985bd22:/utils/advmodes diff --git a/utils/advmodes b/utils/advmodes index e0dd3868..c65a9338 100755 --- a/utils/advmodes +++ b/utils/advmodes @@ -38,6 +38,19 @@ def poly(nbits): if p.irreduciblep(): POLYMAP[nbits] = p; return p raise ValueError, nbits +def prim(nbits): + ## No fancy way to do this: I'd need a much cleverer factoring algorithm + ## than I have in my pockets. + if nbits == 64: cc = [64, 4, 3, 1, 0] + elif nbits == 96: cc = [96, 10, 9, 6, 0] + elif nbits == 128: cc = [128, 7, 2, 1, 0] + elif nbits == 192: cc = [192, 15, 11, 5, 0] + elif nbits == 256: cc = [256, 10, 5, 2, 0] + else: raise ValueError, 'no field for %d bits' % nbits + p = C.GF(0) + for c in cc: p = p.setbit(c) + return p + def Z(n): return C.ByteString.zero(n) @@ -560,6 +573,20 @@ def pmac1(E, m): else: a ^= pad10star(tl, blksz) return E.encrypt(a) +def pmac2(E, m): + blksz = E.__class__.blksz + p = prim(8*blksz) + L = E.encrypt(Z(blksz)) + o = mul_blk_gf(L, 10, p) + a = Z(blksz) + v, tl = blocks(m, blksz) + for x in v: + a ^= E.encrypt(x ^ o) + o = mul_blk_gf(o, 2, p) + if len(tl) == blksz: a ^= tl ^ mul_blk_gf(o, 3, p) + else: a ^= pad10star(tl, blksz) ^ mul_blk_gf(o, 5, p) + return E.encrypt(a) + def pmac1_pub(E, m): if VERBOSE: dump_ocb(E) return pmac1(E, m), @@ -647,6 +674,66 @@ def ocb1dec(E, n, h, y, t): if t == u[:len(t)]: return C.ByteString(m), else: return None, +def ocb2enc(E, n, h, m, tsz = None): + ## For OCB2, it's important for security that n = log_x (x + 1) is large in + ## the field representations of GF(2^w) used -- in fact, we need more, that + ## i n (mod 2^w - 1) is large for i in {4, -3, -2, -1, 1, 2, 3, 4}. The + ## original paper lists the values for 64 and 128, but we support other + ## block sizes, so here's the result of the (rather large, in some cases) + ## computation. + ## + ## Block size log_x (x + 1) + ## + ## 64 9686038906114705801 + ## 96 63214690573408919568138788065 + ## 128 338793687469689340204974836150077311399 + ## 192 161110085006042185925119981866940491651092686475226538785 + ## 256 22928580326165511958494515843249267194111962539778797914076675796261938307298 + + blksz = E.__class__.blksz + if tsz is None: tsz = blksz + p = prim(8*blksz) + L = E.encrypt(n) + o = mul_blk_gf(L, 2, p) + a = Z(blksz) + v, tl = blocks(m, blksz) + y = C.WriteBuffer() + for x in v: + a ^= x + y.put(E.encrypt(x ^ o) ^ o) + o = mul_blk_gf(o, 2, p) + n = len(tl) + yfinal = E.encrypt(C.MP(8*n).storeb(blksz) ^ o) + cfinal = tl ^ yfinal[:n] + a ^= (tl + yfinal[n:]) ^ mul_blk_gf(o, 3, p) + y.put(cfinal) + t = E.encrypt(a) + if h: t ^= pmac2(E, h) + return C.ByteString(y), C.ByteString(t[:tsz]) + +def ocb2dec(E, n, h, y, t): + blksz = E.__class__.blksz + p = prim(8*blksz) + L = E.encrypt(n) + o = mul_blk_gf(L, 2, p) + a = Z(blksz) + v, tl = blocks(y, blksz) + m = C.WriteBuffer() + for x in v: + u = E.encrypt(x ^ o) ^ o + y.put(u) + a ^= u + o = mul_blk_gf(o, 2, p) + n = len(tl) + yfinal = E.encrypt(C.MP(8*n).storeb(blksz) ^ o) + mfinal = tl ^ yfinal[:n] + a ^= (mfinal + yfinal[n:]) ^ mul_blk_gf(o, 3, p) + m.put(mfinal) + u = E.encrypt(a) + if h: u ^= pmac2(E, h) + if t == u[:len(t)]: return C.ByteString(m), + else: return None, + def ocbgen(bc): w = bc.blksz return [(w, 0, 0), (w, 1, 0), (w, 0, 1), @@ -674,6 +761,8 @@ MODEMAP = { 'eax-enc': (eaxgen, 3*[binarg] + [intarg], eaxenc), 'gcm-dec': (dummygen, 4*[binarg], gcmdec), 'ocb1-enc': (ocbgen, 3*[binarg] + [intarg], ocb1enc), 'ocb1-dec': (dummygen, 4*[binarg], ocb1dec), + 'ocb2-enc': (ocbgen, 3*[binarg] + [intarg], ocb2enc), + 'ocb2-dec': (dummygen, 4*[binarg], ocb2dec), 'pmac1': (pmacgen, [binarg], pmac1_pub) } mode = argv[1]