pkcs11/pkcs15-init: remove automagic software key generation. Remove software based secret key handling from PKCS#11.

Support for importing cleartext keys is left untouched, but all transparent key generation by either opensc-pkcs11.so or pkcs15-init is removed, to make the operation with cleartext keys visible to the user and his explicit wish.
OpenSC is a PKCS#11 library for accessing keys protected by a smart card. Key material in software is not protected by smart cards and can leave a false sense of security to the user.

http://www.opensc-project.org/pipermail/opensc-devel/2010-April/013877.html

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4646 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
martin 2010-08-23 14:47:07 +00:00
parent 1f73d32e40
commit 9a63e03e9a
9 changed files with 9 additions and 499 deletions

View File

@ -133,12 +133,6 @@
<command>pkcs15-init</command> will also store the the public portion of the
key as a PKCS #15 public key object.
</para>
<para>
By default, <command>pkcs15-init</command> will try to use the card's
on-board key generation facilities, if available. If the card does not
support on-board key generation, <command>pkcs15-init</command> will fall
back to software key generation.
</para>
</refsect2>
<refsect2>

View File

@ -367,12 +367,6 @@ app opensc-pkcs11 {
# Default: false
# lock_login = true;
# Set this value to true if you want to allow off-card
# keypair generation (in software on your pc)
#
# Default: false
# soft_keygen_allowed = true;
# User PIN unblock style
# none: PIN unblock is not possible with PKCS#11 API;
# set_pin_in_unlogged_session: C_SetPIN() in unlogged session:

View File

@ -12,7 +12,7 @@ INCLUDES = -I$(top_srcdir)/src
OPENSC_PKCS11_INC = sc-pkcs11.h pkcs11.h pkcs11-opensc.h
OPENSC_PKCS11_SRC = pkcs11-global.c pkcs11-session.c pkcs11-object.c misc.c slot.c \
mechanism.c openssl.c secretkey.c framework-pkcs15.c \
mechanism.c openssl.c framework-pkcs15.c \
framework-pkcs15init.c debug.c opensc-pkcs11.exports \
pkcs11-display.c pkcs11-display.h
OPENSC_PKCS11_LIBS = $(OPTIONAL_OPENSSL_LIBS) $(PTHREAD_LIBS) \

View File

@ -6,7 +6,7 @@ TARGET2 = libpkcs11.lib
TARGET3 = pkcs11-spy.dll
OBJECTS = pkcs11-global.obj pkcs11-session.obj pkcs11-object.obj misc.obj slot.obj \
mechanism.obj openssl.obj secretkey.obj framework-pkcs15.obj \
mechanism.obj openssl.obj framework-pkcs15.obj \
framework-pkcs15init.obj debug.obj pkcs11-display.obj \
$(TOPDIR)\win32\versioninfo.res
OBJECTS2 = libpkcs11.obj \

View File

@ -1727,7 +1727,6 @@ static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card,
struct sc_profile *profile = NULL;
struct sc_pkcs15_pin_info *pin;
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
struct sc_pkcs15_card *p15card = fw_data->p15_card;
struct sc_pkcs15init_keygen_args keygen_args;
struct sc_pkcs15init_pubkeyargs pub_args;
struct sc_pkcs15_object *priv_key_obj;
@ -1852,41 +1851,6 @@ static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card,
rv = sc_to_cryptoki_error(rc, "C_GenerateKeyPair");
goto kpgen_done;
}
else {
/* 3.b Try key pair generation in software, if allowed */
if (!sc_pkcs11_conf.soft_keygen_allowed) {
sc_debug(context, SC_LOG_DEBUG_NORMAL, "On card keypair gen not supported, software keypair gen not allowed");
rv = CKR_FUNCTION_FAILED;
goto kpgen_done;
}
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Doing key pair generation in software\n");
rv = sc_pkcs11_gen_keypair_soft(keytype, keybits,
&keygen_args.prkey_args.key, &pub_args.key);
if (rv != CKR_OK) {
sc_debug(context, SC_LOG_DEBUG_NORMAL, "sc_pkcs11_gen_keypair_soft failed: 0x%0x\n", rv);
goto kpgen_done;
}
rc = sc_pkcs15init_store_private_key(p15card, profile, &keygen_args.prkey_args, &priv_key_obj);
if (rc >= 0) {
/* copy ID from private key(s) here to avoid bad link between private and public key */
memcpy(&pub_args.id.value, &keygen_args.prkey_args.id.value, keygen_args.prkey_args.id.len);
pub_args.id.len = keygen_args.prkey_args.id.len;
rc = sc_pkcs15init_store_public_key(p15card, profile, &pub_args, &pub_key_obj);
}
sc_pkcs15_erase_prkey(&keygen_args.prkey_args.key);
sc_pkcs15_erase_pubkey(&pub_args.key);
if (rc < 0) {
sc_debug(context, SC_LOG_DEBUG_NORMAL, "private/public keys not stored: %d\n", rc);
rv = sc_to_cryptoki_error(rc, "C_GenerateKeyPair");
goto kpgen_done;
}
}
/* 4. Create new pkcs11 public and private key object */
@ -2465,9 +2429,9 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *ses, void *obj,
u8 decrypted[256];
int buff_too_small, rv, flags = 0;
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Initiating unwrap/decryption.\n");
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Initiating decryption.\n");
/* See which of the alternative keys supports unwrap/decrypt */
/* See which of the alternative keys supports decrypt */
prkey = (struct pkcs15_prkey_object *) obj;
while (prkey
&& !(prkey->prv_info->usage
@ -2507,7 +2471,7 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *ses, void *obj,
sc_unlock(ses->slot->card->card);
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Key unwrap/decryption complete. Result %d.\n", rv);
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Key decryption complete. Result %d.\n", rv);
if (rv < 0)
return sc_to_cryptoki_error(rv, "C_Decrypt");
@ -2523,28 +2487,6 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *ses, void *obj,
return CKR_OK;
}
static CK_RV
pkcs15_prkey_unwrap(struct sc_pkcs11_session *ses, void *obj,
CK_MECHANISM_PTR pMechanism,
CK_BYTE_PTR pData, CK_ULONG ulDataLen,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
void **result)
{
u8 unwrapped_key[256];
CK_ULONG key_len = sizeof(unwrapped_key);
int rc;
rc = pkcs15_prkey_decrypt(ses, obj, pMechanism, pData, ulDataLen,
unwrapped_key, &key_len);
if (rc < 0)
return sc_to_cryptoki_error(rc, NULL);
return sc_pkcs11_create_secret_key(ses,
unwrapped_key, key_len,
pTemplate, ulAttributeCount,
(struct sc_pkcs11_object **) result);
}
struct sc_pkcs11_object_ops pkcs15_prkey_ops = {
pkcs15_prkey_release,
pkcs15_prkey_set_attribute,
@ -2553,7 +2495,7 @@ struct sc_pkcs11_object_ops pkcs15_prkey_ops = {
pkcs15_any_destroy,
NULL,
pkcs15_prkey_sign,
pkcs15_prkey_unwrap,
NULL, /* unwrap */
pkcs15_prkey_decrypt
};

View File

@ -301,73 +301,6 @@ static void sc_pkcs11_openssl_md_release(sc_pkcs11_operation_t *op)
op->priv_data = NULL;
}
static int
do_convert_bignum(sc_pkcs15_bignum_t *dst, BIGNUM *src)
{
if (src == 0)
return 0;
dst->len = BN_num_bytes(src);
dst->data = malloc(dst->len);
if (dst->data == NULL)
return 0;
BN_bn2bin(src, dst->data);
return 1;
}
CK_RV
sc_pkcs11_gen_keypair_soft(CK_KEY_TYPE keytype, CK_ULONG keybits,
struct sc_pkcs15_prkey *privkey, struct sc_pkcs15_pubkey *pubkey)
{
switch (keytype) {
case CKK_RSA: {
RSA *rsa;
BIO *err;
struct sc_pkcs15_prkey_rsa *sc_priv = &privkey->u.rsa;
struct sc_pkcs15_pubkey_rsa *sc_pub = &pubkey->u.rsa;
err = BIO_new(BIO_s_mem());
rsa = RSA_generate_key(keybits, 0x10001, NULL, err);
BIO_free(err);
if (rsa == NULL) {
sc_debug(context, SC_LOG_DEBUG_NORMAL, "RSA_generate_key() failed\n");
return CKR_FUNCTION_FAILED;
}
privkey->algorithm = pubkey->algorithm = SC_ALGORITHM_RSA;
if (!do_convert_bignum(&sc_priv->modulus, rsa->n)
|| !do_convert_bignum(&sc_priv->exponent, rsa->e)
|| !do_convert_bignum(&sc_priv->d, rsa->d)
|| !do_convert_bignum(&sc_priv->p, rsa->p)
|| !do_convert_bignum(&sc_priv->q, rsa->q)) {
sc_debug(context, SC_LOG_DEBUG_NORMAL, "do_convert_bignum() failed\n");
RSA_free(rsa);
return CKR_FUNCTION_FAILED;
}
if (rsa->iqmp && rsa->dmp1 && rsa->dmq1) {
do_convert_bignum(&sc_priv->iqmp, rsa->iqmp);
do_convert_bignum(&sc_priv->dmp1, rsa->dmp1);
do_convert_bignum(&sc_priv->dmq1, rsa->dmq1);
}
if (!do_convert_bignum(&sc_pub->modulus, rsa->n)
|| !do_convert_bignum(&sc_pub->exponent, rsa->e)) {
sc_debug(context, SC_LOG_DEBUG_NORMAL, "do_convert_bignum() failed\n");
RSA_free(rsa);
return CKR_FUNCTION_FAILED;
}
RSA_free(rsa);
break;
}
default:
return CKR_MECHANISM_PARAM_INVALID;
}
return CKR_OK;
}
#if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC)
static void reverse(unsigned char *buf, size_t len)

View File

@ -966,51 +966,7 @@ CK_RV C_UnwrapKey(CK_SESSION_HANDLE hSession, /* the session's handle */
CK_ULONG ulAttributeCount, /* # of attributes in template */
CK_OBJECT_HANDLE_PTR phKey)
{ /* gets handle of recovered key */
CK_RV rv;
struct sc_pkcs11_session *session;
struct sc_pkcs11_object *object, *result;
rv = sc_pkcs11_lock();
if (rv != CKR_OK)
return rv;
if (pMechanism == NULL_PTR || (pTemplate == NULL_PTR && ulAttributeCount > 0)) {
rv = CKR_ARGUMENTS_BAD;
goto out;
}
rv = get_object_from_session(hSession, hUnwrappingKey, &session, &object);
if (rv != CKR_OK) {
if (rv == CKR_OBJECT_HANDLE_INVALID)
rv = CKR_UNWRAPPING_KEY_HANDLE_INVALID;
goto out;
}
if (!(session->flags & CKF_RW_SESSION)) {
rv = CKR_SESSION_READ_ONLY;
goto out;
}
if (object->ops->sign == NULL_PTR) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto out;
}
rv = object->ops->unwrap_key(session, object, pMechanism,
pWrappedKey, ulWrappedKeyLen,
pTemplate, ulAttributeCount, (void **)&result);
sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_UnwrapKey() = %s", lookup_enum ( RV_T, rv ));
if (rv == CKR_OK) {
result->handle = (long)result;
list_append(&session->slot->objects, result);
}
*phKey = result->handle;
out: sc_pkcs11_unlock();
return rv;
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, /* the session's handle */

View File

@ -1,233 +0,0 @@
/*
* Secret key handling for PKCS#11
*
* This module deals only with secret keys that have been unwrapped
* by the card. At the moment, we do not support key unwrapping
* where the key remains on the token.
*
* Copyright (C) 2002 Olaf Kirch <okir@lst.de>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include "sc-pkcs11.h"
struct pkcs11_secret_key {
struct sc_pkcs11_object object;
char * label;
CK_KEY_TYPE type;
CK_BYTE_PTR value;
CK_ULONG value_len;
};
extern struct sc_pkcs11_object_ops pkcs11_secret_key_ops;
#define set_attr(var, attr) \
if (attr->ulValueLen != sizeof(var)) \
return CKR_ATTRIBUTE_VALUE_INVALID; \
memcpy(&var, attr->pValue, attr->ulValueLen);
#define check_attr(attr, size) \
if (attr->pValue == NULL_PTR) { \
attr->ulValueLen = size; \
return CKR_OK; \
} \
if (attr->ulValueLen < size) { \
attr->ulValueLen = size; \
return CKR_BUFFER_TOO_SMALL; \
} \
attr->ulValueLen = size;
#define get_attr(attr, type, value) \
check_attr(attr, sizeof(type)); \
*(type *) (attr->pValue) = value;
CK_RV
sc_pkcs11_create_secret_key(struct sc_pkcs11_session *session,
const u8 *value, size_t value_len,
CK_ATTRIBUTE_PTR _template,
CK_ULONG attribute_count,
struct sc_pkcs11_object **out)
{
struct pkcs11_secret_key *key;
CK_ATTRIBUTE_PTR attr;
int n, rv;
key = calloc(1, sizeof(*key));
if (!key)
return CKR_HOST_MEMORY;
key->value = malloc(value_len);
if (!key->value) {
pkcs11_secret_key_ops.release(key);
return CKR_HOST_MEMORY; /* XXX correct? */
}
memcpy(key->value, value, value_len);
key->value_len = value_len;
key->object.ops = &pkcs11_secret_key_ops;
/* Make sure the key type is given in the template */
for (n = attribute_count, attr = _template; n--; attr++) {
if (attr->type == CKA_KEY_TYPE) {
set_attr(key->type, attr);
break;
}
}
if (n < 0) {
pkcs11_secret_key_ops.release(key);
return CKR_TEMPLATE_INCOMPLETE;
}
/* Set all the other attributes */
for (n = attribute_count, attr = _template; n--; attr++) {
rv = key->object.ops->set_attribute(session, key, attr);
if (rv != CKR_OK) {
pkcs11_secret_key_ops.release(key);
return rv;
}
}
*out = (struct sc_pkcs11_object *) key;
return CKR_OK;
}
static void
sc_pkcs11_secret_key_release(void *object)
{
struct pkcs11_secret_key *key;
key = (struct pkcs11_secret_key *) object;
if (key) {
if (key->value)
free(key->value);
if (key->label)
free(key->label);
free(key);
}
}
static CK_RV
sc_pkcs11_secret_key_set_attribute(struct sc_pkcs11_session *session,
void *object, CK_ATTRIBUTE_PTR attr)
{
struct pkcs11_secret_key *key;
CK_OBJECT_CLASS ck_class;
CK_KEY_TYPE ck_key_type;
CK_BBOOL ck_bbool;
key = (struct pkcs11_secret_key *) object;
switch (attr->type) {
case CKA_CLASS:
set_attr(ck_class, attr);
if (ck_class != CKO_SECRET_KEY)
return CKR_ATTRIBUTE_VALUE_INVALID;
break;
case CKA_KEY_TYPE:
set_attr(ck_key_type, attr);
if (ck_key_type != key->type)
return CKR_ATTRIBUTE_VALUE_INVALID;
break;
case CKA_LABEL:
if (key->label)
free(key->label);
key->label = strdup((const char *) attr->pValue);
break;
case CKA_TOKEN:
set_attr(ck_bbool, attr);
if (!ck_bbool)
return CKR_ATTRIBUTE_VALUE_INVALID;
break;
case CKA_VALUE:
if (key->value)
free(key->value);
key->value = malloc(attr->ulValueLen);
if (key->value == NULL)
return CKR_HOST_MEMORY;
key->value_len = attr->ulValueLen;
memcpy(key->value, attr->pValue, key->value_len);
break;
case CKA_ENCRYPT:
case CKA_DECRYPT:
case CKA_SIGN:
case CKA_VERIFY:
case CKA_WRAP:
case CKA_UNWRAP:
case CKA_EXTRACTABLE:
case CKA_ALWAYS_SENSITIVE:
case CKA_NEVER_EXTRACTABLE:
/* We ignore these for now, just making sure the argument
* has the right size */
set_attr(ck_bbool, attr);
break;
default:
return CKR_ATTRIBUTE_TYPE_INVALID;
}
return CKR_OK;
}
static CK_RV
sc_pkcs11_secret_key_get_attribute(struct sc_pkcs11_session *session,
void *object, CK_ATTRIBUTE_PTR attr)
{
struct pkcs11_secret_key *key;
key = (struct pkcs11_secret_key *) object;
switch (attr->type) {
case CKA_CLASS:
get_attr(attr, CK_OBJECT_CLASS, CKO_SECRET_KEY);
break;
case CKA_KEY_TYPE:
get_attr(attr, CK_KEY_TYPE, key->type);
case CKA_VALUE:
check_attr(attr, key->value_len);
memcpy(attr->pValue, key->value, key->value_len);
break;
case CKA_VALUE_LEN:
get_attr(attr, CK_ULONG, key->value_len);
break;
case CKA_SENSITIVE:
case CKA_SIGN:
case CKA_VERIFY:
case CKA_WRAP:
case CKA_UNWRAP:
case CKA_NEVER_EXTRACTABLE:
get_attr(attr, CK_BBOOL, 0);
break;
case CKA_ENCRYPT:
case CKA_DECRYPT:
case CKA_EXTRACTABLE:
case CKA_ALWAYS_SENSITIVE:
get_attr(attr, CK_BBOOL, 1);
break;
default:
return CKR_ATTRIBUTE_TYPE_INVALID;
}
return CKR_OK;
}
struct sc_pkcs11_object_ops pkcs11_secret_key_ops = {
sc_pkcs11_secret_key_release,
sc_pkcs11_secret_key_set_attribute,
sc_pkcs11_secret_key_get_attribute,
sc_pkcs11_any_cmp_attribute,
NULL, /* destroy_object */
NULL, /* get_size */
NULL, /* sign */
NULL, /* unwrap_key */
NULL /* decrypt */
};

View File

@ -107,7 +107,6 @@ static int get_key_callback(struct sc_profile *,
int method, int reference,
const u8 *, size_t, u8 *, size_t *);
static int do_generate_key_soft(int, unsigned int, EVP_PKEY **);
static int do_read_private_key(const char *, const char *,
EVP_PKEY **, X509 **, unsigned int);
static int do_read_public_key(const char *, const char *, EVP_PKEY **);
@ -124,7 +123,6 @@ enum {
OPT_EXTRACTABLE,
OPT_UNPROTECTED,
OPT_AUTHORITY,
OPT_SOFT_KEYGEN,
OPT_ASSERT_PRISTINE,
OPT_SECRET,
OPT_PUBKEY_LABEL,
@ -185,7 +183,6 @@ const struct option options[] = {
{ "extractable", no_argument, NULL, OPT_EXTRACTABLE },
{ "insecure", no_argument, NULL, OPT_UNPROTECTED },
{ "soft", no_argument, NULL, OPT_SOFT_KEYGEN },
{ "use-default-transport-keys",
no_argument, NULL, 'T' },
{ "no-prompt", no_argument, NULL, OPT_NO_PROMPT },
@ -319,7 +316,6 @@ static unsigned int opt_actions;
static int opt_extractable = 0,
opt_unprotected = 0,
opt_authority = 0,
opt_softkeygen = 0,
opt_no_prompt = 0,
opt_no_sopin = 0,
opt_use_defkeys = 0,
@ -1401,8 +1397,7 @@ static int
do_generate_key(struct sc_profile *profile, const char *spec)
{
struct sc_pkcs15init_keygen_args keygen_args;
unsigned int evp_algo, keybits = 1024;
EVP_PKEY *pkey;
unsigned int keybits = 1024;
int r;
memset(&keygen_args, 0, sizeof(keygen_args));
@ -1419,11 +1414,9 @@ do_generate_key(struct sc_profile *profile, const char *spec)
/* Parse the key spec given on the command line */
if (!strncasecmp(spec, "rsa", 3)) {
keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_RSA;
evp_algo = EVP_PKEY_RSA;
spec += 3;
} else if (!strncasecmp(spec, "dsa", 3)) {
keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_DSA;
evp_algo = EVP_PKEY_DSA;
spec += 3;
} else if (!strncasecmp(spec, "gost2001", strlen("gost2001"))) {
keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_GOSTR3410;
@ -1431,7 +1424,6 @@ do_generate_key(struct sc_profile *profile, const char *spec)
/* FIXME: now only SC_PKCS15_PARAMSET_GOSTR3410_A */
keygen_args.prkey_args.gost_params.gostr3410 =
SC_PKCS15_PARAMSET_GOSTR3410_A;
evp_algo = 0; /* FIXME */
spec += strlen("gost2001");
} else {
util_error("Unknown algorithm \"%s\"", spec);
@ -1449,32 +1441,7 @@ do_generate_key(struct sc_profile *profile, const char *spec)
return SC_ERROR_INVALID_ARGUMENTS;
}
}
if (!opt_softkeygen) {
r = sc_pkcs15init_generate_key(p15card, profile, &keygen_args,
keybits, NULL);
if (r >= 0 || r != SC_ERROR_NOT_SUPPORTED)
return r;
if (verbose)
printf("Warning: card doesn't support on-board "
"key generation.\n"
"Trying software generation\n");
}
/* Generate the key ourselves */
if ((r = do_generate_key_soft(evp_algo, keybits, &pkey)) < 0
|| (r = do_convert_private_key(&keygen_args.prkey_args.key, pkey) ) < 0)
goto out;
r = sc_pkcs15init_store_private_key(p15card,
profile, &keygen_args.prkey_args, NULL);
/* Store public key portion on card */
if (r >= 0)
r = do_store_public_key(profile, pkey);
out:
EVP_PKEY_free(pkey);
r = sc_pkcs15init_generate_key(p15card, profile, &keygen_args, keybits, NULL);
return r;
}
@ -1854,46 +1821,6 @@ get_key_callback(struct sc_profile *profile,
}
}
/*
* Generate a private key
*/
static int do_generate_key_soft(int algorithm, unsigned int bits,
EVP_PKEY **res)
{
*res = EVP_PKEY_new();
switch (algorithm) {
case EVP_PKEY_RSA: {
RSA *rsa;
BIO *err;
err = BIO_new(BIO_s_mem());
rsa = RSA_generate_key(bits, 0x10001, NULL, err);
BIO_free(err);
if (rsa == 0)
util_fatal("RSA key generation error");
EVP_PKEY_assign_RSA(*res, rsa);
break;
}
case EVP_PKEY_DSA: {
DSA *dsa;
int r = 0;
dsa = DSA_generate_parameters(bits,
NULL, 0, NULL,
NULL, NULL, NULL);
if (dsa)
r = DSA_generate_key(dsa);
if (r == 0 || dsa == 0)
util_fatal("DSA key generation error");
EVP_PKEY_assign_DSA(*res, dsa);
break;
}
default:
util_fatal("Unable to generate key: unsupported algorithm");
}
return 0;
}
/*
* Read a private key
*/
@ -2579,9 +2506,6 @@ handle_option(const struct option *opt)
case OPT_AUTHORITY:
opt_authority = 1;
break;
case OPT_SOFT_KEYGEN:
opt_softkeygen = 1;
break;
case OPT_APPLICATION_NAME:
opt_application_name = optarg;
break;