+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,
+