pkcs15: Expose the map_usage() function from CAC to other pkcs15 emulators

This commit is contained in:
Jakub Jelen 2019-08-12 14:02:24 +02:00
parent 5e1bfe0acc
commit 2882c93ec1
3 changed files with 90 additions and 84 deletions

View File

@ -84,89 +84,6 @@ static const char * cac_get_name(int type)
return ("CAC");
}
/*
* These could move to a helper file for other cards that wish to use usage as a way of getting flags
*/
/* Only certain usages are valid for a given algorithm, return all the usages that the algorithm supports so we
* can use it as a filter for all the public and private key usages */
static unsigned int
cac_alg_flags_from_algorithm(int algorithm)
{
switch (algorithm) {
case SC_ALGORITHM_RSA:
return SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP |
SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER |
SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP |
SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
case SC_ALGORITHM_DSA:
return SC_PKCS15_PRKEY_USAGE_VERIFY| SC_PKCS15_PRKEY_USAGE_SIGN |
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
#ifdef SC_ALGORITHM_DH
case SC_ALGORITHM_DH:
return SC_PKCS15_PRKEY_USAGE_DERIVE ;
#endif
case SC_ALGORITHM_EC:
return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY|
SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
case SC_ALGORITHM_GOSTR3410:
return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY|
SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
}
return 0;
}
/* These are the cert key usage bits that map to various PKCS #11 (and thus PKCS #15) flags */
#define CAC_X509_USAGE_SIGNATURE \
(SC_X509_DIGITAL_SIGNATURE | \
SC_X509_NON_REPUDIATION | \
SC_X509_KEY_CERT_SIGN | \
SC_X509_CRL_SIGN)
#define CAC_X509_USAGE_DERIVE \
SC_X509_KEY_AGREEMENT
#define CAC_X509_USAGE_UNWRAP \
(SC_X509_KEY_ENCIPHERMENT | \
SC_X509_KEY_AGREEMENT)
#define CAC_X509_USAGE_DECRYPT \
(SC_X509_DATA_ENCIPHERMENT | \
SC_X509_ENCIPHER_ONLY)
#define CAC_X509_USAGE_NONREPUDIATION \
SC_X509_NON_REPUDIATION
/* map a cert usage and algorithm to public and private key usages */
static int
cac_map_usage(unsigned int cert_usage, int algorithm, unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr, int allow_nonrepudiation)
{
unsigned int pub_usage = 0, pr_usage = 0;
unsigned int alg_flags = cac_alg_flags_from_algorithm(algorithm);
if (cert_usage & CAC_X509_USAGE_SIGNATURE) {
pub_usage |= SC_PKCS15_PRKEY_USAGE_VERIFY|SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER;
pr_usage |= SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER;
}
if (cert_usage & CAC_X509_USAGE_DERIVE) {
pub_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE;
pr_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE;
}
if (cert_usage & (CAC_X509_USAGE_DECRYPT|CAC_X509_USAGE_UNWRAP)) {
pub_usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT;
pr_usage |= SC_PKCS15_PRKEY_USAGE_DECRYPT;
}
if (allow_nonrepudiation && (cert_usage & CAC_X509_USAGE_NONREPUDIATION)) {
pub_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
pr_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
}
/* filter usages algorithm */
if (pub_usage_ptr) {
*pub_usage_ptr = pub_usage & alg_flags;
}
if (pr_usage_ptr) {
*pr_usage_ptr = pr_usage & alg_flags;
}
return SC_SUCCESS;
}
static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card)
{
static const pindata pins[] = {
@ -409,7 +326,7 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card)
if (r < 0) {
usage = 0xd9ULL; /* basic default usage */
}
cac_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1);
sc_pkcs15_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1);
sc_log(card->ctx, "cert %s: cert_usage=0x%x, pub_usage=0x%x priv_usage=0x%x\n",
sc_dump_hex(cert_info.id.value, cert_info.id.len),
usage, pubkey_info.usage, prkey_info.usage);

View File

@ -257,6 +257,8 @@ sc_pkcs15_get_extension(struct sc_context *ctx, struct sc_pkcs15_cert *cert,
{ NULL, 0, 0, 0, NULL, NULL }
};
LOG_FUNC_CALLED(ctx);
for (next_ext = cert->extensions, next_ext_len = cert->extensions_len; next_ext_len; ) {
/* unwrap the set and point to the next ava */
ext = sc_asn1_skip_tag(ctx, &next_ext, &next_ext_len,
@ -324,6 +326,8 @@ sc_pkcs15_get_bitstring_extension(struct sc_context *ctx,
{ NULL, 0, 0, 0, NULL, NULL }
};
LOG_FUNC_CALLED(ctx);
r = sc_pkcs15_get_extension(ctx, cert, type, &bit_string, &bit_string_len, is_critical);
LOG_TEST_RET(ctx, r, "Get extension error");
@ -550,6 +554,88 @@ sc_pkcs15_encode_cdf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj
return r;
}
/* Only certain usages are valid for a given algorithm, return all the usages
* that the algorithm supports so we can use it as a filter for all
* the public and private key usages
*/
static unsigned int
sc_pkcs15_alg_flags_from_algorithm(int algorithm)
{
switch (algorithm) {
case SC_ALGORITHM_RSA:
return SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP |
SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER |
SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP |
SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
case SC_ALGORITHM_DSA:
return SC_PKCS15_PRKEY_USAGE_VERIFY| SC_PKCS15_PRKEY_USAGE_SIGN |
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
#ifdef SC_ALGORITHM_DH
case SC_ALGORITHM_DH:
return SC_PKCS15_PRKEY_USAGE_DERIVE ;
#endif
case SC_ALGORITHM_EC:
return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY|
SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
case SC_ALGORITHM_GOSTR3410:
return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY|
SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
}
return 0;
}
/* These are the cert key usage bits that map to various PKCS #11 (and thus PKCS #15) flags */
#define SC_PKCS15_X509_USAGE_SIGNATURE \
(SC_X509_DIGITAL_SIGNATURE | \
SC_X509_NON_REPUDIATION | \
SC_X509_KEY_CERT_SIGN | \
SC_X509_CRL_SIGN)
#define SC_PKCS15_X509_USAGE_DERIVE \
SC_X509_KEY_AGREEMENT
#define SC_PKCS15_X509_USAGE_UNWRAP \
(SC_X509_KEY_ENCIPHERMENT | \
SC_X509_KEY_AGREEMENT)
#define SC_PKCS15_X509_USAGE_DECRYPT \
(SC_X509_DATA_ENCIPHERMENT | \
SC_X509_ENCIPHER_ONLY)
#define SC_PKCS15_X509_USAGE_NONREPUDIATION \
SC_X509_NON_REPUDIATION
/* map a cert usage and algorithm to public and private key usages */
int
sc_pkcs15_map_usage(unsigned int cert_usage, int algorithm,
unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr,
int allow_nonrepudiation)
{
unsigned int pub_usage = 0, pr_usage = 0;
unsigned int alg_flags = sc_pkcs15_alg_flags_from_algorithm(algorithm);
if (cert_usage & SC_PKCS15_X509_USAGE_SIGNATURE) {
pub_usage |= SC_PKCS15_PRKEY_USAGE_VERIFY|SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER;
pr_usage |= SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER;
}
if (cert_usage & SC_PKCS15_X509_USAGE_DERIVE) {
pub_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE;
pr_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE;
}
if (cert_usage & (SC_PKCS15_X509_USAGE_DECRYPT|SC_PKCS15_X509_USAGE_UNWRAP)) {
pub_usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT;
pr_usage |= SC_PKCS15_PRKEY_USAGE_DECRYPT;
}
if (allow_nonrepudiation && (cert_usage & SC_PKCS15_X509_USAGE_NONREPUDIATION)) {
pub_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
pr_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
}
/* filter usages algorithm */
if (pub_usage_ptr) {
*pub_usage_ptr = pub_usage & alg_flags;
}
if (pr_usage_ptr) {
*pr_usage_ptr = pr_usage & alg_flags;
}
return SC_SUCCESS;
}
void
sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert)

View File

@ -754,6 +754,9 @@ int sc_pkcs15_get_name_from_dn(struct sc_context *ctx,
const u8 *dn, size_t dn_len,
const struct sc_object_id *type,
u8 **name, size_t *name_len);
int sc_pkcs15_map_usage(unsigned int cert_usage, int algorithm,
unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr,
int allow_nonrepudiation);
int sc_pkcs15_get_extension(struct sc_context *ctx,
struct sc_pkcs15_cert *cert,
const struct sc_object_id *type,