diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/manager/CertificateRepository.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/manager/CertificateRepository.java index ee4f5a7a..baf5cfe1 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/manager/CertificateRepository.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/manager/CertificateRepository.java @@ -125,14 +125,14 @@ public interface CertificateRepository extends JpaRepository /** * Query that retrieves a list of issued attestation certificates using the provided device id, - * isLDevID value and sort value. + * ldevID value and sort value. * * @param deviceId device id - * @param isLDevID is it a LDevId + * @param ldevID is it a LDevId * @param sort sort * @return a list of issued attestation certificates */ - List findByDeviceIdAndIsLDevID(UUID deviceId, boolean isLDevID, Sort sort); + List findByDeviceIdAndLdevID(UUID deviceId, boolean ldevID, Sort sort); /** * Query that retrieves a certificates using the provided certificate hash. @@ -142,3 +142,4 @@ public interface CertificateRepository extends JpaRepository */ Certificate findByCertificateHash(int certificateHash); } + diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/IssuedAttestationCertificate.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/IssuedAttestationCertificate.java index 891bf6b1..3ecdf827 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/IssuedAttestationCertificate.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/IssuedAttestationCertificate.java @@ -29,7 +29,7 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate { public static final String AIC_TYPE_LABEL = "TCPA Trusted Platform Identity"; @Column - private boolean isLDevID; + private boolean ldevID; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "ek_id") @@ -45,18 +45,18 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate { * @param certificateBytes the issued certificate bytes * @param endorsementCredential the endorsement credential * @param platformCredentials the platform credentials - * @param isLDevID is LDevId + * @param ldevID is LDevID * @throws IOException if there is a problem extracting information from the certificate */ public IssuedAttestationCertificate(final byte[] certificateBytes, final EndorsementCredential endorsementCredential, final List platformCredentials, - final boolean isLDevID) + final boolean ldevID) throws IOException { super(certificateBytes); this.endorsementCredential = endorsementCredential; this.platformCredentials = new ArrayList<>(platformCredentials); - this.isLDevID = isLDevID; + this.ldevID = ldevID; } /** @@ -65,14 +65,14 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate { * @param certificatePath path to certificate * @param endorsementCredential the endorsement credential * @param platformCredentials the platform credentials - * @param isLDevID is it an LDev ID + * @param ldevID is it an LDevID * @throws IOException if there is a problem extracting information from the certificate */ public IssuedAttestationCertificate(final Path certificatePath, final EndorsementCredential endorsementCredential, final List platformCredentials, - final boolean isLDevID) + final boolean ldevID) throws IOException { - this(readBytes(certificatePath), endorsementCredential, platformCredentials, isLDevID); + this(readBytes(certificatePath), endorsementCredential, platformCredentials, ldevID); } } diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java index db43ae63..087f4be1 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java @@ -23,7 +23,6 @@ import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.asn1.x509.X509Extension; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509v3CertificateBuilder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; @@ -123,14 +122,14 @@ public class AbstractProcessor { // Add signing extension builder.addExtension( - X509Extension.keyUsage, + Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment) ); // Basic constraints builder.addExtension( - X509Extension.basicConstraints, + Extension.basicConstraints, true, new BasicConstraints(false) ); @@ -255,7 +254,7 @@ public class AbstractProcessor { * @param endorsementCredential the endorsement credential used to generate the AC * @param platformCredentials the platform credentials used to generate the AC * @param device the device to which the attestation certificate is tied - * @param isLDevID whether the certificate is a ldevid + * @param ldevID whether the certificate is a ldevid * @return whether the certificate was saved successfully * @throws {@link CertificateProcessingException} if error occurs in persisting the Attestation * Certificate @@ -265,7 +264,7 @@ public class AbstractProcessor { final EndorsementCredential endorsementCredential, final List platformCredentials, final Device device, - final boolean isLDevID) { + final boolean ldevID) { List issuedAc; boolean generateCertificate = true; PolicyRepository scp = getPolicyRepository(); @@ -275,27 +274,27 @@ public class AbstractProcessor { try { // save issued certificate IssuedAttestationCertificate attCert = new IssuedAttestationCertificate( - derEncodedAttestationCertificate, endorsementCredential, platformCredentials, isLDevID); + derEncodedAttestationCertificate, endorsementCredential, platformCredentials, ldevID); if (scp != null) { policySettings = scp.findByName("Default"); Sort sortCriteria = Sort.by(Sort.Direction.DESC, "endValidity"); - issuedAc = certificateRepository.findByDeviceIdAndIsLDevID(device.getId(), isLDevID, + issuedAc = certificateRepository.findByDeviceIdAndLdevID(device.getId(), ldevID, sortCriteria); - generateCertificate = isLDevID ? policySettings.isIssueDevIdCertificate() + generateCertificate = ldevID ? policySettings.isIssueDevIdCertificate() : policySettings.isIssueAttestationCertificate(); if (issuedAc != null && issuedAc.size() > 0 - && (isLDevID ? policySettings.isDevIdExpirationFlag() + && (ldevID ? policySettings.isDevIdExpirationFlag() : policySettings.isGenerateOnExpiration())) { if (issuedAc.get(0).getEndValidity().after(currentDate)) { // so the issued AC is not expired // however are we within the threshold days = ProvisionUtils.daysBetween(currentDate, issuedAc.get(0).getEndValidity()); generateCertificate = - days < Integer.parseInt(isLDevID ? policySettings.getDevIdReissueThreshold() + days < Integer.parseInt(ldevID ? policySettings.getDevIdReissueThreshold() : policySettings.getReissueThreshold()); } } diff --git a/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/AttestationCertificateAuthorityTest.java b/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/AttestationCertificateAuthorityTest.java index 34bc4d4d..b72dec75 100644 --- a/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/AttestationCertificateAuthorityTest.java +++ b/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/AttestationCertificateAuthorityTest.java @@ -19,7 +19,12 @@ import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.TBSCertificate; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Nested; @@ -33,7 +38,6 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource; import javax.crypto.spec.SecretKeySpec; -import javax.security.auth.x500.X500Principal; import java.io.IOException; import java.math.BigInteger; import java.net.URISyntaxException; @@ -53,6 +57,7 @@ import java.security.cert.X509Certificate; import java.security.interfaces.RSAPublicKey; import java.security.spec.MGF1ParameterSpec; import java.util.Calendar; +import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Objects; @@ -61,6 +66,7 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -376,6 +382,37 @@ public class AttestationCertificateAuthorityTest { verifyNoMoreInteractions(certificate, symmetricKey); } + /** + * Creates a self-signed X.509 public-key certificate. + * + * @param pair KeyPair to create the cert for + * @return self-signed X509Certificate + */ + private static X509Certificate createSelfSignedCertificate(final KeyPair pair) { + Security.addProvider(new BouncyCastleProvider()); + final int timeRange = 10000; + X509Certificate cert = null; + try { + + X500Name issuerName = new X500Name("CN=TEST2, OU=TEST2, O=TEST2, C=TEST2"); + X500Name subjectName = new X500Name("CN=TEST, OU=TEST, O=TEST, C=TEST"); + BigInteger serialNumber = BigInteger.ONE; + Date notBefore = new Date(System.currentTimeMillis() - timeRange); + Date notAfter = new Date(System.currentTimeMillis() + timeRange); + X509v3CertificateBuilder builder = + new JcaX509v3CertificateBuilder(issuerName, serialNumber, notBefore, notAfter, + subjectName, pair.getPublic()); + ContentSigner signer = + new JcaContentSignerBuilder("SHA256WithRSA").setProvider("BC").build( + pair.getPrivate()); + return new JcaX509CertificateConverter().setProvider("BC").getCertificate( + builder.build(signer)); + } catch (Exception e) { + fail("Exception occurred while creating a cert", e); + } + return cert; + } + /** * Tests {@link AttestationCertificateAuthority# * AttestationCertificateAuthority(SupplyChainValidationService, PrivateKey, @@ -390,14 +427,13 @@ public class AttestationCertificateAuthorityTest { final String identityProofLabelString = "label"; byte[] identityProofLabel = identityProofLabelString.getBytes(StandardCharsets.UTF_8); byte[] modulus = ((RSAPublicKey) keyPair.getPublic()).getModulus().toByteArray(); - X500Principal principal = new X500Principal("CN=TEST, OU=TEST, O=TEST, C=TEST"); int validDays = 1; // create mocks for testing IdentityProof identityProof = mock(IdentityProof.class); AsymmetricPublicKey asymmetricPublicKey = mock(AsymmetricPublicKey.class); StorePubKey storePubKey = mock(StorePubKey.class); - X509Certificate acaCertificate = mock(X509Certificate.class); + X509Certificate acaCertificate = createSelfSignedCertificate(keyPair); // assign ACA fields ReflectionTestUtils.setField(aca, "validDays", validDays); @@ -406,10 +442,6 @@ public class AttestationCertificateAuthorityTest { // prepare identity proof interactions when(identityProof.getLabel()).thenReturn(identityProofLabel); - // prepare other mocks - when(acaCertificate.getSubjectX500Principal()).thenReturn(principal); - when(acaCertificate.getIssuerX500Principal()).thenReturn(principal); - // perform the test X509Certificate certificate = abstractProcessor.accessGenerateCredential(keyPair.getPublic(), null, @@ -453,7 +485,6 @@ public class AttestationCertificateAuthorityTest { assertEquals(tomorrow.get(Calendar.DATE), afterDate.get(Calendar.DATE)); // validate mock interactions - verify(acaCertificate).getSubjectX500Principal(); verifyNoMoreInteractions(identityProof, asymmetricPublicKey, storePubKey); } diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/PersistenceJPAConfig.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/PersistenceJPAConfig.java index 36ce7d06..3f4d85eb 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/PersistenceJPAConfig.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/PersistenceJPAConfig.java @@ -74,7 +74,7 @@ public class PersistenceJPAConfig implements WebMvcConfigurer { @Value("${server.ssl.key-store-password:''}") private String keyStorePassword; - @Value("${server.ssl.key-alias}") + @Value("${aca.certificates.signing-key-alias}") private String keyAlias; @Autowired diff --git a/HIRS_AttestationCAPortal/src/main/resources/application.properties b/HIRS_AttestationCAPortal/src/main/resources/application.properties index 10706738..5a35bcbc 100644 --- a/HIRS_AttestationCAPortal/src/main/resources/application.properties +++ b/HIRS_AttestationCAPortal/src/main/resources/application.properties @@ -29,10 +29,11 @@ server.ssl.trust-store=/etc/hirs/certificates/HIRS/TrustStore.jks server.ssl.trust-alias=hirs_aca_tls_rsa_3k_sha384 server.ssl.key-store-type=JKS server.ssl.key-store=/etc/hirs/certificates/HIRS/KeyStore.jks -server.ssl.key-alias=HIRS_leaf_ca3_rsa_3k_sha384.pem +server.ssl.key-alias=hirs_aca_tls_rsa_3k_sha384 server.ssl.enabled-protocols=TLSv1.2, TLSv1.3 server.ssl.ciphers=TLS_AES_256_GCM_SHA384, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-RSA-AES256-GCM-SHA384, DHE-RSA-AES256-GCM-SHA384, AES256-GCM-SHA384 # ACA specific default properties +aca.certificates.signing-key-alias=HIRS_leaf_ca3_rsa_3k_sha384 aca.certificates.validity=3652 # Compression settings server.compression.enabled=true diff --git a/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/issued-certificates.jsp b/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/issued-certificates.jsp index c82a00ca..32890436 100644 --- a/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/issued-certificates.jsp +++ b/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/issued-certificates.jsp @@ -53,7 +53,7 @@ } }, { - data: 'isLDevID', + data: 'ldevID', searchable:false, render: function (data, type, full, meta) { if (data === true) { @@ -134,4 +134,4 @@ - \ No newline at end of file +