|
| 1 | +# Security Assessment - nat20crypto |
| 2 | + |
| 3 | +This module implements the libnat20 crypto interface in terms of |
| 4 | +kernel-provided primitives. It attempts to provide a functionally correct |
| 5 | +implementation and makes an effort to clean sensitive key material from |
| 6 | +memory. But it is **not suitable for production**, specifically the ECC |
| 7 | +signing operation is not constant-time and susceptible to leaking private |
| 8 | +key information through timing side channels. |
| 9 | + |
| 10 | +## Key Material Leak Analysis |
| 11 | + |
| 12 | +### Addressed |
| 13 | + |
| 14 | +- **`nat20crypto_sign`** — stack buffers `z`, `k`, `k_inv`, `rs` are wiped via |
| 15 | + `memzero_explicit` on all exit paths. This covers the nonce, the inverted |
| 16 | + nonce, the byte-swapped private key (in `k_inv` via the `key_bytes` alias), |
| 17 | + and intermediate signature values. |
| 18 | +- **`nat20crypto_key_destroy`** — uses `memzero_explicit` before `kfree`. |
| 19 | +- **`nat20crypto_make_secret`** — the input `secret_in` buffer is caller-owned; |
| 20 | + the output key is heap-allocated and properly zeroed on free. |
| 21 | + |
| 22 | +### Outstanding issues |
| 23 | + |
| 24 | +#### `n20_rfc6979_k_generation` internal state |
| 25 | + |
| 26 | +This function (from nat20lib) uses HMAC internally with the private key as |
| 27 | +input. Whether its internal buffers are zeroed depends on its implementation. |
| 28 | +Out of scope for this module but noted as a dependency. |
| 29 | + |
| 30 | +## Timing Side Channel Analysis |
| 31 | + |
| 32 | +### Threat model |
| 33 | + |
| 34 | +In a DICE boot-time context where signing happens once during module init with |
| 35 | +no concurrent attacker (single-threaded init, no network, no user interaction), |
| 36 | +timing side channels are not practically exploitable. For a general-purpose |
| 37 | +signing oracle accessible from userspace, the issues below would be exploitable. |
| 38 | + |
| 39 | +### High risk |
| 40 | + |
| 41 | +#### `vli_mod_inv` — variable-time modular inverse |
| 42 | + |
| 43 | +The kernel's `vli_mod_inv` computes the modular inverse of `k` using a binary |
| 44 | +extended GCD with data-dependent branches and loop counts. The number of |
| 45 | +iterations depends on the value of `k`, leaking nonce information through |
| 46 | +timing. Partial nonce knowledge enables private key recovery via lattice |
| 47 | +attacks. |
| 48 | + |
| 49 | +#### `ecc_make_pub_key` — variable-time point multiplication |
| 50 | + |
| 51 | +The kernel's ECC point multiplication uses a double-and-add algorithm. Older |
| 52 | +kernels (pre-6.10) use a naive implementation with data-dependent |
| 53 | +doublings/additions, leaking the scalar `k` through timing. |
| 54 | + |
| 55 | +### Medium risk |
| 56 | + |
| 57 | +#### `vli_mod_mult_slow` — conditional subtraction |
| 58 | + |
| 59 | +The kernel's `vli_mod_mult_slow` is a shift-and-add modular multiplication. |
| 60 | +The loop count is constant, but the conditional subtraction after each shift |
| 61 | +(`if (result >= mod) result -= mod`) is data-dependent. This leaks |
| 62 | +intermediate state of `d_A * r` and `k_inv * s`, exposing bits of the private |
| 63 | +key and nonce inverse. |
| 64 | + |
| 65 | +#### Conditional mod-n reduction branches |
| 66 | + |
| 67 | +```c |
| 68 | +if (vli_cmp(k, s, ndigits) <= 0) { |
| 69 | + vli_sub(s, s, k, ndigits); |
| 70 | +} else { |
| 71 | + /* addition path */ |
| 72 | +} |
| 73 | +``` |
| 74 | + |
| 75 | +The branch taken depends on `s` which embeds `d_A * r`, leaking information |
| 76 | +about the private key. |
| 77 | + |
| 78 | +### Low risk |
| 79 | + |
| 80 | +#### RFC 6979 / HMAC-SHA |
| 81 | + |
| 82 | +The kernel's SHA implementations are generally constant-time for the |
| 83 | +compression function. HMAC processes fixed-size blocks. Low timing risk. |
| 84 | + |
| 85 | +#### `ecc_swap_digits` / `memcpy` / simple copies |
| 86 | + |
| 87 | +These process a fixed number of bytes regardless of value. Constant-time. |
| 88 | + |
| 89 | +### Summary table |
| 90 | + |
| 91 | +| Operation | Timing risk | Impact | |
| 92 | +|---|---|---| |
| 93 | +| `vli_mod_inv(k_inv, k, ...)` | Variable-time | Nonce leak, key recovery | |
| 94 | +| `ecc_make_pub_key(k * G)` | Variable-time (pre-6.10) | Nonce leak, key recovery | |
| 95 | +| `vli_mod_mult_slow(s, d_A, r)` | Conditional subtract | Private key leak | |
| 96 | +| Conditional mod-n reduction | Branch on secret | Minor info leak | |
| 97 | +| RFC 6979 / HMAC-SHA | Constant-time | Safe | |
| 98 | +| `ecc_swap_digits` / copies | Constant-time | Safe | |
0 commit comments