Skip to content

Commit

Permalink
add the tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
冯二虎 authored and 冯二虎 committed Jun 20, 2021
1 parent e6df3d6 commit 5f158a7
Show file tree
Hide file tree
Showing 13 changed files with 794 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Running Penglai-TVM with FPGA Board
================================
====================================
5 changes: 4 additions & 1 deletion source/Getting-started/Running-Penglai-TVM-with-QEMU.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Running Penglai-TVM with QEMU
==========================
==============================

Environment requirement
------------------------
Expand All @@ -15,6 +15,7 @@ Get source code
The source code of Penglai-TVM is available, click `here <https://github.com/Penglai-Enclave/Penglai-Enclave-TVM>`_ to jump to our git repo.
You can clone our project with the following script.
::

git clone https://github.com/Penglai-Enclave/Penglai-Enclave-TVM.git

Building
Expand All @@ -23,10 +24,12 @@ Enter the penglai-enclave directory, cd ``Penglai-Enclave-TVM``

And then,
::

git submodule update --init --recursive

Last, build penglai using our Docker image:
::

./docker_cmd.sh build

When the building process finished, you are ready to run penglai.
Expand Down
10 changes: 10 additions & 0 deletions source/Getting-started/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,13 @@ Penglai enclave can support multiple platforms:
Running-Penglai-TVM-with-QEMU.rst
Running-Penglai-TVM-with-FPGABoard.rst

User manual
------------
In Penglai-TVM manual, it defines all interfaces you can use in host application and enclaves.
More details can be found in the following doc:

* :doc:`Penglai-TVM-Manual </Penglai-manual/User-Manual-TVM>`
* :doc:`Penglai-PMP-Manual </Penglai-manual/User-Manual-PMP>`



12 changes: 6 additions & 6 deletions source/Penglai-manual/Penglai-Opensbi-Extension-API.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,12 @@ This document describes the interfaces for Opensbi used by PENGLAI enclave. It c

| Macro | Function ID (a7) | Argument |
| ------------------- | ---------------- | ------------------------------------------------------------ |
| SBI_EXIT_ENCLAVE | 1 | **arg0**: return value |
| SBI_ENCLAVE_OCALL | 2 | **arg0**: ocall_id<br />**arg1...**: the ocall arguments |
| SBI_ACQUIRE_ENCLAVE | 3 | **arg0**: The acquired enclave name |
| SBI_CALL_ENCLAVE | 4 | **arg0**: The callee enclave id<br />**arg1**: IPC struct |
| SBI_ENCLAVE_RETURN | 5 | **arg0**: IPC struct |
| SBI_GET_REPORT | 11 | **arg0**: the attested enclave name<br />**arg1**: attestation report<br />**arg2**: nonce |
| SBI_EXIT_ENCLAVE | 99 | **arg0**: return value |
| SBI_ENCLAVE_OCALL | 98 | **arg0**: ocall_id<br />**arg1...**: the ocall arguments |
| SBI_ACQUIRE_ENCLAVE | 97 | **arg0**: The acquired enclave name |
| SBI_CALL_ENCLAVE | 96 | **arg0**: The callee enclave id<br />**arg1**: IPC struct |
| SBI_ENCLAVE_RETURN | 95 | **arg0**: IPC struct |
| SBI_GET_REPORT | 94 | **arg0**: the attested enclave name<br />**arg1**: attestation report<br />**arg2**: nonce |

**SBI_EXIT_ENCLAVE (FID #1**

Expand Down
2 changes: 1 addition & 1 deletion source/Penglai-manual/User-Manual-TVM.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# User manual for Penglai-tvm
# User manual for Penglai-TVM

### Introduction

Expand Down
85 changes: 85 additions & 0 deletions source/Tutorials/Tutorial-Penglai-TVM-attestation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
Attestation (Penglai-TVM)
==============================

Penglai supports local attestation, required by host and enclave. Monitor will return the attestation report, including the enclave and secure monitor's measurement.


Prerequisite
-------------
Before running this tutorial, please make sure you have finished :doc:`getting started <../Getting-started/intro>`.

In current veriosn, we use ramfs as the rootfs, so it needs to build all the files into ramfs (using buildroot).
To simplify this process, we define a macro ``SDK_FILES``, all the files defined in ``SDK_FILES`` will be added in the initramfs.
So when machine boots, all these files will be existed in the root.

Make sure all the requested files in this tutorial are added in the ``SDK_FILES``.

Required files
>>>>>>>>>>>>>>>

::

penglai.ko
install.sh
test-caller
caller
server
server1

Test scripts
>>>>>>>>>>>>>

::

sh install.sh
./test-caller caller server server1

Get the attestation report in the host
----------------------------------------

.. code-block:: c
struct sm_report_t
{
unsigned char hash[HASH_SIZE];
unsigned char signature[SIGNATURE_SIZE];
unsigned char sm_pub_key[PUBLIC_KEY_SIZE];
};
struct enclave_report_t
{
unsigned char hash[HASH_SIZE];
unsigned char signature[SIGNATURE_SIZE];
uintptr_t nonce;
};
struct report_t
{
struct sm_report_t sm;
struct enclave_report_t enclave;
unsigned char dev_pub_key[PUBLIC_KEY_SIZE];
};
int PLenclave_attest(struct PLenclave *PLenclave, uintptr_t nonce);
Host can call the ``PLenclave_attest`` function to get the enclave attestation report. The attestation report is composed of device public key, secure monitor report and enclave report.
Host can authenticate a legal enclave with these attestation reports. Device public key and secure monitor public key are used to verify corresponding signature.
Nonce is required in the attestation to ensure other can not reuse a stale attestation report.

Get the attestation report in the enclave
-------------------------------------------

Enclave can get the attestation report of itself and other :doc:`server enclaves <Tutorial-Penglai-TVM-server-enclave>`, using the following interface:

.. code-block:: c
int get_report(char* name, struct report_t *report, unsigned long nonce);
get_report(NULL, report, 1);
get_report("server-enclave", report, 1);
Enclave can acquire it attestation report using the ``get_report()``. The structure of the attestation report is same as the report used by host.
If the attested enclave name is set to NULL, it will return the attestation report of current enclave, otherwise, it will return the attestation report with the given server enclave name.
Before invoking a server enclave, it is better to verify the server enclave measurement with ``get_report``.

Remote attestation can be realized based on the local attestation.
213 changes: 213 additions & 0 deletions source/Tutorials/Tutorial-Penglai-TVM-hello-world.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
Hello World (Penglai-TVM)
===========================

This tutorial introduces how to run a hello-world demo in the Penglai-TVM.
It requires two parts to run an enclave: host app and enclave app. Host app, is the untrusted part running in the host kernel, which can create or run an enclave.
Enclave app, is the trusted part running in the enclave.

Prerequisite
-------------
Before running this tutorial, please make sure you have finished :doc:`getting started <../Getting-started/intro>`.

In current veriosn, we use ramfs as the rootfs, so it needs to build all the files into ramfs (using buildroot).
To simplify this process, we define a macro ``SDK_FILES``, all the files defined in ``SDK_FILES`` will be added in the initramfs.
So when machine boots, all these files will be existed in the root.

Make sure all the requested files in this tutorial are added in the ``SDK_FILES``.

Required files
>>>>>>>>>>>>>>>

::

penglai.ko
install.sh
hello-world
host

Test scripts
>>>>>>>>>>>>>

::

sh install.sh
./host hello-world



Host app
----------
.. code-block:: c
#include "penglai-enclave.h"
#include <stdlib.h>
#include <pthread.h>
struct args
{
void* in;
int i;
};
void* create_enclave(void* args0)
{
struct args *args = (struct args*)args0;
void* in = args->in;
int i = args->i;
int ret = 0, result = 0;
struct PLenclave* enclave = malloc(sizeof(struct PLenclave));
struct enclave_args* params = malloc(sizeof(struct enclave_args));
PLenclave_init(enclave);
enclave_args_init(params);
struct elf_args *enclaveFile = (struct elf_args *)in;
if(PLenclave_create(enclave, enclaveFile, params) < 0)
{
printf("host:%d: failed to create enclave\n", i);
}
else
{
while (result = PLenclave_run(enclave))
{
printf("[ERROR] host: result %d val is wrong!\n", result);
goto free_enclave;
}
printf("host: exit enclave is successful \n");
}
printf("host: PLenclave run is finish \n");
free_enclave:
free(enclave);
free(params);
pthread_exit((void*)0);
}
int main(int argc, char** argv)
{
if(argc <= 1)
{
printf("Please input the enclave ELF file name\n");
}
int thread_num = 1;
if(argc == 3)
{
thread_num = atoi(argv[2]);
if(thread_num <= 0)
{
printf("error number\n");
return -1;
}
}
pthread_t* threads = (pthread_t*)malloc(thread_num * sizeof(pthread_t));
struct args* args = (struct args*)malloc(thread_num * sizeof(struct args));
struct elf_args* enclaveFile = malloc(sizeof(struct elf_args));
char* eappfile = argv[1];
elf_args_init(enclaveFile, eappfile);
if(!elf_valid(enclaveFile))
{
printf("error when initializing enclaveFile\n");
goto out;
}
for(int i=0; i< thread_num; ++i)
{
args[i].in = (void*)enclaveFile;
args[i].i = i + 1;
pthread_create(&threads[i], NULL, create_enclave, (void*)&(args[i]));
}
for(int i =0; i< thread_num; ++i)
{
pthread_join(threads[i], (void**)0);
}
printf("host: after exit the thread\n");
out:
elf_args_destroy(enclaveFile);
free(enclaveFile);
free(threads);
free(args);
return 0;
}
It is a basic host app to manipulate an enclave. There are some host-side enclave-related APIs, such as ``PLenclave_create``, ``PLenclave_run``. etc.
You can find more detail in our :doc:`user manual <../Penglai-manual/User-Manual-TVM>`.

Penglai-TVM supports to run multiple enclaves in a single host. So, host can use the pthread to create multiple instances with single enclave file.

There are three basic structures to manipulate an enclave. ``struct elf_args``, ``struct PLenclave`` and ``struct enclave_args``.
``struct elf_args`` records the ELF file of given enclave. ``struct PLenclave`` is the primary enclave structure that host will use to create, run an enclave.
``struct enclave_args`` restores all enclave parameters, which will be used in enclave creation, running, etc.

You can use the following APIs to initialize the above structures.

.. code-block:: c
elf_args_init(enclaveFile, eappfile)
PLenclave_init(enclave)
enclave_args_init(params)
How to run an enclave
>>>>>>>>>>>>>>>>>>>>>>>>>
We provide several interfaces to operate an enclave.

.. code-block:: c
PLenclave_create(enclave, enclaveFile, params)
We use this interface to create an enclave. Monitor will instantiate an enclave instance and return the corresponding ``eid``.
With the different parameters, host can create different kinds of enclave: :doc:`shadow enclave <Tutorial-Penglai-TVM-shadow-enclave>`, :doc:`server enclave <Tutorial-Penglai-TVM-server-enclave>`, etc.

After the creation, enclave will not be running, until someone has invoked ``PLenclave_run``.

.. code-block:: c
result = PLenclave_run(enclave)
Host invokes this API to run a created enclave. The enclave thread will not return to the host,
unless: (1) Enclave has been finished and exited. (2) Enclave does an ocall and needs to return to user-level for handling.
If an enclave is finished successfully, the return result remains zero.

.. code-block:: c
result = PLenclave_run(enclave)
Enclave app
--------------

.. code-block:: c
#include "eapp.h"
#include <stdlib.h>
int hello(unsigned long * args)
{
printf("hello world!\n");
EAPP_RETURN(0);
}
int EAPP_ENTRY main(){
unsigned long * args;
EAPP_RESERVE_REG;
hello(args);
}
As for a very simple demo: hello-world running in enclave. It only needs a minor modification for the original program.
First, you need to include the enclave header file ``eapp.h``, and then, save the enclave context before running.
You can invoke the macro ``EAPP_RESERVE_REG`` just below the main function.

We modify the musl lib to support the ``printf`` in enclave. So you can invoke the ``printf`` in the enclave directly.
This request will be redirected to the host kernel to handle. You can find more details of libc-supported APIs in the :doc:`user manual <../Penglai-manual/User-Manual-TVM>`.



0 comments on commit 5f158a7

Please sign in to comment.