summaryrefslogtreecommitdiff
path: root/net-wireless/crda/files/crda-4.14-openssl-1.1.0-compatibility.patch
blob: a9999da239fd1e4e0fec05c76cc46ff621247d93 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
From 338637ac08c19708eb35523894b44bbe3c726cfa Mon Sep 17 00:00:00 2001
From: quentin <quentin@minster.io>
Date: Mon, 2 Apr 2018 18:07:50 +0200
Subject: [PATCH] crda: Fix for OpenSSL 1.1.0: BIGNUM now opaque

OpenSSL 1.1.0 makes most of OpenSSL's structures opaque, and provides
functions to manipulate them. This means it's no longer possible to
construct an OpenSSL BIGNUM directly from scratch, as was done in
keys-ssl.c.

Use BN_bin2bn() (available since OpenSSL 0.9.8) to build the bignum from
its big-endian representation as a byte array.

This also allows factoring the code in utils/key2pub.py as it's now the
same mechanism as with libgcrypt.

This was tested with OpenSSL 1.1.0g.

Signed-off-by: Quentin Minster <quentin@minster.io>
---
 Makefile         |  12 +++----
 reglib.c         |  44 +++++++++++++++++------
 utils/key2pub.py | 107 ++++++-------------------------------------------------
 3 files changed, 49 insertions(+), 114 deletions(-)

diff --git a/Makefile b/Makefile
index a3ead30..a4e7373 100644
--- a/Makefile
+++ b/Makefile
@@ -38,18 +38,16 @@ all: all_noverify verify
 
 all_noverify: $(LIBREG) crda intersect regdbdump db2rd optimize
 
+$(LIBREG): keys.c
+
 ifeq ($(USE_OPENSSL),1)
 CFLAGS += -DUSE_OPENSSL -DPUBKEY_DIR=\"$(RUNTIME_PUBKEY_DIR)\" `pkg-config --cflags openssl`
 LDLIBS += `pkg-config --libs openssl`
 
-$(LIBREG): keys-ssl.c
-
 else
 CFLAGS += -DUSE_GCRYPT
 LDLIBS += -lgcrypt
 
-$(LIBREG): keys-gcrypt.c
-
 endif
 MKDIR ?= mkdir -p
 INSTALL ?= install
@@ -109,10 +107,10 @@ $(REG_BIN):
 	$(NQ)
 	$(Q) exit 1
 
-keys-%.c: utils/key2pub.py $(wildcard $(PUBKEY_DIR)/*.pem)
+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)./utils/key2pub.py $(wildcard $(PUBKEY_DIR)/*.pem) $@
 
 $(LIBREG): regdb.h reglib.h reglib.c
 	$(NQ) '  CC  ' $@
@@ -187,5 +185,5 @@ install: install-libreg install-libreg-headers crda crda.8.gz regdbdump.8.gz
 
 clean:
 	$(Q)rm -f $(LIBREG) crda regdbdump intersect db2rd optimize \
-		*.o *~ *.pyc keys-*.c *.gz \
+		*.o *~ *.pyc keys.c *.gz \
 	udev/$(UDEV_LEVEL)regulatory.rules udev/regulatory.rules.parsed
diff --git a/reglib.c b/reglib.c
index e00e9b8..00f7f56 100644
--- a/reglib.c
+++ b/reglib.c
@@ -22,6 +22,7 @@
 #include <openssl/rsa.h>
 #include <openssl/sha.h>
 #include <openssl/pem.h>
+#include <openssl/bn.h>
 #endif
 
 #ifdef USE_GCRYPT
@@ -30,12 +31,8 @@
 
 #include "reglib.h"
 
-#ifdef USE_OPENSSL
-#include "keys-ssl.c"
-#endif
-
-#ifdef USE_GCRYPT
-#include "keys-gcrypt.c"
+#if defined(USE_OPENSSL) || defined(USE_GCRYPT)
+#include "keys.c"
 #endif
 
 int debug = 0;
@@ -81,7 +78,8 @@ reglib_array_len(size_t baselen, unsigned int elemcount, size_t elemlen)
 #ifdef USE_OPENSSL
 int reglib_verify_db_signature(uint8_t *db, size_t dblen, size_t siglen)
 {
-	RSA *rsa;
+	RSA *rsa = NULL;
+	BIGNUM *rsa_e = NULL, *rsa_n = NULL;
 	uint8_t hash[SHA_DIGEST_LENGTH];
 	unsigned int i;
 	int ok = 0;
@@ -102,15 +100,35 @@ int reglib_verify_db_signature(uint8_t *db, size_t dblen, size_t siglen)
 			goto out;
 		}
 
-		rsa->e = &keys[i].e;
-		rsa->n = &keys[i].n;
+		rsa_e = BN_bin2bn(keys[i].e, keys[i].len_e, NULL);
+		if (!rsa_e) {
+			fprintf(stderr, "Failed to convert value for RSA e.\n");
+			goto out;
+		}
+		rsa_n = BN_bin2bn(keys[i].n, keys[i].len_n, NULL);
+		if (!rsa_n) {
+			fprintf(stderr, "Failed to convert value for RSA n.\n");
+			goto out;
+		}
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+		rsa->e = rsa_e;
+		rsa->n = rsa_n;
+#else
+		if (RSA_set0_key(rsa, rsa_n, rsa_e, NULL) != 1) {
+			fprintf(stderr, "Failed to set RSA key.\n");
+			goto out;
+		}
+#endif
+		/* BIGNUMs now owned by the RSA object */
+		rsa_e = NULL;
+		rsa_n = NULL;
 
 		ok = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
 				db + dblen, siglen, rsa) == 1;
 
-		rsa->e = NULL;
-		rsa->n = NULL;
 		RSA_free(rsa);
+		rsa = NULL;
 	}
 	if (!ok && (pubkey_dir = opendir(PUBKEY_DIR))) {
 		while (!ok && (nextfile = readdir(pubkey_dir))) {
@@ -123,6 +141,7 @@ int reglib_verify_db_signature(uint8_t *db, size_t dblen, size_t siglen)
 					ok = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
 						db + dblen, siglen, rsa) == 1;
 				RSA_free(rsa);
+				rsa = NULL;
 				fclose(keyfile);
 			}
 		}
@@ -133,6 +152,9 @@ int reglib_verify_db_signature(uint8_t *db, size_t dblen, size_t siglen)
 		fprintf(stderr, "Database signature verification failed.\n");
 
 out:
+	RSA_free(rsa);
+	BN_free(rsa_e);
+	BN_free(rsa_n);
 	return ok;
 }
 #endif /* USE_OPENSSL */
diff --git a/utils/key2pub.py b/utils/key2pub.py
index 9bb04cd..1919270 100755
--- a/utils/key2pub.py
+++ b/utils/key2pub.py
@@ -9,84 +9,7 @@ except ImportError as e:
        sys.stderr.write('On Debian GNU/Linux the package is called "python-m2crypto".\n')
        sys.exit(1)
 
-def print_ssl_64(output, name, val):
-    while val[0:1] == b'\0':
-        val = val[1:]
-    while len(val) % 8:
-        val = b'\0' + val
-    vnew = []
-    while len(val):
-        vnew.append((val[0:1], val[1:2], val[2:3], val[3:4], val[4:5], val[5:6], val[6:7], val[7:8]))
-        val = val[8:]
-    vnew.reverse()
-    output.write('static BN_ULONG %s[%d] = {\n' % (name, len(vnew)))
-    idx = 0
-    for v1, v2, v3, v4, v5, v6, v7, v8 in vnew:
-        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)))
-        idx += 1
-        if idx == 2:
-            idx = 0
-            output.write('\n')
-    if idx:
-        output.write('\n')
-    output.write('};\n\n')
-
-def print_ssl_32(output, name, val):
-    while val[0:1] == b'\0':
-        val = val[1:]
-    while len(val) % 4:
-        val = b'\0' + val
-    vnew = []
-    while len(val):
-        vnew.append((val[0:1], val[1:2], val[2:3], val[3:4]))
-        val = val[4:]
-    vnew.reverse()
-    output.write('static BN_ULONG %s[%d] = {\n' % (name, len(vnew)))
-    idx = 0
-    for v1, v2, v3, v4 in vnew:
-        if not idx:
-            output.write('\t')
-        output.write('0x%.2x%.2x%.2x%.2x, ' % (ord(v1), ord(v2), ord(v3), ord(v4)))
-        idx += 1
-        if idx == 4:
-            idx = 0
-            output.write('\n')
-    if idx:
-        output.write('\n')
-    output.write('};\n\n')
-
-def print_ssl(output, name, val):
-    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'''
-struct pubkey {
-	struct bignum_st e, n;
-};
-
-#define KEY(data) {				\
-	.d = data,				\
-	.top = sizeof(data)/sizeof(data[0]),	\
-}
-
-#define KEYS(e,n)	{ KEY(e), KEY(n), }
-
-static struct pubkey keys[] = {
-''')
-    for n in range(n + 1):
-        output.write('	KEYS(e_%d, n_%d),\n' % (n, n))
-    output.write('};\n')
-    pass
-
-def print_gcrypt(output, name, val):
-    output.write('#include <stdint.h>\n')
+def print_bignum(output, name, val):
     while val[0:1] == b'\0':
         val = val[1:]
     output.write('static const uint8_t %s[%d] = {\n' % (name, len(val)))
@@ -103,11 +26,11 @@ def print_gcrypt(output, name, val):
         output.write('\n')
     output.write('};\n\n')
 
-def print_gcrypt_keys(output, n):
+def print_keys(output, n):
     output.write(r'''
 struct key_params {
 	const uint8_t *e, *n;
-	uint32_t len_e, len_n;
+	const uint32_t len_e, len_n;
 };
 
 #define KEYS(_e, _n) {			\
@@ -120,25 +43,17 @@ static const struct key_params __attribute__ ((unused)) keys[] = {
     for n in range(n + 1):
         output.write('	KEYS(e_%d, n_%d),\n' % (n, n))
     output.write('};\n')
-    
 
-modes = {
-    '--ssl': (print_ssl, print_ssl_keys),
-    '--gcrypt': (print_gcrypt, print_gcrypt_keys),
-}
 
-try:
-    mode = sys.argv[1]
-    files = sys.argv[2:-1]
-    outfile = sys.argv[-1]
-except IndexError:
-    mode = None
+files = sys.argv[1:-1]
+outfile = sys.argv[-1]
 
-if not mode in modes:
-    print('Usage: %s [%s] input-file... output-file' % (sys.argv[0], '|'.join(modes.keys())))
+if len(files) == 0:
+    print('Usage: %s input-file... output-file' % sys.argv[0])
     sys.exit(2)
 
 output = open(outfile, 'w')
+output.write('#include <stdint.h>\n\n\n')
 
 # load key
 idx = 0
@@ -148,10 +63,10 @@ for f in files:
     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:])
+    print_bignum(output, 'e_%d' % idx, key.e[4:])
+    print_bignum(output, 'n_%d' % idx, key.n[4:])
     idx += 1
 
-modes[mode][1](output, idx - 1)
+print_keys(output, idx - 1)
 
 output.close()