Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 547eaad

Browse files
committedFeb 22, 2021
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. Currently supported only for openssl backend. Signed-off-by: Alon Bar-Lev <alon.barlev@gmail.com>
1 parent 3593859 commit 547eaad

File tree

4 files changed

+240
-12
lines changed

4 files changed

+240
-12
lines changed
 

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

+15
Original file line numberDiff line numberDiff line change
@@ -833,4 +833,19 @@ void crypto_free_eddsa(eddsa_key_material_t* keyMat)
833833
if (keyMat->bigA) free(keyMat->bigA);
834834
free(keyMat);
835835
}
836+
837+
// Import a key pair from given path
838+
int crypto_import_certificate
839+
(
840+
CK_SESSION_HANDLE hSession,
841+
char* filePath,
842+
char* label,
843+
char* objID,
844+
size_t objIDLen
845+
)
846+
{
847+
fprintf(stderr, "ERROR: Unsupported in botan.\n");
848+
return 1;
849+
}
850+
836851
#endif

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

+81
Original file line numberDiff line numberDiff line change
@@ -990,4 +990,85 @@ void crypto_free_eddsa(eddsa_key_material_t* keyMat)
990990
free(keyMat);
991991
}
992992

993+
// Import a key pair from given path
994+
int crypto_import_certificate
995+
(
996+
CK_SESSION_HANDLE hSession,
997+
char* filePath,
998+
char* label,
999+
char* objID,
1000+
size_t objIDLen
1001+
)
1002+
{
1003+
BIO* in = NULL;
1004+
1005+
if (!(in = BIO_new_file(filePath, "rb")))
1006+
{
1007+
fprintf(stderr, "ERROR: Could open the PKCS#8 file: %s\n", filePath);
1008+
return 1;
1009+
}
1010+
1011+
X509* x509 = PEM_read_bio_X509(in, NULL, NULL, NULL);
1012+
BIO_free(in);
1013+
1014+
if (!x509)
1015+
{
1016+
fprintf(stderr, "ERROR: Could not read the certificate file.\n");
1017+
return 1;
1018+
}
1019+
1020+
int blobSize = i2d_X509(x509, NULL);
1021+
CK_BYTE_PTR blob = (CK_BYTE_PTR)malloc(blobSize);
1022+
CK_BYTE_PTR p;
1023+
p = blob;
1024+
blobSize = i2d_X509(x509, &p);
1025+
1026+
int nameSize = i2d_X509_NAME(X509_get_subject_name(x509), NULL);
1027+
CK_BYTE_PTR name = (CK_BYTE_PTR)malloc(nameSize);
1028+
p = name;
1029+
nameSize = i2d_X509_NAME(X509_get_subject_name(x509), &p);
1030+
1031+
int issuerSize = i2d_X509_NAME(X509_get_issuer_name(x509), NULL);
1032+
CK_BYTE_PTR issuer = (CK_BYTE_PTR)malloc(issuerSize);
1033+
p = issuer;
1034+
issuerSize = i2d_X509_NAME(X509_get_issuer_name(x509), &p);
1035+
1036+
int serialSize = i2d_ASN1_INTEGER(X509_get_serialNumber(x509), NULL);
1037+
CK_BYTE_PTR serial = (CK_BYTE_PTR)malloc(serialSize);
1038+
p = serial;
1039+
serialSize = i2d_ASN1_INTEGER(X509_get_serialNumber(x509), &p);
1040+
1041+
CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
1042+
CK_CERTIFICATE_TYPE certType = CKC_X_509;
1043+
CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
1044+
CK_ATTRIBUTE certTemplate[] = {
1045+
{ CKA_CLASS, &certClass, sizeof(certClass) },
1046+
{ CKA_CERTIFICATE_TYPE, &certType, sizeof(certType) },
1047+
{ CKA_LABEL, label, strlen(label) },
1048+
{ CKA_ID, objID, objIDLen },
1049+
{ CKA_TOKEN, &ckToken, sizeof(ckToken) },
1050+
{ CKA_PRIVATE, &ckFalse, sizeof(ckTrue) },
1051+
{ CKA_VALUE, blob, (CK_ULONG)blobSize },
1052+
{ CKA_SUBJECT, name, (CK_ULONG)nameSize },
1053+
{ CKA_ISSUER, issuer, (CK_ULONG)issuerSize },
1054+
{ CKA_SERIAL_NUMBER, serial, (CK_ULONG)serialSize }
1055+
};
1056+
1057+
CK_OBJECT_HANDLE hCert;
1058+
CK_RV rv = p11->C_CreateObject(hSession, certTemplate, 10, &hCert);
1059+
free(issuer);
1060+
free(name);
1061+
free(blob);
1062+
X509_free(x509);
1063+
if (rv != CKR_OK)
1064+
{
1065+
fprintf(stderr, "ERROR: Could not save the certificate in the token.\n");
1066+
return 1;
1067+
}
1068+
1069+
printf("The certificate has been imported.\n");
1070+
1071+
return 0;
1072+
}
1073+
9931074
#endif

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

+141-11
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,18 @@ void usage()
101101
printf(" WARNING: Any content in token will be erased.\n");
102102
printf(" -h Shows this help screen.\n");
103103
printf(" --help Shows this help screen.\n");
104-
printf(" --import <path> Import a key pair from the given path.\n");
105-
printf(" The file must be in PKCS#8-format.\n");
106-
printf(" Use with --slot or --token or --serial, --file-pin,\n");
107-
printf(" --label, --id, --no-public-key, and --pin.\n");
104+
printf(" --import <path>\n");
105+
printf(" Import an object from the given path.\n");
106+
printf(" Use with --import-type, --slot or --token or --serial,\n");
107+
printf(" --file-pin, --label, --id, --no-public-key, and --pin.\n");
108+
printf(" --import-type <type>\n");
109+
printf(" Import object type, may be one of:\n");
110+
printf(" keypair [default]\n");
111+
printf(" The file must be in PKCS#8 PEM format.\n");
112+
printf(" aes\n");
113+
printf(" The file must be in binary format.\n");
114+
printf(" cert\n");
115+
printf(" The file must be in X509 PEM format.\n");
108116
printf(" --init-token Initialize the token at a given slot.\n");
109117
printf(" Use with --slot or --token or --serial or --free,\n");
110118
printf(" --label, --so-pin, and --pin.\n");
@@ -114,6 +122,7 @@ void usage()
114122
printf(" --version Show version info.\n");
115123
printf("Options:\n");
116124
printf(" --aes Used to tell import to use file as is and import it as AES.\n");
125+
printf(" Deprecated, use '--import-type aes'.\n");
117126
printf(" --file-pin <PIN> Supply a PIN if the file is encrypted.\n");
118127
printf(" --force Used to override a warning.\n");
119128
printf(" --free Use the first free/uninitialized token.\n");
@@ -130,6 +139,13 @@ void usage()
130139
printf(" --token <label> Will use the token with a matching token label.\n");
131140
}
132141

142+
// Enumeration of import types
143+
enum {
144+
IMPORT_TYPE_KEYPAIR,
145+
IMPORT_TYPE_AES,
146+
IMPORT_TYPE_CERT
147+
};
148+
133149
// Enumeration of the long options
134150
enum {
135151
OPT_DELETE_TOKEN = 0x100,
@@ -139,6 +155,7 @@ enum {
139155
OPT_HELP,
140156
OPT_ID,
141157
OPT_IMPORT,
158+
OPT_IMPORT_TYPE,
142159
OPT_INIT_TOKEN,
143160
OPT_LABEL,
144161
OPT_MODULE,
@@ -162,6 +179,7 @@ static const struct option long_options[] = {
162179
{ "help", 0, NULL, OPT_HELP },
163180
{ "id", 1, NULL, OPT_ID },
164181
{ "import", 1, NULL, OPT_IMPORT },
182+
{ "import-type", 1, NULL, OPT_IMPORT_TYPE },
165183
{ "init-token", 0, NULL, OPT_INIT_TOKEN },
166184
{ "label", 1, NULL, OPT_LABEL },
167185
{ "module", 1, NULL, OPT_MODULE },
@@ -199,7 +217,7 @@ int main(int argc, char* argv[])
199217
int forceExec = 0;
200218
bool freeToken = false;
201219
int noPublicKey = 0;
202-
bool importAES = false;
220+
int importType = IMPORT_TYPE_KEYPAIR;
203221

204222
int doInitToken = 0;
205223
int doShowSlots = 0;
@@ -233,8 +251,20 @@ int main(int argc, char* argv[])
233251
inPath = optarg;
234252
needP11 = true;
235253
break;
254+
case OPT_IMPORT_TYPE:
255+
if (!strcmp(optarg, "keypair"))
256+
importType = IMPORT_TYPE_KEYPAIR;
257+
else if (!strcmp(optarg, "aes"))
258+
importType = IMPORT_TYPE_AES;
259+
else if (!strcmp(optarg, "cert"))
260+
importType = IMPORT_TYPE_CERT;
261+
else
262+
{
263+
fprintf(stderr, "ERROR: Invalid import type '%s'\n", optarg);
264+
}
265+
break;
236266
case OPT_AES:
237-
importAES = true;
267+
importType = IMPORT_TYPE_AES;
238268
break;
239269
case OPT_DELETE_TOKEN:
240270
doDeleteToken = 1;
@@ -352,8 +382,17 @@ int main(int argc, char* argv[])
352382
rv = findSlot(slot, serial, token, slotID);
353383
if (!rv)
354384
{
355-
rv = importAES ? importSecretKey(inPath, slotID, userPIN, label, objectID)
356-
: importKeyPair(inPath, filePIN, slotID, userPIN, label, objectID, forceExec, noPublicKey);
385+
switch(importType)
386+
{
387+
case IMPORT_TYPE_KEYPAIR:
388+
rv = importKeyPair(inPath, filePIN, slotID, userPIN, label, objectID, forceExec, noPublicKey);
389+
break;
390+
case IMPORT_TYPE_AES:
391+
rv = importSecretKey(inPath, slotID, userPIN, label, objectID);
392+
break;
393+
case IMPORT_TYPE_CERT:
394+
rv = importCertificate(inPath, slotID, userPIN, label, objectID, forceExec);
395+
}
357396
}
358397
}
359398

@@ -1099,7 +1138,7 @@ int importKeyPair
10991138
return 1;
11001139
}
11011140

1102-
CK_OBJECT_HANDLE oHandle = searchObject(hSession, objID, objIDLen);
1141+
CK_OBJECT_HANDLE oHandle = searchObject(hSession, CKO_PRIVATE_KEY, objID, objIDLen);
11031142
if (oHandle != CK_INVALID_HANDLE && forceExec == 0)
11041143
{
11051144
free(objID);
@@ -1187,6 +1226,98 @@ int importSecretKey(char* filePath, CK_SLOT_ID slotID, char* userPIN, char* labe
11871226
return result;
11881227
}
11891228

1229+
// Import a certificate from given path
1230+
int importCertificate
1231+
(
1232+
char* filePath,
1233+
CK_SLOT_ID slotID,
1234+
char* userPIN,
1235+
char* label,
1236+
char* objectID,
1237+
int forceExec
1238+
)
1239+
{
1240+
char user_pin_copy[MAX_PIN_LEN+1];
1241+
1242+
if (label == NULL)
1243+
{
1244+
fprintf(stderr, "ERROR: A label for the object must be supplied. "
1245+
"Use --label <text>\n");
1246+
return 1;
1247+
}
1248+
1249+
if (objectID == NULL)
1250+
{
1251+
fprintf(stderr, "ERROR: An ID for the object must be supplied. "
1252+
"Use --id <hex>\n");
1253+
return 1;
1254+
}
1255+
1256+
size_t objIDLen = 0;
1257+
char* objID = hexStrToBin(objectID, strlen(objectID), &objIDLen);
1258+
if (objID == NULL)
1259+
{
1260+
fprintf(stderr, "Please edit --id <hex> to correct error.\n");
1261+
return 1;
1262+
}
1263+
1264+
CK_SESSION_HANDLE hSession;
1265+
CK_RV rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION,
1266+
NULL_PTR, NULL_PTR, &hSession);
1267+
if (rv != CKR_OK)
1268+
{
1269+
if (rv == CKR_SLOT_ID_INVALID)
1270+
{
1271+
fprintf(stderr, "ERROR: The given slot does not exist.\n");
1272+
}
1273+
else
1274+
{
1275+
fprintf(stderr, "ERROR: Could not open a session on the given slot.\n");
1276+
}
1277+
free(objID);
1278+
return 1;
1279+
}
1280+
1281+
// Get the password
1282+
if (getPW(userPIN, user_pin_copy, CKU_USER) != 0)
1283+
{
1284+
fprintf(stderr, "ERROR: Could not get user PIN\n");
1285+
free(objID);
1286+
return 1;
1287+
}
1288+
1289+
rv = p11->C_Login(hSession, CKU_USER, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy));
1290+
if (rv != CKR_OK)
1291+
{
1292+
if (rv == CKR_PIN_INCORRECT) {
1293+
fprintf(stderr, "ERROR: The given user PIN does not match the one in the token.\n");
1294+
}
1295+
else
1296+
{
1297+
fprintf(stderr, "ERROR: Could not log in on the token.\n");
1298+
}
1299+
free(objID);
1300+
return 1;
1301+
}
1302+
1303+
CK_OBJECT_HANDLE oHandle = searchObject(hSession, CKO_CERTIFICATE, objID, objIDLen);
1304+
if (oHandle != CK_INVALID_HANDLE && forceExec == 0)
1305+
{
1306+
free(objID);
1307+
fprintf(stderr, "ERROR: The ID is already assigned to another object. "
1308+
"Use --force to override this message.\n");
1309+
return 1;
1310+
}
1311+
1312+
crypto_init();
1313+
int result = crypto_import_certificate(hSession, filePath, label, objID, objIDLen);
1314+
crypto_final();
1315+
1316+
free(objID);
1317+
1318+
return result;
1319+
}
1320+
11901321
// Convert a char array of hexadecimal characters into a binary representation
11911322
char* hexStrToBin(char* objectID, int idLength, size_t* newLen)
11921323
{
@@ -1273,14 +1404,13 @@ int hexdigit_to_int(char ch)
12731404
}
12741405

12751406
// Search for an object
1276-
CK_OBJECT_HANDLE searchObject(CK_SESSION_HANDLE hSession, char* objID, size_t objIDLen)
1407+
CK_OBJECT_HANDLE searchObject(CK_SESSION_HANDLE hSession, CK_OBJECT_CLASS oClass, char* objID, size_t objIDLen)
12771408
{
12781409
if (objID == NULL)
12791410
{
12801411
return CK_INVALID_HANDLE;
12811412
}
12821413

1283-
CK_OBJECT_CLASS oClass = CKO_PRIVATE_KEY;
12841414
CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
12851415
CK_ULONG objectCount = 0;
12861416

‎src/bin/util/softhsm2-util.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,10 @@ bool rm(std::string path);
4949
int showSlots();
5050
int importKeyPair(char* filePath, char* filePIN, CK_SLOT_ID slotID, char* userPIN, char* objectLabel, char* objectID, int forceExec, int noPublicKey);
5151
int importSecretKey(char* filePath, CK_SLOT_ID slotID, char* userPIN, char* label, char* objectID);
52+
int importCertificate(char* filePath, CK_SLOT_ID slotID, char* userPIN, char* objectLabel, char* objectID, int forceExec);
5253
int crypto_import_key_pair(CK_SESSION_HANDLE hSession, char* filePath, char* filePIN, char* label, char* objID, size_t objIDLen, int noPublicKey);
5354
int crypto_import_aes_key(CK_SESSION_HANDLE hSession, char* filePath, char* label, char* objID, size_t objIDLen);
55+
int crypto_import_certificate(CK_SESSION_HANDLE hSession, char* filePath, char* label, char* objID, size_t objIDLen);
5456

5557
// Support functions
5658

@@ -72,6 +74,6 @@ static void* moduleHandle;
7274
extern CK_FUNCTION_LIST_PTR p11;
7375

7476
/// PKCS#11 support
75-
CK_OBJECT_HANDLE searchObject(CK_SESSION_HANDLE hSession, char* objID, size_t objIDLen);
77+
CK_OBJECT_HANDLE searchObject(CK_SESSION_HANDLE hSession, CK_OBJECT_CLASS oClass, char* objID, size_t objIDLen);
7678

7779
#endif // !_SOFTHSM_V2_SOFTHSM2_UTIL_H

0 commit comments

Comments
 (0)
Please sign in to comment.