@@ -8,7 +8,7 @@ import experimental.quantum.Language
88 * NOTE: TODO: need to handle call by refernece for now. Need to re-evaluate (see notes below)
99 * Such functions may be 'wrappers' for some derived value.
1010 */
11- private module WrapperConfig implements DataFlow:: ConfigSig {
11+ private module ArtifactGeneratingWrapperConfig implements DataFlow:: ConfigSig {
1212 predicate isSource ( DataFlow:: Node source ) {
1313 source .asExpr ( ) instanceof Call and
1414 // not handling references yet, I think we want to flat say references are only ok
@@ -28,25 +28,41 @@ private module WrapperConfig implements DataFlow::ConfigSig {
2828 predicate isSink ( DataFlow:: Node sink ) { sink .asExpr ( ) = any ( Crypto:: ArtifactNode i ) .asElement ( ) }
2929}
3030
31- module WrapperFlow = DataFlow :: Global< WrapperConfig > ;
31+ module ArtifactGeneratingWrapperFlow = TaintTracking :: Global< ArtifactGeneratingWrapperConfig > ;
3232
3333/**
3434 * Using a set approach to determine if reuse of an artifact exists.
3535 * This predicate produces a set of 'wrappers' that flow to the artifact node.
3636 * This set can be compared with the set to another artifact node to determine if they are the same.
3737 */
38- private DataFlow:: Node getWrapperSet ( Crypto:: NonceArtifactNode a ) {
39- WrapperFlow :: flow ( result , DataFlow:: exprNode ( a .asElement ( ) ) )
38+ private DataFlow:: Node getGeneratingWrapperSet ( Crypto:: NonceArtifactNode a ) {
39+ ArtifactGeneratingWrapperFlow :: flow ( result , DataFlow:: exprNode ( a .asElement ( ) ) )
4040 or
4141 result .asExpr ( ) = a .getSourceElement ( )
4242}
4343
44+ private predicate ancestorOfArtifact (
45+ Crypto:: ArtifactNode a , Callable enclosingCallable , ControlFlow:: Node midOrTarget
46+ ) {
47+ a .asElement ( ) .( Expr ) .getEnclosingCallable ( ) = enclosingCallable and
48+ (
49+ midOrTarget .asExpr ( ) = a .asElement ( ) or
50+ midOrTarget .asExpr ( ) .( Call ) .getCallee ( ) .calls * ( a .asElement ( ) .( Expr ) .getEnclosingCallable ( ) )
51+ )
52+ }
53+
4454/**
4555 * Two different artifact nodes are considered reuse if any of the following conditions are met:
4656 * 1. The source for artifact `a` and artifact `b` are the same and the source is a literal.
4757 * 2. The source for artifact `a` and artifact `b` are not the same and the source is a literal of the same value.
48- * 3. For all 'wrappers' that return the source of artifact `a`, and that wrapper also exists for artifact `b`.
49- * 4. For all 'wrappers' that return the source of artifact `b`, and that wrapper also exists for artifact `a`.
58+ * 3. For all 'wrappers' that return the source of artifact `a`, and each wrapper also exists for artifact `b`.
59+ * 4. For all 'wrappers' that return the source of artifact `b`, and each wrapper also exists for artifact `a`.
60+ *
61+ * The above conditions determine that the use of the IV is from the same source, but the use may
62+ * be on separate code paths that do not occur sequentially. We must therefore also find a common callable ancestor
63+ * for both uses, and in that ancestor, there must be control flow from the call or use of one to the call or use of the other.
64+ * Note that if no shared ancestor callable exists, it means the flow is more nuanced and ignore the shared ancestor
65+ * use flow.
5066 */
5167predicate isArtifactReuse ( Crypto:: ArtifactNode a , Crypto:: ArtifactNode b ) {
5268 a != b and
@@ -55,12 +71,32 @@ predicate isArtifactReuse(Crypto::ArtifactNode a, Crypto::ArtifactNode b) {
5571 or
5672 a .getSourceElement ( ) .( Literal ) .getValue ( ) = b .getSourceElement ( ) .( Literal ) .getValue ( )
5773 or
58- forex ( DataFlow:: Node e | e = getWrapperSet ( a ) |
59- exists ( DataFlow:: Node e2 | e2 = getWrapperSet ( b ) | e = e2 )
74+ forex ( DataFlow:: Node e | e = getGeneratingWrapperSet ( a ) |
75+ exists ( DataFlow:: Node e2 | e2 = getGeneratingWrapperSet ( b ) | e = e2 )
6076 )
6177 or
62- forex ( DataFlow:: Node e | e = getWrapperSet ( b ) |
63- exists ( DataFlow:: Node e2 | e2 = getWrapperSet ( a ) | e = e2 )
78+ forex ( DataFlow:: Node e | e = getGeneratingWrapperSet ( b ) |
79+ exists ( DataFlow:: Node e2 | e2 = getGeneratingWrapperSet ( a ) | e = e2 )
80+ )
81+ ) and
82+ // If there is a common parent, there is control flow between the two uses in the parent
83+ // TODO: this logic needs to be examined/revisited to ensure it is correct
84+ (
85+ exists ( Callable commonParent |
86+ ancestorOfArtifact ( a , commonParent , _) and
87+ ancestorOfArtifact ( b , commonParent , _)
88+ )
89+ implies
90+ exists ( Callable commonParent , ControlFlow:: Node aMid , ControlFlow:: Node bMid |
91+ ancestorOfArtifact ( a , commonParent , aMid ) and
92+ ancestorOfArtifact ( b , commonParent , bMid ) and
93+ a instanceof Crypto:: NonceArtifactNode and
94+ b instanceof Crypto:: NonceArtifactNode and
95+ (
96+ aMid .getASuccessor * ( ) = bMid
97+ or
98+ bMid .getASuccessor * ( ) = aMid
99+ )
64100 )
65101 )
66102}
0 commit comments