Skip to content

Commit 6de7737

Browse files
authored
Add support for Ed25519 and Ed448 curves (PKCS#11 v3.2) (#623)
1 parent ef07ad5 commit 6de7737

26 files changed

+2526
-13
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ examples/listkeys
6464
examples/listkeys_ext
6565
examples/eckeygen
6666
examples/rsakeygen
67+
examples/ed25519keygen
68+
examples/ed448keygen
6769
examples/storecert
6870

6971
test-driver
@@ -84,6 +86,10 @@ tests/rsa-oaep-prov
8486
tests/rsa-pss-sign-prov
8587
tests/rsa-keygen
8688
tests/ec-keygen
89+
tests/ed25519-keygen
90+
tests/ed448-keygen
91+
tests/ed25519-keygen-prov
92+
tests/ed448-keygen-prov
8793
tests/check-all-prov
8894

8995
tests/*.log

examples/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir)/src \
44

55
EXTRA_DIST = README
66

7-
noinst_PROGRAMS = auth decrypt getrandom listkeys listkeys_ext eckeygen rsakeygen storecert
7+
noinst_PROGRAMS = auth decrypt getrandom listkeys listkeys_ext ed25519keygen ed448keygen eckeygen rsakeygen storecert
88

99
LDADD = ../src/libp11.la $(OPENSSL_LIBS)
1010

examples/ed25519keygen.c

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/*
2+
* Copyright © 2025 Mobi - Com Polska Sp. z o.o.
3+
* Author: Małgorzata Olszówka <[email protected]>
4+
* All rights reserved.
5+
*
6+
* Elliptic Curve Ed25519 key generation
7+
*
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions
10+
* are met:
11+
* 1. Redistributions of source code must retain the above copyright
12+
* notice, this list of conditions and the following disclaimer.
13+
* 2. Redistributions in binary form must reproduce the above copyright
14+
* notice, this list of conditions and the following disclaimer in the
15+
* documentation and/or other materials provided with the distribution.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27+
* SUCH DAMAGE.
28+
*/
29+
30+
#if !defined(OPENSSL_NO_EC) && OPENSSL_VERSION_NUMBER >= 0x30000000L
31+
32+
#include <libp11.h>
33+
#include <string.h>
34+
35+
#define CHECK_ERR(cond, txt, code) \
36+
do { \
37+
if (cond) { \
38+
fprintf(stderr, "%s\n", (txt)); \
39+
rc=(code); \
40+
goto end; \
41+
} \
42+
} while (0)
43+
44+
static void error_queue(const char *name)
45+
{
46+
if (ERR_peek_last_error()) {
47+
fprintf(stderr, "%s generated errors:\n", name);
48+
ERR_print_errors_fp(stderr);
49+
}
50+
}
51+
52+
static int hex_to_bytes(const char *hex, unsigned char *out, size_t out_len)
53+
{
54+
size_t i;
55+
56+
for (i = 0; i < out_len; i++) {
57+
if (sscanf(hex + (i * 2), "%2hhx", &out[i]) != 1) {
58+
return -1;
59+
}
60+
}
61+
return 0;
62+
}
63+
64+
static void list_keys(const char *title, const PKCS11_KEY *keys,
65+
const unsigned int nkeys) {
66+
unsigned int i;
67+
68+
printf("\n%s:\n", title);
69+
for (i = 0; i < nkeys; i++) {
70+
printf(" #%d id=", i);
71+
for (size_t j = 0; j < keys[i].id_len; j++) {
72+
printf("%02x", keys[i].id[j]);
73+
}
74+
printf(";object=%s\n", keys[i].label);
75+
}
76+
}
77+
78+
int main(int argc, char *argv[])
79+
{
80+
PKCS11_CTX *ctx = NULL;
81+
PKCS11_SLOT *slots = NULL, *slot;
82+
PKCS11_KEY *keys;
83+
unsigned int nslots, nkeys;
84+
unsigned char *key_id = NULL;
85+
size_t len, key_id_len;
86+
const char *key_id_str;
87+
int rc = 0;
88+
PKCS11_params params = {.sensitive = 1, .extractable = 0};
89+
PKCS11_EDDSA_KGEN eddsa = {.nid = NID_ED25519};
90+
PKCS11_KGEN_ATTRS eckg = {0};
91+
92+
if (argc < 5) {
93+
fprintf(stderr, "usage: %s [module] [TOKEN] [KEY-LABEL] [KEY-ID] [PIN]\n", argv[0]);
94+
return 1;
95+
}
96+
key_id_str = argv[4];
97+
len = strlen(key_id_str);
98+
CHECK_ERR(len % 2 != 0, "Invalid key ID format: odd length", 1);
99+
100+
/* key_id_str is a null-terminated string, but key_id is not */
101+
key_id_len = len / 2;
102+
key_id = OPENSSL_malloc(key_id_len);
103+
CHECK_ERR(!key_id, "Memory allocation failed for key ID", 2);
104+
105+
rc = hex_to_bytes(key_id_str, key_id, key_id_len);
106+
CHECK_ERR(rc != 0, "Invalid hex digit in key ID", 3);
107+
108+
ctx = PKCS11_CTX_new();
109+
error_queue("PKCS11_CTX_new");
110+
111+
/* load PKCS#11 module */
112+
rc = PKCS11_CTX_load(ctx, argv[1]);
113+
error_queue("PKCS11_CTX_load");
114+
CHECK_ERR(rc < 0, "loading PKCS#11 module failed", 4);
115+
116+
/* get information on all slots */
117+
rc = PKCS11_enumerate_slots(ctx, &slots, &nslots);
118+
error_queue("PKCS11_enumerate_slots");
119+
CHECK_ERR(rc < 0, "no slots available", 5);
120+
121+
slot = PKCS11_find_token(ctx, slots, nslots);
122+
error_queue("PKCS11_find_token");
123+
while (slot) {
124+
if (slot->token && slot->token->initialized && slot->token->label
125+
&& strcmp(argv[2], slot->token->label) == 0)
126+
break;
127+
slot = PKCS11_find_next_token(ctx, slots, nslots, slot);
128+
};
129+
CHECK_ERR(!slot || !slot->token, "no token available", 6);
130+
131+
printf("Found token:\n");
132+
printf("Slot manufacturer......: %s\n", slot->manufacturer);
133+
printf("Slot description.......: %s\n", slot->description);
134+
printf("Slot token label.......: %s\n", slot->token->label);
135+
printf("Slot token serialnr....: %s\n", slot->token->serialnr);
136+
137+
rc = PKCS11_login(slot, 0, argv[5]);
138+
error_queue("PKCS11_login");
139+
CHECK_ERR(rc < 0, "PKCS11_login failed", 7);
140+
141+
eckg.type = EVP_PKEY_ED25519;
142+
eckg.kgen.eddsa = &eddsa;
143+
eckg.token_label = argv[2];
144+
eckg.key_label = argv[3];
145+
/* key_id is a raw binary buffer of length key_id_len */
146+
eckg.key_id = (const unsigned char *)key_id;
147+
eckg.id_len = key_id_len;
148+
eckg.key_params = &params;
149+
150+
rc = PKCS11_keygen(slot->token, &eckg);
151+
error_queue("PKCS11_keygen");
152+
CHECK_ERR(rc < 0, "Failed to generate a key pair on the token", 8);
153+
154+
printf("\nEd25519 keys generated\n");
155+
156+
/* get private keys */
157+
rc = PKCS11_enumerate_keys(slot->token, &keys, &nkeys);
158+
error_queue("PKCS11_enumerate_keys");
159+
CHECK_ERR(rc < 0, "PKCS11_enumerate_keys failed", 9);
160+
CHECK_ERR(nkeys == 0, "No private keys found", 10);
161+
list_keys("Private keys", keys, nkeys);
162+
163+
end:
164+
if (slots)
165+
PKCS11_release_all_slots(ctx, slots, nslots);
166+
if (ctx) {
167+
PKCS11_CTX_unload(ctx);
168+
PKCS11_CTX_free(ctx);
169+
}
170+
OPENSSL_free(key_id);
171+
172+
if (rc)
173+
printf("Failed (error code %d).\n", rc);
174+
else
175+
printf("Success.\n");
176+
return rc;
177+
}
178+
179+
#else /* !defined(OPENSSL_NO_EC) && OPENSSL_VERSION_NUMBER >= 0x30000000L */
180+
181+
int main(void)
182+
{
183+
return 0;
184+
}
185+
186+
#endif /* !defined(OPENSSL_NO_EC) && OPENSSL_VERSION_NUMBER >= 0x30000000L */
187+
188+
/* vim: set noexpandtab: */

0 commit comments

Comments
 (0)