Browse Source

Load the config into the enclave

Ian Goldberg 1 year ago
parent
commit
5580976796

+ 60 - 2
App/appconfig.cpp

@@ -1,4 +1,5 @@
 #include <iostream>
+#include "Untrusted.hpp"
 #include "appconfig.hpp"
 
 // The next line suppresses a deprecation warning within boost
@@ -21,6 +22,41 @@ static bool split_host_port(std::string &host, std::string &port,
     return true;
 }
 
+// Convert a single hex character into its value from 0 to 15. Return
+// true on success, false if it wasn't a hex character.
+static inline bool hextoval(unsigned char &val, char hex)
+{
+    if (hex >= '0' && hex <= '9') {
+        val = ((unsigned char)hex)-'0';
+    } else if (hex >= 'a' && hex <= 'f') {
+        val = ((unsigned char)hex)-'a'+10;
+    } else if (hex >= 'A' && hex <= 'F') {
+        val = ((unsigned char)hex)-'A'+10;
+    } else {
+        return false;
+    }
+    return true;
+}
+
+// Convert a 2*len hex character string into a len-byte buffer. Return
+// true on success, false on failure.
+static bool hextobuf(unsigned char *buf, const char *str, size_t len)
+{
+    if (strlen(str) != 2*len) {
+        std::cerr << "Hex string was not the expected size\n";
+        return false;
+    }
+    for (size_t i=0;i<len;++i) {
+        unsigned char hi, lo;
+        if (!hextoval(hi, str[2*i]) || !hextoval(lo, str[2*i+1])) {
+            std::cerr << "Cannot parse string as hex\n";
+            return false;
+        }
+        buf[i] = (unsigned char)((hi << 4) + lo);
+    }
+    return true;
+}
+
 bool config_parse(Config &config, const std::string configstr,
     const std::string &myname)
 {
@@ -53,11 +89,14 @@ bool config_parse(Config &config, const std::string configstr,
                     if (!nentry.first.compare("name")) {
                         nc.name = nentry.second.get_value<std::string>();
                         if (!myname.compare(nc.name)) {
-                            config.my_node_num = config.nodes.size();
+                            config.my_node_num =
+                                nodenum_t(config.nodes.size());
                             found_my_node = true;
                         }
                     } else if (!nentry.first.compare("pubkey")) {
-                        nc.pubkey = nentry.second.get_value<std::string>();
+                        ret &= hextobuf((unsigned char *)&nc.pubkey,
+                            nentry.second.get_value<std::string>().c_str(),
+                            sizeof(nc.pubkey));
                     } else if (!nentry.first.compare("weight")) {
                         nc.weight = nentry.second.get_value<std::uint8_t>();
                     } else if (!nentry.first.compare("listen")) {
@@ -90,5 +129,24 @@ bool config_parse(Config &config, const std::string configstr,
         ret = false;
     }
 
+    if (!ret) return ret;
+
+    // Now load the config into the enclave
+    EnclaveAPIParams apiparams;
+    apiparams.msgsize = config.msgsize;
+    nodenum_t num_nodes = (nodenum_t)(config.nodes.size());
+    std::vector<EnclaveAPINodeConfig> apinodeconfigs;
+    apinodeconfigs.resize(num_nodes);
+    for (nodenum_t i=0; i<num_nodes; ++i) {
+        memmove(&apinodeconfigs[i].pubkey,
+            &config.nodes[i].pubkey, sizeof(apinodeconfigs[i].pubkey));
+        apinodeconfigs[i].weight = config.nodes[i].weight;
+    }
+    ret &= ecall_config_load(&apiparams, apinodeconfigs.data(),
+        num_nodes, config.my_node_num);
+    if (!ret) {
+        std::cerr << "Loading config into enclave failed\n";
+    }
+
     return ret;
 }

+ 4 - 2
App/appconfig.hpp

@@ -4,11 +4,13 @@
 #include <string>
 #include <vector>
 #include <cstdint>
+#include "sgx_tcrypto.h"
+#include "../Enclave/enclave_api.h"
 
 // The per-node config
 struct NodeConfig {
     std::string name;
-    std::string pubkey;  // a 128-character hex string
+    sgx_ec256_public_t pubkey;
     std::string listenhost, listenport;
     std::string clistenhost, clistenport;
     uint8_t weight;
@@ -21,7 +23,7 @@ struct Config {
     // config for each node
     std::vector<NodeConfig> nodes;
     // Which node is this one?
-    size_t my_node_num;
+    nodenum_t my_node_num;
 };
 
 bool config_parse(Config &config, const std::string configstr,

+ 4 - 10
App/teems.cpp

@@ -37,12 +37,9 @@ static bool hexdump(FILE *outf, const char *label, void *p, size_t len)
 // already there).  Return true on success, false on failure.
 static bool genkey(const char *sealedprivkeyfile, const char *pubkeyfile)
 {
-    size_t sealedprivsize =
-        sizeof(sgx_sealed_data_t) + sizeof(sgx_ec256_private_t) + 19;
-
     sgx_ec256_public_t pubkey;
     sgx_sealed_data_t *sealedprivkey =
-        (sgx_sealed_data_t *)malloc(sealedprivsize);
+        (sgx_sealed_data_t *)malloc(SEALED_PRIVKEY_SIZE);
 
     ecall_identity_key_new(&pubkey, sealedprivkey);
 
@@ -54,7 +51,7 @@ static bool genkey(const char *sealedprivkeyfile, const char *pubkeyfile)
         perror("Sealed privkey write failed");
         return false;
     }
-    if (fwrite(sealedprivkey, sealedprivsize, 1, sprivf) != 1) {
+    if (fwrite(sealedprivkey, SEALED_PRIVKEY_SIZE, 1, sprivf) != 1) {
         fclose(sprivf);
         free(sealedprivkey);
         perror("Sealed privkey write failed");
@@ -89,14 +86,11 @@ static bool genkey(const char *sealedprivkeyfile, const char *pubkeyfile)
 // present.  Return true on success, false on failure.
 static bool loadkey(FILE *sprivf, const char *pubkeyfile)
 {
-    size_t sealedprivsize =
-        sizeof(sgx_sealed_data_t) + sizeof(sgx_ec256_private_t) + 19;
-
     sgx_ec256_public_t pubkey;
     sgx_sealed_data_t *sealedprivkey =
-        (sgx_sealed_data_t *)malloc(sealedprivsize);
+        (sgx_sealed_data_t *)malloc(SEALED_PRIVKEY_SIZE);
 
-    if (fread(sealedprivkey, sealedprivsize, 1, sprivf) != 1) {
+    if (fread(sealedprivkey, SEALED_PRIVKEY_SIZE, 1, sprivf) != 1) {
         fprintf(stderr, "Could not read sealed privkey file\n");
         return false;
     }

+ 8 - 2
Enclave/Enclave.edl

@@ -2,15 +2,21 @@ enclave {
     include "stdbool.h"
     include "sgx_tcrypto.h"
     include "sgx_tseal.h"
+    include "../Enclave/enclave_api.h"
 
     trusted {
         public void ecall_identity_key_new(
             [out] sgx_ec256_public_t *outpub,
-            [out,size=611] sgx_sealed_data_t *outsealedpriv);
+            [out,size=610] sgx_sealed_data_t *outsealedpriv);
 
         public bool ecall_identity_key_load(
             [out] sgx_ec256_public_t *outpub,
-            [in,size=611] const sgx_sealed_data_t *insealedpriv);
+            [in,size=610] const sgx_sealed_data_t *insealedpriv);
+
+        public bool ecall_config_load(
+            [in] struct EnclaveAPIParams *apiparams,
+            [in,count=num_nodes] struct EnclaveAPINodeConfig *apinodeconfigs,
+            nodenum_t num_nodes, nodenum_t my_node_num);
     };
 
     untrusted {

+ 59 - 8
Enclave/comms.cpp

@@ -1,17 +1,28 @@
+#include <vector>
 #include <cstring>
 
 #include "sgx_tcrypto.h"
 #include "sgx_tseal.h"
 #include "Enclave_t.h"
 #include "utils.hpp"
+#include "config.hpp"
 
 // Our public and private identity keys
-sgx_ec256_private_t g_privkey;
-sgx_ec256_public_t g_pubkey;
+static sgx_ec256_private_t g_privkey;
+static sgx_ec256_public_t g_pubkey;
+
+// Communication state for a node
+struct NodeCommState {
+    sgx_ec256_public_t pubkey;
+};
+
+// The communication states for all the nodes.  There's an entry for
+// ourselves in here, but it is unused.
+static std::vector<NodeCommState> commstates;
 
 // Generate a new identity signature key.  Output the public key and the
-// sealed private key.  outsealedpriv must point to
-// sizeof(sgx_sealed_data_t) + sizeof(sgx_ec256_private_t) + 19 bytes of
+// sealed private key.  outsealedpriv must point to SEALEDPRIVKEY_SIZE =
+// sizeof(sgx_sealed_data_t) + sizeof(sgx_ec256_private_t) + 18 bytes of
 // memory.
 void ecall_identity_key_new(sgx_ec256_public_t *outpub,
     sgx_sealed_data_t *outsealedpriv)
@@ -25,10 +36,9 @@ void ecall_identity_key_new(sgx_ec256_public_t *outpub,
 
     sgx_ecc256_close_context(ecc_handle);
 
-    sgx_seal_data(19, (const uint8_t*)"TEEMS Identity key",
+    sgx_seal_data(18, (const uint8_t*)"TEEMS Identity key",
         sizeof(g_privkey), (const uint8_t*)&g_privkey,
-        sizeof(sgx_sealed_data_t) + sizeof(sgx_ec256_private_t) + 19,
-        outsealedpriv);
+        SEALED_PRIVKEY_SIZE, outsealedpriv);
 }
 
 // Load an identity key from a sealed privkey.  Output the resulting
@@ -40,7 +50,7 @@ bool ecall_identity_key_load(sgx_ec256_public_t *outpub,
 {
     sgx_ecc_state_handle_t ecc_handle;
 
-    char aad[19];
+    char aad[18];
     uint32_t aadsize = sizeof(aad);
     sgx_ec256_private_t privkey;
     uint32_t privkeysize = sizeof(privkey);
@@ -72,3 +82,44 @@ bool ecall_identity_key_load(sgx_ec256_public_t *outpub,
 
     return true;
 }
+
+bool comms_init_nodestate(const EnclaveAPINodeConfig *apinodeconfigs,
+    nodenum_t num_nodes, nodenum_t my_node_num)
+{
+    sgx_ecc_state_handle_t ecc_handle;
+    sgx_ecc256_open_context(&ecc_handle);
+
+    commstates.clear();
+    commstates.resize(num_nodes);
+    for (nodenum_t i=0; i<num_nodes; ++i) {
+        // Check that the pubkey is valid
+        int valid;
+        if (sgx_ecc256_check_point(&apinodeconfigs[i].pubkey,
+                ecc_handle, &valid) ||
+                !valid) {
+            printf("Pubkey for node %hu invalid\n", i);
+            commstates.clear();
+            sgx_ecc256_close_context(ecc_handle);
+            return false;
+        }
+        memmove(&commstates[i].pubkey, &apinodeconfigs[i].pubkey,
+            sizeof(commstates[i].pubkey));
+    }
+    sgx_ecc256_close_context(ecc_handle);
+
+    // Check that no one other than us has our pubkey (deals with
+    // reflection attacks)
+    for (nodenum_t i=0; i<num_nodes; ++i) {
+        if (i == my_node_num) continue;
+        if (!memcmp(&commstates[i].pubkey,
+                &commstates[my_node_num].pubkey,
+                sizeof(commstates[i].pubkey))) {
+            printf("Pubkey %hu matches our own; possible reflection attack?\n",
+                i);
+            commstates.clear();
+            return false;
+        }
+    }
+
+    return true;
+}

+ 9 - 0
Enclave/comms.hpp

@@ -0,0 +1,9 @@
+#ifndef __COMMS_HPP__
+#define __COMMS_HPP__
+
+#include "enclave_api.h"
+
+bool comms_init_nodestate(const EnclaveAPINodeConfig *apinodeconfigs,
+    nodenum_t num_nodes, nodenum_t my_node_num);
+
+#endif

+ 24 - 0
Enclave/config.cpp

@@ -0,0 +1,24 @@
+#include "Enclave_t.h"
+#include "comms.hpp"
+#include "config.hpp"
+
+Config g_teems_config;
+
+bool ecall_config_load(EnclaveAPIParams *apiparams,
+    EnclaveAPINodeConfig *apinodeconfigs,
+    nodenum_t num_nodes, nodenum_t my_node_num)
+{
+    g_teems_config.num_nodes = num_nodes;
+    g_teems_config.my_node_num = my_node_num;
+    g_teems_config.msgsize = apiparams->msgsize;
+    uint16_t cumul_weight = 0;
+    g_teems_config.weights.clear();
+    for (nodenum_t i=0; i<num_nodes; ++i) {
+        NodeWeight nw;
+        nw.startweight = cumul_weight;
+        nw.weight = apinodeconfigs[i].weight;
+        cumul_weight += nw.weight;
+        g_teems_config.weights.push_back(nw);
+    }
+    return comms_init_nodestate(apinodeconfigs, num_nodes, my_node_num);
+}

+ 26 - 0
Enclave/config.hpp

@@ -0,0 +1,26 @@
+#ifndef __CONFIG_HPP__
+#define __CONFIG_HPP__
+
+#include <vector>
+
+#include "enclave_api.h"
+
+// startweight is the running total of all the weight entries of nodes
+// lower numbered than this one.  E.g., if the weights of nodes 0, 1,
+// ..., etc. are [1, 2, 4, 1, 2, ...], the startweight values will be
+// [0, 1, 3, 7, 8, ...].
+struct NodeWeight {
+    uint16_t startweight;
+    uint8_t weight;
+};
+
+struct Config {
+    nodenum_t num_nodes;
+    nodenum_t my_node_num;
+    uint16_t msgsize;
+    std::vector<NodeWeight> weights;
+};
+
+extern Config g_teems_config;
+
+#endif

+ 19 - 0
Enclave/enclave_api.h

@@ -0,0 +1,19 @@
+#ifndef __ENCLAVE_API_H__
+#define __ENCLAVE_API_H__
+
+#include "sgx_tcrypto.h"
+
+typedef uint16_t nodenum_t;
+
+struct EnclaveAPIParams {
+    uint16_t msgsize;
+};
+
+struct EnclaveAPINodeConfig {
+    sgx_ec256_public_t pubkey;
+    uint8_t weight;
+};
+
+#define SEALED_PRIVKEY_SIZE 610
+
+#endif

+ 2 - 0
Enclave/utils.cpp

@@ -1,3 +1,5 @@
+#include <stdio.h>
+
 #include "utils.hpp"
 
 /*

+ 0 - 1
Enclave/utils.hpp

@@ -1,7 +1,6 @@
 #ifndef __UTILS_HPP__
 #define __UTILS_HPP__
 
-#include <stdio.h>
 #include "Enclave_t.h"
 
 void printf(const char *fmt, ...);

+ 14 - 8
Makefile

@@ -274,7 +274,7 @@ endif
 .PHONY: clean
 
 clean:
-	@rm -f .config_* $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) Untrusted/Enclave_u.* $(Enclave_Cpp_Objects) Enclave/Enclave_t.* $(Enclave_Test_Key)
+	@rm -f .config_* $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) Untrusted/Enclave_u.* $(Enclave_Cpp_Objects) Enclave/Enclave_t.*
 
 depend:
 	makedepend -Y -- -IApp -IUntrusted -- $(App_Cpp_Files)
@@ -282,12 +282,18 @@ depend:
 
 # DO NOT DELETE
 
+App/appconfig.o: Untrusted/Untrusted.hpp Enclave/enclave_api.h
 App/appconfig.o: App/appconfig.hpp
-App/net.o: App/net.hpp App/appconfig.hpp
+App/net.o: App/net.hpp App/appconfig.hpp Enclave/enclave_api.h
 App/start.o: App/start.hpp App/net.hpp App/appconfig.hpp
-App/teems.o: Untrusted/Untrusted.hpp App/appconfig.hpp App/net.hpp
-App/teems.o: App/start.hpp
-Untrusted/Untrusted.o: Untrusted/Untrusted.hpp Untrusted/Enclave_u.h
-
-Enclave/comms.o: Enclave/Enclave_t.h Enclave/utils.hpp
-Enclave/utils.o: Enclave/utils.hpp Enclave/Enclave_t.h
+App/start.o: Enclave/enclave_api.h
+App/teems.o: Untrusted/Untrusted.hpp Enclave/enclave_api.h App/appconfig.hpp
+App/teems.o: App/net.hpp App/start.hpp
+Untrusted/Untrusted.o: Untrusted/Untrusted.hpp Enclave/enclave_api.h
+Untrusted/Untrusted.o: Untrusted/Enclave_u.h
+
+Enclave/comms.o: Enclave/Enclave_t.h Enclave/enclave_api.h Enclave/utils.hpp
+Enclave/comms.o: Enclave/config.hpp Enclave/enclave_api.h
+Enclave/config.o: Enclave/Enclave_t.h Enclave/enclave_api.h Enclave/comms.hpp
+Enclave/config.o: Enclave/enclave_api.h Enclave/config.hpp
+Enclave/utils.o: Enclave/utils.hpp Enclave/Enclave_t.h Enclave/enclave_api.h

+ 10 - 0
Untrusted/Untrusted.cpp

@@ -224,3 +224,13 @@ bool ecall_identity_key_load(sgx_ec256_public_t* outpub,
     ecall_identity_key_load(global_eid, &ret, outpub, insealedpriv);
     return ret;
 }
+
+bool ecall_config_load(struct EnclaveAPIParams *apiparams,
+    struct EnclaveAPINodeConfig *apinodeconfigs,
+    nodenum_t num_nodes, nodenum_t my_node_num)
+{
+    bool ret;
+    ecall_config_load(global_eid, &ret, apiparams, apinodeconfigs,
+        num_nodes, my_node_num);
+    return ret;
+}

+ 7 - 0
Untrusted/Untrusted.hpp

@@ -4,6 +4,9 @@
 #include <cstddef>
 
 #include "sgx_eid.h"
+#include "sgx_tseal.h"
+
+#include "../Enclave/enclave_api.h"
 
 extern sgx_enclave_id_t global_eid;
 
@@ -15,4 +18,8 @@ void ecall_identity_key_new(sgx_ec256_public_t* outpub,
 bool ecall_identity_key_load(sgx_ec256_public_t* outpub,
     const sgx_sealed_data_t* insealedpriv);
 
+bool ecall_config_load(struct EnclaveAPIParams *apiparams,
+    struct EnclaveAPINodeConfig *apinodeconfigs,
+    nodenum_t num_nodes, nodenum_t my_node_num);
+
 #endif