diff --git a/src/Makefile.am b/src/Makefile.am index c3110a95..1afb504d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,10 +5,12 @@ noinst_HEADERS = \ asymmetric_cipher.h \ debug.h \ encoder.h \ + decoder.h \ digests.h \ exchange.h \ kdf.h \ keymgmt.h \ + keypair_ref.h \ interface.h \ objects.h \ pkcs11.h \ @@ -30,10 +32,12 @@ pkcs11_la_SOURCES = \ asymmetric_cipher.c \ debug.c \ encoder.c \ + decoder.c \ digests.c \ exchange.c \ kdf.c \ keymgmt.c \ + keypair_ref.c \ interface.c \ objects.c \ provider.h \ diff --git a/src/decoder.c b/src/decoder.c new file mode 100644 index 00000000..adc09632 --- /dev/null +++ b/src/decoder.c @@ -0,0 +1,317 @@ +/* Copyright (C) 2023 Simo Sorce + SPDX-License-Identifier: Apache-2.0 +*/ + +#include "provider.h" +#include "decoder.h" +#include "keypair_ref.h" +#include +#include +#include +#include +#include +#include + +typedef struct p11prov_decoder_ctx { + P11PROV_CTX *provctx; + P11PROV_OBJ *active_object; +} P11PROV_DECODER_CTX; + +static void decoder_active_object_free(struct p11prov_decoder_ctx *ctx) +{ + if (ctx && ctx->active_object) { + p11prov_obj_free(ctx->active_object); + ctx->active_object = NULL; + } +} + +static OSSL_FUNC_decoder_newctx_fn p11prov_decoder_newctx; +static OSSL_FUNC_decoder_freectx_fn p11prov_decoder_freectx; + +static void *p11prov_decoder_newctx(void *provctx) +{ + P11PROV_CTX *cprov; + P11PROV_DECODER_CTX *dctx; + cprov = provctx; + dctx = OPENSSL_zalloc(sizeof(P11PROV_DECODER_CTX)); + if (dctx == NULL) return NULL; + + dctx->provctx = cprov; + return dctx; +} + +static void p11prov_decoder_freectx(void *inctx) +{ + P11PROV_DECODER_CTX *ctx = inctx; + + decoder_active_object_free(ctx); + OPENSSL_clear_free(ctx, sizeof(P11PROV_DECODER_CTX)); +} + +static CK_RV p11prov_decoder_ctx_store_obj(void *pctx, P11PROV_OBJ *obj) +{ + P11PROV_DECODER_CTX *ctx = pctx; + + if (ctx->active_object != NULL) { + P11PROV_raise(ctx->provctx, CKR_GENERAL_ERROR, + "More than one matching object found"); + decoder_active_object_free(ctx); + return CKR_GENERAL_ERROR; + } + + P11PROV_debug("Adding object (handle:%lu)", p11prov_obj_get_handle(obj)); + + if (p11prov_obj_get_class(obj) != CKO_PRIVATE_KEY) { + P11PROV_raise(ctx->provctx, CKR_ARGUMENTS_BAD, + "Object must be private key"); + return CKR_ARGUMENTS_BAD; + } + + ctx->active_object = obj; + + return CKR_OK; +} + +static CK_RV p11prov_decoder_load_key(P11PROV_DECODER_CTX *ctx, + const char *inuri, + OSSL_PASSPHRASE_CALLBACK *pw_cb, + void *pw_cbarg) +{ + P11PROV_URI *parsed_uri = NULL; + CK_RV ret = CKR_GENERAL_ERROR; + P11PROV_SESSION *session; + + if (ctx->active_object) { + P11PROV_debug("This should not happen!"); + P11PROV_raise(ctx->provctx, CKR_GENERAL_ERROR, "Invalid initial state"); + goto done; + } + + parsed_uri = p11prov_parse_uri(ctx->provctx, inuri); + if (parsed_uri == NULL) { + P11PROV_raise(ctx->provctx, CKR_GENERAL_ERROR, "Failed to parse URI"); + goto done; + } + + ret = p11prov_ctx_status(ctx->provctx); + if (ret != CKR_OK) { + P11PROV_raise(ctx->provctx, ret, "Invalid context status"); + } + + CK_SLOT_ID slotid = CK_UNAVAILABLE_INFORMATION; + ret = p11prov_get_session(ctx->provctx, &slotid, NULL, parsed_uri, + CK_UNAVAILABLE_INFORMATION, pw_cb, pw_cbarg, true, + false, &session); + if (ret != CKR_OK) { + P11PROV_raise(ctx->provctx, ret, "Failed to get session to load keys"); + goto done; + } + + ret = p11prov_obj_find(ctx->provctx, session, slotid, parsed_uri, + p11prov_decoder_ctx_store_obj, ctx); + if (ret != CKR_OK) { + P11PROV_raise(ctx->provctx, ret, "Failed to find matching object"); + goto done; + } + + if (!ctx->active_object) { + ret = CKR_ARGUMENTS_BAD; + P11PROV_raise(ctx->provctx, ret, "No matching object stored"); + goto done; + } + + if (p11prov_obj_get_class(ctx->active_object) != CKO_PRIVATE_KEY) { + ret = CKR_ARGUMENTS_BAD; + P11PROV_raise(ctx->provctx, ret, + "Referenced object is not a private key"); + goto done; + } + +done: + p11prov_uri_free(parsed_uri); + + P11PROV_debug("Done (result:%d)", ret); + return ret; +} + +static int +p11prov_decoder_decode_p11key(CK_KEY_TYPE desired_key_type, void *inctx, + OSSL_CORE_BIO *cin, int selection, + OSSL_CALLBACK *object_cb, void *object_cbarg, + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) +{ + P11PROV_DECODER_CTX *ctx = inctx; + P11PROV_KEYPAIR_REF *key = NULL; + BIO *bin; + int ret = 0; + const char *uri = NULL; + + P11PROV_debug("P11 KEY DECODER DECODE (selection:0x%x)", selection); + if ((bin = BIO_new_from_core_bio(p11prov_ctx_get_libctx(ctx->provctx), cin)) + == NULL) { + P11PROV_debug("P11 KEY DECODER BIO_new_from_core_bio failed"); + goto done; + } + + const char *data_type = NULL; + switch (desired_key_type) { + case CKK_RSA: + data_type = P11PROV_NAME_RSA; + break; + case CKK_EC: + data_type = P11PROV_NAME_EC; + break; + default: + ret = 0; + P11PROV_raise(ctx->provctx, CKR_ARGUMENTS_BAD, "Unsupported key type"); + goto done; + } + + const unsigned char *der; + long der_len = BIO_get_mem_data(bin, &der); + if (der_len <= 0) { + P11PROV_debug("P11 KEY DECODER BIO_get_mem_data failed"); + ret = 1; + goto done; + } + if ((key = d2i_P11PROV_KEYPAIR_REF(NULL, &der, der_len)) == NULL) { + P11PROV_debug("P11 KEY DECODER d2i_P11PROV_KEYPAIR_REF failed"); + ret = 1; + goto done; + } + + char oid_txt[64]; + if (OBJ_obj2txt(oid_txt, sizeof(oid_txt), key->type, 1) > 0) { + P11PROV_debug("P11 KEY DECODER got OID %s", oid_txt); + } else { + P11PROV_debug("P11 KEY DECODER OBJ_obj2txt failed"); + goto done; + } + + uri = (const char *)ASN1_STRING_get0_data(key->uri); + if (uri == NULL) { + P11PROV_raise(ctx->provctx, CKR_GENERAL_ERROR, "Failed to get URI"); + goto done; + } + + if (p11prov_decoder_load_key(ctx, uri, pw_cb, pw_cbarg) != CKR_OK) { + P11PROV_debug("P11 KEY DECODER p11prov_decoder_load_key failed"); + goto done; + } + + if (p11prov_obj_get_key_type(ctx->active_object) != desired_key_type) { + P11PROV_debug( + "P11 KEY DECODER p11prov_decoder_load_key wrong key type"); + ret = 1; + goto done; + } + + P11PROV_debug("P11 KEY DECODER p11prov_decoder_load_key OK"); + + void *key_reference = NULL; + size_t key_reference_sz = 0; + p11prov_obj_to_store_reference(ctx->active_object, &key_reference, + &key_reference_sz); + + int object_type = OSSL_OBJECT_PKEY; + OSSL_PARAM params[4]; + params[0] = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &object_type); + params[1] = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE, + (char *)data_type, 0); + /* The address of the key becomes the octet string */ + params[2] = OSSL_PARAM_construct_octet_string( + OSSL_OBJECT_PARAM_REFERENCE, key_reference, key_reference_sz); + params[3] = OSSL_PARAM_construct_end(); + object_cb(params, object_cbarg); + +done: + decoder_active_object_free(ctx); + P11PROV_KEYPAIR_REF_free(key); + BIO_free(bin); + P11PROV_debug("P11 KEY DECODER RESULT=%d", ret); + return ret; +} + +static int p11prov_der_decoder_p11_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_decoder_decode_p11key(CKK_RSA, inctx, cin, selection, + object_cb, object_cbarg, pw_cb, + pw_cbarg); +} + +const OSSL_DISPATCH p11prov_der_decoder_p11_rsa_functions[] = { + DISPATCH_BASE_DECODER_ELEM(NEWCTX, newctx), + DISPATCH_BASE_DECODER_ELEM(FREECTX, freectx), + DISPATCH_DECODER_ELEM(DECODE, der, p11, rsa, decode), + { 0, NULL } +}; + +static int p11prov_der_decoder_p11_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_decoder_decode_p11key(CKK_EC, inctx, cin, selection, + object_cb, object_cbarg, pw_cb, + pw_cbarg); +} + +const OSSL_DISPATCH p11prov_der_decoder_p11_ec_functions[] = { + DISPATCH_BASE_DECODER_ELEM(NEWCTX, newctx), + DISPATCH_BASE_DECODER_ELEM(FREECTX, freectx), + DISPATCH_DECODER_ELEM(DECODE, der, p11, ec, decode), + { 0, NULL } +}; + +static int p11prov_pem_decoder_p11_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) +{ + + BIO *bin; + char *pem_name; + char *pem_header; + unsigned char *der_data; + long der_len; + OSSL_PARAM params[3]; + int ret; + P11PROV_DECODER_CTX *ctx = inctx; + + P11PROV_debug("DER DECODER DECODE (selection:0x%x)", selection); + + if ((bin = BIO_new_from_core_bio(p11prov_ctx_get_libctx(ctx->provctx), cin)) + == NULL) { + P11PROV_debug("BIO_new_from_core_bio failed"); + return 0; + } + P11PROV_debug("DER DECODER PEM_read_pio (fpos:%u)", BIO_tell(bin)); + + if (PEM_read_bio(bin, &pem_name, &pem_header, &der_data, &der_len) > 0 + && strcmp(pem_name, P11PROV_PRIVKEY_PEM_NAME) == 0) { + params[0] = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA, + der_data, der_len); + params[1] = OSSL_PARAM_construct_utf8_string( + OSSL_OBJECT_PARAM_DATA_STRUCTURE, (char *)"P11", 0); + params[2] = OSSL_PARAM_construct_end(); + ret = object_cb(params, object_cbarg); + } else { + /* We return "empty handed". This is not an error. */ + ret = 1; + } + + OPENSSL_free(pem_name); + OPENSSL_free(pem_header); + OPENSSL_free(der_data); + BIO_free(bin); + + P11PROV_debug("DER DECODER RESULT=%d", ret); + return ret; +} + +const OSSL_DISPATCH p11prov_pem_decoder_p11_der_functions[] = { + DISPATCH_BASE_DECODER_ELEM(NEWCTX, newctx), + DISPATCH_BASE_DECODER_ELEM(FREECTX, freectx), + DISPATCH_DECODER_ELEM(DECODE, pem, p11, der, decode), + { 0, NULL } +}; diff --git a/src/decoder.h b/src/decoder.h new file mode 100644 index 00000000..2004617f --- /dev/null +++ b/src/decoder.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2022 Simo Sorce + SPDX-License-Identifier: Apache-2.0 */ + +#ifndef _DECODER_H +#define _DECODER_H + +#include + +/* 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 \ + } +extern const OSSL_DISPATCH p11prov_der_decoder_p11_rsa_functions[]; +extern const OSSL_DISPATCH p11prov_der_decoder_p11_ec_functions[]; +extern const OSSL_DISPATCH p11prov_pem_decoder_p11_der_functions[]; + +#endif /* _DECODER_H */ diff --git a/src/encoder.c b/src/encoder.c index 1de54cc6..bc5beb5c 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -2,6 +2,7 @@ SPDX-License-Identifier: Apache-2.0 */ #include "provider.h" +#include "keypair_ref.h" #include #include #include @@ -463,6 +464,109 @@ const OSSL_DISPATCH p11prov_rsa_encoder_spki_pem_functions[] = { { 0, NULL }, }; +static P11PROV_KEYPAIR_REF * +p11prov_encoder_private_key_to_asn1(P11PROV_CTX *pctx, P11PROV_OBJ *key) +{ + P11PROV_KEYPAIR_REF *out = NULL; + + char *uri = p11prov_key_to_uri(pctx, key); + if (!uri) goto error; + + size_t uri_len = strlen(uri); + P11PROV_debug("uri=%s", uri); + + out = P11PROV_KEYPAIR_REF_new(); + if (!out) goto error; + + out->type = OBJ_txt2obj(P11PROV_OID_URI, 1); + ASN1_STRING_set(out->uri, uri, uri_len); + + goto done; + +error: + P11PROV_KEYPAIR_REF_free(out); + out = NULL; + +done: + return out; +} + +static int p11prov_encoder_private_key_write_pem( + CK_KEY_TYPE expected_key_type, void *inctx, OSSL_CORE_BIO *cbio, + const void *inkey, const OSSL_PARAM key_abstract[], int selection, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + struct p11prov_encoder_ctx *ctx = (struct p11prov_encoder_ctx *)inctx; + P11PROV_OBJ *key = (P11PROV_OBJ *)inkey; + CK_KEY_TYPE key_type; + P11PROV_KEYPAIR_REF *asn1 = NULL; + BIO *out = NULL; + int ret; + + key_type = p11prov_obj_get_key_type(key); + if (key_type != expected_key_type) { + P11PROV_raise(ctx->provctx, CKR_GENERAL_ERROR, + "Key type mismatch (actual:%lu,expected:%lu)", key_type, + expected_key_type); + ret = RET_OSSL_ERR; + goto done; + } + + asn1 = p11prov_encoder_private_key_to_asn1(ctx->provctx, key); + if (!asn1) { + P11PROV_raise(ctx->provctx, CKR_GENERAL_ERROR, + "Failed to encode private key"); + ret = RET_OSSL_ERR; + goto done; + } + + out = BIO_new_from_core_bio(p11prov_ctx_get_libctx(ctx->provctx), cbio); + if (!out) { + P11PROV_raise(ctx->provctx, CKR_GENERAL_ERROR, "Failed to init BIO"); + ret = RET_OSSL_ERR; + goto done; + } + + ret = PEM_write_bio_P11PROV_KEYPAIR_REF(out, asn1); + if (ret != RET_OSSL_OK) { + P11PROV_raise(ctx->provctx, CKR_GENERAL_ERROR, + "Failed to write BIO PEM"); + goto done; + } + +done: + P11PROV_KEYPAIR_REF_free(asn1); + BIO_free(out); + 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, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return p11prov_encoder_private_key_write_pem( + CKK_RSA, inctx, cbio, inkey, key_abstract, selection, cb, cbarg); +} + +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, + does_selection), + DISPATCH_ENCODER_ELEM(ENCODE, rsa, priv_key_info, pem, encode), + { 0, NULL }, +}; + /* ECDSA */ struct ecdsa_key_point { @@ -802,3 +906,30 @@ const OSSL_DISPATCH p11prov_ec_encoder_text_functions[] = { DISPATCH_TEXT_ENCODER_ELEM(ENCODE, ec, encode_text), { 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, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return p11prov_encoder_private_key_write_pem( + CKK_EC, inctx, cbio, inkey, key_abstract, selection, cb, cbarg); +} + +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, + does_selection), + DISPATCH_ENCODER_ELEM(ENCODE, ec, priv_key_info, pem, encode), + { 0, NULL }, +}; diff --git a/src/encoder.h b/src/encoder.h index 1e4b2944..02684441 100644 --- a/src/encoder.h +++ b/src/encoder.h @@ -32,9 +32,11 @@ extern const OSSL_DISPATCH p11prov_rsa_encoder_pkcs1_der_functions[]; extern const OSSL_DISPATCH p11prov_rsa_encoder_pkcs1_pem_functions[]; extern const OSSL_DISPATCH p11prov_rsa_encoder_spki_der_functions[]; extern const OSSL_DISPATCH p11prov_rsa_encoder_spki_pem_functions[]; +extern const OSSL_DISPATCH p11prov_rsa_encoder_priv_key_info_pem_functions[]; extern const OSSL_DISPATCH p11prov_ec_encoder_text_functions[]; 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[]; #endif /* _ENCODER_H */ diff --git a/src/keypair_ref.c b/src/keypair_ref.c new file mode 100644 index 00000000..a9e84da8 --- /dev/null +++ b/src/keypair_ref.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2022 Simo Sorce + SPDX-License-Identifier: Apache-2.0 */ + +#include "keypair_ref.h" +#include + +#include "keypair_ref.gen.c" diff --git a/src/keypair_ref.gen.c b/src/keypair_ref.gen.c new file mode 100644 index 00000000..03a6e590 --- /dev/null +++ b/src/keypair_ref.gen.c @@ -0,0 +1,70 @@ +/* DO NOT EDIT, autogenerated from src/keypair_ref.pre */ +/* Modify src/keypair_ref.pre then run make generate-code */ + +extern P11PROV_KEYPAIR_REF *P11PROV_KEYPAIR_REF_new(void); +extern void P11PROV_KEYPAIR_REF_free(P11PROV_KEYPAIR_REF *a); +extern P11PROV_KEYPAIR_REF *d2i_P11PROV_KEYPAIR_REF(P11PROV_KEYPAIR_REF **a, + const unsigned char **in, + long len); +extern int i2d_P11PROV_KEYPAIR_REF(const P11PROV_KEYPAIR_REF *a, + unsigned char **out); +extern const ASN1_ITEM *P11PROV_KEYPAIR_REF_it(void); +P11PROV_KEYPAIR_REF *d2i_P11PROV_KEYPAIR_REF(P11PROV_KEYPAIR_REF **a, + const unsigned char **in, long len) +{ + return (P11PROV_KEYPAIR_REF *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + (P11PROV_KEYPAIR_REF_it())); +} +int i2d_P11PROV_KEYPAIR_REF(const P11PROV_KEYPAIR_REF *a, unsigned char **out) +{ + return ASN1_item_i2d((const ASN1_VALUE *)a, out, + (P11PROV_KEYPAIR_REF_it())); +} +P11PROV_KEYPAIR_REF *P11PROV_KEYPAIR_REF_new(void) +{ + return (P11PROV_KEYPAIR_REF *)ASN1_item_new((P11PROV_KEYPAIR_REF_it())); +} +void P11PROV_KEYPAIR_REF_free(P11PROV_KEYPAIR_REF *a) +{ + ASN1_item_free((ASN1_VALUE *)a, (P11PROV_KEYPAIR_REF_it())); +} + +static const ASN1_TEMPLATE P11PROV_KEYPAIR_REF_seq_tt[] = { + { (0), (0), __builtin_offsetof(P11PROV_KEYPAIR_REF, type), "type", + (ASN1_OBJECT_it) }, + { (0), (0), __builtin_offsetof(P11PROV_KEYPAIR_REF, uri), "uri", + (ASN1_UTF8STRING_it) }, +}; +const ASN1_ITEM *P11PROV_KEYPAIR_REF_it(void) +{ + static const ASN1_ITEM local_it = { 0x1, + 16, + P11PROV_KEYPAIR_REF_seq_tt, + sizeof(P11PROV_KEYPAIR_REF_seq_tt) + / sizeof(ASN1_TEMPLATE), + ((void *)0), + sizeof(P11PROV_KEYPAIR_REF), + "P11PROV_KEYPAIR_REF" }; + return &local_it; +} + +extern int PEM_write_bio_P11PROV_KEYPAIR_REF(BIO *out, + const P11PROV_KEYPAIR_REF *x); +int PEM_write_bio_P11PROV_KEYPAIR_REF(BIO *out, const P11PROV_KEYPAIR_REF *x) +{ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_P11PROV_KEYPAIR_REF, + P11PROV_PRIVKEY_PEM_NAME, out, x, ((void *)0), + ((void *)0), 0, ((void *)0), ((void *)0)); +} + +extern P11PROV_KEYPAIR_REF * +PEM_read_bio_P11PROV_KEYPAIR_REF(BIO *out, P11PROV_KEYPAIR_REF **x, + pem_password_cb *cb, void *u); +P11PROV_KEYPAIR_REF *PEM_read_bio_P11PROV_KEYPAIR_REF(BIO *bp, + P11PROV_KEYPAIR_REF **x, + pem_password_cb *cb, + void *u) +{ + return PEM_ASN1_read_bio((d2i_of_void *)d2i_P11PROV_KEYPAIR_REF, + P11PROV_PRIVKEY_PEM_NAME, bp, (void **)x, cb, u); +} diff --git a/src/keypair_ref.h b/src/keypair_ref.h new file mode 100644 index 00000000..c83c208e --- /dev/null +++ b/src/keypair_ref.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2022 Simo Sorce + SPDX-License-Identifier: Apache-2.0 */ + +#ifndef _KEYPAIR_REF_H +#define _KEYPAIR_REF_H + +#include + +#define P11PROV_PRIVKEY_PEM_NAME "P11 PRIVATE KEY" +#define P11PROV_OID_URI "2.5.4.83" /* TODO: find a more appropriate oId */ + +typedef struct { + ASN1_OBJECT *type; + ASN1_UTF8STRING *uri; +} P11PROV_KEYPAIR_REF; + +extern P11PROV_KEYPAIR_REF *P11PROV_KEYPAIR_REF_new(void); +extern void P11PROV_KEYPAIR_REF_free(P11PROV_KEYPAIR_REF *a); +extern P11PROV_KEYPAIR_REF *d2i_P11PROV_KEYPAIR_REF(P11PROV_KEYPAIR_REF **a, + const unsigned char **in, + long len); +extern P11PROV_KEYPAIR_REF * +PEM_read_bio_P11PROV_KEYPAIR_REF(BIO *out, P11PROV_KEYPAIR_REF **x, + pem_password_cb *cb, void *u); +extern int PEM_write_bio_P11PROV_KEYPAIR_REF(BIO *out, + const P11PROV_KEYPAIR_REF *x); + +#endif diff --git a/src/keypair_ref.pre b/src/keypair_ref.pre new file mode 100644 index 00000000..a05ac890 --- /dev/null +++ b/src/keypair_ref.pre @@ -0,0 +1,23 @@ +/* Copyright (C) 2022 Simo Sorce + SPDX-License-Identifier: Apache-2.0 */ + +#include +#include + +BEGIN: + +DECLARE_ASN1_FUNCTIONS(P11PROV_KEYPAIR_REF) +IMPLEMENT_ASN1_FUNCTIONS(P11PROV_KEYPAIR_REF) + +ASN1_SEQUENCE(P11PROV_KEYPAIR_REF) = { + ASN1_SIMPLE(P11PROV_KEYPAIR_REF, type, ASN1_OBJECT), + ASN1_SIMPLE(P11PROV_KEYPAIR_REF, uri, ASN1_UTF8STRING), +} ASN1_SEQUENCE_END(P11PROV_KEYPAIR_REF) + +DECLARE_PEM_write_bio(P11PROV_KEYPAIR_REF, P11PROV_KEYPAIR_REF) +IMPLEMENT_PEM_write_bio(P11PROV_KEYPAIR_REF, P11PROV_KEYPAIR_REF, + P11PROV_PRIVKEY_PEM_NAME, P11PROV_KEYPAIR_REF) + +DECLARE_PEM_read_bio(P11PROV_KEYPAIR_REF, P11PROV_KEYPAIR_REF) +IMPLEMENT_PEM_read_bio(P11PROV_KEYPAIR_REF, P11PROV_KEYPAIR_REF, + P11PROV_PRIVKEY_PEM_NAME, P11PROV_KEYPAIR_REF) diff --git a/src/provider.c b/src/provider.c index f4c33107..0fe28834 100644 --- a/src/provider.c +++ b/src/provider.c @@ -2,6 +2,7 @@ SPDX-License-Identifier: Apache-2.0 */ #include "provider.h" +#include "decoder.h" #include #include @@ -1045,6 +1046,9 @@ static CK_RV operations_init(P11PROV_CTX *ctx) p11prov_rsa_encoder_pkcs1_der_functions); ADD_ALGO_EXT(RSA, encoder, "provider=pkcs11,output=pem,structure=pkcs1", p11prov_rsa_encoder_pkcs1_pem_functions); + ADD_ALGO_EXT(RSAKEY, encoder, + "provider=pkcs11,output=pem,structure=PrivateKeyInfo", + p11prov_rsa_encoder_priv_key_info_pem_functions); ADD_ALGO_EXT(RSA, encoder, "provider=pkcs11,output=der,structure=SubjectPublicKeyInfo", p11prov_rsa_encoder_spki_der_functions); @@ -1057,6 +1061,9 @@ static CK_RV operations_init(P11PROV_CTX *ctx) p11prov_ec_encoder_pkcs1_der_functions); ADD_ALGO_EXT(EC, encoder, "provider=pkcs11,output=pem,structure=pkcs1", p11prov_ec_encoder_pkcs1_pem_functions); + ADD_ALGO_EXT(EC, encoder, + "provider=pkcs11,output=pem,structure=PrivateKeyInfo", + p11prov_ec_encoder_priv_key_info_pem_functions); ADD_ALGO_EXT(EC, encoder, "provider=pkcs11,output=der,structure=SubjectPublicKeyInfo", p11prov_ec_encoder_spki_der_functions); @@ -1098,6 +1105,16 @@ static const OSSL_ALGORITHM p11prov_store[] = { { NULL, NULL, NULL, NULL }, }; +static const OSSL_ALGORITHM p11prov_decoders[] = { + { "DER", "provider=pkcs11,input=pem", + p11prov_pem_decoder_p11_der_functions }, + { "RSA:rsaEncryption", "provider=pkcs11,input=der,structure=P11", + p11prov_der_decoder_p11_rsa_functions }, + { "EC:id-ecPublicKey", "provider=pkcs11,input=der,structure=P11", + p11prov_der_decoder_p11_ec_functions }, + { NULL, NULL, NULL } +}; + static const OSSL_ALGORITHM * p11prov_query_operation(void *provctx, int operation_id, int *no_cache) { @@ -1120,6 +1137,8 @@ p11prov_query_operation(void *provctx, int operation_id, int *no_cache) return ctx->op_asym_cipher; case OSSL_OP_ENCODER: return ctx->op_encoder; + case OSSL_OP_DECODER: + return p11prov_decoders; case OSSL_OP_STORE: return p11prov_store; } diff --git a/src/provider.h b/src/provider.h index ad43051c..081e3a2e 100644 --- a/src/provider.h +++ b/src/provider.h @@ -57,6 +57,8 @@ #define P11PROV_DESCS_ED448 "PKCS11 ED448 Implementation" #define P11PROV_NAMES_RAND "PKCS11-RAND" #define P11PROV_DESCS_RAND "PKCS11 Random Generator" +#define P11PROV_NAMES_RSAKEY "RSA" +#define P11PROV_DESCS_RSAKEY "PKCS11 RSA KEY" #define P11PROV_PARAM_URI "pkcs11_uri" #define P11PROV_PARAM_KEY_USAGE "pkcs11_key_usage"