[#43] Additional certificate fields to display

* This change adds in additional information about the certificate, which include the public key and signature algoritms and their sizes, the key usage and extended key usage, the certificate version number for EK and CA certs and the issuer section expanded with Auth Key Id and Auth Info Access.

* Made some fixes to the platform class print out.  Needs to print out string representation of the value.

* Additional changes for the certificate details page.  Going over the spec determining what should be shown and what should be hidden if no information is specified.

* This change adds in additional information about the certificate, which include the public key and signature algoritms and their sizes, the key usage and extended key usage, the certificate version number for EK and CA certs and the issuer section expanded with Auth Key Id and Auth Info Access.

Made some fixes to the platform class print out.  Needs to print out string representation of the value.

Additional changes for the certificate details page.  Going over the spec determining what should be shown and what should be hidden if no information is specified.

Small updates to code commits and statements

* Stashing changes.

* Correcting some unit test fail instances.  The PC Test fails because the tested cert is not updated to new (constantly changing) specs.  Not just on the value but also on the value type.

* Fixing git merge meta data.

* Updates to include the Authority Key information as a set rather than just one item.  Using a bouncy castle defined class.

* Reversed the type of variable the public key value returns so that the unit test for it doesn't have to change.  The type wasn't important, it was a convenience decision.

* Adding changes based on review comments from @apldev3.

* Made changes based on github review comments.

* Additional changes for github comments

* Updated the code for the public key size on CA and EK certificates.  There was a previous issue with 4 additional bytes being included in the size.

* Some more changes for Github comments
This commit is contained in:
Cyrus 2018-12-13 09:30:10 -05:00 committed by apldev3
parent 6f99a10ad3
commit 6624296abe
8 changed files with 810 additions and 114 deletions

View File

@ -4,6 +4,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
@ -44,9 +45,15 @@ public final class CertificateStringMapBuilder {
data.put("issuer", certificate.getIssuer());
//Serial number in hex value
data.put("serialNumber", Long.toHexString(certificate.getSerialNumber().longValue()));
if (!certificate.getAuthoritySerialNumber().equals(BigInteger.ZERO)) {
data.put("authSerialNumber", Long.toHexString(certificate
.getAuthoritySerialNumber().longValue()));
}
data.put("beginValidity", certificate.getBeginValidity().toString());
data.put("endValidity", certificate.getEndValidity().toString());
data.put("signature", Arrays.toString(certificate.getSignature()));
data.put("signatureSize", Integer.toString(certificate.getSignature().length
* Certificate.MIN_ATTR_CERT_LENGTH));
if (certificate.getSubject() != null) {
data.put("subject", certificate.getSubject());
@ -56,9 +63,27 @@ public final class CertificateStringMapBuilder {
data.put("isSelfSigned", "false");
}
data.put("authKeyId", certificate.getAuthKeyId());
data.put("crlPoints", certificate.getCrlPoints());
data.put("signatureAlgorithm", certificate.getSignatureAlgorithm());
if (certificate.getEncodedPublicKey() != null) {
data.put("encodedPublicKey",
Arrays.toString(certificate.getEncodedPublicKey()));
data.put("publicKeyAlgorithm", certificate.getPublicKeyAlgorithm());
}
if (certificate.getPublicKeyModulusHexValue() != null) {
data.put("publicKeyValue", certificate.getPublicKeyModulusHexValue());
data.put("publicKeySize", String.valueOf(certificate.getPublicKeySize()));
}
if (certificate.getKeyUsage() != null) {
data.put("keyUsage", certificate.getKeyUsage());
}
if (certificate.getExtendedKeyUsage() != null
&& !certificate.getExtendedKeyUsage().isEmpty()) {
data.put("extendedKeyUsage", certificate.getExtendedKeyUsage());
}
//Get issuer ID if not self signed
@ -69,7 +94,7 @@ public final class CertificateStringMapBuilder {
data.put("missingChainIssuer", missingCert.getIssuer());
}
//Find all certificates that could be the issuer certificate based on subject name
for (Certificate issuerCert:CertificateAuthorityCredential
for (Certificate issuerCert : CertificateAuthorityCredential
.select(certificateManager)
.bySubject(certificate.getIssuer())
.getCertificates()) {
@ -179,6 +204,11 @@ public final class CertificateStringMapBuilder {
data.putAll(getGeneralCertificateInfo(certificate, certificateManager));
data.put("subjectKeyIdentifier",
Arrays.toString(certificate.getSubjectKeyIdentifier()));
//x509 credential version
data.put("x509Version", Integer.toString(certificate
.getX509CredentialVersion()));
data.put("authInfoAccess", certificate.getAuthInfoAccess());
data.put("credentialType", certificate.getCredentialType());
} else {
LOGGER.error(notFoundMessage);
}
@ -202,12 +232,16 @@ public final class CertificateStringMapBuilder {
if (certificate != null) {
data.putAll(getGeneralCertificateInfo(certificate, certificateManager));
// Set extra fields
data.put("credentialType", certificate.getCredentialType());
data.put("manufacturer", certificate.getManufacturer());
data.put("model", certificate.getModel());
data.put("version", certificate.getVersion());
data.put("policyReference", certificate.getPolicyReference());
data.put("revocationLocator", certificate.getRevocationLocator());
data.put("crlPoints", certificate.getCrlPoints());
data.put("authInfoAccess", certificate.getAuthInfoAccess());
data.put("credentialType", certificate.getCredentialType());
//x509 credential version
data.put("x509Version", Integer.toString(certificate
.getX509CredentialVersion()));
// Add hashmap with TPM information if available
if (certificate.getTpmSpecification() != null) {
data.putAll(

View File

@ -51,27 +51,44 @@
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Issuer</span></div>
<div id="issuer" class="col col-md-8">
<!-- Display the issuer, and provide a link to the issuer details if provided -->
<c:choose>
<c:when test="${not empty initialData.issuerID}">
<a href="${portal}/certificate-details?id=${initialData.issuerID}&type=certificateauthority">
${initialData.issuer}
</a>
</c:when>
<c:otherwise>
${initialData.issuer}
</c:otherwise>
</c:choose>
<div>Distinguished Name:&nbsp;<span>
<c:choose>
<c:when test="${not empty initialData.issuerID}">
<a href="${portal}/certificate-details?id=${initialData.issuerID}&type=certificateauthority">
${initialData.issuer}
</a>
</c:when>
<c:otherwise>
${initialData.issuer}
</c:otherwise>
</c:choose>
</span>
</div>
<div>Authority Key Identifier:&nbsp;
<span id="authorityKeyIdentifier"></span>
</div>
<c:if test="${not empty initialData.authInfoAccess}">
<div>Authority Info Access:&nbsp;<span>
<a href="${initialData.authInfoAccess}">${initialData.authInfoAccess}</a>
</span>
</div>
</c:if>
<c:if test="${not empty initialData.authSerialNumber}">
<div>Authority Serial Number:&nbsp;
<span id="authSerialNumber"></span>
</div>
</c:if>
<c:if test="${param.type!='issued'}">
<span class="chainIcon">
<!-- Icon with link for missing certificate for the chain -->
<c:choose>
<c:when test="${initialData.isSelfSigned == 'true'}">
<img src="${icons}/ic_all_inclusive_black_24dp.png"
title="Self sign certificate.">
<img src="${icons}/ic_all_inclusive_black_24dp.png"
title="Self sign certificate.">
</c:when>
<c:when test="${empty initialData.missingChainIssuer}">
<img src="${icons}/ic_checkbox_marked_circle_black_green_24dp.png"
title="All certificates in the chain were found.">
title="All certificates in the chain were found.">
</c:when>
<c:otherwise>
<img src="${icons}/ic_error_red_24dp.png"
@ -100,81 +117,215 @@
</div>
</div>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Signature</span></div>
<div id="signature" class="col col-md-8"></div>
</div>
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Signature</span></div><div id="signatureSection" class="col col-md-8">
<div class="panel-body">
<div class="panel panel-default">
<div class="panel-heading">
<a role="button" data-toggle="collapse" class="collapsed" href="#signatureComponentcollapse"
aria-expanded="true" data-placement="top" aria-controls="signatureComponentcollapse">
Signature
</a>
</div>
<div id="signatureComponentcollapse" class="panel-body collapse" role="tabpanel" aria-labelledby="headingOne" aria-expanded="false">
<div id="signature" class="fieldValue"></div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<a role="button" data-toggle="collapse" class="collapsed" href="#signatureSizecollapse"
aria-expanded="true" data-placement="top" aria-controls="signatureSizecollapse">
Algorithm
</a>
</div>
<div id="signatureSizecollapse" class="panel-body collapse" role="tabpanel" aria-labelledby="headingOne" aria-expanded="false">
<div>
<span class="fieldValue">
${initialData.signatureAlgorithm} / ${initialData.signatureSize}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<c:if test="${not empty initialData.encodedPublicKey}">
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Public Key</span></div>
<div id="encodedPublicKey" class="col col-md-8"></div>
<div id="publicKeySection" class="col col-md-8">
<div class="panel-body">
<div class="panel panel-default">
<div class="panel-heading">
<a role="button" data-toggle="collapse" class="collapsed" href="#publicKeycollapse"
aria-expanded="true" data-placement="top" aria-controls="publicKeycollapse">
Public Key
</a>
</div>
<div id="publicKeycollapse" class="panel-body collapse" role="tabpanel" aria-labelledby="headingOne" aria-expanded="false">
<c:choose>
<c:when test="${not empty initialData.publicKeyValue}">
<div id="encodedPublicKey" class="fieldValue"></div>
</c:when>
<c:otherwise>
<div id="encodedPublicKey" class="fieldValue"></div>
</c:otherwise>
</c:choose>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<a role="button" data-toggle="collapse" class="collapsed" href="#publicKeySizecollapse"
aria-expanded="true" data-placement="top" aria-controls="publicKeySizecollapse">
Algorithm
</a>
</div>
<div id="publicKeySizecollapse" class="panel-body collapse" role="tabpanel" aria-expanded="false">
<div>
<span class="fieldValue">
${initialData.publicKeyAlgorithm} / ${initialData.publicKeySize}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</c:if>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">X509 Credential Version</span></div>
<div id="credentialVersion" class="col col-md-8 vertical">${initialData.x509Version} (v${initialData.x509Version + 1})</div>
</div>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Credential Type</span></div>
<div id="credentialType" class="col col-md-8">${initialData.credentialType}</div>
</div>
<!-- Add the different fields based on the certificate type -->
<c:choose>
<c:when test="${param.type=='certificateauthority'}">
<c:choose>
<c:when test="${not empty initialData.subjectKeyIdentifier}">
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Subject Key Identifier</span></div>
<div id="subjectKeyIdentifier" class="col col-md-8 vertical"></div>
</div>
</c:when>
</c:choose>
<c:if test="${initialData.crlPoints}">
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Revocation Locator</span></div>
<div id="revocationLocator" class="col col-md-8"><a href="${initialData.crlPoints}">${initialData.crlPoints}</div>
</div>
</c:if>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Subject Key Identifier</span></div>
<div id="subjectKeyIdentifier" class="col col-md-8"></div>
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Key Usage</span></div>
<c:choose>
<c:when test="${not empty initialData.keyUsage}">
<div id="keyUsage" class="col col-md-8 vertical">${initialData.keyUsage}</div>
</c:when>
<c:otherwise>
<div id="keyUsage" class="col col-md-8 vertical">Not Specified</div>
</c:otherwise>
</c:choose>
</div>
<c:choose>
<c:when test="${not empty initialData.extendedKeyUsage}">
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Extended Key Usage</span></div>
<div id="extendedKeyUsage" class="col col-md-8 vertical">${initialData.extendedKeyUsage}</div>
</div>
</c:when>
</c:choose>
</c:when>
<c:when test="${param.type=='endorsement'}">
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Credential Type</span></div>
<div id="credentialType" class="col col-md-8">${initialData.credentialType}</div>
</div>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Manufacturer</span></div>
<div id="manufacturer" class="col col-md-8">${initialData.manufacturer}</div>
</div>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Model</span></div>
<div id="model" class="col col-md-8">${initialData.model}</div>
</div>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Version</span></div>
<div id="version" class="col col-md-8">${initialData.version}</div>
<div class="col-md-1 col-md-offset-1"><span class="colHeader">TPM</span></div>
<div id="subjectAltName" class="col col-md-8">
<div id="manufacturer">Manufacturer:&nbsp;<span>${initialData.manufacturer}</span></div>
<div id="model">Model:&nbsp;<span>${initialData.model}</span></div>
<div id="version">Version:&nbsp;<span>${initialData.version}</span></div>
<div id="serial">Serial NR:&nbsp;<span><!-- optional --></span></div>
</div>
</div>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Policy Reference</span></div>
<div id="policyReference" class="col col-md-8">${initialData.policyReference}</div>
<div id="policyReference" class="col col-md-8">
<c:choose>
<c:when test="${not empty initialData.policyReference}">
${initialData.policyReference}
</c:when>
<c:otherwise>
Not Specified
</c:otherwise>
</c:choose>
</div>
</div>
<c:if test="${initialData.crlPoints}">
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Revocation Locator</span></div>
<div id="revocationLocator" class="col col-md-8"><a href="${initialData.crlPoints}">${initialData.crlPoints}</div>
</div>
</c:if>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Revocation Locator</span></div>
<div id="revocationLocator" class="col col-md-8">${initialData.revocationLocator}</div>
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Key Usage</span></div>
<c:choose>
<c:when test="${not empty initialData.keyUsage}">
<div id="keyUsage" class="col col-md-8 vertical">${initialData.keyUsage}</div>
</c:when>
<c:otherwise>
<div id="keyUsage" class="col col-md-8 vertical">Not Specified</div>
</c:otherwise>
</c:choose>
</div>
<c:choose>
<c:when test="${not empty initialData.extendedKeyUsage}">
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Extended Key Usage</span></div>
<div id="extendedKeyUsage" class="col col-md-8 vertical">${initialData.extendedKeyUsage}</div>
</div>
</c:when>
</c:choose>
<!-- Need to test this -->
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">TPM Specification</span></div>
<div class="col-md-1 col-md-offset-1">
<span class="colHeader">
<a role="button" data-toggle="collapse" class="collapsed" href="#tpmSpecificationInner"
aria-expanded="true" data-placement="top" aria-controls="tpmSpecificationInner">
TPM Specification
</a>
</span>
</div>
<div id="tpmSpecification" class="col col-md-8">
<div>Family:&nbsp;<span>${initialData.TPMSpecificationFamily}</span></div>
<div>Level:&nbsp;<span>${initialData.TPMSpecificationLevel}</span></div>
<div>Revision:&nbsp;<span>${initialData.TPMSpecificationRevision}</span></div>
<div id="tpmSpecificationInner" class="panel-body collapse" role="tabpanel" aria-expanded="false">
<div>Family:&nbsp;<span>${initialData.TPMSpecificationFamily}</span></div>
<div>Level:&nbsp;<span>${initialData.TPMSpecificationLevel}</span></div>
<div>Revision:&nbsp;<span>${initialData.TPMSpecificationRevision}</span></div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">TPM Security Assertion</span></div>
<div class="col-md-1 col-md-offset-1">
<span class="colHeader">
<a role="button" data-toggle="collapse" class="collapsed" href="#tpmSecurityAssertionInner"
aria-expanded="true" data-placement="top" aria-controls="tpmSecurityAssertionInner">
TPM Security Assertion
</a>
</span>
</div>
<div id="tpmSecurityAssertion" class="col col-md-8">
<div>Version:&nbsp;<span>${initialData.TPMSecurityAssertionsVersion}</span></div>
<div>Field Upgradeable:&nbsp;<span>${initialData.TPMSecurityAssertionsFieldUpgradeable}</span></div>
<div>ek Generation Type:&nbsp;<span>${initialData.TPMSecurityAssertionsEkGenType}</span></div>
<div>ek Generation Location:&nbsp;<span>${initialData.TPMSecurityAssertionsEkGenLoc}</span></div>
<div>ek Certificate Generation Location:&nbsp;<span>${initialData.TPMSecurityAssertionsEkCertGenLoc}</span></div>
<div id="tpmSecurityAssertionInner" class="panel-body collapse" role="tabpanel" aria-expanded="false">
<div>Version:&nbsp;<span>${initialData.TPMSecurityAssertionsVersion}</span></div>
<div>Field Upgradeable:&nbsp;<span>${initialData.TPMSecurityAssertionsFieldUpgradeable}</span></div>
<div>ek Generation Type:&nbsp;<span>${initialData.TPMSecurityAssertionsEkGenType}</span></div>
<div>ek Generation Location:&nbsp;<span>${initialData.TPMSecurityAssertionsEkGenLoc}</span></div>
<div>ek Certificate Generation Location:&nbsp;<span>${initialData.TPMSecurityAssertionsEkCertGenLoc}</span></div>
</div>
</div>
</div>
</c:when>
<c:when test="${param.type=='platform'}">
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">X509 Credential Version</span></div>
<div id="credentialVersion" class="col col-md-8 vertical">${initialData.x509Version} (v${initialData.x509Version + 1})</div>
</div>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Credential Type</span></div>
<div id="credentialType" class="col col-md-8">${initialData.credentialType}</div>
</div>
<c:if test="${not empty initialData.CPSuri}">
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Certification Practice Statement URI</span></div>
<div id="credentialType" class="col col-md-8 vertical">
<div id="certificateCPSU" class="col col-md-8 vertical">
<a href="${initialData.CPSuri}"> ${initialData.CPSuri}</a>
</div>
</div>
@ -183,9 +334,10 @@
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Holder</span></div>
<div id="holder" class="col col-md-8">
<c:if test="${not empty initialData.holderIssuer}">
<div><span>${initialData.holderIssuer}</span></div>
<div>EK Certificate:&nbsp;<span>${initialData.holderIssuer}</span></div>
</c:if>
<div id="certificateid">
<div id="certificateid">
<div>EK Identifier:&nbsp;
<c:choose>
<c:when test="${not empty initialData.ekId}">
<span>
@ -195,24 +347,22 @@
</span>
</c:when>
<c:otherwise>
<div><span>${initialData.holderSerialNumber}</span></div>
<span>${initialData.holderSerialNumber}</span>
</c:otherwise>
</c:choose>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Manufacturer</span></div>
<div id="manufacturer" class="col col-md-8">${initialData.manufacturer}</div>
</div>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Model</span></div>
<div id="model" class="col col-md-8">${initialData.model}</div>
</div>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Version</span></div>
<div id="version" class="col col-md-8">${initialData.version}</div>
</div>
<div class="col-md-1 col-md-offset-1"><span class="colHeader">TPM</span></div>
<div id="subjectAltName" class="col col-md-8">
<div id="manufacturer">Manufacturer:&nbsp;<span>${initialData.manufacturer}</span></div>
<div id="model">Model:&nbsp;<span>${initialData.model}</span></div>
<div id="version">Version:&nbsp;<span>${initialData.version}</span></div>
<div id="serial">Serial NR:&nbsp;<span><!-- optional --></span></div>
</div>
</div>
<c:choose>
<c:when test="${fn:contains(initialData.credentialType, 'TCG')}">
<div class="row">
@ -260,12 +410,12 @@
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#tbbsecurity" class="collapsed"
href="#ccinfocollapse" aria-expanded="false" aria-controls="ccinfocollapse">
Common Criteria Measures Information
Common Criteria Measures Information
</a>
</h4>
</div>
<div id="ccinfocollapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingOne">
<div class="panel-body">
<div class="panel-body">
<div id="ccinfo" class="row">
<div class="tbbsecurityLine">
<span class="fieldHeader">Version:</span>
@ -346,7 +496,7 @@
<div class="tbbsecurityLine">
<span class="fieldHeader">Target Hash Value:</span>
<span class="fieldValue">${ccinfo.getTargetUri().getHashValue()}</span>
</div>
</div>
</c:if>
</c:if>
</div>
@ -362,12 +512,12 @@
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#tbbsecurity" class="collapsed"
href="#fipscollapse" aria-expanded="false" aria-controls="fipscollapse">
FIPS Level
FIPS Level
</a>
</h4>
</div>
<div id="fipscollapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo">
<div class="panel-body">
<div class="panel-body">
<div id="fipsLevel" class="row">
<div class="tbbsecurityLine">
<span class="fieldHeader">Version:</span>
@ -398,12 +548,12 @@
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#tbbsecurity" class="collapsed"
href="#iso9000collapse" aria-expanded="false" aria-controls="iso9000collapse">
ISO 9000
ISO 9000
</a>
</h4>
</div>
<div id="iso9000collapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree">
<div class="panel-body">
<div class="panel-body">
<div id="iso9000" class="row">
<div class="tbbsecurityLine">
<c:choose>
@ -444,12 +594,12 @@
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#platformConfiguration" class="collapsed"
href="#componentIdentifiercollapse" aria-expanded="true" aria-controls="componentIdentifiercollapse">
Components
Components
</a>
</h4>
</div>
<div id="componentIdentifiercollapse" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne" aria-expanded="true">
<div class="panel-body">
<div class="panel-body">
<div id="componentIdentifier" class="row">
<c:forEach items="${initialData.componentsIdentifier}" var="component">
<div class="component col col-md-4">
@ -495,12 +645,12 @@
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#platformConfiguration" class="collapsed"
href="#platformPropertiescollapse" aria-expanded="false" aria-controls="platformPropertiescollapse">
Platform Properties
Platform Properties
</a>
</h4>
</div>
<div id="platformPropertiescollapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo">
<div class="panel-body">
<div class="panel-body">
<div id="platformProperties" class="row">
<c:forEach items="${initialData.platformProperties}" var="property">
<div class="component col col-md-4">
@ -526,12 +676,12 @@
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#platformConfiguration" class="collapsed"
href="#platformPropertiesURIcollapse" aria-expanded="false" aria-controls="platformPropertiesURIcollapse">
Platform Properties URI
Platform Properties URI
</a>
</h4>
</div>
<div id="platformPropertiesURIcollapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree">
<div class="panel-body">
<div class="panel-body">
<div id="platformPropertiesURI" class="row">
<span class="fieldHeader">URI:</span>
<a href="${initialData.platformPropertiesURI.getUniformResourceIdentifier()}">
@ -581,13 +731,15 @@
</c:choose>
</div>
<script>
$(document).ready(function() {
$(document).ready(function () {
var type = "${param.type}";
var signature = ${initialData.signature};
var serialNumber = '${initialData.serialNumber}';
var authorityKeyIdentifier = '${initialData.authKeyId}';
var authoritySerialNumber = '${initialData.authSerialNumber}';
//Format validity time
$("#validity span").each(function(){
$("#validity span").each(function () {
$(this).text(formatDateTime($(this).text()));
});
@ -597,39 +749,61 @@
//Convert byte array to string
$("#serialNumber").html(parseSerialNumber(serialNumber));
<c:if test="${not empty initialData.encodedPublicKey}">
//Change publick key byte to hex
var publicKey = ${initialData.encodedPublicKey};
$("#encodedPublicKey").html(byteToHexString(publicKey));
// authority key ID
<c:choose>
<c:when test="${not empty initialData.authKeyId}">
$("#authorityKeyIdentifier").html(parseSerialNumber(authorityKeyIdentifier));
</c:when>
<c:otherwise>
$("#authorityKeyIdentifier").html("Not Specified");
</c:otherwise>
</c:choose>
<c:if test="${not empty initialData.authSerialNumber}">
//Convert string to serial String
$("#authSerialNumber").html(parseSerialNumber(authoritySerialNumber));
</c:if>
<c:choose>
<c:when test="${not empty initialData.publicKeyValue}">
var publicKey = '${initialData.publicKeyValue}';
$("#encodedPublicKey").html(parseHexString(publicKey));
</c:when>
<c:otherwise>
<c:if test="${not empty initialData.encodedPublicKey}">
//Change public key byte to hex
var encPublicKey = ${initialData.encodedPublicKey};
$("#encodedPublicKey").html(byteToHexString(encPublicKey));
</c:if>
</c:otherwise>
</c:choose>
<c:if test="${not empty initialData.subjectKeyIdentifier}">
//Change subject byte to hex only for CACertificate
if(type === "certificateauthority"){
var subjectKeyIdentifier = ${initialData.subjectKeyIdentifier};
$("#subjectKeyIdentifier").html(byteToHexString(subjectKeyIdentifier));
}
</c:if>
<c:if test="${not empty initialData.subjectKeyIdentifier}">
//Change subject byte to hex only for CACertificate
if (type === "certificateauthority") {
var subjectKeyIdentifier = ${initialData.subjectKeyIdentifier};
$("#subjectKeyIdentifier").html(byteToHexString(subjectKeyIdentifier));
}
</c:if>
//Initiliaze tooltips
$('[data-toggle="tooltip"]').tooltip();
//Vertical alignment on data columns
$('.vertical').each(function(){
$('.vertical').each(function () {
$(this).css({
'line-height': $(this).height() + 'px'
});
});
});
//Change link width
$("#headingOne, #headingTwo, #headingThree").each(function(e) {
$("#headingOne, #headingTwo, #headingThree").each(function (e) {
var width = $(this).width();
//Get link width
var linkWidth = $(this).find('a').width();
//Change width for the link
$(this).find('a').css({
"padding-right": (width-linkWidth) + "px"
"padding-right": (width - linkWidth) + "px"
});
});
});

View File

@ -7,6 +7,16 @@ function byteToHexString(arr){
return (str.substring(0, str.length - 2)).toUpperCase();
}
//Parse hex string for display
function parseHexString(hexString) {
var str = hexString.toUpperCase();
//Do not parse if there is 2 characters
if(str.length === 2) {
return str;
}
return str.match(/.{2}/g).join(': ');
}
//Parse the HEX string value to display as byte hex string
function parseSerialNumber(hexString){
var str = hexString.toUpperCase();

View File

@ -3,6 +3,7 @@ package hirs.data.persist.certificate;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.base.Preconditions;
import hirs.data.persist.ArchivableEntity;
import hirs.utils.HexUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bouncycastle.asn1.ASN1BitString;
@ -26,6 +27,15 @@ import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DLSequence;
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
import org.bouncycastle.asn1.x509.AccessDescription;
import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.x509.extension.X509ExtensionUtil;
import javax.persistence.Column;
import javax.persistence.Entity;
@ -46,6 +56,7 @@ import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.util.ArrayList;
@ -53,6 +64,9 @@ import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import org.bouncycastle.asn1.x509.CRLDistPoint;
import org.bouncycastle.asn1.x509.DistributionPoint;
import org.bouncycastle.asn1.x509.DistributionPointName;
/**
@ -70,6 +84,31 @@ public abstract class Certificate extends ArchivableEntity {
private static final int MAX_CERT_LENGTH_BYTES = 2048;
private static final int MAX_NUMERIC_PRECISION = 49; // Can store up to 160 bit values
private static final int MAX_PUB_KEY_MODULUS_HEX_LENGTH = 1024;
private static final int KEY_USAGE_BIT0 = 0;
private static final int KEY_USAGE_BIT1 = 1;
private static final int KEY_USAGE_BIT2 = 2;
private static final int KEY_USAGE_BIT3 = 3;
private static final int KEY_USAGE_BIT4 = 4;
private static final int KEY_USAGE_BIT5 = 5;
private static final int KEY_USAGE_BIT6 = 6;
private static final int KEY_USAGE_BIT7 = 7;
private static final int KEY_USAGE_BIT8 = 8;
private static final String KEY_USAGE_DS = "DIGITAL SIGNATURE";
private static final String KEY_USAGE_NR = "NON-REPUDIATION";
private static final String KEY_USAGE_KE = "KEY ENCIPHERMENT";
private static final String KEY_USAGE_DE = "DATA ENCIPHERMENT";
private static final String KEY_USAGE_KA = "KEY AGREEMENT";
private static final String KEY_USAGE_KC = "KEY CERT SIGN";
private static final String KEY_USAGE_CS = "CRL SIGN";
private static final String KEY_USAGE_EO = "ENCIPHER ONLY";
private static final String KEY_USAGE_DO = "DECIPHER ONLY";
private static final String ECDSA_OID = "1.2.840.10045.4.3.2";
private static final String RSA256_OID = "1.2.840.113549.1.1.11";
private static final String RSA384_OID = "1.2.840.113549.1.1.12";
private static final String RSA512_OID = "1.2.840.113549.1.1.13";
private static final String RSA224_OID = "1.2.840.113549.1.1.14";
private static final String RSA256_STRING = "SHA256WithRSA";
private static final String ECDSA_STRING = "SHA256WithECDSA";
private static final Logger LOGGER = LogManager.getLogger(Certificate.class);
@ -196,14 +235,30 @@ public abstract class Certificate extends ArchivableEntity {
* Holds the name of the 'holderSerialNumber' field.
*/
public static final String HOLDER_SERIAL_NUMBER_FIELD = "holderSerialNumber";
@Column(nullable = false, precision = MAX_NUMERIC_PRECISION, scale = 0)
private final BigInteger holderSerialNumber;
private String holderIssuer;
@Column(nullable = true, precision = MAX_NUMERIC_PRECISION, scale = 0)
private final BigInteger authoritySerialNumber;
@SuppressWarnings("PMD.AvoidUsingHardCodedIP") // this is not an IP address; PMD thinks it is
private static final String POLICY_CONSTRAINTS = "2.5.29.36";
// we don't need to persist this, but we don't want to unpack this cert multiple times
@Transient
private X509Certificate parsedX509Cert = null;
private String signatureAlgorithm;
private String publicKeyAlgorithm;
private String keyUsage;
private String extendedKeyUsage;
private byte[] policyConstraints;
private String authorityKeyIdentifier;
private String authorityInfoAccess;
private String crlPoints;
private int publicKeySize;
/**
* Default constructor necessary for Hibernate.
@ -224,6 +279,16 @@ public abstract class Certificate extends ArchivableEntity {
this.certAndTypeHash = 0;
this.holderSerialNumber = BigInteger.ZERO;
this.holderIssuer = null;
this.publicKeyAlgorithm = null;
this.signatureAlgorithm = null;
this.keyUsage = null;
this.extendedKeyUsage = null;
this.policyConstraints = null;
this.authorityKeyIdentifier = null;
this.authorityInfoAccess = null;
this.authoritySerialNumber = BigInteger.ZERO;
this.crlPoints = null;
this.publicKeySize = 0;
}
/**
@ -267,6 +332,7 @@ public abstract class Certificate extends ArchivableEntity {
this.certificateBytes = Base64.decode(possiblePem);
}
AuthorityKeyIdentifier authKeyIdentifier;
this.certificateBytes = trimCertificate(this.certificateBytes);
// Extract certificate data
@ -278,17 +344,42 @@ public abstract class Certificate extends ArchivableEntity {
this.subject = x509Certificate.getSubjectX500Principal().getName();
this.encodedPublicKey = x509Certificate.getPublicKey().getEncoded();
BigInteger publicKeyModulus = getPublicKeyModulus(x509Certificate);
if (publicKeyModulus != null) {
this.publicKeyModulusHexValue = publicKeyModulus.toString(HEX_BASE);
this.publicKeySize = publicKeyModulus.bitLength();
} else {
this.publicKeyModulusHexValue = null;
}
this.publicKeyAlgorithm = x509Certificate.getPublicKey().getAlgorithm();
this.signatureAlgorithm = x509Certificate.getSigAlgName();
this.signature = x509Certificate.getSignature();
this.beginValidity = x509Certificate.getNotBefore();
this.endValidity = x509Certificate.getNotAfter();
this.holderSerialNumber = BigInteger.ZERO;
this.issuerOrganization = getOrganization(this.issuer);
this.subjectOrganization = getOrganization(this.subject);
this.policyConstraints = x509Certificate
.getExtensionValue(POLICY_CONSTRAINTS);
authKeyIdentifier = AuthorityKeyIdentifier
.getInstance((DLSequence) getExtensionValue(
Extension.authorityKeyIdentifier.getId()));
this.authorityInfoAccess = getAuthorityInfoAccess();
this.keyUsage = parseKeyUsage(x509Certificate.getKeyUsage());
this.crlPoints = getCRLDistributionPoint();
try {
if (x509Certificate.getExtendedKeyUsage() != null) {
StringBuilder sb = new StringBuilder();
for (String s : x509Certificate.getExtendedKeyUsage()) {
sb.append(String.format("%s%n", s));
}
this.extendedKeyUsage = sb.toString();
}
} catch (CertificateParsingException ex) {
// do nothing
}
break;
case ATTRIBUTE_CERTIFICATE:
@ -300,6 +391,21 @@ public abstract class Certificate extends ArchivableEntity {
this.subjectOrganization = null;
this.encodedPublicKey = null;
this.publicKeyModulusHexValue = null;
this.publicKeySize = 0;
authKeyIdentifier = AuthorityKeyIdentifier
.fromExtensions(attCertInfo.getExtensions());
switch (attCert.getSignatureAlgorithm().getAlgorithm().getId()) {
case RSA256_OID:
this.signatureAlgorithm = RSA256_STRING;
break;
case ECDSA_OID:
this.signatureAlgorithm = ECDSA_STRING;
break;
default:
break;
}
// Get attribute certificate information
this.serialNumber = attCertInfo.getSerialNumber().getValue();
@ -328,6 +434,18 @@ public abstract class Certificate extends ArchivableEntity {
throw new IllegalArgumentException("Cannot recognize certificate type.");
}
BigInteger authSerialNumber = null;
if (authKeyIdentifier != null) {
this.authorityKeyIdentifier = authKeyIdentifierToString(authKeyIdentifier);
authSerialNumber = authKeyIdentifier.getAuthorityCertSerialNumber();
}
if (authSerialNumber != null) {
this.authoritySerialNumber = authSerialNumber;
} else {
this.authoritySerialNumber = BigInteger.ZERO;
}
this.certificateHash = Arrays.hashCode(this.certificateBytes);
this.certAndTypeHash = Objects.hash(certificateHash, getClass().getSimpleName());
}
@ -441,6 +559,197 @@ public abstract class Certificate extends ArchivableEntity {
return possiblePEM.contains(PEM_HEADER) || possiblePEM.contains(PEM_ATTRIBUTE_HEADER);
}
private String parseKeyUsage(final boolean[] bools) {
StringBuilder sb = new StringBuilder();
if (bools != null) {
for (int i = 0; i < bools.length; i++) {
if (bools[i]) {
sb.append(getKeyUsageString(i));
}
}
}
return sb.toString();
}
/**
* Return the string associated with the boolean slot.
* @param bit associated with the location in the array.
* @return string value of the bit set.
*/
private String getKeyUsageString(final int bit) {
String tempStr = "";
switch (bit) {
case KEY_USAGE_BIT0:
tempStr = String.format("%s%n", KEY_USAGE_DS);
break;
case KEY_USAGE_BIT1:
tempStr = String.format("%s%n", KEY_USAGE_NR);
break;
case KEY_USAGE_BIT2:
tempStr = String.format("%s%n", KEY_USAGE_KE);
break;
case KEY_USAGE_BIT3:
tempStr = String.format("%s%n", KEY_USAGE_DE);
break;
case KEY_USAGE_BIT4:
tempStr = String.format("%s%n", KEY_USAGE_KA);
break;
case KEY_USAGE_BIT5:
tempStr = String.format("%s%n", KEY_USAGE_KC);
break;
case KEY_USAGE_BIT6:
tempStr = String.format("%s%n", KEY_USAGE_CS);
break;
case KEY_USAGE_BIT7:
tempStr = String.format("%s%n", KEY_USAGE_EO);
break;
case KEY_USAGE_BIT8:
tempStr = String.format("%s%n", KEY_USAGE_DO);
break;
default:
break;
}
return tempStr;
}
/**
* Getter for the authorityKeyIdentifier.
* @return the ID's byte representation
*/
private String authKeyIdentifierToString(final AuthorityKeyIdentifier aki) {
String retValue = "";
if (aki != null) {
byte[] keyArray = aki.getKeyIdentifier();
if (keyArray != null) {
retValue = HexUtils.byteArrayToHexString(keyArray);
}
}
return retValue;
}
/**
* Gets the contents of requested OID.
*
* @param oid Object Identifier
* @return ASN1Primitive Content related to the requested OID
* @throws java.io.IOException
*/
private ASN1Primitive getExtensionValue(final String oid) throws IOException {
byte[] extensionValue = getX509Certificate().getExtensionValue(oid);
ASN1Primitive asn1Primitive = null;
ASN1InputStream asn1InputStream = null;
if (extensionValue != null) {
try {
asn1InputStream = new ASN1InputStream(extensionValue);
DEROctetString oct = (DEROctetString) asn1InputStream.readObject();
asn1InputStream.close();
asn1InputStream = new ASN1InputStream(oct.getOctets());
asn1Primitive = asn1InputStream.readObject();
} catch (IOException ioEx) {
LOGGER.error(ioEx);
} finally {
if (asn1InputStream != null) {
asn1InputStream.close();
}
}
}
return asn1Primitive;
}
/**
* Getter for the AuthorityInfoAccess extension value on list format.
*
* @return List Authority info access list
*/
private String getAuthorityInfoAccess() {
StringBuilder sb = new StringBuilder();
try {
byte[] authAccess = getX509Certificate().getExtensionValue(
Extension.authorityInfoAccess.getId());
if (authAccess != null && authAccess.length > 0) {
AuthorityInformationAccess authInfoAccess = AuthorityInformationAccess
.getInstance(X509ExtensionUtil.fromExtensionValue(authAccess));
for (AccessDescription desc : authInfoAccess.getAccessDescriptions()) {
if (desc.getAccessLocation().getTagNo() == GeneralName
.uniformResourceIdentifier) {
sb.append(String.format("%s%n", ((DERIA5String) desc
.getAccessLocation()
.getName())
.getString()));
}
}
}
} catch (IOException ioEx) {
LOGGER.error(ioEx);
}
return sb.toString();
}
/**
* Getter for the CRL Distribution that is reference by the Revocation Locator
* on the portal.
*
* @return A list of URLs that inform the location of the certificate revocation lists
* @throws java.io.IOException
*/
private String getCRLDistributionPoint() throws IOException {
List<String> crlUrls = new ArrayList<>();
ASN1Primitive primitive = getExtensionValue(Extension.cRLDistributionPoints.getId());
StringBuilder sb = new StringBuilder();
if (primitive != null) {
CRLDistPoint crlDistPoint = CRLDistPoint.getInstance(primitive);
DistributionPoint[] distributionPoints = crlDistPoint.getDistributionPoints();
for (DistributionPoint distributionPoint : distributionPoints) {
DistributionPointName dpn = distributionPoint.getDistributionPoint();
// Look for URIs in fullName
if (dpn != null && dpn.getType() == DistributionPointName.FULL_NAME) {
GeneralName[] genNames = GeneralNames.getInstance(dpn.getName())
.getNames();
for (GeneralName genName : genNames) {
if (genName.getTagNo() == GeneralName.uniformResourceIdentifier) {
String url = DERIA5String.getInstance(genName.getName())
.getString();
crlUrls.add(url);
}
}
}
}
}
for (String s : crlUrls) {
sb.append(String.format("%s%n", s));
}
return sb.toString();
}
/**
* Getter for the x509 Platform Certificate version.
* @return a big integer representing the certificate version. If there
* is an error, return the max value to visible show error.
*/
public int getX509CredentialVersion() {
try {
return getX509Certificate().getVersion() - 1;
} catch (IOException ex) {
LOGGER.warn("X509 Credential Version not found.");
LOGGER.error(ex);
return Integer.MAX_VALUE;
}
}
/**
* Checks if another certificate is the issuer for this certificate.
*
@ -548,6 +857,76 @@ public abstract class Certificate extends ArchivableEntity {
}
/**
* Getter for the Authority Info Access List.
* @return return a list of Info Access
*/
public String getAuthInfoAccess() {
return authorityInfoAccess;
}
/**
* Getter for the authorityKeyIdentifier.
* @return the ID String
*/
public String getAuthKeyId() {
return authorityKeyIdentifier;
}
/**
* Getter for the CRL Distribution Points.
* @return CRLs
*/
public String getCrlPoints() {
return crlPoints;
}
/**
* Getter for the policy statement.
* @return cloned bit representation of constraints
*/
public byte[] getPolicyConstraints() {
if (policyConstraints != null) {
return policyConstraints.clone();
}
return null;
}
/**
* Getter for the keyUsage info.
* @return key usages
*/
public String getKeyUsage() {
return keyUsage;
}
/**
* Getter for the extended key info.
* @return extended key usages
*/
public String getExtendedKeyUsage() {
return extendedKeyUsage;
}
/**
* Getter for the algorithm.
* @return algorithm for the signature
*/
public String getSignatureAlgorithm() {
return signatureAlgorithm;
}
/**
* Getter for the public key algorithm.
* @return public key algorithm
*/
public String getPublicKeyAlgorithm() {
return publicKeyAlgorithm;
}
/**
* Getter the Certificate's Serial Number.
*
* @return this certificate's serial number
*/
public BigInteger getSerialNumber() {
@ -555,6 +934,17 @@ public abstract class Certificate extends ArchivableEntity {
}
/**
* Getter for the Authority's Serial Number.
*
* @return this Authority's Key ID serial number.
*/
public BigInteger getAuthoritySerialNumber() {
return authoritySerialNumber;
}
/**
* Getter for the Holder's Serial Number.
*
* @return this certificate's holder serial number
*/
public BigInteger getHolderSerialNumber() {
@ -583,6 +973,14 @@ public abstract class Certificate extends ArchivableEntity {
return subject;
}
/**
* Getter for the Public Key Size.
* @return bit count.
*/
public int getPublicKeySize() {
return publicKeySize;
}
/**
* @return this certificate's encoded public key
*/
@ -594,6 +992,14 @@ public abstract class Certificate extends ArchivableEntity {
}
}
/**
* Getter for the hex value.
* @return a string for the public key
*/
public String getPublicKeyModulusHexValue() {
return publicKeyModulusHexValue;
}
/**
* @return this certificate's signature
*/

View File

@ -26,6 +26,13 @@ public class CertificateAuthorityCredential extends Certificate {
@Column
private final byte[] subjectKeyIdentifier;
/*
* this field is part of the TCG CA specification, but has not yet been found in
* manufacturer-provided CAs, and is therefore not currently parsed
*/
@Column
private String credentialType = "TCPA Trusted Platform Module Endorsement";
/**
* This class enables the retrieval of CertificateAuthorityCredentials by their attributes.
*/
@ -99,6 +106,15 @@ public class CertificateAuthorityCredential extends Certificate {
subjectKeyIdentifier = null;
}
/**
* Get the credential type label.
* @return the credential type label.
*/
public String getCredentialType() {
return credentialType;
}
/**
* @return this certificate's subject key identifier.
*/
@ -110,6 +126,7 @@ public class CertificateAuthorityCredential extends Certificate {
}
@Override
@SuppressWarnings("checkstyle:avoidinlineconditionals")
public boolean equals(final Object o) {
if (this == o) {
return true;
@ -123,13 +140,19 @@ public class CertificateAuthorityCredential extends Certificate {
CertificateAuthorityCredential that = (CertificateAuthorityCredential) o;
if (this.credentialType != null ? !credentialType.equals(that.credentialType)
: that.credentialType != null) {
return false;
}
return Arrays.equals(subjectKeyIdentifier, that.subjectKeyIdentifier);
}
@Override
@SuppressWarnings("checkstyle:magicnumber")
@SuppressWarnings({"checkstyle:magicnumber", "checkstyle:avoidinlineconditionals"})
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (credentialType != null ? credentialType.hashCode() : 0);
result = 31 * result + Arrays.hashCode(subjectKeyIdentifier);
return result;
}

View File

@ -7,7 +7,6 @@ import hirs.data.persist.certificate.attributes.URIReference;
import hirs.persist.CertificateManager;
import hirs.persist.CertificateSelector;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
@ -73,6 +72,16 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
private static final String TCG_CREDENTIAL_SPECIFICATION = "2.23.133.2.23";
private static final String PLATFORM_CONFIGURATION_URI = "2.23.133.5.1.3";
private static final String PLATFORM_CONFIGURATION = "2.23.133.5.1.7.1";
private static final String PLATFORM_CONFIGURATION_V2 = "2.23.133.5.1.7.2";
/**
* TCG Platform Specification values
* At this time these are placeholder values.
*/
private static final Map<String, String> TCG_PLATFORM_MAP = new HashMap<String, String>() {{
put("#00000000", "Client");
put("#00000001", "Server");
}};
// number of extra bytes potentially present in a cert header.
private static final int PC_CERT_HEADER_BYTE_COUNT = 8;
@ -395,7 +404,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
* @return the platform specification platform class
*/
public String getPlatformClass() {
return platformClass;
return TCG_PLATFORM_MAP.get(platformClass);
}
/**
@ -557,10 +566,19 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
/**
* Get the x509 Platform Certificate version.
* @return a big integer representing the certificate version.
* @throws IOException when reading the certificate.
*/
public BigInteger getX509CredentialVersion() throws IOException {
return getAttributeCertificate().getAcinfo().getVersion().getValue();
@Override
public int getX509CredentialVersion() {
try {
return getAttributeCertificate()
.getAcinfo()
.getVersion()
.getValue().intValue();
} catch (IOException ex) {
LOGGER.warn("X509 Credential Version not found.");
LOGGER.error(ex);
return Integer.MAX_VALUE;
}
}
/**
@ -604,6 +622,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
new URIReference(attributeSequence));
break;
case PLATFORM_CONFIGURATION:
case PLATFORM_CONFIGURATION_V2:
attributes.put("platformConfiguration",
new PlatformConfiguration(attributeSequence));
break;

View File

@ -9,6 +9,7 @@ import org.bouncycastle.asn1.ASN1Boolean;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERUTF8String;
/**
@ -36,10 +37,12 @@ public class ComponentIdentifier {
private static final int COMPONENT_SERIAL = 0;
private static final int COMPONENT_REVISION = 1;
private static final int COMPONENT_IDENTIFIER = 1;
private static final int COMPONENT_MANUFACTURER_ID = 2;
private static final int FIELD_REPLACEABLE = 3;
private static final int COMPONENT_ADDRESS = 4;
private String componentClass;
private DERUTF8String componentManufacturer;
private DERUTF8String componentModel;
private DERUTF8String componentSerial;
@ -52,6 +55,7 @@ public class ComponentIdentifier {
* Default constructor.
*/
public ComponentIdentifier() {
componentClass = null;
componentManufacturer = null;
componentModel = null;
componentSerial = null;
@ -99,9 +103,21 @@ public class ComponentIdentifier {
throw new IllegalArgumentException("Component identifier do not have required values.");
}
ASN1Sequence componentIdSeq;
int tag = 0;
if (sequence.getObjectAt(tag) instanceof ASN1Sequence) {
componentIdSeq = ASN1Sequence.getInstance(sequence.getObjectAt(tag++));
componentClass = DEROctetString.getInstance(componentIdSeq
.getObjectAt(COMPONENT_IDENTIFIER))
.toString();
} else if (sequence.getObjectAt(tag) instanceof DEROctetString) {
componentClass = sequence.getObjectAt(tag++).toString();
}
//Mandatory values
componentManufacturer = DERUTF8String.getInstance(sequence.getObjectAt(0));
componentModel = DERUTF8String.getInstance(sequence.getObjectAt(1));
componentManufacturer = DERUTF8String.getInstance(sequence.getObjectAt(tag++));
componentModel = DERUTF8String.getInstance(sequence.getObjectAt(tag++));
//Optional values (default to null or empty)
componentSerial = null;
@ -111,7 +127,7 @@ public class ComponentIdentifier {
componentAddress = new ArrayList<>();
//Continue reading the sequence if it does contain more than 2 values
for (int i = 2; i < sequence.size(); i++) {
for (int i = tag; i < sequence.size(); i++) {
ASN1TaggedObject taggedObj = ASN1TaggedObject.getInstance(sequence.getObjectAt(i));
switch (taggedObj.getTagNo()) {
case COMPONENT_SERIAL:
@ -137,6 +153,20 @@ public class ComponentIdentifier {
}
}
/**
* @return the componentClass
*/
public String getComponentClass() {
return componentClass;
}
/**
* @param componentClass the componentClass to set
*/
public void setComponentClass(final String componentClass) {
this.componentClass = componentClass;
}
/**
* @return the componentManufacturer
*/

View File

@ -220,7 +220,7 @@ public class PlatformCredentialTest {
Assert.assertEquals(credential.getMajorVersion(), 1);
Assert.assertEquals(credential.getMinorVersion(), 2);
Assert.assertEquals(credential.getRevisionLevel(), 1);
Assert.assertEquals(credential.getPlatformClass(), "1");
Assert.assertEquals(credential.getPlatformClass(), null);
}
/**
@ -269,7 +269,7 @@ public class PlatformCredentialTest {
Assert.assertEquals(credential.getMajorVersion(), 1);
Assert.assertEquals(credential.getMinorVersion(), 2);
Assert.assertEquals(credential.getRevisionLevel(), 1);
Assert.assertEquals(credential.getPlatformClass(), "1");
Assert.assertEquals(credential.getPlatformClass(), null);
}
/**