1 /*
2  * The Initial Developer of the Original Code is International
3  * Business Machines Corporation. Portions created by IBM
4  * Corporation are Copyright (C) 2005 International Business
5  * Machines Corporation. All Rights Reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the Common Public License as published by
9  * IBM Corporation; either version 1 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * Common Public License for more details.
16  *
17  * You should have received a copy of the Common Public License
18  * along with this program; if not, a copy can be viewed at
19  * http://www.opensource.org/licenses/cpl1.0.php.
20  */
21 
22 #include "data_import.h"
23 #include "data_common.h"
24 
25 #include <tpm_pkcs11.h>
26 #include <tpm_utils.h>
27 
28 #include <stdlib.h>
29 #include <unistd.h>
30 #define _GNU_SOURCE
31 #include <getopt.h>
32 #include <errno.h>
33 
34 #include <openssl/rsa.h>
35 #include <openssl/x509.h>
36 #include <openssl/x509v3.h>
37 #include <openssl/pem.h>
38 #include <openssl/asn1.h>
39 #include <openssl/evp.h>
40 #include <openssl/err.h>
41 
42 
43 /*
44  * Global variables
45  */
46 char *g_pszFile   = NULL;		// Object import file name
47 char *g_pszIdFile = NULL;		// Object identification file name
48 char *g_pszType   = NULL;		// Object import type
49 int   g_bPublic   = FALSE;		// Public object specifier
50 int   g_bYes      = FALSE;		// Yes/No prompt reply
51 char *g_pszToken  = NULL;		// Token label to be used
52 
53 int       g_bAttrsValid  = FALSE;
54 CK_BYTE  *g_pchSubject   = NULL;	// SUBJECT attribute value
55 CK_LONG   g_subjectLen = 0;
56 CK_BYTE  *g_pchId        = NULL;	// ID attribute value
57 CK_ULONG  g_ulIdLen      = 0;
58 CK_BYTE  *g_pchName      = NULL;	// LABEL attribute value
59 CK_ULONG  g_ulNameLen    = 0;
60 
61 /*
62  * parseCallback
63  *   Process the command specific options.
64  */
65 int
parseCallback(int a_iOpt,const char * a_pszOptArg)66 parseCallback( int         a_iOpt,
67                const char *a_pszOptArg ) {
68 
69 	switch ( a_iOpt ) {
70 		// File with object to be used to obtain subject/id
71 		case 'i':
72 			if ( !a_pszOptArg )
73 				return -1;
74 
75 			g_pszIdFile = strdup( a_pszOptArg );
76 			break;
77 
78 		// Use the specified token label when finding the token
79 		case 'k':
80 			if ( !a_pszOptArg )
81 				return -1;
82 
83 			g_pszToken = strdup( a_pszOptArg );
84 			break;
85 
86 		// Name to use as the LABEL attribute value
87 		case 'n':
88 			if ( !a_pszOptArg )
89 				return -1;
90 
91 			g_pchName = (CK_BYTE *)strdup( a_pszOptArg );
92 			g_ulNameLen = strlen( a_pszOptArg );
93 			break;
94 
95 		// Make the object public
96 		case 'p':
97 			g_bPublic = TRUE;
98 			break;
99 
100 		// Only import the specified object type
101 		case 't':
102 			if ( !a_pszOptArg )
103 				return -1;
104 
105 			if ( ( strcmp( a_pszOptArg, TOKEN_OBJECT_KEY )  != 0 ) &&
106 			     ( strcmp( a_pszOptArg, TOKEN_OBJECT_CERT ) != 0 ) )
107 				return -1;
108 
109 			g_pszType = strdup( a_pszOptArg );
110 			break;
111 
112 		// Reply "yes" to any yes/no prompts
113 		case 'y':
114 			g_bYes = TRUE;
115 			break;
116 	}
117 
118 	return 0;
119 }
120 
121 /*
122  * usageCallback
123  *   Display command usage information.
124  */
125 void
usageCallback(const char * a_pszCmd)126 usageCallback( const char *a_pszCmd ) {
127 
128 	char *pszArgs[2];
129 	char *pszArgsDesc[2];
130 
131 	pszArgs[ 0 ] = "FILE";
132 	pszArgsDesc[ 0 ] = _("Import the PEM formatted RSA key and/or X.509 certificate object contained in FILE");
133 	pszArgs[ 1 ] = NULL;
134 	pszArgsDesc[ 1 ] = NULL;
135 
136 	logCmdHelpEx( a_pszCmd, pszArgs, pszArgsDesc );
137 	logCmdOption( "-i, --idfile FILE",
138 			_("Use FILE as the PEM formatted X.509 certificate input used to obtain the subject and id attributes") );
139 	logCmdOption( "-k, --token STRING",
140 			_("Use STRING to identify the label of the PKCS#11 token to be used") );
141 	logCmdOption( "-n, --name STRING",
142 			_("Use STRING as the label for the imported object(s)") );
143 	logCmdOption( "-p, --public",
144 			_("Import the object(s) as a public object") );
145 	logCmdOption( "-t, --type key|cert",
146 			_("Import only the specified object type") );
147 	logCmdOption( "-y, --yes",
148 			_("Assume yes as the answer to any confirmation prompt") );
149 }
150 
151 /*
152  * parseCmd
153  *   Parse the command line options.
154  */
155 int
parseCmd(int a_iArgc,char ** a_pszArgv)156 parseCmd( int    a_iArgc,
157           char **a_pszArgv ) {
158 
159 	int  rc;
160 
161 	char          *pszShortOpts  = "i:k:n:pt:y";
162 	struct option  stLongOpts[]  = {
163 			{ "idfile", required_argument, NULL, 'i' },
164 			{ "name", required_argument, NULL, 'n' },
165 			{ "public", no_argument, NULL, 'p' },
166 			{ "token", required_argument, NULL, 'k' },
167 			{ "type", required_argument, NULL, 't' },
168 			{ "yes", no_argument, NULL, 'y' },
169 		};
170 	int  iNumLongOpts = sizeof( stLongOpts ) / sizeof( struct option );
171 
172 	rc = genericOptHandler( a_iArgc, a_pszArgv,
173 		pszShortOpts, stLongOpts, iNumLongOpts,
174 		parseCallback, usageCallback );
175 	if ( rc == -1 )
176 		return -1;
177 
178 	if ( optind >= a_iArgc ) {
179 		logMsg( TOKEN_FILE_ERROR );
180 		usageCallback( a_pszArgv[ 0 ] );
181 		return -1;
182 	}
183 
184 	g_pszFile = strdup( a_pszArgv[ optind ] );
185 
186 	return 0;
187 }
188 
189 /*
190  * findExistingObjects
191  *   Search for objects of the supplied type that have a SUBJECT
192  *   and ID attribute equal to the values of the object to be
193  *   imported.
194  */
195 int
findExistingObjects(CK_SESSION_HANDLE a_hSession,CK_ATTRIBUTE * a_tAttr,CK_ULONG a_ulAttrCount,CK_OBJECT_HANDLE ** a_phObject,CK_ULONG * a_pulObjectCount)196 findExistingObjects( CK_SESSION_HANDLE   a_hSession,
197                      CK_ATTRIBUTE       *a_tAttr,
198                      CK_ULONG            a_ulAttrCount,
199                      CK_OBJECT_HANDLE  **a_phObject,
200                      CK_ULONG           *a_pulObjectCount ) {
201 
202 	CK_RV     rv;
203 	CK_BBOOL  bTrue = TRUE;
204 
205 	// Set up default search attributes
206 	CK_ATTRIBUTE  tDefaultAttr[]     = {
207 			{ CKA_TOKEN, &bTrue, sizeof( bTrue ) },
208 			{ CKA_SUBJECT, g_pchSubject, g_subjectLen },
209 			{ CKA_ID, g_pchId, g_ulIdLen },
210 		};
211 	CK_ULONG      ulDefaultAttrCount = sizeof( tDefaultAttr ) / sizeof( CK_ATTRIBUTE );
212 
213 	CK_ATTRIBUTE  tAttr[ ulDefaultAttrCount + a_ulAttrCount ];
214 	CK_ULONG      ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );
215 
216 	*a_phObject = NULL;
217 	*a_pulObjectCount = 0;
218 
219 	// Apply attributes and search
220 	memcpy( tAttr, tDefaultAttr, ulDefaultAttrCount * sizeof( CK_ATTRIBUTE ) );
221 	if ( a_ulAttrCount )
222 		memcpy( tAttr + ulDefaultAttrCount, a_tAttr, a_ulAttrCount * sizeof( CK_ATTRIBUTE ) );
223 
224 	rv = findObjects( a_hSession, tAttr, ulAttrCount, a_phObject, a_pulObjectCount );
225 
226 	return ( rv == CKR_OK ) ? 0 : -1;
227 }
228 
229 /*
230  * checkExistingObjects
231  *   Use findExistingObjects to determine if objects of the
232  *   supplied type currently exist.  If so, prompt the user as
233  *   to whether to replace the existing objects.
234  */
235 int
checkExistingObjects(CK_SESSION_HANDLE a_hSession,CK_ATTRIBUTE * a_tAttr,CK_ULONG a_ulAttrCount,const char * a_pszObject)236 checkExistingObjects( CK_SESSION_HANDLE  a_hSession,
237                       CK_ATTRIBUTE      *a_tAttr,
238                       CK_ULONG           a_ulAttrCount,
239                       const char        *a_pszObject ) {
240 
241 	int  rc = -1;
242 
243 	CK_OBJECT_HANDLE *phObject      = NULL;
244 	CK_ULONG          ulObjectCount = 0;
245 
246 	char  szPrompt[ strlen( TOKEN_ID_PROMPT ) + strlen( a_pszObject ) + 1 ];
247 	char *pszReply = NULL;
248 
249 	if ( g_bAttrsValid ) {
250 		// Search for existing objects
251 		if ( findExistingObjects( a_hSession, a_tAttr, a_ulAttrCount, &phObject, &ulObjectCount ) == -1 )
252 			goto out;
253 
254 		if ( ulObjectCount > 0 ) {
255 			// One or more objects exists
256 			if ( !g_bYes ) {
257 				// Prompt for whether to replace the existing objects
258 				sprintf( szPrompt, TOKEN_ID_PROMPT, a_pszObject );
259 				pszReply = getReply( szPrompt, 1 );
260 				if ( !pszReply ||
261 					( strlen( pszReply ) == 0 ) ||
262 					( strcasecmp( pszReply, TOKEN_ID_NO ) == 0 ) ) {
263 					goto out;
264 				}
265 			}
266 		}
267 	}
268 
269 	rc = 0;
270 
271 out:
272 	free( phObject );
273 	free( pszReply );
274 
275 	return rc;
276 }
277 
278 /*
279  * destroyExistingObjects
280  *   Use findExistingObjects to locate all objects of the
281  *   supplied type that currently exists and destroy them.
282  */
283 int
destroyExistingObjects(CK_SESSION_HANDLE a_hSession,CK_ATTRIBUTE * a_tAttr,CK_ULONG a_ulAttrCount)284 destroyExistingObjects( CK_SESSION_HANDLE  a_hSession,
285                         CK_ATTRIBUTE      *a_tAttr,
286                         CK_ULONG           a_ulAttrCount ) {
287 
288 	int  rc = -1;
289 
290 	CK_RV             rv;
291 	CK_OBJECT_HANDLE *phObject      = NULL;
292 	CK_ULONG          ulObjectCount = 0;
293 
294 	if ( g_bAttrsValid ) {
295 		// Search for existing objects
296 		if ( findExistingObjects( a_hSession, a_tAttr, a_ulAttrCount, &phObject, &ulObjectCount ) == -1 )
297 			goto out;
298 
299 		// Destroy each object found
300 		while ( ulObjectCount > 0 ) {
301 			rv = destroyObject( a_hSession, phObject[ --ulObjectCount ] );
302 			if ( rv != CKR_OK )
303 				goto out;
304 		}
305 	}
306 
307 	rc = 0;
308 
309 out:
310 	free( phObject );
311 
312 	return rc;
313 }
314 
315 /*
316  * readX509Cert
317  *   Use the OpenSSL library to read a PEM formatted X509 certificate.
318  */
319 int
readX509Cert(const char * a_pszFile,int a_bCheckKey,X509 ** a_pX509)320 readX509Cert( const char  *a_pszFile,
321               int          a_bCheckKey,
322               X509       **a_pX509 ) {
323 
324 	int rc = -1;
325 
326 	FILE     *pFile = stdin;
327 	X509     *pX509 = NULL;
328 	EVP_PKEY *pKey  = NULL;
329 
330 	*a_pX509 = NULL;
331 
332 	// Open the file to be read
333 	if ( a_pszFile ) {
334 		errno = 0;
335 		pFile = fopen( a_pszFile, "r" );
336 		if ( !pFile ) {
337 			logError( TOKEN_FILE_OPEN_ERROR, a_pszFile, strerror( errno ) );
338 			goto out;
339 		}
340 	}
341 
342 	// Read the X509 certificate
343 	pX509 = PEM_read_X509( pFile, NULL, NULL, NULL );
344 	if ( !pX509 ) {
345 		unsigned long  ulError = ERR_get_error( );
346 
347 		// Not necessarily an error if the file doesn't contain the cert
348 		if ( ( ERR_GET_LIB( ulError ) == ERR_R_PEM_LIB ) &&
349 		     ( ERR_GET_REASON( ulError ) == PEM_R_NO_START_LINE ) ) {
350 			logInfo( TOKEN_OPENSSL_ERROR, ERR_error_string( ulError, NULL ) );
351 			rc = 0;
352 		}
353 		else
354 			logError( TOKEN_OPENSSL_ERROR, ERR_error_string( ulError, NULL ) );
355 
356 		goto out;
357 	}
358 
359 	// Make sure the certificate uses an RSA key
360 	if ( !a_bCheckKey ) {
361 		rc = 0;
362 		goto out;
363 	}
364 
365 	pKey = X509_get_pubkey( pX509 );
366 	if ( !pKey ) {
367 		logInfo( TOKEN_OPENSSL_ERROR,
368 			ERR_error_string( ERR_get_error( ), NULL ) );
369 
370 		X509_free( pX509 );
371 		pX509 = NULL;
372 		goto out;
373 	}
374 
375 	if ( EVP_PKEY_type( pKey->type ) != EVP_PKEY_RSA ) {
376 		logError( TOKEN_RSA_KEY_ERROR );
377 
378 		X509_free( pX509 );
379 		pX509 = NULL;
380 		goto out;
381 	}
382 
383 	rc = 0;
384 
385 out:
386 	*a_pX509 = pX509;
387 
388 	if ( a_pszFile && pFile )
389 		fclose( pFile );
390 
391 	return rc;
392 }
393 
394 /*
395  * checkX509Cert
396  *   Use checkExistingObjects to search for X_509 objects
397  *   that match the attributes of the X_509 object to be imported.
398  */
399 int
checkX509Cert(CK_SESSION_HANDLE a_hSession)400 checkX509Cert( CK_SESSION_HANDLE  a_hSession ) {
401 
402 	CK_CERTIFICATE_TYPE  tX509       = CKC_X_509;
403 	CK_ATTRIBUTE         tAttr[]     = {
404 			{ CKA_CERTIFICATE_TYPE, &tX509, sizeof( tX509 ) },
405 		};
406 	CK_ULONG             ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );
407 
408 	return checkExistingObjects( a_hSession, tAttr, ulAttrCount, TOKEN_ID_X509_CERT );
409 }
410 
411 /*
412  * destroyX509CertObject
413  *   Use destroyExistingObjects to destroy X_509 objects
414  *   that match the attributes of the X_509 object to be imported.
415  */
416 int
destroyX509CertObject(CK_SESSION_HANDLE a_hSession)417 destroyX509CertObject( CK_SESSION_HANDLE  a_hSession ) {
418 
419 	CK_CERTIFICATE_TYPE  tX509       = CKC_X_509;
420 	CK_ATTRIBUTE         tAttr[]     = {
421 			{ CKA_CERTIFICATE_TYPE, &tX509, sizeof( tX509 ) },
422 		};
423 	CK_ULONG             ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );
424 
425 	return destroyExistingObjects( a_hSession, tAttr, ulAttrCount );
426 }
427 
428 /*
429  * createX509CertObject
430  *   Create an X_509 object.
431  */
432 int
createX509CertObject(X509 * a_pX509,CK_SESSION_HANDLE a_hSession)433 createX509CertObject( X509              *a_pX509,
434                       CK_SESSION_HANDLE  a_hSession ) {
435 
436 	int  rc = -1;
437 
438 	CK_RV  rv;
439 
440 	CK_BBOOL  bTrue = TRUE;
441 
442 	X509_NAME    *pIssuer    = NULL;
443 	ASN1_INTEGER *pSerialNum = NULL;
444 
445 	CK_BYTE  *pchIssuer      = NULL;
446 	CK_LONG  issuerLen    = 0;
447 	CK_BYTE  *pchSerialNum   = NULL;
448 	CK_LONG  serialNumLen = 0;
449 	CK_BYTE  *pchCert        = NULL;
450 	CK_LONG  certLen      = 0;
451 
452 	CK_OBJECT_CLASS      clCertClass = CKO_CERTIFICATE;
453 	CK_CERTIFICATE_TYPE  tCertType   = CKC_X_509;
454 	CK_BBOOL             bPrivate    = ( !g_bPublic ) ? TRUE : FALSE;
455 
456 	// The issuer, serial number, and value attributes must be completed
457 	// before the object is created
458 	CK_ATTRIBUTE  tCertAttr[] = {
459 			{ CKA_CLASS, &clCertClass, sizeof( clCertClass ) },
460 			{ CKA_TOKEN, &bTrue, sizeof( bTrue ) },
461 			{ CKA_PRIVATE, &bPrivate, sizeof( bPrivate ) },
462 			{ CKA_MODIFIABLE, &bTrue, sizeof( bTrue ) },
463 			{ CKA_LABEL, g_pchName, g_ulNameLen },
464 			{ CKA_CERTIFICATE_TYPE, &tCertType, sizeof( tCertType ) },
465 			{ CKA_SUBJECT, g_pchSubject, g_subjectLen },
466 			{ CKA_ID, g_pchId, g_ulIdLen },
467 			{ CKA_ISSUER, NULL, 0 },
468 			{ CKA_SERIAL_NUMBER, NULL, 0 },
469 			{ CKA_VALUE, NULL, 0 },
470 		};
471 	CK_ULONG  ulCertAttrCount = sizeof( tCertAttr ) / sizeof( CK_ATTRIBUTE );
472 
473 	CK_OBJECT_HANDLE  hObject;
474 
475 	// Get the issuer name from the X509 certificate
476 	pIssuer = X509_get_issuer_name( a_pX509 );
477 	if ( !pIssuer ) {
478 		logError( TOKEN_OPENSSL_ERROR,
479 				ERR_error_string( ERR_get_error( ), NULL ) );
480 		goto out;
481 	}
482 	issuerLen = i2d_X509_NAME( pIssuer, &pchIssuer );
483 	if ( issuerLen < 0 ) {
484 		logError( TOKEN_OPENSSL_ERROR,
485 				ERR_error_string( ERR_get_error( ), NULL ) );
486 		goto out;
487 	}
488 
489 	// Get the serial number from the X509 certificate
490 	pSerialNum = X509_get_serialNumber( a_pX509 );
491 	if ( !pSerialNum ) {
492 		logError( TOKEN_OPENSSL_ERROR,
493 				ERR_error_string( ERR_get_error( ), NULL ) );
494 		goto out;
495 	}
496 	serialNumLen = i2d_ASN1_INTEGER( pSerialNum, &pchSerialNum );
497 	if ( serialNumLen < 0 ) {
498 		logError( TOKEN_OPENSSL_ERROR,
499 				ERR_error_string( ERR_get_error( ), NULL ) );
500 		goto out;
501 	}
502 
503 	// Get a DER encoded format of the X509 certificate
504 	certLen = i2d_X509( a_pX509, &pchCert );
505 	if ( certLen < 0 ) {
506 		logError( TOKEN_OPENSSL_ERROR,
507 				ERR_error_string( ERR_get_error( ), NULL ) );
508 		goto out;
509 	}
510 
511 	// Set the attribute values
512 	tCertAttr[ 8 ].pValue = pchIssuer;
513 	tCertAttr[ 8 ].ulValueLen = issuerLen;
514 	tCertAttr[ 9 ].pValue = pchSerialNum;
515 	tCertAttr[ 9 ].ulValueLen = serialNumLen;
516 	tCertAttr[ 10 ].pValue = pchCert;
517 	tCertAttr[ 10 ].ulValueLen = certLen;
518 
519 	// Create the X509 certificate object
520 	rv = createObject( a_hSession, tCertAttr, ulCertAttrCount, &hObject );
521 	if ( rv != CKR_OK )
522 		goto out;
523 
524 	rc = 0;
525 
526 out:
527 	OPENSSL_free( pchIssuer );
528 	OPENSSL_free( pchCert );
529 	OPENSSL_free( pchSerialNum );
530 
531 	return rc;
532 }
533 
534 /*
535  * doX509Cert
536  *   Process an X509 certificate for import.
537  */
538 int
doX509Cert(X509 * a_pX509,CK_SESSION_HANDLE a_hSession)539 doX509Cert( X509              *a_pX509,
540             CK_SESSION_HANDLE  a_hSession ) {
541 
542 	int  rc = -1;
543 
544 	if ( destroyX509CertObject( a_hSession ) == -1 )
545 		goto out;
546 
547 	if ( createX509CertObject( a_pX509, a_hSession ) == -1 )
548 		goto out;
549 
550 	rc = 0;
551 
552 out:
553 	return rc;
554 }
555 
556 /*
557  * readRsaKey
558  *   Use the OpenSSL library to read a PEM formatted RSA key.
559  */
560 int
readRsaKey(const char * a_pszFile,RSA ** a_pRsa)561 readRsaKey( const char  *a_pszFile,
562             RSA        **a_pRsa ) {
563 
564 	int  rc = -1;
565 
566 	FILE *pFile = stdin;
567 	RSA  *pRsa  = NULL;
568 
569 	*a_pRsa = NULL;
570 
571 	// Open the file to be read
572 	if ( a_pszFile ) {
573 		errno = 0;
574 		pFile = fopen( a_pszFile, "r" );
575 		if ( !pFile ) {
576 			logError( TOKEN_FILE_OPEN_ERROR, a_pszFile, strerror( errno ) );
577 			goto out;
578 		}
579 	}
580 
581 	// Read the RSA key
582 	//   This reads the public key also, not just the private key
583 	pRsa = PEM_read_RSAPrivateKey( pFile, NULL, NULL, NULL );
584 	if ( !pRsa ) {
585 		unsigned long  ulError = ERR_get_error( );
586 
587 		// Not necessarily an error if the file doesn't contain the key
588 		if ( ( ERR_GET_LIB( ulError ) == ERR_R_PEM_LIB ) &&
589 		     ( ERR_GET_REASON( ulError ) == PEM_R_NO_START_LINE ) ) {
590 			logInfo( TOKEN_OPENSSL_ERROR, ERR_error_string( ulError, NULL ) );
591 			rc = 0;
592 		}
593 		else
594 			logError( TOKEN_OPENSSL_ERROR, ERR_error_string( ulError, NULL ) );
595 
596 		goto out;
597 	}
598 
599 	rc = 0;
600 
601 out:
602 	if ( a_pszFile && pFile )
603 		fclose( pFile );
604 
605 	*a_pRsa = pRsa;
606 
607 	return rc;
608 }
609 
610 /*
611  * checkRsaPubKey
612  *   Use checkExistingObjects to search for RSA public key objects
613  *   that match the attributes of the X509's RSA public key object
614  *   to be imported.
615  */
616 int
checkRsaPubKey(CK_SESSION_HANDLE a_hSession)617 checkRsaPubKey( CK_SESSION_HANDLE  a_hSession ) {
618 
619 	CK_OBJECT_CLASS  tPubKey  = CKO_PUBLIC_KEY;
620 	CK_KEY_TYPE      tRsa     = CKK_RSA;
621 	CK_ATTRIBUTE     tAttr[]  = {
622 			{ CKA_CLASS, &tPubKey, sizeof( tPubKey ) },
623 			{ CKA_KEY_TYPE, &tRsa, sizeof( tRsa ) },
624 		};
625 	CK_ULONG         ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );
626 
627 	return checkExistingObjects( a_hSession, tAttr, ulAttrCount, TOKEN_ID_RSA_PUBKEY );
628 }
629 
630 /*
631  * checkRsaKey
632  *   Use checkExistingObjects to search for RSA objects
633  *   that match the attributes of the RSA object to be imported.
634  */
635 int
checkRsaKey(CK_SESSION_HANDLE a_hSession)636 checkRsaKey( CK_SESSION_HANDLE  a_hSession ) {
637 
638 	CK_KEY_TYPE   tRsa        = CKK_RSA;
639 	CK_ATTRIBUTE  tAttr[]     = {
640 			{ CKA_KEY_TYPE, &tRsa, sizeof( tRsa ) },
641 		};
642 	CK_ULONG      ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );
643 
644 	return checkExistingObjects( a_hSession, tAttr, ulAttrCount, TOKEN_ID_RSA_KEY );
645 }
646 
647 /*
648  * destroyRsaKeyObject
649  *   Use destroyExistingObjects to destroy RSA objects
650  *   that match the attributes of the RSA object to be imported.
651  */
652 int
destroyRsaPubKeyObject(CK_SESSION_HANDLE a_hSession)653 destroyRsaPubKeyObject( CK_SESSION_HANDLE  a_hSession ) {
654 
655 	CK_OBJECT_CLASS  tPubKey     = CKO_PUBLIC_KEY;
656 	CK_KEY_TYPE      tRsa        = CKK_RSA;
657 	CK_ATTRIBUTE     tAttr[]     = {
658 			{ CKA_CLASS, &tPubKey, sizeof( tPubKey ) },
659 			{ CKA_KEY_TYPE, &tRsa, sizeof( tRsa ) },
660 		};
661 	CK_ULONG         ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );
662 
663 	return destroyExistingObjects( a_hSession, tAttr, ulAttrCount );
664 }
665 
666 /*
667  * destroyRsaKeyObject
668  *   Use destroyExistingObjects to destroy RSA objects
669  *   that match the attributes of the RSA object to be imported.
670  */
671 int
destroyRsaKeyObject(CK_SESSION_HANDLE a_hSession)672 destroyRsaKeyObject( CK_SESSION_HANDLE  a_hSession ) {
673 
674 	CK_KEY_TYPE   tRsa        = CKK_RSA;
675 	CK_ATTRIBUTE  tAttr[]     = {
676 			{ CKA_KEY_TYPE, &tRsa, sizeof( tRsa ) },
677 		};
678 	CK_ULONG      ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );
679 
680 	return destroyExistingObjects( a_hSession, tAttr, ulAttrCount );
681 }
682 
683 /*
684  * createRsaPubKeyObject
685  *   Create an RSA public key object.
686  */
687 int
createRsaPubKeyObject(RSA * a_pRsa,CK_SESSION_HANDLE a_hSession,CK_OBJECT_HANDLE * a_hObject)688 createRsaPubKeyObject( RSA               *a_pRsa,
689                        CK_SESSION_HANDLE  a_hSession,
690                        CK_OBJECT_HANDLE  *a_hObject ) {
691 
692 	int  rc = -1;
693 
694 	int  nLen = BN_num_bytes( a_pRsa->n );
695 	int  eLen = BN_num_bytes( a_pRsa->e );
696 
697 	CK_RV  rv;
698 
699 	CK_BBOOL  bTrue  = TRUE;
700 	CK_BBOOL  bFalse = FALSE;
701 
702 	CK_BYTE *n = malloc( nLen );
703 	CK_BYTE *e = malloc( eLen );
704 
705 	CK_OBJECT_CLASS  clPubClass  = CKO_PUBLIC_KEY;
706 	CK_KEY_TYPE      tKeyType    = CKK_RSA;
707 	CK_BBOOL         bPrivate    = ( !g_bPublic ) ? TRUE : FALSE;
708 
709 	CK_ATTRIBUTE  tAttr[] = {
710 			{ CKA_CLASS, &clPubClass, sizeof( clPubClass ) },
711 			{ CKA_TOKEN, &bTrue, sizeof( bTrue ) },
712 			{ CKA_PRIVATE, &bPrivate, sizeof( bPrivate ) },
713 			{ CKA_MODIFIABLE, &bTrue, sizeof( bTrue ) },
714 			{ CKA_LABEL, g_pchName, g_ulNameLen },
715 			{ CKA_KEY_TYPE, &tKeyType, sizeof( tKeyType ) },
716 			{ CKA_ID, g_pchId, g_ulIdLen },
717 			{ CKA_SUBJECT, g_pchSubject, g_subjectLen },
718 			{ CKA_ENCRYPT, &bTrue, sizeof( bTrue ) },
719 			{ CKA_VERIFY, &bTrue, sizeof( bTrue ) },
720 			{ CKA_VERIFY_RECOVER, &bFalse, sizeof( bFalse ) },
721 			{ CKA_WRAP, &bFalse, sizeof( bFalse ) },
722 			{ CKA_MODULUS, n, nLen },
723 			{ CKA_PUBLIC_EXPONENT, e, eLen },
724 		};
725 	CK_ULONG  ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );
726 
727 	*a_hObject = 0;
728 
729 	if ( !n || !e ) {
730 		logError( TOKEN_MEMORY_ERROR );
731 		goto out;
732 	}
733 
734 	// Get binary representations of the RSA key information
735 	BN_bn2bin( a_pRsa->n, n );
736 	BN_bn2bin( a_pRsa->e, e );
737 
738 	// Create the RSA public key object
739 	rv = createObject( a_hSession, tAttr, ulAttrCount, a_hObject );
740 	if ( rv != CKR_OK )
741 		goto out;
742 
743 	rc = 0;
744 
745 out:
746 	free( n );
747 	free( e );
748 
749 	return rc;
750 }
751 
752 /*
753  * createRsaPrivKeyObject
754  *   Create an RSA private key object.
755  */
756 int
createRsaPrivKeyObject(RSA * a_pRsa,CK_SESSION_HANDLE a_hSession,CK_OBJECT_HANDLE * a_hObject)757 createRsaPrivKeyObject( RSA               *a_pRsa,
758                         CK_SESSION_HANDLE  a_hSession,
759                         CK_OBJECT_HANDLE  *a_hObject ) {
760 
761 	int  rc = -1;
762 
763 	int  nLen = BN_num_bytes( a_pRsa->n );
764 	int  eLen = BN_num_bytes( a_pRsa->e );
765 	int  dLen = BN_num_bytes( a_pRsa->d );
766 	int  pLen = BN_num_bytes( a_pRsa->p );
767 	int  qLen = BN_num_bytes( a_pRsa->q );
768 	int  dmp1Len = BN_num_bytes( a_pRsa->dmp1 );
769 	int  dmq1Len = BN_num_bytes( a_pRsa->dmq1 );
770 	int  iqmpLen = BN_num_bytes( a_pRsa->iqmp );
771 
772 	CK_RV  rv;
773 
774 	CK_BBOOL  bTrue  = TRUE;
775 	CK_BBOOL  bFalse = FALSE;
776 
777 	CK_BYTE *n = malloc( nLen );
778 	CK_BYTE *e = malloc( eLen );
779 	CK_BYTE *d = malloc( dLen );
780 	CK_BYTE *p = malloc( pLen );
781 	CK_BYTE *q = malloc( qLen );
782 	CK_BYTE *dmp1 = malloc( dmp1Len );
783 	CK_BYTE *dmq1 = malloc( dmq1Len );
784 	CK_BYTE *iqmp = malloc( iqmpLen );
785 
786 	CK_OBJECT_CLASS  clPrivClass = CKO_PRIVATE_KEY;
787 	CK_KEY_TYPE      tKeyType    = CKK_RSA;
788 	CK_BBOOL         bPrivate    = ( !g_bPublic ) ? TRUE : FALSE;
789 
790 	CK_ATTRIBUTE  tAttr[] = {
791 			{ CKA_CLASS, &clPrivClass, sizeof( clPrivClass ) },
792 			{ CKA_TOKEN, &bTrue, sizeof( bTrue ) },
793 			{ CKA_PRIVATE, &bPrivate, sizeof( bPrivate ) },
794 			{ CKA_MODIFIABLE, &bTrue, sizeof( bTrue ) },
795 			{ CKA_LABEL, g_pchName, g_ulNameLen },
796 			{ CKA_KEY_TYPE, &tKeyType, sizeof( tKeyType ) },
797 			{ CKA_ID, g_pchId, g_ulIdLen },
798 			{ CKA_SUBJECT, g_pchSubject, g_subjectLen },
799 			{ CKA_SENSITIVE, &bTrue, sizeof( bTrue ) },
800 			{ CKA_DECRYPT, &bTrue, sizeof( bTrue ) },
801 			{ CKA_SIGN, &bTrue, sizeof( bTrue ) },
802 			{ CKA_SIGN_RECOVER, &bFalse, sizeof( bFalse ) },
803 			{ CKA_UNWRAP, &bFalse, sizeof( bFalse ) },
804 			{ CKA_EXTRACTABLE, &bFalse, sizeof( bFalse ) },
805 			{ CKA_MODULUS, n, nLen },
806 			{ CKA_PUBLIC_EXPONENT, e, eLen },
807 			{ CKA_PRIVATE_EXPONENT, d, dLen },
808 			{ CKA_PRIME_1, p, pLen },
809 			{ CKA_PRIME_2, q, qLen },
810 			{ CKA_EXPONENT_1, dmp1, dmp1Len },
811 			{ CKA_EXPONENT_2, dmq1, dmq1Len },
812 			{ CKA_COEFFICIENT, iqmp, iqmpLen },
813 		};
814 	CK_ULONG  ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );
815 
816 	*a_hObject = 0;
817 
818 	if ( !n || !e || !d || !p || !q || !dmp1 || !dmq1 || !iqmp ) {
819 		logError( TOKEN_MEMORY_ERROR );
820 		goto out;
821 	}
822 
823 	// Get binary representations of the RSA key information
824 	BN_bn2bin( a_pRsa->n, n );
825 	BN_bn2bin( a_pRsa->e, e );
826 	BN_bn2bin( a_pRsa->d, d );
827 	BN_bn2bin( a_pRsa->p, p );
828 	BN_bn2bin( a_pRsa->q, q );
829 	BN_bn2bin( a_pRsa->dmp1, dmp1 );
830 	BN_bn2bin( a_pRsa->dmq1, dmq1 );
831 	BN_bn2bin( a_pRsa->iqmp, iqmp );
832 
833 	// Create the RSA private key object
834 	rv = createObject( a_hSession, tAttr, ulAttrCount, a_hObject );
835 	if ( rv != CKR_OK )
836 		goto out;
837 
838 	rc = 0;
839 
840 out:
841 	free( n );
842 	free( e );
843 	free( d );
844 	free( p );
845 	free( q );
846 	free( dmp1 );
847 	free( dmq1 );
848 	free( iqmp );
849 
850 	return rc;
851 }
852 
853 /*
854  * createRsaKeyObject
855  *   Create an RSA key object (both public and private).
856  */
857 int
createRsaKeyObject(RSA * a_pRsa,CK_SESSION_HANDLE a_hSession)858 createRsaKeyObject( RSA               *a_pRsa,
859                     CK_SESSION_HANDLE  a_hSession ) {
860 
861 	int  rc = -1;
862 
863 	CK_OBJECT_HANDLE  hPubObject;
864 	CK_OBJECT_HANDLE  hPrivObject;
865 
866 	// Create the RSA public key object
867 	if ( createRsaPubKeyObject( a_pRsa, a_hSession, &hPubObject ) == -1 )
868 		goto out;
869 
870 	// Create the RSA private key object
871 	if ( createRsaPrivKeyObject( a_pRsa, a_hSession, &hPrivObject ) == -1 ) {
872 		// Private key object creation failed, destroy the public
873 		// key object just created
874 		destroyObject( a_hSession, hPubObject );
875 		goto out;
876 	}
877 
878 	rc = 0;
879 
880 out:
881 	return rc;
882 }
883 
884 /*
885  * doRsaPubKey
886  *   Process an RSA public key for import.
887  */
888 int
doRsaPubKey(RSA * a_pRsa,CK_SESSION_HANDLE a_hSession)889 doRsaPubKey( RSA               *a_pRsa,
890              CK_SESSION_HANDLE  a_hSession ) {
891 
892 	int  rc = -1;
893 
894 	CK_OBJECT_HANDLE  hObject;
895 
896 	if ( destroyRsaPubKeyObject( a_hSession ) == -1 )
897 		goto out;
898 
899 	if ( createRsaPubKeyObject( a_pRsa, a_hSession, &hObject ) == -1 )
900 		goto out;
901 
902 	rc = 0;
903 
904 out:
905 	return rc;
906 }
907 
908 /*
909  * doRsaKey
910  *   Process an RSA key for import.
911  */
912 int
doRsaKey(RSA * a_pRsa,CK_SESSION_HANDLE a_hSession)913 doRsaKey( RSA               *a_pRsa,
914           CK_SESSION_HANDLE  a_hSession ) {
915 
916 	int  rc = -1;
917 
918 	if ( destroyRsaKeyObject( a_hSession ) == -1 )
919 		goto out;
920 
921 	if ( createRsaKeyObject( a_pRsa, a_hSession ) == -1 )
922 		goto out;
923 
924 	rc = 0;
925 
926 out:
927 	return rc;
928 }
929 
930 /*
931  * getSubjectId
932  *   Extract the subject name and key identifier from an
933  *   X509 certificate for use as the SUBJECT and ID attributes.
934  */
935 int
getSubjectId(X509 * a_pX509)936 getSubjectId( X509 *a_pX509 ) {
937 
938 	int  rc = -1;
939 
940 	char *pszReply = NULL;
941 
942 	X509              *pX509    = a_pX509;
943 	X509_NAME         *pSubject = NULL;
944 	ASN1_OCTET_STRING *pSkid    = NULL;
945 
946 	// Use the Id input file if specified
947 	if ( g_pszIdFile )
948 		if ( readX509Cert( g_pszIdFile, FALSE, &pX509 ) == -1 )
949 			goto out;
950 
951 	if ( !pX509 ) {
952 		// Prompt the user about creating without it.
953 		if ( !g_bYes ) {
954 			// Prompt for whether to import without the attributes
955 			pszReply = getReply( TOKEN_ID_MISSING_PROMPT, 1 );
956 			if ( !pszReply ||
957 				( strlen( pszReply ) == 0 ) ||
958 				( strcasecmp( pszReply, TOKEN_ID_NO ) == 0 ) ) {
959 				goto out;
960 			}
961 		}
962 
963 		rc = 0;
964 		goto out;
965 	}
966 
967 	// Get the subject name from the X509 certificate
968 	pSubject = X509_get_subject_name( pX509 );
969 	if ( !pSubject ) {
970 		logInfo( TOKEN_OPENSSL_ERROR,
971 				ERR_error_string( ERR_get_error( ), NULL ) );
972 		goto out;
973 	}
974 
975 	// Get the DER encoded format of the subject name
976 	g_subjectLen = i2d_X509_NAME( pSubject, &g_pchSubject );
977 	if ( g_subjectLen < 0 ) {
978 		logInfo( TOKEN_OPENSSL_ERROR,
979 				ERR_error_string( ERR_get_error( ), NULL ) );
980 		goto out;
981 	}
982 
983 	// Get the subject key identifier from the X509 certficate
984 	pSkid = X509_get_ext_d2i( pX509, NID_subject_key_identifier, NULL, NULL );
985 	if ( !pSkid ) {
986 		logInfo( TOKEN_OPENSSL_ERROR,
987 				ERR_error_string( ERR_get_error( ), NULL ) );
988 		goto out;
989 	}
990 
991 	// Get the ASCII string format of the subject key identifier
992 	g_pchId = (CK_BYTE *)i2s_ASN1_OCTET_STRING( NULL, pSkid );
993 	if ( !g_pchId ) {
994 		logInfo( TOKEN_OPENSSL_ERROR,
995 				ERR_error_string( ERR_get_error( ), NULL ) );
996 		goto out;
997 	}
998 	g_ulIdLen = strlen( (char *)g_pchId );
999 
1000 	g_bAttrsValid = TRUE;
1001 
1002 	rc = 0;
1003 
1004 out:
1005 	// Free the structure if it was created for this function
1006 	if ( pX509 && ( pX509 != a_pX509 ) )
1007 		X509_free( pX509 );
1008 
1009 	ASN1_OCTET_STRING_free( pSkid );
1010 	free( pszReply );
1011 
1012 	return rc;
1013 }
1014 
1015 int
main(int a_iArgc,char ** a_pszArgv)1016 main( int    a_iArgc,
1017       char **a_pszArgv ) {
1018 
1019 	int  rc = 1;
1020 
1021 	char *pszPin    = NULL;
1022 
1023 	CK_RV              rv        = CKR_OK;
1024 	CK_SESSION_HANDLE  hSession  = 0;
1025 
1026 	X509 *pX509   = NULL;
1027 	RSA  *pPubRsa = NULL;
1028 	RSA  *pRsa    = NULL;
1029 
1030 	// Set up i18n
1031 	initIntlSys( );
1032 
1033 	// Initialize OpenSSL
1034 	OpenSSL_add_all_algorithms( );
1035 	ERR_load_crypto_strings( );
1036 
1037 	// Parse the command
1038 	if ( parseCmd( a_iArgc, a_pszArgv ) == -1 )
1039 		goto out;
1040 
1041 	// Open the PKCS#11 TPM Token
1042 	rv = openToken( g_pszToken );
1043 	if ( rv != CKR_OK )
1044 		goto out;
1045 
1046 	// Make sure the token is initialized
1047 	if ( !isTokenInitialized( ) ) {
1048 		logMsg( TOKEN_NOT_INIT_ERROR );
1049 		goto out;
1050 	}
1051 
1052 	// Create the structures based on the input
1053 	if ( !g_pszType ) {
1054 		if ( readX509Cert( g_pszFile, TRUE, &pX509 ) == -1 )
1055 			goto out;
1056 		if ( readRsaKey( g_pszFile, &pRsa ) == -1 )
1057 			goto out;
1058 		if ( !pX509 && !pRsa ) {
1059 			logError( TOKEN_OBJECT_ERROR );
1060 			goto out;
1061 		}
1062 	}
1063 	else if ( strcmp( g_pszType, TOKEN_OBJECT_CERT ) == 0 ) {
1064 		if ( readX509Cert( g_pszFile, TRUE, &pX509 ) == -1 )
1065 			goto out;
1066 		if ( !pX509 ) {
1067 			logError( TOKEN_OBJECT_ERROR );
1068 			goto out;
1069 		}
1070 	}
1071 	else if ( strcmp( g_pszType, TOKEN_OBJECT_KEY ) == 0 ) {
1072 		if ( readRsaKey( g_pszFile, &pRsa ) == -1 )
1073 			goto out;
1074 		if ( !pRsa ) {
1075 			logError( TOKEN_OBJECT_ERROR );
1076 			goto out;
1077 		}
1078 	}
1079 
1080 	// Open a session
1081 	rv = openTokenSession( CKF_RW_SESSION, &hSession );
1082 	if ( rv != CKR_OK )
1083 		goto out;
1084 
1085 	// Check the scope of the request, which will determine the login
1086 	// requirements:
1087 	//   Public  = no password, no login
1088 	//   Private = user password, user login (default)
1089 	if ( !g_bPublic ) {
1090 		pszPin = getPlainPasswd( TOKEN_USER_PIN_PROMPT, FALSE );
1091 		if ( !pszPin )
1092 			goto out;
1093 
1094 		// Login to the token
1095 		rv = loginToken( hSession, CKU_USER, pszPin );
1096 		if ( rv != CKR_OK )
1097 			goto out;
1098 	}
1099 
1100 	// Obtain the subject name and id, these are used to
1101 	// uniquely identify the certificate/key relation
1102 	if ( getSubjectId( pX509 ) == -1 ) {
1103 		logError( TOKEN_ID_ERROR );
1104 		goto out;
1105 	}
1106 
1107 	// Now check for existing objects that may get replaced
1108 	// prior to processing the request(s)
1109 	if ( pX509 ) {
1110 		if ( checkX509Cert( hSession ) == -1 ) {
1111 			goto out;
1112 		}
1113 
1114 		// If we are not importing any RSA keys, use the
1115 		// public key from the certificate
1116 		if ( !pRsa ) {
1117 			if ( checkRsaPubKey( hSession ) == -1 ) {
1118 				goto out;
1119 			}
1120 		}
1121 
1122 		pPubRsa = EVP_PKEY_get1_RSA( X509_get_pubkey( pX509 ) );
1123 	}
1124 	if ( pRsa ) {
1125 		if ( checkRsaKey( hSession ) == -1 ) {
1126 			goto out;
1127 		}
1128 	}
1129 
1130 	// Process the request(s)
1131 	if ( pX509 ) {
1132 		if ( doX509Cert( pX509, hSession ) == -1 )
1133 			goto out;
1134 
1135 		// If we are not importing any RSA keys, use the
1136 		// public key from the certificate
1137 		if ( !pRsa ) {
1138 			if ( doRsaPubKey( pPubRsa, hSession ) == -1 )
1139 				goto out;
1140 		}
1141 	}
1142 	if ( pRsa ) {
1143 		if ( doRsaKey( pRsa, hSession ) == -1 )
1144 			goto out;
1145 	}
1146 
1147 	rc = 0;
1148 
1149 out:
1150 	shredPasswd( pszPin );
1151 
1152 	if ( hSession )
1153 		closeTokenSession( hSession );
1154 
1155 	closeToken( );
1156 
1157 	free( g_pszFile );
1158 	free( g_pszIdFile );
1159 	free( g_pszType );
1160 	X509_free( pX509 );
1161 	RSA_free( pRsa );
1162 	OPENSSL_free( g_pchSubject );
1163 	OPENSSL_free( g_pchId );
1164 	free( g_pchName );
1165 
1166 	EVP_cleanup( );
1167 
1168 	if ( rc == 0 )
1169 		logInfo( TOKEN_CMD_SUCCESS, a_pszArgv[ 0 ] );
1170 	else
1171 		logInfo( TOKEN_CMD_FAILED, a_pszArgv[ 0 ] );
1172 
1173 	return rc;
1174 }
1175