CardSpace Certificate Chain Validation Issue with Intermediate Certificates

One problem with the original version of CardSpace was that it seemed to reject some legitimate SSL sites, but like all tricky bugs, it didn’t happen consistently enough to be caught in the first release. What was going on was that sometimes CardSpace couldn’t validate the intermediate certificates in the certificate chain because of a disconnect with the browser’s certificate store.

If intermediate certificates aren’t installed on a user’s computer, most browsers use the certificate obtained from the site to reconstruct the whole chain and show the user they are at an SSL site. CardSpace, as it turns out, was not able to get the missing certificates.

Since, this bug could make a legitimate site appear to be fraudulent in CardSpace and because the behavior is intermittent, it might be missed by a web developer adding support for Information Cards to their site.

We asked the IE team and the maintainers of the browser add-on for Firefox to enable CardSpace to retrieve the correct certificate, and they did. The update to IE was included in the October 2007 IE Security Update and the updated Firefox add-on can be downloaded here (thanks Axel!). Implementers of other Identity Selectors should consider whether this issue is present in their code as well. I’ll hand off now to Shan to explain more details about the problem and the fix.

Rob Franco
Lead Program Manager

CardSpace

========

Introduction – How the recipient certificate & its intermediates are retrieved by the browser

When a client navigates to a (https) site in a browser, there is a SSL handshake by the browser with the site. This handshake involves the client receiving the

  • certificate of the site, and
  • any intermediate certificates, if any, that are part of the recipient certificate’s issuer chain.

The intermediate certificates (if any) are necessary to build the certificate chain to a trusted root CA for purposes of certificate validation.

Note that CardSpace does an independent validation of the recipient certificate, in addition to the browser.

Why CardSpace certificate validation in .NET 3.0 would fail when intermediate certificates are not present on the client machine

When CardSpace was being invoked by the browser, the intermediate certificates received during the browser SSL handshake were not passed to CardSpace. Only the leaf certificate was passed in. Since the intermediate certificates were not passed in (and CardSpace did not have a mechanism to receive them), the only way for the chain to be built (and validated) successfully by CardSpace was if the intermediates were already present in the local Intermediate certificate store.

Therefore, when intermediate certificates were NOT present on the client machine, CardSpace validation of the recipient certificate would fail even though the site actually chained up to a trusted CA (and showed up fine within the browser).

A possible workaround for this issue

A potential workaround for this problem is to have relying parties certificates utilize the Authority Information Access (AIA) extension (with accesMethod=cAIssuers). This extension, added by CAs in the issued certificates, allows certificate verifiers to retrieve the issuing certificates when intermediate certificates are not present in the verification environment.

However, it may not be judicious to overly depend on the AIA infrastructure as a workaround for this issue. This is because CAs may not choose to include this extension. In addition, it is often unreliable, especially with enterprise CAs. For example, the URL specified in the AIA extension might be invalid or unreachable.

How have we fixed this issue in the .NET Framework 3.0 SP1 version of CardSpace

The CardSpace team has made a fix in the .NET Framework 3.0 SP1 (which ships as part of .NET 3.5) to address this issue. This change enables the Internet Explorer module (or other browser add-ons) to pass the intermediate certificates that were retrieved during the SSL handshake into CardSpace. These intermediate certificates are then used by CardSpace for chain building and validation. 

To accomplish this fix, we have added a new version of the recipient-policy struct, namely RECIPIENTPOLICY2 to the updated version of CardSpace API “GetBrowserToken”. The old version of the struct, RECIPIENTPOLICY, which only passes the leaf certificate information, should be considered deprecated.

At the same time, the Internet Explorer (IE) module that communicates with CardSpace to pass certificate information from the browser to CardSpace has been updated to provide the complete certificate chain to CardSpace. This update comes in the October 2007 IE Security Update.

Other Information Card browser add-ons written to invoke CardSpace should also be updated to take advantage of this fix.

Some notes for sites using CardSpace

If you are using CardSpace, you do not have to worry about this issue, assuming your clients will be running the .NET Framework 3.5 AND have the latest IE updates (if they are running IE) or have a version of the Firefox add-on that takes advantage of the fix.

You can check for the right version of CardSpace by checking the user agent string for the following token:

Updated CardSpace (.Net 3.5) = .NET CLR 3.5.21022”

Details of the fix for browser add-on developers written to invoke CardSpace

(If you are simply a site using CardSpace, then the below section on how to invoke the GetBrowserToken API with the new structures does NOT apply to you)
As mentioned previously, we have added a new version of the recipient-policy struct, namely RECIPIENTPOLICY2 to the updated version of CardSpace API “GetBrowserToken”:

HRESULT

CARDSPACECALL GetBrowserToken(

__in DWORD dwParamType,

__in PVOID pParam,

__out_opt DWORD* pcbToken,

__out_bcount_opt(*pcbToken) PBYTE* ppToken );

This function is currently documented in MSDN: https://msdn2.microsoft.com/en-us/library/aa702769.aspx ) though it has not yet been updated with the .NET 3.5 changes.

To utilize the intermediate certificate fix in .NET 3.5, i.e. to invoke CardSpace passing in the intermediate certificates of the recipient, you would invoke the API in this following way:

  • dwParamType should be set to value RECIPIENTPOLICYV2 (which is really value 2)
  • pParam should point to a RECIPIENTPOLICY2 structure (see below)
    • For the ENDPOINTADDRESS2,
      • DWORD identityType should be set to 2
      • PVOID identityBytes should be set to a CERTIFICATE_CHAIN_BLOB
        • DATA_BLOB rawCertificates should contain (see struct definition from wincrypt.h below)
          • Count of certificates
          • Bytes of each certificate of the certificate chain retrieved by invoking CertSerializeCertificateStoreElement (which retrieves the bytes of each certificate in the chain in DER encoded form)
          • Note that the recipient certificate is assumed to be the 0th (zeroth) element of this array, followed by its issuer at index 1 (one) etc., followed by the issuer of the issuer at index 2 (two) and so on.

When invoking CardSpace in the no-SSL case, the identityBytes pointer in the ENDPOINTADDRESS2 structure should be NULL.

typedef struct _RECIPIENTPOLICY2

{

ENDPOINTADDRESS2 recipient;

ENDPOINTADDRESS2 issuer;

LPCWSTR tokenType;

CLAIMLIST requiredClaims;

CLAIMLIST optionalClaims;

LPCWSTR privacyUrl;

UINT privacyVersion;

}RECIPIENTPOLICY2, *PRECIPIENTPOLICY2;

typedef struct _ENDPOINTADDRESS2

{

LPCWSTR serviceUrl;

LPCWSTR policyUrl;

DWORD identityType;

PVOID identityBytes;

}ENDPOINTADDRESS2, *PENDPOINTADDRESS2;

typedef struct _CERTIFICATE_CHAIN_BLOB

{

DWORD certCount;

DATA_BLOB* rawCertificates;

}CERTIFICATE_CHAIN_BLOB, *PCERTIFICATE_CHAIN_BLOB;

typedef struct _CRYPTOAPI_BLOB {

DWORD cbData;

BYTE *pbData;

} DATA_BLOB, *PDATA_BLOB,

NOTE: If your clients do not have the have the updated (.NET 3.5) CardSpace bits, then calling the "GetBrowserToken" API with the new RECIPENTPOLICY2 struct would yield E_INVALIDARG for HRESULT. Therefore if you are a browser add-on developer and do not intend to break .NET 3.0 clients then you would check whether .NET 3.5 is installed before invoking the API with the new RECIPENTPOLICY2 struct.

You can do this by checking for the presence of this key:

[HKEY_LOCAL_MACHINE\Software\ Microsoft\NET Framework Setup\NDP\v3.5]

"Install"=dword:00000001"

If the key does not exist then you would resort to using the original RECIPENTPOLICY struct.

---------------------------------------------------------------------------------------------------------------

We hope this fix helps you keep CardSpace running problem free with your sites!

Sudarshan [Shan] Sundar

Software Development Engineer,

CardSpace Team