add backtracking to find division that end up being rounded

This commit is contained in:
Erik Krogh Kristensen
2020-06-15 17:10:10 +02:00
parent b6b838774e
commit 3ef5dc74a1
3 changed files with 17 additions and 6 deletions

View File

@@ -132,6 +132,18 @@ DataFlow::Node goodRandom(DataFlow::SourceNode source) {
result = goodRandom(DataFlow::TypeTracker::end(), source)
}
/**
* Gets a node that is passed to a rounding function from `Math`, using type-backtracker `t`.
*/
DataFlow::Node isRounded(DataFlow::TypeBackTracker t) {
t.start() and
result = DataFlow::globalVarRef("Math").getAMemberCall(["round", "floor", "ceil"]).getArgument(0)
or
exists(DataFlow::TypeBackTracker t2 | t2 = t.smallstep(result, isRounded(t2)))
or
InsecureRandomness::isAdditionalTaintStep(result, isRounded(t.continue()))
}
/**
* Gets a node that that produces a biased result from otherwise cryptographically secure random numbers produced by `source`.
*/
@@ -153,10 +165,7 @@ DataFlow::Node badCrypto(string description, DataFlow::SourceNode source) {
goodRandom(source).asExpr() = div.getLeftOperand() and
description = "division and rounding the result" and
not div.getRightOperand() = isPowerOfTwoMinusOne().asExpr() and // division by (2^n)-1 most of the time produces a uniformly random number between 0 and 1.
DataFlow::globalVarRef("Math")
.getAMemberCall(["round", "floor", "ceil"])
.getArgument(0)
.asExpr() = div
div = isRounded(DataFlow::TypeBackTracker::end()).asExpr()
)
or
// modulo - only bad if not by a power of 2 - and the result is not checked for bias