The PKI Applet specifications that I have seen do not mention any restriction on using the PRIVATE SIGN/DECRYPT command other than verifying the PIN first. I'm assuming that a signing operation using the private key associated with the email encryption certificate will be permitted by the PKI applet, and I will try this out later to confirm, but can you tell me where are you seeing this enforcement?
I'm pretty sure I traced this to the CoolKey-CAC code. I have used other PKCS11 implementations where this was not enforced.
I don't understand your concern with CKA_LABEL and CKA_ID attributes. The PKCS#11 standard mentions that CKA_ID attribute is only meant to distinguish multiple key pairs held by the same subject, but what the CKA_ID value should be is not defined or enforced. It is suggested, for interoperability, that this value should be the subject key identifier, but in reality it can be any value. Generally you locate the certificate you want, get its CKA_ID value, then locate the private key with the same CKA_ID value.
The CKA_LABEL is simply a description of the object, and may in fact be empty. There is no further information in PKCS#11 about the value that should be found in CKA_LABEL.
Say an application wants to use one of the certificates on the CAC and specify which one on the command line or config file. Since the CKA_LABEL and CKA_ID are meaningless (across PKCS11 implementations), the only way to do this is to grab all certs, parse the X.509, and do the compare at that level. Lots of overhead for something that could be very straight forward if it were defined/standardized as a generic token interface.
PKCS#11 is that standard. But you must remeber that the token generally provides limited cryptographic support. Most tokens I have seen (Axalto, Gemplus, CAC, etc) will provide CKM_RSA_PKCS mechanism for signing and decrypting. CKM_SHA1_RSA_PKCS may be provided for signing, but that is generally not done in hardware. So either the PKCS#11 library provides the hashing algorithm, or this is left up to the application before calling PKCS#11.
There are no standard set of mechanisms or operations that must be provided on the token. The application needs to interrogate the token to see what mechanisms it supports so that it can determine how to perform its cryptographic operations. Typically openssl would be used, and a EVP_PKEY that delegates its RSA operations to PKCS#11 would be required.
But if you do not want to use openssl, then your application must at least know how to generate SHA1 digests to be interoperable with most tokens. SHA1 is not difficult. You also need to know how to generate DigestInfo encodings, but these are constant and are defined in PKCS#1.
As far as mechanisms go, it can take a few seconds to get a mechanism list from the card/PKSC11 lib. It's much faster for me to try to use CKM_SHA1_RSA_PKCS to sign something and fall back to creating the SHA1 hash myself (in OpenSSL) and use the card for CKM_RSA_PKCS. But if I try C_SignInit() with CKM_SHA1_RSA_PKCS, and the card does not support that mechanism, it should return an error, not a valid signature for the CKM_RSA_PKCS mechanism.
I guess I just need to admit that PKCS11 is not the generic token interface it was supposed to be, because most of the card vendors developed such card-specific APIs. I'm not a Windows developer, but I wonder if there are similar problems with various CSP vendors? Do you need to write your application to a vendor-specific CSP?
-Ken