📄 ms_capi.c
字号:
status = createPrivkeyContext( deviceInfo, iCryptContext,
&cryptAlgo, hKey, label );
if( cryptStatusError( status ) )
{
if( pCertContext != NULL )
pCertFreeCertificateContext( pCertContext );
return( status );
}
}
/* If there's no certificate available for the key, we're done */
if( pCertContext == NULL )
return( CRYPT_OK );
/* We've got a key and cert, try and get the rest of the chain for the
cert */
{
BOOLEAN publicComponentsOnly = FALSE;
status = iCryptImportCertIndirect( &iCryptCert,
deviceInfo->objectHandle, keyIDtype, keyID,
keyIDlength, publicComponentsOnly ? \
KEYMGMT_FLAG_NONE : \
KEYMGMT_FLAG_DATAONLY_CERT );
}
if( cryptStatusOK( status ) )
{
/* If we're getting a public key, the returned info is the cert
chain */
if( itemType == KEYMGMT_ITEM_PUBLICKEY )
*iCryptContext = iCryptCert;
else
{
/* If we're getting a private key, attach the cert chain to the
context. The cert is an internal object used only by the
context so we tell the kernel to mark it as owned by the
context only */
status = krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,
&iCryptCert, SETDEP_OPTION_NOINCREF );
}
}
/* Clean up */
pCertFreeCertificateContext( pCertContext );
pCertFreeCertificateChain( pChainContext );
return( status );
#if 0
{
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 );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
certPresent = TRUE;
}
else
{
cryptStatus = findCertFromObject( deviceInfo, hObject, &iCryptCert,
( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
FINDCERT_NORMAL : FINDCERT_DATAONLY );
if( cryptStatusError( cryptStatus ) )
{
/* If we get a CRYPT_ERROR_NOTFOUND this is OK since it means
there's no cert present, however anything else is an error. In
addition if we've got a private key whose only function is to
point to an associated cert then not finding anything is also
an error */
if( cryptStatus != CRYPT_ERROR_NOTFOUND || certViaPrivateKey )
return( cryptStatus );
}
else
{
/* We got the cert, if we're being asked for a public key then
we've created a native object to contain it so we return that */
certPresent = TRUE;
if( itemType == KEYMGMT_ITEM_PUBLICKEY )
{
*iCryptContext = iCryptCert;
return( CRYPT_OK );
}
}
}
#endif
}
/* Update a device with a certificate */
static int setItemFunction( DEVICE_INFO *deviceInfo,
const CRYPT_HANDLE iCryptHandle )
{
CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
HCRYPTKEY hKey;
DWORD dwKeySpec = 0;
CRYPT_CERTIFICATE iCryptCert;
BOOLEAN seenNonDuplicate = FALSE;
int status;
/* Lock the cert for our exclusive use (in case it's a cert chain, we
also select the first cert in the chain), update the device with the
cert, and unlock it to allow others access */
krnlSendMessage( iCryptHandle, IMESSAGE_GETDEPENDENT, &iCryptCert,
OBJECT_TYPE_CERTIFICATE );
krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORFIRST,
CRYPT_CERTINFO_CURRENT_CERTIFICATE );
status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );
if( cryptStatusError( status ) )
return( status );
/* Check whether the leaf cert matches any of the user's private keys */
if( pCryptGetUserKey( cryptoapiInfo->hProv, AT_KEYEXCHANGE, &hKey ) )
{
if( isCertKey( cryptoapiInfo, hKey, iCryptCert ) )
dwKeySpec = AT_KEYEXCHANGE;
pCryptDestroyKey( hKey );
}
else
if( pCryptGetUserKey( cryptoapiInfo->hProv, AT_SIGNATURE, &hKey ) )
{
if( isCertKey( cryptoapiInfo, hKey, iCryptCert ) )
dwKeySpec = AT_SIGNATURE;
pCryptDestroyKey( hKey );
}
/* Add each cert in the chain to the store */
do
{
DYNBUF certDB;
BOOL result;
/* Get the certificate data and add it to the store */
status = dynCreate( &certDB, iCryptHandle,
CRYPT_CERTFORMAT_CERTIFICATE );
if( cryptStatusError( status ) )
return( status );
/* If the cert corresponds to one of the user's private keys and
a binding between the key and a cert isn't already established,
establish one now */
if( dwKeySpec != 0 )
{
PCCERT_CONTEXT pCertContext;
CERT_KEY_CONTEXT certKeyContext;
DWORD certKeyContextSize = sizeof( CERT_KEY_CONTEXT );
/* Check whether the cert is already bound to a key and if not,
bind it to the appropriate private key */
pCertContext = pCertCreateCertificateContext( X509_ASN_ENCODING,
dynData( certDB ), dynLength( certDB ) );
if( pCertContext != NULL && \
!pCertGetCertificateContextProperty( pCertContext,
CERT_KEY_CONTEXT_PROP_ID,
&certKeyContext, &certKeyContextSize ) )
{
#if 1
/* Cert the cert stores synchronising the cert's
CERT_KEY_PROV_INFO_PROP_ID with any present private keys
if required */
pCryptFindCertificateKeyProvInfo( pCertContext, 0, NULL );
#elif 0
CRYPT_KEY_PROV_INFO keyProvInfo;
BYTE buffer[ 256 + 8 ];
DWORD length = 256;
wchar_t provName[ 256 + 8 ], container[ 256 + 8 ];
if( pCryptGetProvParam( cryptoapiInfo->hProv, PP_NAME,
buffer, &length, 0 ) )
MultiByteToWideChar( GetACP(), 0, buffer, length + 1,
provName, 256 );
if( pCryptGetProvParam( cryptoapiInfo->hProv, PP_CONTAINER,
buffer, &length, 0 ) )
MultiByteToWideChar( GetACP(), 0, buffer, length + 1,
container, 256 );
memset( &keyProvInfo, 0, sizeof( CRYPT_KEY_PROV_INFO ) );
keyProvInfo.pwszContainerName = container;
keyProvInfo.pwszProvName = provName;
keyProvInfo.dwProvType = PROV_RSA_FULL;
keyProvInfo.cProvParam = 0;
keyProvInfo.dwKeySpec = dwKeySpec;
pCertSetCertificateContextProperty( pCertContext,
CERT_KEY_PROV_HANDLE_PROP_ID, 0,
&keyProvInfo );
#elif 0
memset( &certKeyContext, 0, sizeof( CERT_KEY_CONTEXT ) );
certKeyContext.cbSize = sizeof( CERT_KEY_CONTEXT );
certKeyContext.dwKeySpec = dwKeySpec;
certKeyContext.hCryptProv = cryptoapiInfo->hProv;
pCertSetCertificateContextProperty( pCertContext,
CERT_KEY_CONTEXT_PROP_ID, 0,
&certKeyContext );
#endif
}
/* Add the cert to the store */
if( pCertContext != NULL )
{
result = pCertAddCertificateContextToStore( cryptoapiInfo->hCertStore,
pCertContext, CERT_STORE_ADD_NEW, NULL );
pCertFreeCertificateContext( pCertContext );
}
/* We've now added a bound cert, don't bind the key to any more
certs */
dwKeySpec = 0;
}
else
/* Add the cert to the store */
result = pCertAddEncodedCertificateToStore( cryptoapiInfo->hCertStore,
X509_ASN_ENCODING, dynData( certDB ),
dynLength( certDB ), CER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -