mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Python: Add concepts for public-key generation
I did spend some time to figure out how to best write `minimumSecureKeySize`
predicate. I wanted to write once and for all the recommended sizes for each
cryptosystem.
I considered making the predicate such as
```codeql
int minimumSecureKeySize() {
this.getName() = "RSA" and result = 2048
or
this.getName() = "DSA" and result = 2048
or
this.getName() = "ECC" and result = 244
}
```
but then it would be impossible to add a new model without also being able to
modify the body of this predicate -- which seems like a bad way to start off a
brand new way of modeling things.
So I considered if we could add it to the non-range class, such as
```codeql
class RSAKeyGeneration extends KeyGeneration {
RSAKeyGeneration() { this.getName() = "RSA" }
override int minimumSecureKeySize() { result = 2048 }
}
```
This has the major problem that when you're writing the models for a new
API (and therefore extending KeyGeneration::Range), there is no way for you to
see that you need to take this extra step :| (also problem about how we should
define `minimumSecureKeySize` on `KeyGeneration` class then, since if we make it
abstract, we effectively disable the ability to refine `KeyGeneration` since any
subclass must provide an implementation.)
So, therefore I ended up with this solution ;)
This commit is contained in:
@@ -526,3 +526,90 @@ module HTTP {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides models for cryptographic things. */
|
||||
module Cryptography {
|
||||
/** Provides models for public-key cryptography, also called asymmetric cryptography. */
|
||||
module PublicKey {
|
||||
/**
|
||||
* A data-flow node that generates a new key-pair for use with public-key cryptography.
|
||||
*
|
||||
* Extend this class to refine existing API models. If you want to model new APIs,
|
||||
* extend `KeyGeneration::Range` instead.
|
||||
*/
|
||||
class KeyGeneration extends DataFlow::Node {
|
||||
KeyGeneration::Range range;
|
||||
|
||||
KeyGeneration() { this = range }
|
||||
|
||||
/** Gets the name of the cryptographic algorithm (for example `"RSA"` or `"AES"`). */
|
||||
string getName() { result = range.getName() }
|
||||
|
||||
/** Gets the argument that specifies size of the key in bits, if available. */
|
||||
DataFlow::Node getKeySizeArg() { result = range.getKeySizeArg() }
|
||||
|
||||
/**
|
||||
* Gets the size of the key generated (in bits), as well as the `origin` that
|
||||
* explains how we obtained this specific key size.
|
||||
*/
|
||||
int getKeySizeWithOrigin(DataFlow::Node origin) {
|
||||
result = range.getKeySizeWithOrigin(origin)
|
||||
}
|
||||
|
||||
/** Gets the minimum key size (in bits) for this algorithm to be considered secure. */
|
||||
int minimumSecureKeySize() { result = range.minimumSecureKeySize() }
|
||||
}
|
||||
|
||||
/** Provides classes for modeling new key-pair generation APIs. */
|
||||
module KeyGeneration {
|
||||
/**
|
||||
* A data-flow node that generates a new key-pair for use with public-key cryptography.
|
||||
*
|
||||
* Extend this class to model new APIs. If you want to refine existing API models,
|
||||
* extend `KeyGeneration` instead.
|
||||
*/
|
||||
abstract class Range extends DataFlow::Node {
|
||||
/** Gets the name of the cryptographic algorithm (for example `"RSA"`). */
|
||||
abstract string getName();
|
||||
|
||||
/** Gets the argument that specifies size of the key in bits, if available. */
|
||||
abstract DataFlow::Node getKeySizeArg();
|
||||
|
||||
/**
|
||||
* Gets the size of the key generated (in bits), as well as the `origin` that
|
||||
* explains how we obtained this specific key size.
|
||||
*/
|
||||
int getKeySizeWithOrigin(DataFlow::Node origin) {
|
||||
exists(IntegerLiteral size | origin = DataFlow::exprNode(size) |
|
||||
origin.(DataFlow::LocalSourceNode).flowsTo(this.getKeySizeArg()) and
|
||||
result = size.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the minimum key size (in bits) for this algorithm to be considered secure. */
|
||||
abstract int minimumSecureKeySize();
|
||||
}
|
||||
|
||||
/** A data-flow node that generates a new RSA key-pair. */
|
||||
abstract class RSARange extends Range {
|
||||
override string getName() { result = "RSA" }
|
||||
|
||||
override int minimumSecureKeySize() { result = 2048 }
|
||||
}
|
||||
|
||||
/** A data-flow node that generates a new DSA key-pair. */
|
||||
abstract class DSARange extends Range {
|
||||
override string getName() { result = "DSA" }
|
||||
|
||||
override int minimumSecureKeySize() { result = 2048 }
|
||||
}
|
||||
|
||||
/** A data-flow node that generates a new ECC key-pair. */
|
||||
abstract class ECCRange extends Range {
|
||||
override string getName() { result = "ECC" }
|
||||
|
||||
override int minimumSecureKeySize() { result = 224 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user