commit 1024a263bdbf80cc9451e5171b376aa104d6c4be
parent c226539fea1c99fb6df434406eae0419d39aea00
Author: Jared Tobin <jared@jtobin.io>
Date: Fri, 13 Feb 2026 07:34:27 +0400
misc: improve nct output
Diffstat:
6 files changed, 37 insertions(+), 59 deletions(-)
diff --git a/app/Main.hs b/app/Main.hs
@@ -185,8 +185,14 @@ outputNct opts findings = do
else exitFailure
printNctSummary :: (Text, [NctFinding]) -> IO ()
-printNctSummary (sym, fs) =
+printNctSummary (sym, fs) = do
TIO.putStrLn $ sym <> ": " <> T.pack (show (length fs))
+ mapM_ printFindingIndented fs
+
+printFindingIndented :: NctFinding -> IO ()
+printFindingIndented f = TIO.putStrLn $
+ " " <> T.pack (show (nctLine f)) <> ": "
+ <> nctReasonText (nctReason f) <> ": " <> instrText (nctInstr f)
printNctDetail :: (Text, [NctFinding]) -> IO ()
printNctDetail (sym, fs) = mapM_ (printFinding sym) fs
@@ -201,8 +207,6 @@ nctReasonText r = case r of
CondBranch -> "cond-branch"
IndirectBranch -> "indirect-branch"
Div -> "div"
- MulOp -> "mul"
- VarShift -> "var-shift"
RegIndexAddr -> "reg-index"
instrText :: Instr -> Text
diff --git a/etc/taint.json b/etc/taint.json
@@ -1,7 +1,6 @@
{
"_mul_wnaf_info": {
- "secret": ["X23"],
- "public": ["X19", "X20", "X21", "X22"]
+ "secret": ["X23", "X24"]
},
"_Numeric.Montgomery.Secp256k1.Curve.inv#_info": {
"secret": ["X23", "X24", "X25", "X26"]
diff --git a/etc/taint_inv.json b/etc/taint_inv.json
@@ -0,0 +1,8 @@
+{
+"_ppadzmfixedzm0zi1zi3zminplace_NumericziMontgomeryziSecp256k1ziCurve_invzh_info$def": {
+ "secret": ["X22", "X23", "X24", "X25", "X26"]
+ }
+}
+
+
+
diff --git a/etc/taint_mul_wnaf.json b/etc/taint_mul_wnaf.json
@@ -0,0 +1,5 @@
+{
+ "_mul_wnaf_info": {
+ "stg_secret": [8, 152]
+ }
+}
diff --git a/lib/Audit/AArch64/NCT.hs b/lib/Audit/AArch64/NCT.hs
@@ -33,8 +33,6 @@ data NctReason
= CondBranch -- ^ Conditional branch (b.<cond>, cbz, cbnz, tbz, tbnz)
| IndirectBranch -- ^ Indirect branch (br, blr)
| Div -- ^ Division (udiv, sdiv)
- | MulOp -- ^ Multiplication (mul, madd, msub, umulh, smulh)
- | VarShift -- ^ Variable shift (lsl, lsr, asr, ror with reg operand)
| RegIndexAddr -- ^ Register-indexed memory access
deriving (Eq, Ord, Show, Generic, NFData)
@@ -86,23 +84,10 @@ classifyInstr instr = case instr of
Br _ -> Just IndirectBranch
Blr _ -> Just IndirectBranch
- -- Division
+ -- Division (not DIT per ARM docs)
Udiv _ _ _ -> Just Div
Sdiv _ _ _ -> Just Div
- -- Multiplication
- Mul _ _ _ -> Just MulOp
- Madd _ _ _ _ -> Just MulOp
- Msub _ _ _ _ -> Just MulOp
- Umulh _ _ _ -> Just MulOp
- Smulh _ _ _ -> Just MulOp
-
- -- Variable shifts (only when shift amount is register)
- Lsl _ _ op -> checkVarShiftOp op
- Lsr _ _ op -> checkVarShiftOp op
- Asr _ _ op -> checkVarShiftOp op
- Ror _ _ op -> checkVarShiftOp op
-
-- Load/store with register index
Ldr _ addr -> checkRegIndexAddr addr
Ldrb _ addr -> checkRegIndexAddr addr
@@ -144,14 +129,6 @@ classifyInstr instr = case instr of
_ -> Nothing
--- | Check if operand indicates variable shift (register-based).
-checkVarShiftOp :: Operand -> Maybe NctReason
-checkVarShiftOp op = case op of
- OpReg _ -> Just VarShift
- OpShiftedReg _ _ -> Just VarShift
- OpExtendedReg _ _ -> Just VarShift
- _ -> Nothing
-
-- | Check if address mode uses register indexing.
checkRegIndexAddr :: AddrMode -> Maybe NctReason
checkRegIndexAddr addr = case addr of
diff --git a/test/Main.hs b/test/Main.hs
@@ -1175,65 +1175,50 @@ nctTests = testGroup "NCT" [
[f] -> assertEqual "reason" Div (nctReason f)
_ -> assertFailure "expected 1 finding"
- , testCase "mul: mul" $ do
+ , testCase "no finding: mul (DIT)" $ do
+ -- mul is DIT per ARM docs
let src = "foo:\n mul x0, x1, x2\n"
case parseAsm src of
Left e -> assertFailure $ "parse failed: " ++ show e
Right lns -> do
let m = scanNct lns
- case Map.lookup "foo" m of
- Nothing -> assertFailure "no findings"
- Just fs -> case fs of
- [f] -> assertEqual "reason" MulOp (nctReason f)
- _ -> assertFailure "expected 1 finding"
+ assertEqual "no findings" Nothing (Map.lookup "foo" m)
- , testCase "mul: madd" $ do
+ , testCase "no finding: madd (DIT)" $ do
+ -- madd is DIT per ARM docs
let src = "foo:\n madd x0, x1, x2, x3\n"
case parseAsm src of
Left e -> assertFailure $ "parse failed: " ++ show e
Right lns -> do
let m = scanNct lns
- case Map.lookup "foo" m of
- Nothing -> assertFailure "no findings"
- Just fs -> case fs of
- [f] -> assertEqual "reason" MulOp (nctReason f)
- _ -> assertFailure "expected 1 finding"
+ assertEqual "no findings" Nothing (Map.lookup "foo" m)
- , testCase "mul: umulh" $ do
+ , testCase "no finding: umulh (DIT)" $ do
+ -- umulh is DIT per ARM docs
let src = "foo:\n umulh x0, x1, x2\n"
case parseAsm src of
Left e -> assertFailure $ "parse failed: " ++ show e
Right lns -> do
let m = scanNct lns
- case Map.lookup "foo" m of
- Nothing -> assertFailure "no findings"
- Just fs -> case fs of
- [f] -> assertEqual "reason" MulOp (nctReason f)
- _ -> assertFailure "expected 1 finding"
+ assertEqual "no findings" Nothing (Map.lookup "foo" m)
- , testCase "var-shift: lsl with reg" $ do
+ , testCase "no finding: lsl with reg (DIT)" $ do
+ -- variable shifts are DIT per ARM docs
let src = "foo:\n lsl x0, x1, x2\n"
case parseAsm src of
Left e -> assertFailure $ "parse failed: " ++ show e
Right lns -> do
let m = scanNct lns
- case Map.lookup "foo" m of
- Nothing -> assertFailure "no findings"
- Just fs -> case fs of
- [f] -> assertEqual "reason" VarShift (nctReason f)
- _ -> assertFailure "expected 1 finding"
+ assertEqual "no findings" Nothing (Map.lookup "foo" m)
- , testCase "var-shift: lsr with reg" $ do
+ , testCase "no finding: lsr with reg (DIT)" $ do
+ -- variable shifts are DIT per ARM docs
let src = "foo:\n lsr x0, x1, x2\n"
case parseAsm src of
Left e -> assertFailure $ "parse failed: " ++ show e
Right lns -> do
let m = scanNct lns
- case Map.lookup "foo" m of
- Nothing -> assertFailure "no findings"
- Just fs -> case fs of
- [f] -> assertEqual "reason" VarShift (nctReason f)
- _ -> assertFailure "expected 1 finding"
+ assertEqual "no findings" Nothing (Map.lookup "foo" m)
, testCase "no finding: lsl with imm" $ do
-- lsl x0, x1, #5 should NOT flag (immediate shift)