libekmfweb: Make use of the new libseckey

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Ingo Franzki
2021-04-08 11:51:54 +02:00
committed by Jan Höppner
parent e70cde2c5d
commit 26c34a49b1
6 changed files with 308 additions and 2987 deletions

View File

@@ -21,17 +21,31 @@ else
INSTALL_TARGETS += skip-libekmfweb-openssl
endif
libs = $(rootdir)/libutil/libutil.a
libs = $(rootdir)/libseckey/libseckey.a
TMPFILE := $(shell mktemp)
detect-openssl-version.dep:
echo "#include <openssl/opensslv.h>" > detect-openssl-version.dep
echo "#include <openssl/evp.h>" >> detect-openssl-version.dep
echo "#if OPENSSL_VERSION_NUMBER < 0x10101000L" >> detect-openssl-version.dep
echo " #error openssl version 1.1.1 is required" >> detect-openssl-version.dep
echo "#endif" >> detect-openssl-version.dep
echo "static void __attribute__((unused)) test(void) {" >> detect-openssl-version.dep
echo " EVP_PKEY_meth_remove(NULL);" >> detect-openssl-version.dep
echo "}" >> detect-openssl-version.dep
echo "#include <openssl/opensslv.h>" > $(TMPFILE)
echo "#include <openssl/evp.h>" >> $(TMPFILE)
echo "#ifndef OPENSSL_VERSION_PREREQ" >> $(TMPFILE)
echo " #if defined(OPENSSL_VERSION_MAJOR) && defined(OPENSSL_VERSION_MINOR)" >> $(TMPFILE)
echo " #define OPENSSL_VERSION_PREREQ(maj, min) \\" >> $(TMPFILE)
echo " ((OPENSSL_VERSION_MAJOR << 16) + \\" >> $(TMPFILE)
echo " OPENSSL_VERSION_MINOR >= ((maj) << 16) + (min))" >> $(TMPFILE)
echo " #else" >> $(TMPFILE)
echo " #define OPENSSL_VERSION_PREREQ(maj, min) \\" >> $(TMPFILE)
echo " (OPENSSL_VERSION_NUMBER >= (((maj) << 28) | \\" >> $(TMPFILE)
echo " ((min) << 20)))" >> $(TMPFILE)
echo " #endif" >> $(TMPFILE)
echo "#endif" >> $(TMPFILE)
echo "#if !OPENSSL_VERSION_PREREQ(1, 1)" >> $(TMPFILE)
echo " #error openssl version 1.1 is required" >> $(TMPFILE)
echo "#endif" >> $(TMPFILE)
echo "static void __attribute__((unused)) test(void) {" >> $(TMPFILE)
echo " EVP_PKEY_meth_remove(NULL);" >> $(TMPFILE)
echo "}" >> $(TMPFILE)
mv $(TMPFILE) $@
check-dep-libekmfweb: detect-openssl-version.dep
$(call check_dep, \
@@ -39,7 +53,7 @@ check-dep-libekmfweb: detect-openssl-version.dep
"detect-openssl-version.dep", \
"openssl-devel version >= 1.1.1", \
"HAVE_OPENSSL=0", \
-I. -lcrypto)
-I. -lcrypto -DOPENSSL_SUPPRESS_DEPRECATED)
$(call check_dep, \
"libekmfweb", \
"json-c/json.h", \
@@ -73,7 +87,7 @@ libekmfweb.so.$(VERSION): ALL_CFLAGS += -fPIC `curl-config --cflags`
libekmfweb.so.$(VERSION): LDLIBS = -ljson-c -lcrypto -lssl `curl-config --libs` -ldl
libekmfweb.so.$(VERSION): ALL_LDFLAGS += -shared -Wl,--version-script=libekmfweb.map \
-Wl,-z,defs,-Bsymbolic -Wl,-soname,libekmfweb.so.$(VERM)
libekmfweb.so.$(VERSION): ekmfweb.o utilities.o cca.o
libekmfweb.so.$(VERSION): ekmfweb.o utilities.o cca.o $(libs)
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
ln -srf libekmfweb.so.$(VERSION) libekmfweb.so.$(VERM)
ln -srf libekmfweb.so.$(VERSION) libekmfweb.so

File diff suppressed because it is too large Load Diff

View File

@@ -19,21 +19,6 @@
#include "ekmfweb/ekmfweb.h"
/* CCA PKA Key Generate function */
typedef void (*CSNDPKG_t)(long *return_code,
long *reason_code,
long *exit_data_length,
unsigned char *exit_data,
long *rule_array_count,
unsigned char *rule_array,
long *regeneration_data_length,
unsigned char *regeneration_data,
long *skeleton_key_token_length,
unsigned char *skeleton_key_token,
unsigned char *transport_key_identifier,
long *generated_key_identifier_length,
unsigned char *generated_key_identifier);
/* CCA PKA Key Token Build function */
typedef void (*CSNDPKB_t)(long *return_code,
long *reason_code,
@@ -57,31 +42,6 @@ typedef void (*CSNDPKB_t)(long *return_code,
unsigned char *reserved_5,
long *token_length, unsigned char *token);
/* CCA PKA Key Token Change function */
typedef void (*CSNDKTC_t)(long *return_code,
long *reason_code,
long *exit_data_length,
unsigned char *exit_data,
long *rule_array_count,
unsigned char *rule_array,
long *key_identifier_length,
unsigned char *key_identifier);
/* CCA Digital Signature Generate function */
typedef void (*CSNDDSG_t)(long *return_code,
long *reason_code,
long *exit_data_length,
unsigned char *exit_data,
long *rule_array_count,
unsigned char *rule_array,
long *PKA_private_key_identifier_length,
unsigned char *PKA_private_key_identifier,
long *hash_length,
unsigned char *hash,
long *signature_field_length,
long *signature_bit_length,
unsigned char *signature_field);
/* CCA Key Token Build2 function */
typedef void (*CSNBKTB2_t)(long *return_code,
long *reason_code,
@@ -153,9 +113,6 @@ typedef void (*CSNDSYI2_t)(long *return_code,
struct cca_lib {
CSNDPKB_t dll_CSNDPKB;
CSNDPKG_t dll_CSNDPKG;
CSNDKTC_t dll_CSNDKTC;
CSNDDSG_t dll_CSNDDSG;
CSNBKTB2_t dll_CSNBKTB2;
CSNDEDH_t dll_CSNDEDH;
CSNDSYI2_t dll_CSNDSYI2;
@@ -164,34 +121,6 @@ struct cca_lib {
#define CCA_MAX_PKA_KEY_TOKEN_SIZE 3500
#define CCA_MAX_SYM_KEY_TOKEN_SIZE 725
int cca_generate_ecc_key_pair(const struct ekmf_cca_lib *cca_lib,
int curve_nid, unsigned char *key_token,
size_t *key_token_length, bool verbose);
int cca_generate_rsa_key_pair(const struct ekmf_cca_lib *cca_lib,
size_t modulus_bits, unsigned int pub_exp,
unsigned char *key_token,
size_t *key_token_length, bool verbose);
int cca_get_key_type(const unsigned char *key_token, size_t key_token_length,
int *pkey_type);
int cca_reencipher_key(const struct ekmf_cca_lib *cca_lib,
const unsigned char *key_token, size_t key_token_length,
bool to_new, bool verbose);
int cca_get_ecc_pub_key_as_pkey(const unsigned char *key_token,
size_t key_token_length,
EVP_PKEY **pkey, bool verbose);
int cca_get_ecc_pub_key_as_json_web_key(const unsigned char *key_token,
size_t key_token_length,
json_object **jwk, bool verbose);
int cca_get_rsa_pub_key_as_pkey(const unsigned char *key_token,
size_t key_token_length,
int pkey_type, EVP_PKEY **pkey, bool verbose);
int cca_import_key_from_json_web_key(const struct ekmf_cca_lib *cca_lib,
json_object *jwk, unsigned char *key_token,
size_t *key_token_length, bool verbose);
@@ -225,23 +154,4 @@ int cca_import_external_key(const struct ekmf_cca_lib *cca_lib,
size_t *imported_key_token_length,
bool verbose);
int cca_rsa_sign(const struct ekmf_cca_lib *cca_lib,
const unsigned char *key_token, size_t key_token_length,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen,
int padding_type, int digest_nid, bool verbose);
int cca_rsa_pss_sign(const struct ekmf_cca_lib *cca_lib,
const unsigned char *key_token, size_t key_token_length,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen,
int digest_nid, int mgf_digest_nid, int saltlen,
bool verbose);
int cca_ecdsa_sign(const struct ekmf_cca_lib *cca_lib,
const unsigned char *key_token, size_t key_token_length,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen, int digest_nid,
bool verbose);
#endif

View File

@@ -31,12 +31,12 @@
#include "lib/zt_common.h"
#include "libseckey/sk_openssl.h"
#include "ekmfweb/ekmfweb.h"
#include "utilities.h"
#include "cca.h"
#define SERIAL_NUMBER_BIT_SIZE 159
#define DEFAULT_SESSION_EC_KEY_CURVE NID_secp521r1
#define MAX_KEY_BLOB_SIZE CCA_MAX_PKA_KEY_TOKEN_SIZE
@@ -144,19 +144,61 @@ static const char *accepted_content_types[] = { "application/json",
"text/x-json",
NULL};
struct private_data {
const struct ekmf_ext_lib *ext_lib;
bool verbose;
struct ext_lib_info {
struct sk_ext_lib ext_lib;
union {
struct sk_ext_cca_lib cca; /* Used if type = EXT_LIB_CCA */
struct sk_ext_ep11_lib ep11; /* Used if type = EXT_LIB_EP11 */
};
};
static int _ekmf_setup_sign_context(const unsigned char *key_blob,
size_t key_blob_size, EVP_PKEY *pkey,
int digest_nid,
struct ekmf_rsa_pss_params *rsa_pss_params,
EVP_MD_CTX **md_ctx,
EVP_PKEY_CTX **pkey_ctx,
struct private_data *private,
bool verbose);
static void _ekmf_copy_ext_lib(const struct ekmf_ext_lib *ekmf_ext_lib,
struct ext_lib_info *ext_lib_info)
{
switch (ekmf_ext_lib->type) {
case EKMF_EXT_LIB_CCA:
ext_lib_info->ext_lib.type = SK_EXT_LIB_CCA;
ext_lib_info->ext_lib.cca = &ext_lib_info->cca;
ext_lib_info->cca.cca_lib = ekmf_ext_lib->cca->cca_lib;
break;
default:
ext_lib_info->ext_lib.type = 0;
}
}
static void _ekmf_copy_key_gen_info(const struct ekmf_key_gen_info *ekmf_info,
struct sk_key_gen_info *sk_info)
{
switch (ekmf_info->type) {
case EKMF_KEY_TYPE_ECC:
sk_info->type = SK_KEY_TYPE_EC;
sk_info->ec.curve_nid = ekmf_info->params.ecc.curve_nid;
break;
case EKMF_KEY_TYPE_RSA:
sk_info->type = SK_KEY_TYPE_RSA;
sk_info->rsa.modulus_bits = ekmf_info->params.rsa.modulus_bits;
sk_info->rsa.pub_exp = ekmf_info->params.rsa.pub_exp;
sk_info->rsa.x9_31 = 0;
break;
default:
sk_info->type = 0;
break;
}
}
static void _ekmf_copy_pss_params(
const struct ekmf_rsa_pss_params *ekmf_pss_params,
struct sk_rsa_pss_params *rsa_pss_params)
{
if (ekmf_pss_params != NULL) {
rsa_pss_params->mgf_digest_nid =
ekmf_pss_params->mgf_digest_nid;
rsa_pss_params->salt_len = ekmf_pss_params->salt_len;
} else {
rsa_pss_params->mgf_digest_nid = NID_undef;
rsa_pss_params->salt_len = 0;
}
}
/**
* Extract the public key from a certificate in PEM format and store it into a
@@ -1442,6 +1484,13 @@ int ekmf_get_public_key(const struct ekmf_config *config, CURL **curl_handle,
if (config == NULL)
return -EINVAL;
rc = SK_OPENSSL_init(verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to initialize secure key support: "
"%s", strerror(-rc));
return rc;
}
rc = ekmf_check_login_token(config, &token_valid, &login_token,
verbose);
if (rc != 0 || !token_valid) {
@@ -1509,6 +1558,7 @@ out:
free(login_token);
if (pkey != NULL)
EVP_PKEY_free(pkey);
SK_OPENSSL_term();
return rc;
}
@@ -1938,53 +1988,26 @@ static int _ekmf_build_signature(unsigned char *key_blob,
const struct ekmf_ext_lib *ext_lib,
bool verbose)
{
struct ekmf_rsa_pss_params rsa_pss_params;
struct sk_rsa_pss_params rsa_pss_params;
struct ext_lib_info ext_lib_info;
EVP_PKEY_CTX *pkey_ctx = NULL;
struct private_data private;
EVP_MD_CTX *md_ctx = NULL;
bool pkey_meth = false;
EVP_PKEY *pkey = NULL;
const char *payload;
const char *jws_alg;
int rc, curve_nid;
char *jws = NULL;
int pkey_type;
BIO *b;
switch (ext_lib->type) {
case EKMF_EXT_LIB_CCA:
rc = cca_get_key_type(key_blob, key_blob_length, &pkey_type);
if (rc != 0) {
pr_verbose(verbose, "Failed to get the identity key "
"type");
goto out;
}
_ekmf_copy_ext_lib(ext_lib, &ext_lib_info);
switch (pkey_type) {
case EVP_PKEY_EC:
rc = cca_get_ecc_pub_key_as_pkey(key_blob,
key_blob_length,
&pkey, verbose);
break;
case EVP_PKEY_RSA:
case EVP_PKEY_RSA_PSS:
rc = cca_get_rsa_pub_key_as_pkey(key_blob,
key_blob_length,
use_rsa_pss ?
EVP_PKEY_RSA_PSS :
EVP_PKEY_RSA,
&pkey, verbose);
break;
}
if (rc != 0) {
pr_verbose(verbose, "Failed to get the identity PKEY");
goto out;
}
break;
default:
pr_verbose(verbose, "Invalid ext lib type: %d", ext_lib->type);
return -EINVAL;
rc = SK_OPENSSL_get_secure_key_as_pkey(key_blob, key_blob_length,
use_rsa_pss, &pkey,
&ext_lib_info.ext_lib,
verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to get the identity PKEY");
goto out;
}
/*
@@ -2002,8 +2025,7 @@ static int _ekmf_build_signature(unsigned char *key_blob,
*/
switch (EVP_PKEY_id(pkey)) {
case EVP_PKEY_EC:
curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(
EVP_PKEY_get0_EC_KEY(pkey)));
curve_nid = SK_OPENSSL_get_curve_from_ec_pkey(pkey);
switch (curve_nid) {
case NID_secp521r1:
digest_nid = NID_sha512;
@@ -2069,15 +2091,13 @@ static int _ekmf_build_signature(unsigned char *key_blob,
goto out;
}
private.ext_lib = ext_lib;
private.verbose = verbose;
rc = _ekmf_setup_sign_context(key_blob, key_blob_length, pkey,
digest_nid, &rsa_pss_params, &md_ctx,
&pkey_ctx, &private, verbose);
if (rc != 0)
rc = SK_OPENSSL_setup_sign_context(pkey, false, digest_nid,
&rsa_pss_params, &md_ctx, &pkey_ctx,
verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to setup secure key sign context");
goto out;
pkey_meth = true;
}
payload = json_object_to_json_string_ext(payload_obj,
JSON_C_TO_STRING_PLAIN |
@@ -2111,8 +2131,6 @@ static int _ekmf_build_signature(unsigned char *key_blob,
out:
if (md_ctx != NULL)
EVP_MD_CTX_free(md_ctx);
if (pkey_meth)
cleanup_secure_key_pkey_method(EVP_PKEY_id(pkey));
if (pkey != NULL)
EVP_PKEY_free(pkey);
if (jws != NULL)
@@ -2280,6 +2298,51 @@ out:
return rc;
}
/*
* Callback function for SK_OPENSSL_get_public_from_secure_key. Construct
* a JSON Web key from a public EC key.
*/
static int _ekmf_pub_key_as_json_web_key(const struct sk_pub_key_info *pub_key,
void *private)
{
json_object **jwk_ret = private;
json_object *jwk_obj = NULL;
int rc = 0;
if (pub_key->type != SK_KEY_TYPE_EC)
return -EINVAL;
/* construct the JWK */
jwk_obj = json_object_new_object();
if (jwk_obj == NULL)
return -ENOMEM;
/*
* Note: The order of the fields is important, EKMFWeb expects it in
* exactly this order!
*/
rc = json_object_object_add_ex(jwk_obj, "kty",
json_object_new_string("EC"), 0);
rc |= json_object_object_add_ex(jwk_obj, "crv", json_object_new_string(
EC_curve_nid2nist(pub_key->ec.curve_nid)), 0);
rc |= json_object_object_add_ex(jwk_obj, "x",
json_object_new_base64url(pub_key->ec.x,
pub_key->ec.prime_len),
0);
rc |= json_object_object_add_ex(jwk_obj, "y",
json_object_new_base64url(pub_key->ec.y,
pub_key->ec.prime_len),
0);
if (rc != 0) {
json_object_put(jwk_obj);
return -EIO;
}
*jwk_ret = jwk_obj;
return 0;
}
/**
* Requests a key to be retrieved from EKMFweb and imported under the current
* HSM's master key.
@@ -2342,8 +2405,10 @@ int ekmf_retrieve_key(const struct ekmf_config *config, CURL **curl_handle,
json_object *resp_sess_jwk_obj = NULL;
json_object *req_sess_jwk_obj = NULL;
json_object *resp_exp_jwk_obj = NULL;
struct ext_lib_info ext_lib_info;
json_object *response_obj = NULL;
json_object *request_obj = NULL;
struct sk_key_gen_info gen_info;
EVP_PKEY *server_pubkey = NULL;
char *escaped_uuid = NULL;
char *login_token = NULL;
@@ -2357,6 +2422,15 @@ int ekmf_retrieve_key(const struct ekmf_config *config, CURL **curl_handle,
key_blob_length == NULL || ext_lib == NULL)
return -EINVAL;
_ekmf_copy_ext_lib(ext_lib, &ext_lib_info);
rc = SK_OPENSSL_init(verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to initialize secure key support: "
"%s", strerror(-rc));
return rc;
}
rc = ekmf_check_login_token(config, &token_valid, &login_token,
verbose);
if (rc != 0 || !token_valid) {
@@ -2390,34 +2464,30 @@ int ekmf_retrieve_key(const struct ekmf_config *config, CURL **curl_handle,
goto out;
}
switch (ext_lib->type) {
case EKMF_EXT_LIB_CCA:
req_sess_ec_key_length = sizeof(req_sess_ec_key);
rc = cca_generate_ecc_key_pair(ext_lib->cca,
sess_ec_curve_nid != 0 ?
sess_ec_curve_nid :
DEFAULT_SESSION_EC_KEY_CURVE,
req_sess_ec_key,
&req_sess_ec_key_length,
verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to generate a session EC "
"key");
goto out;
}
gen_info.type = SK_KEY_TYPE_EC;
gen_info.ec.curve_nid = sess_ec_curve_nid != 0 ? sess_ec_curve_nid :
DEFAULT_SESSION_EC_KEY_CURVE;
rc = cca_get_ecc_pub_key_as_json_web_key(req_sess_ec_key,
req_sess_ec_key_length,
&req_sess_jwk_obj,
verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to generate session JWK");
goto out;
}
break;
default:
pr_verbose(verbose, "Invalid ext lib type: %d", ext_lib->type);
return -EINVAL;
req_sess_ec_key_length = sizeof(req_sess_ec_key);
rc = SK_OPENSSL_generate_secure_key(req_sess_ec_key,
&req_sess_ec_key_length,
&gen_info, &ext_lib_info.ext_lib,
verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to generate a session EC "
"key");
goto out;
}
rc = SK_OPENSSL_get_public_from_secure_key(req_sess_ec_key,
req_sess_ec_key_length,
_ekmf_pub_key_as_json_web_key,
&req_sess_jwk_obj,
&ext_lib_info.ext_lib,
verbose);
if (rc != 0 || req_sess_jwk_obj == NULL) {
pr_verbose(verbose, "Failed to generate session JWK");
goto out;
}
req_timestamp_obj = get_json_timestamp();
@@ -2639,6 +2709,7 @@ out:
free(resp_party_info);
if (escaped_uuid != NULL)
curl_free(escaped_uuid);
SK_OPENSSL_term();
return rc;
}
@@ -4803,6 +4874,8 @@ int ekmf_generate_identity_key(const struct ekmf_config *config,
{
unsigned char key_blob[MAX_KEY_BLOB_SIZE];
size_t key_blob_size = sizeof(key_blob);
struct ext_lib_info ext_lib_info;
struct sk_key_gen_info gen_info;
int rc;
if (config == NULL || info == NULL || ext_lib == NULL)
@@ -4810,30 +4883,11 @@ int ekmf_generate_identity_key(const struct ekmf_config *config,
if (config->identity_secure_key == NULL)
return -EINVAL;
switch (ext_lib->type) {
case EKMF_EXT_LIB_CCA:
switch (info->type) {
case EKMF_KEY_TYPE_ECC:
rc = cca_generate_ecc_key_pair(ext_lib->cca,
info->params.ecc.curve_nid,
key_blob, &key_blob_size, verbose);
break;
case EKMF_KEY_TYPE_RSA:
rc = cca_generate_rsa_key_pair(ext_lib->cca,
info->params.rsa.modulus_bits,
info->params.rsa.pub_exp,
key_blob, &key_blob_size, verbose);
break;
default:
pr_verbose(verbose, "Invalid key type: %d", info->type);
return -EINVAL;
}
break;
default:
pr_verbose(verbose, "Invalid ext lib type: %d", ext_lib->type);
return -EINVAL;
}
_ekmf_copy_ext_lib(ext_lib, &ext_lib_info);
_ekmf_copy_key_gen_info(info, &gen_info);
rc = SK_OPENSSL_generate_secure_key(key_blob, &key_blob_size, &gen_info,
&ext_lib_info.ext_lib, verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to generate a key: rc: %d - %s",
rc, strerror(-rc));
@@ -4896,6 +4950,7 @@ int ekmf_reencipher_identity_key(const struct ekmf_config *config,
{
unsigned char key_blob[MAX_KEY_BLOB_SIZE];
size_t key_blob_size = sizeof(key_blob);
struct ext_lib_info ext_lib_info;
const char *out_file;
int rc;
@@ -4904,6 +4959,8 @@ int ekmf_reencipher_identity_key(const struct ekmf_config *config,
if (config->identity_secure_key == NULL)
return -EINVAL;
_ekmf_copy_ext_lib(ext_lib, &ext_lib_info);
rc = read_key_blob(config->identity_secure_key, key_blob,
&key_blob_size);
if (rc != 0) {
@@ -4913,16 +4970,8 @@ int ekmf_reencipher_identity_key(const struct ekmf_config *config,
return rc;
}
switch (ext_lib->type) {
case EKMF_EXT_LIB_CCA:
rc = cca_reencipher_key(ext_lib->cca, key_blob, key_blob_size,
to_new, verbose);
break;
default:
pr_verbose(verbose, "Invalid ext lib type: %d", ext_lib->type);
return -EINVAL;
}
rc = SK_OPENSSL_reencipher_secure_key(key_blob, key_blob_size, to_new,
&ext_lib_info.ext_lib, verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to re-encipher the secure identity "
"key from file '%s': %s",
@@ -4942,217 +4991,6 @@ int ekmf_reencipher_identity_key(const struct ekmf_config *config,
return 0;
}
/**
* Wrapper for the RSA sign callback to route the call to the selected
* secure key library.
*/
static int _ekmf_rsa_sign(const unsigned char *key_blob, size_t key_blob_length,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen,
int padding_type, int md_nid, void *private)
{
struct private_data *prv = (struct private_data *)private;
if (prv == NULL || prv->ext_lib == NULL)
return 1;
switch (prv->ext_lib->type) {
case EKMF_EXT_LIB_CCA:
return cca_rsa_sign(prv->ext_lib->cca, key_blob,
key_blob_length, sig, siglen, tbs, tbslen,
padding_type, md_nid, prv->verbose);
default:
return 1;
}
}
/**
* Wrapper for the RSA-PSS sign callback to route the call to the selected
* secure key library.
*/
static int _ekmf_rsa_pss_sign(const unsigned char *key_blob,
size_t key_blob_length, unsigned char *sig,
size_t *siglen, const unsigned char *tbs,
size_t tbslen, int md_nid, int mgfmd_nid,
int saltlen, void *private)
{
struct private_data *prv = (struct private_data *)private;
if (prv == NULL || prv->ext_lib == NULL)
return 1;
switch (prv->ext_lib->type) {
case EKMF_EXT_LIB_CCA:
return cca_rsa_pss_sign(prv->ext_lib->cca, key_blob,
key_blob_length, sig, siglen, tbs,
tbslen, md_nid, mgfmd_nid, saltlen,
prv->verbose);
default:
return 1;
}
}
/**
* Wrapper for the ECDSA sign callback to route the call to the selected
* secure key library.
*/
static int _ekmf_ecdsa_sign(const unsigned char *key_blob,
size_t key_blob_length, unsigned char *sig,
size_t *siglen, const unsigned char *tbs,
size_t tbslen, int md_nid, void *private)
{
struct private_data *prv = (struct private_data *)private;
if (prv == NULL || prv->ext_lib == NULL)
return 1;
switch (prv->ext_lib->type) {
case EKMF_EXT_LIB_CCA:
return cca_ecdsa_sign(prv->ext_lib->cca, key_blob,
key_blob_length, sig, siglen, tbs, tbslen,
md_nid, prv->verbose);
default:
return 1;
}
}
/**
* Gets the public key from the key blob as a PKEY object.
*/
static int _ekmf_get_pub_key_as_pkey(const unsigned char *key_blob,
size_t key_blob_size, EVP_PKEY **pkey,
bool rsa_pss,
const struct ekmf_ext_lib *ext_lib,
bool verbose)
{
int rc, pkey_type;
switch (ext_lib->type) {
case EKMF_EXT_LIB_CCA:
rc = cca_get_key_type(key_blob, key_blob_size, &pkey_type);
if (rc != 0) {
pr_verbose(verbose, "Failed to get the identity key "
"type: %s", strerror(-rc));
return rc;
}
switch (pkey_type) {
case EVP_PKEY_EC:
rc = cca_get_ecc_pub_key_as_pkey(key_blob,
key_blob_size, pkey, verbose);
break;
case EVP_PKEY_RSA:
case EVP_PKEY_RSA_PSS:
rc = cca_get_rsa_pub_key_as_pkey(key_blob,
key_blob_size, rsa_pss ?
EVP_PKEY_RSA_PSS : pkey_type,
pkey, verbose);
break;
default:
pr_verbose(verbose, "Invalid identity key type: %d",
pkey_type);
return -EIO;
}
if (rc != 0)
return rc;
break;
default:
pr_verbose(verbose, "Invalid ext lib type: %d", ext_lib->type);
return -EINVAL;
}
return 0;
}
/**
* Setup a signing context for the specified key, digest_nid, and RSA-PSS
* parameters.
*/
static int _ekmf_setup_sign_context(const unsigned char *key_blob,
size_t key_blob_size, EVP_PKEY *pkey,
int digest_nid,
struct ekmf_rsa_pss_params *rsa_pss_params,
EVP_MD_CTX **md_ctx,
EVP_PKEY_CTX **pkey_ctx,
struct private_data *private,
bool verbose)
{
struct sk_pkey_sign_func sign_func;
EVP_PKEY_CTX *pctx = NULL;
const EVP_MD *md = NULL;
int rc, default_nid;
EVP_MD_CTX *ctx;
rc = setup_secure_key_pkey_method(EVP_PKEY_id(pkey));
if (rc != 0) {
pr_verbose(verbose, "Failed to setup secure key PKEY method");
return rc;
}
ctx = EVP_MD_CTX_new();
if (ctx == NULL) {
pr_verbose(verbose, "Failed to allocate the digest context");
rc = -ENOMEM;
goto out;
}
if (digest_nid != 0) {
md = EVP_get_digestbynid(digest_nid);
if (md == NULL) {
pr_verbose(verbose, "Requested digest not supported");
rc = -ENOTSUP;
goto out;
}
if (EVP_PKEY_get_default_digest_nid(pkey, &default_nid) == 2 &&
default_nid == 0) {
pr_verbose(verbose, "The signing algorithm requires "
"there to be no digest");
md = NULL;
}
}
rc = EVP_DigestSignInit(ctx, &pctx, md, NULL, pkey);
if (rc != 1) {
pr_verbose(verbose, "Failed to initialize the signing "
"operation");
rc = -EIO;
goto out;
}
sign_func.rsa_sign = _ekmf_rsa_sign;
sign_func.rsa_pss_sign = _ekmf_rsa_pss_sign;
sign_func.ecdsa_sign = _ekmf_ecdsa_sign;
rc = setup_secure_key_pkey_context(pctx, key_blob, key_blob_size,
&sign_func, private);
if (rc != 0) {
pr_verbose(verbose, "Failed to setup the secure key PKEY "
"context: %s", strerror(-rc));
goto out;
}
if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA_PSS && rsa_pss_params != NULL) {
rc = setup_rsa_pss_pkey_context(pctx, rsa_pss_params);
if (rc != 0) {
pr_verbose(verbose, "Failed to setup RSA-PSS context");
goto out;
}
}
*md_ctx = ctx;
*pkey_ctx = pctx;
out:
if (rc != 0) {
cleanup_secure_key_pkey_method(EVP_PKEY_id(pkey));
if (ctx != NULL)
EVP_MD_CTX_free(ctx);
}
return rc;
}
/**
* Generate a certificate signing request using the secure identity key (field
* identity_secure_key in config structure) with the specified subject name,
@@ -5215,15 +5053,10 @@ int ekmf_generate_csr(const struct ekmf_config *config,
const char *csr_pem_filename, bool new_hdr,
const struct ekmf_ext_lib *ext_lib, bool verbose)
{
const STACK_OF(X509_EXTENSION) *cert_exts = NULL;
unsigned char key_blob[MAX_KEY_BLOB_SIZE];
size_t key_blob_size = sizeof(key_blob);
X509_NAME *subject_name = NULL;
EVP_PKEY_CTX *pkey_ctx = NULL;
struct private_data private;
EVP_MD_CTX *md_ctx = NULL;
bool pkey_meth = false;
EVP_PKEY *pkey = NULL;
struct sk_rsa_pss_params pss_params;
struct ext_lib_info ext_lib_info;
X509_REQ *req = NULL;
X509 *cert = NULL;
int rc;
@@ -5238,6 +5071,15 @@ int ekmf_generate_csr(const struct ekmf_config *config,
if (num_extensions != 0 && extensions == NULL)
return -EINVAL;
_ekmf_copy_ext_lib(ext_lib, &ext_lib_info);
rc = SK_OPENSSL_init(verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to initialize secure key support: "
"%s", strerror(-rc));
return rc;
}
rc = read_key_blob(config->identity_secure_key, key_blob,
&key_blob_size);
if (rc != 0) {
@@ -5247,30 +5089,6 @@ int ekmf_generate_csr(const struct ekmf_config *config,
goto out;
}
rc = _ekmf_get_pub_key_as_pkey(key_blob, key_blob_size, &pkey,
rsa_pss_params != NULL, ext_lib,
verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to get identity key as PKEY from "
"file '%s': %s", config->identity_secure_key,
strerror(-rc));
goto out;
}
req = X509_REQ_new();
if (req == NULL) {
pr_verbose(verbose, "X509_REQ_new failed");
rc = -ENOMEM;
goto out;
}
rc = X509_REQ_set_version(req, 0L);
if (rc != 1) {
pr_verbose(verbose, "X509_REQ_set_version failed: rc: %d", rc);
rc = -EIO;
goto out;
}
if (renew_cert_filename != NULL) {
rc = read_x509_certificate(renew_cert_filename, &cert);
if (rc != 0) {
@@ -5279,63 +5097,20 @@ int ekmf_generate_csr(const struct ekmf_config *config,
strerror(-rc));
goto out;
}
subject_name = X509_NAME_dup(X509_get_subject_name(cert));
cert_exts = X509_get0_extensions(cert);
}
if (subject_rdns != NULL && num_subject_rdns > 0) {
rc = build_subject_name(&subject_name, subject_rdns,
num_subject_rdns, subject_utf8);
if (rc != 0) {
pr_verbose(verbose, "Failed to parse the subject name "
"RDSn: %s", strerror(-rc));
goto out;
}
}
if (subject_name == NULL) {
rc = -EINVAL;
pr_verbose(verbose, "Subject name can not be empty");
goto out;
}
_ekmf_copy_pss_params(rsa_pss_params, &pss_params);
rc = X509_REQ_set_subject_name(req, subject_name);
if (rc != 1) {
rc = -EIO;
pr_verbose(verbose, "Failed to set subject name into request");
goto out;
}
rc = build_certificate_extensions(NULL, req, extensions,
num_extensions, cert_exts);
rc = SK_OPENSSL_generate_csr(key_blob, key_blob_size,
subject_rdns, num_subject_rdns,
subject_utf8, cert,
extensions, num_extensions,
digest_nid, &pss_params, &req,
&ext_lib_info.ext_lib, verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to parse the extensions: "
"%s", strerror(-rc));
goto out;
}
rc = X509_REQ_set_pubkey(req, pkey);
if (rc != 1) {
pr_verbose(verbose, "Failed to set the public key");
rc = -EIO;
goto out;
}
private.ext_lib = ext_lib;
private.verbose = verbose;
rc = _ekmf_setup_sign_context(key_blob, key_blob_size, pkey, digest_nid,
rsa_pss_params, &md_ctx, &pkey_ctx,
&private, verbose);
if (rc != 0)
goto out;
pkey_meth = true;
rc = X509_REQ_sign_ctx(req, md_ctx);
if (rc <= 0) {
pr_verbose(verbose, "Failed to perform the signing operation");
rc = -EIO;
pr_verbose(verbose, "SK_OPENSSL_generate_csr failed "
"'%s': %s", csr_pem_filename, strerror(-rc));
goto out;
}
@@ -5346,24 +5121,15 @@ int ekmf_generate_csr(const struct ekmf_config *config,
goto out;
}
if (verbose) {
pr_verbose(verbose, "Certificate Signing Request created:");
X509_REQ_print_fp(stderr, req);
}
pr_verbose(verbose, "Certificate Signing Request created successfully "
"into '%s'", csr_pem_filename);
out:
if (md_ctx != NULL)
EVP_MD_CTX_free(md_ctx);
if (pkey_meth)
cleanup_secure_key_pkey_method(EVP_PKEY_id(pkey));
if (subject_name != NULL)
X509_NAME_free(subject_name);
if (cert != NULL)
X509_free(cert);
if (req != NULL)
X509_REQ_free(req);
if (pkey != NULL)
EVP_PKEY_free(pkey);
SK_OPENSSL_term();
return rc;
}
@@ -5433,15 +5199,10 @@ int ekmf_generate_ss_cert(const struct ekmf_config *config,
const char *cert_pem_filename,
const struct ekmf_ext_lib *ext_lib, bool verbose)
{
const STACK_OF(X509_EXTENSION) *cert_exts = NULL;
unsigned char key_blob[MAX_KEY_BLOB_SIZE];
size_t key_blob_size = sizeof(key_blob);
X509_NAME *subject_name = NULL;
EVP_PKEY_CTX *pkey_ctx = NULL;
struct private_data private;
EVP_MD_CTX *md_ctx = NULL;
bool pkey_meth = false;
EVP_PKEY *pkey = NULL;
struct sk_rsa_pss_params pss_params;
struct ext_lib_info ext_lib_info;
X509 *rcert = NULL;
X509 *cert = NULL;
int rc;
@@ -5456,6 +5217,15 @@ int ekmf_generate_ss_cert(const struct ekmf_config *config,
if (num_extensions != 0 && extensions == NULL)
return -EINVAL;
_ekmf_copy_ext_lib(ext_lib, &ext_lib_info);
rc = SK_OPENSSL_init(verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to initialize secure key support: "
"%s", strerror(-rc));
return rc;
}
rc = read_key_blob(config->identity_secure_key, key_blob,
&key_blob_size);
if (rc != 0) {
@@ -5465,37 +5235,6 @@ int ekmf_generate_ss_cert(const struct ekmf_config *config,
goto out;
}
rc = _ekmf_get_pub_key_as_pkey(key_blob, key_blob_size, &pkey,
rsa_pss_params != NULL, ext_lib,
verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to get identity key as PKEY from "
"file '%s': %s", config->identity_secure_key,
strerror(-rc));
goto out;
}
cert = X509_new();
if (cert == NULL) {
pr_verbose(verbose, "X509_new failed");
rc = -ENOMEM;
goto out;
}
rc = X509_set_version(cert, 2L);
if (rc != 1) {
pr_verbose(verbose, "X509_set_version failed: rc: %d", rc);
rc = -EIO;
goto out;
}
rc = generate_x509_serial_number(cert, SERIAL_NUMBER_BIT_SIZE);
if (rc != 0) {
pr_verbose(verbose, "Failed to set the serial number: %s",
strerror(-rc));
goto out;
}
if (renew_cert_filename != NULL) {
rc = read_x509_certificate(renew_cert_filename, &rcert);
if (rc != 0) {
@@ -5504,83 +5243,20 @@ int ekmf_generate_ss_cert(const struct ekmf_config *config,
strerror(-rc));
goto out;
}
subject_name = X509_NAME_dup(X509_get_subject_name(rcert));
cert_exts = X509_get0_extensions(rcert);
}
if (subject_rdns != NULL && num_subject_rdns > 0) {
rc = build_subject_name(&subject_name, subject_rdns,
num_subject_rdns, subject_utf8);
if (rc != 0) {
pr_verbose(verbose, "Failed to parse the subject name "
"RDSn: %s", strerror(-rc));
goto out;
}
}
_ekmf_copy_pss_params(rsa_pss_params, &pss_params);
if (subject_name == NULL) {
rc = -EINVAL;
pr_verbose(verbose, "Subject name can not be empty");
goto out;
}
rc = X509_set_subject_name(cert, subject_name);
if (rc != 1) {
rc = -EIO;
pr_verbose(verbose, "Failed to set subject name into cert");
goto out;
}
rc = X509_set_issuer_name(cert, subject_name);
if (rc != 1) {
rc = -EIO;
pr_verbose(verbose, "Failed to set issuer name into cert");
goto out;
}
rc = build_certificate_extensions(cert, NULL, extensions,
num_extensions, cert_exts);
rc = SK_OPENSSL_generate_ss_cert(key_blob, key_blob_size,
subject_rdns, num_subject_rdns,
subject_utf8, rcert,
extensions, num_extensions,
validity_days, digest_nid,
&pss_params, &cert,
&ext_lib_info.ext_lib, verbose);
if (rc != 0) {
pr_verbose(verbose, "Failed to parse the extensions: "
"%s", strerror(-rc));
goto out;
}
if (X509_gmtime_adj(X509_getm_notBefore(cert), 0) == NULL) {
rc = -EIO;
pr_verbose(verbose, "Failed to set notBefore time inti cert");
goto out;
}
if (X509_time_adj_ex(X509_getm_notAfter(cert),
validity_days, 0, NULL) == NULL) {
rc = -EIO;
pr_verbose(verbose, "Failed to set notAfter time into cert");
goto out;
}
rc = X509_set_pubkey(cert, pkey);
if (rc != 1) {
pr_verbose(verbose, "Failed to set the public key");
rc = -EIO;
goto out;
}
private.ext_lib = ext_lib;
private.verbose = verbose;
rc = _ekmf_setup_sign_context(key_blob, key_blob_size, pkey, digest_nid,
rsa_pss_params, &md_ctx, &pkey_ctx,
&private, verbose);
if (rc != 0)
goto out;
pkey_meth = true;
rc = X509_sign_ctx(cert, md_ctx);
if (rc <= 0) {
pr_verbose(verbose, "Failed to perform the signing operation");
rc = -EIO;
pr_verbose(verbose, "SK_OPENSSL_generate_ss_cert failed "
"'%s': %s", cert_pem_filename, strerror(-rc));
goto out;
}
@@ -5591,24 +5267,15 @@ int ekmf_generate_ss_cert(const struct ekmf_config *config,
goto out;
}
if (verbose) {
pr_verbose(verbose, "Self-signed Certificate created:");
X509_print_fp(stderr, cert);
}
pr_verbose(verbose, "Self-signed Certificate created successfully "
"into '%s'", cert_pem_filename);
out:
if (md_ctx != NULL)
EVP_MD_CTX_free(md_ctx);
if (pkey_meth)
cleanup_secure_key_pkey_method(EVP_PKEY_id(pkey));
if (subject_name != NULL)
X509_NAME_free(subject_name);
if (cert != NULL)
X509_free(cert);
if (rcert != NULL)
X509_free(rcert);
if (pkey != NULL)
EVP_PKEY_free(pkey);
SK_OPENSSL_term();
return rc;
}

File diff suppressed because it is too large Load Diff

View File

@@ -81,26 +81,6 @@ void free_key_info(struct ekmf_key_info *key);
char *get_http_header_value(const struct curl_slist *headers, const char *name);
size_t ecc_get_curve_prime_bits(int curve_nid);
size_t ecc_get_curve_prime_length(int curve_nid);
const char *ecc_get_curve_id(int curve_nid);
bool ecc_is_prime_curve(int curve_nid);
bool ecc_is_brainpool_curve(int curve_nid);
int ecc_get_curve_by_id(const char *curve_id);
int ecc_get_prime_curve_by_prime_bits(size_t prime_bits);
int ecc_get_brainpool_curve_by_prime_bits(size_t prime_bits);
int ecc_calculate_y_coordinate(int nid, size_t prime_len,
const unsigned char *x, int y_bit,
unsigned char *y);
int ecc_pub_key_as_pkey(int nid, size_t prime_len, const unsigned char *x,
const unsigned char *y, EVP_PKEY **pkey);
int rsa_pub_key_as_pkey(const unsigned char *modulus, size_t modulus_length,
const unsigned char *pub_exp, size_t pub_exp_length,
int pkey_type, EVP_PKEY **pkey);
int json_web_key_as_pkey(json_object *jwk, int pkey_type, EVP_PKEY **pkey);
int write_key_blob(const char *filename, unsigned char *key_blob,
@@ -119,38 +99,6 @@ int read_public_key(const char *pem_filename, EVP_PKEY **pkey);
int write_public_key(const char *pem_filename, EVP_PKEY *pkey);
typedef int (*rsa_sign_t)(const unsigned char *key_blob, size_t key_blob_length,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen,
int padding_type, int md_nid,
void *private);
typedef int (*rsa_pss_sign_t)(const unsigned char *key_blob,
size_t key_blob_length, unsigned char *sig,
size_t *siglen, const unsigned char *tbs,
size_t tbslen, int md_nid, int mfgmd_nid,
int saltlen, void *private);
typedef int (*ecdsa_sign_t)(const unsigned char *key_blob,
size_t key_blob_length, unsigned char *sig,
size_t *siglen, const unsigned char *tbs,
size_t tbslen, int md_nid, void *private);
struct sk_pkey_sign_func {
rsa_sign_t rsa_sign;
rsa_pss_sign_t rsa_pss_sign;
ecdsa_sign_t ecdsa_sign;
};
int setup_secure_key_pkey_method(int pkey_id);
int cleanup_secure_key_pkey_method(int pkey_id);
int setup_secure_key_pkey_context(EVP_PKEY_CTX *pkey_ctx,
const unsigned char *key_blob,
size_t key_blob_len,
struct sk_pkey_sign_func *sign_funcs,
void *private);
int setup_rsa_pss_pkey_context(EVP_PKEY_CTX *pkey_ctx,
struct ekmf_rsa_pss_params *rsa_pss_params);
int build_subject_name(X509_NAME **name, const char *rdns[], size_t num_rdns,
bool utf8);