From 3baa15960f9a1259129574e6cdf3e5d1dd7ba20c Mon Sep 17 00:00:00 2001 From: Michal Kit Date: Mon, 5 Feb 2018 12:39:57 +0000 Subject: [PATCH] Switching to reading the root certificate from the truststore (#449) * Switching to reading the root certificate from the truststore * Addressing review comments --- docs/source/running-signing-service.rst | 10 ++-- network-management/hsm.conf | 6 +-- .../corda/networkmanage/common/HsmBaseTest.kt | 49 +++++++++++-------- .../networkmanage/hsm/HsmAuthenticatorTest.kt | 5 +- .../hsm/HsmSigningServiceTest.kt | 15 ++++-- .../hsm/SigningServiceIntegrationTest.kt | 4 ++ .../r3/corda/networkmanage/doorman/Main.kt | 4 +- .../doorman/NetworkManagementUtilities.kt | 7 +-- .../com/r3/corda/networkmanage/hsm/Main.kt | 7 +-- .../hsm/authentication/Authenticator.kt | 22 ++------- .../hsm/configuration/Configuration.kt | 15 +++--- .../networkmanage/hsm/signer/HsmCsrSigner.kt | 14 +++--- .../networkmanage/hsm/signer/HsmSigner.kt | 2 +- .../hsm/authentication/AuthenticatorTest.kt | 8 +-- 14 files changed, 83 insertions(+), 85 deletions(-) diff --git a/docs/source/running-signing-service.rst b/docs/source/running-signing-service.rst index 8ea9173f52..18d69a1635 100644 --- a/docs/source/running-signing-service.rst +++ b/docs/source/running-signing-service.rst @@ -28,7 +28,9 @@ Allowed parameters are: :device: HSM connection string. It is of the following format 3001@127.0.0.1, where 3001 is the port number. Default value: "3001@127.0.0.1" -:rootKeyGroup: HSM key group for the root certificate key. This parameter is vendor specific (see Utimaco docs). +:rootKeyStoreFile: Location of the key store (trust store) containing the root certificate. + +:rootKeyStorePassword: Password for the key store (trust store) containing the root certificate. :networkMapKeyGroup: HSM key group for the network map certificate key. This parameter is vendor specific (see Utimaco docs). @@ -38,12 +40,8 @@ Allowed parameters are: :rootPrivateKeyPassword: Private key password for the root certificate. -:rootCertificateName: Root certificate name. Default value: "cordarootca". - :csrPrivateKeyPassword: Private key password for the intermediate certificate used to sign certficate signing requests. -:csrCertificateName: Certificate signing requests intermediate certificate name. Default value: "cordaintermediateca". - :csrCertCrlDistPoint: Certificate revocation list location for the node CA certificate. :csrCertCrlIssuer: Certificate revocation list issuer. The expected value is of the X500 name format - e.g. "L=London, C=GB, OU=Org Unit, CN=Service Name". @@ -53,8 +51,6 @@ Allowed parameters are: :dataSourceProperties: Data source properties. It should describe (or point to) the Doorman database. -:networkMapCertificateName: Network map intermediate certificate name. Default value: "cordaintermediateca_nm" - :networkMapPrivateKeyPassword: Private key password for the intermediate certificate used to sign the network map. :validDays: Number of days issued signatures are valid for. diff --git a/network-management/hsm.conf b/network-management/hsm.conf index ab18e93fc7..5802cb1eea 100644 --- a/network-management/hsm.conf +++ b/network-management/hsm.conf @@ -2,11 +2,9 @@ basedir = "." device = "3001@192.168.0.1" keySpecifier = -1 authMode = PASSWORD -rootCertificateName = "corda_root_ca" -csrCertificateName = "intermediate_ca" +rootKeyStoreFile = "dummyfile.jks" +rootKeyStorePassword = "trustpass" csrCertCrlDistPoint = "http://test.com/revoked.crl" -networkMapCertificateName = "intermediate_ca" -rootKeyGroup = "DEV.CORDACONNECT.ROOT" doormanKeyGroup = "DEV.CORDACONNECT.OPS.CERT" networkMapKeyGroup = "DEV.CORDACONNECT.OPS.NETMAP" validDays = 3650 diff --git a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/common/HsmBaseTest.kt b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/common/HsmBaseTest.kt index 57e29c1e01..c90b45b6f2 100644 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/common/HsmBaseTest.kt +++ b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/common/HsmBaseTest.kt @@ -11,27 +11,32 @@ import com.r3.corda.networkmanage.hsm.generator.CertificateConfiguration import com.r3.corda.networkmanage.hsm.generator.GeneratorParameters import com.r3.corda.networkmanage.hsm.generator.UserAuthenticationParameters import net.corda.core.crypto.random63BitValue +import net.corda.core.internal.div import net.corda.nodeapi.internal.crypto.CertificateType import org.junit.Before import org.junit.Rule import org.junit.rules.TemporaryFolder +import java.nio.file.Path import java.util.* abstract class HsmBaseTest { companion object { - val ROOT_CERT_KEY_GROUP = "DEV.CORDACONNECT.ROOT" - val NETWORK_MAP_CERT_KEY_GROUP = "DEV.CORDACONNECT.OPS.NETMAP" - val DOORMAN_CERT_KEY_GROUP = "DEV.CORDACONNECT.OPS.CERT" - val ROOT_CERT_SUBJECT = "CN=Corda Root CA, O=R3 HoldCo LLC, OU=Corda, L=New York, C=US" - val NETWORK_MAP_CERT_SUBJECT = "CN=Corda Network Map, O=R3 HoldCo LLC, OU=Corda, L=New York, C=US" - val DOORMAN_CERT_SUBJECT = "CN=Corda Doorman CA, O=R3 HoldCo LLC, OU=Corda, L=New York, C=US" + const val ROOT_CERT_KEY_GROUP = "DEV.CORDACONNECT.ROOT" + const val NETWORK_MAP_CERT_KEY_GROUP = "DEV.CORDACONNECT.OPS.NETMAP" + const val DOORMAN_CERT_KEY_GROUP = "DEV.CORDACONNECT.OPS.CERT" + const val ROOT_CERT_SUBJECT = "CN=Corda Root CA, O=R3 HoldCo LLC, OU=Corda, L=New York, C=US" + const val NETWORK_MAP_CERT_SUBJECT = "CN=Corda Network Map, O=R3 HoldCo LLC, OU=Corda, L=New York, C=US" + const val DOORMAN_CERT_SUBJECT = "CN=Corda Doorman CA, O=R3 HoldCo LLC, OU=Corda, L=New York, C=US" val HSM_USER_CONFIGS = listOf(UserAuthenticationParameters( username = "INTEGRATION_TEST", authMode = AuthMode.PASSWORD, authToken = "INTEGRATION_TEST", keyFilePassword = null)) + const val ROOT_KEYSTORE_PASSWORD: String = "trustpass" } + protected lateinit var rootKeyStoreFile: Path + @Rule @JvmField val tempFolder = TemporaryFolder() @@ -43,7 +48,8 @@ abstract class HsmBaseTest { private lateinit var dbName: String @Before - fun generateRandomDbName() { + fun generateDbName() { + rootKeyStoreFile = tempFolder.root.toPath() / "truststore.jks" dbName = random63BitValue().toString() } @@ -51,8 +57,8 @@ abstract class HsmBaseTest { return GeneratorParameters( hsmHost = hsmSimulator.host, hsmPort = hsmSimulator.port, - trustStoreDirectory = tempFolder.root.toPath(), - trustStorePassword = "", + trustStoreDirectory = rootKeyStoreFile.parent, + trustStorePassword = ROOT_KEYSTORE_PASSWORD, userConfigs = HSM_USER_CONFIGS, certConfig = certConfig ) @@ -79,16 +85,19 @@ abstract class HsmBaseTest { )) } - protected val hsmSigningServiceConfig = Parameters( - dataSourceProperties = mock(), - device = "${hsmSimulator.port}@${hsmSimulator.host}", - keySpecifier = 1, - rootKeyGroup = ROOT_CERT_KEY_GROUP, - doormanKeyGroup = DOORMAN_CERT_KEY_GROUP, - networkMapKeyGroup = NETWORK_MAP_CERT_KEY_GROUP, - validDays = 3650, - csrCertCrlDistPoint = "http://test.com/revoked.crl" - ) + protected fun createHsmSigningServiceConfig(): Parameters { + return Parameters( + dataSourceProperties = mock(), + device = "${hsmSimulator.port}@${hsmSimulator.host}", + keySpecifier = 1, + rootKeyStoreFile = rootKeyStoreFile, + rootKeyStorePassword = ROOT_KEYSTORE_PASSWORD, + doormanKeyGroup = DOORMAN_CERT_KEY_GROUP, + networkMapKeyGroup = NETWORK_MAP_CERT_KEY_GROUP, + validDays = 3650, + csrCertCrlDistPoint = "http://test.com/revoked.crl" + ) + } protected fun givenHsmUserAuthenticationInput(): InputReader { val inputReader = mock() @@ -97,7 +106,7 @@ abstract class HsmBaseTest { return inputReader } - protected fun makeTestDataSourceProperties(): Properties { + fun makeTestDataSourceProperties(): Properties { return makeTestDataSourceProperties(dbName) } } \ No newline at end of file diff --git a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmAuthenticatorTest.kt b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmAuthenticatorTest.kt index 13c97821fa..327f9df551 100644 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmAuthenticatorTest.kt +++ b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmAuthenticatorTest.kt @@ -13,11 +13,12 @@ class HsmAuthenticatorTest : HsmBaseTest() { fun `Authenticator executes the block once user is successfully authenticated`() { // given val userInput = givenHsmUserAuthenticationInput() - val authenticator = Authenticator(provider = hsmSigningServiceConfig.createProvider(hsmSigningServiceConfig.rootKeyGroup), inputReader = userInput) + val hsmSigningServiceConfig = createHsmSigningServiceConfig() + val authenticator = Authenticator(provider = hsmSigningServiceConfig.createProvider(hsmSigningServiceConfig.doormanKeyGroup), inputReader = userInput) val executed = AtomicBoolean(false) // when - authenticator.connectAndAuthenticate { _, _, _ -> executed.set(true) } + authenticator.connectAndAuthenticate { _, _ -> executed.set(true) } // then assertTrue(executed.get()) diff --git a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmSigningServiceTest.kt b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmSigningServiceTest.kt index 43c11aaf11..a28c754404 100644 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmSigningServiceTest.kt +++ b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmSigningServiceTest.kt @@ -16,19 +16,24 @@ import net.corda.core.crypto.Crypto.generateKeyPair import net.corda.core.identity.CordaX500Name.Companion.parse import net.corda.core.serialization.serialize import net.corda.nodeapi.internal.crypto.CertificateType -import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_INTERMEDIATE_CA -import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA import net.corda.nodeapi.internal.crypto.X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME import net.corda.nodeapi.internal.crypto.X509Utilities.createCertificateSigningRequest +import net.corda.nodeapi.internal.crypto.loadOrCreateKeyStore import net.corda.nodeapi.internal.persistence.DatabaseConfig import net.corda.testing.common.internal.testNetworkParameters import org.assertj.core.api.Assertions.assertThat +import org.junit.Before import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertNotNull class HsmSigningServiceTest : HsmBaseTest() { + @Before + fun setUp() { + loadOrCreateKeyStore(rootKeyStoreFile, ROOT_KEYSTORE_PASSWORD) + } + @Test fun `HSM signing service can sign CSR data`() { // when root cert is created @@ -56,16 +61,15 @@ class HsmSigningServiceTest : HsmBaseTest() { val userInput = givenHsmUserAuthenticationInput() // given HSM CSR signer + val hsmSigningServiceConfig = createHsmSigningServiceConfig() val signer = HsmCsrSigner( mock(), - CORDA_INTERMEDIATE_CA, + hsmSigningServiceConfig.loadRootKeyStore(), "", null, - CORDA_ROOT_CA, 3650, Authenticator( provider = hsmSigningServiceConfig.createProvider(hsmSigningServiceConfig.doormanKeyGroup), - rootProvider = hsmSigningServiceConfig.createProvider(hsmSigningServiceConfig.rootKeyGroup), inputReader = userInput) ) @@ -114,6 +118,7 @@ class HsmSigningServiceTest : HsmBaseTest() { val userInput = givenHsmUserAuthenticationInput() // given HSM network map signer + val hsmSigningServiceConfig = createHsmSigningServiceConfig() val hsmDataSigner = HsmSigner(Authenticator( provider = hsmSigningServiceConfig.createProvider(hsmSigningServiceConfig.networkMapKeyGroup), inputReader = userInput)) diff --git a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/SigningServiceIntegrationTest.kt b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/SigningServiceIntegrationTest.kt index b1c9d5f033..3ca48799e1 100644 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/SigningServiceIntegrationTest.kt +++ b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/SigningServiceIntegrationTest.kt @@ -10,6 +10,7 @@ import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData import com.r3.corda.networkmanage.hsm.persistence.DBSignedCertificateRequestStorage import com.r3.corda.networkmanage.hsm.persistence.SignedCertificateRequestStorage import com.r3.corda.networkmanage.hsm.signer.HsmCsrSigner +import net.corda.core.crypto.random63BitValue import net.corda.core.identity.CordaX500Name import net.corda.core.internal.createDirectories import net.corda.core.internal.div @@ -49,8 +50,11 @@ class SigningServiceIntegrationTest : HsmBaseTest() { private lateinit var rootCaCert: X509Certificate private lateinit var intermediateCa: CertificateAndKeyPair + private lateinit var dbName: String + @Before fun setUp() { + dbName = random63BitValue().toString() timer = Timer() val (rootCa, intermediateCa) = createDevIntermediateCaCertPath() rootCaCert = rootCa.certificate diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/Main.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/Main.kt index 8097ccb2b9..f8afc6cec6 100644 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/Main.kt +++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/Main.kt @@ -5,9 +5,9 @@ import com.r3.corda.networkmanage.common.persistence.CertificationRequestStorage import com.r3.corda.networkmanage.common.persistence.configureDatabase import com.r3.corda.networkmanage.common.utils.* import com.r3.corda.networkmanage.doorman.signer.LocalSigner -import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT_CSR_CERTIFICATE_NAME import net.corda.core.utilities.NetworkHostAndPort import net.corda.nodeapi.internal.crypto.X509KeyStore +import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.network.NetworkParameters import org.bouncycastle.pkcs.PKCS10CertificationRequest import java.time.Instant @@ -24,7 +24,7 @@ private fun processKeyStore(parameters: NetworkManagementServerParameters): Pair val keyStorePassword = parameters.keystorePassword ?: readPassword("Key store password: ") val privateKeyPassword = parameters.caPrivateKeyPassword ?: readPassword("Private key password: ") val keyStore = X509KeyStore.fromFile(parameters.keystorePath, keyStorePassword) - val csrCertPathAndKey = keyStore.getCertPathAndKey(DEFAULT_CSR_CERTIFICATE_NAME, privateKeyPassword) + val csrCertPathAndKey = keyStore.getCertPathAndKey(X509Utilities.CORDA_INTERMEDIATE_CA, privateKeyPassword) val networkMapSigner = LocalSigner(keyStore.getCertificateAndKeyPair(CORDA_NETWORK_MAP, privateKeyPassword)) return Pair(csrCertPathAndKey, networkMapSigner) } diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementUtilities.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementUtilities.kt index 8f7ae167f7..f05536814e 100644 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementUtilities.kt +++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementUtilities.kt @@ -1,12 +1,13 @@ package com.r3.corda.networkmanage.doorman import com.r3.corda.networkmanage.common.utils.CORDA_NETWORK_MAP -import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT_CSR_CERTIFICATE_NAME import net.corda.core.crypto.Crypto import net.corda.core.crypto.SignatureScheme import net.corda.core.internal.createDirectories import net.corda.core.internal.div -import net.corda.nodeapi.internal.crypto.* +import net.corda.nodeapi.internal.crypto.CertificateType +import net.corda.nodeapi.internal.crypto.X509KeyStore +import net.corda.nodeapi.internal.crypto.X509Utilities import java.nio.file.Path import javax.security.auth.x500.X500Principal import kotlin.system.exitProcess @@ -103,7 +104,7 @@ fun generateSigningKeyPairs(keystoreFile: Path, rootStoreFile: Path, rootKeystor } storeCertIfAbsent( - DEFAULT_CSR_CERTIFICATE_NAME, + X509Utilities.CORDA_INTERMEDIATE_CA, CertificateType.INTERMEDIATE_CA, X500Principal("CN=Corda Doorman CA,$CORDA_X500_BASE"), X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/Main.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/Main.kt index c5a5213af0..ddc665046d 100644 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/Main.kt +++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/Main.kt @@ -18,7 +18,6 @@ import com.r3.corda.networkmanage.hsm.persistence.DBSignedCertificateRequestStor import com.r3.corda.networkmanage.hsm.signer.HsmCsrSigner import com.r3.corda.networkmanage.hsm.signer.HsmSigner import com.r3.corda.networkmanage.hsm.utils.mapCryptoServerException -import net.corda.core.utilities.minutes import org.apache.logging.log4j.LogManager import org.bouncycastle.jce.provider.BouncyCastleProvider import java.security.Security @@ -74,10 +73,9 @@ fun run(parameters: Parameters) { val sign: (List) -> Unit = { val signer = HsmCsrSigner( csrStorage, - csrCertificateName, + loadRootKeyStore(), csrCertCrlDistPoint, csrCertCrlIssuer, - rootCertificateName, validDays, Authenticator( authMode, @@ -85,8 +83,7 @@ fun run(parameters: Parameters) { authKeyFilePath, authKeyFilePassword, signAuthThreshold, - provider = createProvider(doormanKeyGroup), - rootProvider = createProvider(rootKeyGroup))) + provider = createProvider(doormanKeyGroup))) signer.sign(it) } Menu().withExceptionHandler(::processError).addItem("1", "Sign all approved and unsigned CSRs", { diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/Authenticator.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/Authenticator.kt index d8438091c1..64a64476cb 100644 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/Authenticator.kt +++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/Authenticator.kt @@ -17,18 +17,16 @@ class Authenticator(private val mode: AuthMode = AuthMode.PASSWORD, private val authKeyFilePass: String? = null, private val authStrengthThreshold: Int = 2, inputReader: InputReader = ConsoleInputReader(), - private val provider: CryptoServerProvider, - private val rootProvider: CryptoServerProvider? = null) : InputReader by inputReader { + private val provider: CryptoServerProvider) : InputReader by inputReader { /** * Interactively (using console) authenticates a user against the HSM. Once authentication is successful the * [block] is executed. * @param block to be executed once the authentication process succeeds. The block should take 3 parameters: * 1) [CryptoServerProvider] instance of the certificate provider - * 2) [CryptoServerProvider] instance of the root certificate provider * 2) List of strings that corresponds to user names authenticated against the HSM. */ - fun connectAndAuthenticate(block: (CryptoServerProvider, CryptoServerProvider?, List) -> T): T { + fun connectAndAuthenticate(block: (CryptoServerProvider, List) -> T): T { return try { val authenticated = mutableListOf() loop@ while (true) { @@ -49,10 +47,6 @@ class Authenticator(private val mode: AuthMode = AuthMode.PASSWORD, println("Authenticating using card reader") println("Accessing the certificate key group data...") provider.loginSign(user, ":cs2:cyb:USB0", null) - if (rootProvider != null) { - println("Accessing the root certificate key group data...") - rootProvider.loginSign(user, ":cs2:cyb:USB0", null) - } } AuthMode.KEY_FILE -> { println("Authenticating using preconfigured key file $authKeyFilePath") @@ -69,10 +63,6 @@ class Authenticator(private val mode: AuthMode = AuthMode.PASSWORD, } println("Accessing the certificate key group data...") provider.loginSign(user, authKeyFilePath.toString(), password) - if (rootProvider != null) { - println("Accessing the root certificate key group data...") - rootProvider.loginSign(user, authKeyFilePath.toString(), password) - } } AuthMode.PASSWORD -> { println("Authenticating using password") @@ -83,10 +73,6 @@ class Authenticator(private val mode: AuthMode = AuthMode.PASSWORD, } println("Accessing the certificate key group data...") provider.loginPassword(user, password) - if (rootProvider != null) { - println("Accessing the root certificate key group data...") - rootProvider.loginPassword(user, password) - } } } authenticated.add(user!!) @@ -99,7 +85,7 @@ class Authenticator(private val mode: AuthMode = AuthMode.PASSWORD, } } if (!authenticated.isEmpty()) { - block(provider, rootProvider, authenticated) + block(provider, authenticated) } else { throw AuthenticationException() } @@ -113,8 +99,8 @@ class Authenticator(private val mode: AuthMode = AuthMode.PASSWORD, } } } -/* +/* * Configuration class for [CryptoServerProvider] */ data class CryptoServerProviderConfig( diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/configuration/Configuration.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/configuration/Configuration.kt index 7a48c82f9d..73d94df294 100644 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/configuration/Configuration.kt +++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/configuration/Configuration.kt @@ -8,7 +8,7 @@ import net.corda.core.internal.div import net.corda.core.internal.isRegularFile import net.corda.core.utilities.minutes import net.corda.nodeapi.internal.config.parseAs -import net.corda.nodeapi.internal.crypto.X509Utilities +import net.corda.nodeapi.internal.crypto.X509KeyStore import net.corda.nodeapi.internal.persistence.DatabaseConfig import java.nio.file.Path import java.nio.file.Paths @@ -21,15 +21,14 @@ data class Parameters(val dataSourceProperties: Properties, val databaseConfig: DatabaseConfig = DatabaseConfig(), val device: String = DEFAULT_DEVICE, // TODO this needs cleaning up after the config-file-only support is implemented - val rootKeyGroup: String, - val doormanKeyGroup:String, + val rootKeyStoreFile: Path, + val rootKeyStorePassword: String, + val doormanKeyGroup: String, val networkMapKeyGroup: String, val keySpecifier: Int = DEFAULT_KEY_SPECIFIER, - val csrCertificateName: String = DEFAULT_CSR_CERTIFICATE_NAME, val csrCertCrlDistPoint: String, val csrCertCrlIssuer: String? = DEFAULT_CSR_CERT_CRL_ISSUER, // X500 name of the issuing authority e.g. "L=New York, C=US, OU=Org Unit, CN=Service Name", // if null parent CA is is considered as an issuer. - val rootCertificateName: String = DEFAULT_ROOT_CERTIFICATE_NAME, val validDays: Int, val signAuthThreshold: Int = DEFAULT_SIGN_AUTH_THRESHOLD, val keyGenAuthThreshold: Int = DEFAULT_KEY_GEN_AUTH_THRESHOLD, @@ -44,8 +43,6 @@ data class Parameters(val dataSourceProperties: Properties, val DEFAULT_AUTH_MODE = AuthMode.PASSWORD val DEFAULT_SIGN_AUTH_THRESHOLD = 2 val DEFAULT_KEY_GEN_AUTH_THRESHOLD = 2 - val DEFAULT_CSR_CERTIFICATE_NAME = X509Utilities.CORDA_INTERMEDIATE_CA - val DEFAULT_ROOT_CERTIFICATE_NAME = X509Utilities.CORDA_ROOT_CA val DEFAULT_KEY_SPECIFIER = 1 val DEFAULT_KEY_FILE_PATH: Path? = null //Paths.get("/Users/michalkit/WinDev1706Eval/Shared/TEST4.key") val DEFAULT_KEY_FILE_PASSWORD: String? = null @@ -53,6 +50,10 @@ data class Parameters(val dataSourceProperties: Properties, val DEFAULT_SIGN_INTERVAL = 1.minutes.toMillis() val DEFAULT_CSR_CERT_CRL_ISSUER: String? = null } + + fun loadRootKeyStore(createNew: Boolean = false): X509KeyStore { + return X509KeyStore.fromFile(rootKeyStoreFile, rootKeyStorePassword, createNew) + } } /** diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmCsrSigner.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmCsrSigner.kt index 779cafa859..59be927f47 100644 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmCsrSigner.kt +++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmCsrSigner.kt @@ -7,18 +7,17 @@ import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.createClientCertifi import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.getAndInitializeKeyStore import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.retrieveCertAndKeyPair import net.corda.nodeapi.internal.crypto.CertificateType +import net.corda.nodeapi.internal.crypto.X509KeyStore import net.corda.nodeapi.internal.crypto.X509Utilities -import net.corda.nodeapi.internal.crypto.getX509Certificate import org.bouncycastle.asn1.x500.X500Name /** * Encapsulates certificate signing logic */ class HsmCsrSigner(private val storage: SignedCertificateRequestStorage, - private val intermediateCertAlias: String, + private val rootKeyStore: X509KeyStore, private val csrCertCrlDistPoint: String, private val csrCertCrlIssuer: String?, - private val rootCertAlias: String, private val validDays: Int, private val authenticator: Authenticator) : CertificateSigningRequestSigner { @@ -33,11 +32,12 @@ class HsmCsrSigner(private val storage: SignedCertificateRequestStorage, * @param toSign list of approved certificates to be signed */ override fun sign(toSign: List) { - authenticator.connectAndAuthenticate { provider, rootProvider, signers -> - val rootKeyStore = getAndInitializeKeyStore(rootProvider!!) - val rootCert = rootKeyStore.getX509Certificate(rootCertAlias) + authenticator.connectAndAuthenticate { provider, signers -> + // This should be changed once we allow for more certificates in the chain. Preferably we should use + // keyStore.getCertificateChain(String) and assume entire chain is stored in the HSM (depending on the support). + val rootCert = rootKeyStore.getCertificate(X509Utilities.CORDA_ROOT_CA) val keyStore = getAndInitializeKeyStore(provider) - val doormanCertAndKey = retrieveCertAndKeyPair(intermediateCertAlias, keyStore) + val doormanCertAndKey = retrieveCertAndKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, keyStore) toSign.forEach { val nodeCaCert = createClientCertificate( CertificateType.NODE_CA, diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmSigner.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmSigner.kt index c3ebaab44e..895e80cfc7 100644 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmSigner.kt +++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmSigner.kt @@ -19,7 +19,7 @@ class HsmSigner(private val authenticator: Authenticator) : Signer { * Signs given data using [CryptoServerJCE.CryptoServerProvider], which connects to the underlying HSM. */ override fun signBytes(data: ByteArray): DigitalSignatureWithCert { - return authenticator.connectAndAuthenticate { provider, _, _ -> + return authenticator.connectAndAuthenticate { provider, _ -> val keyStore = getAndInitializeKeyStore(provider) val certificate = keyStore.getX509Certificate(CORDA_NETWORK_MAP) // Don't worry this is not a real private key but a pointer to one that resides in the HSM. It only works diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/authentication/AuthenticatorTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/authentication/AuthenticatorTest.kt index 42b222814e..bb920779f9 100644 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/authentication/AuthenticatorTest.kt +++ b/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/authentication/AuthenticatorTest.kt @@ -28,7 +28,7 @@ class AuthenticatorTest : TestBase() { // when assertFailsWith { - Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _, _ -> } + Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _ -> } } //then @@ -47,7 +47,7 @@ class AuthenticatorTest : TestBase() { var executed = false // when - Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _, _ -> executed = true } + Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _ -> executed = true } // then verify(provider).loginPassword(username, password) @@ -64,7 +64,7 @@ class AuthenticatorTest : TestBase() { var executed = false // when - Authenticator(provider = provider, inputReader = inputReader, mode = AuthMode.CARD_READER).connectAndAuthenticate { _, _, _ -> executed = true } + Authenticator(provider = provider, inputReader = inputReader, mode = AuthMode.CARD_READER).connectAndAuthenticate { _, _ -> executed = true } // then verify(provider).loginSign(username, ":cs2:cyb:USB0", null) @@ -83,7 +83,7 @@ class AuthenticatorTest : TestBase() { var executed = false // when - Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _, _ -> executed = true } + Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _ -> executed = true } // then verify(provider, times(3)).loginPassword(username, password)