Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement support to expose PKCS#11 Random as openssl rand provider #233

Merged
merged 3 commits into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ jobs:
- name: Check the Style
run: make check-style || (make check-style-show; exit -1)
- name: Check spelling
run: codespell --ignore-words-list="sorce" *.md Makefile.am configure.ac src tests -S src/oasis
run: codespell --ignore-words-list="sorce,clen,adin" *.md Makefile.am configure.ac src tests -S src/oasis
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ noinst_HEADERS = \
pkcs11.h \
platform/endian.h \
provider.h \
random.h \
session.h \
signature.h \
slot.h \
Expand All @@ -40,6 +41,7 @@ pkcs11_la_SOURCES = \
objects.c \
provider.h \
provider.c \
random.c \
session.c \
signature.c \
slot.c \
Expand Down
2 changes: 2 additions & 0 deletions src/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ struct p11prov_interface {
CK_C_VerifyFinal VerifyFinal;
CK_C_GenerateKeyPair GenerateKeyPair;
CK_C_DeriveKey DeriveKey;
CK_C_SeedRandom SeedRandom;
CK_C_GenerateRandom GenerateRandom;
CK_C_GetInterface GetInterface;
};
Expand Down Expand Up @@ -142,6 +143,7 @@ static void populate_interface(P11PROV_INTERFACE *intf, CK_INTERFACE *ck_intf)
ASSIGN_FN(VerifyFinal);
ASSIGN_FN(GenerateKeyPair);
ASSIGN_FN(DeriveKey);
ASSIGN_FN(SeedRandom);
ASSIGN_FN(GenerateRandom);
if (intf->version.major == 3) {
ASSIGN_FN_3_0(GetInterface);
Expand Down
20 changes: 20 additions & 0 deletions src/interface.gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,26 @@ CK_RV p11prov_DeriveKey(P11PROV_CTX *ctx, CK_SESSION_HANDLE hSession,
return ret;
}

CK_RV p11prov_SeedRandom(P11PROV_CTX *ctx, CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
{
P11PROV_INTERFACE *intf = p11prov_ctx_get_interface(ctx);
CK_RV ret = CKR_GENERAL_ERROR;
if (!intf) {
P11PROV_raise(ctx, ret, "Can't get module interfaces");
return ret;
}
P11PROV_debug("Calling C_"
"SeedRandom");
ret = intf->SeedRandom(hSession, pSeed, ulSeedLen);
if (ret != CKR_OK) {
P11PROV_raise(ctx, ret,
"Error returned by C_"
"SeedRandom");
}
return ret;
}

CK_RV p11prov_GenerateRandom(P11PROV_CTX *ctx, CK_SESSION_HANDLE hSession,
CK_BYTE_PTR RandomData, CK_ULONG ulRandomLen)
{
Expand Down
2 changes: 2 additions & 0 deletions src/interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ CK_RV p11prov_DeriveKey(P11PROV_CTX *ctx, CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
CK_OBJECT_HANDLE_PTR phKey);
CK_RV p11prov_SeedRandom(P11PROV_CTX *ctx, CK_SESSION_HANDLE hSession,
CK_BYTE_PTR SeedData, CK_ULONG ulSeedLen);
CK_RV p11prov_GenerateRandom(P11PROV_CTX *ctx, CK_SESSION_HANDLE hSession,
CK_BYTE_PTR RandomData, CK_ULONG ulRandomLen);

Expand Down
3 changes: 3 additions & 0 deletions src/interface.pre
Original file line number Diff line number Diff line change
Expand Up @@ -209,5 +209,8 @@ IMPL_INTERFACE_FN_6_ARG(DeriveKey, CK_SESSION_HANDLE, hSession,
hBaseKey, CK_ATTRIBUTE_PTR, pTemplate, CK_ULONG,
ulAttributeCount, CK_OBJECT_HANDLE_PTR, phKey)

IMPL_INTERFACE_FN_3_ARG(SeedRandom, CK_SESSION_HANDLE, hSession,
CK_BYTE_PTR, pSeed, CK_ULONG, ulSeedLen)

IMPL_INTERFACE_FN_3_ARG(GenerateRandom, CK_SESSION_HANDLE, hSession,
CK_BYTE_PTR, RandomData, CK_ULONG, ulRandomLen)
12 changes: 12 additions & 0 deletions src/provider.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ struct p11prov_ctx {

OSSL_ALGORITHM *op_digest;
OSSL_ALGORITHM *op_kdf;
OSSL_ALGORITHM *op_random;
OSSL_ALGORITHM *op_exchange;
OSSL_ALGORITHM *op_signature;
OSSL_ALGORITHM *op_asym_cipher;
Expand Down Expand Up @@ -487,6 +488,7 @@ static void p11prov_ctx_free(P11PROV_CTX *ctx)

OPENSSL_free(ctx->op_digest);
OPENSSL_free(ctx->op_kdf);
OPENSSL_free(ctx->op_random);
/* keymgmt is static */
OPENSSL_free(ctx->op_exchange);
OPENSSL_free(ctx->op_signature);
Expand Down Expand Up @@ -814,6 +816,7 @@ static CK_RV operations_init(P11PROV_CTX *ctx)
int cl_size = sizeof(checklist) / sizeof(CK_ULONG);
int digest_idx = 0;
int kdf_idx = 0;
int random_idx = 0;
int exchange_idx = 0;
int signature_idx = 0;
int asym_cipher_idx = 0;
Expand Down Expand Up @@ -1013,6 +1016,13 @@ static CK_RV operations_init(P11PROV_CTX *ctx)
p11prov_ec_encoder_spki_der_functions);
TERM_ALGO(encoder);

/* handle random */
ret = p11prov_check_random(ctx);
if (ret == CKR_OK) {
ADD_ALGO_EXT(RAND, random, "provider=pkcs11", p11prov_rand_functions);
TERM_ALGO(random);
}

return CKR_OK;
}

Expand Down Expand Up @@ -1052,6 +1062,8 @@ p11prov_query_operation(void *provctx, int operation_id, int *no_cache)
return ctx->op_digest;
case OSSL_OP_KDF:
return ctx->op_kdf;
case OSSL_OP_RAND:
return ctx->op_random;
case OSSL_OP_KEYMGMT:
return p11prov_keymgmt;
case OSSL_OP_KEYEXCH:
Expand Down
3 changes: 3 additions & 0 deletions src/provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
#define P11PROV_NAMES_ED448 "ED448:1.3.101.113"
#define P11PROV_NAME_ED448 "ED448"
#define P11PROV_DESCS_ED448 "PKCS11 ED448 Implementation"
#define P11PROV_NAMES_RAND "PKCS11-RAND"
#define P11PROV_DESCS_RAND "PKCS11 Random Generator"

#define P11PROV_PARAM_KEY_LABEL "pkcs11_key_label"
#define P11PROV_PARAM_KEY_ID "pkcs11_key_id"
Expand Down Expand Up @@ -133,6 +135,7 @@ int p11prov_pop_error_to_mark(P11PROV_CTX *ctx);
#include "util.h"
#include "session.h"
#include "slot.h"
#include "random.h"

/* TLS */
int tls_group_capabilities(OSSL_CALLBACK *cb, void *arg);
Expand Down
209 changes: 209 additions & 0 deletions src/random.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
/* Copyright (C) 2023 Simo Sorce <simo@redhat.com>
SPDX-License-Identifier: Apache-2.0 */

#include "provider.h"

DISPATCH_RAND_FN(newctx); /* required */
DISPATCH_RAND_FN(freectx); /* required */
DISPATCH_RAND_FN(instantiate); /* required */
DISPATCH_RAND_FN(uninstantiate); /* required */
DISPATCH_RAND_FN(generate); /* required */
DISPATCH_RAND_FN(reseed);
DISPATCH_RAND_FN(get_ctx_params); /* required */

/* following functions are optional only in theory,
* openssl depends on them */
DISPATCH_RAND_FN(enable_locking);
DISPATCH_RAND_FN(lock);
DISPATCH_RAND_FN(unlock);

struct p11prov_rand_ctx {
P11PROV_CTX *provctx;
CK_SLOT_ID slotid;
};

static void *p11prov_rand_newctx(void *provctx, void *parent,
const OSSL_DISPATCH *parent_dispatch)
{
P11PROV_CTX *ctx = (P11PROV_CTX *)provctx;
struct p11prov_rand_ctx *rctx;

P11PROV_debug("rand newctx");

rctx = OPENSSL_zalloc(sizeof(struct p11prov_rand_ctx));
if (!rctx) {
return NULL;
}

rctx->provctx = ctx;
rctx->slotid = CK_UNAVAILABLE_INFORMATION;
return rctx;
}

static void p11prov_rand_freectx(void *pctx)
{
P11PROV_debug("rand: freectx");

OPENSSL_free(pctx);
}

static int p11prov_rand_instantiate(void *pctx, unsigned int strength,
int prediction_resistance,
const unsigned char *pstr, size_t pstr_len,
const OSSL_PARAM params[])
{
struct p11prov_rand_ctx *ctx = (struct p11prov_rand_ctx *)pctx;
CK_RV ret;

P11PROV_debug("rand: instantiate");

ret = p11prov_ctx_status(ctx->provctx);
if (ret != CKR_OK) {
return RET_OSSL_ERR;
}

return RET_OSSL_OK;
}

static int p11prov_rand_uninstantiate(void *pctx)
{
P11PROV_debug("rand: uninstantiate");

return RET_OSSL_OK;
}

static int p11prov_rand_generate(void *pctx, unsigned char *out, size_t outlen,
unsigned int strength,
int prediction_resistance,
const unsigned char *adin, size_t adin_len)
{
struct p11prov_rand_ctx *ctx = (struct p11prov_rand_ctx *)pctx;
P11PROV_SESSION *session = NULL;
CK_RV ret;
int res = RET_OSSL_ERR;

P11PROV_debug("rand: generate (add bytes: %zu)", adin_len);

ret = p11prov_get_session(ctx->provctx, &ctx->slotid, NULL, NULL,
CK_UNAVAILABLE_INFORMATION, NULL, NULL, false,
false, &session);
if (ret != CKR_OK) {
return res;
}

if (adin && adin_len > 0) {
/* we ignore the result, as this is optional */
(void)p11prov_SeedRandom(ctx->provctx, p11prov_session_handle(session),
(CK_BYTE *)adin, adin_len);
}

ret = p11prov_GenerateRandom(ctx->provctx, p11prov_session_handle(session),
(CK_BYTE *)out, outlen);
if (ret == CKR_OK) {
res = RET_OSSL_OK;
}

p11prov_return_session(session);
return res;
}

static int p11prov_rand_reseed(void *pctx, int prediction_resistance,
const unsigned char *entropy, size_t ent_len,
const unsigned char *adin, size_t adin_len)
{
struct p11prov_rand_ctx *ctx = (struct p11prov_rand_ctx *)pctx;
P11PROV_SESSION *session = NULL;
CK_RV ret;
int res = RET_OSSL_ERR;

P11PROV_debug("rand: reseed (ent bytes: %zu, add bytes: %zu)", ent_len,
adin_len);

ret = p11prov_get_session(ctx->provctx, &ctx->slotid, NULL, NULL,
CK_UNAVAILABLE_INFORMATION, NULL, NULL, false,
false, &session);
if (ret != CKR_OK) {
return res;
}

if (entropy && ent_len > 0) {
/* we ignore the result, as this is optional */
(void)p11prov_SeedRandom(ctx->provctx, p11prov_session_handle(session),
(CK_BYTE *)entropy, ent_len);
}

if (adin && adin_len > 0) {
/* we ignore the result, as this is optional */
(void)p11prov_SeedRandom(ctx->provctx, p11prov_session_handle(session),
(CK_BYTE *)adin, adin_len);
}

p11prov_return_session(session);
return res;
}

#define MAX_RAND_REQUEST INT_MAX

static int p11prov_rand_get_ctx_params(void *pctx, OSSL_PARAM params[])
{
OSSL_PARAM *p;
int ret;

P11PROV_debug("rand: get_ctx_params");

p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
if (p) {
ret = OSSL_PARAM_set_size_t(p, MAX_RAND_REQUEST);
if (ret != RET_OSSL_OK) {
return ret;
}
}

return RET_OSSL_OK;
}

static int p11prov_rand_enable_locking(void *pctx)
{
return RET_OSSL_OK;
}

static int p11prov_rand_lock(void *pctx)
{
return RET_OSSL_OK;
}

static void p11prov_rand_unlock(void *pctx)
{
/* nothing to do */
}

const OSSL_DISPATCH p11prov_rand_functions[] = {
DISPATCH_RAND_ELEM(rand, NEWCTX, newctx),
DISPATCH_RAND_ELEM(rand, FREECTX, freectx),
DISPATCH_RAND_ELEM(rand, INSTANTIATE, instantiate),
DISPATCH_RAND_ELEM(rand, UNINSTANTIATE, uninstantiate),
DISPATCH_RAND_ELEM(rand, GENERATE, generate),
DISPATCH_RAND_ELEM(rand, RESEED, reseed),
DISPATCH_RAND_ELEM(rand, GET_CTX_PARAMS, get_ctx_params),
DISPATCH_RAND_ELEM(rand, ENABLE_LOCKING, enable_locking),
DISPATCH_RAND_ELEM(rand, LOCK, lock),
DISPATCH_RAND_ELEM(rand, UNLOCK, unlock),
{ 0, NULL },
};

CK_RV p11prov_check_random(P11PROV_CTX *ctx)
{
struct p11prov_rand_ctx rctx = {
.provctx = ctx,
.slotid = CK_UNAVAILABLE_INFORMATION,
};
unsigned char test[8];
int ret;

ret = p11prov_rand_generate(&rctx, test, 8, 0, 0, NULL, 0);
if (ret != RET_OSSL_OK) {
return CKR_FUNCTION_NOT_SUPPORTED;
}

return CKR_OK;
}
16 changes: 16 additions & 0 deletions src/random.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* Copyright (C) 2023 Simo Sorce <simo@redhat.com>
SPDX-License-Identifier: Apache-2.0 */

#ifndef _PKCS11_RANDOM_H
#define _PKCS11_RANDOM_H

#define DISPATCH_RAND_FN(name) DECL_DISPATCH_FUNC(rand, p11prov_rand, name)
#define DISPATCH_RAND_ELEM(prefix, NAME, name) \
{ \
OSSL_FUNC_RAND_##NAME, (void (*)(void))p11prov_##prefix##_##name \
}
extern const OSSL_DISPATCH p11prov_rand_functions[];

CK_RV p11prov_check_random(P11PROV_CTX *ctx);

#endif /* _PKCS11_RANDOM_H */
3 changes: 2 additions & 1 deletion tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ tmp.softhsm:
dist_check_SCRIPTS = \
helpers.sh setup-softhsm.sh setup-softokn.sh softhsm-proxy.sh \
test-wrapper tbasic tcerts tecc tecdh tedwards tdemoca thkdf \
toaepsha2 trsapss tdigest ttls tpubkey tfork turi
toaepsha2 trsapss tdigest ttls tpubkey tfork turi trand

test_LIST = \
basic-softokn basic-softhsm \
Expand All @@ -69,6 +69,7 @@ test_LIST = \
rsapss-softokn \
genkey-softokn genkey-softhsm \
session-softokn session-softhsm \
rand-softokn rand-softhsm \
readkeys-softokn readkeys-softhsm \
tls-softokn tls-softhsm \
uri-softokn uri-softhsm
Expand Down
1 change: 1 addition & 0 deletions tests/openssl.cnf.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ config_diagnostics = 1

[openssl_init]
providers = provider_sect
#MORECONF

[provider_sect]
default = default_sect
Expand Down
Loading