Re: How to use ICEnroll4::addExtensionToRequest

From: David Cross [MS] (dcross_at_online.microsoft.com)
Date: 03/29/04


Date: Mon, 29 Mar 2004 05:44:02 -0800

Here is an example from an upcoming MSDN article that should help you:

Adding Subject Alternative Name Extension to Requests

In certain situations in order to support non-Microsoft CAs it may be
necessary to add extra extensions to a request. This example shows how to
add the Subject Alternative Name extension to a PKCS #10 request. The
Subject Alternative Name extension is used to store extra identifiers for a
subject including the User Principal Name (UPN) of the user which is used by
Windows for smartcard logon and the user email address (RFC 822 name).
Microsoft Certificate Services automatically populates this field for issued
certificates but other CAs may not do this and hence may need this value
passed to the CA in the enrollment request.

The following C++ code will create a Subject Alternative Extension for a
request.

The structure CERT_ALT_NAME_INFO is used to store the two names that are to
be added to the enrolment request (the email/rfc822 and the UPN).

The email name can be simply added to the array of Alt Names as shown below,

CERT_ALT_NAME_ENTRY AltNames[2];

CERT_ALT_NAME_INFO AltNameInfo = { 2, AltNames };

CRYPT_DATA_BLOB ExtBlob;

AltNames[0].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;

AltNames[0].pwszRfc822Name = (LPWSTR) L"jsmith@acmecorp.net";

The User Principal Name though, requires more effort to be added to the
request. The Name is first converted into an ASN.1 binary blob by calling
CryptEncodeObjectEx as shown below.

CERT_NAME_VALUE UPNName;

CERT_OTHER_NAME ASNupnName;

UPNName.dwValueType = CERT_RDN_UTF8_STRING;

UPNName.Value.pbData = (BYTE *) L"jsmith@acmecorp.net";

UPNName.Value.cbData = 0;

rOK = CryptEncodeObjectEx( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_UNICODE_NAME_VALUE,
&UPNName,
CRYPT_ENCODE_ALLOC_FLAG,
NULL,
&ASNupnName.Value.pbData,
&ASNupnName.Value.cbData );

AltNames[1].dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;

AltNames[1].pOtherName = &ASNupnName;

ASNupnName.pszObjId = szOID_NT_PRINCIPAL_NAME;

Finally an ASN.1 binary blob needs to be created of the Subject Alternative
Name, again by calling CryptEncodeObjectEx but with the structure type
defined as X509_ALTERNATE_NAME as shown below. This is then added to the
request by calling the method addExtensionToRequestWStr. Other extensions
can be added in a similar manner to requests.

rOK = CryptEncodeObjectEx(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_ALTERNATE_NAME,
&AltNameInfo,
CRYPT_ENCODE_ALLOC_FLAG,
NULL,
&ExtBlob.pbData,
&ExtBlob.cbData );

hr = CertEnroll->addExtensionToRequestWStr(TRUE,
CComBSTR(szOID_SUBJECT_ALT_NAME2), &ExtBlob);

If the request is dumped, the following extension can be seen in the
request,

2.5.29.17: Flags = 1(Critical), Length = 3c

    Subject Alternative Name

        RFC822 Name=jsmith@acmecorp.net

        Other Name:

             Principal Name=jsmith@acmecorp.net

The example code PKCS10AltSubName.cpp shows a complete example of the above
code for adding a Subject Alternative Name extension.

Adding DNS Name to Subject Alternative Name

This example shows how to add a DNS Name into the Subject Alternative Name
extension of a PKCS #10 request. Domain Controller Certificates require the
DNS name is to be included in the Subject Alternative Name.

CERT_ALT_NAME_ENTRY AltNames[1];

CERT_ALT_NAME_INFO AltNameInfo = { 1, AltNames };

CRYPT_DATA_BLOB ExtBlob;

AltNames[0].dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;

AltNames[0].pwszDNSName = (LPWSTR) L"rootdc.acmecorp.net";

Next an ASN blob needs to be created for the Subject Alternative Name, by
calling CryptEncodeObjectEx but with the structure type defined as
X509_ALTERNATE_NAME as shown below. This is then added to the request by
calling the method addExtensionToRequestWStr. Other extensions can be added
in a similar manner to requests.

rOK = CryptEncodeObjectEx(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_ALTERNATE_NAME,
&AltNameInfo,
CRYPT_ENCODE_ALLOC_FLAG,
NULL,
&ExtBlob.pbData,
&ExtBlob.cbData );

hr = CertEnroll->addExtensionToRequestWStr(TRUE,
CComBSTR(szOID_SUBJECT_ALT_NAME2), &ExtBlob);

If the request is dumped, the following extension can be seen in the
request,

2.5.29.17: Flags = 1(Critical), Length = 17

Subject Alternative Name

    DNS Name=rootdc.acmecorp.net

-- 
David B. Cross [MS]
--
This posting is provided "AS IS" with no warranties, and confers no rights.
http://support.microsoft.com
"Osk" <anonymous@discussions.microsoft.com> wrote in message
news:9540A894-357B-4E2A-A632-1D88CC62891B@microsoft.com...
> I want to add subject alternative name to a PKCS #10 certificate request.
> Following C codes are for adding subject alternative name(OID =
2.5.29.17).
>
> // --- Start
> CERT_ALT_NAME_ENTRY AltName;
> AltName.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
> AltName.pwszDNSName = (LPWSTR)L"xxx.yyy.local";
> CERT_ALT_NAME_INFO AltNameInfo = {1, &AltName};
> CRYPT_DATA_BLOB ExtBlob;
> ExtBlob.cbData = 0;
> BOOL bResult;
> bResult = CryptEncodeObjectEx(
>     X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
>     X509_ALTERNATE_NAME,
>     &AltNameInfo,
>     0,
>     NULL,
>     NULL,
>    &ExtBlob.cbData);
> if (!bResult)
>     exit(1);
> ExtBlob.pbData = (PBYTE)alloca(ExtBlob.cbData + 1);
> bResult = CryptEncodeObjectEx(
>     X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
>     X509_ALTERNATE_NAME,
>     &AltNameInfo,
>     CRYPT_ENCODE_ALLOC_FLAG,
>     NULL,
>     &ExtBlob.pbData,
>     &ExtBlob.cbData);
> if (!bResult)
>     exit(1);
>
> CHAR szTemp[1000];
> DWORD dwLength = 1000;
> bResult = CryptBinaryToString(
>     ExtBlob.pbData,
>     ExtBlob.cbData,
>     CRYPT_STRING_BASE64,
>     szTemp,
>     &dwLength);
> if (!bResult)
>     exit(1);
> USES_CONVERSION;
> BSTR bstrValue = SysAllocString(T2OLE((LPTSTR)szTemp));
> BSTR bstrName = SysAllocString(L"2.5.29.17");
> HRESULT hResult;
> // pCertEnroll is an ICEnroll4 object.
> hResult = pCertEnroll->addExtensionToRequest(TRUE, bstrName, bstrValue);
> if (hResult)
>     exit(1);
>
> // --- End
>
> And then calls ICEnroll4::createPKCS10(). createPKCS10() creates a PKCS
#10 certificate request. But the certificate request does not include
subject alternative name. Why doesn't it include subject alternative name?
>
>
> Even if calls addExtensionToRequest() with invalid parameter,
addExtensionToRequest returns success. For example;
>
> BSTR bstrName = SysAllocString(L"foo");
> BSTR bstrValue = SysAllocString(L"hoge");
> hResult = pCertEnroll->addExtensionToRequest(TRUE, bstrName, bstrValue);
>
> Why does addExtensionToRequest return success?
>
> Thanks in advance.
>
> Osk


Relevant Pages