@@ -370,6 +370,25 @@ private int getIntArgument(DataFlow::CallNode call, int i) {
370370 result = call .getArgument ( i ) .asExpr ( ) .getConstantValue ( ) .getInt ( )
371371}
372372
373+ bindingset [ blockCipherName]
374+ private Cryptography:: BlockMode getCandidateBlockModeFromCipherName ( string blockCipherName ) {
375+ result = blockCipherName .splitAt ( "-" , [ 1 , 2 ] ) .toUpperCase ( )
376+ }
377+
378+ /**
379+ * Gets the block mode specified as part of a block cipher name used to
380+ * instantiate an `OpenSSL::Cipher` instance. If the block mode is not
381+ * explicitly specified, this defaults to "CBC".
382+ */
383+ bindingset [ blockCipherName]
384+ private Cryptography:: BlockMode getBlockModeFromCipherName ( string blockCipherName ) {
385+ // Extract the block mode from the cipher name
386+ result = getCandidateBlockModeFromCipherName ( blockCipherName )
387+ or
388+ // Fall back on the OpenSSL default of CBC if the block mode is unspecified
389+ not exists ( getCandidateBlockModeFromCipherName ( blockCipherName ) ) and result = "CBC"
390+ }
391+
373392/**
374393 * Holds if `call` is a call to `OpenSSL::Cipher.new` that instantiates a
375394 * `cipher` instance with mode `cipherMode`.
@@ -381,8 +400,9 @@ private predicate cipherInstantiationGeneric(
381400 // `OpenSSL::Cipher.new('<cipherName>')`
382401 call = cipherApi ( ) .getAnInstantiation ( ) and
383402 cipherName = getStringArgument ( call , 0 ) and
384- // CBC is used by default
385- cipherMode .isBlockMode ( "CBC" )
403+ if cipher .getAlgorithm ( ) .isStreamCipher ( )
404+ then cipherMode = TStreamCipher ( )
405+ else cipherMode .isBlockMode ( getBlockModeFromCipherName ( cipherName ) )
386406 )
387407}
388408
@@ -397,12 +417,12 @@ private predicate cipherInstantiationAES(
397417 exists ( string cipherName | cipher .matchesName ( cipherName ) |
398418 // `OpenSSL::Cipher::AES` instantiations
399419 call = cipherApi ( ) .getMember ( "AES" ) .getAnInstantiation ( ) and
400- exists ( string keyLength , string blockMode |
420+ exists ( string keyLength , Cryptography :: BlockMode blockMode |
401421 // `OpenSSL::Cipher::AES.new('<keyLength-blockMode>')
402422 exists ( string arg0 |
403423 arg0 = getStringArgument ( call , 0 ) and
404424 keyLength = arg0 .splitAt ( "-" , 0 ) and
405- blockMode = arg0 . splitAt ( "-" , 1 ) . toUpperCase ( )
425+ blockMode = getBlockModeFromCipherName ( arg0 )
406426 )
407427 or
408428 // `OpenSSL::Cipher::AES.new(<keyLength>, '<blockMode>')`
@@ -418,7 +438,7 @@ private predicate cipherInstantiationAES(
418438 call = cipherApi ( ) .getMember ( mod ) .getAnInstantiation ( ) and
419439 // Canonical representation is `AES-<keyLength>`
420440 blockAlgo = "AES-" + mod .suffix ( 3 ) and
421- exists ( string blockMode |
441+ exists ( Cryptography :: BlockMode blockMode |
422442 if exists ( getStringArgument ( call , 0 ) )
423443 then
424444 // `OpenSSL::Cipher::<blockAlgo>.new('<blockMode>')`
@@ -445,7 +465,7 @@ private predicate cipherInstantiationSpecific(
445465 // Block ciphers with dedicated modules
446466 exists ( string blockAlgo | blockAlgo = [ "BF" , "CAST5" , "DES" , "IDEA" , "RC2" ] |
447467 call = cipherApi ( ) .getMember ( blockAlgo ) .getAnInstantiation ( ) and
448- exists ( string blockMode |
468+ exists ( Cryptography :: BlockMode blockMode |
449469 if exists ( getStringArgument ( call , 0 ) )
450470 then
451471 // `OpenSSL::Cipher::<blockAlgo>.new('<blockMode>')`
0 commit comments