diff --git a/shared/quantum/codeql/quantum/experimental/Model.qll b/shared/quantum/codeql/quantum/experimental/Model.qll index 5370f72ef47b..10875a49b687 100644 --- a/shared/quantum/codeql/quantum/experimental/Model.qll +++ b/shared/quantum/codeql/quantum/experimental/Model.qll @@ -424,6 +424,17 @@ module CryptographyBase Input> { final override ConsumerInputDataFlowNode getInputNode() { result = inputNode } } + final private class SignatureArtifactConsumer extends ArtifactConsumerAndInstance { + ConsumerInputDataFlowNode inputNode; + + SignatureArtifactConsumer() { + exists(SignatureOperationInstance op | inputNode = op.getSignatureConsumer()) and + this = Input::dfn_to_element(inputNode) + } + + final override ConsumerInputDataFlowNode getInputNode() { result = inputNode } + } + /** * An artifact that is produced by an operation, representing a concrete artifact instance rather than a synthetic consumer artifact. */ @@ -458,6 +469,8 @@ module CryptographyBase Input> { } override DataFlowNode getOutputNode() { result = creator.getOutputArtifact() } + + KeyOperationInstance getCreator() { result = creator } } /** @@ -782,6 +795,17 @@ module CryptographyBase Input> { abstract ArtifactOutputDataFlowNode getOutputArtifact(); } + /** + * A key operation instance representing a signature being generated or verified. + */ + abstract class SignatureOperationInstance extends KeyOperationInstance { + /** + * Gets the consumer of the signature that is being verified in case of a + * verification operation. + */ + abstract ConsumerInputDataFlowNode getSignatureConsumer(); + } + /** * A key-based algorithm instance used in cryptographic operations such as encryption, decryption, * signing, verification, and key wrapping. @@ -1264,6 +1288,7 @@ module CryptographyBase Input> { TNonceInput(NonceArtifactConsumer e) or TMessageInput(MessageArtifactConsumer e) or TSaltInput(SaltArtifactConsumer e) or + TSignatureInput(SignatureArtifactConsumer e) or TRandomNumberGeneration(RandomNumberGenerationInstance e) { e.flowsTo(_) } or // Key Creation Operation union type (e.g., key generation, key load) TKeyCreationOperation(KeyCreationOperationInstance e) or @@ -1325,14 +1350,14 @@ module CryptographyBase Input> { /** * Returns the child of this node with the given edge name. * - * This predicate is overriden by derived classes to construct the graph of cryptographic operations. + * This predicate is overridden by derived classes to construct the graph of cryptographic operations. */ NodeBase getChild(string edgeName) { none() } /** * Defines properties of this node by name and either a value or location or both. * - * This predicate is overriden by derived classes to construct the graph of cryptographic operations. + * This predicate is overridden by derived classes to construct the graph of cryptographic operations. */ predicate properties(string key, string value, Location location) { none() } @@ -1505,6 +1530,20 @@ module CryptographyBase Input> { override LocatableElement asElement() { result = instance } } + /** + * A signature input. This may represent a signature, or a signature component + * such as the scalar values r and s in ECDSA. + */ + final class SignatureArtifactNode extends ArtifactNode, TSignatureInput { + SignatureArtifactConsumer instance; + + SignatureArtifactNode() { this = TSignatureInput(instance) } + + final override string getInternalType() { result = "SignatureInput" } + + override LocatableElement asElement() { result = instance } + } + /** * A salt input. */ @@ -1528,13 +1567,22 @@ module CryptographyBase Input> { KeyOperationOutputNode() { this = TKeyOperationOutput(instance) } - final override string getInternalType() { result = "KeyOperationOutput" } + override string getInternalType() { result = "KeyOperationOutput" } override LocatableElement asElement() { result = instance } override string getSourceNodeRelationship() { none() } } + class SignOperationOutputNode extends KeyOperationOutputNode { + SignOperationOutputNode() { + this.asElement().(KeyOperationOutputArtifactInstance).getCreator().getKeyOperationSubtype() = + TSignMode() + } + + override string getInternalType() { result = "SignatureOutput" } + } + /** * A source of random number generation. */ @@ -2107,6 +2155,7 @@ module CryptographyBase Input> { } class SignatureOperationNode extends KeyOperationNode { + override SignatureOperationInstance instance; string nodeName; SignatureOperationNode() { @@ -2116,6 +2165,21 @@ module CryptographyBase Input> { } override string getInternalType() { result = nodeName } + + SignatureArtifactNode getASignatureArtifact() { + result.asElement() = instance.getSignatureConsumer().getConsumer() + } + + override NodeBase getChild(string key) { + result = super.getChild(key) + or + // [KNOWN_OR_UNKNOWN] - only if we know the type is verify + this.getKeyOperationSubtype() = TVerifyMode() and + key = "Signature" and + if exists(this.getASignatureArtifact()) + then result = this.getASignatureArtifact() + else result = this + } } /** @@ -2563,6 +2627,8 @@ module CryptographyBase Input> { or curveName = "CURVE25519" and keySize = 255 and curveFamily = CURVE25519() or + curveName = "CURVE448" and keySize = 448 and curveFamily = CURVE448() + or // TODO: separate these into key agreement logic or sign/verify (ECDSA / ECDH) // or // curveName = "X25519" and keySize = 255 and curveFamily = CURVE25519() @@ -2570,8 +2636,6 @@ module CryptographyBase Input> { // curveName = "ED25519" and keySize = 255 and curveFamily = CURVE25519() // or // curveName = "ED448" and keySize = 448 and curveFamily = CURVE448() - // curveName = "CURVE448" and keySize = 448 and curveFamily = CURVE448() - // or // or // curveName = "X448" and keySize = 448 and curveFamily = CURVE448() curveName = "SM2" and keySize in [256, 512] and curveFamily = SM2()