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 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 
40 extern OSSL_LIB_CTX *tls_libctx;
41 
42 /* A message for signing */
43 static 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 
53 int
54 digest_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 
131 done:
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 */
EVP_MD_CTX_new
static EVP_MD_CTX * EVP_MD_CTX_new(void)
Allocate a new message digest object.
Definition: openssl_compat.h:114
xkey_common.h
EVP_MD_CTX_free
static void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
Free an existing message digest context.
Definition: openssl_compat.h:103
syshead.h
digest_sign_verify
int digest_sign_verify(EVP_PKEY *privkey, EVP_PKEY *pubkey)
config.h
tls_libctx
OSSL_LIB_CTX * tls_libctx
Definition: ssl_openssl.c:72
OSSL_LIB_CTX
void OSSL_LIB_CTX
Definition: openssl_compat.h:774