summaryrefslogtreecommitdiff
path: root/ckcapi-trust.c
diff options
context:
space:
mode:
Diffstat (limited to 'ckcapi-trust.c')
-rw-r--r--ckcapi-trust.c162
1 files changed, 129 insertions, 33 deletions
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;
/*
@@ -148,31 +160,56 @@ trust_ulong_attribute(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr)
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)