From: Luke Kenneth Casson Leighton Date: Tue, 8 Mar 2022 05:14:09 +0000 (+0000) Subject: cleanup, comments, and attribution of sources for various gf2 functions X-Git-Tag: opf_rfc_ls005_v1~3120 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6f0ad90be3c0c324f364fe21b613eb6c371e0a4b;p=libreriscv.git cleanup, comments, and attribution of sources for various gf2 functions --- diff --git a/openpower/sv/gf2.py b/openpower/sv/gf2.py index 420034d46..ee21cd3a9 100644 --- a/openpower/sv/gf2.py +++ b/openpower/sv/gf2.py @@ -1,5 +1,14 @@ +# a mish-mash of various GF(2^m) functions from different sources +# on the internet which help demonstrate arithmetic in GF(2^m) +# these are intended to be implemented in hardware, so the basic +# primitives need to be *real* basic: XOR, shift, AND, OR, etc. +# +# development discussion and links at: +# https://bugs.libre-soc.org/show_bug.cgi?id=782 + from functools import reduce +# https://stackoverflow.com/questions/45442396/ def gf_degree(a) : res = 0 a >>= 1 @@ -8,9 +17,17 @@ def gf_degree(a) : res += 1; return res -# constants used in the multGF2 function + +# useful constants used throughout this module degree = mask1 = mask2 = polyred = None +def getGF2(): + """reconstruct the polynomial coefficients of g(x) + """ + return polyred | mask1 + + +# original at https://jhafranco.com/tag/binary-finite-field/ def setGF2(irPoly): """Define parameters of binary finite field GF(2^m)/g(x) - irPoly: coefficients of irreducible polynomial g(x) @@ -29,12 +46,7 @@ def setGF2(irPoly): polyred = reduce(lambda x, y: (x << 1) + y, i2P(irPoly)[1:]) -def getGF2(): - """reconstruct the polynomial coefficients of g(x) - """ - return polyred | mask1 - - +# original at https://jhafranco.com/tag/binary-finite-field/ def multGF2(p1, p2): """Multiply two polynomials in GF(2^m)/g(x)""" p = 0 @@ -48,6 +60,8 @@ def multGF2(p1, p2): return p & mask2 +# https://github.com/jpahullo/python-multiprocessing/ +# py_ecc/ffield.py def divmodGF2(f, v): fDegree, vDegree = gf_degree(f), gf_degree(v) res, rem = 0, f @@ -62,6 +76,7 @@ def divmodGF2(f, v): return (res, rem) +# https://en.m.wikibooks.org/wiki/Algorithm_Implementation/Mathematics/Extended_Euclidean_algorithm def xgcd(a, b): """return (g, x, y) such that a*x + b*y = g = gcd(a, b)""" x0, x1, y0, y1 = 0, 1, 1, 0 @@ -114,7 +129,7 @@ if __name__ == "__main__": print("%02x" % x) # Define binary field GF(2^8)/x^8 + x^4 + x^3 + x + 1 - # (used in the Advanced Encryption Standard-AES) + # (used in Rijndael) # note that polyred has the MSB stripped! setGF2(0b100011011) # degree 8 @@ -130,14 +145,16 @@ if __name__ == "__main__": # reconstruct x by multiplying divided result by y and adding the remainder x1 = multGF2(res, y) - print("%02x == %02x" % (z, x1 ^ rem)) - + print("%02x == %02x" % (z, x1 ^ rem)) # XOR is "add" in GF2 + # demo output of xgcd print(xgcd(x, y)) #for i in range(1, 256): # print (i, gf_invert(i)) + # show how inversion-and-multiply works. answer here should be "x": + # z = x * y, therefore z * (1/y) should equal "x" y1 = gf_invert(y) z1 = multGF2(z, y1) print(hex(polyred), hex(y1), hex(x), "==", hex(z1))