1From 8228c484a1533ff904b276c342adcb6310abe272 Mon Sep 17 00:00:00 2001 2From: Taahir Ahmed <ahmed.taahir@gmail.com> 3Date: Wed, 30 Mar 2016 11:23:54 -0300 4Subject: [PATCH] crda: support python 3 in utils/key2pub.py 5 6utils/key2pub.py can now be run under either python 2.7 or python 3.x. 7This required some minor syntactical changes as well as switching from 8M2Crypto to pycryptodomex, since M2Crypto doesn't support python 3.x. 9 10In addition, some errors in the generated source file keys-ssl.h are 11fixed: 12 13 * The correct OpenSSL header for BN_ULONG is included. 14 15 * The generated constants are given the 'ull' suffix to prevent 16 warnings about constants that are too large. 17 18[Gustavo: don't call /utils/key2pub.py since that doesn't compute] 19 20Use pycryptodomex insdead of pycrypto 21 22From [1]: 23"PyCryptodome is a fork of PyCrypto, which is not maintained any more 24(the last release dates back to 2013 [2]). It exposes almost the same 25API, but there are a few incompatibilities [3]." 26 27[1] https://github.com/OP-TEE/optee_os/commit/90ad2450436fdd9fc0d28a3f92f3fbcfd89a38f0 28[2] https://pypi.org/project/pycrypto/#history 29[3] https://pycryptodome.readthedocs.io/en/latest/src/vs_pycrypto.html 30 31Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar> 32[Rebased against crda-4.14] 33Signed-off-by: Peter Seiderer <ps.report@gmx.net> 34[Romain: Use pycryptodomex] 35Signed-off-by: Romain Naour <romain.naour@gmail.com> 36--- 37 Makefile | 2 +- 38 utils/key2pub.py | 146 ++++++++++++++++++++++++----------------------- 39 2 files changed, 75 insertions(+), 73 deletions(-) 40 41diff --git a/Makefile b/Makefile 42index a3ead30..8da38d0 100644 43--- a/Makefile 44+++ b/Makefile 45@@ -112,7 +112,7 @@ $(REG_BIN): 46 keys-%.c: utils/key2pub.py $(wildcard $(PUBKEY_DIR)/*.pem) 47 $(NQ) ' GEN ' $@ 48 $(NQ) ' Trusted pubkeys:' $(wildcard $(PUBKEY_DIR)/*.pem) 49- $(Q)./utils/key2pub.py --$* $(wildcard $(PUBKEY_DIR)/*.pem) $@ 50+ $(Q) python utils/key2pub.py --$* $(wildcard $(PUBKEY_DIR)/*.pem) $@ 51 52 $(LIBREG): regdb.h reglib.h reglib.c 53 $(NQ) ' CC ' $@ 54diff --git a/utils/key2pub.py b/utils/key2pub.py 55index 9bb04cd..8a0ba2a 100755 56--- a/utils/key2pub.py 57+++ b/utils/key2pub.py 58@@ -1,126 +1,128 @@ 59 #!/usr/bin/env python 60 61+import io 62 import sys 63 try: 64- from M2Crypto import RSA 65-except ImportError, e: 66- sys.stderr.write('ERROR: Failed to import the "M2Crypto" module: %s\n' % e.message) 67- sys.stderr.write('Please install the "M2Crypto" Python module.\n') 68- sys.stderr.write('On Debian GNU/Linux the package is called "python-m2crypto".\n') 69- sys.exit(1) 70+ from Cryptodome.PublicKey import RSA 71+except ImportError as e: 72+ sys.stderr.write('ERROR: Failed to import the "Cryptodome.PublicKey" module: %s\n' % e.message) 73+ sys.stderr.write('Please install the "Cryptodome.PublicKey" Python module.\n') 74+ sys.stderr.write('On Debian GNU/Linux the package is called "python-cryptodomex".\n') 75+ sys.exit(1) 76+ 77+def bitwise_collect(value, radix_bits): 78+ words = [] 79+ radix_mask = (1 << radix_bits) - 1 80+ while value != 0: 81+ words.append(value & radix_mask) 82+ value >>= radix_bits 83+ return words 84 85 def print_ssl_64(output, name, val): 86- while val[0] == '\0': 87- val = val[1:] 88- while len(val) % 8: 89- val = '\0' + val 90- vnew = [] 91- while len(val): 92- vnew.append((val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7])) 93- val = val[8:] 94- vnew.reverse() 95- output.write('static BN_ULONG %s[%d] = {\n' % (name, len(vnew))) 96+ # OpenSSL expects 64-bit words given least-significant-word first. 97+ vwords = bitwise_collect(val, 64) 98+ 99+ output.write(u'static BN_ULONG {}[] = {{\n'.format(name)) 100 idx = 0 101- for v1, v2, v3, v4, v5, v6, v7, v8 in vnew: 102+ for vword in vwords: 103 if not idx: 104- output.write('\t') 105- output.write('0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x, ' % (ord(v1), ord(v2), ord(v3), ord(v4), ord(v5), ord(v6), ord(v7), ord(v8))) 106+ output.write(u'\t') 107+ output.write(u'0x{:016x}ULL, '.format(vword)) 108 idx += 1 109 if idx == 2: 110 idx = 0 111- output.write('\n') 112+ output.write(u'\n') 113 if idx: 114- output.write('\n') 115- output.write('};\n\n') 116+ output.write(u'\n') 117+ output.write(u'};\n\n') 118 119 def print_ssl_32(output, name, val): 120- while val[0] == '\0': 121- val = val[1:] 122- while len(val) % 4: 123- val = '\0' + val 124- vnew = [] 125- while len(val): 126- vnew.append((val[0], val[1], val[2], val[3], )) 127- val = val[4:] 128- vnew.reverse() 129- output.write('static BN_ULONG %s[%d] = {\n' % (name, len(vnew))) 130+ # OpenSSL expects 32-bit words given least-significant-word first. 131+ vwords = bitwise_collect(val, 32) 132+ 133+ output.write(u'static BN_ULONG {}[] = {{\n'.format(name)) 134 idx = 0 135- for v1, v2, v3, v4 in vnew: 136+ for vword in vwords: 137 if not idx: 138- output.write('\t') 139- output.write('0x%.2x%.2x%.2x%.2x, ' % (ord(v1), ord(v2), ord(v3), ord(v4))) 140+ output.write(u'\t') 141+ output.write(u'0x{:08x}, '.format(vword)) 142 idx += 1 143 if idx == 4: 144 idx = 0 145- output.write('\n') 146+ output.write(u'\n') 147 if idx: 148- output.write('\n') 149- output.write('};\n\n') 150+ output.write(u'\n') 151+ output.write(u'};\n\n') 152 153 def print_ssl(output, name, val): 154+ 155+ output.write(u'#include <stdint.h>\n') 156+ output.write(u'#include <openssl/bn.h>\n') 157+ 158 import struct 159- output.write('#include <stdint.h>\n') 160 if len(struct.pack('@L', 0)) == 8: 161 return print_ssl_64(output, name, val) 162 else: 163 return print_ssl_32(output, name, val) 164 165 def print_ssl_keys(output, n): 166- output.write(r''' 167+ output.write(u''' 168 struct pubkey { 169 struct bignum_st e, n; 170 }; 171 172-#define KEY(data) { \ 173- .d = data, \ 174- .top = sizeof(data)/sizeof(data[0]), \ 175+#define KEY(data) { \\ 176+ .d = data, \\ 177+ .top = sizeof(data)/sizeof(data[0]), \\ 178 } 179 180-#define KEYS(e,n) { KEY(e), KEY(n), } 181+#define KEYS(e,n) { KEY(e), KEY(n), } 182 183 static struct pubkey keys[] = { 184 ''') 185 for n in xrange(n + 1): 186- output.write(' KEYS(e_%d, n_%d),\n' % (n, n)) 187- output.write('};\n') 188+ output.write(u' KEYS(e_{0}, n_{0}),\n'.format(n)) 189+ output.write(u'};\n') 190 pass 191 192 def print_gcrypt(output, name, val): 193- output.write('#include <stdint.h>\n') 194- while val[0] == '\0': 195- val = val[1:] 196- output.write('static const uint8_t %s[%d] = {\n' % (name, len(val))) 197+ # gcrypt expects 8-bit words most-significant-word first 198+ vwords = bitwise_collect(val, 8) 199+ vwords.reverse() 200+ 201+ output.write(u'#include <stdint.h>\n') 202+ output.write(u'static const uint8_t %s[%d] = {\n' % (name, len(vwords))) 203 idx = 0 204- for v in val: 205+ for vword in vwords: 206 if not idx: 207- output.write('\t') 208- output.write('0x%.2x, ' % ord(v)) 209+ output.write(u'\t') 210+ output.write(u'0x{:02x}, '.format(vword)) 211 idx += 1 212 if idx == 8: 213 idx = 0 214- output.write('\n') 215+ output.write(u'\n') 216 if idx: 217- output.write('\n') 218- output.write('};\n\n') 219+ output.write(u'\n') 220+ output.write(u'};\n\n') 221 222 def print_gcrypt_keys(output, n): 223- output.write(r''' 224+ output.write(u''' 225 struct key_params { 226 const uint8_t *e, *n; 227 uint32_t len_e, len_n; 228 }; 229 230-#define KEYS(_e, _n) { \ 231- .e = _e, .len_e = sizeof(_e), \ 232- .n = _n, .len_n = sizeof(_n), \ 233+#define KEYS(_e, _n) { \\ 234+ .e = _e, .len_e = sizeof(_e), \\ 235+ .n = _n, .len_n = sizeof(_n), \\ 236 } 237 238 static const struct key_params __attribute__ ((unused)) keys[] = { 239 ''') 240- for n in xrange(n + 1): 241- output.write(' KEYS(e_%d, n_%d),\n' % (n, n)) 242- output.write('};\n') 243- 244+ for n in range(n + 1): 245+ output.write(u' KEYS(e_{0}, n_{0}),\n'.format(n)) 246+ output.write(u'};\n') 247+ 248 249 modes = { 250 '--ssl': (print_ssl, print_ssl_keys), 251@@ -135,21 +137,21 @@ except IndexError: 252 mode = None 253 254 if not mode in modes: 255- print 'Usage: %s [%s] input-file... output-file' % (sys.argv[0], '|'.join(modes.keys())) 256+ print('Usage: {} [{}] input-file... output-file'.format(sys.argv[0], '|'.join(modes.keys()))) 257 sys.exit(2) 258 259-output = open(outfile, 'w') 260+output = io.open(outfile, 'w') 261 262 # load key 263 idx = 0 264 for f in files: 265- try: 266- key = RSA.load_pub_key(f) 267- except RSA.RSAError: 268- key = RSA.load_key(f) 269 270- modes[mode][0](output, 'e_%d' % idx, key.e[4:]) 271- modes[mode][0](output, 'n_%d' % idx, key.n[4:]) 272+ key_contents = io.open(f, 'rb').read() 273+ key = RSA.importKey(key_contents) 274+ 275+ modes[mode][0](output, 'e_{}'.format(idx), key.e) 276+ modes[mode][0](output, 'n_{}'.format(idx), key.n) 277+ 278 idx += 1 279 280 modes[mode][1](output, idx - 1) 281-- 2822.25.3 283 284