3 from sys
import argv
, exit
4 from struct
import unpack
, pack
5 from itertools
import izip
10 ###--------------------------------------------------------------------------
17 yield [things
[i
] for i
in ii
]
19 if j
== k
- 1: lim
= n
32 try: return POLYMAP
[nbits
]
34 base
= C
.GF(0).setbit(nbits
).setbit(0)
35 for k
in xrange(1, nbits
, 2):
36 for cc
in combs(range(1, nbits
), k
):
37 p
= base
+ sum((C
.GF(0).setbit(c
) for c
in cc
), C
.GF(0))
38 if p
.irreduciblep(): POLYMAP
[nbits
] = p
; return p
39 raise ValueError, nbits
42 ## No fancy way to do this: I'd need a much cleverer factoring algorithm
43 ## than I have in my pockets.
44 if nbits
== 64: cc
= [64, 4, 3, 1, 0]
45 elif nbits
== 96: cc
= [96, 10, 9, 6, 0]
46 elif nbits
== 128: cc
= [128, 7, 2, 1, 0]
47 elif nbits
== 192: cc
= [192, 15, 11, 5, 0]
48 elif nbits
== 256: cc
= [256, 10, 5, 2, 0]
49 else: raise ValueError, 'no field for %d bits' % nbits
51 for c
in cc
: p
= p
.setbit(c
)
55 return C
.ByteString
.zero(n
)
57 def mul_blk_gf(m
, x
, p
): return ((C
.GF
.loadb(m
)*x
)%p
).storeb((p
.nbits
+ 6)/8)
62 except StopIteration: raise ValueError, 'empty iter'
67 except StopIteration: lastp
= True
71 if len(x
): return hex(x
)
76 if isinstance(ksz
, C
.KeySZSet
): kk
= ksz
.set
77 elif isinstance(ksz
, C
.KeySZRange
): kk
= range(ksz
.min, ksz
.max, ksz
.mod
)
78 elif isinstance(ksz
, C
.KeySZAny
): kk
= range(64); sel
= [0]
79 kk
= list(kk
); kk
= kk
[:]
81 while n
and len(sel
) < 4:
84 kk
[i
], kk
[n
] = kk
[n
], kk
[i
]
93 return C
.ByteString(m
)
97 if r
: m
+= '\x80' + Z(r
- 1)
98 return C
.ByteString(m
)
102 while (i
&1) == 0: i
>>= 1; j
+= 1
106 v
, i
, n
= [], 0, len(x
)
108 v
.append(C
.ByteString(x
[i
:i
+ w
]))
110 return v
, C
.ByteString(x
[i
:])
116 if len(tl
) == w
: v
.append(tl
); tl
= EMPTY
119 def dummygen(bc
): return []
123 ###--------------------------------------------------------------------------
126 class RC6Cipher (type):
127 def __new__(cls
, w
, r
):
128 name
= 'rc6-%d/%d' %
(w
, r
)
129 me
= type(name
, (RC6Base
,), {})
134 me
.keysz
= C
.KeySZRange(me
.blksz
, 1, 255, 1)
138 return w
.bit_length() - 1
141 m0
, m1
= C
.MP(0).setbit(w
- n
) - 1, C
.MP(0).setbit(n
) - 1
142 return ((x
&m0
) << n
) |
(x
>> (w
- n
))&m1
145 m0
, m1
= C
.MP(0).setbit(n
) - 1, C
.MP(0).setbit(w
- n
) - 1
146 return ((x
&m0
) << (w
- n
)) |
(x
>> n
)&m1
148 class RC6Base (object):
151 P400
= C
.MP(0xb7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfef324e7738926cfbe5f4bf8d8d8c31d763da06)
152 Q400
= C
.MP(0x9e3779b97f4a7c15f39cc0605cedc8341082276bf3a27251f86c6a11d0c18e952767f0b153d27b7f0347045b5bf1827f0188)
156 ## Build the magic numbers.
157 P
= me
.P400
>> (400 - me
.w
)
159 Q
= me
.Q400
>> (400 - me
.w
)
161 M
= C
.MP(0).setbit(me
.w
) - 1
163 ## Convert the key into words.
165 c
= (len(k
) + wb
- 1)/wb
166 kb
, ktl
= blocks(k
, me
.w
/8)
167 L
= map(C
.MP
.loadl
, kb
+ [ktl
])
170 ## Build the subkey table.
173 S
= [(P
+ i
*Q
)&M
for i
in xrange(n
)]
175 ##for j in xrange(c):
176 ## print 'L[%3d] = %s' % (j, hex(L[j]).upper()[2:].rjust(2*wb, '0'))
177 ##for i in xrange(n):
178 ## print 'S[%3d] = %s' % (i, hex(S[i]).upper()[2:].rjust(2*wb, '0'))
183 for s
in xrange(3*max(c
, n
)):
184 A
= S
[i
] = rol(me
.w
, S
[i
] + A
+ B
, 3)
185 B
= L
[j
] = rol(me
.w
, L
[j
] + A
+ B
, (A
+ B
)%(1 << me
.d
))
186 ##print 'S[%3d] = %s' % (i, hex(S[i]).upper()[2:].rjust(2*wb, '0'))
187 ##print 'L[%3d] = %s' % (j, hex(L[j]).upper()[2:].rjust(2*wb, '0'))
195 M
= C
.MP(0).setbit(me
.w
) - 1
196 a
, b
, c
, d
= map(C
.MP
.loadl
, blocks0(x
, me
.blksz
/4)[0])
199 ##print 'B = %s' % (hex(b).upper()[2:].rjust(me.w/4, '0'))
200 ##print 'D = %s' % (hex(d).upper()[2:].rjust(me.w/4, '0'))
201 for i
in xrange(2, 2*me
.r
+ 2, 2):
202 t
= rol(me
.w
, 2*b
*b
+ b
, me
.d
)
203 u
= rol(me
.w
, 2*d
*d
+ d
, me
.d
)
204 a
= (rol(me
.w
, a ^ t
, u
%(1 << me
.d
)) + me
.s
[i
+ 0])&M
205 c
= (rol(me
.w
, c ^ u
, t
%(1 << me
.d
)) + me
.s
[i
+ 1])&M
206 ##print 'A = %s' % (hex(a).upper()[2:].rjust(me.w/4, '0'))
207 ##print 'C = %s' % (hex(c).upper()[2:].rjust(me.w/4, '0'))
208 a
, b
, c
, d
= b
, c
, d
, a
209 a
= (a
+ me
.s
[2*me
.r
+ 2])&M
210 c
= (c
+ me
.s
[2*me
.r
+ 3])&M
211 ##print 'A = %s' % (hex(a).upper()[2:].rjust(me.w/4, '0'))
212 ##print 'C = %s' % (hex(c).upper()[2:].rjust(me.w/4, '0'))
213 return C
.ByteString(a
.storel(me
.blksz
/4) + b
.storel(me
.blksz
/4) +
214 c
.storel(me
.blksz
/4) + d
.storel(me
.blksz
/4))
217 M
= C
.MP(0).setbit(me
.w
) - 1
218 a
, b
, c
, d
= map(C
.MP
.loadl
, blocks0(x
, me
.blksz
/4))
219 c
= (c
- me
.s
[2*me
.r
+ 3])&M
220 a
= (a
- me
.s
[2*me
.r
+ 2])&M
221 for i
in xrange(2*me
.r
+ 1, 1, -2):
222 a
, b
, c
, d
= d
, a
, b
, c
223 u
= rol(me
.w
, 2*d
*d
+ d
, me
.d
)
224 t
= rol(me
.w
, 2*b
*b
+ b
, me
.d
)
225 c
= ror(me
.w
, (c
- me
.s
[i
+ 1])&M
, t
%(1 << me
.d
)) ^ u
226 a
= ror(me
.w
, (a
- me
.s
[i
+ 0])&M
, u
%(1 << me
.d
)) ^ t
227 a
= (a
+ s
[2*me
.r
+ 2])&M
228 c
= (c
+ s
[2*me
.r
+ 3])&M
229 return C
.ByteString(a
.storel(me
.blksz
/4) + b
.storel(me
.blksz
/4) +
230 c
.storel(me
.blksz
/4) + d
.storel(me
.blksz
/4))
232 for (w
, r
) in [(8, 16), (16, 16), (24, 16), (32, 16),
233 (32, 20), (48, 16), (64, 16), (96, 16), (128, 16),
234 (192, 16), (256, 16), (400, 16)]:
235 CUSTOM
['rc6-%d/%d' %
(w
, r
)] = RC6Cipher(w
, r
)
237 ###--------------------------------------------------------------------------
241 blksz
= E
.__class__
.blksz
245 m0
= mul_blk_gf(L
, C
.GF(2), p
)
246 m1
= mul_blk_gf(m0
, C
.GF(2), p
)
250 blksz
= E
.__class__
.blksz
251 m0
, m1
= omac_masks(E
)
252 print 'L = %s' %
hex(E
.encrypt(Z(blksz
)))
253 print 'm0 = %s' %
hex(m0
)
254 print 'm1 = %s' %
hex(m1
)
256 print 'v%d = %s' %
(t
, hex(E
.encrypt(C
.MP(t
).storeb(blksz
))))
257 print 'z%d = %s' %
(t
, hex(omac(E
, t
, '')))
260 blksz
= E
.__class__
.blksz
261 m0
, m1
= omac_masks(E
)
263 if t
is not None: m
= C
.MP(t
).storeb(blksz
) + m
264 v
, tl
= blocks(m
, blksz
)
265 for x
in v
: a
= E
.encrypt(a ^ x
)
268 a
= E
.encrypt(a ^ tl ^ m0
)
270 pad
= pad10star(tl
, blksz
)
271 a
= E
.encrypt(a ^ pad ^ m1
)
275 if VERBOSE
: dump_omac(E
)
276 return omac(E
, None, m
),
283 ###--------------------------------------------------------------------------
287 blksz
= E
.__class__
.blksz
290 while y
.size
< len(m
):
291 y
.put(E
.encrypt(c
.storeb(blksz
)))
293 return C
.ByteString(m
) ^ C
.ByteString(y
)[:len(m
)]
295 ###--------------------------------------------------------------------------
308 return C
.ByteString(y
)
313 u
, v
= C
.GF
.loadl(gcm_mangle(x
)), C
.GF
.loadl(gcm_mangle(y
))
315 return gcm_mangle(z
.storel(w
))
320 u
= C
.GF
.loadl(gcm_mangle(x
))
322 return gcm_mangle(z
.storel(w
))
324 def gcm_ctr(E
, m
, c0
):
327 c
, = unpack('>L', c0
[-4:])
328 while y
.size
< len(m
):
330 y
.put(E
.encrypt(pre
+ pack('>L', c
)))
331 return C
.ByteString(m
) ^ C
.ByteString(y
)[:len(m
)]
333 def g(what
, x
, m
, a0
= None):
335 if a0
is None: a
= Z(n
)
338 for b
in blocks0(m
, n
)[0]:
339 a
= gcm_mul(a ^ b
, x
)
340 if VERBOSE
: print '%s[%d] = %s -> %s' %
(what
, i
, hex(b
), hex(a
))
345 return C
.ByteString(x
+ Z(-len(x
)%w
))
347 def gcm_lens(w
, a
, b
):
350 return C
.ByteString(C
.MP(a
).storeb(n
) + C
.MP(b
).storeb(n
))
352 def ghash(whata
, whatb
, x
, a
, b
):
354 ha
= g(whata
, x
, gcm_pad(w
, a
))
355 hb
= g(whatb
, x
, gcm_pad(w
, b
))
357 hc
= gcm_mul(ha
, gcm_pow(x
, (len(b
) + w
- 1)/w
)) ^ hb
358 if VERBOSE
: print '%s || %s -> %s' %
(whata
, whatb
, hex(hc
))
361 return g(whatb
, x
, gcm_lens(w
, 8*len(a
), 8*len(b
)), hc
)
363 def gcmenc(E
, n
, h
, m
, tsz
= None):
364 w
= E
.__class__
.blksz
366 if VERBOSE
: print 'x = %s' %
hex(x
)
367 if len(n
) + 4 == w
: c0
= C
.ByteString(n
+ pack('>L', 1))
368 else: c0
= ghash('?', 'n', x
, EMPTY
, n
)
369 if VERBOSE
: print 'c0 = %s' %
hex(c0
)
370 y
= gcm_ctr(E
, m
, c0
)
371 t
= ghash('h', 'y', x
, h
, y
) ^ E
.encrypt(c0
)
374 def gcmdec(E
, n
, h
, y
, t
):
375 w
= E
.__class__
.blksz
377 if VERBOSE
: print 'x = %s' %
hex(x
)
378 if len(n
) + 4 == w
: c0
= C
.ByteString(n
+ pack('>L', 1))
379 else: c0
= ghash('?', 'n', x
, EMPTY
, n
)
380 if VERBOSE
: print 'c0 = %s' %
hex(c0
)
381 m
= gcm_ctr(E
, y
, c0
)
382 tt
= ghash('h', 'y', x
, h
, y
) ^ E
.encrypt(c0
)
383 if t
== tt
: return m
,
387 return [(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1),
388 (bc
.blksz
, 3*bc
.blksz
, 3*bc
.blksz
),
389 (bc
.blksz
- 4, bc
.blksz
+ 3, 3*bc
.blksz
+ 9),
390 (bc
.blksz
- 1, 3*bc
.blksz
- 5, 3*bc
.blksz
+ 5)]
392 def gcm_mul_tests(nbits
):
393 print 'gcm-mul%d {' % nbits
398 print ' %s\n %s\n %s;' %
(hex(x
), hex(y
), hex(z
))
401 ###--------------------------------------------------------------------------
404 def stbe(n
, w
): return C
.MP(n
).storeb(w
)
406 def ccm_fmthdr(blksz
, n
, hsz
, msz
, tsz
):
409 q
= blksz
- len(n
) - 1
414 b
.putu8(f
).put(n
).put(stbe(msz
, q
))
416 q
= blksz
- len(n
) - 1
419 f |
= (tsz
- 2)/2 << 3
421 b
.putu8(f
).put(n
).put(stbe(msz
, q
))
423 q
= blksz
- len(n
) - 2
428 b
.putu8(f0
).putu8(f1
).put(n
).put(stbe(msz
, q
))
430 if VERBOSE
: print 'hdr = %s' %
hex(b
)
433 def ccm_fmtctr(blksz
, n
, i
= 0):
435 if blksz
== 8 or blksz
== 16:
436 q
= blksz
- len(n
) - 1
437 b
.putu8(q
- 1).put(n
).put(stbe(i
, q
))
439 q
= blksz
- len(n
) - 2
440 b
.putu8(0).putu8(q
).put(n
).put(stbe(i
, q
))
442 if VERBOSE
: print 'ctr = %s' %
hex(b
)
445 def ccmaad(b
, h
, blksz
):
448 elif hsz
< 0xfffe: b
.putu16(hsz
)
449 elif hsz
<= 0xffffffff: b
.putu16(0xfffe).putu32(hsz
)
450 else: b
.putu16(0xffff).putu64(hsz
)
451 b
.put(h
); b
.zero((-b
.size
)%blksz
)
453 def ccmenc(E
, n
, h
, m
, tsz
= None):
454 blksz
= E
.__class__
.blksz
455 if tsz
is None: tsz
= blksz
457 b
.put(ccm_fmthdr(blksz
, n
, len(h
), len(m
), tsz
))
459 b
.put(m
); b
.zero((-b
.size
)%blksz
)
462 v
, _
= blocks0(b
, blksz
)
467 print 'b[%d] = %s' %
(i
, hex(x
))
468 print 'a[%d] = %s' %
(i
+ 1, hex(a
))
470 y
= ctr(E
, a
+ m
, ccm_fmtctr(blksz
, n
))
471 return C
.ByteString(y
[blksz
:]), C
.ByteString(y
[0:tsz
])
473 def ccmdec(E
, n
, h
, y
, t
):
474 blksz
= E
.__class__
.blksz
477 b
.put(ccm_fmthdr(blksz
, n
, len(h
), len(y
), tsz
))
479 mm
= ctr(E
, t
+ Z(blksz
- tsz
) + y
, ccm_fmtctr(blksz
, n
))
480 u
, m
= C
.ByteString(mm
[0:tsz
]), C
.ByteString(mm
[blksz
:])
481 b
.put(m
); b
.zero((-b
.size
)%blksz
)
484 v
, _
= blocks0(b
, blksz
)
489 print 'b[%d] = %s' %
(i
, hex(x
))
490 print 'a[%d] = %s' %
(i
+ 1, hex(a
))
492 if u
== a
[:tsz
]: return m
,
497 return [(bsz
- 5, 0, 0, 4), (bsz
- 5, 1, 0, 4), (bsz
- 5, 0, 1, 4),
498 (bsz
/2 + 1, 3*bc
.blksz
, 3*bc
.blksz
),
499 (bsz
/2 + 1, 3*bc
.blksz
- 5, 3*bc
.blksz
+ 5)]
501 ###--------------------------------------------------------------------------
504 def eaxenc(E
, n
, h
, m
, tsz
= None):
506 print 'k = %s' %
hex(k
)
507 print 'n = %s' %
hex(n
)
508 print 'h = %s' %
hex(h
)
509 print 'm = %s' %
hex(m
)
511 if tsz
is None: tsz
= E
.__class__
.blksz
517 print 'c0 = %s' %
hex(c0
)
518 print 'ht = %s' %
hex(ht
)
519 print 'yt = %s' %
hex(yt
)
520 return y
, C
.ByteString((c0 ^ ht ^ yt
)[:tsz
])
522 def eaxdec(E
, n
, h
, y
, t
):
524 print 'k = %s' %
hex(k
)
525 print 'n = %s' %
hex(n
)
526 print 'h = %s' %
hex(h
)
527 print 'y = %s' %
hex(y
)
528 print 't = %s' %
hex(t
)
535 print 'c0 = %s' %
hex(c0
)
536 print 'ht = %s' %
hex(ht
)
537 print 'yt = %s' %
hex(yt
)
538 if t
== (c0 ^ ht ^ yt
)[:len(t
)]: return m
,
542 return [(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1),
543 (bc
.blksz
, 3*bc
.blksz
, 3*bc
.blksz
),
544 (bc
.blksz
- 1, 3*bc
.blksz
- 5, 3*bc
.blksz
+ 5)]
546 ###--------------------------------------------------------------------------
550 blksz
= E
.__class__
.blksz
552 x
= C
.GF(2); xinv
= p
.modinv(x
)
555 Lxinv
= mul_blk_gf(L
, xinv
, p
)
557 for i
in xrange(1, len(Lgamma
)):
558 Lgamma
[i
] = mul_blk_gf(Lgamma
[i
- 1], x
, p
)
562 Lgamma
, Lxinv
= ocb_masks(E
)
563 print 'L x^-1 = %s' %
hex(Lxinv
)
564 for i
, lg
in enumerate(Lgamma
[:16]):
565 print 'L x^%d = %s' %
(i
, hex(lg
))
568 blksz
= E
.__class__
.blksz
569 Lgamma
, Lxinv
= ocb_masks(E
)
572 v
, tl
= blocks(m
, blksz
)
577 a ^
= E
.encrypt(x ^ o
)
579 print 'Z[%d]: %d -> %s' %
(i
, b
, hex(o
))
580 print 'A[%d]: %s' %
(i
, hex(a
))
581 if len(tl
) == blksz
: a ^
= tl ^ Lxinv
582 else: a ^
= pad10star(tl
, blksz
)
586 blksz
= E
.__class__
.blksz
588 L
= E
.encrypt(Z(blksz
))
589 o
= mul_blk_gf(L
, C
.GF(10), p
)
591 v
, tl
= blocks(m
, blksz
)
593 a ^
= E
.encrypt(x ^ o
)
594 o
= mul_blk_gf(o
, C
.GF(2), p
)
595 if len(tl
) == blksz
: a ^
= tl ^
mul_blk_gf(o
, C
.GF(3), p
)
596 else: a ^
= pad10star(tl
, blksz
) ^
mul_blk_gf(o
, C
.GF(5), p
)
600 Lgamma
, _
= ocb_masks(E
)
603 return Lstar
, Ldollar
, Lgamma
[2:]
606 Lstar
, Ldollar
, Lgamma
= ocb3_masks(E
)
607 print 'L_* = %s' %
hex(Lstar
)
608 print 'L_$ = %s' %
hex(Ldollar
)
609 for i
, lg
in enumerate(Lgamma
[:16]):
610 print 'L x^%d = %s' %
(i
, hex(lg
))
613 ## Note that `PMAC3' is /not/ a secure MAC. It depends on other parts of
614 ## OCB3 to prevent a rather easy linear-algebra attack.
615 blksz
= E
.__class__
.blksz
616 Lstar
, Ldollar
, Lgamma
= ocb3_masks(E
)
619 v
, tl
= blocks0(m
, blksz
)
624 a ^
= E
.encrypt(x ^ o
)
626 print 'Z[%d]: %d -> %s' %
(i
, b
, hex(o
))
627 print 'A[%d]: %s' %
(i
, hex(a
))
630 a ^
= E
.encrypt(pad10star(tl
, blksz
) ^ o
)
632 print 'Z[%d]: * -> %s' %
(i
, hex(o
))
633 print 'A[%d]: %s' %
(i
, hex(a
))
637 if VERBOSE
: dump_ocb(E
)
645 ###--------------------------------------------------------------------------
648 def ocb1enc(E
, n
, h
, m
, tsz
= None):
649 ## This is OCB1.PMAC1 from Rogaway's `Authenticated-Encryption with
651 blksz
= E
.__class__
.blksz
652 if VERBOSE
: dump_ocb(E
)
653 Lgamma
, Lxinv
= ocb_masks(E
)
654 if tsz
is None: tsz
= blksz
656 o
= E
.encrypt(n ^ Lgamma
[0])
657 if VERBOSE
: print 'R = %s' %
hex(o
)
660 v
, tl
= blocks(m
, blksz
)
667 print 'Z[%d]: %d -> %s' %
(i
, b
, hex(o
))
668 print 'A[%d]: %s' %
(i
, hex(a
))
669 y
.put(E
.encrypt(x ^ o
) ^ o
)
675 print 'Z[%d]: %d -> %s' %
(i
, b
, hex(o
))
676 print 'LEN = %s' %
hex(C
.MP(8*n
).storeb(blksz
))
677 yfinal
= E
.encrypt(C
.MP(8*n
).storeb(blksz
) ^ Lxinv ^ o
)
678 cfinal
= tl ^ yfinal
[:n
]
679 a ^
= o ^
(tl
+ yfinal
[n
:])
682 if h
: t ^
= pmac1(E
, h
)
683 return C
.ByteString(y
), C
.ByteString(t
[:tsz
])
685 def ocb1dec(E
, n
, h
, y
, t
):
686 ## This is OCB1.PMAC1 from Rogaway's `Authenticated-Encryption with
688 blksz
= E
.__class__
.blksz
689 if VERBOSE
: dump_ocb(E
)
690 Lgamma
, Lxinv
= ocb_masks(E
)
692 o
= E
.encrypt(n ^ Lgamma
[0])
693 if VERBOSE
: print 'R = %s' %
hex(o
)
696 v
, tl
= blocks(y
, blksz
)
702 print 'Z[%d]: %d -> %s' %
(i
, b
, hex(o
))
703 print 'A[%d]: %s' %
(i
, hex(a
))
704 u
= E
.decrypt(x ^ o
) ^ o
712 print 'Z[%d]: %d -> %s' %
(i
, b
, hex(o
))
713 print 'LEN = %s' %
hex(C
.MP(8*n
).storeb(blksz
))
714 yfinal
= E
.encrypt(C
.MP(8*n
).storeb(blksz
) ^ Lxinv ^ o
)
715 mfinal
= tl ^ yfinal
[:n
]
716 a ^
= o ^
(mfinal
+ yfinal
[n
:])
719 if h
: u ^
= pmac1(E
, h
)
720 if t
== u
[:len(t
)]: return C
.ByteString(m
),
723 def ocb2enc(E
, n
, h
, m
, tsz
= None):
724 ## For OCB2, it's important for security that n = log_x (x + 1) is large in
725 ## the field representations of GF(2^w) used -- in fact, we need more, that
726 ## i n (mod 2^w - 1) is large for i in {4, -3, -2, -1, 1, 2, 3, 4}. The
727 ## original paper lists the values for 64 and 128, but we support other
728 ## block sizes, so here's the result of the (rather large, in some cases)
731 ## Block size log_x (x + 1)
733 ## 64 9686038906114705801
734 ## 96 63214690573408919568138788065
735 ## 128 338793687469689340204974836150077311399
736 ## 192 161110085006042185925119981866940491651092686475226538785
737 ## 256 22928580326165511958494515843249267194111962539778797914076675796261938307298
739 blksz
= E
.__class__
.blksz
740 if tsz
is None: tsz
= blksz
743 o
= mul_blk_gf(L
, C
.GF(2), p
)
745 v
, tl
= blocks(m
, blksz
)
749 y
.put(E
.encrypt(x ^ o
) ^ o
)
750 o
= mul_blk_gf(o
, C
.GF(2), p
)
752 yfinal
= E
.encrypt(C
.MP(8*n
).storeb(blksz
) ^ o
)
753 cfinal
= tl ^ yfinal
[:n
]
754 a ^
= (tl
+ yfinal
[n
:]) ^
mul_blk_gf(o
, C
.GF(3), p
)
757 if h
: t ^
= pmac2(E
, h
)
758 return C
.ByteString(y
), C
.ByteString(t
[:tsz
])
760 def ocb2dec(E
, n
, h
, y
, t
):
761 blksz
= E
.__class__
.blksz
764 o
= mul_blk_gf(L
, C
.GF(2), p
)
766 v
, tl
= blocks(y
, blksz
)
769 u
= E
.encrypt(x ^ o
) ^ o
772 o
= mul_blk_gf(o
, C
.GF(2), p
)
774 yfinal
= E
.encrypt(C
.MP(8*n
).storeb(blksz
) ^ o
)
775 mfinal
= tl ^ yfinal
[:n
]
776 a ^
= (mfinal
+ yfinal
[n
:]) ^
mul_blk_gf(o
, C
.GF(3), p
)
779 if h
: u ^
= pmac2(E
, h
)
780 if t
== u
[:len(t
)]: return C
.ByteString(m
),
783 OCB3_STRETCH
= { 4: ( 4, 17),
795 def ocb3nonce(E
, n
, tsz
):
797 ## Figure out how much we need to glue onto the nonce. This ends up being
798 ## [t mod w]_v || 0^p || 1 || N, where w is the block size in bits, t is
799 ## the tag length in bits, v = floor(log_2(w - 1)) + 1, and p = w - l(N) -
800 ## v - 1. But this is an annoying way to think about it because of the
801 ## byte misalignment. Instead, think of it as a byte-aligned prefix
802 ## encoding the tag and an `is the nonce full-length' flag, followed by
803 ## optional padding, and then the nonce:
805 ## F || N if l(N) = w - f
806 ## F || 0^p || 1 || N otherwise
808 ## where F is [t mod w]_v || 0^{f-v-1} || b; f = floor(log_2(w - 1)) + 2;
809 ## b is 1 if l(N) = w - f, or 0 otherwise; and p = w - f - l(N) - 1.
810 blksz
= E
.__class__
.blksz
811 tszbits
= min(C
.MP(8*blksz
- 1).nbits
, 8)
813 f
= 8*(tsz
%blksz
) << + 8*fwd
- tszbits
815 ## Form the augmented nonce.
817 nsz
, nwd
= len(n
), blksz
- fwd
818 if nsz
== nwd
: f |
= 1
819 nb
.put(C
.MP(f
).storeb(fwd
))
820 if nsz
< nwd
: nb
.zero(nwd
- nsz
- 1).putu8(1)
822 nn
= C
.ByteString(nb
)
823 if VERBOSE
: print 'aug-nonce = %s' %
hex(nn
)
825 ## Calculate the initial offset.
826 split
, shift
= OCB3_STRETCH
[blksz
]
827 t2pw
= C
.MP(0).setbit(8*blksz
) - 1
828 lomask
= (C
.MP(0).setbit(split
) - 1)
830 top
, bottom
= nn
&himask
.storeb2c(blksz
), C
.MP
.loadb(nn
)&lomask
831 ktop
= C
.MP
.loadb(E
.encrypt(top
))
832 stretch
= (ktop
<< 8*blksz
) |
(ktop ^
(ktop
<< shift
)&t2pw
)
833 o
= (stretch
>> 8*blksz
- bottom
).storeb(blksz
)
835 print 'stretch = %s' %
hex(stretch
.storeb(2*blksz
))
836 print 'Z[0] = %s' %
hex(o
)
840 def ocb3enc(E
, n
, h
, m
, tsz
= None):
841 blksz
= E
.__class__
.blksz
842 if tsz
is None: tsz
= blksz
843 Lstar
, Ldollar
, Lgamma
= ocb3_masks(E
)
844 if VERBOSE
: dump_ocb3(E
)
847 o
= ocb3nonce(E
, n
, tsz
)
848 a
= C
.ByteString
.zero(blksz
)
850 ## Split the message into blocks.
853 v
, tl
= blocks0(m
, blksz
)
860 print 'Z[%d]: %d -> %s' %
(i
, b
, hex(o
))
861 print 'A[%d]: %s' %
(i
, hex(a
))
862 y
.put(E
.encrypt(x ^ o
) ^ o
)
867 a ^
= pad10star(tl
, blksz
)
869 print 'Z[%d]: * -> %s' %
(i
, hex(o
))
870 print 'A[%d]: %s' %
(i
, hex(a
))
873 t
= E
.encrypt(a ^ o
) ^
pmac3(E
, h
)
874 return C
.ByteString(y
), C
.ByteString(t
[:tsz
])
876 def ocb3dec(E
, n
, h
, y
, t
):
877 blksz
= E
.__class__
.blksz
879 Lstar
, Ldollar
, Lgamma
= ocb3_masks(E
)
880 if VERBOSE
: dump_ocb3(E
)
883 o
= ocb3nonce(E
, n
, tsz
)
884 a
= C
.ByteString
.zero(blksz
)
886 ## Split the message into blocks.
889 v
, tl
= blocks0(y
, blksz
)
895 print 'Z[%d]: %d -> %s' %
(i
, b
, hex(o
))
896 print 'A[%d]: %s' %
(i
, hex(a
))
897 u
= E
.encrypt(x ^ o
) ^ o
905 print 'Z[%d]: * -> %s' %
(i
, hex(o
))
906 print 'A[%d]: %s' %
(i
, hex(a
))
909 a ^
= pad10star(u
, blksz
)
911 u
= E
.encrypt(a ^ o
) ^
pmac3(E
, h
)
912 if t
== u
[:tsz
]: return C
.ByteString(m
),
917 return [(w
, 0, 0), (w
, 1, 0), (w
, 0, 1),
921 (w
, 3*w
- 5, 3*w
+ 5)]
925 return [(w
- 2, 0, 0), (w
- 2, 1, 0), (w
- 2, 0, 1),
929 (w
- 2, 3*w
- 5, 3*w
+ 5)]
931 def ocb3_mct(bc
, ksz
, tsz
):
932 k
= C
.ByteString(C
.WriteBuffer().zero(ksz
- 4).putu32(8*tsz
))
936 cbuf
= C
.WriteBuffer()
937 for i
in xrange(128):
938 s
= C
.ByteString
.zero(i
)
939 y
, t
= ocb3enc(E
, n
.storeb(nw
), s
, s
, tsz
); n
+= 1; cbuf
.put(y
).put(t
)
940 y
, t
= ocb3enc(E
, n
.storeb(nw
), EMPTY
, s
, tsz
); n
+= 1; cbuf
.put(y
).put(t
)
941 y
, t
= ocb3enc(E
, n
.storeb(nw
), s
, EMPTY
, tsz
); n
+= 1; cbuf
.put(y
).put(t
)
942 _
, t
= ocb3enc(E
, n
.storeb(nw
), C
.ByteString(cbuf
), EMPTY
, tsz
)
946 k
= C
.bytes('000102030405060708090a0b0c0d0e0f')
948 tsz
= min(E
.blksz
, 32)
950 cbuf
= C
.WriteBuffer()
951 for i
in xrange(128):
952 sbuf
= C
.WriteBuffer()
953 for j
in xrange(i
): sbuf
.putu8(j
)
954 s
= C
.ByteString(sbuf
)
955 y
, t
= ocb3enc(E
, n
.storeb(2), s
, s
, tsz
); n
+= 1; cbuf
.put(y
).put(t
)
956 y
, t
= ocb3enc(E
, n
.storeb(2), EMPTY
, s
, tsz
); n
+= 1; cbuf
.put(y
).put(t
)
957 y
, t
= ocb3enc(E
, n
.storeb(2), s
, EMPTY
, tsz
); n
+= 1; cbuf
.put(y
).put(t
)
958 _
, t
= ocb3enc(E
, n
.storeb(2), C
.ByteString(cbuf
), EMPTY
, tsz
)
961 ###--------------------------------------------------------------------------
964 class struct (object):
965 def __init__(me
, **kw
):
966 me
.__dict__
.update(kw
)
968 binarg
= struct(mk
= R
.block
, parse
= C
.bytes
, show
= safehex
)
969 intarg
= struct(mk
= lambda x
: x
, parse
= int, show
= None)
971 MODEMAP
= { 'eax-enc': (eaxgen
, 3*[binarg
] + [intarg
], eaxenc
),
972 'eax-dec': (dummygen
, 4*[binarg
], eaxdec
),
973 'ccm-enc': (ccmgen
, 3*[binarg
] + [intarg
], ccmenc
),
974 'ccm-dec': (dummygen
, 4*[binarg
], ccmdec
),
975 'cmac': (cmacgen
, [binarg
], cmac
),
976 'gcm-enc': (gcmgen
, 3*[binarg
] + [intarg
], gcmenc
),
977 'gcm-dec': (dummygen
, 4*[binarg
], gcmdec
),
978 'ocb1-enc': (ocbgen
, 3*[binarg
] + [intarg
], ocb1enc
),
979 'ocb1-dec': (dummygen
, 4*[binarg
], ocb1dec
),
980 'ocb2-enc': (ocbgen
, 3*[binarg
] + [intarg
], ocb2enc
),
981 'ocb2-dec': (dummygen
, 4*[binarg
], ocb2dec
),
982 'ocb3-enc': (ocb3gen
, 3*[binarg
] + [intarg
], ocb3enc
),
983 'ocb3-dec': (dummygen
, 4*[binarg
], ocb3dec
),
984 'pmac1': (pmacgen
, [binarg
], pmac1_pub
) }
987 if len(argv
) == 3 and mode
== 'gcm-mul':
993 for d
in CUSTOM
, C
.gcprps
:
995 except KeyError: pass
997 if bc
is None: raise KeyError, argv
[2]
998 if len(argv
) == 5 and mode
== 'ocb3-mct':
1000 ksz
, tsz
= int(argv
[3]), int(argv
[4])
1001 ocb3_mct(bc
, ksz
, tsz
)
1003 if len(argv
) == 3 and mode
== 'ocb3-mct2':
1009 gen
, argty
, func
= MODEMAP
[mode
]
1010 if mode
.endswith('-enc'): mode
= mode
[:-4]
1011 print '%s-%s {' %
(bc
.name
, mode
)
1012 for ksz
in keylens(bc
.keysz
):
1013 for argvals
in gen(bc
):
1015 args
= [t
.mk(a
) for t
, a
in izip(argty
, argvals
)]
1016 rets
= func(bc(k
), *args
)
1017 print ' %s' % safehex
(k
)
1018 for t
, a
in izip(argty
, args
):
1019 if t
.show
: print ' %s' % t
.show(a
)
1020 for r
, lastp
in with_lastp(rets
):
1021 print ' %s%s' %
(safehex(r
), lastp
and ';' or '')
1025 k
= C
.bytes(argv
[3])
1026 gen
, argty
, func
= MODEMAP
[mode
]
1027 args
= [t
.parse(a
) for t
, a
in izip(argty
, argv
[4:])]
1028 rets
= func(bc(k
), *args
)
1030 if r
is None: print "X"
1033 ###----- That's all, folks --------------------------------------------------