xref: /openbsd-src/regress/lib/libcrypto/pkcs7/pkcs7test.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: pkcs7test.c,v 1.3 2014/11/26 05:48:00 bcook Exp $	*/
2 /*
3  * Copyright (c) 2014 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 <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 
23 #include <openssl/bio.h>
24 #include <openssl/err.h>
25 #include <openssl/evp.h>
26 #include <openssl/pem.h>
27 #include <openssl/pkcs7.h>
28 #include <openssl/x509.h>
29 
30 const char certificate[] = "\
31 -----BEGIN CERTIFICATE----- \n\
32 MIIDpTCCAo2gAwIBAgIJAPYm3GvOr5eTMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV \n\
33 BAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVT \n\
34 VElORyBQVVJQT1NFUyBPTkxZMSUwIwYDVQQDDBxPcGVuU1NMIFRlc3QgSW50ZXJt \n\
35 ZWRpYXRlIENBMB4XDTE0MDUyNDE0NDUxMVoXDTI0MDQwMTE0NDUxMVowZDELMAkG \n\
36 A1UEBhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBU \n\
37 RVNUSU5HIFBVUlBPU0VTIE9OTFkxGTAXBgNVBAMMEFRlc3QgQ2xpZW50IENlcnQw \n\
38 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0ranbHRLcLVqN+0BzcZpY \n\
39 +yOLqxzDWT1LD9eW1stC4NzXX9/DCtSIVyN7YIHdGLrIPr64IDdXXaMRzgZ2rOKs \n\
40 lmHCAiFpO/ja99gGCJRxH0xwQatqAULfJVHeUhs7OEGOZc2nWifjqKvGfNTilP7D \n\
41 nwi69ipQFq9oS19FmhwVHk2wg7KZGHI1qDyG04UrfCZMRitvS9+UVhPpIPjuiBi2 \n\
42 x3/FZIpL5gXJvvFK6xHY63oq2asyzBATntBgnP4qJFWWcvRx24wF1PnZabxuVoL2 \n\
43 bPnQ/KvONDrw3IdqkKhYNTul7jEcu3OlcZIMw+7DiaKJLAzKb/bBF5gm/pwW6As9 \n\
44 AgMBAAGjTjBMMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgXgMCwGCWCGSAGG \n\
45 +EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0B \n\
46 AQUFAAOCAQEAJzA4KTjkjXGSC4He63yX9Br0DneGBzjAwc1H6f72uqnCs8m7jgkE \n\
47 PQJFdTzQUKh97QPUuayZ2gl8XHagg+iWGy60Kw37gQ0+lumCN2sllvifhHU9R03H \n\
48 bWtS4kue+yQjMbrzf3zWygMDgwvFOUAIgBpH9qGc+CdNu97INTYd0Mvz51vLlxRn \n\
49 sC5aBYCWaZFnw3lWYxf9eVFRy9U+DkYFqX0LpmbDtcKP7AZGE6ZwSzaim+Cnoz1u \n\
50 Cgn+QmpFXgJKMFIZ82iSZISn+JkCCGxctZX1lMvai4Wi8Y0HxW9FTFZ6KBNwwE4B \n\
51 zjbN/ehBkgLlW/DWfi44DvwUHmuU6QP3cw== \n\
52 -----END CERTIFICATE----- \n\
53 ";
54 
55 const char private_key[] = "\
56 -----BEGIN RSA PRIVATE KEY----- \n\
57 MIIEpQIBAAKCAQEAtK2p2x0S3C1ajftAc3GaWPsji6scw1k9Sw/XltbLQuDc11/f \n\
58 wwrUiFcje2CB3Ri6yD6+uCA3V12jEc4GdqzirJZhwgIhaTv42vfYBgiUcR9McEGr \n\
59 agFC3yVR3lIbOzhBjmXNp1on46irxnzU4pT+w58IuvYqUBavaEtfRZocFR5NsIOy \n\
60 mRhyNag8htOFK3wmTEYrb0vflFYT6SD47ogYtsd/xWSKS+YFyb7xSusR2Ot6Ktmr \n\
61 MswQE57QYJz+KiRVlnL0cduMBdT52Wm8blaC9mz50PyrzjQ68NyHapCoWDU7pe4x \n\
62 HLtzpXGSDMPuw4miiSwMym/2wReYJv6cFugLPQIDAQABAoIBAAZOyc9MhIwLSU4L \n\
63 p4RgQvM4UVVe8/Id+3XTZ8NsXExJbWxXfIhiqGjaIfL8u4vsgRjcl+v1s/jo2/iT \n\
64 KMab4o4D8gXD7UavQVDjtjb/ta79WL3SjRl2Uc9YjjMkyq6WmDNQeo2NKDdafCTB \n\
65 1uzSJtLNipB8Z53ELPuHJhxX9QMHrMnuha49riQgXZ7buP9iQrHJFhImBjSzbxJx \n\
66 L+TI6rkyLSf9Wi0Pd3L27Ob3QWNfNRYNSeTE+08eSRChkur5W0RuXAcuAICdQlCl \n\
67 LBvWO/LmmvbzCqiDcgy/TliSb6CGGwgiNG7LJZmlkYNj8laGwalNlYZs3UrVv6NO \n\
68 Br2loAECgYEA2kvCvPGj0Dg/6g7WhXDvAkEbcaL1tSeCxBbNH+6HS2UWMWvyTtCn \n\
69 /bbD519QIdkvayy1QjEf32GV/UjUVmlULMLBcDy0DGjtL3+XpIhLKWDNxN1v1/ai \n\
70 1oz23ZJCOgnk6K4qtFtlRS1XtynjA+rBetvYvLP9SKeFrnpzCgaA2r0CgYEA0+KX \n\
71 1ACXDTNH5ySX3kMjSS9xdINf+OOw4CvPHFwbtc9aqk2HePlEsBTz5I/W3rKwXva3 \n\
72 NqZ/bRqVVeZB/hHKFywgdUQk2Uc5z/S7Lw70/w1HubNTXGU06Ngb6zOFAo/o/TwZ \n\
73 zTP1BMIKSOB6PAZPS3l+aLO4FRIRotfFhgRHOoECgYEAmiZbqt8cJaJDB/5YYDzC \n\
74 mp3tSk6gIb936Q6M5VqkMYp9pIKsxhk0N8aDCnTU+kIK6SzWBpr3/d9Ecmqmfyq7 \n\
75 5SvWO3KyVf0WWK9KH0abhOm2BKm2HBQvI0DB5u8sUx2/hsvOnjPYDISbZ11t0MtK \n\
76 u35Zy89yMYcSsIYJjG/ROCUCgYEAgI2P9G5PNxEP5OtMwOsW84Y3Xat/hPAQFlI+ \n\
77 HES+AzbFGWJkeT8zL2nm95tVkFP1sggZ7Kxjz3w7cpx7GX0NkbWSE9O+T51pNASV \n\
78 tN1sQ3p5M+/a+cnlqgfEGJVvc7iAcXQPa3LEi5h2yPR49QYXAgG6cifn3dDSpmwn \n\
79 SUI7PQECgYEApGCIIpSRPLAEHTGmP87RBL1smurhwmy2s/pghkvUkWehtxg0sGHh \n\
80 kuaqDWcskogv+QC0sVdytiLSz8G0DwcEcsHK1Fkyb8A+ayiw6jWJDo2m9+IF4Fww \n\
81 1Te6jFPYDESnbhq7+TLGgHGhtwcu5cnb4vSuYXGXKupZGzoLOBbv1Zw= \n\
82 -----END RSA PRIVATE KEY----- \n\
83 ";
84 
85 const char message[] = "\
86 Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do \r\n\
87 eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut   \r\n\
88 enim ad minim veniam, quis nostrud exercitation ullamco laboris  \r\n\
89 nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor   \r\n\
90 in reprehenderit in voluptate velit esse cillum dolore eu fugiat \r\n\
91 nulla pariatur. Excepteur sint occaecat cupidatat non proident,  \r\n\
92 sunt in culpa qui officia deserunt mollit anim id est laborum.   \r\n\
93 ";
94 
95 static int
96 x509_store_callback(int ok, X509_STORE_CTX *ctx)
97 {
98 	/* Pretend the certificate issuer is valid... */
99 	return 1;
100 }
101 
102 static void
103 fatal(const char *msg)
104 {
105 	warnx("%s", msg);
106 	ERR_print_errors(BIO_new_fd(STDERR_FILENO, 0));
107 	exit(1);
108 }
109 
110 static void
111 message_compare(const char *out, size_t len)
112 {
113 	if (len != sizeof(message)) {
114 		fprintf(stderr, "FAILURE: length mismatch (%zu != %zu)\n",
115 		    len, sizeof(message));
116 		exit(1);
117 	}
118 	if (memcmp(out, message, len) != 0) {
119 		fprintf(stderr, "FAILURE: message mismatch\n");
120 		fprintf(stderr, "Got:\n%s\n", out);
121 		fprintf(stderr, "Want:\n%s\n", message);
122 		exit(1);
123 	}
124 }
125 
126 int
127 main(int argc, char **argv)
128 {
129 	BIO *bio_in, *bio_content, *bio_out, *bio_cert, *bio_pkey;
130 	STACK_OF(X509) *certs;
131 	const EVP_CIPHER *cipher;
132 	EVP_PKEY *pkey;
133 	X509_STORE *store;
134 	X509 *cert;
135 	PKCS7 *p7;
136 	size_t len;
137 	char *out;
138 	int flags;
139 
140 	ERR_load_crypto_strings();
141 	OpenSSL_add_all_algorithms();
142 
143 	/*
144 	 * A bunch of setup...
145 	 */
146 	cipher = EVP_aes_256_cbc();
147 	if (cipher == NULL)
148 		fatal("cipher");
149 
150 	certs = sk_X509_new_null();
151 	if (certs == NULL)
152 		fatal("sk_X509_new_null");
153 
154 	bio_cert = BIO_new_mem_buf((char *)certificate, sizeof(certificate));
155 	if (bio_cert == NULL)
156 		fatal("BIO_new_mem_buf certificate");
157 
158 	cert = PEM_read_bio_X509_AUX(bio_cert, NULL, NULL, NULL);
159 	if (cert == NULL)
160 		fatal("PEM_read_bio_X509_AUX");
161 	sk_X509_push(certs, cert);
162 
163 	store = X509_STORE_new();
164 	if (store == NULL)
165 		fatal("X509_STORE_new");
166 	X509_STORE_set_verify_cb(store, x509_store_callback);
167 
168 	bio_pkey = BIO_new_mem_buf((char *)private_key, sizeof(private_key));
169 	if (bio_pkey == NULL)
170 		fatal("BIO_new_mem_buf private_key");
171 
172 	pkey = PEM_read_bio_PrivateKey(bio_pkey, NULL, NULL, NULL);
173 	if (pkey == NULL)
174 		fatal("PEM_read_bio_PrivateKey");
175 
176 	bio_content = BIO_new_mem_buf((char *)message, sizeof(message));
177 	if (bio_content == NULL)
178 		fatal("BIO_new_mem_buf message");
179 
180 	/*
181 	 * Encrypt and then decrypt.
182 	 */
183 	if (BIO_reset(bio_content) != 1)
184 		fatal("BIO_reset");
185 	bio_out = BIO_new(BIO_s_mem());
186 	if (bio_out == NULL)
187 		fatal("BIO_new");
188 
189 	p7 = PKCS7_encrypt(certs, bio_content, cipher, 0);
190 	if (p7 == NULL)
191 		fatal("PKCS7_encrypt");
192 	if (PEM_write_bio_PKCS7(bio_out, p7) != 1)
193 		fatal("PEM_write_bio_PKCS7");
194 	PKCS7_free(p7);
195 
196 	bio_in = bio_out;
197 	bio_out = BIO_new(BIO_s_mem());
198 	if (bio_out == NULL)
199 		fatal("BIO_new");
200 
201 	p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL);
202 	if (p7 == NULL)
203 		fatal("PEM_read_bio_PKCS7");
204 	if (PKCS7_decrypt(p7, pkey, cert, bio_out, 0) != 1)
205 		fatal("PKCS7_decrypt");
206 
207 	len = BIO_get_mem_data(bio_out, &out);
208 	message_compare(out, len);
209 
210 	BIO_free(bio_out);
211 
212 	/*
213 	 * Sign and then verify.
214 	 */
215 	if (BIO_reset(bio_content) != 1)
216 		fatal("BIO_reset");
217 	bio_out = BIO_new(BIO_s_mem());
218 	if (bio_out == NULL)
219 		fatal("BIO_new");
220 
221 	p7 = PKCS7_sign(cert, pkey, certs, bio_content, 0);
222 	if (p7 == NULL)
223 		fatal("PKCS7_sign");
224 	if (PEM_write_bio_PKCS7(bio_out, p7) != 1)
225 		fatal("PEM_write_bio_PKCS7");
226 	PKCS7_free(p7);
227 
228 	bio_in = bio_out;
229 	bio_out = BIO_new(BIO_s_mem());
230 	if (bio_out == NULL)
231 		fatal("BIO_new");
232 
233 	p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL);
234 	if (p7 == NULL)
235 		fatal("PEM_read_bio_PKCS7");
236 	if (PKCS7_verify(p7, certs, store, NULL, bio_out, 0) != 1)
237 		fatal("PKCS7_verify");
238 
239 	len = BIO_get_mem_data(bio_out, &out);
240 	message_compare(out, len);
241 
242 	BIO_free(bio_in);
243 	BIO_free(bio_out);
244 
245 	/*
246 	 * Sign and then verify with a detached signature.
247 	 */
248 	if (BIO_reset(bio_content) != 1)
249 		fatal("BIO_reset");
250 	bio_out = BIO_new(BIO_s_mem());
251 	if (bio_out == NULL)
252 		fatal("BIO_new");
253 
254 	flags = PKCS7_DETACHED|PKCS7_PARTIAL;
255 	p7 = PKCS7_sign(NULL, NULL, NULL, bio_content, flags);
256 	if (p7 == NULL)
257 		fatal("PKCS7_sign");
258 	if (PKCS7_sign_add_signer(p7, cert, pkey, NULL, flags) == NULL)
259 		fatal("PKCS7_sign_add_signer");
260 	if (PKCS7_final(p7, bio_content, flags) != 1)
261 		fatal("PKCS7_final");
262 	if (PEM_write_bio_PKCS7(bio_out, p7) != 1)
263 		fatal("PEM_write_bio_PKCS7");
264 	PKCS7_free(p7);
265 
266 	/* bio_out contains only the detached signature. */
267 	bio_in = bio_out;
268 	if (BIO_reset(bio_content) != 1)
269 		fatal("BIO_reset");
270 
271 	bio_out = BIO_new(BIO_s_mem());
272 	if (bio_out == NULL)
273 		fatal("BIO_new");
274 
275 	p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL);
276 	if (p7 == NULL)
277 		fatal("PEM_read_bio_PKCS7");
278 	if (PKCS7_verify(p7, certs, store, bio_content, bio_out, flags) != 1)
279 		fatal("PKCS7_verify");
280 
281 	len = BIO_get_mem_data(bio_out, &out);
282 	message_compare(out, len);
283 
284 	BIO_free(bio_in);
285 	BIO_free(bio_out);
286 	BIO_free(bio_content);
287 
288 	return 0;
289 }
290