@@ -56,6 +56,9 @@ module JCAModel {
56
56
bindingset [ name]
57
57
predicate elliptic_curve_names ( string name ) { Crypto:: isEllipticCurveAlgorithmName ( name ) }
58
58
59
+ bindingset [ name]
60
+ predicate key_agreement_names ( string name ) { Crypto:: isKeyAgreementAlgorithmName ( name ) }
61
+
59
62
bindingset [ name]
60
63
Crypto:: TKeyDerivationType kdf_name_to_kdf_type ( string name , string withSubstring ) {
61
64
name .matches ( "PBKDF2With%" ) and
@@ -123,6 +126,10 @@ module JCAModel {
123
126
string getStandardEllipticCurveName ( ) { result = this .getValue ( ) }
124
127
}
125
128
129
+ class KeyAgreementStringLiteral extends StringLiteral {
130
+ KeyAgreementStringLiteral ( ) { key_agreement_names ( this .getValue ( ) ) }
131
+ }
132
+
126
133
class CipherGetInstanceCall extends Call {
127
134
CipherGetInstanceCall ( ) {
128
135
this .getCallee ( ) .hasQualifiedName ( "javax.crypto" , "Cipher" , "getInstance" )
@@ -166,7 +173,7 @@ module JCAModel {
166
173
TaintTracking:: Global< CipherAlgorithmStringToFetchConfig > ;
167
174
168
175
/**
169
- * Data-flow configuration modelling flow from a cipher string literal to a value consumer argument.
176
+ * Data-flow configuration modelling flow from a elliptic curve literal to a value consumer argument.
170
177
*/
171
178
private module EllipticCurveAlgorithmStringToFetchConfig implements DataFlow:: ConfigSig {
172
179
predicate isSource ( DataFlow:: Node src ) { src .asExpr ( ) instanceof EllipticCurveStringLiteral }
@@ -211,6 +218,89 @@ module JCAModel {
211
218
}
212
219
}
213
220
221
+ /**
222
+ * Data-flow configuration modelling flow from a key agreement literal to a value consumer argument.
223
+ */
224
+ private module KeyAgreementAlgorithmStringToFetchConfig implements DataFlow:: ConfigSig {
225
+ predicate isSource ( DataFlow:: Node src ) { src .asExpr ( ) instanceof KeyAgreementStringLiteral }
226
+
227
+ predicate isSink ( DataFlow:: Node sink ) {
228
+ exists ( Crypto:: AlgorithmValueConsumer consumer | sink = consumer .getInputNode ( ) )
229
+ }
230
+ }
231
+
232
+ module KeyAgreementAlgorithmStringToFetchFlow =
233
+ TaintTracking:: Global< KeyAgreementAlgorithmStringToFetchConfig > ;
234
+
235
+ class KeyAgreementInitCall extends MethodCall {
236
+ KeyAgreementInitCall ( ) {
237
+ this .getCallee ( ) .hasQualifiedName ( "javax.crypto" , "KeyAgreement" , "init" )
238
+ }
239
+
240
+ Expr getServerKeyArg ( ) { result = this .getArgument ( 0 ) }
241
+ }
242
+
243
+ private module KeyAgreementInitQualifierToSecretGenQualifierConfig implements DataFlow:: ConfigSig {
244
+ predicate isSource ( DataFlow:: Node src ) {
245
+ exists ( KeyAgreementInitCall init | src .asExpr ( ) = init .getQualifier ( ) )
246
+ }
247
+
248
+ predicate isSink ( DataFlow:: Node sink ) {
249
+ exists ( KeyAgreementGenerateSecretCall c | sink .asExpr ( ) = c .getQualifier ( ) )
250
+ }
251
+
252
+ /**
253
+ * Barrier if we go into another init, assume the second init overwrites the first
254
+ */
255
+ predicate isBarrierIn ( DataFlow:: Node node ) { isSource ( node ) }
256
+ }
257
+
258
+ module KeyAgreementInitQualifierToSecretGenQualifierFlow =
259
+ DataFlow:: Global< KeyAgreementInitQualifierToSecretGenQualifierConfig > ;
260
+
261
+ class KeyAgreementGenerateSecretCall extends MethodCall {
262
+ KeyAgreementGenerateSecretCall ( ) {
263
+ this .getCallee ( ) .hasQualifiedName ( "javax.crypto" , "KeyAgreement" , "generateSecret" )
264
+ }
265
+
266
+ KeyAgreementInitCall getKeyAgreementInitCall ( ) {
267
+ KeyAgreementInitQualifierToSecretGenQualifierFlow:: flow ( DataFlow:: exprNode ( result
268
+ .getQualifier ( ) ) , DataFlow:: exprNode ( this .getQualifier ( ) ) )
269
+ }
270
+ }
271
+
272
+ private module KeyAgreementAVCToInitQualifierConfig implements DataFlow:: ConfigSig {
273
+ predicate isSource ( DataFlow:: Node src ) {
274
+ exists ( KeyAgreementAlgorithmValueConsumer consumer | consumer .getResultNode ( ) = src )
275
+ }
276
+
277
+ predicate isSink ( DataFlow:: Node sink ) {
278
+ exists ( KeyAgreementInitCall init | sink .asExpr ( ) = init .getQualifier ( ) )
279
+ }
280
+ }
281
+
282
+ module KeyAgreementAVCToInitQualifierFlow =
283
+ DataFlow:: Global< KeyAgreementAVCToInitQualifierConfig > ;
284
+
285
+ class KeyAgreementSecretGenerationOperationInstance extends Crypto:: KeyAgreementSecretGenerationOperationInstance instanceof KeyAgreementGenerateSecretCall
286
+ {
287
+ override Crypto:: ConsumerInputDataFlowNode getServerKeyConsumer ( ) {
288
+ this .( KeyAgreementGenerateSecretCall ) .getKeyAgreementInitCall ( ) .getServerKeyArg ( ) =
289
+ result .asExpr ( )
290
+ }
291
+
292
+ override Crypto:: ConsumerInputDataFlowNode getPeerKeyConsumer ( ) {
293
+ none ( ) //TODO
294
+ }
295
+
296
+ override Crypto:: AlgorithmValueConsumer getAnAlgorithmValueConsumer ( ) {
297
+ none ( ) // TODO: key agreeement has it's own algorithm consumer, separate from the key
298
+ // TODO: the char pred must trace from the consumer to here,
299
+ // in theory, along that path we would get the init and doPhase, but can I just get those
300
+ // separately avoiding a complicated config state for dataflow?
301
+ }
302
+ }
303
+
214
304
class CipherStringLiteralModeAlgorithmInstance extends JCAAlgorithmInstance ,
215
305
CipherStringLiteralPaddingAlgorithmInstance , Crypto:: ModeOfOperationAlgorithmInstance instanceof CipherStringLiteral
216
306
{
@@ -339,7 +429,7 @@ module JCAModel {
339
429
}
340
430
341
431
class EllipticCurveStringLiteralAlgorithmInstance extends JCAAlgorithmInstance ,
342
- Crypto:: EllipticCurveAlgorithmInstance instanceof StringLiteral
432
+ Crypto:: EllipticCurveAlgorithmInstance instanceof EllipticCurveStringLiteral
343
433
{
344
434
Crypto:: AlgorithmValueConsumer consumer ;
345
435
@@ -367,6 +457,47 @@ module JCAModel {
367
457
}
368
458
}
369
459
460
+ class KeyAgreementGetInstanceCall extends MethodCall {
461
+ KeyAgreementGetInstanceCall ( ) {
462
+ this .getCallee ( ) .hasQualifiedName ( "javax.crypto" , "KeyAgreement" , "getInstance" )
463
+ }
464
+
465
+ Expr getAlgorithmArg ( ) { result = super .getArgument ( 0 ) }
466
+ }
467
+
468
+ class KeyAgreementAlgorithmValueConsumer extends Crypto:: AlgorithmValueConsumer {
469
+ KeyAgreementGetInstanceCall call ;
470
+
471
+ KeyAgreementAlgorithmValueConsumer ( ) { this = call .getAlgorithmArg ( ) }
472
+
473
+ DataFlow:: Node getResultNode ( ) { result .asExpr ( ) = call }
474
+
475
+ override Crypto:: ConsumerInputDataFlowNode getInputNode ( ) { result .asExpr ( ) = this }
476
+
477
+ override Crypto:: AlgorithmInstance getAKnownAlgorithmSource ( ) {
478
+ result .( KeyAgreementStringLiteralAlgorithmInstance ) .getConsumer ( ) = this
479
+ }
480
+ }
481
+
482
+ class KeyAgreementStringLiteralAlgorithmInstance extends JCAAlgorithmInstance ,
483
+ Crypto:: KeyAgreementAlgorithmInstance instanceof KeyAgreementStringLiteral
484
+ {
485
+ Crypto:: AlgorithmValueConsumer consumer ;
486
+
487
+ KeyAgreementStringLiteralAlgorithmInstance ( ) {
488
+ KeyAgreementAlgorithmStringToFetchFlow:: flow ( DataFlow:: exprNode ( this ) , consumer .getInputNode ( ) )
489
+ }
490
+
491
+ override Crypto:: AlgorithmValueConsumer getConsumer ( ) { result = consumer }
492
+ // override Crypto::EllipticCurveAlgorithmInstance getEllipticCurveAlgorithm() {
493
+ // this.(KeyAgreementStringLiteral).getValue().toUpperCase() in ["X25519", "X448"] and
494
+ // // NOTE: this relies upon modeling the elliptic curve on 'this' separately
495
+ // result = this
496
+ // // TODO: or is ecdh and go find the curve
497
+ // // this.(KeyAgreementStringLiteral).toString().toUpperCase() = ["ECDH"]
498
+ // }
499
+ }
500
+
370
501
class CipherStringLiteralAlgorithmInstance extends JCAAlgorithmInstance ,
371
502
Crypto:: CipherAlgorithmInstance instanceof CipherStringLiteral
372
503
{
0 commit comments