@@ -58,6 +58,10 @@ module JCAModel {
58
58
Expr getProviderArg ( ) { result = this .getArgument ( 1 ) }
59
59
}
60
60
61
+ class CipherDoFinalCall extends Call {
62
+ CipherDoFinalCall ( ) { this .getCallee ( ) .hasQualifiedName ( "javax.crypto" , "Cipher" , "doFinal" ) }
63
+ }
64
+
61
65
/**
62
66
* Data-flow configuration modelling flow from a cipher string literal to a `CipherGetInstanceCall` argument.
63
67
*/
@@ -92,6 +96,57 @@ module JCAModel {
92
96
}
93
97
}
94
98
99
+ // TODO: what if encrypt/decrypt mode isn't known
100
+ private module CipherGetInstanceToFinalizeConfig implements DataFlow:: StateConfigSig {
101
+ class FlowState = string ;
102
+
103
+ predicate isSource ( DataFlow:: Node src , FlowState state ) {
104
+ state = "UNKNOWN" and
105
+ src .asExpr ( ) instanceof CipherGetInstanceCall
106
+ }
107
+
108
+ predicate isSink ( DataFlow:: Node sink , FlowState state ) {
109
+ state in [ "ENCRYPT" , "DECRYPT" , "UNKNOWN" ] and
110
+ exists ( CipherDoFinalCall c | c .getQualifier ( ) = sink .asExpr ( ) )
111
+ }
112
+
113
+ predicate isAdditionalFlowStep (
114
+ DataFlow:: Node node1 , FlowState state1 , DataFlow:: Node node2 , FlowState state2
115
+ ) {
116
+ state1 in [ "UNKNOWN" , "ENCRYPT" , "DECRYPT" ] and
117
+ exists ( CipherInitCall c |
118
+ c .getQualifier ( ) = node1 .asExpr ( ) and
119
+ // TODO: not taking into consideration if the mode traces to this arg
120
+ exists ( FieldAccess fa |
121
+ c .getModeArg ( ) = fa and
122
+ (
123
+ fa .getField ( ) .getName ( ) = "ENCRYPT_MODE" and
124
+ state2 = "ENCRYPT"
125
+ or
126
+ fa .getField ( ) .getName ( ) = "DECRYPT_MODE" and
127
+ state2 = "DECRYPT"
128
+ )
129
+ )
130
+ ) and
131
+ node2 = node1
132
+ }
133
+ }
134
+
135
+ module CipherGetInstanceToFinalizeFlow =
136
+ DataFlow:: GlobalWithState< CipherGetInstanceToFinalizeConfig > ;
137
+
138
+ // TODO: what if the mode is UNKNOWN?
139
+ class CipherEncryptionOperation extends Crypto:: EncryptionOperationInstance instanceof Call {
140
+ CipherEncryptionOperation ( ) {
141
+ exists ( CipherGetInstanceToFinalizeFlow:: PathNode sink , CipherDoFinalCall c |
142
+ CipherGetInstanceToFinalizeFlow:: flowPath ( _, sink ) and
143
+ sink .getNode ( ) .asExpr ( ) = c .getQualifier ( ) and
144
+ sink .getState ( ) = "ENCRYPT" and
145
+ this = c
146
+ )
147
+ }
148
+ }
149
+
95
150
/**
96
151
* A block cipher mode of operation, where the mode is specified in the ALG or ALG/MODE/PADDING format.
97
152
*
@@ -272,6 +327,8 @@ module JCAModel {
272
327
class CipherInitCall extends MethodCall {
273
328
CipherInitCall ( ) { this .getCallee ( ) .hasQualifiedName ( "javax.crypto" , "Cipher" , "init" ) }
274
329
330
+ // TODO: this doesn't account for tracing the mode to this arg if expending this arg to have
331
+ // the actual mode directly
275
332
Expr getModeArg ( ) { result = this .getArgument ( 0 ) }
276
333
277
334
Expr getKey ( ) {
0 commit comments