Skip to content

Commit 3672358

Browse files
committed
signature algorithms are tracked from keys and contexts
1 parent 16c136e commit 3672358

File tree

8 files changed

+79
-53
lines changed

8 files changed

+79
-53
lines changed

cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/PKeyAlgorithmValueConsumer.qll

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ class EVPPKeyAlgorithmConsumer extends PKeyValueConsumer {
6262
Expr getValueArgExpr() { result = valueArgNode.asExpr() }
6363
}
6464

65-
// TODO: not sure where to put these
65+
// TODO: not sure where to put these predicates
66+
Expr getAlgorithmFromArgument(Expr arg) { none() }
6667

6768
/**
6869
* Given context expression (EVP_PKEY_CTX), finds the algorithm.
@@ -81,7 +82,8 @@ Expr getAlgorithmFromCtx(CtxPointerExpr ctx) {
8182
*/
8283
Expr getKeyFromCtx(CtxPointerExpr ctx) {
8384
exists(Call contextCreationCall |
84-
ctxFlowsToCtxArg(contextCreationCall, ctx) and (
85+
ctxFlowsToCtxArg(contextCreationCall, ctx) and
86+
(
8587
contextCreationCall.getTarget().getName() = "EVP_PKEY_CTX_new" and
8688
result = contextCreationCall.getArgument(0)
8789
or
@@ -96,15 +98,11 @@ Expr getKeyFromCtx(CtxPointerExpr ctx) {
9698
*/
9799
module OpenSSLKeyFlowConfig implements DataFlow::ConfigSig {
98100
predicate isSource(DataFlow::Node source) {
99-
exists(EVPKeyGenOperation keygen |
100-
keygen.getOutputKeyArtifact() = source
101-
)
101+
exists(EVPKeyGenOperation keygen | keygen.getOutputKeyArtifact() = source)
102102
}
103103

104104
predicate isSink(DataFlow::Node sink) {
105-
exists(OpenSSLOperation call |
106-
call.(Call).getAnArgument() = sink.asExpr()
107-
)
105+
exists(OpenSSLCall call | call.(Call).getAnArgument() = sink.asExpr())
108106
}
109107
}
110108

cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPSignatureOperation.qll

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,41 +7,32 @@ private import OpenSSLOperationBase
77
private import experimental.quantum.OpenSSL.CtxFlow
88
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.PKeyAlgorithmValueConsumer
99

10-
1110
// TODO: verification functions
1211
class EVP_Signature_Initializer extends EVPInitialize {
13-
boolean isAlgorithmSpecifiedByKey;
14-
boolean isAlgorithmSpecifiedByCtx;
15-
1612
EVP_Signature_Initializer() {
1713
this.(Call).getTarget().getName() in [
1814
"EVP_DigestSignInit", "EVP_DigestSignInit_ex", "EVP_SignInit", "EVP_SignInit_ex",
1915
"EVP_PKEY_sign_init", "EVP_PKEY_sign_init_ex", "EVP_PKEY_sign_init_ex2",
2016
"EVP_PKEY_sign_message_init"
21-
] and
22-
(
23-
if this.(Call).getTarget().getName().matches("EVP_PKEY_%")
24-
then isAlgorithmSpecifiedByKey = false
25-
else isAlgorithmSpecifiedByKey = true
26-
) and
27-
(
28-
if this.(Call).getTarget().getName() in ["EVP_PKEY_sign_init", "EVP_PKEY_sign_init_ex"]
29-
then isAlgorithmSpecifiedByCtx = true
30-
else isAlgorithmSpecifiedByCtx = false
31-
)
17+
]
3218
}
3319

3420
override Expr getAlgorithmArg() {
35-
if this.(Call).getTarget().getName() in ["EVP_PKEY_sign_init_ex2", "EVP_PKEY_sign_message_init"] then
36-
result = this.(Call).getArgument(1)
37-
else
38-
if isAlgorithmSpecifiedByKey = true then
39-
result = getAlgorithmFromKey(this.getKeyArg())
40-
else
41-
if isAlgorithmSpecifiedByCtx = true then
42-
result = getAlgorithmFromCtx(this.getContextArg())
43-
else
44-
none()
21+
// explicit algorithm as argument
22+
this.(Call).getTarget().getName() in ["EVP_PKEY_sign_init_ex2", "EVP_PKEY_sign_message_init"] and
23+
result = this.(Call).getArgument(1)
24+
or
25+
// algorithm (and key) specified in the context
26+
this.(Call).getTarget().getName() in ["EVP_PKEY_sign_init", "EVP_PKEY_sign_init_ex"] and
27+
result = getAlgorithmFromCtx(this.getContextArg())
28+
or
29+
// algorithm specified by the key
30+
this.(Call).getTarget().getName() in ["EVP_DigestSignInit", "EVP_DigestSignInit_ex"] and
31+
result = getAlgorithmFromKey(this.getKeyArg())
32+
or
33+
// cannot determine algorithm from the initialization call
34+
this.(Call).getTarget().getName() in ["EVP_SignInit", "EVP_SignInit_ex"] and
35+
none()
4536
}
4637

4738
/**
@@ -170,10 +161,22 @@ class EVP_Signature_Final_Call extends EVPFinal, EVP_Signature_Operation {
170161
]
171162
}
172163

164+
override Expr getAlgorithmArg() {
165+
// algorithm specified by the key and the key is provided in this operation
166+
if this.(Call).getTarget().getName() in ["EVP_SignFinal", "EVP_SignFinal_ex"]
167+
then result = getAlgorithmFromKey(this.getKeyConsumer().asExpr())
168+
else
169+
// or find algorithm in the initialization call
170+
result = EVP_Signature_Operation.super.getAlgorithmArg()
171+
}
172+
173173
override Crypto::ConsumerInputDataFlowNode getKeyConsumer() {
174+
// key provided as an argument
174175
if this.(Call).getTarget().getName() in ["EVP_SignFinal", "EVP_SignFinal_ex"]
175176
then result = DataFlow::exprNode(this.(Call).getArgument(3))
176-
else result = EVP_Signature_Operation.super.getKeyConsumer()
177+
else
178+
// or find key in the initialization call
179+
result = EVP_Signature_Operation.super.getKeyConsumer()
177180
}
178181

179182
/**

cpp/ql/lib/experimental/quantum/OpenSSL/Operations/OpenSSLOperationBase.qll

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,31 @@ private import experimental.quantum.Language
22
private import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
33
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
44

5+
/**
6+
* All functions from the OpenSSL API.
7+
*/
8+
class OpenSSLCall extends Call { }
9+
510
/**
611
* All OpenSSL operations.
712
*/
8-
abstract class OpenSSLOperation extends Crypto::OperationInstance instanceof Call {
13+
abstract class OpenSSLOperation extends Crypto::OperationInstance instanceof OpenSSLCall {
914
/**
1015
* Expression that specifies the algorithm for the operation.
11-
* Will be an argument of the operation in the simplest case.
16+
* Will be an argument of the operation in the simplest case
17+
* and EVPPKeyAlgorithmConsumer's valueArgExpr in more complex cases.
1218
*/
1319
abstract Expr getAlgorithmArg();
1420

1521
/**
16-
* Algorithm is specified in initialization call or is implicitly established by the key or context.
22+
* Algorithm is either an argument and we track it to AlgorithmValueConsumer
23+
* or we have the AlgorithmValueConsumer already and just return it.
1724
*/
1825
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
1926
AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(),
2027
DataFlow::exprNode(this.getAlgorithmArg()))
28+
or
29+
result.(EVPPKeyAlgorithmConsumer).getValueArgExpr() = this.getAlgorithmArg()
2130
}
2231
}
2332

@@ -26,7 +35,7 @@ abstract class OpenSSLOperation extends Crypto::OperationInstance instanceof Cal
2635
* These are not operations in the sense of Crypto::OperationInstance,
2736
* but they are used to initialize the context for the operation.
2837
*/
29-
abstract class EVPInitialize extends Call {
38+
abstract class EVPInitialize extends OpenSSLCall {
3039
/**
3140
* The context argument that ties together initialization, updates and/or final calls.
3241
*/
@@ -60,7 +69,7 @@ abstract class EVPInitialize extends Call {
6069
* These are not operations in the sense of Crypto::OperationInstance,
6170
* but they are used to update the context for the operation.
6271
*/
63-
abstract class EVPUpdate extends Call {
72+
abstract class EVPUpdate extends OpenSSLCall {
6473
/**
6574
* The context argument that ties together initialization, updates and/or final calls.
6675
*/
@@ -86,7 +95,7 @@ private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig {
8695
}
8796

8897
predicate isSink(DataFlow::Node sink) {
89-
exists(EVPOperation c | c.getAlgorithmArg() = sink.asExpr())
98+
exists(OpenSSLOperation c | c.getAlgorithmArg() = sink.asExpr())
9099
}
91100
}
92101

cpp/ql/test/experimental/library-tests/quantum/openssl/includes/std_stubs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef STD_STUBS_H
22
#define STD_STUBS_H
33

4+
int printf(const char *format, ...);
5+
46
unsigned long strlen(const char *s) {
57
return 0;
68
}

cpp/ql/test/experimental/library-tests/quantum/openssl/signature/openssl_signature.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -322,14 +322,14 @@ int verify_using_evp_pkey_verify(const unsigned char *digest, size_t digest_len,
322322
*/
323323
int sign_using_evp_pkey_sign_message(const unsigned char *message, size_t message_len,
324324
unsigned char **signature, size_t *signature_len,
325-
EVP_PKEY *pkey, const EVP_MD *md) {
325+
EVP_PKEY *pkey, const EVP_MD *md, const char *alg_name) {
326326
EVP_PKEY_CTX *pkey_ctx = NULL;
327327
EVP_SIGNATURE *alg = NULL;
328328
int ret = 0;
329329

330330
if (!(pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL))) goto cleanup;
331331

332-
alg = EVP_SIGNATURE_fetch(NULL, "RSA-SHA256", NULL);
332+
alg = EVP_SIGNATURE_fetch(NULL, alg_name, NULL);
333333

334334
if (EVP_PKEY_sign_message_init(pkey_ctx, alg, NULL) != 1 ||
335335
EVP_PKEY_sign_message_update(pkey_ctx, message, message_len) != 1 ||
@@ -358,14 +358,14 @@ int sign_using_evp_pkey_sign_message(const unsigned char *message, size_t messag
358358
*/
359359
int verify_using_evp_pkey_verify_message(const unsigned char *message, size_t message_len,
360360
const unsigned char *signature, size_t signature_len,
361-
EVP_PKEY *pkey, const EVP_MD *md) {
361+
EVP_PKEY *pkey, const EVP_MD *md, const char *alg_name) {
362362
EVP_PKEY_CTX *pkey_ctx = NULL;
363363
EVP_SIGNATURE *alg = NULL;
364364
int ret = 0;
365365

366366
if (!(pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL))) goto cleanup;
367367

368-
alg = EVP_SIGNATURE_fetch(NULL, "RSA-SHA256", NULL);
368+
alg = EVP_SIGNATURE_fetch(NULL, alg_name, NULL);
369369

370370
if (EVP_PKEY_verify_message_init(pkey_ctx, alg, NULL) != 1) goto cleanup;
371371

@@ -666,8 +666,8 @@ int test_signature_apis(EVP_PKEY *key, const EVP_MD *md,
666666

667667
/* Test 6: EVP_PKEY_sign_message API */
668668
printf("6. EVP_PKEY_sign_message API: ");
669-
if (sign_using_evp_pkey_sign_message(message, message_len, &sig6, &sig_len6, key, md) &&
670-
verify_using_evp_pkey_verify_message(message, message_len, sig6, sig_len6, key, md)) {
669+
if (sign_using_evp_pkey_sign_message(message, message_len, &sig6, &sig_len6, key, md, algo_name) &&
670+
verify_using_evp_pkey_verify_message(message, message_len, sig6, sig_len6, key, md, algo_name)) {
671671
printf("PASS\n");
672672
} else {
673673
printf("FAIL\n");
@@ -708,7 +708,7 @@ int test_signature_apis_rsa(void) {
708708
}
709709

710710
/* Test generic APIs */
711-
if (!test_signature_apis(key, md, set_rsa_pss_padding, "RSA")) {
711+
if (!test_signature_apis(key, md, set_rsa_pss_padding, "RSA-SHA256")) {
712712
success = 0;
713713
}
714714

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
| openssl_signature.c:332:37:332:48 | RSA-SHA256 | RSA | openssl_signature.c:332:11:332:29 | call to EVP_SIGNATURE_fetch |
2-
| openssl_signature.c:368:37:368:48 | RSA-SHA256 | RSA | openssl_signature.c:368:11:368:29 | call to EVP_SIGNATURE_fetch |
31
| openssl_signature.c:552:35:552:46 | 6 | RSA | openssl_signature.c:552:15:552:33 | call to EVP_PKEY_CTX_new_id |
42
| openssl_signature.c:574:50:574:54 | DSA | DSA | openssl_signature.c:574:17:574:42 | call to EVP_PKEY_CTX_new_from_name |
3+
| openssl_signature.c:711:60:711:71 | RSA-SHA256 | RSA | openssl_signature.c:332:11:332:29 | call to EVP_SIGNATURE_fetch |
4+
| openssl_signature.c:711:60:711:71 | RSA-SHA256 | RSA | openssl_signature.c:368:11:368:29 | call to EVP_SIGNATURE_fetch |
5+
| openssl_signature.c:767:60:767:64 | DSA | DSA | openssl_signature.c:332:11:332:29 | call to EVP_SIGNATURE_fetch |
6+
| openssl_signature.c:767:60:767:64 | DSA | DSA | openssl_signature.c:368:11:368:29 | call to EVP_SIGNATURE_fetch |
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
| openssl_signature.c:89:9:89:21 | SignOperation | openssl_signature.c:79:32:79:38 | Message | openssl_signature.c:89:31:89:40 | SignatureOutput | openssl_signature.c:89:53:89:56 | Key | openssl_signature.c:552:35:552:46 | KeyOperationAlgorithm | Sign |
2+
| openssl_signature.c:89:9:89:21 | SignOperation | openssl_signature.c:79:32:79:38 | Message | openssl_signature.c:89:31:89:40 | SignatureOutput | openssl_signature.c:89:53:89:56 | Key | openssl_signature.c:574:50:574:54 | Constant | Sign |
3+
| openssl_signature.c:89:9:89:21 | SignOperation | openssl_signature.c:84:28:84:36 | Message | openssl_signature.c:89:31:89:40 | SignatureOutput | openssl_signature.c:89:53:89:56 | Key | openssl_signature.c:552:35:552:46 | KeyOperationAlgorithm | Sign |
4+
| openssl_signature.c:89:9:89:21 | SignOperation | openssl_signature.c:84:28:84:36 | Message | openssl_signature.c:89:31:89:40 | SignatureOutput | openssl_signature.c:89:53:89:56 | Key | openssl_signature.c:574:50:574:54 | Constant | Sign |
5+
| openssl_signature.c:151:9:151:27 | SignOperation | openssl_signature.c:143:38:143:44 | Message | openssl_signature.c:151:37:151:46 | SignatureOutput | openssl_signature.c:142:52:142:55 | Key | openssl_signature.c:552:35:552:46 | KeyOperationAlgorithm | Sign |
6+
| openssl_signature.c:151:9:151:27 | SignOperation | openssl_signature.c:143:38:143:44 | Message | openssl_signature.c:151:37:151:46 | SignatureOutput | openssl_signature.c:142:52:142:55 | Key | openssl_signature.c:574:50:574:54 | Constant | Sign |
7+
| openssl_signature.c:213:9:213:27 | SignOperation | openssl_signature.c:205:38:205:44 | Message | openssl_signature.c:213:37:213:46 | SignatureOutput | openssl_signature.c:199:57:199:60 | Key | openssl_signature.c:552:35:552:46 | KeyOperationAlgorithm | Sign |
8+
| openssl_signature.c:213:9:213:27 | SignOperation | openssl_signature.c:205:38:205:44 | Message | openssl_signature.c:213:37:213:46 | SignatureOutput | openssl_signature.c:199:57:199:60 | Key | openssl_signature.c:574:50:574:54 | Constant | Sign |
9+
| openssl_signature.c:279:9:279:21 | SignOperation | openssl_signature.c:279:60:279:65 | Message | openssl_signature.c:279:33:279:42 | SignatureOutput | openssl_signature.c:269:39:269:42 | Key | openssl_signature.c:552:35:552:46 | KeyOperationAlgorithm | Sign |
10+
| openssl_signature.c:279:9:279:21 | SignOperation | openssl_signature.c:279:60:279:65 | Message | openssl_signature.c:279:33:279:42 | SignatureOutput | openssl_signature.c:269:39:269:42 | Key | openssl_signature.c:574:50:574:54 | Constant | Sign |
11+
| openssl_signature.c:343:9:343:35 | SignOperation | openssl_signature.c:335:48:335:54 | Message | openssl_signature.c:343:47:343:56 | SignatureOutput | openssl_signature.c:330:39:330:42 | Key | openssl_signature.c:711:60:711:71 | KeyOperationAlgorithm | Sign |
12+
| openssl_signature.c:343:9:343:35 | SignOperation | openssl_signature.c:335:48:335:54 | Message | openssl_signature.c:343:47:343:56 | SignatureOutput | openssl_signature.c:330:39:330:42 | Key | openssl_signature.c:767:60:767:64 | Constant | Sign |

cpp/ql/test/experimental/library-tests/quantum/openssl/signature/signature_operations.ql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import experimental.quantum.OpenSSL.Operations.EVPSignatureOperation
66
import experimental.quantum.OpenSSL.Operations.OpenSSLOperationBase
77

88
from Crypto::SignatureOperationNode n
9-
select n, n.asElement(), n.getAnInputArtifact(), n.getAnOutputArtifact(), n.getAKey(),
10-
n.asElement().(OpenSSLOperation).getAlgorithmArg()
11-
// n.asElement().(Crypto::OperationInstance).getAnAlgorithmValueConsumer(),
12-
// n.getAnAlgorithmOrGenericSource()
9+
select n, n.getAnInputArtifact(), n.getAnOutputArtifact(), n.getAKey(),
10+
n.getAnAlgorithmOrGenericSource(), n.getKeyOperationSubtype()
11+
// , n.getASignatureArtifact()
12+

0 commit comments

Comments
 (0)