@@ -28,7 +28,7 @@ import semmle.code.cpp.dataflow.new.DataFlow
2828 * - EVP_MD_CTX
2929 * - EVP_PKEY_CTX
3030 */
31- private class CtxType extends Type {
31+ class CtxType extends Type {
3232 CtxType ( ) {
3333 // It is possible for users to use the underlying type of the CTX variables
3434 // these have a name matching 'evp_%ctx_%st
@@ -47,7 +47,7 @@ private class CtxType extends Type {
4747/**
4848 * A pointer to a CtxType
4949 */
50- private class CtxPointerExpr extends Expr {
50+ class CtxPointerExpr extends Expr {
5151 CtxPointerExpr ( ) {
5252 this .getType ( ) instanceof CtxType and
5353 this .getType ( ) instanceof PointerType
@@ -57,7 +57,7 @@ private class CtxPointerExpr extends Expr {
5757/**
5858 * A call argument of type CtxPointerExpr.
5959 */
60- private class CtxPointerArgument extends CtxPointerExpr {
60+ class CtxPointerArgument extends CtxPointerExpr {
6161 CtxPointerArgument ( ) { exists ( Call c | c .getAnArgument ( ) = this ) }
6262
6363 Call getCall ( ) { result .getAnArgument ( ) = this }
@@ -83,32 +83,103 @@ private class CtxClearCall extends Call {
8383 }
8484}
8585
86+ abstract private class CtxPassThroughCall extends Call {
87+ abstract DataFlow:: Node getNode1 ( ) ;
88+
89+ abstract DataFlow:: Node getNode2 ( ) ;
90+ }
91+
8692/**
8793 * A call whose target contains 'copy' and has an argument of type
8894 * CtxPointerArgument.
8995 */
90- private class CtxCopyOutArgCall extends Call {
96+ private class CtxCopyOutArgCall extends CtxPassThroughCall {
97+ DataFlow:: Node n1 ;
98+ DataFlow:: Node n2 ;
99+
91100 CtxCopyOutArgCall ( ) {
92101 this .getTarget ( ) .getName ( ) .toLowerCase ( ) .matches ( "%copy%" ) and
93- this .getAnArgument ( ) instanceof CtxPointerArgument
102+ n1 .asExpr ( ) = this .getAnArgument ( ) and
103+ n1 .getType ( ) instanceof CtxType and
104+ n2 .asDefiningArgument ( ) = this .getAnArgument ( ) and
105+ n2 .getType ( ) instanceof CtxType and
106+ n1 .asDefiningArgument ( ) != n2 .asExpr ( )
94107 }
108+
109+ override DataFlow:: Node getNode1 ( ) { result = n1 }
110+
111+ override DataFlow:: Node getNode2 ( ) { result = n2 }
95112}
96113
97114/**
98115 * A call whose target contains 'dup' and has an argument of type
99116 * CtxPointerArgument.
100117 */
101- private class CtxCopyReturnCall extends Call , CtxPointerExpr {
118+ private class CtxCopyReturnCall extends CtxPassThroughCall , CtxPointerExpr {
119+ DataFlow:: Node n1 ;
120+
102121 CtxCopyReturnCall ( ) {
103122 this .getTarget ( ) .getName ( ) .toLowerCase ( ) .matches ( "%dup%" ) and
104- this .getAnArgument ( ) instanceof CtxPointerArgument
123+ n1 .asExpr ( ) = this .getAnArgument ( ) and
124+ n1 .getType ( ) instanceof CtxType
125+ }
126+
127+ override DataFlow:: Node getNode1 ( ) { result = n1 }
128+
129+ override DataFlow:: Node getNode2 ( ) { result .asExpr ( ) = this }
130+ }
131+
132+ /**
133+ * A call to `EVP_PKEY_paramgen` acts as a kind of pass through.
134+ * It's output pkey is eventually used in a new operation generating
135+ * a fresh context pointer (e.g., `EVP_PKEY_CTX_new`).
136+ * It is easier to model this as a pass through
137+ * than to model the flow from the paramgen to the new key generation.
138+ */
139+ private class CtxParamGenCall extends CtxPassThroughCall {
140+ DataFlow:: Node n1 ;
141+ DataFlow:: Node n2 ;
142+
143+ CtxParamGenCall ( ) {
144+ this .getTarget ( ) .getName ( ) = "EVP_PKEY_paramgen" and
145+ n1 .asExpr ( ) = this .getArgument ( 0 ) and
146+ (
147+ n2 .asExpr ( ) = this .getArgument ( 1 )
148+ or
149+ n2 .asDefiningArgument ( ) = this .getArgument ( 1 )
150+ )
105151 }
152+
153+ override DataFlow:: Node getNode1 ( ) { result = n1 }
154+
155+ override DataFlow:: Node getNode2 ( ) { result = n2 }
156+ }
157+
158+ /**
159+ * If the current node gets is an argument to a function
160+ * that returns a pointer type, immediately flow through.
161+ * NOTE: this passthrough is required if we allow
162+ * intermediate steps to go into variables that are not a CTX type.
163+ * See for example `CtxParamGenCall`.
164+ */
165+ private class CallArgToCtxRet extends CtxPassThroughCall , CtxPointerExpr {
166+ DataFlow:: Node n1 ;
167+ DataFlow:: Node n2 ;
168+
169+ CallArgToCtxRet ( ) {
170+ this .getAnArgument ( ) = n1 .asExpr ( ) and
171+ n2 .asExpr ( ) = this
172+ }
173+
174+ override DataFlow:: Node getNode1 ( ) { result = n1 }
175+
176+ override DataFlow:: Node getNode2 ( ) { result = n2 }
106177}
107178
108179/**
109180 * A source Ctx of interest is any argument or return of type CtxPointerExpr.
110181 */
111- private class CtxPointerSource extends CtxPointerExpr {
182+ class CtxPointerSource extends CtxPointerExpr {
112183 CtxPointerSource ( ) {
113184 this instanceof CtxPointerReturn or
114185 this instanceof CtxPointerArgument
@@ -122,43 +193,31 @@ private class CtxPointerSource extends CtxPointerExpr {
122193}
123194
124195/**
125- * Flow from any CtxPointerSource to any CtxPointerArgument .
196+ * Flow from any CtxPointerSource to other CtxPointerSource .
126197 */
127- module OpenSSLCtxSourceToArgumentFlowConfig implements DataFlow:: ConfigSig {
198+ module OpenSSLCtxSourceToSourceFlowConfig implements DataFlow:: ConfigSig {
128199 predicate isSource ( DataFlow:: Node source ) { exists ( CtxPointerSource s | s .asNode ( ) = source ) }
129200
130- predicate isSink ( DataFlow:: Node sink ) { sink . asExpr ( ) instanceof CtxPointerArgument }
201+ predicate isSink ( DataFlow:: Node sink ) { exists ( CtxPointerSource s | s . asNode ( ) = sink ) }
131202
132203 predicate isBarrier ( DataFlow:: Node node ) {
133204 exists ( CtxClearCall c | c .getAnArgument ( ) = node .asExpr ( ) )
134205 }
135206
136207 predicate isAdditionalFlowStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
137- exists ( CtxCopyOutArgCall c |
138- c .getAnArgument ( ) = node1 .asExpr ( ) and
139- c .getAnArgument ( ) = node2 .asExpr ( ) and
140- node1 .asExpr ( ) != node2 .asExpr ( ) and
141- node2 .asExpr ( ) .getType ( ) instanceof CtxType
142- )
143- or
144- exists ( CtxCopyReturnCall c |
145- c .getAnArgument ( ) = node1 .asExpr ( ) and
146- c = node2 .asExpr ( ) and
147- node1 .asExpr ( ) != node2 .asExpr ( ) and
148- node2 .asExpr ( ) .getType ( ) instanceof CtxType
149- )
208+ exists ( CtxPassThroughCall c | c .getNode1 ( ) = node1 and c .getNode2 ( ) = node2 )
150209 }
151210}
152211
153- module OpenSSLCtxSourceToArgumentFlow = DataFlow:: Global< OpenSSLCtxSourceToArgumentFlowConfig > ;
212+ module OpenSSLCtxSourceToArgumentFlow = DataFlow:: Global< OpenSSLCtxSourceToSourceFlowConfig > ;
154213
155214/**
156215 * Holds if there is a context flow from the source to the sink.
157216 */
158- predicate ctxArgOrRetFlowsToCtxArg ( CtxPointerSource source , CtxPointerArgument sink ) {
217+ predicate ctxSrcToSrcFlow ( CtxPointerSource source , CtxPointerSource sink ) {
159218 exists ( DataFlow:: Node a , DataFlow:: Node b |
160219 OpenSSLCtxSourceToArgumentFlow:: flow ( a , b ) and
161220 a = source .asNode ( ) and
162- b . asExpr ( ) = sink
221+ b = sink . asNode ( )
163222 )
164223}
0 commit comments