issue_847: Fixed the majority of the checkstyle errors in the CAPOrtal module. Need to fix 5 more and figure out why two tests are failing. Merged master into local branch.

This commit is contained in:
TheSilentCoder 2024-10-28 16:55:25 -04:00
parent 6d770e9a63
commit f9da12865b
77 changed files with 39332 additions and 595 deletions

View File

@ -118,7 +118,7 @@ public class AbstractProcessor {
+ "Unable to issue certificates");
}
ContentSigner signer = new JcaContentSignerBuilder("SHA1WithRSA")
ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA")
.setProvider("BC").build(getPrivateKey());
X509CertificateHolder holder = builder.build(signer);
return new JcaX509CertificateConverter()

View File

@ -1,6 +1,5 @@
package hirs.attestationca.persist.provision;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2;
import hirs.attestationca.persist.entity.manager.CertificateRepository;
@ -161,16 +160,14 @@ public class CertificateRequestProcessor extends AbstractProcessor {
attestationCertificate);
byte[] derEncodedLdevidCertificate = ProvisionUtils.getDerEncodedCertificate(
ldevidCertificate);
String pemEncodedAttestationCertificate = ProvisionUtils.getPemEncodedCertificate(
attestationCertificate);
String pemEncodedLdevidCertificate = ProvisionUtils.getPemEncodedCertificate(
ldevidCertificate);
// We validated the nonce and made use of the identity claim so state can be deleted
tpm2ProvisionerStateRepository.delete(tpm2ProvisionerState);
// Package the signed certificates into a response
ByteString certificateBytes = ByteString
.copyFrom(derEncodedAttestationCertificate);
ByteString ldevidCertificateBytes = ByteString
.copyFrom(derEncodedLdevidCertificate);
boolean generateAtt = saveAttestationCertificate(certificateRepository,
derEncodedAttestationCertificate,
endorsementCredential, platformCredentials, device, false);
@ -181,10 +178,10 @@ public class CertificateRequestProcessor extends AbstractProcessor {
ProvisionerTpm2.CertificateResponse.Builder builder = ProvisionerTpm2.CertificateResponse.
newBuilder().setStatus(ProvisionerTpm2.ResponseStatus.PASS);
if (generateAtt) {
builder = builder.setCertificate(certificateBytes);
builder = builder.setCertificate(pemEncodedAttestationCertificate);
}
if (generateLDevID) {
builder = builder.setLdevidCertificate(ldevidCertificateBytes);
builder = builder.setLdevidCertificate(pemEncodedLdevidCertificate);
}
ProvisionerTpm2.CertificateResponse response = builder.build();
@ -192,13 +189,12 @@ public class CertificateRequestProcessor extends AbstractProcessor {
} else {
byte[] derEncodedAttestationCertificate = ProvisionUtils.getDerEncodedCertificate(
attestationCertificate);
String pemEncodedAttestationCertificate = ProvisionUtils.getPemEncodedCertificate(
attestationCertificate);
// We validated the nonce and made use of the identity claim so state can be deleted
tpm2ProvisionerStateRepository.delete(tpm2ProvisionerState);
// Package the signed certificates into a response
ByteString certificateBytes = ByteString
.copyFrom(derEncodedAttestationCertificate);
ProvisionerTpm2.CertificateResponse.Builder builder = ProvisionerTpm2.CertificateResponse.
newBuilder().setStatus(ProvisionerTpm2.ResponseStatus.PASS);
@ -206,7 +202,7 @@ public class CertificateRequestProcessor extends AbstractProcessor {
derEncodedAttestationCertificate,
endorsementCredential, platformCredentials, device, false);
if (generateAtt) {
builder = builder.setCertificate(certificateBytes);
builder = builder.setCertificate(pemEncodedAttestationCertificate);
}
ProvisionerTpm2.CertificateResponse response = builder.build();

View File

@ -16,6 +16,7 @@ import hirs.utils.HexUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.ArrayUtils;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
@ -26,6 +27,8 @@ import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.StringWriter;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
@ -138,6 +141,29 @@ public final class ProvisionUtils {
}
}
/**
* Helper method to extract a PEM encoded certificate from an X509 certificate.
*
* @param certificate the X509 certificate to be converted to PEM encoding
* @throws {@link UnexpectedServerException} if error occurs during encoding retrieval
* @return the string representing the PEM encoded certificate
*/
public static String getPemEncodedCertificate(final X509Certificate certificate) {
try {
final StringWriter stringWriter = new StringWriter();
final JcaPEMWriter pemWriter = new JcaPEMWriter(stringWriter);
pemWriter.writeObject(certificate);
pemWriter.flush();
pemWriter.close();
return stringWriter.toString();
} catch (IOException ioEx) {
log.error("Error converting certificate to PEM Encoding.", ioEx);
throw new UnexpectedServerException(
"Encountered error while converting X509 Certificate to PEM Encoding: "
+ ioEx.getMessage(), ioEx);
}
}
/**
* Parse public key from public data segment generated by TPM 2.0.
*

View File

@ -160,8 +160,9 @@ ospackage {
requires('mariadb-server', '10.3', GREATER | EQUAL)
requires('procps-ng', '3.3.15', GREATER | EQUAL)
requires('alternatives', '1.19', GREATER | EQUAL)
requires('hwdata', '0.314', GREATER | EQUAL)
// Post Trans stage (Occurs after required app and postInstall stage)
// Note postInstall wont wait forrequired apps
// Note postInstall wont wait for required apps
postTrans 'update-alternatives --set java java-17-openjdk.x86_64'
postTrans 'firewall-cmd --add-port=8443/tcp --permanent'
postTrans 'firewall-cmd --reload'
@ -181,6 +182,7 @@ ospackage {
requires('openjdk-17-jdk', '17.0', GREATER | EQUAL)
requires('mariadb-server', '10.3', GREATER | EQUAL)
requires('curl')
requires('hwdata', '0.314', GREATER | EQUAL)
// Install after required packages
postInstall 'bash /opt/hirs/aca/scripts/aca/aca_setup.sh -u'
postInstall 'bash /opt/hirs/aca/scripts/systemd/aca_enable_service.sh'

View File

@ -7,7 +7,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
//@EnableAutoConfiguration
@Log4j2
public class HIRSApplication {//extends SpringBootServletInitializer {
public class HIRSApplication {
//extends SpringBootServletInitializer {
// private static final Logger LOGGER = LogManager.getLogger(HIRSApplication.class);
// @Override
// protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
@ -22,7 +23,10 @@ public class HIRSApplication {//extends SpringBootServletInitializer {
// appServlet.setLoadOnStartup(1);
// }
public static void main(String[] args) {
/**
* @param args
*/
public static void main(final String[] args) {
// SpringApplication springApplication = new SpringApplication(HIRSApplication.class);
// springApplication.setDefaultProperties(Collections.singletonMap("server.servlet.context-path",
// "/portal"));

View File

@ -14,6 +14,11 @@ import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatche
public class HIRSDbInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
implements ServletContextListener {
/**
* Initialize context.
*
* @param servletContextEvent servlet context event.
*/
@Override
public void contextInitialized(final ServletContextEvent servletContextEvent) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
@ -35,6 +40,11 @@ public class HIRSDbInitializer extends AbstractAnnotationConfigDispatcherServlet
}
}
/**
* Retrieves root configuration classes.
*
* @return array of root configuration classes.
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] {
@ -42,11 +52,21 @@ public class HIRSDbInitializer extends AbstractAnnotationConfigDispatcherServlet
};
}
/**
* Retrieves servlet configuration classes.
*
* @return null
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
/**
* Retrieves servlet mappings.
*
* @return string array of servlet mappings.
*/
@Override
protected String[] getServletMappings() {
return new String[] {

View File

@ -80,6 +80,11 @@ public class PersistenceJPAConfig implements WebMvcConfigurer {
@Autowired
private Environment environment;
/**
* Entity manager factory bean.
*
* @return a local container entity manager factory bean
*/
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean entityManagerBean =
@ -94,6 +99,11 @@ public class PersistenceJPAConfig implements WebMvcConfigurer {
return entityManagerBean;
}
/**
* Data source bean.
*
* @return a data source
*/
@Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
@ -213,6 +223,9 @@ public class PersistenceJPAConfig implements WebMvcConfigurer {
}
}
/**
* @return
*/
@Bean
public PlatformTransactionManager transactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
@ -220,6 +233,9 @@ public class PersistenceJPAConfig implements WebMvcConfigurer {
return transactionManager;
}
/**
* @return
*/
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
@ -258,6 +274,11 @@ public class PersistenceJPAConfig implements WebMvcConfigurer {
// }
/**
* Configures the default servlet handling.
*
* @param configurer default servlet handler configurer.
*/
@Override
public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) {
configurer.enable();

View File

@ -3,11 +3,11 @@ package hirs.attestationca.portal.datatables;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
/**
* Java representation of a jQuery DataTables Column.
@ -15,7 +15,8 @@ import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@NoArgsConstructor
@ToString
public class Column {
/**
@ -64,14 +65,4 @@ public class Column {
this.search.setValue(searchValue);
}
@Override
public String toString() {
return "Column{"
+ "data='" + data + '\''
+ ", name='" + name + '\''
+ ", searchable=" + searchable
+ ", orderable=" + orderable
+ ", search=" + search
+ '}';
}
}

View File

@ -3,19 +3,20 @@ package hirs.attestationca.portal.datatables;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
/**
* Represents a column ordering with regards to a jQuery DataTable.
* Represents a column ordering in regard to a jQuery DataTable.
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@NoArgsConstructor
@ToString
public class Order {
@ -53,18 +54,7 @@ public class Order {
* @return true if ascending order, false otherwise.
*/
public boolean isAscending() {
if (dir.equalsIgnoreCase("asc")) {
return true;
}
return false;
}
@Override
public String toString() {
return "Order{"
+ "column=" + column
+ ", dir='" + dir + '\''
+ '}';
return dir.equalsIgnoreCase("asc");
}
}

View File

@ -85,7 +85,8 @@ public final class OrderedListQueryDataTableAdapter<T> {
filteredRecordsList.setRecordsTotal(dbManager.count());
filteredRecordsList.addAll((Collection<? extends T>) dbManager.findAll());
filteredRecordsList.setRecordsFiltered(10);
final int recordsFilteredConstant = 10;
filteredRecordsList.setRecordsFiltered(recordsFilteredConstant);
return filteredRecordsList;
@ -95,6 +96,16 @@ public final class OrderedListQueryDataTableAdapter<T> {
// searchableColumnMap, criteriaModifier);
}
/**
* Retrieves an ordered list of reference digest values.
*
* @param dbManager database manager.
* @param dataTableInput data table input.
* @param orderColumnName string representation of the order column name.
* @param criteriaModifier criteria modifier.
* @param entityManager entity manager.
* @return a filtered, ordered records list of the reference digest values
*/
public static FilteredRecordsList<ReferenceDigestValue> getOrderedList(
final JpaRepository<ReferenceDigestValue, UUID> dbManager,
final DataTableInput dataTableInput,
@ -127,7 +138,8 @@ public final class OrderedListQueryDataTableAdapter<T> {
filteredRecordsList.setRecordsTotal(dbManager.count());
filteredRecordsList.addAll(dbManager.findAll());
filteredRecordsList.setRecordsFiltered(10);
final int recordsFilteredConstant = 10;
filteredRecordsList.setRecordsFiltered(recordsFilteredConstant);
return filteredRecordsList;

View File

@ -1,11 +1,11 @@
package hirs.attestationca.portal.datatables;
import jakarta.validation.constraints.NotNull;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
/**
* Represents a jQuery DataTables search parameter.
@ -13,7 +13,8 @@ import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@NoArgsConstructor
@ToString
public class Search {
/**
@ -38,13 +39,5 @@ public class Search {
public Search(final String value) {
this(value, false);
}
@Override
public String toString() {
return "Search{"
+ "value='" + value + '\''
+ ", regex=" + regex
+ '}';
}
}

View File

@ -15,8 +15,13 @@ import java.util.Map;
@Configuration
public class AnnotationDrivenEndpointsListener {
/**
* Annotation Driven Endpoints event listener.
*
* @param event context refreshed event.
*/
@EventListener
public void handleContextRefresh(ContextRefreshedEvent event) {
public void handleContextRefresh(final ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
RequestMappingHandlerMapping requestMappingHandlerMapping = applicationContext
.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);

View File

@ -110,6 +110,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
* @param endorsementCredentialRepository the endorsement credential manager
* @param issuedCertificateRepository the issued certificate manager
* @param caCredentialRepository the ca credential manager
* @param iDevIDCertificateRepository the IDevID certificate repository
* @param acaCertificate the ACA's X509 certificate
*/
@Autowired
@ -255,11 +256,11 @@ public class CertificatePageController extends PageController<NoPageParams> {
public DataTableResponse<? extends Certificate> getTableData(
@PathVariable("certificateType") final String certificateType,
final DataTableInput input) {
log.debug("Handling list request: " + input);
log.debug("Handling list request: {}", input);
// attempt to get the column property based on the order index.
String orderColumnName = input.getOrderColumnName();
log.debug("Ordering on column: " + orderColumnName);
log.debug("Ordering on column: {}", orderColumnName);
// check that the alert is not archived and that it is in the specified report
CriteriaModifier criteriaModifier = new CriteriaModifier() {
@ -275,9 +276,9 @@ public class CertificatePageController extends PageController<NoPageParams> {
// for getting the device (e.g. device name).
// use left join, since device may be null. Query will return all
// Certs of this type, whether it has a Device or not (device field may be null)
if (hasDeviceTableToJoin(certificateType)) {
// criteria.createAlias("device", "device", JoinType.LEFT_OUTER_JOIN);
}
// if (hasDeviceTableToJoin(certificateType)) {
// criteria.createAlias("device", "device", JoinType.LEFT_OUTER_JOIN);
//}
}
};
@ -305,7 +306,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
if (!records.isEmpty()) {
// loop all the platform certificates
for (int i = 0; i < records.size(); i++) {
PlatformCredential pc = (PlatformCredential) records.get(i);
PlatformCredential pc = records.get(i);
// find the EC using the PC's "holder serial number"
associatedEC = this.endorsementCredentialRepository
.findBySerialNumber(pc.getHolderSerialNumber());
@ -525,11 +526,10 @@ public class CertificatePageController extends PageController<NoPageParams> {
// send a 404 error when invalid certificate
response.sendError(HttpServletResponse.SC_NOT_FOUND);
} else {
StringBuilder fileName = new StringBuilder("filename=\"");
fileName.append(getCertificateClass(certificateType).getSimpleName());
fileName.append("_");
fileName.append(certificate.getSerialNumber());
fileName.append(".cer\"");
String fileName = "filename=\"" + getCertificateClass(certificateType).getSimpleName()
+ "_"
+ certificate.getSerialNumber()
+ ".cer\"";
// Set filename for download.
response.setHeader("Content-Disposition", "attachment;" + fileName);
@ -727,11 +727,8 @@ public class CertificatePageController extends PageController<NoPageParams> {
* table, false otherwise.
*/
private boolean hasDeviceTableToJoin(final String certificateType) {
boolean hasDevice = true;
boolean hasDevice = !certificateType.equals(TRUSTCHAIN);
// Trust_Chain Credential do not contain the device table to join.
if (certificateType.equals(TRUSTCHAIN)) {
hasDevice = false;
}
return hasDevice;
}
@ -806,7 +803,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
final String certificateType,
final MultipartFile file,
final PageMessages messages) {
log.info("Received File of Size: " + file.getSize());
log.info("Received File of Size: {}", file.getSize());
byte[] fileBytes;
String fileName = file.getOriginalFilename();
@ -936,7 +933,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
return;
}
}
} /**else {
} /*else {
// this is a delta, check if the holder exists.
PlatformCredential holderPC = PlatformCredential
.select(certificateManager)
@ -953,7 +950,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
LOGGER.error(failMessage);
return;
}
}**/
}*/
}
this.certificateRepository.save(certificate);

View File

@ -23,8 +23,8 @@ import org.springframework.data.domain.Sort;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
@ -49,6 +49,15 @@ public class DevicePageController extends PageController<NoPageParams> {
private final EndorsementCredentialRepository endorsementCredentialRepository;
private final IssuedCertificateRepository issuedCertificateRepository;
/**
* Device Page Controller constructor.
*
* @param deviceRepository device repository.
* @param certificateRepository certificate repository.
* @param platformCertificateRepository platform certificate repository.
* @param endorsementCredentialRepository endorsement credential repository.
* @param issuedCertificateRepository issued certificate repository.
*/
@Autowired
public DevicePageController(final DeviceRepository deviceRepository,
final CertificateRepository certificateRepository,
@ -63,21 +72,34 @@ public class DevicePageController extends PageController<NoPageParams> {
this.issuedCertificateRepository = issuedCertificateRepository;
}
/**
* Initializes page.
*
* @param params The object to map url parameters into.
* @param model The data model for the request. Can contain data from
* redirect.
* @return model and view
*/
@Override
@RequestMapping
public ModelAndView initPage(final NoPageParams params, final Model model) {
return getBaseModelAndView();
}
/**
* GET request that retrieves table data using the provided data table input.
*
* @param input data table input.
* @return a data table response
*/
@ResponseBody
@RequestMapping(value = "/list",
produces = MediaType.APPLICATION_JSON_VALUE,
method = RequestMethod.GET)
@GetMapping(value = "/list",
produces = MediaType.APPLICATION_JSON_VALUE)
public DataTableResponse<HashMap<String, Object>> getTableData(
final DataTableInput input) {
log.debug("Handling request for device list");
String orderColumnName = input.getOrderColumnName();
log.info("Ordering on column: " + orderColumnName);
log.info("Ordering on column: {}", orderColumnName);
// get all the devices
FilteredRecordsList<Device> deviceList = new FilteredRecordsList<>();

View File

@ -9,8 +9,15 @@ import org.springframework.web.servlet.ModelAndView;
@Controller("error")
public class ErrorController {
/**
* Handles exceptions based on the provided request and exception.
*
* @param request http servlet request.
* @param ex exception.
* @return model and view
*/
@ExceptionHandler(Exception.class)
public ModelAndView handleException(HttpServletRequest request, Exception ex) {
public ModelAndView handleException(final HttpServletRequest request, final Exception ex) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("exception", ex.getLocalizedMessage());

View File

@ -8,6 +8,11 @@ import org.springframework.web.bind.annotation.RestController;
@Log4j2
public class LombokLoggingController {
/**
* REST endpoint that logs various issues regarding Lombok.
*
* @return a message that indicates there are logs regarding Lombok that should be looked at
*/
@RequestMapping("/HIRS_AttestationCAPortal/portal/lombok")
public String index() {
log.trace("A TRACE Message");

View File

@ -98,10 +98,13 @@ public class ReferenceManifestDetailsPageController
* @throws CertificateException if a certificate doesn't parse.
*/
public static HashMap<String, Object> getRimDetailInfo(final UUID uuid,
final ReferenceManifestRepository referenceManifestRepository,
final ReferenceDigestValueRepository referenceDigestValueRepository,
final ReferenceManifestRepository
referenceManifestRepository,
final ReferenceDigestValueRepository
referenceDigestValueRepository,
final CertificateRepository certificateRepository,
final CACredentialRepository caCertificateRepository)
final CACredentialRepository
caCertificateRepository)
throws IOException,
CertificateException, NoSuchAlgorithmException {
HashMap<String, Object> data = new HashMap<>();
@ -297,7 +300,7 @@ public class ReferenceManifestDetailsPageController
* @return list of X509Certificates
*/
private static List<X509Certificate> convertCACsToX509Certificates(
Set<CertificateAuthorityCredential> set)
final Set<CertificateAuthorityCredential> set)
throws IOException {
ArrayList<X509Certificate> certs = new ArrayList<>(set.size());
for (CertificateAuthorityCredential cac : set) {

View File

@ -76,8 +76,10 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
* @param referenceDigestValueRepository this is the reference event manager
*/
@Autowired
public ReferenceManifestPageController(final ReferenceManifestRepository referenceManifestRepository,
final ReferenceDigestValueRepository referenceDigestValueRepository) {
public ReferenceManifestPageController(final ReferenceManifestRepository
referenceManifestRepository,
final ReferenceDigestValueRepository
referenceDigestValueRepository) {
super(Page.REFERENCE_MANIFESTS);
this.referenceManifestRepository = referenceManifestRepository;
this.referenceDigestValueRepository = referenceDigestValueRepository;
@ -111,11 +113,11 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
method = RequestMethod.GET)
public DataTableResponse<ReferenceManifest> getTableData(
@Valid final DataTableInput input) {
log.debug("Handling request for summary list: " + input);
log.debug("Handling request for summary list: {}", input);
String orderColumnName = input.getOrderColumnName();
log.info("Ordering on column: " + orderColumnName);
log.info("Querying with the following dataTableInput: " + input);
log.info("Ordering on column: {}", orderColumnName);
log.info("Querying with the following dataTableInput: {}", input);
FilteredRecordsList<ReferenceManifest> records = new FilteredRecordsList<>();
int currentPage = input.getStart() / input.getLength();
@ -136,7 +138,7 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
records.setRecordsFiltered(referenceManifestRepository.findByArchiveFlag(false).size());
log.debug("Returning list of size: " + records.size());
log.debug("Returning list of size: {}", records.size());
return new DataTableResponse<>(records, input);
}
@ -161,7 +163,7 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
Matcher matcher;
List<BaseReferenceManifest> baseRims = new ArrayList<>();
List<SupportReferenceManifest> supportRims = new ArrayList<>();
log.info(String.format("Processing %s uploaded files", files.length));
log.info("Processing {} uploaded files", files.length);
// loop through the files
for (MultipartFile file : files) {
@ -177,20 +179,22 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
if (isBaseRim || isSupportRim) {
parseRIM(file, isSupportRim, messages, baseRims, supportRims);
} else {
String errorString = "The file extension of " + fileName + " was not recognized." +
" Base RIMs support the extension \".swidtag\", and support RIMs support " +
"\".rimpcr\", \".rimel\", \".bin\", and \".log\". " +
"Please verify your upload and retry.";
log.error("File extension in " + fileName + " not recognized as base or support RIM.");
String errorString = "The file extension of " + fileName + " was not recognized."
+ " Base RIMs support the extension \".swidtag\", and support RIMs support "
+ "\".rimpcr\", \".rimel\", \".bin\", and \".log\". "
+ "Please verify your upload and retry.";
log.error("File extension in {} not recognized as base or support RIM.", fileName);
messages.addError(errorString);
}
}
baseRims.stream().forEach((rim) -> {
log.info(String.format("Storing swidtag %s", rim.getFileName()));
baseRims.forEach((rim) -> {
log.info("Storing swidtag {}", rim.getFileName());
this.referenceManifestRepository.save(rim);
});
supportRims.stream().forEach((rim) -> {
log.info(String.format("Storing event log %s", rim.getFileName()));
supportRims.forEach((rim) -> {
log.info("Storing event log {}", rim.getFileName());
this.referenceManifestRepository.save(rim);
});
@ -225,7 +229,7 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
@RequestMapping(value = "/delete", method = RequestMethod.POST)
public RedirectView delete(@RequestParam final String id,
final RedirectAttributes attr) throws URISyntaxException {
log.info("Handling request to delete " + id);
log.info("Handling request to delete {}", id);
Map<String, Object> model = new HashMap<>();
PageMessages messages = new PageMessages();
@ -270,7 +274,7 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
public void download(@RequestParam final String id,
final HttpServletResponse response)
throws IOException {
log.info("Handling RIM request to download " + id);
log.info("Handling RIM request to download {}", id);
try {
ReferenceManifest referenceManifest = getRimFromDb(id);
@ -359,7 +363,7 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
*
* @param id of the RIM
* @return the associated RIM from the DB
* @throws IllegalArgumentException
* @throws IllegalArgumentException if issues arise from attempting to retrieve the rim from the database
*/
private ReferenceManifest getRimFromDb(final String id) throws IllegalArgumentException {
UUID uuid = UUID.fromString(id);
@ -522,11 +526,7 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
this.referenceDigestValueRepository.save(newRdv);
}
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
} catch (CertificateException | NoSuchAlgorithmException | IOException e) {
e.printStackTrace();
}
} else {

View File

@ -58,9 +58,9 @@ public class ValidationReportsPageController extends PageController<NoPageParams
private static final String DEFAULT_COMPANY = "AllDevices";
private static final String UNDEFINED = "undefined";
private static final String TRUE = "true";
private static String systemColumnHeaders = "Verified Manufacturer,"
private static final String SYSTEM_COLUMN_HEADERS = "Verified Manufacturer,"
+ "Model,SN,Verification Date,Device Status";
private static String componentColumnHeaders = "Component name,Component manufacturer,"
private static final String COMPONENT_COLUMN_HEADERS = "Component name,Component manufacturer,"
+ "Component model,Component SN,Issuer,Component status";
private final SupplyChainValidationSummaryRepository supplyChainValidatorSummaryRepository;
private final CertificateRepository certificateRepository;
@ -225,7 +225,7 @@ public class ValidationReportsPageController extends PageController<NoPageParams
if (!columnHeaders.isEmpty()) {
columnHeaders = "," + columnHeaders;
}
columnHeaders = systemColumnHeaders + columnHeaders;
columnHeaders = SYSTEM_COLUMN_HEADERS + columnHeaders;
}
break;
case "component":
@ -234,7 +234,7 @@ public class ValidationReportsPageController extends PageController<NoPageParams
if (!columnHeaders.isEmpty()) {
columnHeaders += ",";
}
columnHeaders += componentColumnHeaders;
columnHeaders += COMPONENT_COLUMN_HEADERS;
}
break;
case "manufacturer":
@ -290,7 +290,7 @@ public class ValidationReportsPageController extends PageController<NoPageParams
reportData.append(pc.getManufacturer() + ","
+ pc.getModel() + ","
+ pc.getPlatformSerial() + ","
+ LocalDateTime.now().toString() + ","
+ LocalDateTime.now() + ","
+ device.getSupplyChainValidationStatus() + ",");
}
if (!systemOnly) {
@ -315,7 +315,7 @@ public class ValidationReportsPageController extends PageController<NoPageParams
}
if (!jsonVersion) {
if (columnHeaders.isEmpty()) {
columnHeaders = systemColumnHeaders + "," + componentColumnHeaders;
columnHeaders = SYSTEM_COLUMN_HEADERS + "," + COMPONENT_COLUMN_HEADERS;
}
bufferedWriter.append(columnHeaders + System.lineSeparator());
bufferedWriter.append(reportData.toString());
@ -354,14 +354,17 @@ public class ValidationReportsPageController extends PageController<NoPageParams
.getSupplyChainValidationStatus().toString());
JsonArray components = new JsonArray();
final int componentDataPosition4 = 3;
final int componentDataPosition5 = 4;
final int componentDataPosition6 = 5;
for (ArrayList<String> componentData : parsedComponents) {
JsonObject component = new JsonObject();
component.addProperty("Component name", componentData.get(0));
component.addProperty("Component manufacturer", componentData.get(1));
component.addProperty("Component model", componentData.get(2));
component.addProperty("Component SN", componentData.get(3));
component.addProperty("Issuer", componentData.get(4));
component.addProperty("Component status", componentData.get(5));
component.addProperty("Component SN", componentData.get(componentDataPosition4));
component.addProperty("Issuer", componentData.get(componentDataPosition5));
component.addProperty("Component status", componentData.get(componentDataPosition6));
components.add(component);
}
systemData.add("Components", components);
@ -410,7 +413,7 @@ public class ValidationReportsPageController extends PageController<NoPageParams
}
}
}
log.info("Component failures: " + componentFailureString.toString());
log.info("Component failures: " + componentFailureString);
for (ArrayList<Object> issuerAndComponent : chainComponents) {
ArrayList<String> componentData = new ArrayList<String>();
String issuer = (String) issuerAndComponent.get(0);

View File

@ -4,6 +4,7 @@ import hirs.attestationca.portal.page.PageParams;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.LinkedHashMap;
@ -13,6 +14,7 @@ import java.util.LinkedHashMap;
@Getter
@Setter
@AllArgsConstructor
@ToString
public class CertificateDetailsPageParams implements PageParams {
private String id;
@ -47,13 +49,4 @@ public class CertificateDetailsPageParams implements PageParams {
map.put("type", type);
return map;
}
@Override
public String toString() {
return "CertificateDetailsPageParams{"
+ "id:' " + id + "',"
+ "type: " + type
+ "}";
}
}

View File

@ -5,18 +5,20 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import java.util.LinkedHashMap;
/**
* URL parameters object for the Reference Manifest Details page and controller.
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class ReferenceManifestDetailsPageParams implements PageParams {
@Getter
@Setter
private String id;
/**
@ -30,11 +32,4 @@ public class ReferenceManifestDetailsPageParams implements PageParams {
map.put("id", id);
return map;
}
@Override
public String toString() {
return "ReferenceManifestDetailsPageParams{"
+ "id:' " + id
+ "}";
}
}

View File

@ -42,8 +42,9 @@ public final class CertificateStringMapBuilder {
/**
* Returns the general information.
*
* @param certificate certificate to get the general information.
* @param certificateRepository the certificate repository for retrieving certs.
* @param certificate certificate to get the general information.
* @param caCertificateRepository CA Certificate repository
* @param certificateRepository the certificate repository for retrieving certs.
* @return a hash map with the general certificate information.
*/
public static HashMap<String, String> getGeneralCertificateInfo(
@ -145,8 +146,9 @@ public final class CertificateStringMapBuilder {
/**
* Recursive function that check if all the certificate chain is present.
*
* @param certificate certificate to get the issuer
* @param certificateRepository the certificate repository for retrieving certs.
* @param certificate certificate to get the issuer
* @param certificateRepository the certificate repository for retrieving certs.
* @param caCredentialRepository CA Certificate repository
* @return a boolean indicating if it has the full chain or not.
*/
public static Certificate containsAllChain(
@ -163,8 +165,8 @@ public final class CertificateStringMapBuilder {
skiCA = caCredentialRepository.findBySubjectKeyIdStringAndArchiveFlag(
certificate.getAuthorityKeyIdentifier(), false);
} else {
log.error(String.format("Certificate (%s) for %s has no authority key identifier.",
certificate.getClass().toString(), certificate.getSubject()));
log.error("Certificate ({}) for {} has no authority key identifier.", certificate.getClass(),
certificate.getSubject());
}
if (skiCA == null) {
@ -207,12 +209,15 @@ public final class CertificateStringMapBuilder {
* Returns the Certificate Authority information.
*
* @param uuid ID for the certificate.
* @param caCertificateRepository the certificate manager for retrieving certs.
* @param certificateRepository the certificate manager for retrieving certs.
* @param caCertificateRepository CA Certificate repository
* @return a hash map with the endorsement certificate information.
*/
public static HashMap<String, String> getCertificateAuthorityInformation(final UUID uuid,
final CertificateRepository certificateRepository,
final CACredentialRepository caCertificateRepository) {
public static HashMap<String, String>
getCertificateAuthorityInformation(final UUID uuid,
final CertificateRepository certificateRepository,
final CACredentialRepository caCertificateRepository) {
if (!caCertificateRepository.existsById(uuid)) {
return new HashMap<>();
}
@ -265,13 +270,15 @@ public final class CertificateStringMapBuilder {
/**
* Returns the endorsement credential information.
*
* @param uuid ID for the certificate.
* @param certificateRepository the certificate repository for retrieving certs.
* @param uuid ID for the certificate.
* @param certificateRepository the certificate repository for retrieving certs.
* @param caCertificateRepository CA Certificate repository
* @return a hash map with the endorsement certificate information.
*/
public static HashMap<String, String> getEndorsementInformation(final UUID uuid,
final CertificateRepository certificateRepository,
final CACredentialRepository caCertificateRepository) {
public static HashMap<String, String> getEndorsementInformation(
final UUID uuid,
final CertificateRepository certificateRepository,
final CACredentialRepository caCertificateRepository) {
HashMap<String, String> data = new HashMap<>();
EndorsementCredential certificate =
(EndorsementCredential) certificateRepository.getCertificate(uuid);
@ -309,16 +316,21 @@ public final class CertificateStringMapBuilder {
/**
* Returns the Platform credential information.
*
* @param uuid ID for the certificate.
* @param certificateRepository the certificate manager for retrieving certs.
* @param uuid ID for the certificate.
* @param certificateRepository the certificate manager for retrieving certs.
* @param componentResultRepository component result repository.
* @param caCertificateRepository CA credential repository.
* @return a hash map with the endorsement certificate information.
* @throws IOException when parsing the certificate
* @throws IllegalArgumentException invalid argument on parsing the certificate
*/
public static HashMap<String, Object> getPlatformInformation(final UUID uuid,
final CertificateRepository certificateRepository,
final ComponentResultRepository componentResultRepository,
final CACredentialRepository caCertificateRepository)
final CertificateRepository
certificateRepository,
final ComponentResultRepository
componentResultRepository,
final CACredentialRepository
caCertificateRepository)
throws IllegalArgumentException, IOException {
HashMap<String, Object> data = new HashMap<>();
PlatformCredential certificate = (PlatformCredential) certificateRepository.getCertificate(uuid);
@ -470,13 +482,16 @@ public final class CertificateStringMapBuilder {
/**
* Returns the Issued Attestation Certificate information.
*
* @param uuid ID for the certificate.
* @param certificateRepository the certificate manager for retrieving certs.
* @param uuid ID for the certificate.
* @param certificateRepository the certificate manager for retrieving certs.
* @param caCredentialRepository CA Credential repository.
* @return a hash map with the endorsement certificate information.
*/
public static HashMap<String, String> getIssuedInformation(final UUID uuid,
final CertificateRepository certificateRepository,
final CACredentialRepository caCredentialRepository) {
final CertificateRepository
certificateRepository,
final CACredentialRepository
caCredentialRepository) {
HashMap<String, String> data = new HashMap<>();
IssuedAttestationCertificate certificate =
(IssuedAttestationCertificate) certificateRepository.getCertificate(uuid);
@ -544,13 +559,16 @@ public final class CertificateStringMapBuilder {
/**
* Returns the IDevID Certificate information.
*
* @param uuid ID for the certificate.
* @param certificateRepository the certificate manager for retrieving certs.
* @param uuid ID for the certificate.
* @param certificateRepository the certificate manager for retrieving certs.
* @param caCredentialRepository CA Credential repository.
* @return a hash map with the endorsement certificate information.
*/
public static HashMap<String, String> getIdevidInformation(final UUID uuid,
final CertificateRepository certificateRepository,
final CACredentialRepository caCredentialRepository) {
final CertificateRepository
certificateRepository,
final CACredentialRepository
caCredentialRepository) {
HashMap<String, String> data = new HashMap<>();
IDevIDCertificate certificate = (IDevIDCertificate) certificateRepository.getCertificate(uuid);
@ -577,7 +595,8 @@ public final class CertificateStringMapBuilder {
if (certificate.hasTCGOIDs()) {
if (hwSerialStr.contains(":")) {
String[] hwSerialArray = hwSerialStr.split(":");
if (hwSerialArray.length >= 3) {
final int minArrayLength = 3;
if (hwSerialArray.length >= minArrayLength) {
data.put("tcgTpmManufacturer", hwSerialArray[0]);
data.put("ekAuthorityKeyIdentifier", hwSerialArray[1]);
data.put("ekCertificateSerialNumber", hwSerialArray[2]);
@ -593,7 +612,9 @@ public final class CertificateStringMapBuilder {
String hwSerialToAdd = hwSerialStr;
// Check if hwSerialNum is a printable ASCII string; default to hex otherwise
if (hwSerialStr.chars().allMatch(c -> c > 0x20 && c <= 0x7F)) {
final int minMatchedNum = 0x20;
final int maxMatchedNum = 0x7F;
if (hwSerialStr.chars().allMatch(c -> c > minMatchedNum && c <= maxMatchedNum)) {
data.put("hwSerialNum", hwSerialStr);
} else {
hwSerialToAdd = Hex.toHexString(certificate.getHwSerialNum());

View File

@ -5,26 +5,22 @@ logging.level.org.springframework.web=ERROR
logging.level.org.hibernate=ERROR
logging.file.path=/var/log/hirs
logging.file.name=HIRS_AttestationCA_Portal.log
# Database Config
spring.jpa.hibernate.ddl-auto=update
jakarta.persistence.sharedCache.mode = UNSPECIFIED
jakarta.persistence.sharedCache.mode=UNSPECIFIED
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
# Tomcat Config
server.tomcat.additional-tld-skip-patterns=jakarta.persistence-api*.jar, jakarta.xml.bind-api*.jar, txw2*.jar, *commons*.jar, *annotations*.jar, *checker*.jar, *lombok*.jar, *jsr*.jar, *guava*.jar, *access*.jar, *activation*.jar, *bcprov*.jar, *bcmail*.jar, *bcutil*.jar, *bcpkix*.jar, *json*.jar
server.tomcat.basedir=/opt/embeddedtomcat
server.servlet.register-default-servlet=true
server.servlet.context-path=/
spring.mvc.servlet.path=/
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.directory=/var/log/hirs
server.tomcat.accesslog.file-date-format=yyyy-MM-dd
server.tomcat.accesslog.prefix=Tomcat_accesslog_
server.tomcat.accesslog.suffix=.log
server.tomcat.accesslog.rotate=true
# Tomcat TLS support
server.port=8443
server.ssl.enabled=true
@ -36,10 +32,8 @@ server.ssl.key-store=/etc/hirs/certificates/HIRS/KeyStore.jks
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.validity = 3652
aca.certificates.validity=3652
# Compression settings
server.compression.enabled=true
# Compression content types

View File

@ -1,4 +1,3 @@
# Logging Config (tomcat may have further config)
logging.level.org.springframework=ERROR
logging.level.org.apache.catalina=ERROR
@ -8,25 +7,23 @@ logging.file.path=C:/ProgramData/hirs/log
logging.file.name=hirs.spring.log
# Database Config
spring.jpa.hibernate.ddl-auto=update
jakarta.persistence.sharedCache.mode = UNSPECIFIED
jakarta.persistence.sharedCache.mode=UNSPECIFIED
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
aca.certificates.validity = 3652
aca.certificates.validity=3652
# Tomcat Config
server.tomcat.additional-tld-skip-patterns=jakarta.persistence-api*.jar, jakarta.xml.bind-api*.jar, txw2*.jar, *commons*.jar, *annotations*.jar, *checker*.jar, *lombok*.jar, *jsr*.jar, *guava*.jar, *access*.jar, *activation*.jar, *bcprov*.jar, *bcmail*.jar, *bcutil*.jar, *bcpkix*.jar, *json*.jar
server.tomcat.basedir=C:/ProgramData/hirs/embeddedtomcat
server.servlet.register-default-servlet=true
server.servlet.context-path=/
spring.mvc.servlet.path=/
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.directory=C:/ProgramData/hirs/log
server.tomcat.accesslog.file-date-format=yyyy-MM-dd
server.tomcat.accesslog.prefix=Tomcat_accesslog_
server.tomcat.accesslog.suffix=.log
server.tomcat.accesslog.rotate=true
# Tomcat TLS support
server.port=8443
server.ssl.enabled=true
@ -38,10 +35,8 @@ server.ssl.key-store=C:/ProgramData/hirs/certificates/HIRS/KeyStore.jks
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
#--server.ssl.key-store-password=123456
#--server.ssl.trust-store-password=123456
#jdbc.driverClassName = com.mysql.cj.jdbc.Driver
#jdbc.url = jdbc:mysql://localhost:3306/hirs_db?autoReconnect=true&useSSL=false
#jdbc.username = root
@ -49,6 +44,5 @@ server.ssl.ciphers=TLS_AES_256_GCM_SHA384, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-
#entitymanager.packagesToScan: hirs.attestationca.portal.page.controllers
#spring.jpa.hibernate.ddl-auto=update
#spring.jpa.show-sql=true
# DB dfault password.
#spring.datasource.password=hirs_db

View File

@ -4,14 +4,11 @@
# color: Indicate the color of the banner
# string: String that will be display on the banner
# dynamic: Dynamic string to display on the banner
banner.color=
banner.string=
banner.dynamic=
# Extra content that will be placed at the bottom of the page either on the left or right
# side of the page
left.content.1=
left.content.2=
left.content.3=

View File

@ -2,9 +2,9 @@ hibernate.connection.url=jdbc:mariadb://localhost:3306/hirs_db?autoReconnect=tru
#hibernate.connection.username=hirs_db
#hibernate.connection.password=hirs_db
hibernate.connection.driver_class=org.mariadb.jdbc.Driver
hibernate.dialect = org.hibernate.dialect.MariaDBDialect
hibernate.show_sql = false
hibernate.format_sql = true
hibernate.hbm2ddl.auto = update
hibernate.dialect=org.hibernate.dialect.MariaDBDialect
hibernate.show_sql=false
hibernate.format_sql=true
hibernate.hbm2ddl.auto=update
#https://github.com/spring-projects/spring-data-jpa/issues/2717
jakarta.persistence.sharedCache.mode = UNSPECIFIED
jakarta.persistence.sharedCache.mode=UNSPECIFIED

View File

@ -10,28 +10,25 @@
# ACA Directories
# root: the root directory of ACA related files
# certificates: the directory for ACA certificate files
aca.directories.root = /etc/hirs/aca
aca.directories.certificates = ${aca.directories.root}/certificates
aca.directories.root=/etc/hirs/aca
aca.directories.certificates=${aca.directories.root}/certificates
# ACA certificate related properties. These are generic properties that apply to the creation of
# any certificate that the ACA is responsible for creating.
# validity: the number of days that credentials generated by the ACA are valid.
aca.certificates.validity = 3652
aca.certificates.validity=3652
# ACA key store properties
# alias: the alias to reference the ACA key and certificate by
# location: the absolute path to the ACA key store.
# password: key store password
aca.keyStore.alias = HIRS_ACA_KEY
aca.keyStore.location = ${aca.directories.certificates}/keyStore.jks
aca.keyStore.password =
aca.keyStore.alias=HIRS_ACA_KEY
aca.keyStore.location=${aca.directories.certificates}/keyStore.jks
aca.keyStore.password=
# ACA setup/initialization properties. These properties are used exclusively by the ACA
# initialization process. Generally these properties do not need to be modified
#
# keySize: the default key size of the ACA key pair stored within the trust store
# subjectName: the CN of the generate X509 certificate
# expiration: the number of days that the generated X509 certificate will expire
aca.setup.keyStore.keySize = 2048
aca.setup.keyStore.subjectName = HIRS_AttestationCA_Endorsement
aca.setup.keyStore.expiration = ${aca.certificates.validity}
aca.setup.keyStore.keySize=2048
aca.setup.keyStore.subjectName=HIRS_AttestationCA_Endorsement
aca.setup.keyStore.expiration=${aca.certificates.validity}

View File

@ -1,26 +1,35 @@
# DataTables plug-in for jQuery
DataTables is a table enhancing plug-in for the [jQuery](//jquery.com) Javascript library, adding sorting, paging and filtering abilities to plain HTML tables with minimal effort. The stated goal of DataTables is:
DataTables is a table enhancing plug-in for the [jQuery](//jquery.com) Javascript library, adding sorting, paging and
filtering abilities to plain HTML tables with minimal effort. The stated goal of DataTables is:
> To enhance the accessibility of data in HTML tables.
To meet this goal, DataTables is developed with two distinct groups of users in mind:
* You the developers using DataTables. For developers DataTables provides a wide array of options for how data should be obtained, displayed and acted upon, along with an extensive API for accessing and manipulating the table.
* End users. For those using the interface DataTables presents, actions to get the most from the information contained in tables, such as sorting and filtering, along with paging and scrolling of the data in table, are easy to use, intuitive and fast.
* You the developers using DataTables. For developers DataTables provides a wide array of options for how data should be
obtained, displayed and acted upon, along with an extensive API for accessing and manipulating the table.
* End users. For those using the interface DataTables presents, actions to get the most from the information contained
in tables, such as sorting and filtering, along with paging and scrolling of the data in table, are easy to use,
intuitive and fast.
## Installing DataTables
To use DataTables, the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download). You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See the [documentation](//datatables.net/manual/installation) for full details.
To use DataTables, the primary way to obtain the software is to use
the [DataTables downloader](//datatables.net/download). You can also include the individual files from
the [DataTables CDN](//cdn.datatables.net). See the [documentation](//datatables.net/manual/installation) for full
details.
### NPM and Bower
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built from this repository under the name `datatables.net`. Styling packages for Bootstrap, Foundation and other styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has details on how to use package managers with DataTables.
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built
from this repository under the name `datatables.net`. Styling packages for Bootstrap, Foundation and other styling
libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation
pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has
details on how to use package managers with DataTables.
## Usage
@ -30,7 +39,9 @@ In its simplest case, DataTables can be initialised with a single line of Javasc
$('table').dataTable();
```
where the jQuery selector is used to obtain a reference to the table you want to enhance with DataTables. Optional configuration parameters can be passed in to DataTables to have it perform certain actions by using a configuration object as the parameter passed in to the DataTables constructor. For example:
where the jQuery selector is used to obtain a reference to the table you want to enhance with DataTables. Optional
configuration parameters can be passed in to DataTables to have it perform certain actions by using a configuration
object as the parameter passed in to the DataTables constructor. For example:
```js
$('table').dataTable( {
@ -43,17 +54,18 @@ will disable paging and enable scrolling.
A full list of the options available for DataTables are available in the [documentation](//datatables.net).
## Documentation
Full documentation of the DataTables options, API and plug-in interface are available on the [DataTables web-site](//datatables.net). The site also contains information on the wide variety of plug-ins that are available for DataTables, which can be used to enhance and customise your table even further.
Full documentation of the DataTables options, API and plug-in interface are available on
the [DataTables web-site](//datatables.net). The site also contains information on the wide variety of plug-ins that are
available for DataTables, which can be used to enhance and customise your table even further.
## Support
Support for DataTables is available through the [DataTables forums](//datatables.net/forums) and [commercial support options](//datatables.net/support) are available.
Support for DataTables is available through the [DataTables forums](//datatables.net/forums)
and [commercial support options](//datatables.net/support) are available.
## License
DataTables is release under the [MIT license](//datatables.net/license). You are free to use, modify and distribute this software, as long as the copyright header is left intact (specifically the comment block which starts with `/*!`.
DataTables is release under the [MIT license](//datatables.net/license). You are free to use, modify and distribute this
software, as long as the copyright header is left intact (specifically the comment block which starts with `/*!`.

View File

@ -1,22 +1,28 @@
# AutoFill
AutoFill adds an Excel data fill like option to a DataTable to click and drag over multiple cells, filling in information over the selected cells and incrementing numbers as needed.
AutoFill adds an Excel data fill like option to a DataTable to click and drag over multiple cells, filling in
information over the selected cells and incrementing numbers as needed.
# Installation
To use AutoFill the best way to obtain the software is to use the [DataTables downloader](//datatables.net/download). You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/autofill/) for full details.
To use AutoFill the best way to obtain the software is to use the [DataTables downloader](//datatables.net/download).
You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See
the [documentation](http://datatables.net/extensions/autofill/) for full details.
## NPM and Bower
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built from this repository under the name `datatables.net-autofill`. Styling packages for Bootstrap, Foundation and other styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has details on how to use package managers with DataTables.
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built
from this repository under the name `datatables.net-autofill`. Styling packages for Bootstrap, Foundation and other
styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation
pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has
details on how to use package managers with DataTables.
# Basic usage
AutoFill is initialised using the `autoFill` option in the DataTables constructor. Further options can be specified using this option as an object - see the documentation for details. For example:
AutoFill is initialised using the `autoFill` option in the DataTables constructor. Further options can be specified
using this option as an object - see the documentation for details. For example:
```js
$(document).ready( function () {
@ -26,14 +32,13 @@ $(document).ready( function () {
} );
```
# Documentation / support
* [Documentation](https://datatables.net/extensions/autofill/)
* [DataTables support forums](http://datatables.net/forums)
# GitHub
If you fancy getting involved with the development of AutoFill and help make it better, please refer to its [GitHub repo](https://github.com/DataTables/AutoFill)
If you fancy getting involved with the development of AutoFill and help make it better, please refer to
its [GitHub repo](https://github.com/DataTables/AutoFill)

View File

@ -1,22 +1,30 @@
# Buttons
The Buttons extension for DataTables provides a common set of options, API methods and styling to display buttons on a page that will interact with a DataTable. Modules are also provided for data export, printing and column visibility control.
The Buttons extension for DataTables provides a common set of options, API methods and styling to display buttons on a
page that will interact with a DataTable. Modules are also provided for data export, printing and column visibility
control.
# Installation
To use Buttons the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download). You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/buttons/) for full details.
To use Buttons the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download).
You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See
the [documentation](http://datatables.net/extensions/buttons/) for full details.
## NPM and Bower
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built from this repository under the name `datatables.net-buttons`. Styling packages for Bootstrap, Foundation and other styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has details on how to use package managers with DataTables.
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built
from this repository under the name `datatables.net-buttons`. Styling packages for Bootstrap, Foundation and other
styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation
pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has
details on how to use package managers with DataTables.
# Basic usage
Buttons is initialised using the `buttons` option in the DataTables constructor, giving an array of the buttons that should be shown. Further options can be specified using this option as an object - see the documentation for details. For example:
Buttons is initialised using the `buttons` option in the DataTables constructor, giving an array of the buttons that
should be shown. Further options can be specified using this option as an object - see the documentation for details.
For example:
```js
$(document).ready( function () {
@ -26,14 +34,13 @@ $(document).ready( function () {
} );
```
# Documentation / support
* [Documentation](https://datatables.net/extensions/buttons/)
* [DataTables support forums](http://datatables.net/forums)
# GitHub
If you fancy getting involved with the development of Buttons and help make it better, please refer to its [GitHub repo](https://github.com/DataTables/Buttons)
If you fancy getting involved with the development of Buttons and help make it better, please refer to
its [GitHub repo](https://github.com/DataTables/Buttons)

View File

@ -1,22 +1,29 @@
# ColReorder
ColReorder adds the ability for the end user to click and drag column headers to reorder a table as they see fit, to DataTables. See the [documentation](http://datatables.net/extensions/colreorder/) for full details.
ColReorder adds the ability for the end user to click and drag column headers to reorder a table as they see fit, to
DataTables. See the [documentation](http://datatables.net/extensions/colreorder/) for full details.
# Installation
To use ColReorder the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download). You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/colreorder/) for full details.
To use ColReorder the primary way to obtain the software is to use
the [DataTables downloader](//datatables.net/download). You can also include the individual files from
the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/colreorder/) for
full details.
## NPM and Bower
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built from this repository under the name `datatables.net-colreorder`. Styling packages for Bootstrap, Foundation and other styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has details on how to use package managers with DataTables.
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built
from this repository under the name `datatables.net-colreorder`. Styling packages for Bootstrap, Foundation and other
styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation
pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has
details on how to use package managers with DataTables.
# Basic usage
ColReorder is initialised using the `colReorder` option in the DataTables constructor - a simple boolean `true` will enable the feature. Further options can be specified using this option as an object - see the documentation for details.
ColReorder is initialised using the `colReorder` option in the DataTables constructor - a simple boolean `true` will
enable the feature. Further options can be specified using this option as an object - see the documentation for details.
Example:
@ -28,7 +35,6 @@ $(document).ready( function () {
} );
```
# Documentation / support
* [Documentation](https://datatables.net/extensions/colreorder/)

View File

@ -1,22 +1,31 @@
# FixedColumns
When making use of DataTables' x-axis scrolling feature (`scrollX`), you may wish to fix the left or right most columns in place. This extension for DataTables provides exactly this option (for non-scrolling tables, please use the FixedHeader extension, which can fix the header and footer).
When making use of DataTables' x-axis scrolling feature (`scrollX`), you may wish to fix the left or right most columns
in place. This extension for DataTables provides exactly this option (for non-scrolling tables, please use the
FixedHeader extension, which can fix the header and footer).
# Installation
To use FixedColumns the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download). You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/fixedcolumns/) for full details.
To use FixedColumns the primary way to obtain the software is to use
the [DataTables downloader](//datatables.net/download). You can also include the individual files from
the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/fixedcolumns/) for
full details.
## NPM and Bower
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built from this repository under the name `datatables.net-fixedcolumns`. Styling packages for Bootstrap, Foundation and other styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has details on how to use package managers with DataTables.
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built
from this repository under the name `datatables.net-fixedcolumns`. Styling packages for Bootstrap, Foundation and other
styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation
pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has
details on how to use package managers with DataTables.
# Basic usage
FixedColumns is initialised using the `fixedColumns` option in the DataTables constructor - a simple boolean `true` will enable the feature. Further options can be specified using this option as an object - see the documentation for details. DataTables' scrolling options should also be enabled to use this feature.
FixedColumns is initialised using the `fixedColumns` option in the DataTables constructor - a simple boolean `true` will
enable the feature. Further options can be specified using this option as an object - see the documentation for details.
DataTables' scrolling options should also be enabled to use this feature.
Example:
@ -32,13 +41,12 @@ $(document).ready(function() {
} );
```
# Documentation / support
* [Documentation](https://datatables.net/extensions/fixedcolumns/)
* [DataTables support forums](http://datatables.net/forums)
# GitHub
If you fancy getting involved with the development of FixedColumns and help make it better, please refer to its [GitHub repo](https://github.com/DataTables/FixedColumns).
If you fancy getting involved with the development of FixedColumns and help make it better, please refer to
its [GitHub repo](https://github.com/DataTables/FixedColumns).

View File

@ -1,22 +1,29 @@
# FixedHeader
The FixedHeader plug-in will freeze in place the header, footer and left and/or right most columns in a DataTable, ensuring that title information will remain always visible.
The FixedHeader plug-in will freeze in place the header, footer and left and/or right most columns in a DataTable,
ensuring that title information will remain always visible.
# Installation
To use FixedHeader the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download). You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/fixedheader/) for full details.
To use FixedHeader the primary way to obtain the software is to use
the [DataTables downloader](//datatables.net/download). You can also include the individual files from
the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/fixedheader/) for
full details.
## NPM and Bower
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built from this repository under the name `datatables.net-fixedheader`. Styling packages for Bootstrap, Foundation and other styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has details on how to use package managers with DataTables.
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built
from this repository under the name `datatables.net-fixedheader`. Styling packages for Bootstrap, Foundation and other
styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation
pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has
details on how to use package managers with DataTables.
# Basic usage
FixedHeader is initialised using the `fixedHeader` option in the DataTables constructor - a simple boolean `true` will enable the feature. Further options can be specified using this option as an object - see the documentation for details.
FixedHeader is initialised using the `fixedHeader` option in the DataTables constructor - a simple boolean `true` will
enable the feature. Further options can be specified using this option as an object - see the documentation for details.
Example:
@ -28,14 +35,13 @@ $(document).ready( function () {
} );
```
# Documentation / support
* [Documentation](https://datatables.net/extensions/fixedheader/)
* [DataTables support forums](http://datatables.net/forums)
# GitHub
If you fancy getting involved with the development of FixedHeader and help make it better, please refer to its [GitHub repo](https://github.com/DataTables/FixedHeader).
If you fancy getting involved with the development of FixedHeader and help make it better, please refer to
its [GitHub repo](https://github.com/DataTables/FixedHeader).

View File

@ -1,22 +1,28 @@
# KeyTable
KeyTable provides Excel like cell navigation on any table. Events (focus, blur, action etc) can be assigned to individual cells, columns, rows or all cells.
KeyTable provides Excel like cell navigation on any table. Events (focus, blur, action etc) can be assigned to
individual cells, columns, rows or all cells.
# Installation
To use KeyTable the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download). You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/keytable/) for full details.
To use KeyTable the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download).
You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See
the [documentation](http://datatables.net/extensions/keytable/) for full details.
## NPM and Bower
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built from this repository under the name `datatables.net-keytable`. Styling packages for Bootstrap, Foundation and other styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has details on how to use package managers with DataTables.
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built
from this repository under the name `datatables.net-keytable`. Styling packages for Bootstrap, Foundation and other
styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation
pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has
details on how to use package managers with DataTables.
# Basic usage
KeyTable is initialised using the `keys` option in the DataTables constructor - a simple boolean `true` will enable the feature. Further options can be specified using this option as an object - see the documentation for details.
KeyTable is initialised using the `keys` option in the DataTables constructor - a simple boolean `true` will enable the
feature. Further options can be specified using this option as an object - see the documentation for details.
```js
$(document).ready( function () {
@ -26,14 +32,13 @@ $(document).ready( function () {
} );
```
# Documentation / support
* [Documentation](https://datatables.net/extensions/keytable/)
* [DataTables support forums](http://datatables.net/forums)
# GitHub
If you fancy getting involved with the development of KeyTable and help make it better, please refer to its [GitHub repo](https://github.com/DataTables/KeyTable).
If you fancy getting involved with the development of KeyTable and help make it better, please refer to
its [GitHub repo](https://github.com/DataTables/KeyTable).

View File

@ -1,22 +1,29 @@
# Responsive
Responsive will automatically optimise the table's layout for different screen sizes through the dynamic column visibility control, making your tables useful on desktop and mobile screens.
Responsive will automatically optimise the table's layout for different screen sizes through the dynamic column
visibility control, making your tables useful on desktop and mobile screens.
# Installation
To use Responsive the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download). You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/responsive/) for full details.
To use Responsive the primary way to obtain the software is to use
the [DataTables downloader](//datatables.net/download). You can also include the individual files from
the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/responsive/) for
full details.
## NPM and Bower
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built from this repository under the name `datatables.net-responsive`. Styling packages for Bootstrap, Foundation and other styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has details on how to use package managers with DataTables.
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built
from this repository under the name `datatables.net-responsive`. Styling packages for Bootstrap, Foundation and other
styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation
pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has
details on how to use package managers with DataTables.
# Basic usage
Responsive is initialised using the `responsive` option in the DataTables constructor - a simple boolean `true` will enable the feature. Further options can be specified using this option as an object - see the documentation for details.
Responsive is initialised using the `responsive` option in the DataTables constructor - a simple boolean `true` will
enable the feature. Further options can be specified using this option as an object - see the documentation for details.
Example:
@ -28,14 +35,13 @@ $(document).ready( function () {
} );
```
# Documentation / support
* [Documentation](https://datatables.net/extensions/responsive/)
* [DataTables support forums](http://datatables.net/forums)
# GitHub
If you fancy getting involved with the development of Responsive and help make it better, please refer to its [GitHub repo](https://github.com/DataTables/Responsive).
If you fancy getting involved with the development of Responsive and help make it better, please refer to
its [GitHub repo](https://github.com/DataTables/Responsive).

View File

@ -1,22 +1,30 @@
# RowReorder
RowReorder adds the ability for rows in a DataTable to be reordered through user interaction with the table (click and drag / touch and drag). Integration with Editor's multi-row editing feature is also available to update rows immediately.
RowReorder adds the ability for rows in a DataTable to be reordered through user interaction with the table (click and
drag / touch and drag). Integration with Editor's multi-row editing feature is also available to update rows
immediately.
# Installation
To use RowReorder the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download). You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/rowreorder/) for full details.
To use RowReorder the primary way to obtain the software is to use
the [DataTables downloader](//datatables.net/download). You can also include the individual files from
the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/rowreorder/) for
full details.
## NPM and Bower
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built from this repository under the name `datatables.net-rowreorder`. Styling packages for Bootstrap, Foundation and other styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has details on how to use package managers with DataTables.
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built
from this repository under the name `datatables.net-rowreorder`. Styling packages for Bootstrap, Foundation and other
styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation
pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has
details on how to use package managers with DataTables.
# Basic usage
RowReorder is initialised using the `rowReorder` option in the DataTables constructor - a simple boolean `true` will enable the feature. Further options can be specified using this option as an object - see the documentation for details.
RowReorder is initialised using the `rowReorder` option in the DataTables constructor - a simple boolean `true` will
enable the feature. Further options can be specified using this option as an object - see the documentation for details.
Example:
@ -28,14 +36,13 @@ $(document).ready( function () {
} );
```
# Documentation / support
* [Documentation](https://datatables.net/extensions/rowreorder/)
* [DataTables support forums](http://datatables.net/forums)
# GitHub
If you fancy getting involved with the development of RowReorder and help make it better, please refer to its [GitHub repo](https://github.com/DataTables/RowReorder).
If you fancy getting involved with the development of RowReorder and help make it better, please refer to
its [GitHub repo](https://github.com/DataTables/RowReorder).

View File

@ -1,6 +1,11 @@
# Scroller
Scroller is a virtual rendering plug-in for DataTables which allows large datasets to be drawn on screen every quickly. What the virtual rendering means is that only the visible portion of the table (and a bit to either side to make the scrolling smooth) is drawn, while the scrolling container gives the visual impression that the whole table is visible. This is done by making use of the pagination abilities of DataTables and moving the table around in the scrolling container DataTables adds to the page. The scrolling container is forced to the height it would be for the full table display using an extra element.
Scroller is a virtual rendering plug-in for DataTables which allows large datasets to be drawn on screen every quickly.
What the virtual rendering means is that only the visible portion of the table (and a bit to either side to make the
scrolling smooth) is drawn, while the scrolling container gives the visual impression that the whole table is visible.
This is done by making use of the pagination abilities of DataTables and moving the table around in the scrolling
container DataTables adds to the page. The scrolling container is forced to the height it would be for the full table
display using an extra element.
Key features include:
@ -10,21 +15,26 @@ Key features include:
* Support for scrolling with millions of rows
* Easy to use
# Installation
To use Scroller the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download). You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/scroller/) for full details.
To use Scroller the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download).
You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See
the [documentation](http://datatables.net/extensions/scroller/) for full details.
## NPM and Bower
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built from this repository under the name `datatables.net-scroller`. Styling packages for Bootstrap, Foundation and other styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has details on how to use package managers with DataTables.
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built
from this repository under the name `datatables.net-scroller`. Styling packages for Bootstrap, Foundation and other
styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation
pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has
details on how to use package managers with DataTables.
# Basic usage
Scroller is initialised using the `scroller` option in the DataTables constructor - a simple boolean `true` will enable the feature. Further options can be specified using this option as an object - see the documentation for details.
Scroller is initialised using the `scroller` option in the DataTables constructor - a simple boolean `true` will enable
the feature. Further options can be specified using this option as an object - see the documentation for details.
```js
$(document).ready( function () {
@ -34,16 +44,17 @@ $(document).ready( function () {
} );
```
Note that rows in the table must all be the same height. Information in a cell which expands on to multiple lines will cause some odd behaviour in the scrolling. Additionally, the table's `cellspacing` parameter must be set to 0, again to ensure the information display is correct.
Note that rows in the table must all be the same height. Information in a cell which expands on to multiple lines will
cause some odd behaviour in the scrolling. Additionally, the table's `cellspacing` parameter must be set to 0, again to
ensure the information display is correct.
# Documentation / support
* [Documentation](https://datatables.net/extensions/scroller/)
* [DataTables support forums](http://datatables.net/forums)
# GitHub
If you fancy getting involved with the development of Scroller and help make it better, please refer to its [GitHub repo](https://github.com/DataTables/Scroller)
If you fancy getting involved with the development of Scroller and help make it better, please refer to
its [GitHub repo](https://github.com/DataTables/Scroller)

View File

@ -1,22 +1,29 @@
# Select
Select adds item selection capabilities to a DataTable. Items can be rows, columns or cells, which can be selected independently, or together. Item selection can be particularly useful in interactive tables where users can perform some action on the table such as editing.
Select adds item selection capabilities to a DataTable. Items can be rows, columns or cells, which can be selected
independently, or together. Item selection can be particularly useful in interactive tables where users can perform some
action on the table such as editing.
# Installation
To use Select the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download). You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See the [documentation](http://datatables.net/extensions/select/) for full details.
To use Select the primary way to obtain the software is to use the [DataTables downloader](//datatables.net/download).
You can also include the individual files from the [DataTables CDN](//cdn.datatables.net). See
the [documentation](http://datatables.net/extensions/select/) for full details.
## NPM and Bower
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built from this repository under the name `datatables.net-select`. Styling packages for Bootstrap, Foundation and other styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has details on how to use package managers with DataTables.
If you prefer to use a package manager such as NPM or Bower, distribution repositories are available with software built
from this repository under the name `datatables.net-select`. Styling packages for Bootstrap, Foundation and other
styling libraries are also available by adding a suffix to the package name.
Please see the DataTables [NPM](//datatables.net/download/npm) and [Bower](//datatables.net/download/bower) installation
pages for further information. The [DataTables installation manual](//datatables.net/manual/installation) also has
details on how to use package managers with DataTables.
# Basic usage
Select is initialised using the `select` option in the DataTables constructor - a simple boolean `true` will enable the feature. Further options can be specified using this option as an object - see the documentation for details.
Select is initialised using the `select` option in the DataTables constructor - a simple boolean `true` will enable the
feature. Further options can be specified using this option as an object - see the documentation for details.
Example:
@ -28,14 +35,13 @@ $(document).ready( function () {
} );
```
# Documentation / support
* [Documentation](https://datatables.net/extensions/select/)
* [DataTables support forums](http://datatables.net/forums)
# GitHub
If you fancy getting involved with the development of Select and help make it better, please refer to its [GitHub repo](https://github.com/DataTables/Select).
If you fancy getting involved with the development of Select and help make it better, please refer to
its [GitHub repo](https://github.com/DataTables/Select).

View File

@ -182,7 +182,7 @@ public abstract class PageControllerTest {
/**
* Create page path (add pre-prefix and prefix path).
*
* @return
* @return the page path
*/
public String getPagePath() {
String pagePath = PRE_PREFIX_PATH + page.getPrefixPath() + page.getViewName();

View File

@ -125,8 +125,8 @@ public class PageTestConfiguration {
public PrivateKey privateKey() {
try {
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("RSA");
PrivateKey dummy_privKey = keyGenerator.generateKeyPair().getPrivate();
return dummy_privKey;
PrivateKey dummyPrivKey = keyGenerator.generateKeyPair().getPrivate();
return dummyPrivKey;
} catch (GeneralSecurityException e) {
throw new AssertionError(e);
}
@ -140,10 +140,10 @@ public class PageTestConfiguration {
public KeyStore keyStore() {
// attempt to create the key store. if that fails, print a message before failing.
try {
KeyStore dummy_keyStore = KeyStore.getInstance("JKS");
dummy_keyStore.load(null);
KeyStore dummyKeyStore = KeyStore.getInstance("JKS");
dummyKeyStore.load(null);
return dummy_keyStore;
return dummyKeyStore;
} catch (Exception ex) {
System.out.println("\nEncountered error while creating a fake (blank) key store for testing");
throw new BeanInitializationException(ex.getMessage(), ex);

View File

@ -299,7 +299,8 @@ public class CertificateDetailsPageControllerTest extends PageControllerTest {
// Check component identifier
assertNotNull(initialData.get("componentsIdentifier"));
List<?> obj = (List<?>) initialData.get("componentsIdentifier");
assertEquals(7, obj.size());
final int expectedSize = 7;
assertEquals(expectedSize, obj.size());
// Check platform properties
assertNotNull(initialData.get("platformProperties"));
@ -338,7 +339,8 @@ public class CertificateDetailsPageControllerTest extends PageControllerTest {
// Check component identifier
assertNotNull(initialData.get("componentsIdentifier"));
List<?> obj = (List<?>) initialData.get("componentsIdentifier");
assertEquals(14, obj.size());
final int expectedSize = 14;
assertEquals(expectedSize, obj.size());
// Check platform properties
assertNotNull(initialData.get("platformProperties"));

View File

@ -129,6 +129,7 @@ public class PlatformCredentialsPageControllerTest extends PageControllerTest {
/**
* Archives test cert that is in db by setting the archive flag.
*
* @param cert certificate.
* @throws Exception if an exception occurs
*/
private void archiveTestCert(final Certificate cert) throws Exception {

View File

@ -33,7 +33,8 @@ public class PolicyPageControllerTest extends PageControllerTest {
@Autowired
private PolicyRepository policyRepository;
// Policy refers to the settings such as whether to validate endorsement credentials, platform credentials, etc
// Policy refers to the settings such as whether to validate endorsement credentials, platform credentials
// , etc
private PolicySettings policy;
/**
@ -102,7 +103,7 @@ public class PolicyPageControllerTest extends PageControllerTest {
ResultActions actions;
//init the database
setPolicy_AllFalse();
setPolicyAllToFalse();
policyRepository.save(policy);
// perform the mock request
@ -133,7 +134,7 @@ public class PolicyPageControllerTest extends PageControllerTest {
ResultActions actions;
//init the database
setPolicy_AllFalse();
setPolicyAllToFalse();
policy.setEcValidationEnabled(true);
policyRepository.save(policy);
@ -188,7 +189,7 @@ public class PolicyPageControllerTest extends PageControllerTest {
ResultActions actions;
//init the database
setPolicy_AllFalse();
setPolicyAllToFalse();
policy.setEcValidationEnabled(true);
policyRepository.save(policy);
@ -243,8 +244,8 @@ public class PolicyPageControllerTest extends PageControllerTest {
ResultActions actions;
//init the database
setPolicy_AllFalse();
setPolicy_PcToTrue();
setPolicyAllToFalse();
setPolicyPcToTrue();
policyRepository.save(policy);
// perform the mock request
@ -298,8 +299,8 @@ public class PolicyPageControllerTest extends PageControllerTest {
ResultActions actions;
//init the database
setPolicy_AllFalse();
setPolicy_PcToTrue();
setPolicyAllToFalse();
setPolicyPcToTrue();
policyRepository.save(policy);
// perform the mock request
@ -352,8 +353,8 @@ public class PolicyPageControllerTest extends PageControllerTest {
ResultActions actions;
setPolicy_AllFalse();
setPolicy_PcAttributeToTrue();
setPolicyAllToFalse();
setPolicyPcAttributeToTrue();
policyRepository.save(policy);
// perform the mock request
@ -377,7 +378,7 @@ public class PolicyPageControllerTest extends PageControllerTest {
* Helper function to set policy member variable back to all false.
* After this function, can set specific values to true and then need to save policy.
*/
private void setPolicy_AllFalse() {
private void setPolicyAllToFalse() {
policy.setEcValidationEnabled(false);
policy.setPcValidationEnabled(false);
policy.setPcAttributeValidationEnabled(false);
@ -388,7 +389,7 @@ public class PolicyPageControllerTest extends PageControllerTest {
* Helper function to set policy member variable - PC Validation to True
* Note: to set PC Validation to true, EC Validation must also be true.
*/
private void setPolicy_PcToTrue() {
private void setPolicyPcToTrue() {
policy.setEcValidationEnabled(true);
policy.setPcValidationEnabled(true);
}
@ -397,8 +398,8 @@ public class PolicyPageControllerTest extends PageControllerTest {
* Helper function to set policy member variable - PC Attribute Validation to True
* Note: to set PC Attribute Validation to true, PC Validation must also be true.
*/
private void setPolicy_PcAttributeToTrue() {
setPolicy_PcToTrue();
private void setPolicyPcAttributeToTrue() {
setPolicyPcToTrue();
policy.setPcAttributeValidationEnabled(true);
}
}

View File

@ -129,9 +129,9 @@ public class TrustChainManagementPageControllerTest extends PageControllerTest {
Certificate cert = uploadTestCert();
String fileName = "attachment;filename=\"" + "CertificateAuthorityCredential_" +
cert.getSerialNumber() +
".cer\"";
String fileName = "attachment;filename=\"" + "CertificateAuthorityCredential_"
+ cert.getSerialNumber()
+ ".cer\"";
// verify cert file attachment and content
getMockMvc()
@ -202,6 +202,7 @@ public class TrustChainManagementPageControllerTest extends PageControllerTest {
/**
* Archives test cert that is in db by setting the archive flag.
*
* @param cert certificate.
* @throws Exception if an exception occurs
*/
private void archiveTestCert(final Certificate cert) throws Exception {

View File

@ -1,6 +1,5 @@
# need to override beans in PersistenceJPAConfig
spring.main.allow-bean-definition-overriding=true
# need to override properties in application.properties and hibernate.properties
hibernate.dialect = org.hibernate.dialect.HSQLDialect
hibernate.hbm2ddl.auto = create
hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.hbm2ddl.auto=create

View File

@ -95,8 +95,8 @@ message CertificateRequest {
}
message CertificateResponse {
optional bytes certificate = 1;
optional string certificate = 1;
optional ResponseStatus status = 2 [default = FAIL];
optional bytes ldevidCertificate = 3;
optional string ldevidCertificate = 3;
}

View File

@ -297,7 +297,7 @@ namespace hirs {
tpm.GetQuote(CommandTpm.DefaultAkHandle, Tpm2Lib.TpmAlgId.Sha256, recoveredSecret, out CommandTpmQuoteResponse ctqr, selectPcrs);
Log.Information("----> Nonce successfully decrypted. Sending attestation certificate request");
CertificateRequest akCertReq = acaClient.CreateAkCertificateRequest(recoveredSecret, ctqr);
byte[] certificate;
string certificate;
Log.Debug("Communicate certificate request to the ACA.");
CertificateResponse cr = await acaClient.PostCertificateRequest(akCertReq);
Log.Debug("Response received from the ACA regarding the certificate request.");
@ -311,34 +311,34 @@ namespace hirs {
}
}
if (cr.HasCertificate) {
certificate = cr.Certificate.ToByteArray(); // contains certificate
certificate = cr.Certificate.ToString(); // contains certificate
String certificateDirPath = settings.certificate_output_directory;
if (certificateDirPath != null) {
String certificateFilePath = FormatCertificatePath(dv, certificateDirPath, DefaultAKCertFileName);
try {
File.WriteAllBytes(certificateFilePath, certificate);
File.WriteAllText(certificateFilePath, certificate);
Log.Debug("Attestation key certificate written to local file system: {0}", certificateFilePath);
}
catch (Exception) {
Log.Debug("Failed to write attestation key certificate to local file system.");
}
}
Log.Debug("Printing attestation key certificate: " + BitConverter.ToString(certificate));
Log.Debug("Printing attestation key certificate: " + certificate);
}
if (cr.HasLdevidCertificate) {
certificate = cr.LdevidCertificate.ToByteArray(); // contains certificate
certificate = cr.LdevidCertificate.ToString(); // contains certificate
String certificateDirPath = settings.certificate_output_directory;
if (certificateDirPath != null) {
String certificateFilePath = FormatCertificatePath(dv, certificateDirPath, DefaultLDevIDCertFileName);
try {
File.WriteAllBytes(certificateFilePath, certificate);
File.WriteAllText(certificateFilePath, certificate);
Log.Debug("LDevID certificate written to local file system: {0}", certificateFilePath);
}
catch (Exception) {
Log.Debug("Failed to write LDevID certificate to local file system.");
}
}
Log.Debug("Printing LDevID certificate: " + BitConverter.ToString(certificate));
Log.Debug("Printing LDevID certificate: " + certificate);
}
} else {
result = ClientExitCodes.MAKE_CREDENTIAL_BLOB_MALFORMED;

View File

@ -14,7 +14,7 @@ namespace hirsTest {
const string address = "https://127.0.0.1:8443/";
byte[] ekCert = Encoding.UTF8.GetBytes("EK CERTIFICATE");
byte[] secret = Encoding.UTF8.GetBytes("AuthCredential Secret");
byte[] acaIssuedCert = Encoding.UTF8.GetBytes("ACA ISSUED CERTIFICATE");
string acaIssuedCert = "ACA ISSUED CERTIFICATE";
byte[] integrityHMAC = Convert.FromBase64String("VAtedc1RlNA1w0XfrtwmhE0ILBlILP6163Tur5HRIo0=");
byte[] encIdentity = Convert.FromBase64String("6e2oGBsK3H9Vzbj667ZsjnVOtvpSpQ==");
byte[] encryptedSecret = Convert.FromBase64String("NekvnOX8RPRdyd0/cxBI4FTCuNkiu0KAnS28yT7yYJUL5Lwfcv5ctEK6zQA0fq0IsX5TlAYSidGKxrAilOSwALJmJ+m7sMiXwMKrZn1cd4gzXObZEQimQoWgSEQbPO7rfpUn1UfI8K5SzmUFUTxc5X3D8zFonaEBp6QCjtdLegKGgioCDcQFdz20Y0PFAa1Itug7YbZdCFpfit570eQQinmqdVryiNyn6CLQdMgIejuBxoEpoTSWszB5eFKEdn5g/+8wcvhp6RpNBQ0hikF+6688TOVK/j8n3JDwKVltJ/WNHjVO+lxa2aLIMJRgs5ZRuzuz6OSMf10KqJjSWZE04w==");
@ -34,7 +34,7 @@ namespace hirsTest {
idClaimResp.CredentialBlob = Google.Protobuf.ByteString.CopyFrom(credentialBlob);
CertificateResponse certResp = new();
certResp.Status = ResponseStatus.Pass;
certResp.Certificate = Google.Protobuf.ByteString.CopyFrom(acaIssuedCert);
certResp.Certificate = acaIssuedCert;
IHirsAcaTpm tpm = A.Fake<IHirsAcaTpm>();
byte[] name = null, qualifiedName = null;

View File

@ -95,8 +95,8 @@ message CertificateRequest {
}
message CertificateResponse {
optional bytes certificate = 1;
optional string certificate = 1;
optional ResponseStatus status = 2 [default = FAIL];
optional bytes ldevidCertificate = 3;
optional string ldevidCertificate = 3;
}

View File

@ -7,6 +7,8 @@ import com.github.marandus.pciid.model.ProgramInterface;
import com.github.marandus.pciid.model.Vendor;
import com.github.marandus.pciid.service.PciIdsDatabase;
import com.google.common.base.Strings;
import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import org.bouncycastle.asn1.ASN1UTF8String;
import org.bouncycastle.asn1.DERUTF8String;
@ -25,30 +27,46 @@ import java.util.List;
@Log4j2
public final class PciIds {
/**
* Track status of pciids file.
*/
@Getter
private static String pciidsFileStatus = UefiConstants.FILESTATUS_NOT_ACCESSIBLE;
/**
* Name of pciids file in code.
*/
private static final String PCIIDS_FILENAME = "/pci.ids";
/**
* This pci ids file can be in different places on different distributions.
* Fedora/RHEL/Rocky/CentOS: /usr/share/hwdata/pci.ids
* Debian/Ubuntu: /usr/share/misc/pci.ids
* If the file is not found on the system (such as with Windows systems),
* the file will have to be accessed from code.
*/
public static final List<String> PCI_IDS_PATH =
Collections.unmodifiableList(new ArrayList<>() {
private static final long serialVersionUID = 1L;
{
add("/usr/share/hwdata/pci.ids");
add("/usr/share/misc/pci.ids");
add("/tmp/pci.ids");
}
});
/**
* The PCI IDs Database object.
* <p>
* This only needs to be loaded one time.
* <p>
* The pci ids library protects the data inside the object by making it immutable.
*/
public static final PciIdsDatabase DB = new PciIdsDatabase();
//Configure the PCI IDs Database object.
static {
if (!DB.isReady()) {
// if pciids file is found on the system, then process using this file
String dbFile = null;
for (final String path : PCI_IDS_PATH) {
if ((new File(path)).exists()) {
@ -57,11 +75,13 @@ public final class PciIds {
break;
}
}
if (dbFile != null) {
InputStream is = null;
try {
is = new FileInputStream(dbFile);
DB.loadStream(is);
pciidsFileStatus = UefiConstants.FILESTATUS_FROM_FILESYSTEM;
} catch (IOException e) {
// DB will not be ready, hardware IDs will not be translated
dbFile = null;
@ -75,14 +95,36 @@ public final class PciIds {
}
}
}
// if pciids file is not found on the system or not accessible, then attempt to grab it from code
if (pciidsFileStatus == UefiConstants.FILESTATUS_NOT_ACCESSIBLE) {
InputStream isFromCode = PciIds.class.getResourceAsStream(PCIIDS_FILENAME);
if (isFromCode != null) {
try {
DB.loadStream(isFromCode);
pciidsFileStatus = UefiConstants.FILESTATUS_FROM_CODE;
} catch (IOException e) {
// DB will not be ready, hardware IDs will not be translated
} finally {
try {
isFromCode.close();
} catch (IOException e) {
}
}
}
}
// if pciids file is not accessible on system or from within code, then log error
if (pciidsFileStatus == UefiConstants.FILESTATUS_NOT_ACCESSIBLE) {
log.info("PCI IDs file was NOT accessible from within the system or within the code");
}
}
}
/**
* Default private constructor so checkstyles doesn't complain.
*/
private PciIds() {
}
private PciIds() { }
/**
* Look up the vendor name from the PCI IDs list, if the input string contains an ID.
@ -93,7 +135,9 @@ public final class PciIds {
*/
public static ASN1UTF8String translateVendor(final ASN1UTF8String refManufacturer) {
ASN1UTF8String manufacturer = refManufacturer;
if (manufacturer != null && manufacturer.getString().trim().matches("^[0-9A-Fa-f]{4}$")) {
if (!pciidsFileStatus.equals(UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& manufacturer != null
&& manufacturer.getString().trim().matches("^[0-9A-Fa-f]{4}$")) {
Vendor ven = DB.findVendor(manufacturer.getString().toLowerCase());
if (ven != null && !Strings.isNullOrEmpty(ven.getName())) {
manufacturer = new DERUTF8String(ven.getName());
@ -111,7 +155,9 @@ public final class PciIds {
*/
public static String translateVendor(final String refManufacturer) {
String manufacturer = refManufacturer;
if (manufacturer != null && manufacturer.trim().matches("^[0-9A-Fa-f]{4}$")) {
if (!pciidsFileStatus.equals(UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& manufacturer != null
&& manufacturer.trim().matches("^[0-9A-Fa-f]{4}$")) {
Vendor ven = DB.findVendor(manufacturer.toLowerCase());
if (ven != null && !Strings.isNullOrEmpty(ven.getName())) {
manufacturer = ven.getName();
@ -126,14 +172,15 @@ public final class PciIds {
* If any part of this fails, return the original model value.
*
* @param refManufacturer ASN1UTF8String, likely from a ComponentIdentifier
* @param refModel ASN1UTF8String, likely from a ComponentIdentifier
* @param refModel ASN1UTF8String, likely from a ComponentIdentifier
* @return ASN1UTF8String with the discovered device name, or the original model value.
*/
public static ASN1UTF8String translateDevice(final ASN1UTF8String refManufacturer,
final ASN1UTF8String refModel) {
ASN1UTF8String manufacturer = refManufacturer;
ASN1UTF8String model = refModel;
if (manufacturer != null
if (!pciidsFileStatus.equals(UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& manufacturer != null
&& model != null
&& manufacturer.getString().trim().matches("^[0-9A-Fa-f]{4}$")
&& model.getString().trim().matches("^[0-9A-Fa-f]{4}$")) {
@ -152,13 +199,14 @@ public final class PciIds {
* If any part of this fails, return the original model value.
*
* @param refManufacturer String, likely from a ComponentResult
* @param refModel String, likely from a ComponentResult
* @param refModel String, likely from a ComponentResult
* @return String with the discovered device name, or the original model value.
*/
public static String translateDevice(final String refManufacturer,
final String refModel) {
String model = refModel;
if (refManufacturer != null
if (!pciidsFileStatus.equals(UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& refManufacturer != null
&& model != null
&& refManufacturer.trim().matches("^[0-9A-Fa-f]{4}$")
&& model.trim().matches("^[0-9A-Fa-f]{4}$")) {
@ -176,20 +224,23 @@ public final class PciIds {
* If any part of this fails, return the original manufacturer value.
*
* @param refClassCode String, formatted as 2 characters (1 byte) for each of the 3 categories
* Example "010802":
* Class: "01"
* Subclass: "08"
* Programming Interface: "02"
* . Example "010802":
* . Class: "01"
* . Subclass: "08"
* . Programming Interface: "02"
* @return List<String> 3-element list with the class code
* 1st element: human-readable description of Class
* 2nd element: human-readable description of Subclass
* 3rd element: human-readable description of Programming Interface
* . 1st element: human-readable description of Class
* . 2nd element: human-readable description of Subclass
* . 3rd element: human-readable description of Programming Interface
*/
public static List<String> translateDeviceClass(final String refClassCode) {
List<String> translatedClassCode = new ArrayList<>();
String classCode = refClassCode;
if (classCode != null && classCode.trim().matches("^[0-9A-Fa-f]{6}$")) {
if (!pciidsFileStatus.equals(UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& classCode != null
&& classCode.trim().matches("^[0-9A-Fa-f]{6}$")) {
final int startIndexOfDeviceClass = 0;
final int endIndexOfDeviceClass = 2;
String deviceClass =

View File

@ -20,9 +20,6 @@ import java.security.cert.CertificateException;
import java.util.Collection;
import java.util.LinkedHashMap;
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_FILESYSTEM;
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE;
/**
* Class for handling different formats of TCG Event logs.
*/
@ -88,7 +85,16 @@ public final class TCGEventLog {
* and if that event causes a different status.
*/
@Getter
private String vendorTableFileStatus = FILESTATUS_FROM_FILESYSTEM;
private String vendorTableFileStatus = UefiConstants.FILESTATUS_FROM_FILESYSTEM;
/**
* Track status of pci.ids
* This is only used if there is an event that uses functions from the pciids class.
* Default is normal status (normal status is from-filesystem).
* Status will only change IF there is an event that uses pciids file, and the file
* causes a different status.
*/
@Getter
private String pciidsFileStatus = UefiConstants.FILESTATUS_FROM_FILESYSTEM;
/**
* Default blank object constructor.
@ -169,11 +175,17 @@ public final class TCGEventLog {
// the if statement is executed
// [new event file status = eventList.get(eventNumber-1).getVendorTableFileStatus()]
// (ie. if the new file status is not-accessible or from-code, then want to update)
if ((vendorTableFileStatus != FILESTATUS_NOT_ACCESSIBLE)
if ((vendorTableFileStatus != UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& (eventList.get(eventNumber - 1).getVendorTableFileStatus()
!= FILESTATUS_FROM_FILESYSTEM)) {
!= UefiConstants.FILESTATUS_FROM_FILESYSTEM)) {
vendorTableFileStatus = eventList.get(eventNumber - 1).getVendorTableFileStatus();
}
//similar to above with vendor-table.json file, but here with pci.ids file
if ((pciidsFileStatus != UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& (eventList.get(eventNumber - 1).getPciidsFileStatus()
!= UefiConstants.FILESTATUS_FROM_FILESYSTEM)) {
pciidsFileStatus = eventList.get(eventNumber - 1).getPciidsFileStatus();
}
}
calculatePcrValues();
}

View File

@ -12,8 +12,8 @@ import java.math.BigInteger;
* Class to for the TCG defined TPMT_HA structure used to support the Crypto Agile Log format.
* <p>
* typedef struct {
* TPMI_ALG_HASH hashAlg;
* TPMU_HA digest;
* . TPMI_ALG_HASH hashAlg;
* . TPMU_HA digest;
* } TPMT_HA;
*/
public class TcgTpmtHa {

View File

@ -39,16 +39,16 @@ import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_FILESYS
* TCG_PCR_EVENT is used when the Event log uses the SHA1 Format as described in the
* TCG Platform Firmware Profile (PFP) specification.
* typedef struct {
* TCG_PCRINDEX PCRIndex; //PCR Index value that either
* //matches the PCRIndex of a
* //previous extend operation or
* //indicates that this Event Log
* //entry is not associated with
* //an extend operation
* TCG_EVENTTYPE EventType; //See Log event types defined in toStrng()
* TCG_DIGEST digest; //The hash of the event data
* UINT32 EventSize; //Size of the event data
* UINT8 Event[EventSize]; //The event data
* . TCG_PCRINDEX PCRIndex; //PCR Index value that either
* . //matches the PCRIndex of a
* . //previous extend operation or
* . //indicates that this Event Log
* . //entry is not associated with
* . //an extend operation
* . TCG_EVENTTYPE EventType; //See Log event types defined in toStrng()
* . TCG_DIGEST digest; //The hash of the event data
* . UINT32 EventSize; //Size of the event data
* . UINT8 Event[EventSize]; //The event data
* } TCG_PCR_EVENT;
*/
@Log4j2
@ -127,6 +127,16 @@ public class TpmPcrEvent {
@Getter
private String vendorTableFileStatus = FILESTATUS_FROM_FILESYSTEM;
/**
* Track status of pci.ids
* This is only used for events that access the pci.ids file.
* Default is normal status (normal status is from-filesystem).
* Status will only change IF this is an event that uses this file,
* and if that event causes a different status.
*/
@Getter
private String pciidsFileStatus = FILESTATUS_FROM_FILESYSTEM;
/**
* Constructor.
*
@ -438,6 +448,7 @@ public class TpmPcrEvent {
specVersion = noAction.getSpecVersion();
specErrataVersion = noAction.getSpecErrataVersion();
}
pciidsFileStatus = noAction.getPciidsFileStatus();
break;
case EvConstants.EV_SEPARATOR:
if (EvPostCode.isAscii(content)) {
@ -523,7 +534,9 @@ public class TpmPcrEvent {
break;
case EvConstants.EV_EFI_SPDM_FIRMWARE_BLOB:
case EvConstants.EV_EFI_SPDM_FIRMWARE_CONFIG:
description += "Event Content:\n" + new EvEfiSpdmDeviceSecurityEvent(content).toString();
EvEfiSpdmDeviceSecurityEvent efiSpdmDse = new EvEfiSpdmDeviceSecurityEvent(content);
description += "Event Content:\n" + efiSpdmDse.toString();
pciidsFileStatus = efiSpdmDse.getPciidsFileStatus();
break;
default:
description += " Unknown Event found" + "\n";

View File

@ -15,11 +15,11 @@ import java.security.cert.CertificateException;
* TCG Platform Firmware Profile specification.
* typedef struct {
* UINT32 PCRIndex; //PCR Index value that either
* //matches the PCRIndex of a
* //previous extend operation or
* //indicates that this Event Log
* //entry is not associated with
* //an extend operation
* . //matches the PCRIndex of a
* . //previous extend operation or
* . //indicates that this Event Log
* . //entry is not associated with
* . //an extend operation
* UINT32 EventType; //See Log event types
* BYTE digest[20]; //The SHA1 hash of the event data
* UINT32 EventSize; //Size of the event data

View File

@ -16,30 +16,30 @@ import java.util.ArrayList;
* TCG Platform Firmware Profile specification.
* This class will only process SHA-256 digests.
* typedef struct {
* UINT32 PCRIndex; //PCR Index value that either
* //matches the PCRIndex of a
* //previous extend operation or
* //indicates that this Event Log
* //entry is not associated with
* //an extend operation
* UINT32 EventType; //See Log event types
* TPML_DIGEST_VALUES digest; //The hash of the event data
* UINT32 EventSize; //Size of the event data
* BYTE Event[1]; //The event data
* } TCG_PCR_EVENT2; //The event data structure to be added
* . UINT32 PCRIndex; //PCR Index value that either
* . //matches the PCRIndex of a
* . //previous extend operation or
* . //indicates that this Event Log
* . //entry is not associated with
* . //an extend operation
* . UINT32 EventType; //See Log event types
* . TPML_DIGEST_VALUES digest; //The hash of the event data
* . UINT32 EventSize; //Size of the event data
* . BYTE Event[1]; //The event data
* } TCG_PCR_EVENT2; //The event data structure to be added
* typedef struct {
* UINT32 count;
* TPMT_HA digests[HASH_COUNT];
* . UINT32 count;
* . TPMT_HA digests[HASH_COUNT];
* } TPML_DIGEST_VALUES;
* typedef struct {
* TPMI_ALG_HASH hashAlg;
* TPMU_HA digest;
* . TPMI_ALG_HASH hashAlg;
* . TPMU_HA digest;
* } TPMT_HA;
* typedef union {
* BYTE sha1[SHA1_DIGEST_SIZE];
* BYTE sha256[SHA256_DIGEST_SIZE];
* BYTE sha384[SHA384_DIGEST_SIZE];
* BYTE sha512[SHA512_DIGEST_SIZE];
* . BYTE sha1[SHA1_DIGEST_SIZE];
* . BYTE sha256[SHA256_DIGEST_SIZE];
* . BYTE sha384[SHA384_DIGEST_SIZE];
* . BYTE sha512[SHA512_DIGEST_SIZE];
* } TPMU_HA;
* define SHA1_DIGEST_SIZE 20
* define SHA256_DIGEST_SIZE 32

View File

@ -1,5 +1,6 @@
package hirs.utils.tpm.eventlog.events;
import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import lombok.Getter;
import lombok.Setter;
@ -7,34 +8,34 @@ import lombok.Setter;
* Abstract base class to process the DEVICE_SECURITY_EVENT_DATA or ..DATA2 event.
* Parses event data per PFP v1.06 Rev52 Tables 20 and 26.
* The event data comes in 2 forms:
* 1) DEVICE_SECURITY_EVENT_DATA or
* 2) DEVICE_SECURITY_EVENT_DATA2
* . 1) DEVICE_SECURITY_EVENT_DATA or
* . 2) DEVICE_SECURITY_EVENT_DATA2
* The first 2 fields of the respective headers are the same in both ..DATA and ..DATA2.
* Field 1:
* The first 16 bytes of the event data header MUST be a String based identifier (Signature),
* per PFP. The only currently defined Signatures are "SPDM Device Sec" and "SPDM Device Sec2",
* which implies the data is a DEVICE_SECURITY_EVENT_DATA or ..DATA2, respectively.
* . The first 16 bytes of the event data header MUST be a String based identifier (Signature),
* . per PFP. The only currently defined Signatures are "SPDM Device Sec" and "SPDM Device Sec2",
* . which implies the data is a DEVICE_SECURITY_EVENT_DATA or ..DATA2, respectively.
* Field 2:
* The Version field also indicates whether the Device Security Event is ..DATA or ..DATA2.
* . The Version field also indicates whether the Device Security Event is ..DATA or ..DATA2.
*
* DEVICE SECURITY EVENT structures defined by PFP v1.06 Rev 52:
* <p>
* typedef struct tdDEVICE_SECURITY_EVENT_DATA {
* DEVICE_SECURITY_EVENT_DATA_HEADER EventDataHeader;
* DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT DeviceContext;
* . DEVICE_SECURITY_EVENT_DATA_HEADER EventDataHeader;
* . DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT DeviceContext;
* } DEVICE_SECURITY_EVENT_DATA;
* <p>
* typedef struct tdDEVICE_SECURITY_EVENT_DATA2 {
* DEVICE_SECURITY_EVENT_DATA_HEADER2 EventDataHeader;
* DEVICE_SECURITY_EVENT_DATA_SUB_HEADER EventDataSubHeader;
* DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT DeviceContext;
* . DEVICE_SECURITY_EVENT_DATA_HEADER2 EventDataHeader;
* . DEVICE_SECURITY_EVENT_DATA_SUB_HEADER EventDataSubHeader;
* . DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT DeviceContext;
* } DEVICE_SECURITY_EVENT_DATA2;
* <p>
* typedef struct tdDEVICE_SECURITY_EVENT_DATA_HEADER or HEADER2 {
* UINT8 Signature[16];
* UINT16 Version;
* ... ...
* (The rest of the components are different for HEADER vs HEADER2)
* . UINT8 Signature[16];
* . UINT16 Version;
* . ... ...
* . (The rest of the components are different for HEADER vs HEADER2)
* }
* <p>
*/
@ -44,7 +45,7 @@ public abstract class DeviceSecurityEvent {
* DeviceSecurityEventDataContext Object.
*/
@Getter
private DeviceSecurityEventDataDeviceContext dsedDevContext = null;
private DeviceSecurityEventDataPciContext dsedPciContext = null;
/**
* Device type.
@ -60,6 +61,18 @@ public abstract class DeviceSecurityEvent {
@Getter
private String deviceContextInfo = "";
/**
* Track status of pci.ids
* This is only used for events that access the pci.ids file.
* (In this class, this is only needed if DeviceSecurityEvent includes
* a DeviceSecurityEventDataPciContext)
* Default is normal status (normal status is from-filesystem).
* Status will only change IF this is an event that uses this file,
* and if that event causes a different status.
*/
@Getter
private String pciidsFileStatus = UefiConstants.FILESTATUS_FROM_FILESYSTEM;
/**
* DeviceSecurityEventData Default Constructor.
*
@ -82,8 +95,11 @@ public abstract class DeviceSecurityEvent {
if (deviceType == DeviceSecurityEventDataDeviceContext.DEVICE_TYPE_NONE) {
deviceContextInfo = "\n No Device Context (indicated by device type value of 0)";
} else if (deviceType == DeviceSecurityEventDataDeviceContext.DEVICE_TYPE_PCI) {
dsedDevContext = new DeviceSecurityEventDataPciContext(dsedDeviceContextBytes);
deviceContextInfo = dsedDevContext.toString();
dsedPciContext = new DeviceSecurityEventDataPciContext(dsedDeviceContextBytes);
deviceContextInfo = dsedPciContext.toString();
// getPciidsFileStatus() must be called after DeviceSecurityEventDataPciContext.toString(),
// because the toString function is where the pciids db gets set up and used
pciidsFileStatus = dsedPciContext.getPciidsFileStatus();
} else if (deviceType == DeviceSecurityEventDataDeviceContext.DEVICE_TYPE_USB) {
deviceContextInfo = " Device Type: USB - To be implemented";
} else {

View File

@ -7,8 +7,8 @@ import lombok.Getter;
* Parses event data per PFP v1.06 Rev52 Table 20.
* <p>
* typedef struct tdDEVICE_SECURITY_EVENT_DATA {
* DEVICE_SECURITY_EVENT_DATA_HEADER EventDataHeader;
* DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT DeviceContext;
* . DEVICE_SECURITY_EVENT_DATA_HEADER EventDataHeader;
* . DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT DeviceContext;
* } DEVICE_SECURITY_EVENT_DATA;
* <p>
*/

View File

@ -7,9 +7,9 @@ import lombok.Getter;
* Parses event data per PFP v1.06 Rev52 Table 26.
* <p>
* typedef struct tdDEVICE_SECURITY_EVENT_DATA2 {
* DEVICE_SECURITY_EVENT_DATA_HEADER2 EventDataHeader;
* DEVICE_SECURITY_EVENT_DATA_SUB_HEADER EventDataSubHeader;
* DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT DeviceContext;
* . DEVICE_SECURITY_EVENT_DATA_HEADER2 EventDataHeader;
* . DEVICE_SECURITY_EVENT_DATA_SUB_HEADER EventDataSubHeader;
* . DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT DeviceContext;
* } DEVICE_SECURITY_EVENT_DATA2;
* <p>
*/

View File

@ -10,8 +10,8 @@ import lombok.Getter;
* or USB connection.
* <p>
* typedef union tdDEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT {
* DEVICE_SECURITY_EVENT_DATA_PCI_CONTEXT PciContext;
* DEVICE_SECURITY_EVENT_DATA_USB_CONTEXT UsbContext;
* . DEVICE_SECURITY_EVENT_DATA_PCI_CONTEXT PciContext;
* . DEVICE_SECURITY_EVENT_DATA_USB_CONTEXT UsbContext;
* } DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT;
* <p>
*/

View File

@ -17,14 +17,14 @@ import java.io.IOException;
* HEADERS defined by PFP v1.06 Rev 52:
* <p>
* typedef struct tdDEVICE_SECURITY_EVENT_DATA_HEADER {
* UINT8 Signature[16];
* UINT16 Version;
* UINT16 Length;
* UINT32 SpdmHashAlg;
* UINT32 DeviceType;
* SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock;
* UINT64 DevicePathLength;
* UNIT8 DevicePath[DevicePathLength]
* . UINT8 Signature[16];
* . UINT16 Version;
* . UINT16 Length;
* . UINT32 SpdmHashAlg;
* . UINT32 DeviceType;
* . SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock;
* . UINT64 DevicePathLength;
* . UNIT8 DevicePath[DevicePathLength]
* } DEVICE_SECURITY_EVENT_DATA_HEADER;
* <p>
* Assumption: there is only 1 SpdmMeasurementBlock per event. Need more test patterns to verify.

View File

@ -11,17 +11,17 @@ import lombok.Getter;
* HEADERS defined by PFP v1.06 Rev 52:
* <p>
* typedef struct tdDEVICE_SECURITY_EVENT_DATA_HEADER2 {
* UINT8 Signature[16];
* UINT16 Version;
* UINT8 AuthState;
* UINT8 Reserved
* UINT32 Length;
* UINT32 DeviceType;
* UINT32 SubHeaderType;
* UINT32 SubHeaderLength;
* UINT64 SubHeaderUID;
* UINT64 DevicePathLength;
* UNIT8 DevicePath[DevicePathLength]
* . UINT8 Signature[16];
* . UINT16 Version;
* . UINT8 AuthState;
* . UINT8 Reserved
* . UINT32 Length;
* . UINT32 DeviceType;
* . UINT32 SubHeaderType;
* . UINT32 SubHeaderLength;
* . UINT64 SubHeaderUID;
* . UINT64 DevicePathLength;
* . UNIT8 DevicePath[DevicePathLength]
* } DEVICE_SECURITY_EVENT_DATA_HEADER2;
* <p>
*/

View File

@ -1,6 +1,8 @@
package hirs.utils.tpm.eventlog.events;
import hirs.utils.HexUtils;
import hirs.utils.PciIds;
import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import lombok.Getter;
import java.util.List;
@ -13,28 +15,28 @@ import static hirs.utils.PciIds.translateVendor;
* Class to process the DEVICE_SECURITY_EVENT_DATA_PCI_CONTEXT event per PFP.
* <p>
* typedef struct tdDEVICE_SECURITY_EVENT_DATA_PCI_CONTEXT {
* UINT16 Version;
* UINT16 Length;
* UINT16 VendorId;
* UINT16 DeviceId;
* UINT16 RevisionId;
* UINT16 ClassCode[3];
* UINT16 SubsystemVendorId;
* UINT16 SubsystemId;
* . UINT16 Version;
* . UINT16 Length;
* . UINT16 VendorId;
* . UINT16 DeviceId;
* . UINT16 RevisionId;
* . UINT16 ClassCode[3];
* . UINT16 SubsystemVendorId;
* . UINT16 SubsystemId;
* <p>
* The following fields are defined by the PCI Express Base Specification rev4.0 v1.0.
* VendorId
* DeviceId
* RevisionId
* ClassCode
* SubsystemVendorId
* SubsystemId
* . VendorId
* . DeviceId
* . RevisionId
* . ClassCode
* . SubsystemVendorId
* . SubsystemId
* Vendor id and device id are registered to specific manufacturers.
* https://admin.pci-ids.ucw.cz/read/PC/
* Ex. vendor id 8086 and device id 0b60: https://admin.pci-ids.ucw.cz/read/PC/8086/0b60
* . https://admin.pci-ids.ucw.cz/read/PC/
* . Ex. vendor id 8086 and device id 0b60: https://admin.pci-ids.ucw.cz/read/PC/8086/0b60
* Class code can be looked up on the web.
* https://admin.pci-ids.ucw.cz/read/PD/
* The revision ID is controlled by the vendor and cannot be looked up.
* . https://admin.pci-ids.ucw.cz/read/PD/
* . The revision ID is controlled by the vendor and cannot be looked up.
*/
public class DeviceSecurityEventDataPciContext extends DeviceSecurityEventDataDeviceContext {
@ -69,6 +71,12 @@ public class DeviceSecurityEventDataPciContext extends DeviceSecurityEventDataDe
@Getter
private String subsystemId = "";
/**
* Track status of pci.ids file.
*/
@Getter
private String pciidsFileStatus = UefiConstants.FILESTATUS_NOT_ACCESSIBLE;
/**
* DeviceSecurityEventDataPciContext Constructor.
*
@ -122,6 +130,13 @@ public class DeviceSecurityEventDataPciContext extends DeviceSecurityEventDataDe
dSEDpciContextInfo += super.toString();
dSEDpciContextInfo += " Device Type = PCI\n";
dSEDpciContextInfo += " Vendor = " + translateVendor(vendorId) + "\n";
// the above call to translateVendor() is the first location in this class where
// a function in pciids class is called
// thus, if pciids db has not previously been set up, this call will trigger that setup
// the setup will look for the pciids file; need to check and store the status of that file
pciidsFileStatus = PciIds.getPciidsFileStatus();
dSEDpciContextInfo += " Device = " + translateDevice(vendorId, deviceId) + "\n";
dSEDpciContextInfo += " RevisionID = " + revisionId + "\n";
@ -133,7 +148,7 @@ public class DeviceSecurityEventDataPciContext extends DeviceSecurityEventDataDe
dSEDpciContextInfo += " Subclass = " + classCodeList.get(1) + "\n";
dSEDpciContextInfo += " Programming Interface = " + classCodeList.get(2) + "\n";
} else {
dSEDpciContextInfo += " ** Class code could not be determined **";
dSEDpciContextInfo += " (Class code could not be determined)\n";
}
dSEDpciContextInfo += " SubsystemVendor = " + translateVendor(subsystemVendorId) + "\n";
dSEDpciContextInfo += " Subsystem = " + translateDevice(subsystemVendorId, subsystemId) + "\n";

View File

@ -5,9 +5,9 @@ package hirs.utils.tpm.eventlog.events;
*
* <p>
* typedef union tdDEVICE_SECURITY_EVENT_DATA_SUB_HEADER {
* DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock;
* DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN SpdmCertChain;
* DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_OEM_MEASUREMENT OemMeasurement;
* . DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock;
* . DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN SpdmCertChain;
* . DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_OEM_MEASUREMENT OemMeasurement;
* } DEVICE_SECURITY_EVENT_DATA_SUB_HEADER;
* <p>
*/

View File

@ -9,11 +9,11 @@ import hirs.utils.tpm.eventlog.spdm.SpdmHa;
*
* <p>
* typedef union tdDEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN {
* UINT16 SpdmVersion;
* UINT8 SpdmSlotId;
* UINT8 Reserved;
* UINT32 SpdmBaseHashAlgo;
* SPDM_CERT_CHAIN SpdmCertChain;
* . UINT16 SpdmVersion;
* . UINT8 SpdmSlotId;
* . UINT8 Reserved;
* . UINT32 SpdmBaseHashAlgo;
* . SPDM_CERT_CHAIN SpdmCertChain;
* } DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN;
* <p>
* SpdmVersion: SpdmBaseHashAlgo

View File

@ -15,21 +15,21 @@ import java.util.List;
*
* <p>
* typedef union tdDEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK {
* UINT16 SpdmVersion;
* UINT8 SpdmMeasurementBlockCount;
* UINT8 Reserved;
* UINT32 SpdmMeasurementHashAlgo;
* SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock[SpdmMeasurementBlockCount];
* . UINT16 SpdmVersion;
* . UINT8 SpdmMeasurementBlockCount;
* . UINT8 Reserved;
* . UINT32 SpdmMeasurementHashAlgo;
* . SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock[SpdmMeasurementBlockCount];
* } DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK;
* <p>
* <p>
* SpdmMeasurementBlock is an array of SPDM_MEASUREMENT_BLOCKs
* The size of each block is the same and can be found by either:
* 1) 4 + SpdmMeasurementBlock MeasurementSize
* OR
* 2) 4 + hash length of the hash algorithm found in
* DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK SpdmMeasurementHashAlgo
* where 4 is the size of the SpdmMeasurementBlock header
* . The size of each block is the same and can be found by either:
* . 1) 4 + SpdmMeasurementBlock MeasurementSize
* . OR
* . 2) 4 + hash length of the hash algorithm found in
* . DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK SpdmMeasurementHashAlgo
* . where 4 is the size of the SpdmMeasurementBlock header
*/
public class DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock extends DeviceSecurityEventDataSubHeader {

View File

@ -17,36 +17,36 @@ import java.nio.charset.StandardCharsets;
* Certain fields are common to both ..HEADER and ..HEADER2, and are noted below the structures.
* <p>
* typedef struct tdDEVICE_SECURITY_EVENT_DATA_HEADER {
* UINT8 Signature[16];
* UINT16 Version;
* UINT16 Length;
* UINT32 SpdmHashAlg;
* UINT32 DeviceType;
* SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock;
* UINT64 DevicePathLength;
* UNIT8 DevicePath[DevicePathLength]
* . UINT8 Signature[16];
* . UINT16 Version;
* . UINT16 Length;
* . UINT32 SpdmHashAlg;
* . UINT32 DeviceType;
* . SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock;
* . UINT64 DevicePathLength;
* . UNIT8 DevicePath[DevicePathLength]
* } DEVICE_SECURITY_EVENT_DATA_HEADER;
* <p>
* typedef struct tdDEVICE_SECURITY_EVENT_DATA_HEADER2 { - NOT IMPLEMENTED YET
* UINT8 Signature[16];
* UINT16 Version;
* UINT8 AuthState;
* UINT8 Reserved;
* UINT32 Length;
* UINT32 DeviceType;
* UINT32 SubHeaderType;
* UINT32 SubHeaderLength;
* UINT32 SubHeaderUID;
* UINT64 DevicePathLength;
* UNIT8 DevicePath[DevicePathLength]
* . UINT8 Signature[16];
* . UINT16 Version;
* . UINT8 AuthState;
* . UINT8 Reserved;
* . UINT32 Length;
* . UINT32 DeviceType;
* . UINT32 SubHeaderType;
* . UINT32 SubHeaderLength;
* . UINT32 SubHeaderUID;
* . UINT64 DevicePathLength;
* . UNIT8 DevicePath[DevicePathLength]
* } DEVICE_SECURITY_EVENT_DATA_HEADER2;
* <p>
* Fields common to both ..HEADER and ..HEADER2:
* Signature
* Version
* DeviceType
* DevicePathLength
* DevicePath
* . Signature
* . Version
* . DeviceType
* . DevicePathLength
* . DevicePath
* <p>
*/
public abstract class DeviceSecurityEventHeader {

View File

@ -2,23 +2,24 @@ package hirs.utils.tpm.eventlog.events;
import hirs.utils.HexUtils;
import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import lombok.Getter;
import java.nio.charset.StandardCharsets;
/**
* Abstract class to process any SPDM event that is solely a DEVICE_SECURITY_EVENT_DATA or
* DEVICE_SECURITY_EVENT_DATA2. The event field MUST be a
* 1) DEVICE_SECURITY_EVENT_DATA or
* 2) DEVICE_SECURITY_EVENT_DATA2
* . 1) DEVICE_SECURITY_EVENT_DATA or
* . 2) DEVICE_SECURITY_EVENT_DATA2
* DEVICE_SECURITY_EVENT_DATA has 2 structures:
* 1) DEVICE_SECURITY_EVENT_DATA_HEADER
* 2) DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT, which has 2 structures
* a) DEVICE_SECURITY_EVENT_DATA_PCI_CONTEXT
* b) DEVICE_SECURITY_EVENT_DATA_USB_CONTEXT
* . 1) DEVICE_SECURITY_EVENT_DATA_HEADER
* . 2) DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT, which has 2 structures
* . a) DEVICE_SECURITY_EVENT_DATA_PCI_CONTEXT
* . b) DEVICE_SECURITY_EVENT_DATA_USB_CONTEXT
* DEVICE_SECURITY_EVENT_DATA2 has 3 structures:
* 1) DEVICE_SECURITY_EVENT_DATA_HEADER2
* 2) DEVICE_SECURITY_EVENT_DATA_SUB_HEADER
* 3) DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT, which has 2 structures (see above)
* . 1) DEVICE_SECURITY_EVENT_DATA_HEADER2
* . 2) DEVICE_SECURITY_EVENT_DATA_SUB_HEADER
* . 3) DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT, which has 2 structures (see above)
* The first 16 bytes of the event data header MUST be a String based identifier (Signature),
* NUL-terminated, per PFP. The only currently defined Signature is "SPDM Device Sec",
* which implies the data is a DEVICE_SECURITY_EVENT_DATA or ..DATA2.
@ -45,6 +46,16 @@ public class EvEfiSpdmDeviceSecurityEvent {
*/
private String spdmInfo = "";
/**
* Track status of pci.ids
* This is only used for events that access the pci.ids file.
* Default is normal status (normal status is from-filesystem).
* Status will only change IF this is an event that uses this file,
* and if that event causes a different status.
*/
@Getter
private String pciidsFileStatus = UefiConstants.FILESTATUS_FROM_FILESYSTEM;
/**
* EvEfiSpdmFirmwareBlob constructor.
*
@ -72,6 +83,7 @@ public class EvEfiSpdmDeviceSecurityEvent {
if (dsedVersion.equals("0200")) {
dsed = new DeviceSecurityEventData2(eventData);
spdmInfo += dsed.toString();
pciidsFileStatus = dsed.getPciidsFileStatus();
} else {
spdmInfo += " Incompatible version for DeviceSecurityEventData2: " + dsedVersion + "\n";
}
@ -82,6 +94,7 @@ public class EvEfiSpdmDeviceSecurityEvent {
if (dsedVersion.equals("0100")) {
dsed = new DeviceSecurityEventData(eventData);
spdmInfo += dsed.toString();
pciidsFileStatus = dsed.getPciidsFileStatus();
} else {
spdmInfo += " Incompatible version for DeviceSecurityEventData: " + dsedVersion + "\n";
}

View File

@ -11,16 +11,16 @@ import java.nio.charset.StandardCharsets;
* Class to process the EV_NO_ACTION event.
* The first 16 bytes of the event data MUST be a String based identifier (Signature).
* Currently defined Signatures are
* "Spec ID Event03"
* - implies the data is a TCG_EfiSpecIDEvent
* - TCG_EfiSpecIDEvent is the first event in a TPM Event Log and is used to determine
* if the format of the Log (SHA1 vs Crypto Agile).
* "StartupLocality"
* - implies the data represents locality info (use lookup to interpret)
* "NvIndexInstance"
* - implies the data is a NV_INDEX_INSTANCE_EVENT_LOG_DATA
* "NvIndexDynamic"
* - implies the data is a NV_INDEX_DYNAMIC_EVENT_LOG_DATA
* . "Spec ID Event03"
* . - implies the data is a TCG_EfiSpecIDEvent
* . - TCG_EfiSpecIDEvent is the first event in a TPM Event Log and is used to determine
* . if the format of the Log (SHA1 vs Crypto Agile).
* . "StartupLocality"
* . - implies the data represents locality info (use lookup to interpret)
* . "NvIndexInstance"
* . - implies the data is a NV_INDEX_INSTANCE_EVENT_LOG_DATA
* . "NvIndexDynamic"
* . - implies the data is a NV_INDEX_DYNAMIC_EVENT_LOG_DATA
* <p>
* Notes:
* 1. First 16 bytes of the structure is an ASCII with a fixed Length of 16
@ -53,6 +53,16 @@ public class EvNoAction {
@Getter
private String noActionInfo = "";
/**
* Track status of pci.ids
* This is only used for events that access the pci.ids file.
* Default is normal status (normal status is from-filesystem).
* Status will only change IF this is an event that uses this file,
* and if that event causes a different status.
*/
@Getter
private String pciidsFileStatus = UefiConstants.FILESTATUS_FROM_FILESYSTEM;
/**
* EvNoAction constructor.
*
@ -78,6 +88,7 @@ public class EvNoAction {
} else if (signature.contains("NvIndexInstance")) {
NvIndexInstanceEventLogData nvIndexInstanceEvent = new NvIndexInstanceEventLogData(eventData);
noActionInfo += nvIndexInstanceEvent.toString();
pciidsFileStatus = nvIndexInstanceEvent.getPciidsFileStatus();
} else if (signature.contains("NvIndexDynamic")) {
NvIndexDynamicEventLogData nvIndexDynamicEvent = new NvIndexDynamicEventLogData(eventData);
noActionInfo += nvIndexDynamicEvent.toString();

View File

@ -8,19 +8,19 @@ import java.nio.charset.StandardCharsets;
* Class to process the NV_INDEX_DYNAMIC_EVENT_LOG_DATA per PFP.
* Per PFP, the first 16 bytes of the structure are a String based identifier (Signature),
* which are a NULL-terminated ASCII string "NvIndexDynamic".
* <p>
*
* HEADERS defined by PFP v1.06 Rev 52.
* Certain fields are common to both ..HEADER and ..HEADER2, and are noted below the structures.
* <p>
* typedef struct tdNV_INDEX_DYNAMIC_EVENT_LOG_DATA {
* BYTE Signature[16];
* UINT16 Version;
* UINT8[6] Reserved;
* UINT64 UID;
* UINT16 DescriptionSize;
* UINT8 Description[DescriptionSize];
* UINT16 DataSize;
* DEVICE_SECURITY_EVENT_DATA2 Data[DataSize];
* . BYTE Signature[16];
* . UINT16 Version;
* . UINT8[6] Reserved;
* . UINT64 UID;
* . UINT16 DescriptionSize;
* . UINT8 Description[DescriptionSize];
* . UINT16 DataSize;
* . UINT8 Data[DataSize];
* } NV_INDEX_DYNAMIC_EVENT_LOG_DATA;
* <p>
*/
@ -61,6 +61,7 @@ public class NvIndexDynamicEventLogData {
nvIndexDynamicInfo += " Nv Index Dynamic Version = " + nvIndexVersion + "\n";
// 6 bytes of Reserved data
final int uidBytesSize = 8;
final int eventDataSrcIndex2 = 24;
byte[] uidBytes = new byte[uidBytesSize];

View File

@ -1,6 +1,8 @@
package hirs.utils.tpm.eventlog.events;
import hirs.utils.HexUtils;
import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import lombok.Getter;
import java.nio.charset.StandardCharsets;
@ -13,10 +15,10 @@ import java.nio.charset.StandardCharsets;
* Certain fields are common to both ..HEADER and ..HEADER2, and are noted below the structures.
* <p>
* typedef struct tdNV_INDEX_INSTANCE_EVENT_LOG_DATA {
* BYTE Signature[16];
* UINT16 Version;
* UINT8[6] Reserved;
* DEVICE_SECURITY_EVENT_DATA2 Data;
* . BYTE Signature[16];
* . UINT16 Version;
* . UINT8[6] Reserved;
* . DEVICE_SECURITY_EVENT_DATA2 Data;
* } NV_INDEX_INSTANCE_EVENT_LOG_DATA;
* <p>
*/
@ -38,6 +40,16 @@ public class NvIndexInstanceEventLogData {
*/
private String nvIndexInstanceInfo = "";
/**
* Track status of pci.ids
* This is only used for events that access the pci.ids file.
* Default is normal status (normal status is from-filesystem).
* Status will only change IF this is an event that uses this file,
* and if that event causes a different status.
*/
@Getter
private String pciidsFileStatus = UefiConstants.FILESTATUS_FROM_FILESYSTEM;
/**
* NvIndexInstanceEventLogData constructor.
*
@ -89,6 +101,7 @@ public class NvIndexInstanceEventLogData {
if (dsedVersion.equals("0200")) {
dsed = new DeviceSecurityEventData2(dsedEventData);
nvIndexInstanceInfo += dsed.toString();
pciidsFileStatus = dsed.getPciidsFileStatus();
} else {
nvIndexInstanceInfo += " Incompatible version for DeviceSecurityEventData2: "
+ dsedVersion + "\n";

View File

@ -15,22 +15,22 @@ import java.util.ArrayList;
* <p>
* Certificate chain format, defined by SPDM v1.03, Sect 10.6.1, Table 33:
* Certificate chain format {
* Length 2 bytes;
* Reserved 2 bytes;
* RootHash <H> bytes;
* Certificates <Length> - (4 + <H>) bytes;
* . Length 2 bytes;
* . Reserved 2 bytes;
* . RootHash <H> bytes;
* . Certificates <Length> - (4 + <H>) bytes;
* }
* <p>
* Length: total length of cert chain including all fields in this block
* H: the output size of the hash algorithm selected by the most recent ALGORITHMS response
* this field shall be in hash byte order
* hash algorithm is included in the DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN
* structure as the member "SpdmBaseHashAlg"
* . this field shall be in hash byte order
* . hash algorithm is included in the DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN
* . structure as the member "SpdmBaseHashAlg"
* RootHash: the digest of the Root Certificate.
* size is determined by hash algorithm selected by the most recent SPDM ALGORITHMS response;
* the hash algorithm is the DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN SpdmBaseHashAlgo
* . size is determined by hash algorithm selected by the most recent SPDM ALGORITHMS response;
* . the hash algorithm is the DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN SpdmBaseHashAlgo
* Certificates: Complete cert chain consisting of 1 or more ASN.1 DER-encoded X.509 v3 certs
* this field shall be in Encoded ASN.1 byte order
* . this field shall be in Encoded ASN.1 byte order
*/
public class SpdmCertificateChain {

View File

@ -8,21 +8,21 @@ import lombok.Getter;
* <p>
* Measurement, defined by SPDM v1.03, Sect 10.11.1, Table 54:
* DMTF measurement spec format {
* DMTFSpecMeasurementValueType 1 byte;
* DMTFSpecMeasurementValueSize 2 bytes;
* DMTFSpecMeasurementValue <DMTFSpecMeasurementValueSize> bytes;
* . DMTFSpecMeasurementValueType 1 byte;
* . DMTFSpecMeasurementValueSize 2 bytes;
* . DMTFSpecMeasurementValue <DMTFSpecMeasurementValueSize> bytes;
* }
* <p>
* DMTFSpecMeasurementValueType[7]
* Indicates how bits [0:6] are represented
* Bit = 0: Digest
* Bit = 1: Raw bit stream
* . Indicates how bits [0:6] are represented
* . Bit = 0: Digest
* . Bit = 1: Raw bit stream
* DMTFSpecMeasurementValueType[6:0] (see SPDM Spec, Table 55 "DMTFSpecMeasurementValueType[6:0]")
* Immutable ROM 0x0
* Mutable firmware 0x1
* Hardware configuration 0x2
* Firmware configuration 0x3
* etc.
* . Immutable ROM 0x0
* . Mutable firmware 0x1
* . Hardware configuration 0x2
* . Firmware configuration 0x3
* . etc.
* <p>
*/
public class SpdmMeasurement {

View File

@ -273,9 +273,9 @@ public final class UefiConstants {
public static final String FILESTATUS_FROM_FILESYSTEM = "fileFromFilesystem";
/**
* file status, where file was not found on local machine, so file from code was used.
* For instance, if vendor-table.json is not found in filesystem at location
* /etc/hirs/aca/default-properties/, it will be grabbed from code at
* HIRS_AttestationCA/src/main/resources/.
* . For instance, if vendor-table.json is not found in filesystem at location
* . /etc/hirs/aca/default-properties/, it will be grabbed from code at
* . HIRS_AttestationCA/src/main/resources/.
*/
public static final String FILESTATUS_FROM_CODE = "fileFromCode";
/**

View File

@ -10,10 +10,6 @@ import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.UUID;
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_CODE;
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_FILESYSTEM;
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE;
/**
* Class to process GUID per the UEFI specification
* GUIDs are essentially UUID as defined by RFC-1422, however Microsoft refers to GUIDS.
@ -44,7 +40,7 @@ public class UefiGuid {
* Track status of vendor-table.json.
*/
@Getter
private String vendorTableFileStatus = FILESTATUS_NOT_ACCESSIBLE;
private String vendorTableFileStatus = UefiConstants.FILESTATUS_NOT_ACCESSIBLE;
/**
* guid byte array.
@ -78,12 +74,12 @@ public class UefiGuid {
"VendorTable");
if (!isVendorTableReferenceHandleEmpty()) {
vendorTableFileStatus = FILESTATUS_FROM_FILESYSTEM;
vendorTableFileStatus = UefiConstants.FILESTATUS_FROM_FILESYSTEM;
} else {
// could not access vendor-table.json from filesystem, so attempt to access from code
uefiVendorRef = JsonUtils.getSpecificJsonObject(JSON_FILENAME, "VendorTable");
if (!isVendorTableReferenceHandleEmpty()) {
vendorTableFileStatus = FILESTATUS_FROM_CODE;
vendorTableFileStatus = UefiConstants.FILESTATUS_FROM_CODE;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -119,9 +119,11 @@ ospackage {
buildRpm {
arch = X86_64
requires('hwdata', '0.314', GREATER | EQUAL)
}
buildDeb {
arch = 'amd64'
requires('hwdata', '0.314', GREATER | EQUAL)
}
}

View File

@ -136,13 +136,24 @@ final class Main {
+ evLog.getEventList().size() + " events:\n\n");
}
if (evLog.getVendorTableFileStatus() == FILESTATUS_NOT_ACCESSIBLE) {
writeOut("*** WARNING: The file vendor-table.json was not accessible from the "
+ "filesystem or the code, so some event data shown in the output of this "
+ "tool may be outdated or omitted.\n\n");
writeOut("*** WARNING: "
+ "The file vendor-table.json was not accessible from the filesystem or the code,\n"
+ " so some event data shown in the output of this tool may be outdated\n"
+ " or omitted.\n\n");
} else if (evLog.getVendorTableFileStatus() == FILESTATUS_FROM_CODE) {
writeOut("*** NOTE: "
writeOut("*** NOTE: "
+ "The file vendor-table.json file was not accessible from the filesystem,\n"
+ " so the vendor-table.json from code was used.\n\n");
+ " so the vendor-table.json from code was used.\n\n");
}
if (evLog.getPciidsFileStatus() == FILESTATUS_NOT_ACCESSIBLE) {
writeOut("*** WARNING: "
+ "The file pci.ids was not accessible from the filesystem or the code,\n"
+ " so some pci device info lookups in the output of this tool\n"
+ " may be omitted or the hex code may be used instead.\n\n");
} else if (evLog.getPciidsFileStatus() == FILESTATUS_FROM_CODE) {
writeOut("*** NOTE: "
+ "The file pci.ids file was not accessible from the filesystem,\n"
+ " so the pci.ids from code was used.\n\n");
}
}
int eventCount = 0;