From 014f22be6a744dd3d116476d95009dd654333311 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Fri, 11 May 2007 22:35:00 +0000 Subject: Do proper usage vs. enhanced usage. --- ckcapi-builtin.c | 4 +- ckcapi-cert.c | 10 ++-- ckcapi-trust.c | 162 +++++++++++++++++++++++++++++++++++++++++++------------ ckcapi.h | 2 + 4 files changed, 137 insertions(+), 41 deletions(-) diff --git a/ckcapi-builtin.c b/ckcapi-builtin.c index 26e9cd9..58a02d8 100644 --- a/ckcapi-builtin.c +++ b/ckcapi-builtin.c @@ -230,9 +230,9 @@ ckcapi_builtin_find(CkCapiSession* sess, CK_OBJECT_CLASS cls, CK_ATTRIBUTE_PTR m { /* Only apply built in objects to appropriate slots */ fl = ckcapi_token_get_flags(sess->slot) & all_builtins[i].slot_flags; - if(fl != all_builtins[i].slot_flags) + /* if(fl != all_builtins[i].slot_flags) continue; - + */ bdata.attr = all_builtins[i].attr; bdata.base.object = 0; bdata.base.data_funcs = &builtin_objdata_vtable; diff --git a/ckcapi-cert.c b/ckcapi-cert.c index 15ab880..9937486 100644 --- a/ckcapi-cert.c +++ b/ckcapi-cert.c @@ -29,8 +29,6 @@ #define CERT_KEY_IDENTIFIER_PROP_ID 20 #endif -#define USE_ENCODINGS (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) - typedef struct _CertObject { CkCapiObject obj; @@ -244,7 +242,7 @@ cert_load_data(CkCapiSession* sess, CkCapiObject* obj, CkCapiObjectData** objdat memcpy(&info.SerialNumber, &cobj->serial, sizeof(info.SerialNumber)); memcpy(&info.Issuer, &cobj->issuer, sizeof(info.Issuer)); - cert = CertGetSubjectCertificateFromStore(sess->store, USE_ENCODINGS, &info); + cert = CertGetSubjectCertificateFromStore(sess->store, CKCAPI_ENCODINGS, &info); if(!cert) { @@ -572,7 +570,7 @@ match_in_store(CkCapiSession* sess, PCERT_INFO info, CK_ATTRIBUTE_PTR match, if(!sess->store) return CKR_OK; - cert = CertGetSubjectCertificateFromStore(sess->store, USE_ENCODINGS, info); + cert = CertGetSubjectCertificateFromStore(sess->store, CKCAPI_ENCODINGS, info); if(cert == NULL) { err = GetLastError(); @@ -642,14 +640,14 @@ ckcapi_cert_find(CkCapiSession* sess, CK_OBJECT_CLASS cls, CK_ATTRIBUTE_PTR matc } else if(!serial && match[i].type == CKA_SERIAL_NUMBER) { - if(!CryptDecodeObject(USE_ENCODINGS, X509_MULTI_BYTE_INTEGER, + if(!CryptDecodeObject(CKCAPI_ENCODINGS, X509_MULTI_BYTE_INTEGER, match[i].pValue, match[i].ulValueLen, 0, NULL, &size)) { continue; } serial = calloc(1, size); - if(!CryptDecodeObject(USE_ENCODINGS, X509_MULTI_BYTE_INTEGER, + if(!CryptDecodeObject(CKCAPI_ENCODINGS, X509_MULTI_BYTE_INTEGER, match[i].pValue, match[i].ulValueLen, 0, serial, &size)) continue; diff --git a/ckcapi-trust.c b/ckcapi-trust.c index 327f385..16e3874 100644 --- a/ckcapi-trust.c +++ b/ckcapi-trust.c @@ -54,29 +54,42 @@ typedef struct _TrustObjectData CkCapiObjectData base; PCCERT_CONTEXT cert; - CERT_ENHKEY_USAGE* usage; + CERT_ENHKEY_USAGE* enhanced_usage; + + BOOL has_usage; + BYTE usage; } TrustObjectData; -static CK_ULONG -has_usage(TrustObjectData* tdata, const char* oid) +static CK_TRUST +has_usage(TrustObjectData* tdata, BYTE restriction) +{ + if(!tdata->has_usage) + CKT_NETSCAPE_TRUST_UNKNOWN; + if((tdata->usage & restriction) == restriction) + return CKT_NETSCAPE_TRUSTED; + return CKT_NETSCAPE_UNTRUSTED; + +} + +static CK_TRUST +has_enhanced_usage(TrustObjectData* tdata, const char* oid) { - CERT_ENHKEY_USAGE* usage = tdata->usage; + CERT_ENHKEY_USAGE* eusage = tdata->enhanced_usage; DWORD i; /* No usages, means anything goes */ - if(usage == NULL) + if(eusage == NULL) return CKT_NETSCAPE_TRUSTED_DELEGATOR; - for(i = 0; i < usage->cUsageIdentifier; ++i) + for(i = 0; i < eusage->cUsageIdentifier; ++i) { - if(usage->rgpszUsageIdentifier[i] && - strcmp(oid, usage->rgpszUsageIdentifier[i]) == 0) + if(eusage->rgpszUsageIdentifier[i] && + strcmp(oid, eusage->rgpszUsageIdentifier[i]) == 0) return CKT_NETSCAPE_TRUSTED_DELEGATOR; } - /* TODO: What's the correct thing to return here? */ - return CKT_NETSCAPE_VALID_DELEGATOR; + return CKT_NETSCAPE_TRUST_UNKNOWN; } static CK_RV @@ -107,10 +120,9 @@ trust_bool_attribute(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr) /* * If object can be modified. - * TODO: This needs to be set to yes once we get change support. */ case CKA_MODIFIABLE: - val = CK_FALSE; + val = CK_TRUE; break; /* @@ -147,32 +159,57 @@ trust_ulong_attribute(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr) val = CKO_NETSCAPE_TRUST; break; + /* + * Key restrictions + */ + case CKA_TRUST_DIGITAL_SIGNATURE: + val = has_usage(tdata, CERT_DIGITAL_SIGNATURE_KEY_USAGE); + break; + case CKA_TRUST_NON_REPUDIATION: + val = has_usage(tdata, CERT_NON_REPUDIATION_KEY_USAGE); + break; + case CKA_TRUST_KEY_ENCIPHERMENT: + val = has_usage(tdata, CERT_KEY_ENCIPHERMENT_KEY_USAGE); + break; + case CKA_TRUST_DATA_ENCIPHERMENT: + val = has_usage(tdata, CERT_DATA_ENCIPHERMENT_KEY_USAGE); + break; + case CKA_TRUST_KEY_AGREEMENT: + val = has_usage(tdata, CERT_KEY_AGREEMENT_KEY_USAGE); + break; + case CKA_TRUST_KEY_CERT_SIGN: + val = has_usage(tdata, CERT_KEY_CERT_SIGN_KEY_USAGE); + break; + case CKA_TRUST_CRL_SIGN: + val = has_usage(tdata, CERT_CRL_SIGN_KEY_USAGE); + break; + /* * Various trust flags */ case CKA_TRUST_SERVER_AUTH: - val = has_usage(tdata, X509_USAGE_SERVER_AUTH); + val = has_enhanced_usage(tdata, X509_USAGE_SERVER_AUTH); break; case CKA_TRUST_CLIENT_AUTH: - val = has_usage(tdata, X509_USAGE_CLIENT_AUTH); + val = has_enhanced_usage(tdata, X509_USAGE_CLIENT_AUTH); break; case CKA_TRUST_CODE_SIGNING: - val = has_usage(tdata, X509_USAGE_CODE_SIGNING); + val = has_enhanced_usage(tdata, X509_USAGE_CODE_SIGNING); break; case CKA_TRUST_EMAIL_PROTECTION: - val = has_usage(tdata, X509_USAGE_EMAIL); + val = has_enhanced_usage(tdata, X509_USAGE_EMAIL); break; case CKA_TRUST_IPSEC_END_SYSTEM: - val = has_usage(tdata, X509_USAGE_IPSEC_ENDPOINT); + val = has_enhanced_usage(tdata, X509_USAGE_IPSEC_ENDPOINT); break; case CKA_TRUST_IPSEC_TUNNEL: - val = has_usage(tdata, X509_USAGE_IPSEC_TUNNEL); + val = has_enhanced_usage(tdata, X509_USAGE_IPSEC_TUNNEL); break; case CKA_TRUST_IPSEC_USER: - val = has_usage(tdata, X509_USAGE_IPSEC_USER); + val = has_enhanced_usage(tdata, X509_USAGE_IPSEC_USER); break; case CKA_TRUST_TIME_STAMPING: - val = has_usage(tdata, X509_USAGE_TIME_STAMPING); + val = has_enhanced_usage(tdata, X509_USAGE_TIME_STAMPING); break; default: @@ -233,8 +270,8 @@ trust_release(void* data) ASSERT(tdata->cert); CertFreeCertificateContext(tdata->cert); - if(tdata->usage) - free(tdata->usage); + if(tdata->enhanced_usage) + free(tdata->enhanced_usage); free(tdata); } @@ -251,27 +288,27 @@ static CK_RV parse_usage(TrustObjectData* tdata, DWORD flags) { DWORD size, err; - CERT_ENHKEY_USAGE* usage; + CERT_ENHKEY_USAGE* eusage; - ASSERT(!tdata->usage); + ASSERT(!tdata->enhanced_usage); - /* Get the size of the usage */ + /* Get the size of the enhanced_usage */ if(!CertGetEnhancedKeyUsage(tdata->cert, flags, NULL, &size)) { err = GetLastError(); - /* No usage data is not an error */ + /* No enhanced_usage data is not an error */ if(err == CRYPT_E_NOT_FOUND) return CKR_OK; return ckcapi_winerr_to_ckr(err); } - usage = (CERT_ENHKEY_USAGE*)calloc(1, size); - if(!usage) + eusage = (CERT_ENHKEY_USAGE*)calloc(1, size); + if(!eusage) return CKR_HOST_MEMORY; - /* Now get the actual usage property */ - if(!CertGetEnhancedKeyUsage(tdata->cert, flags, usage, &size)) + /* Now get the actual enhanced usage property */ + if(!CertGetEnhancedKeyUsage(tdata->cert, flags, eusage, &size)) { err = GetLastError(); if(err == CRYPT_E_NOT_FOUND) @@ -279,7 +316,58 @@ parse_usage(TrustObjectData* tdata, DWORD flags) return ckcapi_winerr_to_ckr(err); } - tdata->usage = usage; + tdata->enhanced_usage = eusage; + return CKR_OK; +} + +static CK_RV +parse_restrictions(TrustObjectData* tdata) +{ + CRYPT_BIT_BLOB* rst; + CERT_EXTENSION* ext; + DWORD size; + + ASSERT(tdata); + ASSERT(tdata->cert); + + tdata->has_usage = CK_FALSE; + tdata->usage = 0x00; + + ext = CertFindExtension(szOID_KEY_USAGE, + tdata->cert->pCertInfo->cExtension, + tdata->cert->pCertInfo->rgExtension); + + /* No key usage, don't care */ + if(!ext) + return CKR_OK; + + /* Find the size of the decoded structure */ + if(!CryptDecodeObject(CKCAPI_ENCODINGS, X509_KEY_USAGE, + ext->Value.pbData, ext->Value.cbData, 0, NULL, &size)) + return ckcapi_winerr_to_ckr(GetLastError()); + + /* Allocate enough memory */ + rst = (CRYPT_BIT_BLOB*)calloc(size, 1); + if(!rst) + return CKR_HOST_MEMORY; + + /* And get the decoded structure */ + if(CryptDecodeObject(CKCAPI_ENCODINGS, X509_KEY_USAGE, + ext->Value.pbData, ext->Value.cbData, 0, rst, &size)) + { + if(rst->cbData != 1 && + rst->cUnusedBits != 0) + { + DBG(("key usage are of invalid size")); + } + else + { + /* A valid byte of key restricted usage flags. Yes all that for one byte */ + tdata->usage = *((BYTE*)(rst->pbData)); + tdata->has_usage = TRUE; + } + } + return CKR_OK; } @@ -306,9 +394,17 @@ trust_load_data(CkCapiSession* sess, CkCapiObject* obj, CkCapiObjectData** objda tdata->cert = ckcapi_cert_object_data_get_certificate (certdata); ASSERT(tdata->cert); - /* Dig up the usage data property, and then try the extension */ + /* Dig up the restrictions data extension */ + ret = parse_restrictions(tdata); + if(ret != CKR_OK) + { + free(tdata); + return ret; + } + + /* Dig up the enhanced usage data property, and then try the extension */ ret = parse_usage(tdata, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG); - if(ret == CKR_OK && !tdata->usage) + if(ret == CKR_OK && !tdata->enhanced_usage) ret = parse_usage(tdata, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG); if(ret != CKR_OK) diff --git a/ckcapi.h b/ckcapi.h index 4ccd1cb..b2f1893 100644 --- a/ckcapi.h +++ b/ckcapi.h @@ -43,6 +43,8 @@ #include #include +#define CKCAPI_ENCODINGS (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) + #define CRYPTOKI_EXPORTS #include "pkcs11/pkcs11.h" -- cgit v1.2.3