Skip to content

Commit e06f291

Browse files
committed
softhsm2-util: support import certificate
The softhsm2-util already support importing keys, why not also import certificates? Useful for test scripts that require both keys and certificates. Add --import-type <type> parameter, depreciate the --aes parameter. Signed-off-by: Alon Bar-Lev <[email protected]>
1 parent 6d75f15 commit e06f291

5 files changed

+361
-29
lines changed

src/bin/util/softhsm2-util-botan.cpp

+61
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
#include <botan/bigint.h>
4848
#include <botan/der_enc.h>
4949
#include <botan/oids.h>
50+
#include <botan/der_enc.h>
51+
#include <botan/x509cert.h>
52+
#include <botan/x509_dn.h>
5053

5154
// Init Botan
5255
void crypto_init()
@@ -209,6 +212,64 @@ int crypto_import_key_pair
209212
return result;
210213
}
211214

215+
int crypto_import_certificate
216+
(
217+
CK_SESSION_HANDLE hSession,
218+
char* filePath,
219+
char* label,
220+
char* objID,
221+
size_t objIDLen
222+
)
223+
{
224+
auto _vector_ptr = [](std::vector<uint8_t> &v) {
225+
return v.size() == 0 ? NULL : &v.front();
226+
};
227+
228+
Botan::X509_Certificate cert(filePath);
229+
std::vector<uint8_t> blob;
230+
std::vector<uint8_t> subject;
231+
std::vector<uint8_t> issuer;
232+
std::vector<uint8_t> serial;
233+
234+
Botan::DER_Encoder blob_encoder(blob);
235+
Botan::DER_Encoder subject_encoder(subject);
236+
Botan::DER_Encoder issuer_encoder(issuer);
237+
Botan::DER_Encoder serial_encoder(serial);
238+
239+
cert.encode_into(blob_encoder);
240+
cert.subject_dn().encode_into(subject_encoder);
241+
cert.issuer_dn().encode_into(issuer_encoder);
242+
serial_encoder.encode(Botan::BigInt::decode(cert.serial_number()));
243+
244+
CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
245+
CK_CERTIFICATE_TYPE certType = CKC_X_509;
246+
CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
247+
CK_ATTRIBUTE certTemplate[] = {
248+
{ CKA_CLASS, &certClass, sizeof(certClass) },
249+
{ CKA_CERTIFICATE_TYPE, &certType, sizeof(certType) },
250+
{ CKA_LABEL, label, strlen(label) },
251+
{ CKA_ID, objID, objIDLen },
252+
{ CKA_TOKEN, &ckToken, sizeof(ckToken) },
253+
{ CKA_PRIVATE, &ckFalse, sizeof(ckTrue) },
254+
{ CKA_VALUE, _vector_ptr(blob), (CK_ULONG)blob.size() },
255+
{ CKA_SUBJECT, _vector_ptr(subject), (CK_ULONG)subject.size() },
256+
{ CKA_ISSUER, _vector_ptr(issuer), (CK_ULONG)issuer.size() },
257+
{ CKA_SERIAL_NUMBER, _vector_ptr(serial), (CK_ULONG)serial.size() }
258+
};
259+
260+
CK_OBJECT_HANDLE hCert;
261+
CK_RV rv = p11->C_CreateObject(hSession, certTemplate, 10, &hCert);
262+
if (rv != CKR_OK)
263+
{
264+
fprintf(stderr, "ERROR: Could not save the certificate in the token.\n");
265+
return 1;
266+
}
267+
268+
printf("The certificate has been imported.\n");
269+
270+
return 0;
271+
}
272+
212273
// Read the key from file
213274
Botan::Private_Key* crypto_read_file(char* filePath, char* filePIN)
214275
{

src/bin/util/softhsm2-util-ossl.cpp

+131
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,137 @@ int crypto_import_key_pair
218218
return result;
219219
}
220220

221+
int crypto_import_certificate
222+
(
223+
CK_SESSION_HANDLE hSession,
224+
char* filePath,
225+
char* label,
226+
char* objID,
227+
size_t objIDLen
228+
)
229+
{
230+
BIO* in = NULL;
231+
X509* x509 = NULL;
232+
CK_BYTE_PTR blob = NULL;
233+
CK_BYTE_PTR subject = NULL;
234+
CK_BYTE_PTR issuer = NULL;
235+
CK_BYTE_PTR serial = NULL;
236+
CK_BYTE_PTR p;
237+
int blobSize;
238+
int subjectSize;
239+
int issuerSize;
240+
int serialSize;
241+
int ret = 1;
242+
243+
if (!(in = BIO_new_file(filePath, "rb")))
244+
{
245+
fprintf(stderr, "ERROR: Could open the PKCS#8 file: %s\n", filePath);
246+
goto cleanup;
247+
}
248+
249+
if ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
250+
{
251+
fprintf(stderr, "ERROR: Could not read the certificate file: %s\n", filePath);
252+
goto cleanup;
253+
}
254+
255+
blobSize = i2d_X509(x509, NULL);
256+
subjectSize = i2d_X509_NAME(X509_get_subject_name(x509), NULL);
257+
issuerSize = i2d_X509_NAME(X509_get_issuer_name(x509), NULL);
258+
serialSize = i2d_ASN1_INTEGER(X509_get_serialNumber(x509), NULL);
259+
260+
if
261+
(
262+
blobSize == -1 ||
263+
subjectSize == -1 ||
264+
issuerSize == -1 ||
265+
serialSize == -1
266+
)
267+
{
268+
fprintf(stderr, "ERROR: Could not convert certificate to DER.\n");
269+
goto cleanup;
270+
}
271+
272+
blob = (CK_BYTE_PTR)malloc(blobSize);
273+
subject = (CK_BYTE_PTR)malloc(subjectSize);
274+
issuer = (CK_BYTE_PTR)malloc(issuerSize);
275+
serial = (CK_BYTE_PTR)malloc(serialSize);
276+
277+
if
278+
(
279+
blob == NULL ||
280+
subject == NULL ||
281+
issuer == NULL ||
282+
serial == NULL
283+
)
284+
{
285+
fprintf(stderr, "ERROR: Could not allocate memory.\n");
286+
return 1;
287+
}
288+
289+
p = blob;
290+
blobSize = i2d_X509(x509, &p);
291+
p = subject;
292+
subjectSize = i2d_X509_NAME(X509_get_subject_name(x509), &p);
293+
p = issuer;
294+
issuerSize = i2d_X509_NAME(X509_get_issuer_name(x509), &p);
295+
p = serial;
296+
serialSize = i2d_ASN1_INTEGER(X509_get_serialNumber(x509), &p);
297+
298+
if
299+
(
300+
blobSize == -1 ||
301+
subjectSize == -1 ||
302+
issuerSize == -1 ||
303+
serialSize == -1
304+
)
305+
{
306+
fprintf(stderr, "ERROR: Could not convert certificate to DER.\n");
307+
goto cleanup;
308+
}
309+
310+
{
311+
CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
312+
CK_CERTIFICATE_TYPE certType = CKC_X_509;
313+
CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
314+
CK_ATTRIBUTE certTemplate[] = {
315+
{ CKA_CLASS, &certClass, sizeof(certClass) },
316+
{ CKA_CERTIFICATE_TYPE, &certType, sizeof(certType) },
317+
{ CKA_LABEL, label, strlen(label) },
318+
{ CKA_ID, objID, objIDLen },
319+
{ CKA_TOKEN, &ckToken, sizeof(ckToken) },
320+
{ CKA_PRIVATE, &ckFalse, sizeof(ckTrue) },
321+
{ CKA_VALUE, blob, (CK_ULONG)blobSize },
322+
{ CKA_SUBJECT, subject, (CK_ULONG)subjectSize },
323+
{ CKA_ISSUER, issuer, (CK_ULONG)issuerSize },
324+
{ CKA_SERIAL_NUMBER, serial, (CK_ULONG)serialSize }
325+
};
326+
327+
CK_OBJECT_HANDLE hCert;
328+
CK_RV rv = p11->C_CreateObject(hSession, certTemplate, 10, &hCert);
329+
if (rv != CKR_OK)
330+
{
331+
fprintf(stderr, "ERROR: Could not save the certificate in the token.\n");
332+
goto cleanup;
333+
}
334+
}
335+
336+
printf("The certificate has been imported.\n");
337+
338+
ret = 0;
339+
340+
cleanup:
341+
342+
free(blob);
343+
free(subject);
344+
free(issuer);
345+
free(serial);
346+
X509_free(x509);
347+
BIO_free(in);
348+
349+
return ret;
350+
}
351+
221352
// Read the key from file
222353
EVP_PKEY* crypto_read_file(char* filePath, char* filePIN)
223354
{

src/bin/util/softhsm2-util.1

+21-17
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,23 @@ softhsm2-util \- support tool for libsofthsm2
2020
.PP
2121
.B softhsm2-util \-\-import
2222
.I path
23+
.RB [ \-\-import-type
24+
.IR type ]
25+
\\
26+
.ti +0.7i
2327
.RB [ \-\-file-pin
2428
.IR PIN ]
2529
.B \-\-token
2630
.I label
31+
.RB [ \-\-pin
32+
.I PIN]
33+
.B [\-\-no\-public\-key]
2734
\\
2835
.ti +0.7i
29-
.RB [ \-\-pin
30-
.I PIN
31-
.B \-\-no\-public\-key]
3236
.B \-\-label
3337
.I text
3438
.B \-\-id
3539
.I hex
36-
.PP
37-
.B softhsm2-util \-\-import
38-
.I path
39-
.B \-\-aes
40-
.B \-\-token
41-
.I label
42-
\\
43-
.ti +0.7i
4440
.RB [ \-\-pin
4541
.I PIN]
4642
.B \-\-label
@@ -125,11 +121,11 @@ Any content in token will be erased.
125121
Show the help information.
126122
.TP
127123
.B \-\-import \fIpath\fR
128-
Import a key pair from the given
124+
Import an object from the given
129125
.IR path .
130-
The file must be in PKCS#8-format.
131126
.br
132127
Use with
128+
.BR \-\-import-type,
133129
.BR \-\-slot
134130
or
135131
.BR \-\-token
@@ -141,10 +137,6 @@ or
141137
.BR \-\-label ,
142138
and
143139
.BR \-\-id .
144-
.br
145-
Can also be used with
146-
.BR \-\-aes
147-
to use file as is and import it as AES.
148140
.TP
149141
.B \-\-init-token
150142
Initialize the token at a given slot, token label or token serial.
@@ -183,8 +175,20 @@ print the default PKCS#11 library.
183175
Show the version info.
184176
.SH OPTIONS
185177
.TP
178+
.B \-\-import-type \fItype\fR
179+
Import object type, \fItype\fR may be one of:
180+
.RS
181+
.IP keypair\ [default]
182+
The file must be in PKCS#8 PEM format.
183+
.IP aes
184+
The file must be in binary format.
185+
.IP cert
186+
The file must be in X509 PEM format.
187+
.RE
188+
.TP
186189
.B \-\-aes
187190
Used to tell import to use file as is and import it as AES.
191+
Deprecated, use \fI--import-type aes\fR instead.
188192
.TP
189193
.B \-\-file-pin \fIPIN\fR
190194
The

0 commit comments

Comments
 (0)