mirror of
https://github.com/corda/corda.git
synced 2025-01-14 00:39:57 +00:00
HSM works
This commit is contained in:
parent
294dc41fe6
commit
904252c0bb
@ -35,4 +35,4 @@ include 'samples:bank-of-corda-demo'
|
||||
include 'cordform-common'
|
||||
include 'doorman'
|
||||
include 'verify-enclave'
|
||||
include 'sgx-jvm/sgx-signtool'
|
||||
include 'sgx-jvm/hsm-tool'
|
||||
|
@ -4,20 +4,16 @@ The build
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
* Install mercurial, gcc/g++, autoconf, automake, libtool, ocaml, protobuf, libprotobuf, libcurl, libopenssl, cmake, zlib headers, libunwind headers, libcurl headers, libprotobuf headers
|
||||
* Install proguard and symlink the proguard.jar by `ln -s <LOCATION OF proguard.jar> sgx-jvm/jvm-enclave/proguard.jar`
|
||||
* Install mercurial, gcc/g++(6), autoconf, automake, ocaml, opendjk(8), libtool, python(2.7)
|
||||
* Make sure JAVA_HOME points to your jdk 8 installation
|
||||
* Make sure CXX points to g++ (the project does NOT compile with other compilers like clang!)
|
||||
* If your hardware supports SGX and you want to use it directly you need to install and load the sgx kernel module (verify by running `lsmod | grep isgx`) and have the sgx service running (on a systemd setup verify by running `systemctl status aesmd`). Note that this is only required for actually running the binary, the build should work fine without.
|
||||
* The SGX SDK has a simulation mode that doesn't require hardware support. To use this edit `sgx-jvm/jvm-enclave/CMakeLists.txt` and change `set(SGX_USE_HARDWARE TRUE)` to `FALSE`
|
||||
|
||||
Troubles with libprotobuf
|
||||
-------------------------
|
||||
|
||||
Unless your distro is very old you will possibly encounter protobuf linker errors when building the SGX SDK. The current version assumes libprotobuf.so.8. If your distro supports downgrades try that, the library version of 2.5.0-4 should work. We may have to include the .so in the repo, or potentially create a pre-setup docker image or something to avoid all this fuss.
|
||||
|
||||
Toplevel Makefile targets
|
||||
-------------------------
|
||||
|
||||
* `make` will download all other dependencies and build the sgx\_experiments binary, residing at `sgx-jvm/jvm-enclave/build/sgx\_experiments`.
|
||||
* `make` will download all other dependencies and build the sgx\_standalone\_verify binary, residing at `sgx-jvm/jvm-enclave/standalone/build/sgx\_standalone\_verify`, as well as a JNI .so residing at `sgx-jvm/jvm-enclave/jni/build/untrusted_corda_sgx.so`
|
||||
* `make clean` will clean all build targets.
|
||||
* `make distclean` will clean all build targets and downloaded dependencies. Ordinarily you shouldn't need to run this.
|
||||
|
||||
|
@ -42,7 +42,7 @@ jar {
|
||||
exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.MF'
|
||||
|
||||
manifest {
|
||||
attributes('Main-Class' : 'com.r3cev.sgx.signtool.MainKt')
|
||||
attributes('Main-Class' : 'com.r3cev.sgx.hsmtool.MainKt')
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,6 +52,3 @@ task copyConfig(type: Copy) {
|
||||
}
|
||||
|
||||
build.dependsOn copyConfig
|
||||
|
||||
|
||||
|
@ -9,10 +9,16 @@ import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
enum class Mode {
|
||||
GenerateKey,
|
||||
Sign
|
||||
}
|
||||
|
||||
data class ToolConfig(val config: Config) {
|
||||
constructor(args: Array<String>) : this({
|
||||
val parser = OptionParser()
|
||||
val sourcePathArg = parser.accepts("source").withRequiredArg().required()
|
||||
val modeArg = parser.accepts("mode").withRequiredArg().defaultsTo(Mode.Sign.name)
|
||||
val sourcePathArg = parser.accepts("source").withRequiredArg()
|
||||
val configPathArg = parser.accepts("config").withRequiredArg()
|
||||
val profileArg = parser.accepts("profile").withRequiredArg().defaultsTo("dev")
|
||||
val publicKeyOutputPathArg = parser.accepts("pubkey").withRequiredArg().defaultsTo("./pubkey.pem")
|
||||
@ -21,6 +27,7 @@ data class ToolConfig(val config: Config) {
|
||||
val keyNameArg = parser.accepts("keyName").withRequiredArg()
|
||||
val keyGroupArg = parser.accepts("keyGroup").withRequiredArg()
|
||||
val keySpecifierArg = parser.accepts("keySpecifier").withRequiredArg()
|
||||
val overwriteArg = parser.accepts("overwriteKey").withOptionalArg()
|
||||
val options = try {
|
||||
parser.parse(*args)
|
||||
} catch (e: Exception) {
|
||||
@ -29,21 +36,27 @@ data class ToolConfig(val config: Config) {
|
||||
exitProcess(1)
|
||||
}
|
||||
|
||||
val sourcePath = options.valueOf(sourcePathArg)!!
|
||||
val publicKeyOutputPath = options.valueOf(publicKeyOutputPathArg)!!
|
||||
val signatureOutputPath = options.valueOf(signatureOutputPathArg)!!
|
||||
val sourcePath = options.valueOf(sourcePathArg)
|
||||
val mode = options.valueOf(modeArg)
|
||||
val publicKeyOutputPath = options.valueOf(publicKeyOutputPathArg)
|
||||
val signatureOutputPath = options.valueOf(signatureOutputPathArg)
|
||||
val baseConfig = if (options.hasArgument(configPathArg)) {
|
||||
val configPath = Paths.get(options.valueOf(configPathArg)!!)
|
||||
require(Files.exists(configPath)) { "Config file $sourcePath not found" }
|
||||
require(Files.exists(configPath)) { "Config file $configPath not found" }
|
||||
ConfigFactory.parseFile(configPath.toFile())
|
||||
} else {
|
||||
ConfigFactory.parseResources(ToolConfig::class.java, "sgxtool.cfg")
|
||||
}
|
||||
|
||||
val profile = options.valueOf(profileArg)!!.toLowerCase()
|
||||
val overrideMap = mutableMapOf("profile" to profile, "sourcePath" to sourcePath,
|
||||
"publicKeyOutputPath" to publicKeyOutputPath,
|
||||
"signatureOutputPath" to signatureOutputPath)
|
||||
val overrideMap = mutableMapOf(
|
||||
"mode" to mode,
|
||||
"profile" to profile
|
||||
)
|
||||
if (sourcePath != null) overrideMap["sourcePath"] = sourcePath
|
||||
if (publicKeyOutputPath != null) overrideMap["publicKeyOutputPath"] = publicKeyOutputPath
|
||||
if (signatureOutputPath != null) overrideMap["signatureOutputPath"] = signatureOutputPath
|
||||
overrideMap["overwriteKey"] = options.has(overwriteArg).toString()
|
||||
if (options.hasArgument(deviceArg)) {
|
||||
overrideMap["$profile.device"] = options.valueOf(deviceArg)
|
||||
}
|
||||
@ -61,18 +74,33 @@ data class ToolConfig(val config: Config) {
|
||||
final!!
|
||||
}())
|
||||
|
||||
val mode: Mode by config
|
||||
val profile: String by config
|
||||
val profileConfig: Config get() = config.getConfig(profile)
|
||||
val device: String by profileConfig
|
||||
val keyName: String by profileConfig
|
||||
val keyGroup: String by profileConfig
|
||||
val keySpecifier: String by profileConfig
|
||||
val sourcePath: Path by config
|
||||
val publicKeyOutputPath: Path by config
|
||||
val signatureOutputPath: Path by config
|
||||
val sourcePath: Path? by config
|
||||
val publicKeyOutputPath: Path? by config
|
||||
val signatureOutputPath: Path? by config
|
||||
val overwriteKey: Boolean by config
|
||||
|
||||
init {
|
||||
when (mode) {
|
||||
Mode.Sign -> {
|
||||
requireNotNull(sourcePath)
|
||||
requireNotNull(signatureOutputPath)
|
||||
requireNotNull(publicKeyOutputPath)
|
||||
}
|
||||
Mode.GenerateKey -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val sb = StringBuilder()
|
||||
sb.append("mode: $mode\n")
|
||||
sb.append("profile: $profile\n")
|
||||
sb.append("device: $device\n")
|
||||
sb.append("keyName: $keyName\n")
|
150
sgx-jvm/hsm-tool/src/main/kotlin/com/r3cev/sgx/hsmtool/Main.kt
Normal file
150
sgx-jvm/hsm-tool/src/main/kotlin/com/r3cev/sgx/hsmtool/Main.kt
Normal file
@ -0,0 +1,150 @@
|
||||
package com.r3cev.sgx.hsmtool
|
||||
|
||||
import CryptoServerAPI.CryptoServerException
|
||||
import CryptoServerCXI.CryptoServerCXI
|
||||
import CryptoServerJCE.CryptoServerProvider
|
||||
import com.r3cev.sgx.config.Mode
|
||||
import com.r3cev.sgx.config.ToolConfig
|
||||
import com.r3cev.sgx.utils.HsmErrors
|
||||
import org.bouncycastle.openssl.jcajce.JcaPEMWriter
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.FileWriter
|
||||
import java.math.BigInteger
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.StandardOpenOption
|
||||
import java.security.*
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
|
||||
fun sign(config: ToolConfig) {
|
||||
require(Files.exists(config.sourcePath)) { "Input ${config.sourcePath} not found" }
|
||||
connectAndAuthenticate(config) { provider ->
|
||||
val keyStore = KeyStore.getInstance("CryptoServer", provider)
|
||||
keyStore.load(null, null)
|
||||
val aliases = keyStore.aliases().toList()
|
||||
println(aliases)
|
||||
val sgxKey = keyStore.getKey(config.keyName, null) as PrivateKey
|
||||
val data = Files.readAllBytes(config.sourcePath)
|
||||
val signer = Signature.getInstance("SHA256WithRSA", provider)
|
||||
signer.initSign(sgxKey)
|
||||
signer.update(data)
|
||||
val signature = signer.sign()
|
||||
|
||||
val javaFactory = KeyFactory.getInstance("RSA")
|
||||
val sgxPub = keyStore.getCertificate(config.keyName).publicKey
|
||||
val sgxPubReImport = javaFactory.generatePublic(X509EncodedKeySpec(sgxPub.encoded))
|
||||
val verify = Signature.getInstance("SHA256WithRSA")
|
||||
verify.initVerify(sgxPubReImport)
|
||||
verify.update(data)
|
||||
|
||||
require(verify.verify(signature)) { "Signature didn't independently verify" }
|
||||
System.setProperty("line.separator", "\n") // Ensure UNIX line endings in PEM files
|
||||
println("Writing signature")
|
||||
saveSignatureAsFile(signature, config.signatureOutputPath!!)
|
||||
println("Writing public key")
|
||||
savePublicKeyAsPEMFile(sgxPubReImport, config.publicKeyOutputPath!!)
|
||||
}
|
||||
}
|
||||
|
||||
fun generateKey(config: ToolConfig) {
|
||||
val generateFlag = if (config.overwriteKey) {
|
||||
println("!!! WARNING: OVERWRITING KEY NAMED ${config.keyName} !!!")
|
||||
CryptoServerCXI.FLAG_OVERWRITE
|
||||
} else {
|
||||
0
|
||||
}
|
||||
connectAndAuthenticate(config) { provider ->
|
||||
val keyAttributes = CryptoServerCXI.KeyAttributes()
|
||||
keyAttributes.apply {
|
||||
algo = CryptoServerCXI.KEY_ALGO_RSA
|
||||
size = 3072
|
||||
setExponent(BigInteger.valueOf(0x03))
|
||||
group = config.keyGroup
|
||||
specifier = config.keySpecifier.toInt()
|
||||
export = 0 // deny export
|
||||
name = config.keyName
|
||||
|
||||
}
|
||||
println("Generating key...")
|
||||
// This should be CryptoServerCXI.MECH_KEYGEN_FIPS186_4_PRIME, however FIPS doesn't support exponent 3
|
||||
val mechanismFlag = CryptoServerCXI.MECH_RND_REAL or CryptoServerCXI.MECH_KEYGEN_ANSI_PRIME
|
||||
provider.cryptoServer.generateKey(generateFlag, keyAttributes, mechanismFlag)
|
||||
}
|
||||
}
|
||||
|
||||
fun connectAndAuthenticate(config: ToolConfig, block: (CryptoServerProvider) -> Unit) {
|
||||
println("Connect to ${config.device}")
|
||||
val provider = createProvider(config.device, config.keyGroup, config.keySpecifier)
|
||||
try {
|
||||
while (true) {
|
||||
print("Enter User Name: ")
|
||||
val user = readLine()
|
||||
println("Login user: $user")
|
||||
provider.loginSign(user, ":cs2:cyb:USB0", null)
|
||||
val auth = provider.cryptoServer.authState
|
||||
if ((auth and 0x0000000F) >= 0x00000002) {
|
||||
println("Auth Sufficient")
|
||||
break
|
||||
}
|
||||
println("Need more permissions. Add extra login")
|
||||
}
|
||||
block(provider)
|
||||
} finally {
|
||||
provider.logoff()
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println("SGX Tool started")
|
||||
val config = ToolConfig(args)
|
||||
println(config)
|
||||
try {
|
||||
when (config.mode) {
|
||||
Mode.Sign -> sign(config)
|
||||
Mode.GenerateKey -> generateKey(config)
|
||||
}
|
||||
println("Done!")
|
||||
} catch (exception: Throwable) {
|
||||
// Try to decode the error code
|
||||
val crypto = exception as? CryptoServerException ?: exception.cause as? CryptoServerException
|
||||
if (crypto != null) {
|
||||
throw Exception(HsmErrors.errors[crypto.ErrorCode], exception)
|
||||
} else {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun saveSignatureAsFile(signature: ByteArray, filename: Path) {
|
||||
Files.write(filename, signature, StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)
|
||||
}
|
||||
|
||||
private fun savePublicKeyAsPEMFile(key: PublicKey, filename: Path) {
|
||||
FileWriter(filename.toFile()).use {
|
||||
JcaPEMWriter(it).use {
|
||||
it.writeObject(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createProvider(device: String, keyGroup: String, keySpecifier: String): CryptoServerProvider {
|
||||
val cfgBuffer = ByteArrayOutputStream()
|
||||
val writer = cfgBuffer.writer(Charsets.UTF_8)
|
||||
writer.write("Device = $device\n")
|
||||
writer.write("ConnectionTimeout = 3000\n")
|
||||
writer.write("Timeout = 30000\n")
|
||||
writer.write("EndSessionOnShutdown = 1\n")
|
||||
writer.write("KeepSessionAlive = 0\n")
|
||||
writer.write("KeyGroup = $keyGroup\n")
|
||||
writer.write("KeySpecifier = $keySpecifier\n")
|
||||
writer.write("StoreKeysExternal = false\n")
|
||||
writer.close()
|
||||
val cfg = ByteArrayInputStream(cfgBuffer.toByteArray())
|
||||
cfgBuffer.close()
|
||||
val provider = CryptoServerProvider(cfg)
|
||||
cfg.close()
|
||||
return provider
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
package com.r3cev.sgx.utils
|
||||
|
||||
import java.util.*
|
||||
|
||||
|
||||
object HsmErrors {
|
||||
val errors: Map<Int, String> by lazy(HsmErrors::load)
|
||||
|
||||
fun load(): Map<Int, String> {
|
||||
val errors = HashMap<Int, String>()
|
||||
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
|
||||
}
|
||||
}
|
4462
sgx-jvm/hsm-tool/src/main/resources/com/r3cev/sgx/utils/hsm_errors
Normal file
4462
sgx-jvm/hsm-tool/src/main/resources/com/r3cev/sgx/utils/hsm_errors
Normal file
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,6 @@ set_target_properties(edger8r PROPERTIES IMPORTED_LOCATION ${SGX_LIBRARY_PATH}/s
|
||||
|
||||
set(GENERATED_EDL_FILES ${GENERATED_RPC_DIR}/java_t.c ${GENERATED_RPC_DIR}/java_t.h ${GENERATED_RPC_DIR}/java_u.c ${GENERATED_RPC_DIR}/java_u.h)
|
||||
set(GENERATED_EDL_FILES ${GENERATED_EDL_FILES} PARENT_SCOPE)
|
||||
message(STATUS FFS "${GENERATED_EDL_FILES}")
|
||||
add_custom_command(
|
||||
OUTPUT ${GENERATED_EDL_FILES}
|
||||
COMMAND edger8r --search-path ${PROJECT_SOURCE_DIR}/rpc --search-path ${SGX_SDK_INCLUDE} --trusted-dir ${GENERATED_RPC_DIR} --untrusted-dir ${GENERATED_RPC_DIR} java.edl
|
||||
|
@ -147,7 +147,7 @@ set_target_properties(sgx_sign PROPERTIES IMPORTED_LOCATION ${SGX_SIGN_TOOL})
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_OUTPUT_LIB}
|
||||
COMMAND sgx_sign sign -key ${PRIVATE_KEY_NAME} -enclave ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED_OUTPUT_LIB} -out ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_OUTPUT_LIB} -config ${CMAKE_CURRENT_SOURCE_DIR}/enclave.xml
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED_OUTPUT_LIB} ${PRIVATE_KEY_NAME}
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED_OUTPUT_LIB} ${PRIVATE_KEY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/enclave.xml
|
||||
)
|
||||
|
||||
add_custom_target(enclave DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_OUTPUT_LIB})
|
||||
|
@ -4,15 +4,25 @@ set(SGX_SDK ${CMAKE_CURRENT_SOURCE_DIR}/../linux-sgx)
|
||||
set(SGX_LIBRARY_PATH ${SGX_SDK}/build/linux)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fpie -fstack-protector")
|
||||
set(SGX_SIGN_TOOL ${SGX_SDK}/build/linux/sgx_sign)
|
||||
set(ENCLAVE_UNSIGNED_OUTPUT_LIB noop_enclave.so)
|
||||
set(ENCLAVE_UNSIGNED noop_enclave.unsigned.so)
|
||||
set(ENCLAVE_BLOB_TO_SIGN noop_enclave_blob_to_sign.bin)
|
||||
set(ENCLAVE_SIGNED_OUTPUT_LIB noop_enclave.signed.so)
|
||||
set(PRIVATE_KEY_NAME selfsigning.pem)
|
||||
set(PUBLIC_KEY_NAME selfsigning.public.pem)
|
||||
set(ENCLAVE_SIGNED_OPENSSL noop_enclave.signed.openssl.so)
|
||||
set(ENCLAVE_SIGNED_HSM noop_enclave.signed.hsm.so)
|
||||
set(ENCLAVE_SIGNATURE_OPENSSL noop_enclave.signature.openssl.sha256)
|
||||
set(ENCLAVE_SIGNATURE_HSM noop_enclave.signature.hsm.sha256)
|
||||
set(ENCLAVE_SIGSTRUCT_OPENSSL noop_enclave.sigstruct.openssl.bin)
|
||||
set(ENCLAVE_SIGSTRUCT_HSM noop_enclave.sigstruct.hsm.bin)
|
||||
set(ENCLAVE_SIGSTRUCT_PRETTY_OPENSSL noop_enclave.sigstruct-pretty.openssl.txt)
|
||||
set(ENCLAVE_SIGSTRUCT_PRETTY_HSM noop_enclave.sigstruct-pretty.hsm.txt)
|
||||
set(PRIVATE_KEY_NAME_OPENSSL selfsigning.pem)
|
||||
set(PUBLIC_KEY_NAME_OPENSSL selfsigning.public.pem)
|
||||
set(PUBLIC_KEY_NAME_HSM hsm.public.pem)
|
||||
set(SIGN_HELPER ${PROJECT_SOURCE_DIR}/sign_helper/sign_helper)
|
||||
set(HSM_SGX_TOOL ${PROJECT_SOURCE_DIR}/../hsm-tool/build/libs/sgx-jvm/hsm-tool-1.0-SNAPSHOT.jar)
|
||||
|
||||
set(NOOP_ENCLAVE noop_enclave_objects)
|
||||
set(SGX_SDK_INCLUDE ${SGX_SDK}/common/inc)
|
||||
set(GENERATED_RPC_DIR ${CMAKE_CURRENT_BINARY_DIR}/rpc)
|
||||
set(ENCLAVE_SIGNATURE noop_enclave.signature.sha256)
|
||||
|
||||
set(GENERATED_EDL_FILES ${GENERATED_RPC_DIR}/empty_t.c ${GENERATED_RPC_DIR}/empty_t.h ${GENERATED_RPC_DIR}/empty_u.c ${GENERATED_RPC_DIR}/empty_u.h)
|
||||
add_custom_command(
|
||||
@ -35,10 +45,14 @@ target_compile_options(${NOOP_ENCLAVE} PUBLIC -nostdinc)
|
||||
add_executable(edger8r IMPORTED)
|
||||
set_target_properties(edger8r PROPERTIES IMPORTED_LOCATION ${SGX_LIBRARY_PATH}/sgx_edger8r)
|
||||
|
||||
set(SGX_USE_HARDWARE FALSE)
|
||||
|
||||
if(SGX_USE_HARDWARE)
|
||||
set(URTS_LIB "sgx_urts")
|
||||
set(TRTS_LIB "sgx_trts")
|
||||
set(SGX_SERVICE_LIB "sgx_tservice")
|
||||
else()
|
||||
set(URTS_LIB "sgx_urts_sim")
|
||||
set(TRTS_LIB "sgx_trts_sim")
|
||||
set(SGX_SERVICE_LIB "sgx_tservice_sim")
|
||||
endif()
|
||||
@ -69,43 +83,100 @@ set(ENCLAVE_LINKER_FLAGS
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED_OUTPUT_LIB}
|
||||
COMMAND ${CMAKE_CXX_COMPILER} -o ${ENCLAVE_UNSIGNED_OUTPUT_LIB} ${ENCLAVE_LINKER_FLAGS}
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED}
|
||||
COMMAND ${CMAKE_CXX_COMPILER} -o ${ENCLAVE_UNSIGNED} ${ENCLAVE_LINKER_FLAGS}
|
||||
DEPENDS ${NOOP_ENCLAVE} ${SGX_LIBRARY_PATH}
|
||||
)
|
||||
|
||||
|
||||
add_executable(sgx_sign IMPORTED)
|
||||
set_target_properties(sgx_sign PROPERTIES IMPORTED_LOCATION ${SGX_SIGN_TOOL})
|
||||
|
||||
# add_custom_command(
|
||||
# OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_OUTPUT_LIB}
|
||||
# COMMAND sgx_sign sign -key ${CMAKE_CURRENT_SOURCE_DIR}/${PRIVATE_KEY_NAME} -enclave ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED_OUTPUT_LIB} -out ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_OUTPUT_LIB} -config ${CMAKE_CURRENT_SOURCE_DIR}/enclave.xml
|
||||
# DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED_OUTPUT_LIB} ${CMAKE_CURRENT_SOURCE_DIR}/${PRIVATE_KEY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/enclave.xml
|
||||
# )
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_BLOB_TO_SIGN}
|
||||
COMMAND sgx_sign gendata -enclave ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED_OUTPUT_LIB} -out ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_BLOB_TO_SIGN} -config ${CMAKE_CURRENT_SOURCE_DIR}/enclave.xml
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED_OUTPUT_LIB}
|
||||
COMMAND sgx_sign gendata -enclave ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED} -out ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_BLOB_TO_SIGN} -config ${CMAKE_CURRENT_SOURCE_DIR}/enclave.xml
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED}
|
||||
)
|
||||
|
||||
# TODO: replace with getting the pubkey from HSM
|
||||
# outputs the unsigned enclave and the blob to sign
|
||||
add_custom_target(unsigned DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED} ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_BLOB_TO_SIGN})
|
||||
|
||||
# OPENSSL ENCLAVE
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PUBLIC_KEY_NAME}
|
||||
COMMAND openssl rsa -in ${CMAKE_CURRENT_SOURCE_DIR}/${PRIVATE_KEY_NAME} -pubout -out ${CMAKE_CURRENT_BINARY_DIR}/${PUBLIC_KEY_NAME}
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PUBLIC_KEY_NAME_OPENSSL}
|
||||
COMMAND openssl rsa -in ${CMAKE_CURRENT_SOURCE_DIR}/${PRIVATE_KEY_NAME_OPENSSL} -pubout -out ${CMAKE_CURRENT_BINARY_DIR}/${PUBLIC_KEY_NAME_OPENSSL}
|
||||
)
|
||||
|
||||
# TODO: replace with signing on HSM
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNATURE}
|
||||
COMMAND openssl dgst -sha256 -sign ${CMAKE_CURRENT_SOURCE_DIR}/${PRIVATE_KEY_NAME} -out ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNATURE} ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_BLOB_TO_SIGN}
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNATURE_OPENSSL}
|
||||
COMMAND openssl dgst -sha256 -sign ${CMAKE_CURRENT_SOURCE_DIR}/${PRIVATE_KEY_NAME_OPENSSL} -out ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNATURE_OPENSSL} ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_BLOB_TO_SIGN}
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_BLOB_TO_SIGN}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_OUTPUT_LIB}
|
||||
COMMAND sgx_sign catsig -enclave ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED_OUTPUT_LIB} -key ${CMAKE_CURRENT_BINARY_DIR}/${PUBLIC_KEY_NAME} -sig ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNATURE} -unsigned ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_BLOB_TO_SIGN} -config ${CMAKE_CURRENT_SOURCE_DIR}/enclave.xml -out ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_OUTPUT_LIB}
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNATURE} ${CMAKE_CURRENT_BINARY_DIR}/${PUBLIC_KEY_NAME}
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_OPENSSL}
|
||||
COMMAND sgx_sign catsig -enclave ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED} -key ${CMAKE_CURRENT_BINARY_DIR}/${PUBLIC_KEY_NAME_OPENSSL} -sig ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNATURE_OPENSSL} -unsigned ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_BLOB_TO_SIGN} -config ${CMAKE_CURRENT_SOURCE_DIR}/enclave.xml -out ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_OPENSSL}
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNATURE_OPENSSL} ${CMAKE_CURRENT_BINARY_DIR}/${PUBLIC_KEY_NAME_OPENSSL}
|
||||
)
|
||||
|
||||
add_custom_target(noop-enclave ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_OUTPUT_LIB})
|
||||
add_custom_target(signed-openssl DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_OPENSSL})
|
||||
# /OPENSSL ENCLAVE
|
||||
|
||||
|
||||
# HSM ENCLAVE
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PUBLIC_KEY_NAME_HSM} ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNATURE_HSM}
|
||||
COMMAND java -jar ${HSM_SGX_TOOL} --mode=Sign --source=${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_BLOB_TO_SIGN} --pubkey=${CMAKE_CURRENT_BINARY_DIR}/${PUBLIC_KEY_NAME_HSM} --signature=${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNATURE_HSM} --profile=\${PROFILE}
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_BLOB_TO_SIGN}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_HSM}
|
||||
COMMAND sgx_sign catsig -enclave ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_UNSIGNED} -key ${CMAKE_CURRENT_BINARY_DIR}/${PUBLIC_KEY_NAME_HSM} -sig ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNATURE_HSM} -unsigned ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_BLOB_TO_SIGN} -config ${CMAKE_CURRENT_SOURCE_DIR}/enclave.xml -out ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_HSM}
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNATURE_HSM} ${CMAKE_CURRENT_BINARY_DIR}/${PUBLIC_KEY_NAME_HSM}
|
||||
)
|
||||
|
||||
add_custom_target(signed-hsm DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_HSM})
|
||||
# /HSM ENCLAVE
|
||||
|
||||
# HSM KEY
|
||||
add_custom_command(
|
||||
OUTPUT __generate-key-hsm-dummy__
|
||||
COMMAND java -jar ${HSM_SGX_TOOL} --mode=GenerateKey --profile=\${PROFILE} \$\(shell bash -c '[[ \${OVERWRITE} = "true" ]] && echo "--overwriteKey"' \)
|
||||
)
|
||||
add_custom_target(generate-key-hsm DEPENDS __generate-key-hsm-dummy__)
|
||||
# /HSM KEY
|
||||
|
||||
# OPENSSL SIGSTRUCT
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_OPENSSL}
|
||||
COMMAND ${SIGN_HELPER} get-css -in ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_OPENSSL} -out ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_OPENSSL}
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_OPENSSL}
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_PRETTY_OPENSSL}
|
||||
COMMAND ${SIGN_HELPER} print-css -in ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_OPENSSL} > ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_PRETTY_OPENSSL}
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_OPENSSL}
|
||||
)
|
||||
add_custom_target(sigstruct-openssl DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_OPENSSL} ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_PRETTY_OPENSSL})
|
||||
# /OPENSSL SIGSTRUCT
|
||||
|
||||
# HSM SIGSTRUCT
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_HSM}
|
||||
COMMAND ${SIGN_HELPER} get-css -in ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_HSM} -out ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_HSM}
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGNED_HSM}
|
||||
)
|
||||
add_custom_target(sigstruct-hsm DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_HSM})
|
||||
# /HSM SIGSTRUCT
|
||||
|
||||
# test
|
||||
add_library(urtslib SHARED IMPORTED)
|
||||
set_target_properties(urtslib PROPERTIES IMPORTED_LOCATION ${SGX_LIBRARY_PATH}/lib${URTS_LIB}.so)
|
||||
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
add_executable(noop_test src/test.cpp ${GENERATED_RPC_DIR}/empty_u.c)
|
||||
target_include_directories(noop_test PUBLIC ${SGX_SDK_INCLUDE} ${GENERATED_RPC_DIR})
|
||||
target_link_libraries(noop_test urtslib Threads::Threads)
|
||||
|
@ -1,5 +1,7 @@
|
||||
.PHONY: all
|
||||
all: build/noop-enclave.so
|
||||
all: build/Makefile
|
||||
$(MAKE) -C $(<D) help
|
||||
exit 1
|
||||
|
||||
build:
|
||||
mkdir -p build
|
||||
@ -7,8 +9,8 @@ build:
|
||||
build/Makefile: | build
|
||||
cd build/ && cmake ..
|
||||
|
||||
build/noop-enclave.so: build/Makefile
|
||||
$(MAKE) -C $(<D) VERBOSE=1
|
||||
%: build/Makefile
|
||||
$(MAKE) -C $(<D) $@
|
||||
|
||||
clean:
|
||||
rm -rf build
|
||||
|
26
sgx-jvm/noop-enclave/README.md
Normal file
26
sgx-jvm/noop-enclave/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
What is this?
|
||||
=============
|
||||
|
||||
This project contains a noop enclave with a single ECALL that does
|
||||
nothing. Its purpose is to demonstrate our ability to create a signed
|
||||
enclave and to test the signature process through an HSM.
|
||||
|
||||
How to run
|
||||
==========
|
||||
|
||||
The following Makefile targets execute different steps in the signing process and output into build/
|
||||
|
||||
`make unsigned` will build the unsigned enclave (noop\_enclave.unsigned.so).
|
||||
|
||||
The following targets use OpenSSL instead of the HSM:
|
||||
`make signed-openssl` will sign the unsigned enclave with openssl using selfsigning.pem (noop\_enclave.signed.openssl.so).
|
||||
`make sigstruct-openssl` will extract the SIGSTRUCT into a blob as well as a pretty printed txt from the openssl signed enclave (noop\_enclave.sigstruct.openssl.bin, noop\_enclave.sigstruct-pretty.openssl.txt).
|
||||
|
||||
The following targets use the HSM. They require an extra `PROFILE=[dev|prod]` argument to indicate whether to use a local HSM simulator or the real thing.
|
||||
`make generate-key-hsm PROFILE=[dev|prod] [OVERWRITE=true]` will generate a fresh key for the profile. By default this will not overwrite an existing key, for that pass in MODE=overwrite.
|
||||
`make signed-hsm PROFILE=[dev|prod]` will sign the unsigned enclave with the HSM. This target requires authentication (noop\_enclave.signed.hsm.so).
|
||||
`make sigstruct-hsm PROFILE=[dev|prod]` will extract the SIGSTRUCT into a blob as well as a pretty printed txt from the HSM signed enclave (noop\_enclave.sigstruct.hsm.bin, noop\_enclave.sigstruct-pretty.hsm.txt).
|
||||
|
||||
`make noop_test` will create a test binary that loads an enclave and runs the noop ECALL inside it. For example:
|
||||
`./build/noop_test ./build/noop_enclave.signed.openssl.so`
|
||||
will run the noop ECALL using the openssl signed enclave.
|
BIN
sgx-jvm/noop-enclave/sign_helper/sign_helper
Executable file
BIN
sgx-jvm/noop-enclave/sign_helper/sign_helper
Executable file
Binary file not shown.
144
sgx-jvm/noop-enclave/src/test.cpp
Normal file
144
sgx-jvm/noop-enclave/src/test.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
#include "empty_u.h"
|
||||
|
||||
#include <sgx_urts.h>
|
||||
#include <sgx.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
typedef struct {
|
||||
sgx_status_t err;
|
||||
const char *message;
|
||||
const char *suggestion;
|
||||
} sgx_errlist_t;
|
||||
|
||||
/* Error code returned by sgx_create_enclave */
|
||||
static sgx_errlist_t sgx_errlist[] = {
|
||||
{
|
||||
SGX_ERROR_UNEXPECTED,
|
||||
"Unexpected error occurred.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_PARAMETER,
|
||||
"Invalid parameter.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_OUT_OF_MEMORY,
|
||||
"Out of memory.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_ENCLAVE_LOST,
|
||||
"Power transition occurred.",
|
||||
"Please refer to the sample \"PowerTransition\" for details."
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_ENCLAVE,
|
||||
"Invalid enclave image.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_ENCLAVE_ID,
|
||||
"Invalid enclave identification.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_SIGNATURE,
|
||||
"Invalid enclave signature.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_OUT_OF_EPC,
|
||||
"Out of EPC memory.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_NO_DEVICE,
|
||||
"Invalid SGX device.",
|
||||
"Please make sure SGX module is enabled in the BIOS, and install SGX driver afterwards."
|
||||
},
|
||||
{
|
||||
SGX_ERROR_MEMORY_MAP_CONFLICT,
|
||||
"Memory map conflicted.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_METADATA,
|
||||
"Invalid enclave metadata.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_DEVICE_BUSY,
|
||||
"SGX device was busy.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_VERSION,
|
||||
"Enclave version was invalid.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_ATTRIBUTE,
|
||||
"Enclave was not authorized.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_ENCLAVE_FILE_ACCESS,
|
||||
"Can't open enclave file.",
|
||||
NULL
|
||||
},
|
||||
};
|
||||
|
||||
/* Check error conditions for loading enclave */
|
||||
void print_error_message(sgx_status_t ret)
|
||||
{
|
||||
size_t idx = 0;
|
||||
size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0];
|
||||
|
||||
for (idx = 0; idx < ttl; idx++) {
|
||||
if(ret == sgx_errlist[idx].err) {
|
||||
if(NULL != sgx_errlist[idx].suggestion)
|
||||
printf("Info: %s\n", sgx_errlist[idx].suggestion);
|
||||
printf("Error: %s\n", sgx_errlist[idx].message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx == ttl)
|
||||
printf("Error: Unexpected error occurred.\n");
|
||||
}
|
||||
|
||||
inline bool check_sgx_return_value(sgx_status_t ret)
|
||||
{
|
||||
if (ret == SGX_SUCCESS)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
print_error_message(ret);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
if (argc != 2) {
|
||||
puts("Usage: <binary> <signed.enclave.so>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *enclave_path = argv[1];
|
||||
sgx_launch_token_t token = {0};
|
||||
sgx_enclave_id_t enclave_id = {0};
|
||||
int updated = 0;
|
||||
if (false == check_sgx_return_value(sgx_create_enclave(enclave_path, SGX_DEBUG_FLAG, &token, &updated, &enclave_id, NULL))) {
|
||||
return 1;
|
||||
}
|
||||
if (false == check_sgx_return_value(noop(enclave_id))) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package com.r3cev.sgx.signtool
|
||||
|
||||
import CryptoServerJCE.CryptoServerProvider
|
||||
import com.r3cev.sgx.config.ToolConfig
|
||||
import org.bouncycastle.openssl.jcajce.JcaPEMWriter
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.FileWriter
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.StandardOpenOption
|
||||
import java.security.*
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println("SGX Tool started")
|
||||
val config = ToolConfig(args)
|
||||
require(Files.exists(config.sourcePath)) { "Input ${config.sourcePath} not found" }
|
||||
println(config)
|
||||
println("Connect to ${config.device}")
|
||||
val provider = createProvider(config.device, config.keyGroup, config.keySpecifier)
|
||||
while (true) {
|
||||
print("Enter User Name: ")
|
||||
val user = readLine()
|
||||
println("Login user: $user")
|
||||
provider.loginSign(user, ":cs2:cyb:USB0", null)
|
||||
val auth = provider.cryptoServer.authState
|
||||
if ((auth and 0x0000000F) >= 0x00000002) {
|
||||
println("Auth Sufficient")
|
||||
break
|
||||
}
|
||||
println("Need more permissions. Add extra login")
|
||||
}
|
||||
val keyStore = KeyStore.getInstance("CryptoServer", provider)
|
||||
keyStore.load(null, null)
|
||||
val aliases = keyStore.aliases().toList()
|
||||
println(aliases)
|
||||
val sgxKey = keyStore.getKey(config.keyName, null) as PrivateKey
|
||||
val data = Files.readAllBytes(config.sourcePath)
|
||||
val signer = Signature.getInstance("SHA256WithRSA", provider)
|
||||
signer.initSign(sgxKey)
|
||||
signer.update(data)
|
||||
val signature = signer.sign()
|
||||
|
||||
val javaFactory = KeyFactory.getInstance("RSA")
|
||||
val sgxPub = keyStore.getCertificate(config.keyName).publicKey
|
||||
val sgxPubReImport = javaFactory.generatePublic(X509EncodedKeySpec(sgxPub.encoded))
|
||||
val verify = Signature.getInstance("SHA256WithRSA")
|
||||
verify.initVerify(sgxPubReImport)
|
||||
verify.update(data)
|
||||
|
||||
require(verify.verify(signature)) { "Signature didn't independently verify" }
|
||||
System.setProperty("line.separator", "\n") // Ensure UNIX line endings in PEM files
|
||||
saveSignatureAsFile(signature, config.signatureOutputPath)
|
||||
savePublicKeyAsPEMFile(sgxPubReImport, config.publicKeyOutputPath)
|
||||
|
||||
provider.logoff()
|
||||
}
|
||||
|
||||
|
||||
private fun saveSignatureAsFile(signature: ByteArray, filename: Path) {
|
||||
Files.write(filename, signature, StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)
|
||||
}
|
||||
|
||||
private fun savePublicKeyAsPEMFile(key: PublicKey, filename: Path) {
|
||||
FileWriter(filename.toFile()).use {
|
||||
JcaPEMWriter(it).use {
|
||||
it.writeObject(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createProvider(device: String, keyGroup: String, keySpecifier: String): CryptoServerProvider {
|
||||
val cfgBuffer = ByteArrayOutputStream()
|
||||
val writer = cfgBuffer.writer(Charsets.UTF_8)
|
||||
writer.write("Device = $device\n")
|
||||
writer.write("ConnectionTimeout = 3000\n")
|
||||
writer.write("Timeout = 30000\n")
|
||||
writer.write("EndSessionOnShutdown = 1\n")
|
||||
writer.write("KeepSessionAlive = 0\n")
|
||||
writer.write("KeyGroup = $keyGroup\n")
|
||||
writer.write("KeySpecifier = $keySpecifier\n")
|
||||
writer.write("StoreKeysExternal = false\n")
|
||||
writer.close()
|
||||
val cfg = ByteArrayInputStream(cfgBuffer.toByteArray())
|
||||
cfgBuffer.close()
|
||||
val provider = CryptoServerProvider(cfg)
|
||||
cfg.close()
|
||||
return provider
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user