Skip to content

Commit

Permalink
encoder/decoder for Edwards curves
Browse files Browse the repository at this point in the history
Add the encoder and decoder methods for the ED25519 and Ed448 curves.

Signed-off-by: Florian Wernli <[email protected]>
  • Loading branch information
Florian Wernli committed Mar 6, 2024
1 parent 211dbe1 commit e7b7b13
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 81 deletions.
48 changes: 10 additions & 38 deletions src/decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,38 +149,6 @@ static int p11prov_der_decoder_p11prov_obj_decode(
return ret;
}

static int p11prov_der_decoder_p11prov_rsa_decode(
void *inctx, OSSL_CORE_BIO *cin, int selection, OSSL_CALLBACK *object_cb,
void *object_cbarg, OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
return p11prov_der_decoder_p11prov_obj_decode(
P11PROV_NAME_RSA, inctx, cin, selection, object_cb, object_cbarg, pw_cb,
pw_cbarg);
}

const OSSL_DISPATCH p11prov_der_decoder_p11prov_rsa_functions[] = {
DISPATCH_BASE_DECODER_ELEM(NEWCTX, newctx),
DISPATCH_BASE_DECODER_ELEM(FREECTX, freectx),
DISPATCH_DECODER_ELEM(DECODE, der, p11prov, rsa, decode),
{ 0, NULL }
};

static int p11prov_der_decoder_p11prov_ec_decode(
void *inctx, OSSL_CORE_BIO *cin, int selection, OSSL_CALLBACK *object_cb,
void *object_cbarg, OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
return p11prov_der_decoder_p11prov_obj_decode(
P11PROV_NAME_EC, inctx, cin, selection, object_cb, object_cbarg, pw_cb,
pw_cbarg);
}

const OSSL_DISPATCH p11prov_der_decoder_p11prov_ec_functions[] = {
DISPATCH_BASE_DECODER_ELEM(NEWCTX, newctx),
DISPATCH_BASE_DECODER_ELEM(FREECTX, freectx),
DISPATCH_DECODER_ELEM(DECODE, der, p11prov, ec, decode),
{ 0, NULL }
};

static int p11prov_pem_decoder_p11prov_der_decode(
void *inctx, OSSL_CORE_BIO *cin, int selection, OSSL_CALLBACK *object_cb,
void *object_cbarg, OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
Expand Down Expand Up @@ -232,9 +200,13 @@ static int p11prov_pem_decoder_p11prov_der_decode(
return ret;
}

const OSSL_DISPATCH p11prov_pem_decoder_p11prov_der_functions[] = {
DISPATCH_BASE_DECODER_ELEM(NEWCTX, newctx),
DISPATCH_BASE_DECODER_ELEM(FREECTX, freectx),
DISPATCH_DECODER_ELEM(DECODE, pem, p11prov, der, decode),
{ 0, NULL }
};
P11PROV_DER_COMMON_DECODE_FN(P11PROV_NAME_RSA, rsa)
P11PROV_DER_COMMON_DECODE_FN(P11PROV_NAME_EC, ec)
P11PROV_DER_COMMON_DECODE_FN(P11PROV_NAME_ED25519, ed25519)
P11PROV_DER_COMMON_DECODE_FN(P11PROV_NAME_ED448, ed448)

DISPATCH_DECODER_FN_LIST(pem, p11prov, der);
DISPATCH_DECODER_FN_LIST(der, p11prov, rsa);
DISPATCH_DECODER_FN_LIST(der, p11prov, ec);
DISPATCH_DECODER_FN_LIST(der, p11prov, ed25519);
DISPATCH_DECODER_FN_LIST(der, p11prov, ed448);
35 changes: 22 additions & 13 deletions src/decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,39 @@
#define RET_OSSL_STOP_DECODING 0

/* DECODERs */
#define DISPATCH_TEXT_DECODER_FN(type, name) \
static OSSL_FUNC_DECODER_##name##_fn p11prov_##type##_DECODER_##name##_text
#define DISPATCH_TEXT_DECODER_ELEM(NAME, type, name) \
{ \
OSSL_FUNC_DECODER_##NAME, \
(void (*)(void))p11prov_##type##_DECODER_##name \
}
#define DISPATCH_BASE_DECODER_FN(name) \
DECL_DISPATCH_FUNC(DECODER, p11prov_decoder_, name)
#define DISPATCH_BASE_DECODER_ELEM(NAME, name) \
{ \
OSSL_FUNC_DECODER_##NAME, (void (*)(void))p11prov_decoder_##name \
}
#define DISPATCH_DECODER_FN(type, structure, format, name) \
DECL_DISPATCH_FUNC(DECODER, \
p11prov_##type##_decoder_##structure##_##format, name)
#define DISPATCH_DECODER_ELEM(NAME, type, structure, format, name) \
{ \
OSSL_FUNC_DECODER_##NAME, \
(void (*)( \
void))p11prov_##type##_decoder_##structure##_##format##_##name \
}
#define DISPATCH_DECODER_FN_LIST(type, structure, format) \
const OSSL_DISPATCH \
p11prov_##type##_decoder_##structure##_##format##_functions[] = { \
DISPATCH_BASE_DECODER_ELEM(NEWCTX, newctx), \
DISPATCH_BASE_DECODER_ELEM(FREECTX, freectx), \
DISPATCH_DECODER_ELEM(DECODE, type, structure, format, decode), \
{ 0, NULL } \
};
#define P11PROV_DER_COMMON_DECODE_FN(FORMAT_NAME, format) \
static int p11prov_der_decoder_p11prov_##format##_decode( \
void *inctx, OSSL_CORE_BIO *cin, int selection, \
OSSL_CALLBACK *object_cb, void *object_cbarg, \
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) \
{ \
return p11prov_der_decoder_p11prov_obj_decode( \
FORMAT_NAME, inctx, cin, selection, object_cb, object_cbarg, \
pw_cb, pw_cbarg); \
}

extern const OSSL_DISPATCH p11prov_pem_decoder_p11prov_der_functions[];
extern const OSSL_DISPATCH p11prov_der_decoder_p11prov_rsa_functions[];
extern const OSSL_DISPATCH p11prov_der_decoder_p11prov_ec_functions[];
extern const OSSL_DISPATCH p11prov_pem_decoder_p11prov_der_functions[];
extern const OSSL_DISPATCH p11prov_der_decoder_p11prov_ed25519_functions[];
extern const OSSL_DISPATCH p11prov_der_decoder_p11prov_ed448_functions[];

#endif /* _DECODER_H */
52 changes: 32 additions & 20 deletions src/encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ static int p11prov_print_buf(BIO *out, const OSSL_PARAM *p, const char *str,
DISPATCH_BASE_ENCODER_FN(newctx);
DISPATCH_BASE_ENCODER_FN(freectx);

DISPATCH_ENCODER_FN(common, priv_key_info, pem, does_selection);

struct p11prov_encoder_ctx {
P11PROV_CTX *provctx;
};
Expand Down Expand Up @@ -552,15 +554,6 @@ static int p11prov_encoder_private_key_write_pem(
return ret;
}

static int p11prov_rsa_encoder_priv_key_info_pem_does_selection(void *inctx,
int selection)
{
if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) {
return RET_OSSL_OK;
}
return RET_OSSL_ERR;
}

static int p11prov_rsa_encoder_priv_key_info_pem_encode(
void *inctx, OSSL_CORE_BIO *cbio, const void *inkey,
const OSSL_PARAM key_abstract[], int selection,
Expand All @@ -573,7 +566,7 @@ static int p11prov_rsa_encoder_priv_key_info_pem_encode(
const OSSL_DISPATCH p11prov_rsa_encoder_priv_key_info_pem_functions[] = {
DISPATCH_BASE_ENCODER_ELEM(NEWCTX, newctx),
DISPATCH_BASE_ENCODER_ELEM(FREECTX, freectx),
DISPATCH_ENCODER_ELEM(DOES_SELECTION, rsa, priv_key_info, pem,
DISPATCH_ENCODER_ELEM(DOES_SELECTION, common, priv_key_info, pem,
does_selection),
DISPATCH_ENCODER_ELEM(ENCODE, rsa, priv_key_info, pem, encode),
{ 0, NULL },
Expand Down Expand Up @@ -919,15 +912,6 @@ const OSSL_DISPATCH p11prov_ec_encoder_text_functions[] = {
{ 0, NULL },
};

static int p11prov_ec_encoder_priv_key_info_pem_does_selection(void *inctx,
int selection)
{
if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) {
return RET_OSSL_OK;
}
return RET_OSSL_ERR;
}

static int p11prov_ec_encoder_priv_key_info_pem_encode(
void *inctx, OSSL_CORE_BIO *cbio, const void *inkey,
const OSSL_PARAM key_abstract[], int selection,
Expand All @@ -940,8 +924,36 @@ static int p11prov_ec_encoder_priv_key_info_pem_encode(
const OSSL_DISPATCH p11prov_ec_encoder_priv_key_info_pem_functions[] = {
DISPATCH_BASE_ENCODER_ELEM(NEWCTX, newctx),
DISPATCH_BASE_ENCODER_ELEM(FREECTX, freectx),
DISPATCH_ENCODER_ELEM(DOES_SELECTION, ec, priv_key_info, pem,
DISPATCH_ENCODER_ELEM(DOES_SELECTION, common, priv_key_info, pem,
does_selection),
DISPATCH_ENCODER_ELEM(ENCODE, ec, priv_key_info, pem, encode),
{ 0, NULL },
};

static int p11prov_ec_edwards_encoder_priv_key_info_pem_encode(
void *inctx, OSSL_CORE_BIO *cbio, const void *inkey,
const OSSL_PARAM key_abstract[], int selection,
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
{
return p11prov_encoder_private_key_write_pem(
CKK_EC_EDWARDS, inctx, cbio, inkey, key_abstract, selection, cb, cbarg);
}

const OSSL_DISPATCH p11prov_ec_edwards_encoder_priv_key_info_pem_functions[] = {
DISPATCH_BASE_ENCODER_ELEM(NEWCTX, newctx),
DISPATCH_BASE_ENCODER_ELEM(FREECTX, freectx),
DISPATCH_ENCODER_ELEM(DOES_SELECTION, common, priv_key_info, pem,
does_selection),
DISPATCH_ENCODER_ELEM(ENCODE, ec_edwards, priv_key_info, pem, encode),
{ 0, NULL },
};

static int
p11prov_common_encoder_priv_key_info_pem_does_selection(void *inctx,
int selection)
{
if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) {
return RET_OSSL_OK;
}
return RET_OSSL_ERR;
}
2 changes: 2 additions & 0 deletions src/encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,7 @@ extern const OSSL_DISPATCH p11prov_ec_encoder_pkcs1_der_functions[];
extern const OSSL_DISPATCH p11prov_ec_encoder_pkcs1_pem_functions[];
extern const OSSL_DISPATCH p11prov_ec_encoder_spki_der_functions[];
extern const OSSL_DISPATCH p11prov_ec_encoder_priv_key_info_pem_functions[];
extern const OSSL_DISPATCH
p11prov_ec_edwards_encoder_priv_key_info_pem_functions[];

#endif /* _ENCODER_H */
12 changes: 12 additions & 0 deletions src/provider.c
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,12 @@ static CK_RV operations_init(P11PROV_CTX *ctx)
ADD_ALGO_EXT(EC, encoder,
"provider=pkcs11,output=pem,structure=PrivateKeyInfo",
p11prov_ec_encoder_priv_key_info_pem_functions);
ADD_ALGO_EXT(ED25519, encoder,
"provider=pkcs11,output=pem,structure=PrivateKeyInfo",
p11prov_ec_edwards_encoder_priv_key_info_pem_functions);
ADD_ALGO_EXT(ED448, encoder,
"provider=pkcs11,output=pem,structure=PrivateKeyInfo",
p11prov_ec_edwards_encoder_priv_key_info_pem_functions);
}

TERM_ALGO(encoder);
Expand Down Expand Up @@ -1139,6 +1145,12 @@ static const OSSL_ALGORITHM p11prov_decoders[] = {
{ P11PROV_NAMES_EC,
"provider=pkcs11,input=der,structure=" P11PROV_DER_STRUCTURE,
p11prov_der_decoder_p11prov_ec_functions },
{ P11PROV_NAMES_ED25519,
"provider=pkcs11,input=der,structure=" P11PROV_DER_STRUCTURE,
p11prov_der_decoder_p11prov_ed25519_functions },
{ P11PROV_NAMES_ED448,
"provider=pkcs11,input=der,structure=" P11PROV_DER_STRUCTURE,
p11prov_der_decoder_p11prov_ed448_functions },
{ NULL, NULL, NULL }
};

Expand Down
60 changes: 50 additions & 10 deletions tests/tpem_encoder
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

source "${TESTSSRCDIR}/helpers.sh"

# Forward declaration to avoid shellcheck's SC2153 did you mean ...
: "${PRIURI:?}" "${ECPRIURI:?}" "${EDPRIURI:=}"
: "${PUBURI:?}" "${ECPUBURI:?}" "${EDPUBURI:=}"

# We need to configure early loading otherwise no digests are loaded,
# and all checks are skipped
sed -e "s/#pkcs11-module-encode-provider-uri-to-pem/pkcs11-module-encode-provider-uri-to-pem = true/" \
Expand Down Expand Up @@ -39,20 +43,34 @@ sign-verify() {
PRIV_KEY=$1
PUB_KEY=$2
FILE=$3
NO_DIGEST=$4

RANDOM_HEX=$(od -A n -N 15 -t x1 /dev/random)
TMP_FILE="${TMPPDIR}/sign-verify-pem-encoder-${RANDOM_HEX// /}.bin"

$CHECKER openssl pkeyutl -sign -rawin -digest sha256 \
-inkey "${PRIV_KEY}" \
-in "${FILE}" \
-out "${TMP_FILE}"

$CHECKER openssl pkeyutl -verify -rawin -digest sha256 \
-inkey "${PUB_KEY}" \
-pubin \
-in "${FILE}" \
-sigfile "${TMP_FILE}"
if [[ -z "${NO_DIGEST}" ]]; then
$CHECKER openssl pkeyutl -sign -rawin -digest sha256 \
-inkey "${PRIV_KEY}" \
-in "${FILE}" \
-out "${TMP_FILE}"

$CHECKER openssl pkeyutl -verify -rawin -digest sha256 \
-inkey "${PUB_KEY}" \
-pubin \
-in "${FILE}" \
-sigfile "${TMP_FILE}"
else
$CHECKER openssl pkeyutl -sign -rawin \
-inkey "${PRIV_KEY}" \
-in "${FILE}" \
-out "${TMP_FILE}"

$CHECKER openssl pkeyutl -verify -rawin \
-inkey "${PUB_KEY}" \
-pubin \
-in "${FILE}" \
-sigfile "${TMP_FILE}"
fi;

rm "${TMP_FILE}"
}
Expand Down Expand Up @@ -98,6 +116,28 @@ sign-verify "${TMPPDIR}/ec-pkey-uri.pem" \
"pkcs11:object=Test-PEM-Encode-EC-${LABEL_SUFFIX_URI}" \
"${TMPPDIR}/64krandom.bin"

# Only run ED test if setup created ed key
if [[ -n "${EDPRIURI}" ]]; then
title PARA "Test PEM Encoding ED support"

make-uri-pem "${EDPRIURI}" "${TMPPDIR}/ed25519priuri-pkey.pem"
sign-verify "${TMPPDIR}/ed25519priuri-pkey.pem" "${EDPUBURI}" "${TMPPDIR}/64krandom.bin" "no-digest"

export ALGORITHM=ED25519
ossl '
genpkey -propquery "provider=pkcs11"
-algorithm "${ALGORITHM}"
-pkeyopt "pkcs11_uri:pkcs11:object=Test-PEM-Encode-ED25519-${LABEL_SUFFIX_URI}"
-out "${TMPPDIR}/ed25519-pkey-uri.pem"'

grep -e "-----BEGIN PKCS#11 PROVIDER URI-----" "${TMPPDIR}/ed25519-pkey-uri.pem"

sign-verify "${TMPPDIR}/ed25519-pkey-uri.pem" \
"pkcs11:object=Test-PEM-Encode-ED25519-${LABEL_SUFFIX_URI}" \
"${TMPPDIR}/64krandom.bin" "no-digest"
else
title PARA "Skipping Test PEM Encoding ED support"
fi;

title PARA "Test visible string has to match"
make-uri-pem "${PRIURI}" "${TMPPDIR}/priuri-wrong-version-key.pem" "PKCS#11 Provider URI v2.0"
Expand Down

0 comments on commit e7b7b13

Please sign in to comment.