@@ -4,78 +4,172 @@ import semmle.code.cpp.dataflow.new.DataFlow
44module OpenSSLModel {
55 import Language
66
7- abstract class KeyDerivationOperation extends Crypto:: KeyDerivationOperation { }
7+ class FunctionCallOrMacroAccess extends Element {
8+ FunctionCallOrMacroAccess ( ) { this instanceof FunctionCall or this instanceof MacroAccess }
9+
10+ string getTargetName ( ) {
11+ result = this .( FunctionCall ) .getTarget ( ) .getName ( )
12+ or
13+ result = this .( MacroAccess ) .getMacroName ( )
14+ }
15+ }
16+
17+ /**
18+ * Hash function references in OpenSSL.
19+ */
20+ predicate hash_ref_type_mapping_known ( string name , Crypto:: THashType algo ) {
21+ // `ma` name has an LN_ or SN_ prefix, which we want to ignore
22+ // capture any name after the _ prefix using regex matching
23+ name = [ "sha1" , "sha160" ] and algo instanceof Crypto:: SHA1
24+ or
25+ name = [ "sha224" , "sha256" , "sha384" , "sha512" ] and algo instanceof Crypto:: SHA2
26+ or
27+ name = [ "sha3-224" , "sha3-256" , "sha3-384" , "sha3-512" ] and algo instanceof Crypto:: SHA3
28+ or
29+ name = "md2" and algo instanceof Crypto:: MD2
30+ or
31+ name = "md4" and algo instanceof Crypto:: MD4
32+ or
33+ name = "md5" and algo instanceof Crypto:: MD5
34+ or
35+ name = "ripemd160" and algo instanceof Crypto:: RIPEMD160
36+ or
37+ name = "whirlpool" and algo instanceof Crypto:: WHIRLPOOL
38+ }
39+
40+ predicate hash_ref_type_mapping ( FunctionCallOrMacroAccess ref , string name , Crypto:: THashType algo ) {
41+ name = ref .getTargetName ( ) .regexpCapture ( "(?:SN_|LN_|EVP_)([a-z0-9]+)" , 1 ) and
42+ hash_ref_type_mapping_known ( name , algo )
43+ }
44+
45+ class HashAlgorithmRef extends Crypto:: HashAlgorithm {
46+ FunctionCallOrMacroAccess instance ;
47+
48+ HashAlgorithmRef ( ) {
49+ this = Crypto:: THashAlgorithm ( instance ) and
50+ hash_ref_type_mapping ( instance , _, _)
51+ }
52+
53+ override string getSHA2OrSHA3DigestSize ( Location location ) {
54+ (
55+ this .getHashType ( ) instanceof Crypto:: SHA2 or
56+ this .getHashType ( ) instanceof Crypto:: SHA3
57+ ) and
58+ exists ( string name |
59+ hash_ref_type_mapping ( instance , name , this .getHashType ( ) ) and
60+ result = name .regexpFind ( "\\d{3}" , 0 , _) and
61+ location = instance .getLocation ( )
62+ )
63+ }
864
9- class SHA1Algo extends Crypto:: HashAlgorithm instanceof MacroAccess {
10- SHA1Algo ( ) { this .getMacro ( ) .getName ( ) = "SN_sha1" }
65+ override string getRawAlgorithmName ( ) { result = instance .getTargetName ( ) }
1166
12- override string getRawAlgorithmName ( ) { result = "SN_sha1" }
67+ override Crypto :: THashType getHashType ( ) { hash_ref_type_mapping ( instance , _ , result ) }
1368
14- override Crypto:: THashType getHashType ( ) { result instanceof Crypto:: SHA1 }
69+ Element getInstance ( ) { result = instance }
70+
71+ override Location getLocation ( ) { result = instance .getLocation ( ) }
1572 }
1673
74+ /**
75+ * Data-flow configuration for key derivation algorithm flow to EVP_KDF_derive.
76+ */
1777 module AlgorithmToEVPKeyDeriveConfig implements DataFlow:: ConfigSig {
18- predicate isSource ( DataFlow:: Node source ) { source .asExpr ( ) instanceof KeyDerivationAlgorithm }
78+ predicate isSource ( DataFlow:: Node source ) {
79+ source .asExpr ( ) = any ( KeyDerivationAlgorithm a ) .getInstance ( )
80+ }
1981
2082 predicate isSink ( DataFlow:: Node sink ) {
21- exists ( EVP_KDF_derive kdo | sink .asExpr ( ) = kdo .getAlgorithmArg ( ) )
83+ exists ( EVP_KDF_derive kdo |
84+ sink .asExpr ( ) = kdo .getAlgorithmArg ( )
85+ or
86+ sink .asExpr ( ) = kdo .getContextArg ( ) // via `EVP_KDF_CTX_set_params`
87+ )
88+ }
89+
90+ predicate isAdditionalFlowStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
91+ none ( ) // TODO
2292 }
2393 }
2494
2595 module AlgorithmToEVPKeyDeriveFlow = DataFlow:: Global< AlgorithmToEVPKeyDeriveConfig > ;
2696
27- predicate algorithm_to_EVP_KDF_derive ( Crypto :: Algorithm algo , EVP_KDF_derive derive ) {
28- algo . ( Expr ) . getEnclosingFunction ( ) = derive . ( Expr ) . getEnclosingFunction ( )
97+ predicate algorithm_to_EVP_KDF_derive ( KeyDerivationAlgorithm algo , EVP_KDF_derive derive ) {
98+ none ( )
2999 }
30100
31- class EVP_KDF_derive extends KeyDerivationOperation instanceof FunctionCall {
32- EVP_KDF_derive ( ) { this .getTarget ( ) .getName ( ) = "EVP_KDF_derive" }
101+ /**
102+ * Key derivation operation (e.g., `EVP_KDF_derive`)
103+ */
104+ abstract class KeyDerivationOperation extends Crypto:: KeyDerivationOperation { }
105+
106+ class EVP_KDF_derive extends KeyDerivationOperation {
107+ FunctionCall instance ;
108+
109+ EVP_KDF_derive ( ) {
110+ this = Crypto:: TKeyDerivationOperation ( instance ) and
111+ instance .getTarget ( ) .getName ( ) = "EVP_KDF_derive"
112+ }
33113
34114 override Crypto:: Algorithm getAlgorithm ( ) { algorithm_to_EVP_KDF_derive ( result , this ) }
35115
36- Expr getAlgorithmArg ( ) { result = this .( FunctionCall ) .getArgument ( 3 ) }
116+ Expr getAlgorithmArg ( ) { result = instance .getArgument ( 3 ) }
117+
118+ Expr getContextArg ( ) { result = instance .getArgument ( 0 ) }
37119 }
38120
39- abstract class KeyDerivationAlgorithm extends Crypto:: KeyDerivationAlgorithm { }
121+ /**
122+ * Key derivation algorithm nodes
123+ */
124+ abstract class KeyDerivationAlgorithm extends Crypto:: KeyDerivationAlgorithm {
125+ abstract Expr getInstance ( ) ;
126+ }
40127
128+ /**
129+ * `EVP_KDF_fetch` returns a key derivation algorithm.
130+ */
41131 class EVP_KDF_fetch_Call extends FunctionCall {
42132 EVP_KDF_fetch_Call ( ) { this .getTarget ( ) .getName ( ) = "EVP_KDF_fetch" }
43133
44134 Expr getAlgorithmArg ( ) { result = this .getArgument ( 1 ) }
45135 }
46136
47- predicate kdf_names ( string algo ) { algo = [ "HKDF" , "PKCS12KDF" ] }
48-
49- class KDFAlgorithmStringLiteral extends Crypto:: NodeBase instanceof StringLiteral {
50- KDFAlgorithmStringLiteral ( ) { kdf_names ( this .getValue ( ) .toUpperCase ( ) ) }
137+ class EVP_KDF_fetch_AlgorithmArg extends Expr {
138+ EVP_KDF_fetch_AlgorithmArg ( ) { exists ( EVP_KDF_fetch_Call call | this = call .getAlgorithmArg ( ) ) }
139+ }
51140
52- override string toString ( ) { result = this . ( StringLiteral ) . toString ( ) }
141+ predicate kdf_names ( string algo ) { algo = [ "HKDF" , "PKCS12KDF" , "PBKDF2" ] }
53142
54- string getValue ( ) { result = this .( StringLiteral ) .getValue ( ) }
143+ class KDFAlgorithmStringLiteral extends StringLiteral {
144+ KDFAlgorithmStringLiteral ( ) { kdf_names ( this .getValue ( ) .toUpperCase ( ) ) }
55145 }
56146
57147 private module AlgorithmStringToFetchConfig implements DataFlow:: ConfigSig {
58148 predicate isSource ( DataFlow:: Node src ) { src .asExpr ( ) instanceof KDFAlgorithmStringLiteral }
59149
60- predicate isSink ( DataFlow:: Node sink ) {
61- exists ( EVP_KDF_fetch_Call call | sink .asExpr ( ) = call .getAlgorithmArg ( ) )
62- }
150+ predicate isSink ( DataFlow:: Node sink ) { sink .asExpr ( ) instanceof EVP_KDF_fetch_AlgorithmArg }
63151 }
64152
65153 module AlgorithmStringToFetchFlow = DataFlow:: Global< AlgorithmStringToFetchConfig > ;
66154
67- predicate algorithmStringToKDFFetchArgFlow ( string name , KDFAlgorithmStringLiteral origin , Expr arg ) {
68- exists ( EVP_KDF_fetch_Call sinkCall |
69- origin .getValue ( ) .toUpperCase ( ) = name and
70- arg = sinkCall .getAlgorithmArg ( ) and
71- AlgorithmStringToFetchFlow:: flow ( DataFlow:: exprNode ( origin ) , DataFlow:: exprNode ( arg ) )
72- )
155+ predicate algorithmStringToKDFFetchArgFlow (
156+ string name , KDFAlgorithmStringLiteral origin , EVP_KDF_fetch_AlgorithmArg arg
157+ ) {
158+ origin .getValue ( ) .toUpperCase ( ) = name and
159+ AlgorithmStringToFetchFlow:: flow ( DataFlow:: exprNode ( origin ) , DataFlow:: exprNode ( arg ) )
73160 }
74161
75- class HKDF extends KeyDerivationAlgorithm , Crypto:: HKDF instanceof Expr {
162+ /**
163+ * HKDF key derivation algorithm.
164+ */
165+ class HKDF extends KeyDerivationAlgorithm , Crypto:: HKDF {
76166 KDFAlgorithmStringLiteral origin ;
167+ EVP_KDF_fetch_AlgorithmArg instance ;
77168
78- HKDF ( ) { algorithmStringToKDFFetchArgFlow ( "HKDF" , origin , this ) }
169+ HKDF ( ) {
170+ this = Crypto:: TKeyDerivationAlgorithm ( instance ) and
171+ algorithmStringToKDFFetchArgFlow ( "HKDF" , origin , instance )
172+ }
79173
80174 override string getRawAlgorithmName ( ) { result = origin .getValue ( ) }
81175
@@ -84,19 +178,61 @@ module OpenSSLModel {
84178 override Crypto:: LocatableElement getOrigin ( string name ) {
85179 result = origin and name = origin .toString ( )
86180 }
181+
182+ override Expr getInstance ( ) { result = origin }
87183 }
88184
89- class PKCS12KDF extends KeyDerivationAlgorithm , Crypto:: PKCS12KDF instanceof Expr {
185+ /**
186+ * PBKDF2 key derivation algorithm.
187+ */
188+ class PBKDF2 extends KeyDerivationAlgorithm , Crypto:: PBKDF2 {
90189 KDFAlgorithmStringLiteral origin ;
190+ EVP_KDF_fetch_AlgorithmArg instance ;
91191
92- PKCS12KDF ( ) { algorithmStringToKDFFetchArgFlow ( "PKCS12KDF" , origin , this ) }
192+ PBKDF2 ( ) {
193+ this = Crypto:: TKeyDerivationAlgorithm ( instance ) and
194+ algorithmStringToKDFFetchArgFlow ( "PBKDF2" , origin , instance )
195+ }
93196
94197 override string getRawAlgorithmName ( ) { result = origin .getValue ( ) }
95198
96- override Crypto:: HashAlgorithm getHashAlgorithm ( ) { none ( ) }
199+ override string getIterationCount ( Location location ) { none ( ) } // TODO
200+
201+ override string getKeyLength ( Location location ) { none ( ) } // TODO
202+
203+ override Crypto:: HashAlgorithm getHashAlgorithm ( ) { none ( ) } // TODO
204+
205+ override Crypto:: LocatableElement getOrigin ( string name ) {
206+ result = origin and name = origin .toString ( )
207+ }
97208
98- override Crypto:: NodeBase getOrigin ( string name ) {
209+ override Expr getInstance ( ) { result = instance }
210+ }
211+
212+ /**
213+ * PKCS12KDF key derivation algorithm.
214+ */
215+ class PKCS12KDF extends KeyDerivationAlgorithm , Crypto:: PKCS12KDF {
216+ KDFAlgorithmStringLiteral origin ;
217+ EVP_KDF_fetch_AlgorithmArg instance ;
218+
219+ PKCS12KDF ( ) {
220+ this = Crypto:: TKeyDerivationAlgorithm ( instance ) and
221+ algorithmStringToKDFFetchArgFlow ( "PKCS12KDF" , origin , instance )
222+ }
223+
224+ override string getRawAlgorithmName ( ) { result = origin .getValue ( ) }
225+
226+ override string getIterationCount ( Location location ) { none ( ) } // TODO
227+
228+ override string getIDByte ( Location location ) { none ( ) } // TODO
229+
230+ override Crypto:: HashAlgorithm getHashAlgorithm ( ) { none ( ) } // TODO
231+
232+ override Crypto:: LocatableElement getOrigin ( string name ) {
99233 result = origin and name = origin .toString ( )
100234 }
235+
236+ override Expr getInstance ( ) { result = instance }
101237 }
102238}
0 commit comments