Browse Source

Hex2str clean up and unit testing (#134)

* Fix off-by-one error in __hex2str()

* Add a unit test and documentation for hex2str, in light of issue #129/PR #130.  Although only used by SGX pal, I moved hex2str into a library function, since it isn't SGX specifix.  Change the function signature to pass in a stack-allocated buffer.  Adjust a few hash types, and make the build stop earlier on a failure.
Don Porter 5 years ago
parent
commit
1f2360c857

+ 2 - 1
LibOS/shim/src/ipc/shim_ipc_nsimpl.h

@@ -987,6 +987,8 @@ int NS_CALLBACK(findns) (IPC_CALLBACK_ARGS)
     lock(cur_process.lock);
     __discover_ns(false, true, true);
     if (NS_LEADER) {
+        /* After __discover_ns, the leader should has its own port */
+        assert(!qstrempty(&NS_LEADER->uri));
         ret = NS_SEND(tellns)(port, msg->src, NS_LEADER, msg->seq);
     } else {
         struct ns_query * query = malloc(sizeof(struct ns_query));
@@ -1019,7 +1021,6 @@ int NS_SEND(tellns) (struct shim_ipc_port * port, IDTYPE dest,
                                 dest);
     NS_MSG_TYPE(tellns) * msgin = (void *) &msg->msg;
     msgin->vmid = leader->vmid;
-    assert(!qstrempty(&leader->uri));
     memcpy(msgin->uri, qstrgetstr(&leader->uri), leader->uri.len + 1);
     msg->seq = seq;
 

+ 1 - 1
LibOS/shim/test/apps/lmbench/lmbench-2.5

@@ -1 +1 @@
-Subproject commit b145ddce0c3d067f8be19e818427a1e540d63718
+Subproject commit 1511feaba06c3a145f48790f35d9463e42a5ac74

+ 57 - 0
Pal/lib/hex.h

@@ -0,0 +1,57 @@
+/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
+/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
+
+/* Copyright (C) 2014 OSCAR lab, Stony Brook University
+   2017 University of North Carolina at Chapel Hill
+   This file is part of Graphene Library OS.
+
+   Graphene Library OS is free software: you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation, either version 3 of the
+   License, or (at your option) any later version.
+
+   Graphene Library OS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef HEX_H
+#define HEX_H
+
+/* This function is a helper for debug printing. 
+ * It accepts a pointer to a numerical value, and 
+ * formats it as a hex string, for printing.
+ * size is the number of bytes pointed to by hex.
+ * str is the caller-provided buffer, len is the length of the buffer.
+ * The len must be at least (size * 2)+1.
+ * 
+ * Note that it does not normalize for endianness, and pads to the
+ * size the compiler things the string is.
+ */
+#include <assert.h>
+static inline __attribute__((always_inline))
+char * __bytes2hexstr(void * hex, size_t size, char *str, size_t len)
+{
+    static char * ch = "0123456789abcdef";
+    assert(len >= size * 2 + 1);
+
+    for (size_t i = 0 ; i < size ; i++) {
+        unsigned char h = ((unsigned char *) hex)[i];
+        str[i * 2] = ch[h / 16];
+        str[i * 2 + 1] = ch[h % 16];
+    }
+
+    str[size * 2] = 0;
+    return str;
+}
+
+#define IS_INDEXABLE(arg) (sizeof((arg)[0]))
+#define IS_ARRAY(arg) (IS_INDEXABLE(arg) > 0 && (((void *) &(arg)) == ((void *) (arg))))
+
+#define bytes2hexstr(array, str, len) (IS_ARRAY(array) ?                \
+                                       __bytes2hexstr((array), sizeof(array), str, len) \
+                                       : NULL)
+#endif // HEX_H

+ 10 - 0
Pal/regression/02_Misc.py

@@ -21,3 +21,13 @@ regression.add_check(name="Generate Random Bits",
 
 rv = regression.run_checks()
 if rv: sys.exit(rv)
+
+regression = Regression(loader, "Hex")
+
+regression.add_check(name="Hex 2 String Helper Function",
+                     check=lambda res: "Hex test 1 is deadbeef" in res[0].log and \
+                     "Hex test 2 is cdcdcdcdcdcdcdcd" in res[0].log)
+
+rv = regression.run_checks()
+if rv: sys.exit(rv)
+

+ 16 - 0
Pal/regression/Hex.c

@@ -0,0 +1,16 @@
+/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
+/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
+
+#include "pal.h"
+#include "pal_debug.h"
+#include "api.h"
+#include "hex.h"
+
+int main() {
+    char x[] = {0xde, 0xad, 0xbe, 0xef};
+    char y[] = {0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd};
+    char buf[(sizeof(y) * 2) + 1];
+    pal_printf("Hex test 1 is %s\n", bytes2hexstr(x, buf, 17));
+    pal_printf("Hex test 2 is %s\n", bytes2hexstr(y, buf, 17));
+    return 0;
+}

+ 4 - 2
Pal/src/host/Linux-SGX/db_process.c

@@ -236,7 +236,8 @@ int _DkProcessCreate (PAL_HANDLE * handle, const char * uri,
                 sizeof(pal_enclave_state.enclave_keyhash),
                 data.keyhash_mac, sizeof data.keyhash_mac);
 
-    SGX_DBG(DBG_P|DBG_S, "Attestation data: %s\n", hex2str(data.keyhash_mac));
+    char mac_buf[MACBUF_SIZE];
+    SGX_DBG(DBG_P|DBG_S, "Attestation data: %s\n", bytes2hexstr(data.keyhash_mac, mac_buf, MACBUF_SIZE));
 
     ret = _DkStreamAttestationRequest(proc, &data,
                                       &check_child_mrenclave, &param);
@@ -305,7 +306,8 @@ int init_child_process (PAL_HANDLE * parent_handle)
                 sizeof(pal_enclave_state.enclave_keyhash),
                 data.keyhash_mac, sizeof data.keyhash_mac);
 
-    SGX_DBG(DBG_P|DBG_S, "Attestation data: %s\n", hex2str(data.keyhash_mac));
+    char mac_buf[MACBUF_SIZE];
+    SGX_DBG(DBG_P|DBG_S, "Attestation data: %s\n", bytes2hexstr(data.keyhash_mac, mac_buf, MACBUF_SIZE));
 
     ret = _DkStreamAttestationRespond(parent, &data,
                                       &check_parent_mrenclave,

+ 32 - 19
Pal/src/host/Linux-SGX/enclave_framework.c

@@ -36,6 +36,7 @@ void sgx_ocfree (void)
     SET_ENCLAVE_TLS(ustack, GET_ENCLAVE_TLS(ustack_top));
 }
 
+#define HASHBUF_SIZE ((sizeof(sgx_arch_hash_t)*2)+1)
 int sgx_get_report (sgx_arch_hash_t * mrenclave,
                     sgx_arch_attributes_t * attributes,
                     void * enclave_data,
@@ -55,24 +56,28 @@ int sgx_get_report (sgx_arch_hash_t * mrenclave,
     if (ret)
         return -PAL_ERROR_DENIED;
 
+    char hash_buf[HASHBUF_SIZE];
+    char mac_buf[MACBUF_SIZE];
+
     SGX_DBG(DBG_S, "Generated report:\n");
     SGX_DBG(DBG_S, "    cpusvn:           %08x %08x\n", report->cpusvn[0],
                                                 report->cpusvn[1]);
-    SGX_DBG(DBG_S, "    mrenclave:        %s\n",        hex2str(report->mrenclave));
-    SGX_DBG(DBG_S, "    mrsigner:         %s\n",        hex2str(report->mrsigner));
+    SGX_DBG(DBG_S, "    mrenclave:        %s\n",        bytes2hexstr(report->mrenclave, hash_buf, HASHBUF_SIZE));
+    SGX_DBG(DBG_S, "    mrsigner:         %s\n",        bytes2hexstr(report->mrsigner, hash_buf, HASHBUF_SIZE));
     SGX_DBG(DBG_S, "    attributes.flags: %016lx\n",    report->attributes.flags);
     SGX_DBG(DBG_S, "    sttributes.xfrm:  %016lx\n",    report->attributes.xfrm);
 
     SGX_DBG(DBG_S, "    isvprodid:        %02x\n",      report->isvprodid);
     SGX_DBG(DBG_S, "    isvsvn:           %02x\n",      report->isvsvn);
-    SGX_DBG(DBG_S, "    keyid:            %s\n",        hex2str(report->keyid));
-    SGX_DBG(DBG_S, "    mac:              %s\n",        hex2str(report->mac));
+    SGX_DBG(DBG_S, "    keyid:            %s\n",        bytes2hexstr(report->keyid, hash_buf, HASHBUF_SIZE));
+    SGX_DBG(DBG_S, "    mac:              %s\n",        bytes2hexstr(report->mac, mac_buf, MACBUF_SIZE));
 
     return 0;
 }
 
 static sgx_arch_key128_t enclave_key;
 
+#define KEYBUF_SIZE ((sizeof(sgx_arch_key128_t) * 2) + 1)
 int sgx_verify_report (sgx_arch_report_t * report)
 {
     sgx_arch_keyrequest_t keyrequest;
@@ -86,7 +91,9 @@ int sgx_verify_report (sgx_arch_report_t * report)
         return -PAL_ERROR_DENIED;
     }
 
-    SGX_DBG(DBG_S, "Get report key for verification: %s\n", hex2str(enclave_key));
+    char key_buf[KEYBUF_SIZE];
+
+    SGX_DBG(DBG_S, "Get report key for verification: %s\n", bytes2hexstr(enclave_key, key_buf, KEYBUF_SIZE));
     return 0;
 }
 
@@ -102,7 +109,8 @@ int init_enclave_key (void)
         return -PAL_ERROR_DENIED;
     }
 
-    SGX_DBG(DBG_S, "Get sealing key: %s\n", hex2str(enclave_key));
+    char key_buf[KEYBUF_SIZE];
+    SGX_DBG(DBG_S, "Get sealing key: %s\n", bytes2hexstr(enclave_key, key_buf, KEYBUF_SIZE));
     return 0;
 }
 
@@ -622,7 +630,7 @@ void test_dh (void)
     DhKey key1, key2;
     uint32_t privsz1, privsz2, pubsz1, pubsz2, agreesz1, agreesz2;
     unsigned char priv1[128], pub1[128], priv2[128], pub2[128], agree1[128],
-                  agree2[128];
+        agree2[128], scratch[257];
 
     InitDhKey(&key1);
     InitDhKey(&key2);
@@ -666,9 +674,9 @@ void test_dh (void)
     FreeDhKey(&key1);
     FreeDhKey(&key2);
 
-    SGX_DBG(DBG_S, "key exchange(side A): %s (%d)\n", __hex2str(agree1, agreesz1),
+    SGX_DBG(DBG_S, "key exchange(side A): %s (%d)\n", __bytes2hexstr(agree1, agreesz1, scratch, (agreesz1 * 2) + 1),
            agreesz1);
-    SGX_DBG(DBG_S, "key exchange(side B): %s (%d)\n", __hex2str(agree2, agreesz2),
+    SGX_DBG(DBG_S, "key exchange(side B): %s (%d)\n", __bytes2hexstr(agree2, agreesz2, scratch, (agreesz2 * 2) + 1),
            agreesz2);
 }
 #endif
@@ -713,8 +721,9 @@ int init_enclave (void)
 
     pal_enclave_config.enclave_key = rsa;
 
+    char hash_buf[HASHBUF_SIZE];
     SGX_DBG(DBG_S, "enclave (software) key hash: %s\n",
-           hex2str(pal_enclave_state.enclave_keyhash));
+            bytes2hexstr(pal_enclave_state.enclave_keyhash, hash_buf, HASHBUF_SIZE));
 
     return 0;
 
@@ -781,7 +790,9 @@ int _DkStreamKeyExchange (PAL_HANDLE stream, PAL_SESSION_KEY * keyptr)
     for (int i = 0 ; i < agreesz ; i++)
         session_key[i % sizeof(session_key)] ^= agree[i];
 
-    SGX_DBG(DBG_S, "key exchange: (%p) %s\n", session_key, hex2str(session_key));
+    char key_buf[KEYBUF_SIZE];
+    SGX_DBG(DBG_S, "key exchange: (%p) %s\n", session_key,
+            bytes2hexstr(session_key, key_buf, KEYBUF_SIZE));
 
     if (keyptr)
         memcpy(keyptr, session_key, sizeof(PAL_SESSION_KEY));
@@ -817,8 +828,9 @@ int _DkStreamAttestationRequest (PAL_HANDLE stream, void * data,
     memcpy(&req.attributes, &pal_sec.enclave_attributes,
            sizeof(sgx_arch_attributes_t));
 
+    char hash_buf[HASHBUF_SIZE];
     SGX_DBG(DBG_S, "Sending attestation request ... (mrenclave = %s)\n",\
-            hex2str(req.mrenclave));
+            bytes2hexstr(req.mrenclave, hash_buf, HASHBUF_SIZE));
 
     for (bytes = 0, ret = 0 ; bytes < sizeof(req) ; bytes += ret) {
         ret = _DkStreamWrite(stream, 0, sizeof(req) - bytes,
@@ -839,7 +851,7 @@ int _DkStreamAttestationRequest (PAL_HANDLE stream, void * data,
     }
 
     SGX_DBG(DBG_S, "Received attestation (mrenclave = %s)\n",
-            hex2str(att.mrenclave));
+            bytes2hexstr(att.mrenclave, hash_buf, HASHBUF_SIZE));
 
     ret = sgx_verify_report(&att.report);
     if (ret < 0) {
@@ -862,7 +874,7 @@ int _DkStreamAttestationRequest (PAL_HANDLE stream, void * data,
 
     if (ret == 1) {
         SGX_DBG(DBG_S, "Not an allowed encalve (mrenclave = %s)\n",
-               hex2str(att.mrenclave));
+                bytes2hexstr(att.mrenclave, hash_buf, HASHBUF_SIZE));
         ret = -PAL_ERROR_DENIED;
         goto out;
     }
@@ -880,7 +892,7 @@ int _DkStreamAttestationRequest (PAL_HANDLE stream, void * data,
            sizeof(sgx_arch_attributes_t));
 
     SGX_DBG(DBG_S, "Sending attestation ... (mrenclave = %s)\n",
-            hex2str(att.mrenclave));
+            bytes2hexstr(att.mrenclave, hash_buf, HASHBUF_SIZE));
 
     for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
         ret = _DkStreamWrite(stream, 0, sizeof(att) - bytes,
@@ -916,8 +928,9 @@ int _DkStreamAttestationRespond (PAL_HANDLE stream, void * data,
         }
     }
 
+    char hash_buf[HASHBUF_SIZE];
     SGX_DBG(DBG_S, "Received attestation request ... (mrenclave = %s)\n",
-            hex2str(req.mrenclave));
+            bytes2hexstr(req.mrenclave, hash_buf, HASHBUF_SIZE));
 
     ret = sgx_get_report(&req.mrenclave, &req.attributes, data, &att.report);
     if (ret < 0) {
@@ -930,7 +943,7 @@ int _DkStreamAttestationRespond (PAL_HANDLE stream, void * data,
            sizeof(sgx_arch_attributes_t));
 
     SGX_DBG(DBG_S, "Sending attestation ... (mrenclave = %s)\n",
-            hex2str(att.mrenclave));
+            bytes2hexstr(att.mrenclave, hash_buf, HASHBUF_SIZE));
 
     for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
         ret = _DkStreamWrite(stream, 0, sizeof(att) - bytes,
@@ -951,7 +964,7 @@ int _DkStreamAttestationRespond (PAL_HANDLE stream, void * data,
     }
 
     SGX_DBG(DBG_S, "Received attestation (mrenclave = %s)\n",
-            hex2str(att.mrenclave));
+            bytes2hexstr(att.mrenclave, hash_buf, HASHBUF_SIZE));
 
     ret = sgx_verify_report(&att.report);
     if (ret < 0) {
@@ -973,7 +986,7 @@ int _DkStreamAttestationRespond (PAL_HANDLE stream, void * data,
 
     if (ret == 1) {
         SGX_DBG(DBG_S, "Not an allowed enclave (mrenclave = %s)\n",
-                hex2str(att.mrenclave));
+                bytes2hexstr(att.mrenclave, hash_buf, HASHBUF_SIZE));
         ret = -PAL_ERROR_DENIED;
         goto out;
     }

+ 2 - 18
Pal/src/host/Linux-SGX/pal_linux.h

@@ -162,7 +162,7 @@ extern struct pal_enclave_state {
                                        enclave */
     uint8_t  data[PAL_ATTESTATION_DATA_SIZE];
                                     /* reserved for filling other data */
-    uint8_t  enclave_keyhash[32];   /* SHA256 digest of enclave's public key
+    sgx_arch_hash_t enclave_keyhash;   /* SHA256 digest of enclave's public key
                                        can also be used as an identifier of the
                                        enclave */
 } __attribute__((packed, aligned (128))) pal_enclave_state;
@@ -177,23 +177,7 @@ extern struct pal_enclave_config {
     void *                 enclave_key;
 } pal_enclave_config;
 
-static inline __attribute__((always_inline))
-char * __hex2str(void * hex, int size)
-{
-    static char * ch = "0123456789abcdef";
-    char * str = __alloca(size * 2 + 1);
-
-    for (int i = 0 ; i < size ; i++) {
-        unsigned char h = ((unsigned char *) hex)[i];
-        str[i * 2] = ch[h / 16];
-        str[i * 2 + 1] = ch[h % 16];
-    }
-
-    str[size * 2] = 0;
-    return str;
-}
-
-#define hex2str(array) __hex2str(array, sizeof(array))
+#include <hex.h>
 
 #else
 

+ 3 - 1
Pal/src/host/Linux-SGX/sgx_arch.h

@@ -29,6 +29,8 @@
 typedef uint8_t sgx_arch_key_t [384];
 typedef uint8_t sgx_arch_hash_t[32];
 typedef uint8_t sgx_arch_mac_t [16];
+// This if for passing a mac to hex2str
+#define MACBUF_SIZE ((sizeof(sgx_arch_mac_t)*2)+1) 
 
 typedef struct {
     uint64_t flags, xfrm;
@@ -204,7 +206,7 @@ typedef struct {
     uint32_t miscselect_mask;
     sgx_arch_attributes_t attribute_mask;
     sgx_arch_hash_t keyid;
-    uint8_t  mac[16];
+    sgx_arch_mac_t mac;
 } __attribute__((packed)) sgx_arch_token_t;
 
 typedef struct {