]> git.codecow.com Git - Monocypher.git/commitdiff
doc: more details on mitigating power side channels in EdDSA
authorFabio Scotoni <34964387+fscoto@users.noreply.github.com>
Fri, 27 Mar 2020 06:29:47 +0000 (07:29 +0100)
committerFabio Scotoni <34964387+fscoto@users.noreply.github.com>
Fri, 27 Mar 2020 06:45:49 +0000 (07:45 +0100)
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
doc/man/man3/crypto_sign_init_first_pass.3monocypher

index 87bc69758a772a4e8618963bd205999f50395dca..5013c4e289dc58e42273ce1f2035219a8133e363 100644 (file)
@@ -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.
index dfa7fd9ad118b757d96a50aed23db8e98d15c694..804845565b43d734f6ab7cbfc1eced7e45d9e967 100644 (file)
@@ -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.