Skip to content

Commit cfebec3

Browse files
committed
unit-mcdc: fail the sp x86_64 whitebox if a refused save still runs
1 parent 9e51546 commit cfebec3

1 file changed

Lines changed: 41 additions & 12 deletions

File tree

tests/unit-mcdc/test_sp_x86_64_whitebox.c

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,18 @@ static int wb_intr_ret = 0;
189189
#include <stdio.h>
190190

191191
static int wb_fail = 0;
192+
/* Set while the save is refused. Every driven operation must fail then, so
193+
* these two counters turn that pass from a coverage sweep into a check. */
194+
static int wb_expect_refusal = 0;
195+
static int wb_contract_fail = 0; /* a refused save failed to stop a call */
196+
static long wb_refused_ok = 0; /* failed as required */
197+
static long wb_refused_bad = 0; /* succeeded despite a refused save */
198+
#define WB_OUTCOME(ret) do { \
199+
if (wb_expect_refusal) { \
200+
if ((ret) == 0) wb_refused_bad++; else wb_refused_ok++; \
201+
} } while (0)
202+
/* Evaluates the call once, records its outcome, yields it to the caller. */
203+
#define WB_CHECK(call) __extension__ ({ int wb_r_ = (call); WB_OUTCOME(wb_r_); wb_r_; })
192204
#define WB_NOTE(msg) do { printf(" [wb] %s\n", (msg)); } while (0)
193205

194206
/* Crafted-input driver shared with the sp_c64.c/sp_c32.c white-boxes: the
@@ -260,33 +272,33 @@ static void wb_run_ecc_curve(int curve_id, int fieldSz, const char* label)
260272
return;
261273
}
262274

263-
if (wc_ecc_make_key_ex(&rng, fieldSz, &keyA, curve_id) != 0) {
275+
if (WB_CHECK(wc_ecc_make_key_ex(&rng, fieldSz, &keyA, curve_id)) != 0) {
264276
WB_NOTE("wc_ecc_make_key_ex(keyA) failed");
265277
wb_fail = 1;
266278
ok = 0;
267279
}
268-
if (ok && wc_ecc_make_key_ex(&rng, fieldSz, &keyB, curve_id) != 0) {
280+
if (ok && WB_CHECK(wc_ecc_make_key_ex(&rng, fieldSz, &keyB, curve_id)) != 0) {
269281
WB_NOTE("wc_ecc_make_key_ex(keyB) failed");
270282
wb_fail = 1;
271283
ok = 0;
272284
}
273285

274286
if (ok) {
275287
sigLen = (word32)sizeof(sig);
276-
if (wc_ecc_sign_hash(wb_digest, (word32)sizeof(wb_digest), sig,
277-
&sigLen, &rng, &keyA) != 0) {
288+
if (WB_CHECK(wc_ecc_sign_hash(wb_digest, (word32)sizeof(wb_digest), sig,
289+
&sigLen, &rng, &keyA)) != 0) {
278290
WB_NOTE("wc_ecc_sign_hash failed");
279291
wb_fail = 1;
280292
}
281-
else if (wc_ecc_verify_hash(sig, sigLen, wb_digest,
282-
(word32)sizeof(wb_digest), &verifyRes, &keyA) != 0) {
293+
else if (WB_CHECK(wc_ecc_verify_hash(sig, sigLen, wb_digest,
294+
(word32)sizeof(wb_digest), &verifyRes, &keyA)) != 0) {
283295
WB_NOTE("wc_ecc_verify_hash failed");
284296
wb_fail = 1;
285297
}
286298

287299
PRIVATE_KEY_UNLOCK();
288300
secretALen = (word32)sizeof(secretA);
289-
if (wc_ecc_shared_secret(&keyA, &keyB, secretA, &secretALen) != 0) {
301+
if (WB_CHECK(wc_ecc_shared_secret(&keyA, &keyB, secretA, &secretALen)) != 0) {
290302
WB_NOTE("wc_ecc_shared_secret(A,B) failed");
291303
wb_fail = 1;
292304
}
@@ -1579,12 +1591,12 @@ static void wb_run_crafted_curve(int curve_id, int fieldSz,
15791591
return;
15801592
}
15811593

1582-
if (wc_ecc_make_key_ex(&rng, fieldSz, &keyA, curve_id) != 0) {
1594+
if (WB_CHECK(wc_ecc_make_key_ex(&rng, fieldSz, &keyA, curve_id)) != 0) {
15831595
WB_NOTE("wc_ecc_make_key_ex(keyA) failed (crafted)");
15841596
wb_fail = 1;
15851597
ok = 0;
15861598
}
1587-
if (ok && wc_ecc_make_key_ex(&rng, fieldSz, &keyB, curve_id) != 0) {
1599+
if (ok && WB_CHECK(wc_ecc_make_key_ex(&rng, fieldSz, &keyB, curve_id)) != 0) {
15881600
WB_NOTE("wc_ecc_make_key_ex(keyB) failed (crafted)");
15891601
wb_fail = 1;
15901602
ok = 0;
@@ -1985,18 +1997,34 @@ int main(void)
19851997
wb_run_crafted();
19861998
wb_spc_all();
19871999

1988-
/* Refused save: every lane returns its error instead of running,
1989-
* so the drivers report failures here by design. */
2000+
/* Refused save: every lane returns its error instead of running, so
2001+
* the drivers report failures here by design. The counters turn that
2002+
* into a check: a call that SUCCEEDS with the save refused means the
2003+
* dispatch found another way to run, which is what this file exists
2004+
* to keep out. */
19902005
cpuid_select_flags(real);
19912006
wb_intr_ret = 1;
2007+
wb_expect_refusal = 1;
19922008
wb_run_ecc();
19932009
wb_run_rsa_signverify();
19942010
wb_run_dh();
19952011
wb_run_dispatch();
19962012
wb_run_crafted();
19972013
wb_spc_all();
2014+
wb_expect_refusal = 0;
19982015
wb_intr_ret = 0;
19992016

2017+
printf(" [wb] refused save: %ld calls failed as required, %ld ran anyway\n",
2018+
wb_refused_ok, wb_refused_bad);
2019+
if (wb_refused_bad != 0) {
2020+
printf(" [wb] FAIL: a refused vector-register save did not stop the call\n");
2021+
wb_contract_fail = 1;
2022+
}
2023+
if (wb_refused_ok == 0) {
2024+
printf(" [wb] FAIL: nothing was seen failing, so this check proves nothing\n");
2025+
wb_contract_fail = 1;
2026+
}
2027+
20002028
wb_run_rsa_free();
20012029

20022030
/* Allocation-failure pass.
@@ -2042,5 +2070,6 @@ int main(void)
20422070
printf(" no SP feature; nothing to exercise\n");
20432071
#endif
20442072
(void)wb_fail;
2045-
return 0;
2073+
/* Coverage sweeps stay advisory; the fail-closed contract does not. */
2074+
return wb_contract_fail;
20462075
}

0 commit comments

Comments
 (0)