Skip to content

Commit

Permalink
Merge pull request #612 from alonbl/import-cert
Browse files Browse the repository at this point in the history
Support import certificate using softhsm2-util
  • Loading branch information
jschlyter authored Dec 17, 2024
2 parents 4be49e3 + c057e57 commit 0053e2b
Show file tree
Hide file tree
Showing 5 changed files with 375 additions and 29 deletions.
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

0 comments on commit 0053e2b

Please sign in to comment.