1 /* 2 * Copyright 2024-2026 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 <openssl/core_names.h> 11 #include <openssl/pem.h> 12 #include <openssl/x509.h> 13 #include <openssl/x509v3.h> 14 15 #include "testutil.h" 16 17 static char *certsDir = NULL; 18 19 /* 20 * Test for the missing X509 version check discussed in issue #5738 and 21 * added in PR #24677. 22 * This test tries to verify a malformed CSR with the X509 version set 23 * version 6, instead of 1. As this request is malformed, even its 24 * signature is valid, the verification must fail. 25 */ 26 static int test_x509_req_detect_invalid_version(void) 27 { 28 char *certFilePath; 29 BIO *bio = NULL; 30 EVP_PKEY *pkey = NULL; 31 X509_REQ *req = NULL; 32 int ret = 0; 33 34 certFilePath = test_mk_file_path(certsDir, "x509-req-detect-invalid-version.pem"); 35 if (certFilePath == NULL) 36 goto err; 37 if (!TEST_ptr(bio = BIO_new_file(certFilePath, "r"))) 38 goto err; 39 req = PEM_read_bio_X509_REQ(bio, NULL, 0, NULL); 40 if (req == NULL) { 41 ret = 1; /* success, reading PEM with invalid CSR data is allowed to fail. */ 42 goto err; 43 } 44 if (!TEST_ptr(pkey = X509_REQ_get_pubkey(req))) 45 goto err; 46 /* Verification MUST fail at this point. ret != 1. */ 47 if (!TEST_int_ne(X509_REQ_verify(req, pkey), 1)) 48 goto err; 49 ret = 1; /* success */ 50 err: 51 EVP_PKEY_free(pkey); 52 X509_REQ_free(req); 53 BIO_free(bio); 54 OPENSSL_free(certFilePath); 55 return ret; 56 } 57 58 static int add_ext(STACK_OF(X509_EXTENSION) *sk, int nid, char *value) 59 { 60 X509_EXTENSION *ex; 61 ex = X509V3_EXT_conf_nid(NULL, NULL, nid, value); 62 if (!ex) 63 return 0; 64 if (sk_X509_EXTENSION_push(sk, ex) <= 0) { 65 X509_EXTENSION_free(ex); 66 return 0; 67 } 68 69 return 1; 70 } 71 72 static int test_x509_req_add_exts(void) 73 { 74 X509_REQ *x = NULL; 75 STACK_OF(X509_EXTENSION) *exts = NULL; 76 EVP_PKEY_CTX *ctx = NULL; 77 EVP_PKEY *pkey = NULL; 78 int ret = 0; 79 int nid = NID_undef; 80 OSSL_PARAM params[2]; 81 size_t bits = 2048; 82 83 params[0] = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_BITS, &bits); 84 params[1] = OSSL_PARAM_construct_end(); 85 86 ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); 87 if (ctx == NULL 88 || EVP_PKEY_keygen_init(ctx) <= 0 89 || EVP_PKEY_CTX_set_params(ctx, params) <= 0 90 || EVP_PKEY_keygen(ctx, &pkey) <= 0 91 || (x = X509_REQ_new()) == NULL 92 || X509_REQ_set_pubkey(x, pkey) <= 0) 93 goto err; 94 95 exts = sk_X509_EXTENSION_new_null(); 96 if (!TEST_ptr(exts)) 97 goto err; 98 99 /* 100 * For request extensions they are all packed in a single attribute. We 101 * save them in a STACK and add them all at once later... 102 */ 103 104 if (!TEST_int_eq(add_ext(exts, NID_netscape_cert_type, "client,email"), 1) 105 || !TEST_int_eq(add_ext(exts, NID_subject_alt_name, "email:steve@openssl.org"), 1) 106 || !TEST_int_eq(add_ext(exts, NID_crl_distribution_points, "URI:http://example.org"), 1) 107 /* These tests require some underlying config but we just check that we don't crash */ 108 || !TEST_int_eq(add_ext(exts, NID_proxyCertInfo, "text:xxx"), 0) 109 || !TEST_int_eq(add_ext(exts, NID_certificate_policies, "xxx:yyy"), 0) 110 /* Some Netscape specific extensions */ 111 || !TEST_int_eq(add_ext(exts, NID_netscape_cert_type, "client,email"), 1)) 112 goto err; 113 114 /* Maybe even add our own extension based on existing */ 115 nid = OBJ_create("1.2.3.4", "MyAlias", "My Test Alias Extension"); 116 if (!TEST_int_ne(nid, NID_undef) 117 || !TEST_int_gt(X509V3_EXT_add_alias(nid, NID_netscape_comment), 0) 118 || !TEST_int_eq(add_ext(exts, nid, "example comment alias"), 1) 119 || !TEST_int_eq(X509_REQ_add_extensions(x, exts), 1)) 120 goto err; 121 122 if (!X509_REQ_sign(x, pkey, EVP_sha256())) 123 goto err; 124 125 ret = 1; 126 err: 127 EVP_PKEY_CTX_free(ctx); 128 129 X509_REQ_free(x); 130 EVP_PKEY_free(pkey); 131 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 132 133 return ret; 134 } 135 OPT_TEST_DECLARE_USAGE("certdir\n") 136 137 int setup_tests(void) 138 { 139 if (!test_skip_common_options()) { 140 TEST_error("Error parsing test options\n"); 141 return 0; 142 } 143 if (!TEST_ptr(certsDir = test_get_argument(0))) 144 return 0; 145 146 ADD_TEST(test_x509_req_detect_invalid_version); 147 ADD_TEST(test_x509_req_add_exts); 148 return 1; 149 } 150 151 void cleanup_tests(void) 152 { 153 } 154