blob: f2b9cca2d6787b876669f64ce90bae01a28126bd [file] [log] [blame]
From 8228c484a1533ff904b276c342adcb6310abe272 Mon Sep 17 00:00:00 2001
From: Taahir Ahmed <ahmed.taahir@gmail.com>
Date: Wed, 30 Mar 2016 11:23:54 -0300
Subject: [PATCH] crda: support python 3 in utils/key2pub.py
utils/key2pub.py can now be run under either python 2.7 or python 3.x.
This required some minor syntactical changes as well as switching from
M2Crypto to pycryptodomex, since M2Crypto doesn't support python 3.x.
In addition, some errors in the generated source file keys-ssl.h are
fixed:
* The correct OpenSSL header for BN_ULONG is included.
* The generated constants are given the 'ull' suffix to prevent
warnings about constants that are too large.
[Gustavo: don't call /utils/key2pub.py since that doesn't compute]
Use pycryptodomex insdead of pycrypto
From [1]:
"PyCryptodome is a fork of PyCrypto, which is not maintained any more
(the last release dates back to 2013 [2]). It exposes almost the same
API, but there are a few incompatibilities [3]."
[1] https://github.com/OP-TEE/optee_os/commit/90ad2450436fdd9fc0d28a3f92f3fbcfd89a38f0
[2] https://pypi.org/project/pycrypto/#history
[3] https://pycryptodome.readthedocs.io/en/latest/src/vs_pycrypto.html
Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar>
[Rebased against crda-4.14]
Signed-off-by: Peter Seiderer <ps.report@gmx.net>
[Romain: Use pycryptodomex]
Signed-off-by: Romain Naour <romain.naour@gmail.com>
---
Makefile | 2 +-
utils/key2pub.py | 146 ++++++++++++++++++++++++-----------------------
2 files changed, 75 insertions(+), 73 deletions(-)
diff --git a/Makefile b/Makefile
index a3ead30..8da38d0 100644
--- a/Makefile
+++ b/Makefile
@@ -112,7 +112,7 @@ $(REG_BIN):
keys-%.c: utils/key2pub.py $(wildcard $(PUBKEY_DIR)/*.pem)
$(NQ) ' GEN ' $@
$(NQ) ' Trusted pubkeys:' $(wildcard $(PUBKEY_DIR)/*.pem)
- $(Q)./utils/key2pub.py --$* $(wildcard $(PUBKEY_DIR)/*.pem) $@
+ $(Q) python utils/key2pub.py --$* $(wildcard $(PUBKEY_DIR)/*.pem) $@
$(LIBREG): regdb.h reglib.h reglib.c
$(NQ) ' CC ' $@
diff --git a/utils/key2pub.py b/utils/key2pub.py
index 9bb04cd..8a0ba2a 100755
--- a/utils/key2pub.py
+++ b/utils/key2pub.py
@@ -1,126 +1,128 @@
#!/usr/bin/env python
+import io
import sys
try:
- from M2Crypto import RSA
-except ImportError, e:
- sys.stderr.write('ERROR: Failed to import the "M2Crypto" module: %s\n' % e.message)
- sys.stderr.write('Please install the "M2Crypto" Python module.\n')
- sys.stderr.write('On Debian GNU/Linux the package is called "python-m2crypto".\n')
- sys.exit(1)
+ from Cryptodome.PublicKey import RSA
+except ImportError as e:
+ sys.stderr.write('ERROR: Failed to import the "Cryptodome.PublicKey" module: %s\n' % e.message)
+ sys.stderr.write('Please install the "Cryptodome.PublicKey" Python module.\n')
+ sys.stderr.write('On Debian GNU/Linux the package is called "python-cryptodomex".\n')
+ sys.exit(1)
+
+def bitwise_collect(value, radix_bits):
+ words = []
+ radix_mask = (1 << radix_bits) - 1
+ while value != 0:
+ words.append(value & radix_mask)
+ value >>= radix_bits
+ return words
def print_ssl_64(output, name, val):
- while val[0] == '\0':
- val = val[1:]
- while len(val) % 8:
- val = '\0' + val
- vnew = []
- while len(val):
- vnew.append((val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]))
- val = val[8:]
- vnew.reverse()
- output.write('static BN_ULONG %s[%d] = {\n' % (name, len(vnew)))
+ # OpenSSL expects 64-bit words given least-significant-word first.
+ vwords = bitwise_collect(val, 64)
+
+ output.write(u'static BN_ULONG {}[] = {{\n'.format(name))
idx = 0
- for v1, v2, v3, v4, v5, v6, v7, v8 in vnew:
+ for vword in vwords:
if not idx:
- output.write('\t')
- 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)))
+ output.write(u'\t')
+ output.write(u'0x{:016x}ULL, '.format(vword))
idx += 1
if idx == 2:
idx = 0
- output.write('\n')
+ output.write(u'\n')
if idx:
- output.write('\n')
- output.write('};\n\n')
+ output.write(u'\n')
+ output.write(u'};\n\n')
def print_ssl_32(output, name, val):
- while val[0] == '\0':
- val = val[1:]
- while len(val) % 4:
- val = '\0' + val
- vnew = []
- while len(val):
- vnew.append((val[0], val[1], val[2], val[3], ))
- val = val[4:]
- vnew.reverse()
- output.write('static BN_ULONG %s[%d] = {\n' % (name, len(vnew)))
+ # OpenSSL expects 32-bit words given least-significant-word first.
+ vwords = bitwise_collect(val, 32)
+
+ output.write(u'static BN_ULONG {}[] = {{\n'.format(name))
idx = 0
- for v1, v2, v3, v4 in vnew:
+ for vword in vwords:
if not idx:
- output.write('\t')
- output.write('0x%.2x%.2x%.2x%.2x, ' % (ord(v1), ord(v2), ord(v3), ord(v4)))
+ output.write(u'\t')
+ output.write(u'0x{:08x}, '.format(vword))
idx += 1
if idx == 4:
idx = 0
- output.write('\n')
+ output.write(u'\n')
if idx:
- output.write('\n')
- output.write('};\n\n')
+ output.write(u'\n')
+ output.write(u'};\n\n')
def print_ssl(output, name, val):
+
+ output.write(u'#include <stdint.h>\n')
+ output.write(u'#include <openssl/bn.h>\n')
+
import struct
- output.write('#include <stdint.h>\n')
if len(struct.pack('@L', 0)) == 8:
return print_ssl_64(output, name, val)
else:
return print_ssl_32(output, name, val)
def print_ssl_keys(output, n):
- output.write(r'''
+ output.write(u'''
struct pubkey {
struct bignum_st e, n;
};
-#define KEY(data) { \
- .d = data, \
- .top = sizeof(data)/sizeof(data[0]), \
+#define KEY(data) { \\
+ .d = data, \\
+ .top = sizeof(data)/sizeof(data[0]), \\
}
-#define KEYS(e,n) { KEY(e), KEY(n), }
+#define KEYS(e,n) { KEY(e), KEY(n), }
static struct pubkey keys[] = {
''')
for n in xrange(n + 1):
- output.write(' KEYS(e_%d, n_%d),\n' % (n, n))
- output.write('};\n')
+ output.write(u' KEYS(e_{0}, n_{0}),\n'.format(n))
+ output.write(u'};\n')
pass
def print_gcrypt(output, name, val):
- output.write('#include <stdint.h>\n')
- while val[0] == '\0':
- val = val[1:]
- output.write('static const uint8_t %s[%d] = {\n' % (name, len(val)))
+ # gcrypt expects 8-bit words most-significant-word first
+ vwords = bitwise_collect(val, 8)
+ vwords.reverse()
+
+ output.write(u'#include <stdint.h>\n')
+ output.write(u'static const uint8_t %s[%d] = {\n' % (name, len(vwords)))
idx = 0
- for v in val:
+ for vword in vwords:
if not idx:
- output.write('\t')
- output.write('0x%.2x, ' % ord(v))
+ output.write(u'\t')
+ output.write(u'0x{:02x}, '.format(vword))
idx += 1
if idx == 8:
idx = 0
- output.write('\n')
+ output.write(u'\n')
if idx:
- output.write('\n')
- output.write('};\n\n')
+ output.write(u'\n')
+ output.write(u'};\n\n')
def print_gcrypt_keys(output, n):
- output.write(r'''
+ output.write(u'''
struct key_params {
const uint8_t *e, *n;
uint32_t len_e, len_n;
};
-#define KEYS(_e, _n) { \
- .e = _e, .len_e = sizeof(_e), \
- .n = _n, .len_n = sizeof(_n), \
+#define KEYS(_e, _n) { \\
+ .e = _e, .len_e = sizeof(_e), \\
+ .n = _n, .len_n = sizeof(_n), \\
}
static const struct key_params __attribute__ ((unused)) keys[] = {
''')
- for n in xrange(n + 1):
- output.write(' KEYS(e_%d, n_%d),\n' % (n, n))
- output.write('};\n')
-
+ for n in range(n + 1):
+ output.write(u' KEYS(e_{0}, n_{0}),\n'.format(n))
+ output.write(u'};\n')
+
modes = {
'--ssl': (print_ssl, print_ssl_keys),
@@ -135,21 +137,21 @@ except IndexError:
mode = None
if not mode in modes:
- print 'Usage: %s [%s] input-file... output-file' % (sys.argv[0], '|'.join(modes.keys()))
+ print('Usage: {} [{}] input-file... output-file'.format(sys.argv[0], '|'.join(modes.keys())))
sys.exit(2)
-output = open(outfile, 'w')
+output = io.open(outfile, 'w')
# load key
idx = 0
for f in files:
- try:
- key = RSA.load_pub_key(f)
- except RSA.RSAError:
- key = RSA.load_key(f)
- modes[mode][0](output, 'e_%d' % idx, key.e[4:])
- modes[mode][0](output, 'n_%d' % idx, key.n[4:])
+ key_contents = io.open(f, 'rb').read()
+ key = RSA.importKey(key_contents)
+
+ modes[mode][0](output, 'e_{}'.format(idx), key.e)
+ modes[mode][0](output, 'n_{}'.format(idx), key.n)
+
idx += 1
modes[mode][1](output, idx - 1)
--
2.25.3