OpenVPN
pkey_test_utils.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2023-2024 Selva Nair <selva.nair@gmail.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by the
12 * Free Software Foundation, either version 2 of the License,
13 * or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29
30#include "syshead.h"
31#include "xkey_common.h"
32#include <setjmp.h>
33#include <cmocka.h>
34
35#ifdef HAVE_XKEY_PROVIDER
36
37#include <openssl/core_names.h>
38#include <openssl/evp.h>
39
41
42/* A message for signing */
43static const char *test_msg = "Lorem ipsum dolor sit amet, consectetur "
44 "adipisici elit, sed eiusmod tempor incidunt "
45 "ut labore et dolore magna aliqua.";
46
53int
54digest_sign_verify(EVP_PKEY *privkey, EVP_PKEY *pubkey)
55{
56 uint8_t *sig = NULL;
57 size_t siglen = 0;
58 int ret = 0;
59
60 OSSL_PARAM params[2] = {OSSL_PARAM_END};
61 const char *mdname = "SHA256";
62
63 if (EVP_PKEY_get_id(privkey) == EVP_PKEY_RSA)
64 {
65 const char *padmode = "pss"; /* RSA_PSS: for all other params, use defaults */
66 params[0] = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE,
67 (char *)padmode, 0);
68 params[1] = OSSL_PARAM_construct_end();
69 }
70 else if (EVP_PKEY_get_id(privkey) == EVP_PKEY_EC)
71 {
72 params[0] = OSSL_PARAM_construct_end();
73 }
74 else
75 {
76 print_error("Unknown key type in digest_sign_verify()");
77 return ret;
78 }
79
80 EVP_PKEY_CTX *pctx = NULL;
81 EVP_MD_CTX *mctx = EVP_MD_CTX_new();
82
83 if (!mctx
84 || EVP_DigestSignInit_ex(mctx, &pctx, mdname, tls_libctx, NULL, privkey, params) <= 0)
85 {
86 /* cmocka assert output for these kinds of failures is hardly explanatory,
87 * print a message and assert in caller. */
88 print_error("Failed to initialize EVP_DigestSignInit_ex()\n");
89 goto done;
90 }
91
92 /* sign with sig = NULL to get required siglen */
93 if (EVP_DigestSign(mctx, sig, &siglen, (uint8_t *)test_msg, strlen(test_msg)) != 1)
94 {
95 print_error("EVP_DigestSign: failed to get required signature size");
96 goto done;
97 }
98 assert_true(siglen > 0);
99
100 if ((sig = test_calloc(1, siglen)) == NULL)
101 {
102 print_error("Out of memory");
103 goto done;
104 }
105 if (EVP_DigestSign(mctx, sig, &siglen, (uint8_t *)test_msg, strlen(test_msg)) != 1)
106 {
107 print_error("EVP_DigestSign: signing failed");
108 goto done;
109 }
110
111 /*
112 * Now validate the signature using OpenSSL. Just use the public key
113 * which is a native OpenSSL key.
114 */
115 EVP_MD_CTX_free(mctx); /* this also frees pctx */
116 mctx = EVP_MD_CTX_new();
117 pctx = NULL;
118 if (!mctx
119 || EVP_DigestVerifyInit_ex(mctx, &pctx, mdname, tls_libctx, NULL, pubkey, params) <= 0)
120 {
121 print_error("Failed to initialize EVP_DigestVerifyInit_ex()");
122 goto done;
123 }
124 if (EVP_DigestVerify(mctx, sig, siglen, (uint8_t *)test_msg, strlen(test_msg)) != 1)
125 {
126 print_error("EVP_DigestVerify failed");
127 goto done;
128 }
129 ret = 1;
130
131done:
132 if (mctx)
133 {
134 EVP_MD_CTX_free(mctx); /* this also frees pctx */
135 }
136 test_free(sig);
137 return ret;
138}
139#endif /* HAVE_XKEY_PROVIDER */
void OSSL_LIB_CTX
OSSL_LIB_CTX * tls_libctx
Definition ssl_openssl.c:79
int digest_sign_verify(EVP_PKEY *privkey, EVP_PKEY *pubkey)