Merge pull request #2 from corda/aslemmer-noop-enclave

Noop enclave
This commit is contained in:
Mike Hearn 2017-06-20 15:25:13 +02:00 committed by GitHub
commit f05caeea3d
34 changed files with 5491 additions and 13 deletions

15
.idea/compiler.xml generated
View File

@ -28,6 +28,8 @@
<module name="docs_source_example-code_main" target="1.8" />
<module name="docs_source_example-code_test" target="1.8" />
<module name="docs_test" target="1.8" />
<module name="doorman_main" target="1.8" />
<module name="doorman_test" target="1.8" />
<module name="experimental_main" target="1.8" />
<module name="experimental_test" target="1.8" />
<module name="explorer-capsule_main" target="1.6" />
@ -73,6 +75,14 @@
<module name="samples_test" target="1.8" />
<module name="sandbox_main" target="1.8" />
<module name="sandbox_test" target="1.8" />
<module name="sgx-jvm_hsm-tool_main" target="1.8" />
<module name="sgx-jvm_hsm-tool_test" target="1.8" />
<module name="sgx-jvm_main" target="1.8" />
<module name="sgx-jvm_sgx-signtool_main" target="1.8" />
<module name="sgx-jvm_sgx-signtool_test" target="1.8" />
<module name="sgx-jvm_test" target="1.8" />
<module name="sgx-signtool_main" target="1.8" />
<module name="sgx-signtool_test" target="1.8" />
<module name="simm-valuation-demo_integrationTest" target="1.8" />
<module name="simm-valuation-demo_main" target="1.8" />
<module name="simm-valuation-demo_test" target="1.8" />
@ -86,6 +96,9 @@
<module name="verifier_integrationTest" target="1.8" />
<module name="verifier_main" target="1.8" />
<module name="verifier_test" target="1.8" />
<module name="verify-enclave_integrationTest" target="1.8" />
<module name="verify-enclave_main" target="1.8" />
<module name="verify-enclave_test" target="1.8" />
<module name="webcapsule_main" target="1.6" />
<module name="webcapsule_test" target="1.6" />
<module name="webserver-webcapsule_main" target="1.6" />
@ -98,4 +111,4 @@
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_STRING" value="-parameters" />
</component>
</project>
</project>

View File

@ -36,3 +36,4 @@ include 'samples:bank-of-corda-demo'
include 'cordform-common'
include 'doorman'
include 'verify-enclave'
include 'sgx-jvm/hsm-tool'

View File

@ -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.

View File

@ -11,12 +11,13 @@
/usr/include/google
/usr/include/openssl
/usr/include/x86_64-linux-gnu/openssl
/usr/include/x86_64-linux-gnu/zconf.h
/usr/include/zconf.h
/usr/include/zlib.h
/usr/lib/x86_64-linux-gnu/libasn1.so.8
/usr/lib/x86_64-linux-gnu/libasn1.so.8.0.0
/usr/lib/x86_64-linux-gnu/libcrypto.so
/usr/lib/x86_64-linux-gnu/libcurl.so
/usr/lib/x86_64-linux-gnu/libcurl.so.4
/usr/lib/x86_64-linux-gnu/libcurl.so.4.4.0
/usr/lib/x86_64-linux-gnu/libffi.so.6
/usr/lib/x86_64-linux-gnu/libgmp.so.10

View File

@ -0,0 +1 @@
libcurl.so.4.4.0

View File

@ -0,0 +1,54 @@
apply plugin: 'java'
apply plugin: 'kotlin'
group 'com.r3cev.sgx'
version '1.0-SNAPSHOT'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
compile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
compile "org.bouncycastle:bcprov-jdk15on:${bouncycastle_version}"
compile "org.bouncycastle:bcpkix-jdk15on:${bouncycastle_version}"
compile "com.typesafe:config:$typesafe_config_version"
compile "net.sf.jopt-simple:jopt-simple:$jopt_simple_version"
testCompile group: 'junit', name: 'junit', version: '4.11'
}
jar {
from(configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) })
exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.MF'
manifest {
attributes('Main-Class' : 'com.r3cev.sgx.hsmtool.MainKt')
}
}
task copyConfig(type: Copy) {
from 'config'
into "$buildDir/libs"
}
build.dependsOn copyConfig

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,129 @@
package com.r3cev.sgx.config
import com.r3cev.sgx.utils.getValue
import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import joptsimple.OptionParser
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import kotlin.system.exitProcess
enum class Mode {
GenerateSgxKey,
Sign
}
data class ToolConfig(val config: Config) {
constructor(args: Array<String>) : this({
val parser = OptionParser()
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()
val signatureOutputPathArg = parser.accepts("signature").withRequiredArg()
val deviceArg = parser.accepts("device").withRequiredArg()
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) {
println(e.message)
parser.printHelpOn(System.out)
printModeHelp()
exitProcess(1)
}
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 $configPath not found" }
ConfigFactory.parseFile(configPath.toFile())
} else {
ConfigFactory.parseResources(ToolConfig::class.java, "sgxtool.cfg")
}
val profile = options.valueOf(profileArg)!!.toLowerCase()
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)
}
if (options.hasArgument(keyNameArg)) {
overrideMap["$profile.keyName"] = options.valueOf(keyNameArg)
}
if (options.hasArgument(keyGroupArg)) {
overrideMap["$profile.keyGroup"] = options.valueOf(keyGroupArg)
}
if (options.hasArgument(keySpecifierArg)) {
overrideMap["$profile.keySpecifier"] = options.valueOf(keySpecifierArg)
}
val overrideConf = ConfigFactory.parseMap(overrideMap)
val final = overrideConf.withFallback(baseConfig).resolve()
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 overwriteKey: Boolean by config
init {
when (mode) {
Mode.Sign -> {
requireNotNull(sourcePath)
requireNotNull(signatureOutputPath)
requireNotNull(publicKeyOutputPath)
}
Mode.GenerateSgxKey -> {
require(sourcePath == null)
require(signatureOutputPath == null)
require(publicKeyOutputPath == null)
}
}
}
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")
sb.append("keyGroup: $keyGroup\n")
sb.append("keySpecifier: $keySpecifier\n")
sb.append("sourcePath: $sourcePath\n")
sb.append("publicKeyOutputPath: $publicKeyOutputPath\n")
sb.append("signatureOutputPath: $signatureOutputPath\n")
return sb.toString()
}
}
fun printModeHelp() {
val message = listOf(
"This tool may be run in two modes, --mode=GenerateSgxKey and --mode=Sign.",
"Both may take --profile as an argument to indicate what HSM profile to use (see sgxtool.cfg)",
"--mode=Sign expects --sourcePath={path to blob to sign}, --signatureOutputPath={path to result signature} and --publicKeyOutputPath={path to output public key}.",
"Providing any of these arguments in --mode=GenerateSgxKey results in an error."
)
println(message.joinToString("\n"))
}

View File

@ -0,0 +1,155 @@
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 generateSgxKey(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 {
try {
provider.logoff()
} catch (throwable: Throwable) {
println("WARNING Exception while logging off")
throwable.printStackTrace(System.out)
}
}
}
fun main(args: Array<String>) {
println("SGX Tool started")
val config = ToolConfig(args)
println(config)
try {
when (config.mode) {
Mode.Sign -> sign(config)
Mode.GenerateSgxKey -> generateSgxKey(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 = 30000\n")
writer.write("Timeout = 60000\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
}

View File

@ -0,0 +1,105 @@
package com.r3cev.sgx.utils
import com.typesafe.config.Config
import com.typesafe.config.ConfigUtil
import java.net.Proxy
import java.net.URL
import java.nio.file.Path
import java.nio.file.Paths
import java.time.Instant
import java.time.LocalDate
import java.util.*
import kotlin.reflect.KClass
import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.jvmErasure
// TODO Move other config parsing to use parseAs and remove this
operator fun <T> Config.getValue(receiver: Any, metadata: KProperty<*>): T {
return getValueInternal(metadata.name, metadata.returnType)
}
fun <T : Any> Config.parseAs(clazz: KClass<T>): T {
require(clazz.isData) { "Only Kotlin data classes can be parsed" }
val constructor = clazz.primaryConstructor!!
val args = constructor.parameters
.filterNot { it.isOptional && !hasPath(it.name!!) }
.associateBy({ it }) { param ->
// Get the matching property for this parameter
val property = clazz.memberProperties.first { it.name == param.name }
getValueInternal<Any>(property.name, param.type)
}
return constructor.callBy(args)
}
inline fun <reified T : Any> Config.parseAs(): T = parseAs(T::class)
fun Config.toProperties(): Properties {
return entrySet().associateByTo(
Properties(),
{ ConfigUtil.splitPath(it.key).joinToString(".") },
{ it.value.unwrapped().toString() })
}
@Suppress("UNCHECKED_CAST")
private fun <T> Config.getValueInternal(path: String, type: KType): T {
return (if (type.arguments.isEmpty()) getSingleValue(path, type) else getCollectionValue(path, type)) as T
}
private fun Config.getSingleValue(path: String, type: KType): Any? {
if (type.isMarkedNullable && !hasPath(path)) return null
val typeClass = type.jvmErasure
return when (typeClass) {
String::class -> getString(path)
Int::class -> getInt(path)
Long::class -> getLong(path)
Double::class -> getDouble(path)
Boolean::class -> getBoolean(path)
LocalDate::class -> LocalDate.parse(getString(path))
Instant::class -> Instant.parse(getString(path))
Path::class -> Paths.get(getString(path))
URL::class -> URL(getString(path))
Properties::class -> getConfig(path).toProperties()
else -> if (typeClass.java.isEnum) {
parseEnum(typeClass.java, getString(path))
} else {
getConfig(path).parseAs(typeClass)
}
}
}
private fun Config.getCollectionValue(path: String, type: KType): Collection<Any> {
val typeClass = type.jvmErasure
require(typeClass == List::class || typeClass == Set::class) { "$typeClass is not supported" }
val elementClass = type.arguments[0].type?.jvmErasure ?: throw IllegalArgumentException("Cannot work with star projection: $type")
if (!hasPath(path)) {
return if (typeClass == List::class) emptyList() else emptySet()
}
val values: List<Any> = when (elementClass) {
String::class -> getStringList(path)
Int::class -> getIntList(path)
Long::class -> getLongList(path)
Double::class -> getDoubleList(path)
Boolean::class -> getBooleanList(path)
LocalDate::class -> getStringList(path).map(LocalDate::parse)
Instant::class -> getStringList(path).map(Instant::parse)
Path::class -> getStringList(path).map { Paths.get(it) }
URL::class -> getStringList(path).map(::URL)
Properties::class -> getConfigList(path).map(Config::toProperties)
else -> if (elementClass.java.isEnum) {
getStringList(path).map { parseEnum(elementClass.java, it) }
} else {
getConfigList(path).map { it.parseAs(elementClass) }
}
}
return if (typeClass == Set::class) values.toSet() else values
}
@Suppress("UNCHECKED_CAST")
private fun parseEnum(enumType: Class<*>, name: String): Enum<*> = enumBridge(enumType as Class<Proxy.Type>, name) // Any enum will do
private fun <T : Enum<T>> enumBridge(clazz: Class<T>, name: String): T = java.lang.Enum.valueOf(clazz, name)

View File

@ -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
}
}

View File

@ -0,0 +1,14 @@
profile = "dev"
dev : {
device = "3001@127.0.0.1"
keyName = "DEV_SGX"
keyGroup = "DEV.SGX"
keySpecifier = "1"
}
prod : {
device = "TCP:10.18.0.47"
keyName = "PROD_SGX"
keyGroup = "PROD.SGX"
keySpecifier = "1"
}

File diff suppressed because it is too large Load Diff

View File

@ -6,14 +6,15 @@ set(SGX_SDK ${CMAKE_CURRENT_SOURCE_DIR}/../../linux-sgx CACHE STRING "")
set(SGX_LIBRARY_PATH ${SGX_SDK}/build/linux CACHE STRING "")
set(SGX_SDK_INCLUDE ${SGX_SDK}/common/inc CACHE STRING "")
set(GENERATED_RPC_DIR ${CMAKE_CURRENT_BINARY_DIR}/rpc CACHE STRING "")
set(PROGUARD_JAR_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../dependencies/root/usr/share/java/proguard.jar CACHE STRING "")
set(DEPENDENCIES_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../dependencies/root)
set(PROGUARD_JAR_PATH ${DEPENDENCIES_ROOT_DIR}/usr/share/java/proguard.jar CACHE STRING "")
set(DEPENDENCIES_LIBRARY_PATH ${DEPENDENCIES_ROOT_DIR}/usr/lib/x86_64-linux-gnu CACHE STRING "")
add_executable(edger8r IMPORTED)
set_target_properties(edger8r PROPERTIES IMPORTED_LOCATION ${SGX_LIBRARY_PATH}/sgx_edger8r)
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

View File

@ -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})

View File

@ -33,6 +33,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../common)
set(SOURCE_FILES main.cpp)
set_source_files_properties(${GENERATED_RPC_DIR}/java_u.c PROPERTIES GENERATED TRUE)
link_directories(${DEPENDENCIES_LIBRARY_PATH})
add_executable(standalone_sgx_verify ${SOURCE_FILES} $<TARGET_OBJECTS:common>)
target_include_directories(standalone_sgx_verify PUBLIC ${SGX_SDK_INCLUDE})
target_link_libraries(standalone_sgx_verify urtslib Threads::Threads)

View File

@ -0,0 +1,191 @@
cmake_minimum_required(VERSION 3.5)
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 noop_enclave.unsigned.so)
set(ENCLAVE_BLOB_TO_SIGN noop_enclave_blob_to_sign.bin)
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(HSM_SGX_TOOL ${PROJECT_SOURCE_DIR}/../hsm-tool/build/libs/sgx-jvm/hsm-tool-1.0-SNAPSHOT.jar)
set(DEPENDENCIES_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/root)
set(DEPENDENCIES_LIBRARY_PATH ${DEPENDENCIES_ROOT_DIR}/usr/lib/x86_64-linux-gnu CACHE STRING "")
set(SIGN_HELPER env LD_LIBRARY_PATH=${DEPENDENCIES_ROOT_DIR}/lib/x86_64-linux-gnu ${PROJECT_SOURCE_DIR}/sign_helper/sign_helper)
set(NOOP_ENCLAVE noop_enclave_objects)
set(SGX_SDK_INCLUDE ${SGX_SDK}/common/inc)
set(GENERATED_RPC_DIR ${CMAKE_CURRENT_BINARY_DIR}/rpc)
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(
OUTPUT ${GENERATED_EDL_FILES}
COMMAND edger8r --search-path ${CMAKE_CURRENT_SOURCE_DIR}/src --search-path ${SGX_SDK_INCLUDE} --trusted-dir ${GENERATED_RPC_DIR} --untrusted-dir ${GENERATED_RPC_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src/empty.edl
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/empty.edl ${SGX_LIBRARY_PATH}/sgx_edger8r ${SGX_SDK_INCLUDE}
)
set_source_files_properties(${GENERATED_EDL_FILES} PROPERTIES GENERATED TRUE)
add_custom_target(
GENERATED_EDL
DEPENDS ${GENERATED_EDL_FILES}
)
add_library(${NOOP_ENCLAVE} ${CMAKE_CURRENT_SOURCE_DIR}/src/noop_enclave.cpp ${GENERATED_RPC_DIR}/empty_t.c)
add_dependencies(${NOOP_ENCLAVE} GENERATED_EDL)
set_property(TARGET ${NOOP_ENCLAVE} PROPERTY POSITION_INDEPENDENT_CODE ON)
target_include_directories(${NOOP_ENCLAVE} PUBLIC ${SGX_SDK_INCLUDE} ${SGX_SDK_INCLUDE}/tlibc ${GENERATED_RPC_DIR})
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 TRUE)
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()
set(ENCLAVE_LINKER_FLAGS
"-Wl,--no-undefined"
"-nostdlib"
"-nodefaultlibs"
"-nostartfiles"
"-L${SGX_LIBRARY_PATH}"
"-Wl,--whole-archive"
"-l${TRTS_LIB}"
"-Wl,--no-whole-archive"
"-Wl,--start-group"
"lib${NOOP_ENCLAVE}.a"
"-lsgx_tstdc"
"-lsgx_tstdcxx"
"-lsgx_tcrypto"
"-l${SGX_SERVICE_LIB}"
"-Wl,--end-group"
"-Wl,-Bstatic"
"-Wl,-Bsymbolic"
"-Wl,--no-undefined"
"-Wl,-pie,-eenclave_entry"
"-Wl,--export-dynamic"
"-Wl,--defsym,__ImageBase=0"
"-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/linkerscript.lds"
)
add_custom_command(
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_BLOB_TO_SIGN}
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}
)
# 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_OPENSSL}
COMMAND openssl rsa -in ${CMAKE_CURRENT_SOURCE_DIR}/${PRIVATE_KEY_NAME_OPENSSL} -pubout -out ${CMAKE_CURRENT_BINARY_DIR}/${PUBLIC_KEY_NAME_OPENSSL}
)
add_custom_command(
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_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(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=GenerateSgxKey --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_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_PRETTY_HSM}
COMMAND ${SIGN_HELPER} print-css -in ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_HSM} > ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_PRETTY_HSM}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_HSM}
)
add_custom_target(sigstruct-hsm DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_HSM} ${CMAKE_CURRENT_BINARY_DIR}/${ENCLAVE_SIGSTRUCT_PRETTY_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)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -g")
link_directories(${DEPENDENCIES_LIBRARY_PATH})
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)

View File

@ -0,0 +1,63 @@
This is a small guide on how to generate the required files for Intel's
Whitelisting form.
To generate the production key
===
At this point the HSM should be set up with the appropriate groups and
permissions.
This step should be done on a separate clean machine, with no internet
connection, only connected to the HSM. The hsm-tool should be used directly,
this way the only dependency is a working JDK.
To generate the key:
`java -jar hsm-tool.jar --mode=GenerateSgxKey --profile=prod`
This will require two separate smartcard authentications. The generation
will fail if there is already an existing production key in the HSM.
To generate a production enclave signature
===
This may be done from a dev machine with an SGX device. This step requires
the outer sgx-jvm to be built.
To generate the signature and related files:
```
make clean
make sigstruct-hsm PROFILE=prod
```
This will require two separate smartcard authentications.
Running the above will produce the following files in `build/`:
* `noop_enclave.unsigned.so`: The unsigned enclave
* `noop_enclave_blob_to_sign.bin`: The unsigned SIGSTRUCT blob to sign.
* `noop_enclave.signed.hsm.so`: The signed enclave(= the unsigned enclave + signed blob).
* `noop_enclave.sigstruct.hsm.bin`: The signed SIGSTRUCT blob extracted from the signed enclave.
* `noop_enclave.sigstruct-pretty.hsm.txt`: The pretty printed SIGSTRUCT.
* `hsm.public.pem`: The public key corresponding to the signature of the HSM.
To sanity check the signed enclave:
```
make noop_test
./build/noop_test ./build/noop_enclave.signed.hsm.so
```
The above should return cleanly.
Intel's whitelisting form requires the MRSIGNER value in hexadecimal
from `noop_enclave.sigstruct-pretty.hsm.txt`, furthermore we need to attach
`noop_enclave.sigstruct.hsm.bin`.

View File

@ -0,0 +1,16 @@
.PHONY: all
all: build/Makefile
$(MAKE) -C $(<D) help
exit 1
build:
mkdir -p build
build/Makefile: | build
cd build/ && cmake ..
%: build/Makefile
$(MAKE) -C $(<D) $@
clean:
rm -rf build

View File

@ -0,0 +1,41 @@
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 and extract the unsigned SIGSTRUCT blob to sign (noop\_enclave.unsigned.so, noop\_enclave\_blob\_to\_sign.bin).
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 OVERWRITE=true.
* `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.
See IntelWhitelistFormInstructions.md for details on how to use this
project to fill the enclave specific parts of Intel's whitelisting form.

View File

@ -0,0 +1,12 @@
<EnclaveConfiguration>
<ProdID>0</ProdID>
<ISVSVN>0</ISVSVN>
<StackMaxSize>0x280000</StackMaxSize>
<HeapMaxSize>0xFF00000</HeapMaxSize>
<HeapExecutable>1</HeapExecutable>
<TCSNum>10</TCSNum>
<TCSPolicy>1</TCSPolicy>
<DisableDebug>0</DisableDebug>
<MiscSelect>0</MiscSelect>
<MiscMask>0xFFFFFFFF</MiscMask>
</EnclaveConfiguration>

View File

@ -0,0 +1,9 @@
noop_enclave.so
{
global:
g_global_data_sim;
g_global_data;
enclave_entry;
local:
*;
};

View File

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

Binary file not shown.

View File

@ -0,0 +1,5 @@
enclave {
trusted {
public void noop();
};
};

View File

@ -0,0 +1,3 @@
extern "C" {
void noop() {}
}

View 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;
}