Remote Attestation Example

Remote Attestation code example is available here: https://github.com/sangfansh

Original unmodified version is available here: https://github.com/svartkanin/linux-sgx-remoteattestation

IAS Service Guide is available here: https://software.intel.com/sites/default/files/managed/7e/3b/ias-api-spec.pdf

Before running the code, some settings have to be set in the GeneralSettings.h file:

  • The application port and IP
  • A server certificate and private key are required for the SSL communication between the SP and the Application (which can be self-signed)
    e.g. openssl req -x509 -nodes -newkey rsa:4096 -keyout server.key -out server.crt -days 365
  • The SPID provided by Intel when registering for the developer account
  • The certificate sent to Intel when registering for the developer account
  • IAS Rest API url (should stay the same)

To be able to run the above code some external libraries are needed:

  • Google Protocol Buffers (should already be installed with the SGX SDK package) otherwise install libprotobuf-dev, libprotobuf-c0-dev and protobuf-compiler

All other required libraries can be installed with the following command:
    sudo apt-get install libboost-thread-dev libboost-system-dev curl libcurl4-openssl-dev libssl-dev liblog4cpp5-dev libjsoncpp-dev

After the installation of those dependencies, the code can be compiled with the following commands:

    cd ServiceProvider
    make
    cd ../Application
    make SGX_MODE=HW SGX_PRERELEASE=1


The sample application has two parts: ServiceProvider and the Application. The Application needs to prove to the ServiceProvider that it is running on a claimed trusted SGX enclave so that the Service Provider can proceed to provision secret data. The messages exchanged during the remote attestation process are serialized using Google Protobuf (https://github.com/google/protobuf).

First let’s examine the Application. The entry point of the Application is inside isv_app.cpp (ISV stands for Individual Software Vendor). It starts by initiating the MessageHandler that handles the messages to be exchanged during remote attestation.

 

MessageHandler (a wrapper of all of the networking functionalities):

The MessageHandler has a protected enclave that handles all the secrets, as well as the generation and processing of cryptographic messages. We can see that MessageHandler has several message generation and handling functions. Specifically they are functions in forms of generateMsgx() and handleMsgx(). Google Protobuf is used by those functions to serialize the messages to be exchanged via network transportation.

The MessageHandler also has a NetworkManagerServer object. The NetworkManagerServer object enables the Application to act as a server to initialize connection and binds itself to a client via SSL (implementation detail in server.h, using object Server* server). It also inherits NetworkManager class in order to serialize and send messages.

msg -> init():

When the MessageHandler msg is initialized using init(), the NetworkManagerServer object inside is also initialized. It causes the initialization of Server object, which sets up the SSL io_service socket and the selected port. Then a function incomingHandler() is connected to the NetworkManagerServer as the CallbackHandler. This function is responsible for generating all the message replies according to the type of the message that it receives.

As mentioned above, incomingHandler(string, int) handles all of the incoming messages and generates corresponding replies. Let’s briefly examine this handler (line 395 at MessageHandler.cpp).

There are four cases:

  • RA_VERIFICATION
  • RA_MSG0
  • RA_MSG2
  • RA_ATT_RESULT

Each case is one type of the messages that are exchanged in time order during remote attestation.

Upon here, the ISV application’s MessageHandler has finished initialization.

 

msg -> start():

Function start() calls NetworkManager’s startService() function, which calls Server’s start_accept() to start SSL service. Upton here, the ISV has started running and is ready for any incoming traffic.

 

Now let’s examine ServiceProvider’s structure and initialization process.

isv_app.cpp inside ServiceProvider:

It’s the ServiceProvider Application itself. Similar to the client’s application, it has its own message handler VerificationManager since it acts as the verifier in the remote attestation process.

Inside the VerificationManager, it has a NetworkManagerClient which also inherits NetworkManager and is responsible for the SSL connection as well as serializing and sending messages.

In addition, it has a WebService object to performs the verification phase with Intel Attestation Service (IAS) using the QUOTE sent from the client enclave. In one word, a ServicePrivider also acts as a wrapper of all the IAS requests and message processing, as well as any encryption key derivation, using WebService.

vm -> init():

First, dynamically allocate a new ServiceProvider to ensure freshness of secret. Then the function initializes NetworkManagerClient that will connect to the Server (the Application) using SSL. Finally, a CallBackHandler similar to the one of the Application is set up. The handler itself is the function incomingHandler(string, int) inside VerificationManager that will handle incoming messages coming from the Application during remote attestation (line 132 at VerificationManager.cpp).

There are also four cases of handling messages:

  • RA_MSG0
  • RA_MSG1
  • RA_MSG3
  • RA_APP_ATT_OK

Notice that at the end of the handler, it initializes the message stream with a RA_VERIFICATION type string and the actual REQUEST. By doing so right after SSL handshake, the ServiceProvider can immediately start the RA process by forwarding the remote attestation request to the Application.

 

vm -> start():

NetworkManagerClient starts the service by connecting the SSL client to server. Then the client starts the SSL handshake process with server. We can see that the Client::handle_handshake() function triggers the remote attestation by sending out the attestation request mentioned above if handshake is successful.

Upon here, ServiceProvider and Application are connected and remote attestation process has started.


Now let’s examine both incomingHandler(string, int) in MessageHandler.cpp and VerificationManager.cpp to reflect the remote attestation process between SP and ISV described in the tutorial.

Summary of function calls:

(Please refer to “Messages.proto” for message structure details.)

(Please refer to the two incomingHandler’s attached below for actual implementation.)

MessageHandler.cpp VerificationManager.cpp
 

 

<——

RA_VERIFICATION

Send InitialMessage.

Receives the requestMsg, type is RA_MSG0.

GenerateMSG0() to get Extended Group ID (GID).

Send MSG0.

 

 

 

——>

 

 

 

<——

Handle MSG0.

Request EPID service if GID is ok.

Send back MSG0.

If ServiceProvider is ok with the GID (SP_OK):

initEnclave();

createEnclave() and init_ra();

Trusted sgx_ra_get_msg1(),  which gets GID and generates gx, gy for DH.

Send MSG1.

 

 

 

 

 

 

——>

 

 

 

 

 

 

 

 

 

<——

Handles MSG1.

sp_ra_proc_msg1_req() gets SigRL form IAS.

Save client’s public ECCDH key.

Generate SP public ECCDH key and save.

Generate shared secret.

Generate other keys for future communication.

Sign MSG2 and CMAC (sigma protocol).

Send MSG2.

Handle MSG2.

Call sgx_ra_proc_msg2(), which generates REPORT and calls get_quote().

sgx_ra_proc_msg2() will handle the key exchange in the enclave by ECalling sgx_ra_proc_msg2_trusted_t().

Send MSG3

 

 

 

 

 

 

——>

 

 

 

 

 

 

<——

Verify MSG3 content (ga, size, sigma MAC).

Verify report_data in QUOTE SHA256(ga | gb | vk).

Verify QUOTE with IAS (using WebService::verifyQUOTE() &  ias_verify_attestation_evidence()).

Respond the client with attestation result and sign using SIGMA.

Send message type RA_ATT_RESULT.

Verify result using MAC.

Verify secret payload.

Reply RA_APP_ATT_OK.

 

 

 

——>

Trusted channel established.