xref: /openbsd-src/regress/lib/libcrypto/pem/x509_info.c (revision 9bc7f6d1f2577ed5495a7a30b1e0fce5553dabbc)
1 /*	$OpenBSD: x509_info.c,v 1.2 2020/09/18 14:41:04 tb Exp $	*/
2 /*
3  * Copyright (c) 2020 Ingo Schwarze <schwarze@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/bio.h>
22 #include <openssl/err.h>
23 #include <openssl/pem.h>
24 #include <openssl/x509.h>
25 
26 static const char *const bogus_pem = "\
27 -----BEGIN BOGUS----- \n\
28 -----END BOGUS----- \n\
29 ";
30 
31 static const char *const cert_pem = "\
32 -----BEGIN CERTIFICATE----- \n\
33 MIIDpTCCAo2gAwIBAgIJAPYm3GvOr5eTMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV \n\
34 BAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVT \n\
35 VElORyBQVVJQT1NFUyBPTkxZMSUwIwYDVQQDDBxPcGVuU1NMIFRlc3QgSW50ZXJt \n\
36 ZWRpYXRlIENBMB4XDTE0MDUyNDE0NDUxMVoXDTI0MDQwMTE0NDUxMVowZDELMAkG \n\
37 A1UEBhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBU \n\
38 RVNUSU5HIFBVUlBPU0VTIE9OTFkxGTAXBgNVBAMMEFRlc3QgQ2xpZW50IENlcnQw \n\
39 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0ranbHRLcLVqN+0BzcZpY \n\
40 +yOLqxzDWT1LD9eW1stC4NzXX9/DCtSIVyN7YIHdGLrIPr64IDdXXaMRzgZ2rOKs \n\
41 lmHCAiFpO/ja99gGCJRxH0xwQatqAULfJVHeUhs7OEGOZc2nWifjqKvGfNTilP7D \n\
42 nwi69ipQFq9oS19FmhwVHk2wg7KZGHI1qDyG04UrfCZMRitvS9+UVhPpIPjuiBi2 \n\
43 x3/FZIpL5gXJvvFK6xHY63oq2asyzBATntBgnP4qJFWWcvRx24wF1PnZabxuVoL2 \n\
44 bPnQ/KvONDrw3IdqkKhYNTul7jEcu3OlcZIMw+7DiaKJLAzKb/bBF5gm/pwW6As9 \n\
45 AgMBAAGjTjBMMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgXgMCwGCWCGSAGG \n\
46 +EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0B \n\
47 AQUFAAOCAQEAJzA4KTjkjXGSC4He63yX9Br0DneGBzjAwc1H6f72uqnCs8m7jgkE \n\
48 PQJFdTzQUKh97QPUuayZ2gl8XHagg+iWGy60Kw37gQ0+lumCN2sllvifhHU9R03H \n\
49 bWtS4kue+yQjMbrzf3zWygMDgwvFOUAIgBpH9qGc+CdNu97INTYd0Mvz51vLlxRn \n\
50 sC5aBYCWaZFnw3lWYxf9eVFRy9U+DkYFqX0LpmbDtcKP7AZGE6ZwSzaim+Cnoz1u \n\
51 Cgn+QmpFXgJKMFIZ82iSZISn+JkCCGxctZX1lMvai4Wi8Y0HxW9FTFZ6KBNwwE4B \n\
52 zjbN/ehBkgLlW/DWfi44DvwUHmuU6QP3cw== \n\
53 -----END CERTIFICATE----- \n\
54 ";
55 
56 int
main(void)57 main(void)
58 {
59 	BIO			*bp;
60 	STACK_OF(X509_INFO)	*skin, *skout;
61 	X509_INFO		*info0, *info1;
62 	const char		*errdata;
63 	unsigned long		 errcode;
64 	int			 errcount, errflags, num;
65 
66 	errcount = 0;
67 	if ((skin = sk_X509_INFO_new_null()) == NULL)
68 		err(1, "sk_X509_INFO_new_null");
69 
70 	/* Test with empty input. */
71 
72 	if ((bp = BIO_new_mem_buf("", 0)) == NULL)
73 		err(1, "BIO_new_mem_buf(empty)");
74 	if ((skout = PEM_X509_INFO_read_bio(bp, skin, NULL, NULL)) == NULL)
75 		err(1, "empty input: %s",
76 		    ERR_error_string(ERR_get_error(), NULL));
77 	if (skout != skin)
78 		errx(1, "empty input did not return the same stack");
79 	skout = NULL;
80 	if ((num = sk_X509_INFO_num(skin)) != 0)
81 		errx(1, "empty input created %d X509_INFO objects", num);
82 	BIO_free(bp);
83 
84 	/* Test with bogus input. */
85 
86 	if ((bp = BIO_new_mem_buf(bogus_pem, strlen(bogus_pem))) == NULL)
87 		err(1, "BIO_new_mem_buf(bogus_pem)");
88 	if ((skout = PEM_X509_INFO_read_bio(bp, skin, NULL, NULL)) != NULL)
89 		errx(1, "success with bogus input on first try");
90 	if ((num = sk_X509_INFO_num(skin)) != 0)
91 		errx(1, "bogus input created %d X509_INFO objects", num);
92 	if (BIO_reset(bp) != 1)
93 		errx(1, "BIO_reset");
94 
95 	/* Populate stack and test again with bogus input. */
96 
97 	if ((info0 = X509_INFO_new()) == NULL)
98 		err(1, "X509_INFO_new");
99 	info0->references = 2;  /* X509_INFO_up_ref(3) doesn't exist. */
100 	if (sk_X509_INFO_push(skin, info0) != 1)
101 		err(1, "sk_X509_INFO_push");
102 	if ((skout = PEM_X509_INFO_read_bio(bp, skin, NULL, NULL)) != NULL)
103 		errx(1, "success with bogus input on second try");
104 	if ((num = sk_X509_INFO_num(skin)) != 1)
105 		errx(1, "bogus input changed stack size from 1 to %d", num);
106 	if (sk_X509_INFO_value(skin, 0) != info0)
107 		errx(1, "bogus input changed stack content");
108 	if (info0->references != 2) {
109 		warnx("bogus input changed ref count from 2 to %d",
110 		    info0->references);
111 		info0->references = 2;
112 		errcount++;
113 	}
114 	BIO_free(bp);
115 
116 	/* Use a real certificate object. */
117 
118 	if ((bp = BIO_new_mem_buf(cert_pem, strlen(cert_pem))) == NULL)
119 		err(1, "BIO_new_mem_buf(cert_pem)");
120 	if ((skout = PEM_X509_INFO_read_bio(bp, skin, NULL, NULL)) == NULL) {
121 		errdata = NULL;
122 		errflags = 0;
123 		while ((errcode = ERR_get_error_line_data(NULL, NULL,
124 		    &errdata, &errflags)) != 0)
125 			if (errdata != NULL && (errflags & ERR_TXT_STRING))
126 				warnx("%s --- %s",
127 				    ERR_error_string(errcode, NULL),
128 				    errdata);
129 			else
130 				warnx("%s", ERR_error_string(errcode, NULL));
131 		err(1, "real input: parsing failed");
132 	}
133 	if (skout != skin)
134 		errx(1, "real input did not return the same stack");
135 	skout = NULL;
136 	if ((num = sk_X509_INFO_num(skin)) != 2)
137 		errx(1, "real input changed stack size from 1 to %d", num);
138 	if (sk_X509_INFO_value(skin, 0) != info0)
139 		errx(1, "real input changed stack content");
140 	if (info0->references != 2)
141 		errx(1, "real input changed ref count from 2 to %d",
142 		    info0->references);
143         info1 = sk_X509_INFO_pop(skin);
144 	if (info1->x509 == NULL)
145 		errx(1, "real input did not create a certificate");
146 	X509_INFO_free(info1);
147 	info1 = NULL;
148 	BIO_free(bp);
149 
150 	/* Two real certificates followed by bogus input. */
151 
152 	if ((bp = BIO_new(BIO_s_mem())) == NULL)
153 		err(1, "BIO_new");
154 	if (BIO_puts(bp, cert_pem) != strlen(cert_pem))
155 		err(1, "BIO_puts(cert_pem) first copy");
156 	if (BIO_puts(bp, cert_pem) != strlen(cert_pem))
157 		err(1, "BIO_puts(cert_pem) second copy");
158 	if (BIO_puts(bp, bogus_pem) != strlen(bogus_pem))
159 		err(1, "BIO_puts(bogus_pem)");
160 	if ((skout = PEM_X509_INFO_read_bio(bp, skin, NULL, NULL)) != NULL)
161 		errx(1, "success with real + bogus input");
162 	if ((num = sk_X509_INFO_num(skin)) != 1) {
163 		warnx("real + bogus input changed stack size from 1 to %d",
164 		    num);
165 		while (sk_X509_INFO_num(skin) > 1)
166 			(void)sk_X509_INFO_pop(skin);
167 		errcount++;
168 	}
169 	if (sk_X509_INFO_value(skin, 0) != info0)
170 		errx(1, "real + bogus input changed stack content");
171 	if (info0->references != 2) {
172 		warnx("real + bogus input changed ref count from 2 to %d",
173 		    info0->references);
174 		errcount++;
175 	}
176 	BIO_free(bp);
177 	info0->references = 1;
178 	X509_INFO_free(info0);
179 	sk_X509_INFO_free(skin);
180 
181 	if (errcount > 0)
182 		errx(1, "%d errors detected", errcount);
183 	return 0;
184 }
185