mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-04-07 11:26:51 +00:00
Merge pull request #327 from nsacyber/issue-308
[#308] Certificate RDN update
This commit is contained in:
commit
20f94b94ec
@ -67,11 +67,11 @@ import javax.crypto.spec.OAEPParameterSpec;
|
||||
import javax.crypto.spec.PSource;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyFactory;
|
||||
@ -411,11 +411,8 @@ public abstract class AbstractAttestationCertificateAuthority
|
||||
// and later tpm20MakeCredential function
|
||||
RSAPublicKey ekPub = parsePublicKey(claim.getEkPublicArea().toByteArray());
|
||||
AppraisalStatus.Status validationResult = AppraisalStatus.Status.FAIL;
|
||||
try {
|
||||
validationResult = doSupplyChainValidation(claim, ekPub);
|
||||
} catch (Exception ex) {
|
||||
LOG.error(ex);
|
||||
}
|
||||
|
||||
validationResult = doSupplyChainValidation(claim, ekPub);
|
||||
if (validationResult == AppraisalStatus.Status.PASS) {
|
||||
|
||||
RSAPublicKey akPub = parsePublicKey(claim.getAkPublicArea().toByteArray());
|
||||
@ -555,19 +552,15 @@ public abstract class AbstractAttestationCertificateAuthority
|
||||
if (request.getQuote() != null && !request.getQuote().isEmpty()) {
|
||||
parseTPMQuote(request.getQuote().toStringUtf8());
|
||||
TPMInfo savedInfo = device.getDeviceInfo().getTPMInfo();
|
||||
TPMInfo tpmInfo = null;
|
||||
try {
|
||||
tpmInfo = new TPMInfo(savedInfo.getTPMMake(),
|
||||
TPMInfo tpmInfo = new TPMInfo(savedInfo.getTPMMake(),
|
||||
savedInfo.getTPMVersionMajor(),
|
||||
savedInfo.getTPMVersionMinor(),
|
||||
savedInfo.getTPMVersionRevMajor(),
|
||||
savedInfo.getTPMVersionRevMinor(),
|
||||
savedInfo.getPcrValues(),
|
||||
this.tpmQuoteHash.getBytes("UTF-8"),
|
||||
this.tpmQuoteSignature.getBytes("UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
this.tpmQuoteHash.getBytes(StandardCharsets.UTF_8),
|
||||
this.tpmQuoteSignature.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
DeviceInfoReport dvReport = new DeviceInfoReport(
|
||||
device.getDeviceInfo().getNetworkInfo(),
|
||||
device.getDeviceInfo().getOSInfo(),
|
||||
@ -859,18 +852,14 @@ public abstract class AbstractAttestationCertificateAuthority
|
||||
|
||||
// Get TPM info, currently unimplemented
|
||||
TPMInfo tpm;
|
||||
try {
|
||||
tpm = new TPMInfo(DeviceInfoReport.NOT_SPECIFIED,
|
||||
(short) 0,
|
||||
(short) 0,
|
||||
(short) 0,
|
||||
(short) 0,
|
||||
this.pcrValues.getBytes("UTF-8"),
|
||||
this.tpmQuoteHash.getBytes("UTF-8"),
|
||||
this.tpmQuoteSignature.getBytes("UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
tpm = new TPMInfo();
|
||||
}
|
||||
tpm = new TPMInfo(DeviceInfoReport.NOT_SPECIFIED,
|
||||
(short) 0,
|
||||
(short) 0,
|
||||
(short) 0,
|
||||
(short) 0,
|
||||
this.pcrValues.getBytes(StandardCharsets.UTF_8),
|
||||
this.tpmQuoteHash.getBytes(StandardCharsets.UTF_8),
|
||||
this.tpmQuoteSignature.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
// Create final report
|
||||
DeviceInfoReport dvReport = new DeviceInfoReport(nw, os, fw, hw, tpm,
|
||||
@ -1272,7 +1261,13 @@ public abstract class AbstractAttestationCertificateAuthority
|
||||
IssuedCertificateAttributeHelper.buildSubjectAlternativeNameFromCerts(
|
||||
endorsementCredential, platformCredentials, deviceName);
|
||||
|
||||
Extension authKeyIdentifier = IssuedCertificateAttributeHelper
|
||||
.buildAuthorityKeyIdentifier(endorsementCredential);
|
||||
|
||||
builder.addExtension(subjectAlternativeName);
|
||||
if (authKeyIdentifier != null) {
|
||||
builder.addExtension(authKeyIdentifier);
|
||||
}
|
||||
// identify cert as an AIK with this extension
|
||||
if (IssuedCertificateAttributeHelper.EXTENDED_KEY_USAGE_EXTENSION != null) {
|
||||
builder.addExtension(IssuedCertificateAttributeHelper.EXTENDED_KEY_USAGE_EXTENSION);
|
||||
|
@ -4,12 +4,14 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||
import org.bouncycastle.asn1.ASN1OctetString;
|
||||
import org.bouncycastle.asn1.DEROctetString;
|
||||
import org.bouncycastle.asn1.DERUTF8String;
|
||||
import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
|
||||
import org.bouncycastle.asn1.x500.RDN;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x500.X500NameBuilder;
|
||||
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
|
||||
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
|
||||
import org.bouncycastle.asn1.x509.Extension;
|
||||
import org.bouncycastle.asn1.x509.Extensions;
|
||||
@ -19,7 +21,6 @@ import org.bouncycastle.asn1.x509.GeneralNamesBuilder;
|
||||
import org.bouncycastle.asn1.x509.KeyPurposeId;
|
||||
import org.bouncycastle.asn1.x509.TBSCertificate;
|
||||
import org.bouncycastle.asn1.x509.AttributeCertificateInfo;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
@ -66,6 +67,31 @@ public final class IssuedCertificateAttributeHelper {
|
||||
// do not construct publicly
|
||||
}
|
||||
|
||||
/**
|
||||
* This method builds the AKI extension that will be stored in the generated
|
||||
* Attestation Issued Certificate.
|
||||
* @param endorsementCredential EK object to pull AKI from.
|
||||
* @return the AKI extension.
|
||||
* @throws IOException on bad get instance for AKI.
|
||||
*/
|
||||
public static Extension buildAuthorityKeyIdentifier(
|
||||
final EndorsementCredential endorsementCredential) throws IOException {
|
||||
if (endorsementCredential == null || endorsementCredential.getX509Certificate() == null) {
|
||||
return null;
|
||||
}
|
||||
byte[] extValue = endorsementCredential.getX509Certificate()
|
||||
.getExtensionValue(Extension.authorityKeyIdentifier.getId());
|
||||
|
||||
if (extValue == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] authExtension = ASN1OctetString.getInstance(extValue).getOctets();
|
||||
AuthorityKeyIdentifier aki = AuthorityKeyIdentifier.getInstance(authExtension);
|
||||
|
||||
return new Extension(Extension.authorityKeyIdentifier, true, aki.getEncoded());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the subject alternative name based on the supplied certificates.
|
||||
* @param endorsementCredential the endorsement credential
|
||||
@ -88,10 +114,8 @@ public final class IssuedCertificateAttributeHelper {
|
||||
// assemble AIK cert SAN, using info from EC and PC
|
||||
X500NameBuilder nameBuilder = new X500NameBuilder();
|
||||
populateEndorsementCredentialAttributes(endorsementCredential, nameBuilder);
|
||||
if (!CollectionUtils.isEmpty(platformCredentials)) {
|
||||
for (PlatformCredential platformCredential : platformCredentials) {
|
||||
populatePlatformCredentialAttributes(platformCredential, nameBuilder);
|
||||
}
|
||||
for (PlatformCredential platformCredential : platformCredentials) {
|
||||
populatePlatformCredentialAttributes(platformCredential, nameBuilder);
|
||||
}
|
||||
|
||||
// add the OID for the TCG-required TPM ID label
|
||||
@ -112,7 +136,7 @@ public final class IssuedCertificateAttributeHelper {
|
||||
private static void populatePlatformCredentialAttributes(
|
||||
final PlatformCredential platformCredential,
|
||||
final X500NameBuilder nameBuilder) throws IOException {
|
||||
if (null == platformCredential) {
|
||||
if (platformCredential == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -134,7 +158,7 @@ public final class IssuedCertificateAttributeHelper {
|
||||
|
||||
private static void populateEndorsementCredentialAttributes(
|
||||
final EndorsementCredential endorsementCredential, final X500NameBuilder nameBuilder) {
|
||||
if (null == endorsementCredential) {
|
||||
if (endorsementCredential == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -16,10 +16,12 @@ import hirs.data.persist.PCRPolicy;
|
||||
import hirs.data.persist.ArchivableEntity;
|
||||
import hirs.tpm.eventlog.TCGEventLog;
|
||||
import hirs.tpm.eventlog.TpmPcrEvent;
|
||||
import hirs.utils.BouncyCastleUtils;
|
||||
import hirs.utils.ReferenceManifestValidator;
|
||||
import hirs.validation.SupplyChainCredentialValidator;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -51,7 +53,6 @@ import hirs.data.persist.ReferenceManifest;
|
||||
import hirs.persist.AppraiserManager;
|
||||
import hirs.persist.CertificateManager;
|
||||
import hirs.persist.ReferenceManifestManager;
|
||||
import hirs.persist.CertificateSelector;
|
||||
import hirs.persist.CrudManager;
|
||||
import hirs.persist.DBManagerException;
|
||||
import hirs.persist.PersistenceConfiguration;
|
||||
@ -803,27 +804,49 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
||||
* certs with an identical subject and issuer org)
|
||||
*
|
||||
* @param credential the credential whose CA chain should be retrieved
|
||||
* @param previouslyQueriedOrganizations a list of organizations to refrain
|
||||
* @param previouslyQueriedSubjects a list of organizations to refrain
|
||||
* from querying
|
||||
* @return a Set containing all relevant CA credentials to the given
|
||||
* certificate's organization
|
||||
*/
|
||||
private Set<CertificateAuthorityCredential> getCaChainRec(
|
||||
final Certificate credential,
|
||||
final Set<String> previouslyQueriedOrganizations
|
||||
) {
|
||||
CertificateSelector<CertificateAuthorityCredential> caSelector
|
||||
= CertificateAuthorityCredential.select(certificateManager)
|
||||
.bySubjectOrganization(credential.getIssuerOrganization());
|
||||
Set<CertificateAuthorityCredential> certAuthsWithMatchingOrg = caSelector.getCertificates();
|
||||
final Set<String> previouslyQueriedSubjects) {
|
||||
CertificateAuthorityCredential skiCA = null;
|
||||
Set<CertificateAuthorityCredential> certAuthsWithMatchingIssuer = new HashSet<>();
|
||||
if (credential.getAuthKeyId() != null
|
||||
&& !credential.getAuthKeyId().isEmpty()) {
|
||||
byte[] bytes = Hex.decode(credential.getAuthKeyId());
|
||||
skiCA = CertificateAuthorityCredential
|
||||
.select(certificateManager)
|
||||
.bySubjectKeyIdentifier(bytes).getCertificate();
|
||||
}
|
||||
|
||||
Set<String> queriedOrganizations = new HashSet<>(previouslyQueriedOrganizations);
|
||||
queriedOrganizations.add(credential.getIssuerOrganization());
|
||||
if (skiCA == null) {
|
||||
if (credential.getIssuerSorted() == null
|
||||
|| credential.getIssuerSorted().isEmpty()) {
|
||||
certAuthsWithMatchingIssuer = CertificateAuthorityCredential
|
||||
.select(certificateManager)
|
||||
.bySubject(credential.getIssuer())
|
||||
.getCertificates();
|
||||
} else {
|
||||
//Get certificates by subject organization
|
||||
certAuthsWithMatchingIssuer = CertificateAuthorityCredential
|
||||
.select(certificateManager)
|
||||
.bySubjectSorted(credential.getIssuerSorted())
|
||||
.getCertificates();
|
||||
}
|
||||
} else {
|
||||
certAuthsWithMatchingIssuer.add(skiCA);
|
||||
}
|
||||
Set<String> queriedOrganizations = new HashSet<>(previouslyQueriedSubjects);
|
||||
queriedOrganizations.add(credential.getIssuer());
|
||||
|
||||
HashSet<CertificateAuthorityCredential> caCreds = new HashSet<>();
|
||||
for (CertificateAuthorityCredential cred : certAuthsWithMatchingOrg) {
|
||||
for (CertificateAuthorityCredential cred : certAuthsWithMatchingIssuer) {
|
||||
caCreds.add(cred);
|
||||
if (!queriedOrganizations.contains(cred.getIssuerOrganization())) {
|
||||
if (!BouncyCastleUtils.x500NameCompare(cred.getIssuer(),
|
||||
cred.getSubject())) {
|
||||
caCreds.addAll(getCaChainRec(cred, queriedOrganizations));
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ public class SupplyChainValidationServiceImplTest extends SpringPersistenceTest
|
||||
// mock endorsement credential
|
||||
ec = mock(EndorsementCredential.class);
|
||||
when(ec.getEncodedPublicKey()).thenReturn(new byte[] {0x0});
|
||||
when(ec.getIssuerOrganization()).thenReturn("STMicroelectronics NV");
|
||||
when(ec.getIssuerSorted()).thenReturn("STMicroelectronics NV");
|
||||
|
||||
Set<Certificate> resultEcs = new HashSet<>();
|
||||
resultEcs.add(ec);
|
||||
@ -131,8 +131,8 @@ public class SupplyChainValidationServiceImplTest extends SpringPersistenceTest
|
||||
when(pc.getX509Certificate()).thenReturn(cert);
|
||||
when(pc.getSerialNumber()).thenReturn(BigInteger.ONE);
|
||||
when(pc.getPlatformSerial()).thenReturn(String.valueOf(Integer.MIN_VALUE));
|
||||
when(pc.getIssuerOrganization()).thenReturn("STMicroelectronics NV");
|
||||
when(ec.getSubjectOrganization()).thenReturn("STMicroelectronics NV");
|
||||
when(pc.getIssuerSorted()).thenReturn("STMicroelectronics NV");
|
||||
when(ec.getSubjectSorted()).thenReturn("STMicroelectronics NV");
|
||||
pcs = new HashSet<PlatformCredential>();
|
||||
pcs.add(pc);
|
||||
|
||||
@ -142,8 +142,8 @@ public class SupplyChainValidationServiceImplTest extends SpringPersistenceTest
|
||||
when(delta.getId()).thenReturn(UUID.randomUUID());
|
||||
when(delta.getX509Certificate()).thenReturn(deltaCert);
|
||||
//when(delta.getSerialNumber()).thenReturn(BigInteger.ONE);
|
||||
when(delta.getIssuerOrganization()).thenReturn("STMicroelectronics NV");
|
||||
when(delta.getSubjectOrganization()).thenReturn("STMicroelectronics NV");
|
||||
when(delta.getIssuerSorted()).thenReturn("STMicroelectronics NV");
|
||||
when(delta.getSubjectSorted()).thenReturn("STMicroelectronics NV");
|
||||
|
||||
Set<Certificate> resultPcs = new HashSet<>();
|
||||
resultPcs.add(pc);
|
||||
|
@ -7,6 +7,7 @@ import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.Comparator;
|
||||
@ -21,6 +22,8 @@ import hirs.data.persist.certificate.attributes.ComponentIdentifier;
|
||||
import hirs.data.persist.certificate.attributes.PlatformConfiguration;
|
||||
import hirs.persist.CertificateManager;
|
||||
import hirs.utils.BouncyCastleUtils;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
@ -134,20 +137,35 @@ public final class CertificateStringMapBuilder {
|
||||
public static Certificate containsAllChain(
|
||||
final Certificate certificate,
|
||||
final CertificateManager certificateManager) {
|
||||
|
||||
Set<CertificateAuthorityCredential> issuerCertificates;
|
||||
Set<CertificateAuthorityCredential> issuerCertificates = new HashSet<>();
|
||||
CertificateAuthorityCredential skiCA = null;
|
||||
//Check if there is a subject organization
|
||||
if (certificate.getIssuerOrganization() == null
|
||||
|| certificate.getIssuerOrganization().isEmpty()) {
|
||||
//Get certificates by subject
|
||||
issuerCertificates = CertificateAuthorityCredential.select(certificateManager)
|
||||
.bySubject(certificate.getIssuer())
|
||||
.getCertificates();
|
||||
if (certificate.getAuthKeyId() != null
|
||||
&& !certificate.getAuthKeyId().isEmpty()) {
|
||||
byte[] bytes = Hex.decode(certificate.getAuthKeyId());
|
||||
skiCA = CertificateAuthorityCredential
|
||||
.select(certificateManager)
|
||||
.bySubjectKeyIdentifier(bytes).getCertificate();
|
||||
} else {
|
||||
//Get certificates by subject organization
|
||||
issuerCertificates = CertificateAuthorityCredential.select(certificateManager)
|
||||
.bySubjectOrganization(certificate.getIssuerOrganization())
|
||||
.getCertificates();
|
||||
LOGGER.info(String.format("Certificate (%s) for %s has no authority key identifier.",
|
||||
certificate.getClass().toString(), certificate.getSubject()));
|
||||
}
|
||||
|
||||
if (skiCA == null) {
|
||||
if (certificate.getIssuerSorted() == null
|
||||
|| certificate.getIssuerSorted().isEmpty()) {
|
||||
//Get certificates by subject
|
||||
issuerCertificates = CertificateAuthorityCredential.select(certificateManager)
|
||||
.bySubject(certificate.getIssuer())
|
||||
.getCertificates();
|
||||
} else {
|
||||
//Get certificates by subject organization
|
||||
issuerCertificates = CertificateAuthorityCredential.select(certificateManager)
|
||||
.bySubjectSorted(certificate.getIssuerSorted())
|
||||
.getCertificates();
|
||||
}
|
||||
} else {
|
||||
issuerCertificates.add(skiCA);
|
||||
}
|
||||
|
||||
for (Certificate issuerCert : issuerCertificates) {
|
||||
|
@ -130,7 +130,7 @@ int provision() {
|
||||
RestfulClientProvisioner provisioner;
|
||||
string nonceBlob = provisioner.sendIdentityClaim(identityClaim);
|
||||
if (nonceBlob == "") {
|
||||
cout << "----> Provisioning failed.";
|
||||
cout << "----> Provisioning failed." << endl;
|
||||
cout << "Please refer to the Attestation CA for details." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.cert.CertificateException;
|
||||
@ -362,7 +363,7 @@ public class DeviceInfoCollector extends AbstractCollector {
|
||||
if (debianRelease.exists()) {
|
||||
try {
|
||||
reader = new BufferedReader(new InputStreamReader(
|
||||
new FileInputStream(debianRelease), "UTF-8"));
|
||||
new FileInputStream(debianRelease), StandardCharsets.UTF_8));
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String[] ubuntuTokens = line.split("=");
|
||||
if (ubuntuTokens.length == 2) {
|
||||
@ -394,7 +395,7 @@ public class DeviceInfoCollector extends AbstractCollector {
|
||||
} else if (redhatRelease.exists()) {
|
||||
try {
|
||||
reader = new BufferedReader(new InputStreamReader(
|
||||
new FileInputStream(redhatRelease), "UTF-8"));
|
||||
new FileInputStream(redhatRelease), StandardCharsets.UTF_8));
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String[] redhatTokens = line.split("release");
|
||||
if (redhatTokens.length == 2) {
|
||||
@ -543,7 +544,7 @@ public class DeviceInfoCollector extends AbstractCollector {
|
||||
Process quoteProcess = processBuilder.start();
|
||||
quoteReader
|
||||
= new BufferedReader(new InputStreamReader(
|
||||
quoteProcess.getInputStream(), "utf-8"));
|
||||
quoteProcess.getInputStream(), StandardCharsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
LOGGER.info("IOException occurred while attempting to read "
|
||||
+ "tpm_version command, assume the TPM is not present and "
|
||||
|
@ -12,7 +12,7 @@ import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
|
||||
@ -100,8 +100,7 @@ public final class PCRPolicy extends Policy {
|
||||
LOGGER.info("Validating quote from associated device.");
|
||||
boolean validated = false;
|
||||
short localityAtRelease = 0;
|
||||
Charset charset = Charset.forName("UTF-8");
|
||||
String quoteString = new String(tpmQuote, charset);
|
||||
String quoteString = new String(tpmQuote, StandardCharsets.UTF_8);
|
||||
|
||||
TPMMeasurementRecord[] measurements = new TPMMeasurementRecord[baselinePcrs.length];
|
||||
try {
|
||||
|
@ -12,9 +12,6 @@ import org.bouncycastle.asn1.ASN1Integer;
|
||||
import org.bouncycastle.asn1.ASN1Primitive;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x500.style.RFC4519Style;
|
||||
import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
|
||||
import org.bouncycastle.asn1.x500.RDN;
|
||||
import org.bouncycastle.asn1.x509.AttributeCertificate;
|
||||
import org.bouncycastle.asn1.x509.AttributeCertificateInfo;
|
||||
import org.bouncycastle.asn1.x509.AttCertIssuer;
|
||||
@ -62,8 +59,10 @@ import java.security.cert.X509Certificate;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Objects;
|
||||
import org.bouncycastle.asn1.x509.CRLDistPoint;
|
||||
import org.bouncycastle.asn1.x509.DistributionPoint;
|
||||
@ -163,6 +162,12 @@ public abstract class Certificate extends ArchivableEntity {
|
||||
public static final String ISSUER_FIELD = "issuer";
|
||||
@Column(nullable = false)
|
||||
private final String issuer;
|
||||
/**
|
||||
* Holds the name of the 'issuerSorted' field.
|
||||
*/
|
||||
public static final String ISSUER_SORTED_FIELD = "issuerSorted";
|
||||
@Column
|
||||
private final String issuerSorted;
|
||||
|
||||
/**
|
||||
* Holds the name of the 'subject' field.
|
||||
@ -170,20 +175,12 @@ public abstract class Certificate extends ArchivableEntity {
|
||||
public static final String SUBJECT_FIELD = "subject";
|
||||
@Column(nullable = true)
|
||||
private final String subject;
|
||||
|
||||
/**
|
||||
* Holds the name of the 'issuerOrganization' field.
|
||||
* Holds the name of the 'subjectSorted' field.
|
||||
*/
|
||||
public static final String ISSUER_ORGANIZATION_FIELD = "issuerOrganization";
|
||||
public static final String SUBJECT_SORTED_FIELD = "subjectSorted";
|
||||
@Column
|
||||
private String issuerOrganization = null;
|
||||
|
||||
/**
|
||||
* Holds the name of the 'subjectOrganization' field.
|
||||
*/
|
||||
public static final String SUBJECT_ORGANIZATION_FIELD = "subjectOrganization";
|
||||
@Column
|
||||
private String subjectOrganization = null;
|
||||
private final String subjectSorted;
|
||||
|
||||
/**
|
||||
* Holds the name of the 'encodedPublicKey' field.
|
||||
@ -255,12 +252,15 @@ public abstract class Certificate extends ArchivableEntity {
|
||||
private String keyUsage;
|
||||
private String extendedKeyUsage;
|
||||
private byte[] policyConstraints;
|
||||
/**
|
||||
* Holds the name of the 'authorityKeyIdentifier' field.
|
||||
*/
|
||||
public static final String AUTHORITY_KEY_ID_FIELD = "authorityKeyIdentifier";
|
||||
private String authorityKeyIdentifier;
|
||||
private String authorityInfoAccess;
|
||||
private String crlPoints;
|
||||
private int publicKeySize;
|
||||
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
@ -269,6 +269,8 @@ public abstract class Certificate extends ArchivableEntity {
|
||||
this.serialNumber = BigInteger.ZERO;
|
||||
this.issuer = null;
|
||||
this.subject = null;
|
||||
this.issuerSorted = null;
|
||||
this.subjectSorted = null;
|
||||
|
||||
this.encodedPublicKey = null;
|
||||
this.publicKeyModulusHexValue = null;
|
||||
@ -359,8 +361,8 @@ public abstract class Certificate extends ArchivableEntity {
|
||||
this.beginValidity = x509Certificate.getNotBefore();
|
||||
this.endValidity = x509Certificate.getNotAfter();
|
||||
this.holderSerialNumber = BigInteger.ZERO;
|
||||
this.issuerOrganization = getOrganization(this.issuer);
|
||||
this.subjectOrganization = getOrganization(this.subject);
|
||||
this.issuerSorted = parseSortDNs(this.issuer);
|
||||
this.subjectSorted = parseSortDNs(this.subject);
|
||||
this.policyConstraints = x509Certificate
|
||||
.getExtensionValue(POLICY_CONSTRAINTS);
|
||||
authKeyIdentifier = AuthorityKeyIdentifier
|
||||
@ -395,7 +397,7 @@ public abstract class Certificate extends ArchivableEntity {
|
||||
|
||||
// Set null values (Attribute certificates do not have this values)
|
||||
this.subject = null;
|
||||
this.subjectOrganization = null;
|
||||
this.subjectSorted = null;
|
||||
this.encodedPublicKey = null;
|
||||
this.publicKeyModulusHexValue = null;
|
||||
this.publicKeySize = 0;
|
||||
@ -434,7 +436,7 @@ public abstract class Certificate extends ArchivableEntity {
|
||||
this.signature = attCert.getSignatureValue().getBytes();
|
||||
this.issuer = getAttributeCertificateIssuerNames(
|
||||
attCertInfo.getIssuer())[0].toString();
|
||||
this.issuerOrganization = getOrganization(this.issuer);
|
||||
this.issuerSorted = parseSortDNs(this.issuer);
|
||||
|
||||
// Parse notBefore and notAfter dates
|
||||
this.beginValidity = recoverDate(attCertInfo
|
||||
@ -536,39 +538,6 @@ public abstract class Certificate extends ArchivableEntity {
|
||||
return CertificateType.INVALID_CERTIFICATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the organization field out of a distinguished name. Returns null if
|
||||
* no organization field exists.
|
||||
* @param distinguishedName distinguished name to extract the organization from
|
||||
* @return the value of the organization field
|
||||
*/
|
||||
protected static String getOrganization(final String distinguishedName) {
|
||||
String organization = null;
|
||||
|
||||
// Return null for empty strings
|
||||
if (distinguishedName.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Parse string to X500Name
|
||||
X500Name name = new X500Name(distinguishedName);
|
||||
if (name.getRDNs(RFC4519Style.o).length > 0) {
|
||||
RDN rdn = name.getRDNs(RFC4519Style.o)[0];
|
||||
// For multivalue check the RDNs Attributes
|
||||
if (rdn.isMultiValued()) {
|
||||
for (AttributeTypeAndValue att: rdn.getTypesAndValues()) {
|
||||
if (RFC4519Style.o.equals(att.getType())) {
|
||||
organization = att.getValue().toString();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
organization = rdn.getFirst().getValue().toString();
|
||||
}
|
||||
}
|
||||
|
||||
return organization;
|
||||
}
|
||||
|
||||
private boolean isPEM(final String possiblePEM) {
|
||||
return possiblePEM.contains(PEM_HEADER) || possiblePEM.contains(PEM_ATTRIBUTE_HEADER);
|
||||
}
|
||||
@ -785,41 +754,39 @@ public abstract class Certificate extends ArchivableEntity {
|
||||
* @throws IOException if there is an issue deserializing either certificate
|
||||
*/
|
||||
public boolean isIssuer(final Certificate issuer) throws IOException {
|
||||
CertificateType cType = issuer.getCertificateType();
|
||||
if (cType != CertificateType.X509_CERTIFICATE) {
|
||||
throw new IllegalArgumentException("issuer cert must be X509Certificate");
|
||||
}
|
||||
|
||||
boolean isIssuer = false;
|
||||
X509Certificate issuerX509 = issuer.getX509Certificate();
|
||||
|
||||
// Validate if it's the issuer
|
||||
switch (getCertificateType()) {
|
||||
case X509_CERTIFICATE:
|
||||
X509Certificate certX509 = getX509Certificate();
|
||||
try {
|
||||
certX509.verify(issuerX509.getPublicKey());
|
||||
isIssuer = true;
|
||||
} catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException
|
||||
| NoSuchProviderException | SignatureException e) {
|
||||
LOGGER.error(e);
|
||||
}
|
||||
break;
|
||||
|
||||
case ATTRIBUTE_CERTIFICATE:
|
||||
AttributeCertificate attCert = getAttributeCertificate();
|
||||
String algorith = "SHA256withRSA";
|
||||
try {
|
||||
Signature sig = Signature.getInstance(algorith);
|
||||
sig.initVerify(issuerX509.getPublicKey());
|
||||
sig.update(attCert.getAcinfo().getEncoded());
|
||||
isIssuer = sig.verify(attCert.getSignatureValue().getBytes());
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
|
||||
LOGGER.error(e);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
// only run if of the correct type, otherwise false
|
||||
if (issuer.getCertificateType() == CertificateType.X509_CERTIFICATE) {
|
||||
X509Certificate issuerX509 = issuer.getX509Certificate();
|
||||
// Validate if it's the issuer
|
||||
switch (getCertificateType()) {
|
||||
case X509_CERTIFICATE:
|
||||
X509Certificate certX509 = getX509Certificate();
|
||||
try {
|
||||
certX509.verify(issuerX509.getPublicKey());
|
||||
isIssuer = true;
|
||||
} catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException
|
||||
| NoSuchProviderException | SignatureException e) {
|
||||
LOGGER.error(e);
|
||||
}
|
||||
break;
|
||||
case ATTRIBUTE_CERTIFICATE:
|
||||
AttributeCertificate attCert = getAttributeCertificate();
|
||||
String algorithm = "SHA256withRSA";
|
||||
try {
|
||||
Signature sig = Signature.getInstance(algorithm);
|
||||
sig.initVerify(issuerX509.getPublicKey());
|
||||
sig.update(attCert.getAcinfo().getEncoded());
|
||||
isIssuer = sig.verify(attCert.getSignatureValue().getBytes());
|
||||
} catch (NoSuchAlgorithmException
|
||||
| InvalidKeyException
|
||||
| SignatureException e) {
|
||||
LOGGER.error(e);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return isIssuer;
|
||||
@ -1055,17 +1022,17 @@ public abstract class Certificate extends ArchivableEntity {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return this certificate's associated issuer organization
|
||||
* @return this certificate's associated issuer sorted
|
||||
*/
|
||||
public String getIssuerOrganization() {
|
||||
return issuerOrganization;
|
||||
public String getIssuerSorted() {
|
||||
return issuerSorted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return this certificate's associated subject organization
|
||||
* @return this certificate's associated subject sorted
|
||||
*/
|
||||
public String getSubjectOrganization() {
|
||||
return subjectOrganization;
|
||||
public String getSubjectSorted() {
|
||||
return subjectSorted;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1187,6 +1154,36 @@ public abstract class Certificate extends ArchivableEntity {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to take the DNs from certificates and sort them in an order
|
||||
* that will be used to lookup issuer certificates. This will not be stored in
|
||||
* the certificate, just the DB for lookup.
|
||||
* @param distinguishedName the original DN string.
|
||||
* @return a modified string of sorted DNs
|
||||
*/
|
||||
public static String parseSortDNs(final String distinguishedName) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String dnsString;
|
||||
|
||||
if (distinguishedName == null || distinguishedName.isEmpty()) {
|
||||
sb.append("BLANK");
|
||||
} else {
|
||||
dnsString = distinguishedName.trim();
|
||||
dnsString = dnsString.toLowerCase();
|
||||
List<String> dnValArray = Arrays.asList(dnsString.split(","));
|
||||
Collections.sort(dnValArray);
|
||||
ListIterator<String> dnListIter = dnValArray.listIterator();
|
||||
while (dnListIter.hasNext()) {
|
||||
sb.append(dnListIter.next());
|
||||
if (dnListIter.hasNext()) {
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the X509 Name array from the issuer in an Attribute Certificate.
|
||||
*
|
||||
|
@ -2,6 +2,7 @@ package hirs.data.persist.certificate;
|
||||
|
||||
import hirs.persist.CertificateManager;
|
||||
import hirs.persist.CertificateSelector;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
@ -15,7 +16,8 @@ import java.util.Arrays;
|
||||
*/
|
||||
@Entity
|
||||
public class CertificateAuthorityCredential extends Certificate {
|
||||
@SuppressWarnings("PMD.AvoidUsingHardCodedIP") // this is not an IP address; PMD thinks it is
|
||||
|
||||
@SuppressWarnings("PMD.AvoidUsingHardCodedIP")
|
||||
private static final String SUBJECT_KEY_IDENTIFIER_EXTENSION = "2.5.29.14";
|
||||
|
||||
/**
|
||||
@ -26,9 +28,12 @@ public class CertificateAuthorityCredential extends Certificate {
|
||||
@Column
|
||||
private final byte[] subjectKeyIdentifier;
|
||||
|
||||
/*
|
||||
@Column
|
||||
private String subjectKeyIdString;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* manufacturer-provided CAs, and is therefore not currently parsed.
|
||||
*/
|
||||
@Column
|
||||
private String credentialType = "TCPA Trusted Platform Module Endorsement";
|
||||
@ -82,6 +87,9 @@ public class CertificateAuthorityCredential extends Certificate {
|
||||
super(certificateBytes);
|
||||
this.subjectKeyIdentifier =
|
||||
getX509Certificate().getExtensionValue(SUBJECT_KEY_IDENTIFIER_EXTENSION);
|
||||
if (this.subjectKeyIdentifier != null) {
|
||||
this.subjectKeyIdString = Hex.encodeHexString(this.subjectKeyIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,12 +127,20 @@ public class CertificateAuthorityCredential extends Certificate {
|
||||
* @return this certificate's subject key identifier.
|
||||
*/
|
||||
public byte[] getSubjectKeyIdentifier() {
|
||||
if (null != subjectKeyIdentifier) {
|
||||
if (subjectKeyIdentifier != null) {
|
||||
return subjectKeyIdentifier.clone();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the string rep of the ID.
|
||||
* @return a string
|
||||
*/
|
||||
public String getSubjectKeyIdString() {
|
||||
return this.subjectKeyIdString;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("checkstyle:avoidinlineconditionals")
|
||||
public boolean equals(final Object o) {
|
||||
|
@ -175,7 +175,8 @@ public abstract class CertificateSelector<T extends Certificate> {
|
||||
public CertificateSelector<T> byIssuer(final String issuer) {
|
||||
Preconditions.checkArgument(
|
||||
StringUtils.isNotEmpty(issuer),
|
||||
"issuer cannot be null or empty."
|
||||
String.format("%s: issuer cannot be null or empty.",
|
||||
this.certificateClass.toString())
|
||||
);
|
||||
|
||||
setFieldValue(Certificate.ISSUER_FIELD, issuer);
|
||||
@ -192,7 +193,8 @@ public abstract class CertificateSelector<T extends Certificate> {
|
||||
public CertificateSelector<T> bySubject(final String subject) {
|
||||
Preconditions.checkArgument(
|
||||
StringUtils.isNotEmpty(subject),
|
||||
"subject cannot be null or empty."
|
||||
String.format("%s: subject cannot be null or empty.",
|
||||
this.certificateClass.toString())
|
||||
);
|
||||
|
||||
setFieldValue(Certificate.SUBJECT_FIELD, subject);
|
||||
@ -200,36 +202,38 @@ public abstract class CertificateSelector<T extends Certificate> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify an issuer organization string that certificates must have to be considered
|
||||
* Specify the sorted issuer string that certificates must have to be considered
|
||||
* as matching.
|
||||
*
|
||||
* @param organization certificate issuer organization string to query, not empty or null
|
||||
* @param issuerSorted certificate issuer organization string to query, not empty or null
|
||||
* @return this instance (for chaining further calls)
|
||||
*/
|
||||
public CertificateSelector<T> byIssuerOrganization(final String organization) {
|
||||
public CertificateSelector<T> byIssuerSorted(final String issuerSorted) {
|
||||
Preconditions.checkArgument(
|
||||
StringUtils.isNotEmpty(organization),
|
||||
"organization cannot be null or empty."
|
||||
StringUtils.isNotEmpty(issuerSorted),
|
||||
String.format("%s: issuerSorted cannot be null or empty.",
|
||||
this.certificateClass.toString())
|
||||
);
|
||||
|
||||
setFieldValue(Certificate.ISSUER_ORGANIZATION_FIELD, organization);
|
||||
setFieldValue(Certificate.ISSUER_SORTED_FIELD, issuerSorted);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a subject organization string that certificates must have to be considered
|
||||
* Specify the sorted subject string that certificates must have to be considered
|
||||
* as matching.
|
||||
*
|
||||
* @param organization certificate subject organization string to query, not empty or null
|
||||
* @param subjectSorted certificate subject organization string to query, not empty or null
|
||||
* @return this instance (for chaining further calls)
|
||||
*/
|
||||
public CertificateSelector<T> bySubjectOrganization(final String organization) {
|
||||
public CertificateSelector<T> bySubjectSorted(final String subjectSorted) {
|
||||
Preconditions.checkArgument(
|
||||
StringUtils.isNotEmpty(organization),
|
||||
"organization cannot be null or empty."
|
||||
StringUtils.isNotEmpty(subjectSorted),
|
||||
String.format("%s: subjectSorted cannot be null or empty.",
|
||||
this.certificateClass.toString())
|
||||
);
|
||||
|
||||
setFieldValue(Certificate.SUBJECT_ORGANIZATION_FIELD, organization);
|
||||
setFieldValue(Certificate.SUBJECT_SORTED_FIELD, subjectSorted);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -243,7 +247,8 @@ public abstract class CertificateSelector<T extends Certificate> {
|
||||
public CertificateSelector<T> byEncodedPublicKey(final byte[] encodedPublicKey) {
|
||||
Preconditions.checkArgument(
|
||||
ArrayUtils.isNotEmpty(encodedPublicKey),
|
||||
"publicKey cannot be null or empty."
|
||||
String.format("%s: publicKey cannot be null or empty.",
|
||||
this.certificateClass.toString())
|
||||
);
|
||||
|
||||
setFieldValue(
|
||||
@ -254,6 +259,23 @@ public abstract class CertificateSelector<T extends Certificate> {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the authority key identifier to find certificate(s).
|
||||
* @param authorityKeyIdentifier the string of the AKI associated with the certificate.
|
||||
* @return this instance
|
||||
*/
|
||||
public CertificateSelector<T> byAuthorityKeyIdentifier(final String authorityKeyIdentifier) {
|
||||
Preconditions.checkArgument(
|
||||
StringUtils.isNotEmpty(authorityKeyIdentifier),
|
||||
String.format("%s: authorityKeyIdentifier cannot be null or empty.",
|
||||
this.certificateClass.toString())
|
||||
);
|
||||
|
||||
setFieldValue(Certificate.AUTHORITY_KEY_ID_FIELD, authorityKeyIdentifier);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a public key modulus that certificates must have to be considered
|
||||
* as matching.
|
||||
@ -264,7 +286,8 @@ public abstract class CertificateSelector<T extends Certificate> {
|
||||
public CertificateSelector<T> byPublicKeyModulus(final BigInteger publicKeyModulus) {
|
||||
Preconditions.checkArgument(
|
||||
publicKeyModulus != null,
|
||||
"Public key modulus cannot be null"
|
||||
String.format("%s: Public key modulus cannot be null",
|
||||
this.certificateClass.toString())
|
||||
);
|
||||
|
||||
setFieldValue(
|
||||
@ -428,8 +451,7 @@ public abstract class CertificateSelector<T extends Certificate> {
|
||||
|
||||
// construct and execute query
|
||||
private Set<T> execute() {
|
||||
Set<T> results = certificateManager.get(this);
|
||||
return results;
|
||||
return certificateManager.get(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,8 +2,8 @@ package hirs.tpm.eventlog;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
@ -350,9 +350,8 @@ public final class TCGEventLog {
|
||||
*
|
||||
* @param log The Event Log
|
||||
* @return true if EfiSpecIDEvent is found and indicates that the format is crypto agile
|
||||
* @throws UnsupportedEncodingException if parsing error occurs.
|
||||
*/
|
||||
private boolean isLogCrytoAgile(final byte[] log) throws UnsupportedEncodingException {
|
||||
private boolean isLogCrytoAgile(final byte[] log) {
|
||||
byte[] eType = new byte[UefiConstants.SIZE_4];
|
||||
System.arraycopy(log, UefiConstants.SIZE_4, eType, 0, UefiConstants.SIZE_4);
|
||||
byte[] eventType = HexUtils.leReverseByte(eType);
|
||||
@ -361,8 +360,10 @@ public final class TCGEventLog {
|
||||
return false;
|
||||
} // Event Type should be EV_NO_ACTION
|
||||
byte[] signature = new byte[SIG_SIZE];
|
||||
System.arraycopy(log, SIG_OFFSET, signature, 0, SIG_SIZE); // should be "Spec ID Event03"
|
||||
String sig = new String(signature, "UTF-8").substring(0, SIG_SIZE - 1); // remove null char
|
||||
// should be "Spec ID Event03"
|
||||
System.arraycopy(log, SIG_OFFSET, signature, 0, SIG_SIZE);
|
||||
// remove null char
|
||||
String sig = new String(signature, StandardCharsets.UTF_8).substring(0, SIG_SIZE - 1);
|
||||
|
||||
return sig.equals("Spec ID Event03");
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hirs.tpm.eventlog.events;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import hirs.tpm.eventlog.uefi.UefiConstants;
|
||||
import hirs.utils.HexUtils;
|
||||
@ -38,7 +39,7 @@ public class EvCompactHash {
|
||||
if (event.length == UefiConstants.SIZE_4) { // older PFP defines as 4 byte ESI pointer.
|
||||
eventInfo = " ESI = " + HexUtils.byteArrayToHexString(event);
|
||||
} else { // otherwise assume the event content is a string
|
||||
eventInfo = " " + new String(event, "UTF-8");
|
||||
eventInfo = " " + new String(event, StandardCharsets.UTF_8);
|
||||
}
|
||||
return eventInfo;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package hirs.tpm.eventlog.events;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import hirs.tpm.eventlog.TcgTpmtHa;
|
||||
@ -67,13 +67,13 @@ public class EvEfiSpecIdEvent {
|
||||
/**
|
||||
* EvEfiSpecIdEvent Constructor.
|
||||
* @param efiSpecId byte array holding the spec ID Event.
|
||||
* @throws UnsupportedEncodingException if input fails to parse.
|
||||
*/
|
||||
public EvEfiSpecIdEvent(final byte[] efiSpecId) throws UnsupportedEncodingException {
|
||||
public EvEfiSpecIdEvent(final byte[] efiSpecId) {
|
||||
byte[] signatureBytes = new byte[UefiConstants.SIZE_16];
|
||||
System.arraycopy(efiSpecId, 0, signatureBytes, 0, UefiConstants.SIZE_16);
|
||||
signature = HexUtils.byteArrayToHexString(signatureBytes);
|
||||
signature = new String(signatureBytes, "UTF-8").substring(0, UefiConstants.SIZE_15);
|
||||
signature = new String(signatureBytes, StandardCharsets.UTF_8)
|
||||
.substring(0, UefiConstants.SIZE_15);
|
||||
|
||||
byte[] platformClassBytes = new byte[UefiConstants.SIZE_4];
|
||||
System.arraycopy(efiSpecId, UefiConstants.OFFSET_16, platformClassBytes, 0,
|
||||
@ -167,12 +167,12 @@ public class EvEfiSpecIdEvent {
|
||||
*/
|
||||
public String toString() {
|
||||
String specInfo = "";
|
||||
if (signature == "Spec ID Event#") {
|
||||
if (signature.equals("Spec ID Event#")) {
|
||||
specInfo += "Platform Profile Specification version = " + vMaj + "." + vMin
|
||||
+ " using errata version" + errata;
|
||||
} else {
|
||||
specInfo = "EV_NO_ACTION event named " + signature
|
||||
+ " ecncountered but support for processing it has not been added to this application";
|
||||
+ " encountered but support for processing it has not been added to this application";
|
||||
}
|
||||
return specInfo;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hirs.tpm.eventlog.events;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import hirs.tpm.eventlog.uefi.UefiConstants;
|
||||
import hirs.tpm.eventlog.uefi.UefiGuid;
|
||||
@ -25,10 +26,9 @@ public class EvSCrtmVersion {
|
||||
/**
|
||||
* Checks if event data is null and if not it converts to a String.
|
||||
* @param data byte array holding the vent content.
|
||||
* @throws UnsupportedEncodingException if parsing issues exist.
|
||||
* @return String representation of the version.
|
||||
*/
|
||||
public String sCrtmVersion(final byte[] data) throws UnsupportedEncodingException {
|
||||
public String sCrtmVersion(final byte[] data) {
|
||||
UefiGuid guid = null;
|
||||
if (data == null) {
|
||||
description = "invalid content event data";
|
||||
@ -42,7 +42,7 @@ public class EvSCrtmVersion {
|
||||
} else if (data.length < UefiConstants.SIZE_4) {
|
||||
description = HexUtils.byteArrayToHexString(data);
|
||||
} else if (EvPostCode.isAscii(data)) {
|
||||
description = new String(data, "UTF-8");
|
||||
description = new String(data, StandardCharsets.UTF_8);
|
||||
} else {
|
||||
description = "Unknown Version format";
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hirs.tpm.eventlog.uefi;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import hirs.utils.HexUtils;
|
||||
|
||||
@ -276,10 +277,8 @@ private String hardDriveSubType(final byte[] path, final int offset) {
|
||||
* @param path
|
||||
* @param offset
|
||||
* @return file path info.
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
private String filePathSubType(final byte[] path, final int offset)
|
||||
throws UnsupportedEncodingException {
|
||||
private String filePathSubType(final byte[] path, final int offset) {
|
||||
subType = "File Path = ";
|
||||
byte[] lengthBytes = new byte[UefiConstants.SIZE_2];
|
||||
System.arraycopy(path, 2 + offset, lengthBytes, 0, UefiConstants.SIZE_2);
|
||||
@ -287,7 +286,7 @@ private String filePathSubType(final byte[] path, final int offset)
|
||||
byte[] filePath = new byte[subTypeLength];
|
||||
System.arraycopy(path, UefiConstants.OFFSET_4 + offset, filePath, 0, subTypeLength);
|
||||
byte[] fileName = convertChar16tobyteArray(filePath);
|
||||
subType += new String(fileName, "UTF-8");
|
||||
subType += new String(fileName, StandardCharsets.UTF_8);
|
||||
return subType;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
package hirs.tpm.eventlog.uefi;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import hirs.utils.HexUtils;
|
||||
/**
|
||||
@ -39,9 +39,8 @@ public class UefiPartition {
|
||||
/**
|
||||
* Processes a UEFI defined partition entry.
|
||||
* @param table byte array holding the partition table.
|
||||
* @throws UnsupportedEncodingException if parsing of the data fails.
|
||||
*/
|
||||
public UefiPartition(final byte[] table) throws UnsupportedEncodingException {
|
||||
public UefiPartition(final byte[] table) {
|
||||
byte[] partitionGuidBytes = new byte[UefiConstants.SIZE_16];
|
||||
System.arraycopy(table, 0, partitionGuidBytes, 0, UefiConstants.SIZE_16);
|
||||
partitionTypeGUID = new UefiGuid(partitionGuidBytes);
|
||||
@ -56,7 +55,7 @@ public class UefiPartition {
|
||||
System.arraycopy(table, UefiConstants.PART_NAME_LENGTH, partitionNameBytes,
|
||||
0, UefiConstants.UEFI_PT_LENGTH);
|
||||
byte[] pName = convertChar16tobyteArray(partitionNameBytes);
|
||||
partitionName = new String(pName, "UTF-8").trim();
|
||||
partitionName = new String(pName, StandardCharsets.UTF_8).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,6 +3,7 @@ package hirs.tpm.eventlog.uefi;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
@ -24,7 +25,7 @@ public class UefiVariable {
|
||||
/** UEFI defined variable identifier GUID. */
|
||||
private UefiGuid uefiGuid = null;
|
||||
/** List of Signature lists. */
|
||||
private ArrayList<UefiSignatureList> certSuperList = new ArrayList<UefiSignatureList>();
|
||||
private ArrayList<UefiSignatureList> certSuperList = new ArrayList<>();
|
||||
/** Name of the UEFI variable. */
|
||||
private String varName = "";
|
||||
/** UEFI defined Boot Variable. */
|
||||
@ -70,15 +71,15 @@ public UefiVariable(final byte[] variableData)
|
||||
uefiVaribelData = new byte[variableLength];
|
||||
System.arraycopy(variableData, UefiConstants.OFFSET_32
|
||||
+ nlength * UefiConstants.SIZE_2, uefiVaribelData, 0, variableLength);
|
||||
varName = new String(name, "UTF-8");
|
||||
varName = new String(name, StandardCharsets.UTF_8);
|
||||
String tmpName = varName;
|
||||
if (varName.contains("Boot00")) {
|
||||
tmpName = "Boot00";
|
||||
}
|
||||
switch (tmpName) {
|
||||
case "PK": processSigList(uefiVaribelData); break;
|
||||
case "KEK": processSigList(uefiVaribelData); break;
|
||||
case "db": processSigList(uefiVaribelData); break;
|
||||
case "PK":
|
||||
case "KEK":
|
||||
case "db":
|
||||
case "dbx": processSigList(uefiVaribelData); break;
|
||||
case "Boot00": bootv = new UefiBootVariable(uefiVaribelData); break;
|
||||
case "BootOrder": booto = new UefiBootOrder(uefiVaribelData); break;
|
||||
@ -147,14 +148,15 @@ public String toString() {
|
||||
tmpName = varName;
|
||||
}
|
||||
switch (tmpName) {
|
||||
case "Shim": efiVariable.append(printCert(uefiVaribelData, 0)); break;
|
||||
case "Shim":
|
||||
case "MokList": efiVariable.append(printCert(uefiVaribelData, 0)); break;
|
||||
case "Boot00": efiVariable.append(bootv.toString()); break;
|
||||
case "BootOrder": efiVariable.append(booto.toString()); break;
|
||||
case "SecureBoot": efiVariable.append(sb.toString()); break;
|
||||
default:
|
||||
if (!tmpName.isEmpty()) {
|
||||
efiVariable.append("Data not provided for UEFI variable named " + tmpName + " ");
|
||||
efiVariable.append(String.format("Data not provided for UEFI variable named %s ",
|
||||
tmpName));
|
||||
} else {
|
||||
efiVariable.append("Data not provided ");
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import org.apache.commons.exec.DefaultExecuteResultHandler;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* An implementation of ExecResult that facilitates working with
|
||||
@ -84,7 +85,7 @@ public class AsynchronousExecResult implements ExecResult {
|
||||
checkFinished();
|
||||
|
||||
if (stdOut != null) {
|
||||
return ((ByteArrayOutputStream) stdOut).toString("UTF-8");
|
||||
return ((ByteArrayOutputStream) stdOut).toString(StandardCharsets.UTF_8.toString());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -481,28 +481,6 @@ public class CertificateTest {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that Certificate's getOrganization method can properly parse an organization
|
||||
* from a comma separated RDN.
|
||||
* @throws IOException unable to parse organization
|
||||
*/
|
||||
@Test
|
||||
public void testGetSingleOrganization() throws IOException {
|
||||
String parsedOrg = Certificate.getOrganization(RDN_COMMA_SEPARATED);
|
||||
Assert.assertEquals(RDN_COMMA_SEPARATED_ORGANIZATION, parsedOrg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that Certificate's getOrganization method can properly parse an organization
|
||||
* from a multivalue RDN.
|
||||
* @throws IOException unable to parse organization
|
||||
*/
|
||||
@Test
|
||||
public void testGetMultiRdnOrganization() throws IOException {
|
||||
String parsedOrg = Certificate.getOrganization(RDN_MULTIVALUE);
|
||||
Assert.assertEquals(RDN_MULTIVALUE_ORGANIZATION, parsedOrg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a CertificateAuthorityCredential from the given parameters.
|
||||
*
|
||||
|
@ -100,7 +100,7 @@ public class CertificateSelectorTest extends SpringPersistenceTest {
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testNullByIssuerOrganization() {
|
||||
CertificateAuthorityCredential.select(certMan).byIssuerOrganization(null);
|
||||
CertificateAuthorityCredential.select(certMan).byIssuerSorted(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,6 +108,6 @@ public class CertificateSelectorTest extends SpringPersistenceTest {
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testNullBySubjectOrganization() {
|
||||
CertificateAuthorityCredential.select(certMan).bySubjectOrganization(null);
|
||||
CertificateAuthorityCredential.select(certMan).bySubjectSorted(null);
|
||||
}
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ public class DBCertificateManagerTest extends SpringPersistenceTest {
|
||||
|
||||
Set<CertificateAuthorityCredential> retrievedCerts =
|
||||
CertificateAuthorityCredential.select(certMan)
|
||||
.bySubjectOrganization(stmEkCert.getIssuerOrganization())
|
||||
.bySubjectSorted(stmEkCert.getIssuerSorted())
|
||||
.getCertificates();
|
||||
|
||||
Assert.assertEquals(
|
||||
@ -355,7 +355,7 @@ public class DBCertificateManagerTest extends SpringPersistenceTest {
|
||||
|
||||
Set<CertificateAuthorityCredential> secondRetrievedCerts =
|
||||
CertificateAuthorityCredential.select(certMan)
|
||||
.bySubjectOrganization(stmRootCaCert.getIssuerOrganization())
|
||||
.bySubjectSorted(stmRootCaCert.getIssuerSorted())
|
||||
.getCertificates();
|
||||
|
||||
Assert.assertEquals(
|
||||
@ -380,7 +380,7 @@ public class DBCertificateManagerTest extends SpringPersistenceTest {
|
||||
|
||||
Set<CertificateAuthorityCredential> retrievedCerts =
|
||||
CertificateAuthorityCredential.select(certMan)
|
||||
.byIssuerOrganization(stmRootCaCert.getIssuerOrganization())
|
||||
.byIssuerSorted(stmRootCaCert.getIssuerSorted())
|
||||
.getCertificates();
|
||||
|
||||
Assert.assertEquals(
|
||||
@ -706,7 +706,7 @@ public class DBCertificateManagerTest extends SpringPersistenceTest {
|
||||
|
||||
/**
|
||||
* Tests that a {@link CertificateSelector} can be used to retrieve certificates in various
|
||||
* forms, including {@link Certificate}, {@link X509Certificate}, and {@link KeyStore}.
|
||||
* forms, including {@link Certificate}.
|
||||
*
|
||||
* @throws IOException if there is a problem creating the certificate
|
||||
* @throws KeyStoreException if there is a problem constructing the resultant KeyStore
|
||||
|
Loading…
x
Reference in New Issue
Block a user