@@ -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
134150enum {
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
11911327char * 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
0 commit comments