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