📄 cryptacm.h
字号:
* *
* Key Management Mechanism ACL Handling *
* *
****************************************************************************/
/* Key management ACL information. These work in the same general way as the
crypto mechanism ACL checks enforced by the kernel. The ACL entries are:
Valid keyset types for general access.
Valid keyset types for query access.
Valid keyset types for getNextCert access.
Valid object types to write.
Valid access types.
Valid key management flags in the mechanism info.
Access type for which an ID parameter is required.
Access type for which a password (or other aux.info) is required
The last two entries are used for parameter checking and represent all
access types for which these parameters are required, even if those
access types aren't currently allowed by the valid access types entry.
This is to allow them to be enabled by changing only the valid access
types entry without having to update the other two entries as well */
static const KEYMGMT_ACL keyManagementACL[] = {
MK_KEYACL( /* No item type */
KEYMGMT_ITEM_NONE, ST_NONE, ST_NONE, ST_NONE, ST_NONE,
ACCESS_KEYSET_xxxxx, KEYMGMT_FLAG_NONE,
ACCESS_KEYSET_xxxxx, ACCESS_KEYSET_xxxxx ),
MK_KEYACL( /* Access public key */
KEYMGMT_ITEM_PUBLICKEY,
ST_KEYSET_ANY | ST_DEV_FORT | ST_DEV_P11,
ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | ST_KEYSET_LDAP,
ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | ST_KEYSET_FILE | ST_DEV_FORT,
ST_CTX_PKC | ST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT,
ACCESS_KEYSET_FNRWD, KEYMGMT_FLAG_CHECK_ONLY | KEYMGMT_FLAG_LABEL_ONLY | \
KEYMGMT_MASK_CERTOPTIONS,
ACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx ),
MK_KEYACL( /* Access private key */
KEYMGMT_ITEM_PRIVATEKEY,
ST_KEYSET_FILE | ST_DEV_FORT | ST_DEV_P11, ST_NONE, ST_NONE,
ST_CTX_PKC,
ACCESS_KEYSET_xxRWD, KEYMGMT_FLAG_CHECK_ONLY | KEYMGMT_FLAG_LABEL_ONLY,
ACCESS_KEYSET_xxRxD, ACCESS_KEYSET_xxXXx ),
MK_KEYACL( /* Access secret key */
KEYMGMT_ITEM_SECRETKEY,
ST_KEYSET_FILE, ST_NONE, ST_NONE,
ST_CTX_CONV,
ACCESS_KEYSET_xxRWD, KEYMGMT_FLAG_NONE,
ACCESS_KEYSET_xxRxD, ACCESS_KEYSET_xxRWx ),
MK_KEYACL( /* Access cert request */
KEYMGMT_ITEM_REQUEST,
ST_KEYSET_DBMS_STORE, ST_KEYSET_DBMS_STORE, ST_NONE,
ST_CERT_CERTREQ | ST_CERT_REQ_CERT | ST_CERT_REQ_REV,
ACCESS_KEYSET_xxRWx, KEYMGMT_FLAG_UPDATE,
ACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx ),
MK_KEYACL( /* Access PKI user info */
KEYMGMT_ITEM_PKIUSER,
ST_KEYSET_DBMS_STORE, ST_KEYSET_DBMS_STORE, ST_NONE,
ST_CERT_PKIUSER,
ACCESS_KEYSET_xxRWx, KEYMGMT_FLAG_NONE,
ACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx ),
MK_KEYACL( /* Access revocation info/CRL */
KEYMGMT_ITEM_REVOCATIONINFO,
ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE, ST_NONE, ST_NONE,
ST_CERT_CRL,
ACCESS_KEYSET_xxRWx, KEYMGMT_FLAG_CHECK_ONLY,
ACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx ),
MK_KEYACL( /* Other data (for PKCS #15 tokens) */
KEYMGMT_ITEM_DATA,
ST_KEYSET_FILE,
ST_NONE, ST_NONE, ST_NONE,
ACCESS_KEYSET_xxRWx, KEYMGMT_FLAG_NONE,
ACCESS_KEYSET_xxRWD, ACCESS_KEYSET_FNxxx ),
MK_KEYACL( /* Last item type */
KEYMGMT_ITEM_LAST, ST_NONE, ST_NONE, ST_NONE, ST_NONE,
ACCESS_KEYSET_xxxxx, KEYMGMT_FLAG_NONE,
ACCESS_KEYSET_xxxxx, ACCESS_KEYSET_xxxxx )
};
/* It's a keyset action message, check the access conditions for the mechanism
objects */
static int preDispatchCheckKeysetAccess( const int objectHandle,
const RESOURCE_MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue,
const void *dummy )
{
const RESOURCE_MESSAGE_TYPE localMessage = message & RESOURCE_MESSAGE_MASK;
const MESSAGE_KEYMGMT_INFO *mechanismInfo = \
( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
const KEYMGMT_ACL *keymgmtACL = \
&keyManagementACL[ messageValue ];
const int accessType = \
( localMessage == RESOURCE_MESSAGE_KEY_GETKEY ) ? ACCESS_FLAG_R : \
( localMessage == RESOURCE_MESSAGE_KEY_SETKEY ) ? ACCESS_FLAG_W : \
( localMessage == RESOURCE_MESSAGE_KEY_DELETEKEY ) ? ACCESS_FLAG_D : \
( localMessage == RESOURCE_MESSAGE_KEY_GETFIRSTCERT ) ? ACCESS_FLAG_F : \
( localMessage == RESOURCE_MESSAGE_KEY_GETNEXTCERT ) ? ACCESS_FLAG_N : 0;
OBJECT_TYPE subType;
/* Preconditions */
PRE( isValidObject( objectHandle ) );
PRE( localMessage == RESOURCE_MESSAGE_KEY_GETKEY || \
localMessage == RESOURCE_MESSAGE_KEY_SETKEY || \
localMessage == RESOURCE_MESSAGE_KEY_DELETEKEY || \
localMessage == RESOURCE_MESSAGE_KEY_GETFIRSTCERT || \
localMessage == RESOURCE_MESSAGE_KEY_GETNEXTCERT );
PRE( messageDataPtr != NULL );
PRE( messageValue > KEYMGMT_ITEM_NONE && \
messageValue < KEYMGMT_ITEM_LAST );
PRE( keymgmtACL->itemType == messageValue );
PRE( accessType != 0 );
/* Make sure the item type being accessed is appropriate for this keyset
type, and that the access type is valid */
subType = objectTable[ objectHandle ].subType;
if( !isValidSubtype( keymgmtACL->keysetSubTypeA, subType ) && \
!isValidSubtype( keymgmtACL->keysetSubTypeB, subType ) )
return( CRYPT_ARGERROR_OBJECT );
if( !( keymgmtACL->allowedAccess & accessType ) )
return( CRYPT_ARGERROR_OBJECT );
/* If this is a non-general-purpose access, make sure it's allowed for
this keyset type */
if( localMessage == RESOURCE_MESSAGE_KEY_GETFIRSTCERT || \
localMessage == RESOURCE_MESSAGE_KEY_GETNEXTCERT )
{
/* The two special-purpose accesses are differentiated by whether
there's state information provided, for a general query the result
set is determined by an initially-submitted query which is
followed by a sequence of fetches, for a getFirst/getNext the
results are determined by a cert identifier with state held
externally in the location pointed to by the auxiliary info
pointer */
if( mechanismInfo->auxInfo == NULL )
{
/* Keyset query. We report this as an arg error since we'll
have been passed a CRYPT_KEYID_NONE or empty keyID, this is
more sensible than an object error since there's nothing
wrong with the object, the problem is that there's no keyID
present */
if( !isValidSubtype( keymgmtACL->querySubTypeA, subType ) && \
!isValidSubtype( keymgmtACL->querySubTypeB, subType ) )
return( ( mechanismInfo->keyIDtype == CRYPT_KEYID_NONE ) ? \
CRYPT_ARGERROR_NUM1 : CRYPT_ARGERROR_STR1 );
}
else
{
/* getFirst/next. We can report an object error here since this
message is only sent internally */
if( !isValidSubtype( keymgmtACL->getNextSubTypeA, subType ) && \
!isValidSubtype( keymgmtACL->getNextSubTypeB, subType ) )
return( CRYPT_ARGERROR_OBJECT );
/* Inner precondition: The state information points to an
integer value containing a reference to the currently
fetched object */
PRE( mechanismInfo->auxInfo != NULL && \
mechanismInfo->auxInfoLength == sizeof( int ) );
}
}
/* Make sure there's ID information present if required */
if( keymgmtACL->idUseFlags & accessType )
{
if( mechanismInfo->keyIDtype == CRYPT_KEYID_NONE )
return( CRYPT_ARGERROR_NUM1 );
if( mechanismInfo->keyID == NULL || mechanismInfo->keyIDlength < 1 )
return( CRYPT_ARGERROR_STR1 );
}
/* Make sure there's a password present/not present if required. We
only check for incorrect parameters here if they were supplied by the
user, non-user-supplied parameters (which come from within cryptlib)
are checked by an assertion later on. For keyset objects the
password is optional on reads since it may be a label-only read or an
opportunistic read which tries to read the key without a password
initially and falls back to retrying with a password if this fails,
for device objects the password is never used since it was supplied
when the user logged on to the device.
Since the semantics of passwords for private keys are too complex to
express with a simple ACL entry, this check is hardcoded */
if( messageValue == KEYMGMT_ITEM_PRIVATEKEY )
if( objectTable[ objectHandle ].type == OBJECT_TYPE_KEYSET )
{
if( localMessage == RESOURCE_MESSAGE_KEY_SETKEY && \
( mechanismInfo->auxInfo == NULL || \
mechanismInfo->auxInfoLength < 1 ) )
/* Private key writes to a keyset must provide a password */
return( CRYPT_ARGERROR_STR1 );
}
else
if( ( mechanismInfo->auxInfo != NULL || \
mechanismInfo->auxInfoLength != 0 ) )
/* Private key access to a device doesn't use a password */
return( ( keymgmtACL->idUseFlags & accessType ) ? \
CRYPT_ARGERROR_STR2 : CRYPT_ARGERROR_STR1 );
/* Inner precondition: Only allowed flags are set, there's only one of
the usage preference flags set, and the object handle to get/set is
not present if required (the presence and validity check when it is
required is performed further down) */
PRE( !( ~keymgmtACL->allowedFlags & mechanismInfo->flags ) );
PRE( mechanismInfo->flags >= KEYMGMT_FLAG_NONE && \
mechanismInfo->flags < KEYMGMT_FLAG_LAST );
PRE( ( mechanismInfo->flags & KEYMGMT_MASK_USAGEOPTIONS ) != \
KEYMGMT_MASK_USAGEOPTIONS );
PRE( localMessage == RESOURCE_MESSAGE_KEY_SETKEY || \
mechanismInfo->cryptHandle == CRYPT_ERROR );
/* Inner precondition: There's ID information and a password/aux.data
present/not present as required. For a private key read the password
is optional so we don't check it, for a getFirst/getNext the aux.data
(a pointer to query state) is used when assembling a cert chain (state
held in the cert) and not used when performing a general query (state
held in the keyset) */
PRE( ( ( keymgmtACL->idUseFlags & accessType ) && \
mechanismInfo->keyIDtype != CRYPT_KEYID_NONE && \
mechanismInfo->keyID != NULL && \
mechanismInfo->keyIDlength >= 1 ) ||
( !( keymgmtACL->idUseFlags & accessType ) && \
mechanismInfo->keyIDtype == CRYPT_KEYID_NONE && \
mechanismInfo->keyID == NULL && \
mechanismInfo->keyIDlength == 0 ) );
PRE( ( messageValue == KEYMGMT_ITEM_PRIVATEKEY && \
localMessage == RESOURCE_MESSAGE_KEY_GETKEY ) ||
localMessage == RESOURCE_MESSAGE_KEY_GETFIRSTCERT ||
localMessage == RESOURCE_MESSAGE_KEY_GETNEXTCERT ||
( ( keymgmtACL->pwUseFlags & accessType ) && \
mechanismInfo->auxInfo != NULL && \
mechanismInfo->auxInfoLength >= 1 ) ||
( !( keymgmtACL->pwUseFlags & accessType ) && \
mechanismInfo->auxInfo == NULL && \
mechanismInfo->auxInfoLength == 0 ) );
/* Perform message-type-specific checking of parameters */
switch( localMessage )
{
case RESOURCE_MESSAGE_KEY_GETKEY:
break;
case RESOURCE_MESSAGE_KEY_SETKEY:
/* Make sure the object being sent is valid and its type is
appropriate for this item (and via previous checks, keyset)
type */
if( !isValidObject( mechanismInfo->cryptHandle ) )
return( CRYPT_ARGERROR_NUM1 );
if( !isSameOwner( objectHandle, mechanismInfo->cryptHandle ) )
return( CRYPT_ARGERROR_NUM1 );
subType = objectTable[ mechanismInfo->cryptHandle ].subType;
if( !isValidSubtype( keymgmtACL->objSubTypeA, subType ) && \
!isValidSubtype( keymgmtACL->objSubTypeB, subType ) )
{
int altCryptHandle;
/* If we're only allowed to add contexts, this could be a
cert object with an associated context, in which case
we look for an associated context and try again */
if( keymgmtACL->objSubTypeA != ST_CTX_PKC )
return( CRYPT_ARGERROR_NUM1 );
altCryptHandle = findTargetType( mechanismInfo->cryptHandle,
OBJECT_TYPE_CONTEXT );
if( cryptStatusError( altCryptHandle ) || \
objectTable[ altCryptHandle ].subType != ST_CTX_PKC )
return( CRYPT_ARGERROR_NUM1 );
}
break;
case RESOURCE_MESSAGE_KEY_DELETEKEY:
break;
case RESOURCE_MESSAGE_KEY_GETFIRSTCERT:
break;
case RESOURCE_MESSAGE_KEY_GETNEXTCERT:
break;
default:
assert( NOTREACHED );
}
/* Postcondition: The access and parameters are valid and the object
being passed in is of the correct type if present. We don't
explicitly state this since it's just regurgitating the checks
already performed above */
return( CRYPT_OK );
}
#endif /* _CRYPTACM_DEFINED */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -