From 1254da9759827c7573e90d7f78048ef6a84cfe1713c747efd02583a5392c2394 Mon Sep 17 00:00:00 2001 From: Matej Cepl Date: Thu, 8 Jul 2021 21:55:28 +0000 Subject: [PATCH 1/4] Accepting request 905118 from home:mcepl:branches:devel:libraries:c_c++ - Add CVE-2021-22918.patch: patch libuv to fix out of bounds read (Medium) (bsc#1187973, CVE-2021-22918) OBS-URL: https://build.opensuse.org/request/show/905118 OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libuv?expand=0&rev=52 --- CVE-2021-22918.patch | 146 +++++++++++++++++++++++++++++++++++++++++++ fix_tests.patch | 18 +++--- libuv.changes | 6 ++ libuv.spec | 3 + 4 files changed, 165 insertions(+), 8 deletions(-) create mode 100644 CVE-2021-22918.patch diff --git a/CVE-2021-22918.patch b/CVE-2021-22918.patch new file mode 100644 index 0000000..edb7032 --- /dev/null +++ b/CVE-2021-22918.patch @@ -0,0 +1,146 @@ +--- + src/idna.c | 49 ++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 36 insertions(+), 13 deletions(-) + +--- a/src/idna.c ++++ b/src/idna.c +@@ -19,6 +19,7 @@ + + #include "uv.h" + #include "idna.h" ++#include + #include + + static unsigned uv__utf8_decode1_slow(const char** p, +@@ -32,7 +33,7 @@ static unsigned uv__utf8_decode1_slow(co + if (a > 0xF7) + return -1; + +- switch (*p - pe) { ++ switch (pe - *p) { + default: + if (a > 0xEF) { + min = 0x10000; +@@ -62,6 +63,8 @@ static unsigned uv__utf8_decode1_slow(co + a = 0; + break; + } ++ /* Fall through. */ ++ case 0: + return -1; /* Invalid continuation byte. */ + } + +@@ -88,6 +91,8 @@ static unsigned uv__utf8_decode1_slow(co + unsigned uv__utf8_decode1(const char** p, const char* pe) { + unsigned a; + ++ assert(*p < pe); ++ + a = (unsigned char) *(*p)++; + + if (a < 128) +@@ -96,9 +101,6 @@ unsigned uv__utf8_decode1(const char** p + return uv__utf8_decode1_slow(p, pe, a); + } + +-#define foreach_codepoint(c, p, pe) \ +- for (; (void) (*p <= pe && (c = uv__utf8_decode1(p, pe))), *p <= pe;) +- + static int uv__idna_toascii_label(const char* s, const char* se, + char** d, char* de) { + static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789"; +@@ -121,15 +123,22 @@ static int uv__idna_toascii_label(const + ss = s; + todo = 0; + +- foreach_codepoint(c, &s, se) { ++ /* Note: after this loop we've visited all UTF-8 characters and know ++ * they're legal so we no longer need to check for decode errors. ++ */ ++ while (s < se) { ++ c = uv__utf8_decode1(&s, se); ++ ++ if (c == -1u) ++ return UV_EINVAL; ++ + if (c < 128) + h++; +- else if (c == (unsigned) -1) +- return UV_EINVAL; + else + todo++; + } + ++ /* Only write "xn--" when there are non-ASCII characters. */ + if (todo > 0) { + if (*d < de) *(*d)++ = 'x'; + if (*d < de) *(*d)++ = 'n'; +@@ -137,9 +146,13 @@ static int uv__idna_toascii_label(const + if (*d < de) *(*d)++ = '-'; + } + ++ /* Write ASCII characters. */ + x = 0; + s = ss; +- foreach_codepoint(c, &s, se) { ++ while (s < se) { ++ c = uv__utf8_decode1(&s, se); ++ assert(c != -1u); ++ + if (c > 127) + continue; + +@@ -166,10 +179,15 @@ static int uv__idna_toascii_label(const + while (todo > 0) { + m = -1; + s = ss; +- foreach_codepoint(c, &s, se) ++ ++ while (s < se) { ++ c = uv__utf8_decode1(&s, se); ++ assert(c != -1u); ++ + if (c >= n) + if (c < m) + m = c; ++ } + + x = m - n; + y = h + 1; +@@ -181,7 +199,10 @@ static int uv__idna_toascii_label(const + n = m; + + s = ss; +- foreach_codepoint(c, &s, se) { ++ while (s < se) { ++ c = uv__utf8_decode1(&s, se); ++ assert(c != -1u); ++ + if (c < n) + if (++delta == 0) + return UV_E2BIG; /* Overflow. */ +@@ -245,8 +266,6 @@ static int uv__idna_toascii_label(const + return 0; + } + +-#undef foreach_codepoint +- + long uv__idna_toascii(const char* s, const char* se, char* d, char* de) { + const char* si; + const char* st; +@@ -256,10 +275,14 @@ long uv__idna_toascii(const char* s, con + + ds = d; + +- for (si = s; si < se; /* empty */) { ++ si = s; ++ while (si < se) { + st = si; + c = uv__utf8_decode1(&si, se); + ++ if (c == -1u) ++ return UV_EINVAL; ++ + if (c != '.') + if (c != 0x3002) /* 。 */ + if (c != 0xFF0E) /* . */ diff --git a/fix_tests.patch b/fix_tests.patch index 46ffe08..4de70ed 100644 --- a/fix_tests.patch +++ b/fix_tests.patch @@ -1,7 +1,9 @@ -Index: libuv-v1.39.0/test/test-list.h -=================================================================== ---- libuv-v1.39.0.orig/test/test-list.h -+++ libuv-v1.39.0/test/test-list.h +--- + test/test-list.h | 11 ----------- + 1 file changed, 11 deletions(-) + +--- a/test/test-list.h ++++ b/test/test-list.h @@ -78,7 +78,6 @@ TEST_DECLARE (tty_pty) TEST_DECLARE (stdio_over_pipes) TEST_DECLARE (stdio_emulate_iocp) @@ -10,7 +12,7 @@ Index: libuv-v1.39.0/test/test-list.h TEST_DECLARE (ipc_heavy_traffic_deadlock_bug) TEST_DECLARE (ipc_listen_before_write) TEST_DECLARE (ipc_listen_after_write) -@@ -166,11 +165,7 @@ TEST_DECLARE (udp_send_hang_loop) +@@ -167,11 +166,7 @@ TEST_DECLARE (udp_send_hang_loop) TEST_DECLARE (udp_send_immediate) TEST_DECLARE (udp_send_unreachable) TEST_DECLARE (udp_mmsg) @@ -22,7 +24,7 @@ Index: libuv-v1.39.0/test/test-list.h TEST_DECLARE (udp_dgram_too_big) TEST_DECLARE (udp_dual_stack) TEST_DECLARE (udp_ipv6_only) -@@ -600,7 +595,6 @@ TASK_LIST_START +@@ -604,7 +599,6 @@ TASK_LIST_START TEST_ENTRY (stdio_over_pipes) TEST_ENTRY (stdio_emulate_iocp) TEST_ENTRY (ip6_pton) @@ -30,7 +32,7 @@ Index: libuv-v1.39.0/test/test-list.h TEST_ENTRY (ipc_heavy_traffic_deadlock_bug) TEST_ENTRY (ipc_listen_before_write) TEST_ENTRY (ipc_listen_after_write) -@@ -731,10 +725,6 @@ TASK_LIST_START +@@ -741,10 +735,6 @@ TASK_LIST_START TEST_ENTRY (udp_options6) TEST_ENTRY (udp_no_autobind) TEST_ENTRY (udp_mmsg) @@ -41,7 +43,7 @@ Index: libuv-v1.39.0/test/test-list.h TEST_ENTRY (udp_multicast_ttl) TEST_ENTRY (udp_sendmmsg_error) TEST_ENTRY (udp_try_send) -@@ -872,7 +862,6 @@ TASK_LIST_START +@@ -882,7 +872,6 @@ TASK_LIST_START TEST_ENTRY (getnameinfo_basic_ip4) TEST_ENTRY (getnameinfo_basic_ip4_sync) diff --git a/libuv.changes b/libuv.changes index 615b83f..870c6b9 100644 --- a/libuv.changes +++ b/libuv.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Thu Jul 8 20:02:46 UTC 2021 - Matej Cepl + +- Add CVE-2021-22918.patch: patch libuv to fix out of bounds read + (Medium) (bsc#1187973, CVE-2021-22918) + ------------------------------------------------------------------- Tue Feb 23 22:43:09 UTC 2021 - Dirk Müller diff --git a/libuv.spec b/libuv.spec index 82926ab..0e32331 100644 --- a/libuv.spec +++ b/libuv.spec @@ -29,6 +29,9 @@ Source1: https://dist.libuv.org/dist/v%{version}/libuv-v%{version}.tar.gz Source2: %{name}.keyring Source3: baselibs.conf Patch1: fix_tests.patch +# PATCH-FIX-UPSTREAM CVE-2021-22918.patch bsc#[0-9]+ mcepl@suse.com +# fix OOB read in punycode decoder (CVE-2021-22918, bsc#1187973) +Patch2: CVE-2021-22918.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: libtool From c85edf857f33b377ea50f43dbfa71ff678e0e90ec6630ae86c444bb6b22c6be4 Mon Sep 17 00:00:00 2001 From: Matej Cepl Date: Mon, 12 Jul 2021 07:13:48 +0000 Subject: [PATCH 2/4] - Fix the patch metadata OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libuv?expand=0&rev=53 --- libuv.changes | 5 +++++ libuv.spec | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libuv.changes b/libuv.changes index 870c6b9..23ad153 100644 --- a/libuv.changes +++ b/libuv.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Mon Jul 12 07:13:40 UTC 2021 - Matej Cepl + +- Fix the patch metadata + ------------------------------------------------------------------- Thu Jul 8 20:02:46 UTC 2021 - Matej Cepl diff --git a/libuv.spec b/libuv.spec index 0e32331..6828561 100644 --- a/libuv.spec +++ b/libuv.spec @@ -29,8 +29,8 @@ Source1: https://dist.libuv.org/dist/v%{version}/libuv-v%{version}.tar.gz Source2: %{name}.keyring Source3: baselibs.conf Patch1: fix_tests.patch -# PATCH-FIX-UPSTREAM CVE-2021-22918.patch bsc#[0-9]+ mcepl@suse.com -# fix OOB read in punycode decoder (CVE-2021-22918, bsc#1187973) +# PATCH-FIX-UPSTREAM CVE-2021-22918.patch bsc#1187973 mcepl@suse.com +# fix OOB read in punycode decoder (CVE-2021-22918) Patch2: CVE-2021-22918.patch BuildRequires: autoconf BuildRequires: automake From 09bdd2c04e6cc87a15f07df5db76a1f7141d104f2be494d47615d063acdc82f2 Mon Sep 17 00:00:00 2001 From: Matej Cepl Date: Tue, 13 Jul 2021 08:54:55 +0000 Subject: [PATCH 3/4] Accepting request 906045 from home:AndreasStieger:branches:devel:libraries:c_c++ replace patch with version bump OBS-URL: https://build.opensuse.org/request/show/906045 OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libuv?expand=0&rev=54 --- CVE-2021-22918.patch | 146 -------------------------------------- libuv-v1.41.0.tar.gz | 3 - libuv-v1.41.0.tar.gz.sign | 17 ----- libuv-v1.41.1.tar.gz | 3 + libuv-v1.41.1.tar.gz.sign | 16 +++++ libuv.changes | 11 +-- libuv.spec | 5 +- 7 files changed, 23 insertions(+), 178 deletions(-) delete mode 100644 CVE-2021-22918.patch delete mode 100644 libuv-v1.41.0.tar.gz delete mode 100644 libuv-v1.41.0.tar.gz.sign create mode 100644 libuv-v1.41.1.tar.gz create mode 100644 libuv-v1.41.1.tar.gz.sign diff --git a/CVE-2021-22918.patch b/CVE-2021-22918.patch deleted file mode 100644 index edb7032..0000000 --- a/CVE-2021-22918.patch +++ /dev/null @@ -1,146 +0,0 @@ ---- - src/idna.c | 49 ++++++++++++++++++++++++++++++++++++------------- - 1 file changed, 36 insertions(+), 13 deletions(-) - ---- a/src/idna.c -+++ b/src/idna.c -@@ -19,6 +19,7 @@ - - #include "uv.h" - #include "idna.h" -+#include - #include - - static unsigned uv__utf8_decode1_slow(const char** p, -@@ -32,7 +33,7 @@ static unsigned uv__utf8_decode1_slow(co - if (a > 0xF7) - return -1; - -- switch (*p - pe) { -+ switch (pe - *p) { - default: - if (a > 0xEF) { - min = 0x10000; -@@ -62,6 +63,8 @@ static unsigned uv__utf8_decode1_slow(co - a = 0; - break; - } -+ /* Fall through. */ -+ case 0: - return -1; /* Invalid continuation byte. */ - } - -@@ -88,6 +91,8 @@ static unsigned uv__utf8_decode1_slow(co - unsigned uv__utf8_decode1(const char** p, const char* pe) { - unsigned a; - -+ assert(*p < pe); -+ - a = (unsigned char) *(*p)++; - - if (a < 128) -@@ -96,9 +101,6 @@ unsigned uv__utf8_decode1(const char** p - return uv__utf8_decode1_slow(p, pe, a); - } - --#define foreach_codepoint(c, p, pe) \ -- for (; (void) (*p <= pe && (c = uv__utf8_decode1(p, pe))), *p <= pe;) -- - static int uv__idna_toascii_label(const char* s, const char* se, - char** d, char* de) { - static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789"; -@@ -121,15 +123,22 @@ static int uv__idna_toascii_label(const - ss = s; - todo = 0; - -- foreach_codepoint(c, &s, se) { -+ /* Note: after this loop we've visited all UTF-8 characters and know -+ * they're legal so we no longer need to check for decode errors. -+ */ -+ while (s < se) { -+ c = uv__utf8_decode1(&s, se); -+ -+ if (c == -1u) -+ return UV_EINVAL; -+ - if (c < 128) - h++; -- else if (c == (unsigned) -1) -- return UV_EINVAL; - else - todo++; - } - -+ /* Only write "xn--" when there are non-ASCII characters. */ - if (todo > 0) { - if (*d < de) *(*d)++ = 'x'; - if (*d < de) *(*d)++ = 'n'; -@@ -137,9 +146,13 @@ static int uv__idna_toascii_label(const - if (*d < de) *(*d)++ = '-'; - } - -+ /* Write ASCII characters. */ - x = 0; - s = ss; -- foreach_codepoint(c, &s, se) { -+ while (s < se) { -+ c = uv__utf8_decode1(&s, se); -+ assert(c != -1u); -+ - if (c > 127) - continue; - -@@ -166,10 +179,15 @@ static int uv__idna_toascii_label(const - while (todo > 0) { - m = -1; - s = ss; -- foreach_codepoint(c, &s, se) -+ -+ while (s < se) { -+ c = uv__utf8_decode1(&s, se); -+ assert(c != -1u); -+ - if (c >= n) - if (c < m) - m = c; -+ } - - x = m - n; - y = h + 1; -@@ -181,7 +199,10 @@ static int uv__idna_toascii_label(const - n = m; - - s = ss; -- foreach_codepoint(c, &s, se) { -+ while (s < se) { -+ c = uv__utf8_decode1(&s, se); -+ assert(c != -1u); -+ - if (c < n) - if (++delta == 0) - return UV_E2BIG; /* Overflow. */ -@@ -245,8 +266,6 @@ static int uv__idna_toascii_label(const - return 0; - } - --#undef foreach_codepoint -- - long uv__idna_toascii(const char* s, const char* se, char* d, char* de) { - const char* si; - const char* st; -@@ -256,10 +275,14 @@ long uv__idna_toascii(const char* s, con - - ds = d; - -- for (si = s; si < se; /* empty */) { -+ si = s; -+ while (si < se) { - st = si; - c = uv__utf8_decode1(&si, se); - -+ if (c == -1u) -+ return UV_EINVAL; -+ - if (c != '.') - if (c != 0x3002) /* 。 */ - if (c != 0xFF0E) /* . */ diff --git a/libuv-v1.41.0.tar.gz b/libuv-v1.41.0.tar.gz deleted file mode 100644 index bfbe449..0000000 --- a/libuv-v1.41.0.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1184533907e1ddad9c0dcd30a5abb0fe25288c287ff7fee303fff7b9b2d6eb6e -size 1272786 diff --git a/libuv-v1.41.0.tar.gz.sign b/libuv-v1.41.0.tar.gz.sign deleted file mode 100644 index aaf367a..0000000 --- a/libuv-v1.41.0.tar.gz.sign +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Comment: GPGTools - https://gpgtools.org - -iQIzBAABCgAdFiEEVzU+Db2qp+g5tmoa/0fV5K2LT9wFAmAoExQACgkQ/0fV5K2L -T9y74Q/8C1oF9SHJYyqUch+S8/7Erf+I1Hdak+BgqimH+FVtTPtyFL5OCzuhXwbI -VzHyi8ddM7ayJY3mVyArlYwxa4u0+uJzOji9EDHH6KoUCnA08/+bUOxcaW26DSOW -S8Tk3yJ9To892BGUQa+QLP1JIJqTlYul3pWZHOVL6pGu/qarPsyfVMMUHr7C+tkb -Z0aFGx9LrCmm+s0WyvoLF7NxfhDBwEVsSnfHZSWd5v6DGTprmGgHWqqbx8EQIzXs -XFu2mKhhV1klr0OxgakjpZiQV4P+GKgkc623lTBnafSGJMVWu57oy9xsEhoKL1pi -Pn1CWyYeeAR1huNham30wb525KrEa4W96kEBWWbJvFHue4Amlnr4vha5vVdzO3NL -GKmxay+s+bTG1wpYdkyk+OiINoV6+AB2tGruiCZVRVnHF96knY7Y3ShZzkpoedlj -s+/0pj4InABnr9n0iTVK0CDBqpUg05VMlgTxJukZE72q6biSTZSo+bKNtJOF3Oc1 -ihwQiyXLMTshk6kwYqaNe+9tu4sVSPUWzK8+8ydEkuDmjmb4k0L+N0T1zt2iKF42 -Dy6sXbNJghWmslHgKOvZ+aFI0EStl4of3MXFCd54Co1ECt3zNMdSQDYN9NcvXRZS -vrb0GsGnDwtU5ndA3PEydNfjZ2tKRgAf9E+4Zie0QDmBDxHlHoo= -=2N+m ------END PGP SIGNATURE----- diff --git a/libuv-v1.41.1.tar.gz b/libuv-v1.41.1.tar.gz new file mode 100644 index 0000000..abd069d --- /dev/null +++ b/libuv-v1.41.1.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65db0c7f2438bc8cd48865de282bf6670027f3557d6e3cb62fb65b2e350a687d +size 1273135 diff --git a/libuv-v1.41.1.tar.gz.sign b/libuv-v1.41.1.tar.gz.sign new file mode 100644 index 0000000..66477ed --- /dev/null +++ b/libuv-v1.41.1.tar.gz.sign @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCAAdFiEErq0KS2hnZ3UaDkrvNKJfsSgkZRQFAmDl/ikACgkQNKJfsSgk +ZRQHmw//f+Ahw0QRZaYQhcwxfvG87pTAIlbgbTX1m6USrlvgGbBSjm/C5eV/VjJ9 +Tf5kRNresN8kh+6cl8gNlGS2HJJWZHYks+4oYUOUk0XfeE8i/1RSoTEQEuSOvXjH +gjFc524EU89aVg/AN3U34mp53oMAiT01PafQVJTVsYdK211kSQN1/AW8XLBhTK15 +Oj6+yktf8vyQ/qogbE3ckvnbPtFGGs2BLdapusWLWKIq9MobYIC4Wmg9xsvgq7v5 +GTM1ZvId9WaHC+/2ZZZd8MKzfFXjr48UhVuH93oa+zixGCdOq+bYTYG7OdJ7e6xg +JssF6VDOmUiaMoP8M2Qhnvfu7cIddCGwrkVq2zRC30RHhVsgKqXOt6FCDVGE3L47 +NVIcYJssJXINIz1jSUCtG05K7ZI0Ok6+oOSy1K+pJe+mMz/Kp4X7xzXhGANJsnjI +bYbq72/WlCTDlqk/biUmMFIvQuUbl22+L78UtJML1+0+UtX4+SeCcFJKxKnoXSyF +IdKJQafoukvg1erOHqOPVEqxJQx1LC2LcIcpGonOH3dPBOb48oJ4T8j/xCnt36Zl +lzyiowTbl/DOvcXUaIsJZl9StU9NlZIDEa4pkUTbzEV+vtIPlBF6f4R+2457lNco +TsyhCGvNYVeQwqNyZaDfXSBTNvwn/seE/2uz1WEp7dnmVJSwazA= +=hLSo +-----END PGP SIGNATURE----- diff --git a/libuv.changes b/libuv.changes index 23ad153..38eff5e 100644 --- a/libuv.changes +++ b/libuv.changes @@ -1,13 +1,8 @@ ------------------------------------------------------------------- -Mon Jul 12 07:13:40 UTC 2021 - Matej Cepl +Tue Jul 13 08:28:21 UTC 2021 - Andreas Stieger -- Fix the patch metadata - -------------------------------------------------------------------- -Thu Jul 8 20:02:46 UTC 2021 - Matej Cepl - -- Add CVE-2021-22918.patch: patch libuv to fix out of bounds read - (Medium) (bsc#1187973, CVE-2021-22918) +- CVE-2021-22918: fix out of bounds read in punycode decoder + (bsc#1187973) ------------------------------------------------------------------- Tue Feb 23 22:43:09 UTC 2021 - Dirk Müller diff --git a/libuv.spec b/libuv.spec index 6828561..bd1b182 100644 --- a/libuv.spec +++ b/libuv.spec @@ -18,7 +18,7 @@ %define somajor 1 Name: libuv -Version: 1.41.0 +Version: 1.41.1 Release: 0 Summary: Asychronous I/O support library License: MIT @@ -29,9 +29,6 @@ Source1: https://dist.libuv.org/dist/v%{version}/libuv-v%{version}.tar.gz Source2: %{name}.keyring Source3: baselibs.conf Patch1: fix_tests.patch -# PATCH-FIX-UPSTREAM CVE-2021-22918.patch bsc#1187973 mcepl@suse.com -# fix OOB read in punycode decoder (CVE-2021-22918) -Patch2: CVE-2021-22918.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: libtool From 1cd9118f80a8e4beb3df96204e036aef6f9ee2d3d0d3dc27ec4fe8ca4ef0c705 Mon Sep 17 00:00:00 2001 From: Matej Cepl Date: Tue, 13 Jul 2021 11:12:02 +0000 Subject: [PATCH 4/4] Update keyring OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libuv?expand=0&rev=55 --- libuv.keyring | 142 +++++++++++++++++++++++++------------------------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/libuv.keyring b/libuv.keyring index 024bcbd..51138e1 100644 --- a/libuv.keyring +++ b/libuv.keyring @@ -1,74 +1,74 @@ -tag pubkey-cjihrig-kb -Tagger: cjihrig -Date: Tue Nov 15 10:10:29 2016 -0500 - -add cjihrig keybase GPG key ------BEGIN PGP SIGNATURE----- -Comment: GPGTools - https://gpgtools.org - -iQIcBAABCgAGBQJYKyWeAAoJEHQ0OQvb6bnFIfwP/2V9uaXz8KNVUU63cRNn/3LH -bPXnGHz0Z4o0/sebfWZBL5X/kSZjvqLArB29to3Xl5aGr1+X5N0jMe59ySKlGR6W -lk8xbqeIoa+3Z0n9zwQ1/KR7ldvKv5esQ1c6jyX1+49dUImrn28iHuNKISVM7tIN -39tUam0LhJ5D6A++4B3TwB0fNNyVNyALWCr0kT+LQQtmPFZ2zVsue+AlBcE/Xy/Z -tJ27+NmoG93q7ivg6qzq97CXZx7x64294Zh0T7Er0o8z8zsTb4o37DgmVv05ZoMe -BZ3SPY9/Ba0AhdmAcwoUtqVoJ2heoZZR0Qpp3ZJrPO9qdde8Co3Z6z315nb8ywZe -g35tMiaX5UZUDK0kumMBSAZkd251QvggJi1iN9ptBzlvKtDxuKbF9Jfb1LplAl+v -QuWzSnaiGgthZdn6KyK52xPaGl9sjx+oPhJBpGlSUyJj6WKm58odyxE7cviLMW2H -DjUkK+8+xiSa9acfi4MR+pdnJ5YdttBKTqrUDjtQ3CLbMKeiK1innHPsr5xFiI4o -NR8c53AMd0VuE9AxWJYeGWF5uTnb53gnwftb8dpOxW6klS3DVCDQoYRX3wZpyW7+ -f9o67dM8tq1deHG5G4idEQ5QRBzamiUtVZMnT+dCNwKtBtWGaTpIbtPhQNzkBqSa -gWhX93cy64e34cF6iewb -=zyNc ------END PGP SIGNATURE----- -----BEGIN PGP PUBLIC KEY BLOCK----- -Comment: GPGTools - https://gpgtools.org -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 -3TFKNHEYMHniXRH590RpVbc= -=MvSK +mQINBGDlNbwBEACcP4bRV2VZjt0gjTl5g9Eild/e9MAemDGd63U2570f+3bJJo3I +ysbIUeIikWtYvmnZPXCQz2rn7skXX2v1bHRpaP8eEyeCxtuzIJ8IFk6cS253abZw +dWuy3fEYFlW0qez9BkLuYF25nbEBi964GBpsivmnGmzlN3hctJT1n+eJgukt/NQw +twp/5aiEfZ6ACW9hrzegOefVjd5ahs+rNViME5COk+a1fkRV8FDcSz6i5nEFxKEs +wDgziOoWhK9jzVCq+5p45uNKcZnp80zdyjerFF9oVpvqwwF6lM2H+FvYx+yT/x7C +zd7iwWB4ERDtOiyqbl+MEu2ES0I/inwYve14/mEiq2CBCvEh6b3kijcahU+ND9/N +1XCMJYUp0tORGEWKAi2xPWB5u8toL2qg/Y9wG2QJ+W81qxyXw1IHAO2N35jUI+Hr +GmyFRuCxdj/T1nBTJT8CfeXEPGbAud2JU2Lb3jLoy86F+BQhLVttJiDvV/y6gJOk +6vQruqrZjdZccLnA3PQ2nUbYaBVTXJZOk2/msTyKntzOGcWdCh4CieO/bB1esz3z +iqrHnUZUZlqvN89PvakeoEH3Q23Y3cOhS/1Ln5+DyB5/DmO6lcKYjSxyvGVN2J9z +Xxc3BnStH2bTOG9//V4v97i/3+pjFkPDnRtrcP5Zxyy6bukrXCqnZpWytQARAQAB +tCBKYW1lc29uIE5hc2ggPHZ0am5hc2hAZ21haWwuY29tPokCTgQTAQgAOBYhBK6t +CktoZ2d1Gg5K7zSiX7EoJGUUBQJg5TW8AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4B +AheAAAoJEDSiX7EoJGUUK8IP/iQrQwmt7hTA1BSL4dk/xoqL4JT0TyzT60zlBxxK +6bya7D7AhBesvFW0emRsTh9hmfC9USlDWUdDgq82O+i2pd86YTNFjaEf5H+BH2r2 +fwFUr6iGJhYskLNmb4dffV93rnBaV4beXKZrwnv7WKwkCjGmBW0DaFaT/Ti/edxF +rnfGE7xj1GeBaz+JroKDNsSiWUrhNwVKahYkAV7Bhi99hVVkoJ36glu+0KlMmlgL +TlGb9NwGYLwWV0I/gCWs/J3iU0H/jLCfPFWXD66NNSrHRBT84xhK3osfMjc3n1AH +5TerHJcm23w/HfdpKq+0/3JVkH7sYnvGBOZs7tLnfZsEFDq1LCM/TIBceWbU63Pk +0ksHbVVEt2UrS4y7/ODReCVZF2m+zK8sFhSJwHbviQoMVPOVwU98DphQVn374WOu +7Bt+okOl9Dsv4FS0QLkEkOb8DTDMpKEW2gj7K8wjSD0HwCXV/Ilea5I+qP18Iio3 +fJQYpwf2hjcGQEBNGzSmrwTumFIekd0fOOSudl2L032Tj+7CVcoWtGfLPPGMr4V9 +do7C2Epgbjy6nDD1t6vXN17HwMul0FkfbFTBe7PZVOqLeu2Y5yLh1IuN4U4ckool +O0OgUHrxd8/FfXZ5WzDutfv4DD/Vhyl56+dKjK9VJF+8XOmIcxBkZNH8TrIqhhwG +JPHwuQINBGDlNbwBEACWa+KP888B8dB07B47NeSzcBrmrBbxyqHfR5aWSEptUR8t +L80xuiUyulZLE2yME2aEHyq1t18g3SkbF3H/w3IbzCIJWhJm0et/HHn3Z1xR9BVj +yh5f+ww0LLdTRaGDihLinvdw7jnUiH92aIuaFoQLINCqT8Q+E+Xbh+DI+Lo3Bshm +AbsUTCavZ+vS2slhvWwstqlcKb3LGZLhv2dlDwM0OxrH+AMT7SjrsBhqIjjoqQPq +z5HlVTt9k7MbA2pzjuYjDp0KxAuzAvXBWSeOOrTawwrRoafjScOPr4WGiOOLIWy5 +W6wFVqAqD1wxiWNS+eglYMiAhVuOA5RlrmouPR2TUxpu7DDMWEJfZ59YdGNw0SOK +8TLG+4VpPWaJ7Zi/CBFmqQLDkMvVbLS22bIAiP+JA5PT4slo/kU/sHMJSA+gaiix +YKTy0gnW4DW+cIGY2nWicpmnbAWhgX4wTRO+BrNXvBnxnufi2MRxN6DbApIQ+ib4 +IMY2SQ1Ii6UQZYbKxqeOkvY2Ez8YGnDmG3Dp1ahMCn11n9kIsrTi/3Zfox1eZuyV +yX4QNJGsxeCjpBukDA8viOrYBfHfXpaeeFZlpYxXCFwItneHTYVeCPFCQQgNyvV3 +DBy544XSjHeRXqjcEua7J1yWkwsXHdDN6f12f+3F7ZKj43AxZUm+8Vrjk5gy0QAR +AQABiQI2BBgBCAAgFiEErq0KS2hnZ3UaDkrvNKJfsSgkZRQFAmDlNbwCGyAACgkQ +NKJfsSgkZRRUmQ/9GmhPURq9WlTZdx+CSj+MUfExak4/9jFMurcdkJwS2sSNL0J7 +9OYUpF1CVx+khff0Ukds+kLyQ3+51brMi3AwJN56NusmQMAs8+JKZbkRxluj0OFe +9FwM3Oxnct4JGDrXT3Ibn9rP/1Scqwtc0PGs0GfA6qZwF0N/gfzftXxElpmRd3rR +Pr2tvA7ZoQTbXcAO88e18iFGRJBMGsleup0+LZQ6gUMafQE6pPhU1IfDnfdvzuRI +mcSMW/x+s7w9PMNJNf2by2w5ScsPUr/QK0hrHQ3xfjETX6ya8yhY/Ep50/HJXM/S +KJMfqA4PpEUHHvbmddmut0gZIRlOtMGG9yH62l2yeAtYWOvx+/yLvY3nFCeVAVg2 +7cL2+RVSGb07+A/rESfbrNUQENdYv36a7bmr2R8sLvKNTqwkCb03F6y5X/fpkaCH +tOARkkjdkApzTDGGMHUDoiG6dX6I0ir+k3RufeCMDQogQ8nUhjPLISWcG8/499HO +g7c7+cxYrGTP4NHO+3leQ6sOPmfXAVo9Dhx0lWN+fUtELL+Opfj43VPbmV4+gv3l +qwcY/Sy9zhkpi2LImhjX+lxbZ4/QSR/lgZWwzvgNiUYpjTDfzAWcVo3Ec5Wsdrz4 +7yroKTxQc2m7Z7Mc2U70v1kGLuAjnhjDJxbADZk03atwv5KDFzUXGQRZ/Eu5Ag0E +YOU1vAEQAKgYVQyATeRv/tgy7lRNlaFctEcogw0scjZsSPrdbfrP6l3XNst/e4k7 +1KgaIO8lReRjxrYOLxwZjJcm9kB9QvMVS0dimlvhvz3J1M352rs4W0x5gglx5bLQ +lV//zXFepSQq9wWQKJwIc2aBXHVUBRS62q4Eik3bimtilcJTTgfWrKlJ0tWrn8jm +EQiBqH0L6Z/7OqxMzmUBQ4/nhi6c0e9FKEDphGikBUIRhz1HM5bIYyPrAIbqorov +aht6IpkYvtRKgKauXQfCHPG4j5Tan94xiGOl6jeiVXre9ILuKwm9Ah9Eof7uFA6j +YrMP6bVOHydj7oqNOin/a2PnLhs/3fOfUOAzHeDRX6//Ccg90J9WndN+XXFOiT+l +kmsqlYGQyz3TPqewnvg9f9x45aPvh958n4yokICyg+b9UX9mDaH2kdGq6XsKz1dJ +AqOqiSNECiTZk9DHMJsJkZR1JYTVIu/isb322mFZjLTXU7wpyz565AMRUWncKdeR +IArTmNiOF1ssr3uPlzYeLNgNeQ96UB1bun4IE9scj1e+BqDdwdvfE7C2ybukLUzR +oNZYcvp5vOxcpkgVIgiNeVP6OPrRdbGMnmqKznCEW6EQgMSw0W34OR4k5iusdMR1 +PCCnlhbFljExaYUkCQF7L2DHkdWs6j35GFkkxJkrI8kK+We3o6GNABEBAAGJAjYE +GAEIACAWIQSurQpLaGdndRoOSu80ol+xKCRlFAUCYOU1vAIbDAAKCRA0ol+xKCRl +FKf9EACWsspfKjLsJ4a3ScTbxYcGn1EmmutaBjxGE6uUIwONxjnF99MnMeowjO0r +ygm13rS4vuORPPuez12Jb9Ss9tHNVrpnWDOsj4V8pN9Luj5VTiIDG/IT4hoxKgwL +WpU97MWhn9gXVtmLkHiNxps9lUEK2PUobCtPm63QQf66N02/lldUDcHOYH+O7nOl +Av27iicjSmHpDV6RPRrJLZG7X1go7y8mjJLM5ZaSfb/SBsGzn2IoLiJHNQN3Zy0s +7uiVKY3gOV1pm1MUhChSNIkBuFqITf6FL8NU4+Y+voP+ixTM/VURmbOOEZB93JpA +K26cDeyNwNnHDWIiSiPHWdzIttMOT+3YlkVprU5wwlKD3kwdiBBkEGVaWlf0QDt5 +22BuXb/Y15KQlAya/rXXrxptMPCcituphZ4sqDu1fJ8HhBv1FqjCwDqYY4J+qEdp +YWjXq1z+tY+LhZ8vVWl+LutBxghNAm5E1WQIW38S2b4O7x25lAVzAamXgCy7qPwm +J0If4dYMZHT4w3UeFJ1FUJmqnGgH0vDbB0LWPyi9BG6QNsigMN6vR8/et7S2JBYQ +1F3bdayVzpbdlM4+MsHOwsi0kNSVGskUAGf/nb65FprqZcpBNP7WQswH5AQCL+Pj +BWaDne9AhaEQzPJfq8cM6AXny1gsjiw0tvpg81oO0Wphv4zMfg== +=50iy -----END PGP PUBLIC KEY BLOCK-----