Add skeleton enclave

Note: the "repo" directory from the conclave 1.2.1 SDK must be copied into the root directory of this project manually
This commit is contained in:
lemjclarke 2022-02-23 10:08:10 +00:00
parent 05fab1dabd
commit 166bc6b3f3
14 changed files with 558 additions and 0 deletions

View File

@ -1,5 +1,7 @@
import com.r3.testing.DistributeTestsBy import com.r3.testing.DistributeTestsBy
import com.r3.testing.PodLogLevel import com.r3.testing.PodLogLevel
import java.nio.file.Files
import java.nio.file.Paths
import static org.gradle.api.JavaVersion.VERSION_11 import static org.gradle.api.JavaVersion.VERSION_11
import static org.gradle.api.JavaVersion.VERSION_1_8 import static org.gradle.api.JavaVersion.VERSION_1_8
@ -189,6 +191,18 @@ buildscript {
mavenCentral() mavenCentral()
jcenter() jcenter()
} }
maven {
def path = Paths.get(rootDir.absolutePath).resolve("./repo").toAbsolutePath().normalize()
if (!Files.isDirectory(path.resolve("com"))) {
if (Files.isDirectory(Paths.get("/repo/com"))) {
path = Paths.get("/repo")
} else {
throw new Exception("Neither $path nor /repo seem to exist, or they aren't Maven repositories; it should be the SDK 'repo' subdirectory.")
}
}
url = path.toFile()
}
} }
dependencies { dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
@ -424,6 +438,18 @@ allprojects {
} }
mavenCentral() mavenCentral()
jcenter() jcenter()
maven {
def path = Paths.get(rootDir.absolutePath).resolve(conclaveRepo).toAbsolutePath().normalize()
if (!Files.isDirectory(path.resolve("com"))) {
if (Files.isDirectory(Paths.get("/repo/com"))) {
path = Paths.get("/repo")
} else {
throw new Exception("Neither $path nor /repo seem to exist, or they aren't Maven repositories; it should be the SDK 'repo' subdirectory.")
}
}
url = path.toFile()
}
} }
} }

View File

@ -0,0 +1,7 @@
apply plugin: 'kotlin'
dependencies {
implementation "com.r3.conclave:conclave-common:$conclaveVersion"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "net.i2p.crypto:eddsa:0.3.0"
}

View File

@ -0,0 +1,29 @@
package com.r3.conclave.cordapp.common
/**
* Generic type for an enclave command.
* This type contains no properties or methods and simply instructs the enclave to perform a specific action.
*/
interface EnclaveCommand {
/**
* Convert this type to a [String].
* @return serialized [String] of this type.
*/
fun serialize(): String {
return this.javaClass.name
}
}
/**
* Deserialize an [EnclaveCommand].
* Convert a serialized string into an [EnclaveCommand] instance.
*/
fun String.toEnclaveCommand(): EnclaveCommand {
return Class.forName(this).newInstance() as EnclaveCommand
}
/**
* An [EnclaveCommand] that instructs the enclave to register a host identity.
*/
class RegisterHostIdentity : EnclaveCommand

View File

@ -0,0 +1,44 @@
package com.r3.conclave.cordapp.common
import java.security.MessageDigest
import java.util.*
/**
* Parse [routingHint] of the format flowId:route and return a pair of flowId [String] and [EnclaveCommand] class.
* @param routingHint the routing hint from receiveMail to parse.
* @return a pair of flowId [String] and [EnclaveCommand].
* @throws [IllegalArgumentException] if the hint cannot be parsed, or if the enclave command is not known.
*/
fun getRoutingInfo(routingHint: String): Pair<String, EnclaveCommand> {
val routingElements = routingHint.split(":")
if (routingElements.size != 2) {
throw IllegalArgumentException("Expected routingHint in the form flowId:route")
}
val (flowId, routeName) = routingElements
try {
UUID.fromString(flowId)
} catch (e: IllegalArgumentException) {
throw IllegalArgumentException("Invalid flowId: $flowId")
}
val route = try {
routeName.trim().toEnclaveCommand()
} catch (e: IllegalArgumentException) {
throw java.lang.IllegalArgumentException("Unknown command: $routeName")
}
return Pair(flowId, route)
}
/**
* Return the hash of the input [String] using the given hashing algorithm.
* @param input the [String] to generate a hash of.
* @param algorithm the hashing algorithm to use.
* @return the generated hash [String].
*/
fun hashString(input: String, algorithm: String = "SHA-256"): String {
return MessageDigest.getInstance(algorithm)
.digest(input.toByteArray())
.fold("") { str, it -> str + "%02x".format(it) }
}

View File

@ -0,0 +1,7 @@
package com.r3.conclave.cordapp.common
/**
* An [EnclaveCommand] that instructs the enclave to initialise a post office to a remote enclave using the serialized
* attestation contained in the mail body (requires an enclave host to be registered).
*/
class InitPostOfficeToRemoteEnclave : EnclaveCommand

View File

@ -0,0 +1,23 @@
package com.r3.conclave.cordapp.common
import java.security.PublicKey
/**
* Defines the interface for querying the sender's identity properties. The SenderIdentity is accessible to the
* the Enclave and it can be used to uniquely identify the sender if the sender decided to share
* its verifiable identity. Any identity shared by the sender goes through a verification process to ensure the identity
* is part of the same certificate chain as the root certificate hardcoded into the enclave.
*/
interface SenderIdentity {
/**
* The verified X.500 subject name of the sender
*/
val name: String
/**
* The verified public key of the sender's identity. Specifically, this is the public key from the sender's X.509 certificate.
* Note, this public key is different to the encryption key used in Mail ([EnclaveMail.authenticatedSender])
*/
val publicKey: PublicKey
}

View File

@ -0,0 +1,137 @@
package com.r3.conclave.cordapp.common.internal
import com.r3.conclave.common.internal.SignatureSchemeEdDSA
import com.r3.conclave.cordapp.common.SenderIdentity
import net.i2p.crypto.eddsa.EdDSASecurityProvider
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.DataInputStream
import java.io.DataOutputStream
import java.security.PublicKey
import java.security.Security
import java.security.SignatureException
import java.security.cert.*
/**
* Implements the [SenderIdentity] interface and allows a sender to prepare and send its identity to en Enclave, and
* allows the Enclave to privately and securely verify the sender X509 name and public key belonging to a network where
* parties are identified by a X509 certificate issued by the CA trusted by the Enclave.
*/
class SenderIdentityImpl(
private val signerCertPath: CertPath,
private val signatureData: ByteArray
) : SenderIdentity {
private val signerCertificate: X509Certificate get() = (signerCertPath.certificates[0] as X509Certificate)
init {
require(signerCertPath.type == "X.509") { "Only X.509 certificates supported" }
val certs = signerCertPath.certificates
require(certs.size >= 2) { "Certificate path must at least include subject and issuing certificates" }
}
/**
* Verifies the sender identified by the [signerCertificate] is the party that signed the [sharedSecret] producing
* the [signatureData]
*/
fun didSign(sharedSecret: ByteArray): Boolean {
return try {
signatureScheme.verify(signerCertificate.publicKey, signatureData, sharedSecret)
true
} catch (e: SignatureException) {
false
}
}
/**
* Verifies the [signerCertPath] is valid and issued by the given trusted root
*
* @param caRoot the root certificate that is used to validate the instance's certificate path [signerCertPath]
*/
fun isTrusted(caRoot: X509Certificate): Boolean {
val trustAnchor = TrustAnchor(caRoot, null)
val parameters = PKIXParameters(setOf(trustAnchor)).apply { isRevocationEnabled = false }
return try {
CertPathValidator.getInstance("PKIX").validate(signerCertPath, parameters)
true
} catch (e: CertPathValidatorException) {
false
}
}
/**
* The verified subject name of the sender
*/
override val name: String get() = signerCertificate.subjectX500Principal.name
/**
* The verified public key of the sender
*/
override val publicKey: PublicKey get() = signerCertificate.publicKey
/**
* Serializes the [SenderIdentity] instance into a byte array.
*
* Used by the mail sender to serialize the [SenderIdentity] instance and privately send it to the Enclave message
* handler where is then deserialized.
*/
fun serialize(): ByteArray {
val baos = ByteArrayOutputStream()
val dos = DataOutputStream(baos)
serialize(dos)
return baos.toByteArray()
}
fun serialize(dos: DataOutputStream) {
dos.writeIntLengthPrefixBytes(signerCertPath.getEncoded("PkiPath"))
dos.writeIntLengthPrefixBytes(signatureData)
}
companion object {
private val signatureScheme = SignatureSchemeEdDSA()
init {
Security.addProvider(EdDSASecurityProvider())
}
private fun deserializeCertPath(dis: DataInputStream): CertPath {
val certBytes = dis.readIntLengthPrefixBytes()
val certFactory = CertificateFactory.getInstance("X.509")
return certFactory.generateCertPath(ByteArrayInputStream(certBytes), "PkiPath")
}
private fun deserializeSignedSecret(dis: DataInputStream): ByteArray = dis.readIntLengthPrefixBytes()
/**
* Deserialzes a serialized [SenderIdentityImpl] instance
*/
fun deserialize(from: ByteArray): SenderIdentityImpl {
val bais = ByteArrayInputStream(from)
val dis = DataInputStream(bais)
return deserialize(dis)
}
fun deserialize(dis: DataInputStream): SenderIdentityImpl {
try {
val signerCertPath = deserializeCertPath(dis)
val signedSecret = deserializeSignedSecret(dis)
return SenderIdentityImpl(signerCertPath, signedSecret)
} catch (e: Exception) {
throw IllegalArgumentException("Corrupted MailerIdentity bytes", e)
}
}
}
}
private fun DataOutputStream.writeIntLengthPrefixBytes(data: ByteArray) {
this.writeInt(data.size)
this.write(data)
}
private fun DataInputStream.readIntLengthPrefixBytes(): ByteArray {
val data = ByteArray(this.readInt())
this.readFully(data)
return data
}

58
enclave/build.gradle Normal file
View File

@ -0,0 +1,58 @@
plugins {
id 'kotlin'
id 'com.r3.conclave.enclave'
}
/**
* The default Java version for enclaves is 11 so we need to set it to 8 for the CorDapp to work.
*/
tasks.withType(JavaCompile) {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
options.encoding = 'UTF-8'
}
/**
* There is no Kotlin code in this project,
* but if there were, this section would be required.
* Note: Java versions above and here have to match.
*/
/*
tasks.withType(AbstractCompile) {
if (it.class.name.startsWith('org.jetbrains.kotlin.gradle.tasks.KotlinCompile')) {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
apiVersion = '1.5'
languageVersion = '1.5'
}
}
}
*/
dependencies {
implementation project(':common-enclave')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation 'junit:junit:4.13.1'
testImplementation(platform('org.junit:junit-bom:5.7.0'))
}
conclave {
productID = 1
revocationLevel = 0
simulation {
signingType = privateKey
signingKey = file("sample_private_key.pem")
}
debug {
signingType = privateKey
signingKey = file("sample_private_key.pem")
}
release {
signingType = privateKey
signingKey = file("sample_private_key.pem")
}
}

View File

@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,113 @@
package com.r3.conclave.cordapp.sample.enclave
import com.r3.conclave.cordapp.common.EnclaveCommand
import com.r3.conclave.cordapp.common.RegisterHostIdentity
import com.r3.conclave.cordapp.common.getRoutingInfo
import com.r3.conclave.cordapp.common.internal.SenderIdentityImpl
import com.r3.conclave.enclave.Enclave
import com.r3.conclave.mail.EnclaveMail
import com.r3.conclave.enclave.EnclavePostOffice
import java.lang.IllegalStateException
import java.security.PublicKey
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import java.util.logging.Logger
abstract class CommandEnclave : Enclave() {
// the public key of the authenticated and registered host
protected lateinit var authenticatedHostKey: PublicKey
// Post office to communicate with our host
// To be initialised when registerHostIdentity is called
protected lateinit var hostPostOffice: EnclavePostOffice
companion object {
private const val trustedRootCertificateResourcePath = "/trustedroot.cer"
@JvmStatic
val trustedRootCertificate: X509Certificate = run {
try {
EncryptedTxEnclave::class.java.getResourceAsStream(trustedRootCertificateResourcePath).use {
val certificateFactory = CertificateFactory.getInstance("X509")
certificateFactory.generateCertificate(it) as X509Certificate
}
} catch (exception: Exception) {
Logger.getGlobal().severe(
"Failed to load trusted root certificate. Please ensure the resource exists and it is not " +
"corrupted. Resource path: $trustedRootCertificateResourcePath"
)
throw exception
}
}
}
/**
* Receive incoming mail and route according to the [EnclaveCommand] class contained in the [routingHint].
* @param mail the received [EnclaveMail].
* @param routingHint a [String] containing the executing flowId and enclave command to execute.
* @throws [IllegalArgumentException] if [routingHint] is null, or cannot be parsed.
*/
override fun receiveMail(mail: EnclaveMail, routingHint: String?) {
routingHint ?: throw IllegalArgumentException(
"routingHint must be set for this enclave: ${this.javaClass.simpleName}")
val (flowId, route) = getRoutingInfo(routingHint)
val registeredHost = if (isHostRegistered()) authenticatedHostKey else null
println("Received route: $route, registered host: $registeredHost")
if (route is RegisterHostIdentity) {
registerHostIdentity(mail, flowId)
} else if (isHostRegistered()) {
receiveMail(mail, flowId, route)
} else {
throw IllegalStateException(
"Host must be registered before executing enclave commands"
)
}
}
abstract fun receiveMail(mail: EnclaveMail, flowId: String, route: EnclaveCommand)
/**
* Deserialize the [SenderIdentityImpl] from the mail body and authenticate the contained identity.
* If the sender is trusted and is the signer of the shared secret, register the host's public key and initialise
* the [hostPostOffice] property. Respond with "ack" if the registration was successful or "nak" otherwise.
* @param mail an incoming [EnclaveMail] containing a serialized [SenderIdentityImpl] instance.
* @param flowId the ID of the flow executing on our host.
*/
protected fun registerHostIdentity(mail: EnclaveMail, flowId: String) {
val identity = SenderIdentityImpl.deserialize(mail.bodyAsBytes)
val sharedSecret = mail.authenticatedSender.encoded
val authenticated = authenticateIdentity(sharedSecret, identity)
if (authenticated) {
authenticatedHostKey = mail.authenticatedSender
hostPostOffice = postOffice(mail)
}
val responseString = if (authenticated) "ack" else "nak"
val reply = postOffice(mail).encryptMail(responseString.toByteArray(Charsets.UTF_8))
postMail(reply, "$flowId:${RegisterHostIdentity().serialize()}")
}
/**
* Return true if a host has successfully registered and authenticated their identity.
* @return [Boolean] indicating if a host has registered with this enclave.
*/
private fun isHostRegistered() = this::authenticatedHostKey.isInitialized
/**
* Return true if [identity] is trusted and is the signer of [sharedSecret].
* @param sharedSecret check identity signature against this shared secret.
* @param identity the [SenderIdentityImpl] instance to authenticate.
*/
private fun authenticateIdentity(sharedSecret: ByteArray, identity: SenderIdentityImpl): Boolean {
val isTrusted = identity.isTrusted(trustedRootCertificate)
val didSign = identity.didSign(sharedSecret)
return isTrusted && didSign
}
}

View File

@ -0,0 +1,50 @@
package com.r3.conclave.cordapp.sample.enclave
import com.r3.conclave.common.EnclaveInstanceInfo
import com.r3.conclave.cordapp.common.*
import com.r3.conclave.enclave.EnclavePostOffice
import com.r3.conclave.mail.EnclaveMail
import java.lang.IllegalStateException
import java.util.*
/**
* Provide commands to exchange a randomly generated message and hash with another instance of this enclave.
*/
class EncryptedTxEnclave : CommandEnclave() {
private lateinit var remoteEnclavePostOffice: EnclavePostOffice
private val commandToCallableMap = mapOf(
InitPostOfficeToRemoteEnclave::class.java.name to ::initPostOfficeToRemoteEnclave
)
override fun receiveMail(mail: EnclaveMail, flowId: String, route: EnclaveCommand) {
if (commandToCallableMap[route.javaClass.name] != null) {
commandToCallableMap[route.javaClass.name]!!.invoke(mail, flowId)
} else {
throw IllegalArgumentException(
"No callable registered for command $route in enclave: ${this.javaClass.simpleName}")
}
}
/**
* Deserialize the enclave attestation and create a post office to the remote enclave.
* @param mail an incoming [EnclaveMail] containing the attestation to deserialize.
* @param flowId the ID of the flow executing on our host.
* @throws [IllegalStateException] if the remote enclave has already been initialised, or if the host identity has
* not been registered.
* @throws [IllegalArgumentException] if the mail sender is not the authenticated host key.
*/
private fun initPostOfficeToRemoteEnclave(mail: EnclaveMail, flowId: String) {
if (this::remoteEnclavePostOffice.isInitialized) {
throw IllegalStateException("Post office for remote enclave has already been initialized")
} else if (mail.authenticatedSender != authenticatedHostKey) {
throw IllegalArgumentException("Mail sender does not match the authenticated host key")
}
val attestation = EnclaveInstanceInfo.deserialize(mail.bodyAsBytes)
// TODO: should we check an enclave constraint?
remoteEnclavePostOffice = postOffice(attestation, flowId)
}
}

View File

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIICCTCCAbCgAwIBAgIIcFe0qctqSucwCgYIKoZIzj0EAwIwWDEbMBkGA1UEAwwS
Q29yZGEgTm9kZSBSb290IENBMQswCQYDVQQKDAJSMzEOMAwGA1UECwwFY29yZGEx
DzANBgNVBAcMBkxvbmRvbjELMAkGA1UEBhMCVUswHhcNMTcwNTIyMDAwMDAwWhcN
MjcwNTIwMDAwMDAwWjBYMRswGQYDVQQDDBJDb3JkYSBOb2RlIFJvb3QgQ0ExCzAJ
BgNVBAoMAlIzMQ4wDAYDVQQLDAVjb3JkYTEPMA0GA1UEBwwGTG9uZG9uMQswCQYD
VQQGEwJVSzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGlm6LFHrVkzfuUHin36
Jrm1aUMarX/NUZXw8n8gSiJmsZPlUEplJ+f/lzZMky5EZPTtCciG34pnOP0eiMd/
JTCjZDBiMB0GA1UdDgQWBBR8rqnfuUgBKxOJC5rmRYUcORcHczALBgNVHQ8EBAMC
AYYwIwYDVR0lBBwwGgYIKwYBBQUHAwEGCCsGAQUFBwMCBgRVHSUAMA8GA1UdEwEB
/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgDaL4SguKsNeTT7SeUkFdoCBACeG8
GqO4M1KlfimphQwCICiq00hDanT5W8bTLqE7GIGuplf/O8AABlpWrUg6uiUB
-----END CERTIFICATE-----

View File

@ -5,3 +5,4 @@ owasp.failOnError=false
owasp.failBuildOnCVSS=11.0 owasp.failBuildOnCVSS=11.0
compilation.allWarningsAsErrors=false compilation.allWarningsAsErrors=false
test.parallel=false test.parallel=false
conclaveVersion=1.2.1

View File

@ -22,8 +22,13 @@ pluginManagement {
mavenLocal() mavenLocal()
gradlePluginPortal() gradlePluginPortal()
maven { url "${artifactory_contextUrl}/corda-dependencies" } maven { url "${artifactory_contextUrl}/corda-dependencies" }
maven { url "$settingsDir/repo" }
} }
} }
plugins {
id 'com.r3.conclave.enclave' version conclaveVersion apply false
}
} }
// The project is named 'corda-project' and not 'corda' because if this is named the same as the // The project is named 'corda-project' and not 'corda' because if this is named the same as the
// output JAR from the capsule then the buildCordaJAR task goes into an infinite loop. // output JAR from the capsule then the buildCordaJAR task goes into an infinite loop.
@ -102,6 +107,9 @@ include 'testing:cordapps:dbfailure:dbfworkflows'
include 'testing:cordapps:missingmigration' include 'testing:cordapps:missingmigration'
include 'testing:cordapps:sleeping' include 'testing:cordapps:sleeping'
// Conclave
include 'enclave'
// Common libraries - start // Common libraries - start
include 'common-validation' include 'common-validation'
project(":common-validation").projectDir = new File("$settingsDir/common/validation") project(":common-validation").projectDir = new File("$settingsDir/common/validation")
@ -112,6 +120,9 @@ project(":common-configuration-parsing").projectDir = new File("$settingsDir/com
include 'common-logging' include 'common-logging'
project(":common-logging").projectDir = new File("$settingsDir/common/logging") project(":common-logging").projectDir = new File("$settingsDir/common/logging")
include 'common-enclave'
project(":common-enclave").projectDir = new File("$settingsDir/common/enclave")
// Common libraries - end // Common libraries - end
apply from: 'buildCacheSettings.gradle' apply from: 'buildCacheSettings.gradle'