@@ -330,4 +330,81 @@ private module CryptographyModel {
330330 override DataFlow:: Node getAnInput ( ) { result in [ this .getArg ( 0 ) , this .getArgByName ( "data" ) ] }
331331 }
332332 }
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+ }
333410}
0 commit comments