⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 data_import.c

📁 Linux下关于TPM的一些检测小工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */#include "data_import.h"#include "data_common.h"#include <tpm_pkcs11.h>#include <tpm_utils.h>#include <stdlib.h>#include <unistd.h>#define _GNU_SOURCE#include <getopt.h>#include <errno.h>#include <openssl/rsa.h>#include <openssl/x509.h>#include <openssl/x509v3.h>#include <openssl/pem.h>#include <openssl/asn1.h>#include <openssl/evp.h>#include <openssl/err.h>/* * Global variables */char *g_pszFile   = NULL;		// Object import file namechar *g_pszIdFile = NULL;		// Object identification file namechar *g_pszType   = NULL;		// Object import typeint   g_bPublic   = FALSE;		// Public object specifierint   g_bYes      = FALSE;		// Yes/No prompt replychar *g_pszToken  = NULL;		// Token label to be usedint       g_bAttrsValid  = FALSE;CK_BYTE  *g_pchSubject   = NULL;	// SUBJECT attribute valueCK_ULONG  g_ulSubjectLen = 0;CK_BYTE  *g_pchId        = NULL;	// ID attribute valueCK_ULONG  g_ulIdLen      = 0;CK_BYTE  *g_pchName      = NULL;	// LABEL attribute valueCK_ULONG  g_ulNameLen    = 0;/* * parseCallback *   Process the command specific options. */intparseCallback( int         a_iOpt,               const char *a_pszOptArg ) {	switch ( a_iOpt ) {		// File with object to be used to obtain subject/id		case 'i':			if ( !a_pszOptArg )				return -1;			g_pszIdFile = strdup( a_pszOptArg );			break;		// Use the specified token label when finding the token		case 'k':			if ( !a_pszOptArg )				return -1;			g_pszToken = strdup( a_pszOptArg );			break;		// Name to use as the LABEL attribute value		case 'n':			if ( !a_pszOptArg )				return -1;			g_pchName = (CK_BYTE *)strdup( a_pszOptArg );			g_ulNameLen = strlen( a_pszOptArg );			break;		// Make the object public		case 'p':			g_bPublic = TRUE;			break;		// Only import the specified object type		case 't':			if ( !a_pszOptArg )				return -1;			if ( ( strcmp( a_pszOptArg, TOKEN_OBJECT_KEY )  != 0 ) &&			     ( strcmp( a_pszOptArg, TOKEN_OBJECT_CERT ) != 0 ) )				return -1;			g_pszType = strdup( a_pszOptArg );			break;		// Reply "yes" to any yes/no prompts		case 'y':			g_bYes = TRUE;			break;	}	return 0;}/* * usageCallback *   Display command usage information. */voidusageCallback( const char *a_pszCmd ) {	char *pszArgs[2];	char *pszArgsDesc[2];	pszArgs[ 0 ] = "FILE";	pszArgsDesc[ 0 ] = _("Import the PEM formatted RSA key and/or X.509 certificate object contained in FILE");	pszArgs[ 1 ] = NULL;	pszArgsDesc[ 1 ] = NULL;	logCmdHelpEx( a_pszCmd, pszArgs, pszArgsDesc );	logCmdOption( "-i, --idfile FILE",			_("Use FILE as the PEM formatted X.509 certificate input used to obtain the subject and id attributes") );	logCmdOption( "-k, --token STRING",			_("Use STRING to identify the label of the PKCS#11 token to be used") );	logCmdOption( "-n, --name STRING",			_("Use STRING as the label for the imported object(s)") );	logCmdOption( "-p, --public",			_("Import the object(s) as a public object") );	logCmdOption( "-t, --type key|cert",			_("Import only the specified object type") );	logCmdOption( "-y, --yes",			_("Assume yes as the answer to any confirmation prompt") );}/* * parseCmd *   Parse the command line options. */intparseCmd( int    a_iArgc,          char **a_pszArgv ) {	int  rc;	char          *pszShortOpts  = "i:k:n:pt:y";	struct option  stLongOpts[]  = {			{ "idfile", required_argument, NULL, 'i' },			{ "name", required_argument, NULL, 'n' },			{ "public", no_argument, NULL, 'p' },			{ "token", required_argument, NULL, 'k' },			{ "type", required_argument, NULL, 't' },			{ "yes", no_argument, NULL, 'y' },		};	int  iNumLongOpts = sizeof( stLongOpts ) / sizeof( struct option );	rc = genericOptHandler( a_iArgc, a_pszArgv,		pszShortOpts, stLongOpts, iNumLongOpts,		parseCallback, usageCallback );	if ( rc == -1 )		return -1;	if ( optind >= a_iArgc ) {		logMsg( TOKEN_FILE_ERROR );		usageCallback( a_pszArgv[ 0 ] );		return -1;	}	g_pszFile = strdup( a_pszArgv[ optind ] );	return 0;}/* * findExistingObjects *   Search for objects of the supplied type that have a SUBJECT *   and ID attribute equal to the values of the object to be *   imported. */intfindExistingObjects( CK_SESSION_HANDLE   a_hSession,                     CK_ATTRIBUTE       *a_tAttr,                     CK_ULONG            a_ulAttrCount,                     CK_OBJECT_HANDLE  **a_phObject,                     CK_ULONG           *a_pulObjectCount ) {	CK_RV     rv;	CK_BBOOL  bTrue = TRUE;	// Set up default search attributes	CK_ATTRIBUTE  tDefaultAttr[]     = {			{ CKA_TOKEN, &bTrue, sizeof( bTrue ) },			{ CKA_SUBJECT, g_pchSubject, g_ulSubjectLen },			{ CKA_ID, g_pchId, g_ulIdLen },		};	CK_ULONG      ulDefaultAttrCount = sizeof( tDefaultAttr ) / sizeof( CK_ATTRIBUTE );	CK_ATTRIBUTE  tAttr[ ulDefaultAttrCount + a_ulAttrCount ];	CK_ULONG      ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );	*a_phObject = NULL;	*a_pulObjectCount = 0;	// Apply attributes and search	memcpy( tAttr, tDefaultAttr, ulDefaultAttrCount * sizeof( CK_ATTRIBUTE ) );	if ( a_ulAttrCount )		memcpy( tAttr + ulDefaultAttrCount, a_tAttr, a_ulAttrCount * sizeof( CK_ATTRIBUTE ) );	rv = findObjects( a_hSession, tAttr, ulAttrCount, a_phObject, a_pulObjectCount );	return ( rv == CKR_OK ) ? 0 : -1;}/* * checkExistingObjects *   Use findExistingObjects to determine if objects of the *   supplied type currently exist.  If so, prompt the user as *   to whether to replace the existing objects. */intcheckExistingObjects( CK_SESSION_HANDLE  a_hSession,                      CK_ATTRIBUTE      *a_tAttr,                      CK_ULONG           a_ulAttrCount,                      const char        *a_pszObject ) {	int  rc = -1;	CK_OBJECT_HANDLE *phObject      = NULL;	CK_ULONG          ulObjectCount = 0;	char  szPrompt[ strlen( TOKEN_ID_PROMPT ) + strlen( a_pszObject ) + 1 ];	char *pszReply = NULL;	if ( g_bAttrsValid ) {		// Search for existing objects		if ( findExistingObjects( a_hSession, a_tAttr, a_ulAttrCount, &phObject, &ulObjectCount ) == -1 )			goto out;		if ( ulObjectCount > 0 ) {			// One or more objects exists			if ( !g_bYes ) {				// Prompt for whether to replace the existing objects				sprintf( szPrompt, TOKEN_ID_PROMPT, a_pszObject );				pszReply = getReply( szPrompt, 1 );				if ( !pszReply ||					( strlen( pszReply ) == 0 ) ||					( strcasecmp( pszReply, TOKEN_ID_NO ) == 0 ) ) {					goto out;				}			}		}	}	rc = 0;out:	free( phObject );	free( pszReply );	return rc;}/* * destroyExistingObjects *   Use findExistingObjects to locate all objects of the *   supplied type that currently exists and destroy them. */intdestroyExistingObjects( CK_SESSION_HANDLE  a_hSession,                        CK_ATTRIBUTE      *a_tAttr,                        CK_ULONG           a_ulAttrCount ) {	int  rc = -1;	CK_RV             rv;	CK_OBJECT_HANDLE *phObject      = NULL;	CK_ULONG          ulObjectCount = 0;	if ( g_bAttrsValid ) {		// Search for existing objects		if ( findExistingObjects( a_hSession, a_tAttr, a_ulAttrCount, &phObject, &ulObjectCount ) == -1 )			goto out;		// Destroy each object found		while ( ulObjectCount > 0 ) {			rv = destroyObject( a_hSession, phObject[ --ulObjectCount ] );			if ( rv != CKR_OK )				goto out;		}	}	rc = 0;out:	free( phObject );	return rc;}/* * readX509Cert *   Use the OpenSSL library to read a PEM formatted X509 certificate. */intreadX509Cert( const char  *a_pszFile,              int          a_bCheckKey,              X509       **a_pX509 ) {	int rc = -1;	FILE     *pFile = stdin;	X509     *pX509 = NULL;	EVP_PKEY *pKey  = NULL;	*a_pX509 = NULL;	// Open the file to be read	if ( a_pszFile ) {		errno = 0;		pFile = fopen( a_pszFile, "r" );		if ( !pFile ) {			logError( TOKEN_FILE_OPEN_ERROR, a_pszFile, strerror( errno ) );			goto out;		}	}	// Read the X509 certificate	pX509 = PEM_read_X509( pFile, NULL, NULL, NULL );	if ( !pX509 ) {		unsigned long  ulError = ERR_get_error( );		// Not necessarily an error if the file doesn't contain the cert		if ( ( ERR_GET_LIB( ulError ) == ERR_R_PEM_LIB ) &&		     ( ERR_GET_REASON( ulError ) == PEM_R_NO_START_LINE ) ) {			logInfo( TOKEN_OPENSSL_ERROR, ERR_error_string( ulError, NULL ) );			rc = 0;		}		else			logError( TOKEN_OPENSSL_ERROR, ERR_error_string( ulError, NULL ) );		goto out;	}	// Make sure the certificate uses an RSA key	if ( !a_bCheckKey ) {		rc = 0;		goto out;	}	pKey = X509_get_pubkey( pX509 );	if ( !pKey ) {		logInfo( TOKEN_OPENSSL_ERROR,			ERR_error_string( ERR_get_error( ), NULL ) );		X509_free( pX509 );		pX509 = NULL;		goto out;	}	if ( EVP_PKEY_type( pKey->type ) != EVP_PKEY_RSA ) {		logError( TOKEN_RSA_KEY_ERROR );		X509_free( pX509 );		pX509 = NULL;		goto out;	}	rc = 0;out:	*a_pX509 = pX509;	if ( a_pszFile && pFile )		fclose( pFile );	return rc;}/* * checkX509Cert *   Use checkExistingObjects to search for X_509 objects *   that match the attributes of the X_509 object to be imported. */intcheckX509Cert( CK_SESSION_HANDLE  a_hSession ) {	CK_CERTIFICATE_TYPE  tX509       = CKC_X_509;	CK_ATTRIBUTE         tAttr[]     = {			{ CKA_CERTIFICATE_TYPE, &tX509, sizeof( tX509 ) },		};	CK_ULONG             ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );	return checkExistingObjects( a_hSession, tAttr, ulAttrCount, TOKEN_ID_X509_CERT );}/* * destroyX509CertObject *   Use destroyExistingObjects to destroy X_509 objects *   that match the attributes of the X_509 object to be imported. */intdestroyX509CertObject( CK_SESSION_HANDLE  a_hSession ) {	CK_CERTIFICATE_TYPE  tX509       = CKC_X_509;	CK_ATTRIBUTE         tAttr[]     = {			{ CKA_CERTIFICATE_TYPE, &tX509, sizeof( tX509 ) },		};	CK_ULONG             ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );	return destroyExistingObjects( a_hSession, tAttr, ulAttrCount );}/* * createX509CertObject *   Create an X_509 object. */intcreateX509CertObject( X509              *a_pX509,                      CK_SESSION_HANDLE  a_hSession ) {	int  rc = -1;	CK_RV  rv;	CK_BBOOL  bTrue = TRUE;	X509_NAME    *pIssuer    = NULL;	ASN1_INTEGER *pSerialNum = NULL;	CK_BYTE  *pchIssuer      = NULL;	CK_ULONG  ulIssuerLen    = 0;	CK_BYTE  *pchSerialNum   = NULL;	CK_ULONG  ulSerialNumLen = 0;	CK_BYTE  *pchCert        = NULL;	CK_ULONG  ulCertLen      = 0;	CK_OBJECT_CLASS      clCertClass = CKO_CERTIFICATE;	CK_CERTIFICATE_TYPE  tCertType   = CKC_X_509;	CK_BBOOL             bPrivate    = ( !g_bPublic ) ? TRUE : FALSE;	// The issuer, serial number, and value attributes must be completed	// before the object is created	CK_ATTRIBUTE  tCertAttr[] = {			{ CKA_CLASS, &clCertClass, sizeof( clCertClass ) },			{ CKA_TOKEN, &bTrue, sizeof( bTrue ) },			{ CKA_PRIVATE, &bPrivate, sizeof( bPrivate ) },			{ CKA_MODIFIABLE, &bTrue, sizeof( bTrue ) },			{ CKA_LABEL, g_pchName, g_ulNameLen },			{ CKA_CERTIFICATE_TYPE, &tCertType, sizeof( tCertType ) },			{ CKA_SUBJECT, g_pchSubject, g_ulSubjectLen },			{ CKA_ID, g_pchId, g_ulIdLen },			{ CKA_ISSUER, NULL, 0 },			{ CKA_SERIAL_NUMBER, NULL, 0 },			{ CKA_VALUE, NULL, 0 },		};	CK_ULONG  ulCertAttrCount = sizeof( tCertAttr ) / sizeof( CK_ATTRIBUTE );	CK_OBJECT_HANDLE  hObject;	// Get the issuer name from the X509 certificate	pIssuer = X509_get_issuer_name( a_pX509 );	if ( !pIssuer ) {		logError( TOKEN_OPENSSL_ERROR,				ERR_error_string( ERR_get_error( ), NULL ) );		goto out;	}	ulIssuerLen = i2d_X509_NAME( pIssuer, &pchIssuer );	if ( ulIssuerLen < 0 ) {		logError( TOKEN_OPENSSL_ERROR,				ERR_error_string( ERR_get_error( ), NULL ) );		goto out;	}	// Get the serial number from the X509 certificate	pSerialNum = X509_get_serialNumber( a_pX509 );	if ( !pSerialNum ) {		logError( TOKEN_OPENSSL_ERROR,				ERR_error_string( ERR_get_error( ), NULL ) );		goto out;	}	ulSerialNumLen = i2d_ASN1_INTEGER( pSerialNum, &pchSerialNum );	if ( ulSerialNumLen < 0 ) {		logError( TOKEN_OPENSSL_ERROR,				ERR_error_string( ERR_get_error( ), NULL ) );		goto out;	}	// Get a DER encoded format of the X509 certificate	ulCertLen = i2d_X509( a_pX509, &pchCert );	if ( ulCertLen < 0 ) {		logError( TOKEN_OPENSSL_ERROR,				ERR_error_string( ERR_get_error( ), NULL ) );		goto out;	}	// Set the attribute values	tCertAttr[ 8 ].pValue = pchIssuer;	tCertAttr[ 8 ].ulValueLen = ulIssuerLen;	tCertAttr[ 9 ].pValue = pchSerialNum;	tCertAttr[ 9 ].ulValueLen = ulSerialNumLen;	tCertAttr[ 10 ].pValue = pchCert;	tCertAttr[ 10 ].ulValueLen = ulCertLen;	// Create the X509 certificate object	rv = createObject( a_hSession, tCertAttr, ulCertAttrCount, &hObject );	if ( rv != CKR_OK )		goto out;	rc = 0;out:	OPENSSL_free( pchIssuer );	OPENSSL_free( pchCert );	OPENSSL_free( pchSerialNum );	return rc;}/* * doX509Cert *   Process an X509 certificate for import. */intdoX509Cert( X509              *a_pX509,            CK_SESSION_HANDLE  a_hSession ) {	int  rc = -1;	if ( destroyX509CertObject( a_hSession ) == -1 )		goto out;	if ( createX509CertObject( a_pX509, a_hSession ) == -1 )		goto out;	rc = 0;out:	return rc;}/* * readRsaKey *   Use the OpenSSL library to read a PEM formatted RSA key. */intreadRsaKey( const char  *a_pszFile,            RSA        **a_pRsa ) {	int  rc = -1;	FILE *pFile = stdin;	RSA  *pRsa  = NULL;	*a_pRsa = NULL;	// Open the file to be read	if ( a_pszFile ) {		errno = 0;		pFile = fopen( a_pszFile, "r" );		if ( !pFile ) {			logError( TOKEN_FILE_OPEN_ERROR, a_pszFile, strerror( errno ) );			goto out;		}	}	// Read the RSA key	//   This reads the public key also, not just the private key	pRsa = PEM_read_RSAPrivateKey( pFile, NULL, NULL, NULL );	if ( !pRsa ) {		unsigned long  ulError = ERR_get_error( );		// Not necessarily an error if the file doesn't contain the key		if ( ( ERR_GET_LIB( ulError ) == ERR_R_PEM_LIB ) &&

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -