├── pod-ext ├── .gitignore ├── style │ ├── main.css │ └── montserrat-font.css ├── popup │ ├── popup.js │ ├── popup.html │ └── popup.css ├── pages │ ├── settings.js │ ├── settings.html │ └── settings.css ├── icons │ ├── pod-32.png │ ├── pod-48.png │ └── pod-96.png ├── resources │ └── header.png ├── README.md ├── js │ ├── check-browser.js │ ├── constants.js │ └── promisify.js ├── frontend.js ├── background.js ├── manifest.json └── LICENSE ├── pod-server ├── migrations │ ├── .gitkeep │ └── 2020-04-09-130041_create_users │ │ ├── down.sql │ │ └── up.sql ├── .gitignore ├── src │ ├── schema.rs │ ├── models.rs │ ├── handlers │ │ ├── register.rs │ │ ├── auth.rs │ │ └── mod.rs │ └── main.rs ├── diesel.toml ├── Cargo.toml ├── README.md └── LICENSE ├── lib ├── c-api │ ├── .gitignore │ ├── pod_log.c │ ├── pod_log.h │ ├── Makefile │ ├── pod_sgx.h │ └── LICENSE ├── api │ ├── .gitignore │ ├── README.md │ ├── Cargo.toml │ ├── src │ │ ├── c.rs │ │ ├── lib.rs │ │ └── wrappers.rs │ └── LICENSE └── rust-sgx-util │ ├── .gitignore │ ├── src │ ├── ser_de.rs │ ├── c.rs │ └── lib.rs │ ├── README.md │ ├── Cargo.toml │ └── examples │ ├── ias_get_sigrl.rs │ └── ias_verify_quote.rs ├── pod-app ├── .gitignore ├── assets │ └── pod_app.json ├── Cargo.toml ├── install.sh ├── build.rs ├── examples │ ├── browser_mock.rs │ └── webservice_client.rs ├── src │ ├── messages.rs │ └── main.rs ├── README.md └── LICENSE ├── pod-web ├── .gitignore ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── src │ ├── assets │ │ ├── login-bg.jpg │ │ ├── register-bg.jpg │ │ ├── click.svg │ │ ├── dollar.svg │ │ └── pod-enabled.svg │ ├── context │ │ └── auth.js │ ├── Constants.js │ ├── setupTests.js │ ├── components │ │ ├── HOC │ │ │ ├── loader.module.css │ │ │ └── Loader.js │ │ ├── Register │ │ │ ├── register.module.css │ │ │ └── index.js │ │ ├── PodIndicator │ │ │ ├── pod.module.css │ │ │ └── index.js │ │ ├── Login │ │ │ ├── login.module.css │ │ │ └── index.js │ │ ├── Header │ │ │ ├── header.module.css │ │ │ └── index.js │ │ └── Home │ │ │ ├── home.module.css │ │ │ └── index.js │ ├── App.test.js │ ├── App.js │ ├── _vars.css │ ├── App.css │ ├── index.js │ ├── hooks │ │ └── useEventListener.js │ ├── provider │ │ └── authProvider.js │ ├── utils │ │ └── request.js │ ├── Router.js │ ├── index.css │ ├── logo.svg │ └── serviceWorker.js ├── README.md └── package.json ├── assets ├── pod-sequence.pdf └── pod-structure.pdf ├── pod-enclave ├── .gitignore ├── pod_enclave.config.xml ├── openssl_parse.awk ├── pod_enclave.h ├── pod_enclave.edl ├── README.rst ├── Makefile └── LICENSE ├── README.md └── LICENSE /pod-ext/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /pod-server/migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/c-api/.gitignore: -------------------------------------------------------------------------------- 1 | /__pycache__ 2 | -------------------------------------------------------------------------------- /pod-ext/style/main.css: -------------------------------------------------------------------------------- 1 | /*Front style*/ -------------------------------------------------------------------------------- /pod-ext/popup/popup.js: -------------------------------------------------------------------------------- 1 | console.log('popup page') -------------------------------------------------------------------------------- /lib/api/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | *.swp 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /pod-ext/pages/settings.js: -------------------------------------------------------------------------------- 1 | console.log('settings page'); -------------------------------------------------------------------------------- /pod-app/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | *.swp 3 | *.sealed 4 | *.pem 5 | -------------------------------------------------------------------------------- /pod-web/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn.lock 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /lib/rust-sgx-util/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | *.swp 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /pod-server/migrations/2020-04-09-130041_create_users/down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE users -------------------------------------------------------------------------------- /lib/api/README.md: -------------------------------------------------------------------------------- 1 | # pod-api 2 | 3 | Idiomatic Rust API for managing the pod-enclave. 4 | -------------------------------------------------------------------------------- /assets/pod-sequence.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/golemfactory/ProofOfDevice/HEAD/assets/pod-sequence.pdf -------------------------------------------------------------------------------- /pod-web/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /assets/pod-structure.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/golemfactory/ProofOfDevice/HEAD/assets/pod-structure.pdf -------------------------------------------------------------------------------- /pod-ext/icons/pod-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/golemfactory/ProofOfDevice/HEAD/pod-ext/icons/pod-32.png -------------------------------------------------------------------------------- /pod-ext/icons/pod-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/golemfactory/ProofOfDevice/HEAD/pod-ext/icons/pod-48.png -------------------------------------------------------------------------------- /pod-ext/icons/pod-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/golemfactory/ProofOfDevice/HEAD/pod-ext/icons/pod-96.png -------------------------------------------------------------------------------- /pod-ext/resources/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/golemfactory/ProofOfDevice/HEAD/pod-ext/resources/header.png -------------------------------------------------------------------------------- /pod-web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/golemfactory/ProofOfDevice/HEAD/pod-web/public/favicon.ico -------------------------------------------------------------------------------- /pod-web/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/golemfactory/ProofOfDevice/HEAD/pod-web/public/logo192.png -------------------------------------------------------------------------------- /pod-web/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/golemfactory/ProofOfDevice/HEAD/pod-web/public/logo512.png -------------------------------------------------------------------------------- /pod-web/src/assets/login-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/golemfactory/ProofOfDevice/HEAD/pod-web/src/assets/login-bg.jpg -------------------------------------------------------------------------------- /pod-web/src/assets/register-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/golemfactory/ProofOfDevice/HEAD/pod-web/src/assets/register-bg.jpg -------------------------------------------------------------------------------- /pod-server/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | config.toml 3 | .env 4 | *.db 5 | pod_pubkey 6 | *.sealed 7 | *.quote 8 | pod-server_* 9 | 10 | -------------------------------------------------------------------------------- /pod-server/src/schema.rs: -------------------------------------------------------------------------------- 1 | table! { 2 | users (id) { 3 | id -> Integer, 4 | login -> Text, 5 | pub_key -> Text, 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /pod-web/src/context/auth.js: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | 3 | const AuthContext = createContext("auth"); 4 | 5 | export default AuthContext; 6 | -------------------------------------------------------------------------------- /pod-server/diesel.toml: -------------------------------------------------------------------------------- 1 | # For documentation on how to configure this file, 2 | # see diesel.rs/guides/configuring-diesel-cli 3 | 4 | [print_schema] 5 | file = "src/schema.rs" 6 | -------------------------------------------------------------------------------- /pod-server/migrations/2020-04-09-130041_create_users/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE users ( 2 | id INTEGER NOT NULL PRIMARY KEY, 3 | login TEXT NOT NULL UNIQUE, 4 | pub_key TEXT NOT NULL 5 | ) 6 | -------------------------------------------------------------------------------- /pod-ext/README.md: -------------------------------------------------------------------------------- 1 | # PoD Extension 2 | Cross browser PoD Extension for Firefox & Chromium 3 | 4 | # Installation 5 | Install web-ext package globally by `npm i -g web-ext` 6 | 7 | # Running 8 | `web-ext run` -------------------------------------------------------------------------------- /pod-app/assets/pod_app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pod_app", 3 | "description": "Proof-of-device native client", 4 | "path": "NATIVE_APP_PATH", 5 | "type": "stdio", 6 | "allowed_extensions": [ "pod_app@golem.network" ] 7 | } 8 | -------------------------------------------------------------------------------- /pod-ext/js/check-browser.js: -------------------------------------------------------------------------------- 1 | var isFirefox; 2 | 3 | function checkBrowser() { 4 | if (typeof browser === 'undefined') { 5 | browser = chrome; 6 | } else { 7 | isFirefox = true; 8 | } 9 | return; 10 | } 11 | 12 | checkBrowser(); 13 | -------------------------------------------------------------------------------- /pod-web/src/Constants.js: -------------------------------------------------------------------------------- 1 | const constants = Object.freeze({ 2 | ORIGIN: "http://localhost:3000", 3 | HOST: "POD_BROWSER", 4 | REMOTE: "POD_EXT", 5 | REGISTER: "get_quote", 6 | CHALLENGE: "sign_challenge", 7 | }) 8 | 9 | module.exports = constants; -------------------------------------------------------------------------------- /pod-enclave/.gitignore: -------------------------------------------------------------------------------- 1 | *.meta 2 | *.mrsigner 3 | *.o 4 | *.so 5 | *.so.sig 6 | *.so.sigdata 7 | 8 | # generated files 9 | pod_enclave_mrsigner.h 10 | pod_enclave_t.c 11 | pod_enclave_t.h 12 | pod_enclave_u.c 13 | pod_enclave_u.h 14 | *.pem 15 | -------------------------------------------------------------------------------- /pod-ext/js/constants.js: -------------------------------------------------------------------------------- 1 | const constants = Object.freeze({ 2 | ORIGIN: "http://localhost:3000", 3 | REMOTE: "POD_BROWSER", 4 | HOST: "POD_EXT", 5 | REGISTER: "get_quote", 6 | CHALLENGE: "sign_challenge", 7 | SPID: "2CFD6C88BD1B280D3D6C33977D53A1A3" 8 | }) -------------------------------------------------------------------------------- /pod-web/README.md: -------------------------------------------------------------------------------- 1 | # Pod-Web 2 | 3 | Test webapp to mimic any wep application with authentication 4 | 5 | # Installation 6 | 7 | - with yarn package manager (recomended), just type `yarn` and enter 8 | - with npm, `npm i` 9 | 10 | # Running 11 | 12 | `npm run start` or `yarn start` -------------------------------------------------------------------------------- /pod-web/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /pod-web/src/components/HOC/loader.module.css: -------------------------------------------------------------------------------- 1 | .loaderScreen { 2 | width: 100%; 3 | height: calc(100vh - 63px); 4 | 5 | display: flex; 6 | justify-content: center; 7 | align-items: center; 8 | 9 | background-color: var(--color5); 10 | } 11 | 12 | .loaderIcon { 13 | width: 100px; 14 | position: absolute; 15 | } -------------------------------------------------------------------------------- /lib/c-api/pod_log.c: -------------------------------------------------------------------------------- 1 | #include "pod_log.h" 2 | 3 | int g_stdout_fd = 1; 4 | int g_stderr_fd = 2; 5 | bool g_verbose = false; 6 | 7 | void set_verbose(bool verbose) { 8 | g_verbose = verbose; 9 | if (verbose) 10 | DBG("Verbose output enabled\n"); 11 | else 12 | DBG("Verbose output disabled\n"); 13 | } 14 | -------------------------------------------------------------------------------- /pod-web/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /pod-web/src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import RootRouter from "./Router"; 3 | import AuthProvider from "./provider/authProvider"; 4 | import "./App.css"; 5 | 6 | function App() { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | ); 14 | } 15 | 16 | export default App; 17 | -------------------------------------------------------------------------------- /pod-web/src/components/Register/register.module.css: -------------------------------------------------------------------------------- 1 | .register { 2 | width: 100%; 3 | height: calc(100vh - 65px); 4 | display: flex; 5 | justify-content: center; 6 | align-items: center; 7 | background-image: url('../../assets/register-bg.jpg'); 8 | background-size: cover; 9 | animation: var(--anim) .5s; 10 | } 11 | 12 | .form { 13 | min-width: 300px; 14 | width: 30%; 15 | } -------------------------------------------------------------------------------- /pod-enclave/pod_enclave.config.xml: -------------------------------------------------------------------------------- 1 | 2 | 1 3 | 0 4 | 0x8000 5 | 0x800000 6 | 16 7 | 1 8 | 0 9 | 0 10 | 0xFFFFFFFF 11 | 12 | -------------------------------------------------------------------------------- /pod-server/src/models.rs: -------------------------------------------------------------------------------- 1 | use crate::schema::users; 2 | 3 | #[derive(Debug, Queryable)] 4 | pub struct User { 5 | pub id: i32, 6 | pub login: String, 7 | pub pub_key: String, // base64 encoded 8 | } 9 | 10 | #[derive(Debug, Insertable)] 11 | #[table_name = "users"] 12 | pub struct NewUser { 13 | pub login: String, 14 | pub pub_key: String, // base64 encoded 15 | } 16 | -------------------------------------------------------------------------------- /pod-web/src/_vars.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --color1: #f03a47ff; 3 | --color2: #af5b5bff; 4 | --color3: #f6f4f3ff; 5 | --color4: #276fbfff; 6 | --color5: #183059ff; 7 | 8 | --anim: bringPage; 9 | } 10 | 11 | 12 | @keyframes bringPage { 13 | 0% { 14 | opacity: 0; 15 | transform: translateY(50px); 16 | } 17 | 18 | 100% { 19 | opacity: 1; 20 | transform: translateY(0); 21 | } 22 | } -------------------------------------------------------------------------------- /pod-enclave/openssl_parse.awk: -------------------------------------------------------------------------------- 1 | BEGIN { 2 | FS = ":" 3 | first = 1 4 | dump = "" 5 | } 6 | 7 | # parse hex dump 8 | / / { 9 | gsub(/ /, "", $0) # strip leading spaces 10 | for (i=1; i<=NF; i++) { 11 | if (first == 1) { 12 | first = 0 13 | if ($i == "00") # skip leading 0 14 | continue 15 | } 16 | dump = $i dump 17 | } 18 | } 19 | 20 | END { 21 | printf dump 22 | } 23 | -------------------------------------------------------------------------------- /pod-web/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | background: var(--color5); 4 | overflow-y: hidden; 5 | } 6 | 7 | .App-logo { 8 | height: 40vmin; 9 | pointer-events: none; 10 | } 11 | 12 | @media (prefers-reduced-motion: no-preference) { 13 | .App-logo { 14 | animation: App-logo-spin infinite 20s linear; 15 | } 16 | } 17 | 18 | @keyframes App-logo-spin { 19 | from { 20 | transform: rotate(0deg); 21 | } 22 | to { 23 | transform: rotate(360deg); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /pod-web/src/components/PodIndicator/pod.module.css: -------------------------------------------------------------------------------- 1 | .podIndicator { 2 | display: flex; 3 | width: auto; 4 | align-items: flex-start; 5 | 6 | position: absolute; 7 | top: -5px; 8 | right: 10px; 9 | 10 | } 11 | 12 | .podInfo { 13 | margin-right: 10px; 14 | opacity: 0; 15 | transition: opacity .5s; 16 | 17 | font-size: 10pt; 18 | 19 | color: var(--color5); 20 | order: 1; 21 | } 22 | 23 | .podImg { 24 | width: 42px; 25 | cursor: pointer; 26 | 27 | order: 2; 28 | } 29 | 30 | .podImg:hover + .podInfo { 31 | opacity: 1; 32 | } -------------------------------------------------------------------------------- /lib/rust-sgx-util/src/ser_de.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "with_serde")] 2 | 3 | use serde::{self, Deserialize, Deserializer, Serializer}; 4 | 5 | pub(crate) fn serialize(blob: &[u8], serializer: S) -> Result 6 | where 7 | S: Serializer, 8 | { 9 | serializer.serialize_str(&base64::encode(blob)) 10 | } 11 | 12 | pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> 13 | where 14 | D: Deserializer<'de>, 15 | { 16 | let string = String::deserialize(deserializer)?; 17 | base64::decode(&string).map_err(serde::de::Error::custom) 18 | } 19 | -------------------------------------------------------------------------------- /lib/api/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pod-api" 3 | version = "0.1.0" 4 | authors = ["Jakub Konka "] 5 | edition = "2018" 6 | license = "LGPL-3.0" 7 | readme = "README.md" 8 | repository = "https://github.com/golemfactory/proofofdevice" 9 | homepage = "https://github.com/golemfactory/proofofdevice" 10 | description = "Idiomatic Rust API for managing the pod-enclave." 11 | 12 | [dependencies] 13 | anyhow = "1" 14 | libc = "0.2" 15 | rust-sgx-util = { path = "../rust-sgx-util", version = "0.2.3"} 16 | 17 | [badges] 18 | maintenance = { status = "actively-developed" } 19 | -------------------------------------------------------------------------------- /pod-web/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './_vars.css'; 4 | import './index.css'; 5 | import App from './App'; 6 | import * as serviceWorker from './serviceWorker'; 7 | 8 | ReactDOM.render( 9 | 10 | 11 | , 12 | document.getElementById('root') 13 | ); 14 | 15 | // If you want your app to work offline and load faster, you can change 16 | // unregister() to register() below. Note this comes with some pitfalls. 17 | // Learn more about service workers: https://bit.ly/CRA-PWA 18 | serviceWorker.unregister(); 19 | -------------------------------------------------------------------------------- /pod-web/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "PoD Web App", 3 | "name": "PoD Web Test App", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /lib/rust-sgx-util/README.md: -------------------------------------------------------------------------------- 1 | # `rust-sgx-util` 2 | 3 | A safe wrapper around Graphene's [`sgx_util`] C-library. 4 | 5 | [`sgx_util`]: https://github.com/oscarlab/graphene/tree/master/Pal/src/host/Linux-SGX/tools 6 | 7 | ```toml 8 | rust-sgx-util = "0.2" 9 | ``` 10 | 11 | For `serde` support, you can enable it with `with_serde` feature: 12 | 13 | ```toml 14 | rust-sgx-util = { version = "0.2", features = ["with_serde"] } 15 | ``` 16 | 17 | ## Prerequisites 18 | 19 | Currently, this crate requires you compile and install `sgx_util` as 20 | a shared library. 21 | 22 | ## Usage examples 23 | 24 | You can find usage examples in the `examples` dir of the crate. 25 | -------------------------------------------------------------------------------- /lib/c-api/pod_log.h: -------------------------------------------------------------------------------- 1 | #ifndef POD_LOG_H 2 | #define POD_LOG_H 3 | 4 | #include 5 | #include 6 | 7 | // Source: https://github.com/oscarlab/graphene/blob/master/Pal/src/host/Linux-SGX/tools/common/util.h#L33 8 | extern int g_stdout_fd; 9 | extern int g_stderr_fd; 10 | extern bool g_verbose; 11 | 12 | #define DBG(fmt, ...) do { if (g_verbose) dprintf(g_stdout_fd, fmt, ##__VA_ARGS__); } while (0) 13 | #define INFO(fmt, ...) do { dprintf(g_stdout_fd, fmt, ##__VA_ARGS__); } while (0) 14 | #define ERROR(fmt, ...) do { dprintf(g_stderr_fd, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__); } while (0) 15 | 16 | void set_verbose(bool verbose); 17 | 18 | #endif /* POD_LOG_H */ 19 | -------------------------------------------------------------------------------- /pod-web/src/hooks/useEventListener.js: -------------------------------------------------------------------------------- 1 | import { useRef, useEffect } from "react"; 2 | function useEventListener(eventName, handler, element = window) { 3 | const savedHandler = useRef(); 4 | useEffect(() => { 5 | savedHandler.current = handler; 6 | }, [handler]); 7 | 8 | useEffect(() => { 9 | const isSupported = element && element.addEventListener; 10 | if (!isSupported) return; 11 | 12 | const eventListener = (event) => savedHandler.current(event); 13 | 14 | element.addEventListener(eventName, eventListener); 15 | 16 | return () => { 17 | element.removeEventListener(eventName, eventListener); 18 | }; 19 | }, [eventName, element]); 20 | } 21 | 22 | export default useEventListener; -------------------------------------------------------------------------------- /lib/rust-sgx-util/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-sgx-util" 3 | version = "0.2.3" 4 | authors = ["Jakub Konka "] 5 | edition = "2018" 6 | license = "LGPL-3.0" 7 | readme = "README.md" 8 | repository = "https://github.com/golemfactory/proofofdevice" 9 | homepage = "https://github.com/golemfactory/proofofdevice" 10 | documentation = "https://docs.rs/rust-sgx-util" 11 | description = "A safe wrapper around Graphene `sgx-util` C-library." 12 | 13 | [dependencies] 14 | libc = "0.2" 15 | thiserror = "1" 16 | serde = { version = "1", features = ["derive"], optional = true} 17 | base64 = { version = "0.12", optional = true } 18 | 19 | [dev-dependencies] 20 | structopt = "0.3" 21 | anyhow = "1" 22 | 23 | [features] 24 | default = [] 25 | with_serde = ["serde", "base64"] 26 | 27 | [badges] 28 | maintenance = { status = "actively-developed" } 29 | -------------------------------------------------------------------------------- /lib/rust-sgx-util/examples/ias_get_sigrl.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use rust_sgx_util::{set_verbose, GroupId, IasHandle}; 3 | use std::str::FromStr; 4 | use structopt::StructOpt; 5 | 6 | #[derive(Debug, StructOpt)] 7 | struct Opt { 8 | /// IAS API key. 9 | api_key: String, 10 | /// EPID group ID (hex string). 11 | group_id: String, 12 | /// Toggle verbose mode. 13 | #[structopt(short, long)] 14 | verbose: bool, 15 | } 16 | 17 | fn main() -> Result<()> { 18 | let opt = Opt::from_args(); 19 | set_verbose(opt.verbose); 20 | let group_id = GroupId::from_str(&opt.group_id)?; 21 | let ias_handle = IasHandle::new(&opt.api_key, None, None)?; 22 | match ias_handle.get_sigrl(&group_id)? { 23 | Some(sigrl) => println!("SigRL for EPID group ID {}: {}.", group_id, sigrl), 24 | None => println!("No SigRL for EPID group ID {}.", group_id), 25 | }; 26 | Ok(()) 27 | } 28 | -------------------------------------------------------------------------------- /pod-web/src/components/Login/login.module.css: -------------------------------------------------------------------------------- 1 | .login { 2 | width: 100%; 3 | height: calc(100vh - 63px); 4 | display: flex; 5 | justify-content: space-around; 6 | align-items: center; 7 | background-image: url('../../assets/login-bg.jpg'); 8 | background-size: cover; 9 | animation: var(--anim) .5s; 10 | animation-fill-mode: forwards; 11 | } 12 | 13 | .motto { 14 | font-size: 4vw; 15 | font-weight: 700; 16 | color: var(--color2); 17 | text-shadow: 2px 2px #fff; 18 | text-align: left; 19 | animation: var(--anim) .5s; 20 | animation-fill-mode: both; 21 | animation-delay: 300ms; 22 | } 23 | 24 | .motto .click { 25 | position: relative; 26 | width: 60px; 27 | filter: brightness(0) invert(1); 28 | top: 5px; 29 | left: 10px; 30 | } 31 | 32 | .form { 33 | min-width: 300px; 34 | width: 30%; 35 | } 36 | 37 | @media only screen and (max-width: 900px) { 38 | .motto { 39 | display: none; 40 | } 41 | } -------------------------------------------------------------------------------- /pod-web/src/provider/authProvider.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import AuthContext from "../context/auth"; 3 | import Cookies from 'js-cookie'; 4 | 5 | class AuthProvider extends Component { 6 | state = { 7 | isLoggedIn: checkCookie(), 8 | }; 9 | 10 | // make get request to `/` here if login is successful or not 11 | setLoggedIn = (isLoggedIn) => { 12 | if(!isLoggedIn) removeCookies(); 13 | this.setState({isLoggedIn}); 14 | } 15 | 16 | render() { 17 | return ( 18 | 21 | {this.props.children} 22 | 23 | ); 24 | } 25 | } 26 | 27 | export default AuthProvider; 28 | 29 | function checkCookie() { // mock 30 | const value = Cookies.get('auth'); 31 | console.log(value); 32 | return !!value; 33 | } 34 | 35 | function removeCookies() { 36 | Cookies.remove('session'); 37 | } -------------------------------------------------------------------------------- /pod-ext/js/promisify.js: -------------------------------------------------------------------------------- 1 | /** 2 | * [promisify description] 3 | * @param {[function]} api [description] 4 | * @param {[Array]} args [description] 5 | * @return {[function]} [description] 6 | * 7 | * @example 8 | * promisify(firefoxFunc, [1,2,3]).then(res => {}) 9 | * 10 | * promisify(chromeFunc, [1,2,3]).then(res => {}) 11 | * 12 | * @author Muhammed Tanrikulu (md.tanrikulu@gmail.com) 13 | */ 14 | const promisify = (api, method, args) => { 15 | const callBack = (resolve, reject, result) => { 16 | if (browser.runtime.lastError) { 17 | reject(chrome.runtime.lastError); 18 | return; 19 | } 20 | resolve(result); 21 | }; 22 | 23 | return new Promise((resolve, reject) => { 24 | if (!isFirefox) 25 | api[method]( 26 | method === 'set' ? args[0] : args, 27 | callBack.bind(this, resolve, reject) 28 | ); 29 | else api[method](...args).then(callBack.bind(this, resolve, reject)); 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /pod-enclave/pod_enclave.h: -------------------------------------------------------------------------------- 1 | #ifndef POD_ENCLAVE_H 2 | #define POD_ENCLAVE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | /*! Enclave sealing policy: 12 | * sealing keys can be derived using MRENCLAVE or MRSIGNER. */ 13 | #define ENCLAVE_SEALING_POLICY SGX_KEYPOLICY_MRENCLAVE 14 | 15 | /*! Enclave flags that will matter for sealing/unsealing secrets (keys). */ 16 | #define ENCLAVE_SEALING_ATTRIBUTES (SGX_FLAGS_INITTED | SGX_FLAGS_DEBUG | SGX_FLAGS_MODE64BIT) 17 | 18 | /*! Size of the EC public key (in bytes). */ 19 | #define EC_PUBLIC_KEY_SIZE 32 20 | 21 | /*! Size of the EC signature (in bytes). */ 22 | #define EC_SIGNATURE_SIZE 64 23 | 24 | /*! EC curve ID used for digital signatures. */ 25 | #define EC_CURVE_ID EVP_PKEY_ED25519 26 | 27 | int seal_keys(void); 28 | 29 | int unseal_keys(const uint8_t* sealed_data, size_t sealed_size); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /lib/api/src/c.rs: -------------------------------------------------------------------------------- 1 | #[link(name = "pod_sgx")] 2 | extern "C" { 3 | pub(super) fn set_verbose(verbose: bool); 4 | pub(super) fn pod_init_enclave( 5 | enclave_path: *const libc::c_char, 6 | sealed_keys: *mut u8, 7 | sealed_keys_size: usize, 8 | ) -> libc::c_int; 9 | pub(super) fn pod_load_enclave( 10 | enclave_path: *const libc::c_char, 11 | sealed_keys: *const u8, 12 | sealed_keys_size: usize, 13 | ) -> libc::c_int; 14 | pub(super) fn pod_unload_enclave() -> libc::c_int; 15 | pub(super) fn pod_get_quote( 16 | sp_id_str: *const libc::c_char, 17 | sp_quote_type_str: *const libc::c_char, 18 | quote_buffer: *mut u8, 19 | quote_buffer_size: usize, 20 | ) -> libc::c_int; 21 | pub(super) fn pod_sign_buffer( 22 | data: *const libc::c_void, 23 | data_size: usize, 24 | signature: *mut libc::c_void, 25 | signature_size: usize, 26 | ) -> libc::c_int; 27 | } 28 | -------------------------------------------------------------------------------- /pod-server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pod-server" 3 | version = "0.1.0" 4 | authors = ["Jakub Konka "] 5 | edition = "2018" 6 | license = "LGPL-3.0" 7 | readme = "README.md" 8 | repository = "https://github.com/golemfactory/proofofdevice" 9 | homepage = "https://github.com/golemfactory/proofofdevice" 10 | description = "Implementation of PoD web server." 11 | 12 | [dependencies] 13 | actix-web = "2" 14 | actix-rt = "1" 15 | actix-session = "0.3" 16 | actix-identity = "0.2" 17 | rust-sgx-util = { path = "../lib/rust-sgx-util", features = ["with_serde"], version = "0.2.3" } 18 | anyhow = "1" 19 | thiserror = "1" 20 | serde = "1" 21 | serde_json = "1" 22 | log = "0.4" 23 | structopt = "0.3" 24 | toml = "0.5" 25 | diesel = { version = "1.0", features = ["sqlite"] } 26 | tokio-diesel = "0.3" 27 | dotenv = "0.9" 28 | getrandom = "0.1" 29 | base64 = "0.12" 30 | ed25519-dalek = "1.0.0-pre.3" 31 | simplelog = "0.7" 32 | 33 | [badges] 34 | maintenance = { status = "actively-developed" } 35 | -------------------------------------------------------------------------------- /pod-app/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pod-app" 3 | version = "0.1.0" 4 | authors = ["Jakub Konka "] 5 | edition = "2018" 6 | license = "LGPL-3.0" 7 | readme = "README.md" 8 | repository = "https://github.com/golemfactory/proofofdevice" 9 | homepage = "https://github.com/golemfactory/proofofdevice" 10 | description = "Native app that PoD uses to interface with pod-enclave" 11 | 12 | [dependencies] 13 | pod-api = { path = "../lib/api", version = "0.1.0" } 14 | rust-sgx-util = { path = "../lib/rust-sgx-util", features = ["with_serde"], version = "0.2.3" } 15 | anyhow = "1" 16 | thiserror = "1" 17 | base64 = "0.12" 18 | serde = { version = "1", features = ["derive"] } 19 | serde_json = "1" 20 | structopt = "0.3" 21 | nix = "0.17" 22 | libc = "0.2" 23 | xdg = "2" 24 | log = "0.4" 25 | simplelog = "0.7" 26 | 27 | [dev-dependencies] 28 | actix-web = "2" 29 | actix-rt = "1" 30 | 31 | [build-dependencies] 32 | cc = "1" 33 | 34 | [badges] 35 | maintenance = { status = "actively-developed" } 36 | 37 | -------------------------------------------------------------------------------- /pod-enclave/pod_enclave.edl: -------------------------------------------------------------------------------- 1 | enclave { 2 | include "stdbool.h" 3 | include "sgx_tkey_exchange.h" 4 | from "sgx_tsgxssl.edl" import *; 5 | 6 | trusted { 7 | public int e_initialize( 8 | [in, size=sealed_size] uint8_t* sealed_data, 9 | size_t sealed_size, 10 | [out, size=pubkey_size] uint8_t* pubkey, 11 | size_t pubkey_size); 12 | 13 | public int e_get_report( 14 | [in] const sgx_target_info_t* target_info, 15 | [out] sgx_report_t* report); 16 | 17 | public int e_sign_data( 18 | [in, size=data_size] const void* data, 19 | size_t data_size, 20 | [out, size=signature_size] void* signature, 21 | size_t signature_size); 22 | }; 23 | 24 | untrusted { 25 | void o_print( 26 | [in, string] const char* str); 27 | 28 | int o_store_sealed_data( 29 | [in, size=data_size] const uint8_t* data, 30 | size_t data_size); 31 | }; 32 | }; 33 | -------------------------------------------------------------------------------- /lib/rust-sgx-util/examples/ias_verify_quote.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use rust_sgx_util::{set_verbose, IasHandle, Nonce, Quote}; 3 | use std::fs; 4 | use std::path::PathBuf; 5 | use structopt::StructOpt; 6 | 7 | #[derive(Debug, StructOpt)] 8 | struct Opt { 9 | /// IAS API key. 10 | api_key: String, 11 | /// Path to quote to verify. 12 | #[structopt(parse(from_os_str))] 13 | quote_path: PathBuf, 14 | /// Nonce to use. 15 | #[structopt(long)] 16 | nonce: Option, 17 | /// Toggle verbose mode. 18 | #[structopt(short, long)] 19 | verbose: bool, 20 | } 21 | 22 | fn main() -> Result<()> { 23 | let opt = Opt::from_args(); 24 | set_verbose(opt.verbose); 25 | let ias_handle = IasHandle::new(&opt.api_key, None, None)?; 26 | let quote = Quote::from(fs::read(&opt.quote_path)?); 27 | let nonce = opt.nonce.as_ref().map(|x| Nonce::from(x.as_bytes())); 28 | match ias_handle.verify_quote("e, nonce.as_ref(), None, None, None, None) { 29 | Err(_) => println!("Verification of quote unsuccessful!"), 30 | Ok(()) => {} 31 | }; 32 | Ok(()) 33 | } 34 | -------------------------------------------------------------------------------- /pod-web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pod-front", 3 | "version": "0.1.0", 4 | "author": "Muhammed Tanrikulu ", 5 | "private": true, 6 | "dependencies": { 7 | "@testing-library/jest-dom": "^4.2.4", 8 | "@testing-library/react": "^9.3.2", 9 | "@testing-library/user-event": "^7.1.2", 10 | "chart.js": "^2.9.3", 11 | "js-cookie": "^2.2.1", 12 | "react": "^16.13.1", 13 | "react-dom": "^16.13.1", 14 | "react-router-dom": "^5.1.2", 15 | "react-scripts": "3.4.1", 16 | "shifty": "^2.8.3" 17 | }, 18 | "scripts": { 19 | "start": "react-scripts start", 20 | "build": "react-scripts build", 21 | "test": "react-scripts test", 22 | "eject": "react-scripts eject" 23 | }, 24 | "eslintConfig": { 25 | "extends": "react-app" 26 | }, 27 | "browserslist": { 28 | "production": [ 29 | ">0.2%", 30 | "not dead", 31 | "not op_mini all" 32 | ], 33 | "development": [ 34 | "last 1 chrome version", 35 | "last 1 firefox version", 36 | "last 1 safari version" 37 | ] 38 | }, 39 | "proxy": "http://localhost:8888" 40 | } 41 | -------------------------------------------------------------------------------- /pod-web/src/utils/request.js: -------------------------------------------------------------------------------- 1 | function parseJSON(response) { 2 | return new Promise((resolve, reject) => 3 | response 4 | .json() 5 | .then((json) => 6 | resolve({ 7 | status: response.status, 8 | ok: response.ok, 9 | json, 10 | }) 11 | ) 12 | .catch((error) => { 13 | reject({ 14 | status: response.status, 15 | message: error.message, 16 | }); 17 | }) 18 | ); 19 | } 20 | 21 | /** 22 | * Requests a URL, returning a promise 23 | * 24 | * @param {string} url The URL we want to request 25 | * @param {object} [options] The options we want to pass to "fetch" 26 | * 27 | * @return {Promise} The request promise 28 | */ 29 | export default function request(url, options) { 30 | return new Promise((resolve, reject) => { 31 | fetch(url, options) 32 | .then(parseJSON) 33 | .then((response) => { 34 | if (response.ok) { 35 | return resolve(response.json); 36 | } 37 | let error = response.json?.description; 38 | return reject(error || response.status); 39 | }) 40 | .catch((error) => { 41 | reject(error); 42 | }); 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /pod-web/src/components/PodIndicator/index.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import { podImg, podIndicator, podInfo } from "./pod.module.css"; 3 | 4 | import podEnabledAsset from "../../assets/pod-enabled.svg"; 5 | import podDisabledAsset from "../../assets/pod-disabled.svg"; 6 | import podWaitingAsset from "../../assets/pod-waiting.svg"; 7 | 8 | const PodIndicator = ({ isReady = false }) => { 9 | const [isEnabled, setEnabled] = useState(false); 10 | useEffect(() => { 11 | if (window.__PROOF_OF_DEVICE__) { 12 | setEnabled(true); 13 | } 14 | }, []); 15 | 16 | return ( 17 | 18 | 29 | 30 | {isEnabled 31 | ? isReady 32 | ? "Proof of Device has been enabled." 33 | : "Waiting reponse from PoD extension" 34 | : "Proof of Device is not available."} 35 | 36 | 37 | ); 38 | }; 39 | 40 | export default PodIndicator; 41 | -------------------------------------------------------------------------------- /pod-web/src/components/Header/header.module.css: -------------------------------------------------------------------------------- 1 | .appHeader { 2 | width: 100%; 3 | background-color: var(--color5); 4 | height: 63px; 5 | display: flex; 6 | align-items: center; 7 | justify-content: space-between; 8 | color: white; 9 | padding: 0 35px; 10 | box-sizing: border-box; 11 | } 12 | 13 | .appHeader .brand { 14 | font-size: 14pt; 15 | font-family: "Lucida Console", Monaco, monospace; 16 | } 17 | 18 | .appHeader nav { 19 | width: 160px; 20 | display: flex; 21 | } 22 | 23 | .navItem { 24 | position: relative; 25 | font-size: 14pt; 26 | cursor: pointer; 27 | outline: 0; 28 | } 29 | 30 | .navItem:hover, 31 | .navItem:focus, 32 | .navItem:active { 33 | outline: 0; 34 | } 35 | 36 | .navActive { 37 | position: relative; 38 | } 39 | 40 | .navActive:after{ 41 | content: ""; 42 | position: absolute; 43 | left: 0; 44 | height: 30px; 45 | animation: underline .5s; 46 | animation-fill-mode: forwards; 47 | border-bottom: 1px solid #fff; 48 | } 49 | 50 | .navItem + .navItem { 51 | margin-left: 35px; 52 | } 53 | 54 | @keyframes underline { 55 | 0% { 56 | width: 0; 57 | } 58 | 59 | 100% { 60 | width: 100%; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/c-api/Makefile: -------------------------------------------------------------------------------- 1 | SGX_SDK ?= /opt/intel/sgxsdk 2 | SGX_SSL ?= /opt/intel/sgxssl 3 | SGX_SSL_LIB ?= $(SGX_SSL)/lib64 4 | SGX_INC ?= $(SGX_SDK)/include 5 | SGX_LIB ?= $(SGX_SDK)/lib64 6 | PREFIX ?= /usr/local 7 | LIBRARY_BIN ?= libpod_sgx.so 8 | 9 | ifeq ($(DEBUG), 1) 10 | CFLAGS := -O0 -g 11 | else 12 | CFLAGS := -O2 13 | endif 14 | 15 | .PHONY: all 16 | all: $(LIBRARY_BIN) 17 | 18 | CFLAGS += -fPIC \ 19 | -Wno-attributes \ 20 | -Wall \ 21 | -Wextra \ 22 | -std=c99 \ 23 | -m64 \ 24 | -D_GNU_SOURCE \ 25 | -I$(SGX_INC) \ 26 | -I../../pod-enclave 27 | 28 | LDFLAGS := -lcrypto \ 29 | -L$(SGX_LIB) -lsgx_urts -lsgx_uae_service \ 30 | -L$(SGX_SSL_LIB) -lsgx_usgxssl \ 31 | -shared 32 | 33 | # Main binary 34 | $(LIBRARY_BIN): pod_sgx.o pod_log.o pod_enclave_u.o 35 | $(CC) $^ $(LDFLAGS) -o $@ 36 | 37 | pod_sgx.o: pod_sgx.c 38 | $(CC) $(CFLAGS) -c $< -o $@ 39 | 40 | pod_log.o: pod_log.c 41 | $(CC) $(CFLAGS) -c $< -o $@ 42 | 43 | pod_enclave_u.o: ../../pod-enclave/pod_enclave_u.c 44 | $(CC) $(CFLAGS) -c $< -o $@ 45 | 46 | .PHONY: install 47 | install: 48 | install $(LIBRARY_BIN) ${PREFIX}/lib 49 | ldconfig 50 | 51 | .PHONY: clean 52 | clean: 53 | $(RM) *.o *.so 54 | -------------------------------------------------------------------------------- /pod-ext/frontend.js: -------------------------------------------------------------------------------- 1 | const { HOST, ORIGIN, REMOTE, REGISTER, CHALLENGE } = constants; 2 | var port = browser.runtime.connect(); 3 | 4 | //insert global variable to be shown 5 | const container = document.head || document.documentElement; 6 | const scriptTag = document.createElement("script"); 7 | scriptTag.setAttribute("async", "false"); 8 | scriptTag.textContent = "window.__PROOF_OF_DEVICE__ = true;"; 9 | container.insertBefore(scriptTag, container.children[0]); 10 | container.removeChild(scriptTag); 11 | 12 | window.addEventListener( 13 | "message", 14 | function(event) { 15 | //block unkown origins 16 | if (event.origin !== ORIGIN || event.data.host !== REMOTE) return; 17 | if (event.source != window) return; 18 | 19 | if (event.data.type) { 20 | let messageToBack = browser.runtime.sendMessage({ 21 | type: event.data.type, 22 | data: event.data.data, 23 | }); 24 | messageToBack.then(handleResponse.bind(null, event.source), handleError); 25 | } 26 | }, 27 | false 28 | ); 29 | 30 | function handleResponse(source, { type, response }) { 31 | source.postMessage({ host: HOST, data: `${response}` }, "*"); 32 | } 33 | 34 | function handleError(error) { 35 | console.log(`Error: ${error}`); 36 | } 37 | -------------------------------------------------------------------------------- /pod-ext/background.js: -------------------------------------------------------------------------------- 1 | const { CHALLENGE, REGISTER, SPID } = constants; 2 | var port = browser.runtime.connectNative("pod_app"); 3 | console.log('port', port); 4 | let waitingResponse = null; 5 | 6 | browser.runtime.onMessage.addListener((request, sender, sendResponse) => { 7 | if (request.type === REGISTER) { 8 | console.info(REGISTER); 9 | port.postMessage({ 10 | msg: REGISTER, 11 | spid: SPID 12 | }) 13 | waitingResponse = curryResponse(sendResponse, REGISTER); 14 | } else if (request.type === CHALLENGE) { 15 | console.info(CHALLENGE, request.data); 16 | port.postMessage({ 17 | msg: CHALLENGE, 18 | challenge: request.data 19 | }) 20 | waitingResponse = curryResponse(sendResponse, CHALLENGE) 21 | } 22 | return true; // for async response 23 | }); 24 | 25 | port.onMessage.addListener(response => { 26 | if (response.msg === REGISTER) { 27 | console.info(REGISTER, response); 28 | waitingResponse(response.quote) 29 | } else if (response.msg === CHALLENGE) { 30 | console.info(CHALLENGE, response); 31 | waitingResponse(response.signed) 32 | } 33 | waitingResponse = null 34 | }) 35 | 36 | function curryResponse(sendResponse, type) { 37 | return response => sendResponse({type, response}) 38 | } 39 | -------------------------------------------------------------------------------- /pod-web/src/components/Header/index.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useContext } from "react"; 2 | import AuthContext from "../../context/auth"; 3 | import { NavLink } from "react-router-dom"; 4 | 5 | import { appHeader, brand, navActive, navItem } from "./header.module.css"; 6 | 7 | const Header = () => { 8 | const auth = useContext(AuthContext); 9 | 10 | const logout = () => auth.setLoggedIn(false); 11 | 12 | return ( 13 | 14 | The X Bank 15 | 16 | {auth.isLoggedIn ? ( 17 | 18 | 19 | Home 20 | 21 | 22 | ) : null} 23 | {!auth.isLoggedIn ? ( 24 | 25 | 26 | 27 | Login 28 | 29 | 30 | 31 | 32 | Register 33 | 34 | 35 | 36 | ) : ( 37 | 38 | Logout 39 | 40 | )} 41 | 42 | 43 | ); 44 | }; 45 | 46 | export default Header; 47 | -------------------------------------------------------------------------------- /pod-ext/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "PoD", 4 | "version": "0.0.1", 5 | "author": "Muhammed Tanrıkulu", 6 | "description": "Extension for Proof of Device", 7 | "homepage_url": "https://golem.network", 8 | "icons": { 9 | "48": "icons/pod-48.png" 10 | }, 11 | 12 | "browser_specific_settings": { 13 | "gecko": { 14 | "id": "pod_app@golem.network" 15 | } 16 | }, 17 | 18 | "background": { 19 | "scripts": [ 20 | "js/check-browser.js", 21 | "js/promisify.js", 22 | "js/constants.js", 23 | "background.js" 24 | ] 25 | }, 26 | 27 | "permissions": ["activeTab", "storage", "nativeMessaging"], 28 | 29 | "content_scripts": [ 30 | { 31 | "matches": ["http://*/*", "https://*/*"], 32 | "js": [ 33 | "js/check-browser.js", 34 | "js/promisify.js", 35 | "js/constants.js", 36 | "frontend.js" 37 | ], 38 | "css": ["style/main.css"], 39 | "run_at": "document_start" 40 | } 41 | ], 42 | 43 | "web_accessible_resources": ["resources/*.png", "pages/*"], 44 | 45 | "options_ui": { 46 | "page": "pages/settings.html", 47 | "open_in_tab": true 48 | }, 49 | 50 | "browser_action": { 51 | "default_icon": "icons/pod-32.png", 52 | "default_title": "Pod-Ext" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /pod-ext/popup/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Pod Ext 16 | 17 | 18 | 19 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | Test 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /pod-app/install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | # Get current dir. 5 | CURRENT_DIR="$( pwd )" 6 | # Name of the manifest file 7 | APP_NAME="pod_app" 8 | # Native App installation path 9 | INSTALL_DIR="$HOME/.local/share/pod-app" 10 | 11 | 12 | # Check if user is root. 13 | if [ "$(whoami)" = "root" ]; then 14 | 15 | # Check if Firefox is 64bit. 16 | if [ -d "/usr/lib64/mozilla/" ]; then 17 | TARGET_DIR="/usr/lib64/mozilla/native-messaging-hosts" 18 | else 19 | TARGET_DIR="/usr/lib/mozilla/native-messaging-hosts" 20 | fi 21 | 22 | else 23 | TARGET_DIR="$HOME/.mozilla/native-messaging-hosts" 24 | fi 25 | 26 | # Create directory to copy manifest. 27 | mkdir -p "$TARGET_DIR" 28 | 29 | # Copy pod_app manifest. 30 | cp "$CURRENT_DIR/assets/$APP_NAME.json" "$TARGET_DIR" 31 | 32 | cargo install --path . --force 33 | 34 | if [ -d $INSTALL_DIR ]; then 35 | rm --recursive $INSTALL_DIR 36 | fi 37 | 38 | mkdir -p $INSTALL_DIR 39 | 40 | cp -f ../pod-enclave/pod_enclave.signed.so $INSTALL_DIR 41 | 42 | APP_DIR="$( which "pod-app" )" 43 | # Update app path in the manifest. 44 | ESCAPED_APP_PATH=${APP_DIR////\\/} 45 | sed -i -e "s/NATIVE_APP_PATH/$ESCAPED_APP_PATH/" "$TARGET_DIR/$APP_NAME.json" 46 | 47 | # Set permissions for the manifest to be shown by all users. 48 | chmod o+r "$TARGET_DIR/$APP_NAME.json" 49 | 50 | echo "$APP_NAME has been installed." 51 | -------------------------------------------------------------------------------- /pod-web/src/Router.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { 3 | BrowserRouter as Router, 4 | Redirect, 5 | Switch, 6 | Route, 7 | } from "react-router-dom"; 8 | import AuthContext from "./context/auth"; 9 | import Loader from "./components/HOC/Loader"; 10 | import Header from "./components/Header"; 11 | import Home from "./components/Home"; 12 | import Login from "./components/Login"; 13 | import Register from "./components/Register"; 14 | 15 | function RootRouter() { 16 | const auth = useContext(AuthContext); 17 | const loadingTime = 1000; 18 | return ( 19 | 20 | 21 | 22 | 23 | 24 | {!auth.isLoggedIn ? ( 25 | 26 | 27 | 28 | ) : ( 29 | 30 | )} 31 | 32 | 33 | {!auth.isLoggedIn ? ( 34 | 35 | 36 | 37 | ) : ( 38 | 39 | )} 40 | 41 | 42 | {auth.isLoggedIn ? ( 43 | 44 | 45 | 46 | ) : ( 47 | 48 | )} 49 | 50 | 51 | 52 | 53 | ); 54 | } 55 | 56 | export default RootRouter; 57 | -------------------------------------------------------------------------------- /pod-app/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::path::Path; 3 | use std::process::{Command, Stdio}; 4 | 5 | const LIB_ROOT: &str = "../lib/c-api"; 6 | const ENCLAVE_ROOT: &str = "../pod-enclave"; 7 | 8 | fn main() { 9 | // Run Makefile for `pod-enclave` first as we need it to build the 10 | // c-api lib. 11 | let mut cmd = Command::new("make"); 12 | cmd.stdout(Stdio::inherit()) 13 | .stderr(Stdio::inherit()) 14 | .current_dir("../pod-enclave"); 15 | cmd.output().expect("make pod-enclave should succeed"); 16 | // Get some basic conf vars 17 | let sgx_sdk = env::var("SGX_SDK").unwrap_or("/opt/intel/sgxsdk".to_string()); 18 | let sgx_sdk_path = Path::new(&sgx_sdk); 19 | let sgx_ssl = env::var("SGX_SSL").unwrap_or("/opt/intel/sgxssl".to_string()); 20 | let lib_root = Path::new(LIB_ROOT); 21 | let enclave_root = Path::new(ENCLAVE_ROOT); 22 | // Build c-api 23 | cc::Build::new() 24 | .files(&[ 25 | lib_root.join("pod_log.c"), 26 | lib_root.join("pod_sgx.c"), 27 | enclave_root.join("pod_enclave_u.c"), 28 | ]) 29 | .include(sgx_sdk_path.join("include")) 30 | .include(enclave_root) 31 | .flag_if_supported("-D_GNU_SOURCE") 32 | .flag_if_supported("-Wno-attributes") 33 | .flag_if_supported("-std=c99") 34 | .compile("libpod_sgx.a"); 35 | // Linker flags 36 | println!("cargo:rustc-flags=-l crypto"); 37 | println!("cargo:rustc-flags=-l sgx_urts"); 38 | println!("cargo:rustc-flags=-l sgx_uae_service"); 39 | println!("cargo:rustc-flags=-l sgx_usgxssl"); 40 | println!("cargo:rustc-flags=-L {}/lib64", sgx_sdk); 41 | println!("cargo:rustc-flags=-L {}/lib64", sgx_ssl); 42 | } 43 | -------------------------------------------------------------------------------- /pod-enclave/README.rst: -------------------------------------------------------------------------------- 1 | =========== 2 | ``pod-enclave`` 3 | =========== 4 | 5 | This sample consists of the PoD SGX enclave (``pod_enclave``). 6 | 7 | The enclave uses ED25519 keys for signing. Public key size is 32 bytes, signature size is 64 bytes. 8 | See ``_. 9 | Enclave public key is stored in the ``report_data`` field of enclave SGX quote. 10 | 11 | Requirements 12 | ============ 13 | 14 | - This sample was tested on Ubuntu 16.04 LTS, but should work on newer systems as well 15 | - Intel SGX capable hardware 16 | - SGX EPID driver installed and running, version 1.9 or above: 17 | ``_ 18 | - SGX platform software (PSW) and SDK version 2.5: 19 | ``_ 20 | - SGX SSL library version 2.5 with OpenSSL v1.1.1d: 21 | ``_ 22 | ``_ 23 | - (Newer versions of SGX PSW/SDK/SSL should work, 2.5 was chosen for Ubuntu 16.04 compatibility) 24 | 25 | Building 26 | ======== 27 | 28 | Check Makefiles for possible configuration options, mainly paths to SGX SDK/SSL (``SGX_SDK``, 29 | ``SGX_SSL``). Default values match default installation paths of these components 30 | (in ``/opt/intel``). 31 | 32 | You need an enclave signing key, which is a 3072-bit RSA key with exponent ``3``. You can generate 33 | it with ``openssl``:: 34 | 35 | openssl genrsa -out enclave_signing_key.pem -3 3072 36 | 37 | ``ENCLAVE_SIGNING_KEY`` environment variable/Makefile option should contain path to the enclave 38 | signing key. 39 | 40 | To build the enclave, and library, just run ``make``. To install the library and 41 | the application, run ``sudo make install``. 42 | 43 | -------------------------------------------------------------------------------- /pod-ext/popup/popup.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --color-primary: #0078e7; 3 | --color-border: #cdcdcd; 4 | } 5 | 6 | html, 7 | body { 8 | width: 300px; 9 | height: 400px; 10 | overflow: hidden; 11 | box-sizing: border-box; 12 | } 13 | 14 | body { 15 | padding: 15px; 16 | } 17 | 18 | header, 19 | header > div { 20 | display: flex; 21 | justify-content: space-between; 22 | align-items: center; 23 | font-size: 12pt; 24 | } 25 | 26 | header { 27 | height: 10%; 28 | } 29 | 30 | header > div > img { 31 | height: 30px; 32 | margin-right: 10px; 33 | } 34 | 35 | .logo a { 36 | display: flex; 37 | align-items: center; 38 | text-decoration: none; 39 | transition: .3s transform ease; 40 | } 41 | 42 | .logo a:link, 43 | .logo a:visited { 44 | color: black; 45 | } 46 | .logo a:hover { 47 | color: black; 48 | transform: scale(1.1); 49 | } 50 | 51 | .logo img { 52 | width: 30px; 53 | margin-right: 5px; 54 | } 55 | 56 | .icono-tiles { 57 | width: 5px; 58 | height: 5px; 59 | transition: 0.2s color linear; 60 | cursor: pointer; 61 | } 62 | 63 | .settings-btn:hover > .icono-tiles { 64 | color: var(--color-primary); 65 | } 66 | 67 | main { 68 | height: 70%; 69 | padding: 15px 0; 70 | } 71 | 72 | main > section { 73 | display: flex; 74 | flex-direction: column; 75 | justify-content: center; 76 | align-items: center; 77 | 78 | height: 70%; 79 | } 80 | 81 | main > section > a { 82 | font-size: 14pt; 83 | font-weight: 500; 84 | text-decoration: none; 85 | color: var(--primary-color); 86 | } 87 | 88 | footer { 89 | height: 10%; 90 | } 91 | 92 | footer > button { 93 | width: 100%; 94 | height: 100%; 95 | } 96 | 97 | footer > button:active { 98 | background: white; 99 | color: #0070d8; 100 | } 101 | -------------------------------------------------------------------------------- /pod-web/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | You need to enable JavaScript to run this app. 31 | 32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /pod-web/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | /*background: linear-gradient(135deg, currentColor 25%, transparent 25%) -10px 0, linear-gradient(225deg, currentColor 25%, transparent 25%) -10px 0, linear-gradient(315deg, currentColor 25%, transparent 25%), linear-gradient(45deg, currentColor 25%, transparent 25%); 9 | background-size: calc(2 * 10px) calc(2 * 10px);*/ 10 | } 11 | 12 | a { 13 | text-decoration: none; 14 | color: white; 15 | } 16 | 17 | a:visited { 18 | color: white; 19 | } 20 | 21 | code { 22 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 23 | monospace; 24 | } 25 | 26 | input{ 27 | height: 40px; 28 | margin-top: 7px; 29 | margin-bottom: 7px; 30 | font-size: 14pt; 31 | padding: 0 14px; 32 | border: 0; 33 | border-radius: 7px; 34 | } 35 | 36 | button { 37 | width: 140px; 38 | height: 35px; 39 | background: var(--color4); 40 | color: var(--color3); 41 | border: none; 42 | font-size: 14pt; 43 | margin-top: 7px; 44 | border-radius: 7px; 45 | cursor: pointer; 46 | } 47 | 48 | button:hover { 49 | background: var(--color5); 50 | } 51 | 52 | fieldset { 53 | position: relative; 54 | padding: 42px 0; 55 | background-color: #ffffff99; 56 | border-radius: 7px; 57 | border: 6px solid white; 58 | } 59 | 60 | fieldset legend { 61 | font-size: 18pt; 62 | margin: 0 12pt; 63 | padding: 2px 16px; 64 | color: black; 65 | background-color: #ffffff; 66 | border-radius: 7px; 67 | border-top: 1px solid white; 68 | } 69 | 70 | li { 71 | display: flex; 72 | justify-content: space-around; 73 | list-style-type: none; 74 | line-height: 1.5em; 75 | font-size: 12pt; 76 | } 77 | -------------------------------------------------------------------------------- /pod-ext/pages/settings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | PoD 16 | 17 | 21 | 22 | 23 | 24 | 25 | Test 26 | 27 | 28 | 29 | Test 30 | 31 | 32 | 33 | Test 34 | 35 | 36 | 37 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /lib/api/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod c; 2 | mod wrappers; 3 | 4 | use anyhow::Result; 5 | use rust_sgx_util::Quote; 6 | use std::cell::RefCell; 7 | use std::fs; 8 | use std::path::Path; 9 | 10 | pub use wrappers::set_verbose; 11 | 12 | pub enum QuoteType { 13 | Linkable, 14 | Unlinkable, 15 | } 16 | 17 | pub struct PodEnclave { 18 | quote: RefCell>, 19 | } 20 | 21 | impl PodEnclave { 22 | pub fn new>(enclave_path: P, sealed_keys_path: P) -> Result { 23 | if !sealed_keys_path.as_ref().exists() { 24 | // Initialize enclave for the first time 25 | let sealed_keys = wrappers::init_enclave(enclave_path)?; 26 | // Save state to file 27 | fs::write(sealed_keys_path.as_ref(), &sealed_keys)?; 28 | sealed_keys 29 | } else { 30 | // Load state from file 31 | let sealed_keys = fs::read(sealed_keys_path.as_ref())?; 32 | wrappers::load_enclave(enclave_path, &sealed_keys)?; 33 | sealed_keys 34 | }; 35 | Ok(Self { 36 | quote: RefCell::new(None), 37 | }) 38 | } 39 | 40 | pub fn get_quote>(&self, spid: S, quote_type: QuoteType) -> Result { 41 | let quote = match self.quote.borrow_mut().take() { 42 | Some(quote) => quote, 43 | None => { 44 | let quote = wrappers::get_quote(spid.as_ref(), quote_type)?; 45 | quote 46 | } 47 | }; 48 | let ret = quote.clone(); 49 | *self.quote.borrow_mut() = Some(quote); 50 | Ok(ret) 51 | } 52 | 53 | pub fn sign>(&self, message: B) -> Result> { 54 | let signature = wrappers::sign_buffer(message)?; 55 | Ok(signature) 56 | } 57 | } 58 | 59 | impl Drop for PodEnclave { 60 | fn drop(&mut self) { 61 | wrappers::unload_enclave().expect("unloading enclave should succeed") 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /pod-ext/style/montserrat-font.css: -------------------------------------------------------------------------------- 1 | /* cyrillic-ext */ 2 | @font-face { 3 | font-family: 'Montserrat'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459WRhyzbi.woff2) format('woff2'); 7 | unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; 8 | } 9 | /* cyrillic */ 10 | @font-face { 11 | font-family: 'Montserrat'; 12 | font-style: normal; 13 | font-weight: 400; 14 | src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459W1hyzbi.woff2) format('woff2'); 15 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; 16 | } 17 | /* vietnamese */ 18 | @font-face { 19 | font-family: 'Montserrat'; 20 | font-style: normal; 21 | font-weight: 400; 22 | src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459WZhyzbi.woff2) format('woff2'); 23 | unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; 24 | } 25 | /* latin-ext */ 26 | @font-face { 27 | font-family: 'Montserrat'; 28 | font-style: normal; 29 | font-weight: 400; 30 | src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459Wdhyzbi.woff2) format('woff2'); 31 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; 32 | } 33 | /* latin */ 34 | @font-face { 35 | font-family: 'Montserrat'; 36 | font-style: normal; 37 | font-weight: 400; 38 | src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459Wlhyw.woff2) format('woff2'); 39 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 40 | } 41 | -------------------------------------------------------------------------------- /pod-web/src/assets/click.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /lib/rust-sgx-util/src/c.rs: -------------------------------------------------------------------------------- 1 | #[repr(C)] 2 | pub(crate) struct IasContext { 3 | _private: [u8; 0], 4 | } 5 | 6 | #[link(name = "sgx_util")] 7 | extern "C" { 8 | // ias.h 9 | pub(crate) fn ias_init( 10 | ias_api_key: *const libc::c_char, 11 | ias_verify_url: *const libc::c_char, 12 | ias_sigrl_url: *const libc::c_char, 13 | ) -> *mut IasContext; 14 | pub(crate) fn ias_cleanup(context: *mut IasContext); 15 | pub(crate) fn ias_get_sigrl( 16 | context: *mut IasContext, 17 | gid: *const u8, 18 | sigrl_size: *mut usize, 19 | sigrl: *mut *mut libc::c_void, 20 | ) -> libc::c_int; 21 | pub(crate) fn ias_verify_quote( 22 | context: *mut IasContext, 23 | quote: *const libc::c_void, 24 | quote_size: usize, 25 | nonce: *const libc::c_char, 26 | report_path: *const libc::c_char, 27 | sig_path: *const libc::c_char, 28 | cert_path: *const libc::c_char, 29 | advisory_path: *const libc::c_char, 30 | ) -> libc::c_int; 31 | // util.h 32 | pub(crate) fn set_verbose(verbose: bool); 33 | // attestation.h 34 | #[allow(unused)] 35 | pub(crate) fn verify_ias_report( 36 | ias_report: *const u8, 37 | ias_report_size: usize, 38 | ias_sig_b64: *mut u8, 39 | ias_sig_64_size: usize, 40 | allow_outdated_tcb: bool, 41 | nonce: *const libc::c_char, 42 | mr_signer: *const libc::c_char, 43 | mr_enclave: *const libc::c_char, 44 | isv_prod_id: *const libc::c_char, 45 | isv_svn: *const libc::c_char, 46 | report_data: *const libc::c_char, 47 | ias_pub_key_pem: *const libc::c_char, 48 | ) -> libc::c_int; 49 | #[allow(unused)] 50 | pub(crate) fn verify_quote( 51 | quote_data: *const libc::c_void, 52 | quote_size: usize, 53 | mr_signer: *const libc::c_char, 54 | mr_enclave: *const libc::c_char, 55 | isv_prod_id: *const libc::c_char, 56 | isv_svn: *const libc::c_char, 57 | report_data: *const libc::c_char, 58 | ) -> libc::c_int; 59 | } 60 | -------------------------------------------------------------------------------- /pod-web/src/components/Home/home.module.css: -------------------------------------------------------------------------------- 1 | .home { 2 | width: 100%; 3 | min-width: 500px; 4 | height: calc(100vh - 63px); 5 | display: flex; 6 | flex-direction: column; 7 | justify-content: flex-start; 8 | align-items: flex-start; 9 | font-size: 21pt; 10 | padding: 0 25vh; 11 | box-sizing: border-box; 12 | transition: padding .5s; 13 | color: var(--color3); 14 | } 15 | 16 | .spentChart { 17 | width: 100%; 18 | height: 450px; 19 | } 20 | 21 | .actionPanel { 22 | position: relative; 23 | bottom: 0; 24 | } 25 | 26 | .displayAmount { 27 | margin-left: 10px; 28 | font-family: monospace; 29 | word-spacing: -10px; 30 | } 31 | 32 | .summary { 33 | width: 100%; 34 | display: flex; 35 | justify-content: space-between; 36 | padding: 0 15px; 37 | box-sizing: border-box; 38 | margin-top: 20px; 39 | } 40 | 41 | .historyScreen, 42 | .withdrawScreen { 43 | width: 30vw; 44 | height: 20vh; 45 | padding: 15px 30px; 46 | border: 1px solid grey; 47 | border-radius: 5px; 48 | text-align: left; 49 | } 50 | 51 | .withdrawScreen { 52 | display: flex; 53 | flex-direction: column; 54 | justify-content: space-between; 55 | position: relative; 56 | } 57 | .historyScreen { 58 | overflow-y: scroll; 59 | } 60 | 61 | .historyScreen ul { 62 | padding: 0; 63 | } 64 | 65 | .historyScreen li { 66 | align-items: center; 67 | border: 1px dashed #999; 68 | height: 60px; 69 | } 70 | 71 | .historyScreen li span:first-child { 72 | text-align: left; 73 | width: 150px; 74 | } 75 | 76 | .historyScreen li span:last-child { 77 | text-align: right; 78 | width: 150px; 79 | } 80 | 81 | @media only screen and (max-width: 1270px) { 82 | .home { 83 | display: block; 84 | padding: 0 15px; 85 | } 86 | } 87 | 88 | @media only screen and (max-width: 900px) { 89 | .spentChart { 90 | height: 280px; 91 | } 92 | .summary { 93 | display: block; 94 | } 95 | 96 | .historyScreen, 97 | .withdrawScreen { 98 | width: 100%; 99 | height: 25vh; 100 | box-sizing: border-box; 101 | margin-top: 10px; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /pod-app/examples/browser_mock.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{anyhow, Result}; 2 | use nix::sys::signal::{self, Signal}; 3 | use nix::unistd::Pid; 4 | use serde_json::Value; 5 | use std::convert::TryFrom; 6 | use std::io::{self, Read, Write}; 7 | use std::path::PathBuf; 8 | use std::process::{Command, Stdio}; 9 | use structopt::StructOpt; 10 | 11 | #[derive(StructOpt)] 12 | struct Opt { 13 | /// Path to native messaging enabled binary. 14 | #[structopt(parse(from_os_str))] 15 | path: PathBuf, 16 | } 17 | 18 | fn main() -> Result<()> { 19 | let opt = Opt::from_args(); 20 | 21 | let mut child = Command::new(&opt.path) 22 | .stdin(Stdio::piped()) 23 | .stdout(Stdio::piped()) 24 | .spawn()?; 25 | loop { 26 | print!("> "); 27 | io::stdout().flush()?; 28 | 29 | let mut json = String::new(); 30 | io::stdin().read_line(&mut json)?; 31 | let json = json.trim(); 32 | 33 | if json.is_empty() { 34 | continue; 35 | } 36 | 37 | if json == "exit" { 38 | break; 39 | } 40 | 41 | let msg_len = json.len(); 42 | let msg_len = u32::try_from(msg_len)?; 43 | 44 | { 45 | let stdin = child 46 | .stdin 47 | .as_mut() 48 | .ok_or(anyhow!("failed to open stdin"))?; 49 | stdin.write_all(&msg_len.to_ne_bytes())?; 50 | stdin.write_all(json.as_bytes())?; 51 | } 52 | 53 | { 54 | let stdout = child 55 | .stdout 56 | .as_mut() 57 | .ok_or(anyhow!("failed to open stdout"))?; 58 | let mut msg_len = [0u8; 4]; 59 | stdout.read_exact(&mut msg_len)?; 60 | let msg_len = u32::from_ne_bytes(msg_len); 61 | let msg_len = usize::try_from(msg_len).expect("u32 should fit into usize"); 62 | 63 | let mut msg = Vec::new(); 64 | msg.resize(msg_len, 0); 65 | stdout.read_exact(&mut msg)?; 66 | let output: Value = serde_json::from_slice(&msg)?; 67 | println!("{}", output); 68 | } 69 | } 70 | signal::kill(Pid::from_raw(child.id() as i32), Some(Signal::SIGTERM))?; 71 | let status_code = child.wait()?; 72 | println!("Child exited with {}", status_code); 73 | 74 | Ok(()) 75 | } 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Proof-of-device 2 | 3 | Proof-of-device, or _pod_, is another take at 2FA or rather U2F. Here, however, the burden of storing 4 | keys for signing and proving your identity is managed by the SGX enclave. The service you're 5 | authenticating with sends you challenge which you sign using a private key embedded within the 6 | enclave in your Intel CPU. The system is very secure since not even you have the knowledge of 7 | the private key that's stored within the enclave. 8 | 9 | ## Project structure 10 | 11 | The project comprises of four main components: 12 | * [`pod-enclave`] -- This is where the private key used for signing authentication challenge requests 13 | is generated and then stored. Note that the private key is actually stored on the 14 | host, however, in an enclave-sealed form which only the enclave that generated it 15 | can unseal to then use it for signing. 16 | * [`pod-app`] -- This is the native app that _pod_ uses to interface with the `pod-enclave`. It implements 17 | [native messaging] and therefore can be used from within a browser environment. 18 | * [`pod-ext`] -- This is the browser extension connects _pod_ to generate quote and sign the challenge for the _pod-web_ authentication mechanism. 19 | * [`pod-web`] -- This is the web app _pod-ext_ connects as a GUI for the end user of the _pod_. 20 | * [`pod-server`] -- This is the web server that the service provider who offers _pod_ as an added authentication 21 | mechanism uses. 22 | 23 | [`pod-enclave`]: https://github.com/golemfactory/ProofOfDevice/tree/master/pod-enclave 24 | [`pod-app`]: https://github.com/golemfactory/ProofOfDevice/tree/master/pod-app 25 | [`pod-ext`]: https://github.com/golemfactory/ProofOfDevice/tree/master/pod-ext 26 | [`pod-web`]: https://github.com/golemfactory/ProofOfDevice/tree/master/pod-web 27 | [`pod-server`]: https://github.com/golemfactory/ProofOfDevice/tree/master/pod-server 28 | [native messaging]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging 29 | 30 | For each of the components, follow the links to learn more and check out how to build and run them. 31 | 32 | ## Caveats 33 | 34 | This project currently builds and was tested on Linux only (both Ubuntu 18.04 and Arch). In the future, it is envisaged 35 | to support Windows however. 36 | 37 | -------------------------------------------------------------------------------- /pod-web/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /pod-server/src/handlers/register.rs: -------------------------------------------------------------------------------- 1 | use super::{AppError, Message}; 2 | use crate::models::{NewUser, User}; 3 | use crate::AppData; 4 | 5 | use diesel::prelude::*; 6 | 7 | use actix_web::error::BlockingError; 8 | use actix_web::{web, HttpResponse, Responder}; 9 | use rust_sgx_util::{IasHandle, Quote}; 10 | use serde::Deserialize; 11 | use std::env; 12 | use tokio_diesel::{AsyncRunQueryDsl, OptionalExtension}; 13 | 14 | #[derive(Debug, Deserialize)] 15 | pub struct RegisterInfo { 16 | login: String, 17 | quote: Quote, 18 | } 19 | 20 | pub async fn post(info: web::Json, app_data: web::Data) -> impl Responder { 21 | use crate::schema::users::dsl::*; 22 | 23 | log::info!( 24 | "Received register request for user with login '{}'.", 25 | info.login 26 | ); 27 | log::debug!("Received data: {:?}", info); 28 | 29 | // Check if the user is already registered. 30 | let result = users 31 | .filter(login.eq(info.login.clone())) 32 | .get_result_async::(&app_data.pool) 33 | .await 34 | .optional()?; 35 | log::debug!("Matching user records found: {:?}", result); 36 | 37 | if let Some(_) = result { 38 | log::info!("User '{}' already registered.", info.login); 39 | return Err(AppError::AlreadyRegistered); 40 | } 41 | 42 | let quote = info.quote.clone(); 43 | if let Err(err) = web::block(move || { 44 | // Verify the provided data with IAS. 45 | let api_key = env::var("POD_SERVER_API_KEY")?; 46 | let handle = IasHandle::new(&api_key, None, None)?; 47 | handle.verify_quote("e, None, None, None, None, None)?; 48 | Ok(()) 49 | }) 50 | .await 51 | { 52 | match err { 53 | BlockingError::Error(err) => return Err(err), 54 | BlockingError::Canceled => return Err(AppError::ActixBlockingCanceled), 55 | } 56 | }; 57 | 58 | // Extract pub_key from Quote 59 | // ED25519 public key is 32 bytes long 60 | let report_data = info.quote.report_data()?; 61 | let pub_key_ = base64::encode(&report_data[..32]); 62 | log::debug!("Extracted public key (base64 encoded): {}", pub_key_); 63 | 64 | // Insert user to the database. 65 | let new_user = NewUser { 66 | login: info.login.clone(), 67 | pub_key: pub_key_, 68 | }; 69 | diesel::insert_into(users) 70 | .values(new_user) 71 | .execute_async(&app_data.pool) 72 | .await?; 73 | 74 | log::info!("User '{}' successfully inserted into db.", info.login); 75 | Ok(HttpResponse::Ok().json(Message::ok().add_param("description", "registration successful"))) 76 | } 77 | -------------------------------------------------------------------------------- /pod-web/src/components/Register/index.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | 3 | import { form, register } from "./register.module.css"; 4 | import useEventListener from "../../hooks/useEventListener"; 5 | import request from "../../utils/request"; 6 | import {HOST, REGISTER, REMOTE, ORIGIN} from "../../Constants"; 7 | import PodIndicator from "../PodIndicator"; 8 | 9 | const getById = id => document.getElementById(id); 10 | 11 | const Register = () => { 12 | const [ errorStatus, setError ] = useState(false); 13 | const [ quote, setQuote ] = useState(null); 14 | useEffect(() => { 15 | window.postMessage( 16 | { host: HOST, type: REGISTER }, 17 | ORIGIN 18 | ); 19 | }, []); 20 | 21 | const messageListener = ({data, origin}) => { 22 | if (origin !== ORIGIN || data.host !== REMOTE) 23 | return; 24 | console.log(data); // Answer here 25 | setQuote(data.data) 26 | }; 27 | 28 | useEventListener("message", messageListener); 29 | 30 | const requestRegister = (event) => { 31 | event.preventDefault(); 32 | const login = getById("usernameInput").value; 33 | //const password = getById("passwordInput").value; 34 | registerRequest({ login, quote }) 35 | .then((result) => { 36 | console.log(result); 37 | }) 38 | .catch((error) => { 39 | setError(true) 40 | }); 41 | }; 42 | 43 | return ( 44 | 45 | 46 | 47 | Registration 48 | {errorStatus ? User already exist! : null} 49 | 50 | 58 | 59 | 60 | 67 | 68 | 69 | 76 | 77 | 78 | Register 79 | 80 | 81 | 82 | 83 | 84 | ); 85 | }; 86 | 87 | export default Register; 88 | 89 | function registerRequest({ login, quote }) { 90 | return request('/register', { 91 | method: 'post', 92 | headers: {'Content-Type': 'application/json'}, 93 | body: JSON.stringify({ 94 | login, 95 | quote, 96 | }) 97 | }) 98 | } 99 | -------------------------------------------------------------------------------- /pod-web/src/components/HOC/Loader.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import { tween } from "shifty"; 3 | 4 | import { loaderIcon, loaderScreen } from "./loader.module.css"; 5 | import loadingSVG from "../../assets/dollar.svg"; 6 | 7 | let time; 8 | function Loader({ children, loadingTime }) { 9 | const [load, setLoad] = useState(false); 10 | const [anim, setAnim] = useState([]); 11 | useEffect(() => { 12 | time = setTimeout(() => setLoad(true), loadingTime); 13 | 14 | tween({ 15 | from: { z: 0 }, 16 | to: { z: -30 }, 17 | duration: 500, 18 | step: ({ z, y }) => 19 | setAnim([ 20 | { transform: `rotateZ(${z}deg)`, transformOrigin: 'left' }, 21 | { transform: `rotateZ(${z * 2}deg)`, transformOrigin: 'left' }, 22 | { transform: `rotateZ(${z * 3}deg)`, transformOrigin: 'left' }, 23 | { transform: `rotateZ(${z * 4}deg)`, transformOrigin: 'left' }, 24 | { transform: `rotateZ(${z * 5}deg)`, transformOrigin: 'left' }, 25 | { transform: `rotateZ(${z * 6}deg)`, transformOrigin: 'left' }, 26 | { transform: `rotateZ(${z * 7}deg)`, transformOrigin: 'left' }, 27 | { transform: `rotateZ(${z * 8}deg)`, transformOrigin: 'left' }, 28 | { transform: `rotateZ(${z * 9}deg)`, transformOrigin: 'left' }, 29 | { transform: `rotateZ(${z * 10}deg)`, transformOrigin: 'left' }, 30 | { transform: `rotateZ(${z * 11}deg)`, transformOrigin: 'left' } 31 | ]) 32 | }, [loadingTime]); 33 | 34 | return () => { 35 | clearTimeout(time); 36 | time = null; 37 | }; 38 | }, [loadingTime]); 39 | if (load) return children; 40 | return ( 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | ); 56 | } 57 | export default Loader; 58 | -------------------------------------------------------------------------------- /pod-app/src/messages.rs: -------------------------------------------------------------------------------- 1 | use super::Config; 2 | use anyhow::Result; 3 | use pod_api::{PodEnclave, QuoteType}; 4 | use rust_sgx_util::Quote; 5 | use serde::{Deserialize, Serialize}; 6 | 7 | #[derive(Debug, Deserialize)] 8 | #[serde(tag = "msg", rename_all = "snake_case")] 9 | enum IncomingMessage { 10 | GetQuote { 11 | spid: String, 12 | }, 13 | SignChallenge { 14 | #[serde(with = "base_64")] 15 | challenge: Vec, 16 | }, 17 | } 18 | 19 | #[derive(Debug, Serialize)] 20 | #[serde(tag = "msg", rename_all = "snake_case")] 21 | #[allow(dead_code)] 22 | pub(super) enum OutgoingMessage { 23 | GetQuote { 24 | quote: Quote, 25 | }, 26 | 27 | SignChallenge { 28 | #[serde(with = "base_64")] 29 | signed: Vec, 30 | }, 31 | } 32 | 33 | impl OutgoingMessage { 34 | pub fn get_quote(quote: Quote) -> Self { 35 | Self::GetQuote { quote } 36 | } 37 | 38 | pub fn sign_challenge>(signed: B) -> Self { 39 | Self::SignChallenge { 40 | signed: signed.as_ref().to_vec(), 41 | } 42 | } 43 | } 44 | 45 | mod base_64 { 46 | use serde::{self, Deserialize, Deserializer, Serializer}; 47 | 48 | pub(crate) fn serialize(blob: &[u8], serializer: S) -> Result 49 | where 50 | S: Serializer, 51 | { 52 | serializer.serialize_str(&base64::encode(blob)) 53 | } 54 | 55 | pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> 56 | where 57 | D: Deserializer<'de>, 58 | { 59 | let string = String::deserialize(deserializer)?; 60 | base64::decode(&string).map_err(serde::de::Error::custom) 61 | } 62 | } 63 | 64 | pub(super) fn reply>(msg: B, config: &Config) -> Result> { 65 | let msg: IncomingMessage = serde_json::from_slice(msg.as_ref())?; 66 | log::debug!("Received message content: {:?}", msg); 67 | 68 | let reply = match msg { 69 | IncomingMessage::GetQuote { spid } => { 70 | let pod_enclave = PodEnclave::new(&config.enclave, &config.private_key)?; 71 | let quote = pod_enclave.get_quote(spid, QuoteType::Unlinkable)?; 72 | let reply = OutgoingMessage::get_quote(quote); 73 | let serialized = serde_json::to_vec(&reply)?; 74 | serialized 75 | } 76 | IncomingMessage::SignChallenge { challenge } => { 77 | let pod_enclave = PodEnclave::new(&config.enclave, &config.private_key)?; 78 | let signature = pod_enclave.sign(challenge)?; 79 | let reply = OutgoingMessage::sign_challenge(signature); 80 | let serialized = serde_json::to_vec(&reply)?; 81 | serialized 82 | } 83 | }; 84 | 85 | log::debug!("Reply content: {:?}", reply); 86 | Ok(reply) 87 | } 88 | -------------------------------------------------------------------------------- /pod-ext/pages/settings.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --panel-height: 700px; 3 | --color-border: #cdcdcd; 4 | } 5 | 6 | body { 7 | display: flex; 8 | flex-direction: column; 9 | justify-content: center; 10 | align-items: center; 11 | color: #4a4a4a; 12 | background-color: #f3f3f3; 13 | font-family: 'Montserrat', sans-serif; 14 | } 15 | 16 | a { 17 | text-decoration: none; 18 | color: black; 19 | } 20 | 21 | .header { 22 | display: flex; 23 | justify-content: space-between; 24 | align-items: center; 25 | width: 60%; 26 | margin-top: 5vh; 27 | margin-bottom: 10px; 28 | } 29 | 30 | .header_name { 31 | display: flex; 32 | align-items: center; 33 | margin: 0 20px; 34 | } 35 | 36 | .header > img { 37 | max-width: 50px; 38 | max-height: 50px; 39 | width: auto; 40 | height: auto; 41 | } 42 | 43 | .panel { 44 | position: relative; 45 | width: 60%; 46 | height: var(--panel-height); 47 | min-width: 500px; 48 | background: #fff; 49 | border: 1px solid var(--color-border); 50 | border-radius: 5px; 51 | } 52 | 53 | .panel header { 54 | padding: 0 30px; 55 | border-bottom: 1px solid var(--color-border); 56 | } 57 | 58 | .panel header > p { 59 | font-size: 10pt; 60 | } 61 | 62 | .panel__action { 63 | border-top: 1px solid var(--color-border); 64 | } 65 | 66 | .pure-form-aligned .pure-control-group label { 67 | width: auto; 68 | } 69 | 70 | .label__shortcut { 71 | width: 170px !important; 72 | text-align: left !important; 73 | margin: 10px 0 !important; 74 | } 75 | 76 | fieldset { 77 | border: none; 78 | } 79 | 80 | section { 81 | display: grid; 82 | grid-template-columns: 25% auto; 83 | grid-template-rows: auto auto; 84 | justify-content: flex-start; 85 | align-items: center; 86 | border-bottom: 1px solid var(--color-border); 87 | padding: 15px 30px; 88 | } 89 | 90 | section:last-of-type { 91 | border-bottom: 0; 92 | } 93 | 94 | /*only chromuim*/ 95 | ::-webkit-scrollbar { 96 | width: 5px; 97 | } 98 | 99 | ::-webkit-scrollbar-track { 100 | margin: 5px 0; 101 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); 102 | } 103 | 104 | ::-webkit-scrollbar-thumb { 105 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5); 106 | } 107 | 108 | .scrollable { 109 | height: calc(var(--panel-height) - 200px); 110 | overflow-y: scroll; 111 | } 112 | 113 | .settings__label { 114 | font-size: 14pt; 115 | font-weight: 900; 116 | color: #000; 117 | } 118 | 119 | .pure-form-aligned .pure-control-group { 120 | margin-bottom: 0; 121 | margin: 0.5em 0; 122 | } 123 | .blacklist > li { 124 | width: 220px; 125 | } 126 | .blacklist > li:hover::after { 127 | content: 'Remove'; 128 | float: right; 129 | font-size: 8pt; 130 | line-height: 16pt; 131 | font-weight: 600; 132 | color: red; 133 | cursor: pointer; 134 | } 135 | 136 | .button-submit { 137 | position: absolute; 138 | bottom: 30px; 139 | right: 30px; 140 | } 141 | -------------------------------------------------------------------------------- /pod-web/src/assets/dollar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /pod-web/src/components/Home/index.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | 3 | import Chart from "chart.js"; 4 | import { tween } from "shifty"; 5 | 6 | import { 7 | actionPanel, 8 | displayAmount, 9 | home, 10 | historyScreen, 11 | spentChart, 12 | summary, 13 | withdrawScreen, 14 | } from "./home.module.css"; 15 | 16 | const Home = () => { 17 | const [amount, setAmount] = useState(0); 18 | useEffect(() => { 19 | loadChart(); 20 | 21 | tween({ 22 | from: { x: 0 }, 23 | to: { x: 569671200 }, 24 | duration: 2500, 25 | easing: "easeInQuint", 26 | step: ({ x }) => 27 | setAmount( 28 | new Intl.NumberFormat("pl-PL", { 29 | style: "currency", 30 | currency: "USD", 31 | }).format(x) 32 | ), 33 | }); 34 | }, []); 35 | return ( 36 | 37 | 38 | 39 | 40 | 41 | 42 | Savings 43 | {amount} 44 | 45 | alert("We went bankrupt :(")}> 46 | Withdraw 47 | 48 | 49 | 50 | 51 | 52 | 53 | Payment 54 | - $1.23 55 | 56 | 57 | Earning 58 | + $12.08 59 | 60 | 61 | Earning 62 | + $3.5 63 | 64 | 65 | Payment 66 | - $42.6 67 | 68 | 69 | Payment 70 | - $136.8 71 | 72 | 73 | Payment 74 | - $12.4 75 | 76 | 77 | 78 | 79 | 80 | ); 81 | }; 82 | 83 | export default Home; 84 | 85 | Chart.defaults.global.defaultFontColor = '#FFF'; 86 | var config = { 87 | type: "line", 88 | data: { 89 | labels: ["January", "February", "March", "April", "May", "June", "July"], 90 | datasets: [ 91 | { 92 | label: "Salary", 93 | borderColor: "#af5b5bff", 94 | backgroundColor: "#af5b5bff", 95 | data: [3, 5, 9, 2, 10, 4, 3, 7], 96 | }, 97 | { 98 | label: "DeFi", 99 | borderColor: "#276fbfff", 100 | backgroundColor: "#276fbfff", 101 | data: [3, 5, 6, 5, 2, 7, 9, 12], 102 | }, 103 | { 104 | label: "Airdrop lol", 105 | borderColor: "#f6f4f3ff", 106 | backgroundColor: "#f6f4f3ff", 107 | data: [8, 7, 5, 3, 8, 3, 8], 108 | }, 109 | ], 110 | }, 111 | options: { 112 | responsive: true, 113 | title: { 114 | display: true, 115 | text: "Earnings", 116 | }, 117 | tooltips: { 118 | mode: "index", 119 | }, 120 | hover: { 121 | mode: "index", 122 | }, 123 | scales: { 124 | x: { 125 | scaleLabel: { 126 | display: true, 127 | labelString: "Month", 128 | }, 129 | }, 130 | y: { 131 | stacked: true, 132 | scaleLabel: { 133 | display: true, 134 | labelString: "Value", 135 | }, 136 | }, 137 | }, 138 | }, 139 | }; 140 | 141 | function loadChart() { 142 | let ctx = document.getElementById("spentChart").getContext("2d"); 143 | window.myLine = new Chart(ctx, config); 144 | } 145 | -------------------------------------------------------------------------------- /pod-server/src/handlers/auth.rs: -------------------------------------------------------------------------------- 1 | use super::{AppError, Message}; 2 | use crate::models::User; 3 | use crate::AppData; 4 | 5 | use diesel::prelude::*; 6 | 7 | use actix_identity::Identity; 8 | use actix_session::Session; 9 | use actix_web::{web, HttpResponse, Responder}; 10 | use serde::Deserialize; 11 | use tokio_diesel::{AsyncRunQueryDsl, OptionalExtension}; 12 | 13 | pub async fn get(session: Session, identity: Identity) -> impl Responder { 14 | if let Some(id) = identity.identity() { 15 | log::info!("User '{}' already authenticated", id); 16 | return Err(AppError::AlreadyAuthenticated); 17 | } 18 | 19 | log::info!("Received challenge request."); 20 | 21 | // Send challenge. 22 | let challenge = match session.get::("challenge") { 23 | Err(_) => return Err(AppError::InvalidCookie), 24 | Ok(Some(challenge)) => challenge, 25 | Ok(None) => { 26 | let mut blob = [0u8; 64]; 27 | getrandom::getrandom(&mut blob)?; 28 | let challenge = base64::encode(&blob[..]); 29 | 30 | log::debug!("Generated challenge: {}", challenge); 31 | 32 | if let Err(_) = session.set("challenge", challenge.clone()) { 33 | return Err(AppError::InvalidCookie); 34 | } 35 | 36 | challenge 37 | } 38 | }; 39 | 40 | Ok(HttpResponse::Ok().json( 41 | Message::ok() 42 | .add_param("description", "challenge successfully generated") 43 | .add_param("challenge", challenge), 44 | )) 45 | } 46 | 47 | #[derive(Deserialize)] 48 | pub struct AuthChallengeResponse { 49 | login: String, 50 | response: String, // base64 encoded 51 | } 52 | 53 | pub async fn post( 54 | response: web::Json, 55 | app_data: web::Data, 56 | session: Session, 57 | identity: Identity, 58 | ) -> impl Responder { 59 | if let Some(ident) = identity.identity() { 60 | log::info!("User '{}' already authenticated!", ident); 61 | return Err(AppError::AlreadyAuthenticated); 62 | } 63 | 64 | use crate::schema::users::dsl::*; 65 | 66 | log::info!( 67 | "Received challenge response from user with login '{}'.", 68 | response.login 69 | ); 70 | 71 | // Fetch user's record and extract their pub_key. 72 | let record = users 73 | .filter(login.eq(response.login.clone())) 74 | .get_result_async::(&app_data.pool) 75 | .await 76 | .optional()?; 77 | let record = match record { 78 | Some(record) => record, 79 | None => return Err(AppError::NotRegistered), 80 | }; 81 | 82 | let blob = match session 83 | .get::("challenge") 84 | .map_err(|_| AppError::InvalidCookie)? 85 | { 86 | Some(challenge) => base64::decode(challenge)?, 87 | None => return Err(AppError::InvalidChallenge), 88 | }; 89 | 90 | let pub_key_ = ed25519_dalek::PublicKey::from_bytes(&base64::decode(&record.pub_key)?)?; 91 | let enc_blob = base64::decode(&response.response)?; 92 | let signature = ed25519_dalek::Signature::from_bytes(&enc_blob)?; 93 | pub_key_.verify(&blob, &signature)?; 94 | 95 | identity.remember(response.login.clone()); 96 | session.purge(); 97 | 98 | Ok( 99 | HttpResponse::Ok() 100 | .json(Message::ok().add_param("description", "authentication successful")), 101 | ) 102 | } 103 | -------------------------------------------------------------------------------- /pod-app/README.md: -------------------------------------------------------------------------------- 1 | # `pod-app` 2 | 3 | The native app that _pod_ uses to interface with the `pod-enclave`. It implements [native messaging] and 4 | therefore can be used from within a browser environment such as [`pod-ext`]. 5 | 6 | ## Installation 7 | 8 | You can install the app together with the enclave file `pod_enclave.signed.so` using the provided simple 9 | `install.sh` script. This script will install the `pod-app` into the local cargo registry, and will create 10 | `$HOME/.local/share/pod-app` local storage dir and copy the enclave file into it. The sealed private key 11 | file `private_key.sealed` will also reside there. 12 | 13 | ``` 14 | ./install.sh 15 | ``` 16 | 17 | ## Native messages handled by `pod-app` 18 | 19 | All requests are in JSON format. See [native messaging] for more info. 20 | 21 | * **Requests**: 22 | - `{ "msg" : "get_quote", "spid": "01234567abcdef" }` 23 | - `{ "msg" : "sign_challenge", "challenge" : "AAADEADBEEF" }` 24 | 25 | * **Responses** 26 | - `{ "msg" : "get_quote", "quote" : "AAAAA...AAA" }` 27 | - `{ "msg" : "sign_challenge", "signed" : "BBBBBAAAAABB" }` 28 | - `{ "msg" : "error", "description" : "description of the error" }` 29 | 30 | ## Development 31 | 32 | ### Building 33 | 34 | Simply run from the repo's root: 35 | 36 | ``` 37 | cargo build 38 | ``` 39 | 40 | This will build [`pod-enclave`] by default which is a prerequisite for the `pod-app`. 41 | 42 | 43 | ## Examples 44 | 45 | ### `browser_mock` app 46 | 47 | For testing purposes, there is a `browser_mock` app as part of the `pod-app` which can be used for 48 | manual testing of the native messaging responses of the `pod-app`. 49 | 50 | To run it, first make sure `pod-app` is built: 51 | 52 | ``` 53 | cargo build 54 | ``` 55 | 56 | And then run: 57 | 58 | ``` 59 | cargo run --example browser_mock target/debug/pod-app 60 | ``` 61 | 62 | You can send all request-type messages to the `pod-app` using `browser_mock` app and observe its 63 | response. For instance: 64 | 65 | ``` 66 | > { "msg": "sign_challenge", "challenge": "deadbeef" } 67 | {"msg":"sign_challenge","signed":"NYPXlzY98WUawum6yFQdelyzVoxC5VdguSSJ022ZJYyFc1W0DmZjnXP6t5t/gVwnckigP5u44yKmi7bIimiRBw=="} 68 | ``` 69 | 70 | [native messaging]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#Closing_the_native_app 71 | 72 | ### `webservice_client` app 73 | 74 | For some end-to-end testing, you can use the provided simple test client which 75 | exposes two bits of functionality: registering and authenticating with the [`pod-server`] 76 | web service. 77 | 78 | The former takes a username and Service Provider's ID (SPID): 79 | 80 | ``` 81 | cargo run --example webservice_client -- register johndoe deadbeef123456 82 | ``` 83 | 84 | This command will initiate a POST request to `/register` entrypoint. 85 | 86 | The latter on the other hand takes only your username as an argument: 87 | 88 | ``` 89 | cargo run --example webservice_client -- authenticate johndoe 90 | ``` 91 | 92 | This command initiates 3 requests: a GET to `/auth` to obtain a challenge, 93 | a POST to `/auth` to validate the challenge and authenticate with the 94 | service, and finally a GET to `/` to verify that we've indeed successfully 95 | signed in. 96 | 97 | [`pod-server`]: https://github.com/golemfactory/proofofdevice/tree/master/pod-server 98 | [`pod-enclave`]: https://github.com/golemfactory/proofofdevice/tree/master/pod-enclave 99 | [native-messaging]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging 100 | -------------------------------------------------------------------------------- /pod-web/src/components/Login/index.js: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect, useState } from "react"; 2 | import AuthContext from "../../context/auth"; 3 | import useEventListener from "../../hooks/useEventListener"; 4 | import request from "../../utils/request"; 5 | import { CHALLENGE, HOST, REMOTE, ORIGIN } from "../../Constants"; 6 | import PodIndicator from "../PodIndicator"; 7 | 8 | import { click, form, login, motto } from "./login.module.css"; 9 | 10 | import clickAsset from "../../assets/click.svg"; 11 | 12 | const getById = (id) => document.getElementById(id); 13 | 14 | const Login = () => { 15 | const auth = useContext(AuthContext); 16 | const [signed, setSigned] = useState(null); 17 | const [errorStatus, setError] = useState(false); 18 | // const [loading, setLoading] = useState(false) for loading animation 19 | useEffect(() => { 20 | challengeRequest() 21 | .then(({ challenge }) => { 22 | if (!challenge) 23 | throw new Error( 24 | "Challenge cannot be empty.\nHint: Try removing cookies." 25 | ); 26 | window.postMessage( 27 | { host: HOST, type: CHALLENGE, data: challenge }, 28 | ORIGIN 29 | ); 30 | }) 31 | .catch((error) => { 32 | console.warn(error); 33 | alert(`Network Error: ${error.status}`); 34 | }); 35 | }, []); 36 | 37 | const messageListener = ({ data, origin }) => { 38 | if (origin !== ORIGIN || data.host !== REMOTE) return; 39 | console.log(data); // Answer 40 | setSigned(data.data); 41 | }; 42 | 43 | useEventListener("message", messageListener); 44 | 45 | const requestLogin = (event) => { 46 | event.preventDefault(); 47 | const login = getById("usernameInput").value; 48 | //const password = getById("passwordInput").value; 49 | authRequest({ login, signed_challenge: signed }) 50 | .then((result) => { 51 | console.log(result); 52 | if (result.status === "Ok") { 53 | auth.setLoggedIn(true); 54 | } else { 55 | setError(true); 56 | } 57 | }) 58 | .catch((error) => { 59 | console.warn(error); 60 | setError(true); 61 | }); 62 | }; 63 | 64 | return ( 65 | 66 | 67 | Possibilites. 68 | 69 | One Click Away 70 | 71 | 72 | 73 | 74 | Login 75 | {errorStatus ? Wrong credentials : null} 76 | 77 | 85 | 86 | 87 | 94 | 95 | 96 | Login 97 | 98 | 99 | 100 | 101 | 102 | ); 103 | }; 104 | 105 | export default Login; 106 | 107 | function challengeRequest() { 108 | return request("/auth", { 109 | method: "get", 110 | }); 111 | } 112 | 113 | function authRequest({ login, signed_challenge }) { 114 | return request("/auth", { 115 | method: "post", 116 | headers: { "Content-Type": "application/json" }, 117 | body: JSON.stringify({ 118 | login, 119 | response: signed_challenge, 120 | }), 121 | }); 122 | } 123 | -------------------------------------------------------------------------------- /pod-enclave/Makefile: -------------------------------------------------------------------------------- 1 | SGX_SDK ?= /opt/intel/sgxsdk 2 | SGX_SSL ?= /opt/intel/sgxssl 3 | SGX_SSL_INC ?= $(SGX_SSL)/include 4 | SGX_SSL_LIB ?= $(SGX_SSL)/lib64 5 | SGX_INC ?= $(SGX_SDK)/include 6 | SGX_LIB ?= $(SGX_SDK)/lib64 7 | ENCLAVE_CONFIG ?= pod_enclave.config.xml 8 | ENCLAVE_SIGNING_PUBLIC_KEY ?= pod_signing_pubkey.pem 9 | ENCLAVE_BINARY ?= pod_enclave.so 10 | ENCLAVE_BINARY_SIGNED ?= pod_enclave.signed.so 11 | 12 | ifeq ($(DEBUG), 1) 13 | CFLAGS += -O0 -g 14 | else 15 | CFLAGS += -O2 16 | endif 17 | 18 | SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r 19 | SGX_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign 20 | EDGER8R_FLAGS := --search-path $(SGX_INC) --search-path $(SGX_SSL_INC) 21 | MRSIGNER := pod_enclave.mrsigner 22 | MRSIGNER_H := pod_enclave_mrsigner.h 23 | 24 | .PHONY: all 25 | all: $(ENCLAVE_BINARY_SIGNED) 26 | 27 | .PHONY: check_key 28 | check_key: 29 | ifndef ENCLAVE_SIGNING_KEY 30 | $(error ENCLAVE_SIGNING_KEY not set) 31 | endif 32 | 33 | $(ENCLAVE_SIGNING_PUBLIC_KEY): check_key $(ENCLAVE_SIGNING_KEY) 34 | openssl rsa -in $(ENCLAVE_SIGNING_KEY) -pubout -out $(ENCLAVE_SIGNING_PUBLIC_KEY) 35 | 36 | # PoD enclave 37 | CFLAGS += -m64 \ 38 | -Wall \ 39 | -Wextra \ 40 | -D_GNU_SOURCE \ 41 | -nostdinc \ 42 | -fvisibility=hidden \ 43 | -fpie \ 44 | -fstack-protector \ 45 | -std=c99 \ 46 | -I$(SGX_INC) \ 47 | -I$(SGX_INC)/tlibc \ 48 | -I$(SGX_SSL_INC) 49 | 50 | LDFLAGS := -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles \ 51 | -L$(SGX_LIB) -L$(SGX_SSL_LIB) \ 52 | -Wl,--whole-archive -lsgx_tsgxssl -Wl,--no-whole-archive -lsgx_tsgxssl_crypto \ 53 | -Wl,--whole-archive -lsgx_trts -Wl,--no-whole-archive \ 54 | -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -lsgx_tcrypto -lsgx_tservice -Wl,--end-group \ 55 | -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ 56 | -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ 57 | -Wl,--defsym,__ImageBase=0 58 | 59 | $(ENCLAVE_BINARY_SIGNED): $(ENCLAVE_BINARY) $(ENCLAVE_SIGNING_KEY) $(ENCLAVE_SIGNING_PUBLIC_KEY) 60 | $(SGX_SIGNER) gendata -enclave $< -out $<.sigdata -config $(ENCLAVE_CONFIG) -ignore-init-sec-error 61 | # replace the command below to use HSM for signing operation 62 | openssl dgst -sha256 -out $<.sig -sign $(ENCLAVE_SIGNING_KEY) $<.sigdata 63 | $(SGX_SIGNER) catsig -enclave $< -sig $<.sig \ 64 | -unsigned $<.sigdata -key $(ENCLAVE_SIGNING_PUBLIC_KEY) -out $@ \ 65 | -config $(ENCLAVE_CONFIG) -ignore-init-sec-error 66 | $(SGX_SIGNER) dump -enclave $@ -dumpfile enclave.meta -ignore-init-sec-error 67 | 68 | $(MRSIGNER): $(ENCLAVE_SIGNING_PUBLIC_KEY) openssl_parse.awk 69 | openssl rsa -in $(ENCLAVE_SIGNING_PUBLIC_KEY) -pubin -text -noout \ 70 | | awk -f openssl_parse.awk | xxd -p -r | sha256sum -b \ 71 | | xxd -r -ps -l 32 > $@ 72 | 73 | # header with mrsigner value 74 | $(MRSIGNER_H): $(MRSIGNER) 75 | xxd -i -c 8 $(MRSIGNER) > $@ 76 | 77 | $(ENCLAVE_BINARY): pod_enclave_t.o pod_enclave.o 78 | $(CC) $^ $(LDFLAGS) -o $@ 79 | 80 | pod_enclave.o: pod_enclave.c $(MRSIGNER_H) pod_enclave_u.c 81 | $(CC) $(CFLAGS) -c $< -o $@ 82 | 83 | pod_enclave_t.o: pod_enclave_t.c 84 | $(CC) $(CFLAGS) -c $< -o $@ 85 | 86 | # ECALL/OCALL interface (generated files) 87 | pod_enclave_t.c: pod_enclave.edl 88 | $(SGX_EDGER8R) $(EDGER8R_FLAGS) --trusted $< 89 | 90 | pod_enclave_u.c: pod_enclave.edl 91 | $(SGX_EDGER8R) $(EDGER8R_FLAGS) --untrusted $< 92 | 93 | .PHONY: install 94 | install: ; 95 | 96 | .PHONY: clean 97 | clean: 98 | $(RM) *.o *.so 99 | $(RM) pod_enclave_t.c pod_enclave_t.h pod_enclave_u.c pod_enclave_u.h 100 | $(RM) *.meta *.mrsigner *_mrsigner.h *.sig *.sigdata $(ENCLAVE_SIGNING_PUBLIC_KEY) 101 | -------------------------------------------------------------------------------- /pod-server/README.md: -------------------------------------------------------------------------------- 1 | # `pod-server` 2 | 3 | A simple implementation of a web service facilitating the Proof-of-device 4 | at the service provider's end. 5 | 6 | ## Basic usage 7 | 8 | The minimal config file to run the server consists of the IAS valid API key, 9 | and 32-byte long private key for signing cookies: 10 | 11 | ```toml 12 | api_key = "0123456abcdef" 13 | cookie_key = "0123456abcdef" 14 | ``` 15 | 16 | By default, the server binds itself to `127.0.0.1:8080` address. You can tweak 17 | it by appending a `[server]` section to the config file: 18 | 19 | ```toml 20 | api_key = "0123456abcdef" 21 | cookie_key = "0123456abcdef" 22 | 23 | [server] 24 | address = "127.0.0.1" 25 | port = 8080 26 | ``` 27 | 28 | The server uses [`diesel`] crate as the ORM and SQLite as the database. In order 29 | to configure the database for use with the app, firstly, you need to specify the 30 | path to the database file in `.env` file: 31 | 32 | ``` 33 | DATABASE_URL=mock.db 34 | ``` 35 | 36 | Secondly, before actually firing up the server for the first time, you need to 37 | init the db: 38 | 39 | ``` 40 | diesel setup 41 | ``` 42 | 43 | Then, and this step should occur whenver you want to redo the tables, re-run 44 | the migrations: 45 | 46 | ``` 47 | diesel migration run 48 | ``` 49 | 50 | Finally, when invoking the server from the command line, you are required to 51 | specify the path to the config file: 52 | 53 | ``` 54 | cargo run -- config.toml -v 55 | ``` 56 | 57 | ## RESTful API 58 | 59 | The service strives to communicate with JSON only, and the message will have a 60 | general structure like below: 61 | 62 | ```json 63 | { 64 | "status": "ok", 65 | "description": "some message" 66 | } 67 | ``` 68 | 69 | `status` assumes either `ok`, or `error`, and details are encapsulated within 70 | the `description` field. 71 | 72 | ### Available entrypoints: 73 | 74 | * GET `/` -- dummy route which will respond with `203` if user successfully 75 | authenticated, or a `403` with description of the error encoded as JSON. 76 | 77 | 78 | * POST `/register` -- route required to register a new user with the service. The 79 | expected content body is a JSON containing at least two fields: `login` and 80 | `quote`. 81 | 82 | Example request content: 83 | 84 | ```json 85 | { 86 | "login": "johndoe", 87 | "quote": "AAAAA...AAA", 88 | "nonce": "AAAAA" 89 | } 90 | ``` 91 | 92 | Nonce is optional, however both quote and nonce should be base64 encoded. 93 | 94 | Upon successful registration, a `200` message will be generated. 95 | 96 | * GET `/auth` -- route required to initiate challenge-response protocol in order 97 | to authenticate the registered user using their SGX enclave (which holds a 98 | private ED25519 key). The challenge which the user is required to signed using 99 | their enclave will be provided inside content as JSON inside `challenge` field. 100 | The challenge will be base64 encoded. 101 | 102 | Example response content: 103 | 104 | ```json 105 | { 106 | "status": "ok", 107 | "description": "challenge successfully generated", 108 | "challenge": "AAAA...AAA" 109 | } 110 | ``` 111 | 112 | * POST `/auth` -- route where the signed `challenge` should be sent to. The signed 113 | challenge should be sent inside JSON under `response` field, and should be base64 114 | encoded. Additinally, the user should supply their login as part of the JSON. 115 | 116 | Example request content: 117 | 118 | ```json 119 | { 120 | "login": "johndoe", 121 | "response": "AAAA...AAA" 122 | } 123 | ``` 124 | -------------------------------------------------------------------------------- /pod-server/src/main.rs: -------------------------------------------------------------------------------- 1 | mod handlers; 2 | mod models; 3 | mod schema; 4 | 5 | #[macro_use] 6 | extern crate diesel; 7 | 8 | use actix_identity::{CookieIdentityPolicy, IdentityService}; 9 | use actix_session::CookieSession; 10 | use actix_web::{middleware, web, App, HttpServer}; 11 | use anyhow::anyhow; 12 | use diesel::r2d2::{ConnectionManager, Pool}; 13 | use diesel::SqliteConnection; 14 | use dotenv::dotenv; 15 | use serde::Deserialize; 16 | use std::path::PathBuf; 17 | use std::time::{SystemTime, UNIX_EPOCH}; 18 | use std::{env, fs}; 19 | use structopt::StructOpt; 20 | 21 | #[derive(StructOpt)] 22 | #[structopt(name = "pod_server", version = env!("CARGO_PKG_VERSION"))] 23 | struct Opt { 24 | /// Path to server config TOML file. 25 | #[structopt(parse(from_os_str))] 26 | config_path: PathBuf, 27 | /// Set verbose mode on/off. 28 | #[structopt(short, long)] 29 | verbose: bool, 30 | } 31 | 32 | #[derive(Deserialize)] 33 | struct ServerConfig { 34 | api_key: String, 35 | cookie_key: String, 36 | #[serde(rename = "server")] 37 | bind: Option, 38 | } 39 | 40 | #[derive(Deserialize)] 41 | struct BindAddress { 42 | address: String, 43 | port: u16, 44 | } 45 | 46 | pub struct AppData { 47 | pool: Pool>, 48 | } 49 | 50 | #[actix_rt::main] 51 | async fn main() -> anyhow::Result<()> { 52 | let opt = Opt::from_args(); 53 | dotenv()?; 54 | // Enable info logging by default. 55 | let level = if opt.verbose { 56 | rust_sgx_util::set_verbose(true); 57 | log::LevelFilter::Debug 58 | } else { 59 | log::LevelFilter::Info 60 | }; 61 | let now = SystemTime::now().duration_since(UNIX_EPOCH)?; 62 | let log_output = fs::File::create(format!("pod-server_{}.log", now.as_secs_f64()))?; 63 | simplelog::WriteLogger::init(level, simplelog::Config::default(), log_output)?; 64 | // Read config file 65 | let config_file = fs::read(&opt.config_path)?; 66 | let config: ServerConfig = toml::from_slice(&config_file)?; 67 | let (address, port) = match &config.bind { 68 | Some(server_config) => (server_config.address.clone(), server_config.port), 69 | None => ("127.0.0.1".to_string(), 8080), 70 | }; 71 | let address_port = [address, port.to_string()].join(":"); 72 | // Set POD_SERVER_API_KEY env variable 73 | env::set_var("POD_SERVER_API_KEY", config.api_key); 74 | 75 | let db_url = env::var("DATABASE_URL")?; 76 | let manager = ConnectionManager::::new(db_url); 77 | let pool = Pool::builder().build(manager)?; 78 | let data = web::Data::new(AppData { pool }); 79 | // Cookie config 80 | let cookie_key = config.cookie_key.clone(); 81 | 82 | HttpServer::new(move || { 83 | App::new() 84 | .wrap( 85 | CookieSession::signed(cookie_key.as_bytes()) 86 | .name("session") 87 | .http_only(false) 88 | .secure(false), 89 | ) 90 | .wrap(IdentityService::new( 91 | CookieIdentityPolicy::new(cookie_key.as_bytes()) 92 | .name("auth") 93 | .secure(false), 94 | )) 95 | .wrap(middleware::Logger::default()) 96 | .app_data(data.clone()) 97 | .route("/", web::get().to(handlers::index)) 98 | .route("/register", web::post().to(handlers::register::post)) 99 | .service( 100 | web::resource("/auth") 101 | .route(web::get().to(handlers::auth::get)) 102 | .route(web::post().to(handlers::auth::post)), 103 | ) 104 | }) 105 | .bind(address_port)? 106 | .run() 107 | .await 108 | .map_err(|err| anyhow!("HttpServer errored out with {:?}", err))?; 109 | 110 | Ok(()) 111 | } 112 | -------------------------------------------------------------------------------- /lib/c-api/pod_sgx.h: -------------------------------------------------------------------------------- 1 | #ifndef POD_SGX_H 2 | #define POD_SGX_H 3 | 4 | /** Enables enclave debugging and NULLIFIES ENCLAVE MEMORY PROTECTION. */ 5 | #define ENCLAVE_DEBUG_ENABLED 1 6 | 7 | /*! 8 | * \brief Get size of an open file. 9 | * 10 | * \param[in] fd Open file descriptor. 11 | * 12 | * \return File size or -1 on error. 13 | */ 14 | ssize_t get_file_size(int fd); 15 | 16 | /*! 17 | * \brief Read file contents to buffer. 18 | * 19 | * \param[in] buffer Buffer to read data to. If NULL, this function allocates one. 20 | * \param[in] path Path to the file. 21 | * \param[in,out] size On entry, number of bytes to read. 0 means to read the entire file. 22 | * On exit, number of bytes read. 23 | * 24 | * \return On success, pointer to the data buffer. If \p buffer was NULL, caller should free this. 25 | * On failure, NULL. 26 | */ 27 | void* read_file(void* buffer, const char* path, size_t* size); 28 | 29 | /*! 30 | * \brief Write buffer to file. 31 | * 32 | * \param[in] path File path. 33 | * \param[in] size \p buffer size. 34 | * \param[in] buffer Buffer to write data from. 35 | * 36 | * \return 0 on success, errno on error. 37 | */ 38 | int write_file(const char* path, size_t size, const void* buffer); 39 | 40 | /*! 41 | * \brief Initialize PoD enclave. 42 | * Loads enclave, generates new enclave key pair, and seals the private key into the provided 43 | * buffer. 44 | * 45 | * \param[in] enclave_path Path to enclave binary. 46 | * \param[in] sealed_state Buffer to seal the private key to. 47 | * \param[in] sealed_state_size Size of the provided buffer. 48 | * 49 | * \return On success, number of bytes written to the buffer. On failure, negative value. 50 | */ 51 | int pod_init_enclave(const char* enclave_path, uint8_t* sealed_state, size_t sealed_state_size); 52 | 53 | /*! 54 | * \brief Load PoD enclave and restore its private key from sealed state. 55 | * 56 | * \param[in] enclave_path Path to enclave binary. 57 | * \param[in] sealed_state_path Path to sealed enclave state. 58 | * 59 | * \return 0 on success, negative on error. 60 | */ 61 | int pod_load_enclave(const char* enclave_path, const uint8_t* sealed_state, size_t sealed_state_size); 62 | 63 | /*! 64 | * \brief Unload PoD enclave. 65 | * 66 | * \return 0 on success, negative on error. 67 | */ 68 | int pod_unload_enclave(void); 69 | 70 | /*! 71 | * \brief Generate valid quote of this PoD enclave for remote attestation with IAS services. 72 | * 73 | * \param[in] sp_id_str Service Provider ID (hex string). 74 | * \param[in] sp_quote_type_str Quote type as string ("linkable"/"unlinkable"). 75 | * \param[in] quote_buffer Buffer to save the quote to. 76 | * \param[in] quote_buffer_size Size of the provided buffer. 77 | * 78 | * \return On success, number of bytes written to the buffer. On failure, negative value. 79 | */ 80 | int pod_get_quote(const char* sp_id_str, const char* sp_quote_type_str, uint8_t* quote_buffer, 81 | size_t quote_buffer_size); 82 | 83 | /*! 84 | * \brief Create PoD enclave digital signature for data buffer. 85 | * 86 | * \param[in] data Buffer with data to sign. 87 | * \param[in] data_size Size of \p data in bytes. 88 | * \param[out] signature Buffer that will receive the signature. 89 | * \param[in] signature_size Size of \p signature in bytes. 90 | * 91 | * \return 0 on success, negative on error. 92 | */ 93 | int pod_sign_buffer(const void* data, size_t data_size, void* signature, size_t signature_size); 94 | 95 | /*! 96 | * \brief Create PoD enclave digital signature for a file. 97 | * 98 | * \param[in] input_path Path to file to sign. 99 | * \param[in] signature_path Path where the signature will be saved. 100 | * 101 | * \return 0 on success, negative on error. 102 | */ 103 | int pod_sign_file(const char* input_path, const char* signature_path); 104 | 105 | #endif /* POD_SGX_H */ 106 | -------------------------------------------------------------------------------- /lib/api/src/wrappers.rs: -------------------------------------------------------------------------------- 1 | use super::{c, QuoteType}; 2 | use anyhow::{anyhow, Result}; 3 | use rust_sgx_util::Quote; 4 | use std::convert::TryFrom; 5 | use std::ffi::CString; 6 | use std::path::Path; 7 | 8 | const MAX_SEALED_KEYS_SIZE: usize = 1024; // Should be plenty for ed25519 private key 9 | const MAX_QUOTE_SIZE: usize = 2048; // Usually around 1200 bytes required 10 | const EC_SIGNATURE: usize = 64; // EC signature should always be 64bytes long! 11 | 12 | pub fn set_verbose(verbose: bool) { 13 | unsafe { c::set_verbose(verbose) } 14 | } 15 | 16 | pub(super) fn init_enclave>(enclave_path: P) -> Result> { 17 | let enclave_path = path_to_c_string(enclave_path)?; 18 | let sealed_keys_buffer = &mut [0u8; MAX_SEALED_KEYS_SIZE]; 19 | let ret = unsafe { 20 | c::pod_init_enclave( 21 | enclave_path.as_ptr(), 22 | sealed_keys_buffer.as_mut_ptr(), 23 | sealed_keys_buffer.len(), 24 | ) 25 | }; 26 | 27 | if ret < 0 { 28 | return Err(anyhow!( 29 | "pod_init_enclave returned non-zero exit code: {}", 30 | ret 31 | )); 32 | } 33 | 34 | let sealed_keys_size = usize::try_from(ret)?; 35 | Ok(Vec::from(&sealed_keys_buffer[..sealed_keys_size])) 36 | } 37 | 38 | pub(super) fn load_enclave, B: AsRef<[u8]>>( 39 | enclave_path: P, 40 | sealed_keys: B, 41 | ) -> Result<()> { 42 | let enclave_path = path_to_c_string(enclave_path)?; 43 | let sealed_keys = sealed_keys.as_ref(); 44 | let ret = unsafe { 45 | c::pod_load_enclave( 46 | enclave_path.as_ptr(), 47 | sealed_keys.as_ptr(), 48 | sealed_keys.len(), 49 | ) 50 | }; 51 | if ret < 0 { 52 | Err(anyhow!( 53 | "pod_load_enclave returned non-zero exit code: {}", 54 | ret 55 | )) 56 | } else { 57 | Ok(()) 58 | } 59 | } 60 | 61 | pub(super) fn unload_enclave() -> Result<()> { 62 | let ret = unsafe { c::pod_unload_enclave() }; 63 | if ret != 0 { 64 | Err(anyhow!( 65 | "pod_unload_enclave returned non-zero exit code: {}", 66 | ret 67 | )) 68 | } else { 69 | Ok(()) 70 | } 71 | } 72 | 73 | pub(super) fn get_quote>(spid: S, quote_type: QuoteType) -> Result { 74 | let spid = CString::new(spid.as_ref())?; 75 | let quote_type = match quote_type { 76 | QuoteType::Linkable => CString::new("l")?, 77 | QuoteType::Unlinkable => CString::new("u")?, 78 | }; 79 | let quote_buffer = &mut [0u8; MAX_QUOTE_SIZE]; 80 | let ret = unsafe { 81 | c::pod_get_quote( 82 | spid.as_ptr(), 83 | quote_type.as_ptr(), 84 | quote_buffer.as_mut_ptr(), 85 | MAX_QUOTE_SIZE, 86 | ) 87 | }; 88 | 89 | if ret < 0 { 90 | return Err(anyhow!( 91 | "pod_init_enclave returned non-zero exit code: {}", 92 | ret 93 | )); 94 | } 95 | let quote_size = usize::try_from(ret)?; 96 | Ok(Quote::from("e_buffer[..quote_size])) 97 | } 98 | 99 | pub(super) fn sign_buffer>(message: B) -> Result> { 100 | let message = message.as_ref(); 101 | let signature = &mut [0u8; EC_SIGNATURE]; 102 | let ret = unsafe { 103 | c::pod_sign_buffer( 104 | message.as_ptr() as *const _, 105 | message.len(), 106 | signature.as_mut_ptr() as *mut _, 107 | signature.len(), 108 | ) 109 | }; 110 | if ret != 0 { 111 | return Err(anyhow!( 112 | "pod_sign_buffer returned non-zero exit code: {}", 113 | ret 114 | )); 115 | } 116 | Ok(signature.to_vec()) 117 | } 118 | 119 | #[cfg(unix)] 120 | fn path_to_c_string>(path: P) -> Result { 121 | use std::os::unix::ffi::OsStrExt; 122 | let s = CString::new(path.as_ref().as_os_str().as_bytes())?; 123 | Ok(s) 124 | } 125 | 126 | #[cfg(windows)] 127 | fn path_to_c_string(path: &Path) -> Result { 128 | use std::os::windows::ffi::OsStringExt; 129 | let utf16: Vec<_> = path.as_os_str().encode_wide().collect(); 130 | let s = String::from_utf16(utf16)?; 131 | let s = CString::new(s.as_bytes())?; 132 | Ok(s) 133 | } 134 | -------------------------------------------------------------------------------- /pod-server/src/handlers/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod auth; 2 | pub mod register; 3 | 4 | use actix_identity::Identity; 5 | use actix_web::dev::HttpResponseBuilder; 6 | use actix_web::http::StatusCode; 7 | use actix_web::{HttpResponse, Responder, ResponseError}; 8 | use serde::Serialize; 9 | use std::collections::HashMap; 10 | 11 | pub async fn index(identity: Identity) -> impl Responder { 12 | match identity.identity() { 13 | Some(_) => Ok(HttpResponse::NoContent()), 14 | None => Err(AppError::NotAuthenticated), 15 | } 16 | } 17 | 18 | #[derive(Serialize)] 19 | enum Status { 20 | Ok, 21 | Error, 22 | } 23 | 24 | #[derive(Serialize)] 25 | struct Message { 26 | status: Status, 27 | #[serde(flatten)] 28 | params: HashMap, 29 | } 30 | 31 | impl Message { 32 | fn ok() -> Self { 33 | Self { 34 | status: Status::Ok, 35 | params: HashMap::new(), 36 | } 37 | } 38 | 39 | fn error() -> Self { 40 | Self { 41 | status: Status::Error, 42 | params: HashMap::new(), 43 | } 44 | } 45 | 46 | fn add_param, S2: AsRef>(mut self, key: S1, value: S2) -> Self { 47 | self.params 48 | .insert(key.as_ref().to_owned(), value.as_ref().to_owned()); 49 | self 50 | } 51 | } 52 | 53 | #[derive(Debug, thiserror::Error)] 54 | enum AppError { 55 | #[error("user not registered yet")] 56 | NotRegistered, 57 | #[error("user already registered")] 58 | AlreadyRegistered, 59 | #[error("invalid challenge")] 60 | InvalidChallenge, 61 | #[error("invalid cookie")] 62 | InvalidCookie, 63 | #[error("user not authenticated")] 64 | NotAuthenticated, 65 | #[error("user already authenticated")] 66 | AlreadyAuthenticated, 67 | #[error("tokio_diesel async op failed with error: {}", _0)] 68 | TokioDieselAsync(#[from] tokio_diesel::AsyncError), 69 | #[error("attesting quote failed with error: {}", _0)] 70 | RustSgxUtil(#[from] rust_sgx_util::Error), 71 | #[error("r2d2 pool error: {}", _0)] 72 | R2d2Pool(#[from] diesel::r2d2::PoolError), 73 | #[error("diesel result error {}", _0)] 74 | DieselResult(#[from] diesel::result::Error), 75 | #[error("var not found in env: {}", _0)] 76 | Var(#[from] std::env::VarError), 77 | #[error("blocking operation was canceled prematurely")] 78 | ActixBlockingCanceled, 79 | #[error("decoding base64 to blob: {}", _0)] 80 | Base64Decode(#[from] base64::DecodeError), 81 | #[error("parsing ed25519 signature: {}", _0)] 82 | Ed25519Signature(#[from] ed25519_dalek::SignatureError), 83 | #[error("fetching entropy: {}", _0)] 84 | GetRandom(#[from] getrandom::Error), 85 | } 86 | 87 | impl ResponseError for AppError { 88 | fn error_response(&self) -> HttpResponse { 89 | let (code, message) = match self { 90 | AppError::NotRegistered => (StatusCode::FORBIDDEN, Message::error()), 91 | AppError::AlreadyRegistered => (StatusCode::OK, Message::ok()), 92 | AppError::InvalidChallenge => (StatusCode::OK, Message::error()), 93 | AppError::InvalidCookie => (StatusCode::OK, Message::error()), 94 | AppError::NotAuthenticated => (StatusCode::FORBIDDEN, Message::error()), 95 | AppError::AlreadyAuthenticated => (StatusCode::OK, Message::ok()), 96 | AppError::TokioDieselAsync(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 97 | AppError::RustSgxUtil(_) => (StatusCode::OK, Message::error()), 98 | AppError::R2d2Pool(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 99 | AppError::DieselResult(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 100 | AppError::Var(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 101 | AppError::ActixBlockingCanceled => { 102 | (StatusCode::INTERNAL_SERVER_ERROR, Message::error()) 103 | } 104 | AppError::Base64Decode(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 105 | AppError::Ed25519Signature(_) => (StatusCode::OK, Message::error()), 106 | AppError::GetRandom(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 107 | }; 108 | HttpResponseBuilder::new(code).json(message.add_param("description", format!("{}", self))) 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /pod-web/src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' }, 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready 134 | .then(registration => { 135 | registration.unregister(); 136 | }) 137 | .catch(error => { 138 | console.error(error.message); 139 | }); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /lib/rust-sgx-util/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! A safe wrapper around Graphene's [`sgx_util`] C-library. 2 | //! 3 | //! [`sgx_util`]: https://github.com/oscarlab/graphene/tree/master/Pal/src/host/Linux-SGX/tools 4 | //! 5 | //! ```toml 6 | //! rust-sgx-util = "0.2" 7 | //! ``` 8 | //! 9 | //! For `serde` support, you can enable it with `with_serde` feature: 10 | //! 11 | //! ```toml 12 | //! rust-sgx-util = { version = "0.2", features = ["with_serde"] } 13 | //! ``` 14 | //! 15 | //! ## Prerequisites 16 | //! 17 | //! Currently, this crate requires you compile and install `sgx_util` as 18 | //! a shared library. 19 | //! 20 | //! ## Usage examples 21 | //! 22 | //! You can find usage examples in the `examples` dir of the crate. 23 | //! 24 | mod c; 25 | mod ias; 26 | #[cfg(feature = "with_serde")] 27 | mod ser_de; 28 | 29 | pub use ias::*; 30 | 31 | #[cfg(feature = "with_serde")] 32 | use serde::{Deserialize, Serialize}; 33 | use std::convert::TryFrom; 34 | use std::ops::Deref; 35 | 36 | /// Convenience wrapper around fallible operation. 37 | pub type Result = std::result::Result; 38 | 39 | /// Error type thrown by fallible operations in this crate. 40 | #[derive(Debug, thiserror::Error)] 41 | pub enum Error { 42 | /// Failed to initialize `IasHandle`. 43 | #[error("failed to initialize IasHandle")] 44 | IasInitNullPtr, 45 | /// `Quote`'s size is too small. 46 | #[error("quote's size is too small")] 47 | QuoteTooShort, 48 | /// `Nonce` exceeded 32 bytes. 49 | #[error("nonce exceeded 32 bytes")] 50 | NonceTooLong, 51 | /// `IasHandle::get_sigrl` returned nonzero return code. 52 | #[error("get_sigrl returned nonzero return code: {}", _0)] 53 | IasGetSigrlNonZero(i32), 54 | /// `IasHandle::verify_quote` returned nonzero return code. 55 | #[error("verify_quote returned nonzero return code: {}", _0)] 56 | IasVerifyQuoteNonZero(i32), 57 | /// Error while parsing int from string. 58 | #[error("parsing int from string: {:?}", _0)] 59 | ParseInt(#[from] std::num::ParseIntError), 60 | /// Found unexpected interior nul byte. 61 | #[error("unexpected interior nul byte: {:?}", _0)] 62 | Nul(#[from] std::ffi::NulError), 63 | /// (Windows only) Encountered invalid UTF16. 64 | #[error("invalid UTF16 encountered: {:?}", _0)] 65 | Utf16(#[from] std::string::FromUtf16Error), 66 | } 67 | 68 | /// Set verbosity on/off. 69 | pub fn set_verbose(verbose: bool) { 70 | unsafe { c::set_verbose(verbose) } 71 | } 72 | 73 | /// A thin wrapper around vector of bytes. Represents quote obtained 74 | /// from the challenged enclave. 75 | /// 76 | /// # Accessing the underlying bytes buffer 77 | /// 78 | /// `Quote` implements `Deref`, therefore dereferencing it will 79 | /// yield its inner buffer of bytes. 80 | /// 81 | /// # Serializing/deserializing 82 | /// 83 | /// With `with_serde` feature enabled, `Quote` can be serialized and deserialized 84 | /// as base64 `String`. 85 | #[derive(Debug, Clone)] 86 | #[cfg_attr(feature = "with_serde", derive(Serialize, Deserialize))] 87 | pub struct Quote(#[cfg_attr(feature = "with_serde", serde(with = "ser_de"))] Vec); 88 | 89 | impl Quote { 90 | const REPORT_BEGIN: usize = 368; 91 | const REPORT_END: usize = 432; 92 | 93 | /// Returns `report_data` bytes embedded within this `Quote`. 94 | /// 95 | /// The size of the returned slice is 64 bytes. 96 | /// 97 | /// # Errors 98 | /// 99 | /// This function will fail with [`Error::QuoteTooShort`] if `Quote` 100 | /// is shorter than `432` bytes. Note that this is only a quick check 101 | /// that we can extract the region in `Quote`'s buffer where we expect 102 | /// the `report_data` to lie in. We don't do any validations on the 103 | /// `Quote` in this method. 104 | /// 105 | /// [`Error::QuoteTooShort`]: enum.Error.html#variant.QuoteTooShort 106 | /// 107 | /// # Examples 108 | /// 109 | /// ``` 110 | /// # use rust_sgx_util::Quote; 111 | /// let quote = Quote::from(&[0u8; 438][..]); 112 | /// assert_eq!(quote.report_data().unwrap().len(), 64); 113 | /// 114 | /// let quote = Quote::from(&[0u8; 10][..]); 115 | /// assert!(quote.report_data().is_err()); 116 | /// ``` 117 | pub fn report_data(&self) -> Result<&[u8]> { 118 | self.0 119 | .get(Self::REPORT_BEGIN..Self::REPORT_END) 120 | .ok_or(Error::QuoteTooShort) 121 | } 122 | } 123 | 124 | impl From<&[u8]> for Quote { 125 | fn from(bytes: &[u8]) -> Self { 126 | Self::from(bytes.to_vec()) 127 | } 128 | } 129 | 130 | impl From> for Quote { 131 | fn from(bytes: Vec) -> Self { 132 | Self(bytes) 133 | } 134 | } 135 | 136 | impl Deref for Quote { 137 | type Target = [u8]; 138 | 139 | fn deref(&self) -> &Self::Target { 140 | &self.0 141 | } 142 | } 143 | 144 | /// A thin wrapper around vector of bytes. Represents nonce obtained 145 | /// from the challenged enclave. 146 | /// 147 | /// Nonce cannot be longer than 32 bytes. 148 | /// 149 | /// # Accessing the underlying bytes buffer 150 | /// 151 | /// `Nonce` implements `Deref`, therefore dereferencing it will 152 | /// yield its inner buffer of bytes. 153 | /// 154 | /// # Serializing/deserializing 155 | /// 156 | /// With `with_serde` feature enabled, `Nonce` can be serialized and deserialized 157 | /// as base64 `String`. 158 | #[derive(Debug, Clone)] 159 | #[cfg_attr(feature = "with_serde", derive(Serialize, Deserialize))] 160 | pub struct Nonce(#[cfg_attr(feature = "with_serde", serde(with = "ser_de"))] Vec); 161 | 162 | impl Nonce { 163 | fn new>>(bytes: B) -> Result { 164 | let bytes = bytes.into(); 165 | if bytes.len() > 32 { 166 | return Err(Error::NonceTooLong); 167 | } 168 | Ok(Self(bytes)) 169 | } 170 | } 171 | 172 | impl TryFrom<&[u8]> for Nonce { 173 | type Error = Error; 174 | 175 | fn try_from(bytes: &[u8]) -> Result { 176 | Self::new(bytes) 177 | } 178 | } 179 | 180 | impl Deref for Nonce { 181 | type Target = [u8]; 182 | 183 | fn deref(&self) -> &Self::Target { 184 | &self.0 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /pod-app/examples/webservice_client.rs: -------------------------------------------------------------------------------- 1 | use actix_web::client::Client; 2 | use actix_web::HttpMessage; 3 | use anyhow::anyhow; 4 | use pod_api::{PodEnclave, QuoteType}; 5 | use rust_sgx_util::Quote; 6 | use serde::Serialize; 7 | use structopt::StructOpt; 8 | 9 | const SEALED_KEYS_PATH: &str = "pod_data.sealed"; 10 | const ENCLAVE_PATH: &str = "../pod-enclave/pod_enclave.signed.so"; 11 | 12 | #[derive(Debug, StructOpt)] 13 | struct Opt { 14 | /// Server address to connect to (defaults to 127.0.0.1). 15 | #[structopt(long)] 16 | address: Option, 17 | /// Server port to connect to (defaults to 8080). 18 | #[structopt(long)] 19 | port: Option, 20 | #[structopt(subcommand)] 21 | cmd: Command, 22 | } 23 | 24 | #[derive(Debug, StructOpt)] 25 | enum Command { 26 | /// Register with the service. 27 | Register { 28 | /// Your username. 29 | login: String, 30 | /// Service Provider's ID (SPID) as given by the SP. 31 | spid: String, 32 | }, 33 | /// Authenticate with the service. 34 | Authenticate { 35 | /// Your username. 36 | login: String, 37 | }, 38 | } 39 | 40 | #[derive(Serialize)] 41 | struct RegisterInfo { 42 | login: String, 43 | quote: Quote, 44 | } 45 | 46 | #[derive(Serialize)] 47 | struct ChallengeResponse { 48 | login: String, 49 | response: String, 50 | } 51 | 52 | #[actix_rt::main] 53 | async fn main() -> anyhow::Result<()> { 54 | let opt = Opt::from_args(); 55 | // Turn on enclave logging 56 | pod_api::set_verbose(true); 57 | 58 | let address = opt.address.unwrap_or_else(|| "127.0.0.1".to_owned()); 59 | let port = opt.port.unwrap_or(8080); 60 | let base_uri = format!("http://{}:{}", address, port); 61 | let client = Client::default(); 62 | let pod_enclave = PodEnclave::new(ENCLAVE_PATH, SEALED_KEYS_PATH)?; 63 | 64 | match opt.cmd { 65 | Command::Register { login, spid } => { 66 | // Get the quote 67 | let quote = pod_enclave.get_quote(&spid, QuoteType::Unlinkable)?; 68 | 69 | println!("POST /register"); 70 | let mut response = client 71 | .post(format!("{}/register", base_uri)) 72 | .header("User-Agent", "TestClient") 73 | .send_json(&RegisterInfo { 74 | login: login.clone(), 75 | quote, 76 | }) 77 | .await 78 | .map_err(|err| anyhow!("{:?}", err))?; 79 | println!(" | status_code: {}", response.status()); 80 | let body = response.body().await.map_err(|err| anyhow!("{:?}", err))?; 81 | let content_length = body.len(); 82 | println!(" | content-length: {}", content_length); 83 | 84 | if content_length > 0 { 85 | let json: serde_json::Value = serde_json::from_slice(&body)?; 86 | println!(" | body: {}", json); 87 | } 88 | } 89 | Command::Authenticate { login } => { 90 | println!("GET /auth"); 91 | let mut response = client 92 | .get(format!("{}/auth", base_uri)) 93 | .header("User-Agent", "TestClient") 94 | .send() 95 | .await 96 | .map_err(|err| anyhow!("{:?}", err))?; 97 | let status_code = response.status(); 98 | println!(" | status_code: {}", status_code); 99 | let body = response.body().await.map_err(|err| anyhow!("{:?}", err))?; 100 | let content_length = body.len(); 101 | println!(" | content-length: {}", content_length); 102 | let cookies = response.cookies()?.clone(); 103 | for cookie in &cookies { 104 | println!(" | cookie: {}", cookie); 105 | } 106 | if status_code != 200 { 107 | return Err(anyhow!("Expected GET /auth to return 200")); 108 | } 109 | let json: serde_json::Value = serde_json::from_slice(&body)?; 110 | println!(" | body: {}", json); 111 | 112 | // Process challenge 113 | let challenge = json["challenge"] 114 | .as_str() 115 | .ok_or(anyhow!("invalid String for challenge"))?; 116 | let challenge = base64::decode(challenge)?; 117 | let response = pod_enclave.sign(&challenge)?; 118 | let response = base64::encode(&response[..]); 119 | 120 | println!("\nPOST /auth"); 121 | let mut builder = client 122 | .post(format!("{}/auth", base_uri)) 123 | .header("User-Agent", "TestClient"); 124 | for cookie in cookies { 125 | builder = builder.cookie(cookie); 126 | } 127 | let mut response = builder 128 | .send_json(&ChallengeResponse { login, response }) 129 | .await 130 | .map_err(|err| anyhow!("{:?}", err))?; 131 | println!(" | status_code: {}", response.status()); 132 | let body = response.body().await.map_err(|err| anyhow!("{:?}", err))?; 133 | let content_length = body.len(); 134 | println!(" | content-length: {}", content_length); 135 | let cookies = response.cookies()?.clone(); 136 | for cookie in &cookies { 137 | println!(" | cookie: {}", cookie); 138 | } 139 | 140 | if content_length > 0 { 141 | let json: serde_json::Value = serde_json::from_slice(&body)?; 142 | println!(" | body: {}", json); 143 | } 144 | 145 | println!("\n GET /"); 146 | let mut builder = client.get(&base_uri).header("User-Agent", "TestClient"); 147 | for cookie in cookies { 148 | builder = builder.cookie(cookie); 149 | } 150 | let mut response = builder.send().await.map_err(|err| anyhow!("{:?}", err))?; 151 | println!(" | status_code: {}", response.status()); 152 | let body = response.body().await.map_err(|err| anyhow!("{:?}", err))?; 153 | let content_length = body.len(); 154 | println!(" | content-length: {}", content_length); 155 | let json: serde_json::Value = serde_json::from_slice(&body)?; 156 | println!(" | body: {}", json); 157 | } 158 | } 159 | 160 | Ok(()) 161 | } 162 | -------------------------------------------------------------------------------- /pod-web/src/assets/pod-enabled.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pod-app/src/main.rs: -------------------------------------------------------------------------------- 1 | mod messages; 2 | 3 | use anyhow::{anyhow, Context, Result}; 4 | use messages::reply; 5 | use nix::sys::signal::{self, SigHandler, Signal}; 6 | use serde::Deserialize; 7 | use std::convert::{TryFrom, TryInto}; 8 | use std::io::{self, Read, Write}; 9 | use std::path::PathBuf; 10 | use std::sync::atomic::{AtomicBool, Ordering}; 11 | use std::time::{SystemTime, UNIX_EPOCH}; 12 | use std::{fs, process}; 13 | 14 | const DEFAULT_PRIVATE_KEY_PATH: &str = "private_key.sealed"; 15 | const DEFAULT_ENCLAVE_PATH: &str = "../pod-enclave/pod_enclave.signed.so"; 16 | 17 | static SIGNALED: AtomicBool = AtomicBool::new(false); 18 | 19 | extern "C" fn handle_signals(signal: libc::c_int) { 20 | let signal = Signal::try_from(signal).expect("valid raw signal value"); 21 | SIGNALED.store( 22 | signal == Signal::SIGINT || signal == Signal::SIGTERM, 23 | Ordering::Relaxed, 24 | ); 25 | } 26 | 27 | #[derive(Debug, Deserialize)] 28 | struct Config { 29 | private_key: PathBuf, 30 | enclave: PathBuf, 31 | log_output: PathBuf, 32 | } 33 | 34 | impl Default for Config { 35 | fn default() -> Self { 36 | let enclave = PathBuf::from(DEFAULT_ENCLAVE_PATH); 37 | let private_key = PathBuf::from(DEFAULT_PRIVATE_KEY_PATH); 38 | let log_output = PathBuf::from(log_filename()); 39 | Self { 40 | enclave, 41 | private_key, 42 | log_output, 43 | } 44 | } 45 | } 46 | 47 | enum Interrupt { 48 | Break, 49 | Continue, 50 | } 51 | 52 | enum Stdio { 53 | Stdin, 54 | Stdout, 55 | } 56 | 57 | fn stdio_with_interrupt(handle: Stdio, buffer: &mut [u8]) -> Result { 58 | let res = match handle { 59 | Stdio::Stdin => io::stdin().read_exact(buffer), 60 | Stdio::Stdout => io::stdout().write_all(buffer), 61 | }; 62 | match res { 63 | Ok(_) => Ok(Interrupt::Continue), 64 | Err(err) => { 65 | match err.kind() { 66 | io::ErrorKind::BrokenPipe | io::ErrorKind::UnexpectedEof => { 67 | // Unless we received a SIGTERM and the other closed the pipe 68 | // on purpose, we need to throw an error! 69 | if !SIGNALED.load(Ordering::Relaxed) { 70 | Err(anyhow!("Unexpected EOF or a broken pipe!")) 71 | } else { 72 | log::debug!("Received termination signal, exiting..."); 73 | Ok(Interrupt::Break) 74 | } 75 | } 76 | _ => Err(anyhow!( 77 | "failed to read message len from stdin (first 4 bytes): {}", 78 | err 79 | )), 80 | } 81 | } 82 | } 83 | } 84 | 85 | fn run(config: Config) -> Result<()> { 86 | // Install signal handler for SIGINT and SIGTERM 87 | let handler = SigHandler::Handler(handle_signals); 88 | unsafe { signal::signal(Signal::SIGTERM, handler)? }; 89 | unsafe { signal::signal(Signal::SIGINT, handler)? }; 90 | log::debug!("Registered SIGTERM and SIGINT signal handlers"); 91 | // Ok, first pass will load and unload enclave at each message received 92 | // event. However, this is definitely not optimal and we should spawn 93 | // it only once and hand out Arc<> to the spawned instance instead. 94 | // This will require some Mutexing though since PodEnclave is not safe to send 95 | // across thread boundaries. 96 | loop { 97 | if SIGNALED.load(Ordering::Relaxed) { 98 | log::debug!("Received termination signal, exiting..."); 99 | break; 100 | } 101 | 102 | let mut msg_len = [0u8; 4]; 103 | match stdio_with_interrupt(Stdio::Stdin, &mut msg_len) { 104 | Err(err) => return Err(err), 105 | Ok(Interrupt::Break) => break, 106 | Ok(Interrupt::Continue) => {} 107 | }; 108 | let msg_len = u32::from_ne_bytes(msg_len); 109 | let msg_len = usize::try_from(msg_len).expect("u32 should fit into usize"); 110 | 111 | if msg_len == 0 { 112 | if SIGNALED.load(Ordering::Relaxed) { 113 | log::debug!("Received termination signal, exiting..."); 114 | break; 115 | } 116 | 117 | // TODO is this correct behaviour? Should we actually simply carry on listening? 118 | continue; 119 | } 120 | 121 | log::debug!("Received message len (first 4 bytes): {}", msg_len); 122 | 123 | let mut msg = Vec::new(); 124 | msg.resize(msg_len as usize, 0); 125 | match stdio_with_interrupt(Stdio::Stdin, &mut msg) { 126 | Err(err) => return Err(err), 127 | Ok(Interrupt::Break) => break, 128 | Ok(Interrupt::Continue) => {} 129 | }; 130 | 131 | log::debug!("Message received"); 132 | 133 | let mut reply = reply(msg, &config)?; 134 | let reply_len: u32 = reply 135 | .len() 136 | .try_into() 137 | .context("reply len overflew 32bit register")?; 138 | match stdio_with_interrupt(Stdio::Stdout, &mut reply_len.to_ne_bytes()) { 139 | Err(err) => return Err(err), 140 | Ok(Interrupt::Break) => break, 141 | Ok(Interrupt::Continue) => {} 142 | }; 143 | 144 | log::debug!("Sent reply len: {}", reply_len); 145 | 146 | match stdio_with_interrupt(Stdio::Stdout, &mut reply) { 147 | Err(err) => return Err(err), 148 | Ok(Interrupt::Break) => break, 149 | Ok(Interrupt::Continue) => {} 150 | }; 151 | io::stdout().flush()?; 152 | 153 | log::debug!("Reply sent"); 154 | } 155 | 156 | Ok(()) 157 | } 158 | 159 | fn config() -> Config { 160 | // Firstly, check in xdg config folder. 161 | let dirs = xdg::BaseDirectories::with_prefix("pod-app") 162 | .expect("couldn't create xdg base dir instance"); 163 | 164 | match dirs.find_data_file("pod_enclave.signed.so") { 165 | Some(enclave) => { 166 | let data_home = dirs.get_data_home(); 167 | let private_key = data_home.join("private_key.sealed"); 168 | let log_output = data_home.join(log_filename()); 169 | 170 | Config { 171 | private_key, 172 | enclave, 173 | log_output, 174 | } 175 | } 176 | None => Config::default(), 177 | } 178 | } 179 | 180 | fn log_filename() -> String { 181 | // TODO add some stronger uniqueness to log names 182 | let now = SystemTime::now() 183 | .duration_since(UNIX_EPOCH) 184 | .expect("could get current system time"); 185 | format!("pod-app_{}.log", now.as_secs_f64()) 186 | } 187 | 188 | fn main() { 189 | let config = config(); 190 | let log_output = 191 | fs::File::create(&config.log_output).expect("could initialize file for logger output"); 192 | 193 | simplelog::WriteLogger::init( 194 | log::LevelFilter::Debug, 195 | simplelog::Config::default(), 196 | log_output, 197 | ) 198 | .expect("could initialize logger"); 199 | 200 | log::debug!("Application started..."); 201 | 202 | if let Err(err) = run(config) { 203 | log::error!("Unexpected error occurred: {}", err); 204 | process::exit(1); 205 | } 206 | 207 | log::debug!("Application successfully stopped..."); 208 | } 209 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /lib/api/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /lib/c-api/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /pod-app/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /pod-enclave/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /pod-ext/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /pod-server/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | --------------------------------------------------------------------------------
Test
{ 41 | let quote = match self.quote.borrow_mut().take() { 42 | Some(quote) => quote, 43 | None => { 44 | let quote = wrappers::get_quote(spid.as_ref(), quote_type)?; 45 | quote 46 | } 47 | }; 48 | let ret = quote.clone(); 49 | *self.quote.borrow_mut() = Some(quote); 50 | Ok(ret) 51 | } 52 | 53 | pub fn sign>(&self, message: B) -> Result> { 54 | let signature = wrappers::sign_buffer(message)?; 55 | Ok(signature) 56 | } 57 | } 58 | 59 | impl Drop for PodEnclave { 60 | fn drop(&mut self) { 61 | wrappers::unload_enclave().expect("unloading enclave should succeed") 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /pod-ext/style/montserrat-font.css: -------------------------------------------------------------------------------- 1 | /* cyrillic-ext */ 2 | @font-face { 3 | font-family: 'Montserrat'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459WRhyzbi.woff2) format('woff2'); 7 | unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; 8 | } 9 | /* cyrillic */ 10 | @font-face { 11 | font-family: 'Montserrat'; 12 | font-style: normal; 13 | font-weight: 400; 14 | src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459W1hyzbi.woff2) format('woff2'); 15 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; 16 | } 17 | /* vietnamese */ 18 | @font-face { 19 | font-family: 'Montserrat'; 20 | font-style: normal; 21 | font-weight: 400; 22 | src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459WZhyzbi.woff2) format('woff2'); 23 | unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; 24 | } 25 | /* latin-ext */ 26 | @font-face { 27 | font-family: 'Montserrat'; 28 | font-style: normal; 29 | font-weight: 400; 30 | src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459Wdhyzbi.woff2) format('woff2'); 31 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; 32 | } 33 | /* latin */ 34 | @font-face { 35 | font-family: 'Montserrat'; 36 | font-style: normal; 37 | font-weight: 400; 38 | src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459Wlhyw.woff2) format('woff2'); 39 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 40 | } 41 | -------------------------------------------------------------------------------- /pod-web/src/assets/click.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /lib/rust-sgx-util/src/c.rs: -------------------------------------------------------------------------------- 1 | #[repr(C)] 2 | pub(crate) struct IasContext { 3 | _private: [u8; 0], 4 | } 5 | 6 | #[link(name = "sgx_util")] 7 | extern "C" { 8 | // ias.h 9 | pub(crate) fn ias_init( 10 | ias_api_key: *const libc::c_char, 11 | ias_verify_url: *const libc::c_char, 12 | ias_sigrl_url: *const libc::c_char, 13 | ) -> *mut IasContext; 14 | pub(crate) fn ias_cleanup(context: *mut IasContext); 15 | pub(crate) fn ias_get_sigrl( 16 | context: *mut IasContext, 17 | gid: *const u8, 18 | sigrl_size: *mut usize, 19 | sigrl: *mut *mut libc::c_void, 20 | ) -> libc::c_int; 21 | pub(crate) fn ias_verify_quote( 22 | context: *mut IasContext, 23 | quote: *const libc::c_void, 24 | quote_size: usize, 25 | nonce: *const libc::c_char, 26 | report_path: *const libc::c_char, 27 | sig_path: *const libc::c_char, 28 | cert_path: *const libc::c_char, 29 | advisory_path: *const libc::c_char, 30 | ) -> libc::c_int; 31 | // util.h 32 | pub(crate) fn set_verbose(verbose: bool); 33 | // attestation.h 34 | #[allow(unused)] 35 | pub(crate) fn verify_ias_report( 36 | ias_report: *const u8, 37 | ias_report_size: usize, 38 | ias_sig_b64: *mut u8, 39 | ias_sig_64_size: usize, 40 | allow_outdated_tcb: bool, 41 | nonce: *const libc::c_char, 42 | mr_signer: *const libc::c_char, 43 | mr_enclave: *const libc::c_char, 44 | isv_prod_id: *const libc::c_char, 45 | isv_svn: *const libc::c_char, 46 | report_data: *const libc::c_char, 47 | ias_pub_key_pem: *const libc::c_char, 48 | ) -> libc::c_int; 49 | #[allow(unused)] 50 | pub(crate) fn verify_quote( 51 | quote_data: *const libc::c_void, 52 | quote_size: usize, 53 | mr_signer: *const libc::c_char, 54 | mr_enclave: *const libc::c_char, 55 | isv_prod_id: *const libc::c_char, 56 | isv_svn: *const libc::c_char, 57 | report_data: *const libc::c_char, 58 | ) -> libc::c_int; 59 | } 60 | -------------------------------------------------------------------------------- /pod-web/src/components/Home/home.module.css: -------------------------------------------------------------------------------- 1 | .home { 2 | width: 100%; 3 | min-width: 500px; 4 | height: calc(100vh - 63px); 5 | display: flex; 6 | flex-direction: column; 7 | justify-content: flex-start; 8 | align-items: flex-start; 9 | font-size: 21pt; 10 | padding: 0 25vh; 11 | box-sizing: border-box; 12 | transition: padding .5s; 13 | color: var(--color3); 14 | } 15 | 16 | .spentChart { 17 | width: 100%; 18 | height: 450px; 19 | } 20 | 21 | .actionPanel { 22 | position: relative; 23 | bottom: 0; 24 | } 25 | 26 | .displayAmount { 27 | margin-left: 10px; 28 | font-family: monospace; 29 | word-spacing: -10px; 30 | } 31 | 32 | .summary { 33 | width: 100%; 34 | display: flex; 35 | justify-content: space-between; 36 | padding: 0 15px; 37 | box-sizing: border-box; 38 | margin-top: 20px; 39 | } 40 | 41 | .historyScreen, 42 | .withdrawScreen { 43 | width: 30vw; 44 | height: 20vh; 45 | padding: 15px 30px; 46 | border: 1px solid grey; 47 | border-radius: 5px; 48 | text-align: left; 49 | } 50 | 51 | .withdrawScreen { 52 | display: flex; 53 | flex-direction: column; 54 | justify-content: space-between; 55 | position: relative; 56 | } 57 | .historyScreen { 58 | overflow-y: scroll; 59 | } 60 | 61 | .historyScreen ul { 62 | padding: 0; 63 | } 64 | 65 | .historyScreen li { 66 | align-items: center; 67 | border: 1px dashed #999; 68 | height: 60px; 69 | } 70 | 71 | .historyScreen li span:first-child { 72 | text-align: left; 73 | width: 150px; 74 | } 75 | 76 | .historyScreen li span:last-child { 77 | text-align: right; 78 | width: 150px; 79 | } 80 | 81 | @media only screen and (max-width: 1270px) { 82 | .home { 83 | display: block; 84 | padding: 0 15px; 85 | } 86 | } 87 | 88 | @media only screen and (max-width: 900px) { 89 | .spentChart { 90 | height: 280px; 91 | } 92 | .summary { 93 | display: block; 94 | } 95 | 96 | .historyScreen, 97 | .withdrawScreen { 98 | width: 100%; 99 | height: 25vh; 100 | box-sizing: border-box; 101 | margin-top: 10px; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /pod-app/examples/browser_mock.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{anyhow, Result}; 2 | use nix::sys::signal::{self, Signal}; 3 | use nix::unistd::Pid; 4 | use serde_json::Value; 5 | use std::convert::TryFrom; 6 | use std::io::{self, Read, Write}; 7 | use std::path::PathBuf; 8 | use std::process::{Command, Stdio}; 9 | use structopt::StructOpt; 10 | 11 | #[derive(StructOpt)] 12 | struct Opt { 13 | /// Path to native messaging enabled binary. 14 | #[structopt(parse(from_os_str))] 15 | path: PathBuf, 16 | } 17 | 18 | fn main() -> Result<()> { 19 | let opt = Opt::from_args(); 20 | 21 | let mut child = Command::new(&opt.path) 22 | .stdin(Stdio::piped()) 23 | .stdout(Stdio::piped()) 24 | .spawn()?; 25 | loop { 26 | print!("> "); 27 | io::stdout().flush()?; 28 | 29 | let mut json = String::new(); 30 | io::stdin().read_line(&mut json)?; 31 | let json = json.trim(); 32 | 33 | if json.is_empty() { 34 | continue; 35 | } 36 | 37 | if json == "exit" { 38 | break; 39 | } 40 | 41 | let msg_len = json.len(); 42 | let msg_len = u32::try_from(msg_len)?; 43 | 44 | { 45 | let stdin = child 46 | .stdin 47 | .as_mut() 48 | .ok_or(anyhow!("failed to open stdin"))?; 49 | stdin.write_all(&msg_len.to_ne_bytes())?; 50 | stdin.write_all(json.as_bytes())?; 51 | } 52 | 53 | { 54 | let stdout = child 55 | .stdout 56 | .as_mut() 57 | .ok_or(anyhow!("failed to open stdout"))?; 58 | let mut msg_len = [0u8; 4]; 59 | stdout.read_exact(&mut msg_len)?; 60 | let msg_len = u32::from_ne_bytes(msg_len); 61 | let msg_len = usize::try_from(msg_len).expect("u32 should fit into usize"); 62 | 63 | let mut msg = Vec::new(); 64 | msg.resize(msg_len, 0); 65 | stdout.read_exact(&mut msg)?; 66 | let output: Value = serde_json::from_slice(&msg)?; 67 | println!("{}", output); 68 | } 69 | } 70 | signal::kill(Pid::from_raw(child.id() as i32), Some(Signal::SIGTERM))?; 71 | let status_code = child.wait()?; 72 | println!("Child exited with {}", status_code); 73 | 74 | Ok(()) 75 | } 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Proof-of-device 2 | 3 | Proof-of-device, or _pod_, is another take at 2FA or rather U2F. Here, however, the burden of storing 4 | keys for signing and proving your identity is managed by the SGX enclave. The service you're 5 | authenticating with sends you challenge which you sign using a private key embedded within the 6 | enclave in your Intel CPU. The system is very secure since not even you have the knowledge of 7 | the private key that's stored within the enclave. 8 | 9 | ## Project structure 10 | 11 | The project comprises of four main components: 12 | * [`pod-enclave`] -- This is where the private key used for signing authentication challenge requests 13 | is generated and then stored. Note that the private key is actually stored on the 14 | host, however, in an enclave-sealed form which only the enclave that generated it 15 | can unseal to then use it for signing. 16 | * [`pod-app`] -- This is the native app that _pod_ uses to interface with the `pod-enclave`. It implements 17 | [native messaging] and therefore can be used from within a browser environment. 18 | * [`pod-ext`] -- This is the browser extension connects _pod_ to generate quote and sign the challenge for the _pod-web_ authentication mechanism. 19 | * [`pod-web`] -- This is the web app _pod-ext_ connects as a GUI for the end user of the _pod_. 20 | * [`pod-server`] -- This is the web server that the service provider who offers _pod_ as an added authentication 21 | mechanism uses. 22 | 23 | [`pod-enclave`]: https://github.com/golemfactory/ProofOfDevice/tree/master/pod-enclave 24 | [`pod-app`]: https://github.com/golemfactory/ProofOfDevice/tree/master/pod-app 25 | [`pod-ext`]: https://github.com/golemfactory/ProofOfDevice/tree/master/pod-ext 26 | [`pod-web`]: https://github.com/golemfactory/ProofOfDevice/tree/master/pod-web 27 | [`pod-server`]: https://github.com/golemfactory/ProofOfDevice/tree/master/pod-server 28 | [native messaging]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging 29 | 30 | For each of the components, follow the links to learn more and check out how to build and run them. 31 | 32 | ## Caveats 33 | 34 | This project currently builds and was tested on Linux only (both Ubuntu 18.04 and Arch). In the future, it is envisaged 35 | to support Windows however. 36 | 37 | -------------------------------------------------------------------------------- /pod-web/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /pod-server/src/handlers/register.rs: -------------------------------------------------------------------------------- 1 | use super::{AppError, Message}; 2 | use crate::models::{NewUser, User}; 3 | use crate::AppData; 4 | 5 | use diesel::prelude::*; 6 | 7 | use actix_web::error::BlockingError; 8 | use actix_web::{web, HttpResponse, Responder}; 9 | use rust_sgx_util::{IasHandle, Quote}; 10 | use serde::Deserialize; 11 | use std::env; 12 | use tokio_diesel::{AsyncRunQueryDsl, OptionalExtension}; 13 | 14 | #[derive(Debug, Deserialize)] 15 | pub struct RegisterInfo { 16 | login: String, 17 | quote: Quote, 18 | } 19 | 20 | pub async fn post(info: web::Json, app_data: web::Data) -> impl Responder { 21 | use crate::schema::users::dsl::*; 22 | 23 | log::info!( 24 | "Received register request for user with login '{}'.", 25 | info.login 26 | ); 27 | log::debug!("Received data: {:?}", info); 28 | 29 | // Check if the user is already registered. 30 | let result = users 31 | .filter(login.eq(info.login.clone())) 32 | .get_result_async::(&app_data.pool) 33 | .await 34 | .optional()?; 35 | log::debug!("Matching user records found: {:?}", result); 36 | 37 | if let Some(_) = result { 38 | log::info!("User '{}' already registered.", info.login); 39 | return Err(AppError::AlreadyRegistered); 40 | } 41 | 42 | let quote = info.quote.clone(); 43 | if let Err(err) = web::block(move || { 44 | // Verify the provided data with IAS. 45 | let api_key = env::var("POD_SERVER_API_KEY")?; 46 | let handle = IasHandle::new(&api_key, None, None)?; 47 | handle.verify_quote("e, None, None, None, None, None)?; 48 | Ok(()) 49 | }) 50 | .await 51 | { 52 | match err { 53 | BlockingError::Error(err) => return Err(err), 54 | BlockingError::Canceled => return Err(AppError::ActixBlockingCanceled), 55 | } 56 | }; 57 | 58 | // Extract pub_key from Quote 59 | // ED25519 public key is 32 bytes long 60 | let report_data = info.quote.report_data()?; 61 | let pub_key_ = base64::encode(&report_data[..32]); 62 | log::debug!("Extracted public key (base64 encoded): {}", pub_key_); 63 | 64 | // Insert user to the database. 65 | let new_user = NewUser { 66 | login: info.login.clone(), 67 | pub_key: pub_key_, 68 | }; 69 | diesel::insert_into(users) 70 | .values(new_user) 71 | .execute_async(&app_data.pool) 72 | .await?; 73 | 74 | log::info!("User '{}' successfully inserted into db.", info.login); 75 | Ok(HttpResponse::Ok().json(Message::ok().add_param("description", "registration successful"))) 76 | } 77 | -------------------------------------------------------------------------------- /pod-web/src/components/Register/index.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | 3 | import { form, register } from "./register.module.css"; 4 | import useEventListener from "../../hooks/useEventListener"; 5 | import request from "../../utils/request"; 6 | import {HOST, REGISTER, REMOTE, ORIGIN} from "../../Constants"; 7 | import PodIndicator from "../PodIndicator"; 8 | 9 | const getById = id => document.getElementById(id); 10 | 11 | const Register = () => { 12 | const [ errorStatus, setError ] = useState(false); 13 | const [ quote, setQuote ] = useState(null); 14 | useEffect(() => { 15 | window.postMessage( 16 | { host: HOST, type: REGISTER }, 17 | ORIGIN 18 | ); 19 | }, []); 20 | 21 | const messageListener = ({data, origin}) => { 22 | if (origin !== ORIGIN || data.host !== REMOTE) 23 | return; 24 | console.log(data); // Answer here 25 | setQuote(data.data) 26 | }; 27 | 28 | useEventListener("message", messageListener); 29 | 30 | const requestRegister = (event) => { 31 | event.preventDefault(); 32 | const login = getById("usernameInput").value; 33 | //const password = getById("passwordInput").value; 34 | registerRequest({ login, quote }) 35 | .then((result) => { 36 | console.log(result); 37 | }) 38 | .catch((error) => { 39 | setError(true) 40 | }); 41 | }; 42 | 43 | return ( 44 | 45 | 46 | 47 | Registration 48 | {errorStatus ? User already exist! : null} 49 | 50 | 58 | 59 | 60 | 67 | 68 | 69 | 76 | 77 | 78 | Register 79 | 80 | 81 | 82 | 83 | 84 | ); 85 | }; 86 | 87 | export default Register; 88 | 89 | function registerRequest({ login, quote }) { 90 | return request('/register', { 91 | method: 'post', 92 | headers: {'Content-Type': 'application/json'}, 93 | body: JSON.stringify({ 94 | login, 95 | quote, 96 | }) 97 | }) 98 | } 99 | -------------------------------------------------------------------------------- /pod-web/src/components/HOC/Loader.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import { tween } from "shifty"; 3 | 4 | import { loaderIcon, loaderScreen } from "./loader.module.css"; 5 | import loadingSVG from "../../assets/dollar.svg"; 6 | 7 | let time; 8 | function Loader({ children, loadingTime }) { 9 | const [load, setLoad] = useState(false); 10 | const [anim, setAnim] = useState([]); 11 | useEffect(() => { 12 | time = setTimeout(() => setLoad(true), loadingTime); 13 | 14 | tween({ 15 | from: { z: 0 }, 16 | to: { z: -30 }, 17 | duration: 500, 18 | step: ({ z, y }) => 19 | setAnim([ 20 | { transform: `rotateZ(${z}deg)`, transformOrigin: 'left' }, 21 | { transform: `rotateZ(${z * 2}deg)`, transformOrigin: 'left' }, 22 | { transform: `rotateZ(${z * 3}deg)`, transformOrigin: 'left' }, 23 | { transform: `rotateZ(${z * 4}deg)`, transformOrigin: 'left' }, 24 | { transform: `rotateZ(${z * 5}deg)`, transformOrigin: 'left' }, 25 | { transform: `rotateZ(${z * 6}deg)`, transformOrigin: 'left' }, 26 | { transform: `rotateZ(${z * 7}deg)`, transformOrigin: 'left' }, 27 | { transform: `rotateZ(${z * 8}deg)`, transformOrigin: 'left' }, 28 | { transform: `rotateZ(${z * 9}deg)`, transformOrigin: 'left' }, 29 | { transform: `rotateZ(${z * 10}deg)`, transformOrigin: 'left' }, 30 | { transform: `rotateZ(${z * 11}deg)`, transformOrigin: 'left' } 31 | ]) 32 | }, [loadingTime]); 33 | 34 | return () => { 35 | clearTimeout(time); 36 | time = null; 37 | }; 38 | }, [loadingTime]); 39 | if (load) return children; 40 | return ( 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | ); 56 | } 57 | export default Loader; 58 | -------------------------------------------------------------------------------- /pod-app/src/messages.rs: -------------------------------------------------------------------------------- 1 | use super::Config; 2 | use anyhow::Result; 3 | use pod_api::{PodEnclave, QuoteType}; 4 | use rust_sgx_util::Quote; 5 | use serde::{Deserialize, Serialize}; 6 | 7 | #[derive(Debug, Deserialize)] 8 | #[serde(tag = "msg", rename_all = "snake_case")] 9 | enum IncomingMessage { 10 | GetQuote { 11 | spid: String, 12 | }, 13 | SignChallenge { 14 | #[serde(with = "base_64")] 15 | challenge: Vec, 16 | }, 17 | } 18 | 19 | #[derive(Debug, Serialize)] 20 | #[serde(tag = "msg", rename_all = "snake_case")] 21 | #[allow(dead_code)] 22 | pub(super) enum OutgoingMessage { 23 | GetQuote { 24 | quote: Quote, 25 | }, 26 | 27 | SignChallenge { 28 | #[serde(with = "base_64")] 29 | signed: Vec, 30 | }, 31 | } 32 | 33 | impl OutgoingMessage { 34 | pub fn get_quote(quote: Quote) -> Self { 35 | Self::GetQuote { quote } 36 | } 37 | 38 | pub fn sign_challenge>(signed: B) -> Self { 39 | Self::SignChallenge { 40 | signed: signed.as_ref().to_vec(), 41 | } 42 | } 43 | } 44 | 45 | mod base_64 { 46 | use serde::{self, Deserialize, Deserializer, Serializer}; 47 | 48 | pub(crate) fn serialize(blob: &[u8], serializer: S) -> Result 49 | where 50 | S: Serializer, 51 | { 52 | serializer.serialize_str(&base64::encode(blob)) 53 | } 54 | 55 | pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> 56 | where 57 | D: Deserializer<'de>, 58 | { 59 | let string = String::deserialize(deserializer)?; 60 | base64::decode(&string).map_err(serde::de::Error::custom) 61 | } 62 | } 63 | 64 | pub(super) fn reply>(msg: B, config: &Config) -> Result> { 65 | let msg: IncomingMessage = serde_json::from_slice(msg.as_ref())?; 66 | log::debug!("Received message content: {:?}", msg); 67 | 68 | let reply = match msg { 69 | IncomingMessage::GetQuote { spid } => { 70 | let pod_enclave = PodEnclave::new(&config.enclave, &config.private_key)?; 71 | let quote = pod_enclave.get_quote(spid, QuoteType::Unlinkable)?; 72 | let reply = OutgoingMessage::get_quote(quote); 73 | let serialized = serde_json::to_vec(&reply)?; 74 | serialized 75 | } 76 | IncomingMessage::SignChallenge { challenge } => { 77 | let pod_enclave = PodEnclave::new(&config.enclave, &config.private_key)?; 78 | let signature = pod_enclave.sign(challenge)?; 79 | let reply = OutgoingMessage::sign_challenge(signature); 80 | let serialized = serde_json::to_vec(&reply)?; 81 | serialized 82 | } 83 | }; 84 | 85 | log::debug!("Reply content: {:?}", reply); 86 | Ok(reply) 87 | } 88 | -------------------------------------------------------------------------------- /pod-ext/pages/settings.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --panel-height: 700px; 3 | --color-border: #cdcdcd; 4 | } 5 | 6 | body { 7 | display: flex; 8 | flex-direction: column; 9 | justify-content: center; 10 | align-items: center; 11 | color: #4a4a4a; 12 | background-color: #f3f3f3; 13 | font-family: 'Montserrat', sans-serif; 14 | } 15 | 16 | a { 17 | text-decoration: none; 18 | color: black; 19 | } 20 | 21 | .header { 22 | display: flex; 23 | justify-content: space-between; 24 | align-items: center; 25 | width: 60%; 26 | margin-top: 5vh; 27 | margin-bottom: 10px; 28 | } 29 | 30 | .header_name { 31 | display: flex; 32 | align-items: center; 33 | margin: 0 20px; 34 | } 35 | 36 | .header > img { 37 | max-width: 50px; 38 | max-height: 50px; 39 | width: auto; 40 | height: auto; 41 | } 42 | 43 | .panel { 44 | position: relative; 45 | width: 60%; 46 | height: var(--panel-height); 47 | min-width: 500px; 48 | background: #fff; 49 | border: 1px solid var(--color-border); 50 | border-radius: 5px; 51 | } 52 | 53 | .panel header { 54 | padding: 0 30px; 55 | border-bottom: 1px solid var(--color-border); 56 | } 57 | 58 | .panel header > p { 59 | font-size: 10pt; 60 | } 61 | 62 | .panel__action { 63 | border-top: 1px solid var(--color-border); 64 | } 65 | 66 | .pure-form-aligned .pure-control-group label { 67 | width: auto; 68 | } 69 | 70 | .label__shortcut { 71 | width: 170px !important; 72 | text-align: left !important; 73 | margin: 10px 0 !important; 74 | } 75 | 76 | fieldset { 77 | border: none; 78 | } 79 | 80 | section { 81 | display: grid; 82 | grid-template-columns: 25% auto; 83 | grid-template-rows: auto auto; 84 | justify-content: flex-start; 85 | align-items: center; 86 | border-bottom: 1px solid var(--color-border); 87 | padding: 15px 30px; 88 | } 89 | 90 | section:last-of-type { 91 | border-bottom: 0; 92 | } 93 | 94 | /*only chromuim*/ 95 | ::-webkit-scrollbar { 96 | width: 5px; 97 | } 98 | 99 | ::-webkit-scrollbar-track { 100 | margin: 5px 0; 101 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); 102 | } 103 | 104 | ::-webkit-scrollbar-thumb { 105 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5); 106 | } 107 | 108 | .scrollable { 109 | height: calc(var(--panel-height) - 200px); 110 | overflow-y: scroll; 111 | } 112 | 113 | .settings__label { 114 | font-size: 14pt; 115 | font-weight: 900; 116 | color: #000; 117 | } 118 | 119 | .pure-form-aligned .pure-control-group { 120 | margin-bottom: 0; 121 | margin: 0.5em 0; 122 | } 123 | .blacklist > li { 124 | width: 220px; 125 | } 126 | .blacklist > li:hover::after { 127 | content: 'Remove'; 128 | float: right; 129 | font-size: 8pt; 130 | line-height: 16pt; 131 | font-weight: 600; 132 | color: red; 133 | cursor: pointer; 134 | } 135 | 136 | .button-submit { 137 | position: absolute; 138 | bottom: 30px; 139 | right: 30px; 140 | } 141 | -------------------------------------------------------------------------------- /pod-web/src/assets/dollar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /pod-web/src/components/Home/index.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | 3 | import Chart from "chart.js"; 4 | import { tween } from "shifty"; 5 | 6 | import { 7 | actionPanel, 8 | displayAmount, 9 | home, 10 | historyScreen, 11 | spentChart, 12 | summary, 13 | withdrawScreen, 14 | } from "./home.module.css"; 15 | 16 | const Home = () => { 17 | const [amount, setAmount] = useState(0); 18 | useEffect(() => { 19 | loadChart(); 20 | 21 | tween({ 22 | from: { x: 0 }, 23 | to: { x: 569671200 }, 24 | duration: 2500, 25 | easing: "easeInQuint", 26 | step: ({ x }) => 27 | setAmount( 28 | new Intl.NumberFormat("pl-PL", { 29 | style: "currency", 30 | currency: "USD", 31 | }).format(x) 32 | ), 33 | }); 34 | }, []); 35 | return ( 36 | 37 | 38 | 39 | 40 | 41 | 42 | Savings 43 | {amount} 44 | 45 | alert("We went bankrupt :(")}> 46 | Withdraw 47 | 48 | 49 | 50 | 51 | 52 | 53 | Payment 54 | - $1.23 55 | 56 | 57 | Earning 58 | + $12.08 59 | 60 | 61 | Earning 62 | + $3.5 63 | 64 | 65 | Payment 66 | - $42.6 67 | 68 | 69 | Payment 70 | - $136.8 71 | 72 | 73 | Payment 74 | - $12.4 75 | 76 | 77 | 78 | 79 | 80 | ); 81 | }; 82 | 83 | export default Home; 84 | 85 | Chart.defaults.global.defaultFontColor = '#FFF'; 86 | var config = { 87 | type: "line", 88 | data: { 89 | labels: ["January", "February", "March", "April", "May", "June", "July"], 90 | datasets: [ 91 | { 92 | label: "Salary", 93 | borderColor: "#af5b5bff", 94 | backgroundColor: "#af5b5bff", 95 | data: [3, 5, 9, 2, 10, 4, 3, 7], 96 | }, 97 | { 98 | label: "DeFi", 99 | borderColor: "#276fbfff", 100 | backgroundColor: "#276fbfff", 101 | data: [3, 5, 6, 5, 2, 7, 9, 12], 102 | }, 103 | { 104 | label: "Airdrop lol", 105 | borderColor: "#f6f4f3ff", 106 | backgroundColor: "#f6f4f3ff", 107 | data: [8, 7, 5, 3, 8, 3, 8], 108 | }, 109 | ], 110 | }, 111 | options: { 112 | responsive: true, 113 | title: { 114 | display: true, 115 | text: "Earnings", 116 | }, 117 | tooltips: { 118 | mode: "index", 119 | }, 120 | hover: { 121 | mode: "index", 122 | }, 123 | scales: { 124 | x: { 125 | scaleLabel: { 126 | display: true, 127 | labelString: "Month", 128 | }, 129 | }, 130 | y: { 131 | stacked: true, 132 | scaleLabel: { 133 | display: true, 134 | labelString: "Value", 135 | }, 136 | }, 137 | }, 138 | }, 139 | }; 140 | 141 | function loadChart() { 142 | let ctx = document.getElementById("spentChart").getContext("2d"); 143 | window.myLine = new Chart(ctx, config); 144 | } 145 | -------------------------------------------------------------------------------- /pod-server/src/handlers/auth.rs: -------------------------------------------------------------------------------- 1 | use super::{AppError, Message}; 2 | use crate::models::User; 3 | use crate::AppData; 4 | 5 | use diesel::prelude::*; 6 | 7 | use actix_identity::Identity; 8 | use actix_session::Session; 9 | use actix_web::{web, HttpResponse, Responder}; 10 | use serde::Deserialize; 11 | use tokio_diesel::{AsyncRunQueryDsl, OptionalExtension}; 12 | 13 | pub async fn get(session: Session, identity: Identity) -> impl Responder { 14 | if let Some(id) = identity.identity() { 15 | log::info!("User '{}' already authenticated", id); 16 | return Err(AppError::AlreadyAuthenticated); 17 | } 18 | 19 | log::info!("Received challenge request."); 20 | 21 | // Send challenge. 22 | let challenge = match session.get::("challenge") { 23 | Err(_) => return Err(AppError::InvalidCookie), 24 | Ok(Some(challenge)) => challenge, 25 | Ok(None) => { 26 | let mut blob = [0u8; 64]; 27 | getrandom::getrandom(&mut blob)?; 28 | let challenge = base64::encode(&blob[..]); 29 | 30 | log::debug!("Generated challenge: {}", challenge); 31 | 32 | if let Err(_) = session.set("challenge", challenge.clone()) { 33 | return Err(AppError::InvalidCookie); 34 | } 35 | 36 | challenge 37 | } 38 | }; 39 | 40 | Ok(HttpResponse::Ok().json( 41 | Message::ok() 42 | .add_param("description", "challenge successfully generated") 43 | .add_param("challenge", challenge), 44 | )) 45 | } 46 | 47 | #[derive(Deserialize)] 48 | pub struct AuthChallengeResponse { 49 | login: String, 50 | response: String, // base64 encoded 51 | } 52 | 53 | pub async fn post( 54 | response: web::Json, 55 | app_data: web::Data, 56 | session: Session, 57 | identity: Identity, 58 | ) -> impl Responder { 59 | if let Some(ident) = identity.identity() { 60 | log::info!("User '{}' already authenticated!", ident); 61 | return Err(AppError::AlreadyAuthenticated); 62 | } 63 | 64 | use crate::schema::users::dsl::*; 65 | 66 | log::info!( 67 | "Received challenge response from user with login '{}'.", 68 | response.login 69 | ); 70 | 71 | // Fetch user's record and extract their pub_key. 72 | let record = users 73 | .filter(login.eq(response.login.clone())) 74 | .get_result_async::(&app_data.pool) 75 | .await 76 | .optional()?; 77 | let record = match record { 78 | Some(record) => record, 79 | None => return Err(AppError::NotRegistered), 80 | }; 81 | 82 | let blob = match session 83 | .get::("challenge") 84 | .map_err(|_| AppError::InvalidCookie)? 85 | { 86 | Some(challenge) => base64::decode(challenge)?, 87 | None => return Err(AppError::InvalidChallenge), 88 | }; 89 | 90 | let pub_key_ = ed25519_dalek::PublicKey::from_bytes(&base64::decode(&record.pub_key)?)?; 91 | let enc_blob = base64::decode(&response.response)?; 92 | let signature = ed25519_dalek::Signature::from_bytes(&enc_blob)?; 93 | pub_key_.verify(&blob, &signature)?; 94 | 95 | identity.remember(response.login.clone()); 96 | session.purge(); 97 | 98 | Ok( 99 | HttpResponse::Ok() 100 | .json(Message::ok().add_param("description", "authentication successful")), 101 | ) 102 | } 103 | -------------------------------------------------------------------------------- /pod-app/README.md: -------------------------------------------------------------------------------- 1 | # `pod-app` 2 | 3 | The native app that _pod_ uses to interface with the `pod-enclave`. It implements [native messaging] and 4 | therefore can be used from within a browser environment such as [`pod-ext`]. 5 | 6 | ## Installation 7 | 8 | You can install the app together with the enclave file `pod_enclave.signed.so` using the provided simple 9 | `install.sh` script. This script will install the `pod-app` into the local cargo registry, and will create 10 | `$HOME/.local/share/pod-app` local storage dir and copy the enclave file into it. The sealed private key 11 | file `private_key.sealed` will also reside there. 12 | 13 | ``` 14 | ./install.sh 15 | ``` 16 | 17 | ## Native messages handled by `pod-app` 18 | 19 | All requests are in JSON format. See [native messaging] for more info. 20 | 21 | * **Requests**: 22 | - `{ "msg" : "get_quote", "spid": "01234567abcdef" }` 23 | - `{ "msg" : "sign_challenge", "challenge" : "AAADEADBEEF" }` 24 | 25 | * **Responses** 26 | - `{ "msg" : "get_quote", "quote" : "AAAAA...AAA" }` 27 | - `{ "msg" : "sign_challenge", "signed" : "BBBBBAAAAABB" }` 28 | - `{ "msg" : "error", "description" : "description of the error" }` 29 | 30 | ## Development 31 | 32 | ### Building 33 | 34 | Simply run from the repo's root: 35 | 36 | ``` 37 | cargo build 38 | ``` 39 | 40 | This will build [`pod-enclave`] by default which is a prerequisite for the `pod-app`. 41 | 42 | 43 | ## Examples 44 | 45 | ### `browser_mock` app 46 | 47 | For testing purposes, there is a `browser_mock` app as part of the `pod-app` which can be used for 48 | manual testing of the native messaging responses of the `pod-app`. 49 | 50 | To run it, first make sure `pod-app` is built: 51 | 52 | ``` 53 | cargo build 54 | ``` 55 | 56 | And then run: 57 | 58 | ``` 59 | cargo run --example browser_mock target/debug/pod-app 60 | ``` 61 | 62 | You can send all request-type messages to the `pod-app` using `browser_mock` app and observe its 63 | response. For instance: 64 | 65 | ``` 66 | > { "msg": "sign_challenge", "challenge": "deadbeef" } 67 | {"msg":"sign_challenge","signed":"NYPXlzY98WUawum6yFQdelyzVoxC5VdguSSJ022ZJYyFc1W0DmZjnXP6t5t/gVwnckigP5u44yKmi7bIimiRBw=="} 68 | ``` 69 | 70 | [native messaging]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#Closing_the_native_app 71 | 72 | ### `webservice_client` app 73 | 74 | For some end-to-end testing, you can use the provided simple test client which 75 | exposes two bits of functionality: registering and authenticating with the [`pod-server`] 76 | web service. 77 | 78 | The former takes a username and Service Provider's ID (SPID): 79 | 80 | ``` 81 | cargo run --example webservice_client -- register johndoe deadbeef123456 82 | ``` 83 | 84 | This command will initiate a POST request to `/register` entrypoint. 85 | 86 | The latter on the other hand takes only your username as an argument: 87 | 88 | ``` 89 | cargo run --example webservice_client -- authenticate johndoe 90 | ``` 91 | 92 | This command initiates 3 requests: a GET to `/auth` to obtain a challenge, 93 | a POST to `/auth` to validate the challenge and authenticate with the 94 | service, and finally a GET to `/` to verify that we've indeed successfully 95 | signed in. 96 | 97 | [`pod-server`]: https://github.com/golemfactory/proofofdevice/tree/master/pod-server 98 | [`pod-enclave`]: https://github.com/golemfactory/proofofdevice/tree/master/pod-enclave 99 | [native-messaging]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging 100 | -------------------------------------------------------------------------------- /pod-web/src/components/Login/index.js: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect, useState } from "react"; 2 | import AuthContext from "../../context/auth"; 3 | import useEventListener from "../../hooks/useEventListener"; 4 | import request from "../../utils/request"; 5 | import { CHALLENGE, HOST, REMOTE, ORIGIN } from "../../Constants"; 6 | import PodIndicator from "../PodIndicator"; 7 | 8 | import { click, form, login, motto } from "./login.module.css"; 9 | 10 | import clickAsset from "../../assets/click.svg"; 11 | 12 | const getById = (id) => document.getElementById(id); 13 | 14 | const Login = () => { 15 | const auth = useContext(AuthContext); 16 | const [signed, setSigned] = useState(null); 17 | const [errorStatus, setError] = useState(false); 18 | // const [loading, setLoading] = useState(false) for loading animation 19 | useEffect(() => { 20 | challengeRequest() 21 | .then(({ challenge }) => { 22 | if (!challenge) 23 | throw new Error( 24 | "Challenge cannot be empty.\nHint: Try removing cookies." 25 | ); 26 | window.postMessage( 27 | { host: HOST, type: CHALLENGE, data: challenge }, 28 | ORIGIN 29 | ); 30 | }) 31 | .catch((error) => { 32 | console.warn(error); 33 | alert(`Network Error: ${error.status}`); 34 | }); 35 | }, []); 36 | 37 | const messageListener = ({ data, origin }) => { 38 | if (origin !== ORIGIN || data.host !== REMOTE) return; 39 | console.log(data); // Answer 40 | setSigned(data.data); 41 | }; 42 | 43 | useEventListener("message", messageListener); 44 | 45 | const requestLogin = (event) => { 46 | event.preventDefault(); 47 | const login = getById("usernameInput").value; 48 | //const password = getById("passwordInput").value; 49 | authRequest({ login, signed_challenge: signed }) 50 | .then((result) => { 51 | console.log(result); 52 | if (result.status === "Ok") { 53 | auth.setLoggedIn(true); 54 | } else { 55 | setError(true); 56 | } 57 | }) 58 | .catch((error) => { 59 | console.warn(error); 60 | setError(true); 61 | }); 62 | }; 63 | 64 | return ( 65 | 66 | 67 | Possibilites. 68 | 69 | One Click Away 70 | 71 | 72 | 73 | 74 | Login 75 | {errorStatus ? Wrong credentials : null} 76 | 77 | 85 | 86 | 87 | 94 | 95 | 96 | Login 97 | 98 | 99 | 100 | 101 | 102 | ); 103 | }; 104 | 105 | export default Login; 106 | 107 | function challengeRequest() { 108 | return request("/auth", { 109 | method: "get", 110 | }); 111 | } 112 | 113 | function authRequest({ login, signed_challenge }) { 114 | return request("/auth", { 115 | method: "post", 116 | headers: { "Content-Type": "application/json" }, 117 | body: JSON.stringify({ 118 | login, 119 | response: signed_challenge, 120 | }), 121 | }); 122 | } 123 | -------------------------------------------------------------------------------- /pod-enclave/Makefile: -------------------------------------------------------------------------------- 1 | SGX_SDK ?= /opt/intel/sgxsdk 2 | SGX_SSL ?= /opt/intel/sgxssl 3 | SGX_SSL_INC ?= $(SGX_SSL)/include 4 | SGX_SSL_LIB ?= $(SGX_SSL)/lib64 5 | SGX_INC ?= $(SGX_SDK)/include 6 | SGX_LIB ?= $(SGX_SDK)/lib64 7 | ENCLAVE_CONFIG ?= pod_enclave.config.xml 8 | ENCLAVE_SIGNING_PUBLIC_KEY ?= pod_signing_pubkey.pem 9 | ENCLAVE_BINARY ?= pod_enclave.so 10 | ENCLAVE_BINARY_SIGNED ?= pod_enclave.signed.so 11 | 12 | ifeq ($(DEBUG), 1) 13 | CFLAGS += -O0 -g 14 | else 15 | CFLAGS += -O2 16 | endif 17 | 18 | SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r 19 | SGX_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign 20 | EDGER8R_FLAGS := --search-path $(SGX_INC) --search-path $(SGX_SSL_INC) 21 | MRSIGNER := pod_enclave.mrsigner 22 | MRSIGNER_H := pod_enclave_mrsigner.h 23 | 24 | .PHONY: all 25 | all: $(ENCLAVE_BINARY_SIGNED) 26 | 27 | .PHONY: check_key 28 | check_key: 29 | ifndef ENCLAVE_SIGNING_KEY 30 | $(error ENCLAVE_SIGNING_KEY not set) 31 | endif 32 | 33 | $(ENCLAVE_SIGNING_PUBLIC_KEY): check_key $(ENCLAVE_SIGNING_KEY) 34 | openssl rsa -in $(ENCLAVE_SIGNING_KEY) -pubout -out $(ENCLAVE_SIGNING_PUBLIC_KEY) 35 | 36 | # PoD enclave 37 | CFLAGS += -m64 \ 38 | -Wall \ 39 | -Wextra \ 40 | -D_GNU_SOURCE \ 41 | -nostdinc \ 42 | -fvisibility=hidden \ 43 | -fpie \ 44 | -fstack-protector \ 45 | -std=c99 \ 46 | -I$(SGX_INC) \ 47 | -I$(SGX_INC)/tlibc \ 48 | -I$(SGX_SSL_INC) 49 | 50 | LDFLAGS := -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles \ 51 | -L$(SGX_LIB) -L$(SGX_SSL_LIB) \ 52 | -Wl,--whole-archive -lsgx_tsgxssl -Wl,--no-whole-archive -lsgx_tsgxssl_crypto \ 53 | -Wl,--whole-archive -lsgx_trts -Wl,--no-whole-archive \ 54 | -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -lsgx_tcrypto -lsgx_tservice -Wl,--end-group \ 55 | -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ 56 | -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ 57 | -Wl,--defsym,__ImageBase=0 58 | 59 | $(ENCLAVE_BINARY_SIGNED): $(ENCLAVE_BINARY) $(ENCLAVE_SIGNING_KEY) $(ENCLAVE_SIGNING_PUBLIC_KEY) 60 | $(SGX_SIGNER) gendata -enclave $< -out $<.sigdata -config $(ENCLAVE_CONFIG) -ignore-init-sec-error 61 | # replace the command below to use HSM for signing operation 62 | openssl dgst -sha256 -out $<.sig -sign $(ENCLAVE_SIGNING_KEY) $<.sigdata 63 | $(SGX_SIGNER) catsig -enclave $< -sig $<.sig \ 64 | -unsigned $<.sigdata -key $(ENCLAVE_SIGNING_PUBLIC_KEY) -out $@ \ 65 | -config $(ENCLAVE_CONFIG) -ignore-init-sec-error 66 | $(SGX_SIGNER) dump -enclave $@ -dumpfile enclave.meta -ignore-init-sec-error 67 | 68 | $(MRSIGNER): $(ENCLAVE_SIGNING_PUBLIC_KEY) openssl_parse.awk 69 | openssl rsa -in $(ENCLAVE_SIGNING_PUBLIC_KEY) -pubin -text -noout \ 70 | | awk -f openssl_parse.awk | xxd -p -r | sha256sum -b \ 71 | | xxd -r -ps -l 32 > $@ 72 | 73 | # header with mrsigner value 74 | $(MRSIGNER_H): $(MRSIGNER) 75 | xxd -i -c 8 $(MRSIGNER) > $@ 76 | 77 | $(ENCLAVE_BINARY): pod_enclave_t.o pod_enclave.o 78 | $(CC) $^ $(LDFLAGS) -o $@ 79 | 80 | pod_enclave.o: pod_enclave.c $(MRSIGNER_H) pod_enclave_u.c 81 | $(CC) $(CFLAGS) -c $< -o $@ 82 | 83 | pod_enclave_t.o: pod_enclave_t.c 84 | $(CC) $(CFLAGS) -c $< -o $@ 85 | 86 | # ECALL/OCALL interface (generated files) 87 | pod_enclave_t.c: pod_enclave.edl 88 | $(SGX_EDGER8R) $(EDGER8R_FLAGS) --trusted $< 89 | 90 | pod_enclave_u.c: pod_enclave.edl 91 | $(SGX_EDGER8R) $(EDGER8R_FLAGS) --untrusted $< 92 | 93 | .PHONY: install 94 | install: ; 95 | 96 | .PHONY: clean 97 | clean: 98 | $(RM) *.o *.so 99 | $(RM) pod_enclave_t.c pod_enclave_t.h pod_enclave_u.c pod_enclave_u.h 100 | $(RM) *.meta *.mrsigner *_mrsigner.h *.sig *.sigdata $(ENCLAVE_SIGNING_PUBLIC_KEY) 101 | -------------------------------------------------------------------------------- /pod-server/README.md: -------------------------------------------------------------------------------- 1 | # `pod-server` 2 | 3 | A simple implementation of a web service facilitating the Proof-of-device 4 | at the service provider's end. 5 | 6 | ## Basic usage 7 | 8 | The minimal config file to run the server consists of the IAS valid API key, 9 | and 32-byte long private key for signing cookies: 10 | 11 | ```toml 12 | api_key = "0123456abcdef" 13 | cookie_key = "0123456abcdef" 14 | ``` 15 | 16 | By default, the server binds itself to `127.0.0.1:8080` address. You can tweak 17 | it by appending a `[server]` section to the config file: 18 | 19 | ```toml 20 | api_key = "0123456abcdef" 21 | cookie_key = "0123456abcdef" 22 | 23 | [server] 24 | address = "127.0.0.1" 25 | port = 8080 26 | ``` 27 | 28 | The server uses [`diesel`] crate as the ORM and SQLite as the database. In order 29 | to configure the database for use with the app, firstly, you need to specify the 30 | path to the database file in `.env` file: 31 | 32 | ``` 33 | DATABASE_URL=mock.db 34 | ``` 35 | 36 | Secondly, before actually firing up the server for the first time, you need to 37 | init the db: 38 | 39 | ``` 40 | diesel setup 41 | ``` 42 | 43 | Then, and this step should occur whenver you want to redo the tables, re-run 44 | the migrations: 45 | 46 | ``` 47 | diesel migration run 48 | ``` 49 | 50 | Finally, when invoking the server from the command line, you are required to 51 | specify the path to the config file: 52 | 53 | ``` 54 | cargo run -- config.toml -v 55 | ``` 56 | 57 | ## RESTful API 58 | 59 | The service strives to communicate with JSON only, and the message will have a 60 | general structure like below: 61 | 62 | ```json 63 | { 64 | "status": "ok", 65 | "description": "some message" 66 | } 67 | ``` 68 | 69 | `status` assumes either `ok`, or `error`, and details are encapsulated within 70 | the `description` field. 71 | 72 | ### Available entrypoints: 73 | 74 | * GET `/` -- dummy route which will respond with `203` if user successfully 75 | authenticated, or a `403` with description of the error encoded as JSON. 76 | 77 | 78 | * POST `/register` -- route required to register a new user with the service. The 79 | expected content body is a JSON containing at least two fields: `login` and 80 | `quote`. 81 | 82 | Example request content: 83 | 84 | ```json 85 | { 86 | "login": "johndoe", 87 | "quote": "AAAAA...AAA", 88 | "nonce": "AAAAA" 89 | } 90 | ``` 91 | 92 | Nonce is optional, however both quote and nonce should be base64 encoded. 93 | 94 | Upon successful registration, a `200` message will be generated. 95 | 96 | * GET `/auth` -- route required to initiate challenge-response protocol in order 97 | to authenticate the registered user using their SGX enclave (which holds a 98 | private ED25519 key). The challenge which the user is required to signed using 99 | their enclave will be provided inside content as JSON inside `challenge` field. 100 | The challenge will be base64 encoded. 101 | 102 | Example response content: 103 | 104 | ```json 105 | { 106 | "status": "ok", 107 | "description": "challenge successfully generated", 108 | "challenge": "AAAA...AAA" 109 | } 110 | ``` 111 | 112 | * POST `/auth` -- route where the signed `challenge` should be sent to. The signed 113 | challenge should be sent inside JSON under `response` field, and should be base64 114 | encoded. Additinally, the user should supply their login as part of the JSON. 115 | 116 | Example request content: 117 | 118 | ```json 119 | { 120 | "login": "johndoe", 121 | "response": "AAAA...AAA" 122 | } 123 | ``` 124 | -------------------------------------------------------------------------------- /pod-server/src/main.rs: -------------------------------------------------------------------------------- 1 | mod handlers; 2 | mod models; 3 | mod schema; 4 | 5 | #[macro_use] 6 | extern crate diesel; 7 | 8 | use actix_identity::{CookieIdentityPolicy, IdentityService}; 9 | use actix_session::CookieSession; 10 | use actix_web::{middleware, web, App, HttpServer}; 11 | use anyhow::anyhow; 12 | use diesel::r2d2::{ConnectionManager, Pool}; 13 | use diesel::SqliteConnection; 14 | use dotenv::dotenv; 15 | use serde::Deserialize; 16 | use std::path::PathBuf; 17 | use std::time::{SystemTime, UNIX_EPOCH}; 18 | use std::{env, fs}; 19 | use structopt::StructOpt; 20 | 21 | #[derive(StructOpt)] 22 | #[structopt(name = "pod_server", version = env!("CARGO_PKG_VERSION"))] 23 | struct Opt { 24 | /// Path to server config TOML file. 25 | #[structopt(parse(from_os_str))] 26 | config_path: PathBuf, 27 | /// Set verbose mode on/off. 28 | #[structopt(short, long)] 29 | verbose: bool, 30 | } 31 | 32 | #[derive(Deserialize)] 33 | struct ServerConfig { 34 | api_key: String, 35 | cookie_key: String, 36 | #[serde(rename = "server")] 37 | bind: Option, 38 | } 39 | 40 | #[derive(Deserialize)] 41 | struct BindAddress { 42 | address: String, 43 | port: u16, 44 | } 45 | 46 | pub struct AppData { 47 | pool: Pool>, 48 | } 49 | 50 | #[actix_rt::main] 51 | async fn main() -> anyhow::Result<()> { 52 | let opt = Opt::from_args(); 53 | dotenv()?; 54 | // Enable info logging by default. 55 | let level = if opt.verbose { 56 | rust_sgx_util::set_verbose(true); 57 | log::LevelFilter::Debug 58 | } else { 59 | log::LevelFilter::Info 60 | }; 61 | let now = SystemTime::now().duration_since(UNIX_EPOCH)?; 62 | let log_output = fs::File::create(format!("pod-server_{}.log", now.as_secs_f64()))?; 63 | simplelog::WriteLogger::init(level, simplelog::Config::default(), log_output)?; 64 | // Read config file 65 | let config_file = fs::read(&opt.config_path)?; 66 | let config: ServerConfig = toml::from_slice(&config_file)?; 67 | let (address, port) = match &config.bind { 68 | Some(server_config) => (server_config.address.clone(), server_config.port), 69 | None => ("127.0.0.1".to_string(), 8080), 70 | }; 71 | let address_port = [address, port.to_string()].join(":"); 72 | // Set POD_SERVER_API_KEY env variable 73 | env::set_var("POD_SERVER_API_KEY", config.api_key); 74 | 75 | let db_url = env::var("DATABASE_URL")?; 76 | let manager = ConnectionManager::::new(db_url); 77 | let pool = Pool::builder().build(manager)?; 78 | let data = web::Data::new(AppData { pool }); 79 | // Cookie config 80 | let cookie_key = config.cookie_key.clone(); 81 | 82 | HttpServer::new(move || { 83 | App::new() 84 | .wrap( 85 | CookieSession::signed(cookie_key.as_bytes()) 86 | .name("session") 87 | .http_only(false) 88 | .secure(false), 89 | ) 90 | .wrap(IdentityService::new( 91 | CookieIdentityPolicy::new(cookie_key.as_bytes()) 92 | .name("auth") 93 | .secure(false), 94 | )) 95 | .wrap(middleware::Logger::default()) 96 | .app_data(data.clone()) 97 | .route("/", web::get().to(handlers::index)) 98 | .route("/register", web::post().to(handlers::register::post)) 99 | .service( 100 | web::resource("/auth") 101 | .route(web::get().to(handlers::auth::get)) 102 | .route(web::post().to(handlers::auth::post)), 103 | ) 104 | }) 105 | .bind(address_port)? 106 | .run() 107 | .await 108 | .map_err(|err| anyhow!("HttpServer errored out with {:?}", err))?; 109 | 110 | Ok(()) 111 | } 112 | -------------------------------------------------------------------------------- /lib/c-api/pod_sgx.h: -------------------------------------------------------------------------------- 1 | #ifndef POD_SGX_H 2 | #define POD_SGX_H 3 | 4 | /** Enables enclave debugging and NULLIFIES ENCLAVE MEMORY PROTECTION. */ 5 | #define ENCLAVE_DEBUG_ENABLED 1 6 | 7 | /*! 8 | * \brief Get size of an open file. 9 | * 10 | * \param[in] fd Open file descriptor. 11 | * 12 | * \return File size or -1 on error. 13 | */ 14 | ssize_t get_file_size(int fd); 15 | 16 | /*! 17 | * \brief Read file contents to buffer. 18 | * 19 | * \param[in] buffer Buffer to read data to. If NULL, this function allocates one. 20 | * \param[in] path Path to the file. 21 | * \param[in,out] size On entry, number of bytes to read. 0 means to read the entire file. 22 | * On exit, number of bytes read. 23 | * 24 | * \return On success, pointer to the data buffer. If \p buffer was NULL, caller should free this. 25 | * On failure, NULL. 26 | */ 27 | void* read_file(void* buffer, const char* path, size_t* size); 28 | 29 | /*! 30 | * \brief Write buffer to file. 31 | * 32 | * \param[in] path File path. 33 | * \param[in] size \p buffer size. 34 | * \param[in] buffer Buffer to write data from. 35 | * 36 | * \return 0 on success, errno on error. 37 | */ 38 | int write_file(const char* path, size_t size, const void* buffer); 39 | 40 | /*! 41 | * \brief Initialize PoD enclave. 42 | * Loads enclave, generates new enclave key pair, and seals the private key into the provided 43 | * buffer. 44 | * 45 | * \param[in] enclave_path Path to enclave binary. 46 | * \param[in] sealed_state Buffer to seal the private key to. 47 | * \param[in] sealed_state_size Size of the provided buffer. 48 | * 49 | * \return On success, number of bytes written to the buffer. On failure, negative value. 50 | */ 51 | int pod_init_enclave(const char* enclave_path, uint8_t* sealed_state, size_t sealed_state_size); 52 | 53 | /*! 54 | * \brief Load PoD enclave and restore its private key from sealed state. 55 | * 56 | * \param[in] enclave_path Path to enclave binary. 57 | * \param[in] sealed_state_path Path to sealed enclave state. 58 | * 59 | * \return 0 on success, negative on error. 60 | */ 61 | int pod_load_enclave(const char* enclave_path, const uint8_t* sealed_state, size_t sealed_state_size); 62 | 63 | /*! 64 | * \brief Unload PoD enclave. 65 | * 66 | * \return 0 on success, negative on error. 67 | */ 68 | int pod_unload_enclave(void); 69 | 70 | /*! 71 | * \brief Generate valid quote of this PoD enclave for remote attestation with IAS services. 72 | * 73 | * \param[in] sp_id_str Service Provider ID (hex string). 74 | * \param[in] sp_quote_type_str Quote type as string ("linkable"/"unlinkable"). 75 | * \param[in] quote_buffer Buffer to save the quote to. 76 | * \param[in] quote_buffer_size Size of the provided buffer. 77 | * 78 | * \return On success, number of bytes written to the buffer. On failure, negative value. 79 | */ 80 | int pod_get_quote(const char* sp_id_str, const char* sp_quote_type_str, uint8_t* quote_buffer, 81 | size_t quote_buffer_size); 82 | 83 | /*! 84 | * \brief Create PoD enclave digital signature for data buffer. 85 | * 86 | * \param[in] data Buffer with data to sign. 87 | * \param[in] data_size Size of \p data in bytes. 88 | * \param[out] signature Buffer that will receive the signature. 89 | * \param[in] signature_size Size of \p signature in bytes. 90 | * 91 | * \return 0 on success, negative on error. 92 | */ 93 | int pod_sign_buffer(const void* data, size_t data_size, void* signature, size_t signature_size); 94 | 95 | /*! 96 | * \brief Create PoD enclave digital signature for a file. 97 | * 98 | * \param[in] input_path Path to file to sign. 99 | * \param[in] signature_path Path where the signature will be saved. 100 | * 101 | * \return 0 on success, negative on error. 102 | */ 103 | int pod_sign_file(const char* input_path, const char* signature_path); 104 | 105 | #endif /* POD_SGX_H */ 106 | -------------------------------------------------------------------------------- /lib/api/src/wrappers.rs: -------------------------------------------------------------------------------- 1 | use super::{c, QuoteType}; 2 | use anyhow::{anyhow, Result}; 3 | use rust_sgx_util::Quote; 4 | use std::convert::TryFrom; 5 | use std::ffi::CString; 6 | use std::path::Path; 7 | 8 | const MAX_SEALED_KEYS_SIZE: usize = 1024; // Should be plenty for ed25519 private key 9 | const MAX_QUOTE_SIZE: usize = 2048; // Usually around 1200 bytes required 10 | const EC_SIGNATURE: usize = 64; // EC signature should always be 64bytes long! 11 | 12 | pub fn set_verbose(verbose: bool) { 13 | unsafe { c::set_verbose(verbose) } 14 | } 15 | 16 | pub(super) fn init_enclave>(enclave_path: P) -> Result> { 17 | let enclave_path = path_to_c_string(enclave_path)?; 18 | let sealed_keys_buffer = &mut [0u8; MAX_SEALED_KEYS_SIZE]; 19 | let ret = unsafe { 20 | c::pod_init_enclave( 21 | enclave_path.as_ptr(), 22 | sealed_keys_buffer.as_mut_ptr(), 23 | sealed_keys_buffer.len(), 24 | ) 25 | }; 26 | 27 | if ret < 0 { 28 | return Err(anyhow!( 29 | "pod_init_enclave returned non-zero exit code: {}", 30 | ret 31 | )); 32 | } 33 | 34 | let sealed_keys_size = usize::try_from(ret)?; 35 | Ok(Vec::from(&sealed_keys_buffer[..sealed_keys_size])) 36 | } 37 | 38 | pub(super) fn load_enclave, B: AsRef<[u8]>>( 39 | enclave_path: P, 40 | sealed_keys: B, 41 | ) -> Result<()> { 42 | let enclave_path = path_to_c_string(enclave_path)?; 43 | let sealed_keys = sealed_keys.as_ref(); 44 | let ret = unsafe { 45 | c::pod_load_enclave( 46 | enclave_path.as_ptr(), 47 | sealed_keys.as_ptr(), 48 | sealed_keys.len(), 49 | ) 50 | }; 51 | if ret < 0 { 52 | Err(anyhow!( 53 | "pod_load_enclave returned non-zero exit code: {}", 54 | ret 55 | )) 56 | } else { 57 | Ok(()) 58 | } 59 | } 60 | 61 | pub(super) fn unload_enclave() -> Result<()> { 62 | let ret = unsafe { c::pod_unload_enclave() }; 63 | if ret != 0 { 64 | Err(anyhow!( 65 | "pod_unload_enclave returned non-zero exit code: {}", 66 | ret 67 | )) 68 | } else { 69 | Ok(()) 70 | } 71 | } 72 | 73 | pub(super) fn get_quote>(spid: S, quote_type: QuoteType) -> Result { 74 | let spid = CString::new(spid.as_ref())?; 75 | let quote_type = match quote_type { 76 | QuoteType::Linkable => CString::new("l")?, 77 | QuoteType::Unlinkable => CString::new("u")?, 78 | }; 79 | let quote_buffer = &mut [0u8; MAX_QUOTE_SIZE]; 80 | let ret = unsafe { 81 | c::pod_get_quote( 82 | spid.as_ptr(), 83 | quote_type.as_ptr(), 84 | quote_buffer.as_mut_ptr(), 85 | MAX_QUOTE_SIZE, 86 | ) 87 | }; 88 | 89 | if ret < 0 { 90 | return Err(anyhow!( 91 | "pod_init_enclave returned non-zero exit code: {}", 92 | ret 93 | )); 94 | } 95 | let quote_size = usize::try_from(ret)?; 96 | Ok(Quote::from("e_buffer[..quote_size])) 97 | } 98 | 99 | pub(super) fn sign_buffer>(message: B) -> Result> { 100 | let message = message.as_ref(); 101 | let signature = &mut [0u8; EC_SIGNATURE]; 102 | let ret = unsafe { 103 | c::pod_sign_buffer( 104 | message.as_ptr() as *const _, 105 | message.len(), 106 | signature.as_mut_ptr() as *mut _, 107 | signature.len(), 108 | ) 109 | }; 110 | if ret != 0 { 111 | return Err(anyhow!( 112 | "pod_sign_buffer returned non-zero exit code: {}", 113 | ret 114 | )); 115 | } 116 | Ok(signature.to_vec()) 117 | } 118 | 119 | #[cfg(unix)] 120 | fn path_to_c_string>(path: P) -> Result { 121 | use std::os::unix::ffi::OsStrExt; 122 | let s = CString::new(path.as_ref().as_os_str().as_bytes())?; 123 | Ok(s) 124 | } 125 | 126 | #[cfg(windows)] 127 | fn path_to_c_string(path: &Path) -> Result { 128 | use std::os::windows::ffi::OsStringExt; 129 | let utf16: Vec<_> = path.as_os_str().encode_wide().collect(); 130 | let s = String::from_utf16(utf16)?; 131 | let s = CString::new(s.as_bytes())?; 132 | Ok(s) 133 | } 134 | -------------------------------------------------------------------------------- /pod-server/src/handlers/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod auth; 2 | pub mod register; 3 | 4 | use actix_identity::Identity; 5 | use actix_web::dev::HttpResponseBuilder; 6 | use actix_web::http::StatusCode; 7 | use actix_web::{HttpResponse, Responder, ResponseError}; 8 | use serde::Serialize; 9 | use std::collections::HashMap; 10 | 11 | pub async fn index(identity: Identity) -> impl Responder { 12 | match identity.identity() { 13 | Some(_) => Ok(HttpResponse::NoContent()), 14 | None => Err(AppError::NotAuthenticated), 15 | } 16 | } 17 | 18 | #[derive(Serialize)] 19 | enum Status { 20 | Ok, 21 | Error, 22 | } 23 | 24 | #[derive(Serialize)] 25 | struct Message { 26 | status: Status, 27 | #[serde(flatten)] 28 | params: HashMap, 29 | } 30 | 31 | impl Message { 32 | fn ok() -> Self { 33 | Self { 34 | status: Status::Ok, 35 | params: HashMap::new(), 36 | } 37 | } 38 | 39 | fn error() -> Self { 40 | Self { 41 | status: Status::Error, 42 | params: HashMap::new(), 43 | } 44 | } 45 | 46 | fn add_param, S2: AsRef>(mut self, key: S1, value: S2) -> Self { 47 | self.params 48 | .insert(key.as_ref().to_owned(), value.as_ref().to_owned()); 49 | self 50 | } 51 | } 52 | 53 | #[derive(Debug, thiserror::Error)] 54 | enum AppError { 55 | #[error("user not registered yet")] 56 | NotRegistered, 57 | #[error("user already registered")] 58 | AlreadyRegistered, 59 | #[error("invalid challenge")] 60 | InvalidChallenge, 61 | #[error("invalid cookie")] 62 | InvalidCookie, 63 | #[error("user not authenticated")] 64 | NotAuthenticated, 65 | #[error("user already authenticated")] 66 | AlreadyAuthenticated, 67 | #[error("tokio_diesel async op failed with error: {}", _0)] 68 | TokioDieselAsync(#[from] tokio_diesel::AsyncError), 69 | #[error("attesting quote failed with error: {}", _0)] 70 | RustSgxUtil(#[from] rust_sgx_util::Error), 71 | #[error("r2d2 pool error: {}", _0)] 72 | R2d2Pool(#[from] diesel::r2d2::PoolError), 73 | #[error("diesel result error {}", _0)] 74 | DieselResult(#[from] diesel::result::Error), 75 | #[error("var not found in env: {}", _0)] 76 | Var(#[from] std::env::VarError), 77 | #[error("blocking operation was canceled prematurely")] 78 | ActixBlockingCanceled, 79 | #[error("decoding base64 to blob: {}", _0)] 80 | Base64Decode(#[from] base64::DecodeError), 81 | #[error("parsing ed25519 signature: {}", _0)] 82 | Ed25519Signature(#[from] ed25519_dalek::SignatureError), 83 | #[error("fetching entropy: {}", _0)] 84 | GetRandom(#[from] getrandom::Error), 85 | } 86 | 87 | impl ResponseError for AppError { 88 | fn error_response(&self) -> HttpResponse { 89 | let (code, message) = match self { 90 | AppError::NotRegistered => (StatusCode::FORBIDDEN, Message::error()), 91 | AppError::AlreadyRegistered => (StatusCode::OK, Message::ok()), 92 | AppError::InvalidChallenge => (StatusCode::OK, Message::error()), 93 | AppError::InvalidCookie => (StatusCode::OK, Message::error()), 94 | AppError::NotAuthenticated => (StatusCode::FORBIDDEN, Message::error()), 95 | AppError::AlreadyAuthenticated => (StatusCode::OK, Message::ok()), 96 | AppError::TokioDieselAsync(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 97 | AppError::RustSgxUtil(_) => (StatusCode::OK, Message::error()), 98 | AppError::R2d2Pool(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 99 | AppError::DieselResult(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 100 | AppError::Var(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 101 | AppError::ActixBlockingCanceled => { 102 | (StatusCode::INTERNAL_SERVER_ERROR, Message::error()) 103 | } 104 | AppError::Base64Decode(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 105 | AppError::Ed25519Signature(_) => (StatusCode::OK, Message::error()), 106 | AppError::GetRandom(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 107 | }; 108 | HttpResponseBuilder::new(code).json(message.add_param("description", format!("{}", self))) 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /pod-web/src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' }, 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready 134 | .then(registration => { 135 | registration.unregister(); 136 | }) 137 | .catch(error => { 138 | console.error(error.message); 139 | }); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /lib/rust-sgx-util/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! A safe wrapper around Graphene's [`sgx_util`] C-library. 2 | //! 3 | //! [`sgx_util`]: https://github.com/oscarlab/graphene/tree/master/Pal/src/host/Linux-SGX/tools 4 | //! 5 | //! ```toml 6 | //! rust-sgx-util = "0.2" 7 | //! ``` 8 | //! 9 | //! For `serde` support, you can enable it with `with_serde` feature: 10 | //! 11 | //! ```toml 12 | //! rust-sgx-util = { version = "0.2", features = ["with_serde"] } 13 | //! ``` 14 | //! 15 | //! ## Prerequisites 16 | //! 17 | //! Currently, this crate requires you compile and install `sgx_util` as 18 | //! a shared library. 19 | //! 20 | //! ## Usage examples 21 | //! 22 | //! You can find usage examples in the `examples` dir of the crate. 23 | //! 24 | mod c; 25 | mod ias; 26 | #[cfg(feature = "with_serde")] 27 | mod ser_de; 28 | 29 | pub use ias::*; 30 | 31 | #[cfg(feature = "with_serde")] 32 | use serde::{Deserialize, Serialize}; 33 | use std::convert::TryFrom; 34 | use std::ops::Deref; 35 | 36 | /// Convenience wrapper around fallible operation. 37 | pub type Result = std::result::Result; 38 | 39 | /// Error type thrown by fallible operations in this crate. 40 | #[derive(Debug, thiserror::Error)] 41 | pub enum Error { 42 | /// Failed to initialize `IasHandle`. 43 | #[error("failed to initialize IasHandle")] 44 | IasInitNullPtr, 45 | /// `Quote`'s size is too small. 46 | #[error("quote's size is too small")] 47 | QuoteTooShort, 48 | /// `Nonce` exceeded 32 bytes. 49 | #[error("nonce exceeded 32 bytes")] 50 | NonceTooLong, 51 | /// `IasHandle::get_sigrl` returned nonzero return code. 52 | #[error("get_sigrl returned nonzero return code: {}", _0)] 53 | IasGetSigrlNonZero(i32), 54 | /// `IasHandle::verify_quote` returned nonzero return code. 55 | #[error("verify_quote returned nonzero return code: {}", _0)] 56 | IasVerifyQuoteNonZero(i32), 57 | /// Error while parsing int from string. 58 | #[error("parsing int from string: {:?}", _0)] 59 | ParseInt(#[from] std::num::ParseIntError), 60 | /// Found unexpected interior nul byte. 61 | #[error("unexpected interior nul byte: {:?}", _0)] 62 | Nul(#[from] std::ffi::NulError), 63 | /// (Windows only) Encountered invalid UTF16. 64 | #[error("invalid UTF16 encountered: {:?}", _0)] 65 | Utf16(#[from] std::string::FromUtf16Error), 66 | } 67 | 68 | /// Set verbosity on/off. 69 | pub fn set_verbose(verbose: bool) { 70 | unsafe { c::set_verbose(verbose) } 71 | } 72 | 73 | /// A thin wrapper around vector of bytes. Represents quote obtained 74 | /// from the challenged enclave. 75 | /// 76 | /// # Accessing the underlying bytes buffer 77 | /// 78 | /// `Quote` implements `Deref`, therefore dereferencing it will 79 | /// yield its inner buffer of bytes. 80 | /// 81 | /// # Serializing/deserializing 82 | /// 83 | /// With `with_serde` feature enabled, `Quote` can be serialized and deserialized 84 | /// as base64 `String`. 85 | #[derive(Debug, Clone)] 86 | #[cfg_attr(feature = "with_serde", derive(Serialize, Deserialize))] 87 | pub struct Quote(#[cfg_attr(feature = "with_serde", serde(with = "ser_de"))] Vec); 88 | 89 | impl Quote { 90 | const REPORT_BEGIN: usize = 368; 91 | const REPORT_END: usize = 432; 92 | 93 | /// Returns `report_data` bytes embedded within this `Quote`. 94 | /// 95 | /// The size of the returned slice is 64 bytes. 96 | /// 97 | /// # Errors 98 | /// 99 | /// This function will fail with [`Error::QuoteTooShort`] if `Quote` 100 | /// is shorter than `432` bytes. Note that this is only a quick check 101 | /// that we can extract the region in `Quote`'s buffer where we expect 102 | /// the `report_data` to lie in. We don't do any validations on the 103 | /// `Quote` in this method. 104 | /// 105 | /// [`Error::QuoteTooShort`]: enum.Error.html#variant.QuoteTooShort 106 | /// 107 | /// # Examples 108 | /// 109 | /// ``` 110 | /// # use rust_sgx_util::Quote; 111 | /// let quote = Quote::from(&[0u8; 438][..]); 112 | /// assert_eq!(quote.report_data().unwrap().len(), 64); 113 | /// 114 | /// let quote = Quote::from(&[0u8; 10][..]); 115 | /// assert!(quote.report_data().is_err()); 116 | /// ``` 117 | pub fn report_data(&self) -> Result<&[u8]> { 118 | self.0 119 | .get(Self::REPORT_BEGIN..Self::REPORT_END) 120 | .ok_or(Error::QuoteTooShort) 121 | } 122 | } 123 | 124 | impl From<&[u8]> for Quote { 125 | fn from(bytes: &[u8]) -> Self { 126 | Self::from(bytes.to_vec()) 127 | } 128 | } 129 | 130 | impl From> for Quote { 131 | fn from(bytes: Vec) -> Self { 132 | Self(bytes) 133 | } 134 | } 135 | 136 | impl Deref for Quote { 137 | type Target = [u8]; 138 | 139 | fn deref(&self) -> &Self::Target { 140 | &self.0 141 | } 142 | } 143 | 144 | /// A thin wrapper around vector of bytes. Represents nonce obtained 145 | /// from the challenged enclave. 146 | /// 147 | /// Nonce cannot be longer than 32 bytes. 148 | /// 149 | /// # Accessing the underlying bytes buffer 150 | /// 151 | /// `Nonce` implements `Deref`, therefore dereferencing it will 152 | /// yield its inner buffer of bytes. 153 | /// 154 | /// # Serializing/deserializing 155 | /// 156 | /// With `with_serde` feature enabled, `Nonce` can be serialized and deserialized 157 | /// as base64 `String`. 158 | #[derive(Debug, Clone)] 159 | #[cfg_attr(feature = "with_serde", derive(Serialize, Deserialize))] 160 | pub struct Nonce(#[cfg_attr(feature = "with_serde", serde(with = "ser_de"))] Vec); 161 | 162 | impl Nonce { 163 | fn new>>(bytes: B) -> Result { 164 | let bytes = bytes.into(); 165 | if bytes.len() > 32 { 166 | return Err(Error::NonceTooLong); 167 | } 168 | Ok(Self(bytes)) 169 | } 170 | } 171 | 172 | impl TryFrom<&[u8]> for Nonce { 173 | type Error = Error; 174 | 175 | fn try_from(bytes: &[u8]) -> Result { 176 | Self::new(bytes) 177 | } 178 | } 179 | 180 | impl Deref for Nonce { 181 | type Target = [u8]; 182 | 183 | fn deref(&self) -> &Self::Target { 184 | &self.0 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /pod-app/examples/webservice_client.rs: -------------------------------------------------------------------------------- 1 | use actix_web::client::Client; 2 | use actix_web::HttpMessage; 3 | use anyhow::anyhow; 4 | use pod_api::{PodEnclave, QuoteType}; 5 | use rust_sgx_util::Quote; 6 | use serde::Serialize; 7 | use structopt::StructOpt; 8 | 9 | const SEALED_KEYS_PATH: &str = "pod_data.sealed"; 10 | const ENCLAVE_PATH: &str = "../pod-enclave/pod_enclave.signed.so"; 11 | 12 | #[derive(Debug, StructOpt)] 13 | struct Opt { 14 | /// Server address to connect to (defaults to 127.0.0.1). 15 | #[structopt(long)] 16 | address: Option, 17 | /// Server port to connect to (defaults to 8080). 18 | #[structopt(long)] 19 | port: Option, 20 | #[structopt(subcommand)] 21 | cmd: Command, 22 | } 23 | 24 | #[derive(Debug, StructOpt)] 25 | enum Command { 26 | /// Register with the service. 27 | Register { 28 | /// Your username. 29 | login: String, 30 | /// Service Provider's ID (SPID) as given by the SP. 31 | spid: String, 32 | }, 33 | /// Authenticate with the service. 34 | Authenticate { 35 | /// Your username. 36 | login: String, 37 | }, 38 | } 39 | 40 | #[derive(Serialize)] 41 | struct RegisterInfo { 42 | login: String, 43 | quote: Quote, 44 | } 45 | 46 | #[derive(Serialize)] 47 | struct ChallengeResponse { 48 | login: String, 49 | response: String, 50 | } 51 | 52 | #[actix_rt::main] 53 | async fn main() -> anyhow::Result<()> { 54 | let opt = Opt::from_args(); 55 | // Turn on enclave logging 56 | pod_api::set_verbose(true); 57 | 58 | let address = opt.address.unwrap_or_else(|| "127.0.0.1".to_owned()); 59 | let port = opt.port.unwrap_or(8080); 60 | let base_uri = format!("http://{}:{}", address, port); 61 | let client = Client::default(); 62 | let pod_enclave = PodEnclave::new(ENCLAVE_PATH, SEALED_KEYS_PATH)?; 63 | 64 | match opt.cmd { 65 | Command::Register { login, spid } => { 66 | // Get the quote 67 | let quote = pod_enclave.get_quote(&spid, QuoteType::Unlinkable)?; 68 | 69 | println!("POST /register"); 70 | let mut response = client 71 | .post(format!("{}/register", base_uri)) 72 | .header("User-Agent", "TestClient") 73 | .send_json(&RegisterInfo { 74 | login: login.clone(), 75 | quote, 76 | }) 77 | .await 78 | .map_err(|err| anyhow!("{:?}", err))?; 79 | println!(" | status_code: {}", response.status()); 80 | let body = response.body().await.map_err(|err| anyhow!("{:?}", err))?; 81 | let content_length = body.len(); 82 | println!(" | content-length: {}", content_length); 83 | 84 | if content_length > 0 { 85 | let json: serde_json::Value = serde_json::from_slice(&body)?; 86 | println!(" | body: {}", json); 87 | } 88 | } 89 | Command::Authenticate { login } => { 90 | println!("GET /auth"); 91 | let mut response = client 92 | .get(format!("{}/auth", base_uri)) 93 | .header("User-Agent", "TestClient") 94 | .send() 95 | .await 96 | .map_err(|err| anyhow!("{:?}", err))?; 97 | let status_code = response.status(); 98 | println!(" | status_code: {}", status_code); 99 | let body = response.body().await.map_err(|err| anyhow!("{:?}", err))?; 100 | let content_length = body.len(); 101 | println!(" | content-length: {}", content_length); 102 | let cookies = response.cookies()?.clone(); 103 | for cookie in &cookies { 104 | println!(" | cookie: {}", cookie); 105 | } 106 | if status_code != 200 { 107 | return Err(anyhow!("Expected GET /auth to return 200")); 108 | } 109 | let json: serde_json::Value = serde_json::from_slice(&body)?; 110 | println!(" | body: {}", json); 111 | 112 | // Process challenge 113 | let challenge = json["challenge"] 114 | .as_str() 115 | .ok_or(anyhow!("invalid String for challenge"))?; 116 | let challenge = base64::decode(challenge)?; 117 | let response = pod_enclave.sign(&challenge)?; 118 | let response = base64::encode(&response[..]); 119 | 120 | println!("\nPOST /auth"); 121 | let mut builder = client 122 | .post(format!("{}/auth", base_uri)) 123 | .header("User-Agent", "TestClient"); 124 | for cookie in cookies { 125 | builder = builder.cookie(cookie); 126 | } 127 | let mut response = builder 128 | .send_json(&ChallengeResponse { login, response }) 129 | .await 130 | .map_err(|err| anyhow!("{:?}", err))?; 131 | println!(" | status_code: {}", response.status()); 132 | let body = response.body().await.map_err(|err| anyhow!("{:?}", err))?; 133 | let content_length = body.len(); 134 | println!(" | content-length: {}", content_length); 135 | let cookies = response.cookies()?.clone(); 136 | for cookie in &cookies { 137 | println!(" | cookie: {}", cookie); 138 | } 139 | 140 | if content_length > 0 { 141 | let json: serde_json::Value = serde_json::from_slice(&body)?; 142 | println!(" | body: {}", json); 143 | } 144 | 145 | println!("\n GET /"); 146 | let mut builder = client.get(&base_uri).header("User-Agent", "TestClient"); 147 | for cookie in cookies { 148 | builder = builder.cookie(cookie); 149 | } 150 | let mut response = builder.send().await.map_err(|err| anyhow!("{:?}", err))?; 151 | println!(" | status_code: {}", response.status()); 152 | let body = response.body().await.map_err(|err| anyhow!("{:?}", err))?; 153 | let content_length = body.len(); 154 | println!(" | content-length: {}", content_length); 155 | let json: serde_json::Value = serde_json::from_slice(&body)?; 156 | println!(" | body: {}", json); 157 | } 158 | } 159 | 160 | Ok(()) 161 | } 162 | -------------------------------------------------------------------------------- /pod-web/src/assets/pod-enabled.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pod-app/src/main.rs: -------------------------------------------------------------------------------- 1 | mod messages; 2 | 3 | use anyhow::{anyhow, Context, Result}; 4 | use messages::reply; 5 | use nix::sys::signal::{self, SigHandler, Signal}; 6 | use serde::Deserialize; 7 | use std::convert::{TryFrom, TryInto}; 8 | use std::io::{self, Read, Write}; 9 | use std::path::PathBuf; 10 | use std::sync::atomic::{AtomicBool, Ordering}; 11 | use std::time::{SystemTime, UNIX_EPOCH}; 12 | use std::{fs, process}; 13 | 14 | const DEFAULT_PRIVATE_KEY_PATH: &str = "private_key.sealed"; 15 | const DEFAULT_ENCLAVE_PATH: &str = "../pod-enclave/pod_enclave.signed.so"; 16 | 17 | static SIGNALED: AtomicBool = AtomicBool::new(false); 18 | 19 | extern "C" fn handle_signals(signal: libc::c_int) { 20 | let signal = Signal::try_from(signal).expect("valid raw signal value"); 21 | SIGNALED.store( 22 | signal == Signal::SIGINT || signal == Signal::SIGTERM, 23 | Ordering::Relaxed, 24 | ); 25 | } 26 | 27 | #[derive(Debug, Deserialize)] 28 | struct Config { 29 | private_key: PathBuf, 30 | enclave: PathBuf, 31 | log_output: PathBuf, 32 | } 33 | 34 | impl Default for Config { 35 | fn default() -> Self { 36 | let enclave = PathBuf::from(DEFAULT_ENCLAVE_PATH); 37 | let private_key = PathBuf::from(DEFAULT_PRIVATE_KEY_PATH); 38 | let log_output = PathBuf::from(log_filename()); 39 | Self { 40 | enclave, 41 | private_key, 42 | log_output, 43 | } 44 | } 45 | } 46 | 47 | enum Interrupt { 48 | Break, 49 | Continue, 50 | } 51 | 52 | enum Stdio { 53 | Stdin, 54 | Stdout, 55 | } 56 | 57 | fn stdio_with_interrupt(handle: Stdio, buffer: &mut [u8]) -> Result { 58 | let res = match handle { 59 | Stdio::Stdin => io::stdin().read_exact(buffer), 60 | Stdio::Stdout => io::stdout().write_all(buffer), 61 | }; 62 | match res { 63 | Ok(_) => Ok(Interrupt::Continue), 64 | Err(err) => { 65 | match err.kind() { 66 | io::ErrorKind::BrokenPipe | io::ErrorKind::UnexpectedEof => { 67 | // Unless we received a SIGTERM and the other closed the pipe 68 | // on purpose, we need to throw an error! 69 | if !SIGNALED.load(Ordering::Relaxed) { 70 | Err(anyhow!("Unexpected EOF or a broken pipe!")) 71 | } else { 72 | log::debug!("Received termination signal, exiting..."); 73 | Ok(Interrupt::Break) 74 | } 75 | } 76 | _ => Err(anyhow!( 77 | "failed to read message len from stdin (first 4 bytes): {}", 78 | err 79 | )), 80 | } 81 | } 82 | } 83 | } 84 | 85 | fn run(config: Config) -> Result<()> { 86 | // Install signal handler for SIGINT and SIGTERM 87 | let handler = SigHandler::Handler(handle_signals); 88 | unsafe { signal::signal(Signal::SIGTERM, handler)? }; 89 | unsafe { signal::signal(Signal::SIGINT, handler)? }; 90 | log::debug!("Registered SIGTERM and SIGINT signal handlers"); 91 | // Ok, first pass will load and unload enclave at each message received 92 | // event. However, this is definitely not optimal and we should spawn 93 | // it only once and hand out Arc<> to the spawned instance instead. 94 | // This will require some Mutexing though since PodEnclave is not safe to send 95 | // across thread boundaries. 96 | loop { 97 | if SIGNALED.load(Ordering::Relaxed) { 98 | log::debug!("Received termination signal, exiting..."); 99 | break; 100 | } 101 | 102 | let mut msg_len = [0u8; 4]; 103 | match stdio_with_interrupt(Stdio::Stdin, &mut msg_len) { 104 | Err(err) => return Err(err), 105 | Ok(Interrupt::Break) => break, 106 | Ok(Interrupt::Continue) => {} 107 | }; 108 | let msg_len = u32::from_ne_bytes(msg_len); 109 | let msg_len = usize::try_from(msg_len).expect("u32 should fit into usize"); 110 | 111 | if msg_len == 0 { 112 | if SIGNALED.load(Ordering::Relaxed) { 113 | log::debug!("Received termination signal, exiting..."); 114 | break; 115 | } 116 | 117 | // TODO is this correct behaviour? Should we actually simply carry on listening? 118 | continue; 119 | } 120 | 121 | log::debug!("Received message len (first 4 bytes): {}", msg_len); 122 | 123 | let mut msg = Vec::new(); 124 | msg.resize(msg_len as usize, 0); 125 | match stdio_with_interrupt(Stdio::Stdin, &mut msg) { 126 | Err(err) => return Err(err), 127 | Ok(Interrupt::Break) => break, 128 | Ok(Interrupt::Continue) => {} 129 | }; 130 | 131 | log::debug!("Message received"); 132 | 133 | let mut reply = reply(msg, &config)?; 134 | let reply_len: u32 = reply 135 | .len() 136 | .try_into() 137 | .context("reply len overflew 32bit register")?; 138 | match stdio_with_interrupt(Stdio::Stdout, &mut reply_len.to_ne_bytes()) { 139 | Err(err) => return Err(err), 140 | Ok(Interrupt::Break) => break, 141 | Ok(Interrupt::Continue) => {} 142 | }; 143 | 144 | log::debug!("Sent reply len: {}", reply_len); 145 | 146 | match stdio_with_interrupt(Stdio::Stdout, &mut reply) { 147 | Err(err) => return Err(err), 148 | Ok(Interrupt::Break) => break, 149 | Ok(Interrupt::Continue) => {} 150 | }; 151 | io::stdout().flush()?; 152 | 153 | log::debug!("Reply sent"); 154 | } 155 | 156 | Ok(()) 157 | } 158 | 159 | fn config() -> Config { 160 | // Firstly, check in xdg config folder. 161 | let dirs = xdg::BaseDirectories::with_prefix("pod-app") 162 | .expect("couldn't create xdg base dir instance"); 163 | 164 | match dirs.find_data_file("pod_enclave.signed.so") { 165 | Some(enclave) => { 166 | let data_home = dirs.get_data_home(); 167 | let private_key = data_home.join("private_key.sealed"); 168 | let log_output = data_home.join(log_filename()); 169 | 170 | Config { 171 | private_key, 172 | enclave, 173 | log_output, 174 | } 175 | } 176 | None => Config::default(), 177 | } 178 | } 179 | 180 | fn log_filename() -> String { 181 | // TODO add some stronger uniqueness to log names 182 | let now = SystemTime::now() 183 | .duration_since(UNIX_EPOCH) 184 | .expect("could get current system time"); 185 | format!("pod-app_{}.log", now.as_secs_f64()) 186 | } 187 | 188 | fn main() { 189 | let config = config(); 190 | let log_output = 191 | fs::File::create(&config.log_output).expect("could initialize file for logger output"); 192 | 193 | simplelog::WriteLogger::init( 194 | log::LevelFilter::Debug, 195 | simplelog::Config::default(), 196 | log_output, 197 | ) 198 | .expect("could initialize logger"); 199 | 200 | log::debug!("Application started..."); 201 | 202 | if let Err(err) = run(config) { 203 | log::error!("Unexpected error occurred: {}", err); 204 | process::exit(1); 205 | } 206 | 207 | log::debug!("Application successfully stopped..."); 208 | } 209 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /lib/api/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /lib/c-api/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /pod-app/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /pod-enclave/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /pod-ext/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /pod-server/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | --------------------------------------------------------------------------------
{ 74 | let spid = CString::new(spid.as_ref())?; 75 | let quote_type = match quote_type { 76 | QuoteType::Linkable => CString::new("l")?, 77 | QuoteType::Unlinkable => CString::new("u")?, 78 | }; 79 | let quote_buffer = &mut [0u8; MAX_QUOTE_SIZE]; 80 | let ret = unsafe { 81 | c::pod_get_quote( 82 | spid.as_ptr(), 83 | quote_type.as_ptr(), 84 | quote_buffer.as_mut_ptr(), 85 | MAX_QUOTE_SIZE, 86 | ) 87 | }; 88 | 89 | if ret < 0 { 90 | return Err(anyhow!( 91 | "pod_init_enclave returned non-zero exit code: {}", 92 | ret 93 | )); 94 | } 95 | let quote_size = usize::try_from(ret)?; 96 | Ok(Quote::from("e_buffer[..quote_size])) 97 | } 98 | 99 | pub(super) fn sign_buffer>(message: B) -> Result> { 100 | let message = message.as_ref(); 101 | let signature = &mut [0u8; EC_SIGNATURE]; 102 | let ret = unsafe { 103 | c::pod_sign_buffer( 104 | message.as_ptr() as *const _, 105 | message.len(), 106 | signature.as_mut_ptr() as *mut _, 107 | signature.len(), 108 | ) 109 | }; 110 | if ret != 0 { 111 | return Err(anyhow!( 112 | "pod_sign_buffer returned non-zero exit code: {}", 113 | ret 114 | )); 115 | } 116 | Ok(signature.to_vec()) 117 | } 118 | 119 | #[cfg(unix)] 120 | fn path_to_c_string>(path: P) -> Result { 121 | use std::os::unix::ffi::OsStrExt; 122 | let s = CString::new(path.as_ref().as_os_str().as_bytes())?; 123 | Ok(s) 124 | } 125 | 126 | #[cfg(windows)] 127 | fn path_to_c_string(path: &Path) -> Result { 128 | use std::os::windows::ffi::OsStringExt; 129 | let utf16: Vec<_> = path.as_os_str().encode_wide().collect(); 130 | let s = String::from_utf16(utf16)?; 131 | let s = CString::new(s.as_bytes())?; 132 | Ok(s) 133 | } 134 | -------------------------------------------------------------------------------- /pod-server/src/handlers/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod auth; 2 | pub mod register; 3 | 4 | use actix_identity::Identity; 5 | use actix_web::dev::HttpResponseBuilder; 6 | use actix_web::http::StatusCode; 7 | use actix_web::{HttpResponse, Responder, ResponseError}; 8 | use serde::Serialize; 9 | use std::collections::HashMap; 10 | 11 | pub async fn index(identity: Identity) -> impl Responder { 12 | match identity.identity() { 13 | Some(_) => Ok(HttpResponse::NoContent()), 14 | None => Err(AppError::NotAuthenticated), 15 | } 16 | } 17 | 18 | #[derive(Serialize)] 19 | enum Status { 20 | Ok, 21 | Error, 22 | } 23 | 24 | #[derive(Serialize)] 25 | struct Message { 26 | status: Status, 27 | #[serde(flatten)] 28 | params: HashMap, 29 | } 30 | 31 | impl Message { 32 | fn ok() -> Self { 33 | Self { 34 | status: Status::Ok, 35 | params: HashMap::new(), 36 | } 37 | } 38 | 39 | fn error() -> Self { 40 | Self { 41 | status: Status::Error, 42 | params: HashMap::new(), 43 | } 44 | } 45 | 46 | fn add_param, S2: AsRef>(mut self, key: S1, value: S2) -> Self { 47 | self.params 48 | .insert(key.as_ref().to_owned(), value.as_ref().to_owned()); 49 | self 50 | } 51 | } 52 | 53 | #[derive(Debug, thiserror::Error)] 54 | enum AppError { 55 | #[error("user not registered yet")] 56 | NotRegistered, 57 | #[error("user already registered")] 58 | AlreadyRegistered, 59 | #[error("invalid challenge")] 60 | InvalidChallenge, 61 | #[error("invalid cookie")] 62 | InvalidCookie, 63 | #[error("user not authenticated")] 64 | NotAuthenticated, 65 | #[error("user already authenticated")] 66 | AlreadyAuthenticated, 67 | #[error("tokio_diesel async op failed with error: {}", _0)] 68 | TokioDieselAsync(#[from] tokio_diesel::AsyncError), 69 | #[error("attesting quote failed with error: {}", _0)] 70 | RustSgxUtil(#[from] rust_sgx_util::Error), 71 | #[error("r2d2 pool error: {}", _0)] 72 | R2d2Pool(#[from] diesel::r2d2::PoolError), 73 | #[error("diesel result error {}", _0)] 74 | DieselResult(#[from] diesel::result::Error), 75 | #[error("var not found in env: {}", _0)] 76 | Var(#[from] std::env::VarError), 77 | #[error("blocking operation was canceled prematurely")] 78 | ActixBlockingCanceled, 79 | #[error("decoding base64 to blob: {}", _0)] 80 | Base64Decode(#[from] base64::DecodeError), 81 | #[error("parsing ed25519 signature: {}", _0)] 82 | Ed25519Signature(#[from] ed25519_dalek::SignatureError), 83 | #[error("fetching entropy: {}", _0)] 84 | GetRandom(#[from] getrandom::Error), 85 | } 86 | 87 | impl ResponseError for AppError { 88 | fn error_response(&self) -> HttpResponse { 89 | let (code, message) = match self { 90 | AppError::NotRegistered => (StatusCode::FORBIDDEN, Message::error()), 91 | AppError::AlreadyRegistered => (StatusCode::OK, Message::ok()), 92 | AppError::InvalidChallenge => (StatusCode::OK, Message::error()), 93 | AppError::InvalidCookie => (StatusCode::OK, Message::error()), 94 | AppError::NotAuthenticated => (StatusCode::FORBIDDEN, Message::error()), 95 | AppError::AlreadyAuthenticated => (StatusCode::OK, Message::ok()), 96 | AppError::TokioDieselAsync(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 97 | AppError::RustSgxUtil(_) => (StatusCode::OK, Message::error()), 98 | AppError::R2d2Pool(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 99 | AppError::DieselResult(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 100 | AppError::Var(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 101 | AppError::ActixBlockingCanceled => { 102 | (StatusCode::INTERNAL_SERVER_ERROR, Message::error()) 103 | } 104 | AppError::Base64Decode(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 105 | AppError::Ed25519Signature(_) => (StatusCode::OK, Message::error()), 106 | AppError::GetRandom(_) => (StatusCode::INTERNAL_SERVER_ERROR, Message::error()), 107 | }; 108 | HttpResponseBuilder::new(code).json(message.add_param("description", format!("{}", self))) 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /pod-web/src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' }, 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready 134 | .then(registration => { 135 | registration.unregister(); 136 | }) 137 | .catch(error => { 138 | console.error(error.message); 139 | }); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /lib/rust-sgx-util/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! A safe wrapper around Graphene's [`sgx_util`] C-library. 2 | //! 3 | //! [`sgx_util`]: https://github.com/oscarlab/graphene/tree/master/Pal/src/host/Linux-SGX/tools 4 | //! 5 | //! ```toml 6 | //! rust-sgx-util = "0.2" 7 | //! ``` 8 | //! 9 | //! For `serde` support, you can enable it with `with_serde` feature: 10 | //! 11 | //! ```toml 12 | //! rust-sgx-util = { version = "0.2", features = ["with_serde"] } 13 | //! ``` 14 | //! 15 | //! ## Prerequisites 16 | //! 17 | //! Currently, this crate requires you compile and install `sgx_util` as 18 | //! a shared library. 19 | //! 20 | //! ## Usage examples 21 | //! 22 | //! You can find usage examples in the `examples` dir of the crate. 23 | //! 24 | mod c; 25 | mod ias; 26 | #[cfg(feature = "with_serde")] 27 | mod ser_de; 28 | 29 | pub use ias::*; 30 | 31 | #[cfg(feature = "with_serde")] 32 | use serde::{Deserialize, Serialize}; 33 | use std::convert::TryFrom; 34 | use std::ops::Deref; 35 | 36 | /// Convenience wrapper around fallible operation. 37 | pub type Result = std::result::Result; 38 | 39 | /// Error type thrown by fallible operations in this crate. 40 | #[derive(Debug, thiserror::Error)] 41 | pub enum Error { 42 | /// Failed to initialize `IasHandle`. 43 | #[error("failed to initialize IasHandle")] 44 | IasInitNullPtr, 45 | /// `Quote`'s size is too small. 46 | #[error("quote's size is too small")] 47 | QuoteTooShort, 48 | /// `Nonce` exceeded 32 bytes. 49 | #[error("nonce exceeded 32 bytes")] 50 | NonceTooLong, 51 | /// `IasHandle::get_sigrl` returned nonzero return code. 52 | #[error("get_sigrl returned nonzero return code: {}", _0)] 53 | IasGetSigrlNonZero(i32), 54 | /// `IasHandle::verify_quote` returned nonzero return code. 55 | #[error("verify_quote returned nonzero return code: {}", _0)] 56 | IasVerifyQuoteNonZero(i32), 57 | /// Error while parsing int from string. 58 | #[error("parsing int from string: {:?}", _0)] 59 | ParseInt(#[from] std::num::ParseIntError), 60 | /// Found unexpected interior nul byte. 61 | #[error("unexpected interior nul byte: {:?}", _0)] 62 | Nul(#[from] std::ffi::NulError), 63 | /// (Windows only) Encountered invalid UTF16. 64 | #[error("invalid UTF16 encountered: {:?}", _0)] 65 | Utf16(#[from] std::string::FromUtf16Error), 66 | } 67 | 68 | /// Set verbosity on/off. 69 | pub fn set_verbose(verbose: bool) { 70 | unsafe { c::set_verbose(verbose) } 71 | } 72 | 73 | /// A thin wrapper around vector of bytes. Represents quote obtained 74 | /// from the challenged enclave. 75 | /// 76 | /// # Accessing the underlying bytes buffer 77 | /// 78 | /// `Quote` implements `Deref`, therefore dereferencing it will 79 | /// yield its inner buffer of bytes. 80 | /// 81 | /// # Serializing/deserializing 82 | /// 83 | /// With `with_serde` feature enabled, `Quote` can be serialized and deserialized 84 | /// as base64 `String`. 85 | #[derive(Debug, Clone)] 86 | #[cfg_attr(feature = "with_serde", derive(Serialize, Deserialize))] 87 | pub struct Quote(#[cfg_attr(feature = "with_serde", serde(with = "ser_de"))] Vec); 88 | 89 | impl Quote { 90 | const REPORT_BEGIN: usize = 368; 91 | const REPORT_END: usize = 432; 92 | 93 | /// Returns `report_data` bytes embedded within this `Quote`. 94 | /// 95 | /// The size of the returned slice is 64 bytes. 96 | /// 97 | /// # Errors 98 | /// 99 | /// This function will fail with [`Error::QuoteTooShort`] if `Quote` 100 | /// is shorter than `432` bytes. Note that this is only a quick check 101 | /// that we can extract the region in `Quote`'s buffer where we expect 102 | /// the `report_data` to lie in. We don't do any validations on the 103 | /// `Quote` in this method. 104 | /// 105 | /// [`Error::QuoteTooShort`]: enum.Error.html#variant.QuoteTooShort 106 | /// 107 | /// # Examples 108 | /// 109 | /// ``` 110 | /// # use rust_sgx_util::Quote; 111 | /// let quote = Quote::from(&[0u8; 438][..]); 112 | /// assert_eq!(quote.report_data().unwrap().len(), 64); 113 | /// 114 | /// let quote = Quote::from(&[0u8; 10][..]); 115 | /// assert!(quote.report_data().is_err()); 116 | /// ``` 117 | pub fn report_data(&self) -> Result<&[u8]> { 118 | self.0 119 | .get(Self::REPORT_BEGIN..Self::REPORT_END) 120 | .ok_or(Error::QuoteTooShort) 121 | } 122 | } 123 | 124 | impl From<&[u8]> for Quote { 125 | fn from(bytes: &[u8]) -> Self { 126 | Self::from(bytes.to_vec()) 127 | } 128 | } 129 | 130 | impl From> for Quote { 131 | fn from(bytes: Vec) -> Self { 132 | Self(bytes) 133 | } 134 | } 135 | 136 | impl Deref for Quote { 137 | type Target = [u8]; 138 | 139 | fn deref(&self) -> &Self::Target { 140 | &self.0 141 | } 142 | } 143 | 144 | /// A thin wrapper around vector of bytes. Represents nonce obtained 145 | /// from the challenged enclave. 146 | /// 147 | /// Nonce cannot be longer than 32 bytes. 148 | /// 149 | /// # Accessing the underlying bytes buffer 150 | /// 151 | /// `Nonce` implements `Deref`, therefore dereferencing it will 152 | /// yield its inner buffer of bytes. 153 | /// 154 | /// # Serializing/deserializing 155 | /// 156 | /// With `with_serde` feature enabled, `Nonce` can be serialized and deserialized 157 | /// as base64 `String`. 158 | #[derive(Debug, Clone)] 159 | #[cfg_attr(feature = "with_serde", derive(Serialize, Deserialize))] 160 | pub struct Nonce(#[cfg_attr(feature = "with_serde", serde(with = "ser_de"))] Vec); 161 | 162 | impl Nonce { 163 | fn new>>(bytes: B) -> Result { 164 | let bytes = bytes.into(); 165 | if bytes.len() > 32 { 166 | return Err(Error::NonceTooLong); 167 | } 168 | Ok(Self(bytes)) 169 | } 170 | } 171 | 172 | impl TryFrom<&[u8]> for Nonce { 173 | type Error = Error; 174 | 175 | fn try_from(bytes: &[u8]) -> Result { 176 | Self::new(bytes) 177 | } 178 | } 179 | 180 | impl Deref for Nonce { 181 | type Target = [u8]; 182 | 183 | fn deref(&self) -> &Self::Target { 184 | &self.0 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /pod-app/examples/webservice_client.rs: -------------------------------------------------------------------------------- 1 | use actix_web::client::Client; 2 | use actix_web::HttpMessage; 3 | use anyhow::anyhow; 4 | use pod_api::{PodEnclave, QuoteType}; 5 | use rust_sgx_util::Quote; 6 | use serde::Serialize; 7 | use structopt::StructOpt; 8 | 9 | const SEALED_KEYS_PATH: &str = "pod_data.sealed"; 10 | const ENCLAVE_PATH: &str = "../pod-enclave/pod_enclave.signed.so"; 11 | 12 | #[derive(Debug, StructOpt)] 13 | struct Opt { 14 | /// Server address to connect to (defaults to 127.0.0.1). 15 | #[structopt(long)] 16 | address: Option, 17 | /// Server port to connect to (defaults to 8080). 18 | #[structopt(long)] 19 | port: Option, 20 | #[structopt(subcommand)] 21 | cmd: Command, 22 | } 23 | 24 | #[derive(Debug, StructOpt)] 25 | enum Command { 26 | /// Register with the service. 27 | Register { 28 | /// Your username. 29 | login: String, 30 | /// Service Provider's ID (SPID) as given by the SP. 31 | spid: String, 32 | }, 33 | /// Authenticate with the service. 34 | Authenticate { 35 | /// Your username. 36 | login: String, 37 | }, 38 | } 39 | 40 | #[derive(Serialize)] 41 | struct RegisterInfo { 42 | login: String, 43 | quote: Quote, 44 | } 45 | 46 | #[derive(Serialize)] 47 | struct ChallengeResponse { 48 | login: String, 49 | response: String, 50 | } 51 | 52 | #[actix_rt::main] 53 | async fn main() -> anyhow::Result<()> { 54 | let opt = Opt::from_args(); 55 | // Turn on enclave logging 56 | pod_api::set_verbose(true); 57 | 58 | let address = opt.address.unwrap_or_else(|| "127.0.0.1".to_owned()); 59 | let port = opt.port.unwrap_or(8080); 60 | let base_uri = format!("http://{}:{}", address, port); 61 | let client = Client::default(); 62 | let pod_enclave = PodEnclave::new(ENCLAVE_PATH, SEALED_KEYS_PATH)?; 63 | 64 | match opt.cmd { 65 | Command::Register { login, spid } => { 66 | // Get the quote 67 | let quote = pod_enclave.get_quote(&spid, QuoteType::Unlinkable)?; 68 | 69 | println!("POST /register"); 70 | let mut response = client 71 | .post(format!("{}/register", base_uri)) 72 | .header("User-Agent", "TestClient") 73 | .send_json(&RegisterInfo { 74 | login: login.clone(), 75 | quote, 76 | }) 77 | .await 78 | .map_err(|err| anyhow!("{:?}", err))?; 79 | println!(" | status_code: {}", response.status()); 80 | let body = response.body().await.map_err(|err| anyhow!("{:?}", err))?; 81 | let content_length = body.len(); 82 | println!(" | content-length: {}", content_length); 83 | 84 | if content_length > 0 { 85 | let json: serde_json::Value = serde_json::from_slice(&body)?; 86 | println!(" | body: {}", json); 87 | } 88 | } 89 | Command::Authenticate { login } => { 90 | println!("GET /auth"); 91 | let mut response = client 92 | .get(format!("{}/auth", base_uri)) 93 | .header("User-Agent", "TestClient") 94 | .send() 95 | .await 96 | .map_err(|err| anyhow!("{:?}", err))?; 97 | let status_code = response.status(); 98 | println!(" | status_code: {}", status_code); 99 | let body = response.body().await.map_err(|err| anyhow!("{:?}", err))?; 100 | let content_length = body.len(); 101 | println!(" | content-length: {}", content_length); 102 | let cookies = response.cookies()?.clone(); 103 | for cookie in &cookies { 104 | println!(" | cookie: {}", cookie); 105 | } 106 | if status_code != 200 { 107 | return Err(anyhow!("Expected GET /auth to return 200")); 108 | } 109 | let json: serde_json::Value = serde_json::from_slice(&body)?; 110 | println!(" | body: {}", json); 111 | 112 | // Process challenge 113 | let challenge = json["challenge"] 114 | .as_str() 115 | .ok_or(anyhow!("invalid String for challenge"))?; 116 | let challenge = base64::decode(challenge)?; 117 | let response = pod_enclave.sign(&challenge)?; 118 | let response = base64::encode(&response[..]); 119 | 120 | println!("\nPOST /auth"); 121 | let mut builder = client 122 | .post(format!("{}/auth", base_uri)) 123 | .header("User-Agent", "TestClient"); 124 | for cookie in cookies { 125 | builder = builder.cookie(cookie); 126 | } 127 | let mut response = builder 128 | .send_json(&ChallengeResponse { login, response }) 129 | .await 130 | .map_err(|err| anyhow!("{:?}", err))?; 131 | println!(" | status_code: {}", response.status()); 132 | let body = response.body().await.map_err(|err| anyhow!("{:?}", err))?; 133 | let content_length = body.len(); 134 | println!(" | content-length: {}", content_length); 135 | let cookies = response.cookies()?.clone(); 136 | for cookie in &cookies { 137 | println!(" | cookie: {}", cookie); 138 | } 139 | 140 | if content_length > 0 { 141 | let json: serde_json::Value = serde_json::from_slice(&body)?; 142 | println!(" | body: {}", json); 143 | } 144 | 145 | println!("\n GET /"); 146 | let mut builder = client.get(&base_uri).header("User-Agent", "TestClient"); 147 | for cookie in cookies { 148 | builder = builder.cookie(cookie); 149 | } 150 | let mut response = builder.send().await.map_err(|err| anyhow!("{:?}", err))?; 151 | println!(" | status_code: {}", response.status()); 152 | let body = response.body().await.map_err(|err| anyhow!("{:?}", err))?; 153 | let content_length = body.len(); 154 | println!(" | content-length: {}", content_length); 155 | let json: serde_json::Value = serde_json::from_slice(&body)?; 156 | println!(" | body: {}", json); 157 | } 158 | } 159 | 160 | Ok(()) 161 | } 162 | -------------------------------------------------------------------------------- /pod-web/src/assets/pod-enabled.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pod-app/src/main.rs: -------------------------------------------------------------------------------- 1 | mod messages; 2 | 3 | use anyhow::{anyhow, Context, Result}; 4 | use messages::reply; 5 | use nix::sys::signal::{self, SigHandler, Signal}; 6 | use serde::Deserialize; 7 | use std::convert::{TryFrom, TryInto}; 8 | use std::io::{self, Read, Write}; 9 | use std::path::PathBuf; 10 | use std::sync::atomic::{AtomicBool, Ordering}; 11 | use std::time::{SystemTime, UNIX_EPOCH}; 12 | use std::{fs, process}; 13 | 14 | const DEFAULT_PRIVATE_KEY_PATH: &str = "private_key.sealed"; 15 | const DEFAULT_ENCLAVE_PATH: &str = "../pod-enclave/pod_enclave.signed.so"; 16 | 17 | static SIGNALED: AtomicBool = AtomicBool::new(false); 18 | 19 | extern "C" fn handle_signals(signal: libc::c_int) { 20 | let signal = Signal::try_from(signal).expect("valid raw signal value"); 21 | SIGNALED.store( 22 | signal == Signal::SIGINT || signal == Signal::SIGTERM, 23 | Ordering::Relaxed, 24 | ); 25 | } 26 | 27 | #[derive(Debug, Deserialize)] 28 | struct Config { 29 | private_key: PathBuf, 30 | enclave: PathBuf, 31 | log_output: PathBuf, 32 | } 33 | 34 | impl Default for Config { 35 | fn default() -> Self { 36 | let enclave = PathBuf::from(DEFAULT_ENCLAVE_PATH); 37 | let private_key = PathBuf::from(DEFAULT_PRIVATE_KEY_PATH); 38 | let log_output = PathBuf::from(log_filename()); 39 | Self { 40 | enclave, 41 | private_key, 42 | log_output, 43 | } 44 | } 45 | } 46 | 47 | enum Interrupt { 48 | Break, 49 | Continue, 50 | } 51 | 52 | enum Stdio { 53 | Stdin, 54 | Stdout, 55 | } 56 | 57 | fn stdio_with_interrupt(handle: Stdio, buffer: &mut [u8]) -> Result { 58 | let res = match handle { 59 | Stdio::Stdin => io::stdin().read_exact(buffer), 60 | Stdio::Stdout => io::stdout().write_all(buffer), 61 | }; 62 | match res { 63 | Ok(_) => Ok(Interrupt::Continue), 64 | Err(err) => { 65 | match err.kind() { 66 | io::ErrorKind::BrokenPipe | io::ErrorKind::UnexpectedEof => { 67 | // Unless we received a SIGTERM and the other closed the pipe 68 | // on purpose, we need to throw an error! 69 | if !SIGNALED.load(Ordering::Relaxed) { 70 | Err(anyhow!("Unexpected EOF or a broken pipe!")) 71 | } else { 72 | log::debug!("Received termination signal, exiting..."); 73 | Ok(Interrupt::Break) 74 | } 75 | } 76 | _ => Err(anyhow!( 77 | "failed to read message len from stdin (first 4 bytes): {}", 78 | err 79 | )), 80 | } 81 | } 82 | } 83 | } 84 | 85 | fn run(config: Config) -> Result<()> { 86 | // Install signal handler for SIGINT and SIGTERM 87 | let handler = SigHandler::Handler(handle_signals); 88 | unsafe { signal::signal(Signal::SIGTERM, handler)? }; 89 | unsafe { signal::signal(Signal::SIGINT, handler)? }; 90 | log::debug!("Registered SIGTERM and SIGINT signal handlers"); 91 | // Ok, first pass will load and unload enclave at each message received 92 | // event. However, this is definitely not optimal and we should spawn 93 | // it only once and hand out Arc<> to the spawned instance instead. 94 | // This will require some Mutexing though since PodEnclave is not safe to send 95 | // across thread boundaries. 96 | loop { 97 | if SIGNALED.load(Ordering::Relaxed) { 98 | log::debug!("Received termination signal, exiting..."); 99 | break; 100 | } 101 | 102 | let mut msg_len = [0u8; 4]; 103 | match stdio_with_interrupt(Stdio::Stdin, &mut msg_len) { 104 | Err(err) => return Err(err), 105 | Ok(Interrupt::Break) => break, 106 | Ok(Interrupt::Continue) => {} 107 | }; 108 | let msg_len = u32::from_ne_bytes(msg_len); 109 | let msg_len = usize::try_from(msg_len).expect("u32 should fit into usize"); 110 | 111 | if msg_len == 0 { 112 | if SIGNALED.load(Ordering::Relaxed) { 113 | log::debug!("Received termination signal, exiting..."); 114 | break; 115 | } 116 | 117 | // TODO is this correct behaviour? Should we actually simply carry on listening? 118 | continue; 119 | } 120 | 121 | log::debug!("Received message len (first 4 bytes): {}", msg_len); 122 | 123 | let mut msg = Vec::new(); 124 | msg.resize(msg_len as usize, 0); 125 | match stdio_with_interrupt(Stdio::Stdin, &mut msg) { 126 | Err(err) => return Err(err), 127 | Ok(Interrupt::Break) => break, 128 | Ok(Interrupt::Continue) => {} 129 | }; 130 | 131 | log::debug!("Message received"); 132 | 133 | let mut reply = reply(msg, &config)?; 134 | let reply_len: u32 = reply 135 | .len() 136 | .try_into() 137 | .context("reply len overflew 32bit register")?; 138 | match stdio_with_interrupt(Stdio::Stdout, &mut reply_len.to_ne_bytes()) { 139 | Err(err) => return Err(err), 140 | Ok(Interrupt::Break) => break, 141 | Ok(Interrupt::Continue) => {} 142 | }; 143 | 144 | log::debug!("Sent reply len: {}", reply_len); 145 | 146 | match stdio_with_interrupt(Stdio::Stdout, &mut reply) { 147 | Err(err) => return Err(err), 148 | Ok(Interrupt::Break) => break, 149 | Ok(Interrupt::Continue) => {} 150 | }; 151 | io::stdout().flush()?; 152 | 153 | log::debug!("Reply sent"); 154 | } 155 | 156 | Ok(()) 157 | } 158 | 159 | fn config() -> Config { 160 | // Firstly, check in xdg config folder. 161 | let dirs = xdg::BaseDirectories::with_prefix("pod-app") 162 | .expect("couldn't create xdg base dir instance"); 163 | 164 | match dirs.find_data_file("pod_enclave.signed.so") { 165 | Some(enclave) => { 166 | let data_home = dirs.get_data_home(); 167 | let private_key = data_home.join("private_key.sealed"); 168 | let log_output = data_home.join(log_filename()); 169 | 170 | Config { 171 | private_key, 172 | enclave, 173 | log_output, 174 | } 175 | } 176 | None => Config::default(), 177 | } 178 | } 179 | 180 | fn log_filename() -> String { 181 | // TODO add some stronger uniqueness to log names 182 | let now = SystemTime::now() 183 | .duration_since(UNIX_EPOCH) 184 | .expect("could get current system time"); 185 | format!("pod-app_{}.log", now.as_secs_f64()) 186 | } 187 | 188 | fn main() { 189 | let config = config(); 190 | let log_output = 191 | fs::File::create(&config.log_output).expect("could initialize file for logger output"); 192 | 193 | simplelog::WriteLogger::init( 194 | log::LevelFilter::Debug, 195 | simplelog::Config::default(), 196 | log_output, 197 | ) 198 | .expect("could initialize logger"); 199 | 200 | log::debug!("Application started..."); 201 | 202 | if let Err(err) = run(config) { 203 | log::error!("Unexpected error occurred: {}", err); 204 | process::exit(1); 205 | } 206 | 207 | log::debug!("Application successfully stopped..."); 208 | } 209 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /lib/api/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /lib/c-api/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /pod-app/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /pod-enclave/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /pod-ext/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /pod-server/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | --------------------------------------------------------------------------------