diff --git a/src/bin/util/softhsm2-util-botan.cpp b/src/bin/util/softhsm2-util-botan.cpp index 9e92eb34..b0cc5a1d 100644 --- a/src/bin/util/softhsm2-util-botan.cpp +++ b/src/bin/util/softhsm2-util-botan.cpp @@ -47,6 +47,9 @@ #include #include #include +#include +#include +#include // Init Botan void crypto_init() @@ -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 &v) { + return v.size() == 0 ? NULL : &v.front(); + }; + + Botan::X509_Certificate cert(filePath); + std::vector blob; + std::vector subject; + std::vector issuer; + std::vector 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) { diff --git a/src/bin/util/softhsm2-util-ossl.cpp b/src/bin/util/softhsm2-util-ossl.cpp index b839d3f0..2ead1586 100644 --- a/src/bin/util/softhsm2-util-ossl.cpp +++ b/src/bin/util/softhsm2-util-ossl.cpp @@ -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) { diff --git a/src/bin/util/softhsm2-util.1 b/src/bin/util/softhsm2-util.1 index cd1c2e9e..f33e464d 100644 --- a/src/bin/util/softhsm2-util.1 +++ b/src/bin/util/softhsm2-util.1 @@ -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 @@ -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 @@ -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. @@ -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 diff --git a/src/bin/util/softhsm2-util.cpp b/src/bin/util/softhsm2-util.cpp index 6ab8e2b8..7d3ab975 100644 --- a/src/bin/util/softhsm2-util.cpp +++ b/src/bin/util/softhsm2-util.cpp @@ -101,10 +101,17 @@ void usage() printf(" WARNING: Any content in token will be erased.\n"); printf(" -h Shows this help screen.\n"); printf(" --help Shows this help screen.\n"); - printf(" --import Import a key pair from the given path.\n"); - printf(" The file must be in PKCS#8-format.\n"); - printf(" Use with --slot or --token or --serial, --file-pin,\n"); - printf(" --label, --id, --no-public-key, and --pin.\n"); + printf(" --import Import an object from the given path.\n"); + printf(" Use with --import-type, --slot or --token or --serial,\n"); + printf(" --file-pin, --label, --id, --no-public-key, and --pin.\n"); + printf(" --import-type \n"); + printf(" Import object type, type may be one of:\n"); + printf(" keypair [default]\n"); + printf(" The file must be in PKCS#8 PEM format.\n"); + printf(" aes\n"); + printf(" The file must be in binary format.\n"); + printf(" cert\n"); + printf(" The file must be in X509 PEM format.\n"); printf(" --init-token Initialize the token at a given slot.\n"); printf(" Use with --slot or --token or --serial or --free,\n"); printf(" --label, --so-pin, and --pin.\n"); @@ -118,6 +125,7 @@ void usage() printf(" --version Show version info.\n"); printf("Options:\n"); printf(" --aes Used to tell import to use file as is and import it as AES.\n"); + printf(" Deprecated, use '--import-type aes'.\n"); printf(" --file-pin Supply a PIN if the file is encrypted.\n"); printf(" --force Used to override a warning.\n"); printf(" --free Use the first free/uninitialized token.\n"); @@ -134,6 +142,13 @@ void usage() printf(" --token