Fix timing leakage in cache hit/miss for non-error conditions
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Dbase32 |
Fix Released
|
Critical
|
Jason Gerard DeRose |
Bug Description
Another timing attack issue, furthering the work started in lp:1359828
https:/
The DB32_REVERSE lookup table means the Dbase32 C implementation is subject to cache timing attacks when the ID to be decoded or validated contains invalid characters. This can't be fully fixed as long as we're using such a lookup table.
However, the current implementation can also potentially leak information through cache hits and misses when decoding or validating a *valid* Dbase32 ID. And this *is* something we can fix.
The problem is that the entries for valid characters in the DB32_REVERSE table span two (64 byte) cache lines, and they aren't distributed uniformly. One cache line will contain 7 valid entries, and the other will contain the remaining 25 valid entries. Even without working out a proof of concept attack against this, the non uniform distribution between two cache lines doesn't pass the security smell test.
I believe the correct solution is probably to rotate the DB32_REVERSE table to the left by 51 bytes so that all valid entries fit in a single cache line. Although it will still be possible to get distinguishing information through cache hits and misses when the ID contains invalid characters, it wont be possible to gain any insight into what characters a valid ID contains.
For reference, here's the reverse table used in Dbase32 1.1 and earlier:
static const uint8_t DB32_REVERSE[256] = {
255,
255,
255,
0, // '3' [51]
1, // '4' [52]
2, // '5' [53]
3, // '6' [54]
4, // '7' [55]
5, // '8' [56]
6, // '9' [57]
255, // ':' [58]
255, // ';' [59]
255, // '<' [60]
255, // '=' [61]
255, // '>' [62]
255, // '?' [63]
255, // '@' [64]
7, // 'A' [65]
8, // 'B' [66]
9, // 'C' [67]
10, // 'D' [68]
11, // 'E' [69]
12, // 'F' [70]
13, // 'G' [71]
14, // 'H' [72]
15, // 'I' [73]
16, // 'J' [74]
17, // 'K' [75]
18, // 'L' [76]
19, // 'M' [77]
20, // 'N' [78]
21, // 'O' [79]
22, // 'P' [80]
23, // 'Q' [81]
24, // 'R' [82]
25, // 'S' [83]
26, // 'T' [84]
27, // 'U' [85]
28, // 'V' [86]
29, // 'W' [87]
30, // 'X' [88]
31, // 'Y' [89]
255,
255,
255,
255,
255,
255,
255,
255,
255,
};
Related branches
- Chad Miller (community): Approve
- dmedia Dev: Pending requested
-
Diff: 363 lines (+204/-70)4 files modified_dbase32.c (+107/-69)
dbase32/gen.py (+44/-1)
dbase32/tests/test_gen.py (+39/-0)
doc/changelog.rst (+14/-0)
summary: |
- Mitagate timing leakage in cache misses for non-error conditions + Fix timing leakage in cache misses for non-error conditions |
summary: |
- Fix timing leakage in cache misses for non-error conditions + Fix timing leakage in cache hit/miss for non-error conditions |
description: | updated |
tags: | added: security |
Changed in dbase32: | |
milestone: | 1.2 → 1.3 |
Changed in dbase32: | |
status: | Triaged → In Progress |
Changed in dbase32: | |
status: | In Progress → Fix Committed |
Changed in dbase32: | |
status: | Fix Committed → Fix Released |
Note that the proposed fix doesn't fix the problem for CPU with a 32 byte (or smaller) L1 cache line size, like ARM Cortex-A9: www.7-cpu. com/cpu/ Cortex- A9.html
http://
However, Cortex-A15 (and newer), plus all modern Intel CPU, use a 64 byte L1 cache line size.