Category Archives: FreeIPA

Creating Your Own CA that issues Extended Validation SSL Certificates

If you have your own FreeIPA install, you may try the marketing thing to get the green bar for some of your SSL certificates. Sadly, issuing your own Extended Validation (EV) certificates and getting the green bar on all browsers is not simple (without special recompiled code, its not possible). The exact reason is described in this article. In way, this is a good thing as it is intended to have stronger security by the the browsers.

We verified 3 browers: Firefox 40, Chrome 45, IE 11.

Why internally issued EV certs & Green bar is not allowed

The answer simply boils down to trust. For EV certs, browsers don’t trust anyone but a hardcoded list in their code. For example in Firefox’s code here :  http://lxr.mozilla.org/firefox/source/security/manager/ssl/src/nsIdentityChecking.cpp

This is to ensure there is no accidentally inserted root certificates into the store that can verify EV certs.

Questionable ‘Higher’ Security/Trust model for hard coded EV Issuer Certificate Stores

Our opinion is this isn’t any real security or trust, it seems to be based in the notion that somehow hiding the EV Issuer Certificates in the browser executable is secure. We find this is slightly worse security than letting OS manage the certificate store. The our argument is, hard coding EV issuer certificates places ‘highly trusted’ certificates in the same trust zone as the browser process space. So a malware does not have mount a privilege escalation attack to mislead the user that a website is ‘highly trusted’. This leads to an inverse security where EV Issuer certificates are  arguably less trusted than the ones in the OS store. Here the assumption we are making is hacking OS cert stores takes a lot more sophistication and escalation into ring 3 (compared to no escalation) to trick the user into believing a fake EV certificate.

This security only limits user naive mistakes and not sophisticated or above average malware.

We evaluated the source code of Firefox and you can see one of the starting functions for checking if the certificate is EV is: nsNSSCertificate::hasValidEVOidTag

This function checks if the certifcate’s EV OID (Extended Policy Object ID values) matches OID from a hard coded EV issuer certs in getRootsForOid(SECOidTag oid_tag) which accesses a static array static struct nsMyTrustedEVInfo myTrustedEVInfos[] . This hardcoding of root certs precludes adding your EV issuing CA certificate to the trusted root in Mozilla certificate store. So no green bar even if your certificate has all the requirements of an EV certificate and have added a trusted CA to Mozilla.

Edit – Mozilla’s security team was nice enough to comment on our analysis – Their take was they take this position to influence CA standards and EV expectations. Our analysis still remains unchanged

Chrome follows a similar policy. IE is different, if you can get to GPO on your CA system, you can set the external OIDs that will allow a green bar. Unfortunately, IE is not a full solution as many people in our org use other browsers.

However, you can generate an ‘EV’ certificate in FreeIPA

Why would one care  if we can’t get green bar? If you can become an intermediate CA of a another CA that will allow you to generate EV certs (which I have not found any CA allowing this). Or if you plan to become an EV cert issuing CA yourself and want to embed your certificate in the browsers. If not for anything, for academic reasons.

FreeIPA Certificate Profile for EV Certificate Issuance

The main characteristics of an EV certificate is presence of OSCP, AIA and Certificate Subject in particular way and the certificate should have a Policy ID and CPS statement line.

Start with IPA’s default caIPAserviceCert (see ipa certprofile-find) Here are the important diffs in the profile to add the certificatePoliciesExt:

policyset.evServerCertSet.1.constraint.class_id=subjectNameConstraintImpl
policyset.evServerCertSet.1.constraint.name=Subject Name Constraint
policyset.evServerCertSet.1.constraint.params.accept=true
policyset.evServerCertSet.1.constraint.params.pattern=.*CN=.+
policyset.evServerCertSet.1.default.class_id=userSubjectNameDefaultImpl
policyset.evServerCertSet.1.default.name=Subject Name Default
policyset.evServerCertSet.1.default.params.name=
. . .
policyset.evServerCertSet.12.constraint.class_id=noConstraintImpl
policyset.evServerCertSet.12.constraint.name=No Constraint
policyset.evServerCertSet.12.default.class_id=certificatePoliciesExtDefaultImpl
policyset.evServerCertSet.12.default.name=Certificate Policies Extension Default
policyset.evServerCertSet.12.default.params.Critical=false
policyset.evServerCertSet.12.default.params.PoliciesExt.num=1
policyset.evServerCertSet.12.default.params.PoliciesExt.certPolicy0.enable=true
policyset.evServerCertSet.12.default.params.PoliciesExt.certPolicy0.policyId=1.3.6.1.4.1.35351.1000.100
policyset.evServerCertSet.12.default.params.PolicyQualifiers.num=1
policyset.evServerCertSet.12.default.params.PoliciesExt.certPolicy0.PolicyQualifiers0.CPSURI.enable=true
policyset.evServerCertSet.12.default.params.PoliciesExt.certPolicy0.PolicyQualifiers0.CPSURI.value=http://idm01.corp.silverskysoft.com/cpsstatement.html
policyset.evServerCertSet.12.default.params.PoliciesExt.certPolicy0.PolicyQualifiers0.usernotice.enable=true
policyset.evServerCertSet.12.default.params.PoliciesExt.certPolicy0.PolicyQualifiers0.usernotice.noticeReference.organization=$request.req_subject_name.cn$
policyset.evServerCertSet.12.default.params.PoliciesExt.certPolicy0.PolicyQualifiers0.usernotice.explicitText.value=SeeLegal
policyset.evServerCertSet.list=1,2,3,4,5,6,7,8,9,10,11,12

The policyID should be an ANSI OID (which can get expensive to obtain). For testing, you can use one from Wikipedia assigned to existing EV CAs.  The other cheaper way is to get an Private Enterprise Number from IANA and use the OID from that point on.

Then import the config file into FreeIPA:
ipa certprofile-import caIPAWebServiceEVCert --store=true --file=websslprofile

Certificate Signing Request

In your CSR, it must contain businessCategory=Private Organization/serialNumber=000

For in depth explanation what fields are required, visit the CA Browser forum https://cabforum.org and look for EV SSL specifications.

Also, thanks to a very nice CSR decode tool at CertLogik: https://certlogik.com/decoder/ that helped in our investigations.

 

 

Creating A Subordinate Certificate Authority in FreeIPA

Within an organization using Free IPA there may be a need to create a subordinate CA. A subordinate CA can issue certificates on behalf of the Root CA in the organization so it should be treated with the same security as an organization’s Root CA. The main advantage is Subordinate CA can be revoked if it goes rogue and so keep part of the organization still working.

Free IPA 4.2.0 allows the use of certificate profiles (certificate template) to sign new certificate requests. This allows you to create your own profiles that will allow sign any type of certificate request. Earlier than FreeIPA 4.2.0, this was not possible, although the underlying dogtag PKI already allowed it.

RFC 5280 is the X.509 certificate description and specifically subordinate CA description. If you have openSSL installed, look at man x509v3_config for detailed description of V3 extensions.

Characteristics of a Sub-CA

For all practical purposes a Sub-CA is a CA that ideally:

  • Has the CA flag set to true
  • Preferably not issue further Sub-CA certificates

Creating the Certificate Profile

A subordinate CA is a very powerful element in the PKI’s trust chain. So ensure people who have access to it have adequate knowledge of what’s happening.

Here is the raw config file we used for our Sub CA certificate profile. Some notes follow this long listing.

[root@idm01 fedora]# cat caSubCACert2.cfg 
desc=This certificate profile is for enrolling Subordinate Certificate Authority certificates.
visible=true
enable=true
auth.instance_id=raCertAuth
classId=caEnrollImpl
enableBy=ipara
name=Manual Certificate Manager Subordinate Signing Certificate Enrollment
input.list=i1,i2
input.i1.class_id=certReqInputImpl
input.i2.class_id=submitterInfoInputImpl
output.list=o1
output.o1.class_id=certOutputImpl
policyset.list=caSubCertSet
policyset.caSubCertSet.list=1,2,3,4,5,6,8,9,10
policyset.caSubCertSet.1.constraint.class_id=subjectNameConstraintImpl
policyset.caSubCertSet.1.constraint.name=Subject Name Constraint
policyset.caSubCertSet.1.constraint.params.pattern=.*CN=.+
policyset.caSubCertSet.1.constraint.params.accept=true
policyset.caSubCertSet.1.default.class_id=userSubjectNameDefaultImpl
policyset.caSubCertSet.1.default.name=Subject Name Default
policyset.caSubCertSet.1.default.params.name=
policyset.caSubCertSet.2.constraint.class_id=validityConstraintImpl
policyset.caSubCertSet.2.constraint.name=Validity Constraint
policyset.caSubCertSet.2.constraint.params.range=7305
policyset.caSubCertSet.2.constraint.params.notBeforeCheck=false
policyset.caSubCertSet.2.constraint.params.notAfterCheck=false
policyset.caSubCertSet.2.default.class_id=caValidityDefaultImpl
policyset.caSubCertSet.2.default.name=CA Certificate Validity Default
policyset.caSubCertSet.2.default.params.range=7305
policyset.caSubCertSet.2.default.params.startTime=0
policyset.caSubCertSet.3.constraint.class_id=keyConstraintImpl
policyset.caSubCertSet.3.constraint.name=Key Constraint
policyset.caSubCertSet.3.constraint.params.keyType=-
policyset.caSubCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096,nistp256,nistp384,nistp521
policyset.caSubCertSet.3.default.class_id=userKeyDefaultImpl
policyset.caSubCertSet.3.default.name=Key Default
policyset.caSubCertSet.4.constraint.class_id=noConstraintImpl
policyset.caSubCertSet.4.constraint.name=No Constraint
policyset.caSubCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl
policyset.caSubCertSet.4.default.name=Authority Key Identifier Default
policyset.caSubCertSet.5.constraint.class_id=basicConstraintsExtConstraintImpl
policyset.caSubCertSet.5.constraint.name=Basic Constraint Extension Constraint
policyset.caSubCertSet.5.constraint.params.basicConstraintsCritical=true
policyset.caSubCertSet.5.constraint.params.basicConstraintsIsCA=true
policyset.caSubCertSet.5.constraint.params.basicConstraintsMinPathLen=0
policyset.caSubCertSet.5.constraint.params.basicConstraintsMaxPathLen=0
policyset.caSubCertSet.5.default.class_id=basicConstraintsExtDefaultImpl
policyset.caSubCertSet.5.default.name=Basic Constraints Extension Default
policyset.caSubCertSet.5.default.params.basicConstraintsCritical=true
policyset.caSubCertSet.5.default.params.basicConstraintsIsCA=true
policyset.caSubCertSet.5.default.params.basicConstraintsPathLen=0
policyset.caSubCertSet.6.constraint.class_id=keyUsageExtConstraintImpl
policyset.caSubCertSet.6.constraint.name=Key Usage Extension Constraint
policyset.caSubCertSet.6.constraint.params.keyUsageCritical=true
policyset.caSubCertSet.6.constraint.params.keyUsageDigitalSignature=true
policyset.caSubCertSet.6.constraint.params.keyUsageNonRepudiation=true
policyset.caSubCertSet.6.constraint.params.keyUsageDataEncipherment=false
policyset.caSubCertSet.6.constraint.params.keyUsageKeyEncipherment=false
policyset.caSubCertSet.6.constraint.params.keyUsageKeyAgreement=false
policyset.caSubCertSet.6.constraint.params.keyUsageKeyCertSign=true
policyset.caSubCertSet.6.constraint.params.keyUsageCrlSign=true
policyset.caSubCertSet.6.constraint.params.keyUsageEncipherOnly=false
policyset.caSubCertSet.6.constraint.params.keyUsageDecipherOnly=false
policyset.caSubCertSet.6.default.class_id=keyUsageExtDefaultImpl
policyset.caSubCertSet.6.default.name=Key Usage Default
policyset.caSubCertSet.6.default.params.keyUsageCritical=true
policyset.caSubCertSet.6.default.params.keyUsageDigitalSignature=true
policyset.caSubCertSet.6.default.params.keyUsageNonRepudiation=true
policyset.caSubCertSet.6.default.params.keyUsageDataEncipherment=false
policyset.caSubCertSet.6.default.params.keyUsageKeyEncipherment=false
policyset.caSubCertSet.6.default.params.keyUsageKeyAgreement=false
policyset.caSubCertSet.6.default.params.keyUsageKeyCertSign=true
policyset.caSubCertSet.6.default.params.keyUsageCrlSign=true
policyset.caSubCertSet.6.default.params.keyUsageEncipherOnly=false
policyset.caSubCertSet.6.default.params.keyUsageDecipherOnly=false
policyset.caSubCertSet.8.constraint.class_id=noConstraintImpl
policyset.caSubCertSet.8.constraint.name=No Constraint
policyset.caSubCertSet.8.default.class_id=subjectKeyIdentifierExtDefaultImpl
policyset.caSubCertSet.8.default.name=Subject Key Identifier Extension Default
policyset.caSubCertSet.8.default.params.critical=false
policyset.caSubCertSet.9.constraint.class_id=signingAlgConstraintImpl
policyset.caSubCertSet.9.constraint.name=No Constraint
policyset.caSubCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withEC,SHA512withEC
policyset.caSubCertSet.9.default.class_id=signingAlgDefaultImpl
policyset.caSubCertSet.9.default.name=Signing Alg
policyset.caSubCertSet.9.default.params.signingAlg=-
policyset.caSubCertSet.9.constraint.class_id=noConstraintImpl
policyset.caSubCertSet.9.constraint.name=No Constraint
policyset.caSubCertSet.9.default.class_id=crlDistributionPointsExtDefaultImpl
policyset.caSubCertSet.9.default.name=CRL Distribution Points Extension Default
policyset.caSubCertSet.9.default.params.crlDistPointsCritical=false
policyset.caSubCertSet.9.default.params.crlDistPointsEnable_0=true
policyset.caSubCertSet.9.default.params.crlDistPointsIssuerName_0=CN=Certificate Authority,o=ipaca
policyset.caSubCertSet.9.default.params.crlDistPointsIssuerType_0=DirectoryName
policyset.caSubCertSet.9.default.params.crlDistPointsNum=1
policyset.caSubCertSet.9.default.params.crlDistPointsPointName_0=http://<your IPA's CRL revocation list>
policyset.caSubCertSet.9.default.params.crlDistPointsPointType_0=URIName
policyset.caSubCertSet.9.default.params.crlDistPointsReasons_0=
policyset.caSubCertSet.10.constraint.class_id=noConstraintImpl
policyset.caSubCertSet.10.constraint.name=No Constraint
policyset.caSubCertSet.10.default.class_id=authInfoAccessExtDefaultImpl
policyset.caSubCertSet.10.default.name=AIA Extension Default
policyset.caSubCertSet.10.default.params.authInfoAccessADEnable_0=true
policyset.caSubCertSet.10.default.params.authInfoAccessADLocationType_0=URIName
policyset.caSubCertSet.10.default.params.authInfoAccessADLocation_0=
policyset.caSubCertSet.10.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1
policyset.caSubCertSet.10.default.params.authInfoAccessCritical=false
policyset.caSubCertSet.10.default.params.authInfoAccessNumADs=1
profileId=caSubCertAuth2
[root@idm01 fedora]# 

This constraint says, the CSR must have a “CN=” string somewhere.

policyset.caSubCertSet.1.constraint.params.pattern=.*CN=.+

The following says that the certificate is for a CA and path len =0, which means the CA can issue further Sub CAs.

policyset.caSubCertSet.5.constraint.params.basicConstraintsIsCA=true
policyset.caSubCertSet.5.constraint.params.basicConstraintsMinPathLen=0
policyset.caSubCertSet.5.constraint.params.basicConstraintsMaxPathLen=0
policyset.caSubCertSet.5.default.params.basicConstraintsIsCA=true
policyset.caSubCertSet.5.default.params.basicConstraintsPathLen=0

Importing the profile into FreeIPA

[root@idm01 fedora]# ipa certprofile-import caSubCertAuth2 --store=true --file=caSubCACert2.cfg 
Profile description: This certificate profile is for enrolling Subordinate Certificate Authority certificates (v2).
---------------------------------
Imported profile "caSubCertAuth2"
---------------------------------
 Profile ID: caSubCertAuth2
 Profile description: This certificate profile is for enrolling Subordinate Certificate Authority certificates (v2).
 Store issued certificates: TRUE
[root@idm01 fedora]#

Don’t forget to add the Certificate ACL allowing appropriate groups s access to the certificate profile either from the WebUI or command line.

Certificate Signing Request

The CSR is not different than other requests you can use OpenSSL to create a CSR. Just ensure the CN and others follow the restrictions that is set in the profile above.

Issuing the Certificate

[root@idm01 fedora]# ipa cert-request ./cert.req --principal SUBCA/SUBCA01.silverskysoft.com --profile-id caSubCertAuth2

This should issue the certificate.

That’s cool, but where’s the green bar?

The green bar that shows up when you visit certain e-commerce websites is a very nice marketing thing. As a result, some users would like to see the green bar. Our next quest is to see if we can create certificate profile that allows generating a certificate with EV flags set. Cursory reading of documentation shows its not well documented and probably not possible.