📄 dev_capi.c
字号:
const int length )
{
CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
if( pCryptGenRandom( cryptoapiInfo->hProv, length, buffer ) )
return( CRYPT_OK );
return( mapError( cryptoapiInfo, CRYPT_ERROR_FAILED ) );
}
/* Instantiate an object in a device. This works like the create context
function but instantiates a cryptlib object using data already contained
in the device (for example a stored private key or certificate). If the
value being read is a public key and there's a certificate attached, the
instantiated object is a native cryptlib object rather than a device
object with a native certificate object attached because there doesn't
appear to be any good reason to create the public-key object in the device,
for most devices the cryptlib native object will be faster anyway, and
some apps see the public key as redundant and delete it, so only the cert
will be present */
static int getItemFunction( DEVICE_INFO *deviceInfo,
CRYPT_CONTEXT *iCryptContext,
const KEYMGMT_ITEM_TYPE itemType,
const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength,
void *auxInfo, int *auxInfoLength,
const int flags )
{
CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
// CRYPT_CERTIFICATE iCryptCert;
// RESOURCE_DATA msgData;
PCCERT_CONTEXT pCertContext = NULL;
CRYPT_DATA_BLOB cryptDataBlob;
CERT_RDN certRDN;
CERT_RDN_ATTR certRDNAttr;
CERT_INFO certInfo;
int status;
BOOLEAN certViaPrivateKey = FALSE, privateKeyViaCert = FALSE;
BOOLEAN certPresent = FALSE;
BOOLEAN cryptAllowed = FALSE, sigAllowed = FALSE;
// char label[ CRYPT_MAX_TEXTSIZE ];
// int keySize, actionFlags = 0, labelLength;
assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_PRIVATEKEY );
/* Set up a search template for the ID type we're using */
if( keyIDtype == CRYPT_KEYID_NAME )
{
memset( &certRDN, 0, sizeof( CERT_RDN ) );
certRDN.rgRDNAttr = &certRDNAttr;
certRDN.cRDNAttr = 1;
memset( &certRDNAttr, 0, sizeof( CERT_RDN_ATTR ) );
certRDNAttr.pszObjId = szOID_COMMON_NAME;
certRDNAttr.dwValueType = CERT_RDN_ANY_TYPE;
certRDNAttr.Value.pbData = ( void * ) keyID;
certRDNAttr.Value.cbData = keyIDlength;
}
if( keyIDtype == CRYPT_KEYID_EMAIL )
{
memset( &certRDN, 0, sizeof( CERT_RDN ) );
certRDN.rgRDNAttr = &certRDNAttr;
certRDN.cRDNAttr = 1;
memset( &certRDNAttr, 0, sizeof( CERT_RDN_ATTR ) );
certRDNAttr.pszObjId = szOID_RSA_emailAddr ;
certRDNAttr.dwValueType = CERT_RDN_ANY_TYPE;
certRDNAttr.Value.pbData = ( void * ) keyID;
certRDNAttr.Value.cbData = keyIDlength;
}
if( keyIDtype == CRYPT_IKEYID_CERTID )
{
memset( &cryptDataBlob, 0, sizeof( CRYPT_DATA_BLOB ) );
cryptDataBlob.pbData = ( void * ) keyID;
cryptDataBlob.cbData = keyIDlength;
}
if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )
{
STREAM stream;
int length;
memset( &certInfo, 0, sizeof( CERT_INFO ) );
sMemConnect( &stream, keyID, keyIDlength );
readSequence( &stream, NULL );
certInfo.Issuer.pbData = sMemBufPtr( &stream );
readSequence( &stream, &length ); /* Issuer DN */
certInfo.Issuer.cbData = ( int ) sizeofObject( length );
sSkip( &stream, length );
certInfo.SerialNumber.pbData = sMemBufPtr( &stream );
readGenericHole( &stream, &length, BER_INTEGER );/* Serial number */
certInfo.SerialNumber.cbData = ( int ) sizeofObject( length );
assert( sStatusOK( &stream ) );
sMemDisconnect( &stream );
}
/* Try for a cert first */
switch( keyIDtype )
{
case CRYPT_KEYID_NAME:
pCertContext = \
pCertFindCertificateInStore( hCertStore,
X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_ATTR,
&certRDN, NULL );
break;
case CRYPT_KEYID_EMAIL:
/* There doesn't appear to be any way to locate a cert using the
email address in an altName, so we have to restrict ourselves
to the most commonly-used OID for certs in DNs */
pCertContext = \
pCertFindCertificateInStore( hCertStore,
X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_ATTR,
&certRDN, NULL );
break;
case CRYPT_IKEYID_KEYID:
/* There doesn't appear to be any way to locate a cert using a
subjectKeyIdentifier */
break;
case CRYPT_IKEYID_CERTID:
pCertContext = \
pCertFindCertificateInStore( hCertStore,
X509_ASN_ENCODING, 0, CERT_FIND_SHA1_HASH,
&cryptDataBlob, NULL );
break;
case CRYPT_IKEYID_ISSUERANDSERIALNUMBER:
pCertContext = \
pCertGetSubjectCertificateFromStore( hCertStore,
X509_ASN_ENCODING, &certInfo );
break;
default:
assert( NOTREACHED );
}
if( pCertContext != NULL )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
/* If we're just checking whether an object exists, return now. If
all we want is the key label, copy it back to the caller and
exit */
if( flags & KEYMGMT_FLAG_CHECK_ONLY )
{
pCertFreeCertificateContext( pCertContext );
return( CRYPT_OK );
}
if( flags & KEYMGMT_FLAG_LABEL_ONLY )
{
// status = getObjectLabel( deviceInfo, iCryptCert,
// auxInfo, auxInfoLength );
status = CRYPT_ERROR;
pCertFreeCertificateContext( pCertContext );
return( status );
}
/* Import the cert as a cryptlib object */
setMessageCreateObjectIndirectInfo( &createInfo,
pCertContext->pbCertEncoded,
pCertContext->cbCertEncoded,
CRYPT_CERTTYPE_CERTIFICATE );
createInfo.arg1 = CRYPT_CERTTYPE_CERTIFICATE;
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusOK( status ) )
*iCryptContext = createInfo.cryptHandle;
/* If there was a problem or we're only looking for a public key,
we're done */
if( cryptStatusError( status ) || \
itemType == KEYMGMT_ITEM_PUBLICKEY )
{
pCertFreeCertificateContext( pCertContext );
return( status );
}
}
else
/* If we're looking for a specific match on a certificate (rather
than just a general public key) and we don't find anything,
exit now */
if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )
return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
/* There were no certs found. At this point we can approach the problem
from one of two sides, if we've got a certHash or an
issuerAndSerialNumber we have to find the matching cert and get the
key from that, otherwise we find the key and get the cert from that */
if( keyIDtype == CRYPT_IKEYID_CERTID || \
keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )
{
// status = findObjectFromObject( deviceInfo, hCertificate,
// CKO_PRIVATE_KEY, &hObject );
if( cryptStatusError( status ) )
return( status );
/* Remember that we've got a cert to attach to the private key */
privateKeyViaCert = TRUE;
}
#if 0
else
{
const int keyTemplateCount = ( keyID == NULL ) ? 1 : 2;
/* Try and find the object with the given label/ID, or the first
object of the given class if no ID is given */
keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) \
( ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
&pubkeyClass : &privkeyClass );
if( keyIDtype != CRYPT_KEYID_NONE )
{
if( keyIDtype == CRYPT_IKEYID_KEYID )
keyTemplate[ 1 ].type = CKA_ID;
keyTemplate[ 1 ].pValue = ( CK_VOID_PTR ) keyID;
keyTemplate[ 1 ].ulValueLen = keyIDlength;
}
cryptStatus = findObject( deviceInfo, &hObject, keyTemplate,
keyTemplateCount );
if( cryptStatus == CRYPT_ERROR_NOTFOUND && \
itemType == KEYMGMT_ITEM_PUBLICKEY )
{
/* Some devices may only contain private key objects with
associated certificates that can't be picked out of the other
cruft that's present without going via the private key, so if
we're looking for a public key and don't find one, we try
again for a private key whose sole function is to point to an
associated cert */
keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;
cryptStatus = findObject( deviceInfo, &hObject, keyTemplate,
keyTemplateCount );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
/* Remember that although we've got a private key object, we only
need it to find the associated cert and not finding an
associated cert is an error */
certViaPrivateKey = TRUE;
}
}
/* If we're looking for any kind of private key and we either have an
explicit cert.ID but couldn't find a cert for it or we don't have a
proper ID to search on and a generic search found more than one
matching object, chances are we're after a generic decrypt key. The
former only occurs in misconfigured or limited-memory tokens, the
latter only in rare tokens that store more than one private key,
typically one for signing and one for verification.
If either of these cases occur we try again looking specifically for
a decryption key. Even this doesn't always work, there's are some
>1-key tokens that mark a signing key as a decryption key so we still
get a CRYPT_ERROR_DUPLICATE error.
Finally, if we can't find a decryption key either, we look for an
unwrapping key. This may or may not work, depending on whether we
have a decryption key marked as valid for unwrapping but not
decryption, or a key that's genuinely only valid for unwrapping, but
at this point we're ready to try anything */
if( itemType == KEYMGMT_ITEM_PRIVATEKEY && \
( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER && \
cryptStatus == CRYPT_ERROR_NOTFOUND ) || \
( cryptStatus == CRYPT_ERROR_DUPLICATE ) )
{
static const CK_BBOOL bTrue = TRUE;
CK_ATTRIBUTE decryptKeyTemplate[] = {
{ CKA_CLASS, ( CK_VOID_PTR ) &privkeyClass, sizeof( CK_OBJECT_CLASS ) },
{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) }
};
cryptStatus = findObject( deviceInfo, &hObject,
decryptKeyTemplate, 2 );
if( cryptStatusError( cryptStatus ) )
{
decryptKeyTemplate[ 1 ].type = CKA_UNWRAP;
cryptStatus = findObject( deviceInfo, &hObject,
decryptKeyTemplate, 2 );
}
}
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
/* If we're just checking whether an object exists, return now. If all
we want is the key label, copy it back to the caller and exit */
if( flags & KEYMGMT_FLAG_CHECK_ONLY )
return( CRYPT_OK );
if( flags & KEYMGMT_FLAG_LABEL_ONLY )
return( getObjectLabel( deviceInfo, hObject, auxInfo,
auxInfoLength ) );
/* We found something, map the key type to a cryptlib algorithm ID,
determine the key size, and find its capabilities */
keyTypeTemplate.pValue = &keyType;
C_GetAttributeValue( cryptoapiInfo->hProv, hObject,
&keyTypeTemplate, 1 );
switch( ( int ) keyType )
{
case CKK_RSA:
cryptAlgo = CRYPT_ALGO_RSA;
keySizeTemplate.type = CKA_MODULUS;
break;
case CKK_DSA:
cryptAlgo = CRYPT_ALGO_DSA;
keySizeTemplate.type = CKA_PRIME;
break;
case CKK_DH:
cryptAlgo = CRYPT_ALGO_DH;
keySizeTemplate.type = CKA_PRIME;
break;
default:
return( CRYPT_ERROR_NOTAVAIL );
}
C_GetAttributeValue( cryptoapiInfo->hProv, hObject,
&keySizeTemplate, 1 );
keySize = keySizeTemplate.ulValueLen;
capabilityInfoPtr = findCapabilityInfo( deviceInfo->capabilityInfo,
cryptAlgo );
if( capabilityInfoPtr == NULL )
return( CRYPT_ERROR_NOTAVAIL );
/* Try and find a certificate which matches the key. The process is as
follows:
if cert object found in issuerAndSerialNumber search
create native data-only cert object
attach cert object to key
else
if public key
if cert
create native cert (+context) object
else
create device pubkey object, mark as "key loaded"
else
create device privkey object, mark as "key loaded"
if cert
create native data-only cert object
attach cert object to key
The reason for doing things this way is given in the comments earlier
on in this function */
if( privateKeyViaCert )
{
/* We've already got the cert object handle, instantiate a native
data-only cert from it */
cryptStatus = instantiateCert( deviceInfo, hCertificate,
&iCryptCert, FALSE );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -