Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support import certificate using softhsm2-util #612

Merged
merged 1 commit into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions src/bin/util/softhsm2-util-botan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@
#include <botan/bigint.h>
#include <botan/der_enc.h>
#include <botan/oids.h>
#include <botan/der_enc.h>
#include <botan/x509cert.h>
#include <botan/x509_dn.h>

// Init Botan
void crypto_init()
Expand Down Expand Up @@ -209,6 +212,64 @@ int crypto_import_key_pair
return result;
}

int crypto_import_certificate
(
CK_SESSION_HANDLE hSession,
char* filePath,
char* label,
char* objID,
size_t objIDLen
)
{
auto _vector_ptr = [](std::vector<uint8_t> &v) {
return v.size() == 0 ? NULL : &v.front();
};

Botan::X509_Certificate cert(filePath);
std::vector<uint8_t> blob;
std::vector<uint8_t> subject;
std::vector<uint8_t> issuer;
std::vector<uint8_t> serial;

Botan::DER_Encoder blob_encoder(blob);
Botan::DER_Encoder subject_encoder(subject);
Botan::DER_Encoder issuer_encoder(issuer);
Botan::DER_Encoder serial_encoder(serial);

cert.encode_into(blob_encoder);
cert.subject_dn().encode_into(subject_encoder);
cert.issuer_dn().encode_into(issuer_encoder);
serial_encoder.encode(Botan::BigInt::decode(cert.serial_number()));

CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
CK_CERTIFICATE_TYPE certType = CKC_X_509;
CK_BBOOL ckFalse = CK_FALSE, ckTrue = CK_TRUE;
CK_ATTRIBUTE certTemplate[] = {
{ CKA_CLASS, &certClass, sizeof(certClass) },
{ CKA_CERTIFICATE_TYPE, &certType, sizeof(certType) },
{ CKA_LABEL, label, strlen(label) },
{ CKA_ID, objID, objIDLen },
{ CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
{ CKA_PRIVATE, &ckFalse, sizeof(ckFalse) },
{ CKA_VALUE, _vector_ptr(blob), (CK_ULONG)blob.size() },
{ CKA_SUBJECT, _vector_ptr(subject), (CK_ULONG)subject.size() },
{ CKA_ISSUER, _vector_ptr(issuer), (CK_ULONG)issuer.size() },
{ CKA_SERIAL_NUMBER, _vector_ptr(serial), (CK_ULONG)serial.size() }
};

CK_OBJECT_HANDLE hCert;
CK_RV rv = p11->C_CreateObject(hSession, certTemplate, 10, &hCert);
if (rv != CKR_OK)
{
fprintf(stderr, "ERROR: Could not save the certificate in the token.\n");
return 1;
}

printf("The certificate has been imported.\n");

return 0;
}

// Read the key from file
Botan::Private_Key* crypto_read_file(char* filePath, char* filePIN)
{
Expand Down
145 changes: 145 additions & 0 deletions src/bin/util/softhsm2-util-ossl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,151 @@ int crypto_import_key_pair
return result;
}

int crypto_import_certificate
(
CK_SESSION_HANDLE hSession,
char* filePath,
char* label,
char* objID,
size_t objIDLen
)
{
BIO* in = NULL;
X509* x509 = NULL;
CK_BYTE_PTR blob = NULL;
CK_BYTE_PTR subject = NULL;
CK_BYTE_PTR issuer = NULL;
CK_BYTE_PTR serial = NULL;
CK_BYTE_PTR p;
int blobSize;
int subjectSize;
int issuerSize;
int serialSize;
int ret = 1;

if (!(in = BIO_new_file(filePath, "rb")))
{
fprintf(stderr, "ERROR: Could open the PKCS#8 file: %s\n", filePath);
goto cleanup;
}

if ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
{
fprintf(stderr, "ERROR: Could not read the certificate file: %s\n", filePath);
goto cleanup;
}

blobSize = i2d_X509(x509, NULL);
subjectSize = i2d_X509_NAME(X509_get_subject_name(x509), NULL);
issuerSize = i2d_X509_NAME(X509_get_issuer_name(x509), NULL);
serialSize = i2d_ASN1_INTEGER(X509_get_serialNumber(x509), NULL);

if
(
blobSize < 0 ||
subjectSize < 0 ||
issuerSize < 0 ||
serialSize < 0
)
{
fprintf(stderr, "ERROR: Could not convert certificate to DER.\n");
goto cleanup;
}

if (blobSize > 0)
{
if ((blob = (CK_BYTE_PTR)malloc(blobSize)) == NULL)
{
fprintf(stderr, "ERROR: Could not allocate memory.\n");
goto cleanup;
}
p = blob;
blobSize = i2d_X509(x509, &p);
}
if (subjectSize > 0) {
if ((subject = (CK_BYTE_PTR)malloc(subjectSize)) == NULL)
{
fprintf(stderr, "ERROR: Could not allocate memory.\n");
goto cleanup;
}
p = subject;
subjectSize = i2d_X509_NAME(X509_get_subject_name(x509), &p);
}
if (issuerSize > 0)
{
if ((issuer = (CK_BYTE_PTR)malloc(issuerSize)) == NULL)
{
fprintf(stderr, "ERROR: Could not allocate memory.\n");
goto cleanup;
}
p = issuer;
issuerSize = i2d_X509_NAME(X509_get_issuer_name(x509), &p);
}
if (serialSize > 0)
{
if ((serial = (CK_BYTE_PTR)malloc(serialSize)) == NULL)
{
fprintf(stderr, "ERROR: Could not allocate memory.\n");
goto cleanup;
}
p = serial;
serialSize = i2d_ASN1_INTEGER(X509_get_serialNumber(x509), &p);
}

if
(
blobSize < 0 ||
subjectSize < 0 ||
issuerSize < 0 ||
serialSize < 0
)
{
fprintf(stderr, "ERROR: Could not convert certificate to DER.\n");
goto cleanup;
}

{
CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
CK_CERTIFICATE_TYPE certType = CKC_X_509;
CK_BBOOL ckFalse = CK_FALSE, ckTrue = CK_TRUE;
CK_ATTRIBUTE certTemplate[] = {
{ CKA_CLASS, &certClass, sizeof(certClass) },
{ CKA_CERTIFICATE_TYPE, &certType, sizeof(certType) },
{ CKA_LABEL, label, strlen(label) },
{ CKA_ID, objID, objIDLen },
{ CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
{ CKA_PRIVATE, &ckFalse, sizeof(ckFalse) },
{ CKA_VALUE, blob, (CK_ULONG)blobSize },
{ CKA_SUBJECT, subject, (CK_ULONG)subjectSize },
{ CKA_ISSUER, issuer, (CK_ULONG)issuerSize },
{ CKA_SERIAL_NUMBER, serial, (CK_ULONG)serialSize }
};

CK_OBJECT_HANDLE hCert;
CK_RV rv = p11->C_CreateObject(hSession, certTemplate, 10, &hCert);
if (rv != CKR_OK)
{
fprintf(stderr, "ERROR: Could not save the certificate in the token.\n");
goto cleanup;
}
}

printf("The certificate has been imported.\n");

ret = 0;

cleanup:

free(blob);
free(subject);
free(issuer);
free(serial);
X509_free(x509);
BIO_free(in);

return ret;
}

// Read the key from file
EVP_PKEY* crypto_read_file(char* filePath, char* filePIN)
{
Expand Down
38 changes: 21 additions & 17 deletions src/bin/util/softhsm2-util.1
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,23 @@ softhsm2-util \- support tool for libsofthsm2
.PP
.B softhsm2-util \-\-import
.I path
.RB [ \-\-import-type
.IR type ]
\\
.ti +0.7i
.RB [ \-\-file-pin
.IR PIN ]
.B \-\-token
.I label
.RB [ \-\-pin
.I PIN]
.B [\-\-no\-public\-key]
\\
.ti +0.7i
.RB [ \-\-pin
.I PIN
.B \-\-no\-public\-key]
.B \-\-label
.I text
.B \-\-id
.I hex
.PP
.B softhsm2-util \-\-import
.I path
.B \-\-aes
.B \-\-token
.I label
\\
.ti +0.7i
.RB [ \-\-pin
.I PIN]
.B \-\-label
Expand Down Expand Up @@ -125,11 +121,11 @@ Any content in token will be erased.
Show the help information.
.TP
.B \-\-import \fIpath\fR
Import a key pair from the given
Import an object from the given
.IR path .
The file must be in PKCS#8-format.
.br
Use with
.BR \-\-import-type,
.BR \-\-slot
or
.BR \-\-token
Expand All @@ -141,10 +137,6 @@ or
.BR \-\-label ,
and
.BR \-\-id .
.br
Can also be used with
.BR \-\-aes
to use file as is and import it as AES.
.TP
.B \-\-init-token
Initialize the token at a given slot, token label or token serial.
Expand Down Expand Up @@ -183,8 +175,20 @@ print the default PKCS#11 library.
Show the version info.
.SH OPTIONS
.TP
.B \-\-import-type \fItype\fR
Import object type, \fItype\fR may be one of:
.RS
.IP keypair\ [default]
The file must be in PKCS#8 PEM format.
.IP aes
The file must be in binary format.
.IP cert
The file must be in X509 PEM format.
.RE
.TP
.B \-\-aes
Used to tell import to use file as is and import it as AES.
Deprecated, use \fI--import-type aes\fR instead.
.TP
.B \-\-file-pin \fIPIN\fR
The
Expand Down
Loading