From 77ba0a95b4f948fc89e015ffa76aba1cf90c2d9d Mon Sep 17 00:00:00 2001 From: Fabio Scotoni <34964387+fscoto@users.noreply.github.com> Date: Fri, 27 Mar 2020 07:29:47 +0100 Subject: [PATCH] doc: more details on mitigating power side channels in EdDSA MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit While already there, add a very sternly worded warning about omitting the first pass that will *appear* to work but will, in fact, just repeat the Sony PlayStation 3 ECDSA nonce disaster with EdDSA instead. RFC 8032 § 8.7 already hates Monocypher's guts for providing this risky interface at all, so we might as well use it for good: By showing how it can be used to mitigate power analysis attacks. The wording is such that crypto_sign.3monocypher redirects to crypto_sign_init_first_pass.3monocypher for how to mitigate power-related side channels; crypto_ed25519_sign_init_first_pass.3monocypher already points to crypto_sign_init_first_pass.3monocypher wholesale anyway. I've intentionally broken the rule that crypto_sign_init_first_pass.3monocypher *only* talks about BLAKE2b in this specific instance because of the redirect on the Ed25519 page so that this content doesn't need to be duplicated. There's no issue doing this with the example code because both hash functions call their internal compression functions. While I could've just *described* what to do, I'd feel uneasy leaving implementers just guessing what it is that we mean and overshoot or undershoot by 32 bytes (undershooting being particularly fatal) or just be too scared to try at all, so I've added example code nonetheless. It's been adorned with the bare minimum of an explanation about the magic number 128-32. Ideally, I'd have a good place to go on at length about EdDSA nonces, but there really isn't. On the other hand, I have very much *intentionally* omitted the fact that you could be okay just hashing a random nonce in (which then should be preferably at least 32 bytes, though you might be able to get away with less as well, I don't think there's a well-defined threshold for randomness with hash->reduce) or other kinds of nonces in the first pass of EdDSA in particular. While this is interesting and sometimes very much useful knowledge, it's also a large footgun and the whole reason why RFC 8032 § 8.7 recommends against init-update-final interfaces in APIs (unless using Ed25519ph, but that means you need a collision-resistant hash function as the prehash, losing the security benefits of *not* requiring collision resistance from the hash function in EdDSA in the first place). --- doc/man/man3/crypto_sign.3monocypher | 20 ++++---- .../crypto_sign_init_first_pass.3monocypher | 50 +++++++++++++++++++ 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/doc/man/man3/crypto_sign.3monocypher b/doc/man/man3/crypto_sign.3monocypher index 87bc697..5013c4e 100644 --- a/doc/man/man3/crypto_sign.3monocypher +++ b/doc/man/man3/crypto_sign.3monocypher @@ -222,13 +222,15 @@ Others only require knowledge of an existing signature. Observing a valid signature only proves that someone with knowledge of the private key signed the document at some point. Do not rely on any other security property. -.Ss Fault injection -Fault injection (also known as glitching) may be used to manipulate the -resulting signature and recover the secret key in some cases. +.Ss Fault injection and power analysis +Fault injection (also known as glitching) and power analysis may be used +to manipulate the resulting signature and recover the secret key in +some cases. This requires hardware access. -If attackers are expected to have such access and the relevant -equipment, use -.Fn crypto_check -to verify the signature before sending it away. -This verification reduces the speed of the whole operation by a factor -of 3, and only provides an incomplete protection. +If attackers are expected to have such access and have the relevant +equipment, you may try use the incremental interface provided by +.Xr crypto_sign_init_first_pass 3monocypher +to mitigate the side channel attacks. +Note that there may still be other power-related side channels (such as +if the CPU leaks information when an operation overflows a register) +that must be considered. diff --git a/doc/man/man3/crypto_sign_init_first_pass.3monocypher b/doc/man/man3/crypto_sign_init_first_pass.3monocypher index dfa7fd9..8048455 100644 --- a/doc/man/man3/crypto_sign_init_first_pass.3monocypher +++ b/doc/man/man3/crypto_sign_init_first_pass.3monocypher @@ -130,6 +130,14 @@ This recomputation doubles the execution time for short messages. .It The first pass proper, with .Fn crypto_sign_update . +Forgetting to call +.Fn crypto_sign_update +will appear to work in that it produces valid signatures, +but also +.Sy loses all security because attackers may now recover the secret key . +Under +.Em no +circumstances must you forget the first pass. .It Initialisation of the second pass with .Fn crypto_sign_init_second_pass . @@ -203,7 +211,41 @@ if (crypto_check_final((crypto_sign_ctx_abstract*)&ctx)) { } else { /* Message is genuine */ } +.Ed +.Pp +This interface can be used to mitigate attacks that leverage power +analysis and fault injection (glitching) \(en both of which require +physical access and appropriate equipment \(en by injecting additional +randomness (at least 32 bytes) and padding (to the hash function's block +size, which is 128 bytes for all hash functions supported by +Monocypher), of which 32 bytes are already inserted into the buffer by +.Fn crypto_sign_init_first_pass . +Access to a cryptographically secure pseudo-random generator is a +requirement for effective side channel mitigation. +Signing a message with increased power-related side channel mitigations: +.Bd -literal -offset indent +const uint8_t message [ 500]; /* Message to sign */ +uint8_t sk [ 32]; /* Secret key */ +const uint8_t pk [ 32]; /* Public key (optional) */ +uint8_t signature[ 64]; /* Output signature */ +uint8_t buf [128-32] = {0}; /* Mitigation buffer */ +crypto_sign_ctx ctx; +crypto_sign_ctx_abstract *actx = (crypto_sign_ctx_abstract *)&ctx; +arc4random(buf, 32); +/* The rest of buf MUST be zeroes. */ + +crypto_sign_init_first_pass(actx, sk, pk); +crypto_sign_update (actx, buf, sizeof(buf)); +crypto_sign_update (actx, message, 500); + +crypto_sign_init_second_pass(actx); +crypto_sign_update (actx, message, 500); +crypto_sign_final (actx, signature); + +crypto_wipe(buf, 32); +/* Wipe the secret key if no longer needed */ +crypto_wipe(sk, 32); .Ed .Sh SEE ALSO .Xr crypto_blake2b 3monocypher , @@ -216,6 +258,9 @@ if (crypto_check_final((crypto_sign_ctx_abstract*)&ctx)) { These functions implement PureEdDSA with Curve25519 and Blake2b, as described in RFC 8032. This is the same as Ed25519, with Blake2b instead of SHA-512. +.Pp +The example for side channel mitigation follows the methodology outlined +in I-D.draft-mattsson-cfrg-det-sigs-with-noise-02. .Sh HISTORY The .Fn crypto_sign_init_first_pass , @@ -246,6 +291,11 @@ Do not process messages before calling When signing messages, the security considerations documented in .Xr crypto_sign 3monocypher also apply. +In particular, if power-related side channels are part of your threat +model, +note that there may still be other power-related side channels (such as +if the CPU leaks information when an operation overflows a register) +that must be considered. .Sh IMPLEMENTATION DETAILS EdDSA signatures require two passes that cannot be performed in parallel. -- 2.47.3