From fb980849c4ffc99bca7a2dd5a347e9f0b4b99469 Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Sun, 21 Jun 2015 18:47:06 +0100 Subject: Add gdb script and psuedo-call graph generator python script for tracing calls to crypto primitives --- tracing/README.rst | 8 ++++ tracing/graph.py | 100 ++++++++++++++++++++++++++++++++++++++++ tracing/trace.gdb | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 241 insertions(+) create mode 100644 tracing/README.rst create mode 100755 tracing/graph.py create mode 100644 tracing/trace.gdb diff --git a/tracing/README.rst b/tracing/README.rst new file mode 100644 index 0000000..d2846ef --- /dev/null +++ b/tracing/README.rst @@ -0,0 +1,8 @@ +Tracing +======= + +To see what crypto functions are being called with what input run + +.. code:: bash + + gdb --batch -x tracing/trace.gdb ./build/test_ratchet | grep "^[- ]" | tr "{}" "[]" | tracing/graph.py diff --git a/tracing/graph.py b/tracing/graph.py new file mode 100755 index 0000000..ac121aa --- /dev/null +++ b/tracing/graph.py @@ -0,0 +1,100 @@ +#! /usr/bin/python + +import sys +import yaml +import array + +class Call(object): + def __init__(self, call): + self.func, = call + args = dict(call[self.func]) + self.output = array.array("B", args.pop("output")).tostring() + self.inputs = { + name: array.array("B", args[name]).tostring() + for name in args + if not name.endswith("_length") + } + self.bind = {} + + def expr(self, stream, indent=" ", level=""): + stream.write(self.func + "(\n") + for name, value in self.inputs.items(): + stream.write(level + indent + name + "=") + self.bind.get(name, Literal(value)).expr( + stream, indent, level + indent + ) + stream.write(",\n") + stream.write(level + ")") + + +class Literal(str): + def expr(self, stream, indent, level): + stream.write("\"" + self.encode("hex") + "\"") + + +class Slice(object): + def __init__(self, thing, start, end): + self.thing = thing + self.start = start + self.end = end + + def expr(self, stream, indent=" ", level=""): + self.thing.expr(stream, indent, level) + stream.write("[%d:%d]" % (self.start, self.end)) + + +class Concat(list): + def expr(self, stream, indent=" ", level=""): + stream.write("concat(\n") + for thing in self: + stream.write(level + indent) + thing.expr(stream, indent, level + indent) + stream.write(",\n") + stream.write(level + ")") + + +calls = [Call(c) for c in yaml.load(sys.stdin)] + +outputs = {} + +for call in calls: + for i in range(8, len(call.output)): + outputs.setdefault(call.output[i - 8: i], []).append(call) + +for call in calls: + for name, value in call.inputs.items(): + for bind in outputs.get(value[:8], ()): + if value == bind.output: + call.bind[name] = bind + else: + for end in range(len(value), len(bind.output) + 1): + start = end - len(value) + if value == bind.output[start:end]: + call.bind[name] = Slice(bind, start, end) + if not name in call.bind: + i = 0 + j = 1 + k = 0 + concat = Concat() + while i < len(value): + for bind in outputs.get(value[i:i+8], ()): + if value[i:].startswith(bind.output): + if k != i: + concat.append(Literal(value[k:i])) + concat.append(bind) + j = len(bind.output) + k = i + j + break + i += j + j = 1 + if concat: + if k != i: + concat.append(Literal(value[k:i])) + call.bind[name] = concat + +for call in calls: + if call.func.startswith("h"): + sys.stdout.write("\"" + call.output.encode("hex") + "\" = ") + call.expr(sys.stdout) + sys.stdout.write("\n") + diff --git a/tracing/trace.gdb b/tracing/trace.gdb new file mode 100644 index 0000000..bdece2e --- /dev/null +++ b/tracing/trace.gdb @@ -0,0 +1,133 @@ +set print pretty off +set print repeats unlimited +set print elements unlimited +set breakpoint pending on + + +break crypto.cpp:273 +commands +silent +printf "- hmac_sha256:\n" +printf " key_length: %d\n", key_length +printf " input_length: %d\n", input_length +if key_length > 0 + printf " key: " + output/x *key@key_length + printf "\n" +else + printf " key: {}\n" +end +if input_length > 0 + printf " input: " + output/x *input@input_length + printf "\n" +else + printf " input: {}\n" +end +cont +end + + +break crypto.cpp:280 +commands +silent +printf " output: " +output/x *output@32 +printf "\n" +cont +end + + +break crypto.cpp:307 +commands +silent +set $hkdf_output = output +cont +end + + +break crypto.cpp:323 +commands +silent +printf "- hkdf_sha256:\n" +printf " input_length: %d\n", input_length +printf " salt_length: %d\n", salt_length +printf " info_length: %d\n", info_length +printf " output_length: %d\n", output_length +if input_length > 0 + printf " input: " + output/x *input@input_length + printf "\n" +else + printf " input: {}\n" +end +if salt_length > 0 + printf " salt: " + output/x *salt@salt_length + printf "\n" +else + printf " salt: {}\n" +end +if info_length > 0 + printf " info: " + output/x *info@info_length + printf "\n" +else + printf " info: {}\n" +end +printf " output: " +output/x *$hkdf_output@output_length +printf "\n" +cont +end + + +break crypto.cpp:156 +commands +silent +printf "- curve25519:\n" +printf " public: " +output/x *their_key.public_key@32 +printf "\n" +printf " private: " +output/x *our_key.private_key@32 +printf "\n" +printf " output: " +output/x *output@32 +printf "\n" +cont +end + +break crypto.cpp:156 +commands +silent +printf "- curve25519:\n" +printf " public: " +output/x *their_key.public_key@32 +printf "\n" +printf " private: " +output/x *our_key.private_key@32 +printf "\n" +printf " output: " +output/x *output@32 +printf "\n" +cont +end + +break crypto.cpp:147 +commands +silent +printf "- curve25519:\n" +printf " public: " +output/x *CURVE25519_BASEPOINT@32 +printf "\n" +printf " private: " +output/x *key_pair.private_key@32 +printf "\n" +printf " output: " +output/x *key_pair.public_key@32 +printf "\n" +cont +end + +run -- cgit v1.2.3