1 /* $OpenBSD: pkcs7test.c,v 1.5 2021/04/07 17:21:40 tb 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_fp(stderr); 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 PKCS7_free(p7); 207 208 len = BIO_get_mem_data(bio_out, &out); 209 message_compare(out, len); 210 211 BIO_free(bio_in); 212 BIO_free(bio_out); 213 214 /* 215 * Sign and then verify. 216 */ 217 if (BIO_reset(bio_content) != 1) 218 fatal("BIO_reset"); 219 bio_out = BIO_new(BIO_s_mem()); 220 if (bio_out == NULL) 221 fatal("BIO_new"); 222 223 p7 = PKCS7_sign(cert, pkey, certs, bio_content, 0); 224 if (p7 == NULL) 225 fatal("PKCS7_sign"); 226 if (PEM_write_bio_PKCS7(bio_out, p7) != 1) 227 fatal("PEM_write_bio_PKCS7"); 228 PKCS7_free(p7); 229 230 bio_in = bio_out; 231 bio_out = BIO_new(BIO_s_mem()); 232 if (bio_out == NULL) 233 fatal("BIO_new"); 234 235 p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL); 236 if (p7 == NULL) 237 fatal("PEM_read_bio_PKCS7"); 238 if (PKCS7_verify(p7, certs, store, NULL, bio_out, 0) != 1) 239 fatal("PKCS7_verify"); 240 PKCS7_free(p7); 241 242 len = BIO_get_mem_data(bio_out, &out); 243 message_compare(out, len); 244 245 BIO_free(bio_in); 246 BIO_free(bio_out); 247 248 /* 249 * Sign and then verify with a detached signature. 250 */ 251 if (BIO_reset(bio_content) != 1) 252 fatal("BIO_reset"); 253 bio_out = BIO_new(BIO_s_mem()); 254 if (bio_out == NULL) 255 fatal("BIO_new"); 256 257 flags = PKCS7_DETACHED|PKCS7_PARTIAL; 258 p7 = PKCS7_sign(NULL, NULL, NULL, bio_content, flags); 259 if (p7 == NULL) 260 fatal("PKCS7_sign"); 261 if (PKCS7_sign_add_signer(p7, cert, pkey, NULL, flags) == NULL) 262 fatal("PKCS7_sign_add_signer"); 263 if (PKCS7_final(p7, bio_content, flags) != 1) 264 fatal("PKCS7_final"); 265 if (PEM_write_bio_PKCS7(bio_out, p7) != 1) 266 fatal("PEM_write_bio_PKCS7"); 267 PKCS7_free(p7); 268 269 /* bio_out contains only the detached signature. */ 270 bio_in = bio_out; 271 if (BIO_reset(bio_content) != 1) 272 fatal("BIO_reset"); 273 274 bio_out = BIO_new(BIO_s_mem()); 275 if (bio_out == NULL) 276 fatal("BIO_new"); 277 278 p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL); 279 if (p7 == NULL) 280 fatal("PEM_read_bio_PKCS7"); 281 if (PKCS7_verify(p7, certs, store, bio_content, bio_out, flags) != 1) 282 fatal("PKCS7_verify"); 283 PKCS7_free(p7); 284 285 len = BIO_get_mem_data(bio_out, &out); 286 message_compare(out, len); 287 288 BIO_free(bio_in); 289 BIO_free(bio_out); 290 BIO_free(bio_content); 291 BIO_free(bio_cert); 292 BIO_free(bio_pkey); 293 294 EVP_PKEY_free(pkey); 295 296 X509_free(cert); 297 X509_STORE_free(store); 298 sk_X509_free(certs); 299 300 return 0; 301 } 302