1 /* 2 * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <stdio.h> 11 #include <string.h> 12 13 #include <openssl/pem.h> 14 #include <openssl/x509.h> 15 #include "testutil.h" 16 17 /* 18 * c: path of a cert in PEM format 19 * k: path of a key in PEM format 20 * t: API type, "cert" for X509_ and "req" for X509_REQ_ APIs. 21 * e: expected, "ok" for success, "failed" for what should fail. 22 */ 23 static const char *c; 24 static const char *k; 25 static const char *t; 26 static const char *e; 27 28 static int test_x509_check_cert_pkey(void) 29 { 30 BIO *bio = NULL; 31 X509 *x509 = NULL; 32 X509_REQ *x509_req = NULL; 33 EVP_PKEY *pkey = NULL; 34 int ret = 0, type = 0, expected = 0, result = 0; 35 36 /* 37 * we check them first thus if fails we don't need to do 38 * those PEM parsing operations. 39 */ 40 if (strcmp(t, "cert") == 0) { 41 type = 1; 42 } else if (strcmp(t, "req") == 0) { 43 type = 2; 44 } else { 45 TEST_error("invalid 'type'"); 46 goto failed; 47 } 48 49 if (strcmp(e, "ok") == 0) { 50 expected = 1; 51 } else if (strcmp(e, "failed") == 0) { 52 expected = 0; 53 } else { 54 TEST_error("invalid 'expected'"); 55 goto failed; 56 } 57 58 /* process private key */ 59 if (!TEST_ptr(bio = BIO_new_file(k, "r"))) 60 goto failed; 61 62 if (!TEST_ptr(pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))) 63 goto failed; 64 65 BIO_free(bio); 66 67 /* process cert or cert request, use the same local var */ 68 if (!TEST_ptr(bio = BIO_new_file(c, "r"))) 69 goto failed; 70 71 switch (type) { 72 case 1: 73 x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); 74 if (x509 == NULL) { 75 TEST_error("read PEM x509 failed"); 76 goto failed; 77 } 78 79 result = X509_check_private_key(x509, pkey); 80 break; 81 case 2: 82 x509_req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL); 83 if (x509_req == NULL) { 84 TEST_error("read PEM x509 req failed"); 85 goto failed; 86 } 87 88 result = X509_REQ_check_private_key(x509_req, pkey); 89 break; 90 default: 91 /* should never be here */ 92 break; 93 } 94 95 if (!TEST_int_eq(result, expected)) { 96 TEST_error("check private key: expected: %d, got: %d", expected, result); 97 goto failed; 98 } 99 100 ret = 1; 101 failed: 102 BIO_free(bio); 103 X509_free(x509); 104 X509_REQ_free(x509_req); 105 EVP_PKEY_free(pkey); 106 return ret; 107 } 108 109 static const char *file; /* path of a cert/CRL/key file in PEM format */ 110 static const char *num; /* expected number of certs/CRLs/keys included */ 111 112 static int test_PEM_X509_INFO_read_bio(void) 113 { 114 BIO *in; 115 STACK_OF(X509_INFO) *sk; 116 X509_INFO *it; 117 int i, count = 0; 118 int expected = 0; 119 120 if (!TEST_ptr((in = BIO_new_file(file, "r")))) 121 return 0; 122 sk = PEM_X509_INFO_read_bio(in, NULL, NULL, ""); 123 BIO_free(in); 124 sscanf(num, "%d", &expected); 125 for (i = 0; i < sk_X509_INFO_num(sk); i++) { 126 it = sk_X509_INFO_value(sk, i); 127 if (it->x509 != NULL) 128 count++; 129 if (it->crl != NULL) 130 count++; 131 if (it->x_pkey != NULL) 132 count++; 133 } 134 sk_X509_INFO_pop_free(sk, X509_INFO_free); 135 return TEST_int_eq(count, expected); 136 } 137 138 const OPTIONS *test_get_options(void) 139 { 140 enum { OPT_TEST_ENUM }; 141 static const OPTIONS test_options[] = { 142 OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("cert key type expected\n" 143 " or [options] file num\n"), 144 { OPT_HELP_STR, 1, '-', "cert\tcertificate or CSR filename in PEM\n" }, 145 { OPT_HELP_STR, 1, '-', "key\tprivate key filename in PEM\n" }, 146 { OPT_HELP_STR, 1, '-', "type\t\tvalue must be 'cert' or 'req'\n" }, 147 { OPT_HELP_STR, 1, '-', "expected\tthe expected return value, either 'ok' or 'failed'\n" }, 148 { OPT_HELP_STR, 1, '-', "file\tPEM format file containing certs, keys, and/OR CRLs\n" }, 149 { OPT_HELP_STR, 1, '-', "num\texpected number of credentials to be loaded from file\n" }, 150 { NULL } 151 }; 152 return test_options; 153 } 154 155 int setup_tests(void) 156 { 157 if (!test_skip_common_options()) { 158 TEST_error("Error parsing test options\n"); 159 return 0; 160 } 161 162 if (test_get_argument_count() == 2) { 163 if (!TEST_ptr(file = test_get_argument(0)) 164 || !TEST_ptr(num = test_get_argument(1))) 165 return 0; 166 ADD_TEST(test_PEM_X509_INFO_read_bio); 167 return 1; 168 } 169 170 if (!TEST_ptr(c = test_get_argument(0)) 171 || !TEST_ptr(k = test_get_argument(1)) 172 || !TEST_ptr(t = test_get_argument(2)) 173 || !TEST_ptr(e = test_get_argument(3))) { 174 return 0; 175 } 176 177 ADD_TEST(test_x509_check_cert_pkey); 178 return 1; 179 } 180