xref: /OK3568_Linux_fs/buildroot/package/crda/0001-crda-support-python-3-in-utils-key2pub.py.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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