summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjsing <>2021-12-05 13:01:08 +0000
committerjsing <>2021-12-05 13:01:08 +0000
commite10c7420e88fda87d03688ffc20e3208ea5bc9db (patch)
tree342cd4115f3f974cb419d1dd123846219ade19de /src
parent697a41c3309703f7933eb0f6bc702c4002ac3129 (diff)
downloadopenbsd-e10c7420e88fda87d03688ffc20e3208ea5bc9db.tar.gz
openbsd-e10c7420e88fda87d03688ffc20e3208ea5bc9db.tar.bz2
openbsd-e10c7420e88fda87d03688ffc20e3208ea5bc9db.zip
Add initial regress for CT.
This provides test coverage for SCT encoding/decoding.
Diffstat (limited to 'src')
-rw-r--r--src/regress/lib/libcrypto/Makefile3
-rw-r--r--src/regress/lib/libcrypto/ct/Makefile19
-rw-r--r--src/regress/lib/libcrypto/ct/cttest.c355
-rw-r--r--src/regress/lib/libcrypto/ct/libressl.org.crt39
4 files changed, 415 insertions, 1 deletions
diff --git a/src/regress/lib/libcrypto/Makefile b/src/regress/lib/libcrypto/Makefile
index 6f7b024c47..1c346f6e3b 100644
--- a/src/regress/lib/libcrypto/Makefile
+++ b/src/regress/lib/libcrypto/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.41 2020/12/26 00:48:56 bluhm Exp $ 1# $OpenBSD: Makefile,v 1.42 2021/12/05 13:01:08 jsing Exp $
2 2
3SUBDIR += aead 3SUBDIR += aead
4SUBDIR += aeswrap 4SUBDIR += aeswrap
@@ -12,6 +12,7 @@ SUBDIR += cast
12SUBDIR += certs 12SUBDIR += certs
13SUBDIR += chacha 13SUBDIR += chacha
14SUBDIR += cms 14SUBDIR += cms
15SUBDIR += ct
15SUBDIR += cts128 16SUBDIR += cts128
16SUBDIR += curve25519 17SUBDIR += curve25519
17SUBDIR += des 18SUBDIR += des
diff --git a/src/regress/lib/libcrypto/ct/Makefile b/src/regress/lib/libcrypto/ct/Makefile
new file mode 100644
index 0000000000..ba93566d29
--- /dev/null
+++ b/src/regress/lib/libcrypto/ct/Makefile
@@ -0,0 +1,19 @@
1# $OpenBSD: Makefile,v 1.1 2021/12/05 13:01:08 jsing Exp $
2
3PROG= cttest
4LDADD= ${CRYPTO_INT}
5DPADD= ${LIBCRYPTO}
6
7WARNINGS= Yes
8CFLAGS+= -Wundef -Werror
9CFLAGS+= -DLIBRESSL_CRYPTO_INTERNAL -DLIBRESSL_INTERNAL
10CFLAGS+= -I$(BSDSRCDIR)/lib/libcrypto
11
12REGRESS_TARGETS= \
13 regress-cttest
14
15regress-cttest: ${PROG}
16 ./cttest \
17 ${.CURDIR}/../../libcrypto/ct/libressl.org.crt
18
19.include <bsd.regress.mk>
diff --git a/src/regress/lib/libcrypto/ct/cttest.c b/src/regress/lib/libcrypto/ct/cttest.c
new file mode 100644
index 0000000000..f4c5237e5a
--- /dev/null
+++ b/src/regress/lib/libcrypto/ct/cttest.c
@@ -0,0 +1,355 @@
1/* $OpenBSD: cttest.c,v 1.1 2021/12/05 13:01:08 jsing Exp $ */
2/*
3 * Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <err.h>
19#include <string.h>
20
21#include <openssl/err.h>
22#include <openssl/pem.h>
23#include <openssl/x509v3.h>
24
25#include "ct/ct.h"
26
27const char *test_cert_file;
28
29const int debug = 0;
30
31const uint8_t scts_asn1[] = {
32 0x04, 0x81, 0xf2, 0x00, 0xf0, 0x00, 0x77, 0x00,
33 0x29, 0x79, 0xbe, 0xf0, 0x9e, 0x39, 0x39, 0x21,
34 0xf0, 0x56, 0x73, 0x9f, 0x63, 0xa5, 0x77, 0xe5,
35 0xbe, 0x57, 0x7d, 0x9c, 0x60, 0x0a, 0xf8, 0xf9,
36 0x4d, 0x5d, 0x26, 0x5c, 0x25, 0x5d, 0xc7, 0x84,
37 0x00, 0x00, 0x01, 0x7d, 0x39, 0x51, 0x1f, 0x6f,
38 0x00, 0x00, 0x04, 0x03, 0x00, 0x48, 0x30, 0x46,
39 0x02, 0x21, 0x00, 0x93, 0xed, 0x3a, 0x65, 0x98,
40 0x9a, 0x85, 0xf0, 0x3b, 0x3c, 0x26, 0xf7, 0x52,
41 0x94, 0xd7, 0x92, 0x48, 0xc2, 0xc0, 0x64, 0xcb,
42 0x01, 0xf5, 0xec, 0xf7, 0x6d, 0x41, 0xe0, 0xbd,
43 0x28, 0x56, 0xad, 0x02, 0x21, 0x00, 0xc2, 0x4f,
44 0x92, 0xfb, 0xa0, 0xbb, 0xef, 0x55, 0x67, 0x80,
45 0x06, 0x10, 0x07, 0xe7, 0xb9, 0xb1, 0x96, 0xa7,
46 0xa9, 0x8b, 0xb2, 0xcb, 0xd3, 0x9c, 0x4e, 0x02,
47 0xe8, 0xdb, 0x24, 0x65, 0x1e, 0xc8, 0x00, 0x75,
48 0x00, 0x6f, 0x53, 0x76, 0xac, 0x31, 0xf0, 0x31,
49 0x19, 0xd8, 0x99, 0x00, 0xa4, 0x51, 0x15, 0xff,
50 0x77, 0x15, 0x1c, 0x11, 0xd9, 0x02, 0xc1, 0x00,
51 0x29, 0x06, 0x8d, 0xb2, 0x08, 0x9a, 0x37, 0xd9,
52 0x13, 0x00, 0x00, 0x01, 0x7d, 0x39, 0x51, 0x20,
53 0x3b, 0x00, 0x00, 0x04, 0x03, 0x00, 0x46, 0x30,
54 0x44, 0x02, 0x20, 0x26, 0xc9, 0x12, 0x28, 0x70,
55 0x2d, 0x15, 0x05, 0xa7, 0xa2, 0xea, 0x12, 0x1a,
56 0xff, 0x39, 0x36, 0x5f, 0x93, 0xdf, 0x83, 0x36,
57 0x5f, 0xed, 0x07, 0x38, 0xb8, 0x0a, 0x40, 0xe1,
58 0x8d, 0xb9, 0xfa, 0x02, 0x20, 0x61, 0xae, 0x2b,
59 0x86, 0xbd, 0x8e, 0x86, 0x65, 0x2b, 0xfb, 0x63,
60 0xe1, 0xda, 0x77, 0xb3, 0xf3, 0xc5, 0x2a, 0x32,
61 0xb8, 0x23, 0x1e, 0x7e, 0xfa, 0x7d, 0x83, 0xa5,
62 0x49, 0x00, 0xc4, 0x57, 0xb8,
63};
64
65const uint8_t sct_signature1[] = {
66 0x30, 0x46, 0x02, 0x21, 0x00, 0x93, 0xed, 0x3a,
67 0x65, 0x98, 0x9a, 0x85, 0xf0, 0x3b, 0x3c, 0x26,
68 0xf7, 0x52, 0x94, 0xd7, 0x92, 0x48, 0xc2, 0xc0,
69 0x64, 0xcb, 0x01, 0xf5, 0xec, 0xf7, 0x6d, 0x41,
70 0xe0, 0xbd, 0x28, 0x56, 0xad, 0x02, 0x21, 0x00,
71 0xc2, 0x4f, 0x92, 0xfb, 0xa0, 0xbb, 0xef, 0x55,
72 0x67, 0x80, 0x06, 0x10, 0x07, 0xe7, 0xb9, 0xb1,
73 0x96, 0xa7, 0xa9, 0x8b, 0xb2, 0xcb, 0xd3, 0x9c,
74 0x4e, 0x02, 0xe8, 0xdb, 0x24, 0x65, 0x1e, 0xc8
75};
76
77const uint8_t sct_signature2[] = {
78 0x30, 0x44, 0x02, 0x20, 0x26, 0xc9, 0x12, 0x28,
79 0x70, 0x2d, 0x15, 0x05, 0xa7, 0xa2, 0xea, 0x12,
80 0x1a, 0xff, 0x39, 0x36, 0x5f, 0x93, 0xdf, 0x83,
81 0x36, 0x5f, 0xed, 0x07, 0x38, 0xb8, 0x0a, 0x40,
82 0xe1, 0x8d, 0xb9, 0xfa, 0x02, 0x20, 0x61, 0xae,
83 0x2b, 0x86, 0xbd, 0x8e, 0x86, 0x65, 0x2b, 0xfb,
84 0x63, 0xe1, 0xda, 0x77, 0xb3, 0xf3, 0xc5, 0x2a,
85 0x32, 0xb8, 0x23, 0x1e, 0x7e, 0xfa, 0x7d, 0x83,
86 0xa5, 0x49, 0x00, 0xc4, 0x57, 0xb8
87};
88
89struct sct_data {
90 uint8_t version;
91 uint8_t log_id[32];
92 uint64_t timestamp;
93 size_t extensions_len;
94 int signature_nid;
95 const uint8_t *signature;
96 size_t signature_len;
97};
98
99const struct sct_data sct_test_data[] = {
100 {
101 .version = 0,
102 .log_id = {
103 0x29, 0x79, 0xbe, 0xf0, 0x9e, 0x39, 0x39, 0x21,
104 0xf0, 0x56, 0x73, 0x9f, 0x63, 0xa5, 0x77, 0xe5,
105 0xbe, 0x57, 0x7d, 0x9c, 0x60, 0x0a, 0xf8, 0xf9,
106 0x4d, 0x5d, 0x26, 0x5c, 0x25, 0x5d, 0xc7, 0x84,
107 },
108 .timestamp = 1637344157551,
109 .extensions_len = 0,
110 .signature_nid = NID_ecdsa_with_SHA256,
111 .signature = sct_signature1,
112 .signature_len = sizeof(sct_signature1),
113 },
114 {
115 .version = 0,
116 .log_id = {
117 0x6f, 0x53, 0x76, 0xac, 0x31, 0xf0, 0x31, 0x19,
118 0xd8, 0x99, 0x00, 0xa4, 0x51, 0x15, 0xff, 0x77,
119 0x15, 0x1c, 0x11, 0xd9, 0x02, 0xc1, 0x00, 0x29,
120 0x06, 0x8d, 0xb2, 0x08, 0x9a, 0x37, 0xd9, 0x13
121 },
122 .timestamp = 1637344157755,
123 .extensions_len = 0,
124 .signature_nid = NID_ecdsa_with_SHA256,
125 .signature = sct_signature2,
126 .signature_len = sizeof(sct_signature2),
127 },
128};
129
130#define N_SCT_TEST_DATA (sizeof(sct_test_data) / sizeof(*sct_test_data))
131
132static void
133hexdump(const unsigned char *buf, size_t len)
134{
135 size_t i;
136
137 for (i = 1; i <= len; i++)
138 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
139
140 if (len % 8)
141 fprintf(stderr, "\n");
142}
143
144static void
145cert_from_file(const char *filename, X509 **cert)
146{
147 BIO *bio = NULL;
148 X509 *x;
149
150 if ((bio = BIO_new_file(filename, "r")) == NULL) {
151 ERR_print_errors_fp(stderr);
152 errx(1, "failed to create bio");
153 }
154 if ((x = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL)
155 errx(1, "failed to read PEM");
156
157 *cert = x;
158
159 BIO_free(bio);
160}
161
162static int
163ct_compare_test_scts(STACK_OF(SCT) *scts)
164{
165 const struct sct_data *sdt;
166 BIO *bio_err = NULL;
167 SCT *sct;
168 uint8_t *data;
169 size_t len;
170 int i;
171 int ret = 0;
172
173 bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
174
175 if (sk_SCT_num(scts) != N_SCT_TEST_DATA) {
176 fprintf(stderr, "FAIL: got %d SCTS, want %zu\n",
177 sk_SCT_num(scts), N_SCT_TEST_DATA);
178 goto failure;
179 }
180
181 for (i = 0; i < sk_SCT_num(scts); i++) {
182 sct = sk_SCT_value(scts, i);
183 sdt = &sct_test_data[i];
184
185 if (debug > 0) {
186 SCT_print(sct, bio_err, 0, NULL);
187 BIO_printf(bio_err, "\n");
188 }
189
190 if (SCT_get_version(sct) != sdt->version) {
191 fprintf(stderr, "FAIL: SCT %d - got version %u, "
192 "want %u\n", i, SCT_get_version(sct), sdt->version);
193 goto failure;
194 }
195 len = SCT_get0_log_id(sct, &data);
196 if (len != sizeof(sdt->log_id)) {
197 fprintf(stderr, "FAIL: SCT %d - got version %u, "
198 "want %u\n", i, SCT_get_version(sct), sdt->version);
199 goto failure;
200 }
201 if (memcmp(data, sdt->log_id, len) != 0) {
202 fprintf(stderr, "FAIL: SCT %d - log ID differs\n", i);
203 fprintf(stderr, "Got:\n");
204 hexdump(data, len);
205 fprintf(stderr, "Want:\n");
206 hexdump(sdt->log_id, sizeof(sdt->log_id));
207 goto failure;
208 }
209 if (SCT_get_timestamp(sct) != sdt->timestamp) {
210 fprintf(stderr, "FAIL: SCT %d - got timestamp %llu, "
211 "want %llu\n", i, SCT_get_timestamp(sct),
212 sdt->timestamp);
213 goto failure;
214 }
215 if (SCT_get_signature_nid(sct) != sdt->signature_nid) {
216 fprintf(stderr, "FAIL: SCT %d - got signature_nid %d, "
217 "want %d\n", i, SCT_get_signature_nid(sct),
218 sdt->signature_nid);
219 goto failure;
220 }
221 len = SCT_get0_extensions(sct, &data);
222 if (len != sdt->extensions_len) {
223 fprintf(stderr, "FAIL: SCT %d - got extensions with "
224 "length %zu, want %zu\n", i, len,
225 sdt->extensions_len);
226 goto failure;
227 }
228 len = SCT_get0_signature(sct, &data);
229 if (len != sdt->signature_len) {
230 fprintf(stderr, "FAIL: SCT %d - got signature with "
231 "length %zu, want %zu\n", i, len,
232 sdt->signature_len);
233 goto failure;
234 }
235 if (memcmp(data, sdt->signature, len) != 0) {
236 fprintf(stderr, "FAIL: SCT %d - signature differs\n",
237 i);
238 fprintf(stderr, "Got:\n");
239 hexdump(data, len);
240 fprintf(stderr, "Want:\n");
241 hexdump(sdt->signature, sdt->signature_len);
242 goto failure;
243 }
244 }
245
246 ret = 1;
247
248 failure:
249 BIO_free(bio_err);
250
251 return ret;
252}
253
254static int
255ct_cert_test(void)
256{
257 X509 *cert = NULL;
258 X509_EXTENSION *ext;
259 STACK_OF(SCT) *scts = NULL;
260 int idx;
261 int failed = 1;
262
263 cert_from_file(test_cert_file, &cert);
264
265 if ((idx = X509_get_ext_by_NID(cert, NID_ct_precert_scts, -1)) == -1) {
266 fprintf(stderr, "FAIL: failed to find SCTs\n");
267 goto failure;
268 }
269 if ((ext = X509_get_ext(cert, idx)) == NULL) {
270 fprintf(stderr, "FAIL: failed to get SCT extension\n");
271 goto failure;
272 }
273 if ((scts = X509V3_EXT_d2i(ext)) == NULL) {
274 fprintf(stderr, "FAIL: failed to decode SCTs\n");
275 ERR_print_errors_fp(stderr);
276 goto failure;
277 }
278
279 if (!ct_compare_test_scts(scts))
280 goto failure;
281
282 failed = 0;
283
284 failure:
285 SCT_LIST_free(scts);
286 X509_free(cert);
287
288 return failed;
289}
290
291static int
292ct_sct_test(void)
293{
294 STACK_OF(SCT) *scts = NULL;
295 const uint8_t *p;
296 uint8_t *data = NULL;
297 int len;
298 int failed = 1;
299
300 p = scts_asn1;
301 if ((scts = d2i_SCT_LIST(NULL, &p, sizeof(scts_asn1))) == NULL) {
302 fprintf(stderr, "FAIL: failed to decode SCTS from ASN.1\n");
303 ERR_print_errors_fp(stderr);
304 goto failure;
305 }
306
307 if (!ct_compare_test_scts(scts))
308 goto failure;
309
310 data = NULL;
311 if ((len = i2d_SCT_LIST(scts, &data)) <= 0) {
312 fprintf(stderr, "FAIL: failed to encode SCTS to ASN.1\n");
313 ERR_print_errors_fp(stderr);
314 goto failure;
315 }
316 if (len != sizeof(scts_asn1)) {
317 fprintf(stderr, "FAIL: ASN.1 length differs - got %d, want "
318 "%zu\n", len, sizeof(scts_asn1));
319 goto failure;
320 }
321 if (memcmp(data, scts_asn1, len) != 0) {
322 fprintf(stderr, "FAIL: ASN.1 for SCTS differs\n");
323 fprintf(stderr, "Got:\n");
324 hexdump(data, len);
325 fprintf(stderr, "Want:\n");
326 hexdump(scts_asn1, sizeof(scts_asn1));
327 goto failure;
328 }
329
330 failed = 0;
331
332 failure:
333 SCT_LIST_free(scts);
334 free(data);
335
336 return failed;
337}
338
339int
340main(int argc, char **argv)
341{
342 int failed = 0;
343
344 if (argc != 2) {
345 fprintf(stderr, "usage: %s certfile\n", argv[0]);
346 exit(1);
347 }
348
349 test_cert_file = argv[1];
350
351 failed |= ct_cert_test();
352 failed |= ct_sct_test();
353
354 return (failed);
355}
diff --git a/src/regress/lib/libcrypto/ct/libressl.org.crt b/src/regress/lib/libcrypto/ct/libressl.org.crt
new file mode 100644
index 0000000000..4259548797
--- /dev/null
+++ b/src/regress/lib/libcrypto/ct/libressl.org.crt
@@ -0,0 +1,39 @@
1-----BEGIN CERTIFICATE-----
2MIIG3DCCBcSgAwIBAgISA7cdK3Ainj5sW/nVzBz0QTKzMA0GCSqGSIb3DQEBCwUA
3MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
4EwJSMzAeFw0yMTExMTkxNjQ5MTdaFw0yMjAyMTcxNjQ5MTZaMBoxGDAWBgNVBAMT
5D3d3dy5vcGVuYnNkLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
6AONf/xu/gf0QoQT8nqjEpfUQaaygDkhPBw5mswqAU0fOMg9ZaZT7Nx8g9qAH0mgi
76GNd/y7I2fMM7vvkFk/NQn8pu51EMLJ7aNKv6o4ThJYzyvPikdZW+RcdIdt185wJ
8ws7MNq2kaZ0gJRXsIE8haE0iDB9nPRtJ8HAbhxOeCRczrALjvJBI6blg/9TBI+sd
9zvA8yEOelGRox6AikFSP6JDmSmzoBgVSTXq9riKKQeK1j+Wa6vBYmsN2LFmbWPYN
101TbJk1C37E7Q3CTCkHt+CZNcAqBFIovClb9jmR+0QU3NQnTSqeXnyKyOe2RtYHOx
113oRs9A8bsRPybvh6zYf33Od2QbFwCGOS1H9sRux1LJEeZlCFDuccRpU3X9f7IO1X
12n5cYr9eIUFIniTAfiksGvL7do2nYNmX/ujdraX7ttPmJZMVVDBjct9g4KGC7aMvB
13CSc695JcLA7RJuJ8qKXcKxINavIpSHsFPobLDPwl43xxihCMQpMfb8Eg3fi5CQcu
14FjdljawMkFeAiVv4iI1rbpWhpZeOGQTKxxjagWd9UNJW9PQxqh+x63I2zO47+W6r
15jSbk2SicUrYTK7F1W+4HRPbA4e5U+hFk881nngnG0mB0D3sinqzxWIyM5DWTDuVp
16ePBJQq3odt2/ityGRY0FcO35mlYkuB26/7Dfq/KmI4olAgMBAAGjggMCMIIC/jAO
17BgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwG
18A1UdEwEB/wQCMAAwHQYDVR0OBBYEFIQBXV9xwD2xyW1oHNhKs8qxdQFtMB8GA1Ud
19IwQYMBaAFBQusxe3WFbLrlAJQOYfr52LFMLGMFUGCCsGAQUFBwEBBEkwRzAhBggr
20BgEFBQcwAYYVaHR0cDovL3IzLm8ubGVuY3Iub3JnMCIGCCsGAQUFBzAChhZodHRw
21Oi8vcjMuaS5sZW5jci5vcmcvMIHRBgNVHREEgckwgcaCD2Z0cC5vcGVuYnNkLm9y
22Z4IMbGlicmVzc2wub3JnggtvcGVuYnNkLm9yZ4IMb3BlbmlrZWQub3JnggtvcGVu
23c3NoLmNvbYIPcnBraS1jbGllbnQub3JnghB3d3cubGlicmVzc2wub3Jngg93d3cu
24b3BlbmJzZC5vcmeCEHd3dy5vcGVuaWtlZC5vcmeCEXd3dy5vcGVucnN5bmMub3Jn
25gg93d3cub3BlbnNzaC5jb22CE3d3dy5ycGtpLWNsaWVudC5vcmcwTAYDVR0gBEUw
26QzAIBgZngQwBAgEwNwYLKwYBBAGC3xMBAQEwKDAmBggrBgEFBQcCARYaaHR0cDov
27L2Nwcy5sZXRzZW5jcnlwdC5vcmcwggEEBgorBgEEAdZ5AgQCBIH1BIHyAPAAdwAp
28eb7wnjk5IfBWc59jpXflvld9nGAK+PlNXSZcJV3HhAAAAX05UR9vAAAEAwBIMEYC
29IQCT7TplmJqF8Ds8JvdSlNeSSMLAZMsB9ez3bUHgvShWrQIhAMJPkvugu+9VZ4AG
30EAfnubGWp6mLssvTnE4C6NskZR7IAHUAb1N2rDHwMRnYmQCkURX/dxUcEdkCwQAp
31Bo2yCJo32RMAAAF9OVEgOwAABAMARjBEAiAmyRIocC0VBaei6hIa/zk2X5PfgzZf
327Qc4uApA4Y25+gIgYa4rhr2OhmUr+2Ph2nez88UqMrgjHn76fYOlSQDEV7gwDQYJ
33KoZIhvcNAQELBQADggEBADMSIRTpbJOdHjy/ju4TPXmc9H7mhyXwXH382FKnkC+T
34VaqPsJL7Mve7Lgr96tzRGVU8hLF3oRXpZVv6qSNmV3ULyCDVG8JoYDZbJV/v7ziU
35RITnWsraI8BYtxgDx6YU8ISbWU0Kh8REdi+mQ49FWmmPaJO9XyvkvG2BD2e+t1Zh
368O78YFFhtQLuwTtOYa4WKOzWVXD8t2vZBGecJ+APnhcPGS6NQ9qqpKdDwmm0qYG7
37gafHxcWd2k2phmqbp7R3qqY/VP21VyUXCXoGAp+IaqJRunyEmTBAUyB6LkFBfQpc
38y0LH4LFzj5ouo5HtlZQRR5z3MN9WmwAej1gNpC/j688=
39-----END CERTIFICATE-----