Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 23ac33d

Browse files
Ivan StepicIvan Stepic
Ivan Stepic
authored and
Ivan Stepic
committedSep 12, 2022
Introduce generic keypair generation interface and engine ctrl command
As discussed in OpenSC#379 and OpenSC#378 we need a generic interface that supports multiple algorithms for key generation. Attempt was made to create a new keygen method and register it in PKCS11_pkey_meths()in p11_pkey.c but multiple design issues appeared. How and where do you pass the key ID, token label and alike was the first question. As suggested by the maintainer here: OpenSC#379 (comment), app_data was (mis)used and that worked well. The reason why this approach was abandoned is because a good (or bad) way to get a handle of the PKCS11_CTX_private, that is necessary for the Cryptoki call, was not found. The way other operations work is that they rely on the key being loaded _first_ through ENGINE_load_public(private)_key because this is when the PKCS11_CTX gets initialized and a handle to PKCS11_OBJECT_private gets set to the ex_data of the underlying key. Key generation obviously cannot rely on that mechanism since key doesn't yet exist. Instead, a generic PKCS11_generate_key interface was made that takes a structure describing the key generation algorithm. For now it only contains simple options like curve name for ECC or number of bits for RSA key generation. This interface can then be used as any other PKCS11 wrapper interface or using the ENGINE control commands. Using it with ENGINE control commands is demonstrated in the new tests/keygen.c file. Code for ECC keygen was taken from: OpenSC#379 and reworked to compile and work with some new additions to libp11 i.e. templates.
1 parent b2ba7ce commit 23ac33d

11 files changed

+543
-32
lines changed
 

‎src/eng_back.c

+60
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,64 @@ EVP_PKEY *ctx_load_privkey(ENGINE_CTX *ctx, const char *s_key_id,
890890
return PKCS11_get_private_key(key);
891891
}
892892

893+
static int ctx_keygen(ENGINE_CTX *ctx, void *p)
894+
{
895+
int rv = 1;
896+
int i;
897+
PKCS11_KGEN_ATTRS *kg_attrs = p;
898+
PKCS11_SLOT* slot = NULL;
899+
900+
pthread_mutex_lock(&ctx->lock);
901+
/* Delayed libp11 initialization */
902+
if (ctx_init_libp11_unlocked(ctx)) {
903+
ENGerr(ENG_F_CTX_LOAD_OBJECT, ENG_R_INVALID_PARAMETER);
904+
goto done;
905+
}
906+
907+
// Take the first token that has a matching label
908+
// TODO: make this more intelligent
909+
for (i = 0; i < ctx->slot_count; ++i) {
910+
slot = ctx->slot_list + i;
911+
if (slot && slot->token && slot->token->initialized &&
912+
slot->token->label &&
913+
!strncmp(slot->token->label, kg_attrs->token_label, 32)) {
914+
break;
915+
}
916+
}
917+
918+
if (i == ctx->slot_count) {
919+
ctx_log(ctx, 0, "Initialized token with matching label not found...\n");
920+
goto done;
921+
}
922+
923+
if (!ctx->force_login) {
924+
ERR_clear_error();
925+
rv = PKCS11_generate_key(slot->token, kg_attrs);
926+
if (rv == 0) {
927+
goto done;
928+
}
929+
}
930+
931+
// Try with logging in
932+
ERR_clear_error();
933+
if (slot->token->loginRequired) {
934+
if (!ctx_login(ctx, slot, slot->token,
935+
NULL, NULL)) {
936+
ctx_log(ctx, 0, "Login to token failed, returning 0...\n");
937+
rv = 1;
938+
goto done;
939+
}
940+
rv = PKCS11_generate_key(slot->token, kg_attrs);
941+
if (rv < 0) {
942+
ctx_log(ctx, 0, "Failed to generate a key pair on the token."
943+
" Error code: %d\n", rv);
944+
}
945+
}
946+
947+
done:
948+
pthread_mutex_unlock(&ctx->lock);
949+
return rv ? 0 : 1;
950+
}
893951
/******************************************************************************/
894952
/* Engine ctrl request handling */
895953
/******************************************************************************/
@@ -1008,6 +1066,8 @@ int ctx_engine_ctrl(ENGINE_CTX *ctx, int cmd, long i, void *p, void (*f)())
10081066
return ctx_ctrl_force_login(ctx);
10091067
case CMD_RE_ENUMERATE:
10101068
return ctx_enumerate_slots(ctx, ctx->pkcs11_ctx);
1069+
case CMD_KEYGEN:
1070+
return ctx_keygen(ctx, p);
10111071
default:
10121072
ENGerr(ENG_F_CTX_ENGINE_CTRL, ENG_R_UNKNOWN_COMMAND);
10131073
break;

‎src/eng_front.c

+4
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ static const ENGINE_CMD_DEFN engine_cmd_defns[] = {
7979
"RE_ENUMERATE",
8080
"re enumerate slots",
8181
ENGINE_CMD_FLAG_NO_INPUT},
82+
{CMD_KEYGEN,
83+
"KEYGEN",
84+
"Generate asymmetric key pair",
85+
ENGINE_CMD_FLAG_INTERNAL},
8286
{0, NULL, NULL, 0}
8387
};
8488

‎src/engine.h

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#define CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 8)
5353
#define CMD_FORCE_LOGIN (ENGINE_CMD_BASE+9)
5454
#define CMD_RE_ENUMERATE (ENGINE_CMD_BASE+10)
55+
#define CMD_KEYGEN (ENGINE_CMD_BASE+11)
5556

5657
typedef struct st_engine_ctx ENGINE_CTX; /* opaque */
5758

‎src/libp11-int.h

+10-5
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ extern int ERR_load_CKR_strings(void);
125125
pkcs11_strdup((char *) s, sizeof(s))
126126
extern char *pkcs11_strdup(char *, size_t);
127127

128+
/* Hex to bin */
129+
extern int pkcs11_hex_to_bin(const char *, unsigned char *, size_t *);
130+
128131
/* Emulate the OpenSSL 1.1 getters */
129132
#if OPENSSL_VERSION_NUMBER < 0x10100003L || ( defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3000000L )
130133
#define EVP_PKEY_get0_RSA(key) ((key)->pkey.rsa)
@@ -307,12 +310,14 @@ extern int pkcs11_store_certificate(PKCS11_SLOT_private *, X509 * x509,
307310
extern int pkcs11_seed_random(PKCS11_SLOT_private *, const unsigned char *s, unsigned int s_len);
308311
extern int pkcs11_generate_random(PKCS11_SLOT_private *, unsigned char *r, unsigned int r_len);
309312

310-
/* Internal implementation of deprecated features */
311-
312313
/* Generate and store a private key on the token */
313-
extern int pkcs11_generate_key(PKCS11_SLOT_private *tpriv,
314-
int algorithm, unsigned int bits,
315-
char *label, unsigned char* id, size_t id_len);
314+
extern int pkcs11_rsa_keygen(PKCS11_SLOT_private *tpriv,
315+
unsigned int bits, char *label, unsigned char* id, size_t id_len);
316+
317+
extern int pkcs11_ec_keygen(PKCS11_SLOT_private *tpriv,
318+
const char *curve , char *label, unsigned char* id, size_t id_len);
319+
320+
/* Internal implementation of deprecated features */
316321

317322
/* Get the RSA key modulus size (in bytes) */
318323
extern int pkcs11_get_key_size(PKCS11_OBJECT_private *);

‎src/libp11.h

+30-15
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,25 @@ typedef struct PKCS11_ctx_st {
106106
void *_private;
107107
} PKCS11_CTX;
108108

109+
typedef struct PKCS11_ec_kgen_st {
110+
const char *curve;
111+
} PKCS11_EC_KGEN;
112+
113+
typedef struct PKCS11_rsa_kgen_st {
114+
unsigned int bits;
115+
} PKCS11_RSA_KGEN;
116+
117+
typedef struct PKCS11_kgen_attrs_st {
118+
int type;
119+
union {
120+
PKCS11_EC_KGEN *ec;
121+
PKCS11_RSA_KGEN *rsa;
122+
} kgen;
123+
char *token_label;
124+
char *key_label;
125+
char *key_id;
126+
} PKCS11_KGEN_ATTRS;
127+
109128
/**
110129
* Create a new libp11 context
111130
*
@@ -382,6 +401,17 @@ extern int PKCS11_store_certificate(PKCS11_TOKEN * token, X509 * x509,
382401
char *label, unsigned char *id, size_t id_len,
383402
PKCS11_CERT **ret_cert);
384403

404+
/**
405+
* Generate key pair on the token
406+
*
407+
* @param token on which the key should be generated
408+
* @param kgen_attrs struct describing key generation (selection of algorithm,
409+
* algorithm parameters...)
410+
* @retval 0 on success
411+
* @retval negative number on error
412+
*/
413+
extern int PKCS11_generate_key(PKCS11_TOKEN *token, PKCS11_KGEN_ATTRS *kgen_attrs);
414+
385415
/* Access the random number generator */
386416
extern int PKCS11_seed_random(PKCS11_SLOT *slot, const unsigned char *s, unsigned int s_len);
387417
extern int PKCS11_generate_random(PKCS11_SLOT *slot, unsigned char *r, unsigned int r_len);
@@ -438,21 +468,6 @@ extern void ERR_load_PKCS11_strings(void);
438468
* duplicate the functionality OpenSSL provides for EVP_PKEY objects
439469
*/
440470

441-
/**
442-
* Generate a private key on the token
443-
*
444-
* @param token token returned by PKCS11_find_token()
445-
* @param algorithm IGNORED (still here for backward compatibility)
446-
* @param bits size of the modulus in bits
447-
* @param label label for this key
448-
* @param id bytes to use as the id value
449-
* @param id_len length of the id value
450-
* @retval 0 success
451-
* @retval -1 error
452-
*/
453-
P11_DEPRECATED_FUNC extern int PKCS11_generate_key(PKCS11_TOKEN * token,
454-
int algorithm, unsigned int bits,
455-
char *label, unsigned char* id, size_t id_len);
456471

457472
/* Get the RSA key modulus size (in bytes) */
458473
P11_DEPRECATED_FUNC extern int PKCS11_get_key_size(PKCS11_KEY *);

‎src/p11_front.c

+24-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1717
*/
1818

19+
#include <string.h>
20+
1921
#include "libp11-int.h"
2022

2123
/* The following exported functions are *not* implemented here:
@@ -367,18 +369,34 @@ int PKCS11_set_ui_method(PKCS11_CTX *pctx, UI_METHOD *ui_method, void *ui_user_d
367369
return pkcs11_set_ui_method(ctx, ui_method, ui_user_data);
368370
}
369371

370-
/* External interface to the deprecated features */
371-
372-
int PKCS11_generate_key(PKCS11_TOKEN *token,
373-
int algorithm, unsigned int bits,
374-
char *label, unsigned char *id, size_t id_len)
372+
int PKCS11_generate_key(PKCS11_TOKEN *token, PKCS11_KGEN_ATTRS *kg)
375373
{
376374
PKCS11_SLOT_private *slot = PRIVSLOT(token->slot);
377375
if (check_slot_fork(slot) < 0)
378376
return -1;
379-
return pkcs11_generate_key(slot, algorithm, bits, label, id, id_len);
377+
unsigned char out[128] = {0};
378+
size_t key_id_len = 0;
379+
if (kg && kg->key_id) {
380+
key_id_len = strlen(kg->key_id);
381+
if (key_id_len > 127) {
382+
return -2;
383+
}
384+
pkcs11_hex_to_bin(kg->key_id, out, &key_id_len);
385+
}
386+
switch(kg->type) {
387+
case EVP_PKEY_RSA:
388+
return pkcs11_rsa_keygen(slot, kg->kgen.rsa->bits,
389+
kg->key_label, out, key_id_len);
390+
case EVP_PKEY_EC:
391+
return pkcs11_ec_keygen(slot, kg->kgen.ec->curve,
392+
kg->key_label, out, key_id_len);
393+
default:
394+
return -3;
395+
}
380396
}
381397

398+
/* External interface to the deprecated features */
399+
382400
int PKCS11_get_key_size(PKCS11_KEY *pkey)
383401
{
384402
PKCS11_OBJECT_private *key = PRIVKEY(pkey);

‎src/p11_key.c

+90-4
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ int pkcs11_reload_object(PKCS11_OBJECT_private *obj)
252252
/**
253253
* Generate a key pair directly on token
254254
*/
255-
int pkcs11_generate_key(PKCS11_SLOT_private *slot, int algorithm, unsigned int bits,
255+
int pkcs11_rsa_keygen(PKCS11_SLOT_private *slot, unsigned int bits,
256256
char *label, unsigned char* id, size_t id_len) {
257257

258258
PKCS11_CTX_private *ctx = slot->ctx;
@@ -266,10 +266,8 @@ int pkcs11_generate_key(PKCS11_SLOT_private *slot, int algorithm, unsigned int b
266266
CK_OBJECT_HANDLE pub_key_obj, priv_key_obj;
267267
int rv;
268268

269-
(void)algorithm; /* squash the unused parameter warning */
270-
271269
if (pkcs11_get_session(slot, 1, &session))
272-
return -1;
270+
return -10;
273271

274272
/* pubkey attributes */
275273
pkcs11_addattr(&pubtmpl, CKA_ID, id, id_len);
@@ -310,6 +308,94 @@ int pkcs11_generate_key(PKCS11_SLOT_private *slot, int algorithm, unsigned int b
310308
return 0;
311309
}
312310

311+
int pkcs11_ec_keygen(PKCS11_SLOT_private *slot, const char *curve,
312+
char *label, unsigned char *id, size_t id_len)
313+
{
314+
PKCS11_CTX_private *ctx = slot->ctx;
315+
CK_SESSION_HANDLE session;
316+
PKCS11_TEMPLATE pubtmpl = {0}, privtmpl = {0};
317+
CK_MECHANISM mechanism = {
318+
CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0
319+
};
320+
321+
CK_OBJECT_HANDLE pub_key_obj, priv_key_obj;
322+
int rv;
323+
324+
unsigned char *ecdsa_params = NULL;
325+
int ecdsa_params_len = 0;
326+
unsigned char *tmp = NULL;
327+
ASN1_OBJECT *curve_obj = NULL;
328+
int curve_nid = NID_undef;
329+
330+
if (pkcs11_get_session(slot, 1, &session)) {
331+
return -20;
332+
}
333+
334+
curve_nid = EC_curve_nist2nid(curve);
335+
if (curve_nid == NID_undef)
336+
curve_nid = OBJ_sn2nid(curve);
337+
if (curve_nid == NID_undef)
338+
curve_nid = OBJ_ln2nid(curve);
339+
if (curve_nid == NID_undef)
340+
return -21;
341+
342+
curve_obj = OBJ_nid2obj(curve_nid);
343+
if (!curve_obj)
344+
return -22;
345+
ecdsa_params_len = i2d_ASN1_OBJECT(curve_obj, NULL);
346+
ecdsa_params = (unsigned char *)OPENSSL_malloc(ecdsa_params_len);
347+
if (!ecdsa_params)
348+
return -23;
349+
tmp = ecdsa_params;
350+
i2d_ASN1_OBJECT(curve_obj, &tmp);
351+
352+
/* pubkey attributes */
353+
pkcs11_addattr(&pubtmpl, CKA_ID, id, id_len);
354+
if (label)
355+
pkcs11_addattr_s(&pubtmpl, CKA_LABEL, label);
356+
pkcs11_addattr_bool(&pubtmpl, CKA_TOKEN, TRUE);
357+
pkcs11_addattr_bool(&pubtmpl, CKA_DERIVE, TRUE);
358+
pkcs11_addattr_bool(&pubtmpl, CKA_WRAP, FALSE);
359+
pkcs11_addattr_bool(&pubtmpl, CKA_VERIFY, TRUE);
360+
pkcs11_addattr_bool(&pubtmpl, CKA_VERIFY_RECOVER, FALSE);
361+
pkcs11_addattr_bool(&pubtmpl, CKA_ENCRYPT, FALSE);
362+
pkcs11_addattr(&pubtmpl, CKA_ECDSA_PARAMS, ecdsa_params, ecdsa_params_len);
363+
364+
/* privkey attributes */
365+
pkcs11_addattr(&privtmpl, CKA_ID, id, id_len);
366+
if (label)
367+
pkcs11_addattr_s(&privtmpl, CKA_LABEL, label);
368+
pkcs11_addattr_bool(&privtmpl, CKA_TOKEN, TRUE);
369+
pkcs11_addattr_bool(&privtmpl, CKA_PRIVATE, TRUE);
370+
pkcs11_addattr_bool(&privtmpl, CKA_SENSITIVE, TRUE);
371+
pkcs11_addattr_bool(&privtmpl, CKA_DERIVE, TRUE);
372+
pkcs11_addattr_bool(&privtmpl, CKA_UNWRAP, FALSE);
373+
pkcs11_addattr_bool(&privtmpl, CKA_SIGN, TRUE);
374+
pkcs11_addattr_bool(&privtmpl, CKA_DECRYPT, FALSE);
375+
376+
/* call the pkcs11 module to create the key pair */
377+
rv = CRYPTOKI_call(ctx, C_GenerateKeyPair(
378+
session,
379+
&mechanism,
380+
pubtmpl.attrs,
381+
pubtmpl.nattr,
382+
privtmpl.attrs,
383+
privtmpl.nattr,
384+
&pub_key_obj,
385+
&priv_key_obj
386+
));
387+
388+
pkcs11_put_session(slot, session);
389+
390+
/* zap all memory allocated when building the template */
391+
pkcs11_zap_attrs(&privtmpl);
392+
pkcs11_zap_attrs(&pubtmpl);
393+
OPENSSL_free(ecdsa_params);
394+
395+
CRYPTOKI_checkerr(CKR_F_PKCS11_GENERATE_KEY, rv);
396+
return 0;
397+
}
398+
313399
/*
314400
* Store a private key on the token
315401
*/

‎src/p11_misc.c

+75
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,79 @@ int pkcs11_atomic_add(int *value, int amount, pthread_mutex_t *lock)
6060
#endif
6161
}
6262

63+
/* Stolen from OpenSC/src/libopensc/sc.c */
64+
int pkcs11_hex_to_bin(const char *in, unsigned char *out, size_t *outlen)
65+
{
66+
const char *sc_hex_to_bin_separators = " :";
67+
if (in == NULL || out == NULL || outlen == NULL) {
68+
return -1;
69+
}
70+
71+
int byte_needs_nibble = 0;
72+
int r = 0;
73+
size_t left = *outlen;
74+
unsigned char byte = 0;
75+
while (*in != '\0' && 0 != left) {
76+
char c = *in++;
77+
unsigned char nibble;
78+
if ('0' <= c && c <= '9')
79+
nibble = c - '0';
80+
else if ('a' <= c && c <= 'f')
81+
nibble = c - 'a' + 10;
82+
else if ('A' <= c && c <= 'F')
83+
nibble = c - 'A' + 10;
84+
else {
85+
if (strchr(sc_hex_to_bin_separators, (int) c)) {
86+
if (byte_needs_nibble) {
87+
r = -2;
88+
goto err;
89+
}
90+
continue;
91+
}
92+
r = -3;
93+
goto err;
94+
}
95+
96+
if (byte_needs_nibble) {
97+
byte |= nibble;
98+
*out++ = (unsigned char) byte;
99+
left--;
100+
byte_needs_nibble = 0;
101+
} else {
102+
byte = nibble << 4;
103+
byte_needs_nibble = 1;
104+
}
105+
}
106+
107+
if (left == *outlen && 1 == byte_needs_nibble && 0 != left) {
108+
/* no output written so far, but we have a valid nibble in the upper
109+
* bits. Allow this special case. */
110+
*out = (unsigned char) byte>>4;
111+
left--;
112+
byte_needs_nibble = 0;
113+
}
114+
115+
/* for ease of implementation we only accept completely hexed bytes. */
116+
if (byte_needs_nibble) {
117+
r = -4;
118+
goto err;
119+
}
120+
121+
/* skip all trailing separators to see if we missed something */
122+
while (*in != '\0') {
123+
if (NULL == strchr(sc_hex_to_bin_separators, (int) *in))
124+
break;
125+
in++;
126+
}
127+
if (*in != '\0') {
128+
r = -5;
129+
goto err;
130+
}
131+
132+
err:
133+
*outlen -= left;
134+
return r;
135+
}
136+
137+
63138
/* vim: set noexpandtab: */

‎tests/Makefile.am

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ check_PROGRAMS = \
1818
rsa-oaep \
1919
check-privkey \
2020
store-cert \
21-
dup-key
21+
dup-key \
22+
keygen
2223
dist_check_SCRIPTS = \
2324
rsa-testpkcs11.softhsm \
2425
rsa-testfork.softhsm \
@@ -35,7 +36,8 @@ dist_check_SCRIPTS = \
3536
pkcs11-uri-without-token.softhsm \
3637
search-all-matching-tokens.softhsm \
3738
ec-cert-store.softhsm \
38-
ec-copy.softhsm
39+
ec-copy.softhsm \
40+
keygen.softhsm
3941
dist_check_DATA = \
4042
rsa-cert.der rsa-prvkey.der rsa-pubkey.der \
4143
ec-cert.der ec-prvkey.der ec-pubkey.der

‎tests/keygen.c

+206
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/*
2+
* This program is free software: you can redistribute it and/or modify
3+
* it under the terms of the GNU General Public License as published by
4+
* the Free Software Foundation, either version 3 of the License, or
5+
* (at your option) any later version.
6+
*
7+
* This program is distributed in the hope that it will be useful,
8+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
* GNU General Public License for more details.
11+
*
12+
* You should have received a copy of the GNU General Public License
13+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
14+
*/
15+
16+
#include <libp11.h>
17+
#include <openssl/conf.h>
18+
#include <openssl/engine.h>
19+
#include <openssl/pem.h>
20+
#include <string.h>
21+
22+
static void
23+
usage(char* argv[])
24+
{
25+
fprintf(stderr,
26+
"%s token_label key_label [module]\n",
27+
argv[0]);
28+
}
29+
30+
static void
31+
display_openssl_errors(int l)
32+
{
33+
const char* file;
34+
char buf[120];
35+
int e, line;
36+
37+
if (ERR_peek_error() == 0)
38+
return;
39+
fprintf(stderr, "At main.c:%d:\n", l);
40+
41+
while ((e = ERR_get_error_line(&file, &line))) {
42+
ERR_error_string(e, buf);
43+
fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line);
44+
}
45+
}
46+
47+
static int sign_verify_test(EVP_PKEY *priv, EVP_PKEY *pub) {
48+
EVP_MD_CTX *mdctx = NULL;
49+
int retval = 0;
50+
char *msg = "libp11";
51+
size_t slen;
52+
unsigned char *sig = NULL;
53+
54+
if (!priv || !pub) {
55+
fprintf(stderr, "Where are the keys?\n");
56+
return -1;
57+
}
58+
if(!(mdctx = EVP_MD_CTX_create())) {
59+
display_openssl_errors(__LINE__);
60+
retval = -2;
61+
goto err;
62+
}
63+
if(1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, priv)) {
64+
display_openssl_errors(__LINE__);
65+
retval = -3;
66+
goto err;
67+
}
68+
if(1 != EVP_DigestSignUpdate(mdctx, msg, strlen(msg))) {
69+
display_openssl_errors(__LINE__);
70+
retval = -4;
71+
goto err;
72+
}
73+
if(1 != EVP_DigestSignFinal(mdctx, NULL, &slen)) {
74+
display_openssl_errors(__LINE__);
75+
retval = -5;
76+
goto err;
77+
}
78+
if(!(sig = OPENSSL_malloc(sizeof(unsigned char) * (slen)))) {
79+
display_openssl_errors(__LINE__);
80+
retval = -6;
81+
goto err;
82+
}
83+
if(1 != EVP_DigestSignFinal(mdctx, sig, &slen)) {
84+
display_openssl_errors(__LINE__);
85+
retval = -7;
86+
fprintf(stderr, "Sign fail\n");
87+
goto err;
88+
}
89+
printf("Sign success\n");
90+
91+
if(1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pub)) {
92+
display_openssl_errors(__LINE__);
93+
retval = -8;
94+
goto err;
95+
}
96+
if(1 != EVP_DigestVerifyUpdate(mdctx, msg, strlen(msg))) {
97+
display_openssl_errors(__LINE__);
98+
retval = -9;
99+
goto err;
100+
}
101+
if(1 == EVP_DigestVerifyFinal(mdctx, sig, slen))
102+
{
103+
printf("Verify success\n");
104+
retval = 0;
105+
}
106+
else
107+
{
108+
display_openssl_errors(__LINE__);
109+
fprintf(stderr, "Verify fail\n");
110+
retval = -10;
111+
goto err;
112+
}
113+
114+
err:
115+
if(sig) OPENSSL_free(sig);
116+
if(mdctx) EVP_MD_CTX_destroy(mdctx);
117+
return retval;
118+
}
119+
120+
int
121+
main(int argc, char* argv[])
122+
{
123+
int ret = 0;
124+
ENGINE* engine = NULL;
125+
char *module = argv[3];
126+
127+
if (argc < 3) {
128+
fprintf(stderr, "Too few arguments\n");
129+
usage(argv);
130+
return 1;
131+
}
132+
133+
ENGINE_load_builtin_engines();
134+
engine = ENGINE_by_id("pkcs11");
135+
if (engine == NULL) {
136+
fprintf(stderr, "Could not get engine\n");
137+
display_openssl_errors(__LINE__);
138+
exit(1);
139+
}
140+
if (!ENGINE_ctrl_cmd_string(engine, "PIN", "1234", 0)) {
141+
display_openssl_errors(__LINE__);
142+
exit(1);
143+
}
144+
if (!ENGINE_ctrl_cmd_string(engine, "VERBOSE", NULL, 0)) {
145+
display_openssl_errors(__LINE__);
146+
exit(1);
147+
}
148+
if (module) {
149+
if (!ENGINE_ctrl_cmd_string(engine, "MODULE_PATH", module, 0)) {
150+
display_openssl_errors(__LINE__);
151+
exit(1);
152+
}
153+
}
154+
if (!ENGINE_init(engine)) {
155+
fprintf(stderr, "Could not initialize engine\n");
156+
display_openssl_errors(__LINE__);
157+
exit(1);
158+
}
159+
160+
PKCS11_EC_KGEN ec = {
161+
.curve = "P-256"
162+
};
163+
PKCS11_KGEN_ATTRS eckg =
164+
{
165+
.type = EVP_PKEY_EC,
166+
.kgen.ec = &ec,
167+
.token_label = argv[1],
168+
.key_label = argv[2],
169+
.key_id = "1234",
170+
};
171+
172+
if (!ENGINE_ctrl_cmd(engine, "KEYGEN", 0, &eckg, NULL, 1)) {
173+
fprintf(stderr, "Could not generate ECC keys\n");
174+
exit(1);
175+
}
176+
177+
EVP_PKEY *ecpb = ENGINE_load_public_key(engine, "1234", NULL, NULL);
178+
EVP_PKEY *ecpr = ENGINE_load_private_key(engine, "1234", NULL, NULL);
179+
if ((ret = sign_verify_test(ecpr, ecpb)) < 0) {
180+
fprintf(stderr, "ECC Sign-verify failed with err code: %d\n", ret);
181+
exit(1);
182+
}
183+
PKCS11_RSA_KGEN rsa = {
184+
.bits = 2048
185+
};
186+
PKCS11_KGEN_ATTRS rsakg = {
187+
.type = EVP_PKEY_RSA,
188+
.kgen.rsa = &rsa,
189+
.token_label = argv[1],
190+
.key_label = argv[2],
191+
.key_id = "4321",
192+
};
193+
if (!ENGINE_ctrl_cmd(engine, "KEYGEN", 0, &rsakg, NULL, 1)) {
194+
fprintf(stderr, "Could not generate RSA keys\n");
195+
exit(1);
196+
}
197+
EVP_PKEY *rsapb = ENGINE_load_public_key(engine, "4321", NULL, NULL);
198+
EVP_PKEY *rsapr = ENGINE_load_private_key(engine, "4321", NULL, NULL);
199+
if ((ret = sign_verify_test(rsapr, rsapb)) < 0) {
200+
fprintf(stderr, "RSA Sign-verify failed with err code: %d\n", ret);
201+
exit(1);
202+
}
203+
204+
ENGINE_finish(engine);
205+
return ret;
206+
}

‎tests/keygen.softhsm

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/sh
2+
3+
# This program is free software: you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License as published by
5+
# the Free Software Foundation, either version 3 of the License, or
6+
# (at your option) any later version.
7+
#
8+
# This program is distributed in the hope that it will be useful,
9+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
# GNU General Public License for more details.
12+
#
13+
# You should have received a copy of the GNU General Public License
14+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
15+
16+
outdir="output.$$"
17+
18+
# Load common test functions
19+
. ${srcdir}/ec-no-pubkey.sh
20+
21+
sed -e "s|@MODULE_PATH@|${MODULE}|g" -e "s|@ENGINE_PATH@|../src/.libs/pkcs11.so|g" <"${srcdir}/engines.cnf.in" >"${outdir}/engines.cnf"
22+
23+
export OPENSSL_ENGINES="../src/.libs/"
24+
25+
./keygen libp11-test libp11-keylabel ${MODULE}
26+
if test $? != 0;then
27+
echo "Key generation failed"
28+
exit 1;
29+
fi
30+
31+
pkcs11-tool -p 1234 --module ${MODULE} -l -O | grep -q libp11-keylabel
32+
if test $? != 0;then
33+
echo "The key was not properly generated"
34+
exit 1;
35+
fi
36+
37+
rm -rf "$outdir"
38+
39+
exit 0

0 commit comments

Comments
 (0)
Please sign in to comment.