Skip to content

Commit a970212

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. Currently supported only for openssl backend. Signed-off-by: Alon Bar-Lev <[email protected]>
1 parent 3593859 commit a970212

File tree

4 files changed

+245
-12
lines changed

4 files changed

+245
-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

+146-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,22 @@ 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+
break;
396+
default:
397+
fprintf(stderr, "Invalid importType %d.\n", importType);
398+
rv = 1;
399+
break;
400+
}
357401
}
358402
}
359403

@@ -1099,7 +1143,7 @@ int importKeyPair
10991143
return 1;
11001144
}
11011145

1102-
CK_OBJECT_HANDLE oHandle = searchObject(hSession, objID, objIDLen);
1146+
CK_OBJECT_HANDLE oHandle = searchObject(hSession, CKO_PRIVATE_KEY, objID, objIDLen);
11031147
if (oHandle != CK_INVALID_HANDLE && forceExec == 0)
11041148
{
11051149
free(objID);
@@ -1187,6 +1231,98 @@ int importSecretKey(char* filePath, CK_SLOT_ID slotID, char* userPIN, char* labe
11871231
return result;
11881232
}
11891233

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

12751411
// Search for an object
1276-
CK_OBJECT_HANDLE searchObject(CK_SESSION_HANDLE hSession, char* objID, size_t objIDLen)
1412+
CK_OBJECT_HANDLE searchObject(CK_SESSION_HANDLE hSession, CK_OBJECT_CLASS oClass, char* objID, size_t objIDLen)
12771413
{
12781414
if (objID == NULL)
12791415
{
12801416
return CK_INVALID_HANDLE;
12811417
}
12821418

1283-
CK_OBJECT_CLASS oClass = CKO_PRIVATE_KEY;
12841419
CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
12851420
CK_ULONG objectCount = 0;
12861421

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)