aboutsummaryrefslogtreecommitdiff
path: root/lib/base
diff options
context:
space:
mode:
Diffstat (limited to 'lib/base')
-rw-r--r--lib/base/Makefile.am2
-rw-r--r--lib/base/etpm.cpp161
-rw-r--r--lib/base/etpm.h46
3 files changed, 208 insertions, 1 deletions
diff --git a/lib/base/Makefile.am b/lib/base/Makefile.am
index 6ea9d03f..05085632 100644
--- a/lib/base/Makefile.am
+++ b/lib/base/Makefile.am
@@ -8,5 +8,5 @@ libenigma_base_a_SOURCES = \
init.cpp message.cpp thread.cpp \
smartptr.cpp estring.cpp connection.cpp \
filepush.cpp encoding.cpp console.cpp rawfile.cpp \
- nconfig.cpp ioprio.cpp
+ nconfig.cpp ioprio.cpp etpm.cpp
diff --git a/lib/base/etpm.cpp b/lib/base/etpm.cpp
new file mode 100644
index 00000000..f1ac07ba
--- /dev/null
+++ b/lib/base/etpm.cpp
@@ -0,0 +1,161 @@
+#include <linux/socket.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <openssl/bn.h>
+#include <openssl/sha.h>
+#include <lib/base/etpm.h>
+
+DEFINE_REF(eTPM);
+
+eTPM::eTPM()
+{
+ struct sockaddr_un addr;
+ unsigned char buf[8];
+ unsigned int tag, len;
+ unsigned char *val;
+
+ level2_cert_read = level3_cert_read = false;
+
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, TPMD_SOCKET);
+
+ fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ eDebug("[eTPM] socket error");
+ return;
+ }
+
+ if (connect(fd, (const struct sockaddr *)&addr, SUN_LEN(&addr)) < 0) {
+ eDebug("[eTPM] connect error");
+ return;
+ }
+
+ buf[0] = TPMD_DT_LEVEL2_CERT;
+ buf[1] = TPMD_DT_LEVEL3_CERT;
+ if (!send_cmd(TPMD_CMD_GET_DATA, buf, 2))
+ {
+ return;
+ }
+
+ val = (unsigned char*)recv_cmd(&tag, &len);
+ if (val == NULL)
+ {
+ return;
+ }
+
+ parse_data(val, len);
+ free(val);
+}
+
+eTPM::~eTPM()
+{
+
+}
+
+bool eTPM::send_cmd(enum tpmd_cmd cmd, const void *data, unsigned int len)
+{
+ unsigned char buf[len + 4];
+
+ buf[0] = (cmd >> 8) & 0xff;
+ buf[1] = (cmd >> 0) & 0xff;
+ buf[2] = (len >> 8) & 0xff;
+ buf[3] = (len >> 0) & 0xff;
+ memcpy(&buf[4], data, len);
+
+ if (write(fd, buf, sizeof(buf)) != (ssize_t)sizeof(buf)) {
+ fprintf(stderr, "%s: incomplete write\n", __func__);
+ return false;
+ }
+
+ return true;
+}
+
+void* eTPM::recv_cmd(unsigned int *tag, unsigned int *len)
+{
+ unsigned char buf[4];
+ void *val;
+
+ if (read(fd, buf, 4) != 4) {
+ fprintf(stderr, "%s: incomplete read\n", __func__);
+ return NULL;
+ }
+
+ *tag = (buf[0] << 8) | buf[1];
+ *len = (buf[2] << 8) | buf[3];
+
+ val = malloc(*len);
+ if (val == NULL)
+ return NULL;
+
+ if (read(fd, val, *len) != (ssize_t)*len) {
+ fprintf(stderr, "%s: incomplete read\n", __func__);
+ free(val);
+ return NULL;
+ }
+
+ return val;
+}
+
+void eTPM::parse_data(const unsigned char *data, unsigned int datalen)
+{
+ unsigned int i, j;
+ unsigned int tag;
+ unsigned int len;
+ const unsigned char *val;
+
+ for (i = 0; i < datalen; i += len) {
+ tag = data[i++];
+ len = data[i++];
+ val = &data[i];
+
+ switch (tag) {
+ case TPMD_DT_LEVEL2_CERT:
+ if (len != 210)
+ break;
+ memcpy(level2_cert, val, 210);
+ level2_cert_read = true;
+ break;
+ case TPMD_DT_LEVEL3_CERT:
+ if (len != 210)
+ break;
+ memcpy(level3_cert, val, 210);
+ level3_cert_read = true;
+ break;
+ }
+ }
+}
+
+PyObject *eTPM::getCert(cert_type type)
+{
+ if (type == TPMD_DT_LEVEL2_CERT && level2_cert_read)
+ return PyBuffer_FromMemory(level2_cert, 210);
+ else if (type == TPMD_DT_LEVEL3_CERT && level3_cert_read)
+ return PyBuffer_FromMemory(level3_cert, 210);
+ return Py_None;
+
+}
+
+PyObject *eTPM::challenge(PyObject* rnd)
+{
+ if (PyString_Check(rnd) && PyString_Size(rnd) == 8)
+ {
+ char* buf = PyString_AsString(rnd);
+ if (!send_cmd(TPMD_CMD_COMPUTE_SIGNATURE, buf, 8))
+ return Py_None;
+
+ unsigned int tag, len;
+ unsigned char *val = (unsigned char*)recv_cmd(&tag, &len);
+
+ if (tag != TPMD_CMD_COMPUTE_SIGNATURE)
+ return Py_None;
+
+ return PyBuffer_FromMemory(val, len);
+ }
+ else
+ return Py_None;
+}
diff --git a/lib/base/etpm.h b/lib/base/etpm.h
new file mode 100644
index 00000000..3728249b
--- /dev/null
+++ b/lib/base/etpm.h
@@ -0,0 +1,46 @@
+#ifndef __lib_base_etpm_h
+#define __lib_base_etpm_h
+
+#include <lib/base/object.h>
+#include <lib/python/python.h>
+
+#ifndef SWIG
+#define TPMD_SOCKET "/var/run/tpmd_socket"
+#endif
+
+class eTPM: public Object, public iObject
+{
+ DECLARE_REF(eTPM);
+#ifndef SWIG
+ int fd;
+ unsigned char level2_cert[210];
+ unsigned char level3_cert[210];
+ bool level2_cert_read;
+ bool level3_cert_read;
+
+ enum tpmd_cmd {
+ TPMD_CMD_RESERVED = 0x0000,
+ TPMD_CMD_GET_DATA = 0x0001,
+ TPMD_CMD_APDU = 0x0002,
+ TPMD_CMD_COMPUTE_SIGNATURE = 0x0003,
+ TPMD_CMD_APP_CERT = 0x0004,
+ };
+
+ bool send_cmd(enum tpmd_cmd cmd, const void *data, unsigned int len);
+ void *recv_cmd(unsigned int *tag, unsigned int *len);
+ void parse_data(const unsigned char *data, unsigned int datalen);
+
+#endif
+public:
+ eTPM();
+ ~eTPM();
+
+ enum cert_type {
+ TPMD_DT_LEVEL2_CERT = 0x04,
+ TPMD_DT_LEVEL3_CERT = 0x05
+ };
+ PyObject *getCert(cert_type type);
+ PyObject *challenge(PyObject *rnd);
+};
+
+#endif // __lib_base_etpm_h