Browse code

strongswan: Fix for CVE-2018-16151 and CVE-2018-16152

Change-Id: I9df7435c46e8a001c14732a07c2f0485983b4d4b
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/6439
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Tapas Kundu <tkundu@vmware.com>
Reviewed-by: Anish Swaminathan <anishs@vmware.com>

Keerthana K authored on 2019/01/03 17:10:06
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,323 @@
0
+From 511563ce763b1e98e3fb3b3e3addfef550ff99b2 Mon Sep 17 00:00:00 2001
1
+From: Tobias Brunner <tobias@strongswan.org>
2
+Date: Tue, 28 Aug 2018 11:26:24 +0200
3
+Subject: [PATCH] gmp: Don't parse PKCS1 v1.5 RSA signatures to verify them
4
+
5
+Instead we generate the expected signature encoding and compare it to the
6
+decrypted value.
7
+
8
+Due to the lenient nature of the previous parsing code (minimum padding
9
+length was not enforced, the algorithmIdentifier/OID parser accepts arbitrary
10
+data after OIDs and in the parameters field etc.) it was susceptible to
11
+Daniel Bleichenbacher's low-exponent attack (from 2006!), which allowed
12
+forging signatures for keys that use low public exponents (i.e. e=3).
13
+
14
+Since the public exponent is usually set to 0x10001 (65537) since quite a
15
+while, the flaws in the previous code should not have had that much of a
16
+practical impact in recent years.
17
+
18
+Fixes: CVE-2018-16151, CVE-2018-16152
19
+---
20
+ .../plugins/gmp/gmp_rsa_private_key.c              |  66 +++++----
21
+ src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c | 156 ++-------------------
22
+ 2 files changed, 52 insertions(+), 170 deletions(-)
23
+
24
+diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
25
+index 241ef7d3b12b..edc178e96a4f 100644
26
+--- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
27
+@@ -264,14 +264,15 @@ static chunk_t rsasp1(private_gmp_rsa_private_key_t *this, chunk_t data)
28
+ }
29
+ 
30
+ /**
31
+- * Build a signature using the PKCS#1 EMSA scheme
32
++ * Hashes the data and builds the plaintext signature value with EMSA
33
++ * PKCS#1 v1.5 padding.
34
++ *
35
++ * Allocates the signature data.
36
+  */
37
+-static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this,
38
+-									   hash_algorithm_t hash_algorithm,
39
+-									   chunk_t data, chunk_t *signature)
40
++bool gmp_emsa_pkcs1_signature_data(hash_algorithm_t hash_algorithm,
41
++								   chunk_t data, size_t keylen, chunk_t *em)
42
+ {
43
+ 	chunk_t digestInfo = chunk_empty;
44
+-	chunk_t em;
45
+ 
46
+ 	if (hash_algorithm != HASH_UNKNOWN)
47
+ 	{
48
+@@ -295,43 +296,56 @@ static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this,
49
+ 		/* build DER-encoded digestInfo */
50
+ 		digestInfo = asn1_wrap(ASN1_SEQUENCE, "mm",
51
+ 						asn1_algorithmIdentifier(hash_oid),
52
+-						asn1_simple_object(ASN1_OCTET_STRING, hash)
53
+-					  );
54
+-		chunk_free(&hash);
55
++						asn1_wrap(ASN1_OCTET_STRING, "m", hash));
56
++
57
+ 		data = digestInfo;
58
+ 	}
59
+ 
60
+-	if (data.len > this->k - 3)
61
++	if (data.len > keylen - 11)
62
+ 	{
63
+-		free(digestInfo.ptr);
64
+-		DBG1(DBG_LIB, "unable to sign %d bytes using a %dbit key", data.len,
65
+-			 mpz_sizeinbase(this->n, 2));
66
++		chunk_free(&digestInfo);
67
++		DBG1(DBG_LIB, "signature value of %zu bytes is too long for key of "
68
++			 "%zu bytes", data.len, keylen);
69
+ 		return FALSE;
70
+ 	}
71
+ 
72
+-	/* build chunk to rsa-decrypt:
73
+-	 * EM = 0x00 || 0x01 || PS || 0x00 || T.
74
+-	 * PS = 0xFF padding, with length to fill em
75
++	/* EM = 0x00 || 0x01 || PS || 0x00 || T.
76
++	 * PS = 0xFF padding, with length to fill em (at least 8 bytes)
77
+ 	 * T = encoded_hash
78
+ 	 */
79
+-	em.len = this->k;
80
+-	em.ptr = malloc(em.len);
81
++	*em = chunk_alloc(keylen);
82
+ 
83
+ 	/* fill em with padding */
84
+-	memset(em.ptr, 0xFF, em.len);
85
++	memset(em->ptr, 0xFF, em->len);
86
+ 	/* set magic bytes */
87
+-	*(em.ptr) = 0x00;
88
+-	*(em.ptr+1) = 0x01;
89
+-	*(em.ptr + em.len - data.len - 1) = 0x00;
90
+-	/* set DER-encoded hash */
91
+-	memcpy(em.ptr + em.len - data.len, data.ptr, data.len);
92
++	*(em->ptr) = 0x00;
93
++	*(em->ptr+1) = 0x01;
94
++	*(em->ptr + em->len - data.len - 1) = 0x00;
95
++	/* set encoded hash */
96
++	memcpy(em->ptr + em->len - data.len, data.ptr, data.len);
97
++
98
++	chunk_clear(&digestInfo);
99
++	return TRUE;
100
++}
101
++
102
++/**
103
++ * Build a signature using the PKCS#1 EMSA scheme
104
++ */
105
++static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this,
106
++									   hash_algorithm_t hash_algorithm,
107
++									   chunk_t data, chunk_t *signature)
108
++{
109
++	chunk_t em;
110
++
111
++	if (!gmp_emsa_pkcs1_signature_data(hash_algorithm, data, this->k, &em))
112
++	{
113
++		return FALSE;
114
++	}
115
+ 
116
+ 	/* build signature */
117
+ 	*signature = rsasp1(this, em);
118
+ 
119
+-	free(digestInfo.ptr);
120
+-	free(em.ptr);
121
+-
122
++	chunk_free(&em);
123
+ 	return TRUE;
124
+ }
125
+ 
126
+diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
127
+index 52bc9fb38046..ce9a80fadf2a 100644
128
+--- a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
129
+@@ -70,7 +70,9 @@ struct private_gmp_rsa_public_key_t {
130
+ /**
131
+  * Shared functions defined in gmp_rsa_private_key.c
132
+  */
133
+-extern chunk_t gmp_mpz_to_chunk(const mpz_t value);
134
++chunk_t gmp_mpz_to_chunk(const mpz_t value);
135
++bool gmp_emsa_pkcs1_signature_data(hash_algorithm_t hash_algorithm,
136
++								   chunk_t data, size_t keylen, chunk_t *em);
137
+ 
138
+ /**
139
+  * RSAEP algorithm specified in PKCS#1.
140
+--- a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
141
+@@ -115,26 +115,13 @@
142
+ }
143
+ 
144
+ /**
145
+- * ASN.1 definition of digestInfo
146
+- */
147
+-static const asn1Object_t digestInfoObjects[] = {
148
+-	{ 0, "digestInfo",			ASN1_SEQUENCE,		ASN1_OBJ  }, /*  0 */
149
+-	{ 1,   "digestAlgorithm",	ASN1_EOC,			ASN1_RAW  }, /*  1 */
150
+-	{ 1,   "digest",			ASN1_OCTET_STRING,	ASN1_BODY }, /*  2 */
151
+-	{ 0, "exit",				ASN1_EOC,			ASN1_EXIT }
152
+-};
153
+-#define DIGEST_INFO					0
154
+-#define DIGEST_INFO_ALGORITHM		1
155
+-#define DIGEST_INFO_DIGEST			2
156
+-
157
+-/**
158
+  * Verification of an EMPSA PKCS1 signature described in PKCS#1
159
+  */
160
+ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
161
+ 										hash_algorithm_t algorithm,
162
+ 										chunk_t data, chunk_t signature)
163
+ {
164
+-	chunk_t em_ori, em;
165
++	chunk_t em_expected, em;
166
+ 	bool success = FALSE;
167
+ 
168
+ 	/* remove any preceding 0-bytes from signature */
169
+@@ -148,140 +137,19 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
170
+ 		return FALSE;
171
+ 	}
172
+ 
173
+-	/* unpack signature */
174
+-	em_ori = em = rsavp1(this, signature);
175
+-
176
+-	/* result should look like this:
177
+-	 * EM = 0x00 || 0x01 || PS || 0x00 || T.
178
+-	 * PS = 0xFF padding, with length to fill em
179
+-	 * T = oid || hash
180
+-	 */
181
+-
182
+-	/* check magic bytes */
183
+-	if (em.len < 2 || *(em.ptr) != 0x00 || *(em.ptr+1) != 0x01)
184
++	/* generate expected signature value */
185
++	if (!gmp_emsa_pkcs1_signature_data(algorithm, data, this->k, &em_expected))
186
+ 	{
187
+-		goto end;
188
+-	}
189
+-	em = chunk_skip(em, 2);
190
+-
191
+-	/* find magic 0x00 */
192
+-	while (em.len > 0)
193
+-	{
194
+-		if (*em.ptr == 0x00)
195
+-		{
196
+-			/* found magic byte, stop */
197
+-			em = chunk_skip(em, 1);
198
+-			break;
199
+-		}
200
+-		else if (*em.ptr != 0xFF)
201
+-		{
202
+-			/* bad padding, decryption failed ?!*/
203
+-			goto end;
204
+-		}
205
+-		em = chunk_skip(em, 1);
206
+-	}
207
+-
208
+-	if (em.len == 0)
209
+-	{
210
+-		/* no digestInfo found */
211
+-		goto end;
212
+-	}
213
+-
214
+-	if (algorithm == HASH_UNKNOWN)
215
+-	{   /* IKEv1 signatures without digestInfo */
216
+-		if (em.len != data.len)
217
+-		{
218
+-			DBG1(DBG_LIB, "hash size in signature is %u bytes instead of"
219
+-				 " %u bytes", em.len, data.len);
220
+-			goto end;
221
+-		}
222
+-		success = memeq_const(em.ptr, data.ptr, data.len);
223
++		return FALSE;
224
+ 	}
225
+-	else
226
+-	{   /* IKEv2 and X.509 certificate signatures */
227
+-		asn1_parser_t *parser;
228
+-		chunk_t object;
229
+-		int objectID;
230
+-		hash_algorithm_t hash_algorithm = HASH_UNKNOWN;
231
+-
232
+-		DBG2(DBG_LIB, "signature verification:");
233
+-		parser = asn1_parser_create(digestInfoObjects, em);
234
+ 
235
+-		while (parser->iterate(parser, &objectID, &object))
236
+-		{
237
+-			switch (objectID)
238
+-			{
239
+-				case DIGEST_INFO:
240
+-				{
241
+-					if (em.len > object.len)
242
+-					{
243
+-						DBG1(DBG_LIB, "digestInfo field in signature is"
244
+-							 " followed by %u surplus bytes",
245
+-							 em.len - object.len);
246
+-						goto end_parser;
247
+-					}
248
+-					break;
249
+-				}
250
+-				case DIGEST_INFO_ALGORITHM:
251
+-				{
252
+-					int hash_oid = asn1_parse_algorithmIdentifier(object,
253
+-										 parser->get_level(parser)+1, NULL);
254
+-
255
+-					hash_algorithm = hasher_algorithm_from_oid(hash_oid);
256
+-					if (hash_algorithm == HASH_UNKNOWN || hash_algorithm != algorithm)
257
+-					{
258
+-						DBG1(DBG_LIB, "expected hash algorithm %N, but found"
259
+-							 " %N (OID: %#B)", hash_algorithm_names, algorithm,
260
+-							 hash_algorithm_names, hash_algorithm,  &object);
261
+-						goto end_parser;
262
+-					}
263
+-					break;
264
+-				}
265
+-				case DIGEST_INFO_DIGEST:
266
+-				{
267
+-					chunk_t hash;
268
+-					hasher_t *hasher;
269
+-
270
+-					hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm);
271
+-					if (hasher == NULL)
272
+-					{
273
+-						DBG1(DBG_LIB, "hash algorithm %N not supported",
274
+-							 hash_algorithm_names, hash_algorithm);
275
+-						goto end_parser;
276
+-					}
277
+-
278
+-					if (object.len != hasher->get_hash_size(hasher))
279
+-					{
280
+-						DBG1(DBG_LIB, "hash size in signature is %u bytes"
281
+-							 " instead of %u bytes", object.len,
282
+-							 hasher->get_hash_size(hasher));
283
+-						hasher->destroy(hasher);
284
+-						goto end_parser;
285
+-					}
286
+-
287
+-					/* build our own hash and compare */
288
+-					if (!hasher->allocate_hash(hasher, data, &hash))
289
+-					{
290
+-						hasher->destroy(hasher);
291
+-						goto end_parser;
292
+-					}
293
+-					hasher->destroy(hasher);
294
+-					success = memeq_const(object.ptr, hash.ptr, hash.len);
295
+-					free(hash.ptr);
296
+-					break;
297
+-				}
298
+-				default:
299
+-					break;
300
+-			}
301
+-		}
302
++	/* unpack signature */
303
++	em = rsavp1(this, signature);
304
+ 
305
+-end_parser:
306
+-		success &= parser->success(parser);
307
+-		parser->destroy(parser);
308
+-	}
309
++	success = chunk_equals_const(em_expected, em);
310
+ 
311
+-end:
312
+-	free(em_ori.ptr);
313
++	chunk_free(&em_expected);
314
++	chunk_free(&em);
315
+ 	return success;
316
+ }
317
+ 
318
+-- 
319
+2.7.4
... ...
@@ -1,7 +1,7 @@
1 1
 Summary:          The OpenSource IPsec-based VPN Solution
2 2
 Name:             strongswan
3 3
 Version:          5.5.2
4
-Release:          5%{?dist}
4
+Release:          6%{?dist}
5 5
 License:          GPLv2+
6 6
 URL:              https://www.strongswan.org/
7 7
 Group:            System Environment/Security
... ...
@@ -14,6 +14,7 @@ Patch1:           CVE-2017-9023.patch
14 14
 Patch2:           CVE-2017-11185.patch
15 15
 Patch3:           CVE-2018-5388.patch
16 16
 Patch4:           CVE-2018-10811.patch
17
+Patch5:           CVE-2018-16151-16152.patch
17 18
 BuildRequires:    autoconf
18 19
 
19 20
 %description
... ...
@@ -26,6 +27,7 @@ strongSwan is a complete IPsec implementation for Linux 2.6, 3.x, and 4.x kernel
26 26
 %patch2 -p1
27 27
 %patch3 -p1
28 28
 %patch4 -p1
29
+%patch5 -p1
29 30
 
30 31
 %build
31 32
 ./configure --prefix=%{_prefix} --sysconfdir=%{_sysconfdir}
... ...
@@ -55,6 +57,8 @@ rm -rf %{buildroot}/*
55 55
 %{_datadir}/strongswan/*
56 56
 
57 57
 %changelog
58
+*   Thu Jan 03 2019 Keerthana K <keerthanak@vmware.com> 5.5.2-6
59
+-   Fix for CVE-2018-16151 and CVE-2018-16152.
58 60
 *   Thu Aug 16 2018 Tapas Kundu <tkundu@vmware.com> 5.5.2-5
59 61
 -   Fix for CVE-2018-10811
60 62
 *   Mon Jul 16 2018 Ajay Kaher <akaher@vmware.com> 5.5.2-4