@@ -330,4 +330,81 @@ private module CryptographyModel {
330
330
override DataFlow:: Node getAnInput ( ) { result in [ this .getArg ( 0 ) , this .getArgByName ( "data" ) ] }
331
331
}
332
332
}
333
+
334
+ /** Provides models for the `cryptography.hazmat.primitives.hashes` package */
335
+ private module Hashes {
336
+ /**
337
+ * Gets a reference to a `cryptography.hazmat.primitives.hashes` class, representing
338
+ * a hashing algorithm.
339
+ */
340
+ API:: Node algorithmClassRef ( string algorithmName ) {
341
+ result =
342
+ API:: moduleImport ( "cryptography" )
343
+ .getMember ( "hazmat" )
344
+ .getMember ( "primitives" )
345
+ .getMember ( "hashes" )
346
+ .getMember ( algorithmName )
347
+ }
348
+
349
+ /** Gets a reference to a Hash instance using algorithm with `algorithmName`. */
350
+ private DataFlow:: LocalSourceNode hashInstance ( DataFlow:: TypeTracker t , string algorithmName ) {
351
+ t .start ( ) and
352
+ exists ( DataFlow:: CallCfgNode call | result = call |
353
+ call =
354
+ API:: moduleImport ( "cryptography" )
355
+ .getMember ( "hazmat" )
356
+ .getMember ( "primitives" )
357
+ .getMember ( "hashes" )
358
+ .getMember ( "Hash" )
359
+ .getACall ( ) and
360
+ algorithmClassRef ( algorithmName ) .getReturn ( ) .getAUse ( ) in [
361
+ call .getArg ( 0 ) , call .getArgByName ( "algorithm" )
362
+ ]
363
+ )
364
+ or
365
+ // Due to bad performance when using normal setup with `hashInstance(t2, algorithmName).track(t2, t)`
366
+ // we have inlined that code and forced a join
367
+ exists ( DataFlow:: TypeTracker t2 |
368
+ exists ( DataFlow:: StepSummary summary |
369
+ hashInstance_first_join ( t2 , algorithmName , result , summary ) and
370
+ t = t2 .append ( summary )
371
+ )
372
+ )
373
+ }
374
+
375
+ pragma [ nomagic]
376
+ private predicate hashInstance_first_join (
377
+ DataFlow:: TypeTracker t2 , string algorithmName , DataFlow:: Node res ,
378
+ DataFlow:: StepSummary summary
379
+ ) {
380
+ DataFlow:: StepSummary:: step ( hashInstance ( t2 , algorithmName ) , res , summary )
381
+ }
382
+
383
+ /** Gets a reference to a Hash instance using algorithm with `algorithmName`. */
384
+ DataFlow:: Node hashInstance ( string algorithmName ) {
385
+ hashInstance ( DataFlow:: TypeTracker:: end ( ) , algorithmName ) .flowsTo ( result )
386
+ }
387
+
388
+ /**
389
+ * An hashing operation from `cryptography.hazmat.primitives.hashes`.
390
+ */
391
+ class CryptographyGenericHashOperation extends Cryptography:: CryptographicOperation:: Range ,
392
+ DataFlow:: CallCfgNode {
393
+ string algorithmName ;
394
+
395
+ CryptographyGenericHashOperation ( ) {
396
+ exists ( DataFlow:: AttrRead attr |
397
+ this .getFunction ( ) = attr and
398
+ attr .getAttributeName ( ) = "update" and
399
+ attr .getObject ( ) = hashInstance ( algorithmName )
400
+ )
401
+ }
402
+
403
+ override Cryptography:: CryptographicAlgorithm getAlgorithm ( ) {
404
+ result .matchesName ( algorithmName )
405
+ }
406
+
407
+ override DataFlow:: Node getAnInput ( ) { result in [ this .getArg ( 0 ) , this .getArgByName ( "data" ) ] }
408
+ }
409
+ }
333
410
}
0 commit comments