diff --git a/network-management/README.md b/network-management/README.md deleted file mode 100644 index dade095078..0000000000 --- a/network-management/README.md +++ /dev/null @@ -1,374 +0,0 @@ - -# Building the binaries - -## Network management server -To build a fat jar containing all the doorman code you can simply invoke: -``` - ./gradlew network-management:capsule:buildDoormanJAR -``` - -The built file will appear in: -``` -network-management/capsule/build/libs/doorman-.jar -``` -## HSM signing server -To build a fat jar containing all the HSM signing server code you can simply invoke: -``` - ./gradlew network-management:capsule-hsm:buildHsmJAR -``` - -The built file will appear in: -``` -network-management/capsule-hsm/build/libs/hsm-.jar -``` - -The binaries can also be obtained from artifactory after deployment in TeamCity. - -To run the HSM signing server: - -``` -cd network-management -java -jar capsule-hsm/build/libs/hsm-.jar --config-file [hsm-configuration-file] -``` - -For a list of options the HSM signing server takes, run with the `--help` option: -``` -java -jar capsule-hsm/build/libs/hsm-.jar --help -``` - -## HSM Certificate Generator - -To build a fat jar containing all the hsm certificate generator code you can simply invoke -``` - ./gradlew network-management:capsule-hsm-cert-generator:buildHsmCertGeneratorJAR -``` - -The built file will appear in -``` -network-management/capsule-hsm-cert-generator/build/libs/hsm-cert-generator-.jar -``` - -## HSM CRL Generator - -To build a fat jar containing all the hsm CRL generator code you can simply invoke -``` - ./gradlew network-management:capsule-hsm-crl-generator:buildHsmCrlGeneratorJAR -``` - -The built file will appear in -``` -network-management/capsule-hsm-crl-generator/build/libs/hsm-crl-generator-.jar -``` - -## Certificate Revocation Request Submission Tool - -To build a fat jar containing all the CRR submission tool code you can simply invoke -``` - ./gradlew network-management:capsule-crr-submission:buildCrrSubmissionJAR -``` - -The built file will appear in -``` -network-management/capsule-crr-submission/build/libs/crr-submission-.jar -``` - - -# Logs -In order to set the desired logging level the system properties need to be used. -Appropriate system properties can be set at the execution time. -Example: -``` -java -DdefaultLogLevel=TRACE -DconsoleLogLevel=TRACE -jar doorman-.jar --config-file -``` - -#Configuring network management service -### Local signing - - When `keystorePath` is provided in the config file, a signer will be created to handle all the signing periodically - using the CA keys in the provided keystore. - - The network management service can be started without a signer, the signing will be delegated to external process - (e.g. HSM) connecting to the same database, the server will poll the database periodically for newly signed data and - update the statuses accordingly. - - Additional configuration needed for local signer: - ``` - #For local signing - rootStorePath = ${basedir}"/certificates/rootstore.jks" - keystorePath = ${basedir}"/certificates/caKeystore.jks" - keystorePassword = "password" - caPrivateKeyPassword = "password" - ``` - -## Doorman Service -Doorman service can be started with the following options : - -### JIRA - -The doorman service can use JIRA to manage both the certificate signing request and the certificate revocation request approval work flows. -This can be turned on by providing JIRA connection configuration in the config file. - ``` - doorman { - jira { - address = "https://doorman-jira-host.com/" - projectCode = "TD" - username = "username" - password = "password" - } - . - . - . - } - ``` -#### JIRA project configuration -* The JIRA project should setup as "Business Project" with "Task" workflow. -* Custom text field input "Request ID", and "Reject Reason" should be created in JIRA, doorman will exit with error without -these custom fields. - -### Auto approval - When `approveAll` is set to `true`, the doorman will approve all requests on receive. (*This should only be enabled in a - test environment) - -### Network map service - Network map service can be enabled by providing the following config: - ``` - networkMap { - cacheTimeout = 600000 - signInterval = 10000 - } - ``` - `cacheTimeout`(ms) determines how often the server should poll the database for a newly signed network map and also how often nodes should poll for a new network map (by including this value in the HTTP response header). **This is not how often changes to the network map are signed, which is a different process.** - `signInterval`(ms) this is only relevant when local signer is enabled. The signer poll the database according to the `signInterval`, and create a new network map if the collection of node info hashes is different from the current network map. - -## Example config file -``` -basedir = "." -address = "localhost:0" -rootStorePath = ${basedir}"/certificates/rootstore.jks" -keystorePath = ${basedir}"/certificates/caKeystore.jks" -#keystorePassword = "password" #Optional if not specified, user will be prompted on the console. -#caPrivateKeyPassword = "password" #Optional if not specified, user will be prompted on the console. -#rootPrivateKeyPassword = "password" #Optional if not specified, user will be prompted on the console. -#rootKeystorePassword = "password" #Optional if not specified, user will be prompted on the console. - -dataSourceProperties { - dataSourceClassName = org.h2.jdbcx.JdbcDataSource - "dataSource.url" = "jdbc:h2:file:"${basedir}"/persistence;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=10000;WRITE_DELAY=0;AUTO_SERVER_PORT="${h2port} - "dataSource.user" = sa - "dataSource.password" = "" -} - -database { - runMigration = true -} - -h2port = 0 - -# Comment out this section if running without doorman service -doorman { - approveInterval = 10000 - approveAll = false - jira { - address = "https://doorman-jira-host.com/" - projectCode = "TD" - username = "username" - password = "password" - } -} - -# Comment out this section if running without the revocation service -revocation { - approveInterval = 10000 - approveAll = false - crlUpdateInterval = 86400000 - crlEndpoint = "http://test.com/crl" - crlCacheTimeout = 86400000 - jira { - address = "https://doorman-jira-host.com/" - projectCode = "CRR" - username = "username" - password = "password" - } -} - -# Comment out this section if running without network map service -networkMap { - cacheTimeout = 600000 - signInterval = 10000 -} -``` - -# Running the network - -### 1. Create keystore for local signer - - If local signer is enabled, the server will look for key stores in the certificate folder on start up. - The key stores can be created using `--mode` flag. - ``` - java -jar doorman-.jar --config-file --mode ROOT_KEYGEN - ``` - and - ``` - java -jar doorman-.jar --config-file --mode CA_KEYGEN - ``` - - A trust store containing the root certificate will be created in the location `distribute-nodes / network-root-truststore.jks` - (relative to `rootStorePath`). The trust store's password can be set using command line argument `--trust-store-password`, - or the doorman's keygen utility will ask for password input if trust store password is not provided using this flag. - This trust store file is to be distributed to every node that wishes to register with the doorman. The node cannot - register without it. - -### 2. Start Doorman service for notary registration - Start the network management server with the doorman service for initial bootstrapping. Network map service (`networkMap`) - should be **disabled** at this point. **Comment out** network map config in the config file and start the server by running : - ``` - java -jar doorman-.jar --config-file - ``` - -### 3. Create notary node and register with the doorman - After the doorman service is started, start the notary node for registration. - ``` - java -jar corda.jar --initial-registration --network-root-truststore-password - ``` - By default it will expect trust store file received from the doorman to be in the location ``certificates/network-root-truststore.jks``. - This can be overridden with the additional `--network-root-truststore` flag. - - NOTE: This step applies to all nodes that wish to register with the doorman. You will have to configure ``compatibiityZoneURL`` and set ``devMode`` to false on each node. - -### 4. Generate node info files for notary nodes - Once notary nodes are registered, run the notary nodes with the `just-generate-node-info` flag. - This will generate the node info files, which then should be referenced in the network parameters configuration. - -### 5. Add notary identities to the network parameters - The network parameters should contain reference to the notaries node info files. - Example network parameters file: - - notaries : [ - { - notaryNodeInfoFile: "/Path/To/NodeInfo/File1" - validating: true - }, - { - notaryNodeInfoFile: "/Path/To/NodeInfo/File2" - validating: false - } - ] - minimumPlatformVersion = 1 - maxMessageSize = 10485760 - maxTransactionSize = 10485760 - eventHorizonDays = 30 # Duration in days - - Save the parameters to `network-parameters.conf` - -### 6. Load the initial network parameters -A network parameters file is required to start the network map service for the first time. The initial network parameters -file can be loaded using the `--set-network-parameters` flag. We can now restart the network management server with -both doorman and network map service. -``` -java -jar doorman-.jar --config-file --set-network-parameters network-parameters.conf -``` - -The server will terminate once this process is complete. Start it back up again with both the doorman and network map service. -``` -java -jar doorman-.jar --config-file -``` - -### 7. Archive policy -The ``node_info`` and ``network_map`` table are designed to retain all historical data for auditing purposes and will grow over time. -**It is recommended to monitor the space usage and archive these tables according to the data retention policy.** - -Run the following SQL script to archive the node info table (change the timestamp according to the archive policy): -``` - delect from node_info where is_current = false and published_at < '2018-03-12' -``` - -# Updating the network parameters -The initial network parameters can be subsequently changed through an update process. However, these changes must first -be advertised to the entire network to allow nodes time to agree to the changes. Every time the server needs to be shutdown -and run with one of the following flags: `--set-network-parameters`, `--flag-day` or `--cancel-update`. For change to be -advertised to the nodes new network map has to be signed (either by HSM or by local signer). - -Typical update process is as follows: -1. Start network map with initial network parameters. -2. To advertise an update: - * Stop network-management. - * Run it with ``--set-network-parameters`` flag. The network parameters file must have `parametersUpdate` config block: - ``` - parametersUpdate { - description = "Important update" - updateDeadline = "2017-08-31T05:10:36.297Z" # ISO-8601 time, substitute it with update deadline - } - ``` - Where `description` is a short description of the update that will be communicated to the nodes and `updateDeadline` is - the time (in ISO-8601 format) by which all nodes in the network must decide that they have accepted the new parameters. - - NOTE: Currently only backwards compatible changes to the network parameters can be made, i.e. notaries can't be removed, - max transaction size can only increase, etc. - - The process will exit, nothing will be sent to the nodes yet. - * Start network-management as normal without any flags. This time, the nodes will be notified of the new parameters - update next time they poll. -3. Before the `updateDeadline` time, nodes will have to run the RPC command to accept new parameters. -This will not activate the new network parameters on the nodes. It is possible to poll the network map database to check -how many network participants have accepted the new network parameters - the information is stored in the `node-info.accepted_parameters_hash` column. -4. When the flag day comes. Restart network-management with ``--flag-day`` flag. This will cause all nodes in the network -to shutdown when they see that the network parameters have changed. -The nodes that didn't accept the parameters will be removed from the network map. The ones that accepted, will need to be manually restarted. - -It is possible to cancel the previously scheduled update. To do so simply run: -``` -java -jar doorman-.jar --cancel-update -``` - -The network map will continue to advertise the cancelled update until the new network map is signed. - -# Private Network Map -The private network is a tactical solution to provide temporary privacy to the initial network map. - -## Creating a private network -To create a new private network, an entry has to be created in the ``private_network`` table manually. - -Run the following SQL script to create a new private network: - -``` -insert into private_network (id, name) -values (NEWID(), 'Private Network Name') -``` - -Then use the following SQL to retrieve the private network ID for the private network owner: -``` -select id from private_network where name = 'Private Network Name' -``` - -## Modify existing private network registration -Since this is a tactical solution, any modification will require manual database changes. - -**We should try to keep these changes to the minimal** - -### Add nodes to a private network - -``` -update certificate_signing_request -set private_network = '<>' -where request_id in ('<>', ...) -``` - -or this SQL script to add all approved nodes to the private network map. - -``` -update certificate_signing_request -set private_network = '<>' -where status = 'APPROVED' -``` - -**Important** -If notary is to be used by private network participants add private network UUIDs to notary's ``node.conf`` using -``extraNetworkMapKeys`` list. - -### Move a node from its private network and into the global network map** - -``` -update certificate_signing_request -set private_network = null -where request_id = '<>' -``` diff --git a/network-management/build.gradle b/network-management/build.gradle deleted file mode 100644 index 771a485029..0000000000 --- a/network-management/build.gradle +++ /dev/null @@ -1,124 +0,0 @@ - -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -description 'Network management module encapsulating components such as Doorman, HSM Signing Service and Network Map' - -apply plugin: 'us.kirchmeier.capsule' -apply plugin: 'kotlin' -apply plugin: 'kotlin-jpa' - -repositories { - mavenLocal() - mavenCentral() - maven { - url 'http://oss.sonatype.org/content/repositories/snapshots' - } - jcenter() - maven { - url 'http://ci-artifactory.corda.r3cev.com/artifactory/corda-dev' - } - maven { - url 'http://ci-artifactory.corda.r3cev.com/artifactory/corda-releases' - } -} - -configurations { - integrationTestCompile.extendsFrom testCompile - integrationTestRuntime.extendsFrom testRuntime -} - -sourceSets { - integrationTest { - kotlin { - compileClasspath += main.output + test.output - runtimeClasspath += main.output + test.output - srcDir file('src/integration-test/kotlin') - } - java { - compileClasspath += main.output + test.output - runtimeClasspath += main.output + test.output - srcDir file('src/integration-test/java') - } - resources { - srcDir file('src/integration-test/resources') - } - } -} - -task integrationTest(type: Test) { - testClassesDirs = sourceSets.integrationTest.output.classesDirs - classpath = sourceSets.integrationTest.runtimeClasspath -} - -dependencies { - compile fileTree(dir: 'libs', include: '*.jar') - - compile project(':node-api') - - compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - - // Log4J: logging framework (with SLF4J bindings) - compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}" - compile "org.apache.logging.log4j:log4j-core:${log4j_version}" - compile "org.apache.logging.log4j:log4j-web:${log4j_version}" - - // Web stuff: for HTTP[S] servlets - compile "org.eclipse.jetty:jetty-servlet:${jetty_version}" - compile "org.eclipse.jetty:jetty-webapp:${jetty_version}" - compile "javax.servlet:javax.servlet-api:3.1.0" - - // Jersey for JAX-RS implementation for use in Jetty - compile "org.glassfish.jersey.core:jersey-server:${jersey_version}" - compile "org.glassfish.jersey.containers:jersey-container-servlet-core:${jersey_version}" - compile "org.glassfish.jersey.containers:jersey-container-jetty-http:${jersey_version}" - - // JOpt: for command line flags. - compile "net.sf.jopt-simple:jopt-simple:5.0.4" - - // TypeSafe Config: for simple and human friendly config files. - compile "com.typesafe:config:$typesafe_config_version" - - // Hibernate audit plugin - compile "org.hibernate:hibernate-envers:5.2.11.Final" - - // Manifests: for reading stuff from the manifest file - compile "com.jcabi:jcabi-manifests:1.1" - - testCompile project(':test-utils') - testCompile project(':node-driver') - - // Unit testing helpers. - testCompile "junit:junit:$junit_version" - testCompile "org.assertj:assertj-core:${assertj_version}" - testCompile "com.nhaarman:mockito-kotlin:1.5.0" - testCompile "com.spotify:docker-client:8.9.1" - - compile('com.atlassian.jira:jira-rest-java-client-core:5.0.4') { - // The jira client includes jersey-core 1.5 which breaks everything. - exclude module: 'jersey-core' - } - // Needed by jira rest client - compile "com.atlassian.fugue:fugue:2.6.1" - - // SQL connection pooling library - compile "com.zaxxer:HikariCP:${hikari_version}" - - // For H2 database support in persistence - compile "com.h2database:h2:$h2_version" - - //TODO remove once we can put driver jar into a predefined directory - //JDBC driver can be passed to the Node at startup using setting the jarDirs property in the Node configuration file. - compile 'com.microsoft.sqlserver:mssql-jdbc:6.2.1.jre8' - - // Bouncy Castle for HSM signing - compile "org.bouncycastle:bcprov-jdk15on:${bouncycastle_version}" - compile "org.bouncycastle:bcpkix-jdk15on:${bouncycastle_version}" -} diff --git a/network-management/capsule-crr-submission/build.gradle b/network-management/capsule-crr-submission/build.gradle deleted file mode 100644 index 9b37a407d4..0000000000 --- a/network-management/capsule-crr-submission/build.gradle +++ /dev/null @@ -1,49 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -apply plugin: 'net.corda.plugins.publish-utils' -apply plugin: 'us.kirchmeier.capsule' - -description 'HSM Certificate Generator' - -version project(':network-management').version - -configurations { - runtimeArtifacts.extendsFrom runtime -} - -task buildCrrSubmissionJAR(type: FatCapsule, dependsOn: 'jar') { - applicationClass 'com.r3.corda.networkmanage.tools.crr.submission.MainKt' - archiveName "crr-submission-${version}.jar" - capsuleManifest { - applicationVersion = corda_release_version - systemProperties['visualvm.display.name'] = 'CRR Submission Tool' - minJavaVersion = '1.8.0' - jvmArgs = ['-XX:+UseG1GC'] - } - applicationSource = files( - project(':network-management').configurations.runtime, - project(':network-management').jar - ) -} - -artifacts { - runtimeArtifacts buildCrrSubmissionJAR - publish buildCrrSubmissionJAR -} - -jar { - classifier "ignore" -} - -publish { - name 'crr-submission' - disableDefaultJar = true -} \ No newline at end of file diff --git a/network-management/capsule-hsm-cert-generator/build.gradle b/network-management/capsule-hsm-cert-generator/build.gradle deleted file mode 100644 index 8f62714baa..0000000000 --- a/network-management/capsule-hsm-cert-generator/build.gradle +++ /dev/null @@ -1,49 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -apply plugin: 'net.corda.plugins.publish-utils' -apply plugin: 'us.kirchmeier.capsule' - -description 'HSM Certificate Generator' - -version project(':network-management').version - -configurations { - runtimeArtifacts.extendsFrom runtime -} - -task buildHsmCertGeneratorJAR(type: FatCapsule, dependsOn: 'jar') { - applicationClass 'com.r3.corda.networkmanage.hsm.generator.certificate.MainKt' - archiveName "hsm-cert-generator-${version}.jar" - capsuleManifest { - applicationVersion = corda_release_version - systemProperties['visualvm.display.name'] = 'HSM Certificate Generator' - minJavaVersion = '1.8.0' - jvmArgs = ['-XX:+UseG1GC'] - } - applicationSource = files( - project(':network-management').configurations.runtime, - project(':network-management').jar - ) -} - -artifacts { - runtimeArtifacts buildHsmCertGeneratorJAR - publish buildHsmCertGeneratorJAR -} - -jar { - classifier "ignore" -} - -publish { - name 'hsm-cert-generator' - disableDefaultJar = true -} \ No newline at end of file diff --git a/network-management/capsule-hsm-crl-generator/build.gradle b/network-management/capsule-hsm-crl-generator/build.gradle deleted file mode 100644 index 1d62be19fc..0000000000 --- a/network-management/capsule-hsm-crl-generator/build.gradle +++ /dev/null @@ -1,49 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -apply plugin: 'net.corda.plugins.publish-utils' -apply plugin: 'us.kirchmeier.capsule' - -description 'HSM Certificate Generator' - -version project(':network-management').version - -configurations { - runtimeArtifacts.extendsFrom runtime -} - -task buildHsmCrlGeneratorJAR(type: FatCapsule, dependsOn: 'jar') { - applicationClass 'com.r3.corda.networkmanage.hsm.generator.crl.MainKt' - archiveName "hsm-crl-generator-${version}.jar" - capsuleManifest { - applicationVersion = corda_release_version - systemProperties['visualvm.display.name'] = 'HSM CRL Generator' - minJavaVersion = '1.8.0' - jvmArgs = ['-XX:+UseG1GC'] - } - applicationSource = files( - project(':network-management').configurations.runtime, - project(':network-management').jar - ) -} - -artifacts { - runtimeArtifacts buildHsmCrlGeneratorJAR - publish buildHsmCrlGeneratorJAR -} - -jar { - classifier "ignore" -} - -publish { - name 'hsm-crl-generator' - disableDefaultJar = true -} \ No newline at end of file diff --git a/network-management/capsule-hsm/build.gradle b/network-management/capsule-hsm/build.gradle deleted file mode 100644 index a0688d06c7..0000000000 --- a/network-management/capsule-hsm/build.gradle +++ /dev/null @@ -1,55 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -apply plugin: 'net.corda.plugins.publish-utils' -apply plugin: 'us.kirchmeier.capsule' -apply plugin: 'com.jfrog.artifactory' - -description 'Doorman default' - -version project(':network-management').version - -configurations { - runtimeArtifacts.extendsFrom runtime -} - -task buildHsmJAR(type: FatCapsule, dependsOn: 'jar') { - applicationClass 'com.r3.corda.networkmanage.hsm.MainKt' - archiveName "hsm-${version}.jar" - capsuleManifest { - applicationVersion = corda_release_version - systemProperties['visualvm.display.name'] = 'HSM Signing Service' - minJavaVersion = '1.8.0' - jvmArgs = ['-XX:+UseG1GC'] - } - applicationSource = files( - project(':network-management').configurations.runtime, - project(':network-management').jar - ) - tasks.withType(Jar) { task -> - manifest { - attributes('Signing-Service-Version': version) - } - } -} - -artifacts { - runtimeArtifacts buildHsmJAR - publish buildHsmJAR -} - -jar { - classifier "ignore" -} - -publish { - name 'doorman-hsm' - disableDefaultJar = true -} \ No newline at end of file diff --git a/network-management/capsule/build.gradle b/network-management/capsule/build.gradle deleted file mode 100644 index aea7f03af1..0000000000 --- a/network-management/capsule/build.gradle +++ /dev/null @@ -1,57 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -apply plugin: 'net.corda.plugins.publish-utils' -apply plugin: 'us.kirchmeier.capsule' -apply plugin: 'com.jfrog.artifactory' - -description 'Doorman default' - -version project(':network-management').version - -configurations { - runtimeArtifacts.extendsFrom runtime -} - -task buildDoormanJAR(type: FatCapsule, dependsOn: ':network-management:jar') { - applicationClass 'com.r3.corda.networkmanage.doorman.MainKt' - archiveName "doorman-${version}.jar" - capsuleManifest { - applicationVersion = corda_release_version - systemProperties['visualvm.display.name'] = 'Doorman' - minJavaVersion = '1.8.0' - jvmArgs = ['-XX:+UseG1GC'] - } - applicationSource = files( - project(':network-management').configurations.runtime, - project(':network-management').jar - ) - tasks.withType(Jar) { task -> - manifest { - attributes('Doorman-Version': version) - } - } -} - -artifacts { - runtimeArtifacts buildDoormanJAR - publish buildDoormanJAR { - classifier "" - } -} - -jar { - classifier "ignore" -} - -publish { - name 'doorman' - disableDefaultJar = true -} \ No newline at end of file diff --git a/network-management/cert-generator.conf b/network-management/cert-generator.conf deleted file mode 100644 index 6af78434b3..0000000000 --- a/network-management/cert-generator.conf +++ /dev/null @@ -1,28 +0,0 @@ -hsmHost = 127.0.0.1 -hsmPort = 3001 -trustStoreDirectory = "." -trustStorePassword = "trustpass" - -certConfig { - subject = "CN=Corda Root, O=R3 HoldCo LLC, OU=Corda, L=New York, C=US" - certificateType = ROOT_CA - validDays = 3650 - keyOverride = 0 - keyAlgorithm = 4 - keyExport = 0 - keyCurve = "NIST-P256" - keyGenMechanism = 4 - keyGroup = "DEV.DOORMAN" - keySpecifier = 1 - storeKeysExternal = false - crlDistributionUrl = "http://r3.com/revoked.crl" - crlIssuer = "CN=Corda Test, O=R3Cev, L=London, C=GB" -} - -userConfigs = [ - { - username = "INTEGRATION_TEST" - authMode = PASSWORD - authToken = "INTEGRATION_TEST" - } -] diff --git a/network-management/config/network-management-base.conf b/network-management/config/network-management-base.conf deleted file mode 100644 index 1f4bb095ce..0000000000 --- a/network-management/config/network-management-base.conf +++ /dev/null @@ -1,26 +0,0 @@ -basedir = "." -host = localhost -port = 0 - -# Database config -dataSourceProperties { - dataSourceClassName = org.h2.jdbcx.JdbcDataSource - "dataSource.url" = "jdbc:h2:file:"${basedir}"/persistence;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=10000;WRITE_DELAY=0;AUTO_SERVER_PORT="${h2port} - "dataSource.user" = sa - "dataSource.password" = "" -} -h2port = 0 - -# Doorman config -# Comment out this section if running without doorman service -doorman { - approveInterval = 10000 - approveAll = false -} - -# Network map config -# Comment out this section if running without network map service -networkMap { - cacheTimeout = 600000 - signInterval = 10000 -} diff --git a/network-management/config/network-management-jira.conf b/network-management/config/network-management-jira.conf deleted file mode 100644 index b3d956463d..0000000000 --- a/network-management/config/network-management-jira.conf +++ /dev/null @@ -1,33 +0,0 @@ -basedir = "." -host = localhost -port = 0 - -# Database config -dataSourceProperties { - dataSourceClassName = org.h2.jdbcx.JdbcDataSource - "dataSource.url" = "jdbc:h2:file:"${basedir}"/persistence;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=10000;WRITE_DELAY=0;AUTO_SERVER_PORT="${h2port} - "dataSource.user" = sa - "dataSource.password" = "" -} -h2port = 0 - -# Doorman config -# Comment out this section if running without doorman service -doorman { - approveInterval = 10000 - approveAll = false - jira { - address = "https://doorman-jira-host.com/" - projectCode = "TD" - username = "username" - password = "password" - doneTransitionCode = 41 - } -} - -# Network map config -# Comment out this section if running without network map service -networkMap { - cacheTimeout = 600000 - signInterval = 10000 -} diff --git a/network-management/config/network-management-local-signing.conf b/network-management/config/network-management-local-signing.conf deleted file mode 100644 index 39cea6e363..0000000000 --- a/network-management/config/network-management-local-signing.conf +++ /dev/null @@ -1,33 +0,0 @@ -basedir = "." -host = localhost -port = 0 - -#For local signing -rootStorePath = ${basedir}"/certificates/rootstore.jks" -keystorePath = ${basedir}"/certificates/caKeystore.jks" -keystorePassword = "password" -caPrivateKeyPassword = "password" - -# Database config -dataSourceProperties { - dataSourceClassName = org.h2.jdbcx.JdbcDataSource - "dataSource.url" = "jdbc:h2:file:"${basedir}"/persistence;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=10000;WRITE_DELAY=0;AUTO_SERVER_PORT="${h2port} - "dataSource.user" = sa - "dataSource.password" = "" -} -h2port = 0 - -# Doorman config -# Comment out this section if running without doorman service -doorman { - approveInterval = 10000 - approveAll = false -} - -# Network map config -# Comment out this section if running without network map service -networkMap { - cacheTimeout = 600000 - signInterval = 10000 -} - diff --git a/network-management/crl-generator.conf b/network-management/crl-generator.conf deleted file mode 100644 index b6e51b144e..0000000000 --- a/network-management/crl-generator.conf +++ /dev/null @@ -1,33 +0,0 @@ -hsmHost = 127.0.0.1 -hsmPort = 3001 -trustStoreFile = "./truststore.jks" -trustStorePassword = "trustpass" - -crl { - keyGroup = "TEST.CORDACONNECT.ROOT" - keySpecifier = 1 - validDays = 3650 - crlEndpoint = "http://test.com/crl" - indirectIssuer = true - filePath = "./bytes.crl" - revocations = [ - { - certificateSerialNumber = "12345" - dateInMillis = 1526643707290 - reason = "KEY_COMPROMISE" - }, - { - certificateSerialNumber = "6789012" - dateInMillis = 1526643712345 - reason = "KEY_COMPROMISE" - } - ] -} - -userConfigs = [ - { - username = "INTEGRATION_TEST" - authMode = PASSWORD - authToken = "INTEGRATION_TEST" - } -] diff --git a/network-management/dev-generator.conf b/network-management/dev-generator.conf deleted file mode 100644 index dbbe1246e4..0000000000 --- a/network-management/dev-generator.conf +++ /dev/null @@ -1,6 +0,0 @@ -privateKeyPass ="cordacadevkeypass" -keyStorePass = "cordacadevpass" -keyStoreFileName = "cordadevcakeys.jks" -trustStorePass = "trustpass" -trustStoreFileName = "cordatruststore.jks" -directory = "./certificates" diff --git a/network-management/doorman.conf b/network-management/doorman.conf deleted file mode 100644 index dc99924194..0000000000 --- a/network-management/doorman.conf +++ /dev/null @@ -1,55 +0,0 @@ -basedir = "." -address = "localhost:0" -rootStorePath = ${basedir}"/certificates/rootstore.jks" -keystorePath = ${basedir}"/certificates/caKeystore.jks" -#keystorePassword = "password" #Optional if not specified, user will be prompted on the console. -#caPrivateKeyPassword = "password" #Optional if not specified, user will be prompted on the console. -#rootPrivateKeyPassword = "password" #Optional if not specified, user will be prompted on the console. -#rootKeystorePassword = "password" #Optional if not specified, user will be prompted on the console. - -dataSourceProperties { - dataSourceClassName = org.h2.jdbcx.JdbcDataSource - "dataSource.url" = "jdbc:h2:file:"${basedir}"/persistence;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=10000;WRITE_DELAY=0;AUTO_SERVER_PORT="${h2port} - "dataSource.user" = sa - "dataSource.password" = "" -} - -database { - runMigration = true -} - -h2port = 0 - -# Comment out this section if running without the doorman service -doorman { - approveInterval = 10000 - approveAll = false - jira { - address = "https://doorman-jira-host.com/" - projectCode = "CSR" - username = "username" - password = "password" - } -} - -# Comment out this section if running without the revocation service -revocation { - approveInterval = 10000 - approveAll = false - crlUpdateInterval = 86400000 - crlEndpoint = "http://test.com/crl" - crlCacheTimeout = 86400000 - jira { - address = "https://doorman-jira-host.com/" - projectCode = "CRR" - username = "username" - password = "password" - } -} - -# Comment out this section if running without network map service -networkMap { - cacheTimeout = 600000 - signInterval = 10000 -} - diff --git a/network-management/hsm-for-doorman.conf b/network-management/hsm-for-doorman.conf deleted file mode 100644 index 03b05fc267..0000000000 --- a/network-management/hsm-for-doorman.conf +++ /dev/null @@ -1,27 +0,0 @@ -basedir = "." -device = "3001@192.168.0.1" -keySpecifier = -1 - -doorman { - crlDistributionPoint = "http://test.com/revoked.crl" - crlServerSocketAddress = "test.com:2333" - crlUpdatePeriod = 200000 - validDays = 3650 - mode = CSR - rootKeyStoreFile = "dummyfile.jks" - rootKeyStorePassword = "trustpass" - keyGroup = "DEV.CORDACONNECT.OPS.CERT" - authParameters { - mode = PASSWORD - password = "PASSWORD" - threshold = 2 - } -} - -h2port = 0 -dataSourceProperties { - "dataSourceClassName" = org.h2.jdbcx.JdbcDataSource - "dataSource.url" = "jdbc:h2:file:"${basedir}"/persistence;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=10000;WRITE_DELAY=0;AUTO_SERVER_PORT="${h2port} - "dataSource.user" = sa - "dataSource.password" = "" -} diff --git a/network-management/hsm-for-networkmap.conf b/network-management/hsm-for-networkmap.conf deleted file mode 100644 index 59556ea46a..0000000000 --- a/network-management/hsm-for-networkmap.conf +++ /dev/null @@ -1,22 +0,0 @@ -basedir = "." -device = "3001@192.168.0.1" -keySpecifier = -1 - -networkMap { - username = "TEST_USERNAME", - keyGroup = "DEV.CORDACONNECT.OPS.NETMAP" - authParameters { - mode = KEY_FILE - password = "PASSWORD" - keyFilePath = "./Administrator.KEY" - threshold = 2 - } -} - -h2port = 0 -dataSourceProperties { - "dataSourceClassName" = org.h2.jdbcx.JdbcDataSource - "dataSource.url" = "jdbc:h2:file:"${basedir}"/persistence;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=10000;WRITE_DELAY=0;AUTO_SERVER_PORT="${h2port} - "dataSource.user" = sa - "dataSource.password" = "" -} diff --git a/network-management/libs/CryptoServerCXI.jar b/network-management/libs/CryptoServerCXI.jar deleted file mode 100644 index 11e6412b14..0000000000 Binary files a/network-management/libs/CryptoServerCXI.jar and /dev/null differ diff --git a/network-management/libs/CryptoServerJCE.jar b/network-management/libs/CryptoServerJCE.jar deleted file mode 100644 index 913d72af30..0000000000 Binary files a/network-management/libs/CryptoServerJCE.jar and /dev/null differ diff --git a/network-management/network-parameters.conf b/network-management/network-parameters.conf deleted file mode 100644 index 0245c99e4e..0000000000 --- a/network-management/network-parameters.conf +++ /dev/null @@ -1,11 +0,0 @@ -notaries : [{ - notaryNodeInfoFile: "/Path/To/NodeInfo/File1" - validating: true -}, { - notaryNodeInfoFile: "/Path/To/NodeInfo/File2" - validating: false -}] -minimumPlatformVersion = 1 -maxMessageSize = 10485760 -maxTransactionSize = 10485760 -eventHorizonDays = 30 # Duration in days \ No newline at end of file diff --git a/network-management/registration-tool/README.md b/network-management/registration-tool/README.md deleted file mode 100644 index 362bdceb96..0000000000 --- a/network-management/registration-tool/README.md +++ /dev/null @@ -1,79 +0,0 @@ -#Distributed Notary Registration Tool - -The notary registration tool creates a CSR (Certificate Signing Request) with ``SERVICE_IDENTITY`` certificate role and sent to compatibility zone doorman for approval. -A keystore and a trust store will be created once the request is approved. - -##Configuration file -The tool creates the CSR using information provided by the config file, the path to the config file should be provided -using the ``--config-file`` flag on start up. - -The config file should contain the following parameters. - -``` -Parameter Description ---------- ----------- -legalName Legal name of the requester. It can be in form of X.500 string or CordaX500Name in typesafe config object format. - -email Requester's e-mail address. - -compatibilityZoneURL Compatibility zone URL. - -networkRootTrustStorePath Path to the network root trust store. - -networkRootTrustStorePassword Network root trust store password, to be provided by the network operator. Optional, the tool will prompt for password input if not provided. - -keyStorePassword Generated keystore's password. Optional, the tool will prompt for password input if not provided. - -trustStorePassword Generated trust store's password. Optional, the tool will prompt for password input if not provided. - -keystorePath [Optional] Path of the generated keystore file, default to certificates/notaryidentitykeystore.jks -``` - -Example config file -``` -legalName { - organisationUnit = "R3 Corda" - organisation = "R3 LTD" - locality = "London" - country = "GB" -} -# legalName = "C=GB, L=London, O=R3 LTD, OU=R3 Corda" -email = "test@email.com" -compatibilityZoneURL = "http://doorman.url.com" -networkRootTrustStorePath = "networkRootTrustStore.jks" - -networkRootTrustStorePassword = "password" -keyStorePassword = "password" -trustStorePassword = "password" - -``` - -##Running the registration tool - -``java -jar registration-tool-<>.jar --config-file <>`` - -# Private key copy tool - -The key copy tool copies the private key from the source keystore to the destination keystore, it's similar to the -``importkeystore`` option in Java keytool with extra support for Corda's key algorithms. -**This is useful for provisioning keystores for distributed notaries.** - -### Usage - -``java -jar registration-tool-<>.jar --importkeystore [options]`` - -### Example - -Copy ``distributed-notary-private-key`` from distributed notaries keystore to node's keystore. - -``` -java -jar registration-tool-<>.jar \ ---importkeystore \ ---srckeystore notaryKeystore.jks \ ---destkeystore node.jks \ ---srcstorepass notaryPassword \ ---deststorepass nodepassword \ ---srcalias distributed-notary-private-key -``` - -``--help`` prints a list of all the available options. diff --git a/network-management/registration-tool/build.gradle b/network-management/registration-tool/build.gradle deleted file mode 100644 index c95fa84c15..0000000000 --- a/network-management/registration-tool/build.gradle +++ /dev/null @@ -1,75 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -apply plugin: 'net.corda.plugins.publish-utils' -apply plugin: 'us.kirchmeier.capsule' -apply plugin: 'kotlin' - -description 'Network registration tool' - -version project(':network-management').version - -repositories { - mavenLocal() - mavenCentral() - maven { - url 'http://oss.sonatype.org/content/repositories/snapshots' - } - jcenter() - maven { - url 'http://ci-artifactory.corda.r3cev.com/artifactory/corda-dev' - } - maven { - url 'http://ci-artifactory.corda.r3cev.com/artifactory/corda-releases' - } -} - -configurations { - runtimeArtifacts.extendsFrom runtime - integrationTestCompile.extendsFrom testCompile - integrationTestRuntime.extendsFrom testRuntime -} - -task buildRegistrationTool(type: FatCapsule, dependsOn: 'jar') { - group = "build" - applicationClass 'com.r3.corda.networkmanage.registration.MainKt' - archiveName "registration-tool-${version}.jar" - capsuleManifest { - applicationVersion = corda_release_version - systemProperties['visualvm.display.name'] = 'Corda Network Registration Tool' - minJavaVersion = '1.8.0' - } - applicationSource = files( - project(':network-management:registration-tool').configurations.runtime, - project(':network-management:registration-tool').jar - ) -} - -artifacts { - runtimeArtifacts buildRegistrationTool - publish buildRegistrationTool -} - -jar { - classifier "ignore" -} - -publish { - name 'registration-tool' - disableDefaultJar = true -} - -dependencies { - compile project(':node') - // TODO: remove this when ArgsParser is moved into corda. - compile project(':network-management') - testCompile 'junit:junit:4.12' - testCompile "org.assertj:assertj-core:${assertj_version}" -} diff --git a/network-management/registration-tool/src/main/kotlin/com/r3/corda/networkmanage/registration/KeyCopyTool.kt b/network-management/registration-tool/src/main/kotlin/com/r3/corda/networkmanage/registration/KeyCopyTool.kt deleted file mode 100644 index 4a75570891..0000000000 --- a/network-management/registration-tool/src/main/kotlin/com/r3/corda/networkmanage/registration/KeyCopyTool.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.r3.corda.networkmanage.registration - -import com.r3.corda.networkmanage.registration.ToolOption.KeyCopierOption -import net.corda.nodeapi.internal.crypto.X509KeyStore - -/** - * This utility will copy private key with [KeyCopierOption.sourceAlias] from provided source keystore and copy it to target - * keystore with the same alias, or [KeyCopierOption.destinationAlias] if provided. - * - * This tool uses Corda's security provider which support EdDSA keys. - */ -fun KeyCopierOption.copyKeystore() { - println("**************************************") - println("* *") - println("* Key copy tool *") - println("* *") - println("**************************************") - println() - println("This utility will copy private key with [srcalias] from provided source keystore and copy it to target keystore with the same alias, or [destalias] if provided.") - println() - - // Read private key and certificates from notary identity keystore. - val srcKeystore = X509KeyStore.fromFile(sourceFile, sourcePassword ?: readPassword("Source key store password:")) - val srcPrivateKey = srcKeystore.getPrivateKey(sourceAlias) - val srcCertChain = srcKeystore.getCertificateChain(sourceAlias) - - X509KeyStore.fromFile(destinationFile, destinationPassword ?: readPassword("Destination key store password:")).update { - val keyAlias = destinationAlias ?: sourceAlias - setPrivateKey(keyAlias, srcPrivateKey, srcCertChain) - println("Added '$keyAlias' to keystore : $destinationFile") - } -} diff --git a/network-management/registration-tool/src/main/kotlin/com/r3/corda/networkmanage/registration/Main.kt b/network-management/registration-tool/src/main/kotlin/com/r3/corda/networkmanage/registration/Main.kt deleted file mode 100644 index f4c051da8a..0000000000 --- a/network-management/registration-tool/src/main/kotlin/com/r3/corda/networkmanage/registration/Main.kt +++ /dev/null @@ -1,94 +0,0 @@ -package com.r3.corda.networkmanage.registration - -import com.r3.corda.networkmanage.common.utils.ArgsParser -import com.r3.corda.networkmanage.registration.ToolOption.KeyCopierOption -import com.r3.corda.networkmanage.registration.ToolOption.RegistrationOption -import joptsimple.OptionSet -import joptsimple.OptionSpecBuilder -import joptsimple.util.PathConverter -import joptsimple.util.PathProperties -import net.corda.core.crypto.Crypto -import java.nio.file.Path - -fun main(args: Array) { - Crypto.registerProviders() // Required to register Providers first thing on boot. - val options = ToolArgsParser().parseOrExit(*args, printHelpOn = System.out) - when (options) { - is RegistrationOption -> options.runRegistration() - is KeyCopierOption -> options.copyKeystore() - } -} - -class ToolArgsParser : ArgsParser() { - private val importKeyStoreArg = optionParser.accepts("importkeystore") - - private val configFileArg = optionParser - .accepts("config-file", "Path to the registration config file") - .availableUnless(importKeyStoreArg) - .requiredUnless(importKeyStoreArg) - .withRequiredArg() - .withValuesConvertedBy(PathConverter(PathProperties.FILE_EXISTING)) - // key copy tool args - private val destKeystorePathArg = optionParser.accepts("destkeystore", "Path to the destination keystore which the private key should be copied to") - .requireOnlyIf(importKeyStoreArg) - .withRequiredArg() - .withValuesConvertedBy(PathConverter(PathProperties.FILE_EXISTING)) - - private val srcKeystorePathArg = optionParser.accepts("srckeystore", "Path to the source keystore containing the private key") - .requireOnlyIf(importKeyStoreArg) - .withRequiredArg() - .withValuesConvertedBy(PathConverter(PathProperties.FILE_EXISTING)) - - private val destPasswordArg = optionParser.accepts("deststorepass", "Source keystore password. Read in from the console if not specified.") - .availableIf(importKeyStoreArg) - .withRequiredArg() - - private val srcPasswordArg = optionParser.accepts("srcstorepass", "Destination keystore password. Read in from the console if not specified.") - .availableIf(importKeyStoreArg) - .withRequiredArg() - - private val destAliasArg = optionParser.accepts("destalias", "The alias under which the private key will be stored in the destination key store. If not provided then [srcalias] is used.") - .availableIf(importKeyStoreArg) - .withRequiredArg() - - private val srcAliasArg = optionParser.accepts("srcalias", "The alias under which the private key resides in the source key store") - .requireOnlyIf(importKeyStoreArg) - .withRequiredArg() - - override fun parse(optionSet: OptionSet): ToolOption { - val isCopyKey = optionSet.has(importKeyStoreArg) - return if (isCopyKey) { - val srcKeystorePath = optionSet.valueOf(srcKeystorePathArg) - val targetKeystorePath = optionSet.valueOf(destKeystorePathArg) - val srcPassword = optionSet.valueOf(srcPasswordArg) - val destPassword = optionSet.valueOf(destPasswordArg) - val srcAlias = optionSet.valueOf(srcAliasArg) - val destAlias = optionSet.valueOf(destAliasArg) - KeyCopierOption(srcKeystorePath, targetKeystorePath, srcPassword, destPassword, srcAlias, destAlias) - } else { - val configFile = optionSet.valueOf(configFileArg) - RegistrationOption(configFile) - } - } -} - -private fun OptionSpecBuilder.requireOnlyIf(option: OptionSpecBuilder): OptionSpecBuilder = requiredIf(option).availableIf(option) - -sealed class ToolOption { - data class RegistrationOption(val configFile: Path) : ToolOption() - data class KeyCopierOption(val sourceFile: Path, - val destinationFile: Path, - val sourcePassword: String?, - val destinationPassword: String?, - val sourceAlias: String, - val destinationAlias: String?) : ToolOption() -} - -fun readPassword(fmt: String): String { - return if (System.console() != null) { - String(System.console().readPassword(fmt)) - } else { - print(fmt) - readLine() ?: "" - } -} diff --git a/network-management/registration-tool/src/main/kotlin/com/r3/corda/networkmanage/registration/NotaryRegistrationTool.kt b/network-management/registration-tool/src/main/kotlin/com/r3/corda/networkmanage/registration/NotaryRegistrationTool.kt deleted file mode 100644 index 2ff23b6295..0000000000 --- a/network-management/registration-tool/src/main/kotlin/com/r3/corda/networkmanage/registration/NotaryRegistrationTool.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.registration - -import com.r3.corda.networkmanage.registration.ToolOption.RegistrationOption -import com.typesafe.config.ConfigFactory -import com.typesafe.config.ConfigParseOptions -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.CertRole -import net.corda.core.internal.div -import net.corda.node.utilities.registration.HTTPNetworkRegistrationService -import net.corda.node.utilities.registration.NetworkRegistrationHelper -import net.corda.nodeapi.internal.DevIdentityGenerator -import net.corda.nodeapi.internal.config.SSLConfiguration -import net.corda.nodeapi.internal.config.parseAs -import java.net.URL -import java.nio.file.Path -import java.nio.file.Paths - -const val NOTARY_PRIVATE_KEY_ALIAS = "${DevIdentityGenerator.DISTRIBUTED_NOTARY_ALIAS_PREFIX}-private-key" - -fun RegistrationOption.runRegistration() { - println("**********************************************************") - println("* *") - println("* Notary identity registration tool *") - println("* *") - println("**********************************************************") - println() - println("This tool will create a notary identity certificate signing request using information found in '$configFile'") - println() - - val config = ConfigFactory.parseFile(configFile.toFile(), ConfigParseOptions.defaults().setAllowMissing(false)) - .resolve() - .parseAs() - - val sslConfig = object : SSLConfiguration { - override val keyStorePassword: String by lazy { config.keyStorePassword ?: readPassword("Node Keystore password:") } - override val trustStorePassword: String by lazy { config.trustStorePassword ?: readPassword("Node TrustStore password:") } - val parent = configFile.parent - override val certificatesDirectory: Path = if (parent != null) parent / "certificates" else Paths.get("certificates") - override val nodeKeystore: Path get() = config.keystorePath ?: certificatesDirectory/"notaryidentitykeystore.jks" - override val crlCheckSoftFail: Boolean = config.crlCheckSoftFail - } - - NetworkRegistrationHelper(sslConfig, - config.legalName, - config.email, - HTTPNetworkRegistrationService(config.compatibilityZoneURL), - config.networkRootTrustStorePath, - config.networkRootTrustStorePassword ?: readPassword("Network trust root password:"), - NOTARY_PRIVATE_KEY_ALIAS, - CertRole.SERVICE_IDENTITY).buildKeystore() -} - -data class NotaryRegistrationConfig(val legalName: CordaX500Name, - val email: String, - val compatibilityZoneURL: URL, - val networkRootTrustStorePath: Path, - val keyStorePassword: String?, - val networkRootTrustStorePassword: String?, - val trustStorePassword: String?, - val keystorePath: Path?, - val crlCheckSoftFail: Boolean, - val crlDistributionPoint: URL? = null) diff --git a/network-management/registration-tool/src/main/resources/registration.conf b/network-management/registration-tool/src/main/resources/registration.conf deleted file mode 100644 index b9912d44fa..0000000000 --- a/network-management/registration-tool/src/main/resources/registration.conf +++ /dev/null @@ -1,15 +0,0 @@ -legalName { - organisationUnit = "R3 Corda" - organisation = "R3 LTD" - locality = "London" - country = "GB" -} -# legalName = "C=GB, L=London, O=R3 LTD, OU=R3 Corda" -email = "test@email.com" -compatibilityZoneURL = "http://doorman.url.com" -networkRootTrustStorePath = "networkRootTrustStore.jks" -certRole = "NODE_CA" - -networkRootTrustStorePassword = "password" -keyStorePassword = "password" -trustStorePassword = "password" diff --git a/network-management/registration-tool/src/test/kotlin/com/r3/corda/networkmanage/registration/KeyCopyToolTest.kt b/network-management/registration-tool/src/test/kotlin/com/r3/corda/networkmanage/registration/KeyCopyToolTest.kt deleted file mode 100644 index b4c184ab17..0000000000 --- a/network-management/registration-tool/src/test/kotlin/com/r3/corda/networkmanage/registration/KeyCopyToolTest.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.r3.corda.networkmanage.registration - -import net.corda.core.crypto.Crypto -import net.corda.core.internal.div -import net.corda.nodeapi.internal.crypto.X509KeyStore -import net.corda.nodeapi.internal.crypto.X509Utilities -import org.junit.Assert.assertEquals -import org.junit.Rule -import org.junit.Test -import org.junit.rules.TemporaryFolder -import java.nio.file.Path -import javax.security.auth.x500.X500Principal - -class KeyCopyToolTest { - @Rule - @JvmField - val tempFolder = TemporaryFolder() - private val tempDir: Path by lazy { tempFolder.root.toPath() } - - @Test - fun `key copy correctly`() { - val keyCopyOption = ToolOption.KeyCopierOption( - sourceFile = tempDir / "srcKeystore.jks", - destinationFile = tempDir / "destKeystore.jks", - sourcePassword = "srctestpass", - destinationPassword = "desttestpass", - sourceAlias = "TestKeyAlias", - destinationAlias = null) - - // Prepare source and destination keystores - val keyPair = Crypto.generateKeyPair() - val cert = X509Utilities.createSelfSignedCACertificate(X500Principal("O=Test"), keyPair) - - X509KeyStore.fromFile(keyCopyOption.sourceFile, keyCopyOption.sourcePassword!!, createNew = true).update { - setPrivateKey(keyCopyOption.sourceAlias, keyPair.private, listOf(cert)) - } - X509KeyStore.fromFile(keyCopyOption.destinationFile, keyCopyOption.destinationPassword!!, createNew = true) - - // Copy private key from src keystore to dest keystore using the tool - keyCopyOption.copyKeystore() - - // Verify key copied correctly - val destKeystore = X509KeyStore.fromFile(keyCopyOption.destinationFile, keyCopyOption.destinationPassword!!) - assertEquals(keyPair.private, destKeystore.getPrivateKey(keyCopyOption.sourceAlias, keyCopyOption.destinationPassword!!)) - assertEquals(cert, destKeystore.getCertificate(keyCopyOption.sourceAlias)) - } -} \ No newline at end of file diff --git a/network-management/registration-tool/src/test/kotlin/com/r3/corda/networkmanage/registration/OptionParserTest.kt b/network-management/registration-tool/src/test/kotlin/com/r3/corda/networkmanage/registration/OptionParserTest.kt deleted file mode 100644 index 8614bfa177..0000000000 --- a/network-management/registration-tool/src/test/kotlin/com/r3/corda/networkmanage/registration/OptionParserTest.kt +++ /dev/null @@ -1,92 +0,0 @@ -package com.r3.corda.networkmanage.registration - -import joptsimple.OptionException -import net.corda.core.internal.div -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.rules.TemporaryFolder -import java.nio.file.Files -import java.nio.file.Path - -class OptionParserTest { - @Rule - @JvmField - val tempFolder = TemporaryFolder() - lateinit var tempDir: Path - - @Before - fun setup() { - tempDir = tempFolder.root.toPath() - Files.createFile(tempDir / "test.file") - Files.createFile(tempDir / "source.jks") - Files.createFile(tempDir / "target.jks") - } - - @Test - fun `parse registration args correctly`() { - val options = ToolArgsParser().parseOrExit("--config-file", "${tempDir / "test.file"}") as ToolOption.RegistrationOption - assertThat(options.configFile).isEqualTo(tempDir / "test.file") - } - - @Test - fun `registration args should be unavailable in key copy mode`() { - val keyCopyArgs = arrayOf( - "--importkeystore", - "--srckeystore", "${tempDir / "source.jks"}", - "--srcstorepass", "password1", - "--destkeystore", "${tempDir / "target.jks"}", - "--deststorepass", "password2", - "--srcalias", "testalias") - assertThatThrownBy { ToolArgsParser().parseOrExit(*keyCopyArgs, "--config-file", "test.file", printHelpOn = null) } - .isInstanceOf(OptionException::class.java) - .hasMessageContaining("Option(s) [config-file] are unavailable given other options on the command line") - } - - @Test - fun `key copy args should be unavailable in registration mode`() { - assertThatThrownBy { - ToolArgsParser().parseOrExit("--config-file", "${tempDir / "test.file"}", "--srckeystore", "${tempDir / "source.jks"}", printHelpOn = null) - }.isInstanceOf(OptionException::class.java) - .hasMessageContaining("Option(s) [srckeystore] are unavailable given other options on the command line") - } - - @Test - fun `all import keystore options`() { - val keyCopyArgs = arrayOf( - "--importkeystore", - "--srckeystore", "${tempDir / "source.jks"}", - "--srcstorepass", "password1", - "--destkeystore", "${tempDir / "target.jks"}", - "--deststorepass", "password2", - "--srcalias", "testalias", - "--destalias", "testalias2") - assertThat(ToolArgsParser().parseOrExit(*keyCopyArgs)).isEqualTo(ToolOption.KeyCopierOption( - sourceFile = tempDir / "source.jks", - destinationFile = tempDir / "target.jks", - sourcePassword = "password1", - destinationPassword = "password2", - sourceAlias = "testalias", - destinationAlias = "testalias2" - )) - } - - @Test - fun `minimum import keystore options`() { - val keyCopyArgs = arrayOf( - "--importkeystore", - "--srckeystore", "${tempDir / "source.jks"}", - "--destkeystore", "${tempDir / "target.jks"}", - "--srcalias", "testalias") - assertThat(ToolArgsParser().parseOrExit(*keyCopyArgs)).isEqualTo(ToolOption.KeyCopierOption( - sourceFile = tempDir / "source.jks", - destinationFile = tempDir / "target.jks", - sourcePassword = null, - destinationPassword = null, - sourceAlias = "testalias", - destinationAlias = null - )) - } -} diff --git a/network-management/registration-tool/src/test/kotlin/com/r3/corda/networkmanage/registration/RegistrationConfigTest.kt b/network-management/registration-tool/src/test/kotlin/com/r3/corda/networkmanage/registration/RegistrationConfigTest.kt deleted file mode 100644 index a5e64741bd..0000000000 --- a/network-management/registration-tool/src/test/kotlin/com/r3/corda/networkmanage/registration/RegistrationConfigTest.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.registration - -import com.typesafe.config.ConfigFactory -import com.typesafe.config.ConfigParseOptions -import net.corda.core.identity.CordaX500Name -import net.corda.nodeapi.internal.config.parseAs -import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue -import org.junit.Test -import java.nio.file.Paths - -class RegistrationConfigTest { - @Test - fun `parse config file correctly`() { - val testConfig = """ -legalName { - organisationUnit = "R3 Corda" - organisation = "R3 LTD" - locality = "London" - country = "GB" -} -email = "test@email.com" -compatibilityZoneURL = "http://doorman.url.com" -networkRootTrustStorePath = "networkRootTrustStore.jks" -keystorePath = "notaryidentitykeystore.jks" - -networkRootTrustStorePassword = "password" -keyStorePassword = "password" -trustStorePassword = "password" -crlCheckSoftFail = true -""".trimIndent() - - val config = ConfigFactory.parseString(testConfig, ConfigParseOptions.defaults().setAllowMissing(false)) - .resolve() - .parseAs() - - assertEquals(CordaX500Name.parse("OU=R3 Corda, O=R3 LTD, L=London, C=GB"), config.legalName) - assertEquals("http://doorman.url.com", config.compatibilityZoneURL.toString()) - assertEquals("test@email.com", config.email) - assertEquals(Paths.get("networkRootTrustStore.jks"), config.networkRootTrustStorePath) - assertEquals("password", config.networkRootTrustStorePassword) - assertEquals(Paths.get("notaryidentitykeystore.jks"), config.keystorePath) - assertTrue(config.crlCheckSoftFail) - } -} \ No newline at end of file diff --git a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/HsmSimulator.kt b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/HsmSimulator.kt deleted file mode 100644 index b062199a61..0000000000 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/HsmSimulator.kt +++ /dev/null @@ -1,190 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage - -import CryptoServerAPI.CryptoServerException -import com.r3.corda.networkmanage.hsm.authentication.CryptoServerProviderConfig -import com.r3.corda.networkmanage.hsm.authentication.createProvider -import com.spotify.docker.client.DefaultDockerClient -import com.spotify.docker.client.DockerClient -import com.spotify.docker.client.messages.ContainerConfig -import com.spotify.docker.client.messages.HostConfig -import com.spotify.docker.client.messages.PortBinding -import com.spotify.docker.client.messages.RegistryAuth -import net.corda.core.utilities.loggerFor -import net.corda.testing.core.freeLocalHostAndPort -import org.junit.Assume.assumeFalse -import org.junit.rules.ExternalResource - -data class CryptoUserCredentials(val username: String, val password: String) - -/** - * HSM Simulator rule allowing to use the HSM Simulator within the integration tests. It is designed to be used mainly - * on the TeamCity, but if the required setup is available it can be executed locally as well. - * It will bind to the simulator to the local port - * To use it locally, the following pre-requisites need to be met: - * 1) Docker engine needs to be installed on the machine - * 2) Environment variables (AZURE_CR_USER and AZURE_CR_PASS) are available and hold valid credentials to the corda.azurecr.io - * repository - * 3) HSM requires Unlimited Strength Jurisdiction extension to be installed on the machine connecting with the HSM box. - * See http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html - * - * Since the above setup is not a strong requirement for the integration tests to be executed it is intended that this - * rule is used together with the assumption mechanism in tests. - */ -class HsmSimulator(private val serverAddress: String = DEFAULT_SERVER_ADDRESS, - private val imageRepoTag: String = DEFAULT_IMAGE_REPO_TAG, - private val imageVersion: String = DEFAULT_IMAGE_VERSION, - private val pullImage: Boolean = DEFAULT_PULL_IMAGE, - private val registryUser: String? = REGISTRY_USERNAME, - private val registryPass: String? = REGISTRY_PASSWORD) : ExternalResource() { - - private companion object { - val DEFAULT_SERVER_ADDRESS = "corda.azurecr.io" - /* - * Currently we have following images: - * 1) corda.azurecr.io/network-management/hsm-simulator - having only one user configured: - * - INTEGRATION_TEST (password: INTEGRATION_TEST) with the CXI_GROUP="*" - * 2)corda.azurecr.io/network-management/hsm-simulator-with-groups - having following users configured: - * - INTEGRATION_TEST (password: INTEGRATION_TEST) with the CXI_GROUP=* - * - INTEGRATION_TEST_SUPER (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT - * - INTEGRATION_TEST_ROOT (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.ROOT - * - INTEGRATION_TEST_OPS (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.OPS - * - INTEGRATION_TEST_SUPER_ (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.* - * - INTEGRATION_TEST_ROOT_ (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.ROOT.* - * - INTEGRATION_TEST_OPS_ (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.OPS.* - * - INTEGRATION_TEST_OPS_CERT (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.OPS.CERT - * - INTEGRATION_TEST_OPS_NETMAP (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.OPS.NETMAP - * - INTEGRATION_TEST_OPS_CERT (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.OPS.CERT.* - * - INTEGRATION_TEST_OPS_NETMAP (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.OPS.NETMAP.* - */ - val DEFAULT_IMAGE_REPO_TAG = "corda.azurecr.io/network-management/hsm-simulator-with-groups" - val DEFAULT_IMAGE_VERSION = "latest" - val DEFAULT_PULL_IMAGE = true - - val HSM_SIMULATOR_PORT = "3001/tcp" - val CONTAINER_KILL_TIMEOUT_SECONDS = 10 - - val CRYPTO_USER = System.getProperty("CRYPTO_USER", "INTEGRATION_TEST") - val CRYPTO_PASSWORD = System.getProperty("CRYPTO_PASSWORD", "INTEGRATION_TEST") - - val REGISTRY_USERNAME = System.getenv("AZURE_CR_USER") - val REGISTRY_PASSWORD = System.getenv("AZURE_CR_PASS") - - val log = loggerFor() - - private val HSM_STARTUP_SLEEP_INTERVAL_MS = 500L - private val HSM_STARTUP_POLL_MAX_COUNT = 10; - } - - private val localHostAndPortBinding = freeLocalHostAndPort() - private lateinit var docker: DockerClient - private var containerId: String? = null - - override fun before() { - assumeFalse("Docker registry username is not set!. Skipping the test.", registryUser.isNullOrBlank()) - assumeFalse("Docker registry password is not set!. Skipping the test.", registryPass.isNullOrBlank()) - docker = DefaultDockerClient.fromEnv().build() - if (pullImage) { - docker.pullHsmSimulatorImageFromRepository() - } - containerId = docker.createContainer() - docker.startHsmSimulatorContainer() - } - - override fun after() { - docker.stopAndRemoveHsmSimulatorContainer() - } - - /** - * Retrieves the port at which simulator is listening at. - */ - val port get(): Int = localHostAndPortBinding.port - - /** - * Retrieves the host IP address, which the simulator is listening at. - */ - val host get(): String = localHostAndPortBinding.host - - /** - * Retrieves the HSM user credentials. Those are supposed to be preconfigured on the HSM itself. Thus, when - * tests are executed these credentials can be used to access HSM crypto user's functionality. - * It is assumed that the docker image state has those configured already and they should match the ones returned. - */ - fun cryptoUserCredentials(): CryptoUserCredentials { - return CryptoUserCredentials(CRYPTO_USER, CRYPTO_PASSWORD) - } - - private fun DockerClient.stopAndRemoveHsmSimulatorContainer() { - if (containerId != null) { - log.debug("Stopping container $containerId...") - this.stopContainer(containerId, CONTAINER_KILL_TIMEOUT_SECONDS) - log.debug("Removing container $containerId...") - this.removeContainer(containerId) - } - } - - private fun DockerClient.startHsmSimulatorContainer() { - if (containerId != null) { - log.debug("Starting container $containerId...") - this.startContainer(containerId) - pollAndWaitForHsmSimulator() - } - } - - private fun pollAndWaitForHsmSimulator() { - val config = CryptoServerProviderConfig( - Device = "${localHostAndPortBinding.port}@${localHostAndPortBinding.host}", - KeyGroup = "*", - KeySpecifier = -1 - ) - var pollCount = HSM_STARTUP_POLL_MAX_COUNT - while (pollCount > 0) { - val provider = createProvider(config) - try { - provider.loginPassword(CRYPTO_USER, CRYPTO_PASSWORD) - provider.cryptoServer.authState - return - } catch (e: CryptoServerException) { - pollCount-- - Thread.sleep(HSM_STARTUP_SLEEP_INTERVAL_MS) - } finally { - provider.logoff() - } - } - throw IllegalStateException("Unable to obtain connection to initialised HSM Simulator") - } - - private fun getImageFullName() = "$imageRepoTag:$imageVersion" - - private fun DockerClient.pullHsmSimulatorImageFromRepository(): DockerClient { - this.pull(imageRepoTag, - RegistryAuth.builder() - .serverAddress(serverAddress) - .username(registryUser) - .password(registryPass) - .build()) - return this - } - - private fun DockerClient.createContainer(): String? { - val portBindings = mapOf(HSM_SIMULATOR_PORT to listOf(PortBinding.create(localHostAndPortBinding.host, localHostAndPortBinding.port.toString()))) - val hostConfig = HostConfig.builder().portBindings(portBindings).build() - val containerConfig = ContainerConfig.builder() - .hostConfig(hostConfig) - .portSpecs() - .image(getImageFullName()) - .exposedPorts(HSM_SIMULATOR_PORT) - .build() - val containerCreation = this.createContainer(containerConfig) - return containerCreation.id() - } -} \ No newline at end of file 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 deleted file mode 100644 index 62211f8fad..0000000000 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/common/HsmBaseTest.kt +++ /dev/null @@ -1,203 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common - -import com.nhaarman.mockito_kotlin.any -import com.nhaarman.mockito_kotlin.mock -import com.nhaarman.mockito_kotlin.whenever -import com.r3.corda.networkmanage.HsmSimulator -import com.r3.corda.networkmanage.hsm.authentication.CryptoServerProviderConfig -import com.r3.corda.networkmanage.hsm.authentication.InputReader -import com.r3.corda.networkmanage.hsm.configuration.* -import com.r3.corda.networkmanage.hsm.generator.UserAuthenticationParameters -import com.r3.corda.networkmanage.hsm.generator.certificate.CertificateConfiguration -import com.r3.corda.networkmanage.hsm.generator.certificate.GeneratorParameters -import net.corda.core.crypto.random63BitValue -import net.corda.core.internal.div -import net.corda.core.utilities.NetworkHostAndPort -import net.corda.nodeapi.internal.crypto.CertificateType -import net.corda.nodeapi.internal.persistence.DatabaseConfig -import net.corda.testing.internal.IntegrationTest -import net.corda.testing.internal.IntegrationTestSchemas -import net.corda.testing.node.internal.makeTestDataSourceProperties -import net.corda.testing.node.internal.makeTestDatabaseProperties -import org.junit.Before -import org.junit.ClassRule -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import java.net.URL -import java.nio.file.Path -import java.util.* -import com.r3.corda.networkmanage.hsm.authentication.AuthMode as SigningServiceAuthMode -import com.r3.corda.networkmanage.hsm.generator.AuthMode as GeneratorAuthMode - -abstract class HsmBaseTest : IntegrationTest() { - companion object { - const val ROOT_CERT_KEY_GROUP = "TEST.CORDACONNECT.ROOT" - const val NETWORK_MAP_CERT_KEY_GROUP = "TEST.CORDACONNECT.OPS.NETMAP" - const val DOORMAN_CERT_KEY_GROUP = "TEST.CORDACONNECT.OPS.CERT" - const val ROOT_CERT_SUBJECT = "CN=Corda Root CA, OU=Corda, O=R3 Ltd, L=London, C=GB" - const val NETWORK_MAP_CERT_SUBJECT = "CN=Corda Network Map, OU=Corda, O=R3 Ltd, L=London, C=GB" - const val DOORMAN_CERT_SUBJECT = "CN=Corda Doorman CA, OU=Corda, O=R3 Ltd, L=London, C=GB" - const val TRUSTSTORE_PASSWORD: String = "trustpass" - const val HSM_USERNAME = "INTEGRATION_TEST" - const val HSM_PASSWORD = "INTEGRATION_TEST" - const val HSM_USERNAME_SUPER = "INTEGRATION_TEST_SUPER" - const val HSM_USERNAME_OPS = "INTEGRATION_TEST_OPS" - const val HSM_USERNAME_ROOT = "INTEGRATION_TEST_ROOT" - const val HSM_USERNAME_SUPER_ = "INTEGRATION_TEST_SUPER_" - const val HSM_USERNAME_OPS_ = "INTEGRATION_TEST_OPS_" - const val HSM_USERNAME_ROOT_ = "INTEGRATION_TEST_ROOT_" - const val HSM_USERNAME_OPS_CERT = "INTEGRATION_TEST_OPS_CERT" - const val HSM_USERNAME_OPS_NETMAP = "INTEGRATION_TEST_OPS_NETMAP" - const val HSM_USERNAME_OPS_CERT_ = "INTEGRATION_TEST_OPS_CERT_" - const val HSM_USERNAME_OPS_NETMAP_ = "INTEGRATION_TEST_OPS_NETMAP_" - val HSM_USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME) - val HSM_SUPER_USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_SUPER) - val HSM_ROOT_USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_ROOT) - val HSM_OPS_USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_OPS) - val HSM_SUPER__USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_SUPER_) - val HSM_ROOT__USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_ROOT_) - val HSM_OPS__USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_OPS_) - val HSM_OPS_CERT_USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_OPS_CERT) - val HSM_OPS_NETMAP_USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_OPS_NETMAP) - val HSM_OPS_CERT__USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_OPS_CERT_) - val HSM_OPS_NETMAP__USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_OPS_NETMAP_) - - private fun createHsmUserConfigs(username: String): List { - return listOf(UserAuthenticationParameters( - username = username, - authMode = GeneratorAuthMode.PASSWORD, - authToken = "INTEGRATION_TEST", - keyFilePassword = null)) - } - - @ClassRule - @JvmField - val databaseSchemas = IntegrationTestSchemas(DOORMAN_DB_NAME) - } - - protected lateinit var rootKeyStoreFile: Path - - @Rule - @JvmField - val tempFolder = TemporaryFolder() - - @Rule - @JvmField - val hsmSimulator: HsmSimulator = HsmSimulator() - - private lateinit var dbName: String - - @Before - fun generateDbName() { - rootKeyStoreFile = tempFolder.root.toPath() / "truststore.jks" - dbName = random63BitValue().toString() - } - - private fun createGeneratorParameters(certConfig: CertificateConfiguration, - userConfigs: List): GeneratorParameters { - return GeneratorParameters( - hsmHost = hsmSimulator.host, - hsmPort = hsmSimulator.port, - trustStoreDirectory = rootKeyStoreFile.parent, - trustStorePassword = TRUSTSTORE_PASSWORD, - userConfigs = userConfigs, - certConfig = certConfig - ) - } - - protected fun createGeneratorParameters(keyGroup: String, - rootKeyGroup: String?, - certificateType: CertificateType, - subject: String, - hsmUserConfigs: List = HSM_USER_CONFIGS): GeneratorParameters { - return createGeneratorParameters(CertificateConfiguration( - keySpecifier = 1, - keyGroup = keyGroup, - storeKeysExternal = false, - rootKeyGroup = rootKeyGroup, - subject = subject, - validDays = 3650, - keyCurve = "NIST-P256", - certificateType = certificateType, - keyExport = 0, - keyGenMechanism = 4, - keyOverride = 0, - crlIssuer = null, - crlDistributionUrl = null - ), hsmUserConfigs) - } - - protected fun createHsmSigningServiceConfig(doormanCertConfig: DoormanCertificateConfig?, - networkMapCertificateConfig: NetworkMapCertificateConfig?): SigningServiceConfig { - return SigningServiceConfig( - dataSourceProperties = mock(), - device = "${hsmSimulator.port}@${hsmSimulator.host}", - keySpecifier = 1, - doorman = doormanCertConfig, - networkMap = networkMapCertificateConfig - ) - } - - protected fun createDoormanCertificateConfig(): DoormanCertificateConfig { - return DoormanCertificateConfig( - rootKeyStoreFile = rootKeyStoreFile, - keyGroup = DOORMAN_CERT_KEY_GROUP, - validDays = 3650, - rootKeyStorePassword = TRUSTSTORE_PASSWORD, - crlDistributionPoint = URL("http://test.com/revoked.crl"), - crlServerSocketAddress = NetworkHostAndPort("test.com", 4555), - crlUpdatePeriod = 1000, - mode = ManualMode.CSR, - authParameters = AuthParametersConfig( - mode = SigningServiceAuthMode.PASSWORD, - threshold = 2 - ) - ) - } - - protected fun createNetworkMapCertificateConfig(): NetworkMapCertificateConfig { - return NetworkMapCertificateConfig( - username = "INTEGRATION_TEST", - keyGroup = NETWORK_MAP_CERT_KEY_GROUP, - authParameters = AuthParametersConfig( - mode = SigningServiceAuthMode.PASSWORD, - password = "INTEGRATION_TEST", - threshold = 2 - ) - ) - } - - protected fun givenHsmUserAuthenticationInput(username: String = HSM_USERNAME, - password: String = HSM_PASSWORD): InputReader { - val inputReader = mock() - whenever(inputReader.readLine()).thenReturn(username) - whenever(inputReader.readPassword(any())).thenReturn(password) - return inputReader - } - - fun makeTestDataSourceProperties(): Properties { - return makeTestDataSourceProperties(DOORMAN_DB_NAME, configSupplier = configSupplierForSupportedDatabases()) - } - - fun makeTestDatabaseProperties(): DatabaseConfig { - return makeTestDatabaseProperties(DOORMAN_DB_NAME, configSupplier = configSupplierForSupportedDatabases()) - } - - protected fun createProviderConfig(keyGroup: String): CryptoServerProviderConfig { - return CryptoServerProviderConfig( - Device = "${hsmSimulator.port}@${hsmSimulator.host}", - KeySpecifier = 1, - KeyGroup = keyGroup, - StoreKeysExternal = false) - } -} \ No newline at end of file diff --git a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/common/TestUtils.kt b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/common/TestUtils.kt deleted file mode 100644 index b8dc16810e..0000000000 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/common/TestUtils.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common - -import com.r3.corda.networkmanage.common.utils.createSignedCrl -import com.r3.corda.networkmanage.doorman.signer.LocalSigner -import com.typesafe.config.Config -import com.typesafe.config.ConfigFactory -import net.corda.core.crypto.SecureHash -import net.corda.core.utilities.NetworkHostAndPort -import net.corda.core.utilities.days -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import net.corda.testing.database.DatabaseConstants -import net.corda.testing.node.internal.databaseProviderDataSourceConfig -import org.apache.commons.io.FileUtils -import org.junit.rules.TemporaryFolder -import java.net.URL -import java.nio.file.Path - -const val HOST = "localhost" - -const val DOORMAN_DB_NAME = "doorman" - -fun networkMapInMemoryH2DataSourceConfig(nodeName: String? = null, postfix: String? = null): Config { - val nodeName = nodeName ?: SecureHash.randomSHA256().toString() - val h2InstanceName = if (postfix != null) nodeName + "_" + postfix else nodeName - - return ConfigFactory.parseMap(mapOf( - DatabaseConstants.DATA_SOURCE_CLASSNAME to "org.h2.jdbcx.JdbcDataSource", - DatabaseConstants.DATA_SOURCE_URL to "jdbc:h2:mem:${h2InstanceName};DB_CLOSE_DELAY=-1", - DatabaseConstants.DATA_SOURCE_USER to "sa", - DatabaseConstants.DATA_SOURCE_PASSWORD to "")) -} - -fun generateEmptyCrls(tempFolder: TemporaryFolder, rootCertAndKeyPair: CertificateAndKeyPair, directEndpoint: URL, indirectEndpoint: URL): Pair { - val localSigner = LocalSigner(rootCertAndKeyPair) - val directCrl = createSignedCrl(rootCertAndKeyPair.certificate, directEndpoint, 10.days, localSigner, emptyList(), false) - val indirectCrl = createSignedCrl(rootCertAndKeyPair.certificate, indirectEndpoint, 10.days, localSigner, emptyList(), true) - val directCrlFile = tempFolder.newFile() - FileUtils.writeByteArrayToFile(directCrlFile, directCrl.encoded) - val indirectCrlFile = tempFolder.newFile() - FileUtils.writeByteArrayToFile(indirectCrlFile, indirectCrl.encoded) - return Pair(directCrlFile.toPath(), indirectCrlFile.toPath()) -} - -fun getCaCrlEndpoint(serverAddress: NetworkHostAndPort) = URL("http://$serverAddress/certificate-revocation-list/root") -fun getEmptyCrlEndpoint(serverAddress: NetworkHostAndPort) = URL("http://$serverAddress/certificate-revocation-list/empty") -fun getNodeCrlEndpoint(serverAddress: NetworkHostAndPort) = URL("http://$serverAddress/certificate-revocation-list/doorman") - -//TODO add more dbs to test once doorman supports them -fun configSupplierForSupportedDatabases(): (String?, String?) -> Config = - when (System.getProperty("custom.databaseProvider", "")) { - "integration-sql-server", "integration-azure-sql" -> ::databaseProviderDataSourceConfig - else -> { _, _ -> ConfigFactory.empty() } - } \ No newline at end of file diff --git a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/doorman/NetworkParametersUpdateTest.kt b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/doorman/NetworkParametersUpdateTest.kt deleted file mode 100644 index 2049753f83..0000000000 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/doorman/NetworkParametersUpdateTest.kt +++ /dev/null @@ -1,188 +0,0 @@ -package com.r3.corda.networkmanage.doorman - -import com.r3.corda.networkmanage.common.DOORMAN_DB_NAME -import com.r3.corda.networkmanage.common.configSupplierForSupportedDatabases -import com.r3.corda.networkmanage.common.networkMapInMemoryH2DataSourceConfig -import com.r3.corda.networkmanage.common.utils.CertPathAndKey -import com.r3.corda.networkmanage.doorman.signer.LocalSigner -import net.corda.core.crypto.random63BitValue -import net.corda.core.internal.bufferUntilSubscribed -import net.corda.core.internal.div -import net.corda.core.internal.readObject -import net.corda.core.messaging.ParametersUpdateInfo -import net.corda.core.utilities.getOrThrow -import net.corda.core.utilities.seconds -import net.corda.nodeapi.internal.createDevNetworkMapCa -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME -import net.corda.nodeapi.internal.network.SignedNetworkParameters -import net.corda.nodeapi.internal.persistence.DatabaseConfig -import net.corda.testing.core.* -import net.corda.testing.driver.PortAllocation -import net.corda.testing.driver.internal.NodeHandleInternal -import net.corda.testing.internal.IntegrationTest -import net.corda.testing.internal.IntegrationTestSchemas -import net.corda.testing.internal.createDevIntermediateCaCertPath -import net.corda.testing.internal.toDatabaseSchemaName -import net.corda.testing.node.internal.CompatibilityZoneParams -import net.corda.testing.node.internal.internalDriver -import net.corda.testing.node.internal.makeTestDataSourceProperties -import org.assertj.core.api.Assertions.assertThat -import org.junit.* -import org.junit.Assert.assertEquals -import java.net.URL -import java.security.cert.X509Certificate -import java.time.Instant - -class NetworkParametersUpdateTest : IntegrationTest() { - companion object { - private val timeoutMillis = 5.seconds.toMillis() - @ClassRule - @JvmField - val databaseSchemas = IntegrationTestSchemas(ALICE_NAME.toDatabaseSchemaName(), BOB_NAME.toDatabaseSchemaName(), - DUMMY_NOTARY_NAME.toDatabaseSchemaName(), DOORMAN_DB_NAME) - } - - @Rule - @JvmField - val testSerialization = SerializationEnvironmentRule(true) - - private val portAllocation = PortAllocation.Incremental(10000) - private val serverAddress = portAllocation.nextHostAndPort() - - private lateinit var rootCaCert: X509Certificate - private lateinit var doormanCa: CertificateAndKeyPair - private lateinit var networkMapCa: CertificateAndKeyPair - //for normal integration tests (not against standalone db) to create a unique db name for each tests against H2 - private lateinit var dbNamePostfix: String - - private var server: NetworkManagementServer? = null - - @Before - fun init() { - dbNamePostfix = random63BitValue().toString() - val (rootCa, doormanCa) = createDevIntermediateCaCertPath() - rootCaCert = rootCa.certificate - this.doormanCa = doormanCa - networkMapCa = createDevNetworkMapCa(rootCa) - } - - @After - fun cleanUp() { - server?.close() - } - - @Test - fun `network parameters update commnunicated to node`() { - // Initialise the server with some network parameters - val initialNetParams = NetworkParametersCmd.Set( - notaries = emptyList(), - minimumPlatformVersion = 1, - maxMessageSize = 1_000_000, - maxTransactionSize = 1_000_000, - parametersUpdate = null, - eventHorizonDays = 30 - ) - applyNetworkParametersAndStart(initialNetParams) - - val compatibilityZone = CompatibilityZoneParams( - URL("http://$serverAddress"), - publishNotaries = {}, - rootCert = rootCaCert - ) - - internalDriver( - portAllocation = portAllocation, - compatibilityZone = compatibilityZone, - notarySpecs = emptyList(), - initialiseSerialization = false, - extraCordappPackagesToScan = listOf("net.corda.finance"), - notaryCustomOverrides = mapOf("devMode" to false) - ) { - var (alice, bob) = listOf( - startNode(providedName = ALICE_NAME, customOverrides = mapOf("devMode" to false)), - startNode(providedName = BOB_NAME, customOverrides = mapOf("devMode" to false)) - ).map { it.getOrThrow() as NodeHandleInternal } - - // Make sure that stopping Bob doesn't remove him from the network map - bob.stop() - Thread.sleep(timeoutMillis * 2) - assertThat(alice.rpc.networkMapSnapshot().map { it.legalIdentities[0].name }).contains(BOB_NAME) - - val snapshot = alice.rpc.networkParametersFeed().snapshot - val updates = alice.rpc.networkParametersFeed().updates.bufferUntilSubscribed() - assertThat(snapshot).isNull() - - val updateDeadline = Instant.now() + 10.seconds - - applyNetworkParametersAndStart(initialNetParams.copy( - maxTransactionSize = 1_000_001, - parametersUpdate = ParametersUpdateConfig( - description = "Very Important Update", - updateDeadline = updateDeadline - ) - )) - - updates.expectEvents(isStrict = true) { - sequence( - expect { update: ParametersUpdateInfo -> - assertEquals(update.description, "Very Important Update") - assertEquals(update.parameters.maxTransactionSize, 1_000_001) - assertEquals(update.parameters.epoch, 2) // The epoch must increment automatically. - } - ) - } - - val paramUpdateInfo = alice.rpc.networkParametersFeed().snapshot!! - alice.rpc.acceptNewNetworkParameters(paramUpdateInfo.hash) - - // Make sure we've passed the deadline - Thread.sleep(Math.max(updateDeadline.toEpochMilli() - System.currentTimeMillis(), 0)) - applyNetworkParametersAndStart(NetworkParametersCmd.FlagDay) - - alice.stop() - alice = startNode(providedName = ALICE_NAME, customOverrides = mapOf("devMode" to false)).getOrThrow() as NodeHandleInternal - - // TODO It is also possible to check what version of parameters node runs by writing flow that reads that value from ServiceHub - val networkParameters = (alice.configuration.baseDirectory / NETWORK_PARAMS_FILE_NAME) - .readObject().verified() - assertEquals(networkParameters, paramUpdateInfo.parameters) - assertThat(alice.rpc.networkParametersFeed().snapshot).isNull() // Check that NMS doesn't advertise updates anymore. - // Check that Bob is no longer on the network as it didn't accept the new parameteres. - assertThat(alice.rpc.networkMapSnapshot().map { it.legalIdentities[0].name }).doesNotContain(BOB_NAME) - } - } - - private fun startServer(startNetworkMap: Boolean = true): NetworkManagementServer { - val doormanConfig = DoormanConfig(approveAll = true, jira = null, approveInterval = timeoutMillis) - val server = NetworkManagementServer(makeTestDataSourceProperties(DOORMAN_DB_NAME, dbNamePostfix, configSupplier = configSupplierForSupportedDatabases(), fallBackConfigSupplier = ::networkMapInMemoryH2DataSourceConfig), - DatabaseConfig(runMigration = true), doormanConfig, null) - server.start( - serverAddress, - CertPathAndKey(listOf(doormanCa.certificate, rootCaCert), doormanCa.keyPair.private), - if (startNetworkMap) { - NetworkMapStartParams( - LocalSigner(networkMapCa), - NetworkMapConfig(cacheTimeout = timeoutMillis, signInterval = timeoutMillis) - ) - } else { - null - } - ) - return server - } - - private fun applyNetworkParametersAndStart(networkParametersCmd: NetworkParametersCmd) { - server?.close() - NetworkManagementServer( - makeTestDataSourceProperties(DOORMAN_DB_NAME, dbNamePostfix, configSupplier = configSupplierForSupportedDatabases(), fallBackConfigSupplier = ::networkMapInMemoryH2DataSourceConfig), - DatabaseConfig(runMigration = true), - DoormanConfig(approveAll = true, jira = null, approveInterval = timeoutMillis), - null).use { - it.netParamsUpdateHandler.processNetworkParameters(networkParametersCmd) - } - server = startServer(startNetworkMap = true) - // Wait for server to process the parameters update and for the nodes to poll again - Thread.sleep(timeoutMillis * 2) - } -} diff --git a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/doorman/NodeRegistrationTest.kt b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/doorman/NodeRegistrationTest.kt deleted file mode 100644 index 25c9c7aec5..0000000000 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/doorman/NodeRegistrationTest.kt +++ /dev/null @@ -1,215 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman - -import com.r3.corda.networkmanage.common.* -import com.r3.corda.networkmanage.common.utils.CertPathAndKey -import com.r3.corda.networkmanage.doorman.signer.LocalSigner -import net.corda.cordform.CordformNode -import net.corda.core.crypto.random63BitValue -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.div -import net.corda.core.internal.exists -import net.corda.core.internal.list -import net.corda.core.messaging.startFlow -import net.corda.core.utilities.OpaqueBytes -import net.corda.core.utilities.getOrThrow -import net.corda.core.utilities.seconds -import net.corda.finance.DOLLARS -import net.corda.finance.flows.CashIssueAndPaymentFlow -import net.corda.nodeapi.internal.createDevNetworkMapCa -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import net.corda.testing.core.SerializationEnvironmentRule -import net.corda.testing.core.singleIdentity -import net.corda.testing.driver.NodeHandle -import net.corda.testing.driver.PortAllocation -import net.corda.testing.driver.internal.NodeHandleInternal -import net.corda.testing.internal.IntegrationTest -import net.corda.testing.internal.IntegrationTestSchemas -import net.corda.testing.internal.createDevIntermediateCaCertPath -import net.corda.testing.node.NotarySpec -import net.corda.testing.node.internal.CompatibilityZoneParams -import net.corda.testing.node.internal.internalDriver -import net.corda.testing.node.internal.makeTestDataSourceProperties -import net.corda.testing.node.internal.makeTestDatabaseProperties -import org.assertj.core.api.Assertions.assertThat -import org.junit.* -import org.junit.rules.TemporaryFolder -import java.net.URL -import java.nio.file.Path -import java.security.cert.X509Certificate -import kotlin.streams.toList - -// This is the same test as the one in net.corda.node.utilities.registration but using the real doorman and with some -// extra checks on the network map. -class NodeRegistrationTest : IntegrationTest() { - companion object { - private val notaryName = CordaX500Name("NotaryService", "Zurich", "CH") - private val aliceName = CordaX500Name("Alice", "London", "GB") - private val genevieveName = CordaX500Name("Genevieve", "London", "GB") - private val timeoutMillis = 5.seconds.toMillis() - - @ClassRule - @JvmField - val databaseSchemas = IntegrationTestSchemas(notaryName.organisation, aliceName.organisation, genevieveName.organisation, - DOORMAN_DB_NAME) - } - - @Rule - @JvmField - val testSerialization = SerializationEnvironmentRule(true) - - private val portAllocation = PortAllocation.Incremental(10000) - private val serverAddress = portAllocation.nextHostAndPort() - - private lateinit var rootCaCert: X509Certificate - private lateinit var doormanCa: CertificateAndKeyPair - private lateinit var networkMapCa: CertificateAndKeyPair - //for normal integration tests (not against standalone db) to create a unique db name for each tests against H2 - private lateinit var dbNamePostfix: String - - private var server: NetworkManagementServer? = null - - @Rule - @JvmField - val tempFolder = TemporaryFolder() - - private val doormanConfig: DoormanConfig get() = DoormanConfig(approveAll = true, jira = null, approveInterval = timeoutMillis) - private lateinit var revocationConfig: CertificateRevocationConfig - - private fun createCertificateRevocationConfig(emptyCrlPath: Path, caCrlPath: Path): CertificateRevocationConfig { - return CertificateRevocationConfig( - approveAll = true, - jira = null, - approveInterval = timeoutMillis, - crlCacheTimeout = timeoutMillis, - localSigning = CertificateRevocationConfig.LocalSigning( - crlEndpoint = getNodeCrlEndpoint(serverAddress), - crlUpdateInterval = timeoutMillis), - emptyCrlPath = emptyCrlPath, - caCrlPath = caCrlPath) - } - - @Before - fun init() { - dbNamePostfix = random63BitValue().toString() - val (rootCa, doormanCa) = createDevIntermediateCaCertPath() - rootCaCert = rootCa.certificate - this.doormanCa = doormanCa - networkMapCa = createDevNetworkMapCa(rootCa) - val (caCrlPath, emptyCrlPath) = generateEmptyCrls(tempFolder, rootCa, getCaCrlEndpoint(serverAddress), getEmptyCrlEndpoint(serverAddress)) - revocationConfig = createCertificateRevocationConfig(emptyCrlPath, caCrlPath) - } - - @After - fun cleanUp() { - server?.close() - } - - @Test - fun `register nodes with doorman and then they transact with each other`() { - // Start the server without the network parameters config which won't start the network map. Just the doorman - // registration process will start up, allowing us to register the notaries which will then be used in the network - // parameters. - server = startServer(startNetworkMap = false) - val compatibilityZone = CompatibilityZoneParams( - URL("http://$serverAddress"), - publishNotaries = { notaryInfos -> - val setNetParams = NetworkParametersCmd.Set( - notaries = notaryInfos, - minimumPlatformVersion = 1, - maxMessageSize = 10485760, - maxTransactionSize = 10485760, - parametersUpdate = null, - eventHorizonDays = 30 - ) - // Restart the server once we're able to generate the network parameters - applyNetworkParametersAndStart(setNetParams) - }, - rootCert = rootCaCert - ) - internalDriver( - portAllocation = portAllocation, - compatibilityZone = compatibilityZone, - initialiseSerialization = false, - notarySpecs = listOf(NotarySpec(notaryName)), - extraCordappPackagesToScan = listOf("net.corda.finance"), - notaryCustomOverrides = mapOf("devMode" to false) - ) { - val (alice, notary) = listOf( - startNode(providedName = aliceName, customOverrides = mapOf("devMode" to false)), - defaultNotaryNode - ).map { it.getOrThrow() as NodeHandleInternal } - - alice.onlySeesFromNetworkMap(alice, notary) - notary.onlySeesFromNetworkMap(alice, notary) - - val genevieve = startNode(providedName = genevieveName, customOverrides = mapOf("devMode" to false)).getOrThrow() as NodeHandleInternal - - // Wait for the nodes to poll again - Thread.sleep(timeoutMillis * 2) - - // Make sure the new node is visible to everyone - alice.onlySeesFromNetworkMap(alice, genevieve, notary) - notary.onlySeesFromNetworkMap(alice, genevieve, notary) - genevieve.onlySeesFromNetworkMap(alice, genevieve, notary) - - // Check the nodes can communicate among themselves (and the notary). - val anonymous = false - genevieve.rpc.startFlow( - ::CashIssueAndPaymentFlow, - 1000.DOLLARS, - OpaqueBytes.of(12), - alice.nodeInfo.singleIdentity(), - anonymous, - defaultNotaryIdentity - ).returnValue.getOrThrow() - } - } - - private fun NodeHandleInternal.onlySeesFromNetworkMap(vararg nodes: NodeHandle) { - // Make sure the nodes aren't getting the node infos from their additional directories - val nodeInfosDir = configuration.baseDirectory / CordformNode.NODE_INFO_DIRECTORY - if (nodeInfosDir.exists()) { - assertThat(nodeInfosDir.list { it.toList() }).isEmpty() - } - assertThat(rpc.networkMapSnapshot()).containsOnlyElementsOf(nodes.map { it.nodeInfo }) - } - - private fun startServer(startNetworkMap: Boolean = true): NetworkManagementServer { - val server = NetworkManagementServer(makeTestDataSourceProperties(DOORMAN_DB_NAME, dbNamePostfix, configSupplier = configSupplierForSupportedDatabases(), fallBackConfigSupplier = ::networkMapInMemoryH2DataSourceConfig), - makeTestDatabaseProperties(DOORMAN_DB_NAME, configSupplier = configSupplierForSupportedDatabases()), doormanConfig, revocationConfig) - server.start( - serverAddress, - CertPathAndKey(listOf(doormanCa.certificate, rootCaCert), doormanCa.keyPair.private), - if (startNetworkMap) { - NetworkMapStartParams( - LocalSigner(networkMapCa), - NetworkMapConfig(cacheTimeout = timeoutMillis, signInterval = timeoutMillis) - ) - } else { - null - } - ) - return server - } - - private fun applyNetworkParametersAndStart(networkParametersCmd: NetworkParametersCmd) { - server?.close() - NetworkManagementServer(makeTestDataSourceProperties(DOORMAN_DB_NAME, dbNamePostfix, configSupplier = configSupplierForSupportedDatabases(), fallBackConfigSupplier = ::networkMapInMemoryH2DataSourceConfig), - makeTestDatabaseProperties(DOORMAN_DB_NAME, configSupplier = configSupplierForSupportedDatabases()), doormanConfig, revocationConfig).use { - it.netParamsUpdateHandler.processNetworkParameters(networkParametersCmd) - } - server = startServer(startNetworkMap = true) - // Wait for server to process the parameters update and for the nodes to poll again - Thread.sleep(timeoutMillis * 2) - } -} 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 deleted file mode 100644 index fc25d27ac5..0000000000 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmAuthenticatorTest.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm - -import com.r3.corda.networkmanage.common.HsmBaseTest -import com.r3.corda.networkmanage.hsm.authentication.Authenticator -import com.r3.corda.networkmanage.hsm.authentication.createProvider -import org.junit.Test -import java.util.concurrent.atomic.AtomicBoolean -import kotlin.test.assertTrue - -class HsmAuthenticatorTest : HsmBaseTest() { - - @Test - fun `Authenticator executes the block once user is successfully authenticated`() { - // given - val userInput = givenHsmUserAuthenticationInput() - val hsmSigningServiceConfig = createHsmSigningServiceConfig(createDoormanCertificateConfig(), null) - val doormanCertificateConfig = hsmSigningServiceConfig.doorman!! - val authenticator = Authenticator(provider = createProvider( - doormanCertificateConfig.keyGroup, - hsmSigningServiceConfig.keySpecifier, - hsmSigningServiceConfig.device), inputReader = userInput) - val executed = AtomicBoolean(false) - - // when - authenticator.connectAndAuthenticate { _, _ -> executed.set(true) } - - // then - assertTrue(executed.get()) - } -} \ No newline at end of file diff --git a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmEmptyCrlGenerationTest.kt b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmEmptyCrlGenerationTest.kt deleted file mode 100644 index 2159eb8c43..0000000000 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmEmptyCrlGenerationTest.kt +++ /dev/null @@ -1,137 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm - -import com.nhaarman.mockito_kotlin.any -import com.nhaarman.mockito_kotlin.mock -import com.nhaarman.mockito_kotlin.whenever -import com.r3.corda.networkmanage.common.HsmBaseTest -import com.r3.corda.networkmanage.hsm.authentication.InputReader -import com.r3.corda.networkmanage.hsm.generator.AutoAuthenticator -import com.r3.corda.networkmanage.hsm.generator.UserAuthenticationParameters -import com.r3.corda.networkmanage.hsm.generator.crl.CrlConfig -import com.r3.corda.networkmanage.hsm.generator.crl.GeneratorConfig -import com.r3.corda.networkmanage.hsm.generator.crl.RevocationConfig -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities -import net.corda.nodeapi.internal.crypto.CertificateType -import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA -import org.apache.commons.io.FileUtils -import org.junit.Before -import org.junit.Test -import java.net.URL -import java.security.cert.CertificateFactory -import java.security.cert.X509CRL -import java.security.cert.X509Certificate -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertTrue -import com.r3.corda.networkmanage.hsm.generator.certificate.run as runCertificateGeneration -import com.r3.corda.networkmanage.hsm.generator.crl.run as runCrlGeneration - -class HsmEmptyCrlGenerationTest : HsmBaseTest() { - - private lateinit var inputReader: InputReader - - @Before - override fun setUp() { - super.setUp() - inputReader = mock() - whenever(inputReader.readLine()).thenReturn(hsmSimulator.cryptoUserCredentials().username) - whenever(inputReader.readPassword(any())).thenReturn(hsmSimulator.cryptoUserCredentials().password) - } - - @Test - fun `An empty CRL is generated`() { - // when root cert is created - runCertificateGeneration(createGeneratorParameters( - keyGroup = ROOT_CERT_KEY_GROUP, - rootKeyGroup = null, - certificateType = CertificateType.ROOT_CA, - subject = ROOT_CERT_SUBJECT - )) - - // then root cert is persisted in the HSM - AutoAuthenticator(createProviderConfig(ROOT_CERT_KEY_GROUP), HSM_USER_CONFIGS).connectAndAuthenticate { provider -> - val keyStore = HsmX509Utilities.getAndInitializeKeyStore(provider) - val rootCert = keyStore.getCertificate(CORDA_ROOT_CA) as X509Certificate - assertEquals(rootCert.issuerX500Principal, rootCert.subjectX500Principal) - } - - val generatedFile = tempFolder.newFile() - runCrlGeneration(createCrlGeneratorParameters(CrlConfig( - crlEndpoint = URL("http://test.com/crl"), - filePath = generatedFile.toPath(), - keyGroup = ROOT_CERT_KEY_GROUP, - keySpecifier = 1, - validDays = 1000, - indirectIssuer = true, - revocations = emptyList()), HSM_ROOT_USER_CONFIGS)) - val crl = CertificateFactory.getInstance("X.509") - .generateCRL(FileUtils.readFileToByteArray(generatedFile).inputStream()) as X509CRL - assertNotNull(crl) - assertEquals(ROOT_CERT_SUBJECT, crl.issuerDN.name) - assertTrue { crl.revokedCertificates.isEmpty() } - } - - @Test - fun `A non-empty CRL is generated`() { - // when root cert is created - runCertificateGeneration(createGeneratorParameters( - keyGroup = ROOT_CERT_KEY_GROUP, - rootKeyGroup = null, - certificateType = CertificateType.ROOT_CA, - subject = ROOT_CERT_SUBJECT - )) - - // then root cert is persisted in the HSM - AutoAuthenticator(createProviderConfig(ROOT_CERT_KEY_GROUP), HSM_USER_CONFIGS).connectAndAuthenticate { provider -> - val keyStore = HsmX509Utilities.getAndInitializeKeyStore(provider) - val rootCert = keyStore.getCertificate(CORDA_ROOT_CA) as X509Certificate - assertEquals(rootCert.issuerX500Principal, rootCert.subjectX500Principal) - } - - val generatedFile = tempFolder.newFile() - val revokedSerialNumber = "1234567890" - runCrlGeneration(createCrlGeneratorParameters(CrlConfig( - crlEndpoint = URL("http://test.com/crl"), - filePath = generatedFile.toPath(), - keyGroup = ROOT_CERT_KEY_GROUP, - keySpecifier = 1, - validDays = 1000, - indirectIssuer = false, - revocations = listOf( - RevocationConfig( - certificateSerialNumber = "1234567890", - dateInMillis = 0, - reason = "KEY_COMPROMISE" - ) - )), HSM_ROOT_USER_CONFIGS)) - val crl = CertificateFactory.getInstance("X.509") - .generateCRL(FileUtils.readFileToByteArray(generatedFile).inputStream()) as X509CRL - assertNotNull(crl) - assertEquals(ROOT_CERT_SUBJECT, crl.issuerDN.name) - assertEquals(1, crl.revokedCertificates.size) - val revoked = crl.revokedCertificates.first() - assertEquals(revoked.serialNumber.toString(), revokedSerialNumber) - } - - private fun createCrlGeneratorParameters(crlConfg: CrlConfig, - userConfigs: List): GeneratorConfig { - return GeneratorConfig( - hsmHost = hsmSimulator.host, - hsmPort = hsmSimulator.port, - trustStoreFile = rootKeyStoreFile, - trustStorePassword = TRUSTSTORE_PASSWORD, - userConfigs = userConfigs, - crl = crlConfg - ) - } -} \ No newline at end of file diff --git a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmKeyGenerationTest.kt b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmKeyGenerationTest.kt deleted file mode 100644 index b7144f9e80..0000000000 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmKeyGenerationTest.kt +++ /dev/null @@ -1,95 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm - -import com.nhaarman.mockito_kotlin.any -import com.nhaarman.mockito_kotlin.mock -import com.nhaarman.mockito_kotlin.whenever -import com.r3.corda.networkmanage.common.HsmBaseTest -import com.r3.corda.networkmanage.common.utils.CORDA_NETWORK_MAP -import com.r3.corda.networkmanage.hsm.authentication.InputReader -import com.r3.corda.networkmanage.hsm.generator.AutoAuthenticator -import com.r3.corda.networkmanage.hsm.generator.certificate.run -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities -import net.corda.core.identity.CordaX500Name -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 org.junit.Before -import org.junit.Test -import java.security.cert.X509Certificate -import kotlin.test.assertEquals -import kotlin.test.assertNotNull - -class HsmKeyGenerationTest : HsmBaseTest() { - - private lateinit var inputReader: InputReader - - @Before - override fun setUp() { - super.setUp() - inputReader = mock() - whenever(inputReader.readLine()).thenReturn(hsmSimulator.cryptoUserCredentials().username) - whenever(inputReader.readPassword(any())).thenReturn(hsmSimulator.cryptoUserCredentials().password) - } - - @Test - fun `Root and network map certificates have different namespace`() { - // when root cert is created - run(createGeneratorParameters( - keyGroup = ROOT_CERT_KEY_GROUP, - rootKeyGroup = null, - certificateType = CertificateType.ROOT_CA, - subject = ROOT_CERT_SUBJECT - )) - // when network map cert is created - run(createGeneratorParameters( - keyGroup = NETWORK_MAP_CERT_KEY_GROUP, - rootKeyGroup = ROOT_CERT_KEY_GROUP, - certificateType = CertificateType.NETWORK_MAP, - subject = NETWORK_MAP_CERT_SUBJECT - )) - // when doorman cert is created - run(createGeneratorParameters( - keyGroup = DOORMAN_CERT_KEY_GROUP, - rootKeyGroup = ROOT_CERT_KEY_GROUP, - certificateType = CertificateType.INTERMEDIATE_CA, - subject = DOORMAN_CERT_SUBJECT - )) - - // then root cert is persisted in the HSM - AutoAuthenticator(createProviderConfig(ROOT_CERT_KEY_GROUP), HSM_USER_CONFIGS).connectAndAuthenticate { provider -> - val keyStore = HsmX509Utilities.getAndInitializeKeyStore(provider) - val rootCert = keyStore.getCertificate(CORDA_ROOT_CA) as X509Certificate - assertEquals(rootCert.issuerX500Principal, rootCert.subjectX500Principal) - } - - // then network map cert is persisted in the HSM - - AutoAuthenticator(createProviderConfig(NETWORK_MAP_CERT_KEY_GROUP), HSM_USER_CONFIGS) - .connectAndAuthenticate { provider -> - val keyStore = HsmX509Utilities.getAndInitializeKeyStore(provider) - val networkMapCert = keyStore.getCertificate(CORDA_NETWORK_MAP) as X509Certificate - assertNotNull(networkMapCert) - assertEquals(CordaX500Name.parse(ROOT_CERT_SUBJECT).x500Principal, networkMapCert.issuerX500Principal) - } - - // then doorman cert is persisted in the HSM - - AutoAuthenticator(createProviderConfig(DOORMAN_CERT_KEY_GROUP), HSM_USER_CONFIGS) - .connectAndAuthenticate { provider -> - val keyStore = HsmX509Utilities.getAndInitializeKeyStore(provider) - val networkMapCert = keyStore.getCertificate(CORDA_INTERMEDIATE_CA) as X509Certificate - assertNotNull(networkMapCert) - assertEquals(CordaX500Name.parse(ROOT_CERT_SUBJECT).x500Principal, networkMapCert.issuerX500Principal) - } - } -} \ No newline at end of file diff --git a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmPermissionTest.kt b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmPermissionTest.kt deleted file mode 100644 index 523e5e4e26..0000000000 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmPermissionTest.kt +++ /dev/null @@ -1,174 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm - -import com.nhaarman.mockito_kotlin.mock -import com.r3.corda.networkmanage.common.HsmBaseTest -import com.r3.corda.networkmanage.hsm.authentication.Authenticator -import com.r3.corda.networkmanage.hsm.authentication.createProvider -import com.r3.corda.networkmanage.hsm.generator.UserAuthenticationParameters -import com.r3.corda.networkmanage.hsm.generator.certificate.run -import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData -import com.r3.corda.networkmanage.hsm.signer.HsmCsrSigner -import net.corda.core.crypto.Crypto.generateKeyPair -import net.corda.core.identity.CordaX500Name.Companion.parse -import net.corda.nodeapi.internal.crypto.CertificateType -import net.corda.nodeapi.internal.crypto.X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME -import net.corda.nodeapi.internal.crypto.X509Utilities.createCertificateSigningRequest -import org.junit.Test -import java.security.GeneralSecurityException -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith -import kotlin.test.assertNotNull - -class HsmPermissionTest : HsmBaseTest() { - - /** - * This test case scenario reflects the issue observed on 02.02.2018, when permissions user CXI_GROUP permissions - * were wrongly configured on the PROD HSM box. - * - * Key groups are as follows: - * "TEST.CORDACONNECT.ROOT" - * "TEST.CORDACONNECT.OPS.NETMAP" - * "TEST.CORDACONNECT.OPS.CERT" - * - * User CXI_GROUP configurations are as follows: - * Root cert creator: TEST.CORDACONNECT.* - * Doorman cert creator: TEST.CORDACONNECT.* - * Networkmap cert creator: TEST.CORDACONNECT.* - * - * CSR signing user CXI_GROUP is as follows: - * TEST.CORDACONNECT.OPS.CERT.* - */ - @Test - fun `HSM signing service cannot sign CSR data when HSM user CXI_GROUP permissions are wrongly configured`() { - // given certs created - givenCertificatesCreated(HSM_SUPER__USER_CONFIGS, HSM_SUPER__USER_CONFIGS, HSM_SUPER__USER_CONFIGS) - // given authenticated user - val userInput = givenHsmUserAuthenticationInput(HSM_USERNAME_OPS_CERT_) - - // given HSM CSR signer - val hsmSigningServiceConfig = createHsmSigningServiceConfig(createDoormanCertificateConfig(), null) - val signer = HsmCsrSigner( - mock(), - hsmSigningServiceConfig.doorman!!.loadRootKeyStore(), - "", - null, - 3650, - Authenticator( - provider = createProvider( - hsmSigningServiceConfig.doorman!!.keyGroup, - hsmSigningServiceConfig.keySpecifier, - hsmSigningServiceConfig.device), - inputReader = userInput) - ) - - // give random data to sign - val toSign = ApprovedCertificateRequestData( - "test", - createCertificateSigningRequest( - parse("O=R3Cev,L=London,C=GB").x500Principal, - "my@mail.com", - generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME))) - - // then - // The GeneralSecurityException is thrown by the JCE layer. - // This exception is caused by the CryptoServerException with code B0680001 - permission denied. - assertFailsWith(GeneralSecurityException::class) { - signer.sign(listOf(toSign)) - } - } - - /** - * This test case scenario reflects the fix for the issue observed on 02.02.2018, when permissions user CXI_GROUP permissions - * were wrongly configured on the PROD HSM box. - * - * Key groups are as follows: - * "TEST.CORDACONNECT.ROOT" - * "TEST.CORDACONNECT.OPS.NETMAP" - * "TEST.CORDACONNECT.OPS.CERT" - * - * User CXI_GROUP configurations are as follows: - * Root cert creator: TEST.CORDACONNECT.* - * Doorman cert creator: TEST.CORDACONNECT.* - * Networkmap cert creator: TEST.CORDACONNECT.* - * - * CSR signing user CXI_GROUP is as follows: - * TEST.CORDACONNECT.OPS.CERT - */ - @Test - fun `HSM signing service signs CSR data when HSM user CXI_GROUP permissions are correctly configured`() { - // given certs created - givenCertificatesCreated(HSM_SUPER__USER_CONFIGS, HSM_SUPER__USER_CONFIGS, HSM_SUPER__USER_CONFIGS) - // given authenticated user - val userInput = givenHsmUserAuthenticationInput(HSM_USERNAME_OPS_CERT) - - // given HSM CSR signer - val hsmSigningServiceConfig = createHsmSigningServiceConfig(createDoormanCertificateConfig(), null) - val signer = HsmCsrSigner( - mock(), - hsmSigningServiceConfig.doorman!!.loadRootKeyStore(), - "trustpass", - null, - 3650, - Authenticator( - provider = createProvider( - hsmSigningServiceConfig.doorman!!.keyGroup, - hsmSigningServiceConfig.keySpecifier, - hsmSigningServiceConfig.device), - inputReader = userInput) - ) - - // give random data to sign - val toSign = ApprovedCertificateRequestData( - "test", - createCertificateSigningRequest( - parse("O=R3Cev,L=London,C=GB").x500Principal, - "my@mail.com", - generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME))) - - // when - signer.sign(listOf(toSign)) - - // then - assertNotNull(toSign.certPath) - val certificates = toSign.certPath!!.certificates - assertEquals(3, certificates.size) - } - - private fun givenCertificatesCreated(rootCertUserConfigs: List, - doormanCertUserConfigs: List, - netMapCertUserConfigs: List) { - // when root cert is created - run(createGeneratorParameters( - keyGroup = ROOT_CERT_KEY_GROUP, - rootKeyGroup = null, - certificateType = CertificateType.ROOT_CA, - subject = ROOT_CERT_SUBJECT, - hsmUserConfigs = rootCertUserConfigs)) - // when network map cert is created - run(createGeneratorParameters( - keyGroup = NETWORK_MAP_CERT_KEY_GROUP, - rootKeyGroup = ROOT_CERT_KEY_GROUP, - certificateType = CertificateType.NETWORK_MAP, - subject = NETWORK_MAP_CERT_SUBJECT, - hsmUserConfigs = netMapCertUserConfigs - )) - // when doorman cert is created - run(createGeneratorParameters( - keyGroup = DOORMAN_CERT_KEY_GROUP, - rootKeyGroup = ROOT_CERT_KEY_GROUP, - certificateType = CertificateType.INTERMEDIATE_CA, - subject = DOORMAN_CERT_SUBJECT, - hsmUserConfigs = doormanCertUserConfigs - )) - } -} \ No newline at end of file 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 deleted file mode 100644 index 77fe191a34..0000000000 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/HsmSigningServiceTest.kt +++ /dev/null @@ -1,198 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm - -import com.nhaarman.mockito_kotlin.mock -import com.r3.corda.networkmanage.common.HsmBaseTest -import com.r3.corda.networkmanage.common.persistence.PersistentNetworkMapStorage -import com.r3.corda.networkmanage.common.persistence.configureDatabase -import com.r3.corda.networkmanage.common.signer.NetworkMapSigner -import com.r3.corda.networkmanage.common.utils.CORDA_NETWORK_MAP -import com.r3.corda.networkmanage.common.utils.initialiseSerialization -import com.r3.corda.networkmanage.hsm.authentication.Authenticator -import com.r3.corda.networkmanage.hsm.authentication.createProvider -import com.r3.corda.networkmanage.hsm.generator.certificate.run -import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData -import com.r3.corda.networkmanage.hsm.signer.HsmCsrSigner -import com.r3.corda.networkmanage.hsm.signer.HsmSigner -import net.corda.core.crypto.Crypto.generateKeyPair -import net.corda.core.identity.CordaX500Name.Companion.parse -import net.corda.core.internal.CertRole -import net.corda.core.serialization.serialize -import net.corda.nodeapi.internal.crypto.CertificateType -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.crypto.x509 -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.assertNotEquals -import kotlin.test.assertNotNull - -class HsmSigningServiceTest : HsmBaseTest() { - @Before - override fun setUp() { - super.setUp() - loadOrCreateKeyStore(rootKeyStoreFile, TRUSTSTORE_PASSWORD) - } - - @Test - fun `HSM signing service can sign node CSR data`() { - setupCertificates() - - // given authenticated user - val userInput = givenHsmUserAuthenticationInput() - - // given HSM CSR signer - val hsmSigningServiceConfig = createHsmSigningServiceConfig(createDoormanCertificateConfig(), null) - val doormanCertificateConfig = hsmSigningServiceConfig.doorman!! - val signer = HsmCsrSigner( - mock(), - doormanCertificateConfig.loadRootKeyStore(), - "", - null, - 3650, - Authenticator( - provider = createProvider( - doormanCertificateConfig.keyGroup, - hsmSigningServiceConfig.keySpecifier, - hsmSigningServiceConfig.device), - inputReader = userInput) - ) - - // give random data to sign - val toSign = ApprovedCertificateRequestData( - "test", - createCertificateSigningRequest( - parse("O=R3Cev,L=London,C=GB").x500Principal, - "my@mail.com", - generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME))) - - // when - signer.sign(listOf(toSign)) - - // then - assertNotNull(toSign.certPath) - val certificates = toSign.certPath!!.certificates - assertEquals(3, certificates.size) - // Is a CA - assertNotEquals(-1, certificates.first().x509.basicConstraints) - assertEquals(CertRole.NODE_CA, CertRole.extract(certificates.first().x509)) - } - - @Test - fun `HSM signing service can sign service identity CSR data`() { - setupCertificates() - - // given authenticated user - val userInput = givenHsmUserAuthenticationInput() - - // given HSM CSR signer - val hsmSigningServiceConfig = createHsmSigningServiceConfig(createDoormanCertificateConfig(), null) - val doormanCertificateConfig = hsmSigningServiceConfig.doorman!! - val signer = HsmCsrSigner( - mock(), - doormanCertificateConfig.loadRootKeyStore(), - "", - null, - 3650, - Authenticator( - provider = createProvider( - doormanCertificateConfig.keyGroup, - hsmSigningServiceConfig.keySpecifier, - hsmSigningServiceConfig.device), - inputReader = userInput) - ) - - // give random data to sign - val toSign = ApprovedCertificateRequestData( - "test", - createCertificateSigningRequest( - parse("O=R3Cev,L=London,C=GB").x500Principal, - "my@mail.com", - generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME), - certRole = CertRole.SERVICE_IDENTITY)) - - // when - signer.sign(listOf(toSign)) - - // then - assertNotNull(toSign.certPath) - val certificates = toSign.certPath!!.certificates - assertEquals(3, certificates.size) - // Not a CA - assertEquals(-1, certificates.first().x509.basicConstraints) - assertEquals(CertRole.SERVICE_IDENTITY, CertRole.extract(certificates.first().x509)) - } - - @Test - fun `HSM signing service can sign and serialize network map data to the Doorman DB`() { - setupCertificates() - - // given authenticated user - val userInput = givenHsmUserAuthenticationInput() - - // given HSM network map signer - val hsmSigningServiceConfig = createHsmSigningServiceConfig(null, createNetworkMapCertificateConfig()) - val networkMapCertificateConfig = hsmSigningServiceConfig.networkMap!! - val hsmDataSigner = HsmSigner(Authenticator( - provider = createProvider( - networkMapCertificateConfig.keyGroup, - hsmSigningServiceConfig.keySpecifier, - hsmSigningServiceConfig.device), - inputReader = userInput), - keyName = CORDA_NETWORK_MAP) - - val database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties()) - val networkMapStorage = PersistentNetworkMapStorage(database) - - // given network map parameters - val networkMapParameters = testNetworkParameters(emptyList()) - val networkMapSigner = NetworkMapSigner(networkMapStorage, hsmDataSigner) - - // when - initialiseSerialization() - networkMapStorage.saveNetworkParameters(networkMapParameters, hsmDataSigner.signBytes(networkMapParameters.serialize().bytes)) - networkMapSigner.signNetworkMaps() - - // then - val persistedNetworkMap = networkMapStorage.getNetworkMaps().publicNetworkMap!!.toSignedNetworkMap().verified() - assertEquals(networkMapParameters.serialize().hash, persistedNetworkMap.networkParameterHash) - assertThat(persistedNetworkMap.nodeInfoHashes).isEmpty() - } - - private fun setupCertificates() { - // when root cert is created - run(createGeneratorParameters( - keyGroup = ROOT_CERT_KEY_GROUP, - rootKeyGroup = null, - certificateType = CertificateType.ROOT_CA, - subject = ROOT_CERT_SUBJECT - )) - // when network map cert is created - run(createGeneratorParameters( - keyGroup = NETWORK_MAP_CERT_KEY_GROUP, - rootKeyGroup = ROOT_CERT_KEY_GROUP, - certificateType = CertificateType.NETWORK_MAP, - subject = NETWORK_MAP_CERT_SUBJECT - )) - // when doorman cert is created - run(createGeneratorParameters( - keyGroup = DOORMAN_CERT_KEY_GROUP, - rootKeyGroup = ROOT_CERT_KEY_GROUP, - certificateType = CertificateType.INTERMEDIATE_CA, - subject = DOORMAN_CERT_SUBJECT - )) - } -} \ No newline at end of file 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 deleted file mode 100644 index db7d13bdb4..0000000000 --- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/hsm/SigningServiceIntegrationTest.kt +++ /dev/null @@ -1,189 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm - -import com.nhaarman.mockito_kotlin.* -import com.r3.corda.networkmanage.common.* -import com.r3.corda.networkmanage.common.persistence.configureDatabase -import com.r3.corda.networkmanage.doorman.CertificateRevocationConfig -import com.r3.corda.networkmanage.doorman.DoormanConfig -import com.r3.corda.networkmanage.doorman.NetworkManagementServer -import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData -import com.r3.corda.networkmanage.hsm.persistence.DBSignedCertificateRequestStorage -import com.r3.corda.networkmanage.hsm.persistence.SignedCertificateSigningRequestStorage -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 -import net.corda.core.internal.uncheckedCast -import net.corda.core.utilities.seconds -import net.corda.node.NodeRegistrationOption -import net.corda.node.services.config.NodeConfiguration -import net.corda.node.utilities.registration.HTTPNetworkRegistrationService -import net.corda.node.utilities.registration.NodeRegistrationHelper -import net.corda.nodeapi.internal.createDevNodeCa -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import net.corda.nodeapi.internal.crypto.X509KeyStore -import net.corda.nodeapi.internal.crypto.X509Utilities -import net.corda.testing.core.ALICE_NAME -import net.corda.testing.core.SerializationEnvironmentRule -import net.corda.testing.driver.PortAllocation -import net.corda.testing.internal.createDevIntermediateCaCertPath -import net.corda.testing.internal.rigorousMock -import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import java.net.URL -import java.nio.file.Path -import java.security.cert.X509Certificate -import java.util.* -import javax.persistence.PersistenceException -import kotlin.concurrent.scheduleAtFixedRate - -class SigningServiceIntegrationTest : HsmBaseTest() { - - @Rule - @JvmField - val testSerialization = SerializationEnvironmentRule(true) - - private val portAllocation = PortAllocation.Incremental(10000) - private val serverAddress = portAllocation.nextHostAndPort() - - private lateinit var timer: Timer - private lateinit var rootCaCert: X509Certificate - private lateinit var intermediateCa: CertificateAndKeyPair - private val timeoutMillis = 5.seconds.toMillis() - - private lateinit var dbName: String - - private val doormanConfig: DoormanConfig get() = DoormanConfig(approveAll = true, approveInterval = 2.seconds.toMillis(), jira = null) - private lateinit var revocationConfig: CertificateRevocationConfig - - private fun createCertificateRevocationConfig(emptyCrlPath: Path, caCrlPath: Path): CertificateRevocationConfig { - return CertificateRevocationConfig( - approveAll = true, - jira = null, - approveInterval = timeoutMillis, - crlCacheTimeout = timeoutMillis, - localSigning = CertificateRevocationConfig.LocalSigning( - crlEndpoint = getNodeCrlEndpoint(serverAddress), - crlUpdateInterval = timeoutMillis), - emptyCrlPath = emptyCrlPath, - caCrlPath = caCrlPath) - } - - @Before - override fun setUp() { - super.setUp() - dbName = random63BitValue().toString() - timer = Timer() - val (rootCa, intermediateCa) = createDevIntermediateCaCertPath() - rootCaCert = rootCa.certificate - this.intermediateCa = intermediateCa - val (caCrlPath, emptyCrlPath) = generateEmptyCrls(tempFolder, rootCa, getCaCrlEndpoint(serverAddress), getEmptyCrlEndpoint(serverAddress)) - revocationConfig = createCertificateRevocationConfig(emptyCrlPath, caCrlPath) - } - - @After - override fun tearDown() { - super.tearDown() - timer.cancel() - } - - private fun givenSignerSigningAllRequests(storage: SignedCertificateSigningRequestStorage): HsmCsrSigner { - // Mock signing logic but keep certificate persistence - return mock { - on { sign(any()) }.then { - val approvedRequests: List = uncheckedCast(it.arguments[0]) - for (approvedRequest in approvedRequests) { - JcaPKCS10CertificationRequest(approvedRequest.request).run { - val nodeCa = createDevNodeCa(intermediateCa, CordaX500Name.parse(subject.toString())) - approvedRequest.certPath = X509Utilities.buildCertPath(nodeCa.certificate, intermediateCa.certificate, rootCaCert) - } - } - storage.store(approvedRequests, "TEST") - } - } - } - - @Test - fun `Signing service signs approved CSRs`() { - //Start doorman server - NetworkManagementServer(makeTestDataSourceProperties(), makeTestDatabaseProperties(), doormanConfig, revocationConfig).use { server -> - server.start( - hostAndPort = serverAddress, - csrCertPathAndKey = null, - startNetworkMap = null) - val doormanHostAndPort = server.hostAndPort - // Start Corda network registration. - val config = createConfig().also { - doReturn(ALICE_NAME).whenever(it).myLegalName - doReturn(URL("http://${doormanHostAndPort.host}:${doormanHostAndPort.port}")).whenever(it).compatibilityZoneURL - } - val signingServiceStorage = DBSignedCertificateRequestStorage(configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties())) - - val hsmSigner = givenSignerSigningAllRequests(signingServiceStorage) - // Poll the database for approved requests - timer.scheduleAtFixedRate(0, 1.seconds.toMillis()) { - // The purpose of this tests is to validate the communication between this service and Doorman - // by the means of data in the shared database. - // Therefore the HSM interaction logic is mocked here. - try { - val approved = signingServiceStorage.getApprovedRequests() - if (approved.isNotEmpty()) { - hsmSigner.sign(approved) - timer.cancel() - } - } catch (exception: PersistenceException) { - // It may happen that Doorman DB is not created at the moment when the signing service polls it. - // This is due to the fact that schema is initialized at the time first hibernate session is established. - // Since Doorman does this at the time the first CSR arrives, which in turn happens after signing service - // startup, the very first iteration of the signing service polling fails with - // [org.hibernate.tool.schema.spi.SchemaManagementException] being thrown as the schema is missing. - } - } - config.certificatesDirectory.createDirectories() - val networkTrustStorePath = config.certificatesDirectory / "network-root-truststore.jks" - val networkTrustStorePassword = "network-trust-password" - val networkTrustStore = X509KeyStore.fromFile(networkTrustStorePath, networkTrustStorePassword, createNew = true) - networkTrustStore.update { - setCertificate(X509Utilities.CORDA_ROOT_CA, rootCaCert) - } - val trustStore = X509KeyStore.fromFile(config.trustStoreFile, config.trustStorePassword, createNew = true) - val nodeKeyStore = X509KeyStore.fromFile(config.nodeKeystore, config.keyStorePassword, createNew = true) - val sslKeyStore = X509KeyStore.fromFile(config.sslKeystore, config.keyStorePassword, createNew = true) - config.also { - doReturn(trustStore).whenever(it).loadTrustStore(any()) - doReturn(nodeKeyStore).whenever(it).loadNodeKeyStore(any()) - doReturn(sslKeyStore).whenever(it).loadSslKeyStore(any()) - } - val regConfig = NodeRegistrationOption(networkTrustStorePath, networkTrustStorePassword) - NodeRegistrationHelper(config, HTTPNetworkRegistrationService(config.compatibilityZoneURL!!), regConfig).buildKeystore() - verify(hsmSigner).sign(any()) - } - } - - private fun createConfig(): NodeConfiguration { - return rigorousMock().also { - doReturn(tempFolder.root.toPath()).whenever(it).baseDirectory - doReturn(it.baseDirectory / "certificates").whenever(it).certificatesDirectory - doReturn(it.certificatesDirectory / "truststore.jks").whenever(it).trustStoreFile - doReturn(it.certificatesDirectory / "nodekeystore.jks").whenever(it).nodeKeystore - doReturn(it.certificatesDirectory / "sslkeystore.jks").whenever(it).sslKeystore - doReturn("trustpass").whenever(it).trustStorePassword - doReturn("cordacadevpass").whenever(it).keyStorePassword - doReturn("iTest@R3.com").whenever(it).emailAddress - } - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/configuration/ConfigFilePathArgsParser.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/configuration/ConfigFilePathArgsParser.kt deleted file mode 100644 index 1df0e4a504..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/configuration/ConfigFilePathArgsParser.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.r3.corda.networkmanage.common.configuration - -import com.r3.corda.networkmanage.common.utils.ArgsParser -import joptsimple.OptionSet -import joptsimple.util.PathConverter -import joptsimple.util.PathProperties -import java.nio.file.Path - -/** - * Parses key generator command line options. - */ -class ConfigFilePathArgsParser : ArgsParser() { - private val configFileArg = optionParser - .accepts("config-file", "The path to the config file") - .withRequiredArg() - .required() - .describedAs("filepath") - .withValuesConvertedBy(PathConverter(PathProperties.FILE_EXISTING)) - - override fun parse(optionSet: OptionSet): Path { - return optionSet.valueOf(configFileArg).toAbsolutePath() - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/ApproveAllCertificateRevocationRequestStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/ApproveAllCertificateRevocationRequestStorage.kt deleted file mode 100644 index c7db99060a..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/ApproveAllCertificateRevocationRequestStorage.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationRequestStorage.Companion.DOORMAN_SIGNATURE -import net.corda.nodeapi.internal.network.CertificateRevocationRequest - -/** - * This storage automatically approves all created requests. - */ -class ApproveAllCertificateRevocationRequestStorage(private val delegate: CertificateRevocationRequestStorage) : CertificateRevocationRequestStorage by delegate { - - override fun saveRevocationRequest(request: CertificateRevocationRequest): String { - val requestId = delegate.saveRevocationRequest(request) - delegate.markRequestTicketCreated(requestId) - approveRevocationRequest(requestId, DOORMAN_SIGNATURE) - return requestId - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/ApproveAllCertificateSigningRequestStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/ApproveAllCertificateSigningRequestStorage.kt deleted file mode 100644 index c0d10cfae9..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/ApproveAllCertificateSigningRequestStorage.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.r3.corda.networkmanage.common.persistence - -import org.bouncycastle.pkcs.PKCS10CertificationRequest - -/** - * This storage automatically approves all created requests. - */ -class ApproveAllCertificateSigningRequestStorage(private val delegate: CertificateSigningRequestStorage) : CertificateSigningRequestStorage by delegate { - override fun saveRequest(request: PKCS10CertificationRequest): String { - val requestId = delegate.saveRequest(request) - delegate.markRequestTicketCreated(requestId) - approveRequest(requestId, CertificateSigningRequestStorage.DOORMAN_SIGNATURE) - return requestId - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/CertificateRevocationListStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/CertificateRevocationListStorage.kt deleted file mode 100644 index ba4851fee3..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/CertificateRevocationListStorage.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.r3.corda.networkmanage.common.persistence - -import java.security.cert.X509CRL -import java.time.Instant - -/** - * Interface for managing certificate revocation list persistence - */ -interface CertificateRevocationListStorage { - companion object { - val DOORMAN_SIGNATURE = "Doorman-Crl-Signer" - } - - /** - * Retrieves the latest certificate revocation list. - * - * @param crlIssuer CRL issuer CA type. - * @return latest revocation list. - */ - fun getCertificateRevocationList(crlIssuer: CrlIssuer): X509CRL? - - /** - * Persists a new revocation list. Upon saving, statuses - * of the approved revocation requests will automatically change to [RequestStatus.DONE]. - * - * @param crl signed instance of the certificate revocation list. It will be serialized and stored as part of a - * database entity. - * @param crlIssuer CRL issuer CA type. - * @param signedBy who signed this CRL. - * @param revokedAt revocation time. - */ - fun saveCertificateRevocationList(crl: X509CRL, crlIssuer: CrlIssuer, signedBy: String, revokedAt: Instant) -} - -/** - * There are 2 CAs that issue CRLs (i.e. Root CA and Doorman CA). - */ -enum class CrlIssuer { - ROOT, DOORMAN -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/CertificateRevocationRequestStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/CertificateRevocationRequestStorage.kt deleted file mode 100644 index c56d20c99f..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/CertificateRevocationRequestStorage.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.r3.corda.networkmanage.common.persistence - -import net.corda.core.identity.CordaX500Name -import net.corda.core.serialization.CordaSerializable -import net.corda.nodeapi.internal.network.CertificateRevocationRequest -import java.math.BigInteger -import java.security.cert.CRLReason -import java.security.cert.X509Certificate -import java.time.Instant - -/** - * This data class is intended to be used internally certificate revocation request service. - */ -@CordaSerializable -data class CertificateRevocationRequestData(val requestId: String, // This is a uniquely generated string - val certificateSigningRequestId: String, - val certificate: X509Certificate, - val certificateSerialNumber: BigInteger, - val modifiedAt: Instant, - val legalName: CordaX500Name, - val status: RequestStatus, - val reason: CRLReason, - val reporter: String) // Username of the reporter - -/** - * Interface for managing certificate revocation requests persistence - */ -interface CertificateRevocationRequestStorage { - companion object { - val DOORMAN_SIGNATURE = "Doorman-Crr-Signer" - } - - /** - * Creates a new revocation request for the given [certificateSerialNumber]. - * The newly created revocation request has the [RequestStatus.NEW] status. - * If the revocation request with the [certificateSerialNumber] already exists and has status - * [RequestStatus.NEW], [RequestStatus.APPROVED] or [RequestStatus.REVOKED] - * then nothing is persisted and the existing revocation request identifier is returned. - * - * @param request certificate revocation request to be stored. - * - * @return identifier of the newly created (or existing) revocation request. - */ - fun saveRevocationRequest(request: CertificateRevocationRequest): String - - /** - * Retrieves the revocation request with the given [requestId] - * - * @param requestId revocation request identifier - * - * @return CertificateRevocationRequest matching the specified identifier. Or null if it doesn't exist. - */ - fun getRevocationRequest(requestId: String): CertificateRevocationRequestData? - - /** - * Retrieves all the revocation requests with the specified revocation request status. - * - * @param revocationStatus revocation request status of the returned revocation requests. - * - * @return list of certificate revocation requests that match the revocation request status. - */ - fun getRevocationRequests(revocationStatus: RequestStatus): List - - /** - * Changes the revocation request status to [RequestStatus.APPROVED]. - * - * @param requestId revocation request identifier - * @param approvedBy who is approving it - */ - fun approveRevocationRequest(requestId: String, approvedBy: String) - - /** - * Changes the revocation request status to [RequestStatus.REJECTED]. - * - * @param requestId revocation request identifier - * @param rejectedBy who is rejecting it - * @param reason description of the reason of this rejection. - */ - fun rejectRevocationRequest(requestId: String, rejectedBy: String, reason: String?) - - /** - * Persist the fact that a ticket has been created for the given [requestId]. - */ - fun markRequestTicketCreated(requestId: String) -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/CertificateSigningRequestStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/CertificateSigningRequestStorage.kt deleted file mode 100644 index c3beeecaa2..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/CertificateSigningRequestStorage.kt +++ /dev/null @@ -1,133 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence - -import net.corda.core.crypto.SecureHash -import net.corda.core.identity.CordaX500Name -import net.corda.core.serialization.CordaSerializable -import org.bouncycastle.pkcs.PKCS10CertificationRequest -import java.security.PublicKey -import java.security.cert.CertPath - -data class CertificateData(val certStatus: CertificateStatus, val certPath: CertPath) - -data class CertificateSigningRequest(val requestId: String, - val legalName: CordaX500Name?, - val publicKeyHash: SecureHash, - val status: RequestStatus, - val request: PKCS10CertificationRequest, - val remark: String?, - val modifiedBy: String, - val certData: CertificateData?) - -/** - * Provide certificate signing request storage for the certificate signing server. - */ -interface CertificateSigningRequestStorage { - companion object { - val DOORMAN_SIGNATURE = "Doorman-Csr-Signer" - } - - /** - * Persist [PKCS10CertificationRequest] in storage for further approval if it's a valid request. - * If not then it will be automatically rejected and not subject to any approval process. - * In both cases a randomly generated request ID is returned. - * @param request request to be stored - */ - fun saveRequest(request: PKCS10CertificationRequest): String - - /** - * Retrieve certificate singing request using [requestId]. - * @return certificate signing request or null if the request does not exist - */ - fun getRequest(requestId: String): CertificateSigningRequest? - - /** - * Retrieve list of certificate signing request based on the [RequestStatus]. - */ - fun getRequests(requestStatus: RequestStatus): List - - /** - * Persist the fact that a ticket has been created for the given [requestId]. - */ - fun markRequestTicketCreated(requestId: String) - - /** - * Approve the given request if it has not already been approved. Otherwise do nothing. - * @param requestId id of the certificate signing request - * @param approvedBy authority (its identifier) approving this request. - */ - // TODO: Merge status changing methods. - fun approveRequest(requestId: String, approvedBy: String) - - /** - * Reject the given request using the given reason. - * @param requestId id of the certificate signing request - * @param rejectedBy authority (its identifier) rejecting this request. - * @param rejectReason brief description of the rejection reason - */ - fun rejectRequest(requestId: String, rejectedBy: String, rejectReason: String?) - - /** - * Store certificate path with [requestId], this will store the encoded [CertPath] and transit request status to [RequestStatus.DONE]. - * @param requestId id of the certificate signing request - * @param certPath chain of certificates starting with the one generated in response to the CSR up to the root. - * @param signedBy authority (its identifier) signing this request. - * @throws IllegalArgumentException if request is not found or not in Approved state. - */ - fun putCertificatePath(requestId: String, certPath: CertPath, signedBy: String) - - /** - * Retrieves the certificate path for the given public key hash if such exists and its certificate is considered to be valid. - * - * @param publicKey public key corresponding to the certificate being searched. - * @return certificate path for the given public key hash or null if such certificate does not exist or is not valid. - */ - fun getValidCertificatePath(publicKey: PublicKey): CertPath? -} - -sealed class CertificateResponse { - object NotReady : CertificateResponse() - data class Ready(val certificatePath: CertPath) : CertificateResponse() - data class Unauthorised(val message: String) : CertificateResponse() -} - -@CordaSerializable -enum class RequestStatus { - /** - * The request has been received, this is the initial state in which a request has been created. - */ - NEW, - - /** - * A ticket has been created but has not yet been approved nor rejected. - */ - TICKET_CREATED, - - /** - * The request has been approved, but not yet signed. - */ - APPROVED, - - /** - * The request has been rejected, this is a terminal state, once a request gets in this state it won't change anymore. - */ - REJECTED, - - /** - * The request has been successfully processed, this is a terminal state, once a request gets in this state it won't change anymore. - */ - DONE -} - -enum class CertificateStatus { - VALID, SUSPENDED, REVOKED -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/NetworkMapStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/NetworkMapStorage.kt deleted file mode 100644 index c7cf8e16b6..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/NetworkMapStorage.kt +++ /dev/null @@ -1,89 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.common.persistence.entity.* -import net.corda.core.crypto.SecureHash -import net.corda.core.internal.DigitalSignatureWithCert -import net.corda.core.node.NetworkParameters -import net.corda.nodeapi.internal.network.NetworkMapAndSigned -import net.corda.nodeapi.internal.network.SignedNetworkParameters -import java.time.Instant - -/** - * Data access object interface for NetworkMap persistence layer - */ -// TODO This storage abstraction needs some thought. Some of the methods clearly don't make sense e.g. setParametersUpdateStatus. -// TODO: We should avoid exposing entity objects. -// The NetworkMapSignerTest uses a mock of this which means we need to provide methods for every trivial db operation. -interface NetworkMapStorage { - /** - * Returns the network maps containing public network map and private network maps. - */ - fun getNetworkMaps(): NetworkMaps - - /** - * Persist the new network map for provided network ID, replacing any existing network map. - * The map will be stored as public network map if [networkId] = null. - */ - fun saveNewNetworkMap(networkId: String? = null, networkMapAndSigned: NetworkMapAndSigned) - - /** - * Retrieves node info hashes for both public and private networks where [NodeInfoEntity.isCurrent] is true and the certificate status is [CertificateStatus.VALID], - * and that were published less than eventHorizon ago. - * Nodes should have declared that they are using correct set of parameters. - */ - fun getNodeInfoHashes(): NodeInfoHashes - - /** - * Retrieve the signed with certificate network parameters by their hash. The hash is that of the underlying - * [NetworkParameters] object and not the [SignedNetworkParameters] object that's returned. - * @return signed network parameters corresponding to the given hash or null if it does not exist (parameters don't exist or they haven't been signed yet) - */ - fun getSignedNetworkParameters(hash: SecureHash): SignedNetworkParameters? - - /** - * Persists given network parameters with signature if provided. - * @return The newly inserted [NetworkParametersEntity] - */ - fun saveNetworkParameters(networkParameters: NetworkParameters, signature: DigitalSignatureWithCert?): NetworkParametersEntity - - /** - * Save new parameters update information with corresponding network parameters. Only one parameters update entity - * can be NEW or FLAG_DAY at any time - if one exists it will be cancelled. - */ - fun saveNewParametersUpdate(networkParameters: NetworkParameters, description: String, updateDeadline: Instant) - - /** - * Retrieves the latest (i.e. most recently inserted) network parameters entity - * Note that they may not have been signed up yet. - * @return latest network parameters entity - */ - fun getLatestNetworkParameters(): NetworkParametersEntity? - - /** Returns the single new or flag day parameters update, or null if there isn't one. */ - fun getCurrentParametersUpdate(): ParametersUpdateEntity? - - fun setParametersUpdateStatus(update: ParametersUpdateEntity, newStatus: UpdateStatus) - - /** - * Perform the switch of parameters on the flagDay. - * 1. Change status of ParametersUpdateEntity to [UpdateStatus.APPLIED] - * 2. Mark all the node infos that didn't accept the update as not current (so they won't be advertised in the network map) - */ - fun switchFlagDay(update: ParametersUpdateEntity) -} - -data class NetworkMaps(val publicNetworkMap: NetworkMapEntity?, val privateNetworkMap: Map) { - val allNodeInfoHashes: Set = privateNetworkMap.flatMap { it.value.networkMap.nodeInfoHashes }.toSet() + (publicNetworkMap?.networkMap?.nodeInfoHashes ?: emptySet()) -} - -data class NodeInfoHashes(val publicNodeInfoHashes: List, val privateNodeInfoHashes: Map>) \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/NodeInfoStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/NodeInfoStorage.kt deleted file mode 100644 index ad4f354ddb..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/NodeInfoStorage.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.common.persistence.entity.ParametersUpdateEntity -import net.corda.core.crypto.SecureHash -import net.corda.core.node.NodeInfo -import net.corda.nodeapi.internal.NodeInfoAndSigned -import net.corda.nodeapi.internal.SignedNodeInfo -import java.security.PublicKey -import java.security.cert.CertPath - -/** - * Data access object interface for NetworkMap/NodeInfo persistence layer - */ -interface NodeInfoStorage { - /** - * Retrieve node certificate path using the node public key hash. - * @return [CertPath] or null if the public key is not registered with the Doorman. - */ - fun getCertificatePath(publicKeyHash: SecureHash): CertPath? - - /** - * Retrieve node info together with its signature using nodeInfo's hash - * @return [NodeInfo] or null if the node info is not registered. - */ - fun getNodeInfo(nodeInfoHash: SecureHash): SignedNodeInfo? - - /** - * Returns the parameters update the node has accepted or null if couldn't find node info with given hash or - * there is no information on accepted parameters update stored for this entity. - */ - fun getAcceptedParametersUpdate(nodeInfoHash: SecureHash): ParametersUpdateEntity? - - /** - * The [nodeInfoAndSigned] is keyed by the public key, old node info with the same public key will be replaced by the new node info. - * If republishing of the same nodeInfo happens, then we will record the time it was republished in the database. - * Based on that information we can remove unresponsive nodes from network (event horizon is the parameter that tells how - * long node can be down before it gets removed). If the nodes becomes active again, it will enter back to the network map - * after republishing its [NodeInfo]. - * @param nodeInfoAndSigned signed node info data to be stored - * @return hash for the newly created node info entry - */ - fun putNodeInfo(nodeInfoAndSigned: NodeInfoAndSigned): SecureHash - - /** - * Store information about latest accepted [NetworkParameters] hash. - * @param publicKey Public key that accepted network parameters. This public key should belong to [NodeInfo] - * @param acceptedParametersHash Hash of latest accepted network parameters. - */ - fun ackNodeInfoParametersUpdate(publicKey: PublicKey, acceptedParametersHash: SecureHash) -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistenceUtils.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistenceUtils.kt deleted file mode 100644 index a74e868ffa..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistenceUtils.kt +++ /dev/null @@ -1,80 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.common.persistence.entity.* -import com.zaxxer.hikari.HikariConfig -import com.zaxxer.hikari.HikariDataSource -import net.corda.core.schemas.MappedSchema -import net.corda.nodeapi.internal.persistence.CordaPersistence -import net.corda.nodeapi.internal.persistence.DatabaseConfig -import net.corda.nodeapi.internal.persistence.DatabaseTransaction -import net.corda.nodeapi.internal.persistence.SchemaMigration -import org.hibernate.Session -import org.hibernate.query.Query -import java.util.* -import javax.persistence.LockModeType -import javax.persistence.criteria.CriteriaBuilder -import javax.persistence.criteria.Path -import javax.persistence.criteria.Predicate - -inline fun Session.fromQuery(query: String): Query { - return createQuery("from ${T::class.java.name} $query", T::class.java) -} - -inline fun DatabaseTransaction.uniqueEntityWhere(predicate: (CriteriaBuilder, Path) -> Predicate): T? { - return entitiesWhere(predicate).setMaxResults(1).uniqueResult() -} - -inline fun DatabaseTransaction.entitiesWhere(predicate: (CriteriaBuilder, Path) -> Predicate): Query { - val builder = session.criteriaBuilder - val criteriaQuery = builder.createQuery(T::class.java) - val query = criteriaQuery.from(T::class.java).run { - criteriaQuery.where(predicate(builder, this)) - } - return session.createQuery(query).setLockMode(LockModeType.PESSIMISTIC_WRITE) -} - -inline fun DatabaseTransaction.deleteEntity(predicate: (CriteriaBuilder, Path) -> Predicate): Int { - val builder = session.criteriaBuilder - val criteriaDelete = builder.createCriteriaDelete(T::class.java) - val delete = criteriaDelete.from(T::class.java).run { - criteriaDelete.where(predicate(builder, this)) - } - return session.createQuery(delete).executeUpdate() -} - -fun configureDatabase(dataSourceProperties: Properties, - databaseConfig: DatabaseConfig = DatabaseConfig()): CordaPersistence { - val config = HikariConfig(dataSourceProperties) - val dataSource = HikariDataSource(config) - - val schemas = setOf(NetworkManagementSchemaServices.SchemaV1) - SchemaMigration(schemas, dataSource, true, databaseConfig).nodeStartup() - - return CordaPersistence(dataSource, databaseConfig, schemas, config.dataSourceProperties.getProperty("url", ""), emptyList()) -} - -sealed class NetworkManagementSchemaServices { - object SchemaV1 : MappedSchema(schemaFamily = NetworkManagementSchemaServices::class.java, version = 1, - mappedTypes = listOf( - CertificateSigningRequestEntity::class.java, - CertificateDataEntity::class.java, - CertificateRevocationRequestEntity::class.java, - PrivateNetworkEntity::class.java, - CertificateRevocationListEntity::class.java, - NodeInfoEntity::class.java, - NetworkParametersEntity::class.java, - NetworkMapEntity::class.java, - ParametersUpdateEntity::class.java)) { - override val migrationResource = "network-manager.changelog-master" - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRevocationListStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRevocationListStorage.kt deleted file mode 100644 index 0782d73754..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRevocationListStorage.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.common.persistence.entity.CertificateDataEntity -import com.r3.corda.networkmanage.common.persistence.entity.CertificateRevocationListEntity -import com.r3.corda.networkmanage.common.persistence.entity.CertificateRevocationRequestEntity -import net.corda.nodeapi.internal.persistence.CordaPersistence -import net.corda.nodeapi.internal.persistence.DatabaseTransaction -import java.math.BigInteger -import java.security.cert.X509CRL -import java.time.Instant - -class PersistentCertificateRevocationListStorage(private val database: CordaPersistence) : CertificateRevocationListStorage { - override fun getCertificateRevocationList(crlIssuer: CrlIssuer): X509CRL? { - return database.transaction { - val builder = session.criteriaBuilder - val query = builder.createQuery(CertificateRevocationListEntity::class.java).run { - from(CertificateRevocationListEntity::class.java).run { - orderBy(builder.desc(get(CertificateRevocationListEntity::id.name))) - where(builder.equal(get(CertificateRevocationListEntity::crlIssuer.name), crlIssuer)) - } - } - // We just want the last signed entry - session.createQuery(query).setMaxResults(1).uniqueResult()?.crl - } - } - - override fun saveCertificateRevocationList(crl: X509CRL, crlIssuer: CrlIssuer, signedBy: String, revokedAt: Instant) { - database.transaction { - crl.revokedCertificates?.forEach { - revokeCertificate(it.serialNumber, revokedAt, this) - } - session.save(CertificateRevocationListEntity( - crl = crl, - crlIssuer = crlIssuer, - signedBy = signedBy, - modifiedAt = Instant.now() - )) - } - } - - private fun revokeCertificate(certificateSerialNumber: BigInteger, time: Instant, transaction: DatabaseTransaction) { - val revocation = transaction.uniqueEntityWhere { builder, path -> - builder.and( - builder.equal(path.get(CertificateRevocationRequestEntity::certificateSerialNumber.name), certificateSerialNumber), - builder.notEqual(path.get(CertificateRevocationRequestEntity::status.name), RequestStatus.REJECTED) - ) - } - revocation ?: throw IllegalStateException("The certificate revocation request for $certificateSerialNumber does not exist") - check(revocation.status in arrayOf(RequestStatus.APPROVED, RequestStatus.DONE)) { - "The certificate revocation request for $certificateSerialNumber has unexpected status of ${revocation.status}" - } - val session = transaction.session - val certificateData = session.merge(revocation.certificateData.copy(certificateStatus = CertificateStatus.REVOKED)) as CertificateDataEntity - session.merge(revocation.copy( - status = RequestStatus.DONE, - modifiedAt = time, - certificateData = certificateData - )) - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRevocationRequestStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRevocationRequestStorage.kt deleted file mode 100644 index 42ec4db79b..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRevocationRequestStorage.kt +++ /dev/null @@ -1,237 +0,0 @@ -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.common.persistence.entity.CertificateDataEntity -import com.r3.corda.networkmanage.common.persistence.entity.CertificateRevocationRequestEntity -import com.r3.corda.networkmanage.common.persistence.entity.CertificateSigningRequestEntity -import net.corda.core.crypto.SecureHash -import net.corda.core.identity.CordaX500Name -import net.corda.core.utilities.contextLogger -import net.corda.nodeapi.internal.network.CertificateRevocationRequest -import net.corda.nodeapi.internal.persistence.CordaPersistence -import net.corda.nodeapi.internal.persistence.DatabaseTransaction -import net.corda.nodeapi.internal.persistence.TransactionIsolationLevel -import java.math.BigInteger -import java.security.cert.CRLReason -import java.security.cert.X509Certificate -import java.time.Instant - -class PersistentCertificateRevocationRequestStorage(private val database: CordaPersistence) : CertificateRevocationRequestStorage { - private companion object { - val ALLOWED_REASONS = arrayOf( - CRLReason.KEY_COMPROMISE, - CRLReason.AFFILIATION_CHANGED, - CRLReason.CA_COMPROMISE, - CRLReason.CESSATION_OF_OPERATION, - CRLReason.PRIVILEGE_WITHDRAWN, - CRLReason.SUPERSEDED, - CRLReason.UNSPECIFIED - ) - val logger = contextLogger() - } - - override fun saveRevocationRequest(request: CertificateRevocationRequest): String { - return database.transaction(TransactionIsolationLevel.SERIALIZABLE) { - // Get matching CSR - validate(request) - val csr = requireNotNull(retrieveCsr(request.certificateSerialNumber, request.csrRequestId, request.legalName)) { - "No CSR matching the given criteria was found" - } - // Check if there is an entry for the given certificate serial number - val revocation = uniqueEntityWhere { builder, path -> - val serialNumberEqual = builder.equal(path.get(CertificateRevocationRequestEntity::certificateSerialNumber.name), request.certificateSerialNumber) - val statusNotEqualRejected = builder.notEqual(path.get(CertificateRevocationRequestEntity::status.name), RequestStatus.REJECTED) - builder.and(serialNumberEqual, statusNotEqualRejected) - } - if (revocation != null) { - revocation.requestId - } else { - val certificateData = csr.certificateData!! - requireNotNull(certificateData) { "The certificate with the given serial number cannot be found." } - val requestId = SecureHash.randomSHA256().toString() - session.save(CertificateRevocationRequestEntity( - certificateSerialNumber = certificateData.certificateSerialNumber, - revocationReason = request.reason, - requestId = requestId, - modifiedBy = request.reporter, - certificateData = certificateData, - reporter = request.reporter, - legalName = certificateData.legalName - )) - requestId - } - } - } - - private fun validate(request: CertificateRevocationRequest) { - require(request.reason in ALLOWED_REASONS) { "The given revocation reason is not allowed." } - } - - private fun DatabaseTransaction.retrieveCsr(certificateSerialNumber: BigInteger?, csrRequestId: String?, legalName: CordaX500Name?): CertificateSigningRequestEntity? { - val csr = if (csrRequestId != null) { - uniqueEntityWhere { builder, path -> - builder.and( - builder.equal(path.get(CertificateSigningRequestEntity::requestId.name), csrRequestId), - builder.notEqual(path.get(CertificateSigningRequestEntity::status.name), RequestStatus.REJECTED), - builder.equal(path - .get(CertificateSigningRequestEntity::certificateData.name) - .get(CertificateDataEntity::certificateStatus.name), CertificateStatus.VALID) - ) - } - } else if (legalName != null) { - uniqueEntityWhere { builder, path -> - builder.and( - builder.equal(path.get(CertificateSigningRequestEntity::legalName.name), legalName.toString()), - builder.notEqual(path.get(CertificateSigningRequestEntity::status.name), RequestStatus.REJECTED), - builder.equal(path - .get(CertificateSigningRequestEntity::certificateData.name) - .get(CertificateDataEntity::certificateStatus.name), CertificateStatus.VALID) - ) - } - } else { - val certificateData = uniqueEntityWhere { builder, path -> - builder.and( - builder.equal(path.get(CertificateDataEntity::certificateStatus.name), CertificateStatus.VALID), - builder.equal(path.get(CertificateDataEntity::certificateSerialNumber.name), certificateSerialNumber) - ) - } - certificateData?.certificateSigningRequest - } - return csr?.let { - validateCsrConsistency(certificateSerialNumber, csrRequestId, legalName, it) - } - } - - private fun validateCsrConsistency(certificateSerialNumber: BigInteger?, - csrRequestId: String?, - legalName: CordaX500Name?, - result: CertificateSigningRequestEntity): CertificateSigningRequestEntity { - val certData = result.certificateData!! - require(legalName == null || result.legalName == legalName) { - "The legal name does not match." - } - require(csrRequestId == null || result.requestId == csrRequestId) { - "The CSR request ID does not match." - } - require(certificateSerialNumber == null || certData.certificateSerialNumber == certificateSerialNumber) { - "The certificate serial number does not match." - } - return result - } - - override fun getRevocationRequest(requestId: String): CertificateRevocationRequestData? { - return database.transaction { - getRevocationRequestEntity(requestId)?.toCertificateRevocationRequestData() - } - } - - override fun getRevocationRequests(revocationStatus: RequestStatus): List { - return database.transaction { - val builder = session.criteriaBuilder - val query = builder.createQuery(CertificateRevocationRequestEntity::class.java).run { - from(CertificateRevocationRequestEntity::class.java).run { - where(builder.equal(get(CertificateRevocationRequestEntity::status.name), revocationStatus)) - } - } - session.createQuery(query).resultList.map { it.toCertificateRevocationRequestData() } - } - } - - override fun approveRevocationRequest(requestId: String, approvedBy: String) { - database.transaction { - val revocation = getRevocationRequestEntity(requestId) - if (revocation == null) { - throw NoSuchElementException("Error while approving! Certificate revocation id=$id does not exist") - } else { - when (revocation.status) { - RequestStatus.TICKET_CREATED -> { - session.merge(revocation.copy( - status = RequestStatus.APPROVED, - modifiedAt = Instant.now(), - modifiedBy = approvedBy - )) - logger.debug("`request id` = $requestId marked as APPROVED") - } - else -> { - logger.warn("`request id` = $requestId cannot be marked as APPROVED. Its current status is ${revocation.status}") - return@transaction - } - } - } - } - } - - override fun rejectRevocationRequest(requestId: String, rejectedBy: String, reason: String?) { - database.transaction { - val revocation = getRevocationRequestEntity(requestId) - if (revocation == null) { - throw NoSuchElementException("Error while rejecting! Certificate revocation id=$id does not exist") - } else { - when (revocation.status) { - RequestStatus.TICKET_CREATED -> { - session.merge(revocation.copy( - status = RequestStatus.REJECTED, - modifiedAt = Instant.now(), - modifiedBy = rejectedBy, - remark = reason - )) - logger.debug("`request id` = $requestId marked as REJECTED") - } - else -> { - logger.warn("`request id` = $requestId cannot be marked as REJECTED. Its current status is ${revocation.status}") - return@transaction - } - } - } - } - } - - override fun markRequestTicketCreated(requestId: String) { - database.transaction { - val revocation = getRevocationRequestEntity(requestId) - if (revocation == null) { - throw NoSuchElementException("Error while marking the request as ticket created! Certificate revocation id=$id does not exist") - } else { - when (revocation.status) { - RequestStatus.NEW -> { - session.merge(revocation.copy( - modifiedAt = Instant.now(), - status = RequestStatus.TICKET_CREATED - )) - logger.debug("`request id` = $requestId marked as TICKED_CREATED") - } - else -> { - logger.warn("`request id` = $requestId cannot be marked as TICKED_CREATED. Its current status is ${revocation.status}") - return@transaction - } - } - } - } - } - - private fun getRevocationRequestEntity(requestId: String, status: RequestStatus? = null): CertificateRevocationRequestEntity? { - return database.transaction { - uniqueEntityWhere { builder, path -> - val idEqual = builder.equal(path.get(CertificateRevocationRequestEntity::requestId.name), requestId) - if (status == null) { - idEqual - } else { - builder.and(idEqual, builder.equal(path.get(CertificateRevocationRequestEntity::status.name), status)) - } - } - } - } - - private fun CertificateRevocationRequestEntity.toCertificateRevocationRequestData(): CertificateRevocationRequestData { - return CertificateRevocationRequestData( - requestId, - certificateData.certificateSigningRequest.requestId, - certificateData.certPath.certificates.first() as X509Certificate, - certificateSerialNumber, - modifiedAt, - legalName, - status, - revocationReason, - reporter - ) - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateSigningRequestStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateSigningRequestStorage.kt deleted file mode 100644 index e15cd61822..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateSigningRequestStorage.kt +++ /dev/null @@ -1,222 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.common.persistence.entity.CertificateDataEntity -import com.r3.corda.networkmanage.common.persistence.entity.CertificateSigningRequestEntity -import com.r3.corda.networkmanage.common.utils.getCertRole -import net.corda.core.crypto.Crypto.toSupportedPublicKey -import net.corda.core.crypto.SecureHash -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.CertRole -import net.corda.core.internal.hash -import net.corda.nodeapi.internal.crypto.x509Certificates -import net.corda.nodeapi.internal.persistence.CordaPersistence -import net.corda.nodeapi.internal.persistence.DatabaseTransaction -import net.corda.nodeapi.internal.persistence.TransactionIsolationLevel -import org.bouncycastle.pkcs.PKCS10CertificationRequest -import java.security.PublicKey -import java.security.cert.CertPath -import java.time.Instant -import javax.persistence.LockModeType -import javax.security.auth.x500.X500Principal - -/** - * Database implementation of the [CertificateSigningRequestStorage] interface. - */ -class PersistentCertificateSigningRequestStorage(private val database: CordaPersistence) : CertificateSigningRequestStorage { - companion object { - // TODO: make this configurable? - private val allowedCertRoles = setOf(CertRole.NODE_CA, CertRole.SERVICE_IDENTITY) - } - - override fun putCertificatePath(requestId: String, certPath: CertPath, signedBy: String) { - return database.transaction(TransactionIsolationLevel.SERIALIZABLE) { - val request = requireNotNull(uniqueEntityWhere { builder, path -> - val requestIdEq = builder.equal(path.get(CertificateSigningRequestEntity::requestId.name), requestId) - val statusEq = builder.equal(path.get(CertificateSigningRequestEntity::status.name), RequestStatus.APPROVED) - builder.and(requestIdEq, statusEq) - }) { "Cannot retrieve 'APPROVED' certificate signing request for request id: $requestId" } - val certificateSigningRequest = request.copy( - modifiedBy = signedBy, - modifiedAt = Instant.now(), - status = RequestStatus.DONE) - session.merge(certificateSigningRequest) - val certificateDataEntity = CertificateDataEntity( - certificateStatus = CertificateStatus.VALID, - certPath = certPath, - certificateSigningRequest = certificateSigningRequest, - certificateSerialNumber = certPath.x509Certificates.first().serialNumber) - session.persist(certificateDataEntity) - } - } - - override fun saveRequest(request: PKCS10CertificationRequest): String { - return database.transaction(TransactionIsolationLevel.SERIALIZABLE) { - val (legalName, exception) = try { - val legalName = parseLegalName(request) - // Return existing request ID, if request already exists for the same request. - validateRequest(legalName, request)?.let { return@transaction it } - Pair(legalName, null) - } catch (e: RequestValidationException) { - Pair(e.legalName, e) - } - - val requestEntity = CertificateSigningRequestEntity( - requestId = SecureHash.randomSHA256().toString(), - legalName = legalName, - publicKeyHash = toSupportedPublicKey(request.subjectPublicKeyInfo).hash, - request = request, - remark = exception?.rejectMessage, - modifiedBy = CertificateSigningRequestStorage.DOORMAN_SIGNATURE, - status = if (exception == null) RequestStatus.NEW else RequestStatus.REJECTED - ) - session.save(requestEntity) as String - } - } - - private fun DatabaseTransaction.findRequest(requestId: String, - requestStatus: RequestStatus? = null): CertificateSigningRequestEntity? { - return uniqueEntityWhere { builder, path -> - val idClause = builder.equal(path.get(CertificateSigningRequestEntity::requestId.name), requestId) - if (requestStatus == null) { - idClause - } else { - val statusClause = builder.equal(path.get(CertificateSigningRequestEntity::status.name), requestStatus) - builder.and(idClause, statusClause) - } - } - } - - override fun markRequestTicketCreated(requestId: String) { - database.transaction(TransactionIsolationLevel.SERIALIZABLE) { - val request = requireNotNull(findRequest(requestId, RequestStatus.NEW)) { "Error when creating request ticket with id: $requestId. Request does not exist or its status is not NEW." } - val update = request.copy( - modifiedAt = Instant.now(), - status = RequestStatus.TICKET_CREATED) - session.merge(update) - } - } - - override fun approveRequest(requestId: String, approvedBy: String) { - database.transaction(TransactionIsolationLevel.SERIALIZABLE) { - findRequest(requestId, RequestStatus.TICKET_CREATED)?.let { - val update = it.copy( - modifiedBy = approvedBy, - modifiedAt = Instant.now(), - status = RequestStatus.APPROVED) - session.merge(update) - } - } - } - - override fun rejectRequest(requestId: String, rejectedBy: String, rejectReason: String?) { - database.transaction(TransactionIsolationLevel.SERIALIZABLE) { - val request = requireNotNull(findRequest(requestId)) { "Error when rejecting request with id: $requestId. Request does not exist." } - val update = request.copy( - modifiedBy = rejectedBy, - modifiedAt = Instant.now(), - status = RequestStatus.REJECTED, - remark = rejectReason - ) - session.merge(update) - } - } - - override fun getValidCertificatePath(publicKey: PublicKey): CertPath? { - return database.transaction { - session.createQuery( - "select a.certificateData.certPath from ${CertificateSigningRequestEntity::class.java.name} a " + - "where a.publicKeyHash = :publicKeyHash and a.status = 'DONE' and a.certificateData.certificateStatus = 'VALID'", CertPath::class.java) - .setParameter("publicKeyHash", publicKey.hash.toString()) - .uniqueResult() - } - } - - override fun getRequest(requestId: String): CertificateSigningRequest? { - return database.transaction { - findRequest(requestId)?.toCertificateSigningRequest() - } - } - - override fun getRequests(requestStatus: RequestStatus): List { - return database.transaction(TransactionIsolationLevel.SERIALIZABLE) { - val builder = session.criteriaBuilder - val query = builder.createQuery(CertificateSigningRequestEntity::class.java).run { - from(CertificateSigningRequestEntity::class.java).run { - where(builder.equal(get(CertificateSigningRequestEntity::status.name), requestStatus)) - } - } - session.createQuery(query).resultList.map { it.toCertificateSigningRequest() } - } - } - - private fun parseLegalName(request: PKCS10CertificationRequest): CordaX500Name { - return try { - CordaX500Name.build(X500Principal(request.subject.encoded)) - } catch (e: IllegalArgumentException) { - throw RequestValidationException(null, request.subject.toString(), rejectMessage = "Name validation failed: ${e.message}") - } - } - - /** - * Validate certificate signing request, returns request ID if same request already exists. - */ - private fun DatabaseTransaction.validateRequest(legalName: CordaX500Name, request: PKCS10CertificationRequest): String? { - // Check if the same request exists and returns the request id. - val existingRequestByPubKeyHash = nonRejectedRequest(CertificateSigningRequestEntity::publicKeyHash.name, toSupportedPublicKey(request.subjectPublicKeyInfo).hash) - - existingRequestByPubKeyHash?.let { - // Compare subject, attribute. - // We cannot compare the request directly because it contains nonce. - if (certNotRevoked(it) && it.request.subject == request.subject && it.request.attributes.asList() == request.attributes.asList()) { - return it.requestId - } else { - //TODO Consider following scenario: There is a CSR that is signed but the certificate itself has expired or was revoked - throw RequestValidationException(legalName, rejectMessage = "Duplicate public key") - } - } - // Check if requested role is valid. - if (request.getCertRole() !in allowedCertRoles) - throw RequestValidationException(legalName, rejectMessage = "Requested certificate role ${request.getCertRole()} is not allowed.") - // TODO consider scenario: There is a CSR that is signed but the certificate itself has expired or was revoked - // Also, at the moment we assume that once the CSR is approved it cannot be rejected. - // What if we approved something by mistake. - val existingRequestByLegalName = nonRejectedRequest(CertificateSigningRequestEntity::legalName.name, legalName) - existingRequestByLegalName?.let { - if (certNotRevoked(it)) { - throw RequestValidationException(legalName, rejectMessage = "Duplicate legal name") - } - } - return null - } - - private fun certNotRevoked(request: CertificateSigningRequestEntity): Boolean { - return request.status != RequestStatus.DONE || request.certificateData?.certificateStatus != CertificateStatus.REVOKED - } - - /** - * Retrieve "non-rejected" request which matches provided column and value predicate. - */ - private fun DatabaseTransaction.nonRejectedRequest(columnName: String, value: T): CertificateSigningRequestEntity? { - val query = session.criteriaBuilder.run { - val criteriaQuery = createQuery(CertificateSigningRequestEntity::class.java) - criteriaQuery.from(CertificateSigningRequestEntity::class.java).run { - val valueQuery = equal(get(columnName), value) - val statusQuery = notEqual(get(CertificateSigningRequestEntity::status.name), RequestStatus.REJECTED) - criteriaQuery.where(and(valueQuery, statusQuery)) - } - } - return session.createQuery(query).setLockMode(LockModeType.PESSIMISTIC_WRITE).setMaxResults(1).uniqueResult() - } - - private data class RequestValidationException(val legalName: CordaX500Name?, val subjectName: String = legalName.toString(), val rejectMessage: String) : Exception("Validation failed for $subjectName. $rejectMessage.") -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNetworkMapStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNetworkMapStorage.kt deleted file mode 100644 index 6b2cd38acf..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNetworkMapStorage.kt +++ /dev/null @@ -1,187 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.common.persistence.entity.* -import com.r3.corda.networkmanage.common.utils.logger -import net.corda.core.crypto.SecureHash -import net.corda.core.internal.DigitalSignatureWithCert -import net.corda.core.node.NetworkParameters -import net.corda.core.serialization.serialize -import net.corda.nodeapi.internal.network.NetworkMapAndSigned -import net.corda.nodeapi.internal.network.SignedNetworkParameters -import net.corda.nodeapi.internal.persistence.CordaPersistence -import net.corda.nodeapi.internal.persistence.DatabaseTransaction -import java.time.Instant - -/** - * Database implementation of the [NetworkMapStorage] interface - */ -class PersistentNetworkMapStorage(private val database: CordaPersistence) : NetworkMapStorage { - companion object { - // Used internally to identify global network map in database table. - private const val PUBLIC_NETWORK_ID = "PUBLIC_NETWORK" - } - - override fun getNetworkMaps(): NetworkMaps { - return database.transaction { - val networkMapEntities = session.createQuery("from ${NetworkMapEntity::class.java.name}", NetworkMapEntity::class.java) - .resultList - .associateBy { it.id } - NetworkMaps(networkMapEntities[PUBLIC_NETWORK_ID], networkMapEntities.filterKeys { it != PUBLIC_NETWORK_ID }) - } - } - - override fun saveNewNetworkMap(networkId: String?, networkMapAndSigned: NetworkMapAndSigned) { - val (networkMap, signedNetworkMap) = networkMapAndSigned - database.transaction { - val networkParametersEntity = checkNotNull(getNetworkParametersEntity(networkMap.networkParameterHash)) { - "Network parameters ${networkMap.networkParameterHash} must be first persisted" - } - check(networkParametersEntity.isSigned) { - "Network parameters ${networkMap.networkParameterHash} are not signed" - } - session.merge(NetworkMapEntity( - id = networkId ?: PUBLIC_NETWORK_ID, - networkMap = networkMap, - signature = signedNetworkMap.sig.bytes, - certificate = signedNetworkMap.sig.by, - networkParameters = networkParametersEntity - )) - } - } - - override fun getSignedNetworkParameters(hash: SecureHash): SignedNetworkParameters? { - return database.transaction { - getNetworkParametersEntity(hash)?.let { - if (it.isSigned) it.toSignedNetworkParameters() else null - } - } - } - - override fun getNodeInfoHashes(): NodeInfoHashes { - return database.transaction { - val currentParameters = getNetworkMaps().publicNetworkMap?.networkParameters?.networkParameters - val builder = session.criteriaBuilder - // TODO Convert this query to JPQL so it's more readable. - val query = builder.createTupleQuery().run { - from(NodeInfoEntity::class.java).run { - val certStatusExpression = get(NodeInfoEntity::certificateSigningRequest.name) - .get(CertificateSigningRequestEntity::certificateData.name) - .get(CertificateDataEntity::certificateStatus.name) - // TODO When revoking certs, all node-infos that point to it must be made non-current. Then this check - // isn't needed. - val certStatusEq = builder.equal(certStatusExpression, CertificateStatus.VALID) - val isCurrentNodeInfo = builder.isTrue(get(NodeInfoEntity::isCurrent.name)) - // We enable eventHorizon only if minimum platform version is greater than 3, nodes on previous versions - // don't republish their node infos on regular intervals so they shouldn't be evicted from network after eventHorizon. - val eventHorizonAgo = if (currentParameters != null && currentParameters.minimumPlatformVersion >= 4) { - builder.greaterThanOrEqualTo(get(NodeInfoEntity::publishedAt.name), - Instant.now().minus(currentParameters.eventHorizon)) - } else { - builder.and() // This expression is always true. It's needed when eventHorizon isn't enabled. - } - val networkIdSelector = get(NodeInfoEntity::certificateSigningRequest.name) - .get(CertificateSigningRequestEntity::privateNetwork.name) - .get(PrivateNetworkEntity::networkId.name) - multiselect(networkIdSelector, get(NodeInfoEntity::nodeInfoHash.name)) - .where(builder.and(certStatusEq, isCurrentNodeInfo, eventHorizonAgo)) - } - } - val allNodeInfos = session.createQuery(query).resultList.groupBy { it[0]?.toString() ?: PUBLIC_NETWORK_ID }.mapValues { it.value.map { SecureHash.parse(it.get(1, String::class.java)) } } - NodeInfoHashes(allNodeInfos[PUBLIC_NETWORK_ID] ?: emptyList(), allNodeInfos.filterKeys { it != PUBLIC_NETWORK_ID }) - } - } - - override fun saveNetworkParameters(networkParameters: NetworkParameters, signature: DigitalSignatureWithCert?): NetworkParametersEntity { - val serialized = networkParameters.serialize() - signature?.verify(serialized) - val hash = serialized.hash - return database.transaction { - val entity = getNetworkParametersEntity(hash) - val newNetworkParamsEntity = entity?.copy( - signature = signature?.bytes, - certificate = signature?.by - ) ?: NetworkParametersEntity( - networkParameters = networkParameters, - hash = hash.toString(), - signature = signature?.bytes, - certificate = signature?.by - ) - session.merge(newNetworkParamsEntity) as NetworkParametersEntity - } - } - - override fun getLatestNetworkParameters(): NetworkParametersEntity? { - return database.transaction { - val query = session.criteriaBuilder.run { - createQuery(NetworkParametersEntity::class.java).run { - from(NetworkParametersEntity::class.java).run { - orderBy(desc(get(NetworkParametersEntity::created.name))) - } - } - } - // We just want the last entry - session.createQuery(query).setMaxResults(1).uniqueResult() - } - } - - override fun saveNewParametersUpdate(networkParameters: NetworkParameters, description: String, updateDeadline: Instant) { - database.transaction { - val existingUpdate = getCurrentParametersUpdate() - if (existingUpdate != null) { - logger.info("Cancelling existing update: $existingUpdate") - session.merge(existingUpdate.copy(status = UpdateStatus.CANCELLED)) - } - val netParamsEntity = saveNetworkParameters(networkParameters, null) - session.save(ParametersUpdateEntity( - networkParameters = netParamsEntity, - description = description, - updateDeadline = updateDeadline - )) - } - } - - override fun getCurrentParametersUpdate(): ParametersUpdateEntity? { - return database.transaction { - val newParamsUpdates = session.fromQuery("u where u.status in :statuses") - .setParameterList("statuses", listOf(UpdateStatus.NEW, UpdateStatus.FLAG_DAY)) - .resultList - when (newParamsUpdates.size) { - 0 -> null - 1 -> newParamsUpdates[0] - else -> throw IllegalStateException("More than one update found: $newParamsUpdates") - } - } - } - - override fun setParametersUpdateStatus(update: ParametersUpdateEntity, newStatus: UpdateStatus) { - require(newStatus != UpdateStatus.NEW) - database.transaction { - session.merge(update.copy(status = newStatus)) - } - } - - override fun switchFlagDay(update: ParametersUpdateEntity) { - database.transaction { - setParametersUpdateStatus(update, UpdateStatus.APPLIED) - session.createQuery("update ${NodeInfoEntity::class.java.name} n set n.isCurrent = false " + - "where (n.acceptedParametersUpdate != :acceptedParamUp or n.acceptedParametersUpdate is null) and n.isCurrent = true") - .setParameter("acceptedParamUp", update).executeUpdate() - } - } -} - -internal fun DatabaseTransaction.getNetworkParametersEntity(hash: SecureHash): NetworkParametersEntity? { - return uniqueEntityWhere { builder, path -> - builder.equal(path.get(NetworkParametersEntity::hash.name), hash.toString()) - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNodeInfoStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNodeInfoStorage.kt deleted file mode 100644 index 59e3340e84..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNodeInfoStorage.kt +++ /dev/null @@ -1,134 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.common.persistence.entity.CertificateSigningRequestEntity -import com.r3.corda.networkmanage.common.persistence.entity.NodeInfoEntity -import com.r3.corda.networkmanage.common.persistence.entity.ParametersUpdateEntity -import com.r3.corda.networkmanage.common.persistence.entity.UpdateStatus -import com.r3.corda.networkmanage.common.utils.logger -import net.corda.core.crypto.SecureHash -import net.corda.core.internal.CertRole -import net.corda.core.internal.CertRole.NODE_CA -import net.corda.core.internal.hash -import net.corda.core.utilities.debug -import net.corda.nodeapi.internal.NodeInfoAndSigned -import net.corda.nodeapi.internal.SignedNodeInfo -import net.corda.nodeapi.internal.crypto.x509Certificates -import net.corda.nodeapi.internal.persistence.CordaPersistence -import net.corda.nodeapi.internal.persistence.DatabaseTransaction -import java.security.PublicKey -import java.security.cert.CertPath -import java.time.Instant - -/** - * Database implementation of the [NetworkMapStorage] interface - */ -class PersistentNodeInfoStorage(private val database: CordaPersistence) : NodeInfoStorage { - override fun putNodeInfo(nodeInfoAndSigned: NodeInfoAndSigned): SecureHash { - val (nodeInfo, signedNodeInfo) = nodeInfoAndSigned - val nodeInfoHash = signedNodeInfo.raw.hash - - // Extract identities issued by the intermediate CAs (doorman). - val registeredIdentities = nodeInfo.legalIdentitiesAndCerts.map { it.certPath.x509Certificates.single { CertRole.extract(it) in setOf(CertRole.SERVICE_IDENTITY, NODE_CA) } } - - database.transaction { - // Record fact of republishing of the node info, it's treated as a heartbeat from the node. - val rowsUpdated = session.createQuery("update ${NodeInfoEntity::class.java.name} n set publishedAt = :now " + - "where n.nodeInfoHash = :nodeInfoHash and n.isCurrent = true") - .setParameter("now", Instant.now()) - .setParameter("nodeInfoHash", nodeInfoHash.toString()) - .executeUpdate() - if (rowsUpdated != 0) { - logger.debug { "Republish of $nodeInfo" } - return@transaction nodeInfoHash - } - // TODO Move these checks out of data access layer - // For each identity known by the doorman, validate against it's CSR. - val requests = registeredIdentities.map { - val request = requireNotNull(getSignedRequestByPublicHash(it.publicKey.hash)) { - "Node-info not registered with us" - } - request.certificateData?.certificateStatus.let { - require(it == CertificateStatus.VALID) { "Certificate is no longer valid: $it" } - } - CertRole.extract(it) to request - } - - // Ensure only 1 NodeCA identity. - // TODO: make this support multiple node identities. - val (_, request) = requireNotNull(requests.singleOrNull { it.first == CertRole.NODE_CA }) { "Require exactly 1 Node CA identity in the node-info." } - - val existingNodeInfos = session.fromQuery( - "n where n.certificateSigningRequest = :csr and n.isCurrent = true order by n.publishedAt desc") - .setParameter("csr", request) - .resultList - - // Update any [NodeInfoEntity] instance for this CSR as not current. - existingNodeInfos.forEach { session.merge(it.copy(isCurrent = false)) } - - session.saveOrUpdate(NodeInfoEntity( - nodeInfoHash = nodeInfoHash.toString(), - publicKeyHash = nodeInfo.legalIdentities[0].owningKey.hash, - certificateSigningRequest = request, - signedNodeInfo = signedNodeInfo, - isCurrent = true, - acceptedParametersUpdate = existingNodeInfos.firstOrNull()?.acceptedParametersUpdate - )) - } - - return nodeInfoHash - } - - override fun getNodeInfo(nodeInfoHash: SecureHash): SignedNodeInfo? { - return database.transaction { - session.find(NodeInfoEntity::class.java, nodeInfoHash.toString())?.signedNodeInfo - } - } - - override fun getAcceptedParametersUpdate(nodeInfoHash: SecureHash): ParametersUpdateEntity? { - return database.transaction { - session.find(NodeInfoEntity::class.java, nodeInfoHash.toString())?.acceptedParametersUpdate - } - } - - override fun getCertificatePath(publicKeyHash: SecureHash): CertPath? { - return database.transaction { - val request = getSignedRequestByPublicHash(publicKeyHash) - request?.let { it.certificateData!!.certPath } - } - } - - override fun ackNodeInfoParametersUpdate(publicKey: PublicKey, acceptedParametersHash: SecureHash) { - return database.transaction { - val nodeInfoEntity = session.fromQuery( - "n where n.publicKeyHash = :publicKeyHash and isCurrent = true") - .setParameter("publicKeyHash", publicKey.hash) - .singleResult - val parametersUpdateEntity = session.fromQuery( - "u where u.networkParameters.hash = :acceptedParametersHash"). - setParameter("acceptedParametersHash", acceptedParametersHash.toString()) - .singleResult - require(parametersUpdateEntity.status in listOf(UpdateStatus.NEW, UpdateStatus.FLAG_DAY)) { - "$parametersUpdateEntity can no longer be accepted as it's ${parametersUpdateEntity.status}" - } - session.merge(nodeInfoEntity.copy(acceptedParametersUpdate = parametersUpdateEntity)) - } - } - - private fun DatabaseTransaction.getSignedRequestByPublicHash(publicKeyHash: SecureHash): CertificateSigningRequestEntity? { - return uniqueEntityWhere { builder, path -> - val publicKeyEq = builder.equal(path.get(CertificateSigningRequestEntity::publicKeyHash.name), publicKeyHash) - val statusEq = builder.equal(path.get(CertificateSigningRequestEntity::status.name), RequestStatus.DONE) - builder.and(publicKeyEq, statusEq) - } - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/AttributeConverters.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/AttributeConverters.kt deleted file mode 100644 index 576156053d..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/AttributeConverters.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.r3.corda.networkmanage.common.persistence.entity - -import com.r3.corda.networkmanage.common.utils.buildCertPath -import net.corda.core.crypto.SecureHash -import net.corda.core.identity.CordaX500Name -import net.corda.core.node.NetworkParameters -import net.corda.core.serialization.SerializationFactory -import net.corda.core.serialization.serialize -import net.corda.core.utilities.sequence -import net.corda.nodeapi.internal.SignedNodeInfo -import net.corda.nodeapi.internal.crypto.X509CertificateFactory -import net.corda.nodeapi.internal.network.NetworkMap -import org.bouncycastle.pkcs.PKCS10CertificationRequest -import java.security.cert.CertPath -import java.security.cert.X509CRL -import java.security.cert.X509Certificate -import javax.persistence.AttributeConverter - -class PKCS10CertificationRequestConverter : AttributeConverter { - override fun convertToEntityAttribute(dbData: ByteArray?): PKCS10CertificationRequest? = dbData?.let(::PKCS10CertificationRequest) - override fun convertToDatabaseColumn(attribute: PKCS10CertificationRequest?): ByteArray? = attribute?.encoded -} - -class CertPathConverter : AttributeConverter { - override fun convertToEntityAttribute(dbData: ByteArray?): CertPath? = dbData?.let(::buildCertPath) - override fun convertToDatabaseColumn(attribute: CertPath?): ByteArray? = attribute?.encoded -} - -class X509CertificateConverter : AttributeConverter { - override fun convertToEntityAttribute(dbData: ByteArray?): X509Certificate? { - return dbData?.let { X509CertificateFactory().generateCertificate(it.inputStream()) } - } - override fun convertToDatabaseColumn(attribute: X509Certificate?): ByteArray? = attribute?.encoded -} - -class X509CRLConverter : AttributeConverter { - override fun convertToEntityAttribute(dbData: ByteArray?): X509CRL? { - return dbData?.let { X509CertificateFactory().delegate.generateCRL(it.inputStream()) as X509CRL } - } - override fun convertToDatabaseColumn(attribute: X509CRL?): ByteArray? = attribute?.encoded -} - -class NetworkParametersConverter : CordaSerializationConverter(NetworkParameters::class.java) - -class NetworkMapConverter : CordaSerializationConverter(NetworkMap::class.java) - -class SignedNodeInfoConverter : CordaSerializationConverter(SignedNodeInfo::class.java) - -class CordaX500NameAttributeConverter : ToStringConverter(CordaX500Name.Companion::parse) - -class SecureHashAttributeConverter : ToStringConverter(SecureHash.Companion::parse) - -abstract class CordaSerializationConverter(private val clazz: Class) : AttributeConverter { - override fun convertToEntityAttribute(dbData: ByteArray?): T? { - return dbData?.let { - val serializationFactory = SerializationFactory.defaultFactory - serializationFactory.deserialize(it.sequence(), clazz, serializationFactory.defaultContext) - } - } - - override fun convertToDatabaseColumn(attribute: T?): ByteArray? = attribute?.serialize()?.bytes -} - -abstract class ToStringConverter(private val parser: (String) -> T) : AttributeConverter { - override fun convertToDatabaseColumn(attribute: T?): String? = attribute?.toString() - override fun convertToEntityAttribute(dbData: String?): T? = dbData?.let { parser(it) } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/CertificateRevocationListEntity.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/CertificateRevocationListEntity.kt deleted file mode 100644 index 7a184b3fdc..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/CertificateRevocationListEntity.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.r3.corda.networkmanage.common.persistence.entity - -import com.r3.corda.networkmanage.common.persistence.CrlIssuer -import java.io.Serializable -import java.security.cert.X509CRL -import java.time.Instant -import javax.persistence.* - -@Entity -@Table(name = "cert_revocation_list") -class CertificateRevocationListEntity( - @Id - @GeneratedValue(strategy = GenerationType.SEQUENCE) - val id: Long? = null, - - @Column(name = "issuer", length = 16, nullable = false, columnDefinition = "NVARCHAR(16)") - @Enumerated(EnumType.STRING) - val crlIssuer: CrlIssuer, - - @Lob - @Column(name = "crl_bytes", nullable = false) - @Convert(converter = X509CRLConverter::class) - val crl: X509CRL, - - @Column(name = "signed_by", length = 64, nullable = false) - val signedBy: String, - - @Column(name = "modified_at", nullable = false) - val modifiedAt: Instant = Instant.now() -) : Serializable \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/CertificateRevocationRequestEntity.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/CertificateRevocationRequestEntity.kt deleted file mode 100644 index 410bde5a42..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/CertificateRevocationRequestEntity.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.r3.corda.networkmanage.common.persistence.entity - -import com.r3.corda.networkmanage.common.persistence.RequestStatus -import net.corda.core.identity.CordaX500Name -import org.hibernate.envers.Audited -import java.io.Serializable -import java.math.BigInteger -import java.security.cert.CRLReason -import java.time.Instant -import javax.persistence.* - -@Entity -@Table(name = "cert_revocation_request") -data class CertificateRevocationRequestEntity( - @Id - @GeneratedValue(strategy = GenerationType.SEQUENCE) - val id: Long? = null, - - @Column(name = "request_id", length = 64, nullable = false, unique = true) - val requestId: String, - - @OneToOne(fetch = FetchType.EAGER) - @JoinColumn(name = "cert_data", nullable = false) - val certificateData: CertificateDataEntity, - - @Column(name = "cert_serial_number", nullable = false, columnDefinition = "NUMERIC(28)") - val certificateSerialNumber: BigInteger, - - @Column(name = "legal_name", length = 256, nullable = false) - @Convert(converter = CordaX500NameAttributeConverter::class) - val legalName: CordaX500Name, - - // Setting [columnDefinition] is a work around for a hibernate problem when using SQL database. - // TODO: Remove this when we find out the cause of the problem. - @Audited - @Column(name = "status", length = 16, nullable = false, columnDefinition = "NVARCHAR(16)") - @Enumerated(EnumType.STRING) - val status: RequestStatus = RequestStatus.NEW, - - @Column(name = "reporter", nullable = false, length = 64) - val reporter: String, - - @Audited - @Column(name = "modified_by", nullable = false, length = 64) - val modifiedBy: String, - - @Audited - @Column(name = "modified_at", nullable = false) - val modifiedAt: Instant = Instant.now(), - - // Setting [columnDefinition] is a work around for a hibernate problem when using SQL database. - // TODO: Remove this when we find out the cause of the problem. - @Audited - @Column(name = "revocation_reason", length = 32, nullable = false, columnDefinition = "NVARCHAR(32)") - @Enumerated(EnumType.STRING) - val revocationReason: CRLReason, - - @Audited - @Column(name = "remark", length = 256) - val remark: String? = null -) : Serializable \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/CertificateSigningRequestEntity.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/CertificateSigningRequestEntity.kt deleted file mode 100644 index 4834ea5019..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/CertificateSigningRequestEntity.kt +++ /dev/null @@ -1,130 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence.entity - -import com.r3.corda.networkmanage.common.persistence.CertificateData -import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequest -import com.r3.corda.networkmanage.common.persistence.CertificateStatus -import com.r3.corda.networkmanage.common.persistence.RequestStatus -import net.corda.core.crypto.SecureHash -import net.corda.core.identity.CordaX500Name -import net.corda.nodeapi.internal.crypto.x509Certificates -import org.bouncycastle.pkcs.PKCS10CertificationRequest -import org.hibernate.envers.Audited -import java.io.Serializable -import java.math.BigInteger -import java.security.cert.CertPath -import java.time.Instant -import javax.persistence.* - -@Entity -@Table(name = "cert_signing_request", indexes = arrayOf(Index(name = "IDX__CSR__PKH", columnList = "public_key_hash"))) -data class CertificateSigningRequestEntity( - @Id - @Column(name = "request_id", length = 64, nullable = false) - val requestId: String, - - // TODO: Store X500Name with a proper schema. - @Column(name = "legal_name", length = 256) - @Convert(converter = CordaX500NameAttributeConverter::class) - val legalName: CordaX500Name?, - - @Column(name = "public_key_hash", length = 64, nullable = false) - @Convert(converter = SecureHashAttributeConverter::class) - val publicKeyHash: SecureHash, - - // Setting [columnDefinition] is a work around for a hibernate problem when using SQL database. - // TODO: Remove this when we find out the cause of the problem. - @Audited - @Column(name = "status", length = 16, nullable = false, columnDefinition = "NVARCHAR(16)") - @Enumerated(EnumType.STRING) - val status: RequestStatus = RequestStatus.NEW, - - @Audited - @Column(name = "modified_by", length = 64, nullable = false) - val modifiedBy: String, - - // TODO: Use audit framework instead. - @Column(name = "modified_at", nullable = false) - val modifiedAt: Instant = Instant.now(), - - @Audited - @Column(name = "remark", length = 256) - val remark: String? = null, - - @OneToOne(fetch = FetchType.EAGER, mappedBy = "certificateSigningRequest") - val certificateData: CertificateDataEntity? = null, - - @Lob - @Column(name = "request_bytes", nullable = false) - @Convert(converter = PKCS10CertificationRequestConverter::class) - val request: PKCS10CertificationRequest, - - @ManyToOne - @JoinColumn(name = "private_network", foreignKey = ForeignKey(name = "FK__CSR__PN")) - val privateNetwork: PrivateNetworkEntity? = null -) : Serializable { - fun toCertificateSigningRequest(): CertificateSigningRequest { - return CertificateSigningRequest( - requestId = requestId, - legalName = legalName, - publicKeyHash = publicKeyHash, - status = status, - request = request, - remark = remark, - modifiedBy = modifiedBy, - certData = certificateData?.toCertificateData() - ) - } -} - -@Entity -@Table(name = "cert_data") -data class CertificateDataEntity( - @Id - @GeneratedValue(strategy = GenerationType.SEQUENCE) - val id: Long? = null, - - // Setting [columnDefinition] is a work around for a hibernate problem when using SQL database. - // TODO: Remove this when we find out the cause of the problem. - @Column(name = "cert_status", length = 16, nullable = false, columnDefinition = "NVARCHAR(16)") - @Enumerated(EnumType.STRING) - val certificateStatus: CertificateStatus, - - @Lob - @Column(name = "cert_path_bytes", nullable = false) - @Convert(converter = CertPathConverter::class) - val certPath: CertPath, - - @OneToOne(fetch = FetchType.EAGER, optional = false) - @JoinColumn(name = "cert_signing_request", foreignKey = ForeignKey(name = "FK__CD__CSR"), nullable = false) - val certificateSigningRequest: CertificateSigningRequestEntity, - - @Column(name = "cert_serial_number", unique = true, nullable = false, columnDefinition = "NUMERIC(28)") - val certificateSerialNumber: BigInteger -) : Serializable { - fun toCertificateData(): CertificateData = CertificateData(certificateStatus, certPath) - - val legalName: CordaX500Name get() { - return CordaX500Name.build(certPath.x509Certificates[0].subjectX500Principal) - } -} - -@Entity -@Table(name = "private_network") -data class PrivateNetworkEntity( - @Id - @Column(name = "id", length = 64) - val networkId: String, - - @Column(name = "name", length = 255, nullable = false) - val networkName: String -) : Serializable \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NetworkMapEntity.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NetworkMapEntity.kt deleted file mode 100644 index 0b0d841264..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NetworkMapEntity.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence.entity - -import net.corda.core.internal.DigitalSignatureWithCert -import net.corda.core.serialization.serialize -import net.corda.nodeapi.internal.network.NetworkMap -import net.corda.nodeapi.internal.network.SignedNetworkMap -import org.hibernate.envers.Audited -import org.hibernate.envers.RelationTargetAuditMode -import java.io.Serializable -import java.security.cert.X509Certificate -import java.time.Instant -import javax.persistence.* - -@Entity -@Audited -@Table(name = "network_map") -class NetworkMapEntity( - @Id - @Column(name = "id") - val id: String, - - @Lob - @Column(name = "serialized_network_map", nullable = false) - @Convert(converter = NetworkMapConverter::class) - val networkMap: NetworkMap, - - @Lob - @Column(name = "signature", nullable = false) - val signature: ByteArray, - - @Lob - @Column(name = "cert", nullable = false) - @Convert(converter = X509CertificateConverter::class) - val certificate: X509Certificate, - - @ManyToOne(optional = false, fetch = FetchType.EAGER) - @JoinColumn(name = "network_parameters", nullable = false) - @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED) - val networkParameters: NetworkParametersEntity, - - @Column(nullable = false) - val timestamp: Instant = Instant.now() -) : Serializable { - fun toSignedNetworkMap(): SignedNetworkMap { - return SignedNetworkMap(networkMap.serialize(), DigitalSignatureWithCert(certificate, signature)) - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NetworkParametersEntity.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NetworkParametersEntity.kt deleted file mode 100644 index 31c3f8b6af..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NetworkParametersEntity.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence.entity - -import net.corda.core.internal.DigitalSignatureWithCert -import net.corda.core.node.NetworkParameters -import net.corda.core.serialization.serialize -import net.corda.nodeapi.internal.network.SignedNetworkParameters -import java.io.Serializable -import java.security.cert.X509Certificate -import java.time.Instant -import javax.persistence.* - -@Entity -@Table(name = "network_parameters", indexes = arrayOf(Index(name = "IDX_NP_HASH", columnList = "hash"))) -class NetworkParametersEntity( - @Id - @Column(name = "hash", length = 64, nullable = false) - // AttributeConverters can't be used on @Id attributes, otherwise this would be SecureHash - val hash: String, - - @Column(nullable = false) - val created: Instant = Instant.now(), - - @Lob - @Column(name = "parameters_bytes", nullable = false) - @Convert(converter = NetworkParametersConverter::class) - val networkParameters: NetworkParameters, - - // Both of the fields below are nullable, because of the way we sign network map data. NetworkParameters can be - // inserted into database without signature. Then signing service will sign them. - @Lob - @Column(name = "signature") - val signature: ByteArray?, - - @Lob - @Column(name = "cert") - @Convert(converter = X509CertificateConverter::class) - val certificate: X509Certificate? -) : Serializable { - val isSigned: Boolean get() = certificate != null && signature != null - - fun toSignedNetworkParameters(): SignedNetworkParameters { - val cert = certificate ?: throw IllegalStateException("Network parameters entity is not signed: $hash") - val sign = signature ?: throw IllegalStateException("Network parameters entity is not signed: $hash") - return SignedNetworkParameters(networkParameters.serialize(), DigitalSignatureWithCert(cert, sign)) - } - - fun copy(parametersHash: String = this.hash, - created: Instant = this.created, - networkParameters: NetworkParameters = this.networkParameters, - signature: ByteArray? = this.signature, - certificate: X509Certificate? = this.certificate - ): NetworkParametersEntity { - return NetworkParametersEntity( - hash = parametersHash, - created = created, - networkParameters = networkParameters, - signature = signature, - certificate = certificate - ) - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NodeInfoEntity.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NodeInfoEntity.kt deleted file mode 100644 index 4f0f224323..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NodeInfoEntity.kt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence.entity - -import net.corda.core.crypto.SecureHash -import net.corda.nodeapi.internal.SignedNodeInfo -import org.hibernate.annotations.UpdateTimestamp -import java.io.Serializable -import java.time.Instant -import javax.persistence.* - -@Entity -@Table(name = "node_info") -data class NodeInfoEntity( - // Hash of serialized [NodeInfo] without signatures. - @Id - @Column(name = "node_info_hash", length = 64) - // AttributeConverters can't be used on @Id attributes, otherwise this would be SecureHash - val nodeInfoHash: String, - - @Column(name = "public_key_hash", length = 64) - @Convert(converter = SecureHashAttributeConverter::class) - val publicKeyHash: SecureHash, - - @ManyToOne(optional = false, fetch = FetchType.LAZY) - @JoinColumn(name = "cert_signing_request", nullable = false) - val certificateSigningRequest: CertificateSigningRequestEntity, - - @Lob - @Column(name = "signed_node_info_bytes", nullable = false) - @Convert(converter = SignedNodeInfoConverter::class) - val signedNodeInfo: SignedNodeInfo, - - @Column(name = "is_current", nullable = false) - val isCurrent: Boolean, - - @Column(name = "published_at", nullable = false) - @UpdateTimestamp - val publishedAt: Instant = Instant.now(), - - @ManyToOne(fetch = FetchType.EAGER) - @JoinColumn(name = "accepted_params_update") - val acceptedParametersUpdate: ParametersUpdateEntity? -) : Serializable diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/ParametersUpdateEntity.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/ParametersUpdateEntity.kt deleted file mode 100644 index efdefe897b..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/ParametersUpdateEntity.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.r3.corda.networkmanage.common.persistence.entity - -import net.corda.core.crypto.SecureHash -import net.corda.nodeapi.internal.network.ParametersUpdate -import java.io.Serializable -import java.time.Instant -import javax.persistence.* - -@Entity -@Table(name = "parameters_update") -data class ParametersUpdateEntity( - @Id - @GeneratedValue(strategy = GenerationType.SEQUENCE) - val id: Long? = null, - - // TODO use @MapsId to get rid of additional sequence - @ManyToOne(fetch = FetchType.EAGER, optional = false) - @JoinColumn(name = "network_parameters", foreignKey = ForeignKey(name = "FK__param_up__net_param")) - val networkParameters: NetworkParametersEntity, - - @Column(name = "description", nullable = false) - val description: String, - - @Column(name = "update_deadline", nullable = false) - val updateDeadline: Instant, - - @Column(name = "status", length = 16, nullable = false, columnDefinition = "NVARCHAR(16)") - @Enumerated(EnumType.STRING) - val status: UpdateStatus = UpdateStatus.NEW -) : Serializable { - fun toParametersUpdate(): ParametersUpdate { - return ParametersUpdate(SecureHash.parse(networkParameters.hash), description, updateDeadline) - } -} - -enum class UpdateStatus { - /** A newly created update. */ - NEW, - /** - * An update that has passed its deadline and flagged to be made active on the next signing event. At most only one - * update with status either NEW or FLAG_DAY can exist. - */ - FLAG_DAY, - /** Any previously flagged update that has been activated into the network map. */ - APPLIED, - /** A new or flag day update that has been cancelled. */ - CANCELLED -} - diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/CertificateRevocationListSigner.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/CertificateRevocationListSigner.kt deleted file mode 100644 index 7f3a08300d..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/CertificateRevocationListSigner.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.r3.corda.networkmanage.common.signer - -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationListStorage -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationRequestData -import com.r3.corda.networkmanage.common.persistence.CrlIssuer -import com.r3.corda.networkmanage.common.persistence.RequestStatus -import com.r3.corda.networkmanage.common.utils.Revocation -import com.r3.corda.networkmanage.common.utils.createSignedCrl -import net.corda.core.utilities.contextLogger -import net.corda.core.utilities.debug -import net.corda.core.utilities.trace -import java.net.URL -import java.security.cert.X509CRL -import java.security.cert.X509Certificate -import java.time.Duration -import java.time.Instant -import java.util.* - -class CertificateRevocationListSigner( - private val revocationListStorage: CertificateRevocationListStorage, - private val issuerCertificate: X509Certificate, - private val updateInterval: Duration, - private val endpoint: URL, - private val signer: Signer) { - private companion object { - private val logger = contextLogger() - } - - /** - * Builds, signs and persists a new certificate revocation list. - * It happens only if there are new entries to be added to the current list. - * - * @param newCRRs list of approved certificate revocation requests. An approved certificate revocation request - * is a request that has status [RequestStatus.APPROVED] - i.e. it has not yet been included in any CRL. - * @param existingCRRs list of revoked certificate revocation requests. A revoked certificate revocation request - * is a request that has status [RequestStatus.DONE] - i.e. it has already been included in another CRL. - * @param signedBy who signs this CRL. - * - * @return A new signed CRL containing both revoked and approved certificate revocation requests. - */ - fun createSignedCRL(newCRRs: List, - existingCRRs: List, - signedBy: String): X509CRL { - require(existingCRRs.all { it.status == RequestStatus.DONE }) { "All existing CRRs need to be in the ${RequestStatus.DONE} state" } - require(newCRRs.all { it.status == RequestStatus.APPROVED }) { "All newly included CRRs need to be in the ${RequestStatus.APPROVED} state" } - logger.info("Signing a new Certificate Revocation List...") - logger.debug("Retrieving approved Certificate Revocation Requests...") - val revocationTime = Instant.now() - val approvedWithTimestamp = newCRRs.map { it.copy(modifiedAt = revocationTime) } - logger.trace { "Approved Certificate Revocation Requests to be included in the new Certificate Revocation List: $approvedWithTimestamp" } - logger.debug("Retrieving revoked Certificate Revocation Requests...") - logger.trace { "Revoked Certificate Revocation Requests to be included in the new Certificate Revocation List: $existingCRRs" } - val revocations = (existingCRRs + approvedWithTimestamp).map { - Revocation(it.certificateSerialNumber, Date(it.modifiedAt.toEpochMilli()), it.reason) - } - val crl = createSignedCrl(issuerCertificate, endpoint, updateInterval, signer, revocations) - logger.debug { "Created a new Certificate Revocation List $crl" } - revocationListStorage.saveCertificateRevocationList(crl, CrlIssuer.DOORMAN, signedBy, revocationTime) - logger.info("A new Certificate Revocation List has been persisted.") - return crl - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSigner.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSigner.kt deleted file mode 100644 index 7fc38f29a5..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSigner.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.signer - -import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage -import com.r3.corda.networkmanage.common.persistence.entity.NetworkMapEntity -import com.r3.corda.networkmanage.common.persistence.entity.UpdateStatus.FLAG_DAY -import com.r3.corda.networkmanage.common.persistence.entity.UpdateStatus.NEW -import com.r3.corda.networkmanage.common.utils.join -import net.corda.core.crypto.SecureHash -import net.corda.core.node.NetworkParameters -import net.corda.core.utilities.contextLogger -import net.corda.core.utilities.debug -import net.corda.nodeapi.internal.network.NetworkMap -import net.corda.nodeapi.internal.network.NetworkMapAndSigned -import net.corda.nodeapi.internal.network.ParametersUpdate - -class NetworkMapSigner(private val networkMapStorage: NetworkMapStorage, private val signer: Signer) { - private companion object { - val logger = contextLogger() - } - - /** - * Signs the network map and latest network parameters if they haven't been signed yet. - */ - fun signNetworkMaps() { - val (publicNetworkMap, privateNetworkMaps) = networkMapStorage.getNetworkMaps() - val (publicNodeInfoHashes, privateNodeInfoHashes) = networkMapStorage.getNodeInfoHashes() - - val (networkParameterHash, parametersUpdate) = maybeUpdateNetworkParameters(publicNetworkMap?.networkMap?.networkParameterHash) - logger.debug { "Current network parameters: $networkParameterHash" } - - // Process public network map. - maybeSignNetworkMap(publicNetworkMap, publicNodeInfoHashes, parametersUpdate, networkParameterHash) - - // Process each private network map. - privateNetworkMaps.join(privateNodeInfoHashes).forEach { networkId, (currentNetworkMap, nodeInfoHashes) -> - maybeSignNetworkMap(currentNetworkMap, nodeInfoHashes, parametersUpdate, networkParameterHash, networkId) - } - } - - private fun maybeSignNetworkMap(currentNetworkMap: NetworkMapEntity?, nodeInfoHashes: List?, parametersUpdate: ParametersUpdate?, networkParameterHash: SecureHash, networkId: String? = null) { - val printableNetworkId = networkId ?: "Public Network" - if (currentNetworkMap == null) { - logger.info("There is currently no network map for network '$printableNetworkId'") - } else { - logger.debug { "Current network map for network '$printableNetworkId': ${currentNetworkMap.networkMap}" } - } - - logger.debug { "Retrieved node info hashes for network '$printableNetworkId' :\n${nodeInfoHashes?.joinToString("\n")}" } - - val newNetworkMap = NetworkMap(nodeInfoHashes ?: emptyList(), networkParameterHash, parametersUpdate) - logger.debug { "Potential new network map for network '$printableNetworkId': $newNetworkMap" } - - if (currentNetworkMap?.networkMap != newNetworkMap) { - val newNetworkMapAndSigned = NetworkMapAndSigned(newNetworkMap) { signer.signBytes(it.bytes) } - networkMapStorage.saveNewNetworkMap(networkId, newNetworkMapAndSigned) - logger.info("Signed new network map for network '$printableNetworkId' : $newNetworkMap") - } else { - logger.debug("Current network map for network '$printableNetworkId' is up-to-date") - } - } - - private fun maybeUpdateNetworkParameters(currentNetworkParametersHash: SecureHash?): Pair { - val latestNetworkParameters = requireNotNull(networkMapStorage.getLatestNetworkParameters()) { "No network parameters present" } - logger.debug { "Retrieved latest network parameters: ${latestNetworkParameters.networkParameters}" } - - val parametersUpdate = networkMapStorage.getCurrentParametersUpdate() - logger.debug { "Retrieved parameters update: $parametersUpdate" } - check(parametersUpdate == null || parametersUpdate.networkParameters.hash == latestNetworkParameters.hash) { - "The latest network parameters are not the scheduled updated ones" - } - - // We persist signed parameters only if they were not persisted before (they are not in currentSignedNetworkMap as - // normal parameters or as an update) - if (!latestNetworkParameters.isSigned) { - signAndPersistNetworkParameters(latestNetworkParameters.networkParameters) - } else { - logger.debug { "No need to sign any network parameters as they're up-to-date" } - } - - val parametersToNetworkMap = if (parametersUpdate?.status == FLAG_DAY || currentNetworkParametersHash == null) { - parametersUpdate?.let { networkMapStorage.switchFlagDay(it) } - SecureHash.parse(latestNetworkParameters.hash) - } else { - currentNetworkParametersHash - } - - return Pair(parametersToNetworkMap, parametersUpdate?.let { if (it.status == NEW) it.toParametersUpdate() else null }) - } - - fun signAndPersistNetworkParameters(networkParameters: NetworkParameters) { - networkMapStorage.saveNetworkParameters(networkParameters, signer.signObject(networkParameters).sig) - logger.info("Signed network parameters: $networkParameters") - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/Signer.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/Signer.kt deleted file mode 100644 index 223ef775b3..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/Signer.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.signer - -import net.corda.core.internal.DigitalSignatureWithCert -import net.corda.core.internal.SignedDataWithCert -import net.corda.core.serialization.serialize - -/** - * An interface for arbitrary data signing functionality. - */ -interface Signer { - /** - * Signs given bytes. The signing key selection strategy is left to the implementing class. - * @return [DigitalSignatureWithCert] that encapsulates the signature and the certificate path used in the signing process. - * @throws [AuthenticationException] if fails authentication - */ - fun signBytes(data: ByteArray): DigitalSignatureWithCert - - fun signObject(obj: T): SignedDataWithCert { - val serialised = obj.serialize() - return SignedDataWithCert(serialised, signBytes(serialised.bytes)) - } -} - -class AuthenticationException : Exception() diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/sockets/CertificateRevocationListSubmission.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/sockets/CertificateRevocationListSubmission.kt deleted file mode 100644 index 5e11c50a45..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/sockets/CertificateRevocationListSubmission.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.r3.corda.networkmanage.common.sockets - -import net.corda.core.serialization.CordaSerializable -import java.security.cert.X509CRL -import java.time.Instant - -@CordaSerializable -data class CertificateRevocationListSubmission(val list: X509CRL, - val signer: String, - val revocationTime: Instant) \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/sockets/CrrSocketMessage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/sockets/CrrSocketMessage.kt deleted file mode 100644 index 6212e86b4b..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/sockets/CrrSocketMessage.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.r3.corda.networkmanage.common.sockets - -import com.r3.corda.networkmanage.common.persistence.RequestStatus -import net.corda.core.serialization.CordaSerializable -import java.security.cert.X509CRL - -@CordaSerializable -interface CrrSocketMessage - -/** - * CRL retrieval message type - */ -class CrlRetrievalMessage : CrrSocketMessage - -/** - * CRL response message type - */ -data class CrlResponseMessage(val crl: X509CRL?) : CrrSocketMessage - -/** - * CRL submission message type - */ -class CrlSubmissionMessage : CrrSocketMessage - -/** - * By status CRRs retrieval message type - */ -data class CrrsByStatusMessage(val status: RequestStatus) : CrrSocketMessage \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/AMQPNetworkServicesSerializationScheme.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/AMQPNetworkServicesSerializationScheme.kt deleted file mode 100644 index eb22a2725d..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/AMQPNetworkServicesSerializationScheme.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.r3.corda.networkmanage.common.utils - -import net.corda.core.serialization.ClassWhitelist -import net.corda.core.serialization.SerializationContext -import net.corda.core.serialization.SerializationCustomSerializer -import net.corda.serialization.internal.CordaSerializationMagic -import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme -import net.corda.serialization.internal.amqp.SerializerFactory -import net.corda.serialization.internal.amqp.amqpMagic -import java.util.concurrent.ConcurrentHashMap - -class AMQPNetworkServicesSerializationScheme ( - cordappCustomSerializers: Set>, - serializerFactoriesForContexts: MutableMap, SerializerFactory> - ) : AbstractAMQPSerializationScheme(cordappCustomSerializers, serializerFactoriesForContexts) { - - constructor() : this(emptySet(), ConcurrentHashMap()) - - override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory { - throw UnsupportedOperationException() - } - - override fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory { - throw UnsupportedOperationException() - } - - override fun canDeserializeVersion(magic: CordaSerializationMagic, target: SerializationContext.UseCase) = - (magic == amqpMagic && target == SerializationContext.UseCase.P2P) -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/ArgsParser.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/ArgsParser.kt deleted file mode 100644 index 02006b467d..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/ArgsParser.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.r3.corda.networkmanage.common.utils - -import joptsimple.OptionException -import joptsimple.OptionParser -import joptsimple.OptionSet -import java.io.PrintStream -import kotlin.system.exitProcess - -// TODO: This class could be useful for the rest of the codebase. -abstract class ArgsParser { - protected val optionParser = OptionParser() - private val helpOption = optionParser.acceptsAll(listOf("h", "help"), "show help").forHelp() - - /** - If [printHelpOn] output stream is not null, this method will print help message and exit process - when encountered any error during args parsing, or when help flag is set. - */ - fun parseOrExit(vararg args: String, printHelpOn: PrintStream? = System.out): T { - val optionSet = try { - optionParser.parse(*args) - } catch (e: OptionException) { - printHelpOn?.let { - it.println(e.message ?: "Unable to parse arguments.") - optionParser.printHelpOn(it) - exitProcess(1) - } - throw e - } - - if (optionSet.has(helpOption)) { - printHelpOn?.let(optionParser::printHelpOn) - exitProcess(0) - } - - return try { - parse(optionSet) - } catch (e: RuntimeException) { - // We handle errors from the parsing of the command line arguments as a runtime - // exception because the joptsimple library is overly helpful and doesn't expose - // parsing / conversion exceptions in a way that makes reporting the message out - // to the user possible. Thus, that library is re-throwing those exceptions as simple - // runtime exceptions with a modified cause to preserve the error location - printHelpOn?.let { - it.println("ERROR: ${e.message ?: "Unable to parse arguments."}") - exitProcess(2) - } - throw e - } - } - - protected abstract fun parse(optionSet: OptionSet): T -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/CrlUtils.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/CrlUtils.kt deleted file mode 100644 index cbea01a593..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/CrlUtils.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.r3.corda.networkmanage.common.utils - -import com.r3.corda.networkmanage.common.signer.Signer -import net.corda.nodeapi.internal.crypto.X509Utilities -import org.bouncycastle.asn1.x500.X500Name -import org.bouncycastle.asn1.x509.* -import org.bouncycastle.cert.X509v2CRLBuilder -import org.bouncycastle.cert.jcajce.JcaX509CRLConverter -import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils -import org.bouncycastle.jce.provider.BouncyCastleProvider -import org.bouncycastle.operator.ContentSigner -import java.io.ByteArrayOutputStream -import java.io.OutputStream -import java.math.BigInteger -import java.net.URL -import java.security.cert.CRLReason -import java.security.cert.X509CRL -import java.security.cert.X509Certificate -import java.time.Duration -import java.time.Instant -import java.util.* - -fun createSignedCrl(issuerCertificate: X509Certificate, - endpointUrl: URL, - nextUpdateInterval: Duration, - signer: Signer, - includeInCrl: List, - indirectIssuingPoint: Boolean = false): X509CRL { - val extensionUtils = JcaX509ExtensionUtils() - val builder = X509v2CRLBuilder(X500Name.getInstance(issuerCertificate.subjectX500Principal.encoded), Date()) - builder.addExtension(Extension.authorityKeyIdentifier, false, extensionUtils.createAuthorityKeyIdentifier(issuerCertificate)) - val issuingDistributionPointName = GeneralName(GeneralName.uniformResourceIdentifier, endpointUrl.toString()) - val issuingDistributionPoint = IssuingDistributionPoint(DistributionPointName(GeneralNames(issuingDistributionPointName)), indirectIssuingPoint, false) - builder.addExtension(Extension.issuingDistributionPoint, true, issuingDistributionPoint) - builder.setNextUpdate(Date(Instant.now().toEpochMilli() + nextUpdateInterval.toMillis())) - includeInCrl.forEach { - builder.addCRLEntry(it.certificateSerialNumber, it.date, it.reason.ordinal) - } - val crlHolder = builder.build(CrlContentSigner(signer)) - return JcaX509CRLConverter().setProvider(BouncyCastleProvider()).getCRL(crlHolder) -} - -data class Revocation(val certificateSerialNumber: BigInteger, val date: Date, val reason: CRLReason) - -private class CrlContentSigner(private val signer: Signer) : ContentSigner { - - private val outputStream = ByteArrayOutputStream() - - override fun getAlgorithmIdentifier(): AlgorithmIdentifier = X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME.signatureOID - override fun getOutputStream(): OutputStream = outputStream - override fun getSignature(): ByteArray = signer.signBytes(outputStream.toByteArray()).bytes -} - -enum class SupportedCrlReasons { - UNSPECIFIED, - KEY_COMPROMISE, - CA_COMPROMISE, - AFFILIATION_CHANGED, - SUPERSEDED, - CESSATION_OF_OPERATION, - PRIVILEGE_WITHDRAWN -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/SocketUtils.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/SocketUtils.kt deleted file mode 100644 index 540f1f3d06..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/SocketUtils.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.r3.corda.networkmanage.common.utils - -import net.corda.core.serialization.deserialize -import net.corda.core.serialization.serialize -import java.io.DataInputStream -import java.io.DataOutputStream -import java.io.InputStream -import java.io.OutputStream - -inline fun InputStream.readObject(): T { - DataInputStream(this).run { - val messageSize = this.readInt() - val messageBytes = ByteArray(messageSize) - this.read(messageBytes) - return messageBytes.deserialize() - } -} - -fun OutputStream.writeObject(message: Any) { - DataOutputStream(this).run { - val messageBytes = message.serialize().bytes - this.writeInt(messageBytes.size) - this.write(messageBytes) - this.flush() - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/Utils.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/Utils.kt deleted file mode 100644 index 35faf66066..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/Utils.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.utils - -import com.typesafe.config.ConfigFactory -import com.typesafe.config.ConfigParseOptions -import com.typesafe.config.ConfigRenderOptions -import net.corda.core.CordaOID -import net.corda.core.internal.CertRole -import net.corda.core.serialization.internal.SerializationEnvironmentImpl -import net.corda.core.serialization.internal.nodeSerializationEnv -import net.corda.nodeapi.internal.config.UnknownConfigKeysPolicy -import net.corda.nodeapi.internal.config.parseAs -import net.corda.nodeapi.internal.crypto.X509CertificateFactory -import net.corda.nodeapi.internal.crypto.X509KeyStore -import net.corda.serialization.internal.AMQP_P2P_CONTEXT -import net.corda.serialization.internal.SerializationFactoryImpl -import org.bouncycastle.asn1.ASN1Encodable -import org.bouncycastle.asn1.ASN1ObjectIdentifier -import org.bouncycastle.asn1.x500.style.BCStyle -import org.bouncycastle.pkcs.PKCS10CertificationRequest -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import java.nio.file.Path -import java.security.KeyPair -import java.security.PrivateKey -import java.security.cert.CertPath -import java.security.cert.X509Certificate - -const val CORDA_NETWORK_MAP = "cordanetworkmap" -const val NETWORK_ROOT_TRUSTSTORE_FILENAME = "network-root-truststore.jks" - -val logger: Logger = LoggerFactory.getLogger("com.r3.corda.networkmanage.common.utils") - -data class CertPathAndKey(val certPath: List, val key: PrivateKey) { - fun toKeyPair(): KeyPair = KeyPair(certPath[0].publicKey, key) -} - -inline fun parseConfig(file: Path): T { - val config = ConfigFactory.parseFile(file.toFile(), ConfigParseOptions.defaults().setAllowMissing(true)).resolve() - logger.info(config.root().render(ConfigRenderOptions.defaults())) - return config.parseAs(UnknownConfigKeysPolicy.IGNORE::handle) -} - -fun buildCertPath(certPathBytes: ByteArray): CertPath = X509CertificateFactory().delegate.generateCertPath(certPathBytes.inputStream()) - -fun X509KeyStore.getCertPathAndKey(alias: String, privateKeyPassword: String): CertPathAndKey { - return CertPathAndKey(getCertificateChain(alias), getPrivateKey(alias, privateKeyPassword)) -} - -fun initialiseSerialization() { - val context = AMQP_P2P_CONTEXT - nodeSerializationEnv = SerializationEnvironmentImpl( - SerializationFactoryImpl().apply { - registerScheme(AMQPNetworkServicesSerializationScheme()) - }, - context) -} - -private fun PKCS10CertificationRequest.firstAttributeValue(identifier: ASN1ObjectIdentifier): ASN1Encodable? { - return getAttributes(identifier).firstOrNull()?.attrValues?.firstOrNull() -} - -/** - * Helper method to extract cert role from certificate signing request. Default to NODE_CA if not exist for backward compatibility. - */ -fun PKCS10CertificationRequest.getCertRole(): CertRole { - // Default cert role to Node_CA for backward compatibility. - val encoded = firstAttributeValue(ASN1ObjectIdentifier(CordaOID.X509_EXTENSION_CORDA_ROLE))?.toASN1Primitive()?.encoded ?: return CertRole.NODE_CA - return CertRole.getInstance(encoded) -} - -/** - * Helper method to extract email from certificate signing request. - */ -fun PKCS10CertificationRequest.getEmail(): String = firstAttributeValue(BCStyle.E).toString() - -fun Map.join(otherMap: Map): Map> = (keys + otherMap.keys).map { it to Pair(get(it), otherMap[it]) }.toMap() diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/dev/Configuration.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/dev/Configuration.kt deleted file mode 100644 index 70b5aa332a..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/dev/Configuration.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.dev - -import com.typesafe.config.ConfigFactory -import com.typesafe.config.ConfigParseOptions -import net.corda.nodeapi.internal.* -import net.corda.nodeapi.internal.config.parseAs -import java.io.File -import java.nio.file.Path - -/** - * Holds configuration necessary for generating DEV key store and trust store. - */ -data class GeneratorConfiguration(val privateKeyPass: String = DEV_CA_PRIVATE_KEY_PASS, - val keyStorePass: String = DEV_CA_KEY_STORE_PASS, - val keyStoreFileName: String = DEV_CA_KEY_STORE_FILE, - val trustStorePass: String = DEV_CA_TRUST_STORE_PASS, - val trustStoreFileName: String = DEV_CA_TRUST_STORE_FILE, - val directory: Path = DEFAULT_DIRECTORY) { - companion object { - val DEFAULT_DIRECTORY = File("./certificates").toPath() - } -} - -/** - * Parses a configuration file, which contains all the configuration - i.e. for the key store generator. - */ -fun parseParameters(configFile: Path?): GeneratorConfiguration { - return if (configFile == null) { - GeneratorConfiguration() - } else { - ConfigFactory.parseFile(configFile.toFile(), ConfigParseOptions.defaults().setAllowMissing(true)) - .resolve() - .parseAs() - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/dev/Main.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/dev/Main.kt deleted file mode 100644 index 1644010a86..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/dev/Main.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.dev - -import com.r3.corda.networkmanage.common.configuration.ConfigFilePathArgsParser -import com.r3.corda.networkmanage.doorman.CORDA_X500_BASE -import net.corda.core.crypto.Crypto -import net.corda.core.internal.createDirectories -import net.corda.core.internal.div -import net.corda.nodeapi.internal.crypto.CertificateType -import net.corda.nodeapi.internal.crypto.X509KeyStore -import net.corda.nodeapi.internal.crypto.X509Utilities -import org.apache.logging.log4j.LogManager -import java.io.File -import javax.security.auth.x500.X500Principal -import kotlin.system.exitProcess - -private val logger = LogManager.getLogger("com.r3.corda.networkmanage.dev.Main") - -/** - * This is an internal utility method used to generate a DEV certificate store file containing both root and doorman keys/certificates. - * Additionally, it generates a trust file containing the root certificate. - * - * Note: It can be quickly executed in IntelliJ by right-click on the main method. It will generate the keystore and the trustore - * with settings expected by node running in the dev mode. The files will be generated in the root project directory. - * Look for the 'certificates' directory. - */ -fun main(args: Array) { - run(parseParameters(ConfigFilePathArgsParser().parseOrExit(*args))) -} - -fun run(configuration: GeneratorConfiguration) { - configuration.run { - val keyStoreFile = File("$directory/$keyStoreFileName").toPath() - keyStoreFile.parent.createDirectories() - val keyStore = X509KeyStore.fromFile(keyStoreFile, keyStorePass, createNew = true) - - checkCertificateNotInKeyStore(X509Utilities.CORDA_ROOT_CA, keyStore) { exitProcess(1) } - checkCertificateNotInKeyStore(X509Utilities.CORDA_INTERMEDIATE_CA, keyStore) { exitProcess(1) } - - val rootKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) - val rootCert = X509Utilities.createSelfSignedCACertificate( - X500Principal("CN=Corda Root CA,$CORDA_X500_BASE"), - rootKeyPair) - keyStore.update { - setPrivateKey(X509Utilities.CORDA_ROOT_CA, rootKeyPair.private, listOf(rootCert), privateKeyPass) - } - logger.info("Root CA keypair and certificate stored in ${keyStoreFile.toAbsolutePath()}.") - logger.info(rootCert) - - val trustStorePath = directory / trustStoreFileName - X509KeyStore.fromFile(trustStorePath, trustStorePass, createNew = true).update { - setCertificate(X509Utilities.CORDA_ROOT_CA, rootCert) - } - logger.info("Trust store for distribution to nodes created in $trustStorePath") - - val doormanKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) - val cert = X509Utilities.createCertificate( - CertificateType.INTERMEDIATE_CA, - rootCert, - rootKeyPair, - X500Principal("CN=Corda Doorman CA,$CORDA_X500_BASE"), - doormanKeyPair.public - ) - keyStore.update { - setPrivateKey(X509Utilities.CORDA_INTERMEDIATE_CA, doormanKeyPair.private, listOf(cert, rootCert), privateKeyPass) - } - logger.info("Doorman CA keypair and certificate stored in ${keyStoreFile.toAbsolutePath()}.") - logger.info(cert) - } -} - -private fun checkCertificateNotInKeyStore(certAlias: String, keyStore: X509KeyStore, onFail: () -> Unit) { - if (certAlias in keyStore) { - logger.info("$certAlias already exists in keystore, process will now terminate.") - logger.info(keyStore.getCertificate(certAlias)) - onFail.invoke() - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/CrrJiraCient.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/CrrJiraCient.kt deleted file mode 100644 index 9430020f72..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/CrrJiraCient.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman - -import com.atlassian.jira.rest.client.api.JiraRestClient -import com.atlassian.jira.rest.client.api.domain.input.IssueInputBuilder -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationRequestData -import net.corda.core.identity.CordaX500Name - -class CrrJiraClient(restClient: JiraRestClient, projectCode: String) : JiraClient(restClient, projectCode) { - fun createCertificateRevocationRequestTicket(revocationRequest: CertificateRevocationRequestData) { - val ticketDescription = "Legal name: ${revocationRequest.legalName}\n" + - "Certificate serial number: ${revocationRequest.certificateSerialNumber}\n" + - "Revocation reason: ${revocationRequest.reason.name}\n" + - "Reporter: ${revocationRequest.reporter}\n" + - "Original CSR request ID: ${revocationRequest.certificateSigningRequestId}" - - val subject = CordaX500Name.build(revocationRequest.certificate.subjectX500Principal) - val ticketSummary = if (subject.organisationUnit != null) { - "${subject.organisationUnit}, ${subject.organisation}" - } else { - subject.organisation - } - - val issue = IssueInputBuilder().setIssueTypeId(taskIssueType.id) - .setProjectKey(projectCode) - .setDescription(ticketDescription) - .setSummary(ticketSummary) - .setFieldValue(requestIdField.id, revocationRequest.requestId) - - val attachment = Pair("${revocationRequest.certificateSerialNumber}.cer", revocationRequest.certificate.encoded.inputStream()) - createJiraTicket(revocationRequest.requestId, issue.build(), attachment) - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/CsrJiraCient.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/CsrJiraCient.kt deleted file mode 100644 index 0737292ee5..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/CsrJiraCient.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman - -import com.atlassian.jira.rest.client.api.JiraRestClient -import com.atlassian.jira.rest.client.api.domain.input.IssueInputBuilder -import com.r3.corda.networkmanage.common.utils.getCertRole -import com.r3.corda.networkmanage.common.utils.getEmail -import net.corda.core.identity.CordaX500Name -import org.bouncycastle.openssl.jcajce.JcaPEMWriter -import org.bouncycastle.pkcs.PKCS10CertificationRequest -import org.bouncycastle.util.io.pem.PemObject -import java.io.StringWriter -import javax.security.auth.x500.X500Principal - -class CsrJiraClient(restClient: JiraRestClient, projectCode: String) : JiraClient(restClient, projectCode) { - fun createCertificateSigningRequestTicket(requestData: CertificationRequestData) { - val (requestId, signingRequest) = requestData - - // TODO The subject of the signing request has already been validated and parsed into a CordaX500Name. We shouldn't - // have to do it again here. - val subject = CordaX500Name.build(X500Principal(signingRequest.subject.encoded)) - - val ticketSummary = if (subject.organisationUnit != null) { - "${subject.organisationUnit}, ${subject.organisation}" - } else { - subject.organisation - } - - val data = mapOf( - "Requested Role Type" to signingRequest.getCertRole().name, - "Common Name" to subject.commonName, - "Organisation" to subject.organisation, - "Organisation Unit" to subject.organisationUnit, - "State" to subject.state, - "Nearest City" to subject.locality, - "Country" to subject.country, - "Email" to signingRequest.getEmail(), - "X500 Name" to subject.toString()) - - val requestPemString = StringWriter().apply { - JcaPEMWriter(this).use { - it.writeObject(PemObject("CERTIFICATE REQUEST", signingRequest.encoded)) - } - }.toString() - - val ticketDescription = data.filter { it.value != null }.map { "${it.key}: ${it.value}" }.joinToString("\n") + "\n\n{code}$requestPemString{code}" - - val issue = IssueInputBuilder().setIssueTypeId(taskIssueType.id) - .setProjectKey(projectCode) - .setDescription(ticketDescription) - .setSummary(ticketSummary) - .setFieldValue(requestIdField.id, requestId) - - createJiraTicket(requestId, issue.build()) - } -} - -// TODO: Parse PKCS10 request. -data class CertificationRequestData(val requestId: String, val rawRequest: PKCS10CertificationRequest) - - diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/DoormanArgsParser.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/DoormanArgsParser.kt deleted file mode 100644 index c15d32d8ff..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/DoormanArgsParser.kt +++ /dev/null @@ -1,135 +0,0 @@ -package com.r3.corda.networkmanage.doorman - -import com.google.common.primitives.Booleans -import com.r3.corda.networkmanage.common.utils.ArgsParser -import joptsimple.OptionException -import joptsimple.OptionSet -import joptsimple.util.EnumConverter -import joptsimple.util.PathConverter -import joptsimple.util.PathProperties -import net.corda.core.node.NetworkParameters -import net.corda.core.node.NotaryInfo -import net.corda.core.utilities.days -import java.nio.file.Path -import java.time.Instant - -class DoormanArgsParser : ArgsParser() { - private val configFileArg = optionParser - .accepts("config-file", "The path to the config file") - .withRequiredArg() - .withValuesConvertedBy(PathConverter(PathProperties.FILE_EXISTING)) - .required() - private val modeArg = optionParser - .accepts("mode", "Set the mode of this application") - .withRequiredArg() - .withValuesConvertedBy(object : EnumConverter(Mode::class.java) {}) - .defaultsTo(Mode.DOORMAN) - private val setNetworkParametersArg = optionParser - .accepts("set-network-parameters", "Set the network parameters using the given file. This can be for either the initial set or to schedule an update.") - .withRequiredArg() - .withValuesConvertedBy(PathConverter(PathProperties.FILE_EXISTING)) - private val flagDayArg = optionParser.accepts("flag-day", "Roll over the scheduled network parameters to be the current.") - private val cancelUpdateArg = optionParser.accepts("cancel-update", "Cancel the scheduled update of the network parameters.") - private val trustStorePasswordArg = optionParser - .accepts("trust-store-password", "Password for the generated network root trust store. Only applicable when operating in ${Mode.ROOT_KEYGEN} mode.") - .withRequiredArg() - - override fun parse(optionSet: OptionSet): DoormanCmdLineOptions { - val configFile = try { - optionSet.valueOf(configFileArg) - } catch (e: OptionException) { - throw RuntimeException("Specified config file doesn't exist").apply { - initCause(e.cause) - } - } - - val mode = try { - optionSet.valueOf(modeArg) - } catch (e: OptionException) { - throw RuntimeException( - "Unknown mode specified, valid options are [${Mode.values().joinToString(", ")}]" - ).apply { - initCause(e.cause) - } - } - - val setNetworkParametersFile = optionSet.valueOf(setNetworkParametersArg) - val flagDay = optionSet.has(flagDayArg) - val cancelUpdate = optionSet.has(cancelUpdateArg) - require(Booleans.countTrue(setNetworkParametersFile != null, flagDay, cancelUpdate) <= 1) { - "Only one of $setNetworkParametersArg, $flagDay and $cancelUpdate can be specified" - } - val trustStorePassword = optionSet.valueOf(trustStorePasswordArg) - return DoormanCmdLineOptions(configFile, mode, trustStorePassword, setNetworkParametersFile, flagDay, cancelUpdate) - } -} - -data class DoormanCmdLineOptions(val configFile: Path, - val mode: Mode, - val trustStorePassword: String?, - val setNetworkParametersFile: Path?, - val flagDay: Boolean, - val cancelUpdate: Boolean -) { - init { - // Make sure trust store password is only specified in root keygen mode. - if (mode != Mode.ROOT_KEYGEN) { - require(trustStorePassword == null) { "Trust store password should not be specified in this mode." } - } - } -} - -sealed class NetworkParametersCmd { - /** - * This is the same as [NetworkParametersConfig] but instead of using [NotaryConfig] it uses the simpler to test with - * [NotaryInfo]. - */ - data class Set(val minimumPlatformVersion: Int, - val notaries: List, - val maxMessageSize: Int, - val maxTransactionSize: Int, - val eventHorizonDays: Int, - val parametersUpdate: ParametersUpdateConfig? - ) : NetworkParametersCmd() { - companion object { - fun fromConfig(config: NetworkParametersConfig): Set { - return Set( - config.minimumPlatformVersion, - config.notaries.map { it.toNotaryInfo() }, - config.maxMessageSize, - config.maxTransactionSize, - config.eventHorizonDays, - config.parametersUpdate - ) - } - } - - fun checkCompatibility(currentNetParams: NetworkParameters) { - // TODO Comment it out when maxMessageSize is properly wired -// require(previousParameters.maxMessageSize <= newParameters.maxMessageSize) { "maxMessageSize can only increase" } - require(maxTransactionSize >= currentNetParams.maxTransactionSize) { "maxTransactionSize can only increase" } - val removedNames = currentNetParams.notaries.map { it.identity.name } - notaries.map { it.identity.name } - require(removedNames.isEmpty()) { "notaries cannot be removed: $removedNames" } - val removedKeys = currentNetParams.notaries.map { it.identity.owningKey } - notaries.map { it.identity.owningKey } - require(removedKeys.isEmpty()) { "notaries cannot be removed: $removedKeys" } - } - - fun toNetworkParameters(modifiedTime: Instant, epoch: Int): NetworkParameters { - return NetworkParameters( - minimumPlatformVersion, - notaries, - maxMessageSize, - maxTransactionSize, - modifiedTime, - epoch, - // TODO: Tudor, Michal - pass the actual network parameters where we figure out how - emptyMap(), - eventHorizonDays.days - ) - } - } - - object FlagDay : NetworkParametersCmd() - - object CancelUpdate : NetworkParametersCmd() -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/DoormanParameters.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/DoormanParameters.kt deleted file mode 100644 index 088d9d14dc..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/DoormanParameters.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman - -import com.google.common.primitives.Booleans -import net.corda.core.internal.div -import net.corda.core.utilities.NetworkHostAndPort -import net.corda.core.utilities.seconds -import net.corda.nodeapi.internal.config.OldConfig -import net.corda.nodeapi.internal.persistence.DatabaseConfig -import java.net.URL -import java.nio.file.Path -import java.util.* - -data class NetworkManagementServerConfig( // TODO: Move local signing to signing server. - val address: NetworkHostAndPort, - val dataSourceProperties: Properties, - @OldConfig("databaseConfig") - val database: DatabaseConfig = DatabaseConfig(), - - @OldConfig("doormanConfig") - val doorman: DoormanConfig?, - @OldConfig("networkMapConfig") - val networkMap: NetworkMapConfig?, - val revocation: CertificateRevocationConfig?, - - // TODO Should be part of a localSigning sub-config - val keystorePath: Path? = null, - // TODO Should be part of a localSigning sub-config - val rootStorePath: Path? = null, - val keystorePassword: String?, - // TODO Should be part of a localSigning sub-config - val caPrivateKeyPassword: String?, - // TODO Should be part of a localSigning sub-config - val rootKeystorePassword: String?, - // TODO Should be part of a localSigning sub-config - val rootPrivateKeyPassword: String?, - // TODO Should be part of a localSigning sub-config - val caCrlPath: Path? = null, - // TODO Should be part of a localSigning sub-config - val caCrlUrl: URL? = null, - // TODO Should be part of a localSigning sub-config - val emptyCrlPath: Path? = null, - // TODO Should be part of a localSigning sub-config - val emptyCrlUrl: URL? = null -) { - companion object { - // TODO: Do we really need these defaults? - val DEFAULT_APPROVE_INTERVAL = 5.seconds - val DEFAULT_SIGN_INTERVAL = 5.seconds - } -} - -data class DoormanConfig(val approveAll: Boolean = false, - @OldConfig("jiraConfig") - val jira: JiraConfig? = null, - val crlEndpoint: URL? = null, - val approveInterval: Long = NetworkManagementServerConfig.DEFAULT_APPROVE_INTERVAL.toMillis()) { - init { - require(Booleans.countTrue(approveAll, jira != null) == 1) { - "Either 'approveAll' or 'jira' config settings need to be specified but not both" - } - } -} - -data class CertificateRevocationConfig(val approveAll: Boolean = false, - val jira: JiraConfig? = null, - val localSigning: LocalSigning?, - val crlCacheTimeout: Long, - val caCrlPath: Path, - val emptyCrlPath: Path, - val approveInterval: Long = NetworkManagementServerConfig.DEFAULT_APPROVE_INTERVAL.toMillis()) { - init { - require(Booleans.countTrue(approveAll, jira != null) == 1) { - "Either 'approveAll' or 'jira' config settings need to be specified but not both" - } - } - - data class LocalSigning(val crlUpdateInterval: Long, - val crlEndpoint: URL) -} - -data class NetworkMapConfig(val cacheTimeout: Long, - // TODO: Move signing to signing server. - val signInterval: Long = NetworkManagementServerConfig.DEFAULT_SIGN_INTERVAL.toMillis()) - -enum class Mode { - // TODO CA_KEYGEN now also generates the network map cert, so it should be renamed. - DOORMAN, - CA_KEYGEN, - ROOT_KEYGEN -} - -data class JiraConfig( - val address: String, - val projectCode: String, - val username: String, - val password: String -) diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/JiraCient.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/JiraCient.kt deleted file mode 100644 index dde9586b5b..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/JiraCient.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman - -import com.atlassian.jira.rest.client.api.IssueRestClient -import com.atlassian.jira.rest.client.api.JiraRestClient -import com.atlassian.jira.rest.client.api.domain.Comment -import com.atlassian.jira.rest.client.api.domain.Field -import com.atlassian.jira.rest.client.api.domain.Issue -import com.atlassian.jira.rest.client.api.domain.IssueType -import com.atlassian.jira.rest.client.api.domain.input.IssueInput -import com.atlassian.jira.rest.client.api.domain.input.TransitionInput -import com.r3.corda.networkmanage.doorman.JiraConstant.DONE_TRANSITION_KEY -import com.r3.corda.networkmanage.doorman.JiraConstant.START_TRANSITION_KEY -import com.r3.corda.networkmanage.doorman.JiraConstant.STOP_TRANSITION_KEY -import net.corda.core.internal.ConcurrentBox -import net.corda.core.utilities.contextLogger -import org.slf4j.Logger -import java.io.InputStream - -/** - * The Jira client class manages concurrent access to the [JiraRestClient] to ensure atomic read and write for some operations to prevent race condition. - */ -abstract class JiraClient(restClient: JiraRestClient, protected val projectCode: String) { - companion object { - val logger = contextLogger() - } - - private val restClientLock = ConcurrentBox(restClient) - - // The JIRA project must have a Request ID and reject reason field, and the Task issue type. - protected val requestIdField: Field = requireNotNull(restClient.metadataClient.fields.claim().find { it.name == "Request ID" }) { "Request ID field not found in JIRA '$projectCode'" } - protected val taskIssueType: IssueType = requireNotNull(restClient.metadataClient.issueTypes.claim().find { it.name == "Task" }) { "Task issue type field not found in JIRA '$projectCode'" } - private val rejectReasonField: Field = requireNotNull(restClient.metadataClient.fields.claim().find { it.name == "Reject Reason" }) { "Reject Reason field not found in JIRA '$projectCode'" } - - private val transitions = mutableMapOf() - - fun getApprovedRequests(): List { - return restClientLock.concurrent { - val issues = searchClient.searchJql("project = $projectCode AND status = Approved").claim().issues - issues.mapNotNull { issue -> - val requestId = requireNotNull(issue.getField(requestIdField.id)?.value?.toString()) { "Error processing request '${issue.key}' : RequestId cannot be null." } - // Issue retrieved via search doesn't contain change logs. - val fullIssue = issueClient.getIssue(issue.key, listOf(IssueRestClient.Expandos.CHANGELOG)).claim() - val approvedBy = fullIssue.changelog?.last { it.items.any { it.field == "status" && it.toString == "Approved" } } - ApprovedRequest(requestId, approvedBy?.author?.displayName ?: "Unknown") - } - } - } - - fun getRejectedRequests(): List { - return restClientLock.concurrent { - val issues = searchClient.searchJql("project = $projectCode AND status = Rejected").claim().issues - issues.mapNotNull { issue -> - val requestId = requireNotNull(issue.getField(requestIdField.id)?.value?.toString()) { "Error processing request '${issue.key}' : RequestId cannot be null." } - val rejectedReason = issue.getField(rejectReasonField.id)?.value?.toString() - // Issue retrieved via search doesn't contain comments. - val fullIssue = issueClient.getIssue(issue.key, listOf(IssueRestClient.Expandos.CHANGELOG)).claim() - val rejectedBy = fullIssue.changelog?.last { it.items.any { it.field == "status" && it.toString == "Rejected" } } - RejectedRequest(requestId, rejectedBy?.author?.displayName ?: "Unknown", rejectedReason) - } - } - } - - fun updateRejectedRequest(requestId: String) { - restClientLock.exclusive { - val issue = requireNotNull(getIssueById(requestId)) { "Issue with the `request ID` = $requestId does not exist." } - // Move status to in progress. - issueClient.transition(issue, TransitionInput(getTransitionId(START_TRANSITION_KEY, issue))).fail { logger.error("Error processing request '${issue.key}' : Exception when transiting JIRA status.", it) }.claim() - // Move status to stopped. - issueClient.transition(issue, TransitionInput(getTransitionId(STOP_TRANSITION_KEY, issue))).fail { logger.error("Error processing request '${issue.key}' : Exception when transiting JIRA status.", it) }.claim() - issueClient.addComment(issue.commentsUri, Comment.valueOf("Request cancelled by doorman.")).claim() - } - } - - private fun JiraRestClient.getIssueById(requestId: String): Issue? { - // Jira only support ~ (contains) search for custom textfield. - return searchClient.searchJql("'Request ID' ~ $requestId").claim().issues.firstOrNull() - } - - private fun getTransitionId(transitionKey: String, issue: Issue): Int { - return transitions.computeIfAbsent(transitionKey, { key -> - restClientLock.concurrent { - issueClient.getTransitions(issue.transitionsUri).claim().single { it.name == key }.id - } - }) - } - - protected fun createJiraTicket(requestId: String, issue: IssueInput, attachment: Pair? = null) { - restClientLock.exclusive { - if (getIssueById(requestId) != null) { - logger.warn("There is already a ticket corresponding to request Id $requestId, not creating a new one.") - return - } - // This will block until the issue is created. - issueClient.createIssue(issue).fail { logger.error("Exception when creating JIRA issue for request: '$requestId'.", it) }.claim() - attachment?.let { addAttachment(requestId, it) } - } - } - - fun transitRequestStatusToDone(requestId: String, attachment: Pair? = null) { - restClientLock.exclusive { - val issue = requireNotNull(getIssueById(requestId)) { "Cannot find the JIRA ticket `request ID` = $requestId" } - issueClient.transition(issue, TransitionInput(getTransitionId(DONE_TRANSITION_KEY, issue))).fail { logger.error("Exception when transiting JIRA status.", it) }.claim() - attachment?.let { addAttachment(requestId, it) } - } - } - - private fun JiraRestClient.addAttachment(requestId: String, attachment: Pair) { - val createdIssue = checkNotNull(getIssueById(requestId)) { "Missing the JIRA ticket for the request ID: $requestId" } - issueClient.addAttachment(createdIssue.attachmentsUri, attachment.second, attachment.first) - .fail { logger.error("Error processing request '${createdIssue.key}' : Exception when uploading attachment to JIRA.", it) }.claim() - } -} - -data class ApprovedRequest(val requestId: String, val approvedBy: String) - -data class RejectedRequest(val requestId: String, val rejectedBy: String, val reason: String?) - -inline fun Iterable.forEachWithExceptionLogging(logger: Logger, action: (T) -> Unit) { - for (element in this) { - try { - action(element) - } catch (e: Exception) { - logger.error("Error while processing an element: $element", e) - } - } -} - -object JiraConstant{ - const val DONE_TRANSITION_KEY = "Done" - const val START_TRANSITION_KEY = "Start Progress" - const val STOP_TRANSITION_KEY = "Stop Progress" -} 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 deleted file mode 100644 index fecdcb19f5..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/Main.kt +++ /dev/null @@ -1,129 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman - -import com.jcabi.manifests.Manifests -import com.r3.corda.networkmanage.common.utils.* -import com.r3.corda.networkmanage.doorman.signer.LocalSigner -import net.corda.core.crypto.Crypto -import net.corda.core.internal.exists -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import net.corda.nodeapi.internal.crypto.X509KeyStore -import net.corda.nodeapi.internal.crypto.X509Utilities -import org.slf4j.LoggerFactory -import java.time.Instant -import kotlin.system.exitProcess - -private val logger = LoggerFactory.getLogger("com.r3.corda.networkmanage.doorman") - -fun main(args: Array) { - Crypto.registerProviders() // Required to register Providers first thing on boot. - if (Manifests.exists("Doorman-Version")) { - println("Version: ${Manifests.read("Doorman-Version")}") - } - - initialiseSerialization() - val cmdLineOptions = DoormanArgsParser().parseOrExit(*args, printHelpOn = System.err) - - val config = parseConfig(cmdLineOptions.configFile) - - logger.info("Running in ${cmdLineOptions.mode} mode") - when (cmdLineOptions.mode) { - Mode.ROOT_KEYGEN -> { - val emptyCrlPath = requireNotNull(config.emptyCrlPath) { "emptyCrlPath needs to be specified" } - val emptyCrlUrl = requireNotNull(config.emptyCrlUrl) { "emptyCrlUrl needs to be specified" } - val caCrlPath = requireNotNull(config.caCrlPath) { "caCrlPath needs to be specified" } - val caCrlUrl = requireNotNull(config.caCrlUrl) { "caCrlUrl needs to be specified" } - val rootCertificateAndKeyPair = rootKeyGenMode(cmdLineOptions, config) - createEmptyCrls(rootCertificateAndKeyPair, emptyCrlPath, emptyCrlUrl, caCrlPath, caCrlUrl) - } - Mode.CA_KEYGEN -> caKeyGenMode(config) - Mode.DOORMAN -> doormanMode(cmdLineOptions, config) - } -} - -data class NetworkMapStartParams(val signer: LocalSigner?, val config: NetworkMapConfig) - -data class NetworkManagementServerStatus(var serverStartTime: Instant = Instant.now(), var lastRequestCheckTime: Instant? = null) - -private fun processKeyStore(config: NetworkManagementServerConfig): Pair? { - if (config.keystorePath == null) return null - if (!config.keystorePath.exists()) { - println("Could not find keystore: ${config.keystorePath}. You need to create it first or point to the correct location. Please consult the documentation.") - exitProcess(0) - } - // Get password from console if not in config. - val keyStorePassword = config.keystorePassword ?: readPassword("Key store password: ") - val privateKeyPassword = config.caPrivateKeyPassword ?: readPassword("Private key password: ") - val keyStore = X509KeyStore.fromFile(config.keystorePath, keyStorePassword) - val csrCertPathAndKey = keyStore.getCertPathAndKey(X509Utilities.CORDA_INTERMEDIATE_CA, privateKeyPassword) - val networkMapSigner = LocalSigner(keyStore.getCertificateAndKeyPair(CORDA_NETWORK_MAP, privateKeyPassword)) - return Pair(csrCertPathAndKey, networkMapSigner) -} - -private fun rootKeyGenMode(cmdLineOptions: DoormanCmdLineOptions, config: NetworkManagementServerConfig): CertificateAndKeyPair { - return generateRootKeyPair( - requireNotNull(config.rootStorePath) { "The 'rootStorePath' parameter must be specified when generating keys!" }, - config.rootKeystorePassword, - config.rootPrivateKeyPassword, - cmdLineOptions.trustStorePassword - ) -} - -private fun caKeyGenMode(config: NetworkManagementServerConfig) { - generateSigningKeyPairs( - requireNotNull(config.keystorePath) { "The 'keystorePath' parameter must be specified when generating keys!" }, - requireNotNull(config.rootStorePath) { "The 'rootStorePath' parameter must be specified when generating keys!" }, - config.rootKeystorePassword, - config.rootPrivateKeyPassword, - config.keystorePassword, - config.caPrivateKeyPassword, - config.caCrlUrl - ) -} - -private fun doormanMode(cmdLineOptions: DoormanCmdLineOptions, config: NetworkManagementServerConfig) { - val networkManagementServer = NetworkManagementServer(config.dataSourceProperties, config.database, config.doorman, config.revocation) - - val networkParametersCmd = when { - cmdLineOptions.setNetworkParametersFile != null -> - networkManagementServer.netParamsUpdateHandler.loadParametersFromFile(cmdLineOptions.setNetworkParametersFile) - cmdLineOptions.flagDay -> NetworkParametersCmd.FlagDay - cmdLineOptions.cancelUpdate -> NetworkParametersCmd.CancelUpdate - else -> null - } - if (networkParametersCmd == null) { - // TODO: move signing to signing server. - val csrAndNetworkMap = processKeyStore(config) - if (csrAndNetworkMap != null) { - logger.info("Starting network management services with local signing") - } - - val networkMapStartParams = config.networkMap?.let { - NetworkMapStartParams(csrAndNetworkMap?.second, it) - } - - networkManagementServer.start( - config.address, - csrAndNetworkMap?.first, - networkMapStartParams) - - Runtime.getRuntime().addShutdownHook(object : Thread("ShutdownHook") { - override fun run() { - networkManagementServer.close() - } - }) - } else { - networkManagementServer.use { - it.netParamsUpdateHandler.processNetworkParameters(networkParametersCmd) - } - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementServer.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementServer.kt deleted file mode 100644 index ac0f9cc2bb..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementServer.kt +++ /dev/null @@ -1,197 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman - -import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory -import com.r3.corda.networkmanage.common.persistence.* -import com.r3.corda.networkmanage.common.signer.NetworkMapSigner -import com.r3.corda.networkmanage.common.utils.CertPathAndKey -import com.r3.corda.networkmanage.doorman.signer.* -import com.r3.corda.networkmanage.doorman.webservice.* -import net.corda.core.utilities.NetworkHostAndPort -import net.corda.core.utilities.contextLogger -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import net.corda.nodeapi.internal.persistence.DatabaseConfig -import org.apache.commons.io.FileUtils -import java.io.Closeable -import java.net.URI -import java.time.Duration -import java.time.Instant -import java.util.* -import java.util.concurrent.Executors -import java.util.concurrent.TimeUnit - -class NetworkManagementServer(dataSourceProperties: Properties, - databaseConfig: DatabaseConfig, - private val doormanConfig: DoormanConfig?, // TODO Doorman config shouldn't be optional as the doorman is always required to run - private val revocationConfig: CertificateRevocationConfig?) : Closeable { - companion object { - private val logger = contextLogger() - } - - private val closeActions = mutableListOf<() -> Unit>() - private val database = configureDatabase(dataSourceProperties, databaseConfig).also { closeActions += it::close } - private val networkMapStorage = PersistentNetworkMapStorage(database) - private val nodeInfoStorage = PersistentNodeInfoStorage(database) - private val csrStorage = PersistentCertificateSigningRequestStorage(database).let { - if (doormanConfig?.approveAll ?: false) { - ApproveAllCertificateSigningRequestStorage(it) - } else { - it - } - } - val netParamsUpdateHandler = ParametersUpdateHandler(csrStorage, networkMapStorage) - - lateinit var hostAndPort: NetworkHostAndPort - - override fun close() { - logger.info("Closing server...") - for (closeAction in closeActions.reversed()) { - try { - closeAction() - } catch (e: Exception) { - logger.warn("Disregarding exception thrown during close", e) - } - } - } - - private fun getNetworkMapService(config: NetworkMapConfig, signer: LocalSigner?): NetworkMapWebService { - logger.info("Starting Network Map server.") - val localNetworkMapSigner = signer?.let { NetworkMapSigner(networkMapStorage, it) } - val latestParameters = networkMapStorage.getLatestNetworkParameters()?.networkParameters ?: throw IllegalStateException("No network parameters were found. Please upload new network parameters before starting network map service") - logger.info("Starting network map service with latest network parameters: $latestParameters") - localNetworkMapSigner?.signAndPersistNetworkParameters(latestParameters) - - if (localNetworkMapSigner != null) { - logger.info("Starting background worker for signing the network map using the local key store") - val scheduledExecutor = Executors.newScheduledThreadPool(1) - scheduledExecutor.scheduleAtFixedRate({ - try { - localNetworkMapSigner.signNetworkMaps() - } catch (e: Exception) { - // Log the error and carry on. - logger.error("Unable to sign network map", e) - } - }, config.signInterval, config.signInterval, TimeUnit.MILLISECONDS) - closeActions += scheduledExecutor::shutdown - } - return NetworkMapWebService(nodeInfoStorage, networkMapStorage, PersistentCertificateSigningRequestStorage(database), config) - } - - private fun getDoormanService(config: DoormanConfig, - csrCertPathAndKey: CertPathAndKey?, - serverStatus: NetworkManagementServerStatus): RegistrationWebService { - logger.info("Starting Doorman server.") - - val jiraConfig = config.jira - val requestProcessor = if (jiraConfig != null) { - val jiraWebAPI = AsynchronousJiraRestClientFactory().createWithBasicHttpAuthentication(URI(jiraConfig.address), jiraConfig.username, jiraConfig.password) - val jiraClient = CsrJiraClient(jiraWebAPI, jiraConfig.projectCode) - JiraCsrHandler(jiraClient, csrStorage, DefaultCsrHandler(csrStorage, csrCertPathAndKey, config.crlEndpoint)) - } else { - DefaultCsrHandler(csrStorage, csrCertPathAndKey, config.crlEndpoint) - } - - val scheduledExecutor = Executors.newScheduledThreadPool(1) - val approvalThread = Runnable { - try { - serverStatus.lastRequestCheckTime = Instant.now() - // Process Jira approved tickets. - requestProcessor.processRequests() - } catch (e: Exception) { - // Log the error and carry on. - logger.error("Error encountered when approving request.", e) - } - } - scheduledExecutor.scheduleAtFixedRate(approvalThread, config.approveInterval, config.approveInterval, TimeUnit.MILLISECONDS) - closeActions += scheduledExecutor::shutdown - - return RegistrationWebService(requestProcessor, Duration.ofMillis(config.approveInterval)) - } - - private fun getRevocationServices(config: CertificateRevocationConfig, - csrCertPathAndKeyPair: CertPathAndKey?): Pair { - logger.info("Starting Revocation server.") - - val crrStorage = PersistentCertificateRevocationRequestStorage(database).let { - if (config.approveAll) { - ApproveAllCertificateRevocationRequestStorage(it) - } else { - it - } - } - val crlStorage = PersistentCertificateRevocationListStorage(database) - val crlHandler = csrCertPathAndKeyPair?.let { - LocalCrlHandler(crrStorage, - crlStorage, - CertificateAndKeyPair(it.certPath[0], it.toKeyPair()), - Duration.ofMillis(config.localSigning!!.crlUpdateInterval), - config.localSigning.crlEndpoint) - } - - val jiraConfig = config.jira - val crrHandler = if (jiraConfig != null) { - val jiraWebAPI = AsynchronousJiraRestClientFactory().createWithBasicHttpAuthentication(URI(jiraConfig.address), jiraConfig.username, jiraConfig.password) - val jiraClient = CrrJiraClient(jiraWebAPI, jiraConfig.projectCode) - JiraCrrHandler(jiraClient, crrStorage, crlHandler) - } else { - DefaultCrrHandler(crrStorage, crlHandler) - } - - val scheduledExecutor = Executors.newScheduledThreadPool(1) - val approvalThread = Runnable { - try { - // Process Jira approved tickets. - crrHandler.processRequests() - } catch (e: Exception) { - // Log the error and carry on. - logger.error("Error encountered when approving request.", e) - } - } - scheduledExecutor.scheduleAtFixedRate(approvalThread, config.approveInterval, config.approveInterval, TimeUnit.MILLISECONDS) - closeActions += scheduledExecutor::shutdown - // TODO start socket server - return Pair( - CertificateRevocationRequestWebService(crrHandler), - CertificateRevocationListWebService( - crlStorage, - FileUtils.readFileToByteArray(config.caCrlPath.toFile()), - FileUtils.readFileToByteArray(config.emptyCrlPath.toFile()), - Duration.ofMillis(config.crlCacheTimeout))) - } - - fun start(hostAndPort: NetworkHostAndPort, - csrCertPathAndKey: CertPathAndKey?, - startNetworkMap: NetworkMapStartParams? - ) { - val services = mutableListOf() - val serverStatus = NetworkManagementServerStatus() - - startNetworkMap?.let { services += getNetworkMapService(it.config, it.signer) } - doormanConfig?.let { services += getDoormanService(it, csrCertPathAndKey, serverStatus) } - revocationConfig?.let { - val revocationServices = getRevocationServices(it, csrCertPathAndKey) - services += revocationServices.first - services += revocationServices.second - } - - require(services.isNotEmpty()) { "No service created, please provide at least one service config." } - - // TODO: use mbean to expose audit data? - services += MonitoringWebService(serverStatus) - - val webServer = NetworkManagementWebServer(hostAndPort, *services.toTypedArray()) - webServer.start() - - closeActions += webServer::close - this.hostAndPort = webServer.hostAndPort - } -} 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 deleted file mode 100644 index 33b4467fef..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementUtilities.kt +++ /dev/null @@ -1,151 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman - -import com.r3.corda.networkmanage.common.utils.CORDA_NETWORK_MAP -import com.r3.corda.networkmanage.common.utils.NETWORK_ROOT_TRUSTSTORE_FILENAME -import com.r3.corda.networkmanage.common.utils.createSignedCrl -import com.r3.corda.networkmanage.doorman.signer.LocalSigner -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.core.utilities.days -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import net.corda.nodeapi.internal.crypto.CertificateType -import net.corda.nodeapi.internal.crypto.X509KeyStore -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.createCertificate -import net.corda.nodeapi.internal.crypto.X509Utilities.createSelfSignedCACertificate -import org.apache.commons.io.FileUtils -import java.net.URL -import java.nio.file.Path -import javax.security.auth.x500.X500Principal -import kotlin.system.exitProcess - -// TODO The cert subjects need to be configurable -const val CORDA_X500_BASE = "O=R3 HoldCo LLC,OU=Corda,L=New York,C=US" - -/** Read password from console, do a readLine instead if console is null (e.g. when debugging in IDE). */ -internal fun readPassword(fmt: String): String { - return if (System.console() != null) { - String(System.console().readPassword(fmt)) - } else { - print(fmt) - readLine() ?: "" - } -} - -// Keygen utilities. -fun generateRootKeyPair(rootStoreFile: Path, rootKeystorePass: String?, rootPrivateKeyPass: String?, networkRootTrustPass: String?): CertificateAndKeyPair { - println("Generating Root CA keypair and certificate.") - // Get password from console if not in config. - val rootKeystorePassword = rootKeystorePass ?: readPassword("Root Keystore Password: ") - // Ensure folder exists. - rootStoreFile.parent.createDirectories() - val rootStore = X509KeyStore.fromFile(rootStoreFile, rootKeystorePassword, createNew = true) - val rootPrivateKeyPassword = rootPrivateKeyPass ?: readPassword("Root Private Key Password: ") - - if (CORDA_ROOT_CA in rootStore) { - println("$CORDA_ROOT_CA already exists in keystore, process will now terminate.") - println(rootStore.getCertificate(CORDA_ROOT_CA)) - exitProcess(1) - } - - val selfSignKey = Crypto.generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME) - // TODO Make the cert subject configurable - val rootCert = createSelfSignedCACertificate( - X500Principal("CN=Corda Root CA,$CORDA_X500_BASE"), - selfSignKey) - rootStore.update { - setPrivateKey(CORDA_ROOT_CA, selfSignKey.private, listOf(rootCert), rootPrivateKeyPassword) - } - - val trustStorePath = (rootStoreFile.parent / "distribute-nodes").createDirectories() / NETWORK_ROOT_TRUSTSTORE_FILENAME - - val networkRootTrustPassword = networkRootTrustPass ?: readPassword("Network Root Trust Store Password: ") - - X509KeyStore.fromFile(trustStorePath, networkRootTrustPassword, createNew = true).update { - setCertificate(CORDA_ROOT_CA, rootCert) - } - - println("Trust store for distribution to nodes created in $trustStorePath") - println("Root CA keypair and certificate stored in ${rootStoreFile.toAbsolutePath()}.") - println(rootCert) - return CertificateAndKeyPair(rootCert, selfSignKey) -} - -fun createEmptyCrls(rootCertificateAndKeyPair: CertificateAndKeyPair, emptyCrlPath: Path, emptyCrlUrl: URL, caCrlPath: Path, caCrlUrl: URL) { - val rootCert = rootCertificateAndKeyPair.certificate - val rootKey = rootCertificateAndKeyPair.keyPair.private - val emptyCrl = createSignedCrl(rootCert, emptyCrlUrl, 3650.days, LocalSigner(rootKey, rootCert), emptyList(), true) - FileUtils.writeByteArrayToFile(emptyCrlPath.toFile(), emptyCrl.encoded) - val caCrl = createSignedCrl(rootCert, caCrlUrl, 3650.days, LocalSigner(rootKey, rootCert), emptyList()) - FileUtils.writeByteArrayToFile(caCrlPath.toFile(), caCrl.encoded) - println("Empty CRL: $emptyCrl") - println("CA CRL: $caCrl") - println("Root signed empty and CA CRL files created in $emptyCrlPath and $caCrlPath respectively") -} - -fun generateSigningKeyPairs(keystoreFile: Path, rootStoreFile: Path, rootKeystorePass: String?, rootPrivateKeyPass: String?, keystorePass: String?, caPrivateKeyPass: String?, caCrlUrl: URL?) { - println("Generating intermediate and network map key pairs and certificates using root key store $rootStoreFile.") - // Get password from console if not in config. - val rootKeystorePassword = rootKeystorePass ?: readPassword("Root key store password: ") - val rootPrivateKeyPassword = rootPrivateKeyPass ?: readPassword("Root private key password: ") - val rootKeyStore = X509KeyStore.fromFile(rootStoreFile, rootKeystorePassword) - - val rootKeyPairAndCert = rootKeyStore.getCertificateAndKeyPair(CORDA_ROOT_CA, rootPrivateKeyPassword) - - val keyStorePassword = keystorePass ?: readPassword("Key store Password: ") - val privateKeyPassword = caPrivateKeyPass ?: readPassword("Private key Password: ") - // Ensure folder exists. - keystoreFile.parent.createDirectories() - val keyStore = X509KeyStore.fromFile(keystoreFile, keyStorePassword, createNew = true) - - fun storeCertIfAbsent(alias: String, certificateType: CertificateType, subject: X500Principal, signatureScheme: SignatureScheme) { - if (alias in keyStore) { - println("$alias already exists in keystore:") - println(keyStore.getCertificate(alias)) - return - } - - val keyPair = Crypto.generateKeyPair(signatureScheme) - val cert = createCertificate( - certificateType, - rootKeyPairAndCert.certificate, - rootKeyPairAndCert.keyPair, - subject, - keyPair.public, - crlDistPoint = caCrlUrl?.toString() - ) - - keyStore.update { - setPrivateKey(alias, keyPair.private, listOf(cert, rootKeyPairAndCert.certificate), privateKeyPassword) - } - - println("$certificateType key pair and certificate stored in $keystoreFile.") - println(cert) - } - - storeCertIfAbsent( - CORDA_INTERMEDIATE_CA, - CertificateType.INTERMEDIATE_CA, - X500Principal("CN=Corda Doorman CA,$CORDA_X500_BASE"), - DEFAULT_TLS_SIGNATURE_SCHEME) - - storeCertIfAbsent( - CORDA_NETWORK_MAP, - CertificateType.NETWORK_MAP, - X500Principal("CN=Corda Network Map,$CORDA_X500_BASE"), - Crypto.EDDSA_ED25519_SHA512) -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementWebServer.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementWebServer.kt deleted file mode 100644 index 70732990fe..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementWebServer.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman - -import net.corda.core.utilities.NetworkHostAndPort -import net.corda.core.utilities.contextLogger -import net.corda.core.utilities.loggerFor -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.server.ServerConnector -import org.eclipse.jetty.server.handler.HandlerCollection -import org.eclipse.jetty.servlet.ServletContextHandler -import org.eclipse.jetty.servlet.ServletHolder -import org.glassfish.jersey.server.ResourceConfig -import org.glassfish.jersey.servlet.ServletContainer -import java.io.Closeable -import java.net.InetSocketAddress - -/** - * NetworkManagementWebServer runs on Jetty server and provides service via http. - */ -class NetworkManagementWebServer(hostAndPort: NetworkHostAndPort, private vararg val webServices: Any) : Closeable { - companion object { - val logger = contextLogger() - } - - private val server: Server = Server(InetSocketAddress(hostAndPort.host, hostAndPort.port)).apply { - handler = HandlerCollection().apply { - addHandler(buildServletContextHandler()) - } - } - - val hostAndPort: NetworkHostAndPort - get() = server.connectors.mapNotNull { it as? ServerConnector } - .map { NetworkHostAndPort(it.host, it.localPort) } - .first() - - override fun close() { - logger.info("Shutting down network management web services...") - server.stop() - server.join() - } - - fun start() { - logger.info("Starting network management web services...") - server.start() - logger.info("Network management web services started on $hostAndPort with ${webServices.map { it.javaClass.simpleName }}") - println("Network management web services started on $hostAndPort with ${webServices.map { it.javaClass.simpleName }}") - } - - private fun buildServletContextHandler(): ServletContextHandler { - return ServletContextHandler().apply { - contextPath = "/" - val resourceConfig = ResourceConfig().apply { - // Add your API provider classes (annotated for JAX-RS) here - webServices.forEach { register(it) } - } - val jerseyServlet = ServletHolder(ServletContainer(resourceConfig)).apply { initOrder = 0 }// Initialise at server start - addServlet(jerseyServlet, "/*") - } - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkParametersConfig.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkParametersConfig.kt deleted file mode 100644 index 6e3a043185..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkParametersConfig.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman - -import com.typesafe.config.ConfigFactory -import net.corda.core.internal.readObject -import net.corda.core.node.NetworkParameters -import net.corda.core.node.NodeInfo -import net.corda.core.node.NotaryInfo -import net.corda.nodeapi.internal.SignedNodeInfo -import java.nio.file.Path -import java.time.Instant -import java.time.Duration - -/** - * Data class representing a [NotaryInfo] which can be easily parsed by a typesafe [ConfigFactory]. - * @property notaryNodeInfoFile path to the node info file of the notary node. - * @property validating whether the notary is validating - */ -data class NotaryConfig(private val notaryNodeInfoFile: Path, - private val validating: Boolean) { - val nodeInfo by lazy { toNodeInfo() } - fun toNotaryInfo(): NotaryInfo { - // It is always the last identity (in the list of identities) that corresponds to the notary identity. - // In case of a single notary, the list has only one element. In case of distributed notaries the list has - // two items and the second one corresponds to the notary identity. - return NotaryInfo(nodeInfo.legalIdentities.last(), validating) - } - - private fun toNodeInfo(): NodeInfo = notaryNodeInfoFile.readObject().verified() -} - -data class ParametersUpdateConfig(val description: String, val updateDeadline: Instant) { - init { - val now = Instant.now() - require(updateDeadline == now || updateDeadline.isAfter(now)) { "The updateDeadline time must be in the future." } - } -} - -/** - * Data class containing the fields from [NetworkParameters] which can be read at start-up time from doorman. - * It is a proper subset of [NetworkParameters] except for the [notaries] field which is replaced by a list of - * [NotaryConfig] which is parsable. - */ -data class NetworkParametersConfig(val minimumPlatformVersion: Int, - val notaries: List, - val maxMessageSize: Int, - val maxTransactionSize: Int, - val eventHorizonDays: Int, - val parametersUpdate: ParametersUpdateConfig?) diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/ParametersUpdateHandler.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/ParametersUpdateHandler.kt deleted file mode 100644 index 20534e73b9..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/ParametersUpdateHandler.kt +++ /dev/null @@ -1,123 +0,0 @@ -package com.r3.corda.networkmanage.doorman - -import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequestStorage -import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage -import com.r3.corda.networkmanage.common.persistence.entity.UpdateStatus -import com.typesafe.config.ConfigFactory -import com.typesafe.config.ConfigParseOptions -import net.corda.core.internal.CertRole -import net.corda.core.node.NetworkParameters -import net.corda.core.node.NodeInfo -import net.corda.core.utilities.contextLogger -import net.corda.nodeapi.internal.config.parseAs -import net.corda.nodeapi.internal.crypto.x509Certificates -import java.nio.file.Path -import java.time.Instant - -class ParametersUpdateHandler(val csrStorage: CertificateSigningRequestStorage, val networkMapStorage: NetworkMapStorage) { - companion object { - private val logger = contextLogger() - } - - fun loadParametersFromFile(file: Path): NetworkParametersCmd.Set { - val netParamsConfig = ConfigFactory.parseFile(file.toFile(), ConfigParseOptions.defaults()) - .parseAs() - checkNotaryCertificates(netParamsConfig.notaries.map { it.nodeInfo }) - return NetworkParametersCmd.Set.fromConfig(netParamsConfig) - } - - fun processNetworkParameters(networkParametersCmd: NetworkParametersCmd) { - when (networkParametersCmd) { - is NetworkParametersCmd.Set -> handleSetNetworkParameters(networkParametersCmd) - NetworkParametersCmd.FlagDay -> handleFlagDay() - NetworkParametersCmd.CancelUpdate -> handleCancelUpdate() - } - } - - private fun checkNotaryCertificates(notaryNodeInfos: List) { - notaryNodeInfos.forEach { notaryInfo -> - val cert = notaryInfo.legalIdentitiesAndCerts.last().certPath.x509Certificates.find { - val certRole = CertRole.extract(it) - certRole == CertRole.SERVICE_IDENTITY || certRole == CertRole.NODE_CA - } - cert ?: throw IllegalArgumentException("The notary certificate path does not contain SERVICE_IDENTITY or NODE_CA role in it") - csrStorage.getValidCertificatePath(cert.publicKey) - ?: throw IllegalArgumentException("Notary with node info: $notaryInfo is not registered with the doorman") - } - } - - private fun handleSetNetworkParameters(setNetParams: NetworkParametersCmd.Set) { - logger.info("maxMessageSize is not currently wired in the nodes") - val activeMap = networkMapStorage.getNetworkMaps().publicNetworkMap - val activeNetParams = activeMap?.networkParameters?.networkParameters - // Setting initial parameters case. - if (activeNetParams == null) { - require(setNetParams.parametersUpdate == null) { - "'parametersUpdate' specified in network parameters file but there are no network parameters to update" - } - val initialNetParams = setNetParams.toNetworkParameters(modifiedTime = Instant.now(), epoch = 1) - logger.info("Saving initial network parameters to be signed:\n$initialNetParams") - networkMapStorage.saveNetworkParameters(initialNetParams, null) - println("Saved initial network parameters to be signed:\n$initialNetParams") - } else { // An update. - val parametersUpdate = requireNotNull(setNetParams.parametersUpdate) { - "'parametersUpdate' not specified in network parameters file but there is already an active set of network parameters" - } - setNetParams.checkCompatibility(activeNetParams) - val latestNetParams = checkNotNull(networkMapStorage.getLatestNetworkParameters()?.networkParameters) { - "Something has gone wrong! We have an active set of network parameters ($activeNetParams) but apparently no latest network parameters!" - } - // It's not necessary that latestNetParams is the current active network parameters. It can be the network - // parameters from a previous update attempt which hasn't activated yet. We still take the epoch value for this - // new set from latestNetParams to make sure the advertised update attempts have incrementing epochs. - // This has the implication that *active* network parameters may have gaps in their epochs. - val newNetParams = setNetParams.toNetworkParameters(modifiedTime = Instant.now(), epoch = latestNetParams.epoch + 1) - val activeUpdate = activeMap.networkMap.parametersUpdate - if (sameNetworkParameters(latestNetParams, newNetParams) && activeUpdate != null) { - // TODO We don't have cancel event propagation on client side. - throw IllegalArgumentException("New network parameters are the same as the latest ones and there is an update scheduled: $activeUpdate\n" + - "If you want to just change updateDeadline or update description - cancel old update first.") - } - logger.info("Enabling update to network parameters:\n$newNetParams\n$parametersUpdate") - networkMapStorage.saveNewParametersUpdate(newNetParams, parametersUpdate.description, parametersUpdate.updateDeadline) - - logger.info("Update enabled") - println("Enabled update to network parameters:\n$newNetParams\n$parametersUpdate") - } - } - - private fun sameNetworkParameters(params1: NetworkParameters, params2: NetworkParameters): Boolean { - return params1.copy(epoch = 1, modifiedTime = Instant.MAX) == params2.copy(epoch = 1, modifiedTime = Instant.MAX) - } - - private fun handleFlagDay() { - val parametersUpdate = checkNotNull(networkMapStorage.getCurrentParametersUpdate()) { - "No network parameters updates are scheduled" - } - check(Instant.now() >= parametersUpdate.updateDeadline) { - "Update deadline of ${parametersUpdate.updateDeadline} hasn't passed yet" - } - val latestNetParamsEntity = networkMapStorage.getLatestNetworkParameters() - check(parametersUpdate.networkParameters.hash == networkMapStorage.getLatestNetworkParameters()?.hash) { - "The latest network parameters is not the scheduled one:\n${latestNetParamsEntity?.networkParameters}\n${parametersUpdate.toParametersUpdate()}" - } - val activeNetParams = networkMapStorage.getNetworkMaps().publicNetworkMap?.networkParameters - check(parametersUpdate.networkParameters.isSigned) { - "Parameters we are trying to switch to haven't been signed yet" - } - logger.info("""Flag day has occurred, however the new network parameters won't be active until the new network map is signed. -From: ${activeNetParams?.networkParameters} -To: ${parametersUpdate.networkParameters.networkParameters}""") - networkMapStorage.setParametersUpdateStatus(parametersUpdate, UpdateStatus.FLAG_DAY) - } - - private fun handleCancelUpdate() { - val parametersUpdate = checkNotNull(networkMapStorage.getCurrentParametersUpdate()) { - "No network parameters updates are scheduled" - } - logger.info("""Cancelling parameters update: ${parametersUpdate.toParametersUpdate()}. -However, the network map will continue to advertise this update until the new one is signed.""") - networkMapStorage.setParametersUpdateStatus(parametersUpdate, UpdateStatus.CANCELLED) - println("Done with cancel update") - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/CrlHandler.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/CrlHandler.kt deleted file mode 100644 index 706b2ae054..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/CrlHandler.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.signer - -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationListStorage -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationListStorage.Companion.DOORMAN_SIGNATURE -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationRequestStorage -import com.r3.corda.networkmanage.common.persistence.CrlIssuer -import com.r3.corda.networkmanage.common.persistence.RequestStatus -import com.r3.corda.networkmanage.common.signer.CertificateRevocationListSigner -import net.corda.core.utilities.contextLogger -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import java.net.URL -import java.time.Duration - -class LocalCrlHandler(private val crrStorage: CertificateRevocationRequestStorage, - private val crlStorage: CertificateRevocationListStorage, - issuerCertAndKey: CertificateAndKeyPair, - crlUpdateInterval: Duration, - crlEndpoint: URL) { - private companion object { - private val logger = contextLogger() - } - - private val crlSigner = CertificateRevocationListSigner( - crlStorage, - issuerCertAndKey.certificate, - crlUpdateInterval, - crlEndpoint, - LocalSigner(issuerCertAndKey)) - - fun signCrl() { - if (crlStorage.getCertificateRevocationList(CrlIssuer.DOORMAN) == null) { - val crl = crlSigner.createSignedCRL(emptyList(), emptyList(), DOORMAN_SIGNATURE) - logger.info("Saving a new empty CRL: $crl") - return - } - logger.info("Executing CRL signing...") - val approvedRequests = crrStorage.getRevocationRequests(RequestStatus.APPROVED) - logger.debug("Approved certificate revocation requests retrieved: $approvedRequests") - if (approvedRequests.isEmpty()) { - // Nothing to add to the current CRL - logger.debug("There are no APPROVED certificate revocation requests. Aborting CRL signing.") - return - } - val currentRequests = crrStorage.getRevocationRequests(RequestStatus.DONE) - logger.debug("Existing certificate revocation requests retrieved: $currentRequests") - val crl = crlSigner.createSignedCRL(approvedRequests, currentRequests, DOORMAN_SIGNATURE) - logger.info("New CRL signed: $crl") - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/CrrHandler.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/CrrHandler.kt deleted file mode 100644 index 5d6a13de4b..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/CrrHandler.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.signer - -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationRequestStorage -import net.corda.nodeapi.internal.network.CertificateRevocationRequest - -interface CrrHandler { - fun processRequests() - fun saveRevocationRequest(request: CertificateRevocationRequest): String -} - -class DefaultCrrHandler(private val crrStorage: CertificateRevocationRequestStorage, - private val localCrlHandler: LocalCrlHandler?) : CrrHandler { - override fun saveRevocationRequest(request: CertificateRevocationRequest): String = crrStorage.saveRevocationRequest(request) - override fun processRequests() { - localCrlHandler?.signCrl() - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/CsrHandler.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/CsrHandler.kt deleted file mode 100644 index 38fef2c500..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/CsrHandler.kt +++ /dev/null @@ -1,84 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.signer - -import com.r3.corda.networkmanage.common.persistence.CertificateResponse -import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequestStorage -import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequestStorage.Companion.DOORMAN_SIGNATURE -import com.r3.corda.networkmanage.common.persistence.RequestStatus -import com.r3.corda.networkmanage.common.utils.CertPathAndKey -import com.r3.corda.networkmanage.common.utils.getCertRole -import net.corda.nodeapi.internal.crypto.X509CertificateFactory -import net.corda.nodeapi.internal.crypto.X509Utilities -import net.corda.nodeapi.internal.crypto.certificateType -import org.bouncycastle.asn1.x509.GeneralName -import org.bouncycastle.asn1.x509.GeneralSubtree -import org.bouncycastle.asn1.x509.NameConstraints -import org.bouncycastle.pkcs.PKCS10CertificationRequest -import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest -import java.net.URL -import java.security.cert.CertPath -import javax.security.auth.x500.X500Principal - -interface CsrHandler { - fun saveRequest(rawRequest: PKCS10CertificationRequest): String - fun processRequests() - fun getResponse(requestId: String): CertificateResponse -} - -class DefaultCsrHandler(private val storage: CertificateSigningRequestStorage, - private val csrCertPathAndKey: CertPathAndKey?, - private val crlDistributionPoint: URL? = null) : CsrHandler { - - override fun processRequests() { - if (csrCertPathAndKey == null) return - storage.getRequests(RequestStatus.APPROVED).forEach { - val nodeCertPath = createSignedNodeCertificate(it.request, csrCertPathAndKey) - // Since Doorman is deployed in the auto-signing mode (i.e. signer != null), - // we use DOORMAN_SIGNATURE as the signer. - storage.putCertificatePath(it.requestId, nodeCertPath, DOORMAN_SIGNATURE) - } - } - - override fun saveRequest(rawRequest: PKCS10CertificationRequest): String = storage.saveRequest(rawRequest) - - override fun getResponse(requestId: String): CertificateResponse { - val response = storage.getRequest(requestId) - return when (response?.status) { - RequestStatus.NEW, RequestStatus.APPROVED, RequestStatus.TICKET_CREATED, null -> CertificateResponse.NotReady - RequestStatus.REJECTED -> CertificateResponse.Unauthorised(response.remark ?: "Unknown reason") - RequestStatus.DONE -> CertificateResponse.Ready(requireNotNull(response.certData?.certPath) { "Certificate should not be null." }) - } - } - - private fun createSignedNodeCertificate(certificationRequest: PKCS10CertificationRequest, - csrCertPathAndKey: CertPathAndKey): CertPath { - // The sub certs issued by the client must satisfy this directory name (or legal name in Corda) constraints, - // sub certs' directory name must be within client CA's name's subtree, - // please see [sun.security.x509.X500Name.isWithinSubtree()] for more information. - // We assume all attributes in the subject name has been checked prior approval. - // TODO: add validation to subject name. - val request = JcaPKCS10CertificationRequest(certificationRequest) - val certRole = request.getCertRole() - val nameConstraints = NameConstraints( - arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, request.subject))), - arrayOf()) - val nodeCaCert = X509Utilities.createCertificate( - certRole.certificateType, - csrCertPathAndKey.certPath[0], - csrCertPathAndKey.toKeyPair(), - X500Principal(request.subject.encoded), - request.publicKey, - nameConstraints = nameConstraints, - crlDistPoint = crlDistributionPoint?.toString()) - return X509CertificateFactory().generateCertPath(listOf(nodeCaCert) + csrCertPathAndKey.certPath) - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/JiraCrrHandler.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/JiraCrrHandler.kt deleted file mode 100644 index 24e885c838..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/JiraCrrHandler.kt +++ /dev/null @@ -1,84 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.signer - -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationRequestData -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationRequestStorage -import com.r3.corda.networkmanage.common.persistence.RequestStatus -import com.r3.corda.networkmanage.doorman.* -import net.corda.core.utilities.contextLogger -import net.corda.nodeapi.internal.network.CertificateRevocationRequest - -class JiraCrrHandler(private val jiraClient: CrrJiraClient, - private val crrStorage: CertificateRevocationRequestStorage, - private val localCrlHandler: LocalCrlHandler?) : CrrHandler { - private companion object { - val logger = contextLogger() - } - - override fun saveRevocationRequest(request: CertificateRevocationRequest): String { - try { - val requestId = crrStorage.saveRevocationRequest(request) - val requestData = crrStorage.getRevocationRequest(requestId) - requestData ?: throw IllegalStateException("Request $requestId does not exist.") - jiraClient.createCertificateRevocationRequestTicket(requestData) - crrStorage.markRequestTicketCreated(requestId) - return requestId - } catch (e: Exception) { - logger.error("There was an error while creating JIRA tickets", e) - throw e - } - } - - override fun processRequests() { - createTickets() - val (approvedRequests, rejectedRequests) = updateRequestStatuses() - updateJiraTickets(approvedRequests, rejectedRequests) - localCrlHandler?.signCrl() - } - - private fun updateRequestStatuses(): Pair, List> { - // Update local request statuses. - val approvedRequest = jiraClient.getApprovedRequests() - approvedRequest.forEachWithExceptionLogging(logger) { (id, approvedBy) -> crrStorage.approveRevocationRequest(id, approvedBy) } - val rejectedRequest = jiraClient.getRejectedRequests() - rejectedRequest.forEachWithExceptionLogging(logger) { (id, rejectedBy, reason) -> crrStorage.rejectRevocationRequest(id, rejectedBy, reason) } - return Pair(approvedRequest, rejectedRequest) - } - - private fun updateJiraTickets(approvedRequest: List, rejectedRequest: List) { - // Reconfirm request status and update jira status - logger.debug("Updating JIRA tickets: `approved` = $approvedRequest, `rejected` = $rejectedRequest") - approvedRequest.mapNotNull { crrStorage.getRevocationRequest(it.requestId) } - .filter { it.status == RequestStatus.DONE } - .forEachWithExceptionLogging(logger) { jiraClient.transitRequestStatusToDone(it.requestId) } - rejectedRequest.mapNotNull { crrStorage.getRevocationRequest(it.requestId) } - .filter { it.status == RequestStatus.REJECTED } - .forEachWithExceptionLogging(logger) { jiraClient.updateRejectedRequest(it.requestId) } - } - - /** - * Creates Jira tickets for all request in [RequestStatus.NEW] state. - * - * Usually requests are expected to move to the [RequestStatus.TICKET_CREATED] state immediately, - * they might be left in the [RequestStatus.NEW] state if Jira is down. - */ - private fun createTickets() { - crrStorage.getRevocationRequests(RequestStatus.NEW).forEachWithExceptionLogging(logger) { - createTicket(it) - } - } - - private fun createTicket(revocationRequest: CertificateRevocationRequestData) { - jiraClient.createCertificateRevocationRequestTicket(revocationRequest) - crrStorage.markRequestTicketCreated(revocationRequest.requestId) - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/JiraCsrHandler.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/JiraCsrHandler.kt deleted file mode 100644 index ebd1dd6579..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/JiraCsrHandler.kt +++ /dev/null @@ -1,95 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.signer - -import com.r3.corda.networkmanage.common.persistence.CertificateResponse -import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequest -import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequestStorage -import com.r3.corda.networkmanage.common.persistence.RequestStatus -import com.r3.corda.networkmanage.doorman.* -import net.corda.core.utilities.contextLogger -import net.corda.nodeapi.internal.crypto.X509Utilities -import org.bouncycastle.pkcs.PKCS10CertificationRequest - -class JiraCsrHandler(private val jiraClient: CsrJiraClient, private val storage: CertificateSigningRequestStorage, private val delegate: CsrHandler) : CsrHandler by delegate { - private companion object { - val logger = contextLogger() - } - - override fun saveRequest(rawRequest: PKCS10CertificationRequest): String { - val requestId = delegate.saveRequest(rawRequest) - // Make sure request has been accepted. - try { - if (delegate.getResponse(requestId) !is CertificateResponse.Unauthorised) { - jiraClient.createCertificateSigningRequestTicket(CertificationRequestData(requestId, rawRequest)) - storage.markRequestTicketCreated(requestId) - } - } catch (e: Exception) { - logger.warn("There was an error while creating Jira tickets", e) - } finally { - return requestId - } - } - - override fun processRequests() { - createTickets() - val (approvedRequests, rejectedRequests) = updateRequestStatus() - delegate.processRequests() - updateJiraTickets(approvedRequests, rejectedRequests) - } - - private fun updateRequestStatus(): Pair, List> { - // Update local request statuses. - val approvedRequest = jiraClient.getApprovedRequests() - approvedRequest.forEachWithExceptionLogging(logger) { (id, approvedBy) -> - storage.approveRequest(id, approvedBy) - } - val rejectedRequest = jiraClient.getRejectedRequests() - rejectedRequest.forEachWithExceptionLogging(logger) { (id, rejectedBy, reason) -> - storage.rejectRequest(id, rejectedBy, reason) - } - return Pair(approvedRequest, rejectedRequest) - } - - private fun updateJiraTickets(approvedRequest: List, rejectedRequest: List) { - // Reconfirm request status and update jira status - approvedRequest.mapNotNull { storage.getRequest(it.requestId) } - .filter { it.status == RequestStatus.DONE && it.certData != null } - .forEachWithExceptionLogging(logger) { - val attachment = it.certData?.certPath?.certificates?.firstOrNull()?.let { - Pair("${X509Utilities.CORDA_CLIENT_CA}.cer", it.encoded.inputStream()) - } - jiraClient.transitRequestStatusToDone(it.requestId, attachment) - } - rejectedRequest.mapNotNull { storage.getRequest(it.requestId) } - .filter { it.status == RequestStatus.REJECTED } - .forEachWithExceptionLogging(logger) { - jiraClient.updateRejectedRequest(it.requestId) - } - } - - /** - * Creates Jira tickets for all request in [RequestStatus.NEW] state. - * - * Usually requests are expected to move to the [RequestStatus.TICKET_CREATED] state immediately, - * they might be left in the [RequestStatus.NEW] state if Jira is down. - */ - private fun createTickets() { - storage.getRequests(RequestStatus.NEW).forEachWithExceptionLogging(logger) { - createTicket(it) - } - } - - private fun createTicket(signingRequest: CertificateSigningRequest) { - jiraClient.createCertificateSigningRequestTicket(CertificationRequestData(signingRequest.requestId, signingRequest.request)) - storage.markRequestTicketCreated(signingRequest.requestId) - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/LocalSigner.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/LocalSigner.kt deleted file mode 100644 index d7e722232e..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/LocalSigner.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.signer - -import com.r3.corda.networkmanage.common.signer.Signer -import net.corda.core.crypto.Crypto -import net.corda.core.internal.DigitalSignatureWithCert -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import java.security.KeyStore -import java.security.PrivateKey -import java.security.cert.X509Certificate - -/** - * This local signer is intended to be used in testing environment where hardware signing module is not available. - */ -class LocalSigner(private val signingKey: PrivateKey, private val signingCert: X509Certificate) : Signer { - constructor(certAndKeyPair: CertificateAndKeyPair) : this(certAndKeyPair.keyPair.private, certAndKeyPair.certificate) - - override fun signBytes(data: ByteArray): DigitalSignatureWithCert { - return DigitalSignatureWithCert(signingCert, Crypto.doSign(signingKey, data)) - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/sockets/CertificateRevocationSocketServer.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/sockets/CertificateRevocationSocketServer.kt deleted file mode 100644 index b13383a0ce..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/sockets/CertificateRevocationSocketServer.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.r3.corda.networkmanage.doorman.sockets - -import com.google.common.util.concurrent.MoreExecutors.shutdownAndAwaitTermination -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationListStorage -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationRequestStorage -import com.r3.corda.networkmanage.common.persistence.CrlIssuer -import com.r3.corda.networkmanage.common.sockets.* -import com.r3.corda.networkmanage.common.utils.readObject -import com.r3.corda.networkmanage.common.utils.writeObject -import net.corda.core.utilities.contextLogger -import net.corda.core.utilities.seconds -import java.net.ServerSocket -import java.util.concurrent.Executors -import java.util.concurrent.TimeUnit - -class CertificateRevocationSocketServer(val port: Int, - private val crlStorage: CertificateRevocationListStorage, - private val crrStorage: CertificateRevocationRequestStorage) : AutoCloseable { - private companion object { - private val logger = contextLogger() - - private val RECONNECT_INTERVAL = 10.seconds.toMillis() - } - - private val executor = Executors.newSingleThreadScheduledExecutor() - - @Volatile - private var isRunning = false - - fun start() { - check(!isRunning) { "The server has already been started." } - isRunning = true - executor.submit { - while (isRunning) { - try { - listen() - } catch (e: Exception) { - logger.error("Socket execution error.", e) - if (isRunning) { - logger.info("Server socket will be recreated in $RECONNECT_INTERVAL milliseconds") - Thread.sleep(RECONNECT_INTERVAL) - logger.info("Recreating server socket...") - } - } - } - } - } - - override fun close() { - isRunning = false - shutdownAndAwaitTermination(executor, RECONNECT_INTERVAL, TimeUnit.MILLISECONDS) - } - - private fun listen() { - ServerSocket(port).use { - logger.info("Server socket is running.") - while (isRunning) { - logger.debug("Waiting for socket data...") - val acceptedSocket = it.accept() - acceptedSocket.use { - val message = it.getInputStream().readObject() - logger.debug("Received message type is $message.") - acceptedSocket.getOutputStream().let { - when (message) { - is CrlRetrievalMessage -> { - val crl = crlStorage.getCertificateRevocationList(CrlIssuer.DOORMAN) - it.writeObject(CrlResponseMessage(crl)) - logger.debug("Sending the current certificate revocation list.") - } - is CrrsByStatusMessage -> { - it.writeObject(crrStorage.getRevocationRequests(message.status)) - logger.debug("Sending ${message.status.name} certificate revocation requests.") - } - is CrlSubmissionMessage -> { - val crlSubmission = acceptedSocket.getInputStream().readObject() - crlStorage.saveCertificateRevocationList(crlSubmission.list, CrlIssuer.DOORMAN, crlSubmission.signer, crlSubmission.revocationTime) - } - else -> logger.warn("Unknown message type $message") - } - } - } - } - } - } - - -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/CertificateRevocationListWebService.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/CertificateRevocationListWebService.kt deleted file mode 100644 index 1f2f4931c7..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/CertificateRevocationListWebService.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.r3.corda.networkmanage.doorman.webservice - -import com.github.benmanes.caffeine.cache.Caffeine -import com.github.benmanes.caffeine.cache.LoadingCache -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationListStorage -import com.r3.corda.networkmanage.common.persistence.CrlIssuer -import com.r3.corda.networkmanage.doorman.webservice.CertificateRevocationListWebService.Companion.CRL_PATH -import net.corda.core.utilities.contextLogger -import java.time.Duration -import java.util.concurrent.TimeUnit -import javax.ws.rs.GET -import javax.ws.rs.Path -import javax.ws.rs.Produces -import javax.ws.rs.core.Response -import javax.ws.rs.core.Response.ok -import javax.ws.rs.core.Response.status - -@Path(CRL_PATH) -class CertificateRevocationListWebService(private val revocationListStorage: CertificateRevocationListStorage, - private val caCrlBytes: ByteArray, - private val emptyCrlBytes: ByteArray, - cacheTimeout: Duration) { - companion object { - private val logger = contextLogger() - const val CRL_PATH = "certificate-revocation-list" - const val CRL_DATA_TYPE = "application/pkcs7-crl" - const val DOORMAN = "doorman" - const val ROOT = "root" - const val EMPTY = "empty" - } - - private val crlCache: LoadingCache = Caffeine.newBuilder() - .expireAfterWrite(cacheTimeout.toMillis(), TimeUnit.MILLISECONDS) - .build({ key -> - revocationListStorage.getCertificateRevocationList(key)?.encoded - }) - - @GET - @Path(DOORMAN) - @Produces(CRL_DATA_TYPE) - fun getDoormanRevocationList(): Response { - return getCrlResponse(CrlIssuer.DOORMAN) - } - - @GET - @Path(ROOT) - @Produces(CRL_DATA_TYPE) - fun getRootRevocationList(): Response { - return ok(caCrlBytes).build() - } - - @GET - @Path(EMPTY) - @Produces(CRL_DATA_TYPE) - fun getEmptyRevocationList(): Response { - return ok(emptyCrlBytes).build() - } - - private fun getCrlResponse(issuer: CrlIssuer): Response { - return try { - val crlBytes = crlCache.get(issuer) - if (crlBytes != null) { - ok(crlBytes).build() - } else { - status(Response.Status.NOT_FOUND).build() - } - } catch (e: Exception) { - logger.error("Error when retrieving the ${issuer.name} crl.", e) - status(Response.Status.INTERNAL_SERVER_ERROR).build() - } - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/CertificateRevocationRequestWebService.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/CertificateRevocationRequestWebService.kt deleted file mode 100644 index 7b683aba8e..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/CertificateRevocationRequestWebService.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.r3.corda.networkmanage.doorman.webservice - -import com.r3.corda.networkmanage.doorman.signer.CrrHandler -import com.r3.corda.networkmanage.doorman.webservice.CertificateRevocationRequestWebService.Companion.CRR_PATH -import net.corda.core.internal.readObject -import net.corda.core.utilities.contextLogger -import net.corda.nodeapi.internal.network.CertificateRevocationRequest -import java.io.InputStream -import javax.ws.rs.Consumes -import javax.ws.rs.POST -import javax.ws.rs.Path -import javax.ws.rs.Produces -import javax.ws.rs.core.MediaType -import javax.ws.rs.core.Response -import javax.ws.rs.core.Response.ok -import javax.ws.rs.core.Response.status - -@Path(CRR_PATH) -class CertificateRevocationRequestWebService(private val crrHandler: CrrHandler) { - - companion object { - const val CRR_PATH = "certificate-revocation-request" - val logger = contextLogger() - } - - @POST - @Consumes(MediaType.APPLICATION_OCTET_STREAM) - @Produces(MediaType.TEXT_PLAIN) - fun submitRequest(input: InputStream): Response { - return try { - val request = input.readObject() - val requestId = crrHandler.saveRevocationRequest(request) - ok(requestId) - } catch (e: Exception) { - logger.warn("Unable to process the revocation request.", e) - when (e) { - is IllegalArgumentException -> status(Response.Status.BAD_REQUEST).entity(e.message) - else -> throw e - } - }.build() - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/MonitoringWebService.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/MonitoringWebService.kt deleted file mode 100644 index 72ecb761dd..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/MonitoringWebService.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.webservice - -import com.r3.corda.networkmanage.doorman.NetworkManagementServerStatus -import org.codehaus.jackson.map.ObjectMapper -import javax.ws.rs.GET -import javax.ws.rs.Path -import javax.ws.rs.Produces -import javax.ws.rs.core.MediaType -import javax.ws.rs.core.Response - -@Path("/status") -class MonitoringWebService(private val serverStatus: NetworkManagementServerStatus) { - @GET - @Produces(MediaType.APPLICATION_JSON) - fun status(): Response { - return Response.ok(ObjectMapper().writeValueAsString(serverStatus)).build() - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/NetworkMapWebService.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/NetworkMapWebService.kt deleted file mode 100644 index 8a207eaad1..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/NetworkMapWebService.kt +++ /dev/null @@ -1,231 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.webservice - -import com.github.benmanes.caffeine.cache.Caffeine -import com.github.benmanes.caffeine.cache.LoadingCache -import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequestStorage -import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage -import com.r3.corda.networkmanage.common.persistence.NetworkMaps -import com.r3.corda.networkmanage.common.persistence.NodeInfoStorage -import com.r3.corda.networkmanage.common.persistence.entity.NetworkMapEntity -import com.r3.corda.networkmanage.doorman.NetworkMapConfig -import com.r3.corda.networkmanage.doorman.webservice.NetworkMapWebService.Companion.NETWORK_MAP_PATH -import net.corda.core.crypto.CompositeKey -import net.corda.core.crypto.SecureHash -import net.corda.core.crypto.SignedData -import net.corda.core.internal.CertRole -import net.corda.core.internal.readObject -import net.corda.core.node.NetworkParameters -import net.corda.core.node.NodeInfo -import net.corda.core.serialization.serialize -import net.corda.core.utilities.contextLogger -import net.corda.core.utilities.debug -import net.corda.core.utilities.trace -import net.corda.nodeapi.internal.NodeInfoAndSigned -import net.corda.nodeapi.internal.SignedNodeInfo -import net.corda.nodeapi.internal.crypto.X509Utilities.validateCertPath -import net.corda.nodeapi.internal.crypto.x509 -import net.corda.nodeapi.internal.crypto.x509Certificates -import java.io.InputStream -import java.security.InvalidKeyException -import java.security.SignatureException -import java.security.cert.CertPathValidatorException -import java.time.Duration -import java.time.Instant -import java.time.ZoneId -import java.time.format.DateTimeFormatter -import java.util.concurrent.TimeUnit -import javax.servlet.http.HttpServletRequest -import javax.ws.rs.* -import javax.ws.rs.core.Context -import javax.ws.rs.core.MediaType -import javax.ws.rs.core.Response -import javax.ws.rs.core.Response.ok -import javax.ws.rs.core.Response.status - -@Path(NETWORK_MAP_PATH) -class NetworkMapWebService(private val nodeInfoStorage: NodeInfoStorage, - private val networkMapStorage: NetworkMapStorage, - private val certificateSigningRequestStorage: CertificateSigningRequestStorage, - private val config: NetworkMapConfig) { - - companion object { - val logger = contextLogger() - const val NETWORK_MAP_PATH = "network-map" - } - - private val networkMapCache: LoadingCache = Caffeine.newBuilder() - .expireAfterWrite(config.cacheTimeout, TimeUnit.MILLISECONDS) - .build { - logger.info("Re-publishing network map") - networkMapStorage.getNetworkMaps() - } - - private val nodeInfoCache: LoadingCache = Caffeine.newBuilder() - // TODO: Define cache retention policy. - .softValues() - .build(nodeInfoStorage::getNodeInfo) - - private val networkMaps: NetworkMaps? - get() { - if (networkMapCache[true]?.publicNetworkMap == null) { - // Refresh cache every time the public network map is NULL. - networkMapCache.refresh(true) - } - return networkMapCache[true] - } - - private val currentNodeInfoHashes: Set get() = networkMaps?.allNodeInfoHashes ?: emptySet() - private val currentNetworkParameters: NetworkParameters? get() = networkMaps?.publicNetworkMap?.networkParameters?.networkParameters - - @POST - @Path("publish") - @Consumes(MediaType.APPLICATION_OCTET_STREAM) - fun registerNode(input: InputStream): Response { - val signedNodeInfo = input.readObject() - var nodeInfo: NodeInfo? = null - return try { - // Store the NodeInfo - val nodeInfoAndSigned = NodeInfoAndSigned(signedNodeInfo) - nodeInfo = nodeInfoAndSigned.nodeInfo - logger.debug { "Publishing node-info: $nodeInfo" } - verifyNodeInfo(nodeInfo) - nodeInfoStorage.putNodeInfo(nodeInfoAndSigned) - ok() - } catch (e: Exception) { - logger.warn("Unable to process node-info: $nodeInfo", e) - when (e) { - is NetworkMapNotInitialisedException -> status(Response.Status.SERVICE_UNAVAILABLE).entity(e.message) - is RequestException -> status(Response.Status.BAD_REQUEST).entity(e.message) - is InvalidKeyException, is SignatureException -> status(Response.Status.UNAUTHORIZED).entity(e.message) - // Rethrow e if its not one of the expected exception, the server will return http 500 internal error. - else -> throw e - } - }.build() - } - - @POST - @Path("ack-parameters") - @Consumes(MediaType.APPLICATION_OCTET_STREAM) - fun ackNetworkParameters(input: InputStream): Response { - return try { - val signedParametersHash = input.readObject>() - val hash = signedParametersHash.verified() - requireNotNull(networkMapStorage.getSignedNetworkParameters(hash)) { "No network parameters with hash $hash" } - logger.debug { "Received ack-parameters with $hash from ${signedParametersHash.sig.by}" } - nodeInfoStorage.ackNodeInfoParametersUpdate(signedParametersHash.sig.by, hash) - ok() - } catch (e: SignatureException) { - status(Response.Status.FORBIDDEN).entity(e.message) - }.build() - } - - @GET - @Produces(MediaType.APPLICATION_OCTET_STREAM) - fun getNetworkMap(): Response = createNetworkMapResponse(networkMaps?.publicNetworkMap) - - @GET - @Path("{id}") - @Produces(MediaType.APPLICATION_OCTET_STREAM) - fun getNetworkMap(@PathParam("id") privateNetworkID: String?): Response = createNetworkMapResponse(networkMaps?.privateNetworkMap?.get(privateNetworkID)) - - private fun createNetworkMapResponse(networkMap: NetworkMapEntity?) = createResponse(networkMap?.toSignedNetworkMap(), addCacheTimeout = true, timestamp = networkMap?.timestamp) - - @GET - @Path("node-info/{nodeInfoHash}") - @Produces(MediaType.APPLICATION_OCTET_STREAM) - fun getNodeInfo(@PathParam("nodeInfoHash") nodeInfoHash: String): Response { - // Only serve node info if its in the current network map, otherwise return 404. - logger.trace { "Processing node info request for hash: '$nodeInfoHash'" } - val signedNodeInfo = if (SecureHash.parse(nodeInfoHash) in currentNodeInfoHashes) { - nodeInfoCache.get(SecureHash.parse(nodeInfoHash)) - } else { - logger.trace { "Requested node info is not current, returning null." } - null - } - logger.trace { "Node Info: ${signedNodeInfo?.verified()}" } - return createResponse(signedNodeInfo) - } - - @GET - @Path("network-parameters/{hash}") - @Produces(MediaType.APPLICATION_OCTET_STREAM) - fun getNetworkParameters(@PathParam("hash") hash: String): Response { - val signedNetParams = networkMapStorage.getSignedNetworkParameters(SecureHash.parse(hash)) - logger.trace { "Precessed network parameter request for hash: '$hash'" } - logger.trace { "Network parameter : ${signedNetParams?.verified()}" } - return createResponse(signedNetParams) - } - - @GET - @Path("my-ip") - fun myIp(@Context request: HttpServletRequest): Response { - val ip = request.getHeader("X-Forwarded-For")?.split(",")?.first() ?: "${request.remoteHost}:${request.remotePort}" - logger.trace { "Processed IP request from client, IP: '$ip'" } - return ok(ip).build() - } - - private fun verifyNodeInfo(nodeInfo: NodeInfo) { - checkCertificates(nodeInfo) - checkCompositeKeys(nodeInfo) - val minimumPlatformVersion = currentNetworkParameters?.minimumPlatformVersion - ?: throw NetworkMapNotInitialisedException("Network parameters have not been initialised") - if (nodeInfo.platformVersion < minimumPlatformVersion) { - throw RequestException("Minimum platform version is $minimumPlatformVersion") - } - } - - private fun checkCompositeKeys(nodeInfo: NodeInfo) { - val compositeKeyIdentities = nodeInfo.legalIdentities.filter { it.owningKey is CompositeKey } - if (compositeKeyIdentities.isEmpty()) { - return - } - val parameters = checkNotNull(currentNetworkParameters) { "Network parameters not available." } - val notaryIdentities = parameters.notaries.map { it.identity } - if (!notaryIdentities.containsAll(compositeKeyIdentities)) { - throw RequestException("A composite key needs to belong to a notary.") - } - } - - private fun createResponse(payload: Any?, addCacheTimeout: Boolean = false, timestamp: Instant? = null): Response { - return if (payload != null) { - val ok = Response.ok(payload.serialize().bytes) - if (addCacheTimeout) { - ok.header("Cache-Control", "max-age=${Duration.ofMillis(config.cacheTimeout).seconds}") - } - timestamp?.let { - ok.header("Last-Modified", DateTimeFormatter.RFC_1123_DATE_TIME.withZone(ZoneId.of("GMT")).format(it)) - } - ok - } else { - status(Response.Status.NOT_FOUND) - }.build() - } - - private fun checkCertificates(nodeInfo: NodeInfo) { - val nodeCaCert = nodeInfo.legalIdentitiesAndCerts.first().certPath.x509Certificates.find { CertRole.extract(it) == CertRole.NODE_CA } - nodeCaCert ?: throw RequestException("The node certificate path does not contain the node CA certificate type in it.") - val nodeCertPath = certificateSigningRequestStorage.getValidCertificatePath(nodeCaCert.publicKey) - nodeCertPath ?: throw RequestException("Node certificate is either no longer valid or was never registered.") - val rootCert = nodeCertPath.certificates.last().x509 - try { - nodeInfo.legalIdentitiesAndCerts.forEach { - validateCertPath(rootCert, it.certPath) - } - } catch (e: CertPathValidatorException) { - throw RequestException("Invalid certificate path.") - } - } - - class NetworkMapNotInitialisedException(message: String?) : Exception(message) - class RequestException(message: String) : Exception(message) -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebService.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebService.kt deleted file mode 100644 index 5a47d45602..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebService.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.webservice - -import com.r3.corda.networkmanage.common.persistence.CertificateResponse -import com.r3.corda.networkmanage.doorman.signer.CsrHandler -import net.corda.core.internal.readFully -import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA -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.isSignatureValid -import org.bouncycastle.pkcs.PKCS10CertificationRequest -import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest -import java.io.ByteArrayOutputStream -import java.io.InputStream -import java.time.Duration -import java.util.zip.ZipEntry -import java.util.zip.ZipOutputStream -import javax.servlet.http.HttpServletRequest -import javax.ws.rs.* -import javax.ws.rs.core.Context -import javax.ws.rs.core.MediaType -import javax.ws.rs.core.Response -import javax.ws.rs.core.Response.* -import javax.ws.rs.core.Response.Status.UNAUTHORIZED - -/** - * Provides functionality for asynchronous submission of certificate signing requests and retrieval of the results. - */ -@Path("certificate") -class RegistrationWebService(private val csrHandler: CsrHandler, private val clientPollInterval: Duration) { - @Context lateinit var request: HttpServletRequest - /** - * Accept stream of [PKCS10CertificationRequest] from user and persists in [CertificateRequestStorage] for approval. - * Server returns HTTP 200 response with random generated request Id after request has been persisted. - */ - @POST - @Consumes(MediaType.APPLICATION_OCTET_STREAM) - @Produces(MediaType.TEXT_PLAIN) - fun submitRequest(input: InputStream): Response { - val csr = JcaPKCS10CertificationRequest(input.readFully()) - if (!csr.isSignatureValid()) { - return status(Response.Status.BAD_REQUEST).entity("Invalid CSR signature").build() - } - val requestId = csrHandler.saveRequest(csr) - return ok(requestId).build() - } - - /** - * Retrieve Certificate signing request from storage using the [requestId] and create a signed certificate if request has been approved. - * Returns HTTP 200 with DER encoded signed certificates if request has been approved else HTTP 204 No content - */ - @GET - @Path("{var}") - @Produces(MediaType.APPLICATION_OCTET_STREAM) - fun retrieveCert(@PathParam("var") requestId: String): Response { - val response = csrHandler.getResponse(requestId) - return when (response) { - is CertificateResponse.Ready -> { - // Write certificate chain to a zip stream and extract the bit array output. - val baos = ByteArrayOutputStream() - ZipOutputStream(baos).use { zip -> - // Client certificate must come first and root certificate should come last. - val certificates = ArrayList(response.certificatePath.certificates) - listOf(CORDA_CLIENT_CA, CORDA_INTERMEDIATE_CA, CORDA_ROOT_CA).zip(certificates).forEach { - zip.putNextEntry(ZipEntry("${it.first}.cer")) - zip.write(it.second.encoded) - zip.closeEntry() - } - } - ok(baos.toByteArray()) - .type("application/zip") - .header("Content-Disposition", "attachment; filename=\"certificates.zip\"") - } - is CertificateResponse.NotReady -> noContent().header("Cache-Control", "max-age=${clientPollInterval.seconds}") - is CertificateResponse.Unauthorised -> status(UNAUTHORIZED).entity(response.message) - }.build() - } -} \ No newline at end of file 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 deleted file mode 100644 index 904e9dba6f..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/Main.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm - -import com.jcabi.manifests.Manifests -import com.r3.corda.networkmanage.common.persistence.configureDatabase -import com.r3.corda.networkmanage.common.utils.initialiseSerialization -import com.r3.corda.networkmanage.common.utils.parseConfig -import com.r3.corda.networkmanage.hsm.configuration.ManualMode -import com.r3.corda.networkmanage.hsm.configuration.SigningServiceArgsParser -import com.r3.corda.networkmanage.hsm.configuration.SigningServiceConfig -import com.r3.corda.networkmanage.hsm.processor.CrrProcessor -import com.r3.corda.networkmanage.hsm.processor.CsrProcessor -import com.r3.corda.networkmanage.hsm.processor.NetworkMapProcessor -import net.corda.core.internal.exists -import org.apache.logging.log4j.LogManager -import org.bouncycastle.jce.provider.BouncyCastleProvider -import java.security.Security -import javax.crypto.Cipher - -private val logger = LogManager.getLogger("com.r3.corda.networkmanage.hsm.Main") - -fun main(args: Array) { - if (Manifests.exists("Signing-Service-Version")) { - println("Signing Service Version: ${Manifests.read("Signing-Service-Version")}") - } - - val cmdLineOptions = SigningServiceArgsParser().parseOrExit(*args) - - val config = if (cmdLineOptions.configFile.exists()) { - parseConfig(cmdLineOptions.configFile) - } else { - println("Please provide existing HSM config file using --config-file option") - return - } - - // Validate - // Grabbed from https://stackoverflow.com/questions/7953567/checking-if-unlimited-cryptography-is-available - require(Cipher.getMaxAllowedKeyLength("AES") >= 256) { - "Unlimited Strength Jurisdiction Policy Files must be installed, see http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html" - } - - // Ensure the BouncyCastle provider is installed - if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { - Security.addProvider(BouncyCastleProvider()) - } - - initialiseSerialization() - // Create DB connection. - val persistence = configureDatabase(config.dataSourceProperties, config.database) - if (config.networkMap != null) { - NetworkMapProcessor(config.networkMap, config.device, config.keySpecifier, persistence).run() - } else if (config.doorman != null) { - when (config.doorman.mode) { - ManualMode.CSR -> CsrProcessor(config.doorman, config.device, config.keySpecifier, persistence).showMenu() - ManualMode.CRL -> CrrProcessor(config.doorman, config.device, config.keySpecifier).showMenu() - } - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/AuthMode.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/AuthMode.kt deleted file mode 100644 index e6749766a5..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/AuthMode.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.authentication - -/** - * Supported authentication modes - */ -enum class AuthMode { - PASSWORD, CARD_READER, KEY_FILE -} \ No newline at end of file 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 deleted file mode 100644 index 5fcda421d5..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/Authenticator.kt +++ /dev/null @@ -1,159 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.authentication - -import CryptoServerJCE.CryptoServerProvider -import com.r3.corda.networkmanage.common.signer.AuthenticationException -import java.io.ByteArrayOutputStream -import java.nio.file.Path -import kotlin.reflect.full.memberProperties - -/** - * Performs user authentication against the HSM - */ -class Authenticator(private val mode: AuthMode = AuthMode.PASSWORD, - private val autoUsername: String? = null, - private val authKeyFilePath: Path? = null, - private val authKeyFilePass: String? = null, - private val authStrengthThreshold: Int = 2, - inputReader: InputReader = ConsoleInputReader(), - 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) List of strings that corresponds to user names authenticated against the HSM. - */ - fun connectAndAuthenticate(block: (CryptoServerProvider, List) -> T): T { - return try { - val authenticated = mutableListOf() - loop@ while (true) { - val user = if (autoUsername.isNullOrEmpty()) { - print("Enter User Name (or Q to quit): ") - val input = readLine() - if (input != null && "q" == input.toLowerCase()) { - authenticated.clear() - break - } - input - } else { - println("Authenticating using preconfigured user name: $autoUsername") - autoUsername - } - when (mode) { - AuthMode.CARD_READER -> { - println("Authenticating using card reader") - println("Accessing the certificate key group data...") - provider.loginSign(user, ":cs2:cyb:USB0", null) - } - AuthMode.KEY_FILE -> { - println("Authenticating using preconfigured key file $authKeyFilePath") - val password = if (authKeyFilePass == null) { - val input = readPassword("Enter key file password (or Q to quit): ") - if ("q" == input.toLowerCase().trim()) { - authenticated.clear() - break@loop - } else { - input - } - } else { - authKeyFilePass - } - println("Accessing the certificate key group data...") - provider.loginSign(user, authKeyFilePath.toString(), password) - } - AuthMode.PASSWORD -> { - println("Authenticating using password") - val password = readPassword("Enter password (or Q to quit): ") - if ("q" == password.toLowerCase()) { - authenticated.clear() - break@loop - } - println("Accessing the certificate key group data...") - provider.loginPassword(user, password) - } - } - authenticated.add(user!!) - val auth = provider.cryptoServer.authState - if ((auth and 0x0000000F) >= authStrengthThreshold) { - println("Authentication sufficient") - break - } else { - println("Need more permissions. Add extra login") - } - } - if (!authenticated.isEmpty()) { - block(provider, authenticated) - } else { - throw AuthenticationException() - } - } finally { - try { - provider.logoff() - } catch (throwable: Throwable) { - println("WARNING Exception while logging off") - throwable.printStackTrace(System.out) - } - } - } -} - -/* - * Configuration class for [CryptoServerProvider] - */ -data class CryptoServerProviderConfig( - val Device: String = "3001@127.0.0.1", - val ConnectionTimeout: Int = 30000, - val Timeout: Int = 60000, - val EndSessionOnShutdown: Int = 1, - val KeepSessionAlive: Int = 0, - val KeyGroup: String = "*", - val KeySpecifier: Int = -1, - val StoreKeysExternal: Boolean = false -) - -/** - * Creates an instance of [CryptoServerProvider] that corresponds to the HSM. - * - * @param keyGroup HSM key group. - * @param keySpecifier HSM key specifier. - * @param device HSM device address. - * - * @return preconfigured instance of [CryptoServerProvider] - */ -fun createProvider(keyGroup: String, keySpecifier: Int, device: String): CryptoServerProvider { - val config = CryptoServerProviderConfig( - Device = device, - KeyGroup = keyGroup, - KeySpecifier = keySpecifier - ) - return createProvider(config) -} - -/** - * Creates an instance of [CryptoServerProvider] configured accordingly to the passed configuration. - * - * @param config crypto server provider configuration. - * - * @return preconfigured instance of [CryptoServerProvider] - */ -fun createProvider(config: CryptoServerProviderConfig): CryptoServerProvider { - val cfgBuffer = ByteArrayOutputStream() - val writer = cfgBuffer.writer(Charsets.UTF_8) - for (property in CryptoServerProviderConfig::class.memberProperties) { - writer.write("${property.name} = ${property.get(config)}\n") - } - writer.close() - val cfg = cfgBuffer.toByteArray().inputStream() - return CryptoServerProvider(cfg) -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/InputReader.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/InputReader.kt deleted file mode 100644 index 47c05f1d70..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/InputReader.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.authentication - -/** - * User input reader interface - */ -interface InputReader { - /** - * Reads a single line from user's input. - */ - fun readLine(): String? - - /** - * Reads a single line from user's input. The characters from the input are masked while being entered. - * @param format message string displayed before user's input - */ - fun readPassword(format: String): String -} - -class ConsoleInputReader : InputReader { - private val console = System.console() - - /** Read password from console, do a readLine instead if console is null (e.g. when debugging in IDE). */ - override fun readPassword(format: String): String { - return if (console != null) { - String(console.readPassword(format)) - } else { - print(format) - requireNotNull(kotlin.io.readLine()) { "Password required" } - } - } - - /** Read console line */ - override fun readLine(): String? { - return if (console == null) { - kotlin.io.readLine() - } else { - console.readLine() - } - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/configuration/SigningServiceConfig.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/configuration/SigningServiceConfig.kt deleted file mode 100644 index f56ef1c273..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/configuration/SigningServiceConfig.kt +++ /dev/null @@ -1,101 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.configuration - -import com.google.common.primitives.Booleans -import com.r3.corda.networkmanage.common.utils.ArgsParser -import com.r3.corda.networkmanage.hsm.authentication.AuthMode -import joptsimple.OptionSet -import joptsimple.util.PathConverter -import joptsimple.util.PathProperties -import net.corda.core.internal.div -import net.corda.core.utilities.NetworkHostAndPort -import net.corda.nodeapi.internal.crypto.X509KeyStore -import net.corda.nodeapi.internal.persistence.DatabaseConfig -import java.net.URL -import java.nio.file.Path -import java.nio.file.Paths -import java.util.* - -/** - * Configuration parameters. Those are general configuration parameters shared with both - * network map and certificate signing requests processes. - */ -data class SigningServiceConfig(val dataSourceProperties: Properties, - val database: DatabaseConfig = DatabaseConfig(), - val device: String, - val keySpecifier: Int, - val networkMap: NetworkMapCertificateConfig? = null, - val doorman: DoormanCertificateConfig? = null) { - init { - require(Booleans.countTrue(doorman != null, networkMap != null) == 1) { - "Exactly one networkMap or doorman configuration needs to be specified." - } - } -} - -/** - * Network map signing process specific parameters. - */ -data class NetworkMapCertificateConfig(val username: String, - val keyGroup: String, - val authParameters: AuthParametersConfig) - -/** - * Certificate signing requests process specific parameters. - */ -data class DoormanCertificateConfig(val crlDistributionPoint: URL, - val crlServerSocketAddress: NetworkHostAndPort, - val crlUpdatePeriod: Long, - val mode: ManualMode, - val keyGroup: String, - val validDays: Int, - val rootKeyStoreFile: Path, - val rootKeyStorePassword: String, - val authParameters: AuthParametersConfig) { - fun loadRootKeyStore(createNew: Boolean = false): X509KeyStore { - return X509KeyStore.fromFile(rootKeyStoreFile, rootKeyStorePassword, createNew) - } -} - -enum class ManualMode { - CRL, // Run manual mode for the certificate revocation list. - CSR // Run manual mode for the certificate signing requests. -} - -/** - * Authentication related parameters. - */ -data class AuthParametersConfig(val mode: AuthMode, - val password: String? = null, // This is either HSM password or key file password, depending on the mode. - val keyFilePath: Path? = null, - val threshold: Int) - -class SigningServiceArgsParser : ArgsParser() { - private val baseDirArg = optionParser - .accepts("basedir", "Overriding configuration filepath, default to current directory.") - .withRequiredArg() - .withValuesConvertedBy(PathConverter(PathProperties.DIRECTORY_EXISTING)) - .defaultsTo(Paths.get(".")) - private val configFileArg = optionParser - .accepts("config-file", "The path to the config file") - .withRequiredArg() - .withValuesConvertedBy(PathConverter(PathProperties.FILE_EXISTING)) - .required() - - override fun parse(optionSet: OptionSet): SigningServiceCmdLineOptions { - val baseDir = optionSet.valueOf(baseDirArg) - val configFile = optionSet.valueOf(configFileArg) - return SigningServiceCmdLineOptions(baseDir, configFile) - } -} - -data class SigningServiceCmdLineOptions(val baseDir: Path, val configFile: Path) diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/AutoAuthenticator.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/AutoAuthenticator.kt deleted file mode 100644 index 707abc9c0e..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/AutoAuthenticator.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.generator - -import CryptoServerJCE.CryptoServerProvider -import com.r3.corda.networkmanage.hsm.authentication.CryptoServerProviderConfig -import com.r3.corda.networkmanage.hsm.authentication.createProvider - -/** - * Holds configuration necessary for user's authentication against HSM. - */ -data class UserAuthenticationParameters(val username: String, - val authMode: AuthMode, - val authToken: String?, // password or path to the key file, depending on the [authMode] - val keyFilePassword: String?) { // used only if authMode == [AuthMode.KEY_FILE] - init { - require(keyFilePassword == null || authMode == AuthMode.KEY_FILE) { - "keyFilePassword can only be specified if the authMode is set to KEY_FILE" - } - } -} - -/** - * Supported authentication modes. - */ -enum class AuthMode { - PASSWORD, CARD_READER, KEY_FILE -} - -/** - * Performs user authentication against the HSM - */ -class AutoAuthenticator(providerConfig: CryptoServerProviderConfig, - private val userConfigs: List) { - private val provider = createProvider(providerConfig) - - /** - * Interactively (using console) authenticates a user against the HSM. Once authentication is completed successfully - * the [block] is executed. - * @param block to be executed once the authentication process succeeds. The block should take a [CryptoServerProvider] instance as the parameter. - */ - fun connectAndAuthenticate(block: (CryptoServerProvider) -> Unit) { - try { - for (userConfig in userConfigs) { - when (userConfig.authMode) { - AuthMode.PASSWORD -> provider.loginPassword(userConfig.username, userConfig.authToken) - AuthMode.CARD_READER -> provider.loginSign(userConfig.username, ":cs2:cyb:USB0", null) - AuthMode.KEY_FILE -> provider.loginSign(userConfig.username, userConfig.keyFilePassword, userConfig.authToken) - } - } - block(provider) - } finally { - try { - provider.logoff() - } catch (throwable: Throwable) { - println("WARNING Exception while logging off") - throwable.printStackTrace(System.out) - } - } - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/certificate/GeneratorParameters.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/certificate/GeneratorParameters.kt deleted file mode 100644 index fd9fd5d7fc..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/certificate/GeneratorParameters.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.generator.certificate - -import com.r3.corda.networkmanage.hsm.generator.UserAuthenticationParameters -import com.typesafe.config.ConfigFactory -import com.typesafe.config.ConfigParseOptions -import net.corda.nodeapi.internal.config.UnknownConfigKeysPolicy -import net.corda.nodeapi.internal.config.parseAs -import net.corda.nodeapi.internal.crypto.CertificateType -import java.nio.file.Path - -/** - * Holds generator parameters. - */ -data class GeneratorParameters(val hsmHost: String, - val hsmPort: Int, - val trustStoreDirectory: Path, - val trustStorePassword: String, - val userConfigs: List, - val certConfig: CertificateConfiguration) - -/** - * Holds certificate specific configuration. - */ -data class CertificateConfiguration(val keyGroup: String, - val keySpecifier: Int, - val storeKeysExternal: Boolean, - val certificateType: CertificateType, - val rootKeyGroup: String?, - val subject: String, // it is certificate [X500Name] subject - val validDays: Int, - val crlDistributionUrl: String?, - val crlIssuer: String?, // X500 name of the issuing authority e.g. "L=New York, C=US, OU=Org Unit, CN=Service Name" - val keyOverride: Int, // 1 for allow and 0 deny - val keyExport: Int, // 1 for allow, 0 for deny - val keyCurve: String, // we use "NIST-P256", check Utimaco docs for other options - val keyGenMechanism: Int) // MECH_KEYGEN_UNCOMP = 4 or MECH_RND_REAL = 0 - -/** - * Parses a configuration file, which contains all the configuration - i.e. for user and certificate parameters. - */ -fun parseParameters(configFile: Path): GeneratorParameters { - return ConfigFactory - .parseFile(configFile.toFile(), ConfigParseOptions.defaults().setAllowMissing(true)) - .resolve() - .parseAs(UnknownConfigKeysPolicy.IGNORE::handle) -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/certificate/KeyCertificateGenerator.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/certificate/KeyCertificateGenerator.kt deleted file mode 100644 index 604e6ec8c1..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/certificate/KeyCertificateGenerator.kt +++ /dev/null @@ -1,141 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.generator.certificate - -import CryptoServerCXI.CryptoServerCXI.KEY_ALGO_ECDSA -import CryptoServerCXI.CryptoServerCXI.KeyAttributes -import CryptoServerJCE.CryptoServerProvider -import com.r3.corda.networkmanage.common.utils.CORDA_NETWORK_MAP -import com.r3.corda.networkmanage.common.utils.NETWORK_ROOT_TRUSTSTORE_FILENAME -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.cleanEcdsaPublicKey -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.createIntermediateCert -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.createSelfSignedCert -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.getAndInitializeKeyStore -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.retrieveCertAndKeyPair -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.div -import net.corda.core.internal.isDirectory -import net.corda.core.internal.x500Name -import net.corda.core.utilities.contextLogger -import net.corda.nodeapi.internal.crypto.CertificateType.* -import net.corda.nodeapi.internal.crypto.X509KeyStore -import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_INTERMEDIATE_CA -import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA -import org.bouncycastle.asn1.x500.X500Name -import java.nio.file.Path -import java.security.Key -import java.security.KeyPair -import java.security.KeyStore -import java.security.PrivateKey -import java.security.cert.Certificate -import java.security.cert.X509Certificate - -/** - * Encapsulates logic for key and certificate generation. - * - */ -class KeyCertificateGenerator(private val parameters: GeneratorParameters) { - companion object { - val logger = contextLogger() - } - - fun generate(provider: CryptoServerProvider, rootProvider: CryptoServerProvider? = null) { - parameters.run { - require(trustStoreDirectory.isDirectory()) { "trustStoreDirectory must point to a directory." } - val keyName = when (certConfig.certificateType) { - ROOT_CA -> CORDA_ROOT_CA - INTERMEDIATE_CA -> CORDA_INTERMEDIATE_CA - NETWORK_MAP -> CORDA_NETWORK_MAP - else -> throw IllegalArgumentException("Invalid certificate type. ${certConfig.certificateType}") - } - val keyStore = getAndInitializeKeyStore(provider) - val keyPair = certConfig.generateEcdsaKeyPair(keyName, provider, keyStore) - val certChain = if (rootProvider == null) { - arrayOf(certConfig.generateRootCert(provider, keyPair, trustStoreDirectory, trustStorePassword)) - } else { - val rootKeyStore = getAndInitializeKeyStore(rootProvider) - certConfig.generateIntermediateCertChain(rootProvider, keyPair, rootKeyStore) - } - keyStore.addOrReplaceKey(keyName, keyPair.private, null, certChain) - logger.info("New certificate and key pair named $keyName have been generated and stored in HSM") - } - } - - // TODO remove this and modify the node-api internal version of this method - nullable password - fun KeyStore.addOrReplaceKey(alias: String, key: Key, password: CharArray?, chain: Array) { - if (containsAlias(alias)) { - this.deleteEntry(alias) - } - this.setKeyEntry(alias, key, password, chain) - } - - private fun CertificateConfiguration.generateRootCert(provider: CryptoServerProvider, - keyPair: KeyPair, - networkRootTrustStoreDirectory: Path, - networkRootTrustStorePassword: String): X509Certificate { - val rootCert = createSelfSignedCert( - ROOT_CA, - CordaX500Name.parse(subject).x500Name, - keyPair, - validDays, - provider, - crlDistributionUrl, - crlIssuer?.let { X500Name(it) }) - logger.info("Created root cert:\n$rootCert") - val trustStorePath = networkRootTrustStoreDirectory / NETWORK_ROOT_TRUSTSTORE_FILENAME - X509KeyStore.fromFile(trustStorePath, networkRootTrustStorePassword, createNew = true).update { - setCertificate(CORDA_ROOT_CA, rootCert) - } - logger.info("Trust store containing the root for distribution to the nodes created in $trustStorePath") - return rootCert - } - - private fun CertificateConfiguration.generateIntermediateCertChain( - provider: CryptoServerProvider, - keyPair: KeyPair, - rootKeyStore: KeyStore): Array { - logger.info("Retrieving the root key pair.") - val rootKeysAndCertChain = retrieveCertAndKeyPair(CORDA_ROOT_CA, rootKeyStore) - val certificateAndKeyPair = createIntermediateCert( - certificateType, - CordaX500Name.parse(subject).x500Name, - rootKeysAndCertChain, - keyPair, - validDays, - provider, - crlDistributionUrl, - crlIssuer?.let { X500Name(it) }) - logger.info("Certificate for $subject created.") - return arrayOf(certificateAndKeyPair.certificate, rootKeysAndCertChain.certificate) - } - - private fun CertificateConfiguration.generateECDSAKey(keyName: String, provider: CryptoServerProvider) { - val keyAttributes = KeyAttributes() - keyAttributes.apply { - algo = KEY_ALGO_ECDSA - group = keyGroup - specifier = keySpecifier - export = keyExport - name = keyName - setCurve(keyCurve) - } - logger.info("Generating key $keyName.") - provider.cryptoServer.generateKey(keyOverride, keyAttributes, keyGenMechanism) - logger.info("$keyName key generated.") - } - - private fun CertificateConfiguration.generateEcdsaKeyPair(keyName: String, provider: CryptoServerProvider, keyStore: KeyStore): KeyPair { - generateECDSAKey(keyName, provider) - val privateKey = keyStore.getKey(keyName, null) as PrivateKey - val publicKey = keyStore.getCertificate(keyName).publicKey - return KeyPair(cleanEcdsaPublicKey(publicKey), privateKey) - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/certificate/Main.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/certificate/Main.kt deleted file mode 100644 index 7a5f35e5ad..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/certificate/Main.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.generator.certificate - -import com.r3.corda.networkmanage.common.configuration.ConfigFilePathArgsParser -import com.r3.corda.networkmanage.hsm.authentication.CryptoServerProviderConfig -import com.r3.corda.networkmanage.hsm.generator.AutoAuthenticator -import com.r3.corda.networkmanage.hsm.utils.mapCryptoServerException -import net.corda.nodeapi.internal.crypto.CertificateType.ROOT_CA -import org.apache.logging.log4j.LogManager - -private val logger = LogManager.getLogger("com.r3.corda.networkmanage.hsm.generator.certificate.Main") - -fun main(args: Array) { - run(parseParameters(ConfigFilePathArgsParser().parseOrExit(*args))) -} - -fun run(parameters: GeneratorParameters) { - parameters.run { - val providerConfig = CryptoServerProviderConfig( - Device = "$hsmPort@$hsmHost", - KeySpecifier = certConfig.keySpecifier, - KeyGroup = certConfig.keyGroup, - StoreKeysExternal = certConfig.storeKeysExternal) - try { - AutoAuthenticator(providerConfig, userConfigs).connectAndAuthenticate { provider -> - val generator = KeyCertificateGenerator(this) - logger.info("Generating ${certConfig.certificateType.name} certificate.") - if (certConfig.certificateType == ROOT_CA) { - generator.generate(provider) - } else { - requireNotNull(certConfig.rootKeyGroup) - val rootProviderConfig = CryptoServerProviderConfig( - Device = "$hsmPort@$hsmHost", - KeySpecifier = certConfig.keySpecifier, - KeyGroup = requireNotNull(certConfig.rootKeyGroup) { "rootKeyGroup needs to be specified." }, - StoreKeysExternal = certConfig.storeKeysExternal) - AutoAuthenticator(rootProviderConfig, userConfigs).connectAndAuthenticate { rootProvider -> - generator.generate(provider, rootProvider) - rootProvider.logoff() - } - } - provider.logoff() - } - } catch (e: Exception) { - logger.error("HSM certificate generation error.", mapCryptoServerException(e)) - } - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/crl/GeneratorConfig.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/crl/GeneratorConfig.kt deleted file mode 100644 index 917e9f0a27..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/crl/GeneratorConfig.kt +++ /dev/null @@ -1,81 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.generator.crl - -import com.r3.corda.networkmanage.common.utils.SupportedCrlReasons -import com.r3.corda.networkmanage.hsm.generator.UserAuthenticationParameters -import com.typesafe.config.ConfigFactory -import com.typesafe.config.ConfigParseOptions -import net.corda.nodeapi.internal.config.UnknownConfigKeysPolicy -import net.corda.nodeapi.internal.config.parseAs -import net.corda.nodeapi.internal.crypto.X509KeyStore -import java.net.URL -import java.nio.file.Path - -/** - * Holds generator parameters. - */ -data class GeneratorConfig(val hsmHost: String, - val hsmPort: Int, - val userConfigs: List, - val trustStoreFile: Path, - val trustStorePassword: String, - val crl: CrlConfig) { - fun loadTrustStore(): X509KeyStore { - return X509KeyStore.fromFile(trustStoreFile, trustStorePassword, false) - } -} - -/** - * Holds CRL specific configuration. - */ -data class CrlConfig(val keyGroup: String, - val keySpecifier: Int, - val validDays: Long, - val crlEndpoint: URL, - val indirectIssuer: Boolean, - val filePath: Path, - val revocations: List = emptyList()) - -/** - * Supported revocation reasons: - * UNSPECIFIED, - * KEY_COMPROMISE, - * CA_COMPROMISE, - * AFFILIATION_CHANGED, - * SUPERSEDED, - * CESSATION_OF_OPERATION, - * PRIVILEGE_WITHDRAWN - */ -data class RevocationConfig(val certificateSerialNumber: String, val dateInMillis: Long, val reason: String) { - - companion object { - val reasonErrorMessage = "Error when parsing the revocation reason. Allowed values: ${SupportedCrlReasons.values()}" - } - - init { - try { - SupportedCrlReasons.valueOf(reason) - } catch (e: Exception) { - throw IllegalArgumentException(reasonErrorMessage) - } - } -} - -/** - * Parses a configuration file, which contains all the configuration - i.e. for user and certificate parameters. - */ -fun parseParameters(configFile: Path): GeneratorConfig { - return ConfigFactory - .parseFile(configFile.toFile(), ConfigParseOptions.defaults().setAllowMissing(true)) - .resolve() - .parseAs(UnknownConfigKeysPolicy.IGNORE::handle) -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/crl/Main.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/crl/Main.kt deleted file mode 100644 index 0022fa129c..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/generator/crl/Main.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.generator.crl - -import com.r3.corda.networkmanage.common.configuration.ConfigFilePathArgsParser -import com.r3.corda.networkmanage.common.utils.Revocation -import com.r3.corda.networkmanage.common.utils.createSignedCrl -import com.r3.corda.networkmanage.hsm.authentication.CryptoServerProviderConfig -import com.r3.corda.networkmanage.hsm.generator.AutoAuthenticator -import com.r3.corda.networkmanage.hsm.signer.HsmSigner -import com.r3.corda.networkmanage.hsm.utils.mapCryptoServerException -import net.corda.nodeapi.internal.crypto.X509Utilities -import org.apache.commons.io.FileUtils -import org.apache.logging.log4j.LogManager -import java.math.BigInteger -import java.security.cert.CRLReason -import java.time.Duration -import java.util.* - -private val logger = LogManager.getLogger("com.r3.corda.networkmanage.hsm.generator.crl.Main") - -fun main(args: Array) { - run(parseParameters(ConfigFilePathArgsParser().parseOrExit(*args))) -} - -fun run(parameters: GeneratorConfig) { - parameters.run { - val providerConfig = CryptoServerProviderConfig( - Device = "$hsmPort@$hsmHost", - KeySpecifier = crl.keySpecifier, - KeyGroup = crl.keyGroup) - try { - AutoAuthenticator(providerConfig, userConfigs).connectAndAuthenticate { provider -> - logger.info("Generating an empty CRL...") - val issuerCertificate = loadTrustStore().getCertificate(X509Utilities.CORDA_ROOT_CA) - val generatedCrl = createSignedCrl(issuerCertificate, - crl.crlEndpoint, - Duration.ofDays(crl.validDays), - HsmSigner(provider = provider, keyName = X509Utilities.CORDA_ROOT_CA), - crl.revocations.map { Revocation( - BigInteger(it.certificateSerialNumber), - Date(it.dateInMillis), - CRLReason.valueOf(it.reason) - ) }, - crl.indirectIssuer) - FileUtils.writeByteArrayToFile(crl.filePath.toFile(), generatedCrl.encoded) - provider.logoff() - } - } catch (e: Exception) { - logger.error("HSM CRL generation error.", mapCryptoServerException(e)) - } - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/menu/Menu.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/menu/Menu.kt deleted file mode 100644 index 93bc136757..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/menu/Menu.kt +++ /dev/null @@ -1,113 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.menu - -/** - * Single menu item described by the selection [key], label associated with this item, action to be executed on response - * to the item selection and termination flag used to decide whether to loop after action completion. - */ -data class MenuItem(val key: String, val label: String, val action: () -> Unit, val isTerminating: Boolean = false) - -/** - * A generic menu class for console based interactions with user. - * Inspired by https://github.com/bryandh/genericmenu, but adjusted to our the particular needs of this project. - */ -class Menu { - private val items = mutableMapOf() - private var quit: Pair? = null - private var exceptionHandler: (exception: Exception) -> Unit = { exception -> println(exception.message) } - - /** - * Adds a menu item to the list of the menu items. The order in which the items are added matters. - * If the exit option is set (@see [setExitOption] then it will be displayed always as the last element in the menu. - * - * @param key itemization label. E.g. If you pass "1", it will be displayed as [1]. - * @param label menu item label - * @param action lambda that is executed when user selects this option. - * @param isTerminating flag that specifies whether the completion of the action should exit this menu. - */ - fun addItem(key: String, label: String, action: () -> Unit, isTerminating: Boolean = false): Menu { - items[key.toLowerCase()] = MenuItem(key, label, action, isTerminating) - return this - } - - /** - * Assigns the exception handler for this menu. The exception handler is invoked every time - * any of the menu item selection handler function throws an exception. - * - */ - fun withExceptionHandler(handler: (exception: Exception) -> Unit): Menu { - exceptionHandler = handler - return this - } - - /** - * Sets the exit option with given key and label. - */ - fun setExitOption(key: String, label: String): Menu { - quit = Pair(key, label) - return this - } - - /** - * Removes exit option from the list of the menu items. - */ - fun unsetExitOption(): Menu { - quit = null - return this - } - - private fun printItems() { - items.forEach { _, (key, label, _) -> println("[$key] $label") } - if (quit != null) println("[${quit?.first}] ${quit?.second}") - } - - private fun readInput(): String? { - print("> ") - return readLine() - } - - private fun run(key: String): Boolean { - val selected = items[key.toLowerCase()] - if (selected == null) { - throw IllegalArgumentException("No valid option for $key found, try again.") - } else { - selected.action() - return selected.isTerminating - } - } - - /** - * Shows the menu built out of the given menu items and (if present) exit option. - */ - fun showMenu() { - while (true) { - printItems() - val choice = readInput() - if (choice != null) { - if ((quit != null) && choice.toLowerCase() == quit!!.first.toLowerCase()) { - break - } else { - try { - if (run(choice)) { - break - } - } catch (exception: Exception) { - exceptionHandler(exception) - } - } - } else { - // No more input - break - } - } - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/persistence/DBSignedCertificateRequestStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/persistence/DBSignedCertificateRequestStorage.kt deleted file mode 100644 index dab1bf6743..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/persistence/DBSignedCertificateRequestStorage.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.persistence - -import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequest -import com.r3.corda.networkmanage.common.persistence.PersistentCertificateSigningRequestStorage -import com.r3.corda.networkmanage.common.persistence.RequestStatus -import net.corda.nodeapi.internal.persistence.CordaPersistence -import org.bouncycastle.pkcs.PKCS10CertificationRequest -import java.security.cert.CertPath - -data class ApprovedCertificateRequestData(val requestId: String, val request: PKCS10CertificationRequest, var certPath: CertPath? = null) - -class DBSignedCertificateRequestStorage(database: CordaPersistence) : SignedCertificateSigningRequestStorage { - - private val storage = PersistentCertificateSigningRequestStorage(database) - - override fun store(requests: List, signer: String) { - for ((requestId, _, certPath) in requests) { - storage.putCertificatePath(requestId, certPath!!, signer) - } - } - - override fun getApprovedRequests(): List { - return storage.getRequests(RequestStatus.APPROVED).map { it.toRequestData() } - } - - private fun CertificateSigningRequest.toRequestData() = ApprovedCertificateRequestData(requestId, request) -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/persistence/SignedCertificateSigningRequestStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/persistence/SignedCertificateSigningRequestStorage.kt deleted file mode 100644 index 7520ee408f..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/persistence/SignedCertificateSigningRequestStorage.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.persistence - -/** - * Provides an API for storing signed CSRs (Certificate Signing Requests). - */ -interface SignedCertificateSigningRequestStorage { - - /** - * Returns all certificate signing requests that have been approved for signing. - */ - fun getApprovedRequests(): List - - /** - * Marks the database CSR entries as signed. Also it persists the certificate and the signature in the database. - * - * @param requests Signed requests that are to be stored. - * @param signers List of user names that signed those requests. To be specific, each request has been signed by all of those users. - */ - fun store(requests: List, signer: String) -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/processor/CrrProcessor.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/processor/CrrProcessor.kt deleted file mode 100644 index 9d95b5962c..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/processor/CrrProcessor.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.r3.corda.networkmanage.hsm.processor - -import com.r3.corda.networkmanage.common.persistence.CrlIssuer -import com.r3.corda.networkmanage.common.signer.CertificateRevocationListSigner -import com.r3.corda.networkmanage.hsm.authentication.Authenticator -import com.r3.corda.networkmanage.hsm.authentication.createProvider -import com.r3.corda.networkmanage.hsm.configuration.DoormanCertificateConfig -import com.r3.corda.networkmanage.hsm.menu.Menu -import com.r3.corda.networkmanage.hsm.signer.HsmSigner -import com.r3.corda.networkmanage.hsm.sockets.SocketCertificateRevocationList -import com.r3.corda.networkmanage.hsm.sockets.CertificateRevocationRequestRetriever -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.getAndInitializeKeyStore -import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_INTERMEDIATE_CA -import net.corda.nodeapi.internal.crypto.getX509Certificate -import java.time.Duration - -class CrrProcessor(private val config: DoormanCertificateConfig, - private val device: String, - private val keySpecifier: Int) : Processor() { - private companion object { - private const val RESET = "\u001B[0m" - private const val BLACK = "\u001B[30m" - private const val RED = "\u001B[31m" - private const val GREEN = "\u001B[32m" - private const val YELLOW = "\u001B[33m" - private const val BLUE = "\u001B[34m" - private const val CYAN = "\u001B[36m" - private const val WHITE = "\u001B[37m" - } - - private val auth = config.authParameters - - fun showMenu() { - val authenticator = Authenticator( - provider = createProvider(config.keyGroup, keySpecifier, device), - mode = auth.mode, - authStrengthThreshold = auth.threshold) - Menu().withExceptionHandler(this::processError).setExitOption("2", "Quit").addItem("1", "View current and sign a new certificate revocation list", { - val crlTransceiver = SocketCertificateRevocationList(config.crlServerSocketAddress) - val currentCrl = crlTransceiver.getCertificateRevocationList(CrlIssuer.DOORMAN) - printlnColor("Current CRL:") - printlnColor(currentCrl.toString(), YELLOW) - val crrRetriever = CertificateRevocationRequestRetriever(config.crlServerSocketAddress) - val approvedRequests = crrRetriever.retrieveApprovedCertificateRevocationRequests() - if (approvedRequests.isEmpty()) { - printlnColor("There are no approved Certificate Revocation Requests.", GREEN) - } else { - printlnColor("Following are the approved Certificate Revocation Requests which will be added to the CRL:") - approvedRequests.forEach { - printlnColor("Certificate DN: ${it.legalName}, Certificate serial number: ${it.certificateSerialNumber}", GREEN) - } - } - Menu().withExceptionHandler(this::processError).setExitOption("2", "Go back"). - addItem("1", "Create and sign a new Certificate Revocation List", { - authenticator.connectAndAuthenticate { provider, signers -> - val keyStore = getAndInitializeKeyStore(provider) - val issuerCertificate = keyStore.getX509Certificate(CORDA_INTERMEDIATE_CA) - val crlSigner = CertificateRevocationListSigner( - revocationListStorage = crlTransceiver, - issuerCertificate = issuerCertificate, - updateInterval = Duration.ofMillis(config.crlUpdatePeriod), - endpoint = config.crlDistributionPoint, - signer = HsmSigner(provider = provider, keyName = CORDA_INTERMEDIATE_CA)) - val currentRequests = crrRetriever.retrieveDoneCertificateRevocationRequests() - crlSigner.createSignedCRL(approvedRequests, currentRequests, signers.toString()) - } - }) - }).showMenu() - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/processor/CsrProcessor.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/processor/CsrProcessor.kt deleted file mode 100644 index 42efac8ab5..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/processor/CsrProcessor.kt +++ /dev/null @@ -1,124 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.processor - -import com.r3.corda.networkmanage.hsm.authentication.Authenticator -import com.r3.corda.networkmanage.hsm.authentication.createProvider -import com.r3.corda.networkmanage.hsm.configuration.DoormanCertificateConfig -import com.r3.corda.networkmanage.hsm.menu.Menu -import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData -import com.r3.corda.networkmanage.hsm.persistence.DBSignedCertificateRequestStorage -import com.r3.corda.networkmanage.hsm.persistence.SignedCertificateSigningRequestStorage -import com.r3.corda.networkmanage.hsm.signer.HsmCsrSigner -import net.corda.core.utilities.contextLogger -import net.corda.nodeapi.internal.persistence.CordaPersistence - -class CsrProcessor(private val config: DoormanCertificateConfig, - private val device: String, - private val keySpecifier: Int, - private val database: CordaPersistence) : Processor() { - private companion object { - private val logger = contextLogger() - } - - private val auth = config.authParameters - - fun showMenu() { - val csrStorage = DBSignedCertificateRequestStorage(database) - val authenticator = Authenticator( - provider = createProvider(config.keyGroup, keySpecifier, device), - mode = auth.mode, - authStrengthThreshold = auth.threshold) - val signCsr: (List) -> Unit = { - val csrSigner = config.run { - HsmCsrSigner( - csrStorage, - loadRootKeyStore(), - crlDistributionPoint.toString(), - null, - validDays, - authenticator) - } - logger.debug("Signing requests: $it") - csrSigner.sign(it) - } - showMenu(csrStorage, signCsr) - } - - private fun showMenu(csrStorage: SignedCertificateSigningRequestStorage, signCsr: (List) -> Unit) { - Menu().withExceptionHandler(this::processError).setExitOption("3", "Quit").addItem("1", "Sign all approved and unsigned CSRs", { - logger.debug("Fetching approved requests...") - val approved = csrStorage.getApprovedRequests() - logger.debug("Approved requests fetched: $approved") - if (approved.isNotEmpty()) { - if (confirmedSign(approved)) { - signCsr(approved) - } - } else { - printlnColor("There are no approved CSRs") - } - }).addItem("2", "List all approved and unsigned CSRs", { - logger.debug("Fetching approved requests...") - val approved = csrStorage.getApprovedRequests() - logger.debug("Approved requests fetched: $approved") - if (approved.isNotEmpty()) { - printlnColor("Approved CSRs:") - approved.forEachIndexed { index, item -> printlnColor("${index + 1}. ${item.request.subject}") } - Menu().withExceptionHandler(this::processError).setExitOption("3", "Go back"). - addItem("1", "Sign all listed CSRs", { - if (confirmedSign(approved)) { - signCsr(approved) - } - }, isTerminating = true). - addItem("2", "Select and sign CSRs", { - val selectedItems = getSelection(approved) - if (confirmedSign(selectedItems)) { - signCsr(selectedItems) - } - }, isTerminating = true).showMenu() - } else { - printlnColor("There is no approved and unsigned CSR") - } - }).showMenu() - } - - private fun confirmedSign(selectedItems: List): Boolean { - printlnColor("Are you sure you want to sign the following requests:") - selectedItems.forEachIndexed { index, data -> - printlnColor("${index + 1} ${data.request.subject}") - } - var result = false - Menu().addItem("Y", "Yes", { result = true }, true).setExitOption("N", "No").showMenu() - return result - } - - private fun getSelection(toSelect: List): List { - print("CSRs to be signed (comma separated list): ") - val line = readLine() - if (line == null) { - printlnColor("EOF reached") - return emptyList() - } - return try { - line.split(",").map { - val result = it.toInt() - 1 - if (result > toSelect.size - 1) { - throw IllegalArgumentException("Selected ${result + 1} item is out of bounds") - } else { - toSelect[result] - } - } - } catch (exception: Exception) { - printlnColor(exception.message) - emptyList() - } - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/processor/NetworkMapProcessor.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/processor/NetworkMapProcessor.kt deleted file mode 100644 index a513755ba8..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/processor/NetworkMapProcessor.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.processor - -import com.r3.corda.networkmanage.common.persistence.PersistentNetworkMapStorage -import com.r3.corda.networkmanage.common.signer.NetworkMapSigner -import com.r3.corda.networkmanage.common.utils.CORDA_NETWORK_MAP -import com.r3.corda.networkmanage.hsm.authentication.AuthMode -import com.r3.corda.networkmanage.hsm.authentication.Authenticator -import com.r3.corda.networkmanage.hsm.authentication.createProvider -import com.r3.corda.networkmanage.hsm.configuration.NetworkMapCertificateConfig -import com.r3.corda.networkmanage.hsm.signer.HsmSigner -import net.corda.core.utilities.contextLogger -import net.corda.nodeapi.internal.persistence.CordaPersistence - -class NetworkMapProcessor(private val config: NetworkMapCertificateConfig, - private val device: String, - private val keySpecifier: Int, - private val database: CordaPersistence) { - companion object { - val logger = contextLogger() - } - - init { - config.authParameters.run { - requireNotNull(password) - require(mode != AuthMode.CARD_READER) - if (mode == AuthMode.KEY_FILE) { - require(keyFilePath != null) { "Key file path cannot be null when authentication mode is ${AuthMode.KEY_FILE}" } - } - } - } - - fun run() { - logger.info("Starting network map processor.") - config.run { - val networkMapStorage = PersistentNetworkMapStorage(database) - val signer = HsmSigner( - Authenticator( - AuthMode.KEY_FILE, - username, - authParameters.keyFilePath, - authParameters.password, - authParameters.threshold, - provider = createProvider(keyGroup, keySpecifier, device)), - keyName = CORDA_NETWORK_MAP) - val networkMapSigner = NetworkMapSigner(networkMapStorage, signer) - try { - logger.info("Executing network map signing...") - networkMapSigner.signNetworkMaps() - } catch (e: Exception) { - logger.error("Exception thrown while signing network map", e) - } - } - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/processor/Processor.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/processor/Processor.kt deleted file mode 100644 index 7cf9d90c31..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/processor/Processor.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.r3.corda.networkmanage.hsm.processor - -import com.r3.corda.networkmanage.hsm.utils.mapCryptoServerException - -abstract class Processor { - - protected fun processError(exception: Exception) { - val processed = mapCryptoServerException(exception) - System.err.println("An error occurred:") - processed.printStackTrace() - } - - protected fun printlnColor(line: String?, color: String = "") { - println(color + line) - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/CertificateSigningRequestSigner.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/CertificateSigningRequestSigner.kt deleted file mode 100644 index cbd312d191..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/CertificateSigningRequestSigner.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.signer - -import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData - -/** - * Encapsulates the logic related to the certificate signing process. - */ -interface CertificateSigningRequestSigner { - - /** - * Signs the provided list of [ApprovedCertificateRequestData] with the key/certificate chosen - * by the implementing class. - */ - fun sign(toSign: List) - -} \ No newline at end of file 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 deleted file mode 100644 index dcdebe5349..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmCsrSigner.kt +++ /dev/null @@ -1,84 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.signer - -import com.r3.corda.networkmanage.common.utils.getCertRole -import com.r3.corda.networkmanage.hsm.authentication.Authenticator -import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData -import com.r3.corda.networkmanage.hsm.persistence.SignedCertificateSigningRequestStorage -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.createClientCertificate -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.getAndInitializeKeyStore -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.retrieveCertAndKeyPair -import net.corda.core.utilities.contextLogger -import net.corda.nodeapi.internal.crypto.X509KeyStore -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.buildCertPath -import net.corda.nodeapi.internal.crypto.certificateType -import org.bouncycastle.asn1.x500.X500Name -import java.io.PrintStream - -/** - * Encapsulates certificate signing logic - */ -class HsmCsrSigner(private val storage: SignedCertificateSigningRequestStorage, - private val rootKeyStore: X509KeyStore, - private val csrCertCrlDistPoint: String, - private val csrCertCrlIssuer: String?, - private val validDays: Int, - private val authenticator: Authenticator, - private val printStream: PrintStream = System.out) : CertificateSigningRequestSigner { - - companion object { - val logger = contextLogger() - } - - /** - * Signs the provided list of approved certificate signing requests. By signature we mean creation of the client-level certificate - * that is accompanied with a key pair (public + private) and signed by the intermediate CA (stored on the HSM) - * using its private key. - * That key (along with the certificate) is retrieved from the key store obtained from the provider given as a result of the - * connectAndAuthenticate method of the authenticator. - * The method iterates through the collection of the [ApprovedCertificateRequestData] instances passed as the method parameter - * and sets the certificate field with an appropriate value. - * @param toSign list of approved certificates to be signed - */ - override fun sign(toSign: List) { - authenticator.connectAndAuthenticate { provider, signers -> - logger.debug("Retrieving the root certificate ${CORDA_ROOT_CA} from HSM...") - val rootCert = rootKeyStore.getCertificate(CORDA_ROOT_CA) - logger.debug("Initializing doorman key store...") - val keyStore = getAndInitializeKeyStore(provider) - logger.debug("Retrieving the doorman certificate $CORDA_INTERMEDIATE_CA from HSM...") - val doormanCertAndKey = retrieveCertAndKeyPair(CORDA_INTERMEDIATE_CA, keyStore) - toSign.forEach { - val certRole = it.request.getCertRole() - val nodeCaCert = createClientCertificate( - certRole.certificateType, - doormanCertAndKey, - it.request, - validDays, - provider, - csrCertCrlDistPoint, - csrCertCrlIssuer?.let { X500Name(it) }) - it.certPath = buildCertPath(nodeCaCert, doormanCertAndKey.certificate, rootCert) - } - logger.debug("Storing signed CSRs...") - storage.store(toSign, signers.toString()) - printStream.println("The following certificates have been signed by $signers:") - logger.debug("The following certificates have been signed by $signers:") - toSign.forEachIndexed { index, data -> - printStream.println("${index + 1} ${data.request.subject}") - logger.debug("${index + 1} ${data.request.subject}") - } - } - } -} \ No newline at end of file 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 deleted file mode 100644 index 78b0d3ee0f..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmSigner.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.signer - -import CryptoServerJCE.CryptoServerProvider -import com.google.common.primitives.Booleans -import com.r3.corda.networkmanage.common.signer.Signer -import com.r3.corda.networkmanage.hsm.authentication.Authenticator -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.getAndInitializeKeyStore -import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.verify -import net.corda.core.internal.DigitalSignatureWithCert -import net.corda.nodeapi.internal.crypto.getX509Certificate -import java.security.PrivateKey -import java.security.Signature - -/** - * Signer which connects to a HSM using the given [authenticator] and provider to sign bytes. - */ -class HsmSigner(private val authenticator: Authenticator? = null, - private val provider: CryptoServerProvider? = null, - private val keyName: String) : Signer { - /** - * Signs given data using [CryptoServerJCE.CryptoServerProvider], which connects to the underlying HSM. - */ - init { - require(Booleans.countTrue(authenticator != null, provider != null) == 1) { - "Either authenticator or provider needs to be non-null." - } - } - - override fun signBytes(data: ByteArray): DigitalSignatureWithCert { - if (provider == null) { - return authenticator!!.connectAndAuthenticate { provider, _ -> - signBytes(data, provider) - } - } else { - return signBytes(data, provider) - } - } - - private fun signBytes(data: ByteArray, provider: CryptoServerProvider): DigitalSignatureWithCert { - val keyStore = getAndInitializeKeyStore(provider) - val certificate = keyStore.getX509Certificate(keyName) - // Don't worry this is not a real private key but a pointer to one that resides in the HSM. It only works - // when used with the given provider. - val key = keyStore.getKey(keyName, null) as PrivateKey - val signature = Signature.getInstance(HsmX509Utilities.SIGNATURE_ALGORITHM, provider).run { - initSign(key) - update(data) - sign() - } - verify(data, signature, certificate.publicKey) - return DigitalSignatureWithCert(certificate, signature) - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/sockets/CertificateRevocationRequestRetriever.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/sockets/CertificateRevocationRequestRetriever.kt deleted file mode 100644 index 0da2d7b1ff..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/sockets/CertificateRevocationRequestRetriever.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.r3.corda.networkmanage.hsm.sockets - -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationRequestData -import com.r3.corda.networkmanage.common.persistence.RequestStatus -import com.r3.corda.networkmanage.common.sockets.CrrsByStatusMessage -import com.r3.corda.networkmanage.common.utils.readObject -import com.r3.corda.networkmanage.common.utils.writeObject -import net.corda.core.utilities.NetworkHostAndPort -import net.corda.core.utilities.contextLogger -import java.net.Socket - -class CertificateRevocationRequestRetriever(private val serverHostAndPort: NetworkHostAndPort) { - - private companion object { - private val logger = contextLogger() - } - - fun retrieveApprovedCertificateRevocationRequests(): List { - return retrieveCertificateRevocationRequests(RequestStatus.APPROVED) - } - - fun retrieveDoneCertificateRevocationRequests(): List { - return retrieveCertificateRevocationRequests(RequestStatus.DONE) - } - - private fun retrieveCertificateRevocationRequests(status: RequestStatus): List { - require(status == RequestStatus.DONE || status == RequestStatus.APPROVED) { "Allowed status values: APPROVED, DONE" } - return Socket(serverHostAndPort.host, serverHostAndPort.port).use { - it.getOutputStream().let { - logger.debug("Requesting $status certificate revocation requests...") - it.writeObject(CrrsByStatusMessage(status)) - } - it.getInputStream().readObject() - } - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/sockets/SocketCertificateRevocationList.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/sockets/SocketCertificateRevocationList.kt deleted file mode 100644 index 0dc722fcf2..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/sockets/SocketCertificateRevocationList.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.r3.corda.networkmanage.hsm.sockets - -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationListStorage -import com.r3.corda.networkmanage.common.persistence.CrlIssuer -import com.r3.corda.networkmanage.common.sockets.CertificateRevocationListSubmission -import com.r3.corda.networkmanage.common.sockets.CrlResponseMessage -import com.r3.corda.networkmanage.common.sockets.CrlRetrievalMessage -import com.r3.corda.networkmanage.common.sockets.CrlSubmissionMessage -import com.r3.corda.networkmanage.common.utils.readObject -import com.r3.corda.networkmanage.common.utils.writeObject -import net.corda.core.utilities.NetworkHostAndPort -import net.corda.core.utilities.contextLogger -import java.net.Socket -import java.security.cert.X509CRL -import java.time.Instant - -class SocketCertificateRevocationList(private val serverHostAndPort: NetworkHostAndPort) : CertificateRevocationListStorage { - - private companion object { - private val logger = contextLogger() - } - - override fun getCertificateRevocationList(crlIssuer: CrlIssuer): X509CRL? { - return Socket(serverHostAndPort.host, serverHostAndPort.port).use { - logger.debug("Requesting the current revocation list...") - it.getOutputStream().writeObject(CrlRetrievalMessage()) - it.getInputStream().readObject().crl - } - } - - override fun saveCertificateRevocationList(crl: X509CRL, crlIssuer: CrlIssuer, signedBy: String, revokedAt: Instant) { - Socket(serverHostAndPort.host, serverHostAndPort.port).use { - it.getOutputStream().let { - it.writeObject(CrlSubmissionMessage()) - logger.debug("Submitting a new revocation list...") - it.writeObject(CertificateRevocationListSubmission(crl, signedBy, revokedAt)) - } - } - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/utils/HsmErrors.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/utils/HsmErrors.kt deleted file mode 100644 index 6ef1a5f04c..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/utils/HsmErrors.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.utils - -import CryptoServerAPI.CryptoServerException -import java.util.* - -/** - * CryptoServer error translator object. - * It holds mapping between CryptoServer error code to its human readable description. - */ -// TODO this code (incl. the hsm_errors file) is duplicated with the SGX module -object HsmErrors { - val errors: Map by lazy(HsmErrors::load) - - private fun load(): Map { - val errors = HashMap() - val hsmErrorsStream = HsmErrors::class.java.getResourceAsStream("hsm_errors") - hsmErrorsStream.bufferedReader().lines().reduce(null) { previous, current -> - if (previous == null) { - current - } else { - errors[java.lang.Long.decode(previous).toInt()] = current - null - } - } - return errors - } -} - -/** - * Utility function for providing human readable error description in case of the [CryptoServerException] being thrown. - * If the exception is of different type the method does nothing. - */ -fun mapCryptoServerException(exception: Exception): Exception { - // Try to decode the error code - val crypto = exception as? CryptoServerException ?: exception.cause as? CryptoServerException - return if (crypto != null) { - Exception("(CryptoServer) ${HsmErrors.errors[crypto.ErrorCode]}", exception) - } else { - exception - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/utils/HsmX509Utilities.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/utils/HsmX509Utilities.kt deleted file mode 100644 index 07badd7803..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/utils/HsmX509Utilities.kt +++ /dev/null @@ -1,310 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.utils - -import CryptoServerJCE.CryptoServerProvider -import net.corda.core.CordaOID -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.x500Name -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import net.corda.nodeapi.internal.crypto.CertificateType -import net.corda.nodeapi.internal.crypto.getX509Certificate -import net.corda.nodeapi.internal.crypto.toJca -import org.bouncycastle.asn1.ASN1EncodableVector -import org.bouncycastle.asn1.ASN1ObjectIdentifier -import org.bouncycastle.asn1.ASN1Sequence -import org.bouncycastle.asn1.DERSequence -import org.bouncycastle.asn1.x500.X500Name -import org.bouncycastle.asn1.x509.* -import org.bouncycastle.cert.X509CertificateHolder -import org.bouncycastle.cert.X509v3CertificateBuilder -import org.bouncycastle.cert.bc.BcX509ExtensionUtils -import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils -import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder -import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder -import org.bouncycastle.pkcs.PKCS10CertificationRequest -import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest -import java.math.BigInteger -import java.security.* -import java.security.cert.X509Certificate -import java.security.spec.X509EncodedKeySpec -import java.time.Instant -import java.time.temporal.ChronoUnit -import java.util.* - -object HsmX509Utilities { - - const val SIGNATURE_ALGORITHM = "SHA256withECDSA" - - /** - * Create a de novo root self-signed X509 v3 CA cert for the specified [KeyPair]. - * @param type type of the certificate to be created - * @param subject X500 name of the certificate subject - * @param keyPair public and private keys to be associated with the generated certificate - * @param validDays number of days which this certificate is valid for - * @param provider provider to be used during the certificate signing process - * @param crlDistPoint url to the certificate revocation list of this certificate - * @param crlIssuer issuer of the certificate revocation list of this certificate - * @return the new root cert. - * Note the generated certificate tree is capped at max depth of 2 to be in line with commercially available certificates - */ - fun createSelfSignedCert(type: CertificateType, - subject: X500Name, - keyPair: KeyPair, - validDays: Int, - provider: Provider, - crlDistPoint: String? = null, - crlIssuer: X500Name? = null): X509Certificate { - // TODO this needs to be changed - val serial = BigInteger.valueOf(random63BitValue(provider)) - - // Ten year certificate validity - // TODO how do we manage certificate expiry, revocation and loss - val window = getCertificateValidityWindow(0, validDays) - val keyPurposes = DERSequence(ASN1EncodableVector().apply { type.purposes.forEach { add(it) } }) - - val builder = JcaX509v3CertificateBuilder(subject, serial, window.first, window.second, subject, keyPair.public) - builder.addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyIdentifier(keyPair.public)) - builder.addExtension(Extension.basicConstraints, true, BasicConstraints(type.isCA)) - builder.addExtension(Extension.keyUsage, false, type.keyUsage) - builder.addExtension(Extension.extendedKeyUsage, false, keyPurposes) - builder.addExtension(Extension.authorityKeyIdentifier, false, JcaX509ExtensionUtils().createAuthorityKeyIdentifier(keyPair.public)) - if (type.role != null) { - builder.addExtension(ASN1ObjectIdentifier(CordaOID.X509_EXTENSION_CORDA_ROLE), false, type.role) - } - addCrlInfo(builder, crlDistPoint, crlIssuer) - - val cert = signCertificate(builder, keyPair.private, provider) - - cert.checkValidity() - cert.verify(keyPair.public) - - return cert - } - - /** - * This is a helper function, which purpose is to workaround a bug in the bouncycastle library - * that is associated with the incorrect encoded byte production when the EC algorithm is used with the passed keys. - * @param publicKey public key - * @return cleaned [PublicKey] instance - */ - fun cleanEcdsaPublicKey(publicKey: PublicKey): PublicKey { - return KeyFactory.getInstance("EC").generatePublic(X509EncodedKeySpec(publicKey.encoded)) - } - - /** - * Retrieves key pair and certificate from the given key store. Also, the keys retrieved are cleaned in a sense of the - * [cleanEcdsaPublicKey] method. - * @param alias certificate and key name (alias) to be used when querying the key store. - * @param keyStore key store that holds the certificate with its keys. - * @return instance of [CertificateAndKeyPair] holding the key pair and the certificate. - */ - fun retrieveCertAndKeyPair(alias: String, keyStore: KeyStore): CertificateAndKeyPair { - val privateKey = keyStore.getKey(alias, null) as PrivateKey - val certificate = keyStore.getX509Certificate(alias) - return CertificateAndKeyPair(certificate, KeyPair(cleanEcdsaPublicKey(certificate.publicKey), privateKey)) - } - - /** - * Create a de novo root intermediate X509 v3 CA cert and KeyPair. - * @param type type of the certificate to be created - * @param subject X500 name of the certificate subject - * @param certificateAuthority The Public certificate and KeyPair of the root CA certificate above this used to sign it. - * @param keyPair public and private keys to be associated with the generated certificate - * @param validDays number of days which this certificate is valid for - * @param provider provider to be used during the certificate signing process - * @param crlDistPoint url to the certificate revocation list of this certificate - * @param crlIssuer issuer of the certificate revocation list of this certificate - * @return an instance of [CertificateAndKeyPair] class is returned containing the new intermediate CA Cert and its KeyPair for signing downstream certificates. - * Note the generated certificate tree is capped at max depth of 1 below this to be in line with commercially available certificates - */ - fun createIntermediateCert(type: CertificateType, - subject: X500Name, - certificateAuthority: CertificateAndKeyPair, - keyPair: KeyPair, - validDays: Int, - provider: Provider, - crlDistPoint: String?, - crlIssuer: X500Name?): CertificateAndKeyPair { - - val issuer = X509CertificateHolder(certificateAuthority.certificate.encoded).subject - val serial = BigInteger.valueOf(random63BitValue(provider)) - val pubKey = keyPair.public - - // Ten year certificate validity - // TODO how do we manage certificate expiry, revocation and loss - val window = getCertificateValidityWindow(0, validDays, certificateAuthority.certificate.notBefore, certificateAuthority.certificate.notAfter) - val keyPurposes = DERSequence(ASN1EncodableVector().apply { type.purposes.forEach { add(it) } }) - - val builder = JcaX509v3CertificateBuilder(issuer, serial, window.first, window.second, subject, pubKey) - builder.addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyIdentifier(pubKey)) - builder.addExtension(Extension.basicConstraints, true, BasicConstraints(type.isCA)) - builder.addExtension(Extension.keyUsage, false, type.keyUsage) - builder.addExtension(Extension.extendedKeyUsage, false, keyPurposes) - builder.addExtension(Extension.authorityKeyIdentifier, false, JcaX509ExtensionUtils().createAuthorityKeyIdentifier(certificateAuthority.keyPair.public)) - if (type.role != null) { - builder.addExtension(ASN1ObjectIdentifier(CordaOID.X509_EXTENSION_CORDA_ROLE), false, type.role) - } - addCrlInfo(builder, crlDistPoint, crlIssuer) - - val cert = signCertificate(builder, certificateAuthority.keyPair.private, provider) - - cert.checkValidity(Date()) - cert.verify(certificateAuthority.keyPair.public) - - return CertificateAndKeyPair(cert, keyPair) - } - - /** - * Creates and signs a X509 v3 client certificate. - * @param type type of the certificate to be created - * @param caCertAndKey signing certificate authority certificate and its keys - * @param request certificate signing request - * @param validDays number of days which this certificate is valid for - * @param provider provider to be used during the certificate signing process - * @param crlDistPoint url to the certificate revocation list of this certificate - * @param crlIssuer issuer of the certificate revocation list of this certificate - * @return an instance of [CertificateAndKeyPair] class is returned containing the signed client certificate. - */ - fun createClientCertificate(type: CertificateType, - caCertAndKey: CertificateAndKeyPair, - request: PKCS10CertificationRequest, - validDays: Int, - provider: Provider, - crlDistPoint: String?, - crlIssuer: X500Name?): X509Certificate { - val jcaRequest = JcaPKCS10CertificationRequest(request) - // This can be adjusted more to our future needs. - val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, CordaX500Name.parse(jcaRequest.subject.toString()).copy(commonName = null).x500Name))), arrayOf()) - val issuerCertificate = caCertAndKey.certificate - val issuerKeyPair = caCertAndKey.keyPair - val validityWindow = getCertificateValidityWindow(0, validDays, issuerCertificate.notBefore, issuerCertificate.notAfter) - val serial = BigInteger.valueOf(random63BitValue(provider)) - val subject = CordaX500Name.parse(jcaRequest.subject.toString()).x500Name - val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(jcaRequest.publicKey.encoded)) - val keyPurposes = DERSequence(ASN1EncodableVector().apply { type.purposes.forEach { add(it) } }) - val builder = JcaX509v3CertificateBuilder(issuerCertificate, serial, validityWindow.first, validityWindow.second, subject, jcaRequest.publicKey) - .addExtension(Extension.subjectKeyIdentifier, false, BcX509ExtensionUtils().createSubjectKeyIdentifier(subjectPublicKeyInfo)) - .addExtension(Extension.basicConstraints, type.isCA, BasicConstraints(type.isCA)) - .addExtension(Extension.keyUsage, false, type.keyUsage) - .addExtension(Extension.extendedKeyUsage, false, keyPurposes) - .addExtension(Extension.nameConstraints, true, nameConstraints) - .addExtension(Extension.authorityKeyIdentifier, false, JcaX509ExtensionUtils().createAuthorityKeyIdentifier(issuerKeyPair.public)) - if (type.role != null) { - builder.addExtension(ASN1ObjectIdentifier(CordaOID.X509_EXTENSION_CORDA_ROLE), false, type.role) - } - addCrlInfo(builder, crlDistPoint, crlIssuer) - val certificate = signCertificate(builder, issuerKeyPair.private, provider) - certificate.checkValidity(Date()) - certificate.verify(issuerKeyPair.public) - return certificate - } - - /** - * Helper method to get a notBefore and notAfter pair from current day bounded by parent certificate validity range - * @param daysBefore number of days to roll back returned start date relative to current date - * @param daysAfter number of days to roll forward returned end date relative to current date - * @param parentNotBefore if provided is used to lower bound the date interval returned - * @param parentNotAfter if provided is used to upper bound the date interval returned - * Note we use Date rather than LocalDate as the consuming java.security and BouncyCastle certificate apis all use Date - * Thus we avoid too many round trip conversions. - */ - fun getCertificateValidityWindow(daysBefore: Int, daysAfter: Int, parentNotBefore: Date? = null, parentNotAfter: Date? = null): Pair { - val startOfDayUTC = Instant.now().truncatedTo(ChronoUnit.DAYS) - - var notBefore = Date.from(startOfDayUTC.minus(daysBefore.toLong(), ChronoUnit.DAYS)) - if (parentNotBefore != null) { - if (parentNotBefore.after(notBefore)) { - notBefore = parentNotBefore - } - } - - var notAfter = Date.from(startOfDayUTC.plus(daysAfter.toLong(), ChronoUnit.DAYS)) - if (parentNotAfter != null) { - if (parentNotAfter.after(notAfter)) { - notAfter = parentNotAfter - } - } - - return Pair(notBefore, notAfter) - } - - /** - * Creates and initializes a key store from the given crypto server provider. - * @param provider crypto server provider to be used for the key store creation - * @return created key store instance - */ - fun getAndInitializeKeyStore(provider: CryptoServerProvider): KeyStore { - val keyStore = KeyStore.getInstance("CryptoServer", provider) - keyStore.load(null, null) - return keyStore - } - - /** - * Encode provided public key in correct format for inclusion in certificate issuer/subject fields - */ - private fun createSubjectKeyIdentifier(key: Key): SubjectKeyIdentifier { - val info = SubjectPublicKeyInfo.getInstance(key.encoded) - return BcX509ExtensionUtils().createSubjectKeyIdentifier(info) - } - - /** - * Generate a random value using the provider. - */ - private fun random63BitValue(provider: Provider): Long = Math.abs(newSecureRandom(provider).nextLong()) - - private fun newSecureRandom(provider: Provider? = null): SecureRandom { - if (provider != null && provider.name == "CryptoServer") { - return SecureRandom.getInstance("CryptoServer", provider) - } - if (System.getProperty("os.name") == "Linux") { - return SecureRandom.getInstance("NativePRNGNonBlocking") - } else { - return SecureRandom.getInstanceStrong() - } - } - - fun verify(data: ByteArray, - signature: ByteArray, - publicKey: PublicKey, - signatureAlgorithm: String = SIGNATURE_ALGORITHM) { - val verify = Signature.getInstance(signatureAlgorithm) - verify.initVerify(publicKey) - verify.update(data) - require(verify.verify(signature)) { "Signature didn't independently verify" } - } - - /** - * Use bouncy castle utilities to sign completed X509 certificate with CA cert private key - */ - private fun signCertificate(certificateBuilder: X509v3CertificateBuilder, - signedWithPrivateKey: PrivateKey, - provider: Provider, - signatureAlgorithm: String = SIGNATURE_ALGORITHM): X509Certificate { - val signer = JcaContentSignerBuilder(signatureAlgorithm).setProvider(provider).build(signedWithPrivateKey) - return certificateBuilder.build(signer).toJca() - } - - private fun addCrlInfo(builder: X509v3CertificateBuilder, crlDistPoint: String?, crlIssuer: X500Name?) { - if (crlDistPoint != null) { - val distPointName = DistributionPointName(GeneralNames(GeneralName(GeneralName.uniformResourceIdentifier, crlDistPoint))) - val crlIssuerGeneralNames = crlIssuer?.let { - GeneralNames(GeneralName(crlIssuer)) - } - // The second argument is flag that allows you to define what reason of certificate revocation is served by this distribution point see [ReasonFlags]. - // The idea is that you have different revocation per revocation reason. Since we won't go into such a granularity, we can skip that parameter. - // The third argument allows you to specify the name of the CRL issuer, it needs to be consistent with the crl (IssuingDistributionPoint) extension and the idp argument. - // If idp == true, set it, if idp == false, leave it null as done here. - val distPoint = DistributionPoint(distPointName, null, crlIssuerGeneralNames) - builder.addExtension(Extension.cRLDistributionPoints, false, CRLDistPoint(arrayOf(distPoint))) - } - } -} diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/tools/crr/submission/CRRToolArgsParser.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/tools/crr/submission/CRRToolArgsParser.kt deleted file mode 100644 index 291c22acc4..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/tools/crr/submission/CRRToolArgsParser.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.r3.corda.networkmanage.tools.crr.submission - -import com.r3.corda.networkmanage.common.utils.ArgsParser -import joptsimple.OptionSet -import java.net.URL - -class CRRToolArgsParser : ArgsParser() { - private val submissionUrlArg = optionParser - .accepts("submission-url", "CRR submission endpoint.") - .withRequiredArg() - .required() - - override fun parse(optionSet: OptionSet): URL { - return URL(optionSet.valueOf(submissionUrlArg)) - } -} \ No newline at end of file diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/tools/crr/submission/Main.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/tools/crr/submission/Main.kt deleted file mode 100644 index c11f7b9a0d..0000000000 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/tools/crr/submission/Main.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.r3.corda.networkmanage.tools.crr.submission - -import com.r3.corda.networkmanage.common.utils.SupportedCrlReasons -import com.r3.corda.networkmanage.common.utils.initialiseSerialization -import com.r3.corda.networkmanage.hsm.authentication.ConsoleInputReader -import com.r3.corda.networkmanage.hsm.authentication.InputReader -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.post -import net.corda.core.serialization.serialize -import net.corda.nodeapi.internal.network.CertificateRevocationRequest -import org.apache.logging.log4j.LogManager -import java.math.BigInteger -import java.net.URL -import java.security.cert.CRLReason - -private val logger = LogManager.getLogger("com.r3.corda.networkmanage.common.tools.crr.Main") - -fun main(args: Array) { - initialiseSerialization() - try { - submit(CRRToolArgsParser().parseOrExit(*args)) - } catch (e: Exception) { - logger.error("Error when submitting a certificate revocation request.", e) - throw e - } -} - -fun submit(url: URL, inputReader: InputReader = ConsoleInputReader()) { - val certificateSerialNumber = inputReader.getOptionalInput("certificate serial number")?.let { BigInteger(it) } - val csrRequestId = inputReader.getOptionalInput("certificate signing request ID") - val legalName = inputReader.getOptionalInput("node X.500 legal name")?.let { CordaX500Name.parse(it) } - CertificateRevocationRequest.validateOptional(certificateSerialNumber, csrRequestId, legalName) - val reason = getReason(inputReader) - val reporter = inputReader.getRequiredInput("reporter of the revocation request") - val request = CertificateRevocationRequest(certificateSerialNumber, csrRequestId, legalName, reason, reporter) - logger.debug("POST to $url request: $request") - val requestId = String(url.post(request.serialize())) - logger.debug("Certificate revocation request successfully submitted. Request ID: $requestId") - println("Successfully submitted certificate revocation request. Generated request ID: $requestId") -} - -private fun InputReader.getOptionalInput(attributeName: String): String? { - print("Type in $attributeName (press enter if not available):") - return this.readLine()?.let { - if (it.isBlank()) null else it - } -} - -private fun InputReader.getRequiredInput(attributeName: String): String { - print("Type in $attributeName:") - val line = this.readLine() - return if (line == null || line.isNullOrBlank()) { - throw IllegalArgumentException("The $attributeName needs to be specified.") - } else { - line - } -} - -private fun getReason(inputReader: InputReader): CRLReason { - while (true) { - SupportedCrlReasons.values().forEachIndexed { index, value -> - println("${index + 1}. $value") - } - print("Selected the reason for the revocation:") - val input = inputReader.readLine()!!.toInt() - if (input < 1 || input > SupportedCrlReasons.values().size) { - println("Incorrect selection. Try again.") - } else { - return CRLReason.valueOf(SupportedCrlReasons.values()[input - 1].name) - } - } -} \ No newline at end of file diff --git a/network-management/src/main/resources/com/r3/corda/networkmanage/hsm/utils/hsm_errors b/network-management/src/main/resources/com/r3/corda/networkmanage/hsm/utils/hsm_errors deleted file mode 100644 index 4b203b9309..0000000000 --- a/network-management/src/main/resources/com/r3/corda/networkmanage/hsm/utils/hsm_errors +++ /dev/null @@ -1,4462 +0,0 @@ -0xB000 -E_OS: CryptoServer module SMOS -0xB00001 -E_OS_SENS: SENS section -0xB0000100 -E_OS_SENS_WRITE_ERR: Sensory write error -0xB0000101 -E_OS_SENS_READ_ERR: Sensory read error -0xB0000102 -E_OS_SENS_BAD_TYPE: Bad info type -0xB0000103 -E_OS_SENS_MEM_ALLOC: Error during memory allocation -0xB0000104 -E_OS_SENS_IO_ERR: Sensory I/O error -0xB0000105 -E_OS_SENS_MK_CORR: Corrupted Master Key -0xB0000106 -E_OS_SENS_NACK: Sensory error answer -0xB0000107 -E_OS_SENS_NO_ALARM: CryptoServer not in alarm state -0xB0000108 -E_OS_SENS_READ_TIMEOUT: Sensory read timeout -0xB0000109 -E_OS_SENS_ALARM_PRESENT: Alarm still present, can't reset -0xB000010A -E_OS_SENS_MSP_TIMEOUT: Controller: read timeout -0xB000010B -E_OS_SENS_MSP_CMD: Controller: bad command -0xB000010C -E_OS_SENS_MSP_ADDR: Controller: bad address -0xB000010D -E_OS_SENS_MSP_DATA: Controller: bad data -0xB000010E -E_OS_SENS_MSP_CRC: Controller: bad CRC -0xB000010F -E_OS_SENS_BAD_CRC: Bad CRC in answer -0xB0000110 -E_OS_SENS_PARAM: Invalid parameter -0xB0000111 -E_OS_SENS_BUF_SIZE: Buffer size too small -0xB0000112 -E_OS_SENS_ANSW_LEN: Invalid length of answer data -0xB0000113 -E_OS_SENS_JOB_STATE: Invalid job state -0xB0000114 -E_OS_SENS_LOCKED: Sensory controller is locked -0xB000013 -E_OS_SENS_CTRL: Sensory Controller section -0xB0000130 -E_OS_SENS_CTRL_NACK: unknown error code -0xB0000131 -E_OS_SENS_CTRL_TIMEOUT: timeout -0xB0000132 -E_OS_SENS_CTRL_CMD: bad command -0xB0000133 -E_OS_SENS_CTRL_ADDR: bad address -0xB0000134 -E_OS_SENS_CTRL_DATA: bad data -0xB0000135 -E_OS_SENS_CTRL_CRC: bad CRC -0xB0000136 -E_OS_SENS_CTRL_I2C: I2C error -0xB0000137 -E_OS_SENS_CTRL_BUSY: currently busy -0xB00002 -E_OS_DEV: device section -0xB0000201 -E_OS_DEV_ERR: notifies if an error occurs during operation -0xB0000202 -E_OS_DEV_ALREADY_OPEN: device is used by an other session -0xB0000203 -E_OS_DEV_NAME_INVALID: illegal device name length or characterset -0xB0000204 -E_OS_DEV_MODE_INVALID: illegal mode of operation -0xB0000205 -E_OS_DEV_PARAMETER_INVALID: passed parameter illegal -0xB0000206 -E_OS_DEV_HDL_INVALID: session handle not allowed -0xB0000207 -E_OS_DEV_DATA_INVALID: corrupted data -0xB0000209 -E_OS_DEV_NO_MEM: can't allocate memory space -0xB000020A -E_OS_DEV_NO_SUCH_FUNCTION: no private module function -0xB000020B -E_OS_DEV_NO_DEVICE: no serial device available -0xB00003 -E_OS_DEV_SL: serial device section -0xB0000301 -E_OS_DEV_SL_BAD_HDL: bad handle -0xB0000302 -E_OS_DEV_SL_ALREADY_OPEN: device already open -0xB000030D -E_OS_DEV_SL_READ: read error on serial line -0xB000030E -E_OS_DEV_SL_INVALID_PARAM: parameter to be modified is invalid -0xB0000310 -E_OS_DEV_SL_PARAM_VAL: invalid parameter value to set control of SL -0xB0000311 -E_OS_DEV_SL_TIMEOUT: timeout while reading char from serial line -0xB0000312 -E_OS_DEV_SL_PARITY_ERR: parity error -0xB0000313 -E_OS_DEV_SL_OVERRUN: receiver over-run -0xB0000314 -E_OS_DEV_SL_FRAME: receiver frame error -0xB0000315 -E_OS_DEV_SL_NO_DATA: no data ready to read -0xB0000381 -E_OS_DEV_SL_TOOMANY: too many lines open -0xB0000382 -E_OS_DEV_SL_TCATTR: error setting line parameters -0xB0000383 -E_OS_DEV_SL_OPEN: can't open device -0xB0000384 -E_OS_DEV_SL_NOT_OPEN: handle not open -0xB0000385 -E_OS_DEV_SL_NO_VALID_HDL: invalid handle -0xB0000386 -E_OS_DEV_SL_NO_VALID_PARA_VALUE: invalid parameter value -0xB0000387 -E_OS_DEV_SL_NO_VALID_PARA_TYPE: invalid parameter type -0xB0000388 -E_OS_DEV_SL_READ_ERROR: error on read -0xB0000389 -E_OS_DEV_SL_READ_TIME_OUT: timeout on read -0xB000038A -E_OS_DEV_SL_WRITE_ERROR: error on write -0xB000038B -E_OS_DEV_SL_WRITE_TIME_OUT: timeout on write -0xB000038C -E_OS_DEV_SL_CTRL_ERROR: error on ioctl -0xB0000390 -E_OS_DEV_SL_NO_VALID_NAME: no valid device name -0xB0000391 -E_OS_DEV_SL_NO_VALID_BUF_SLCT: no valid Buffer selected -0xB0000392 -E_OS_DEV_SL_NO_VALID_LINE_STATE: line state parameter incorrect -0xB0000393 -E_OS_DEV_SL_NO_VALID_LINE_SLCT: line select parameter incorrect -0xB0000394 -E_OS_DEV_SL_COM_STATE: error in comunication driver -0xB0000395 -E_OS_DEV_SL_PARITY: Parity Error -0xB00004 -E_OS_DEV_I2C: i2c device section -0xB0000401 -E_OS_DEV_I2C_PARA_INV: one parameter is wrong -0xB0000402 -E_OS_DEV_I2C_NO_ACK: got no acknowledge after sending a byte -0xB0000403 -E_OS_DEV_I2C_BAD_DEVICE: bad device identifier -0xB0000404 -E_OS_DEV_I2C_NO_DEV: device does not exist -0xB00005 -E_OS_FILE: file section -0xB0000501 -E_OS_FILE_INIT: file system not initialized -0xB0000502 -E_OS_FILE_ALREADY_OPEN: the file is already opened -0xB0000503 -E_OS_FILE_ILL_NAME: file name is not allowed -0xB0000504 -E_OS_FILE_ILL_ATTRIB: invalid open mode -0xB0000505 -E_OS_FILE_NO_SUCH_PATH: the directory does not exist -0xB0000506 -E_OS_FILE_NO_SUCH_FILE: the file does not exist -0xB0000507 -E_OS_FILE_EXIST: the file doesn't / already exists -0xB0000508 -E_OS_FILE_ILL_PARAM: invalid parameter -0xB000050A -E_OS_FILE_NOT_OPEN: the file isn't open for access mode -0xB000050B -E_OS_FILE_ILL_POS: position offset not allowed -0xB000050C -E_OS_FILE_NO_MEM: no more memory space available -0xB000050D -E_OS_FILE_NO_TABLE: no bad block table -0xB000050E -E_OS_FILE_MAGIC: invalid magic tag -0xB0000510 -E_OS_FILE_FF_BUSY: flash file device is still busy -0xB0000511 -E_OS_FILE_FF_FAILED: flash file device replies an error -0xB0000513 -E_OS_FILE_FF_ADDRESS: illegal page address -0xB0000514 -E_OS_FILE_ECC: page parity error -0xB0000515 -E_OS_FILE_RDONLY: file system is read only -0xB0000516 -E_OS_FILE_HANDLE: bad file handle -0xB0000517 -E_OS_FILE_NO_SPACE: file system full -0xB0000518 -E_OS_FILE_TABLE_FULL: file table full -0xB0000519 -E_OS_FILE_CORR: file corrupted -0xB000051A -E_OS_FILE_EXDEV: different file systems -0xB000051B -E_OS_FILE_BAD_FSTYPE: bad file system type, can't mount -0xB000051C -E_OS_FILE_BAD_BAD: too many bad blocks, giving up -0xB000051D -E_OS_FILE_FF_BAD: detected bad block in flash file -0xB000051E -E_OS_FILE_GEOMETRY: bad flash page geometry -0xB000051F -E_OS_FILE_HDL_TOOMANY: too many open file handles -0xB00006 -E_OS_TASK: task section -0xB0000601 -E_OS_TASK_STACK_OVL: stack overflow -0xB0000602 -E_OS_TASK_STACK_CORR: stack corrupted -0xB0000603 -E_OS_TASK_BUFSIZE: buffer size to small -0xB0000604 -E_OS_TASK_MALLOC: memory allocation failed -0xB00007 -E_OS_AUDIT: AUDIT section -0xB0000700 -E_OS_AUDIT_EXIST: Audit file does not exist -0xB0000701 -E_OS_AUDIT_FULL: Audit files full -0xB0000702 -E_OS_AUDIT_FSFULL: File system full -0xB0000703 -E_OS_AUDIT_BUFF_TOO_SMALL: Buffer too small -0xB0000704 -E_OS_AUDIT_MALLOC: Memory allocation failed -0xB0000705 -E_OS_AUDIT_CFG_ITEM: Invalid configuration item -0xB0000706 -E_OS_AUDIT_CFG_RANGE: Configuration value out of range -0xB0000707 -E_OS_AUDIT_PARAM: Invalid parameter value -0xB0000708 -E_OS_AUDIT_INVALID_HANDLE: Invalid audit handle -0xB00008 -E_OS_MDL: MDL section -0xB0000801 -E_OS_MDL_MEM_ALLOC: Error during memory allocation -0xB0000802 -E_OS_MDL_PARA_INVALID: Invalid input parameter -0xB0000803 -E_OS_MDL_EXIST: module already exists -0xB0000804 -E_OS_MDL_TABLE: module table full -0xB0000805 -E_OS_MDL_PARAMETER: illegall parameter passed -0xB0000806 -E_OS_MDL_EVENT: event not reached -0xB0000807 -E_OS_MDL_NOT_FOUND: module not found -0xB0000808 -E_OS_MDL_WRITE: can't write module to SDRAM directory -0xB0000809 -E_OS_MDL_SLF_BAD: bad signed licence file -0xB000080A -E_OS_MDL_BL_INI: can't read bl_ini file -0xB000080B -E_OS_MDL_SLF_FOUND: SLF parameter not found -0xB000080C -E_OS_MDL_MTC_INV: invalid MTC file -0xB000080D -E_OS_MDL_MMC_INV: invalid MMC file -0xB000080E -E_OS_MDL_NO_MTC_SIG: No MTC signature present -0xB000080F -E_OS_MDL_CFG_FOUND: Config parameter not found -0xB0000810 -E_OS_MDL_HW_TYPE: Module does not match hardware type -0xB0000811 -E_OS_MDL_MSC_INV: invalid MSC file -0xB0000812 -E_OS_MDL_MSC_VERIFY_FAILED: MSC verification failed -0xB0000813 -E_OS_MDL_NOT_SUPP: Function not supported -0xB0000814 -E_OS_MDL_NOT_AVAILABLE: Function not available -0xB00009 -E_OS_MEM: memory section -0xB0000901 -E_OS_MEM_BAD_TYPE: illegal memory type -0xB0000902 -E_OS_MEM_CORR: corrupted memory structure -0xB0000903 -E_OS_MEM_BUF_SIZE: buffer size too small -0xB0000904 -E_OS_MEM_BAD_ADDR: bad memory address -0xB0000A -E_OS_STR: string section -0xB0000A01 -E_OS_STR_MALLOC: memory allocation failed -0xB0000B -E_OS_CFG: Config section -0xB0000B01 -E_OS_CFG_MALLOC: memory allocation failed -0xB0000B02 -E_OS_CFG_INVALID_PARAM: invalid parameter -0xB0000B03 -E_OS_CFG_INVALID_HDL: invalid handle -0xB0000B04 -E_OS_CFG_BAD: bad config file -0xB0000B05 -E_OS_CFG_SECT_NOT_FOUND: section not found -0xB0000B06 -E_OS_CFG_ITEM_NOT_FOUND: item not found -0xB00010 -E_OS_PCI: PCI section -0xB0001000 -E_OS_PCI_DMA_TMOUT: DMA timeout -0xB0001001 -E_OS_PCI_CANCEL: request canceled -0xB0001002 -E_OS_PCI_MBR_RD_TMOUT: MBR read timeout -0xB0001003 -E_OS_PCI_MBR_WR_TMOUT: MBR write timeout -0xB0001004 -E_OS_PCI_MBR_CMD: bad MBR command -0xB0001005 -E_OS_PCI_RX_CRC: rx crc error -0xB0001006 -E_OS_PCI_NOT_IMPL: function not implememted -0xB0001007 -E_OS_PCI_SHUTDOWN: shutdown request received -0xB0001008 -E_OS_PCI_MEM: memory allocation failed -0xB0001009 -E_OS_PCI_SEQCT: bad sequence counter -0xB000100A -E_OS_PCI_RD_TMOUT: read timeout -0xB000100B -E_OS_PCI_WR_TMOUT: write timeout -0xB000100C -E_OS_PCI_LENERR: block length error -0xB000100D -E_OS_PCI_SOCKET: socket error -0xB000100E -E_OS_PCI_STATE: bad state for receive -0xB00011 -E_OS_RTC: RTC section -0xB0001100 -E_OS_RTC_FAIL: RTC failed -0xB0001101 -E_OS_RTC_NOT_INIT: RTC not initialized -0xB0001102 -E_OS_RTC_PARAM: Bad parameter -0xB00013 -E_OS_CRYPT: CRYPT section -0xB0001301 -E_OS_CRYPT_MEM_ALLOC: Error during memory allocation -0xB0001302 -E_OS_CRYPT_PARA_INVALID: Invalid input parameter -0xB0001303 -E_OS_CRYPT_MK_READ: Error reading master key -0xB0001304 -E_OS_CRYPT_NO_MK: no internal access to CS2 master key -0xB0001305 -E_OS_CRYPT_MK_CORR: CS2 master key corrupted -0xB0001306 -E_OS_CRYPT_MK_WRITE: Error updating master key -0xB0001307 -E_OS_CRYPT_NOT_SUPP: Function not supported -0xB0001308 -E_OS_CRYPT_RND_FAIL: Random number generator failed -0xB0001309 -E_OS_CRYPT_SHA512_KAT: SHA-512 Known Answer Test failed -0xB0001310 -E_OS_CRYPT_RND_TMOUT: Random number generator timeout -0xB0001311 -E_OS_CRYPT_RND_KAT: Known answer test failed -0xB0001312 -E_OS_CRYPT_RND_INIT: Random Number Generator is not initialized -0xB0001313 -E_OS_CRYPT_RND_SEC_STRENGTH: Given security strength not supported -0xB0001314 -E_OS_CRYPT_RND_REQ: Max number of requested randombits per call exceeded -0xB0001315 -E_OS_CRYPT_RND_PRED_RESISTANCE: Prediction resistance not supported for current handle -0xB0001316 -E_OS_CRYPT_RND_RESEED: Random Number Generator needs to be reseeded -0xB0002 -E_OS_COFF: COFF section -0xB0002001 -E_OS_COFF_RELOC_LO16: relocation error (low 16 bits) -0xB0002002 -E_OS_COFF_RELOC_HI16: relocation error (high 16 bits) -0xB0002003 -E_OS_COFF_RELOC_PCR21: relocation error (PC relative) -0xB0002004 -E_OS_COFF_RELOC_LONG: relocation error (long) -0xB0002005 -E_OS_COFF_ALLOC: can't allocate memory -0xB0002006 -E_OS_COFF_BAD_NSCN: bad number of section headers -0xB0002007 -E_OS_COFF_2BSS: multiple BSS segments -0xB0002008 -E_OS_COFF_2CINIT: multiple CINIT segments -0xB0002009 -E_OS_COFF_NO_DATA: missing data in segment -0xB000200A -E_OS_COFF_BAD_ENTRY: bad entry function -0xB000200B -E_OS_COFF_NO_SYMTAB: missing symbol table -0xB000200C -E_OS_COFF_REL_DATA: bad relocation data -0xB000200D -E_OS_COFF_REL_SCN: bad section number in relocation data -0xB000200E -E_OS_COFF_REL_DISP: bad displacement in relocation data -0xB000200F -E_OS_COFF_REL_SYMIDX: bad symbol index in relocation data -0xB0002010 -E_OS_COFF_REL_TYPE: bad relocation type -0xB0002011 -E_OS_COFF_HEADER: bad coff file header -0xB0002012 -E_OS_COFF_MISS: missing information in coff file -0xB0002013 -E_OS_COFF_BSS_NEMPTY: BSS segment is not empty -0xB0002014 -E_OS_COFF_CINIT_NEMPTY: CINIT segment is not empty -0xB0002015 -E_OS_COFF_CPU_TYPE: module does not match CPU type -0xB0002016 -E_OS_COFF_REL_TARGET: bad relocation target address -0xB0002017 -E_OS_COFF_REL_STACKOVF: symbol stack overflow -0xB0002018 -E_OS_COFF_RELOC_USTFLD: relocation error (USTFLD) -0xB0002019 -E_OS_COFF_RELOC_XSTFLD: relocation error (XSTFLD) -0xB0003 -E_OS_USB: USB section -0xB0003001 -E_OS_USB_MALLOC: memory allocation failed -0xB0003002 -E_OS_USB_PARAM: invalid parameter -0xB0003003 -E_OS_USB_NOT_SUPPORTED: USB not supported -0xB0003004 -E_OS_USB_INIT_FAILED: initialization of host controller failed -0xB0003005 -E_OS_USB_DEVICE_CONNECT: device is not connected -0xB0003006 -E_OS_USB_DEVICE_STATE: invalid device state -0xB0003007 -E_OS_USB_TIMEOUT: timeout occured -0xB0003008 -E_OS_USB_NAK: NAK received -0xB0003009 -E_OS_USB_PROTOCOL: protocol error -0xB000300A -E_OS_USB_IDTAB_FULL: ID table is full -0xB000300B -E_OS_USB_NOT_FOUND: item not found -0xB000300C -E_OS_USB_DATA_LEN: invalid data length -0xB00031 -E_OS_USB_ERR: transaction error -0xB00032 -E_OS_USB_LIBUSB: libusb -0xB00050 -E_OS_PNC_0: panic message -0xB0005001 -E_OS_PNC_BL: Can't start bootloader (CRC) -0xB0005002 -E_OS_PNC_SDRAM: Can't start bootloader (SDRAM error) -0xB000500B -E_OS_PNC_PCI: PCI interface closed -0xB000500C -E_OS_PNC_MEMORY: memory corruption detected -0xB00053 -E_OS_PNC_3: shutdown message -0xB0005306 -E_OS_PNC_HIGH_TEMP: High temperature -0xB000530A -E_OS_PNC_RESET_ALARM: Alarm reseted -0xB000530E -E_OS_PNC_CLEAR: CryptoServer cleared -0xB0005344 -E_OS_PNC_HALT: CryptoServer halted -0xB001 -E_FIPS140: CryptoServer module FIPS140 -0xB0010001 -E_FIPS140_INVALID_MDL_VERSION: invalid module version -0xB0010002 -E_FIPS140_ILLEGAL_MDL: illegal firmware module in FIPS mode -0xB0010003 -E_FIPS140_MISSING_APPR_MDL: missing approved module -0xB0010004 -E_FIPS140_APPR_MDL_INIT_FAILED: approved module initialization failed -0xB0010010 -E_FIPS140_DES_KAT: known answer test of DES failed -0xB0010011 -E_FIPS140_RSA_KAT: known answer test of RSA failed -0xB0010012 -E_FIPS140_AES_KAT: known answer test of AES failed -0xB0010013 -E_FIPS140_ECDSA_PCT: pair-wise consistency test of ECDSA failed -0xB0010014 -E_FIPS140_HASH_KAT: known answer test of HASH failed -0xB0010020 -E_FIPS140_AES_ENC_KAT_FAILED: known answer test for AES encrypt/decrypt failed -0xB0010021 -E_FIPS140_AES_MAC_KAT_FAILED: known answer test for AES CBC-MAC failed -0xB0010022 -E_FIPS140_AES_CMAC_KAT_FAILED: known answer test for AES CMAC failed -0xB0010023 -E_FIPS140_AES_GCM_KAT_FAILED: known answer test for AES GCM failed -0xB0010024 -E_FIPS140_AES_OFB_KAT_FAILED: known answer test for AES OFB failed -0xB0010025 -E_FIPS140_AES_GMAC_KAT_FAILED: known answer test for AES GMAC failed -0xB0010030 -E_FIPS140_RSA_SIGN_KAT_FAILED: known answer test for RSA sign/verify failed -0xB0010031 -E_FIPS140_RSA_ENC_PCT_FAILED: pair-wise consistency test for RSA encrypt/decrypt failed -0xB0010040 -E_FIPS140_HMAC_KAT_FAILED: known answer test for HMAC failed -0xB0010050 -E_FIPS140_DSA_SIGN_PCT_FAILED: pair-wise consistency test for DSA sign/verify failed -0xB0010060 -E_FIPS140_ECC_CDH_KAT_FAILED: known answer test for ECC CDH failed -0xB0010070 -E_FIPS140_KDF_800108_KAT_FAILED: known answer test for KDF_800108 failed -0xB0010080 -E_FIPS150_UTL_TEST_FAILED: known answer tests for (internally used only) utility functions failed -0xB0010100 -E_FIPS140_CMD_LEN: bad command length -0xB0010200 -E_FIPS140_INVALID_PARAM: function called with invalid parameter -0xB006 -E_BL3: Bootloader -0xB0060000 -E_BL3_PARA_INV: invalid parameter -0xB0060001 -E_BL3_ITEM_NOT_FOUND: item not found -0xB0060002 -E_BL3_ITEM_LEN: invalid item length -0xB0060003 -E_BL3_BUF_SIZE: buffer size too small -0xB006001 -E_BL3_CMD: command section -0xB0060010 -E_BL3_CMD_FMT_LEN: bad length within format string -0xB0060011 -E_BL3_CMD_BAD_OUT: bad parameter structure -0xB0060012 -E_BL3_CMD_BAD_FMT: bad format string -0xB0060013 -E_BL3_CMD_BAD_CMD: bad format -0xB0060014 -E_BL3_CMD_TIMEOUT: timeout occured -0xB0060015 -E_BL3_CMD_PROHIBIT: command is not allowed -0xB0060016 -E_BL3_CMD_INVALID_HEADER: invalid command header -0xB0060017 -E_BL3_CMD_INVALID_LENGTH: invalid command length -0xB0060018 -E_BL3_CMD_INVALID_FC: invalid function code -0xB0060019 -E_BL3_CMD_INVALID_SFC: invalid sub-function code -0xB006001A -E_BL3_CMD_INVALID_CHALLENGE: invalid challenge -0xB006001B -E_BL3_CMD_FIPS_PROHIBIT: command is not allowed in FIPS mode -0xB006001C -E_BL3_CMD_SFC_DISABLED: command not available in current configuration -0xB006003 -E_BL3_MDL: module section -0xB0060031 -E_BL3_MDL_MTC_HDR_INV: invalid MTC Header -0xB0060032 -E_BL3_MDL_MTC_NO_SIG: no MTC signature present -0xB0060033 -E_BL3_MDL_MMC_HDR_INV: invalid MMC Header -0xB0060034 -E_BL3_MDL_MMC_NO_SIG: no MMC signature present -0xB0060035 -E_BL3_MDL_MMC_HASH: MMC hash compare failed -0xB0060036 -E_BL3_MDL_MSC_HDR_INV: invalid MSC Header -0xB0060037 -E_BL3_MDL_MSC_HASH: MSC hash compare failed -0xB0060038 -E_BL3_MDL_NO_INFO: no module info found -0xB006004 -E_BL3_COFF: coff section -0xB0060040 -E_BL3_COFF_NAME_INV: invalid coff name -0xB0060041 -E_BL3_COFF_HDR_INV: invalid coff header -0xB0060042 -E_BL3_COFF_OPT_HDR_MAGIC: invalid header magic -0xB0060043 -E_BL3_COFF_OPT_HDR_SIZE: invalid header size -0xB0060044 -E_BL3_COFF_SECT_INV: invalid section -0xB0060045 -E_BL3_COFF_SECT_RELOC_INV: invalid relocation of section -0xB0060046 -E_BL3_COFF_SECT_ADR_RUN_ALG: invalid run address -0xB0060047 -E_BL3_COFF_SECT_ADR_LOAD_ALG: invalid load address -0xB0060048 -E_BL3_COFF_SECT_MEM_INV: invalid section memory -0xB0060049 -E_BL3_COFF_OPT_HDR_INV: invalid opt header -0xB006004A -E_BL3_COFF_SIZE_INV: invalid size -0xB006004B -E_BL3_COFF_ADR_INV: invalid address -0xB006004C -E_BL3_COFF_MTC_INV: invalid MTC -0xB006004D -E_BL3_COFF_ENTRY_INV: invalid entry point -0xB006004E -E_BL3_COFF_CPU_TYPE: invalid CPU type -0xB006004F -E_BL3_COFF_INV: invalid coff file -0xB006005 -E_BL3_SIG: signature secture -0xB0060050 -E_BL3_SIG_PKCS1: invalid pkcs1 padding -0xB0060051 -E_BL3_SIG_HASH: hash compare failed -0xB006006 -E_BL3_RSA: RSA section -0xB0060060 -E_BL3_RSA_RES_OFLOW: rsa result overflow -0xB0060061 -E_BL3_RSA_DIV_OFLOW: modulus is zero -0xB0060062 -E_BL3_RSA_INP_GE_MOD: modulus is smaller than operand -0xB006007 -E_BL3_FILE: file section -0xB0060071 -E_BL3_FILE_FLASH_FORMAT: error formating flash file -0xB0060072 -E_BL3_FILE_AFTER_FORMAT_LOOP: flash file formated succesfully, now looping forever -0xB0060073 -E_BL3_FILE_INIT: Initialization of file system failed -0xB0060074 -E_BL3_FILE_EXIST: file already exists -0xB0060075 -E_BL3_FILE_NAME: invalid filename -0xB0060076 -E_BL3_FILE_TYPE: invalid file type -0xB0060077 -E_BL3_FILE_SIZE: invalid file size -0xB0060078 -E_BL3_FILE_NOT_FOUND: file not found -0xB006007A -E_BL3_FILE_OPEN: file open error -0xB006007B -E_BL3_FILE_READ: file read error -0xB006007C -E_BL3_FILE_WRITE: file write error -0xB006007D -E_BL3_FILE_CLOSE: file close error -0xB006008 -E_BL3_PCI: PCI section -0xB0060080 -E_BL3_PCI_TIMEOUT: timeout occured -0xB0060081 -E_BL3_PCI_PROTOCOL: protocol error -0xB0060082 -E_BL3_PCI_LENGTH: length error -0xB0060083 -E_BL3_PCI_CRC: crc error -0xB0060084 -E_BL3_PCI_BUFSIZE: buffer size too small -0xB0060085 -E_BL3_PCI_PARAM: invalid parameter -0xB006009 -E_BL3_UID: UID section -0xB0060090 -E_BL3_UID_CRC: bad CRC on UID -0xB0060091 -E_BL3_UID_NOT_FOUND: UID not found -0xB0060092 -E_BL3_UID_EXT_INV: Extended UID invalid -0xB00600A -E_BL3_SL: SL section -0xB00600A0 -E_BL3_SL_NAME_INV: invalid device name -0xB00600A1 -E_BL3_SL_HDL_INV: invalid handle value -0xB00600A2 -E_BL3_SL_NOT_OPEN: device is not open -0xB00600A3 -E_BL3_SL_INUSE: device is already in use -0xB00600A4 -E_BL3_SL_PARAM: invalid parameter -0xB00600A5 -E_BL3_SL_PARAM_VALUE: invalid parameter value -0xB00600A6 -E_BL3_SL_TIMEOUT: timeout -0xB00600A7 -E_BL3_SL_CRC: invalid crc -0xB00600A8 -E_BL3_SL_OVERRUN: overrun error -0xB00600A9 -E_BL3_SL_PARITY: parity error -0xB00600AA -E_BL3_SL_FRAME: framing error -0xB00600AB -E_BL3_SL_DATA_COMP: data compare failed -0xB00600B -E_BL3_MSP_BSL: MSP BSL section -0xB00600B1 -E_BL3_MSP_BSL_VERSION: get version failed -0xB00600B2 -E_BL3_MSP_BSL_SYNC: sync failed -0xB00600B3 -E_BL3_MSP_BSL_ERASE: erase failed -0xB00600B4 -E_BL3_MSP_BSL_LOGIN: login failed -0xB00600B5 -E_BL3_MSP_BSL_WRITE: write failed -0xB00600C -E_BL3_JTAG: JTAG section -0xB00600C0 -E_BL3_JTAG_STATE: invalid state -0xB00600C1 -E_BL3_JTAG_IDCODE: unexpected IDCODE -0xB00600D -E_BL3_FLASH: Flash section -0xB00600D0 -E_BL3_FLASH_TIMEOUT: timeout during flash operation -0xB00600D1 -E_BL3_FLASH_ID: error reading flash id -0xB00600D2 -E_BL3_FLASH_ERASE: erase failed -0xB00600D3 -E_BL3_FLASH_PAGE_READ: error reading flash page -0xB00600D4 -E_BL3_FLASH_PAGE_WRITE: error writing flash page -0xB00600D5 -E_BL3_FLASH_PAGE_DATA: bad page data -0xB00600D6 -E_BL3_FLASH_CRC: invalid CRC -0xB00600E -E_BL3_LOG: log section -0xB00600E0 -E_BL3_LOG_DOES_NOT_EXIST: log file does not exist -0xB00600F -E_BL3_SDRAM: SDRAM section -0xB00600F1 -E_BL3_SDRAM_BUS_DATA: data bus test failed -0xB00600F2 -E_BL3_SDRAM_BUS_ADR: address bus test failed -0xB00600F3 -E_BL3_SDRAM_BUS_DEV: device test failed -0xB006010 -E_BL3_USB: USB section -0xB0060100 -E_BL3_USB_NACK: NACK received -0xB0060101 -E_BL3_USB_TIMEOUT: timeout occured -0xB0060102 -E_BL3_USB_PROT: protocol error -0xB0060103 -E_BL3_USB_DEVICE: device error -0xB0060104 -E_BL3_USB_PARAM: invalid parameter -0xB0060105 -E_BL3_USB_NOT_SUPPORTED: function not supported -0xB0060106 -E_BL3_USB_INIT_FAILED: initialisation failed -0xB0060107 -E_BL3_USB_DEVICE_CONNECT: error connecting device -0xB0060108 -E_BL3_USB_DEVICE_STATE: error determining device state -0xB0060109 -E_BL3_USB_PROTOCOL: usb protocol error -0xB006011 -E_BL3_FF: flash file section -0xB0060111 -E_BL3_FF_NO_CONFIG: no config page -0xB0060112 -E_BL3_FF_CONFIG_SIZE: invalid flash size -0xB0060113 -E_BL3_FF_NO_BBT: no bad block table -0xB0060114 -E_BL3_FF_INVALID_BBT: invalid bad block table -0xB0060115 -E_BL3_FF_BBT_STORE: unable to store bad block -0xB0060116 -E_BL3_FF_NOT_BLANK: page is not blank -0xB006012 -E_BL3_I2C: i2c device section -0xB0060120 -E_BL3_I2C_PARA_INV: one parameter is wrong -0xB0060121 -E_BL3_I2C_NO_ACK: got no acknowledge after sending a byte -0xB0060122 -E_BL3_I2C_NO_DEV: device does not exist -0xB006013 -E_BL3_XSVF: XSVF section -0xB0060131 -E_BL3_XSVF_UNKNOWN: unknown error -0xB0060132 -E_BL3_XSVF_TDOMISMATCH: TDO mismatch -0xB0060133 -E_BL3_XSVF_MAXRETRIES: TDO mismatch after max retries -0xB0060134 -E_BL3_XSVF_ILLEGALCMD: illegal command -0xB0060135 -E_BL3_XSVF_ILLEGALSTATE: illegal state -0xB0060136 -E_BL3_XSVF_DATAOVERFLOW: buffer overflow -0xB006014 -E_BL3_SHA512: SHA512 section -0xB0060140 -E_BL3_SHA512_KAT: SHA512 known answer test failed -0xB006015 -E_BL3_NVRAM: NVRAM section -0xB0060150 -E_BL3_NVRAM_TIMEOUT: timeout during nvram operation -0xB0060151 -E_BL3_NVRAM_PAGE_READ: error reading nvram page -0xB0060152 -E_BL3_NVRAM_PAGE_WRITE: error writing nvram page -0xB0060153 -E_BL3_NVRAM_PAGE_DATA: bad page data -0xB0060154 -E_BL3_NVRAM_ID: error reading flash id -0xB0060155 -E_BL3_NVRAM_NOT_AVAILABLE: NVRAM not available in Bootloader mode -0xB00602 -E_BL3_MSP: MSP section -0xB0060201 -E_BL3_MSP_DATA_LEN: data len for communication with msp too large -0xB0060202 -E_BL3_MSP_IO_ERR: timeout occurred -0xB00602A5 -E_BL3_MSP_CMD: invalid command -0xB00602BD -E_BL3_MSP_ADDR: invalid address -0xB00602C3 -E_BL3_MSP_DATA: invalid data -0xB00602DB -E_BL3_MSP_CRC: invalid crc -0xB00603 -E_BL3_USB_ERR: SPI section -0xB0060401 -E_BL3_SPI_RD_TO: read timeout -0xB0060402 -E_BL3_SPI_XRDY_TO: timeout waiting for receiver ready -0xB0060403 -E_BL3_SPI_MSP_RDY_TO: timeout waiting for MSP ready -0xB0060404 -E_BL3_SPI_MSP_NRDY_TO: timeout waiting for MSP ready low -0xB0060405 -E_BL3_SPI_RRDY_TO: timeout waiting for RRDY -0xB0060500 -E_BL3_EXAR: EXAR section -0xB0060501 -E_BL3_EXAR_TIMEOUT: timeout during pci cfg operation -0xB0060502 -E_BL3_EXAR_DATA_TEST: wrong data read -0xB0060503 -E_BL3_EXAR_PCI_BUSY: pci interface for accelerator busy -0xB0060504 -E_BL3_EXAR_DETECT: no exar accelerator found -0xB0060511 -E_BL3_SCF_MALLOC: memory allocation failed -0xB0060512 -E_BL3_SCF_INVALID_PARAM: invalid parameter -0xB0060513 -E_BL3_SCF_INVALID_HDL: invalid handle -0xB0060514 -E_BL3_SCF_BAD: bad config file -0xB0060515 -E_BL3_SCF_SECT_NOT_FOUND: section not found -0xB0060516 -E_BL3_SCF_ITEM_NOT_FOUND: item not found -0xB007001F -E_BL_WRONG_FC: Wrong Function Code (included for backward compatibility) -0xB007001F -E_BL_WRONG_FC: Wrong Function Code (included for backward compatibility) -0xB00A -E_HCE: CryptoServer module HCE -0xB00A0001 -E_HCE_MEM: memory allocation failed -0xB00A0002 -E_HCE_PCI_MASTER: PCI master access error (DSP) -0xB00A0003 -E_HCE_KEY_SIZE: key size not supported -0xB00A0004 -E_HCE_EXP_SIZE: exponent greater modulus -0xB00A0005 -E_HCE_TIMEOUT: hardware engine timeout -0xB00A0006 -E_HCE_RESULT_SIZE: result too big for buffer -0xB00A0007 -E_HCE_PRIME_SIZE: illegal sizes of prime -0xB00A0008 -E_HCE_DATA_LEN: data size too big (greater than modulus) -0xB00A0009 -E_HCE_SELFTST_FAIL: Self-test failed -0xB00A000A -E_HCE_NO_LNA: Module LNA not found -0xB00A000B -E_HCE_DMA: PCI DMA master access error -0xB00A000C -E_HCE_NO_DRIVER: No driver module found -0xB00A000D -E_HCE_DRIVER_INCOMPATIBLE: Driver does not allow routing from HCE to driver. -0xB00A000E -E_HCE_PARAM_INVALID: invalid parameter -0xB00A000F -E_HCE_NOT_SUPPORTED: function is not supported -0xB00A0010 -E_HCE_VERIFY_FAILED: Signature verification failed -0xB00A80 -E_HCE_ENGN_ERR: hardware engine error -0xB00D -E_EXAR: CryptoServer module EXAR -0xB00D0001 -E_EXAR_NO_MARVEL: no Marvell bridge detected -0xB00D0002 -E_EXAR_NO_EXAR: no Exar chip detected -0xB00D0003 -E_EXAR_INVAL: invalid parameter -0xB00D0004 -E_EXAR_TIMEOUT: timeout -0xB00D0005 -E_EXAR_MALLOC: memory allocation failed -0xB00D0006 -E_EXAR_SELFTEST: selftest failed -0xB00D0007 -E_EXAR_BUF_SIZE: insufficient buffer size -0xB00D0008 -E_EXAR_STATE: invalid command state -0xB00D0009 -E_EXAR_PARAM_LEN: invalid parameter length -0xB00D000A -E_EXAR_SIGN_FAILED: sign failed -0xB00D000B -E_EXAR_VERIFY_FAILED: signature verification failed -0xB00D000C -E_EXAR_KEY_SIZE: key size not supported -0xB00D000D -E_EXAR_DATA_LEN: data size too big -0xB00D0010 -E_EXAR_ERR_ADDR: address error -0xB00D0011 -E_EXAR_ERR_ECC: ECC error -0xB00D0012 -E_EXAR_BUSY: all engines are busy -0xB00D0020 -E_EXAR_PCI_BUSY: PCI is busy -0xB00D0021 -E_EXAR_PCI_TIMEOUT: PCI timeout -0xB00D0022 -E_EXAR_PCI_ACCESS: PCI access error -0xB00E -E_BCM: CryptoServer module HCE -0xB00E0001 -E_BCM_MEM: memory allocation failed -0xB00E0002 -E_BCM_PCI_MASTER: PCI master access error (DSP) -0xB00E0003 -E_BCM_KEY_SIZE: key size not supported -0xB00E0004 -E_BCM_EXP_SIZE: exponent greater modulus -0xB00E0005 -E_BCM_TIMEOUT: hardware engine timeout -0xB00E0006 -E_BCM_RESULT_SIZE: result too big for buffer -0xB00E0007 -E_BCM_PRIME_SIZE: illegal sizes of prime -0xB00E0008 -E_BCM_DATA_LEN: data size too big (greater than modulus) -0xB00E0009 -E_BCM_SELFTST_FAIL: Self-test failed -0xB00E000A -E_BCM_NO_LNA: Module LNA not found -0xB00E000B -E_BCM_DMA: PCI DMA master access error -0xB00E80 -E_BCM_ENGN_ERR: hardware engine error -0xB050 -E_PK: CryptoServer module PK -0xB0500001 -E_PK_PARAMETER: invalid parameter -0xB0500002 -E_PK_MEMORY: memory allocation failed -0xB0500003 -E_PK_UNKNOWN_DN_TYPE: unknown distinguished name type -0xB0500004 -E_PK_INVALID_DN: invalid distinguished name (value or length) -0xB0500005 -E_PK_INVALID_TIME_FORMAT: invalid time format -0xB0500006 -E_PK_UNKNOWN_KEY_TYPE: unknown / unsupported key type -0xB0500007 -E_PK_UNKNOWN_SIGN_ALGO: unknown / unsupported signature algorithm -0xB0500008 -E_PK_UNKNOWN_HASH_ALGO: unknown / unsupported hash algorithm -0xB0500009 -E_PK_INVALID_VERSION: invalid / unsupported version -0xB050000A -E_PK_P7_UNKNOWN_CONTENT_TYPE: unknown / unsupported PKCS7 content type -0xB050000B -E_PK_P7_NO_VERSION_FOUND: no PKCS7 version found -0xB050000C -E_PK_P7_UNKNOWN_ELEM_TYPE: unknown PKCS7 element type -0xB050000D -E_PK_P7_ELEM_TYPE_SIGNATURE: element type SIGNATURE not found -0xB050000E -E_PK_P7_ELEM_TYPE_ENVELOPED: element type ENVELOPED not found -0xB050000F -E_PK_P7_ELEM_TYPE_CERT: element type CERT not found -0xB0500010 -E_PK_P7_ELEM_TYPE_AUTH_ATT: element type AUTH_ATT not found -0xB0500011 -E_PK_P7_ELEM_TYPE_UNAUTH_ATT: element type UNAUTH_ATT not found -0xB0500012 -E_PK_P7_ELEM_TYPE_SIG_TIME: element type SIG_TIME not found -0xB0500013 -E_PK_P7_ELEM_TYPE_DATA: element type DATA not found -0xB0500014 -E_PK_P7_SIGNER_CERTIFICATE: no signer certificate given -0xB0500015 -E_PK_P7_NO_DATA_OR_HASH: no data or hash given to perform sign / verify operation -0xB0500016 -E_PK_P7_INVALID_CONTENT_TYPE: invalid PKCS7 content type -0xB0500017 -E_PK_P7_NO_DIGEST_ALGORITHM: no digest algorithm in PKCS7 data found -0xB0500018 -E_PK_P7_NO_SIGNER_INFOS: no signer infos found -0xB0500019 -E_PK_P7_NO_ISSUER: no issuer / serial number found -0xB050001A -E_PK_P7_NO_OF_ELEM: number of PK_P7_ELEM too small -0xB050001B -E_PK_P7_SIGNER_REF: invalid signer reference -0xB050001C -E_PK_P7_CONTENT_TYPE_NOT_SD: content type is not SignedData -0xB050001D -E_PK_P7_CONTENT_TYPE_NOT_ENV: content type is not Enveloped -0xB050001E -E_PK_P7_KEY_TYPE_MISMATCH: digestEncryptionAlgorithm doesn't match signer certificate key type -0xB050001F -E_PK_P7_VERIFICATION: signature verfication failed -0xB0500020 -E_PK_P7_RECIPIENT_CERT: no recipient certificate given -0xB0500021 -E_PK_P7_UNKNOWN_ENC_KEY_TYPE: unknown / unsupported encryption key type -0xB0500022 -E_PK_P7_MULTIPLE_RCPTS: multiple recipients not supported -0xB0500023 -E_PK_P7_CERT_MISMATCH: given certificate doesn't match certificate in PKCS7 structure -0xB0500024 -E_PK_P7_KEK_ALGO: given key doesn't match key encryption algorithm -0xB0500025 -E_PK_P7_NO_ENC_KEY_ALGO: no key encryption algorithm identifier found -0xB0500026 -E_PK_P7_NO_CONTENT_TYPE: no content type found -0xB0500027 -E_PK_P7_NO_CONTENT_KEY_ALGO: no content encryption algorithm identifier found -0xB0500028 -E_PK_P7_ATTRIBUTE: invalid attribute structure -0xB0500029 -E_PK_P7_NEED_MORE_SPACE: given buffer / struct doesn't contain enough space for this operation -0xB0500030 -E_PK_AES_MODULE: Firmware module AES not loaded -0xB0500031 -E_PK_UNKNOWN_ATT_TYPE: unknown attribute type -0xB0500032 -E_PK_CRL_ISSUER_MISMATCH: CRL issuer doesn't match certificate's subject / issuer -0xB0500033 -E_PK_CRL_ATTR_NOT_AVAILABLE: requested attribute not available (optional) -0xB0500034 -E_PK_CRL_BAD_FORMAT: bad CRL format -0xB0500035 -E_PK_CRL_NOT_VALID: CRL is not yet valid -0xB0500036 -E_PK_CRL_INIT_NOT_CALLED: partial CRL verification not initialized -0xB0500037 -E_PK_CRL_HALGO_MISMATCH: algorithm oid of crl header and trailer differ -0xB0500040 -E_PK_UNSUPPORTED_TIME_FORMAT: unsupported time format -0xB0500041 -E_PK_UNSUPPORTED_CENTURY: given time format contains century < 2000 -0xB0500042 -E_PK_INDEF_LEN: indefinite length not supportet -0xB0500043 -E_PK_NO_ECDSA: Firmware module ECDSA not loaded -0xB0500050 -E_PK_P7_INVALID_SIGNER: invalid signer / invalid signer information -0xB0500051 -E_PK_P7_INVALID_SIGNER_STRUCT: invalid signer structure (ASN.1 error) -0xB061 -E_CTS: CryptoServer module CTS -0xB0610001 -E_CTS_CMD_LEN: Wrong command length -0xB0610002 -E_CTS_MEMORY: memory allocation error -0xB0610003 -E_CTS_INVALID_KEY_ID: Invalid key index -0xB0610004 -E_CTS_SIGNATURE_OID: Signature Algorithm unsupported (hash or signing) -0xB0610005 -E_CTS_DB_ENTRY_EXIST: key index already exists in database -0xB0610006 -E_CTS_KEY_NOT_ACTIVE: selected key is not enabled for signing -0xB0610007 -E_CTS_NO_ACCORDING_KEY: No key for the imported certificate available -0xB0610008 -E_CTS_DATE_EXPIRED: certification validity expired -0xB0610009 -E_CTS_DATE_NOT_YET_VALID: certificate is not yet valid -0xB061000A -E_CTS_PERMISSION_DENIED: permission denied -0xB061000B -E_CTS_NO_CERT_IMPORTED: No certificate to the according key imported -0xB061000C -E_CTS_MBK_NOT_FOUND: mbk from MBK module not found -0xB061000D -E_CTS_MBK_NOT_LOADED: MBK module not loaded -0xB061000E -E_CTS_INVALID_TOKEN_LEN: RSA key token length invalid -0xB061000F -E_CTS_INVALID_HASH: Calculated hash doesn't match given one -0xB0610010 -E_CTS_WRONG_DN_TYPE: Unknown DN component -0xB0610011 -E_CTS_DN_NO_STRUCT: Given ASN1_ITEM of a DN is no struct -0xB0610012 -E_CTS_DN_NOT_EQUAL: Issuer and Subject not the same -0xB0610013 -E_CTS_UNKNOWN_TAG: (ASN1) Tag unknown -0xB0610014 -E_CTS_NOT_FOUND: Given issuer / subject not found -0xB0610015 -E_CTS_CERT_EXIST: Certificate already exist -0xB0610016 -E_CTS_INVALID_TS_STRUCT: TimeStamp ASN.1 structure not correct -0xB0610017 -E_CTS_INVALID_CERTIFICATE: Given certificate not equal to the one in the database -0xB0610018 -E_CTS_INVALID_TIME_DELAY: Given delay to set the new time is too big -0xB0610019 -E_CTS_EXCEEDED_TIME_DELAY: Too many time adjustments on this day -0xB061001A -E_CTS_INVALID_TSA_NAME: TSA name contained in timestamp doesn't match signer name -0xB064 -E_PKCS11: CryptoServer module PKCS11 -0xB0640001 -E_PKCS11_OBJ_CORR: corrupted object data structure -0xB0640002 -E_PKCS11_BAD_ARG: bad arguments -0xB0640003 -E_PKCS11_OBJ_BIG: object has to many attributes -0xB0640004 -E_PKCS11_APP_COUNT: too many concurrent applications -0xB0640005 -E_PKCS11_APP_BAD: bad application reference -0xB0640006 -E_PKCS11_OBJHDL_OVL: object handle overflow -0xB0640007 -E_PKCS11_BAD_PUBEXP: bad public exponent -0xB0640008 -E_PKCS11_BAD_MODULUS: bad modulus -0xB0640009 -E_PKCS11_NO_AES: AES module not found -0xB064000A -E_PKCS11_NO_EC: ECA/ECDSA modules not found -0xB064000B -E_PKCS11_DENIED: access denied -0xB064000C -E_PKCS11_SLOT_CORR: corrupted slot data structure -0xB064000D -E_PKCS11_NO_MBK: MBK module not found -0xB064000E -E_PKCS11_NO_MBK_KEY: no MBK key loaded -0xB064000F -E_PKCS11_INV_BACKUP: invalid backup -0xB0640010 -E_PKCS11_SHUTDOWN: PKCS#11 service terminated -0xB0640011 -E_PKCS11_SLOT_NOT_EMPTY: slot not empty -0xB0640012 -E_PKCS11_NO_DSA: DSA module not found -0xB0640013 -E_PKCS11_APP_TIMEOUT: application timeout -0xB0640014 -E_PKCS11_VALIDITY_PERIOD: validity period has expired -0xB0648 -E_PKCS11_STD: PKCS#11 standard error -0xB068 -E_CXI: CryptoServer module CXI -0xB0680000 -E_CXI_MALLOC: memory allocation error -0xB0680001 -E_CXI_PERMISSION_DENIED: permission denied -0xB0680002 -E_CXI_BUF_SIZE: buffer size too small -0xB0680003 -E_CXI_NOT_SUPPORTED: function not supported -0xB0680004 -E_CXI_MBK_NOT_LOADED: MBK firmware module not loaded -0xB0680005 -E_CXI_INVALID_PARAM_TAG: invalid parameter tag -0xB0680006 -E_CXI_INVALID_PARAM_LEN: invalid parameter length -0xB0680007 -E_CXI_INVALID_PARAM_VAL: invalid parameter value -0xB0680008 -E_CXI_INVALID_FLAGS: invalid flags -0xB0680009 -E_CXI_SFC_RFU: SFC is reserved for further use -0xB068000A -E_CXI_INTERNAL: an internal error occured -0xB068000B -E_CXI_MBK_TYPE: invalid MBK key type -0xB068000C -E_CXI_VALIDITY_PERIOD: validity period has expired -0xB0680010 -E_CXI_PROP_ABSENT: property has to be absent -0xB0680011 -E_CXI_PROP_UNKNOWN: unknown property -0xB0680012 -E_CXI_PROP_NOT_FOUND: property not found -0xB0680013 -E_CXI_PROP_EXISTS: property already exists -0xB0680014 -E_CXI_PROP_READONLY: property is read-only -0xB0680015 -E_CXI_PROP_PROTECTED: property is protected -0xB0680016 -E_CXI_PROP_TAG: invalid property tag -0xB0680017 -E_CXI_PROP_VAL: invalid property value -0xB0680018 -E_CXI_PROP_LEN: invalid property length -0xB0680019 -E_CXI_PROP_SENSITIVE: property is sensitive -0xB068001A -E_CXI_PROP_COMPARE: property doesn't match given template -0xB068001B -E_CXI_PROP_LOCAL_ONLY: property only valid for objects in a group -0xB0680020 -E_CXI_KEY_INVALID_ALGO: invalid key algo -0xB0680021 -E_CXI_KEY_INVALID_SIZE: invalid key size -0xB0680022 -E_CXI_KEY_INVALID_TAG: invalid key tag -0xB0680023 -E_CXI_KEY_INVALID_COMP: invalid key component -0xB0680024 -E_CXI_KEY_BLOB_FORMAT: invalid format of key blob -0xB0680025 -E_CXI_KEY_TYPE: invalid key type -0xB0680026 -E_CXI_KEY_BLOB_MAC: invalid mac of key blob -0xB0680027 -E_CXI_KEY_INVALID_NAME: invalid key name -0xB0680028 -E_CXI_KEY_INVALID_TOKEN: invalid key token -0xB0680029 -E_CXI_KEY_MISSING_COMP: missing key component -0xB068002B -E_CXI_KEY_EXPORT_DENIED: key export is denied -0xB068002C -E_CXI_KEY_IMPORT_DENIED: key import is denied -0xB068002D -E_CXI_KEY_MECH_NOT_ALLOWED: mechanism not allowed -0xB068002E -E_CXI_KEY_INVALID_BLEN: invalid block length -0xB068002F -E_CXI_KEY_USAGE: illegal key usage -0xB0680030 -E_CXI_CRYPT_PADDING: invalid padding -0xB0680031 -E_CXI_CRYPT_MECH: invalid mechanism -0xB0680032 -E_CXI_CRYPT_IV_LEN: invalid IV length -0xB0680033 -E_CXI_CRYPT_SIGN_VERIFY: signature verification failed -0xB0680034 -E_CXI_CRYPT_DATA_LEN: invalid data length -0xB0680035 -E_CXI_CRYPT_MECH_PARA: invalid mechanism parameter -0xB0680040 -E_CXI_ITEM_NOT_FOUND: item not found -0xB0680041 -E_CXI_ITEM_TAG: invalid item tag -0xB0680042 -E_CXI_ITEM_LEN: invalid item length -0xB0680043 -E_CXI_ITEM_VAL: invalid item value -0xB0680044 -E_CXI_ITEM_COUNT: invalid number of items -0xB0680050 -E_CXI_FILE_SIZE: invalid file size -0xB0680060 -E_CXI_ABORT_ENUM: enumeration was aborted -0xB0680061 -E_CXI_INVALID_IN_PARAM: invalid input parameter -0xB06801 -E_CXI_FIPS: FIPS mode -0xB0680100 -E_CXI_FIPS_BLOCKED: function not available in FIPS mode -0xB0680101 -E_CXI_FIPS_MECH: mechanism not supported in FIPS mode -0xB0680102 -E_CXI_FIPS_OBJ_TYPE: object type not available in FIPS mode -0xB0680103 -E_CXI_FIPS_ALGO: algorithm not available in FIPS mode -0xB0680104 -E_CXI_FIPS_KEY_SIZE: key size not allowed in FIPS mode -0xB0680105 -E_CXI_FIPS_KEY_IMPORT: clear text key import not allowed in FIPS mode -0xB0680106 -E_CXI_FIPS_KEY_EXPORT: clear text key export not allowed in FIPS mode -0xB0680107 -E_CXI_FIPS_PROP: property not available in FIPS mode -0xB0680108 -E_CXI_NO_FIPS_CURVE: Curve not available in FIPS mode -0xB0680109 -E_CXI_FIPS_KEY_USAGE: Key usage is restricted in FIPS mode -0xB06802 -E_CXI_SECURE: SECURE -0xB0680200 -E_CXI_SECURE_PROP_DECRYPT: decrypt property true not allowed -0xB0680201 -E_CXI_SECURE_PROP_ENCRYPT: encrypt property true not allowed -0xB0680202 -E_CXI_SECURE_PROP_ALWAYS_SENSITIVE_FALSE: always sensitive property false not allowed -0xB0680203 -E_CXI_SECURE_PROP_SENSITIVE_FALSE: sensitive property false not allowed -0xB0680204 -E_CXI_SECURE_PROP_WRAP: wrap property true not allowed -0xB0680205 -E_CXI_SECURE_PUBLIC_WRAPPING: cannot use public keys for wrapping -0xB0680206 -E_CXI_SECURE_PROP_CHECK_VALUE: check value missing or invalid -0xB0800001 -E_FTEST_MALLOC: CryptoServer module VDES -0xB0810001 -E_VDES_DATA_LEN: length of data is not a multiple of 8 bytes -0xB0810002 -E_VDES_KEY_LEN: length of key is not 8, 16, or 24 -0xB0810003 -E_VDES_MEM: cannot allocate memory -0xB0810004 -E_VDES_WEAK: key is weak -0xB0810005 -E_VDES_SEMI_WEAK: key is semi-weak -0xB0810006 -E_VDES_SHORT_KEY: two of the 8byte key parts are identical -0xB0810007 -E_VDES_MODE: mode is unknown -0xB0810008 -E_VDES_READ_MASTER_KEY: could not get local Master Key -0xB0810009 -E_VDES_PAD_TYPE: unknown padding mechanism -0xB081000A -E_VDES_PAD: invalid padding -0xB081000B -E_VDES_PARAM: invalid parameter -0xB081000C -E_VDES_POSSIBLY_WEAK: key is possibly weak -0xB081000E -E_VDES_ZERO_LENGTH: Zero length not allowed -0xB082 -E_PP: CryptoServer module PP, PIN pad driver -0xB0820001 -E_PP_ABORT: operation aborted by user -0xB0820002 -E_PP_LEN: command block too long -0xB0820003 -E_PP_WRITE_TIMEOUT: timeout while writing to PIN pad -0xB0820004 -E_PP_BUFSIZE: answer buffer too small -0xB0820005 -E_PP_READ_TIMEOUT: timeout while reading from PIN pad -0xB0820006 -E_PP_IO: IO error -0xB0820007 -E_PP_NOT_OPEN: connection not open -0xB0820008 -E_PP_INVAL: invalid parameter -0xB0820009 -E_PP_BAD_RAPDU: bad RAPDU from smartcard -0xB082000A -E_PP_NO_CARD: no smartcard in reader -0xB082000B -E_PP_BAD_TYPE: bad PIN pad type specified -0xB082000C -E_PP_DATALEN: bad length of command block -0xB082000D -E_PP_PROT: protocol error -0xB082000E -E_PP_KEY_TIMEOUT: timeout while waiting for key input -0xB082000F -E_PP_RESET_TIMEOUT: timeout while waiting for card insertation -0xB0820010 -E_PP_PIN_REPETITION: bad repetition of PIN entry -0xB0820011 -E_PP_NOT_SUPPORTED: function is not supported -0xB0820012 -E_PP_PARAM: invalid parameter -0xB0820013 -E_PP_ACCESS_DENIED: access denied -0xB0820014 -E_PP_BAD_INPUT: bad input -0xB0820015 -E_PP_CARD_TIMEOUT: no response from smartcard -0xB0820016 -E_PP_READER_NOT_CONNECTED: no supported smartcard reader connected -0xB0820017 -E_PP_CC_BLOCKED: not allowed in CC Endorsed Mode -0xB08201 -E_PP_PPERR: PIN pad error -0xB08202 -E_PP_CCID: CCID Error -0xB083 -E_CMDS: CryptoServer module CMDS, Command scheduler -0xB0830001 -E_CMDS_DENIED: permission denied -0xB0830002 -E_CMDS_NO_MEM: can't alloc memory -0xB0830003 -E_CMDS_INVAL: invalid parameter -0xB0830004 -E_CMDS_IN_USE: module id already in use -0xB0830005 -E_CMDS_BAD_FC: bad function code (module ID) -0xB0830006 -E_CMDS_BAD_SFC: function doesn't exist -0xB0830007 -E_CMDS_BAD_NAME: invalid user name -0xB0830008 -E_CMDS_DATA_LEN: illegal length of command block -0xB0830009 -E_CMDS_TASK_ERR: can't create task -0xB083000A -E_CMDS_BAD_TAG: bad tag of command block -0xB083000B -E_CMDS_FMT_LEN: bad length within format string (scanf) -0xB083000C -E_CMDS_BAD_CMD: bad format of command block -0xB083000D -E_CMDS_BAD_OUT: bad parameter structure (scanf) -0xB083000E -E_CMDS_BAD_FMT: bad format string (scanf) -0xB083000F -E_CMDS_USER_EXISTS: user already exists -0xB0830010 -E_CMDS_BAD_MECH: invalid mechanism -0xB0830011 -E_CMDS_NO_DB: no DB module present -0xB0830012 -E_CMDS_BAD_AUTH_CMD: invalid AUTH layer command -0xB0830013 -E_CMDS_AUTH_FAILED: authentication failed -0xB0830014 -E_CMDS_NO_VRSA: no VRSA module present -0xB0830015 -E_CMDS_BAD_PERM: bad permission mask -0xB0830016 -E_CMDS_NO_USER: unknown user -0xB0830017 -E_CMDS_BAD_ATT: bad user attributes -0xB083001B -E_CMDS_LOGOFF_FAILED: logoff failed -0xB083001C -E_CMDS_USER_ACTIVE: logged in user can't be deleted -0xB083001D -E_CMDS_BAD_TOKEN: bad user token (key or password) -0xB083001E -E_CMDS_NO_VDES: no VDES module present -0xB083001F -E_CMDS_NO_UTIL: no UTIL module present -0xB0830020 -E_CMDS_NO_HASH: no HASH module present -0xB0830021 -E_CMDS_SM_FAILED: secure messaging failed -0xB0830022 -E_CMDS_SM_EXPIRED: secure messaging session expired -0xB0830023 -E_CMDS_SM_ID: invalid secure messaging ID -0xB0830024 -E_CMDS_BF_OVL: internal buffer overflow -0xB0830025 -E_CMDS_FIPS_INIT: FIPS140 initialization failed -0xB0830026 -E_CMDS_USER_MODE: mode does not match user -0xB0830027 -E_CMDS_BAD_MODE: invalid mode -0xB0830028 -E_CMDS_BAD_SIZE: illegal answer buffer size -0xB0830029 -E_CMDS_NO_MBK: no MBK module present -0xB083002A -E_CMDS_INVAL_BCK: invalid backup data -0xB083002B -E_CMDS_BAD_UDB_ENTRY: bad entry in user DB (internal error) -0xB083002C -E_CMDS_BUFF_SIZE: buffer size too small -0xB083002D -E_CMDS_NO_MBK_KEY: no MBK key found -0xB083002E -E_CMDS_MBK_TYPE: MBK type does not match -0xB083002F -E_CMDS_NO_AES: no AES module present -0xB0830030 -E_CMDS_NO_HMAC: no HMAC algorithm available -0xB0830031 -E_CMDS_NO_ECC: no ECC algorithm available -0xB0830032 -E_CMDS_ALARM: ALARM state -0xB0830033 -E_CMDS_BAD_INITKEY: bad file 'init.key' -0xB0830034 -E_CMDS_ADMIN_AMPUTATION: Administrator must remain -0xB0830035 -E_CMDS_USER_FLAG_NOT_ALLOWED: user flag not allowed -0xB0830036 -E_CMDS_SM_PERM_DIFF: permissions of users of same session must not differ -0xB0830037 -E_CMDS_NVRAM: error acessing NVRAM -0xB0830038 -E_CMDS_AUTH_FAIL_CNT_EXCEEDED: too many unsuccessful authentication tries -0xB0830039 -E_CMDS_PARAM_FIPS: parameter not valid in FIPS mode -0xB083003A -E_CMDS_DENIED_FIPS: authentication mandatory in FIPS mode -0xB083003B -E_CMDS_BAD_MECH_FIPS: mechanism not allowed in FIPS mode -0xB083003C -E_CMDS_BAD_ATT_FIPS: user attributes not allowed in FIPS mode -0xB083003D -E_CMDS_BAD_USER_FLAG_FIPS: user flag not allowed in FIPS mode -0xB083003E -E_CMDS_MAX_AUTH_USER_REACHED: maximum of logged in/authenticated users reached -0xB083003F -E_CMDS_SM_MISSING_FIPS: authentication without secure messaging not allowed in FIPS mode -0xB0830040 -E_CMDS_LOGIN_FIPS: static login not allowed in FIPS mode -0xB0830041 -E_CMDS_AUTH_FIPS_ESTATE: authentication not available in FIPS error state -0xB0830042 -E_CMDS_FIPS_BLOCKED: function not available in FIPS mode -0xB0830043 -E_CMDS_FIPS_ERROR_STATE: function not available in FIPS error state -0xB0830044 -E_CMDS_ADMIN_BAD_FUNC: function is blocked in Administration Mode -0xB0830046 -E_CMDS_MAX_AUTH_FAIL_READ: file for MaxAuthFailures corrupted -0xB0830050 -E_CMDS_LOGIN_CC: static login not allowed in CC mode -0xB0830051 -E_CMDS_AUTH_CC_ESTATE: authentication not available in CC error state -0xB0830052 -E_CMDS_CC_BLOCKED: function not available in CC mode -0xB0830053 -E_CMDS_CC_ERROR_STATE: function not available in CC error state -0xB0830054 -E_CMDS_CC_INIT: CC-CMS initialization failed -0xB0830055 -E_CMDS_BAD_PERM_CC: permissions must not overlap in CC mode -0xB0830056 -E_CMDS_CC_MISSING: cc-cms.msc module missing in flash -0xB0830057 -E_CMDS_BAD_TOKEN_CC: RSA token < 1024 bit not allowed in CC mode -0xB0830059 -E_CMDS_PARAM_CC: parameter not valid in CC mode -0xB083005A -E_CMDS_DENIED_CC: authentication mandatory in CC mode -0xB083005B -E_CMDS_BAD_MECH_CC: mechanism not allowed in CC mode -0xB083005C -E_CMDS_BAD_ATT_CC: user attributes not allowed in CC mode -0xB083005D -E_CMDS_BAD_USER_FLAG_CC: user flag not allowed in CC mode -0xB083005F -E_CMDS_SM_MISSING_CC: authentication without secure messaging not allowed in CC mode -0xB0830060 -E_CMDS_SM_DH_BAD_PARAM: DH parameter from host for sessionkey is weak -0xB0830061 -E_CMDS_SFC_DISABLED: This function is not available in this HSM configuration -0xB0830062 -E_CMDS_HASH_VERS: wrong version of HASH module -0xB0830063 -E_CMDS_CHALLENGE_LEN: illegal challenge length requested -0xB0830064 -E_CMDS_SM_MA_ALARM: Mutual Authentication not available in alarm state -0xB084 -E_VRSA: CryptoServer module VRSA -0xB0840001 -E_VRSA_MEM: cannot allocate memory -0xB0840002 -E_VRSA_BUFF_TOO_SMALL: buffer for result is to small -0xB0840003 -E_VRSA_BAD_DATA: bad raw data value -0xB0840004 -E_VRSA_BAD_MODULUS: modulus is not p * q -0xB0840006 -E_VRSA_P_GREATER_Q: p is greater or equal than q -0xB0840009 -E_VRSA_BAD_U: u is not (1/q) mod p -0xB084000A -E_VRSA_BAD_DP: dp is not d mod (p-1) -0xB084000B -E_VRSA_BAD_DQ: dq is not d mod (q-1) -0xB084000C -E_VRSA_NO_KEYTOKEN: byte string is not a keytoken -0xB084000D -E_VRSA_NO_COMP: component is not a member of this key token -0xB084000E -E_VRSA_DOUBLE_COMP: component is already a member of this key token -0xB084000F -E_VRSA_INVALID_FLAG: value for flags is invalid -0xB0840010 -E_VRSA_HASH_ALGO: Invalid hash algorithm -0xB0840011 -E_VRSA_VERIFY_FAILED: Signature verification failed -0xB0840012 -E_VRSA_KEY_TOO_SMALL: Key length too small -0xB0840014 -E_VRSA_MOD_TOO_SMALL: modulus to small -0xB0840015 -E_VRSA_BAD_KEY: bad key components P and Q -0xB0840016 -E_VRSA_DATA_LEN: data size too big (greater than modulus) -0xB0840017 -E_VRSA_MISS_COMP: missing component in key token -0xB0840018 -E_VRSA_INV_PARAM: invalid parameter -0xB0840019 -E_VRSA_BAD_PEXP: gcd(p-1,e) != 1 or gcd(q-1,e) != 1 -0xB084001A -E_VRSA_BAD_SEXP: d * e != 1 mod (p-1)(q-1) -0xB084001B -E_VRSA_OBSOLETE: function obsolete -0xB084001C -E_VRSA_KGEN_FAILED: key generation failed -0xB084001D -E_VRSA_BAD_BLINDING: invalid blinding value -0xB084001E -E_VRSA_BVGEN_FAILED: blinding value generation failed -0xB084001F -E_VRSA_DECRYPT_FAILED: PKCS#1 decryption failed -0xB0840020 -E_VRSA_INV_PEXP: invalid public exponent -0xB0840021 -E_VRSA_KEYT_LEN: bad length of key token -0xB0840022 -E_VRSA_ENCODING: PKCS#1 encoding error -0xB0840023 -E_VRSA_PAIRWISE_CONSISTENCY: The pairwise consistency test failed ! -0xB0840024 -E_VRSA_FUNC_NOT_AVAILABLE: Function is not available -0xB0840025 -E_VRSA_BAD_BLINDING_MECH: Blinding mechanism unknown -0xB0840100 -E_VRSA_BAD_KEYT: bad key token in command string -0xB0840101 -E_VRSA_RND_SYNC: random number request does not match (FIPS test) -0xB0840102 -E_VRSA_KEY_TOO_SMALL_FIPS: Key length too small (FIPS140) -0xB0840103 -E_VRSA_KEY_TOO_SMALL_CC: Key length too small (CC) -0xB085 -E_SC: CryptoServer Module SC -0xB0850001 -E_SC_APPL_NAME: Bad Length of Application Name -0xB0850002 -E_SC_APDU_SELECT: Card Error from "select" Command -0xB0850003 -E_SC_APDU_IAUTH: Card Error from "internal auth." Command -0xB0850004 -E_SC_BAD_KEY: Wrong SM Key -0xB0850005 -E_SC_APDU_VERPWD: Card Error from "ver. passw." Command -0xB0850006 -E_SC_APDU_MSE: Card Error from "mse" Command -0xB0850007 -E_SC_APDU_READREC: Card Error from "read record" Command -0xB0850008 -E_SC_RECLEN: Bad Record Length -0xB0850009 -E_SC_NO_RECORD: Record not Found -0xB085000A -E_SC_NO_FILE: File not Found -0xB085000B -E_SC_DENIED: Access Denid -0xB085000C -E_SC_BAD_PARAM: Bad Parameter: SFI, REC# -0xB085000D -E_SC_DATALEN: Bad Data Length -0xB085000E -E_SC_SM: Bad Tag for SM -0xB085000F -E_SC_APDU_UPDREC: Card Error from "update record" Command -0xB0850010 -E_SC_APDU_CHGPWD: Card Error from "chg. passw." Command -0xB0850011 -E_SC_NO_PWDFILE: Pasword File not Found -0xB0850012 -E_SC_BAD_PDATA: Bad Personalization Data -0xB0850013 -E_SC_APDU_PERS: Card Error while Personalizing -0xB0850014 -E_SC_APDU_GETSKEY: Card Error from "get sessionkey" Command -0xB0850015 -E_SC_NO_APPL: Application not Found -0xB0850016 -E_SC_APDU_READBIN: Card Error from "read binary" Command -0xB0850017 -E_SC_BAD_PIN_LEN: Bad PIN Length -0xB0850018 -E_SC_MEM: Memory Allocation Error -0xB0850019 -E_SC_APDU_PSO: Card Error from "pso" Command -0xB085001A -E_SC_BAD_CERT: Bad Certificate Format -0xB085001B -E_SC_APDU_GETDATA: Card Error from "get data" Command -0xB085001C -E_SC_BAD_APPLTYPE: Unknown Application Type -0xB085001D -E_SC_NOT_IMPLEMENTED: This Action is not Implmented on the Found Card Type -0xB085001E -E_SC_INVALID_PIN: Invalid Pin -0xB085001F -E_SC_NOT_SUPPORTED: Signing Supported until 48 Byte (Possible Hashes md5, ripemd160, sha1, sha224) -0xB0850020 -E_SC_WRONG_CARD_MODE: Wrong Command for Card Application -0xB0850021 -E_SC_HASH_SIZE: Hash Size Bigger than 40% of the Key Size -0xB0850022 -E_SC_NOPEN_OR_UNKNOWN: Card not Opened Before or Unknown Card -0xB086 -E_UTIL: CryptoServer module UTIL -0xB0860001 -E_UTIL_RTC_OPEN: Error opening RTC Device -0xB0860002 -E_UTIL_RTC_IOCTL: RTC: IOCTL Error -0xB0860003 -E_UTIL_RTC_READ: RTC: Read Error -0xB0860004 -E_UTIL_RTC_WRITE: RTC: Write Error -0xB0860005 -E_UTIL_RTC_CLOSE: Error closing RTC Device -0xB0860006 -E_UTIL_TIME_WRONG_FORMAT: Wrong Time Format -0xB0860007 -E_UTIL_TIME_NULL_POINTER: Null Pointer given -0xB0860008 -E_UTIL_FILE_OPEN: File Open Error -0xB0860009 -E_UTIL_FILE_READ: File Read Error -0xB086000A -E_UTIL_FILE_CLOSE: File Close Error -0xB086000B -E_UTIL_RND_NULL_POINTER: Null Pointer given -0xB086000C -E_UTIL_RND_FAILED: Random Number Generator failed -0xB086000D -E_UTIL_MALLOC: Error allocating Memory -0xB086000E -E_UTIL_INVAL: invalid argument -0xB086000F -E_UTIL_NOT_SUPPORTED: function not supported -0xB0860010 -E_UTIL_RND_KAT: Known answer test failed -0xB0860011 -E_UTIL_RND_INIT: Random Number Generator is not initialized -0xB0860012 -E_UTIL_RND_PARAMETER: Bad Parameter -0xB0860013 -E_UTIL_RND_SEC_STRENGTH: Given security strength not supported -0xB0860014 -E_UTIL_RND_REQ: Max number of requested randombits per call exceeded -0xB0860015 -E_UTIL_RND_PRED_RESISTANCE: prediction resistance not supported for current handle -0xB0860020 -E_UTIL_TIME_RTC_POWER_FAILED: RTC has lost power -0xB0860021 -E_UTIL_TIME_NOT_INIT: RTC is not initialized (RTC has to be set) -0xB086FC00 -E_UTIL_LINK_SMOS: SMOS Version does not match -0xB087 -E_ADM: CryptoServer module ADM -0xB0870001 -E_ADM_FILE_OPEN: file open error -0xB0870002 -E_ADM_FILE_READ: file read error -0xB0870003 -E_ADM_FILE_WRITE: file write error -0xB0870004 -E_ADM_FILE_CLOSE: file close error -0xB0870005 -E_ADM_FILE_MISSING: file (module) does not exist -0xB0870006 -E_ADM_WRONG_FILE_NAME: wrong filename syntax -0xB0870007 -E_ADM_NO_MDL_INFO: no module info found -0xB0870008 -E_ADM_FILE_NOT_FOUND: file not found -0xB087000A -E_ADM_MDL_VERSION_MISSING: no modules version found -0xB087000B -E_ADM_DATA_LEN: wrong command data length -0xB087000C -E_ADM_I2C_OPEN: unable to open i2c device -0xB087000D -E_ADM_I2C_READ: unable to read i2c device -0xB087000F -E_ADM_PERMISSION_DENIED: permission denied -0xB0870011 -E_ADM_FILE_SIZE_TOO_BIG: file size exceeds limit -0xB0870012 -E_ADM_BAD_SIGNATURE: bad signature -0xB0870013 -E_ADM_NO_UTIL: no UTIL module present -0xB0870014 -E_ADM_MALLOC: memory allocation error -0xB0870015 -E_ADM_NOT_SUPPORTED: function not supported -0xB0870016 -E_ADM_INVALID_CRC: invalid crc -0xB0870017 -E_ADM_INVALID_SIZE: invalid size -0xB0870018 -E_ADM_BAD_MMC: bad MMC format -0xB0870019 -E_ADM_NO_HASH: no HASH module present -0xB087001A -E_ADM_NO_VRSA: no VRSA module present -0xB087001B -E_ADM_NO_DB: no DB module present -0xB087001C -E_ADM_NO_AES: no AES module present -0xB087001D -E_ADM_MDL_DEC_FAIL: module decryption failed -0xB087001E -E_ADM_KEY_TYPE: invalid key type -0xB087001F -E_ADM_INVALID_PARAM: invalid parameter -0xB0870020 -E_ADM_FILE_TYPE: invalid file type -0xB0870021 -E_ADM_ITEM_LEN: invalid item length -0xB0870022 -E_ADM_ITEM_NOT_FOUND: item not found -0xB0870023 -E_ADM_NO_MBK: no MBK module present -0xB0870024 -E_ADM_NO_MBK_KEY: no MBK key available -0xB0870025 -E_ADM_MEM: cannot allocate memory -0xB0870026 -E_ADM_MEM_SEC: cannot allocate secure memory -0xB0870027 -E_ADM_MBK_DB_EXP: export of MBK database not allowed -0xB0870028 -E_ADM_MBK_TYPE: invalid MBK value (valid: 0 (DES), 1 (AES)) -0xB0870029 -E_ADM_MBK_DIFFER: given MBK type differs to stored MBK with the highest priority -0xB087002A -E_ADM_MAC: given MAC differs to calculated MAC -0xB087002B -E_ADM_KEY_INDEX: given DB index differs to original DB index -0xB087002C -E_ADM_SESSION_DB_IMP: import of database session.db not allowed -0xB087002D -E_ADM_SESSION_DB_EXP: export of database session.db not allowed -0xB087002E -E_ADM_MBK_DB_IMP: import of MBK database not allowed -0xB087003 -E_ADM_MDL: module section -0xB0870030 -E_ADM_MDL_MTC_HDR_INV: invalid MTC header -0xB0870031 -E_ADM_MDL_MMC_HDR_INV: invalid MMC header -0xB0870032 -E_ADM_MDL_MSC_HDR_INV: invalid MSC header -0xB0870033 -E_ADM_MDL_SIG_HDR_INV: invalid MSC header -0xB0870034 -E_ADM_MDL_SLF_HDR_INV: invalid SLF header -0xB0870035 -E_ADM_MDL_NO_INFO: no module info found -0xB0870036 -E_ADM_MDL_MTC_NO_SIG: MTC doesn't contain signature -0xB0870037 -E_ADM_MDL_MMC_HASH: invalid MMC hash -0xB0870038 -E_ADM_MDL_DECRYPT: can't decrypt firmware module -0xB0870039 -E_ADM_MDL_SCF_HDR_INV: invalid SCF header -0xB087004 -E_ADM_KEY: key section -0xB0870040 -E_ADM_KEY_CORRUPTED: key is corrupted -0xB087005 -E_ADM_CFG: cfg section -0xB0870051 -E_ADM_CFG_MDL_NOT_FOUND: could not retrieve version of requested module -0xB0870052 -E_ADM_CFG_MDL_TOO_OLD: requested module is too old, does not yet support cfg -0xB0870053 -E_ADM_CFG_MDL_UNKNOWN: unknown module, unknown how to cfg -0xB0870054 -E_ADM_CFG_AMSK_BLOCKED: loading of an Alternative Module Signature Key is blocked -0xB087006 -E_ADM_FIPS: FIPS section -0xB0870061 -E_ADM_FIPS_MDL: evaluation of FIPS mode has gone wrong -0xB0870062 -E_ADM_FIPS_RESTRICTED: virtual error code for restricted FIPS mode -0xB0870063 -E_ADM_FIPS_BLOCKED: function not available in FIPS mode -0xB0870064 -E_ADM_FIPS_ERROR_STATE: function not available in FIPS error state -0xB0870070 -E_ADM_CC_BLOCKED: not allowed in CC Endorsed Mode -0xB0870071 -E_ADM_CC_ERROR_STATE: not allowed in CC Error State -0xB0870080 -E_ADM_AUTH_KEY_DB_IMP: import of authentication key database not allowed -0xB0870081 -E_ADM_AUTH_KEY_DB_EXP: export of authentication key database not allowed -0xB088 -E_DB: CryptoServer Database Module -0xB0880001 -E_DB_NO_MEM: memory allocation failed -0xB0880002 -E_DB_BAD_MKEY: bad master encryption key -0xB0880003 -E_DB_NO_SPACE: no space in database -0xB0880004 -E_DB_NOT_FOUND: record not found -0xB0880005 -E_DB_EXISTS: record already exists -0xB0880006 -E_DB_NO_CACHE: no space in cache -0xB0880007 -E_DB_COR_FILE: corrupted database file -0xB0880008 -E_DB_REC_CRC: record CRC error -0xB0880009 -E_DB_BAD_NAME: bad database name -0xB088000A -E_DB_BAD_HANDLE: bad database handle -0xB088000B -E_DB_FILE_TYPE: bad file type of database file -0xB088000D -E_DB_BAD_INFO: bad info structure -0xB088000E -E_DB_IN_USE: database in use -0xB088000F -E_DB_LENGTH: bad data length -0xB0880011 -E_DB_HDL_CONF: database handle confused -0xB0880012 -E_DB_INCONS: internal inconsistency -0xB0880013 -E_DB_SMOSVER: SMOS version is too old -0xB0881000 -E_DB_DATALEN: bad length of command block -0xB0881001 -E_DB_FILE_ERR: io error on database file -0xB0881002 -E_DB_NOT_OPEN: test database not open -0xB0881003 -E_DB_CORR_HDL: db handle corrupted -0xB0881004 -E_DB_CORR_NODE: db node corrupted -0xB0881005 -E_DB_CORR_CACHE: db cache corrupted -0xB089 -E_HASH: CryptoServer module HASH -0xB0890001 -E_HASH_MEM: Memory Error -0xB0890002 -E_HASH_PARAMETER: Illegal Parameter -0xB0890003 -E_HASH_LEN: Illegal Length -0xB0890004 -E_HASH_MODE: Illegal Mode -0xB0890005 -E_HASH_FUNCTION: Function not supported -0xB0890006 -E_HASH_MODE_FIPS: Mode not permitted in FIPS mode -0xB08B -E_AES: CryptoServer module AES -0xB08B0001 -E_AES_DATA_LEN: length of data is not a multiple of 16 bytes -0xB08B0002 -E_AES_KEY_LEN: length of key is not 16, 24, or 32 -0xB08B0003 -E_AES_MEM: cannot allocate memory -0xB08B0004 -E_AES_MODE: mode is unknown -0xB08B0005 -E_AES_CFB1_DEC_MODE: For cfb1 decryption the key must always prepared for encryption -0xB08B0006 -E_AES_PAD_TYPE: unknown padding mechanism -0xB08B0007 -E_AES_PAD: invalid padding -0xB08B0008 -E_AES_PARAM: invalid parameter -0xB08B0009 -E_AES_READ_MASTER_KEY: could not get local Master Key -0xB08B000A -E_AES_MODE_MISMATCH: mode of prepared key does not match mode parameter -0xB08B000C -E_AES_ZERO_LEN: Zero data length is not allowed -0xB08B000D -E_AES_CTR_OVERFLOW: Overflow of block counter in CTR chaining mode -0xB08B000E -E_AES_TAG_VERIFICATION: Tag verification on CCM/GCM decrypt failed -0xB08D -E_DSA: CryptoServer module DSA -0xB08D0001 -E_DSA_MEM: cannot allocate memory -0xB08D0002 -E_DSA_P_TOO_SMALL: prime P is too small -0xB08D0003 -E_DSA_Q_TOO_SMALL: prime Q is too small -0xB08D0004 -E_DSA_GEN_FAILED: domain parameter generation failed -0xB08D0005 -E_DSA_BAD_G: invalid generator value G -0xB08D0006 -E_DSA_BAD_PRIMES: bad primes P and Q -0xB08D0007 -E_DSA_NO_KEYTOKEN: byte string is not a keytoken -0xB08D0008 -E_DSA_NO_COMP: component is not a member of this token -0xB08D0009 -E_DSA_DOUBLE_COMP: component is already a member of this token -0xB08D000A -E_DSA_INVALID_FLAG: value for flags is invalid -0xB08D000B -E_DSA_HASH_LEN: wrong hash value length -0xB08D000C -E_DSA_BAD_KEY: private and public key do not correspond -0xB08D000D -E_DSA_INV_PARAM: invalid parameter -0xB08D000E -E_DSA_BAD_PKEY: bad public key -0xB08D000F -E_DSA_BAD_SKEY: bad private key -0xB08D0010 -E_DSA_KEYT_LEN: bad length of key token -0xB08D0011 -E_DSA_VERIFY_FAILED: signature verification failed -0xB08D0012 -E_DSA_BAD_SIGN_FMT: bad format of signature -0xB08D0013 -E_DSA_NO_ASN1: no ASN.1 module loaded -0xB08D0014 -E_DSA_BUFF_TOO_SMALL: buffer for result is to small -0xB08D0015 -E_DSA_KEYGEN_TEST: pairwise consistency check failed on keygen -0xB08D0018 -E_DSA_ZERO_LEN: Zero length not allowed -0xB08D0030 -E_DSA_NOT_SUPPORTED: The function called is no longer supported -0xB08D0100 -E_DSA_BAD_KEYT: bad key token in command string -0xB08E -E_LNA: CryptoServer module LNA -0xB08E0001 -E_LNA_OVL: result overflow -0xB08E0002 -E_LNA_NEG: result negativ -0xB08E0003 -E_LNA_MOD_LEN: modulus too short -0xB08E0004 -E_LNA_DATA_LEN: data greater than modulus -0xB08E0005 -E_LNA_MEM: can't alloc memory -0xB08E0006 -E_LNA_EXP0: exponent is 0 -0xB08E0007 -E_LNA_DIV0: division by zero -0xB08E0008 -E_LNA_NUM_LEN: number too short -0xB08E0009 -E_LNA_PARAM: bad parameter -0xB08E000A -E_LNA_NOT_FOUND: no prime found -0xB08E000B -E_LNA_MOD_EVEN: modulus is even -0xB08E0100 -E_LNA_RESOVL: result overflow -0xB08E0101 -E_LNA_ARG_LEN: bad argument length -0xB08E0102 -E_LNA_INT: internal error while generating prime -0xB08F -E_ECA: CryptoServer module ECA -0xB08F0001 -E_ECA_MEM: can't alloc memory -0xB08F0002 -E_ECA_NOT_SUPP: not supported -0xB08F0003 -E_ECA_BAD_PARAM: bad parameter -0xB08F0004 -E_ECA_NOT_FOUND: curve not found -0xB08F0005 -E_ECA_EXISTS: curve already registered -0xB08F0006 -E_ECA_TOO_BIG: input number too big -0xB08F0007 -E_ECA_INFINITE: infinite result -0xB08F0008 -E_ECA_PCP_INCOMP: incompatible precalculated point -0xB08F0009 -E_ECA_LEN: bad length of argument -0xB08F000A -E_ECA_BAD_TAG: bad tag of point -0xB08F000B -E_ECA_NO_SQRT: no square root found -0xB08F000C -E_ECA_NO_NON_RESIDUE: non-residue could not be found -0xB08F000D -E_ECA_NO_ASN1: no ASN.1 module found -0xB08F000E -E_ECA_ECDP_DECODE: error decoding ASN.1 EC domain parameter -0xB08F000F -E_ECA_BAD_POINT: bad value of EC point -0xB08F0010 -E_ECA_BAD_VALUE: bad value of EC domain parameter -0xB08F0011 -E_ECA_ECDP_DIFFER: EC domain parameters differ -0xB08F0012 -E_ECA_BAD_DOMAIN_PARA: invalid domain parameter -0xB08F0013 -E_ECA_BAD_POLYNOM: invalid irreducible polynomial -0xB08F0014 -E_ECA_NO_FIPS_CURVE: curve not available in FIPS mode -0xB08F0015 -E_ECA_NO_FIPS_FUNCTION: function not available in FIPS mode -0xB08F0016 -E_ECA_NO_SECURE_CURVE: Curve not secure for CC standards -0xB08F0017 -E_ECA_BL_TBL: table of precalculated values empty/inconsistent -0xB08F0101 -E_ECA_ARG_LEN: bad argument length -0xB08F0102 -E_ECA_INT: internal error -0xB090 -E_TECA: CryptoServer module TECA -0xB0900001 -E_TECA_PERMISSION_DENIED: permission denied -0xB0900002 -E_TECA_PARAM: invalid parameter -0xB0900003 -E_TECA_PARAM_LEN: invalid parameter length -0xB0900004 -E_TECA_MALLOC: memory allocation failed -0xB0900005 -E_TECA_MODE: invalid mode -0xB0900006 -E_TECA_ITEM_NOT_FOUND: item not found -0xB0900007 -E_TECA_MODULE_DEP: unresolved module dependency -0xB0900008 -E_TECA_FILE_IO: file I/O error -0xB091 -E_ASN1: CryptoServer module ASN1 -0xB0910001 -E_ASN1_MEM: Memory Error -0xB0910002 -E_ASN1_FLAG: Parameter flag is incorrect -0xB0910003 -E_ASN1_TAB_OVL: ASN1_ITEM table overflow -0xB0910004 -E_ASN1_BAD_ZKA: bad ZKA format -0xB0910005 -E_ASN1_DATASIZE: ASN1 data overrun -0xB0910006 -E_ASN1_TAGSIZE: tag too big -0xB0910007 -E_ASN1_INDEF_LEN: indefinite length not supportet -0xB0910008 -E_ASN1_LENSIZE: lenght field too big -0xB0910009 -E_ASN1_STACK_OVL: internal stack overflow -0xB091000A -E_ASN1_NOT_FOUND: item not found -0xB091000B -E_ASN1_BUFF_OVL: ASN1 buffer overflow -0xB091000C -E_ASN1_ITEMCOUNT: bad value of 'nitems' in ITEM table -0xB091000D -E_ASN1_BADTAG: zero tag -0xB091000E -E_ASN1_BAD_PKCS1: bad PKCS#1 format -0xB091000F -E_ASN1_DECODE_ERR: decoding error -0xB0910010 -E_ASN1_SIZE_EXCEEDED: calculated size exceeds given datasize -0xB096 -E_MBK: CryptoServer module MBK -0xB0960001 -E_MBK_PARA: Parameter mismatch -0xB0960002 -E_MBK_DB_NO_SERVICE: MBK database is suspended -0xB0960003 -E_MBK_NULL_PTR: Unexpected null pointer -0xB0960004 -E_MBK_PERMISSION: Permission denied -0xB0960005 -E_MBK_ISO_HASH_FAIL: ISO hash check of key failed -0xB0960006 -E_MBK_IG_KEY_TYPES_NM: Key types do not match -0xB0960007 -E_MBK_IG_KEY_DATE_NM: Key generation date do not match -0xB0960008 -E_MBK_IG_KEY_TIME_NM: Key generation time do not match -0xB0960009 -E_MBK_IG_KEY_NAME_NM: Key names do not match -0xB096000A -E_MBK_EX_KEY_CHK_FAIL: Verify of existing master key failed -0xB096000B -E_MBK_SLOT_EMPTY: Slot is empty -0xB096000C -E_MBK_KEY_NO: Slot number not valid -0xB096000D -E_MBK_REC_NO: Record number not valid -0xB096000E -E_MBK_KEY_LB: Key length not valid -0xB096000F -E_MBK_TIME_WRONG_FORMAT: Wrong format in time structure detected -0xB0960010 -E_MBK_BCD_LB: BCD coded time length mismatch -0xB0960011 -E_MBK_KEY_NAME: No key name or NULL pointer for key name -0xB0960012 -E_MBK_ACTION_CANCELED: Action canceled by user -0xB0960013 -E_MBK_MODE_INV: Invalid mode for AES key passed -0xB0960014 -E_MBK_DB_VERSION: Both versions of the MBK database exists -0xB0960015 -E_MBK_EI_PARA_SET_EXT: External parameter already set from extern and overwrite flag is not set -0xB0960016 -E_MBK_AES_NA: The AES Module is not available -0xB0960017 -E_MBK_KEY_TYPE: Invalid key type -0xB0960018 -E_MBK_ALLOC: memory allocation failed -0xB0960019 -E_MBK_BAD_DB_FORMAT: bad database format -0xB096001A -E_MBK_RECORD_EMPTY: smartcard record is empty -0xB096001B -E_MBK_SC_EMPTY: smartcard only contains empty records -0xB096001C -E_MBK_SEMA_REQ: unable to require semaphore -0xB096001D -E_MBK_MAX_KEK: maximum numbers of key exchange keys reached -0xB096001E -E_MBK_FLAGS_INV: invalid flags value -0xB096001F -E_MBK_INFO_LB: info length not valid -0xB0960020 -E_MBK_KEY_EXISTS: key alread exists -0xB0960021 -E_MBK_SHARE_LB: invalid length of key share -0xB0960022 -E_MBK_SHARE_CNT: invalid number of key shares -0xB0960023 -E_MBK_ECA_NA: the ECA module is not available -0xB0960024 -E_MBK_IG_KEY_SHARE_CNT_NM: number of key shares doesn't match -0xB0960025 -E_MBK_KEY_ID_INV: invalid key ID -0xB0960026 -E_MBK_KEY_ID_SAME: multiple occurence of same key ID -0xB0960027 -E_MBK_KEK_NOT_FOUND: no kek found with given hash -0xB0960028 -E_MBK_NOT_SUPPORTED: function is not supported -0xB0960029 -E_MBK_NO_PP: no PIN pad module found -0xB096002A -E_MBK_NO_SC: no smartcard module found -0xB096002B -E_MBK_FIPS_BLOCKED: function not available in FIPS mode -0xB096002C -E_MBK_CC_BLOCKED: not allowed in CC Endorsed Mode -0xB096002D -E_MBK_DEPRECATED: function is deprecated -0xB099 -E_PIN: CryptoServer module PIN -0xB0990001 -E_PIN_BAD_FMT: bad PIN block format -0xB0990002 -E_PIN_BAD_PARA: bad parameter -0xB0990003 -E_PIN_NO_MEM: can't allocate memory -0xB0990004 -E_PIN_BAD_LENGTH: bad PIN length -0xB0990005 -E_PIN_LESS_DIGITS: not enaugh digits found -0xB0990006 -E_PIN_BAD_XTAB: bad translation table -0xB0990007 -E_PIN_BAD_COND: bad PIN conditions -0xB0990008 -E_PIN_REJECT: PIN does not meet conditions -0xB09A -E_NTP: CryptoServer module NTP -0xB09A0001 -E_NTP_CMD_LEN: NTP: Command with invalid data length -0xB09A0002 -E_NTP_INVALID_TIME_DELAY: NTP: requested time delay too big -0xB09A0003 -E_NTP_DAILY_TIME_DELAY_EXCEEDED: NTP: daily time delay exceeded -0xB09A0004 -E_NTP_DEPRECATED_FUNCTION_CALL: NTP: old function call; use new one -0xB09A0005 -E_NTP_NEGATIVE_TIME_SET: NTP: negative time set; use flag to set backward -0xB09A0006 -E_NTP_NOT_ACTIVATED: NTP: ntp module is not activated -0xB09A0007 -E_NTP_DB_ERROR: NTP: database error -0xB09A0008 -E_NTP_PERMISSION_DENIED: NTP: permission denied -0xB09C -E_ECDSA: CryptoServer module ECDSA -0xB09C0001 -E_ECDSA_MEM: cannot allocate memory -0xB09C0002 -E_ECDSA_R_S_IS_NULL: null component in signature (r,s) -0xB09C0003 -E_ECDSA_INV_FLAG: value for flags is invalid -0xB09C0004 -E_ECDSA_BAD_KEY: private and public key do not correspond -0xB09C0005 -E_ECDSA_BAD_PKEY: bad public key -0xB09C0006 -E_ECDSA_BAD_SKEY: bad private key -0xB09C0007 -E_ECDSA_VERIFY_FAILED: signature verification failed -0xB09C0008 -E_ECDSA_BAD_SIGN_FMT: bad format of signature -0xB09C0009 -E_ECDSA_NO_ASN1: no ASN.1 module loaded -0xB09C000A -E_ECDSA_BUFF_TOO_SMALL: buffer for result is to small -0xB09C000B -E_ECDSA_BAD_KEY_FMT: malformed ASN.1 coded key pair -0xB09C000C -E_ECDSA_ECIES_PARAM: bad parameter -0xB09C000D -E_ECDSA_ECIES_MAC_CHECK: mac check of ecies encrypted data failed -0xB09C000E -E_ECDSA_NO_AES: no AES module loaded -0xB09C000F -E_ECDSA_KEYGEN_TEST: pairwise consistency check failed on keygen -0xB09C0010 -E_ECDSA_ZERO_LEN: Zero length not allowed -0xB09C0011 -E_ECDSA_NO_SEC_MODE: secure mode of curve not available -0xB09C0012 -E_ECDSA_BULK_MAX: count of signatures per command exceeds limit -0xB900 -E_CSA: CryptoServer API -0xB90000 -E_CSA_CORE: CryptoServer API core functions -0xB9000000 -E_CSA_CORE_BAD_TAG: bad tag in data block -0xB9000001 -E_CSA_CORE_HANDLE: invalid handle -0xB9000002 -E_CSA_CORE_INVAL: invalid argument -0xB9000003 -E_CSA_CORE_MEM: can't alloc memory -0xB9000004 -E_CSA_CORE_STACK: malformed protocol stack -0xB9000005 -E_CSA_CORE_SIZE: data block too big -0xB9000007 -E_CSA_CORE_V24_DEV: bad V24 device -0xB9000008 -E_CSA_CORE_V24_PARAM: bad V24 parameter -0xB9000009 -E_CSA_CORE_BLK_LEN: can't calculate block length -0xB900000A -E_CSA_CORE_EMPTY: empty command block -0xB900000B -E_CSA_CORE_BAD_ANSW: malformed answer block from CSLAN -0xB900000C -E_CSA_CORE_V24_CTRL: can't set V24 device -0xB900000D -E_CSA_CORE_NO_V24: V24 mode not activated -0xB900000E -E_CSA_CORE_V24_CRC: V24 crc error on read -0xB9000010 -E_CSA_CORE_FMT_LEN: bad length within format string (scanf) -0xB9000011 -E_CSA_CORE_BAD_CMD: bad format of command block -0xB9000012 -E_CSA_CORE_BAD_OUT: bad parameter structure (scanf) -0xB9000013 -E_CSA_CORE_BAD_FMT: bad format string (scanf) -0xB9000014 -E_CSA_CORE_SCANF: cs_scanf not supported -0xB9000015 -E_CSA_CORE_HDL_IN_USE: CSAPI handle still in use -0xB90001 -E_CSA_KS: command layer for old KryptoServer -0xB9000100 -E_CSA_KS_ALEN: length error of answer block -0xB9000101 -E_CSA_KS_CLEN: bad length error of command data -0xB9000102 -E_CSA_KS_PARAM: missing parameter structure -0xB90002 -E_CSA_CMDS: command layer CMDS for CryptoServer -0xB9000200 -E_CSA_CMDS_ALEN: length error of answer block -0xB9000201 -E_CSA_CMDS_CLEN: bad length of command data -0xB9000202 -E_CSA_CMDS_PARAM: missing parameter structure -0xB9000203 -E_CSA_CMDS_TAG: bad tag of answer block -0xB90003 -E_CSA_CHNL: command layer CHNL for CryptoServer -0xB9000300 -E_CSA_CHNL_ALEN: length error of answer block -0xB9000301 -E_CSA_CHNL_TAG: bad tag of answer block -0xB90004 -E_CSA_AUTH: authentication layer for CryptoServer -0xB9000400 -E_CSA_AUTH_ALEN: length error of answer block -0xB9000401 -E_CSA_AUTH_BAD_FC: invalid function code -0xB9000402 -E_CSA_AUTH_BAD_ANSW: malformed answer block -0xB9000403 -E_CSA_AUTH_BAD_MECH: invalid authentication mechanism -0xB9000404 -E_CSA_AUTH_HASH_ERR: error in hash function -0xB9000405 -E_CSA_AUTH_SIGN_ERR: error in signature function -0xB9000406 -E_CSA_AUTH_HMAC_ERR: error in HMAC function -0xB90005 -E_CSA_BL: command layer BL for CryptoServer -0xB9000500 -E_CSA_BL_ALEN: length error of answer block -0xB9000501 -E_CSA_BL_CLEN: bad length error of command data -0xB9000502 -E_CSA_BL_PARAM: missing parameter structure -0xB9000503 -E_CSA_BL_TAG: bad tag of answer block -0xB90006 -E_CSA_SM: secure messaging layer for CryptoServer -0xB9000600 -E_CSA_SM_ALEN: length error of answer block -0xB9000601 -E_CSA_SM_BAD_ANSW: malformed answer block -0xB9000602 -E_CSA_SM_BAD_MECH: invalid SM mechanism -0xB9000603 -E_CSA_SM_NO_DATA: zero length data -0xB9000604 -E_CSA_SM_DES_ERR: en- / decryption / MAC error -0xB9000605 -E_CSA_SM_UNWRAP: secure messaging unwrap error -0xB9000A -E_CSA_CDI: command layer CDI for CryptoServer -0xB9000A00 -E_CSA_CDI_ALEN: length error of answer block -0xB9000A01 -E_CSA_CDI_CLEN: bad length error of command data -0xB9000A02 -E_CSA_CDI_PARAM: missing parameter structure -0xB9000A03 -E_CSA_CDI_TAG: bad tag of answer block -0xB9000C -E_CSA_TL: command layer TL for CryptoServer -0xB9000C00 -E_CSA_TL_ALEN: length error of answer block -0xB9000C01 -E_CSA_TL_TAG: bad tag of answer block -0xB9000E -E_CSA_DUMY: command layer DUMY for CryptoServer -0xB9000E00 -E_CSA_DUMY_ALEN: length error of answer block -0xB9000E01 -E_CSA_DUMY_CLEN: bad length error of command data -0xB9000E02 -E_CSA_DUMY_PARAM: missing parameter structure -0xB901 -E_CSA_LX: CryptoServer API LINUX -0xB9010001 -E_CSA_LX_PATH: path name too long -0xB9010002 -E_CSA_LX_PORT: bad port number -0xB9010003 -E_CSA_LX_ADDR: bad IP address -0xB9010004 -E_CSA_LX_HOSTNAME: bad host name -0xB9010005 -E_CSA_LX_TERM: connection terminated by remote host -0xB9010006 -E_CSA_LX_MEM: can't alloc memory -0xB9010007 -E_CSA_LX_TIMEOUT: timeout occured -0xB9010008 -E_CSA_LX_INVAL: invalid argument -0xB9010009 -E_CSA_LX_ADDRLEN: no space for sockaddr (internal error) -0xB901000A -E_CSA_LX_BLKSIZE: bad block size received -0xB901000B -E_CSA_LX_NOT_RDY: no ready message from CMDS -0xB901000C -E_CSA_LX_CRIT_TEMP: cs2 exceeds critical temperature -0xB901000D -E_CSA_LX_PROC: error on /proc file -0xB901000E -E_CSA_LX_DEV: can't stat device file -0xB901000F -E_CSA_LX_BUF_SIZE: buffer size too small -0xB9011 -E_CSA_LX_OPEN: can't open device -0xB9012 -E_CSA_LX_SOCKET: can't creat socket -0xB9013 -E_CSA_LX_CONNECT: can't get connection -0xB9014 -E_CSA_LX_POLL: error while polling -0xB9015 -E_CSA_LX_READ: read error -0xB9015701 -E_CSA_LX_READ_701: timeout -0xB9015706 -E_CSA_LX_READ_706: operation interruptet by reset -0xB9015707 -E_CSA_LX_READ_707: high temperature -0xB901570A -E_CSA_LX_READ_70A: CryptoServer halted -0xB901570B -E_CSA_LX_READ_70B: panic message from CryptoServer -0xB9016 -E_CSA_LX_WRITE: write error -0xB9016701 -E_CSA_LX_WRITE_701: timeout -0xB9016703 -E_CSA_LX_WRITE_703: request rejectet by CS2 -0xB9016706 -E_CSA_LX_WRITE_706: operation interruptet by reset -0xB9016707 -E_CSA_LX_WRITE_707: high temperature -0xB901670A -E_CSA_LX_WRITE_70A: CryptoServer halted -0xB901670B -E_CSA_LX_WRITE_70B: panic message from CryptoServer -0xB9017 -E_CSA_LX_IOCTL: ioctl error -0xB9017701 -E_CSA_LX_IOCTL_701: timeout -0xB9017706 -E_CSA_LX_IOCTL_706: operation interrupted by reset -0xB9017707 -E_CSA_LX_IOCTL_707: high temperature -0xB901770A -E_CSA_LX_IOCTL_70A: CryptoServer halted -0xB901770B -E_CSA_LX_IOCTL_70B: panic message from CryptoServer -0xB901773 -E_CSA_LX_IOCTL_73: reset of CryptoServer failed -0xB9018 -E_CSA_LX_LOCK: ioctl error (locking) -0xB9018706 -E_CSA_LX_LOCK_706: operation interruptet by reset -0xB9019 -E_CSA_LX_RECV: tcp receive error -0xB901A -E_CSA_LX_SEND: tcp send error -0xB902 -E_CSA_WIN: CryptoServer API Windows -0xB9020001 -E_CSA_WIN_PATH: path name too long -0xB9020002 -E_CSA_WIN_PORT: bad port number -0xB9020003 -E_CSA_WIN_ADDR: bad IP address -0xB9020004 -E_CSA_WIN_HOSTNAME: bad host name -0xB9020005 -E_CSA_WIN_TERM: connection terminated by remote host -0xB9020006 -E_CSA_WIN_MEM: can't alloc memory -0xB9020007 -E_CSA_WIN_TIMEOUT: timeout occured -0xB9020008 -E_CSA_WIN_INVAL: invalid argument -0xB9020009 -E_CSA_WIN_ADDRLEN: no space for sockaddr (internal error) -0xB902000A -E_CSA_WIN_BLKSIZE: bad block size received -0xB902000B -E_CSA_WIN_CMDS_NOT_RDY: no ready message from CMDS -0xB902000C -E_CSA_WIN_CRIT_TEMP: cs2 exceeds critical temperature -0xB9020010 -E_CSA_WIN_INVALID_PARAM: invalid parameter -0xB9020011 -E_CSA_WIN_INVALID_HANDLE: invalid handle value -0xB9020013 -E_CSA_WIN_CREATE_MUTEX: error creating mutex -0xB9020014 -E_CSA_WIN_LOCK: unable to set lock -0xB9020015 -E_CSA_WIN_LOCK_TIMEOUT: timeout while waiting for mutex -0xB9020016 -E_CSA_WIN_LOCK_HANDLE: no valid mutex object -0xB90201 -E_CSA_WIN_OPEN: tcp: can't open device -0xB90202 -E_CSA_WIN_SOCKET: tcp: can't create socket -0xB90203 -E_CSA_WIN_CONNECT: tcp: can't get connection -0xB90204 -E_CSA_WIN_POLL: tcp: error while polling -0xB90204F0 -E_CSA_WIN_CONNECT_FAIL: can't get connection -0xB90205 -E_CSA_WIN_READ: tcp: read error -0xB90206 -E_CSA_WIN_WRITE: tcp: write error -0xB90207 -E_CSA_WIN_INIT: tcp: init error -0xB90208 -E_CSA_WIN_IOCTL: tcp: ioctl error -0xB9021 -E_CSA_WIN_DCI_OPEN: dci: can't open device -0xB9022 -E_CSA_WIN_DCI_READ: read error -0xB9022001 -E_CSA_WIN_DCI_READ_RLEN: read returned wrong length -0xB90220B5 -E_CSA_WIN_DCI_READ_TMOUT: read timeout -0xB9022706 -E_CSA_WIN_DCI_READ_706: operation interruptet by reset -0xB9022707 -E_CSA_WIN_DCI_READ_707: high temperature -0xB902273 -E_CSA_WIN_DCI_READ_73: reset failed -0xB9023 -E_CSA_WIN_DCI_WRITE: dci: write error -0xB9023001 -E_CSA_WIN_DCI_WRITE_RLEN: write returned wrong length -0xB90230B5 -E_CSA_WIN_DCI_WRITE_TMOUT: write timeout -0xB9023706 -E_CSA_WIN_DCI_WRITE_706: operation interrupted by reset -0xB9023707 -E_CSA_WIN_DCI_WRITE_707: high temperature -0xB902373 -E_CSA_WIN_DCI_WRITE_73: reset failed -0xB9024 -E_CSA_WIN_DCI_IOCTL: dci: ioctl error -0xB9024001 -E_CSA_WIN_DCI_IOCTL_NOT_RDY: no ready message from CMDS -0xB90240B5 -E_CSA_WIN_DCI_IOCTL_TMOUT: ioctl timeout -0xB9024706 -E_CSA_WIN_DCI_IOCTL_706: operation interruptet by reset -0xB9024707 -E_CSA_WIN_DCI_IOCTL_707: high temperature -0xB902473 -E_CSA_WIN_DCI_IOCTL_73: reset failed -0xB9025 -E_CSA_WIN_MTX: mutex section -0xB9028 -E_CSA_WIN_TCP_STARTUP: tcp: startup error -0xB9029 -E_CSA_WIN_TCP_ADDR: tcp: address error -0xB902A -E_CSA_WIN_TCP_SOCKET: tcp: can't create socket -0xB902B -E_CSA_WIN_TCP_CONNECT: tcp: can't get connection -0xB902B03C -E_CSA_WIN_TCP_CONNECT_TIMEOUT: connection attempt timed out -0xB902B03D -E_CSA_WIN_TCP_CONNECT_REFUSED: connection attempt refused -0xB902C -E_CSA_WIN_TCP_SELECT: tcp: error on select -0xB902D -E_CSA_WIN_TCP_RECV: tcp: receive error -0xB902E -E_CSA_WIN_TCP_SEND: tcp: send error -0xB902F -E_CSA_WIN_TCP_IOCTL: tcp: ioctl error -0xB904 -E_YACL: yacl library -0xB90400 -E_YACL_DES: DES modul -0xB9040000 -E_YACL_DES_KEY_LEN: length of DES-Key is not 8, 16 or 24 byte -0xB9040001 -E_YACL_DES_DATA_LEN: length of input data is not a multiple of 8 -0xB9040013 -E_YACL_ECA_BAD_POLYNOM: invalid irreducible polynomial -0xB90401 -E_YACL_RSA: RSA modul -0xB9040100 -E_YACL_RSA_RESULT_TOO_LONG: effective length of result is greater -0xB9040101 -E_YACL_RSA_OPERAND_TOO_LONG: effective length of on input operand -0xB9040102 -E_YACL_RSA_RESULT_NEGATIV: result of subtraction would be negativ -0xB9040103 -E_YACL_RSA_DIVISOR_ZERO: divisor/modulus is zero with division -0xB9040104 -E_YACL_RSA_BAD_OPERAND: operand for 'esm' is greater than modulus -0xB90402 -E_YACL_LNA: Long Number Arithmetic -0xB9040201 -E_YACL_LNA_OVL: result overflow -0xB9040202 -E_YACL_LNA_NEG: result negativ -0xB9040203 -E_YACL_LNA_MOD_LEN: modulus too short -0xB9040204 -E_YACL_LNA_DATA_LEN: data greater than modulus -0xB9040205 -E_YACL_LNA_MEM: can't alloc memory -0xB9040206 -E_YACL_LNA_EXP0: exponent is 0 -0xB9040207 -E_YACL_LNA_DIV0: division by zero -0xB9040208 -E_YACL_LNA_NUM_LEN: number too short -0xB9040209 -E_YACL_LNA_PARAM: bad parameter -0xB904020A -E_YACL_LNA_NOT_FOUND: no prime found -0xB904020B -E_YACL_LNA_MOD_EVEN: modulus is even -0xB90403 -E_YACL_VRSA: RSA functions -0xB9040301 -E_YACL_VRSA_MEM: cannot allocate memory -0xB9040302 -E_YACL_VRSA_BUFF_TOO_SMALL: buffer for result is to small -0xB9040303 -E_YACL_VRSA_DATA_LEN: data size too big (greater than modulus) -0xB9040304 -E_YACL_VRSA_BAD_MODULUS: modulus is not p * q -0xB9040305 -E_YACL_VRSA_P_GREATER_Q: p is greater then q -0xB9040306 -E_YACL_VRSA_BAD_U: u is not (1/q) mod p -0xB9040307 -E_YACL_VRSA_BAD_DP: dp is not d mod (p-1) -0xB9040308 -E_YACL_VRSA_BAD_DQ: dq is not d mod (q-1) -0xB9040309 -E_YACL_VRSA_BAD_PEXP: gcd(p-1,e) != 1 or gcd(q-1,e) != 1 -0xB904030A -E_YACL_VRSA_BAD_SEXP: d * e != 1 mod (p-1)(q-1) -0xB904030B -E_YACL_VRSA_KEY_TOO_SMALL: Key length too small -0xB904030C -E_YACL_VRSA_MOD_TOO_SMALL: modulus to small -0xB904030D -E_YACL_VRSA_BAD_KEY: bad key components -0xB904030E -E_YACL_VRSA_INV_PARAM: invalid parameter -0xB904030F -E_YACL_VRSA_KGEN_FAILED: key generation failed -0xB9040310 -E_YACL_VRSA_HASH_ALGO: Invalid hash algorithm -0xB9040311 -E_YACL_VRSA_VERIFY_FAILED: Signature verification failed -0xB9040312 -E_YACL_VRSA_DECRYPT_FAILED: PKCS#1 decryption failed -0xB9040313 -E_YACL_VRSA_ENCODING: PKCS#1 encoding error -0xB9040314 -E_YACL_VRSA_INV_PEXP: invalid public exponent -0xB90404 -E_YACL_SAFER: SAFER module -0xB9040400 -E_YACL_SAFER_KEY_LEN: length of SAFER-Key is not 8 or 16 -0xB9040401 -E_YACL_SAFER_DATA_LEN: length of input data is not a multiple of 8 -0xB90405 -E_YACL_RND: Pseudo Random Number Generator -0xB9040501 -E_YACL_RND_NULL_POINTER: Null pointer in argument -0xB9040502 -E_YACL_RND_WRONG_SEED_LENGTH: Wrong length of seed -0xB9040503 -E_YACL_RND_AUTO_INIT: Can't auto initialize rnd generator -0xB90406 -E_YACL_AES: AES module -0xB9040600 -E_YACL_AES_KEY_LEN: length of AES-Key is not 16, 24 or 32 -0xB9040601 -E_YACL_AES_DATA_LEN: length of input data is not a multiple of 16 -0xB9040602 -E_YACL_AES_PARAM: bad input parameter (eg. NULL pointer not allowed) -0xB90408 -E_YACL_ASN1: ASN1 module -0xB9040821 -E_YACL_ASN1_MEM: Memory Error -0xB9040822 -E_YACL_ASN1_FLAG: Parameter flag is incorrect -0xB9040823 -E_YACL_ASN1_TAB_OVL: ASN1_ITEM table overflow -0xB9040824 -E_YACL_ASN1_COMP_FLAG: Component flag is not defined -0xB9040825 -E_YACL_ASN1_DATASIZE: ASN1 data overrun -0xB9040826 -E_YACL_ASN1_TAGSIZE: tag too big -0xB9040827 -E_YACL_ASN1_INDEF_LEN: indefinite length not supportet -0xB9040828 -E_YACL_ASN1_LENSIZE: lenght field too big -0xB904082A -E_YACL_ASN1_NOT_FOUND: item not found -0xB904082B -E_YACL_ASN1_BUFF_OVL: ASN1 buffer overflow -0xB904082C -E_YACL_ASN1_ITEMCOUNT: bad value of 'nitems' in ITEM table -0xB904082D -E_YACL_ASN1_BADTAG: zero tag -0xB904082F -E_YACL_ASN1_DECODE_ERR: decoding error -0xB9040830 -E_YACL_ASN1_SIZE_EXCEEDED: calculated size exceeds given datasize -0xB90409 -E_YACL_HASH: Hash module -0xB9040901 -E_YACL_HASH_MODE: Invalid hash mode -0xB9040902 -E_YACL_HASH_LEN: Invalid length -0xB9040903 -E_YACL_HASH_PARAM: Invalid parameter -0xB9040A -E_YACL_ECA: module ECA -0xB9040A01 -E_YACL_ECA_MEM: can't alloc memory -0xB9040A02 -E_YACL_ECA_NOT_SUPP: not supported -0xB9040A03 -E_YACL_ECA_BAD_PARAM: bad parameter -0xB9040A04 -E_YACL_ECA_NOT_FOUND: curve not found -0xB9040A05 -E_YACL_ECA_EXISTS: curve already registered -0xB9040A06 -E_YACL_ECA_TOO_BIG: input number too big -0xB9040A07 -E_YACL_ECA_INFINITE: infinite result -0xB9040A08 -E_YACL_ECA_PCP_INCOMP: incompatible precalculated point -0xB9040A09 -E_YACL_ECA_LEN: bad length of argument -0xB9040A0A -E_YACL_ECA_BAD_TAG: bad tag of point -0xB9040A0B -E_YACL_ECA_NO_SQRT: no square root found -0xB9040A0C -E_YACL_ECA_NO_NON_RESIDUE: non-residue could not be found -0xB9040A0D -E_YACL_ECA_NO_ASN1: no ASN.1 module found -0xB9040A0E -E_YACL_ECA_ECDP_DECODE: error decoding ASN.1 EC domain parameter -0xB9040A0F -E_YACL_ECA_BAD_POINT: bad value of EC point -0xB9040A10 -E_YACL_ECA_BAD_VALUE: bad value of EC domain parameter -0xB9040A11 -E_YACL_ECA_ECDP_DIFFER: EC domain parameters differ -0xB9040A12 -E_YACL_ECA_BAD_DOMAIN_PARA: invalid domain parameter -0xB9040B -E_YACL_ECDSA: module ECDSA -0xB9040B01 -E_YACL_ECDSA_MEM: cannot allocate memory -0xB9040B02 -E_YACL_ECDSA_R_S_IS_NULL: null component in signature (r,s) -0xB9040B03 -E_YACL_ECDSA_INV_FLAG: value for flags is invalid -0xB9040B04 -E_YACL_ECDSA_BAD_KEY: private and public key do not correspond -0xB9040B05 -E_YACL_ECDSA_BAD_PKEY: bad public key -0xB9040B06 -E_YACL_ECDSA_BAD_SKEY: bad private key -0xB9040B07 -E_YACL_ECDSA_VERIFY_FAILED: signature verification failed -0xB9040B08 -E_YACL_ECDSA_BAD_SIGN_FMT: bad format of signature -0xB9040B09 -E_YACL_ECDSA_NO_ASN1: no ASN.1 module loaded -0xB9040B0A -E_YACL_ECDSA_BUFF_TOO_SMALL: buffer for result is to small -0xB9040B0B -E_YACL_ECDSA_BAD_KEY_FMT: malformed ASN.1 coded key pair -0xB9040C -E_YACL_DSA: module DSA -0xB9040C01 -E_YACL_DSA_P_TOO_SMALL: prime P is too small -0xB9040C02 -E_YACL_DSA_Q_TOO_SMALL: prime Q is too small -0xB9040C03 -E_YACL_DSA_GEN_FAILED: domain parameter generation failed -0xB9040C04 -E_YACL_DSA_BAD_G: invalid generator value G -0xB9040C05 -E_YACL_DSA_BAD_PRIMES: bad primes P and Q -0xB9040C06 -E_YACL_DSA_HASH_LEN: hash value too long -0xB9040C07 -E_YACL_DSA_BAD_KEY: private and public key do not correspond -0xB9040C08 -E_YACL_DSA_INV_PARAM: invalid parameter -0xB9040C09 -E_YACL_DSA_BAD_PKEY: bad public key -0xB9040C0A -E_YACL_DSA_BAD_SKEY: bad private key -0xB9040C0B -E_YACL_DSA_VERIFY_FAILED: signature verification failed -0xB9040C0C -E_YACL_DSA_BAD_SIGN_FMT: bad format of signature -0xB9040C0D -E_YACL_DSA_BUFF_TOO_SMALL: buffer for result is to small -0xB9040D -E_YACL_PK: PK module -0xB9040D01 -E_YACL_PK_PARAMETER: invalid parameter -0xB9040D02 -E_YACL_PK_MEMORY: memory allocation failed -0xB9040D03 -E_YACL_PK_UNKNOWN_DN_TYPE: unknown distinguished name type -0xB9040D04 -E_YACL_PK_INVALID_DN: invalid distinguished name (value or length) -0xB9040D05 -E_YACL_PK_INVALID_TIME_FORMAT: invalid time format -0xB9040D06 -E_YACL_PK_UNKNOWN_KEY_TYPE: unknown / unsupported key type -0xB9040D07 -E_YACL_PK_UNKNOWN_SIGN_ALGO: unknown / unsupported signature algorithm -0xB9040D08 -E_YACL_PK_UNKNOWN_HASH_ALGO: unknown / unsupported hash algorithm -0xB9040D09 -E_YACL_PK_INVALID_VERSION: invalid / unsupported version -0xB9040D0A -E_YACL_PK_P7_UNKNOWN_CONTENT_TYPE: unknown / unsupported PKCS7 content type -0xB9040D0B -E_YACL_PK_P7_NO_VERSION_FOUND: no PKCS7 version found -0xB9040D0C -E_YACL_PK_P7_UNKNOWN_ELEM_TYPE: unknown PKCS7 element type -0xB9040D0D -E_YACL_PK_P7_ELEM_TYPE_SIGNATURE: element type SIGNATURE not found -0xB9040D0E -E_YACL_PK_P7_ELEM_TYPE_ENVELOPED: element type ENVELOPED not found -0xB9040D0F -E_YACL_PK_P7_ELEM_TYPE_CERT: element type CERT not found -0xB9040D10 -E_YACL_PK_P7_ELEM_TYPE_AUTH_ATT: element type AUTH_ATT not found -0xB9040D11 -E_YACL_PK_P7_ELEM_TYPE_UNAUTH_ATT: element type UNAUTH_ATT not found -0xB9040D12 -E_YACL_PK_P7_ELEM_TYPE_SIG_TIME: element type SIG_TIME not found -0xB9040D13 -E_YACL_PK_P7_ELEM_TYPE_DATA: element type DATA not found -0xB9040D14 -E_YACL_PK_P7_SIGNER_CERTIFICATE: no signer certificate given -0xB9040D15 -E_YACL_PK_P7_NO_DATA_OR_HASH: no data or hash given to perform sign / verify operation -0xB9040D16 -E_YACL_PK_P7_INVALID_CONTENT_TYPE: invalid PKCS7 content type -0xB9040D17 -E_YACL_PK_P7_NO_DIGEST_ALGORITHM: no digest algorithm in PKCS7 data found -0xB9040D18 -E_YACL_PK_P7_NO_SIGNER_INFOS: no signer infos found -0xB9040D19 -E_YACL_PK_P7_NO_ISSUER: no issuer / serial number found -0xB9040D1A -E_YACL_PK_P7_NO_OF_ELEM: number of PK_P7_ELEM too small -0xB9040D1B -E_YACL_PK_P7_SIGNER_REF: invalid signer reference -0xB9040D1C -E_YACL_PK_P7_CONTENT_TYPE_NOT_SD: content type is not SignedData -0xB9040D1D -E_YACL_PK_P7_CONTENT_TYPE_NOT_ENV: content type is not Enveloped -0xB9040D1E -E_YACL_PK_P7_KEY_TYPE_MISMATCH: digestEncryptionAlgorithm doesn't match signer certificate key type -0xB9040D1F -E_YACL_PK_P7_VERIFICATION: signature verfication failed -0xB9040D20 -E_YACL_PK_P7_RECIPIENT_CERT: no recipient certificate given -0xB9040D21 -E_YACL_PK_P7_UNKNOWN_ENC_KEY_TYPE: unknown / unsupported encryption key type -0xB9040D22 -E_YACL_PK_P7_MULTIPLE_RCPTS: multiple recipients not supported -0xB9040D23 -E_YACL_PK_P7_CERT_MISMATCH: given certificate doesn't match certificate in PKCS7 structure -0xB9040D24 -E_YACL_PK_P7_KEK_ALGO: given key doesn't match key encryption algorithm -0xB9040D25 -E_YACL_PK_P7_NO_ENC_KEY_ALGO: no key encryption algorithm identifier found -0xB9040D26 -E_YACL_PK_P7_NO_CONTENT_TYPE: no content type found -0xB9040D27 -E_YACL_PK_P7_NO_CONTENT_KEY_ALGO: no content encryption algorithm identifier found -0xB9040D28 -E_YACL_PK_P7_ATTRIBUTE: invalid attribute structure -0xB9040D29 -E_YACL_PK_P7_NEED_MORE_SPACE: given buffer / struct doesn't contain enough space for this operation -0xB9040D30 -E_YACL_PK_TIME_ERROR: Unable to retrieve system time / convert time; -0xB9040D31 -E_YACL_PK_UNKNOWN_ATT_TYPE: unknown attribute type -0xB9040D32 -E_YACL_PK_CRL_ISSUER_MISMATCH: CRL issuer doesn't match certificate's subject / issuer -0xB9040D33 -E_YACL_PK_CRL_ATTR_NOT_AVAILABLE: requested attribute not available (optional) -0xB9040D34 -E_YACL_PK_CRL_BAD_FORMAT: bad CRL format -0xB9040D35 -E_YACL_PK_CRL_NOT_VALID: CRL is not yet valid -0xB9040D36 -E_YACL_PK_CRL_INIT_NOT_CALLED: partial CRL verification not initialized -0xB9040D40 -E_YACL_PK_UNSUPPORTED_TIME_FORMAT: unsupported time format -0xB9040D41 -E_YACL_PK_UNSUPPORTED_CENTURY: given time format contains century < 1900 -0xB9040D42 -E_YACL_PK_INDEF_LEN: indefinite length not supportet -0xB9040D50 -E_YACL_PK_P7_INVALID_SIGNER: invalid signer / invalid signer information -0xB9040D51 -E_YACL_PK_P7_INVALID_SIGNER_STRUCT: invalid signer structure (ASN.1 error) -0xB9040E -E_YACL_CRYPT: crypt module -0xB9040E01 -E_YACL_OLD_CRYPT_VERSION: Old Crypt Version -0xB905 -E_SL: Serial Driver -0xB9050001 -E_SL_TOOMANY: too many lines open -0xB9050002 -E_SL_TCATTR: error setting line parameters -0xB9050003 -E_SL_OPEN: can't open device -0xB9050004 -E_SL_NOT_OPEN: handle not open -0xB9050005 -E_SL_NO_VALID_HDL: invalid handle -0xB9050006 -E_SL_NO_VALID_PARA_VALUE: invalid parameter value -0xB9050007 -E_SL_NO_VALID_PARA_TYPE: invalid parameter type -0xB9050008 -E_SL_READ_ERROR: error on read -0xB9050009 -E_SL_READ_TIME_OUT: timeout on read -0xB905000A -E_SL_WRITE_ERROR: error on write -0xB905000B -E_SL_WRITE_TIME_OUT: timeout on write -0xB905000C -E_SL_CTRL_ERROR: error on ioctl -0xB9050010 -E_SL_NO_VALID_NAME: no valid device name -0xB9050011 -E_SL_NO_VALID_BUF_SLCT: no valid Buffer selected -0xB9050012 -E_SL_NO_VALID_LINE_STATE: line state parameter incorrect -0xB9050013 -E_SL_NO_VALID_LINE_SLCT: line select parameter incorrect -0xB9050014 -E_SL_COM_STATE: error in comunication driver -0xB9050015 -E_SL_PARITY: Parity Error -0xB9050016 -E_SL_FRAME: Frame Error -0xB9050017 -E_SL_FLUSH_FAILED: Flush failed -0xB9050018 -E_SL_READ_EOF: EOF on read -0xB906 -E_CAL: CryptoServer admin library -0xB9060001 -E_CAL_BAD_MEM: malloc() failed -0xB9060002 -E_CAL_PPAPP_LIST: malformed PIN-Pad application list -0xB9061 -E_CAL_UTL: Utility Functions -0xB9061001 -E_CAL_UTL_FILE_OPEN: File Open Error -0xB9061002 -E_CAL_UTL_KEY_INIT: Key Structure has not been initialized -0xB9061003 -E_CAL_UTL_KEY_FILE_OPEN: unable to open Keyfile -0xB9061004 -E_CAL_UTL_KEY_FILE_TYPE: unknown Type of Keyfile -0xB9061005 -E_CAL_UTL_KEY_FILE_READ: Error reading Keyfile -0xB9061006 -E_CAL_UTL_KEY_FILE_WRITE: Error writing Keyfile -0xB9061007 -E_CAL_UTL_KEY_TOK_FORMAT: Wrong Keyfile Format in .tok file -0xB9061008 -E_CAL_UTL_KEY_ASC_FORMAT: Wrong Keyfile Format in .key file -0xB9061009 -E_CAL_UTL_KEY_WRONG_FILENAME: Wrong File Name -0xB906100A -E_CAL_UTL_KEY_SOURCE: invalid Key Source (file or smartcard) -0xB906100B -E_CAL_UTL_KEY_TYPE: invalid Key Type (private or public) -0xB906100C -E_CAL_UTL_KEY_INVALID_DATA_LEN: invalid Data Length -0xB906100D -E_CAL_UTL_KEY_INVALID_LEN: invalid Key Length -0xB906100E -E_CAL_UTL_KEY_DECRYPT: can't decrypt keyfile -0xB906100F -E_CAL_UTL_KEY_PASSFCT: no get_pass function specified (or twice) -0xB9061010 -E_CAL_UTL_TIME_WRONG_FORMAT: Wrong Time Format YYYYMMDDHHMMSS -0xB9061011 -E_CAL_UTL_FILE_NOT_FOUND: file not found -0xB9061012 -E_CAL_UTL_INVALID_PARAM: invalid parameter -0xB9061013 -E_CAL_UTL_NOT_SUPPORTED: function not supported -0xB9062 -E_CAL_BL: Bootloader Command Interface -0xB9062001 -E_CAL_BL_SHA1: Error calculating Hash with SHA1 -0xB9062002 -E_CAL_BL_RSA: error executing RSA -0xB9062003 -E_CAL_BL_NO_RND: no random value present -0xB9062004 -E_CAL_BL_INVALID_PARAM: invalid parameter -0xB9062005 -E_CAL_BL_INVALID_KEY: invalid key format -0xB9062006 -E_CAL_BL_FILE_OPEN: file open error -0xB9062007 -E_CAL_BL_FILE_READ: file read error -0xB9062008 -E_CAL_BL_MALLOC: memory allocation error -0xB9062009 -E_CAL_BL_RESPONSE_ERR: response error from Cryptoserver -0xB906200A -E_CAL_BL_WRONG_FILE_NAME: Module Name Syntax incorrect -0xB906200B -E_CAL_BL_WRONG_RSP_LENGTH: Wrong Response Length from CS2 -0xB906200C -E_CAL_BL_NO_FILE: file does not exist -0xB906200D -E_CAL_BL_TIME_CONVERT: unable to convert time -0xB906200E -E_CAL_BL_KEY_SIZE: invalid key size -0xB906200F -E_CAL_BL_NO_EXT_ERASE: no external erase prevailing -0xB9063 -E_CAL_ADM: Admin Module Command Interface -0xB9063001 -E_CAL_ADM_INVALID_PARAM: invalid Parameter -0xB9063002 -E_CAL_ADM_WRONG_NAME: File Name Syntax incorrect -0xB9063003 -E_CAL_ADM_FILE_OPEN: File Open Error -0xB9063004 -E_CAL_ADM_FILE_READ: File Read Error -0xB9063005 -E_CAL_ADM_WRONG_PATH: File Path incorrect -0xB9063006 -E_CAL_ADM_MALLOC: Memory Allocation Error -0xB9063007 -E_CAL_ADM_WRONG_RSP_LENGTH: wrong response length from CS2 -0xB9063008 -E_CAL_ADM_NO_FILE: file does not exist -0xB9063009 -E_CAL_ADM_BATT_STATE: unknown battery state -0xB906300A -E_CAL_ADM_TIME_CONVERT: unable to convert time -0xB906300B -E_CAL_ADM_AUDIT_BAD: malformed audit log file -0xB906300C -E_CAL_ADM_NO_EXT_ERASE: no external erase prevailing -0xB906300D -E_CAL_ADM_AUDITCFG_SVM: struct version mismatch (binary length) -0xB906300E -E_CAL_ADM_INVALID_NO_ARGS: invalid number of arguments returning -0xB906300F -E_CAL_ADM_MODEL_NOT_SUITABLE: file not suitable for cryptoserver model -0xB9063010 -E_CAL_ADM_FILE_WRITE: File Write Error -0xB9064 -E_CAL_MXC: MMC / MTC tools -0xB9064001 -E_CAL_MXC_MALLOC: Memory Allocation Error -0xB9064002 -E_CAL_MXC_FILE_OPEN: unable to open file -0xB9064003 -E_CAL_MXC_FILE_READ: Error reading file -0xB9064004 -E_CAL_MXC_FILE_WRITE: Error writing file -0xB9064005 -E_CAL_MXC_FILE_TYPE: unknown file type -0xB9064006 -E_CAL_MXC_INVALID_ENC_MODE: invalid encryption mode -0xB9064007 -E_CAL_MXC_NO_MDL_INFO: Module does not contain mdl_info -0xB9064008 -E_CAL_MXC_READ_MMC_HEADER: Error reading mmc-header -0xB9064009 -E_CAL_MXC_READ_MTC_HEADER: Error reading mtc-header -0xB906400A -E_CAL_MXC_DES_KEYGEN_DIV8: key length isn't divisible by 8 -0xB906400B -E_CAL_MXC_DES_DECRYPT: Error executing DES Decryption -0xB906400C -E_CAL_MXC_DES_ENCRYPT: Error executing DES Encryption -0xB906400D -E_CAL_MXC_HASH_SHA1: Error executing SHA1 Hash -0xB906400E -E_CAL_MXC_HASH_INVALID_ALGO: invalid Hash algo -0xB906400F -E_CAL_MXC_INVALID_SIG_KEY: invalid Signature Key -0xB9064010 -E_CAL_MXC_PARAM_NULL_POINTER: Null Pointer in Parameter -0xB9064011 -E_CAL_MXC_NO_SIG: Container is without Signature -0xB9064012 -E_CAL_MXC_NO_SIG_INFO: MTC is without Signature Info -0xB9064013 -E_CAL_MXC_INVALID_MMC_HDR: invalid MMC header -0xB9064014 -E_CAL_MXC_INVALID_MTC_HDR: invalid MTC header -0xB9064015 -E_CAL_MXC_INVALID_SIG_HDR: invalid signature header -0xB9064016 -E_CAL_MXC_ENC_NOT_SUPPORTED: encryption not supported -0xB9064017 -E_CAL_MXC_NO_CPU_INFO: unknown target CPU of Module -0xB9064018 -E_CAL_MXC_NO_FW_DEC_KEY: firmware decryption key required -0xB9064019 -E_CAL_MXC_NO_FW_DEC_ERR: error decrypting firmware module -0xB906401A -E_CAL_MXC_SIGN_TYPE: invalid sign type -0xB906401B -E_CAL_MXC_NO_DATA: write operation with zero data blocks -0xB9064020 -E_CAL_MXC_SIG_INVALID_ALGO: invalid signature algo -0xB9064021 -E_CAL_MXC_SIG_CMP_RESULT: calculated Hash doesn't match with decrypted Hash -0xB9064022 -E_CAL_MXC_SIG_INVALID_MODULUS: invalid RSA Modulus to en-/decrypt signature -0xB9064023 -E_CAL_MXC_SIG_INVALID_PUBEXP: invalid RSA Public Exponent to decrypt signature -0xB9064024 -E_CAL_MXC_SIG_INVALID_PRVEXP: invalid RSA Modulus Exponent to encrypt signature -0xB9064025 -E_CAL_MXC_SIG_RSA_DECRYPT: Error RSA-decryption signature -0xB9064026 -E_CAL_MXC_SIG_RSA_ENCRYPT: Error RSA-encrypting signature -0xB9064027 -E_CAL_MXC_SIG_READ_HEADER: Error reading header of signature -0xB9064028 -E_CAL_MXC_SIG_INVALID_HASH_ALGO: invlaid Hash algo for signature -0xB9064029 -E_CAL_MXC_SIG_INVALID_KEY_LEN: invalid Key Length -0xB906402A -E_CAL_MXC_SIG_INVALID_BTYPE: invalid block type -0xB906402B -E_CAL_MXC_SIG_INVALID_PKCS1: invalid pkcs#1 format -0xB906402C -E_CAL_MXC_SIG_BAD_HASH: bad hash value -0xB906402D -E_CAL_MXC_NO_HW_INFO: unknown target hardware of Module -0xB906402E -E_CAL_MXC_DOUBLE_SIGNED: cannot sign an already signed SCF file -0xB9064040 -E_CAL_MXC_PARSE: parse error found in licence file -0xB9064041 -E_CAL_MXC_NO_LICFILE: not a licence file -0xB9064050 -E_CAL_MXC_NO_FILES: package archive contains no files -0xB9066 -E_CAL_AUTH: Authentication / Session layer -0xB9066001 -E_CAL_AUTH_BAD_USERNAME: Bad user name -0xB9066002 -E_CAL_AUTH_BAD_MEM: malloc failed -0xB9066003 -E_CAL_AUTH_BAD_LIST: bad user list returned from CS2 -0xB9066004 -E_CAL_AUTH_ALEN: bad length of answer from CS2 -0xB9066006 -E_CAL_AUTH_KEY_SIZE: specified keysize does not match smartcard -0xB9066008 -E_CAL_AUTH_INVAL: invalid parameter -0xB9066009 -E_CAL_AUTH_USER_EXIST: user already exists -0xB906600A -E_CAL_AUTH_FILE_EXIST: file already exists -0xB906600B -E_CAL_AUTH_FILE_OPEN: file open error -0xB906600C -E_CAL_AUTH_FILE_READ: file read error -0xB906600D -E_CAL_AUTH_FILE_WRITE: file write error -0xB906600E -E_CAL_AUTH_BAD_BACKUP: bad user backup data -0xB906600F -E_CAL_AUTH_USER_SKIPPED: at least one user has been skipped -0xB9066010 -E_CAL_AUTH_NO_LONG_NAME: long username not supported -0xB9066011 -E_CAL_AUTH_NOT_SUPPORTED: function not supported -0xB9066012 -E_CAL_AUTH_BAD_HALGO: unknown hash algorithm -0xB9066013 -E_CAL_AUTH_RSA_MODE: only CRT sign supported -0xB9066014 -E_CAL_AUTH_SM_MECH: illegal SM mechanism -0xB9066015 -E_CAL_AUTH_DEC_SKEY: error decrypting session key -0xB9066016 -E_CAL_AUTH_SIG_BUFF: buffer too small for signature -0xB9066017 -E_CAL_AUTH_SMC_ID: too many concurrent SC authentications -0xB9066018 -E_CAL_AUTH_NO_PUBKEY: no public key found on smartcard -0xB9066019 -E_CAL_AUTH_SM_BAD_MODE: illegal SM mode -0xB906601A -E_CAL_AUTH_SM_BAD_SIGNATURE: CryptoServer's signature could not be verified -0xB906601B -E_CAL_AUTH_SM_BAD_KEY_FILE: illegal format in auth keys file -0xB906601C -E_CAL_AUTH_KEY_NOT_FOUND: auth keys file does not contain key for this CryptoServer -0xB906601D -E_CAL_AUTH_KEY_TYPE_UNSUPPORTED: HSM auth key type not supported -0xB906601E -E_CAL_AUTH_KEY_MODE_UNSUPPORTED: HSM auth key mode not supported -0xB9067 -E_CAL_CSL: CSL Command Interface -0xB9067001 -E_CAL_CSL_INVALID_REC_LEN: invalid record length returned -0xB9067002 -E_CAL_CSL_MALLOC: memory allocation error -0xB9067003 -E_CAL_CSL_INVALID_DATA_LEN: invalid data length returned -0xB9067004 -E_CAL_CSL_CRYPT: password encryption failed -0xB9067005 -E_CAL_CSL_INVAL_PARAM: invalid parameter -0xB9067006 -E_CAL_CSL_BFSIZE: buffer size too small -0xB9067007 -E_CAL_CSL_ANSW_DATA: invalid answer data -0xB9068 -E_CAL_PKG: PKG Command Interface -0xB9068001 -E_CAL_PKG_FOP: accessing directory failed -0xB9068002 -E_CAL_PKG_FNAME_LEN: filename too long -0xB9068003 -E_CAL_PKG_FOPEN: open file failed -0xB9068004 -E_CAL_PKG_FREAD: read file failed -0xB9068005 -E_CAL_PKG_FWRITE: write file failed/ -0xB9068006 -E_CAL_PKG_MEMORY: memory allocation failed -0xB9068007 -E_CAL_PKG_NO_FILES: directory contains no files -0xB9068008 -E_CAL_PKG_INVALID_FILE: invalid package file -0xB9068009 -E_CAL_PKG_INVALID_NAME: invalid package name -0xB906800A -E_CAL_PKG_DIR_EXISTS: directory already exist -0xB906800B -E_CAL_PKG_CREATE_DIR: creating directory failed -0xB906800C -E_CAL_PKG_PARAM: Invalid parameter -0xB906800D -E_CAL_PKG_KEY: No key specifier given -0xB906800E -E_CAL_PKG_SLF_NAME: Invalid SingedLicenseFile name -0xB9068010 -E_CAL_PKG_LOOP: Possible loop in state machine detected -0xB9068011 -E_CAL_PKG_LOAD_FILE: Load file failed -0xB9068012 -E_CAL_PKG_FW_CONFIG: different module names with the same id /abbrev - config mismatch -0xB9068013 -E_CAL_PKG_MDL_START_NOK: could not start firmware module(s) -0xB9068014 -E_CAL_PKG_MDL: CryptoServer firmware module(s) differs from archive content -0xB9068015 -E_CAL_PKG_FLAGS_BLCLEAR: Given flag forbids to perform a BLClear -0xB9068016 -E_CAL_PKG_BASE_FIRMWARE: base firmware is missing / incomplete -0xB9068017 -E_CAL_PKG_FW_NO_ARCHIVE: firmware module not contained in archive -0xB9068018 -E_CAL_PKG_FW_CPU_TYPE: firmware module is contained in archive but with different CPU type -0xB9068019 -E_CAL_PKG_ALARM: CryptoServer in alarm state -0xB906801A -E_CAL_PKG_UNDEF_STATE: cryptoserver remains in an undefined state -0xB906801B -E_CAL_PKG_TMP_DIR: creating temporary directory failed -0xB906801C -E_CAL_PKG_OLD_SDK: old CryptoServer SDK version not supported -0xB906801D -E_CAL_PKG_VERIFICATION: verification of firmware package failed -0xB9068020 -E_CAL_PKG_AUTH_PARAM: bad auth/sm parameter -0xB9068021 -E_CAL_PKG_SESSION: bad session -0xB9068022 -E_CAL_PKG_FLAGS: illegal flag parameter -0xB9068023 -E_CAL_PKG_MODEL: package loader <--> CryptoServer model mismatch -0xB9069 -E_CAL_MBK: MBK tools -0xB9069001 -E_CAL_MBK_PKCS1_FORMAT: bad pkcs1 format -0xB9069002 -E_CAL_MBK_BUF_SIZE: buffer size too small -0xB9069003 -E_CAL_MBK_RESP_LEN: invalid response length -0xB9069004 -E_CAL_MBK_ALLOC: memory allocation failed -0xB9069005 -E_CAL_MBK_FILE_OPEN: unable to open file -0xB9069006 -E_CAL_MBK_FILE_FORMAT: invalid file format -0xB9069007 -E_CAL_MBK_PARAM_INVAL: invalid parameter -0xB9069008 -E_CAL_MBK_ACTION_CANCELED: aborted by user -0xB9069009 -E_CAL_MBK_RESP_DATA: invalid answer data -0xB906900A -E_CAL_MBK_KEY_LEN: invalid key length -0xB906900B -E_CAL_MBK_NO_PWD: no password given -0xB906900C -E_CAL_MBK_NO_SESSION: no session -0xB9069010 -E_CAL_MBK_SC_ERR: smartcard responds error -0xB9069011 -E_CAL_MBK_SC_NO_RECORD: record not found -0xB9069012 -E_CAL_MBK_SC_NO_FILE: file not found -0xB9069013 -E_CAL_MBK_SC_DENIED: access denied -0xB9069014 -E_CAL_MBK_SC_SM: secure messaging failed -0xB9069015 -E_CAL_MBK_SC_RECLEN: invalid record length -0xB9069016 -E_CAL_MBK_SC_VERIFY_FAILED: password verification failed -0xB9069017 -E_CAL_MBK_SC_CARD_LOCKED: smartcard is locked -0xB9069018 -E_CAL_MBK_SC_PIN_REPETITION: bad pin repetition -0xB9069019 -E_CAL_MBK_SC_NULL_PIN: null pin still active -0xB906902 -E_CAL_MBK_SC_INVALID_PIN: invalid pin -0xB906A -E_CAL_SMC: cs2adm smartcard tools -0xB906A001 -E_CAL_SMC_ALLOC: memory allocation failed -0xB906A002 -E_CAL_SMC_BAD_DEV_NAME: bad device name -0xB906A003 -E_CAL_SMC_TOOMANY: too many open handles -0xB906A004 -E_CAL_SMC_ID_IN_USE: requested smc_id already in use -0xB906A005 -E_CAL_SMC_CHANNEL_NOT_OPEN: channel is not open -0xB906A006 -E_CAL_SMC_DATA_LEN: invalid data length -0xB906A007 -E_CAL_SMC_BUF_SIZE: buffer size too small -0xB906A008 -E_CAL_SMC_LOCKED: smartcard is locked -0xB906A009 -E_CAL_SMC_BAD_RESPONSE: bad response from smartcard -0xB906A00A -E_CAL_SMC_CARD_UNKNOWN: unknown smartcard -0xB906A00B -E_CAL_SMC_FCT_NOT_SUPP: function not supported for given cardtype -0xB906A00C -E_CAL_SMC_EXTD_APDU_N_SUPP: function not supported for given cardtype -0xB906A00D -E_CAL_SMC_PARAMETER: bad parameter given -0xB906A00E -E_CAL_SMC_LOGIN_MISS: login condition for this function not supplied -0xB906A00F -E_CAL_SMC_BAD_KEYSIZE: keylength not suitable for given card -0xB906A010 -E_CAL_SMC_PIN_LEN: invalid PIN length -0xB906A011 -E_CAL_SMC_FILE_NOT_FOUND: PIN file doesn't exist -0xB906A012 -E_CAL_SMC_NULLPIN: Null-PIN is still active -0xB906A01C -E_CAL_SMC_INVALID_PIN: PIN is invalid, no tries left -0xB906A01D -E_CAL_SMC_INVALID_PIN1: PIN is invalid, 1 try left -0xB906A01E -E_CAL_SMC_INVALID_PIN2: PIN is invalid, 2 tries left -0xB906A01F -E_CAL_SMC_INVALID_PIN3: PIN is invalid, 3 or more tries left -0xB906A020 -E_CAL_SMC_RECOVER_BAD_DATA: bad data from backup card -0xB906A021 -E_CAL_SMC_RECOVER_TOO_MANY: more keyhalfs given than existing -0xB906A022 -E_CAL_SMC_COS_BAD_DATA: bad data structure on Siemens CardOS card -0xB906B -E_CAL_NTP: NTP Module Command Interface -0xB906B001 -E_CAL_NTP_INVALID_PARAM: invalid Parameter -0xB906B002 -E_CAL_NTP_WRONG_RSP_LENGTH: wrong response length from CS2 -0xB906B003 -E_CAL_NTP_TIME_CONVERT: unable to convert time -0xB906C001 -E_CAL_CLONE_FILE_EMPTY: there are no database entries in the given file -0xB906F -E_CAL_CLONE: Clone Database Command Interface -0xB906F002 -E_CAL_CLONE_FILE_STRUCTURE: incorrect structure of backup file -0xB906F003 -E_CAL_CLONE_FILE_OPEN: unable to open backup file -0xB906F004 -E_CAL_CLONE_MALLOC: memory allocation failed -0xB906F005 -E_CAL_CLONE_FILE_LEN: incorrect length of backup file -0xB906F006 -E_CAL_CLONE_SEARCH_KEY1: cannot find search_key1 -0xB906F007 -E_CAL_CLONE_SEARCH_KEY2: cannot find search_key2 -0xB906F008 -E_CAL_CLONE_SNIPPET_LEN: invalid length of snippet -0xB908 -E_DSP: LCD Display module -0xB9080001 -E_DSP_DATALEN: string too long -0xB9080002 -E_DSP_MAXDSP: Cannot open another display -0xB9080003 -E_DSP_TIMEOUT: timeout reached -0xB9080004 -E_DSP_MEM: memory allocation failed -0xB9080005 -E_DSP_HDL: display not open -0xB9080006 -E_DSP_CANCEL: dsp_getexp cancelled -0xB9080007 -E_DSP_PARAM: parameter out of range -0xB90A -E_CSLAN: CSLAN -0xB90A01 -E_CSLAN_CTRL: CSLAN Control Module -0xB90A0101 -E_CSLAN_CTRL_BADCMD: wrong parameter -0xB90A0102 -E_CSLAN_CTRL_FAILED: system call failure -0xB90A0103 -E_CSLAN_CTRL_DENIED: wrong permission for file operations -0xB90A0104 -E_CSLAN_CTRL_NO_ROUTE: no relation between port and cs device -0xB90A0105 -E_CSLAN_CTRL_FILE: no such file -0xB90A0106 -E_CSLAN_CTRL_BADSIZE: length mismatch for vchar parameter -0xB90A0107 -E_CSLAN_CTRL_RESET: operation aborted because cs has been reset -0xB90A0108 -E_CSLAN_CTRL_AUTH: authentication failed -0xB90A0109 -E_CSLAN_CTRL_MEM: memory allocation failed -0xB90A010A -E_CSLAN_CTRL_NO_SER: no serial number available -0xB90A010B -E_CSLAN_CTRL_LOCKED: CryptoServer is locked -0xB90A010C -E_CSLAN_CTRL_ALREADY_LOCKED: CryptoServer is already locked -0xB90A010D -E_CSLAN_CTRL_LOCK_DENIED: CryptoServer lock denied (on loadbalancing ports) -0xB90A010E -E_CSLAN_CTRL_NO_SPACE: No space left on device for this operation -0xB90A010F -E_CSLAN_CTRL_TO_MANY_ROUTES: To many routes for the state device(s) -0xB90A0120 -E_CSLAN_CTRL_NO_KSAPI: ksapi compatibility listener not found -0xB90A0121 -E_CSLAN_CTRL_INVALID_SFC: nonexistent subfunction code -0xB90A0201 -E_CSLAN_CTRL_CONFIG: illegal configuration file -0xB90A0301 -E_CSLAN_QUEUE: queue full -0xB90A0302 -E_CSLAN_AVAIL: no cryptoserver online -0xB90A0303 -E_CSLAN_LEN_MISMATCH: mismatch between real packet length and data length -0xB90A0304 -E_CSLAN_NO_CONN: connection table full -0xB90A0305 -E_CSLAN_MAPPING: ksapi compatibility mapping not found -0xB90B -E_CSADM: csadm Tool -0xB90B0001 -E_CSADM_MEM: memory allocation failed -0xB90B0002 -E_CSADM_PWD_NULL: NULL passphrase -0xB90B0003 -E_CSADM_PWD_DIFF: passphrase repetition wrong -0xB90B0004 -E_CSADM_BUF_SIZE: buffer size to small -0xB90B0005 -E_CSADM_CMD_WRONGCALL: command wrongly called -0xB90B0010 -E_CSADM_ARG_CNT: invalid number of arguments -0xB90B0011 -E_CSADM_ARG_FMT: invalid argument format -0xB90B0012 -E_CSADM_ABORT: aborted by user -0xB90B0013 -E_CSADM_ARG_LEN: invalid argument length -0xB90B0014 -E_CSADM_RESP_LEN: invalid response length -0xB90B0015 -E_CSADM_RESP_DATA: invalid response data -0xB90B0020 -E_CSADM_KEY_PART_CNT: invalid number of key parts -0xB90C -E_CSXAPI: CSXAPI -0xB90C0001 -E_CSXAPI_ALLOC: memory allocation failed -0xB90C0002 -E_CSXAPI_DATA_LEN: invalid data length -0xB90C0003 -E_CSXAPI_RESP_LEN: invalid response length -0xB90C0004 -E_CSXAPI_BUF_SIZE: buffer size too small -0xB90C0005 -E_CSXAPI_PARAM: invalid parameter value -0xB90C0006 -E_CSXAPI_MAX_PIN: maximum number of cached pins reached -0xB90C0007 -E_CSXAPI_SESSION_INVALID: invalid session -0xB90C01 -E_CSXAPI_CLUSTER: Cluster API -0xB90C0101 -E_CSXAPI_CLUSTER_OPEN: unable to open any device -0xB90C0102 -E_CSXAPI_CLUSTER_LOGON: unable to logon to any device -0xB90C0103 -E_CSXAPI_CLUSTER_EXEC: unable to execute command on any device -0xB90C0104 -E_CSXAPI_CLUSTER_NAME: unknown device name -0xB90C0105 -E_CSXAPI_CLUSTER_CON_PARAM: invalid connection parameter -0xB90C0106 -E_CSXAPI_CLUSTER_HDL_IN_USE: handle still in use -0xB90C1 -E_CSXAPI_WIN: windows system error -0xB90C2 -E_CSXAPI_UNIX: unix system error -0xB90D -E_ULOG: ulog library -0xB90D0001 -E_ULOG_TMOUT: timeout reading socket -0xB90D1 -E_ULOG_SOCKET: socket failed -0xB90D2 -E_ULOG_BIND: bind failed -0xB90D3 -E_ULOG_SEND: send failed -0xB90D4 -E_ULOG_POLL: poll failed -0xB90D5 -E_ULOG_RECV: recv failed -0xB90E -E_SDB: Simple Database library -0xB90E0001 -E_SDB_NO_MEM: memory allocation failed -0xB90E0002 -E_SDB_NO_DB: database file does not exist -0xB90E0003 -E_SDB_NOT_FOUND: record not found -0xB90E0004 -E_SDB_EXISTS: record already exists -0xB90E0005 -E_SDB_COR_FILE: corrupted database file -0xB90E0006 -E_SDB_BAD_HANDLE: bad database handle -0xB90E0007 -E_SDB_BAD_INFO: bad info structure -0xB90E0008 -E_SDB_LENGTH: bad data length -0xB90E0009 -E_SDB_LOCK: locking failed -0xB90E000A -E_SDB_FILE_NAME: invalid file name -0xB90E1 -E_SDB_SYS_OPEN: open failed -0xB90E2 -E_SDB_SYS_CREAT: creat failed -0xB90E3 -E_SDB_SYS_SEEK: lseek failed -0xB90E4 -E_SDB_SYS_READ: read failed -0xB90E5 -E_SDB_SYS_WRITE: write failed -0xB90E6 -E_SDB_MTX_CREATE: creating mutex failed -0xB90E7 -E_SDB_MTX_LOCK: locking mutex failed -0xB90E8 -E_SDB_FILE_LOCK: locking file failed -0xB90F -E_P11ADM: P11 admin library -0xB90F0001 -E_P11ADM_ALLOC: memory allocation error -0xB90F0002 -E_P11ADM_PARAM: invalid parameter -0xB90F0003 -E_P11ADM_BUF_SIZE: insufficient buffer size -0xB90F0004 -E_P11ADM_KEY_TYPE: invalid key type -0xB90F0005 -E_P11ADM_FILE_OPEN: unable to open / create file -0xB90F0006 -E_P11ADM_MECHANISM: invalid mechanism -0xB90F0007 -E_P11ADM_KEY_LEN: invalid key length -0xB90F1 -E_P11ADM_OSSL: OpenSSL section -0xB90F2 -E_P11ADM_PKCS11: PKCS#11 section -0xB912 -E_HSD: Host Service Daemon -0xB9120001 -E_HSD_MALLOC: memory allocation error -0xB9120002 -E_HSD_WSASTARTUP: error on WSAStartup -0xB9120003 -E_HSD_WSACLEANUP: error on WSACleanup -0xB9120004 -E_HSD_CREATEMUTEX: err creating mutex -0xB9120005 -E_HSD_NO_DEVICES: error creating socket -0xB9120006 -E_HSD_CREATESOCKET: socket creating error -0xB9120007 -E_HSD_TIMEOUT: timeout -0xB9120008 -E_HSD_TERM: connection was terminated -0xB9120009 -E_HSD_INVALID_DATA_LEN: invalid cmds data length -0xB912000A -E_HSD_INVALID_HDR_LEN: invalid cmds header length -0xB912000B -E_HSD_INVALID_ARG: invalid argument -0xB912000C -E_HSD_BINDSOCKET: binding socket failed -0xB912000D -E_HSD_LISTEN: listen failed -0xB912000E -E_HSD_SETSOCKOPT: setsockopt failed -0xB912000F -E_HSD_BAD_CONFIG: bad configuration -0xB9120010 -E_HSD_PROTOCOL: protocol error -0xB9120011 -E_HSD_LOAD_LIBRARY: unable to load auxiliary library -0xB9120012 -E_HSD_MUTEX_CREATE: unable to create mutex -0xB9120013 -E_HSD_MUTEX_LOCK: unable to lock mutex -0xB9120014 -E_HSD_MUTEX_UNLOCK: unable to unlock mutex -0xB9120015 -E_HSD_MUTEX_LOCK_TIMEOUT: timeout while trying to lock mutex -0xB9121 -E_HSD_SELECT: select error -0xB9122 -E_HSD_RECV: receive error -0xB9123 -E_HSD_SEND: send error -0xB9124 -E_HSD_CTRL: control module -0xB9124001 -E_HSD_CTRL_WRONG_SFC: wrong subfunction code -0xB9124002 -E_HSD_CTRL_BADCMD: bad control command -0xB9124003 -E_HSD_CTRL_AUTH: authentication failed -0xB9124004 -E_HSD_CTRL_CS2_BAD_ANSW: bad CryptoServer answer -0xB9125 -E_HSD_INIT: init failed -0xB915 -E_DSPA: dsp_admin3 - DSP Daemon on CSLAN -0xB9150001 -E_DSPA_PARAM: wrong parameter or parameter usage -0xB9150002 -E_DSPA_TIME_CONV: some of the manyfold time conversions failed (w/o userinteraction) -0xB9150003 -E_DSPA_TIME_CONV_USER: some of the manyfold time conversions failed (w/ userinteraction) -0xB9150004 -E_DSPA_BUFFERSIZE: some provided buffer was too small -0xB9150042 -E_DSPA_INTERNAL_PARSE: some data struct could not be parsed internally -0xB91501 -E_DSPA_CS: CryptoServer Administration section -0xB9150101 -E_DSPA_CS_NO_ALARM: No Alarm prevailing -0xB9150102 -E_DSPA_CS_FNA_FIPS: Function not available in FIPS mode -0xB91502 -E_DSPA_LAN: CSLAN Administration section -0xB91503 -E_DSPA_LAN_UPDATE: CSLAN Administration - Update -0xB9150300 -E_DSPA_LAN_UPDATE_BASE: CSLAN Administration - Update - calcbase -0xB9150301 -E_DSPA_LAN_UPDATE_NOTGZ: Extraction of archive failed -0xB9150302 -E_DSPA_LAN_UPDATE_NOLANAR: Not a CSLAN OS archive file. -0xB9150303 -E_DSPA_LAN_UPDATE_NOINDI: Did not find expected indicator in archive. -0xB9150304 -E_DSPA_LAN_UPDATE_NOTARGPAR: Wrong/missing argument -0xB9150305 -E_DSPA_LAN_UPDATE_CANTMOUNT: Can't mount user1/user2 -0xB9150306 -E_DSPA_LAN_UPDATE_CANTTOUCH: Could not touch INIT-COPY-CONFIG ActionFile -0xB9150307 -E_DSPA_LAN_UPDATE_POSTUPSCR: Post update script returned error -0xB915037F -E_DSPA_LAN_UPDATE_SHNOTEXEC: sh could not be executed -0xB91503FF -E_DSPA_LAN_UPDATE_NO_TGZ_O: file was no .tar.gz (old msg) -0xB91504 -E_DSPA_LAN_ACTIONF: CSLAN Administration - ActionFiles -0xB9150400 -E_DSPA_LAN_ACTIONF_BASE: CSLAN Administration - ActionFiles - calcbase -0xB9150401 -E_DSPA_LAN_ACTIONF_COMMAND: Wrong/missing argument -0xB9150402 -E_DSPA_LAN_ACTIONF_ACTIONFLE: Wrong/missing argument -0xB9150403 -E_DSPA_LAN_ACTIONF_PARTITION: Wrong/missing argument -0xB9150404 -E_DSPA_LAN_ACTIONF_PREVAILIN: prevailing actionFile -0xB9150405 -E_DSPA_LAN_ACTIONF_MNTTARGET: can't mount target user1/user2 -0xB915047F -E_DSPA_LAN_ACTIONF_SHNOTEXEC: sh could not be executed -0xB91505 -E_DSPA_LAN_SNMP: CSLAN Administration - SNMP -0xB9150500 -E_DSPA_LAN_SNMP_BASE: CSLAN Administration - SNMP - calcbase -0xB9150501 -E_DSPA_LAN_SNMP_COMMAND: Wrong/missing argument -0xB9150502 -E_DSPA_LAN_SNMP_SYSCSNMPD: Failed to write /etc/sysconfig/snmpd -0xB9150503 -E_DSPA_LAN_SNMP_SYSCTRAPD: Failed to write /etc/sysconfig/trapd -0xB9150504 -E_DSPA_LAN_SNMP_ETCSNMPD: Failed to write /etc/snmp/snmpd.conf -0xB915057F -E_DSPA_LAN_SNMP_SHNOTEXEC: sh could not be executed -0xB91505FF -E_DSPA_LAN_SNMP_FORKFAILED: fork(2) failed -0xB91506 -E_DSPA_LINUXERROR: Error Code from Linux: -0xB916 -E_CTS_API: Host API CTS - Crypto Timestamp -0xB9164001 -E_CTS_API_DEVICE_ENV: Environment variable CRYPTOSERVER not set -0xB9164002 -E_CTS_API_DEVICE_TCP: Environment variable CRYPTOSERVER not configured for TCP -0xB9164003 -E_CTS_API_ARGS: Incorrect function arguments given -0xB9164004 -E_CTS_API_ASN_ENCODE: Error occurred while encoding the timestamp request -0xB9164005 -E_CTS_API_ASN_ENCODE_LEN: Given input buffer is too small to copy encoded data -0xB9164006 -E_CTS_API_RECV: Incorrect data received from TimestampServer -0xB9164007 -E_CTS_API_TS: Error returned from the TimestampServer -0xB9164008 -E_CTS_API_FOPEN: Cannot open file -0xB9164009 -E_CTS_API_PKCS7_INVALID_OBJECT: given data is not pkcs7 encoded -0xB916400A -E_CTS_API_PKCS7_UNSUPPORTED_TYPE: only signed and signedAndEnveloped PKCS7 types supported -0xB916400B -E_CTS_API_PKCS7_MULTIPLE_CERTS: given data contains more than one certificate -0xB916400C -E_CTS_API_PKCS7_NO_CERTS: given data contains no certificate -0xB916400D -E_CTS_API_X509_NO_CERT: given data contains no plain certificate -0xB916400E -E_CTS_API_INVALID_TS_STRUCT: Given TimeStamp structure is not a valid ASN.1 format -0xB916400F -E_CTS_API_HASH_ALGO: Unsupported hash algorithm -0xB9164010 -E_CTS_API_INVALID_HASH: Calculated hash value does not match with the hash value contained in the TimeStamp -0xB9164011 -E_CTS_API_OUT_OVL: given memory buffer too small or invalid length returned from the CSLAN -0xB9164012 -E_CTS_API_MALLOC: can't allocate memory -0xB9164013 -E_CTS_API_PKCS7_RW: Error while reading/writing PKCS7 data -0xB9164014 -E_CTS_API_ASN_NO_TS: Given timestamp contains no timestamp token (maybe error in request?) -0xB9164015 -E_CTS_API_HASH_LENGTH: invalid hash length -0xB9164016 -E_CTS_API_HTTP_BAD_RESP: invalid http response -0xB9164100 -E_CTS_API_TCP_INIT: tcp: init error -0xB9164101 -E_CTS_API_TCP_ADDR: tcp: incorrect IP address -0xB9164102 -E_CTS_API_TCP_HOSTNAME: tcp: incorrect hostname -0xB9164103 -E_CTS_API_TCP_PORT: tcp: incorrect port number -0xB9164104 -E_CTS_API_TCP_TIMEOUT: tcp: connection timeout -0xB9164105 -E_CTS_API_TCP_CLOSED: tcp: connection closed by remote host -0xB91642 -E_CTS_API_TCP_SOCKET: tcp: can't create socket -0xB91643 -E_CTS_API_TCP_CONNECT: tcp: can't get connection -0xB91644 -E_CTS_API_TCP_RECV: tcp: recv error -0xB91645 -E_CTS_API_TCP_SEND: tcp: send error -0xB91646 -E_CTS_API_TCP_SELECT: tcp: select error -0xB9164800 -E_CTS_API_HTTP: HTTP error -0xB9164990 -E_CTS_API_HTTP_BAD_REQUEST: HTTP error 400: Bad Request -0xB9164993 -E_CTS_API_HTTP_FORBIDDEN: HTTP error 403: Forbidden -0xB9164994 -E_CTS_API_HTTP_NOT_FOUND: HTTP error 404: Not Found -0xB9164995 -E_CTS_API_HTTP_METHOD_NOT_ALLOWED: HTTP error 405: Method not allowed -0xB91649F4 -E_CTS_API_HTTP_SERVER_ERROR: HTTP error 500: Server error -0xB91649F7 -E_CTS_API_HTTP_SERVICE_UNAVAIL: HTTP error 503: Service unavailable -0xB917 -E_CSPD: CryptoServer Protocol Daemon -0xB9170001 -E_CSPD_MALLOC: memory allocation error -0xB9170002 -E_CSPD_PARAM: invalid parameter -0xB9170003 -E_CSPD_BAD_CONFIG: bad configuration -0xB9170004 -E_CSPD_NO_DEVICE: can't open any device -0xB9170005 -E_CSPD_TIMEOUT: timeout -0xB9170006 -E_CSPD_TERM: connection was terminated -0xB9170007 -E_CSPD_INVALID_DATA_LEN: invalid command data length -0xB9170008 -E_CSPD_PROTOCOL: protocol error -0xB9170009 -E_CSPD_MAX_CONNECTIONS: maximum number of connections reached -0xB917000A -E_CSPD_FILE_OPEN: can't open file -0xB917000B -E_CSPD_BUF_SIZE: buffer size too small -0xB917001 -E_CSPD_MUTEX: mutex section -0xB9170012 -E_CSPD_MUTEX_CREATE: unable to create mutex -0xB9170013 -E_CSPD_MUTEX_DELETE: timeout while trying to lock mutex -0xB9170014 -E_CSPD_MUTEX_LOCK: unable to lock mutex -0xB9170015 -E_CSPD_MUTEX_LOCK_TIMEOUT: atempt to lock mutex timed out -0xB9170016 -E_CSPD_MUTEX_UNLOCK: unable to unlock mutex -0xB917002 -E_CSPD_CTRL: control module -0xB9170021 -E_CSPD_CTRL_WRONG_SFC: wrong subfunction code -0xB9170022 -E_CSPD_CTRL_BAD_CMD: bad control command -0xB9170023 -E_CSPD_CTRL_AUTH: authentication failed -0xB9170024 -E_CSPD_CTRL_BAD_ANSW: bad CryptoServer answer -0xB9170025 -E_CSPD_CTRL_PARAM: invalid parameter -0xB9171 -E_CSPD_TCP: TCP error -0xB9172 -E_CSPD_SYS: system error -0xB918 -E_PPD: CryptoServer Protocol Daemon -0xB9180001 -E_PPD_MALLOC: memory allocation error -0xB9180002 -E_PPD_PARAM: invalid parameter -0xB9180003 -E_PPD_BAD_CONFIG: bad configuration -0xB9180004 -E_PPD_NO_DEVICE: can't open any device -0xB9180005 -E_PPD_TIMEOUT: timeout -0xB9180006 -E_PPD_TERM: connection was terminated -0xB9180007 -E_PPD_INVALID_DATA_LEN: invalid command data length -0xB9180008 -E_PPD_PROTOCOL: protocol error -0xB9180009 -E_PPD_MAX_CONNECTIONS: maximum number of connections reached -0xB918000A -E_PPD_FILE_OPEN: can't open file -0xB918000B -E_PPD_BUF_SIZE: buffer size too small -0xB918000C -E_PPD_AUTH_FAILED: authentication failed -0xB9180010 -E_PPD_CMD_LEN: invalid command length -0xB9180011 -E_PPD_CMD_FC: invalid function code -0xB9180012 -E_PPD_CMD_SFC: invalid sub-function code -0xB918002 -E_PPD_MUTEX: mutex section -0xB9180022 -E_PPD_MUTEX_CREATE: unable to create mutex -0xB9180023 -E_PPD_MUTEX_DELETE: timeout while trying to lock mutex -0xB9180024 -E_PPD_MUTEX_LOCK: unable to lock mutex -0xB9180025 -E_PPD_MUTEX_LOCK_TIMEOUT: atempt to lock mutex timed out -0xB9180026 -E_PPD_MUTEX_UNLOCK: unable to unlock mutex -0xB9181 -E_PPD_TCP: TCP error -0xB9182 -E_PPD_SYS: system error -0xB91C -E_P11_API: CryptoServer PKCS11 API -0xB91C0000 -E_P11_CMD_SIZE: CryptoServer command size exceeded -0xB91C0001 -E_P11_AUTH_METHOD: Unknown authentication method -0xB91C0002 -E_P11_AUTH_CREDENTIALS: Invalid authentication credentials -0xB91C0003 -E_P11_HASH_ALGO: Unknown hash algorithm -0xB91C0004 -E_P11_ANSW: Malformed answer of CryptoServer -0xB91C0005 -E_P11_LOGIN_STRING_COUNT: Number of login strings < 2 -0xB91C0006 -E_P11_LOGIN_STRING: Login string too long -0xB91C0007 -E_P11_LOGIN_STRING_INVALID: Invalid login string -0xB91C0008 -E_P11_HANDLE_LOST: CryptoServer handle lost -0xB91D -E_PPA: PIN pad API -0xB91D0001 -E_PPA_ALLOC: memory allocation failed -0xB91D0002 -E_PPA_TYPE: invalid PIN pad type -0xB91D0003 -E_PPA_NO_DEVICE: no device found -0xB91D0004 -E_PPA_BAD_DEV_NAME: bad device name -0xB91D0005 -E_PPA_TOOMANY: too may open connections -0xB91D0006 -E_PPA_BAD_HANDLE: bad handle -0xB91D0007 -E_PPA_PARAM: invalid parameter -0xB91D0008 -E_PPA_NOT_SUPPORTED: requested feature is not supported -0xB91D0009 -E_PPA_NOT_OPEN: connection is not open -0xB91D000A -E_PPA_TIMEOUT: timeout occurred -0xB91D000B -E_PPA_ABORT: action canceled -0xB91D000C -E_PPA_DATA_LEN: invalid data length -0xB91D000D -E_PPA_PIN_REPETITION: bad PIN repetition -0xB91D000E -E_PPA_BUF_SIZE: invalid buffer size -0xB91D000F -E_PPA_PROTOCOL: protocol error -0xB91D0010 -E_PPA_ICC_STATE: bad ICC state -0xB91D0011 -E_PPA_ICC_DATA_LEN: bad data length returned from ICC -0xB91D0012 -E_PPA_ICC_BAD_RESPONSE: bad response recieved from ICC -0xB91D0013 -E_PPA_ICC_NO_CARD: no smartcard inserted -0xB91D0020 -E_PPA_USB_DRIVER: USB driver is not running -0xB91D0021 -E_PPA_USB_OPEN: USB open failed -0xB91D0022 -E_PPA_USB_WRITE: USB write failed -0xB91D0023 -E_PPA_USB_READ: USB read failed -0xB91D0024 -E_PPA_USB_NOT_AVAIL: USB is not available -0xB91D0030 -E_PPA_BAD_INPUT: bad input -0xB91D0031 -E_PPA_ACCESS_DENIED: access denied -0xB91D0032 -E_PPA_CONNECT: no reader connected -0xB91D0041 -E_PPA_JCOP_TIMEOUT: JCOP simulator send/receive timeout -0xB91D0044 -E_PPA_JCOP_OTHER: JCOP simulator unknown error -0xB91D1 -E_PPA_PCSC: PC/SC -0xB91D2 -E_PPA_MKT: MKT -0xB91D3 -E_PPA_CP8: CP8 -0xB91D4 -E_PPA_ACR80: ACR80 -0xB91D5 -E_PPA_LIBUSB: USB -0xB91D6 -E_PPA_CCID: CCID -0xB91D7 -E_PPA_CYBERJACK: cyberJack -0xB91D8 -E_PPA_JCOP: JCOP -0xB91E -E_COPA: copa Config Parser -0xB91E0000 -E_COPA_FILE: Cant open/access configuration file -0xB91E0100 -E_COPA_LINE_TO_LONG: line from input file to long -0xB91E0101 -E_COPA_NO_MATCHING_BRACKET: No matching ] found -0xB91E0102 -E_COPA_NO_EQUAL_FOUND: No = after variable found -0xB91E0103 -E_COPA_NO_VALUE_FOR_VAL_FOUND: No value for variable after = found -0xB91E0104 -E_COPA_NO_MATCHING_QUOTE: No Matching \" or' found -0xB91E0105 -E_COPA_INVALID_HEXNUMBER: No valid Hex Number after $ -0xB91E0106 -E_COPA_NO_TWO_BYTE_HEXNUMBER: not all hex codes are two byte -0xB91E0107 -E_COPA_NO_VALUES_IN_LIST: No Value in List found -0xB91E0108 -E_COPA_SECOND_CHAR_NO_HEX: second char after $ is no valid hex value -0xB91E0109 -E_COPA_LIST_NOT_IN_FILE: One of the list elements it not in the config file -0xB91E0110 -E_COPA_FILE_NOT_IN_LIST: One of the config file elements it not in the list -0xB91E0111 -E_COPA_VALUE_NOT_BOOL: Value is not a Boolean value -0xB91E0112 -E_COPA_INVALID_INTEGER: Value is not an Integer number -0xB91E0113 -E_COPA_NON_PRINTABLE_CHAR: Char in String is non printable -0xB91E0114 -E_COPA_LONG_DOESNT_FIT_IN_INT: strol returns long, the result does not fit in int -0xB91E0115 -E_COPA_OUT_OF_RANGE: strol returns variable is out of range -0xB920 -E_CXI_API: CryptoServer Core API Cxi -0xB9200001 -E_CXI_API_ALLOC: memory allocation failed -0xB9200002 -E_CXI_API_PARAM: invalid parameter -0xB9200003 -E_CXI_API_PARAM_LEN: invalid parameter length -0xB9200004 -E_CXI_API_PARAM_RANGE: parameter out of range -0xB9200005 -E_CXI_API_BUF_SIZE: buffer size too small -0xB9200006 -E_CXI_API_ANSW_LEN: invalid answer length -0xB9200007 -E_CXI_API_ANSW_DATA: invalid format of answer data -0xB9200008 -E_CXI_API_STRING_TERM: unterminated string -0xB9200009 -E_CXI_API_STRING_CONV: string conversion failed -0xB920000A -E_CXI_API_NOT_FOUND: object/item not found -0xB920000B -E_CXI_API_COMPARE: compare failed -0xB920000C -E_CXI_API_ALGO: invalid algorithm -0xB920000D -E_CXI_API_STATE: invalid state -0xB920000E -E_CXI_API_FILE: file error -0xB920000F -E_CXI_API_USER_NOT_FOUND: user does not exist -0xB9200010 -E_CXI_API_NOT_SUPPORTED: operation not supported -0xB9200011 -E_CXI_API_INVALID_KEY: invalid key -0xB9200012 -E_CXI_API_IO: I/O error -0xB9200013 -E_CXI_API_LOG: log access error -0xB9200014 -E_CXI_API_DB: database access error -0xB9200015 -E_CXI_API_ASN1_FORMAT: invalid ASN.1 format -0xB9200016 -E_CXI_API_MEM_CORR: memory corruption -0xB9200017 -E_CXI_API_MECHS_LENGTH: invalid number of mechs -0xB9201 -E_CXI_API_SYSTEM: system error -0xB921 -E_OSTESTTOOL: OS test tool -0xB9210001 -E_OSTESTTOOL_MALLOC: memory allocation failed -0xB9210002 -E_OSTESTTOOL_INVALID_PARAM: invalid parameter -0xB9210003 -E_OSTESTTOOL_ANSW_LEN: invalid length of answer data -0xB9210004 -E_OSTESTTOOL_ERROR_EXPECTED: actual error doesn't match expected error -0xB9210005 -E_OSTESTTOOL_DATA_COMPARE: data compare error -0xB9210006 -E_OSTESTTOOL_FILE: file error -0xB9210007 -E_OSTESTTOOL_RANGE: value exceeds expected range -0xB980 -E_JCSA: java CryptoServer API -0xB9800001 -E_JCSA_TERM: Connection terminated by remote host -0xB9800002 -E_JCSA_BLK_LEN: Bad block length received -0xB9800003 -E_JCSA_BAD_ANSW: Bad answer length -0xB9800004 -E_JCSA_BAD_TAG: Bad tag of answer block -0xB9800005 -E_JCSA_AUTH_MAX: Too many authentications -0xB9800006 -E_JCSA_PWD_LEN: Bad length of password -0xB9800007 -E_JCSA_TRANS_NAME: Can't translate user name -0xB9800008 -E_JCSA_JCE_ALGO: Hash algo not available -0xB9800009 -E_JCSA_GET_CH: Could not get challenge -0xB980000A -E_JCSA_JCE_PROV: JCE Provider not found -0xB980000B -E_JCSA_JCE_KEY: JCE Key Exception (Jurisdiction files installed?) -0xB980000C -E_JCSA_JCE_EXC: JCE Exception -0xB980000D -E_JCSA_SM_FAIL: Secure Messaging failed -0xB980000E -E_JCSA_SM_MODE: Unknown SM mode -0xB980000F -E_JCSA_SK_DEC: Bad session key decryption -0xB9800010 -E_JCSA_JNI_ERR: JNI Interface Error -0xB9800011 -E_JCSA_BAD_PARA: Bad parameter -0xB9800012 -E_JCSA_NO_AUTH: Missung authentication -0xB9800013 -E_JCSA_CHARSET: Unsupported encoding -0xB9800014 -E_JCSA_DATALEN: Invalid data length -0xB9800015 -E_JCSA_KEY_DECRYPT: Can't decrypt key file -0xB9800016 -E_JCSA_IO: I/O Error -0xB9800017 -E_JCSA_NO_DEV: No device specified -0xB9800018 -E_JCSA_AUTH_MECH: Invalid authentication mechanism -0xB980002 -E_JCSA_CLUSTER: CryptoServer Cluster API -0xB9800021 -E_JCSA_CLUSTER_OPEN: Unable to open any CryptoServer -0xB9800022 -E_JCSA_CLUSTER_LOGON: Unable to logon to any CryptoServer -0xB9800023 -E_JCSA_CLUSTER_EXEC: Unable to execute command on any CryptoServer -0xB98001 -E_JCSA_KEY: RSA Key class -0xB9800101 -E_JCSA_KEY_BAD_FILE: Malformed RSA Key file -0xB9800102 -E_JCSA_KEY_DEC: Decryption failed -0xB98002 -E_JCSA_SMC: CryptoServer Smartcard API -0xB9800200 -E_JCSA_SMC_STATUS: Smartcard returned error status -0xB9800201 -E_JCSA_SMC_PADDING: bad padding -0xB9800202 -E_JCSA_SMC_SPEC: invalid specifier -0xB98003 -E_JCSA_DB: CryptoServer Database API -0xB9800300 -E_JCSA_DB_JNI_ERR: JNI Interface Error -0xB981 -E_JCXI: Java CryptoServer API CXI -0xB9810000 -E_JCXI_PARAM: invalid parameter -0xB9810001 -E_JCXI_BAD_NAME: bad key name -0xB9810002 -E_JCXI_NAME_REQ: key name required for internal storage -0xB9810003 -E_JCXI_CHARSET: internal charset converting error -0xB9810004 -E_JCXI_BAD_KTOK: bad key token -0xB9810005 -E_JCXI_BAD_ANSW: malformed answer block of CryptoServer -0xB9810006 -E_JCXI_KEY_ATTR: bad key attributes from CryptoServer -0xB9810007 -E_JCXI_BAD_ALGO: bad algorithm -0xB9810008 -E_JCXI_USER_NAME: bad user name -0xB9810009 -E_JCXI_NO_DEVICE: missing device entry -0xB981000A -E_JCXI_NO_KEY_COMP: key component not found -0xB981000B -E_JCXI_NO_KEY: key not found -0xB981000C -E_JCXI_CSA_VERSION: version of CryptoServerAPI too small -0xB981000D -E_JCXI_NO_EC_PARAM: no EC parameter data available -0xB981000E -E_JCXI_NO_IV_OUT: no output IV available -0xB981000F -E_JCXI_FW_VER: firmware version too small -0xB9810010 -E_JCXI_ASN1_DECODE: ASN.1 decoding error -0xB9810011 -E_JCXI_AES_DECRYPT: JCE AES decrypt error -0xB9810020 -E_JCXI_ECC_PARAM: bad ECC parameter -0xB9810030 -E_JCXI_CONFIG: config item missing -0xB9810040 -E_JCXI_DATA_LENGTH: invalid data length -0xB9810050 -E_JCXI_MECHS_LENGTH: invalid number of mechs -0xB982 -E_JSDB: Database API Java -0xB9820000 -E_JSDB_JNI_ERR: JNI Interface Error -0xB983 -E_JPPA: PinPad API Java -0xB9830000 -E_JPPA_JNI_ERR: JNI Interface Error -0xB9830001 -E_JPPA_SPEC: invalid specifier -0xB984 -E_JCE: JCA/JCE provider -0xB9840002 -E_JCE_MISSING_KEYSTOREPATH: KeyStorePath -0xB985 -E_CSAN: CryptoServerAPI.NET -0xB9850001 -E_CSAN_PARAM: Invalid parameter -0xB9850002 -E_CSAN_AUTH_MECH: Invalid authentication mechanism -0xB985002 -E_CSAN_CLUSTER: CryptoServer Cluster API -0xB9850021 -E_CSAN_CLUSTER_OPEN: Unable to open any CryptoServer -0xB9850022 -E_CSAN_CLUSTER_LOGON: Unable to logon to any CryptoServer -0xB9850023 -E_CSAN_CLUSTER_EXEC: Unable to execute command on any CryptoServer -0xB986 -E_CXIN: CryptoServer API CXI.NET -0xB9860000 -E_CXIN_PARAM: invalid parameter -0xB9860001 -E_CXIN_MALLOC: memory allocation failed -0xB9860002 -E_CXIN_STATE: invalid state -0xB9860005 -E_CXIN_BAD_ANSW: malformed answer block of CryptoServer -0xB986000B -E_CXIN_NO_KEY: key not found -0xB986000E -E_CXIN_NO_IV_OUT: no output IV available -0xB9860030 -E_CXIN_CONFIG: config item missing diff --git a/network-management/src/main/resources/log4j2.xml b/network-management/src/main/resources/log4j2.xml deleted file mode 100644 index becdc35200..0000000000 --- a/network-management/src/main/resources/log4j2.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - logs - node-${hostName} - ${sys:log-path}/archive - error - info - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/network-management/src/main/resources/migration/README.md b/network-management/src/main/resources/migration/README.md deleted file mode 100644 index 255c13c59a..0000000000 --- a/network-management/src/main/resources/migration/README.md +++ /dev/null @@ -1,17 +0,0 @@ -#How to generate change log xml from database - -* Download liquidBase binary from[here](http://download.liquibase.org) -* Download H2 driver from[here](http://www.h2database.com/html/download.html) -* Generate a H2 database by starting the network map server (can be done using one of the integration test). - -Run the following command to generate change log XML. -``` -java -jar liquibase.jar --driver=org.h2.Driver \ ---classpath=h2-1.4.196.jar \ ---changeLogFile=network-manager.changelog.xml \ ---url="jdbc:h2:file:./networkMap" \ ---username=sa \ ---password= \ -generateChangeLog -``` -TODO : This instruction is only for initial changelog generation, remove this after R3C v3. \ No newline at end of file diff --git a/network-management/src/main/resources/migration/network-manager.changelog-init.xml b/network-management/src/main/resources/migration/network-manager.changelog-init.xml deleted file mode 100644 index 6e435bb819..0000000000 --- a/network-management/src/main/resources/migration/network-manager.changelog-init.xml +++ /dev/null @@ -1,352 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/network-management/src/main/resources/migration/network-manager.changelog-master.xml b/network-management/src/main/resources/migration/network-manager.changelog-master.xml deleted file mode 100644 index f1b23a1e6f..0000000000 --- a/network-management/src/main/resources/migration/network-manager.changelog-master.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - diff --git a/network-management/src/main/resources/migration/network-manager.changelog-network-map-table-change.xml b/network-management/src/main/resources/migration/network-manager.changelog-network-map-table-change.xml deleted file mode 100644 index 293679aa31..0000000000 --- a/network-management/src/main/resources/migration/network-manager.changelog-network-map-table-change.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/CertificateRevocationListNodeTests.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/CertificateRevocationListNodeTests.kt deleted file mode 100644 index 7ab2ae6b94..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/CertificateRevocationListNodeTests.kt +++ /dev/null @@ -1,107 +0,0 @@ -package com.r3.corda.networkmanage - -import net.corda.core.toFuture -import net.corda.core.utilities.NetworkHostAndPort -import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.P2P_PREFIX -import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.PEER_USER -import net.corda.nodeapi.internal.crypto.X509KeyStore -import net.corda.nodeapi.internal.protonwrapper.messages.MessageStatus -import net.corda.nodeapi.internal.protonwrapper.netty.AMQPClient -import net.corda.nodeapi.internal.protonwrapper.netty.AMQPServer -import net.corda.testing.core.* -import org.bouncycastle.jce.provider.BouncyCastleProvider -import org.junit.Before -import org.junit.Ignore -import org.junit.Rule -import org.junit.Test -import org.junit.rules.TemporaryFolder -import java.nio.file.Path -import java.nio.file.Paths -import java.security.Security -import kotlin.test.assertEquals - -/** - * This test is to perform manual testing of the SSL connection using local key stores. It aims to assess the - * correct behaviour of the SSL connection between 2 nodes with respect to the CRL validation. - * In order to debug the certificate path validation please use the following JVM parameters when running the test: - * -Djavax.net.debug=ssl,handshake -Djava.security.debug=certpath - */ -@Ignore -class CertificateRevocationListNodeTests { - @Rule - @JvmField - val temporaryFolder = TemporaryFolder() - - private val serverPort = freePort() - - private val serverSslKeyStore: Path = Paths.get("/certificatesServer/sslkeystore.jks") - private val clientSslKeyStore: Path = Paths.get("/certificatesClient/sslkeystore.jks") - private val serverTrustStore: Path = Paths.get("/certificatesServer/truststore.jks") - private val clientTrustStore: Path = Paths.get("/certificatesClient/truststore.jks") - - @Before - fun setUp() { - Security.addProvider(BouncyCastleProvider()) - } - - @Test - fun `Simple AMPQ Client to Server connection works`() { - val amqpServer = createServer(serverPort) - amqpServer.use { - amqpServer.start() - val receiveSubs = amqpServer.onReceive.subscribe { - assertEquals(BOB_NAME.toString(), it.sourceLegalName) - assertEquals(P2P_PREFIX + "Test", it.topic) - assertEquals("Test", String(it.payload)) - it.complete(true) - } - val amqpClient = createClient(serverPort) - amqpClient.use { - val serverConnected = amqpServer.onConnection.toFuture() - val clientConnected = amqpClient.onConnection.toFuture() - amqpClient.start() - val serverConnect = serverConnected.get() - assertEquals(true, serverConnect.connected) - val clientConnect = clientConnected.get() - assertEquals(true, clientConnect.connected) - val msg = amqpClient.createMessage("Test".toByteArray(), - P2P_PREFIX + "Test", - ALICE_NAME.toString(), - emptyMap()) - amqpClient.write(msg) - assertEquals(MessageStatus.Acknowledged, msg.onComplete.get()) - receiveSubs.unsubscribe() - } - } - } - - private fun createClient(targetPort: Int): AMQPClient { - val tS = X509KeyStore.fromFile(clientTrustStore, "trustpass").internal - val sslS = X509KeyStore.fromFile(clientSslKeyStore, "cordacadevpass").internal - return AMQPClient( - listOf(NetworkHostAndPort("localhost", targetPort)), - setOf(ALICE_NAME, CHARLIE_NAME), - PEER_USER, - PEER_USER, - sslS, - "cordacadevpass", - tS, - false, - MAX_MESSAGE_SIZE) - } - - private fun createServer(port: Int): AMQPServer { - val tS = X509KeyStore.fromFile(serverTrustStore, "trustpass").internal - val sslS = X509KeyStore.fromFile(serverSslKeyStore, "cordacadevpass").internal - return AMQPServer( - "0.0.0.0", - port, - PEER_USER, - PEER_USER, - sslS, - "cordacadevpass", - tS, - false, - MAX_MESSAGE_SIZE) - } -} diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/TestBase.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/TestBase.kt deleted file mode 100644 index 9b96affffd..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/TestBase.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage - -import com.nhaarman.mockito_kotlin.mock -import com.r3.corda.networkmanage.common.persistence.* -import net.corda.core.crypto.SecureHash -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.CertRole -import net.corda.nodeapi.internal.crypto.X509Utilities -import net.corda.nodeapi.internal.crypto.x509Certificates -import net.corda.testing.core.ALICE_NAME -import net.corda.testing.core.SerializationEnvironmentRule -import net.corda.testing.internal.createDevNodeCaCertPath -import org.bouncycastle.pkcs.PKCS10CertificationRequest -import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest -import org.junit.Rule -import java.security.KeyPair -import java.security.cert.CertPath -import java.security.cert.X509Certificate -import javax.security.auth.x500.X500Principal - -abstract class TestBase { - @Rule - @JvmField - val testSerialization = SerializationEnvironmentRule() - - protected fun certificateSigningRequest( - requestId: String = SecureHash.randomSHA256().toString(), - status: RequestStatus = RequestStatus.NEW, - legalName: CordaX500Name = ALICE_NAME, - publicKeyHash: SecureHash = SecureHash.randomSHA256(), - remark: String = "Test remark", - request: PKCS10CertificationRequest = mock(), - certData: CertificateData = mock(), - modifiedBy: String = "Test" - ): CertificateSigningRequest { - return CertificateSigningRequest( - requestId = requestId, - status = status, - legalName = legalName, - publicKeyHash = publicKeyHash, - remark = remark, - certData = certData, - request = request, - modifiedBy = modifiedBy - ) - } - - protected fun certificateData(certStatus: CertificateStatus = CertificateStatus.VALID, - certPath: CertPath = mock()): CertificateData { - return CertificateData( - certStatus = certStatus, - certPath = certPath - ) - } - - private fun generateSignedCertPath(csr: PKCS10CertificationRequest, keyPair: KeyPair): CertPath { - return JcaPKCS10CertificationRequest(csr).run { - val (rootCa, intermediateCa, nodeCa) = createDevNodeCaCertPath(CordaX500Name.build(X500Principal(subject.encoded)), keyPair) - X509Utilities.buildCertPath(nodeCa.certificate, intermediateCa.certificate, rootCa.certificate) - } - } - - protected fun createNodeCertificate(csrStorage: CertificateSigningRequestStorage, legalName: String = "LegalName"): X509Certificate { - val (csr, nodeKeyPair) = createRequest(legalName, certRole = CertRole.NODE_CA) - // Add request to DB. - val requestId = csrStorage.saveRequest(csr) - csrStorage.markRequestTicketCreated(requestId) - csrStorage.approveRequest(requestId, "Approver") - val certPath = generateSignedCertPath(csr, nodeKeyPair) - csrStorage.putCertificatePath( - requestId, - certPath, - CertificateSigningRequestStorage.DOORMAN_SIGNATURE - ) - return certPath.x509Certificates.first() - } - -} \ No newline at end of file diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/TestUtils.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/TestUtils.kt deleted file mode 100644 index 59386c26d6..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/TestUtils.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.r3.corda.networkmanage - -import com.r3.corda.networkmanage.common.persistence.NetworkMaps -import com.r3.corda.networkmanage.common.persistence.entity.NetworkMapEntity -import com.r3.corda.networkmanage.common.persistence.entity.NetworkParametersEntity -import com.r3.corda.networkmanage.doorman.NetworkParametersCmd -import com.r3.corda.networkmanage.doorman.ParametersUpdateConfig -import net.corda.core.crypto.SecureHash -import net.corda.core.node.NetworkParameters -import net.corda.core.serialization.serialize -import net.corda.nodeapi.internal.createDevNetworkMapCa -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import net.corda.nodeapi.internal.network.NetworkMap -import net.corda.nodeapi.internal.network.ParametersUpdate -import net.corda.testing.common.internal.testNetworkParameters -import java.time.Instant - -fun createNetworkParametersEntity(signingCertAndKeyPair: CertificateAndKeyPair = createDevNetworkMapCa(), - networkParameters: NetworkParameters = testNetworkParameters()): NetworkParametersEntity { - val signedNetParams = signingCertAndKeyPair.sign(networkParameters) - return NetworkParametersEntity( - hash = signedNetParams.raw.hash.toString(), - networkParameters = networkParameters, - signature = signedNetParams.sig.bytes, - certificate = signedNetParams.sig.by - ) -} - -fun createNetworkParametersEntityUnsigned(networkParameters: NetworkParameters = testNetworkParameters()): NetworkParametersEntity { - return NetworkParametersEntity( - hash = networkParameters.serialize().hash.toString(), - networkParameters = networkParameters, - signature = null, - certificate = null - ) -} - -fun createNetworkMaps(signingCertAndKeyPair: CertificateAndKeyPair = createDevNetworkMapCa(), - netParamsEntity: NetworkParametersEntity, - nodeInfoHashes: List = emptyList(), - privateNodeInfoHashes: Map> = emptyMap(), - parametersUpdate: ParametersUpdate? = null, - timestamp: Instant = Instant.now()): NetworkMaps { - val publicMapEntity = createNetworkMapEntity("PUBLIC_NETWORK", nodeInfoHashes, netParamsEntity, parametersUpdate, signingCertAndKeyPair, timestamp) - val privateNetworkMaps = privateNodeInfoHashes.mapValues { - createNetworkMapEntity(it.key, it.value, netParamsEntity, parametersUpdate, signingCertAndKeyPair, timestamp) - } - return NetworkMaps(publicMapEntity, privateNetworkMaps) -} - -private fun createNetworkMapEntity(id: String, - nodeInfoHashes: List, - netParamsEntity: NetworkParametersEntity, - parametersUpdate: ParametersUpdate?, - signingCertAndKeyPair: CertificateAndKeyPair, - timestamp: Instant): NetworkMapEntity { - val networkMap = NetworkMap(nodeInfoHashes, SecureHash.parse(netParamsEntity.hash), parametersUpdate) - val signedNetworkMap = signingCertAndKeyPair.sign(networkMap) - return NetworkMapEntity( - id = id, - networkMap = networkMap, - signature = signedNetworkMap.sig.bytes, - certificate = signedNetworkMap.sig.by, - networkParameters = netParamsEntity, - timestamp = timestamp) -} - -fun createNetworkMaps(signingCertAndKeyPair: CertificateAndKeyPair = createDevNetworkMapCa(), - networkParameters: NetworkParameters = testNetworkParameters(), - nodeInfoHashes: List = emptyList(), - privateNodeInfoHashes: Map> = emptyMap(), - timestamp: Instant = Instant.now()): NetworkMaps { - val netParamsEntity = createNetworkParametersEntity(signingCertAndKeyPair, networkParameters) - return createNetworkMaps(signingCertAndKeyPair, netParamsEntity, nodeInfoHashes, privateNodeInfoHashes, timestamp = timestamp) -} - -fun NetworkParameters.toCmd(parametersUpdate: ParametersUpdateConfig? = null): NetworkParametersCmd.Set { - return NetworkParametersCmd.Set( - minimumPlatformVersion = minimumPlatformVersion, - notaries = notaries, - maxMessageSize = maxMessageSize, - maxTransactionSize = maxTransactionSize, - parametersUpdate = parametersUpdate, - eventHorizonDays = eventHorizon.toDays().toInt() - ) -} diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRevocationListStorageTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRevocationListStorageTest.kt deleted file mode 100644 index 7b8bf81b87..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRevocationListStorageTest.kt +++ /dev/null @@ -1,134 +0,0 @@ -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.TestBase -import net.corda.core.utilities.minutes -import net.corda.nodeapi.internal.network.CertificateRevocationRequest -import net.corda.nodeapi.internal.persistence.CordaPersistence -import net.corda.nodeapi.internal.persistence.DatabaseConfig -import net.corda.testing.internal.DEV_INTERMEDIATE_CA -import net.corda.testing.node.MockServices -import org.bouncycastle.asn1.x509.* -import org.bouncycastle.cert.jcajce.JcaX509CRLConverter -import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils -import org.bouncycastle.cert.jcajce.JcaX509v2CRLBuilder -import org.bouncycastle.jce.provider.BouncyCastleProvider -import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder -import org.junit.After -import org.junit.Before -import org.junit.Test -import java.math.BigInteger -import java.security.cert.CRLReason -import java.security.cert.X509CRL -import java.time.Instant -import java.util.* -import kotlin.test.assertEquals -import kotlin.test.assertNotNull - -class PersistentCertificateRevocationListStorageTest : TestBase() { - private lateinit var crrStorage: PersistentCertificateRevocationRequestStorage - private lateinit var csrStorage: PersistentCertificateSigningRequestStorage - private lateinit var crlStorage: PersistentCertificateRevocationListStorage - private lateinit var persistence: CordaPersistence - - companion object { - const val REPORTER = "TestReporter" - const val SIGNATURE_ALGORITHM = "SHA256withECDSA" - val REVOCATION_REASON = CRLReason.KEY_COMPROMISE - } - - @Before - fun startDb() { - persistence = configureDatabase(MockServices.makeTestDataSourceProperties(), DatabaseConfig(runMigration = true)) - crrStorage = PersistentCertificateRevocationRequestStorage(persistence) - csrStorage = PersistentCertificateSigningRequestStorage(persistence) - crlStorage = PersistentCertificateRevocationListStorage(persistence) - } - - @After - fun closeDb() { - persistence.close() - } - - @Test - fun `Saving CRL persists it in the DB and changes the status of the certificate revocation requests to DONE`() { - // given - val certificate = createNodeCertificate(csrStorage) - val requestId = crrStorage.saveRevocationRequest(CertificateRevocationRequest( - certificateSerialNumber = certificate.serialNumber, - reason = REVOCATION_REASON, - reporter = REPORTER)) - crrStorage.markRequestTicketCreated(requestId) - crrStorage.approveRevocationRequest(requestId, "Approver") - val revocationRequest = crrStorage.getRevocationRequest(requestId)!! - val crl = createDummyCertificateRevocationList(listOf(revocationRequest.certificateSerialNumber)) - - // when - crlStorage.saveCertificateRevocationList(crl, CrlIssuer.DOORMAN, "TestSigner", Instant.now()) - - // then - assertNotNull(crlStorage.getCertificateRevocationList(CrlIssuer.DOORMAN)).apply { - assertEquals(crl, this) - } - assertNotNull(crrStorage.getRevocationRequest(requestId)).apply { - assertEquals(RequestStatus.DONE, status) - } - } - - @Test - fun `Saving CRL does not change the status of other requests`() { - // given - val done = crrStorage.saveRevocationRequest(CertificateRevocationRequest( - certificateSerialNumber = createNodeCertificate(csrStorage, legalName = "Bank A").serialNumber, - reason = REVOCATION_REASON, - reporter = REPORTER)) - crrStorage.markRequestTicketCreated(done) - crrStorage.approveRevocationRequest(done, "Approver") - val doneRevocationRequest = crrStorage.getRevocationRequest(done)!! - - val new = crrStorage.saveRevocationRequest(CertificateRevocationRequest( - certificateSerialNumber = createNodeCertificate(csrStorage, legalName = "Bank B").serialNumber, - reason = REVOCATION_REASON, - reporter = REPORTER)) - - val crl = createDummyCertificateRevocationList(listOf(doneRevocationRequest.certificateSerialNumber)) - crlStorage.saveCertificateRevocationList(crl, CrlIssuer.DOORMAN, "TestSigner", Instant.now()) - - val approved = crrStorage.saveRevocationRequest(CertificateRevocationRequest( - certificateSerialNumber = createNodeCertificate(csrStorage, legalName = "Bank C").serialNumber, - reason = REVOCATION_REASON, - reporter = REPORTER)) - crrStorage.markRequestTicketCreated(approved) - crrStorage.approveRevocationRequest(approved, "Approver") - val approvedRevocationRequest = crrStorage.getRevocationRequest(approved)!! - - val newCrl = createDummyCertificateRevocationList(listOf(doneRevocationRequest.certificateSerialNumber, approvedRevocationRequest.certificateSerialNumber)) - // when - crlStorage.saveCertificateRevocationList(newCrl, CrlIssuer.DOORMAN, "TestSigner", Instant.now()) - - // then - assertNotNull(crrStorage.getRevocationRequest(done)).apply { - assertEquals(RequestStatus.DONE, status) - } - assertNotNull(crrStorage.getRevocationRequest(new)).apply { - assertEquals(RequestStatus.NEW, status) - } - } - - private fun createDummyCertificateRevocationList(serialNumbers: List = emptyList()): X509CRL { - val (doormanCert, doormanKeys) = DEV_INTERMEDIATE_CA - val builder = JcaX509v2CRLBuilder(doormanCert.subjectX500Principal, Date()) - val extensionUtils = JcaX509ExtensionUtils() - builder.addExtension(Extension.authorityKeyIdentifier, false, extensionUtils.createAuthorityKeyIdentifier(doormanCert)) - val issuingDistPointName = GeneralName( - GeneralName.uniformResourceIdentifier, "http://dummy.com") - // This is required and needs to match the certificate settings with respect to being indirect - val issuingDistPoint = IssuingDistributionPoint(DistributionPointName(GeneralNames(issuingDistPointName)), false, false) - builder.addExtension(Extension.issuingDistributionPoint, true, issuingDistPoint) - builder.setNextUpdate(Date(System.currentTimeMillis() + 10.minutes.toMillis())) - serialNumbers.forEach { - builder.addCRLEntry(it, Date(System.currentTimeMillis() - 10.minutes.toMillis()), ReasonFlags.certificateHold) - } - val signer = JcaContentSignerBuilder(SIGNATURE_ALGORITHM).setProvider(BouncyCastleProvider.PROVIDER_NAME).build(doormanKeys.private) - return JcaX509CRLConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME).getCRL(builder.build(signer)) - } -} \ No newline at end of file diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRevocationRequestStorageTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRevocationRequestStorageTest.kt deleted file mode 100644 index 024799930e..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRevocationRequestStorageTest.kt +++ /dev/null @@ -1,150 +0,0 @@ -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.TestBase -import net.corda.nodeapi.internal.network.CertificateRevocationRequest -import net.corda.nodeapi.internal.persistence.CordaPersistence -import net.corda.nodeapi.internal.persistence.DatabaseConfig -import net.corda.testing.node.MockServices -import org.junit.After -import org.junit.Before -import org.junit.Test -import java.math.BigInteger -import java.security.cert.CRLReason -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith -import kotlin.test.assertNotNull - -class PersistentCertificateRevocationRequestStorageTest : TestBase() { - private lateinit var crrStorage: PersistentCertificateRevocationRequestStorage - private lateinit var csrStorage: PersistentCertificateSigningRequestStorage - private lateinit var persistence: CordaPersistence - - companion object { - const val REPORTER = "TestReporter" - val REVOCATION_REASON = CRLReason.KEY_COMPROMISE - } - - @Before - fun startDb() { - persistence = configureDatabase(MockServices.makeTestDataSourceProperties(), DatabaseConfig(runMigration = true)) - crrStorage = PersistentCertificateRevocationRequestStorage(persistence) - csrStorage = PersistentCertificateSigningRequestStorage(persistence) - } - - @After - fun closeDb() { - persistence.close() - } - - @Test - fun `Certificate revocation request is persisted correctly`() { - // given - val certificate = createNodeCertificate(csrStorage) - - // when - val requestId = crrStorage.saveRevocationRequest(CertificateRevocationRequest( - certificateSerialNumber = certificate.serialNumber, - reason = REVOCATION_REASON, - reporter = REPORTER)) - - // then - assertNotNull(crrStorage.getRevocationRequest(requestId)).apply { - assertEquals(certificate.serialNumber, certificateSerialNumber) - assertEquals(REVOCATION_REASON, reason) - assertEquals(REPORTER, reporter) - } - } - - @Test - fun `Retrieving a certificate revocation request succeeds`() { - // given - val certificate = createNodeCertificate(csrStorage) - val requestId = crrStorage.saveRevocationRequest(CertificateRevocationRequest( - certificateSerialNumber = certificate.serialNumber, - reason = REVOCATION_REASON, - reporter = REPORTER)) - - // when - val request = crrStorage.getRevocationRequest(requestId) - - // then - assertNotNull(request) - } - - @Test - fun `Retrieving a certificate revocation requests by status returns correct data`() { - // given - (1..10).forEach { - crrStorage.saveRevocationRequest(CertificateRevocationRequest( - certificateSerialNumber = createNodeCertificate(csrStorage, "LegalName" + it.toString()).serialNumber, - reason = REVOCATION_REASON, - reporter = REPORTER)) - } - (11..15).forEach { - val requestId = crrStorage.saveRevocationRequest(CertificateRevocationRequest( - certificateSerialNumber = createNodeCertificate(csrStorage, "LegalName" + it.toString()).serialNumber, - reason = REVOCATION_REASON, - reporter = REPORTER)) - crrStorage.markRequestTicketCreated(requestId) - crrStorage.approveRevocationRequest(requestId, "Approver") - } - - // when - val result = crrStorage.getRevocationRequests(RequestStatus.APPROVED) - - // then - assertEquals(5, result.size) - } - - @Test - fun `revocation request fails if a valid certificate cannot be found`() { - // given - - // then - assertFailsWith(IllegalArgumentException::class) { - // when - crrStorage.saveRevocationRequest(CertificateRevocationRequest( - certificateSerialNumber = BigInteger.TEN, - reason = REVOCATION_REASON, - reporter = REPORTER)) - } - } - - @Test - fun `Approving a certificate revocation request changes its status`() { - // given - val certificate = createNodeCertificate(csrStorage) - val requestId = crrStorage.saveRevocationRequest(CertificateRevocationRequest( - certificateSerialNumber = certificate.serialNumber, - reason = REVOCATION_REASON, - reporter = REPORTER)) - crrStorage.markRequestTicketCreated(requestId) - - // when - crrStorage.approveRevocationRequest(requestId, "Approver") - - // then - assertNotNull(crrStorage.getRevocationRequest(requestId)).apply { - assertEquals(RequestStatus.APPROVED, status) - } - } - - @Test - fun `Rejecting a certificate revocation request changes its status`() { - // given - val certificate = createNodeCertificate(csrStorage) - val requestId = crrStorage.saveRevocationRequest(CertificateRevocationRequest( - certificateSerialNumber = certificate.serialNumber, - reason = REVOCATION_REASON, - reporter = REPORTER)) - crrStorage.markRequestTicketCreated(requestId) - - // when - crrStorage.rejectRevocationRequest(requestId, "Rejector", "No reason") - - // then - assertNotNull(crrStorage.getRevocationRequest(requestId)).apply { - assertEquals(RequestStatus.REJECTED, status) - } - } -} \ No newline at end of file diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateSigningRequestStorageTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateSigningRequestStorageTest.kt deleted file mode 100644 index 55bf476039..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateSigningRequestStorageTest.kt +++ /dev/null @@ -1,335 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.TestBase -import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequestStorage.Companion.DOORMAN_SIGNATURE -import com.r3.corda.networkmanage.common.persistence.entity.CertificateSigningRequestEntity -import net.corda.core.crypto.Crypto -import net.corda.core.crypto.SecureHash -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.CertRole -import net.corda.nodeapi.internal.crypto.X509Utilities -import net.corda.nodeapi.internal.persistence.CordaPersistence -import net.corda.nodeapi.internal.persistence.DatabaseConfig -import net.corda.testing.internal.createDevNodeCaCertPath -import org.assertj.core.api.Assertions.assertThat -import org.bouncycastle.pkcs.PKCS10CertificationRequest -import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest -import org.hibernate.envers.AuditReaderFactory -import org.junit.After -import org.junit.Before -import org.junit.Test -import java.security.KeyPair -import java.security.cert.CertPath -import java.util.* -import javax.security.auth.x500.X500Principal -import kotlin.test.* - -class PersistentCertificateRequestStorageTest : TestBase() { - private lateinit var storage: PersistentCertificateSigningRequestStorage - private lateinit var persistence: CordaPersistence - - @Before - fun startDb() { - persistence = configureDatabase(makeTestDataSourceProperties(), DatabaseConfig(runMigration = true)) - storage = PersistentCertificateSigningRequestStorage(persistence) - } - - @After - fun closeDb() { - persistence.close() - } - - @Test - fun `valid request`() { - val request = createRequest("LegalName", certRole = CertRole.NODE_CA).first - val requestId = storage.saveRequest(request) - assertNotNull(storage.getRequest(requestId)).apply { - assertEquals(request, this.request) - } - assertThat(storage.getRequests(RequestStatus.NEW).map { it.requestId }).containsOnly(requestId) - } - - @Test - fun `valid service identity request`() { - val request = createRequest("LegalName", certRole = CertRole.SERVICE_IDENTITY).first - val requestId = storage.saveRequest(request) - assertNotNull(storage.getRequest(requestId)).apply { - assertEquals(request, this.request) - } - assertThat(storage.getRequests(RequestStatus.NEW).map { it.requestId }).containsOnly(requestId) - } - - @Test - fun `submit same request twice returns the first request ID`() { - val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) - val request = createRequest("LegalName", keyPair, certRole = CertRole. NODE_CA).first - val firstRequestId = storage.saveRequest(request) - - assertNotNull(storage.getRequest(firstRequestId)).apply { - assertEquals(request, this.request) - } - assertThat(storage.getRequests(RequestStatus.NEW).map { it.requestId }).containsOnly(firstRequestId) - - val request2 = createRequest("LegalName", keyPair, certRole = CertRole.NODE_CA).first - val secondRequestId = storage.saveRequest(request2) - - assertEquals(firstRequestId, secondRequestId) - - assertNotNull(storage.getRequest(secondRequestId)).apply { - assertEquals(request, this.request) - } - assertThat(storage.getRequests(RequestStatus.NEW).map { it.requestId }).containsOnly(firstRequestId) - } - - @Test - fun `invalid cert role request`() { - val request = createRequest("LegalName", certRole = CertRole.INTERMEDIATE_CA).first - val requestId = storage.saveRequest(request) - assertNotNull(storage.getRequest(requestId)).apply { - assertEquals(request, this.request) - } - assertThat(storage.getRequests(RequestStatus.REJECTED).map { it.requestId }).containsOnly(requestId) - } - - @Test - fun `approve request`() { - val (request, _) = createRequest("LegalName", certRole = CertRole.NODE_CA) - // Add request to DB. - val requestId = storage.saveRequest(request) - // Pending request should equals to 1. - assertEquals(1, storage.getRequests(RequestStatus.NEW).size) - // Certificate should be empty. - assertNull(storage.getRequest(requestId)!!.certData) - // Signal that a ticket has been created for the request. - storage.markRequestTicketCreated(requestId) - // Store certificate to DB. - storage.approveRequest(requestId, DOORMAN_SIGNATURE) - // Check request is not ready yet. - // assertTrue(storage.getResponse(requestId) is CertificateResponse.NotReady) - // New request should be empty. - assertTrue(storage.getRequests(RequestStatus.NEW).isEmpty()) - } - - @Test - fun `sign request`() { - val (csr, nodeKeyPair) = createRequest("LegalName", certRole = CertRole.NODE_CA) - // Add request to DB. - val requestId = storage.saveRequest(csr) - // New request should equals to 1. - assertEquals(1, storage.getRequests(RequestStatus.NEW).size) - // Certificate should be empty. - assertNull(storage.getRequest(requestId)!!.certData) - storage.markRequestTicketCreated(requestId) - // Store certificate to DB. - storage.approveRequest(requestId, DOORMAN_SIGNATURE) - // Check request is not ready yet. - assertEquals(RequestStatus.APPROVED, storage.getRequest(requestId)!!.status) - // New request should be empty. - assertTrue(storage.getRequests(RequestStatus.NEW).isEmpty()) - // Sign certificate - storage.putCertificatePath( - requestId, - generateSignedCertPath(csr, nodeKeyPair), - DOORMAN_SIGNATURE - ) - // Check request is ready - assertNotNull(storage.getRequest(requestId)!!.certData) - } - - @Test - fun `get valid certificate path returns correct value`() { - // given - val (csr, nodeKeyPair) = createRequest("LegalName", certRole = CertRole.NODE_CA) - val requestId = storage.saveRequest(csr) - storage.markRequestTicketCreated(requestId) - storage.approveRequest(requestId, DOORMAN_SIGNATURE) - val certPath = generateSignedCertPath(csr, nodeKeyPair) - storage.putCertificatePath( - requestId, - certPath, - DOORMAN_SIGNATURE - ) - - // when - val storedCertPath = storage.getValidCertificatePath(nodeKeyPair.public) - - // then - assertEquals(certPath, storedCertPath) - } - - @Test - fun `get valid certificate path returns null if the certificate path cannot be found`() { - // given - val (_, nodeKeyPair) = createRequest("LegalName", certRole = CertRole.NODE_CA) - - // when - val storedCertPath = storage.getValidCertificatePath(nodeKeyPair.public) - - // then - assertNull(storedCertPath) - } - - @Test - fun `sign request ignores subsequent sign requests`() { - val (csr, nodeKeyPair) = createRequest("LegalName", certRole = CertRole.NODE_CA) - // Add request to DB. - val requestId = storage.saveRequest(csr) - // Store certificate to DB. - storage.markRequestTicketCreated(requestId) - storage.approveRequest(requestId, DOORMAN_SIGNATURE) - // Sign certificate - storage.putCertificatePath( - requestId, - generateSignedCertPath(csr, nodeKeyPair), - DOORMAN_SIGNATURE - ) - // When subsequent signature requested - assertFailsWith(IllegalArgumentException::class) { - storage.putCertificatePath( - requestId, - generateSignedCertPath(csr, nodeKeyPair), - DOORMAN_SIGNATURE) - } - } - - @Test - fun `sign request rejects requests with the same public key`() { - val (csr, nodeKeyPair) = createRequest("LegalName", certRole = CertRole.NODE_CA) - // Add request to DB. - val requestId = storage.saveRequest(csr) - // Store certificate to DB. - storage.markRequestTicketCreated(requestId) - storage.approveRequest(requestId, DOORMAN_SIGNATURE) - // Sign certificate - storage.putCertificatePath( - requestId, - generateSignedCertPath(csr, nodeKeyPair), - DOORMAN_SIGNATURE - ) - // Sign certificate - // When request with the same public key is requested - val (newCsr, _) = createRequest("NewLegalName", nodeKeyPair, certRole = CertRole.NODE_CA) - val duplicateRequestId = storage.saveRequest(newCsr) - assertThat(storage.getRequests(RequestStatus.NEW)).isEmpty() - val duplicateRequest = storage.getRequest(duplicateRequestId) - assertThat(duplicateRequest!!.status).isEqualTo(RequestStatus.REJECTED) - assertThat(duplicateRequest.remark).isEqualTo("Duplicate public key") - } - - @Test - fun `reject request`() { - val requestId = storage.saveRequest(createRequest("BankA", certRole = CertRole.NODE_CA).first) - storage.rejectRequest(requestId, DOORMAN_SIGNATURE, "Because I said so!") - assertThat(storage.getRequests(RequestStatus.NEW)).isEmpty() - assertThat(storage.getRequest(requestId)!!.remark).isEqualTo("Because I said so!") - } - - @Test - fun `request with the same legal name as a pending request`() { - val requestId1 = storage.saveRequest(createRequest("BankA", certRole = CertRole.NODE_CA).first) - assertThat(storage.getRequests(RequestStatus.NEW).map { it.requestId }).containsOnly(requestId1) - val requestId2 = storage.saveRequest(createRequest("BankA", certRole = CertRole.NODE_CA).first) - assertThat(storage.getRequests(RequestStatus.NEW).map { it.requestId }).containsOnly(requestId1) - assertEquals(RequestStatus.REJECTED, storage.getRequest(requestId2)!!.status) - assertThat(storage.getRequest(requestId2)!!.remark).containsIgnoringCase("duplicate") - // Make sure the first request is processed properly - storage.markRequestTicketCreated(requestId1) - storage.approveRequest(requestId1, DOORMAN_SIGNATURE) - assertThat(storage.getRequest(requestId1)!!.status).isEqualTo(RequestStatus.APPROVED) - } - - @Test - fun `request with the same legal name as a previously approved request`() { - val requestId1 = storage.saveRequest(createRequest("BankA", certRole = CertRole.NODE_CA).first) - storage.markRequestTicketCreated(requestId1) - storage.approveRequest(requestId1, DOORMAN_SIGNATURE) - val requestId2 = storage.saveRequest(createRequest("BankA", certRole = CertRole.NODE_CA).first) - assertThat(storage.getRequest(requestId2)!!.remark).containsIgnoringCase("duplicate") - } - - @Test - fun `request with the same legal name as a previously signed request`() { - val (csr, nodeKeyPair) = createRequest("BankA", certRole = CertRole.NODE_CA) - val requestId = storage.saveRequest(csr) - storage.markRequestTicketCreated(requestId) - storage.approveRequest(requestId, DOORMAN_SIGNATURE) - // Sign certificate - storage.putCertificatePath( - requestId, - generateSignedCertPath(csr, nodeKeyPair), - DOORMAN_SIGNATURE - ) - val rejectedRequestId = storage.saveRequest(createRequest("BankA", certRole = CertRole.NODE_CA).first) - assertThat(storage.getRequest(rejectedRequestId)!!.remark).containsIgnoringCase("duplicate") - } - - @Test - fun `request with the same legal name as a previously rejected request`() { - val requestId1 = storage.saveRequest(createRequest("BankA", certRole = CertRole.NODE_CA).first) - storage.rejectRequest(requestId1, DOORMAN_SIGNATURE, "Because I said so!") - val requestId2 = storage.saveRequest(createRequest("BankA", certRole = CertRole.NODE_CA).first) - assertThat(storage.getRequests(RequestStatus.NEW).map { it.requestId }).containsOnly(requestId2) - storage.markRequestTicketCreated(requestId2) - storage.approveRequest(requestId2, DOORMAN_SIGNATURE) - assertThat(storage.getRequest(requestId2)!!.status).isEqualTo(RequestStatus.APPROVED) - } - - @Test - fun `audit data is available for CSRs`() { - // given - val approver = "APPROVER" - - // when - val requestId = storage.saveRequest(createRequest("BankA", certRole = CertRole.NODE_CA).first) - storage.markRequestTicketCreated(requestId) - storage.approveRequest(requestId, approver) - - // then - persistence.transaction { - val auditReader = AuditReaderFactory.get(persistence.entityManagerFactory.createEntityManager()) - val newRevision = auditReader.find(CertificateSigningRequestEntity::class.java, requestId, 1) - assertEquals(RequestStatus.NEW, newRevision.status) - assertEquals(DOORMAN_SIGNATURE, newRevision.modifiedBy) - - val ticketCreatedRevision = auditReader.find(CertificateSigningRequestEntity::class.java, requestId, 2) - assertEquals(RequestStatus.TICKET_CREATED, ticketCreatedRevision.status) - assertEquals(DOORMAN_SIGNATURE, ticketCreatedRevision.modifiedBy) - - val approvedRevision = auditReader.find(CertificateSigningRequestEntity::class.java, requestId, 3) - assertEquals(RequestStatus.APPROVED, approvedRevision.status) - assertEquals(approver, approvedRevision.modifiedBy) - } - } - - private fun generateSignedCertPath(csr: PKCS10CertificationRequest, keyPair: KeyPair): CertPath { - return JcaPKCS10CertificationRequest(csr).run { - val (rootCa, intermediateCa, nodeCa) = createDevNodeCaCertPath(CordaX500Name.build(X500Principal(subject.encoded)), keyPair) - X509Utilities.buildCertPath(nodeCa.certificate, intermediateCa.certificate, rootCa.certificate) - } - } - - private fun makeTestDataSourceProperties(nodeName: String = SecureHash.randomSHA256().toString()): Properties { - val props = Properties() - props.setProperty("dataSourceClassName", "org.h2.jdbcx.JdbcDataSource") - props.setProperty("dataSource.url", "jdbc:h2:mem:${nodeName}_persistence;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE") - props.setProperty("dataSource.user", "sa") - props.setProperty("dataSource.password", "") - return props - } -} - -internal fun createRequest(organisation: String, keyPair: KeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME), certRole: CertRole): Pair { - val request = X509Utilities.createCertificateSigningRequest(X500Principal("O=$organisation,L=London,C=GB"), "my@mail.com", keyPair, certRole = certRole) - // encode and decode the request to make sure class information (CertRole) etc are not passed into the test. - return Pair(JcaPKCS10CertificationRequest(request.encoded), keyPair) -} \ No newline at end of file diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNetworkMapStorageTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNetworkMapStorageTest.kt deleted file mode 100644 index b416b5c765..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNetworkMapStorageTest.kt +++ /dev/null @@ -1,242 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.TestBase -import com.r3.corda.networkmanage.common.persistence.entity.NodeInfoEntity -import com.r3.corda.networkmanage.common.persistence.entity.ParametersUpdateEntity -import com.r3.corda.networkmanage.common.persistence.entity.PrivateNetworkEntity -import com.r3.corda.networkmanage.common.persistence.entity.UpdateStatus -import net.corda.core.crypto.SecureHash -import net.corda.core.serialization.serialize -import net.corda.core.utilities.days -import net.corda.core.utilities.seconds -import net.corda.nodeapi.internal.createDevNetworkMapCa -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import net.corda.nodeapi.internal.network.NetworkMap -import net.corda.nodeapi.internal.network.NetworkMapAndSigned -import net.corda.nodeapi.internal.network.verifiedNetworkMapCert -import net.corda.nodeapi.internal.persistence.CordaPersistence -import net.corda.nodeapi.internal.persistence.DatabaseConfig -import net.corda.testing.common.internal.testNetworkParameters -import net.corda.testing.internal.createDevIntermediateCaCertPath -import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties -import org.assertj.core.api.Assertions.assertThat -import org.junit.After -import org.junit.Before -import org.junit.Test -import java.security.cert.X509Certificate -import java.time.Instant -import java.util.* - -class PersistentNetworkMapStorageTest : TestBase() { - private lateinit var persistence: CordaPersistence - private lateinit var networkMapStorage: PersistentNetworkMapStorage - private lateinit var nodeInfoStorage: PersistentNodeInfoStorage - private lateinit var requestStorage: PersistentCertificateSigningRequestStorage - - private lateinit var rootCaCert: X509Certificate - private lateinit var networkMapCertAndKeyPair: CertificateAndKeyPair - - @Before - fun startDb() { - val (rootCa) = createDevIntermediateCaCertPath() - rootCaCert = rootCa.certificate - networkMapCertAndKeyPair = createDevNetworkMapCa(rootCa) - persistence = configureDatabase(makeTestDataSourceProperties(), DatabaseConfig(runMigration = true)) - networkMapStorage = PersistentNetworkMapStorage(persistence) - nodeInfoStorage = PersistentNodeInfoStorage(persistence) - requestStorage = PersistentCertificateSigningRequestStorage(persistence) - } - - @After - fun closeDb() { - persistence.close() - } - - @Test - fun `create active network map`() { - // given - // Create node info. - val (signedNodeInfo) = createValidSignedNodeInfo("Test", requestStorage) - val nodeInfoHash = nodeInfoStorage.putNodeInfo(signedNodeInfo) - - // Create network parameters - val networkParameters = testNetworkParameters(maxTransactionSize = 1234567) - val networkParametersSig = networkMapCertAndKeyPair.sign(networkParameters).sig - val networkParametersHash = networkMapStorage.saveNetworkParameters(networkParameters, networkParametersSig).hash - val networkMap = NetworkMap(listOf(nodeInfoHash), SecureHash.parse(networkParametersHash), null) - val networkMapAndSigned = NetworkMapAndSigned(networkMap) { networkMapCertAndKeyPair.sign(networkMap).sig } - - // when - networkMapStorage.saveNewNetworkMap(networkMapAndSigned = networkMapAndSigned) - - // then - val networkMaps = networkMapStorage.getNetworkMaps() - val activeSignedNetworkMap = networkMaps.publicNetworkMap!!.toSignedNetworkMap() - val activeNetworkMap = activeSignedNetworkMap.verifiedNetworkMapCert(rootCaCert) - - assertThat(activeNetworkMap).isEqualTo(networkMap) - assertThat(activeSignedNetworkMap.sig).isEqualTo(networkMapAndSigned.signed.sig) - } - - @Test - fun `getLatestNetworkParameters returns last inserted`() { - val params1 = testNetworkParameters(minimumPlatformVersion = 1) - val params2 = testNetworkParameters(minimumPlatformVersion = 2) - networkMapStorage.saveNetworkParameters(params1, networkMapCertAndKeyPair.sign(params1).sig) - // We may have not signed them yet. - networkMapStorage.saveNetworkParameters(params2, null) - - assertThat(networkMapStorage.getLatestNetworkParameters()?.networkParameters).isEqualTo(params2) - } - - @Test - fun `getValidNodeInfoHashes returns node-infos for public and private networks`() { - // given - // Create node infos. - - val nodes = listOf("TestA", "TestB", "TestC", "TestD", "TestE") - - val nodeInfos = nodes.map { it to createValidSignedNodeInfo(it, requestStorage) }.toMap() - - // Put signed node info data - - val storedNodeInfos = nodeInfos.mapValues { nodeInfoStorage.putNodeInfo(it.value.first) } - - val (testNet1, testNet2) = persistence.transaction { - val testNet1 = PrivateNetworkEntity(UUID.randomUUID().toString(), "TestNet1").apply { session.save(this) } - val testNet2 = PrivateNetworkEntity(UUID.randomUUID().toString(), "TestNet2").apply { session.save(this) } - - // set different private network for node info - session.find(NodeInfoEntity::class.java, storedNodeInfos["TestA"].toString()).apply { - session.merge(certificateSigningRequest.copy(privateNetwork = testNet1)) - } - session.find(NodeInfoEntity::class.java, storedNodeInfos["TestC"].toString()).apply { - session.merge(certificateSigningRequest.copy(privateNetwork = testNet2)) - } - Pair(testNet1, testNet2) - } - - // when - val nodeInfoHashes = networkMapStorage.getNodeInfoHashes() - - // then - assertThat(nodeInfoHashes.publicNodeInfoHashes).containsOnlyElementsOf(storedNodeInfos.filterKeys { it !in setOf("TestA", "TestC") }.values) - assertThat(nodeInfoHashes.privateNodeInfoHashes.keys).containsOnlyElementsOf(listOf(testNet1.networkId, testNet2.networkId)) - assertThat(nodeInfoHashes.privateNodeInfoHashes[testNet1.networkId]).containsOnlyElementsOf(listOf(storedNodeInfos["TestA"])) - assertThat(nodeInfoHashes.privateNodeInfoHashes[testNet2.networkId]).containsOnlyElementsOf(listOf(storedNodeInfos["TestC"])) - } - - @Test - fun `saveNewParametersUpdate marks update as NEW and persists network parameters as the latest`() { - val networkParameters = testNetworkParameters() - val updateDeadline = Instant.now() + 10.days - networkMapStorage.saveNewParametersUpdate(networkParameters, "Update 1", updateDeadline) - val parameterUpdate = networkMapStorage.getCurrentParametersUpdate()!! - assertThat(parameterUpdate.description).isEqualTo("Update 1") - assertThat(parameterUpdate.updateDeadline).isEqualTo(updateDeadline) - assertThat(parameterUpdate.status).isEqualTo(UpdateStatus.NEW) - assertThat(parameterUpdate.networkParameters.networkParameters).isEqualTo(networkParameters) - assertThat(networkMapStorage.getLatestNetworkParameters()?.networkParameters).isEqualTo(networkParameters) - } - - @Test - fun `saveNewParametersUpdate marks previous update as cancelled`() { - networkMapStorage.saveNewParametersUpdate(testNetworkParameters(epoch = 1), "Update 1", Instant.now() + 1.days) - networkMapStorage.saveNewParametersUpdate(testNetworkParameters(epoch = 2), "Update of update", Instant.now() + 2.days) - val firstUpdate = persistence.transaction { - session.fromQuery("u where u.description = 'Update 1'").singleResult - } - assertThat(firstUpdate.status).isEqualTo(UpdateStatus.CANCELLED) - assertThat(networkMapStorage.getCurrentParametersUpdate()?.description).isEqualTo("Update of update") - } - - @Test - fun `switch ParametersUpdate on flag day`() { - // Update - val networkParameters1 = testNetworkParameters() - val updateDeadline = Instant.now() + 10.days - networkMapStorage.saveNewParametersUpdate(networkParameters1, "Update 1", updateDeadline) - // given - val (signedNodeInfoA) = createValidSignedNodeInfo("TestA", requestStorage) // null as acceptedParametersUpdate - val (signedNodeInfoB) = createValidSignedNodeInfo("TestB", requestStorage) // accepts update - - // Put signed node info data - nodeInfoStorage.putNodeInfo(signedNodeInfoA) - val nodeInfoHashB = nodeInfoStorage.putNodeInfo(signedNodeInfoB) - - nodeInfoStorage.ackNodeInfoParametersUpdate(signedNodeInfoB.nodeInfo.legalIdentities[0].owningKey, networkParameters1.serialize().hash) - val parameterUpdate = networkMapStorage.getCurrentParametersUpdate()!! - networkMapStorage.switchFlagDay(parameterUpdate) - // when - val validNodeInfoHashes = networkMapStorage.getNodeInfoHashes().publicNodeInfoHashes - // then - assertThat(validNodeInfoHashes).containsOnly(nodeInfoHashB) - } - - @Test - fun `accept second set of parameters and switch on flag day`() { - // Update 1 - val networkParameters1 = testNetworkParameters() - val updateDeadline = Instant.now() + 10.days - networkMapStorage.saveNewParametersUpdate(networkParameters1, "Update 1", updateDeadline) - // given - val (signedNodeInfoA) = createValidSignedNodeInfo("TestA", requestStorage) // Update 1 as acceptedParametersUpdate - val (signedNodeInfoB) = createValidSignedNodeInfo("TestB", requestStorage) // Update 2 as acceptedParametersUpdate - - // Put signed node info data - nodeInfoStorage.putNodeInfo(signedNodeInfoA) - val nodeInfoHashB = nodeInfoStorage.putNodeInfo(signedNodeInfoB) - - nodeInfoStorage.ackNodeInfoParametersUpdate(signedNodeInfoA.nodeInfo.legalIdentities[0].owningKey, networkParameters1.serialize().hash) - // Update 2 - val networkParameters2 = testNetworkParameters(epoch = 2) - networkMapStorage.saveNewParametersUpdate(networkParameters2, "Update 2", updateDeadline + 10.days) - nodeInfoStorage.ackNodeInfoParametersUpdate(signedNodeInfoB.nodeInfo.legalIdentities[0].owningKey, networkParameters2.serialize().hash) - val parameterUpdate = networkMapStorage.getCurrentParametersUpdate()!! - networkMapStorage.switchFlagDay(parameterUpdate) - // when - val validNodeInfoHashes = networkMapStorage.getNodeInfoHashes().publicNodeInfoHashes - // then - assertThat(validNodeInfoHashes).containsOnly(nodeInfoHashB) - } - - @Test - fun `remove nodes older than eventHorizon from network map`() { - val networkParameters = testNetworkParameters(eventHorizon = 1.seconds, minimumPlatformVersion = 4) - val (signedNodeInfoA) = createValidSignedNodeInfo("TestA", requestStorage) - val networkParametersEntity = networkMapStorage.saveNetworkParameters(networkParameters, networkMapCertAndKeyPair.sign(networkParameters).sig) - val networkMap = NetworkMap(emptyList(), SecureHash.parse(networkParametersEntity.hash), null) - val networkMapAndSigned = NetworkMapAndSigned(networkMap) { networkMapCertAndKeyPair.sign(networkMap).sig } - networkMapStorage.saveNewNetworkMap(networkMapAndSigned = networkMapAndSigned) - nodeInfoStorage.putNodeInfo(signedNodeInfoA) - assertThat(networkMapStorage.getNodeInfoHashes().publicNodeInfoHashes).containsExactly(signedNodeInfoA.signed.raw.hash) - Thread.sleep(2000) // Wait for node to be older than eventHorizon - assertThat(networkMapStorage.getNodeInfoHashes().publicNodeInfoHashes).doesNotContain(signedNodeInfoA.signed.raw.hash) - nodeInfoStorage.putNodeInfo(signedNodeInfoA) // Republish - assertThat(networkMapStorage.getNodeInfoHashes().publicNodeInfoHashes).containsExactly(signedNodeInfoA.signed.raw.hash) - } - - @Test - fun `don't enable eventHorizon for platform version less than 4`() { - val networkParameters = testNetworkParameters(eventHorizon = 1.seconds, minimumPlatformVersion = 3) - val (signedNodeInfoA) = createValidSignedNodeInfo("TestA", requestStorage) - val networkParametersEntity = networkMapStorage.saveNetworkParameters(networkParameters, networkMapCertAndKeyPair.sign(networkParameters).sig) - val networkMap = NetworkMap(emptyList(), SecureHash.parse(networkParametersEntity.hash), null) - val networkMapAndSigned = NetworkMapAndSigned(networkMap) { networkMapCertAndKeyPair.sign(networkMap).sig } - networkMapStorage.saveNewNetworkMap(networkMapAndSigned = networkMapAndSigned) - nodeInfoStorage.putNodeInfo(signedNodeInfoA) - assertThat(networkMapStorage.getNodeInfoHashes().publicNodeInfoHashes).containsExactly(signedNodeInfoA.signed.raw.hash) - Thread.sleep(2000) // Wait for eventHorizon to pass - assertThat(networkMapStorage.getNodeInfoHashes().publicNodeInfoHashes).containsExactly(signedNodeInfoA.signed.raw.hash) - } -} diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNodeInfoStorageTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNodeInfoStorageTest.kt deleted file mode 100644 index f4f258820c..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNodeInfoStorageTest.kt +++ /dev/null @@ -1,283 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.persistence - -import com.r3.corda.networkmanage.TestBase -import com.r3.corda.networkmanage.common.persistence.entity.NodeInfoEntity -import net.corda.core.crypto.Crypto -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.CertRole -import net.corda.core.internal.hash -import net.corda.core.node.NodeInfo -import net.corda.core.serialization.serialize -import net.corda.core.utilities.days -import net.corda.nodeapi.internal.NodeInfoAndSigned -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import net.corda.nodeapi.internal.crypto.CertificateType -import net.corda.nodeapi.internal.crypto.X509Utilities -import net.corda.nodeapi.internal.persistence.CordaPersistence -import net.corda.nodeapi.internal.persistence.DatabaseConfig -import net.corda.testing.common.internal.testNetworkParameters -import net.corda.testing.internal.TestNodeInfoBuilder -import net.corda.testing.internal.createDevIntermediateCaCertPath -import net.corda.testing.internal.signWith -import net.corda.testing.node.MockServices -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.After -import org.junit.Before -import org.junit.Test -import java.security.PrivateKey -import java.security.cert.X509Certificate -import java.time.Instant -import javax.security.auth.x500.X500Principal -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertNull -import kotlin.test.assertTrue - -class PersistentNodeInfoStorageTest : TestBase() { - private lateinit var requestStorage: CertificateSigningRequestStorage - private lateinit var nodeInfoStorage: PersistentNodeInfoStorage - private lateinit var networkMapStorage: PersistentNetworkMapStorage - private lateinit var persistence: CordaPersistence - private lateinit var rootCaCert: X509Certificate - private lateinit var doormanCertAndKeyPair: CertificateAndKeyPair - - @Before - fun startDb() { - val (rootCa, intermediateCa) = createDevIntermediateCaCertPath() - rootCaCert = rootCa.certificate - this.doormanCertAndKeyPair = intermediateCa - persistence = configureDatabase(MockServices.makeTestDataSourceProperties(), DatabaseConfig(runMigration = true)) - nodeInfoStorage = PersistentNodeInfoStorage(persistence) - requestStorage = PersistentCertificateSigningRequestStorage(persistence) - networkMapStorage = PersistentNetworkMapStorage(persistence) - } - - @After - fun closeDb() { - persistence.close() - } - - @Test - fun `test getCertificatePath`() { - // Create node info. - val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) - val name = CordaX500Name(organisation = "Test", locality = "London", country = "GB") - val nodeCaCert = X509Utilities.createCertificate( - CertificateType.NODE_CA, - doormanCertAndKeyPair.certificate, - doormanCertAndKeyPair.keyPair, - name.x500Principal, - keyPair.public) - - val request = X509Utilities.createCertificateSigningRequest(name.x500Principal, "my@mail.com", keyPair) - - val requestId = requestStorage.saveRequest(request) - requestStorage.markRequestTicketCreated(requestId) - requestStorage.approveRequest(requestId, CertificateSigningRequestStorage.DOORMAN_SIGNATURE) - - assertNull(nodeInfoStorage.getCertificatePath(keyPair.public.hash)) - - requestStorage.putCertificatePath( - requestId, - X509Utilities.buildCertPath(nodeCaCert, doormanCertAndKeyPair.certificate, rootCaCert), - CertificateSigningRequestStorage.DOORMAN_SIGNATURE) - - val storedCertPath = nodeInfoStorage.getCertificatePath(keyPair.public.hash) - assertNotNull(storedCertPath) - - assertEquals(nodeCaCert, storedCertPath!!.certificates.first()) - } - - @Test - fun `getNodeInfo returns persisted SignedNodeInfo using the hash of just the NodeInfo`() { - // given - val (nodeA) = createValidSignedNodeInfo("TestA", requestStorage) - val (nodeB) = createValidSignedNodeInfo("TestB", requestStorage) - - // Put signed node info data - nodeInfoStorage.putNodeInfo(nodeA) - nodeInfoStorage.putNodeInfo(nodeB) - - // when - val persistedSignedNodeInfoA = nodeInfoStorage.getNodeInfo(nodeA.nodeInfo.serialize().hash) - val persistedSignedNodeInfoB = nodeInfoStorage.getNodeInfo(nodeB.nodeInfo.serialize().hash) - - // then - assertEquals(persistedSignedNodeInfoA?.verified(), nodeA.nodeInfo) - assertEquals(persistedSignedNodeInfoB?.verified(), nodeB.nodeInfo) - } - - @Test - fun `same public key with different node info`() { - // Create node info. - val (node1, key) = createValidSignedNodeInfo("Test", requestStorage) - val nodeInfo2 = node1.nodeInfo.copy(serial = 2) - val node2 = NodeInfoAndSigned(nodeInfo2.signWith(listOf(key))) - - val nodeInfo1Hash = nodeInfoStorage.putNodeInfo(node1) - assertEquals(node1.nodeInfo, nodeInfoStorage.getNodeInfo(nodeInfo1Hash)?.verified()) - assertTrue(networkMapStorage.getNodeInfoHashes().publicNodeInfoHashes.contains(nodeInfo1Hash)) - - // This should replace the node info. - val nodeInfo2Hash = nodeInfoStorage.putNodeInfo(node2) - - // Old node info should be removed from list of current node info hashes, but still accessible if required. - assertThat(networkMapStorage.getNodeInfoHashes().publicNodeInfoHashes).doesNotContain(nodeInfo1Hash) - assertThat(networkMapStorage.getNodeInfoHashes().publicNodeInfoHashes).contains(nodeInfo2Hash) - assertNotNull(nodeInfoStorage.getNodeInfo(nodeInfo1Hash)) - assertEquals(nodeInfo2, nodeInfoStorage.getNodeInfo(nodeInfo2.serialize().hash)?.verified()) - } - - @Test - fun `putNodeInfo persists SignedNodeInfo with its signature`() { - // given - val (nodeInfoAndSigned) = createValidSignedNodeInfo("Test", requestStorage) - - // when - val nodeInfoHash = nodeInfoStorage.putNodeInfo(nodeInfoAndSigned) - - // then - val persistedSignedNodeInfo = nodeInfoStorage.getNodeInfo(nodeInfoHash) - assertThat(persistedSignedNodeInfo?.signatures).isEqualTo(nodeInfoAndSigned.signed.signatures) - } - - @Test - fun `publish same node info twice`() { - fun singleNodeInfo() = persistence.transaction { session.fromQuery("").singleResult } - - val (nodeInfoAndSigned) = createValidSignedNodeInfo("Test", requestStorage) - nodeInfoStorage.putNodeInfo(nodeInfoAndSigned) - val nodeInfo = singleNodeInfo() - Thread.sleep(500) - nodeInfoStorage.putNodeInfo(nodeInfoAndSigned) - assertThat(nodeInfo.publishedAt).isBefore(singleNodeInfo().publishedAt) // Check publishAt has changed - assertThat(singleNodeInfo().isCurrent).isTrue() - } - - @Test - fun `publish same node info twice after isCurrent change`() { - fun singleNodeInfo() = persistence.transaction { session.fromQuery("").singleResult } - - val (nodeInfoAndSigned) = createValidSignedNodeInfo("Test", requestStorage) - nodeInfoStorage.putNodeInfo(nodeInfoAndSigned) - // Change isCurrent to false (that happens on flagDay change) - persistence.transaction { - val ni = singleNodeInfo() - session.merge(ni.copy(isCurrent = false)) - } - assertThat(singleNodeInfo().isCurrent).isFalse() - val nodeInfo = singleNodeInfo() - nodeInfoStorage.putNodeInfo(nodeInfoAndSigned) - assertThat(nodeInfo.publishedAt).isBeforeOrEqualTo(singleNodeInfo().publishedAt) - assertThat(singleNodeInfo().isCurrent).isTrue() - } - - @Test - fun `accept parameters updates node info correctly`() { - // given - val (nodeInfoAndSigned) = createValidSignedNodeInfo("Test", requestStorage) - - // when - val networkParameters = testNetworkParameters() - val netParamsHash = networkParameters.serialize().hash - networkMapStorage.saveNewParametersUpdate(networkParameters, "Update", Instant.now() + 1.days) - val nodeInfoHash = nodeInfoStorage.putNodeInfo(nodeInfoAndSigned) - nodeInfoStorage.ackNodeInfoParametersUpdate(nodeInfoAndSigned.nodeInfo.legalIdentities[0].owningKey, netParamsHash) - - // then - val acceptedUpdate = nodeInfoStorage.getAcceptedParametersUpdate(nodeInfoHash) - assertThat(acceptedUpdate?.networkParameters?.hash).isEqualTo(netParamsHash.toString()) - } - - @Test - fun `updating node info after it's accepted network parameters`() { - val networkParameters = testNetworkParameters() - val netParamsHash = networkParameters.serialize().hash - networkMapStorage.saveNewParametersUpdate(networkParameters, "Update", Instant.now() + 1.days) - - val (nodeInfoAndSigned, privateKey) = createValidSignedNodeInfo("Test", requestStorage) - nodeInfoStorage.putNodeInfo(nodeInfoAndSigned) - - nodeInfoStorage.ackNodeInfoParametersUpdate(nodeInfoAndSigned.nodeInfo.legalIdentities[0].owningKey, netParamsHash) - - val nodeInfo2 = nodeInfoAndSigned.nodeInfo.copy(serial = 2) - val nodeInfoAndSigned2 = NodeInfoAndSigned(nodeInfo2.signWith(listOf(privateKey))) - val nodeInfoHash2 = nodeInfoStorage.putNodeInfo(nodeInfoAndSigned2) - - val acceptedUpdate = nodeInfoStorage.getAcceptedParametersUpdate(nodeInfoHash2) - assertThat(acceptedUpdate?.networkParameters?.hash).isEqualTo(netParamsHash.toString()) - } - - @Test - fun `persist node info with multiple node CA identities`() { - val (nodeInfo1, nodeKeyPair1) = createValidNodeInfo("Alice", requestStorage) - val (nodeInfo2, nodeKeyPair2) = createValidNodeInfo("Bob", requestStorage) - - val multiIdentityNodeInfo = nodeInfo1.copy(legalIdentitiesAndCerts = nodeInfo1.legalIdentitiesAndCerts + nodeInfo2.legalIdentitiesAndCerts) - val signedNodeInfo = multiIdentityNodeInfo.signWith(listOf(nodeKeyPair1, nodeKeyPair2)) - - assertThatThrownBy { nodeInfoStorage.putNodeInfo(NodeInfoAndSigned(signedNodeInfo)) } - .isInstanceOf(IllegalArgumentException::class.java) - .hasMessageContaining("Require exactly 1 Node CA identity in the node-info.") - } - - @Test - fun `persist node info with service identity`() { - val (nodeInfo, nodeKeyPairs) = createValidNodeInfo(requestStorage, CertRole.NODE_CA to "Alice", CertRole.SERVICE_IDENTITY to "Alice Notary") - val signedNodeInfo = nodeInfo.signWith(nodeKeyPairs) - nodeInfoStorage.putNodeInfo(NodeInfoAndSigned(signedNodeInfo)) - } - - @Test - fun `persist node info with unregistered service identity`() { - val (nodeInfo1, nodeKeyPair1) = createValidNodeInfo("Alice", requestStorage) - // Create a unregistered cert path with valid intermediate cert. - val (identity, key) = TestNodeInfoBuilder().addServiceIdentity(CordaX500Name("Test", "London", "GB"), Crypto.generateKeyPair()) - - val multiIdentityNodeInfo = nodeInfo1.copy(legalIdentitiesAndCerts = nodeInfo1.legalIdentitiesAndCerts + identity) - val signedNodeInfo = multiIdentityNodeInfo.signWith(listOf(nodeKeyPair1, key)) - - assertThatThrownBy { nodeInfoStorage.putNodeInfo(NodeInfoAndSigned(signedNodeInfo)) } - .isInstanceOf(IllegalArgumentException::class.java) - .hasMessageContaining("Node-info not registered with us") - } -} - -internal fun createValidNodeInfo(organisation: String, storage: CertificateSigningRequestStorage): Pair { - val (nodeInfo, keys) = createValidNodeInfo(storage, CertRole.NODE_CA to organisation) - return Pair(nodeInfo, keys.single()) -} - -internal fun createValidNodeInfo(storage: CertificateSigningRequestStorage, vararg identities: Pair): Pair> { - val nodeInfoBuilder = TestNodeInfoBuilder() - val keys = identities.map { (certRole, name) -> - val (csr, nodeKeyPair) = createRequest(name, certRole = certRole) - val requestId = storage.saveRequest(csr) - storage.markRequestTicketCreated(requestId) - storage.approveRequest(requestId, "TestUser") - val (identity, key) = when (certRole) { - CertRole.NODE_CA -> nodeInfoBuilder.addLegalIdentity(CordaX500Name.build(X500Principal(csr.subject.encoded)), nodeKeyPair) - CertRole.SERVICE_IDENTITY -> nodeInfoBuilder.addServiceIdentity(CordaX500Name.build(X500Principal(csr.subject.encoded)), nodeKeyPair) - else -> throw IllegalArgumentException("Unsupported cert role $certRole.") - } - storage.putCertificatePath(requestId, identity.certPath, "Test") - key - } - return Pair(nodeInfoBuilder.build(), keys) -} - -internal fun createValidSignedNodeInfo(organisation: String, storage: CertificateSigningRequestStorage): Pair { - val (nodeInfo, key) = createValidNodeInfo(organisation, storage) - return Pair(NodeInfoAndSigned(nodeInfo.signWith(listOf(key))), key) -} diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/CertificateRevocationListSignerTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/CertificateRevocationListSignerTest.kt deleted file mode 100644 index 2f6777bac3..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/CertificateRevocationListSignerTest.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.r3.corda.networkmanage.common.signer - -import com.nhaarman.mockito_kotlin.* -import com.r3.corda.networkmanage.TestBase -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationListStorage -import com.r3.corda.networkmanage.common.persistence.CertificateRevocationRequestData -import com.r3.corda.networkmanage.common.persistence.CrlIssuer -import com.r3.corda.networkmanage.common.persistence.RequestStatus -import net.corda.core.crypto.SecureHash -import net.corda.core.crypto.random63BitValue -import net.corda.core.crypto.sign -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.DigitalSignatureWithCert -import net.corda.core.utilities.millis -import net.corda.nodeapi.internal.DEV_INTERMEDIATE_CA -import org.junit.Before -import org.junit.Test -import java.math.BigInteger -import java.net.URL -import java.security.cert.CRLReason -import java.security.cert.X509CRL -import java.time.Instant -import kotlin.test.assertNotNull - -class CertificateRevocationListSignerTest : TestBase() { - private val signer = TestSigner() - private lateinit var crlStorage: CertificateRevocationListStorage - private lateinit var crlSigner: CertificateRevocationListSigner - - @Before - fun setUp() { - crlStorage = mock() - crlSigner = CertificateRevocationListSigner(crlStorage, DEV_INTERMEDIATE_CA.certificate, 600.millis, URL("http://dummy.com"), signer) - } - - @Test - fun `signCertificateRevocationList creates correct CRL and saves c`() { - // given - val approvedReq = givenCertificateRevocationRequest(RequestStatus.APPROVED) - val revokedReq = givenCertificateRevocationRequest(RequestStatus.DONE) - val signedBy = "Signer" - - // when - crlSigner.createSignedCRL(listOf(approvedReq), listOf(revokedReq), signedBy) - - // then - argumentCaptor().apply { - verify(crlStorage).saveCertificateRevocationList(capture(), eq(CrlIssuer.DOORMAN), eq(signedBy), any()) - val crl = firstValue - crl.verify(DEV_INTERMEDIATE_CA.keyPair.public) - assertNotNull(crl.getRevokedCertificate(approvedReq.certificateSerialNumber)) - assertNotNull(crl.getRevokedCertificate(revokedReq.certificateSerialNumber)) - } - } - - private class TestSigner : Signer { - override fun signBytes(data: ByteArray): DigitalSignatureWithCert { - return DigitalSignatureWithCert(DEV_INTERMEDIATE_CA.certificate, DEV_INTERMEDIATE_CA.keyPair.private.sign(data).bytes) - } - } - - private fun givenCertificateRevocationRequest(status: RequestStatus): CertificateRevocationRequestData { - return CertificateRevocationRequestData( - SecureHash.randomSHA256().toString(), - "CSR-ID-1", - mock(), - BigInteger.valueOf(random63BitValue()), - Instant.now(), - CordaX500Name.parse("CN=Bank A, O=$status, L=London, C=GB"), - status, - CRLReason.KEY_COMPROMISE, - "Reporter") - } - -} \ No newline at end of file diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSignerTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSignerTest.kt deleted file mode 100644 index 58aad75253..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSignerTest.kt +++ /dev/null @@ -1,241 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.common.signer - -import com.nhaarman.mockito_kotlin.* -import com.r3.corda.networkmanage.TestBase -import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage -import com.r3.corda.networkmanage.common.persistence.NetworkMaps -import com.r3.corda.networkmanage.common.persistence.NodeInfoHashes -import com.r3.corda.networkmanage.common.persistence.entity.ParametersUpdateEntity -import com.r3.corda.networkmanage.common.persistence.entity.UpdateStatus -import com.r3.corda.networkmanage.createNetworkMaps -import com.r3.corda.networkmanage.createNetworkParametersEntity -import com.r3.corda.networkmanage.createNetworkParametersEntityUnsigned -import net.corda.core.crypto.Crypto -import net.corda.core.crypto.SecureHash -import net.corda.core.crypto.random63BitValue -import net.corda.core.internal.DigitalSignatureWithCert -import net.corda.core.internal.uncheckedCast -import net.corda.core.node.NetworkParameters -import net.corda.core.serialization.SerializedBytes -import net.corda.core.serialization.serialize -import net.corda.nodeapi.internal.createDevNetworkMapCa -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import net.corda.nodeapi.internal.network.NetworkMapAndSigned -import net.corda.nodeapi.internal.network.SignedNetworkParameters -import net.corda.testing.common.internal.testNetworkParameters -import net.corda.testing.internal.createDevIntermediateCaCertPath -import org.assertj.core.api.Assertions.assertThat -import org.junit.Before -import org.junit.Test -import java.security.cert.X509Certificate -import java.time.Instant -import kotlin.test.assertEquals - -class NetworkMapSignerTest : TestBase() { - private lateinit var signer: Signer - private lateinit var networkMapStorage: NetworkMapStorage - private lateinit var networkMapSigner: NetworkMapSigner - - private lateinit var rootCaCert: X509Certificate - private lateinit var signingCertAndKeyPair: CertificateAndKeyPair - - @Before - fun setUp() { - val (rootCa) = createDevIntermediateCaCertPath() - rootCaCert = rootCa.certificate - signingCertAndKeyPair = createDevNetworkMapCa(rootCa) - signer = mock() - networkMapStorage = mock() - networkMapSigner = NetworkMapSigner(networkMapStorage, signer) - whenever(signer.signBytes(any())).then { - DigitalSignatureWithCert(signingCertAndKeyPair.certificate, Crypto.doSign(signingCertAndKeyPair.keyPair.private, it.arguments[0] as ByteArray)) - } - whenever(signer.signObject(any())).then { - val serialised: SerializedBytes = uncheckedCast(it.arguments[0].serialize()) - SignedNetworkParameters(serialised, signer.signBytes(serialised.bytes)) - } - } - - @Test - fun `signNetworkMap builds and signs network map and network parameters`() { - // given - val nodeInfoHashes = NodeInfoHashes(listOf(SecureHash.randomSHA256(), SecureHash.randomSHA256()), emptyMap()) - val latestNetParams = testNetworkParameters(epoch = 3) - val latestNetParamsEntity = createNetworkParametersEntityUnsigned(latestNetParams) - whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(latestNetParamsEntity) - whenever(networkMapStorage.getNodeInfoHashes()).thenReturn(nodeInfoHashes) - whenever(networkMapStorage.getNetworkMaps()).thenReturn(NetworkMaps(null, emptyMap())) - whenever(networkMapStorage.getCurrentParametersUpdate()).thenReturn(null) - - // when - networkMapSigner.signNetworkMaps() - - // then - // Verify networkMapStorage calls - verify(networkMapStorage).getNodeInfoHashes() - verify(networkMapStorage).getNetworkMaps() - verify(networkMapStorage).getCurrentParametersUpdate() - verify(networkMapStorage).getLatestNetworkParameters() - argumentCaptor().apply { - verify(networkMapStorage).saveNewNetworkMap(anyOrNull(), capture()) - val capturedNetworkMap = firstValue.networkMap - // Parameters in network map got swapped for latest ones. - assertEquals(latestNetParams.serialize().hash, capturedNetworkMap.networkParameterHash) - assertThat(capturedNetworkMap.nodeInfoHashes).isEqualTo(nodeInfoHashes.publicNodeInfoHashes) - } - val paramsCaptor = argumentCaptor() - val signatureCaptor = argumentCaptor() - verify(networkMapStorage).saveNetworkParameters(paramsCaptor.capture(), signatureCaptor.capture()) - assertEquals(paramsCaptor.firstValue, latestNetParams) - assertThat(signatureCaptor.firstValue.verify(latestNetParams.serialize())) - } - - @Test - fun `signNetworkMap does NOT create a new network map if there are no changes`() { - // given - val netParamsEntity = createNetworkParametersEntity(signingCertAndKeyPair) - val netMapEntity = createNetworkMaps(signingCertAndKeyPair, netParamsEntity, emptyList()) - whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(netParamsEntity) - whenever(networkMapStorage.getNodeInfoHashes()).thenReturn(NodeInfoHashes(emptyList(), emptyMap())) - whenever(networkMapStorage.getNetworkMaps()).thenReturn(netMapEntity) - - // when - networkMapSigner.signNetworkMaps() - - // then - // Verify networkMapStorage is not called - verify(networkMapStorage, never()).saveNewNetworkMap(any(), any()) - verify(networkMapStorage, never()).saveNetworkParameters(any(), any()) - } - - @Test - fun `signNetworkMap creates a new network map if there is no current network map`() { - // given - val netParams = testNetworkParameters() - whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(createNetworkParametersEntityUnsigned(netParams)) - whenever(networkMapStorage.getNodeInfoHashes()).thenReturn(NodeInfoHashes(emptyList(), emptyMap())) - whenever(networkMapStorage.getNetworkMaps()).thenReturn(NetworkMaps(null, emptyMap())) - whenever(networkMapStorage.getCurrentParametersUpdate()).thenReturn(null) - - // when - networkMapSigner.signNetworkMaps() - - // then - // Verify networkMapStorage calls - verify(networkMapStorage).getNodeInfoHashes() - verify(networkMapStorage).getNetworkMaps() - verify(networkMapStorage).getLatestNetworkParameters() - verify(networkMapStorage).getCurrentParametersUpdate() - argumentCaptor().apply { - verify(networkMapStorage).saveNewNetworkMap(anyOrNull(), capture()) - assertEquals(netParams.serialize().hash, firstValue.networkMap.networkParameterHash) - } - val paramsCaptor = argumentCaptor() - val signatureCaptor = argumentCaptor() - verify(networkMapStorage).saveNetworkParameters(paramsCaptor.capture(), signatureCaptor.capture()) - assertEquals(paramsCaptor.firstValue, netParams) - assertThat(signatureCaptor.firstValue.verify(netParams.serialize())) - } - - @Test - fun `signNetworkMap signs new network parameters`() { - // given - val currentNetworkParameters = createNetworkParametersEntity(signingCertAndKeyPair) - val updateNetworkParameters = createNetworkParametersEntityUnsigned(testNetworkParameters(epoch = 2)) - val parametersUpdate = ParametersUpdateEntity(0, updateNetworkParameters, "Update time", Instant.ofEpochMilli(random63BitValue())) - val netMapEntity = createNetworkMaps(signingCertAndKeyPair, currentNetworkParameters) - whenever(networkMapStorage.getNetworkMaps()).thenReturn(netMapEntity) - whenever(networkMapStorage.getCurrentParametersUpdate()).thenReturn(parametersUpdate) - whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(updateNetworkParameters) - whenever(networkMapStorage.getNodeInfoHashes()).thenReturn(NodeInfoHashes(emptyList(), emptyMap())) - - // when - networkMapSigner.signNetworkMaps() - - // then - // Verify networkMapStorage calls - verify(networkMapStorage).getNetworkMaps() - verify(networkMapStorage).getNodeInfoHashes() - verify(networkMapStorage).getLatestNetworkParameters() - verify(networkMapStorage).getCurrentParametersUpdate() - - val paramsCaptor = argumentCaptor() - val signatureCaptor = argumentCaptor() - verify(networkMapStorage, times(1)).saveNetworkParameters(paramsCaptor.capture(), signatureCaptor.capture()) - assertEquals(paramsCaptor.firstValue, updateNetworkParameters.networkParameters) - signatureCaptor.firstValue.verify(updateNetworkParameters.networkParameters.serialize()) - } - - @Test - fun `signNetworkMap fails if there is parameter update without relevant parameters stored`() { - val updateNetworkParameters = createNetworkParametersEntityUnsigned(testNetworkParameters(epoch = 2)) - val parametersUpdate = ParametersUpdateEntity(0, updateNetworkParameters, "Update time", Instant.ofEpochMilli(random63BitValue())) - whenever(networkMapStorage.getNetworkMaps()).thenReturn(NetworkMaps(null, emptyMap())) - whenever(networkMapStorage.getCurrentParametersUpdate()).thenReturn(parametersUpdate) - whenever(networkMapStorage.getNodeInfoHashes()).thenReturn(NodeInfoHashes(emptyList(), emptyMap())) - whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(createNetworkParametersEntity()) - - verify(networkMapStorage, never()).saveNetworkParameters(any(), any()) - verify(networkMapStorage, never()).saveNewNetworkMap(any(), any()) - } - - @Test - fun `setting flag day on parameters update changes parameters inside network map`() { - val activeNetworkParameters = createNetworkParametersEntity(signingCertAndKeyPair, testNetworkParameters(epoch = 1)) - val updateNetworkParameters = createNetworkParametersEntity(signingCertAndKeyPair, testNetworkParameters(epoch = 2)) - val parametersUpdate = ParametersUpdateEntity(0, updateNetworkParameters, "Update time", Instant.ofEpochMilli(random63BitValue())) - val activeNetworkMaps = createNetworkMaps(signingCertAndKeyPair, activeNetworkParameters, parametersUpdate = parametersUpdate.toParametersUpdate()) - - whenever(networkMapStorage.getNetworkMaps()).thenReturn(activeNetworkMaps) - whenever(networkMapStorage.getNodeInfoHashes()).thenReturn(NodeInfoHashes(emptyList(), emptyMap())) - whenever(networkMapStorage.getCurrentParametersUpdate()).thenReturn(parametersUpdate.copy(status = UpdateStatus.FLAG_DAY)) - whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(updateNetworkParameters) - - // when - networkMapSigner.signNetworkMaps() - - //then - argumentCaptor().apply { - verify(networkMapStorage).saveNewNetworkMap(anyOrNull(), capture()) - val netMap = firstValue.networkMap - assertEquals(SecureHash.parse(updateNetworkParameters.hash), netMap.networkParameterHash) - assertEquals(emptyList(), netMap.nodeInfoHashes) - assertEquals(null, netMap.parametersUpdate) - } - } - - @Test - fun `cancel update test`() { - val activeNetworkParameters = createNetworkParametersEntity(signingCertAndKeyPair, testNetworkParameters(epoch = 1)) - val updateNetworkParameters = createNetworkParametersEntityUnsigned(testNetworkParameters(epoch = 2)) - val parametersUpdate = ParametersUpdateEntity(0, updateNetworkParameters, "Update time", Instant.ofEpochMilli(random63BitValue())) - val activeNetworkMaps = createNetworkMaps(signingCertAndKeyPair, activeNetworkParameters, parametersUpdate = parametersUpdate.toParametersUpdate()) - - whenever(networkMapStorage.getNetworkMaps()).thenReturn(activeNetworkMaps) - whenever(networkMapStorage.getNodeInfoHashes()).thenReturn(NodeInfoHashes(emptyList(), emptyMap())) - whenever(networkMapStorage.getCurrentParametersUpdate()).thenReturn(null) - whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(createNetworkParametersEntity()) - - // when - networkMapSigner.signNetworkMaps() - - //then - argumentCaptor().apply { - verify(networkMapStorage).saveNewNetworkMap(anyOrNull(), capture()) - val netMap = firstValue.networkMap - assertEquals(SecureHash.parse(activeNetworkParameters.hash), netMap.networkParameterHash) - assertEquals(emptyList(), netMap.nodeInfoHashes) - assertEquals(null, netMap.parametersUpdate) - } - } -} diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/dev/DevGeneratorTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/dev/DevGeneratorTest.kt deleted file mode 100644 index 7f6f6baa08..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/dev/DevGeneratorTest.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.dev - -import net.corda.nodeapi.internal.crypto.X509KeyStore -import net.corda.nodeapi.internal.crypto.X509Utilities -import org.junit.Rule -import org.junit.Test -import org.junit.rules.TemporaryFolder -import java.io.File -import kotlin.test.assertTrue - -class DevGeneratorTest { - - @Rule - @JvmField - val tempFolder = TemporaryFolder() - - @Test - fun `key store and trust store are created and contain the certificates`() { - // given - val config = GeneratorConfiguration(directory = tempFolder.root.toPath()) - - // when - run(config) - - // then - val keyStoreFile = File("${config.directory}/${config.keyStoreFileName}").toPath() - val keyStore = X509KeyStore.fromFile(keyStoreFile, config.keyStorePass, createNew = true) - - assertTrue(X509Utilities.CORDA_INTERMEDIATE_CA in keyStore) - assertTrue(X509Utilities.CORDA_ROOT_CA in keyStore) - } -} \ No newline at end of file diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/dev/GeneratorConfigurationTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/dev/GeneratorConfigurationTest.kt deleted file mode 100644 index f72d8cd4eb..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/dev/GeneratorConfigurationTest.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.dev - -import com.r3.corda.networkmanage.common.configuration.ConfigFilePathArgsParser -import net.corda.nodeapi.internal.DEV_CA_KEY_STORE_FILE -import net.corda.nodeapi.internal.DEV_CA_KEY_STORE_PASS -import net.corda.nodeapi.internal.DEV_CA_TRUST_STORE_FILE -import net.corda.nodeapi.internal.DEV_CA_TRUST_STORE_PASS -import org.junit.Rule -import org.junit.Test -import org.junit.rules.TemporaryFolder -import java.io.File -import kotlin.test.assertEquals - -class GeneratorConfigurationTest { - - @Rule - @JvmField - val tempFolder = TemporaryFolder() - - private val configPath = File("dev-generator.conf").absolutePath - - @Test - fun `config file is parsed correctly`() { - val config = parseParameters(ConfigFilePathArgsParser().parseOrExit("--config-file", configPath)) - assertEquals(GeneratorConfiguration.DEFAULT_DIRECTORY, config.directory) - assertEquals(DEV_CA_KEY_STORE_FILE, config.keyStoreFileName) - assertEquals(DEV_CA_KEY_STORE_PASS, config.keyStorePass) - assertEquals(DEV_CA_TRUST_STORE_PASS, config.trustStorePass) - assertEquals(DEV_CA_TRUST_STORE_FILE, config.trustStoreFileName) - } -} \ No newline at end of file diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/CsrJiraClientTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/CsrJiraClientTest.kt deleted file mode 100644 index 185c5f0b31..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/CsrJiraClientTest.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman - -import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory -import net.corda.core.crypto.Crypto -import net.corda.core.crypto.SecureHash -import net.corda.core.identity.CordaX500Name -import net.corda.nodeapi.internal.crypto.X509Utilities -import org.junit.Before -import org.junit.Ignore -import org.junit.Test -import java.net.URI -import javax.security.auth.x500.X500Principal - -@Ignore -// This is manual test for testing Jira API. -class CsrJiraClientTest { - private lateinit var jiraClient: CsrJiraClient - @Before - fun init() { - val jiraWebAPI = AsynchronousJiraRestClientFactory().createWithBasicHttpAuthentication(URI("http://jira.url.com"), "username", "password") - jiraClient = CsrJiraClient(jiraWebAPI, "DOOR") - } - - @Test - fun createRequestTicket() { - val request = X509Utilities.createCertificateSigningRequest(CordaX500Name("JiraAPITest", "R3 Ltd 3", "London", "GB").x500Principal, "test@test.com", Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)) - jiraClient.createCertificateSigningRequestTicket(CertificationRequestData(SecureHash.randomSHA256().toString(), request)) - } - - @Test - fun getApprovedRequests() { - jiraClient.getApprovedRequests().forEach { println(it) } - } - - @Test - fun getRejectedRequests() { - val requests = jiraClient.getRejectedRequests() - requests.forEach { println(it) } - } - - @Test - fun updateSignedRequests() { - val selfSignedCaCertPath = X509Utilities.buildCertPath(X509Utilities.createSelfSignedCACertificate( - X500Principal("O=test,L=london,C=GB"), - Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME))) - jiraClient.getApprovedRequests().forEach { - val attachment = Pair("${X509Utilities.CORDA_CLIENT_CA}.cer", selfSignedCaCertPath.certificates.first().encoded.inputStream()) - jiraClient.transitRequestStatusToDone(it.requestId, attachment) - } - } - - @Test - fun updateRejectedRequests() { - jiraClient.getRejectedRequests().forEach { - jiraClient.updateRejectedRequest(it.requestId) - } - - assert(jiraClient.getRejectedRequests().isEmpty()) - } -} diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/DoormanArgsParserTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/DoormanArgsParserTest.kt deleted file mode 100644 index 3a287f4ae9..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/DoormanArgsParserTest.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman - -import joptsimple.OptionException -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.Test -import java.io.File -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith -import kotlin.test.assertNull - -class DoormanArgsParserTest { - private val validConfigPath = File("doorman.conf").absolutePath - private val argsParser = DoormanArgsParser() - - @Test - fun `should fail when network parameters file is missing`() { - assertThatThrownBy { - argsParser.parseOrExit("--config-file", validConfigPath, "--set-network-parameters", "not-here", - printHelpOn = null) - }.hasMessageContaining("not-here") - } - - @Test - fun `should fail when config file is missing`() { - assertThatThrownBy { - argsParser.parseOrExit("--config-file", "not-existing-file", printHelpOn = null) - }.hasMessageContaining("Specified config file doesn't exist") - } - - @Test - fun `should parse trust store password correctly`() { - val parameter = argsParser.parseOrExit("--config-file", validConfigPath, "--mode", "ROOT_KEYGEN", "--trust-store-password", "testPassword") - assertEquals("testPassword", parameter.trustStorePassword) - - assertFailsWith { - argsParser.parseOrExit("--trust-store-password", printHelpOn = null) - } - - // Should fail if password is provided in mode other then root keygen. - assertFailsWith { - argsParser.parseOrExit("--config-file", validConfigPath, "--trust-store-password", "testPassword", printHelpOn = null) - } - - // trust store password is optional. - assertNull(argsParser.parseOrExit("--config-file", validConfigPath, printHelpOn = null).trustStorePassword) - } -} diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/NetworkParametersCmdTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/NetworkParametersCmdTest.kt deleted file mode 100644 index 06d78ae59a..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/NetworkParametersCmdTest.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.r3.corda.networkmanage.doorman - -import com.r3.corda.networkmanage.toCmd -import net.corda.core.identity.CordaX500Name -import net.corda.core.identity.Party -import net.corda.core.node.NotaryInfo -import net.corda.testing.common.internal.testNetworkParameters -import net.corda.testing.core.ALICE_NAME -import net.corda.testing.core.BOB_NAME -import net.corda.testing.core.TestIdentity -import org.assertj.core.api.Assertions.assertThatExceptionOfType -import org.junit.Test - -class NetworkParametersCmdTest { - @Test - fun `maxTransactionSize cannot decrease`() { - val netParams = testNetworkParameters(maxTransactionSize = 100) - val netParamsCmd = netParams.toCmd() - assertThatExceptionOfType(IllegalArgumentException::class.java) - .isThrownBy { netParamsCmd.copy(maxTransactionSize = 99).checkCompatibility(netParams) } - .withMessageContaining("maxTransactionSize") - netParamsCmd.copy(maxTransactionSize = 100).checkCompatibility(netParams) - netParamsCmd.copy(maxTransactionSize = 101).checkCompatibility(netParams) - } - - @Test - fun `notary cannot be removed`() { - val alice = NotaryInfo(TestIdentity(ALICE_NAME).party, true) - val bob = NotaryInfo(TestIdentity(BOB_NAME).party, true) - val netParams = testNetworkParameters(notaries = listOf(alice, bob)) - val netParamsCmd = netParams.toCmd() - assertThatExceptionOfType(IllegalArgumentException::class.java) - .isThrownBy { netParamsCmd.copy(notaries = listOf(alice)).checkCompatibility(netParams) } - .withMessageContaining("notaries") - assertThatExceptionOfType(IllegalArgumentException::class.java) - .isThrownBy { netParamsCmd.copy(notaries = emptyList()).checkCompatibility(netParams) } - .withMessageContaining("notaries") - } - - @Test - fun `notary identity key cannot change`() { - val netParams = testNetworkParameters(notaries = listOf(NotaryInfo(freshParty(ALICE_NAME), true))) - val notaryKeyChanged = netParams.toCmd().copy(notaries = listOf(NotaryInfo(freshParty(ALICE_NAME), true))) - assertThatExceptionOfType(IllegalArgumentException::class.java) - .isThrownBy { notaryKeyChanged.checkCompatibility(netParams) } - .withMessageContaining("notaries") - } - - @Test - fun `notary name cannot change`() { - val identity = freshParty(ALICE_NAME) - val netParams = testNetworkParameters(notaries = listOf(NotaryInfo(identity, true))) - val notaryNameChanged = netParams.toCmd().copy(notaries = listOf(NotaryInfo(Party(BOB_NAME, identity.owningKey), true))) - assertThatExceptionOfType(IllegalArgumentException::class.java) - .isThrownBy { notaryNameChanged.checkCompatibility(netParams) } - .withMessageContaining("notaries") - } - - private fun freshParty(name: CordaX500Name) = TestIdentity(name).party -} \ No newline at end of file diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/NotaryConfigTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/NotaryConfigTest.kt deleted file mode 100644 index 04cc249cdd..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/NotaryConfigTest.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman - -import com.google.common.jimfs.Jimfs -import net.corda.core.internal.copyTo -import net.corda.core.serialization.serialize -import net.corda.testing.core.ALICE_NAME -import net.corda.testing.core.SerializationEnvironmentRule -import net.corda.testing.internal.createNodeInfoAndSigned -import org.assertj.core.api.Assertions.assertThat -import org.junit.After -import org.junit.Rule -import org.junit.Test -import java.util.* - -class NotaryConfigTest { - @Rule - @JvmField - val testSerialization = SerializationEnvironmentRule() - - private val fs = Jimfs.newFileSystem() - - @After - fun cleanUp() { - fs.close() - } - - @Test - fun toNotaryInfo() { - val (nodeInfo, signedNodeInfo) = createNodeInfoAndSigned(ALICE_NAME) - - val file = fs.getPath(UUID.randomUUID().toString()) - signedNodeInfo.serialize().open().copyTo(file) - - val notaryConfig = NotaryConfig(file, true) - val notaryInfo = notaryConfig.toNotaryInfo() - val nodeInfoFromFile = notaryConfig.nodeInfo - assertThat(nodeInfoFromFile).isEqualTo(nodeInfo) - assertThat(notaryInfo.identity).isEqualTo(nodeInfo.legalIdentities[0]) - assertThat(notaryInfo.validating).isTrue() - } -} diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/ParametersUpdateHandlerTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/ParametersUpdateHandlerTest.kt deleted file mode 100644 index 0ee01532e0..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/ParametersUpdateHandlerTest.kt +++ /dev/null @@ -1,168 +0,0 @@ -package com.r3.corda.networkmanage.doorman - -import com.nhaarman.mockito_kotlin.mock -import com.r3.corda.networkmanage.common.persistence.* -import com.r3.corda.networkmanage.toCmd -import com.typesafe.config.* -import net.corda.core.crypto.SecureHash -import net.corda.core.internal.* -import net.corda.core.node.NetworkParameters -import net.corda.core.serialization.serialize -import net.corda.core.utilities.days -import net.corda.nodeapi.internal.createDevNetworkMapCa -import net.corda.nodeapi.internal.network.NetworkMap -import net.corda.nodeapi.internal.network.NetworkMapAndSigned -import net.corda.nodeapi.internal.network.ParametersUpdate -import net.corda.nodeapi.internal.persistence.CordaPersistence -import net.corda.nodeapi.internal.persistence.DatabaseConfig -import net.corda.testing.common.internal.testNetworkParameters -import net.corda.testing.core.SerializationEnvironmentRule -import net.corda.testing.internal.createDevIntermediateCaCertPath -import net.corda.testing.internal.signWith -import net.corda.testing.node.MockServices -import org.assertj.core.api.Assertions -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.rules.TemporaryFolder -import java.nio.file.Path -import java.time.Instant -import java.util.* - -class ParametersUpdateHandlerTest { - @Rule - @JvmField - val testSerialization = SerializationEnvironmentRule() - @Rule - @JvmField - val tempFolder = TemporaryFolder() - - private lateinit var persistence: CordaPersistence - private lateinit var csrStorage: CertificateSigningRequestStorage - private lateinit var netParamsUpdateHandler: ParametersUpdateHandler - private lateinit var networkMapStorage: PersistentNetworkMapStorage - - @Before - fun init() { - persistence = configureDatabase(MockServices.makeTestDataSourceProperties(), DatabaseConfig(runMigration = true)) - csrStorage = PersistentCertificateSigningRequestStorage(persistence) - networkMapStorage = PersistentNetworkMapStorage(persistence) - netParamsUpdateHandler = ParametersUpdateHandler(csrStorage, networkMapStorage) - } - - @After - fun cleanUp() { - persistence.close() - } - - @Test - fun `load parameters from file and check notaries registered`() { - // Create identities and put them into CertificateSigningStorage - val (nodeInfo1, keys1) = createValidNodeInfo(csrStorage, CertRole.NODE_CA to "Alice", CertRole.SERVICE_IDENTITY to "Alice Notary") - val (nodeInfo2, keys2) = createValidNodeInfo(csrStorage, CertRole.NODE_CA to "Bob Notary") - val signedNodeInfo1 = nodeInfo1.signWith(keys1) - val signedNodeInfo2 = nodeInfo2.signWith(keys2) - val notaryFile1 = tempFolder.root.toPath() / UUID.randomUUID().toString() - val notaryFile2 = tempFolder.root.toPath() / UUID.randomUUID().toString() - signedNodeInfo1.serialize().open().copyTo(notaryFile1) - signedNodeInfo2.serialize().open().copyTo(notaryFile2) - val configFile = tempFolder.root.toPath() / UUID.randomUUID().toString() - saveConfig(configFile, listOf(notaryFile1, notaryFile2)) - val cmd = netParamsUpdateHandler.loadParametersFromFile(configFile) - assertThat(cmd.notaries.map { it.identity }).containsExactly(nodeInfo1.legalIdentities.last(), nodeInfo2.legalIdentities.last()) - } - - @Test - fun `notaries not registered`() { - // Create notary NodeInfo with SERVICE_IDENTITY role but don't put in CertificateSigningStorage - val (nodeInfo, keys) = createValidNodeInfo(mock(), CertRole.NODE_CA to "Alice", CertRole.SERVICE_IDENTITY to "Alice Notary") - val signedNodeInfo = nodeInfo.signWith(keys) - val notaryFile = tempFolder.root.toPath() / UUID.randomUUID().toString() - signedNodeInfo.serialize().open().copyTo(notaryFile) - val configFile = tempFolder.root.toPath() / UUID.randomUUID().toString() - saveConfig(configFile, listOf(notaryFile)) - Assertions.assertThatThrownBy {netParamsUpdateHandler.loadParametersFromFile(configFile)} - .isInstanceOf(IllegalArgumentException::class.java) - .hasMessageContaining("is not registered with the doorman") - } - - @Test - fun `set twice initial parameters`() { - val testParams = testNetworkParameters() - val setInitialCmd = testParams.toCmd() - netParamsUpdateHandler.processNetworkParameters(setInitialCmd) - val testParams2 = testParams.copy(minimumPlatformVersion = 7) - netParamsUpdateHandler.processNetworkParameters(testParams2.toCmd()) - assertThat(networkMapStorage.getLatestNetworkParameters()!!.networkParameters.minimumPlatformVersion).isEqualTo(7) - assertThatThrownBy { netParamsUpdateHandler.processNetworkParameters( - testParams2.toCmd(parametersUpdate = ParametersUpdateConfig("It needs changing. Now!", updateDeadline = Instant.now()))) - }.hasMessageContaining("'parametersUpdate' specified in network parameters file but there are no network parameters to update") - } - - @Test - fun `cancel parameters and then set the same`() { - loadInitialParams() - val paramsForUpdate = testNetworkParameters(minimumPlatformVersion = 101) - val updateDeadline1 = Instant.now() + 10.days - val updateParamsCmd = paramsForUpdate.toCmd(ParametersUpdateConfig("Update", updateDeadline1)) - netParamsUpdateHandler.processNetworkParameters(updateParamsCmd) - val cancelCmd = NetworkParametersCmd.CancelUpdate - netParamsUpdateHandler.processNetworkParameters(cancelCmd) - // Use just cancelled parameters - netParamsUpdateHandler.processNetworkParameters(updateParamsCmd) - } - - @Test - fun `set parameters update and then change update deadline`() { - loadInitialParams() - val paramsForUpdate = testNetworkParameters(minimumPlatformVersion = 101) - val updateDeadline1 = Instant.now() + 10.days - val updateParamsCmd = paramsForUpdate.toCmd(ParametersUpdateConfig("Update", updateDeadline1)) - netParamsUpdateHandler.processNetworkParameters(updateParamsCmd) - // Just change description - netParamsUpdateHandler.processNetworkParameters(paramsForUpdate.toCmd(ParametersUpdateConfig("Update again", updateDeadline1))) - // Just change update deadline - netParamsUpdateHandler.processNetworkParameters(paramsForUpdate.toCmd(ParametersUpdateConfig("Update again", updateDeadline1 + 10.days))) - } - - @Test - fun `try to change active update`() { - val paramsForUpdate = testNetworkParameters(minimumPlatformVersion = 101) - val updateDeadline = Instant.now() + 10.days - val description = "Update" - val paramsUpdate = ParametersUpdate(paramsForUpdate.serialize().hash, description, updateDeadline) - loadInitialParams(parametersUpdate = paramsUpdate) - networkMapStorage.saveNetworkParameters(paramsForUpdate, null) - val updateParamsCmd = paramsForUpdate.toCmd(ParametersUpdateConfig(description, updateDeadline)) - assertThatThrownBy { netParamsUpdateHandler.processNetworkParameters(updateParamsCmd) } - .hasMessageContaining("New network parameters are the same as the latest ones") - } - - // Load initial parameters to db and sign them, set them to be in active network map. - private fun loadInitialParams(params: NetworkParameters = testNetworkParameters(), parametersUpdate: ParametersUpdate? = null) { - val (rootCa) = createDevIntermediateCaCertPath() - val networkMapCertAndKeyPair = createDevNetworkMapCa(rootCa) - val networkParametersSig = networkMapCertAndKeyPair.sign(params).sig - val networkParametersHash = networkMapStorage.saveNetworkParameters(params, networkParametersSig).hash - val networkMap = NetworkMap(emptyList(), SecureHash.parse(networkParametersHash), parametersUpdate) - val networkMapAndSigned = NetworkMapAndSigned(networkMap) { networkMapCertAndKeyPair.sign(networkMap).sig } - networkMapStorage.saveNewNetworkMap(networkMapAndSigned = networkMapAndSigned) - } - - private fun saveConfig(configFile: Path, notaryFiles: List) { - val config = ConfigValueFactory.fromMap( - mapOf("minimumPlatformVersion" to 1, - "maxMessageSize" to 10485760, - "maxTransactionSize" to 10485760, - "notaries" to notaryFiles.map { mapOf("notaryNodeInfoFile" to it.toString(), "validating" to true) }, - "eventHorizonDays" to 7 - ) - - ).toConfig() - val configString = config.root().render(ConfigRenderOptions.defaults()) - configFile.writeText(configString) - } -} diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/signer/DefaultCsrHandlerTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/signer/DefaultCsrHandlerTest.kt deleted file mode 100644 index 8218c3ebdd..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/signer/DefaultCsrHandlerTest.kt +++ /dev/null @@ -1,141 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.signer - -import com.nhaarman.mockito_kotlin.* -import com.r3.corda.networkmanage.TestBase -import com.r3.corda.networkmanage.common.persistence.CertificateResponse -import com.r3.corda.networkmanage.common.persistence.CertificateStatus -import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequestStorage -import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequestStorage.Companion.DOORMAN_SIGNATURE -import com.r3.corda.networkmanage.common.persistence.RequestStatus -import com.r3.corda.networkmanage.common.utils.CertPathAndKey -import net.corda.core.crypto.Crypto -import net.corda.core.internal.CertRole -import net.corda.nodeapi.internal.crypto.X509Utilities -import net.corda.nodeapi.internal.crypto.x509Certificates -import net.corda.testing.internal.createDevIntermediateCaCertPath -import org.assertj.core.api.Assertions.assertThat -import org.junit.Test -import java.security.cert.CertPath -import java.security.cert.X509Certificate -import javax.security.auth.x500.X500Principal -import kotlin.test.assertEquals - -class DefaultCsrHandlerTest : TestBase() { - @Test - fun getResponse() { - val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) - val cert = X509Utilities.createSelfSignedCACertificate(X500Principal("O=Test,L=London,C=GB"), keyPair) - - val requestStorage: CertificateSigningRequestStorage = mock { - on { getRequest("New") }.thenReturn(certificateSigningRequest()) - on { getRequest("Signed") }.thenReturn(certificateSigningRequest( - status = RequestStatus.DONE, - certData = certificateData(CertificateStatus.VALID, X509Utilities.buildCertPath(cert)) - )) - on { getRequest("Rejected") }.thenReturn(certificateSigningRequest(status = RequestStatus.REJECTED, remark = "Random reason")) - } - val requestProcessor = DefaultCsrHandler(requestStorage, null) - - assertEquals(CertificateResponse.NotReady, requestProcessor.getResponse("random")) - assertEquals(CertificateResponse.NotReady, requestProcessor.getResponse("New")) - assertEquals(CertificateResponse.Ready(X509Utilities.buildCertPath(cert)), requestProcessor.getResponse("Signed")) - assertEquals(CertificateResponse.Unauthorised("Random reason"), requestProcessor.getResponse("Rejected")) - } - - @Test - fun processApprovedRequests() { - val requests = (1..3).map { - X509Utilities.createCertificateSigningRequest( - X500Principal("O=Test$it,L=London,C=GB"), - "my@email.com", - Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)) - } - - val requestStorage: CertificateSigningRequestStorage = mock { - on { getRequests(RequestStatus.APPROVED) }.thenReturn(listOf( - certificateSigningRequest(requestId = "1", request = requests[0], status = RequestStatus.APPROVED), - certificateSigningRequest(requestId = "2", request = requests[1], status = RequestStatus.APPROVED) - )) - on { getRequests(RequestStatus.REJECTED) }.thenReturn(listOf( - certificateSigningRequest(requestId = "3", request = requests[2], status = RequestStatus.REJECTED) - )) - } - - val (rootCa, csrCa) = createDevIntermediateCaCertPath() - val csrCertPathAndKey = CertPathAndKey(listOf(csrCa.certificate, rootCa.certificate), csrCa.keyPair.private) - val requestProcessor = DefaultCsrHandler(requestStorage, csrCertPathAndKey) - - requestProcessor.processRequests() - - val certPathCapture = argumentCaptor() - - // Verify only the approved requests are taken - verify(requestStorage, times(1)).getRequests(RequestStatus.APPROVED) - verify(requestStorage, times(1)).putCertificatePath(eq("1"), certPathCapture.capture(), eq(DOORMAN_SIGNATURE)) - verify(requestStorage, times(1)).putCertificatePath(eq("2"), certPathCapture.capture(), eq(DOORMAN_SIGNATURE)) - - // Then make sure the generated node cert paths are correct - certPathCapture.allValues.forEachIndexed { index, certPath -> - X509Utilities.validateCertificateChain(rootCa.certificate, certPath.x509Certificates) - assertThat(certPath.certificates).hasSize(3).element(1).isEqualTo(csrCa.certificate) - (certPath.certificates[0] as X509Certificate).apply { - assertThat(CertRole.extract(this)).isEqualTo(CertRole.NODE_CA) - assertThat(publicKey).isEqualTo(Crypto.toSupportedPublicKey(requests[index].subjectPublicKeyInfo)) - assertThat(subjectX500Principal).isEqualTo(X500Principal("O=Test${index + 1},L=London,C=GB")) - // Is CA - assertThat(basicConstraints != -1) - } - } - } - - @Test - fun `process approved service identity request`() { - val requests = (1..3).map { - X509Utilities.createCertificateSigningRequest( - X500Principal("O=Test$it,L=London,C=GB"), - "my@email.com", - Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME), certRole = CertRole.SERVICE_IDENTITY) - } - - val requestStorage: CertificateSigningRequestStorage = mock { - on { getRequests(RequestStatus.APPROVED) }.thenReturn(listOf( - certificateSigningRequest(requestId = "1", request = requests[0], status = RequestStatus.APPROVED) - )) - } - - val (rootCa, csrCa) = createDevIntermediateCaCertPath() - val csrCertPathAndKey = CertPathAndKey(listOf(csrCa.certificate, rootCa.certificate), csrCa.keyPair.private) - val requestProcessor = DefaultCsrHandler(requestStorage, csrCertPathAndKey) - - requestProcessor.processRequests() - - val certPathCapture = argumentCaptor() - - // Verify only the approved requests are taken - verify(requestStorage, times(1)).getRequests(RequestStatus.APPROVED) - verify(requestStorage, times(1)).putCertificatePath(eq("1"), certPathCapture.capture(), eq(DOORMAN_SIGNATURE)) - - // Then make sure the generated node cert paths are correct - certPathCapture.allValues.forEachIndexed { index, certPath -> - X509Utilities.validateCertificateChain(rootCa.certificate, certPath.x509Certificates) - assertThat(certPath.certificates).hasSize(3).element(1).isEqualTo(csrCa.certificate) - (certPath.certificates[0] as X509Certificate).apply { - assertThat(CertRole.extract(this)).isEqualTo(CertRole.SERVICE_IDENTITY) - assertThat(publicKey).isEqualTo(Crypto.toSupportedPublicKey(requests[index].subjectPublicKeyInfo)) - assertThat(subjectX500Principal).isEqualTo(X500Principal("O=Test${index + 1},L=London,C=GB")) - // Not a CA - assertThat(basicConstraints == -1) - } - } - } -} diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/signer/JiraCsrHandlerTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/signer/JiraCsrHandlerTest.kt deleted file mode 100644 index 4f34badf63..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/signer/JiraCsrHandlerTest.kt +++ /dev/null @@ -1,161 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.signer - -import com.nhaarman.mockito_kotlin.* -import com.r3.corda.networkmanage.TestBase -import com.r3.corda.networkmanage.common.persistence.* -import com.r3.corda.networkmanage.doorman.ApprovedRequest -import com.r3.corda.networkmanage.doorman.CertificationRequestData -import com.r3.corda.networkmanage.doorman.CsrJiraClient -import com.r3.corda.networkmanage.doorman.RejectedRequest -import net.corda.core.crypto.Crypto -import net.corda.core.crypto.SecureHash -import net.corda.core.identity.CordaX500Name -import net.corda.nodeapi.internal.crypto.X509Utilities -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.mockito.Mock -import org.mockito.junit.MockitoJUnit -import org.mockito.junit.MockitoRule -import java.security.cert.CertPath -import kotlin.test.assertEquals - -class JiraCsrHandlerTest : TestBase() { - @Rule - @JvmField - val mockitoRule: MockitoRule = MockitoJUnit.rule() - - @Mock - private lateinit var jiraClient: CsrJiraClient - - @Mock - private lateinit var certificationRequestStorage: CertificateSigningRequestStorage - - @Mock - private lateinit var defaultCsrHandler: DefaultCsrHandler - - @Mock - private val certPath: CertPath = mock() - - private lateinit var jiraCsrHandler: JiraCsrHandler - private val requestId = "id" - private lateinit var certificateResponse: CertificateResponse.Ready - - private val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) - private val pkcS10CertificationRequest = X509Utilities.createCertificateSigningRequest( - CordaX500Name(locality = "London", organisation = "LegalName", country = "GB").x500Principal, - "my@mail.com", - keyPair) - - @Before - fun setup() { - jiraCsrHandler = JiraCsrHandler(jiraClient, certificationRequestStorage, defaultCsrHandler) - certificateResponse = CertificateResponse.Ready(certPath) - } - - @Test - fun `If jira connection fails we don't mark the ticket as created`() { - whenever(defaultCsrHandler.saveRequest(any())).thenReturn(requestId) - whenever(defaultCsrHandler.getResponse(requestId)).thenReturn(certificateResponse) - whenever(jiraClient.createCertificateSigningRequestTicket(any())).thenThrow(IllegalStateException("something broke")) - - // Test - jiraCsrHandler.saveRequest(pkcS10CertificationRequest) - - verify(certificationRequestStorage, never()).markRequestTicketCreated(requestId) - } - - @Test - fun `If jira connection works we mark the ticket as created`() { - whenever(defaultCsrHandler.saveRequest(any())).thenReturn(requestId) - whenever(defaultCsrHandler.getResponse(requestId)).thenReturn(certificateResponse) - - // Test - jiraCsrHandler.saveRequest(pkcS10CertificationRequest) - - verify(certificationRequestStorage, times(1)).markRequestTicketCreated(requestId) - } - - @Test - fun `create tickets`() { - val csr = certificateSigningRequest( - requestId = requestId, - legalName = CordaX500Name.parse("O=Test Org., C=GB, L=London"), - status = RequestStatus.NEW, - request = pkcS10CertificationRequest) - whenever(certificationRequestStorage.getRequests(RequestStatus.NEW)).thenReturn(listOf(csr)) - // Test - jiraCsrHandler.processRequests() - - verify(jiraClient).createCertificateSigningRequestTicket(CertificationRequestData(requestId, csr.request)) - verify(certificationRequestStorage).markRequestTicketCreated(requestId) - } - - @Test - fun `sync tickets status`() { - val id1 = SecureHash.randomSHA256().toString() - val id2 = SecureHash.randomSHA256().toString() - val csr1 = CertificateSigningRequest(id1, CordaX500Name.parse("O=Test1 Org., C=GB, L=London"), SecureHash.randomSHA256(), RequestStatus.NEW, pkcS10CertificationRequest, null, "Test", null) - val csr2 = CertificateSigningRequest(id2, CordaX500Name.parse("O=Test2 Org., C=GB, L=London"), SecureHash.randomSHA256(), RequestStatus.NEW, pkcS10CertificationRequest, null, "Test", null) - - val requests = mutableMapOf(id1 to csr1, id2 to csr2) - - // Mocking storage behaviour. - whenever(certificationRequestStorage.getRequests(RequestStatus.NEW)).thenReturn(requests.values.filter { it.status == RequestStatus.NEW }) - whenever(certificationRequestStorage.getRequest(any())).thenAnswer { requests[it.getArgument(0)] } - whenever(certificationRequestStorage.approveRequest(any(), any())).then { - val id = it.getArgument(0) - if (requests[id]?.status == RequestStatus.NEW) { - requests[id] = requests[id]!!.copy(status = RequestStatus.APPROVED, modifiedBy = it.getArgument(1)) - } - null - } - whenever(certificationRequestStorage.rejectRequest(any(), any(), any())).then { - val id = it.getArgument(0) - requests[id] = requests[id]!!.copy(status = RequestStatus.REJECTED, modifiedBy = it.getArgument(1), remark = it.getArgument(2)) - null - } - - // Status change from jira. - whenever(jiraClient.getApprovedRequests()).thenReturn(listOf(ApprovedRequest(id1, "Me"))) - whenever(jiraClient.getRejectedRequests()).thenReturn(listOf(RejectedRequest(id2, "Me", "Test reject"))) - - // Test. - jiraCsrHandler.processRequests() - - verify(jiraClient).createCertificateSigningRequestTicket(CertificationRequestData(id1, csr1.request)) - verify(jiraClient).createCertificateSigningRequestTicket(CertificationRequestData(id2, csr2.request)) - - verify(certificationRequestStorage).markRequestTicketCreated(id1) - verify(certificationRequestStorage).markRequestTicketCreated(id2) - - // Verify request has the correct status in DB. - assertEquals(RequestStatus.APPROVED, requests[id1]!!.status) - assertEquals(RequestStatus.REJECTED, requests[id2]!!.status) - - // Verify jira client get the correct call. - verify(jiraClient).updateRejectedRequest(id2) - verify(jiraClient, never()).transitRequestStatusToDone(any(), anyOrNull()) - - // Sign request 1 - val certPath = mock() - val certData = CertificateData(CertificateStatus.VALID, certPath) - requests[id1] = requests[id1]!!.copy(status = RequestStatus.DONE, certData = certData) - - // Process request again. - jiraCsrHandler.processRequests() - - // Update signed request should be called. - verify(jiraClient).transitRequestStatusToDone(eq(id1), anyOrNull()) - } -} diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/sockets/CertificateRevocationSocketServerTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/sockets/CertificateRevocationSocketServerTest.kt deleted file mode 100644 index 67122880d9..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/sockets/CertificateRevocationSocketServerTest.kt +++ /dev/null @@ -1,126 +0,0 @@ -package com.r3.corda.networkmanage.doorman.sockets - -import com.nhaarman.mockito_kotlin.eq -import com.nhaarman.mockito_kotlin.mock -import com.r3.corda.networkmanage.common.persistence.* -import com.r3.corda.networkmanage.common.sockets.CrlResponseMessage -import com.r3.corda.networkmanage.common.sockets.CrlRetrievalMessage -import com.r3.corda.networkmanage.common.sockets.CrrsByStatusMessage -import com.r3.corda.networkmanage.common.utils.readObject -import com.r3.corda.networkmanage.common.utils.writeObject -import net.corda.core.crypto.Crypto -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.x500Name -import net.corda.nodeapi.internal.createDevNodeCa -import net.corda.nodeapi.internal.crypto.ContentSignerBuilder -import net.corda.testing.core.SerializationEnvironmentRule -import net.corda.testing.core.freePort -import net.corda.testing.internal.DEV_INTERMEDIATE_CA -import org.bouncycastle.cert.X509v2CRLBuilder -import org.bouncycastle.cert.jcajce.JcaX509CRLConverter -import org.bouncycastle.jce.provider.BouncyCastleProvider -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import java.math.BigInteger -import java.net.Socket -import java.security.cert.CRLReason -import java.security.cert.X509CRL -import java.time.Instant -import java.util.* -import kotlin.test.assertEquals -import kotlin.test.assertNotNull - -class CertificateRevocationSocketServerTest { - - @Rule - @JvmField - val testSerialization = SerializationEnvironmentRule(true) - - private lateinit var crlStorage: CertificateRevocationListStorage - private lateinit var crrStorage: CertificateRevocationRequestStorage - private lateinit var server: CertificateRevocationSocketServer - - @Before - fun setUp() { - crlStorage = mock { - on { getCertificateRevocationList(eq(CrlIssuer.DOORMAN)) }.then { createCrl() } - } - crrStorage = mock { - on { getRevocationRequests(eq(RequestStatus.APPROVED)) }.then { listOf(createCertificateRevocationRequest(RequestStatus.APPROVED)) } - on { getRevocationRequests(eq(RequestStatus.DONE)) }.then { listOf(createCertificateRevocationRequest(RequestStatus.DONE)) } - } - server = CertificateRevocationSocketServer(freePort(), crlStorage, crrStorage) - server.start() - Thread.sleep(100) - } - - @After - fun tearDown() { - server.close() - } - - @Test - fun `crl is served correctly`() { - // given - - // when - val crl = Socket("localhost", server.port).use { - it.getOutputStream().writeObject(CrlRetrievalMessage()) - it.getInputStream().readObject().crl - } - - // then - assertNotNull(crl) - } - - @Test - fun `approved requests are served correctly`() { - // given - - // when - val approvedRequests = Socket("localhost", server.port).use { - it.getOutputStream().writeObject(CrrsByStatusMessage(RequestStatus.APPROVED)) - it.getInputStream().readObject>() - } - // then - assertNotNull(approvedRequests) - assertEquals(RequestStatus.APPROVED, approvedRequests.first().status) - } - - @Test - fun `done requests are served correctly`() { - // given - - // when - val doneRequests = Socket("localhost", server.port).use { - it.getOutputStream().writeObject(CrrsByStatusMessage(RequestStatus.DONE)) - it.getInputStream().readObject>() - } - // then - assertNotNull(doneRequests) - assertEquals(RequestStatus.DONE, doneRequests.first().status) - } - - private fun createCrl(): X509CRL { - val builder = X509v2CRLBuilder(CordaX500Name.build(DEV_INTERMEDIATE_CA.certificate.issuerX500Principal).x500Name, Date()) - val provider = BouncyCastleProvider() - val crlHolder = builder.build(ContentSignerBuilder.build(Crypto.RSA_SHA256, Crypto.generateKeyPair(Crypto.RSA_SHA256).private, provider)) - return JcaX509CRLConverter().setProvider(provider).getCRL(crlHolder) - } - - private fun createCertificateRevocationRequest(status: RequestStatus): CertificateRevocationRequestData { - return CertificateRevocationRequestData( - requestId = "123", - legalName = CordaX500Name.parse("CN=Test Corp, O=Test, L=London, C=GB"), - reporter = "Test", - certificateSerialNumber = BigInteger.TEN, - status = status, - reason = CRLReason.KEY_COMPROMISE, - modifiedAt = Instant.now(), - certificateSigningRequestId = "CSR-ID", - certificate = createDevNodeCa(DEV_INTERMEDIATE_CA, CordaX500Name.parse("O=R3Cev, L=London, C=GB")).certificate - ) - } -} \ No newline at end of file diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/webservice/MonitoringWebServiceTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/webservice/MonitoringWebServiceTest.kt deleted file mode 100644 index dbbe7aeb00..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/webservice/MonitoringWebServiceTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.webservice - -import com.r3.corda.networkmanage.doorman.NetworkManagementServerStatus -import com.r3.corda.networkmanage.doorman.NetworkManagementWebServer -import net.corda.core.internal.openHttpConnection -import net.corda.core.utilities.NetworkHostAndPort -import org.codehaus.jackson.map.ObjectMapper -import org.junit.Test -import java.net.URL -import kotlin.test.assertEquals - -class MonitoringWebServiceTest { - @Test - fun `get server status`() { - val status = NetworkManagementServerStatus() - val jsonStatus = ObjectMapper().writeValueAsString(status) - NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), MonitoringWebService(status)).use { - it.start() - val conn = URL("http://${it.hostAndPort}/status").openHttpConnection() - assertEquals(200, conn.responseCode) - assertEquals(jsonStatus, conn.inputStream.bufferedReader().readLine()) - } - } -} \ No newline at end of file diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/webservice/NetworkMapWebServiceTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/webservice/NetworkMapWebServiceTest.kt deleted file mode 100644 index 1346e1a6e3..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/webservice/NetworkMapWebServiceTest.kt +++ /dev/null @@ -1,303 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.webservice - -import com.nhaarman.mockito_kotlin.* -import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequestStorage -import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage -import com.r3.corda.networkmanage.common.persistence.NodeInfoStorage -import com.r3.corda.networkmanage.createNetworkMaps -import com.r3.corda.networkmanage.doorman.NetworkManagementWebServer -import com.r3.corda.networkmanage.doorman.NetworkMapConfig -import net.corda.core.crypto.Crypto -import net.corda.core.crypto.SecureHash -import net.corda.core.crypto.SecureHash.Companion.randomSHA256 -import net.corda.core.crypto.SignedData -import net.corda.core.crypto.sign -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.openHttpConnection -import net.corda.core.internal.post -import net.corda.core.internal.responseAs -import net.corda.core.internal.sign -import net.corda.core.serialization.serialize -import net.corda.core.utilities.NetworkHostAndPort -import net.corda.core.utilities.OpaqueBytes -import net.corda.core.utilities.seconds -import net.corda.nodeapi.internal.SignedNodeInfo -import net.corda.nodeapi.internal.createDevNetworkMapCa -import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair -import net.corda.nodeapi.internal.network.SignedNetworkMap -import net.corda.nodeapi.internal.network.SignedNetworkParameters -import net.corda.nodeapi.internal.network.verifiedNetworkMapCert -import net.corda.testing.common.internal.testNetworkParameters -import net.corda.testing.core.SerializationEnvironmentRule -import net.corda.testing.internal.createDevIntermediateCaCertPath -import net.corda.testing.internal.createNodeInfoAndSigned -import org.assertj.core.api.Assertions.* -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import java.io.IOException -import java.net.URL -import java.security.cert.X509Certificate -import java.time.Duration -import java.time.Instant -import java.time.ZoneId -import java.time.format.DateTimeFormatter -import kotlin.collections.component1 -import kotlin.collections.component2 -import kotlin.collections.first -import kotlin.collections.forEach -import kotlin.collections.listOf -import kotlin.collections.mapOf -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith - -class NetworkMapWebServiceTest { - @Rule - @JvmField - val testSerialization = SerializationEnvironmentRule(true) - - private lateinit var rootCaCert: X509Certificate - private lateinit var signingCertAndKeyPair: CertificateAndKeyPair - - private val testNetworkMapConfig = NetworkMapConfig(10.seconds.toMillis(), 10.seconds.toMillis()) - - @Before - fun init() { - val (rootCa) = createDevIntermediateCaCertPath() - rootCaCert = rootCa.certificate - signingCertAndKeyPair = createDevNetworkMapCa(rootCa) - } - - @Test - fun `submit nodeInfo`() { - // Create node info. - val (_, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name("Test", "London", "GB")) - val networkMapStorage: NetworkMapStorage = mock { - on { getNetworkMaps() }.thenReturn(createNetworkMaps()) - } - val csrStorage: CertificateSigningRequestStorage = mock { - on { getValidCertificatePath(any()) }.thenReturn(signedNodeInfo.verified().legalIdentitiesAndCerts.first().certPath) - } - - NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NetworkMapWebService(mock(), networkMapStorage, csrStorage, testNetworkMapConfig)).use { - it.start() - // Post node info and signature to doorman, this should pass without any exception. - it.doPost("publish", signedNodeInfo.serialize()) - } - } - - @Test - fun `submit nodeInfo with an unknown public key fails`() { - // Create node info. - val (_, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name("Test", "London", "GB")) - val networkMapStorage: NetworkMapStorage = mock { - on { getNetworkMaps() }.thenReturn(createNetworkMaps()) - } - val csrStorage: CertificateSigningRequestStorage = mock { - on { getValidCertificatePath(any()) }.thenReturn(null) - } - - NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NetworkMapWebService(mock(), networkMapStorage, csrStorage, testNetworkMapConfig)).use { - it.start() - // Post node info and signature to doorman, this should pass without any exception. - assertFailsWith("Response Code 400") { - it.doPost("publish", signedNodeInfo.serialize()) - } - } - } - - @Test - fun `submit old nodeInfo`() { - // Create node info. - val (_, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name("Test", "London", "GB"), platformVersion = 1) - val networkMapStorage: NetworkMapStorage = mock { - on { getNetworkMaps() }.thenReturn(createNetworkMaps(networkParameters = testNetworkParameters(minimumPlatformVersion = 2))) - } - val csrStorage: CertificateSigningRequestStorage = mock { - on { getValidCertificatePath(any()) }.thenReturn(signedNodeInfo.verified().legalIdentitiesAndCerts.first().certPath) - } - - NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NetworkMapWebService(mock(), networkMapStorage, csrStorage, testNetworkMapConfig)).use { - it.start() - assertThatThrownBy { it.doPost("publish", signedNodeInfo.serialize()) } - .hasMessageStartingWith("Response Code 400: Minimum platform version is 2") - } - } - - @Test - fun `submit nodeInfo when no network map`() { - // Create node info. - val (_, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name("Test", "London", "GB"), platformVersion = 1) - val networkMapStorage: NetworkMapStorage = mock { - on { getNetworkMaps() }.thenReturn(null) - } - val csrStorage: CertificateSigningRequestStorage = mock { - on { getValidCertificatePath(any()) }.thenReturn(signedNodeInfo.verified().legalIdentitiesAndCerts.first().certPath) - } - - NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NetworkMapWebService(mock(), networkMapStorage, csrStorage, testNetworkMapConfig)).use { - it.start() - assertThatThrownBy { it.doPost("publish", signedNodeInfo.serialize()) } - .hasMessageStartingWith("Response Code 503: Network parameters have not been initialised") - } - } - - @Test - fun `get network map`() { - val networkMaps = createNetworkMaps( - signingCertAndKeyPair = signingCertAndKeyPair, - nodeInfoHashes = listOf(randomSHA256(), randomSHA256())) - - val networkMapStorage: NetworkMapStorage = mock { - on { getNetworkMaps() }.thenReturn(networkMaps) - } - - NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NetworkMapWebService(mock(), networkMapStorage, mock(), testNetworkMapConfig)).use { - it.start() - val signedNetworkMapResponse = it.doGet("") - verify(networkMapStorage, times(1)).getNetworkMaps() - assertEquals(signedNetworkMapResponse.verifiedNetworkMapCert(rootCaCert), networkMaps.publicNetworkMap!!.networkMap) - } - } - - @Test - fun `network map response contains correct http header parameter`() { - val timestamp = Instant.now() - val networkMaps = createNetworkMaps( - signingCertAndKeyPair = signingCertAndKeyPair, - nodeInfoHashes = listOf(randomSHA256(), randomSHA256()), - timestamp = timestamp) - - val networkMapStorage: NetworkMapStorage = mock { - on { getNetworkMaps() }.thenReturn(networkMaps) - } - - NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NetworkMapWebService(mock(), networkMapStorage, mock(), testNetworkMapConfig)).use { - it.start() - val headers = URL("http://${it.hostAndPort}/network-map/").openHttpConnection().headerFields - assertEquals("max-age=${Duration.ofMillis(testNetworkMapConfig.cacheTimeout).seconds}", headers["Cache-Control"]?.first()) - assertEquals(DateTimeFormatter.RFC_1123_DATE_TIME.withZone(ZoneId.of("GMT")).format(timestamp), headers["Last-Modified"]?.first()) - } - } - - @Test - fun `get private network map`() { - val publicNodeInfoHashes = listOf(randomSHA256(), randomSHA256()) - val privateNodeInfoHashes = mapOf("PrivateNet1" to listOf(randomSHA256(), randomSHA256()), "PrivateNet2" to listOf(randomSHA256(), randomSHA256())) - - val networkMaps = createNetworkMaps( - signingCertAndKeyPair = signingCertAndKeyPair, - nodeInfoHashes = publicNodeInfoHashes, - privateNodeInfoHashes = privateNodeInfoHashes - ) - - val networkMapStorage: NetworkMapStorage = mock { - on { getNetworkMaps() }.thenReturn(networkMaps) - } - - NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NetworkMapWebService(mock(), networkMapStorage, mock(), testNetworkMapConfig)).use { - it.start() - val signedNetworkMapResponse = it.doGet("") - verify(networkMapStorage, times(1)).getNetworkMaps() - assertEquals(signedNetworkMapResponse.verifiedNetworkMapCert(rootCaCert), networkMaps.publicNetworkMap!!.networkMap) - - networkMaps.privateNetworkMap.forEach { (key, privateNetworkMapEntity) -> - val response = it.doGet(key) - // Result cached. - verify(networkMapStorage, times(1)).getNetworkMaps() - assertEquals(response.verifiedNetworkMapCert(rootCaCert), privateNetworkMapEntity.networkMap) - } - } - } - - @Test - fun `get node info`() { - // Mock node info storage - val (nodeInfo, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name("Test", "London", "GB")) - val nodeInfoHash = nodeInfo.serialize().hash - val nodeInfoStorage: NodeInfoStorage = mock { - on { getNodeInfo(nodeInfoHash) }.thenReturn(signedNodeInfo) - } - - // Mock network map storage - val networkMapStorage: NetworkMapStorage = mock { - on { getNetworkMaps() }.thenReturn(createNetworkMaps(nodeInfoHashes = listOf(nodeInfoHash))) - } - - NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NetworkMapWebService(nodeInfoStorage, networkMapStorage, mock(), testNetworkMapConfig)).use { - it.start() - val nodeInfoResponse = it.doGet("node-info/$nodeInfoHash") - verify(nodeInfoStorage, times(1)).getNodeInfo(nodeInfoHash) - assertEquals(nodeInfo, nodeInfoResponse.verified()) - - assertThatExceptionOfType(IOException::class.java) - .isThrownBy { it.doGet("node-info/${randomSHA256()}") } - .withMessageContaining("404") - } - } - - @Test - fun `get network parameters`() { - val networkParameters = testNetworkParameters() - val signedNetworkParameters = signingCertAndKeyPair.sign(networkParameters) - val networkParametersHash = signedNetworkParameters.raw.hash - - val networkMapStorage: NetworkMapStorage = mock { - on { getSignedNetworkParameters(networkParametersHash) }.thenReturn(signedNetworkParameters) - } - - NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NetworkMapWebService(mock(), networkMapStorage, mock(), testNetworkMapConfig)).use { - it.start() - val netParamsResponse = it.doGet("network-parameters/$networkParametersHash") - verify(networkMapStorage, times(1)).getSignedNetworkParameters(networkParametersHash) - assertThat(netParamsResponse.verified()).isEqualTo(networkParameters) - assertThat(netParamsResponse.sig.by).isEqualTo(signingCertAndKeyPair.certificate) - assertThatExceptionOfType(IOException::class.java) - .isThrownBy { it.doGet("network-parameters/${randomSHA256()}") } - .withMessageContaining("404") - } - } - - @Test - fun `ack network parameters update`() { - val netParams = testNetworkParameters() - val hash = netParams.serialize().hash - val nodeInfoStorage: NodeInfoStorage = mock { - on { ackNodeInfoParametersUpdate(any(), eq(hash)) }.then { Unit } - } - val networkMapStorage: NetworkMapStorage = mock { - on { getSignedNetworkParameters(hash) }.thenReturn(signingCertAndKeyPair.sign(netParams)) - } - NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NetworkMapWebService(nodeInfoStorage, networkMapStorage, mock(), testNetworkMapConfig)).use { - it.start() - val keyPair = Crypto.generateKeyPair() - val signedHash = hash.serialize().sign { keyPair.sign(it) } - it.doPost("ack-parameters", signedHash.serialize()) - verify(nodeInfoStorage).ackNodeInfoParametersUpdate(keyPair.public, hash) - val randomSigned = SecureHash.randomSHA256().serialize().sign { keyPair.sign(it) } - assertThatThrownBy { it.doPost("ack-parameters", randomSigned.serialize()) } - .hasMessageContaining("HTTP ERROR 500") - val badSigned = SignedData(signedHash.raw, randomSigned.sig) - assertThatThrownBy { it.doPost("ack-parameters", badSigned.serialize()) } - .hasMessageStartingWith("Response Code 403: Signature Verification failed!") - } - } - - private fun NetworkManagementWebServer.doPost(path: String, payload: OpaqueBytes) { - URL("http://$hostAndPort/network-map/$path").post(payload) - } - - private inline fun NetworkManagementWebServer.doGet(path: String): T { - return URL("http://$hostAndPort/network-map/$path").openHttpConnection().responseAs() - } -} diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebServiceTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebServiceTest.kt deleted file mode 100644 index 5387ad714b..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebServiceTest.kt +++ /dev/null @@ -1,273 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.doorman.webservice - -import com.nhaarman.mockito_kotlin.* -import com.r3.corda.networkmanage.TestBase -import com.r3.corda.networkmanage.common.persistence.CertificateResponse -import com.r3.corda.networkmanage.doorman.NetworkManagementWebServer -import com.r3.corda.networkmanage.doorman.signer.CsrHandler -import net.corda.core.CordaOID -import net.corda.core.crypto.Crypto -import net.corda.core.crypto.SecureHash -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.CertRole -import net.corda.core.internal.errorMessage -import net.corda.core.internal.post -import net.corda.core.utilities.NetworkHostAndPort -import net.corda.core.utilities.OpaqueBytes -import net.corda.core.utilities.seconds -import net.corda.node.utilities.registration.cacheControl -import net.corda.nodeapi.internal.crypto.* -import net.corda.nodeapi.internal.crypto.X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME -import net.corda.testing.internal.createDevIntermediateCaCertPath -import org.assertj.core.api.Assertions.assertThat -import org.bouncycastle.asn1.ASN1ObjectIdentifier -import org.bouncycastle.asn1.DERUTF8String -import org.bouncycastle.asn1.x500.X500Name -import org.bouncycastle.asn1.x500.style.BCStyle -import org.bouncycastle.asn1.x509.GeneralName -import org.bouncycastle.asn1.x509.GeneralSubtree -import org.bouncycastle.asn1.x509.NameConstraints -import org.bouncycastle.pkcs.PKCS10CertificationRequest -import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest -import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder -import org.junit.After -import org.junit.Before -import org.junit.Test -import java.io.IOException -import java.net.HttpURLConnection -import java.net.HttpURLConnection.* -import java.net.URL -import java.security.KeyPair -import java.security.cert.CertPath -import java.security.cert.X509Certificate -import java.util.* -import java.util.zip.ZipInputStream -import javax.security.auth.x500.X500Principal -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith - -class RegistrationWebServiceTest : TestBase() { - private lateinit var webServer: NetworkManagementWebServer - private lateinit var rootCaCert: X509Certificate - private lateinit var intermediateCa: CertificateAndKeyPair - private val pollInterval = 10.seconds - - @Before - fun init() { - val (rootCa, intermediateCa) = createDevIntermediateCaCertPath() - rootCaCert = rootCa.certificate - this.intermediateCa = intermediateCa - } - - private fun startSigningServer(csrHandler: CsrHandler) { - webServer = NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), RegistrationWebService(csrHandler, pollInterval)) - webServer.start() - } - - @After - fun close() { - webServer.close() - } - - @Test - fun `submit request succeeds`() { - val id = SecureHash.randomSHA256().toString() - - val requestProcessor = mock { - on { saveRequest(any()) }.then { id } - } - - startSigningServer(requestProcessor) - - val keyPair = Crypto.generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME) - val request = X509Utilities.createCertificateSigningRequest( - CordaX500Name(locality = "London", organisation = "Legal Name", country = "GB").x500Principal, - "my@mail.com", - keyPair) - // Post request to signing server via http. - - assertEquals(id, submitRequest(request)) - verify(requestProcessor, times(1)).saveRequest(any()) - submitRequest(request) - verify(requestProcessor, times(2)).saveRequest(any()) - } - - @Test - fun `submit request fails with invalid public key`() { - startSigningServer(mock()) - - val keyPairGenuine = Crypto.generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME) - val keyPairMalicious = Crypto.generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME) - val request = createUnverifiedCertificateSigningRequest( - CordaX500Name(locality = "London", organisation = "Legal Name", country = "GB").x500Principal, - "my@mail.com", - KeyPair(keyPairMalicious.public, keyPairGenuine.private)) - // Post request to signing server via http. - assertFailsWith("Invalid CSR signature") { - submitRequest(request) - } - } - - @Test - fun `retrieve certificate`() { - val keyPair = Crypto.generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME) - val id = SecureHash.randomSHA256().toString() - - val subject = CordaX500Name(locality = "London", organisation = "LegalName", country = "GB").x500Principal - - // Mock Storage behaviour. - val certificateStore = mutableMapOf() - val requestProcessor = mock { - on { getResponse(eq(id)) }.then { - certificateStore[id]?.let { - CertificateResponse.Ready(it) - } ?: CertificateResponse.NotReady - } - on { processRequests() }.then { - val request = X509Utilities.createCertificateSigningRequest(subject, "my@mail.com", keyPair) - certificateStore[id] = JcaPKCS10CertificationRequest(request).run { - val tlsCert = X509Utilities.createCertificate( - CertificateType.TLS, - intermediateCa.certificate, - intermediateCa.keyPair, - X500Principal(subject.encoded), - publicKey) - X509Utilities.buildCertPath(tlsCert, intermediateCa.certificate, rootCaCert) - } - null - } - } - - startSigningServer(requestProcessor) - - val response = pollForResponse(id) - assertEquals(pollInterval, (response as PollResponse.NotReady).pollInterval.seconds) - - requestProcessor.processRequests() - - val certificates = (pollForResponse(id) as PollResponse.Ready).certChain - verify(requestProcessor, times(2)).getResponse(any()) - - assertThat(certificates).hasSize(3) - assertThat(certificates[0].subjectX500Principal).isEqualTo(subject) - assertThat(certificates).endsWith(intermediateCa.certificate, rootCaCert) - } - - @Test - fun `retrieve certificate and create valid TLS certificate`() { - val nodeCaKeyPair = Crypto.generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME) - val id = SecureHash.randomSHA256().toString() - - // Mock Storage behaviour. - val certificateStore = mutableMapOf() - val storage = mock { - on { getResponse(eq(id)) }.then { - certificateStore[id]?.let { - CertificateResponse.Ready(it) - } ?: CertificateResponse.NotReady - } - on { processRequests() }.then { - val request = X509Utilities.createCertificateSigningRequest( - CordaX500Name(locality = "London", organisation = "Legal Name", country = "GB").x500Principal, - "my@mail.com", - nodeCaKeyPair) - certificateStore[id] = JcaPKCS10CertificationRequest(request).run { - val nameConstraints = NameConstraints( - arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, X500Name("CN=LegalName, L=London")))), - arrayOf()) - val clientCert = X509Utilities.createCertificate( - CertificateType.NODE_CA, - intermediateCa.certificate, - intermediateCa.keyPair, - X500Principal(subject.encoded), - publicKey, - nameConstraints = nameConstraints) - X509Utilities.buildCertPath(clientCert, intermediateCa.certificate, rootCaCert) - } - true - } - } - - startSigningServer(storage) - val response = pollForResponse(id) - assertEquals(pollInterval, (response as PollResponse.NotReady).pollInterval.seconds) - - storage.processRequests() - - val certificates = (pollForResponse(id) as PollResponse.Ready).certChain - verify(storage, times(2)).getResponse(any()) - assertEquals(3, certificates.size) - - val sslKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) - val sslCert = X509Utilities.createCertificate( - CertificateType.TLS, - certificates[0], - nodeCaKeyPair, - // TODO Investigate why X500Principal("CN=LegalName, L=London") results in a name constraints violation - X500Principal(X500Name("CN=LegalName, L=London").encoded), - sslKeyPair.public) - - // TODO: This is temporary solution, remove all certificate re-shaping after identity refactoring is done. - X509Utilities.validateCertificateChain(rootCaCert, sslCert, *certificates.toTypedArray()) - } - - @Test - fun `request not authorised`() { - val id = SecureHash.randomSHA256().toString() - - val requestProcessor = mock { - on { getResponse(eq(id)) }.then { CertificateResponse.Unauthorised("Not Allowed") } - } - - startSigningServer(requestProcessor) - assertThat(pollForResponse(id)).isEqualTo(PollResponse.Unauthorised("Not Allowed")) - } - - private fun submitRequest(request: PKCS10CertificationRequest): String { - return String(URL("http://${webServer.hostAndPort}/certificate").post(OpaqueBytes(request.encoded))) - } - - private fun pollForResponse(id: String): PollResponse { - val url = URL("http://${webServer.hostAndPort}/certificate/$id") - val conn = url.openConnection() as HttpURLConnection - conn.requestMethod = "GET" - - return when (conn.responseCode) { - HTTP_OK -> ZipInputStream(conn.inputStream).use { - val certificates = ArrayList() - val factory = X509CertificateFactory() - while (it.nextEntry != null) { - certificates += factory.generateCertificate(it) - } - PollResponse.Ready(certificates) - } - HTTP_NO_CONTENT -> PollResponse.NotReady(conn.cacheControl.maxAgeSeconds()) - HTTP_UNAUTHORIZED -> PollResponse.Unauthorised(conn.errorMessage) - else -> throw IOException("Cannot connect to Certificate Signing Server, HTTP response code : ${conn.responseCode}") - } - } - - private fun createUnverifiedCertificateSigningRequest(subject: X500Principal, email: String, keyPair: KeyPair): PKCS10CertificationRequest { - val signer = ContentSignerBuilder.build(DEFAULT_TLS_SIGNATURE_SCHEME, keyPair.private, Crypto.findProvider(DEFAULT_TLS_SIGNATURE_SCHEME.providerName)) - return JcaPKCS10CertificationRequestBuilder(subject, keyPair.public) - .addAttribute(BCStyle.E, DERUTF8String(email)) - .addAttribute(ASN1ObjectIdentifier(CordaOID.X509_EXTENSION_CORDA_ROLE), CertRole.NODE_CA) - .build(signer) - } - - private interface PollResponse { - data class NotReady(val pollInterval: Int) : PollResponse - data class Ready(val certChain: List) : PollResponse - data class Unauthorised(val message: String?) : PollResponse - } -} \ No newline at end of file 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 deleted file mode 100644 index 351d2f9dd6..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/authentication/AuthenticatorTest.kt +++ /dev/null @@ -1,119 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.authentication - -import CryptoServerJCE.CryptoServerProvider -import com.nhaarman.mockito_kotlin.* -import com.r3.corda.networkmanage.TestBase -import com.r3.corda.networkmanage.common.signer.AuthenticationException -import org.junit.Before -import org.junit.Test -import kotlin.test.assertFailsWith -import kotlin.test.assertTrue - -class AuthenticatorTest : TestBase() { - - private lateinit var provider: CryptoServerProvider - private lateinit var inputReader: InputReader - - @Before - fun setUp() { - provider = mock() - whenever(provider.cryptoServer).thenReturn(mock()) - inputReader = mock() - } - - @Test - fun `connectAndAuthenticate aborts when user inputs Q`() { - // given - givenUserConsoleInputOnReadLine("Q") - - // when - assertFailsWith { - Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _ -> } - } - - //then - verify(provider, never()).loginPassword(any(), any()) - verify(provider, never()).loginSign(any(), any(), any()) - } - - @Test - fun `connectAndAuthenticate authenticates user with password`() { - // given - val username = "TEST_USER" - val password = "TEST_PASSWORD" - givenUserConsoleInputOnReadLine(username) - givenUserConsoleInputOnReadPassword(password) - givenAuthenticationResult(true) - var executed = false - - // when - Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _ -> executed = true } - - // then - verify(provider).loginPassword(username, password) - verify(provider, never()).loginSign(any(), any(), any()) - assertTrue(executed) - } - - @Test - fun `connectAndAuthenticate authenticates user with card reader`() { - // given - val username = "TEST_USER" - givenUserConsoleInputOnReadLine(username) - givenAuthenticationResult(true) - var executed = false - - // when - Authenticator(provider = provider, inputReader = inputReader, mode = AuthMode.CARD_READER).connectAndAuthenticate { _, _ -> executed = true } - - // then - verify(provider).loginSign(username, ":cs2:cyb:USB0", null) - verify(provider, never()).loginPassword(any(), any()) - assertTrue(executed) - } - - @Test - fun `connectAndAuthenticate authenticates multiple users with password`() { - // given - val username = "TEST_USER" - val password = "TEST_PASSWORD" - givenUserConsoleInputOnReadLine(username) - givenUserConsoleInputOnReadPassword(password) - givenAuthenticationResult(false, false, true) - var executed = false - - // when - Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _ -> executed = true } - - // then - verify(provider, times(3)).loginPassword(username, password) - verify(provider, never()).loginSign(any(), any(), any()) - assertTrue(executed) - } - - private fun givenAuthenticationResult(sufficient: Boolean, vararg subsequent: Boolean) { - val stub = whenever(provider.cryptoServer.authState).thenReturn(if (sufficient) 3 else 0) - subsequent.forEach { - stub.thenReturn(if (it) 3 else 0) - } - } - - private fun givenUserConsoleInputOnReadPassword(input: String) { - whenever(inputReader.readPassword(any())).thenReturn(input) - } - - private fun givenUserConsoleInputOnReadLine(input: String) { - whenever(inputReader.readLine()).thenReturn(input) - } - -} \ No newline at end of file diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/configuration/SigningServiceArgsParserTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/configuration/SigningServiceArgsParserTest.kt deleted file mode 100644 index d7304cf368..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/configuration/SigningServiceArgsParserTest.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.configuration - -import com.r3.corda.networkmanage.TestBase -import com.r3.corda.networkmanage.common.utils.parseConfig -import com.r3.corda.networkmanage.hsm.authentication.AuthMode -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.Test -import java.io.File -import java.nio.file.Paths -import kotlin.test.assertEquals - -class SigningServiceArgsParserTest : TestBase() { - private val doormanConfigPath = File("./hsm-for-doorman.conf").absolutePath - private val networkMapConfigPath = File("./hsm-for-networkmap.conf").absolutePath - private val argsParser = SigningServiceArgsParser() - - @Test - fun `doorman-based config file is parsed correctly`() { - val cmdLineOptions = argsParser.parseOrExit("--config-file", doormanConfigPath) - val config = parseConfig(cmdLineOptions.configFile) - assertEquals("3001@192.168.0.1", config.device) - val doormanCertParameters = config.doorman!! - assertEquals(AuthMode.PASSWORD, doormanCertParameters.authParameters.mode) - assertEquals(2, doormanCertParameters.authParameters.threshold) - assertEquals(3650, doormanCertParameters.validDays) - } - - @Test - fun `networkmap-based config file is parsed correctly`() { - val cmdLineOptions = argsParser.parseOrExit("--config-file", networkMapConfigPath) - val config = parseConfig(cmdLineOptions.configFile) - assertEquals("3001@192.168.0.1", config.device) - val networkMapConfig = config.networkMap!! - assertEquals(AuthMode.KEY_FILE, networkMapConfig.authParameters.mode) - assertEquals(Paths.get("./Administrator.KEY"), networkMapConfig.authParameters.keyFilePath) - assertEquals(2, networkMapConfig.authParameters.threshold) - assertEquals("PASSWORD", networkMapConfig.authParameters.password) - assertEquals("TEST_USERNAME", networkMapConfig.username) - } - - @Test - fun `should fail when config file is missing`() { - assertThatThrownBy { - argsParser.parseOrExit("--config-file", "not-existing-file", printHelpOn = null) - }.hasMessageContaining("not-existing-file") - } -} diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/generator/cert/GeneratorParametersTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/generator/cert/GeneratorParametersTest.kt deleted file mode 100644 index 31b0396a16..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/generator/cert/GeneratorParametersTest.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.generator.cert - -import com.r3.corda.networkmanage.common.configuration.ConfigFilePathArgsParser -import com.r3.corda.networkmanage.hsm.generator.AuthMode -import com.r3.corda.networkmanage.hsm.generator.certificate.GeneratorParameters -import com.r3.corda.networkmanage.hsm.generator.certificate.parseParameters -import com.typesafe.config.ConfigException -import joptsimple.OptionException -import net.corda.nodeapi.internal.crypto.CertificateType -import org.assertj.core.api.Assertions -import org.junit.Test -import java.io.File -import java.nio.file.Paths -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith -import kotlin.test.assertFalse - -class GeneratorParametersTest { - private val validConfigPath = File("cert-generator.conf").absolutePath - private val invalidConfigPath = File(javaClass.getResource("/cert-generator_fail.conf").toURI()).absolutePath - private val validArgs = arrayOf("--config-file", validConfigPath) - - @Test - fun `should fail when config file is missing`() { - val message = assertFailsWith { - ConfigFilePathArgsParser().parseOrExit("--config-file", "not-existing-file", printHelpOn = null) - }.message - Assertions.assertThat(message).contains("not-existing-file") - } - - @Test - fun `should fail when config is invalid`() { - assertFailsWith { - parseParameters(ConfigFilePathArgsParser().parseOrExit("--config-file", invalidConfigPath)) - } - } - - @Test - fun `should parse generator config correctly`() { - val parameters = parseCommandLineAndGetParameters() - assertEquals("127.0.0.1", parameters.hsmHost) - assertEquals(3001, parameters.hsmPort) - val certConfig = parameters.certConfig - assertEquals(1, certConfig.keySpecifier) - assertEquals("trustpass", parameters.trustStorePassword) - assertEquals(Paths.get("."), parameters.trustStoreDirectory) - assertFalse(certConfig.storeKeysExternal) - assertFalse(parameters.userConfigs.isEmpty()) - val userConfig = parameters.userConfigs.first() - assertEquals("INTEGRATION_TEST", userConfig.username) - assertEquals(AuthMode.PASSWORD, userConfig.authMode) - assertEquals("INTEGRATION_TEST", userConfig.authToken) - assertEquals(3650, certConfig.validDays) - assertEquals(CertificateType.ROOT_CA, certConfig.certificateType) - assertEquals("NIST-P256", certConfig.keyCurve) - } - - private fun parseCommandLineAndGetParameters(): GeneratorParameters { - return parseParameters(ConfigFilePathArgsParser().parseOrExit(*validArgs)) - } -} \ No newline at end of file diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/generator/crl/GeneratorParametersTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/generator/crl/GeneratorParametersTest.kt deleted file mode 100644 index d428dfaecc..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/generator/crl/GeneratorParametersTest.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.hsm.generator.crl - -import com.r3.corda.networkmanage.common.configuration.ConfigFilePathArgsParser -import com.r3.corda.networkmanage.hsm.generator.AuthMode -import com.typesafe.config.ConfigException -import joptsimple.OptionException -import org.assertj.core.api.Assertions -import org.junit.Test -import java.io.File -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith -import kotlin.test.assertFalse - -class GeneratorParametersTest { - private val validConfigPath = File("crl-generator.conf").absolutePath - private val invalidConfigPath = File(javaClass.getResource("/crl-generator_fail.conf").toURI()).absolutePath - private val validArgs = arrayOf("--config-file", validConfigPath) - - @Test - fun `should fail when config file is missing`() { - val message = assertFailsWith { - ConfigFilePathArgsParser().parseOrExit("--config-file", "not-existing-file", printHelpOn = null) - }.message - Assertions.assertThat(message).contains("not-existing-file") - } - - @Test - fun `should fail when config is invalid`() { - assertFailsWith { - parseParameters(ConfigFilePathArgsParser().parseOrExit("--config-file", invalidConfigPath)) - } - } - - @Test - fun `should parse generator config correctly`() { - val parameters = parseCommandLineAndGetParameters() - assertEquals("127.0.0.1", parameters.hsmHost) - assertEquals(3001, parameters.hsmPort) - assertEquals("trustpass", parameters.trustStorePassword) - val crlConfig = parameters.crl - assertEquals(1, crlConfig.keySpecifier) - assertFalse(parameters.userConfigs.isEmpty()) - val revocationsConfig = crlConfig.revocations - assertEquals(2, revocationsConfig.size) - val revocationConfig = revocationsConfig.first() - assertEquals(revocationConfig.reason, "KEY_COMPROMISE") - assertEquals(revocationConfig.certificateSerialNumber, "12345") - val userConfig = parameters.userConfigs.first() - assertEquals("INTEGRATION_TEST", userConfig.username) - assertEquals(AuthMode.PASSWORD, userConfig.authMode) - assertEquals("INTEGRATION_TEST", userConfig.authToken) - } - - private fun parseCommandLineAndGetParameters(): GeneratorConfig { - return parseParameters(ConfigFilePathArgsParser().parseOrExit(*validArgs)) - } -} \ No newline at end of file diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/tools/crr/submission/CertificateRevocationRequestSubmissionToolTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/tools/crr/submission/CertificateRevocationRequestSubmissionToolTest.kt deleted file mode 100644 index 793cf4b0ef..0000000000 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/tools/crr/submission/CertificateRevocationRequestSubmissionToolTest.kt +++ /dev/null @@ -1,95 +0,0 @@ -/* - * R3 Proprietary and Confidential - * - * Copyright (c) 2018 R3 Limited. All rights reserved. - * - * The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law. - * - * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. - */ - -package com.r3.corda.networkmanage.tools.crr.submission - -import com.nhaarman.mockito_kotlin.eq -import com.nhaarman.mockito_kotlin.mock -import com.nhaarman.mockito_kotlin.verify -import com.nhaarman.mockito_kotlin.whenever -import com.r3.corda.networkmanage.doorman.NetworkManagementWebServer -import com.r3.corda.networkmanage.doorman.signer.CrrHandler -import com.r3.corda.networkmanage.doorman.webservice.CertificateRevocationRequestWebService -import com.r3.corda.networkmanage.hsm.authentication.InputReader -import net.corda.core.crypto.SecureHash -import net.corda.core.identity.CordaX500Name -import net.corda.nodeapi.internal.network.CertificateRevocationRequest -import net.corda.testing.core.SerializationEnvironmentRule -import net.corda.testing.core.freeLocalHostAndPort -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import java.math.BigInteger -import java.net.URL -import java.security.cert.CRLReason - -class CertificateRevocationRequestSubmissionToolTest { - - @Rule - @JvmField - val testSerialization = SerializationEnvironmentRule(true) - - private val hostAndPort = freeLocalHostAndPort() - private lateinit var webServer: NetworkManagementWebServer - private lateinit var inputReader: InputReader - - @Before - fun setUp() { - inputReader = mock() - } - - @After - fun close() { - webServer.close() - } - - @Test - fun `submit request succeeds`() { - // given - val request = CertificateRevocationRequest( - certificateSerialNumber = BigInteger.TEN, - csrRequestId = "TestCSRId", - legalName = CordaX500Name.parse("O=TestOrg, C=GB, L=London"), - reason = CRLReason.KEY_COMPROMISE, - reporter = "TestReporter" - ) - - givenUserConsoleSequentialInputOnReadLine(request.certificateSerialNumber.toString(), - request.csrRequestId!!, - request.legalName.toString(), - "${request.reason.ordinal + 1}", - request.reporter) - - val requestId = SecureHash.randomSHA256().toString() - val requestProcessor = mock { - on { saveRevocationRequest(eq(request)) }.then { requestId } - } - startSigningServer(requestProcessor) - - // when - submit(URL("http://$hostAndPort/certificate-revocation-request"), inputReader) - - // then - verify(requestProcessor).saveRevocationRequest(eq(request)) - } - - private fun givenUserConsoleSequentialInputOnReadLine(vararg inputs: String) { - var sequence = whenever(inputReader.readLine()).thenReturn(inputs.first()) - inputs.drop(1).forEach { - sequence = sequence.thenReturn(it) - } - } - - private fun startSigningServer(handler: CrrHandler) { - webServer = NetworkManagementWebServer(hostAndPort, CertificateRevocationRequestWebService(handler)) - webServer.start() - } -} \ No newline at end of file diff --git a/network-management/src/test/resources/cert-generator_fail.conf b/network-management/src/test/resources/cert-generator_fail.conf deleted file mode 100644 index 28bcc921c8..0000000000 --- a/network-management/src/test/resources/cert-generator_fail.conf +++ /dev/null @@ -1,12 +0,0 @@ -hsmHost = 127.0.0.1 -hsmPort = 3001 -keyGroup = "DEV.DOORMAN" -keySpecifier = 1 - -userConfigs = [ - { - username = "INTEGRATION_TEST" - authMode = PASSWORD - authToken = "INTEGRATION_TEST" - } -] diff --git a/network-management/src/test/resources/crl-generator_fail.conf b/network-management/src/test/resources/crl-generator_fail.conf deleted file mode 100644 index e611a6cdad..0000000000 --- a/network-management/src/test/resources/crl-generator_fail.conf +++ /dev/null @@ -1,12 +0,0 @@ -hsmHost = 127.0.0.1 -hsmPort = 3001 -trustStoreFile = "./truststore.jks" -trustStorePassword = "trustpass" - -userConfigs = [ - { - username = "INTEGRATION_TEST" - authMode = PASSWORD - authToken = "INTEGRATION_TEST" - } -] \ No newline at end of file diff --git a/network-management/src/test/resources/doorman_fail.conf b/network-management/src/test/resources/doorman_fail.conf deleted file mode 100644 index 0c6e89c3b3..0000000000 --- a/network-management/src/test/resources/doorman_fail.conf +++ /dev/null @@ -1,6 +0,0 @@ -keystorePath = "/opt/doorman/certificates/caKeystore.jks" -keyStorePassword = "password" -caPrivateKeyPassword = "password" -host = "localhost" -port = 8080 -h2port = 0 diff --git a/network-management/src/test/resources/hsm_fail.conf b/network-management/src/test/resources/hsm_fail.conf deleted file mode 100644 index 6d748db0f6..0000000000 --- a/network-management/src/test/resources/hsm_fail.conf +++ /dev/null @@ -1,9 +0,0 @@ -device = "3001@127.0.0.1" -keyGroup = "DEV.DOORMAN" -keySpecifier = -1 -authMode = PASSWORD -csrPrivateKeyPassword = "" -csrCertCrlDistPoint = "http://test.com/revoked.crl" -networkMapPrivateKeyPassword = "" -rootPrivateKeyPassword = "" -keyGroup = "DEV.DOORMAN" \ No newline at end of file diff --git a/network-management/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/network-management/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker deleted file mode 100644 index ca6ee9cea8..0000000000 --- a/network-management/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker +++ /dev/null @@ -1 +0,0 @@ -mock-maker-inline \ No newline at end of file diff --git a/network-management/src/test/resources/oldNodeInfoDB.mv.db b/network-management/src/test/resources/oldNodeInfoDB.mv.db deleted file mode 100644 index e20bfcd05f..0000000000 Binary files a/network-management/src/test/resources/oldNodeInfoDB.mv.db and /dev/null differ diff --git a/settings.gradle b/settings.gradle index 6ebce63542..706ce1bc10 100644 --- a/settings.gradle +++ b/settings.gradle @@ -47,13 +47,6 @@ include 'perftestcordapp' project(":$it").projectDir = new File("$settingsDir/testing/$it") } include 'testing:qa:behave:tools:rpc-proxy' -include 'network-management' -include 'network-management:capsule' -include 'network-management:capsule-hsm' -include 'network-management:capsule-hsm-cert-generator' -include 'network-management:capsule-hsm-crl-generator' -include 'network-management:capsule-crr-submission' -include 'network-management:registration-tool' include 'tools:jmeter' include 'tools:explorer' include 'tools:explorer:capsule'