1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
/* SPDX-License-Identifier: BSD-3-Clause */
#include <string.h>
#include <openssl/core_names.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/provider.h>
#include <openssl/store.h>
#include <openssl/ui.h>
int generate_and_save(const char *filename, const char *password)
{
OSSL_PARAM params[3];
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
BIO *out = NULL;
int ret = 1;
if (!(pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", "provider=tpm2")))
goto error;
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, "P-256", 0);
params[1] = OSSL_PARAM_construct_utf8_string("user-auth", (char *)password, 0);
params[2] = OSSL_PARAM_construct_end();
if (EVP_PKEY_keygen_init(pctx) <= 0
|| EVP_PKEY_CTX_set_params(pctx, params) <= 0
|| EVP_PKEY_generate(pctx, &pkey) <= 0)
goto error;
// save the TPM2-protected private key as the "TSS2 PRIVATE KEY"
if ((out = BIO_new_file(filename, "w")) == NULL
|| !PEM_write_bio_PrivateKey(out, pkey, 0, NULL, 0, 0, NULL))
goto error;
ret = 0;
error:
BIO_free_all(out);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(pctx);
return ret;
}
int provide_password(char *buf, int size, int rwflag, void *u)
{
const char *password = (char *)u;
size_t len = strlen(password);
if (len > size)
len = size;
memcpy(buf, password, len);
return len;
}
int sign_message(EVP_PKEY *pkey)
{
EVP_MD_CTX *sctx = NULL;
EVP_MD_CTX *vctx = NULL;
unsigned char *sig = NULL;
size_t sig_len = 0;
int ret = 1;
const char *message = "Sabai Sabai";
// sign
if (!(sctx = EVP_MD_CTX_new()))
goto error;
if (!EVP_DigestSignInit_ex(sctx, NULL, "SHA-256", NULL, "provider=tpm2", pkey, NULL)
|| !EVP_DigestSign(sctx, NULL, &sig_len, (const unsigned char *)message, strlen(message)))
goto error;
if (!(sig = OPENSSL_malloc(sig_len)))
goto error;
if (!EVP_DigestSign(sctx, sig, &sig_len, (const unsigned char *)message, strlen(message)))
goto error;
// verify
if (!(vctx = EVP_MD_CTX_new()))
goto error;
if (!EVP_DigestVerifyInit_ex(vctx, NULL, "SHA-256", NULL, "provider=tpm2", pkey, NULL)
|| EVP_DigestVerify(vctx, sig, sig_len, (const unsigned char *)message, strlen(message)) != 1)
goto error;
ret = 0;
error:
OPENSSL_free(sig);
EVP_MD_CTX_free(vctx);
EVP_MD_CTX_free(sctx);
return ret;
}
int load_and_sign(const char *filename, const char *password)
{
OSSL_STORE_CTX *ctx = NULL;
UI_METHOD *ui_method = NULL;
int ret = 1;
if (!(ui_method = UI_UTIL_wrap_read_pem_callback(provide_password, 0)))
goto error;
if ((ctx = OSSL_STORE_open(filename, ui_method, (void *)password, NULL, NULL))) {
while (OSSL_STORE_eof(ctx) == 0) {
OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
if (info && OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) {
EVP_PKEY *pkey;
if ((pkey = OSSL_STORE_INFO_get0_PKEY(info)))
ret = sign_message(pkey);
OSSL_STORE_INFO_free(info);
}
}
}
error:
OSSL_STORE_close(ctx);
UI_destroy_method(ui_method);
return ret;
}
#define TEST_FILENAME "ec_genpkey_store_load.pem"
#define TEST_PASSWORD "secret"
int main()
{
OSSL_PROVIDER *defprov = NULL, *tpm2prov = NULL;
int ret = 1;
if ((defprov = OSSL_PROVIDER_load(NULL, "default")) == NULL)
goto error;
if ((tpm2prov = OSSL_PROVIDER_load(NULL, "tpm2")) == NULL)
goto error;
if (generate_and_save(TEST_FILENAME, TEST_PASSWORD)
|| load_and_sign(TEST_FILENAME, TEST_PASSWORD))
goto error;
ret = 0;
error:
ERR_print_errors_fp(stderr);
remove(TEST_FILENAME);
OSSL_PROVIDER_unload(tpm2prov);
OSSL_PROVIDER_unload(defprov);
return ret;
}
|