@@ -25,6 +25,26 @@ abstract class CryptographicOperation extends Expr {
25
25
*/
26
26
abstract class CryptographicKey extends DataFlow:: ValueNode { }
27
27
28
+ /**
29
+ * The creation of a cryptographic key.
30
+ */
31
+ abstract class CryptographicKeyCreation extends DataFlow:: Node {
32
+ /**
33
+ * Gets the algorithm used to create the key.
34
+ */
35
+ abstract CryptographicAlgorithm getAlgorithm ( ) ;
36
+
37
+ /**
38
+ * Gets the size of the key.
39
+ */
40
+ abstract int getSize ( ) ;
41
+
42
+ /**
43
+ * Gets whether the key is symmetric.
44
+ */
45
+ abstract predicate isSymmetricKey ( ) ;
46
+ }
47
+
28
48
/**
29
49
* A key used in a cryptographic algorithm, viewed as a `CredentialsExpr`.
30
50
*/
@@ -141,21 +161,62 @@ private module NodeJSCrypto {
141
161
* Also matches `createHash`, `createHmac`, `createSign` instead of `createCipher`.
142
162
*/
143
163
144
- exists ( DataFlow:: SourceNode mod , string createSuffix |
145
- createSuffix = "Hash" or
146
- createSuffix = "Hmac" or
147
- createSuffix = "Sign" or
148
- createSuffix = "Cipher"
149
- |
164
+ exists ( DataFlow:: SourceNode mod |
150
165
mod = DataFlow:: moduleImport ( "crypto" ) and
151
- this = mod .getAMemberCall ( "create" + createSuffix ) and
166
+ this = mod .getAMemberCall ( "create" + [ "Hash" , "Hmac" , "Sign" , "Cipher" ] ) and
152
167
algorithm .matchesName ( getArgument ( 0 ) .getStringValue ( ) )
153
168
)
154
169
}
155
170
156
171
CryptographicAlgorithm getAlgorithm ( ) { result = algorithm }
157
172
}
158
173
174
+ private class CreateKey extends CryptographicKeyCreation , DataFlow:: CallNode {
175
+ boolean symmetric ;
176
+
177
+ CreateKey ( ) {
178
+ // crypto.generateKey(type, options, callback)
179
+ // crypto.generateKeyPair(type, options, callback)
180
+ // crypto.generateKeyPairSync(type, options)
181
+ // crypto.generateKeySync(type, options)
182
+ exists ( DataFlow:: SourceNode mod , string keyType |
183
+ keyType = "Key" and symmetric = true
184
+ or
185
+ keyType = "KeyPair" and symmetric = false
186
+ |
187
+ mod = DataFlow:: moduleImport ( "crypto" ) and
188
+ this = mod .getAMemberCall ( "generate" + keyType + [ "" , "Sync" ] )
189
+ )
190
+ }
191
+
192
+ override CryptographicAlgorithm getAlgorithm ( ) {
193
+ result .matchesName ( getArgument ( 0 ) .getStringValue ( ) )
194
+ }
195
+
196
+ override int getSize ( ) {
197
+ symmetric = true and
198
+ result = getOptionArgument ( 1 , "length" ) .getIntValue ( )
199
+ or
200
+ symmetric = false and
201
+ result = getOptionArgument ( 1 , "modulusLength" ) .getIntValue ( )
202
+ }
203
+
204
+ override predicate isSymmetricKey ( ) { symmetric = true }
205
+ }
206
+
207
+ private class CreateDiffieHellmanKey extends CryptographicKeyCreation , DataFlow:: CallNode {
208
+ // require("crypto").createDiffieHellman(prime_length);
209
+ CreateDiffieHellmanKey ( ) {
210
+ this = DataFlow:: moduleMember ( "crypto" , "createDiffieHellman" ) .getACall ( )
211
+ }
212
+
213
+ override CryptographicAlgorithm getAlgorithm ( ) { none ( ) }
214
+
215
+ override int getSize ( ) { result = getArgument ( 0 ) .getIntValue ( ) }
216
+
217
+ override predicate isSymmetricKey ( ) { none ( ) }
218
+ }
219
+
159
220
private class Apply extends CryptographicOperation , MethodCallExpr {
160
221
InstantiatedAlgorithm instantiation ;
161
222
@@ -282,6 +343,35 @@ private module CryptoJS {
282
343
)
283
344
}
284
345
}
346
+
347
+ private class CreateKey extends CryptographicKeyCreation , DataFlow:: CallNode {
348
+ string algorithm ;
349
+ int optionArg ;
350
+
351
+ CreateKey ( ) {
352
+ // var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 });
353
+ this =
354
+ getAlgorithmExpr ( any ( CryptographicAlgorithm algo | algo .getName ( ) = algorithm ) ) .getACall ( ) and
355
+ optionArg = 2
356
+ or
357
+ // var key = CryptoJS.algo.PBKDF2.create({ keySize: 8 });
358
+ this =
359
+ DataFlow:: moduleMember ( "crypto-js" , "algo" )
360
+ .getAPropertyRead ( algorithm )
361
+ .getAMethodCall ( "create" ) and
362
+ optionArg = 0
363
+ }
364
+
365
+ override CryptographicAlgorithm getAlgorithm ( ) { result .matchesName ( algorithm ) }
366
+
367
+ override int getSize ( ) {
368
+ result = getOptionArgument ( optionArg , "keySize" ) .getIntValue ( ) * 32 // size is in words
369
+ or
370
+ result = getArgument ( optionArg ) .getIntValue ( ) * 32 // size is in words
371
+ }
372
+
373
+ override predicate isSymmetricKey ( ) { any ( ) }
374
+ }
285
375
}
286
376
287
377
/**
@@ -467,6 +557,39 @@ private module Forge {
467
557
private class Key extends CryptographicKey {
468
558
Key ( ) { this = any ( KeyCipher cipher ) .getKey ( ) }
469
559
}
560
+
561
+ private class CreateKey extends CryptographicKeyCreation , DataFlow:: CallNode {
562
+ CryptographicAlgorithm algorithm ;
563
+
564
+ CreateKey ( ) {
565
+ // var cipher = forge.rc2.createEncryptionCipher(key, 128);
566
+ this =
567
+ getAnImportNode ( )
568
+ .getAPropertyRead ( any ( string s | algorithm .matchesName ( s ) ) )
569
+ .getAMemberCall ( "createEncryptionCipher" )
570
+ or
571
+ // var key = forge.random.getBytesSync(16);
572
+ // var cipher = forge.cipher.createCipher('AES-CBC', key);
573
+ this =
574
+ getAnImportNode ( )
575
+ .getAPropertyRead ( "cipher" )
576
+ .getAMemberCall ( [ "createCipher" , "createDecipher" ] ) and
577
+ algorithm .matchesName ( this .getArgument ( 0 ) .getStringValue ( ) )
578
+ }
579
+
580
+ override CryptographicAlgorithm getAlgorithm ( ) { result = algorithm }
581
+
582
+ override int getSize ( ) {
583
+ result = this .getArgument ( 1 ) .getIntValue ( )
584
+ or
585
+ exists ( DataFlow:: CallNode call | call .getCalleeName ( ) = [ "getBytes" , "getBytesSync" ] |
586
+ getArgument ( 1 ) .getALocalSource ( ) = call and
587
+ result = call .getArgument ( 0 ) .getIntValue ( ) * 8 // bytes to bits
588
+ )
589
+ }
590
+
591
+ override predicate isSymmetricKey ( ) { any ( ) }
592
+ }
470
593
}
471
594
472
595
/**
@@ -556,13 +679,38 @@ private module Hasha {
556
679
557
680
override CryptographicAlgorithm getAlgorithm ( ) { result = algorithm }
558
681
}
682
+ }
559
683
560
- /**
561
- * Provides classes for working with the `express-jwt` package (https://github.com/auth0/express-jwt);
562
- */
563
- module ExpressJwt {
564
- private class Key extends CryptographicKey {
565
- Key ( ) { this = DataFlow:: moduleMember ( "express-jwt" , "sign" ) .getACall ( ) .getArgument ( 1 ) }
684
+ /**
685
+ * Provides classes for working with the `express-jwt` package (https://github.com/auth0/express-jwt);
686
+ */
687
+ private module ExpressJwt {
688
+ private class Key extends CryptographicKey {
689
+ Key ( ) { this = DataFlow:: moduleMember ( "express-jwt" , "sign" ) .getACall ( ) .getArgument ( 1 ) }
690
+ }
691
+ }
692
+
693
+ /**
694
+ * Provides classes for working with the `node-rsa` package (https://www.npmjs.com/package/node-rsa)
695
+ */
696
+ private module NodeRsa {
697
+ private class CreateKey extends CryptographicKeyCreation , API:: InvokeNode {
698
+ CryptographicAlgorithm algorithm ;
699
+
700
+ CreateKey ( ) {
701
+ this = API:: moduleImport ( "node-rsa" ) .getAnInstantiation ( )
702
+ or
703
+ this = API:: moduleImport ( "node-rsa" ) .getInstance ( ) .getMember ( "generateKeyPair" ) .getACall ( )
566
704
}
705
+
706
+ override CryptographicAlgorithm getAlgorithm ( ) { result .matchesName ( "rsa" ) }
707
+
708
+ override int getSize ( ) {
709
+ result = this .getArgument ( 0 ) .getIntValue ( )
710
+ or
711
+ result = this .getOptionArgument ( 0 , "b" ) .getIntValue ( )
712
+ }
713
+
714
+ override predicate isSymmetricKey ( ) { none ( ) }
567
715
}
568
716
}
0 commit comments