Continuing my 2-post series about Certificate Policies certificate extension. In the first part we covered theoretical questions and common design scenarios. In this post I will show how you can add Certificate Policies extension in CA and end-entity certificates.

Certificate Policies extension in CA certificates

When installing Windows CA, either, via Server Manager UI, or PowerShell, there is no way to provide additional information to include in the CA certificate. To include this information, Windows supports a special CA configuration file named “CAPolicy.inf” which must be saved in the %systemroot% directory (usually, it is C:\Windows). CA installation code reads this file in two cases:

  1. During new CA installation;
  2. During existing CA certificate renewal.

CAPolicy.inf syntax is another story, so we will focus on our subject only. Main section in the INF file is [PolicyStatementExtension] and has the following syntax:

[PolicyStatementExtension]
Policies = Policy1, Policy2, ... PolicyN

[Policy1]
OID = 1.3.6.1.4.1.{PENnumber}.1.1
URL = http//www.company.com/rpa

[Policy2]
OID = 1.3.6.1.4.1.{PENnumber}.1.2
URL = https://www.company.com/policies/smartcardpol.aspx

<...>
[PolicyN]
OID = 1.3.6.1.4.1.{PENnumber}.1.3
URL = http://www.company.com/sec/pol/cps.aspx

remember, once policy is explicitly defined at 2nd level, all certificates below shall contain only valid policies. In other words, child CAs may define all or subset of policies defined in the 2nd level CA certificate. Certificates below cannot extend this list.

A single CA certificate may host multiple policies in the certificate policies extension. In the “Policies” key you specify a comma-separated list of policy names. These names are used by CA installation code and are not inserted in the certificate. So you can choose an arbitrary name for each policy. Policy name must not contain spaces or any non-alphanumerical value.

After that, you create INF sections where each section name matches policy identifier specified in the “Policies” key. Each policy section must consist of at least two keys:

  • OID – specifies the policy identifier. Must be specified only once per policy;
  • One or more combination of “URL” and/or “Notice” qualifiers, where:
    • URL key is CPS Pointer, or an url to a resource that contains particular policy description (CPS). You can specify multiple URLs where policy’s CPS is located;
    • Notice key is User Notice and its use is not recommended, so you should avoid it whenever possible.

“URL” qualifier is CPS Pointer, or an url to a resource that contains particular policy description (CPS). You can specify multiple URLs for single policy.

Certificate Policies extension in end-entity certificates

Depending on enrollment practice, there are three main approaches how to include certificate policies in end entity certificates.

Certreq.exe with INF syntax

When using INF-templated certreq.exe to create offline requests, you can use the same syntax as in the CAPolicy.inf file.

PowerShell with CertEnroll syntax

When using PowerShell and CertEnroll COM interfaces to create either, offline or online certificate request, the following code may be used:

# prepare policyID=policyQualifier
# instantiate X509ExtensionCertificatePolicies COM object:
$CertPoliciesExt = New-Object -ComObject X509Enrollment.CX509ExtensionCertificatePolicies
# prepare a policy collection
$Policies = New-Object -ComObject X509Enrollment.CCertificatePolicies
# the code below may be used in a loop when adding multiple policies
# prepare first policy object
$Policy = New-Object -ComObject X509Enrollment.CCertificatePolicy
# create policy identifier
$oid = New-Object -ComObject X509Enrollment.CObjectId
$oid.InitializeFromValue("1.3.6.1.4.1.99999.1.1")
# initialize policy from policy identifier
$Policy.Initialize($oid)
# instantiate policy qualifier
$Qualifier = New-Object -ComObject X509Enrollment.CPolicyQualifier
$Qualifier.InitializeEncode("http//www.company.com/rpa",1)
# and add this qualifier to certificate policy object
$Policy.PolicyQualifiers.Add($Qualifier)
# add policy to a policy collection
$Policies.Add($Policy)
# end of possible loop.
# initialize Certificate Policies extension from a collection of policies
$CertPoliciesExt.InitializeEncode($Policies)
# add certificate policies extension to your request object
$RequestObject.X509Extensions.Add($CertPoliciesExt)

The code looks a bit large for inline scripting, but it should be automated by using reusable functions and loop operators.

Certificate Templates GUI

In Active Directory environments and Enterprise CAs you can configure certificate policies on a certificate template basis. And all certificates issued based on that template will have a certificate policies extension. To configure certificate template to include certificate policies, the following steps should be used:

  1. Log on to computer where ADCS RSAT is installed with Enterprise Admins or delegated permissions;
  2. Open Certificate Templates MMC snap-in (certtmpl.msc);
  3. In the Certificate Templates snap-in, select desired certificate template and select its properties;
  4. In the certificate template editor dialog, switch to Extensions tab and select Issuance Policies extension;
  5. Press Add button to add policies to include;

Add Issuance Policies

At this point you will see certificate policy management dialog, where you can select one or more policies from a list. If there is no such policy, you can create a new one:

Create Issuance Policy

never use auto-generated policy identifier in production environments, because they are generated under Microsoft’s arc where you do not have permissions.

Phinal. HTH


Share this article:

Comments:

AndrePKI
AndrePKI 02.10.2016 23:35 (GMT+3) Certificate Policies extension – all you should know (part 2)

So you can create a policy from the Templates console like you show. (Or you could use 'certutil -oid "displayname"  <locale id> 2' (which clears the displayName BTW)).

But can you then actually issue certificates based on that template, when the issuing CA does not have this policy in its CA-certificate - I think not. You will get "invalid policy" errors in the CA's eventlog and the failed requests list. Either you have to renew the CA's certificate to include the new policy or set the flag to ignore invalid policies (the latter I do not recommend).

Vadims Podāns
Vadims Podāns 05.11.2016 23:36 (GMT+3) Certificate Policies extension – all you should know (part 2)

> But can you then actually issue certificates based on that template, when the issuing CA does not have this policy in its CA-certificate - I think not

correct, you cannot. Once policy identifier disappears from CA certificate it becomes invalid at n + 1 level.

> or set the flag to ignore invalid policies (the latter I do not recommend).

yes, this flag makes very little sense. Although, CA will be able to issue the certificate, but any policy validation by client will fail in any way.

PKIcurious
PKIcurious 09.07.2018 03:37 (GMT+3) Certificate Policies extension – all you should know (part 2)

Hi Vadims

 

Long time fan.   but anyhoo.   I have a two-tier PKI setup in my lab I have a IANA assigned PEN for my business and have it added to my two tier PKI at the issuing CA level via the capolicy.inf as stated.   Everything is working great with it, I can see the statement button light up, it is available to add on all the templates, and certificates are issuing fine and working great.    I noticed that everytime I use certutil -verify <pathtoexportedcertificate.cer>  I receive the message: 

Cannot find object or property. 0x80092004 (-2146885628 CRYPT_E_NOT_FOUND)
------------------------------------
CertUtil: -verify command FAILED: 0x80092004 (-2146885628 CRYPT_E_NOT_FOUND)
CertUtil: Cannot find object or property.

If I strip the issuance policy from the certificate it verifies fine.    

Is this because my root is allowing all issuance policies?   

thanks in advance.  

 

PKIcurious
PKIcurious 22.07.2018 00:12 (GMT+3) Certificate Policies extension – all you should know (part 2)

Update on my above post in case other folks are working through this.  

I am doing a two tier PKI,  the first run with the root allowing all issuance policies, and the issuing CAs with the appropriate OID mapped to issuance policies, I couldn't get certutil -verify to successfully verify either user or computer certs when issued with the issuance policy (on the template).   The next run (rebuild) I included all the OID's that I will be using linked to the different Issuance policies in my domain from the root on down the chain to the different issuing CAs.      Added the Issuance policies to the domain, and issued certs with appropriate issuance policies stamped on cert.   This was successful in verifying the chain.   It seems that with Server 2016 if you are doing a two tier PKI without policy CA's, then it may be wise to determine the different level of assurances and then create the issuance policies ahead of time, and then after adding to domain, certs are validating appropriately.  

Vadims Podāns
Vadims Podāns 22.07.2018 00:23 (GMT+3) Certificate Policies extension – all you should know (part 2)

> from the root on down the chain to the different issuing CAs

that's wrong. An inability to validate policies has nothing to do with root CA. This indicate that you made mistake somewhere in your design or implementation. The article is still correct for Windows Server 2016.


Post your comment:

Please, solve this little equation and enter result below. Captcha