summaryrefslogtreecommitdiff
path: root/design-documents/010-exchange-helpers.rst
blob: cf7a4dff0b182ed29f0a83d6b7df5443b2560cc2 (plain)
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
Exchange crypto helper design
#############################

Summary
=======

A way to minimize the attack surface for extraction of the private online
signing keys (RSA and EdDSA) from the exchange is described.


Motivation
==========

We want to provide an additional layer of protection for the private online
signing keys used by the exchange. The exchange is network-facing, includes an
HTTP server, Postgres interaction, JSON parser and quite a bit of other logic
which may all be theoretically vulnerable to remote exploitation.  Thus, it
would be good from a security perspective to protect the private online
signing keys via an additional layer of protection.


Requirements
============

* The solution should not result in a dramatic loss of performance.
* An attacker with a successful arbitrary code execution on the exchange
  must not be able to extract the private keys.
* Ideally, we should be able to determine the number of signatures
  obtained illicitly by the attacker.
* Key management for operators should be simplified to improve usability.
* Both RSA and EdDSA online signing keys need to be protected.


Proposed Solution
=================

The private keys are to be created, used and deleted by two helper processes
running under a different user ID (UID).  The exchange's HTTP process will be
required to interact with those helpers via a UNIX domain socket.

Specific design details:

* The helpers will process requests from the exchange to sign and revoke keys.
* The helpers will tell the exchange when keys are created or deleted/expired.
* SOCK_DGRAM will be used to avoid needing to parse a data stream.
* The helpers will only know about (private) key lifetime. They will not know about
  details like currency, fee structure, master or auditor signatures.
  Those will be managed by the HTTP process to keep the helpers minimal.
* The exchange will expose the corresponding public keys via a ``/keys?future``
  endpoint to the auditor and the offline signing process. Auditor and master
  signatures will be POSTed to the exchange via the ``/keys`` endpoint.
  The exchange will keep those signatures in the Postgres database.
* Each exchange thread will create its own connection to the helpers, and will
  block while waiting on the helper to create a signature.  This keeps the
  exchange logic simple and similar to the existing in-line signing calls.
  Suspending and resuming would be difficult as we currently do not have a
  way to wait for a UNIX domain socket to resume the MHD logic.
  If a signal is received while waiting for the helper, the signature operation
  fails. Signature operations can also fail if the helper is not running or
  responding with incorrect data. However, signature operations do NOT have a
  timeout.
* The helpers will use a single-threaded, GNUnet-scheduler-driven event loop
  to process incoming requests from the UNIX domain sockets. However, the
  actual signing will be done by a thread pool of workers that only process
  signing requests from a work queue. Reference counting is used to avoid
  releasing private keys while workers are actively using them to sign requests.
* The work queue is managed via a pthread-style semaphore.
* The master thread is informed about completed work via an ``eventfd()``.
* The master thread is responsible for handling revocations, creating future
  private keys and expiring old keys.


Alternatives
============

* The helpers could have been given the information to validate the signing
  request. However, without database access, validating the reserve key
  signature (and others) is pretty useless. Thus, this direction would only
  complicate the helper (which we want to keep minimal to minimize attack
  surface) without real benefits. Even validating revocation requests (checking
  signatures by auditor or master public key) makes no sense, as if an attacker
  triggers a revocation, we should probably be thankful: That's a white-hat
  demonstrating that they got control in the least harmful way.
* Instead of two helpers, we could have just one helper. But there is limited
  overlap between the (RSA) denomination key logic and the (EdDSA) signing
  key logic. Separation may improve security.
* We could have proposed a helper per denomination. But as the code of all of
  these helpers would be identical, this would have no security advantages.
* We could have implemented our own event loop and configuration parser,
  instead of relying on libgnunetutil. But this part of GNUnet is very
  robust.
* We could have had a thread pool reading requests from the exchange clients,
  instead of a master thread doling out the work. But this would become really
  complicted with key revocations, and as really only the cryptography should
  be the bottleneck, performance advantages should be minimal. If IPC ever
  becomes the issue, then the entire idea of moving signatures to another
  process would be flawed.
* More portable mechanisms (like a ``pipe()``) could be used for signaling
  instead of ``eventfd()``. But, this can always be implemented if we truly
  ever have an exchange operator needing support for such a platform.
* We could have left the helper single-threaded, to avoid the complications
  arising from the use of threads. However, given that signing is expected to
  be a bottleneck of the exchange, this would have had serious performance
  implications for the entire system.


Drawbacks
=========

* Additional work to properly setup an exchange and to run
  our automated tests.
* Slight (?) performance impact.
* UNIX only. Likely Linux-only for now (but fixable).
* If exchange receives ANY (not ignored) signal during signing
  operation, a discrepancy in the number of signatures created
  between exchange (DB) and the helper will arise.  Thus,
  auditors have to allow for small discrepancies (increasing
  over time).  Note that we only expect the exchange to receive
  signals if the software is updated or the process is terminated.
* If helper is stopped (SIGSTOP), exchange HTTP will itself block
  (no timeout!). Timeout-based mitigation would additionally increase
  discrepancies in the count of the number of signatures created.


Discussion / Q&A
================

(This should be filled in with results from discussions on mailing lists / personal communication.)