|
|
@@ -104,6 +104,13 @@ public final class SecurityUtils {
|
|
|
static Logger logger = LogManager.getLogger(SecurityUtils.class.getSimpleName());
|
|
|
static ExiCodec exiCodec;
|
|
|
|
|
|
+ public static enum ContractCertificateStatus {
|
|
|
+ UPDATE_NEEDED,
|
|
|
+ INSTALLATION_NEEDED,
|
|
|
+ OK,
|
|
|
+ UNKNOWN // is used as default for communication session context
|
|
|
+ }
|
|
|
+
|
|
|
public static Logger getLogger() {
|
|
|
return logger;
|
|
|
}
|
|
|
@@ -825,9 +832,12 @@ public final class SecurityUtils {
|
|
|
keyStore.store(fos, GlobalValues.PASSPHRASE_FOR_CERTIFICATES_AND_KEYS.toString().toCharArray());
|
|
|
fos.close();
|
|
|
|
|
|
+ X509Certificate contractCert = getCertificate(contractCertChain.getCertificate());
|
|
|
+
|
|
|
getLogger().info("Contract certificate with distinguished name '" +
|
|
|
- getCertificate(contractCertChain.getCertificate())
|
|
|
- .getSubjectX500Principal().getName() + "' saved");
|
|
|
+ contractCert.getSubjectX500Principal().getName() + "' saved. " +
|
|
|
+ "Valid until " + contractCert.getNotAfter()
|
|
|
+ );
|
|
|
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException | NullPointerException e) {
|
|
|
getLogger().error(e.getClass().getSimpleName() + " occurred while trying to save contract " +
|
|
|
"certificate chain", e);
|
|
|
@@ -838,6 +848,11 @@ public final class SecurityUtils {
|
|
|
}
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
+ * Gets the contract certificate from the EVCC keystore.
|
|
|
+ *
|
|
|
+ * @return The contract certificate if present, null otherwise
|
|
|
+ */
|
|
|
public static X509Certificate getContractCertificate() {
|
|
|
X509Certificate contractCertificate = null;
|
|
|
|
|
|
@@ -856,6 +871,89 @@ public final class SecurityUtils {
|
|
|
}
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
+ * A convenience function which checks if a contract certificate installation is needed.
|
|
|
+ * Normally not needed because of function getContractCertificateStatus().
|
|
|
+ *
|
|
|
+ * @return True, if no contract certificate is store or if the stored certificate is not valid, false otherwise
|
|
|
+ */
|
|
|
+ public static boolean isContractCertificateInstallationNeeded() {
|
|
|
+ X509Certificate contractCert = getContractCertificate();
|
|
|
+
|
|
|
+ if (contractCert == null) {
|
|
|
+ getLogger().info("No contract certificate stored");
|
|
|
+ return true;
|
|
|
+ } else if (contractCert != null && !isCertificateValid(contractCert)) {
|
|
|
+ getLogger().info("Stored contract certificate with distinguished name '" +
|
|
|
+ contractCert.getSubjectX500Principal().getName() + "' is not valid");
|
|
|
+ return true;
|
|
|
+ } else return false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * A convenience function which checks if a contract certificate update is needed.
|
|
|
+ * Normally not needed because of function getContractCertificateStatus().
|
|
|
+ *
|
|
|
+ * @return True, if contract certificate is still valid but about to expire, false otherwise.
|
|
|
+ * The expiration period is given in GlobalValues.CERTIFICATE_EXPIRES_SOON_PERIOD.
|
|
|
+ */
|
|
|
+ public static boolean isContractCertificateUpdateNeeded() {
|
|
|
+ X509Certificate contractCert = getContractCertificate();
|
|
|
+ short validityOfContractCert = getValidityPeriod(contractCert);
|
|
|
+
|
|
|
+ if (validityOfContractCert < 0) {
|
|
|
+ getLogger().warn("Contract certificate with distinguished name '" +
|
|
|
+ contractCert.getSubjectX500Principal().getName() + "' is not valid any more, expired " +
|
|
|
+ Math.abs(validityOfContractCert) + " days ago");
|
|
|
+ return false;
|
|
|
+ } else if (validityOfContractCert <= GlobalValues.CERTIFICATE_EXPIRES_SOON_PERIOD.getShortValue()) {
|
|
|
+ getLogger().info("Contract certificate with distinguished name '" +
|
|
|
+ contractCert.getSubjectX500Principal().getName() + "' is about to expire in " +
|
|
|
+ validityOfContractCert + " days");
|
|
|
+ return true;
|
|
|
+ } else return false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Checks whether a contract certificate
|
|
|
+ * - is stored
|
|
|
+ * - in case it is stored, if it is valid
|
|
|
+ * - in case it is valid, if it expires soon
|
|
|
+ *
|
|
|
+ * This method is intended to reduce cryptographic computation overhead by checking both, if installation or
|
|
|
+ * update is needed, at the same time. When executing either method by itself (isContractCertificateUpdateNeeded() and
|
|
|
+ * isContractCertificateInstallationNeeded()), each time the certificate is read anew from the Java keystore
|
|
|
+ * holding the contract certificate. With this method the contract certificate is read just once from the keystore.
|
|
|
+ *
|
|
|
+ * @return An enumeration value ContractCertificateStatus (either UPDATE_NEEDED, INSTALLATION_NEEDED, or OK)
|
|
|
+ */
|
|
|
+ public static ContractCertificateStatus getContractCertificateStatus() {
|
|
|
+ X509Certificate contractCert = getContractCertificate();
|
|
|
+
|
|
|
+ if (contractCert == null) {
|
|
|
+ getLogger().info("No contract certificate stored");
|
|
|
+ return ContractCertificateStatus.INSTALLATION_NEEDED;
|
|
|
+ } else if (contractCert != null && !isCertificateValid(contractCert)) {
|
|
|
+ getLogger().info("Stored contract certificate with distinguished name '" +
|
|
|
+ contractCert.getSubjectX500Principal().getName() + "' is not valid");
|
|
|
+ return ContractCertificateStatus.INSTALLATION_NEEDED;
|
|
|
+ } else {
|
|
|
+ short validityOfContractCert = getValidityPeriod(contractCert);
|
|
|
+ // Checking for a negative value of validityOfContractCert is not needed because the method
|
|
|
+ // isCertificateValid() already checks for that
|
|
|
+ if (validityOfContractCert <= GlobalValues.CERTIFICATE_EXPIRES_SOON_PERIOD.getShortValue()) {
|
|
|
+ getLogger().info("Contract certificate with distinguished name '" +
|
|
|
+ contractCert.getSubjectX500Principal().getName() + "' is about to expire in " +
|
|
|
+ validityOfContractCert + " days");
|
|
|
+ return ContractCertificateStatus.UPDATE_NEEDED;
|
|
|
+ }
|
|
|
+ return ContractCertificateStatus.OK;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* Returns a list of certificates from the given CertificateChainType with the leaf certificate
|
|
|
* being the first element and potential subcertificates (intermediate CA certificatess)
|