Quellcode durchsuchen

Modified testing NL and added SecureChannel test.

The testing NetworkLayer now writes the data it 'Sends' into a buffer,
so we can check the buffer in our unit tests.
The new test checks if the headers etc. are encoded correctly and
if the encryption functions are called for the correct data.
Mark vor 7 Jahren
Ursprung
Commit
0cabd40863

+ 80 - 7
tests/check_securechannel.c

@@ -6,6 +6,13 @@
 #include <stdlib.h>
 #include <src_generated/ua_types_generated.h>
 #include <testing_networklayers.h>
+#include <ua_types_encoding_binary.h>
+#include <src_generated/ua_transport_generated_encoding_binary.h>
+#include <src_generated/ua_transport_generated.h>
+#include <ua_types.h>
+#include <src_generated/ua_types_generated_encoding_binary.h>
+#include <ua_plugin_securitypolicy.h>
+#include <src_generated/ua_transport_generated_handling.h>
 
 #include "testing_policy.h"
 #include "ua_securechannel.h"
@@ -18,6 +25,7 @@ UA_SecureChannel testChannel;
 UA_ByteString dummyCertificate = UA_BYTESTRING_STATIC("DUMMY CERTIFICATE DUMMY CERTIFICATE DUMMY CERTIFICATE");
 UA_SecurityPolicy dummyPolicy;
 UA_Connection testingConnection;
+UA_ByteString sentData;
 
 
 funcs_called fCalled;
@@ -27,7 +35,7 @@ setup_secureChannel(void) {
     TestingPolicy(&dummyPolicy, dummyCertificate, &fCalled);
     UA_SecureChannel_init(&testChannel, &dummyPolicy, &dummyCertificate);
 
-    testingConnection = createDummyConnection();
+    testingConnection = createDummyConnection(&sentData);
     UA_Connection_attachSecureChannel(&testingConnection, &testChannel);
     testChannel.connection = &testingConnection;
 }
@@ -145,10 +153,16 @@ START_TEST(SecureChannel_revolveTokens)
     }
 END_TEST
 
+static void
+createDummyResponse(UA_OpenSecureChannelResponse *response) {
+    UA_OpenSecureChannelResponse_init(response);
+    memset(response, 0, sizeof(UA_OpenSecureChannelResponse));
+}
+
 START_TEST(SecureChannel_sendAsymmetricOPNMessage_withoutConnection)
     {
         UA_OpenSecureChannelResponse dummyResponse;
-        UA_OpenSecureChannelResponse_init(&dummyResponse);
+        createDummyResponse(&dummyResponse);
         testChannel.securityMode = UA_MESSAGESECURITYMODE_NONE;
 
         // Remove connection to provoke error
@@ -167,7 +181,7 @@ END_TEST
 START_TEST(SecureChannel_sendAsymmetricOPNMessage_invalidParameters)
     {
         UA_OpenSecureChannelResponse dummyResponse;
-        UA_OpenSecureChannelResponse_init(&dummyResponse);
+        createDummyResponse(&dummyResponse);
 
         UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel,
                                                                          42,
@@ -193,7 +207,7 @@ START_TEST(SecureChannel_sendAsymmetricOPNMessage_SecurityModeInvalid)
     {
         // Configure our channel correctly for OPN messages and setup dummy message
         UA_OpenSecureChannelResponse dummyResponse;
-        UA_OpenSecureChannelResponse_init(&dummyResponse);
+        createDummyResponse(&dummyResponse);
 
         testChannel.securityMode = UA_MESSAGESECURITYMODE_INVALID;
 
@@ -209,7 +223,7 @@ START_TEST(SecureChannel_sendAsymmetricOPNMessage_SecurityModeNone)
     {
         // Configure our channel correctly for OPN messages and setup dummy message
         UA_OpenSecureChannelResponse dummyResponse;
-        UA_OpenSecureChannelResponse_init(&dummyResponse);
+        createDummyResponse(&dummyResponse);
         testChannel.securityMode = UA_MESSAGESECURITYMODE_NONE;
 
         UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel,
@@ -226,7 +240,7 @@ START_TEST(SecureChannel_sendAsymmetricOPNMessage_SecurityModeSign)
     {
         // Configure our channel correctly for OPN messages and setup dummy message
         UA_OpenSecureChannelResponse dummyResponse;
-        UA_OpenSecureChannelResponse_init(&dummyResponse);
+        createDummyResponse(&dummyResponse);
         testChannel.securityMode = UA_MESSAGESECURITYMODE_SIGN;
 
         UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel,
@@ -243,7 +257,7 @@ START_TEST(SecureChannel_sendAsymmetricOPNMessage_SecurityModeSignAndEncrypt)
     {
         // Configure our channel correctly for OPN messages and setup dummy message
         UA_OpenSecureChannelResponse dummyResponse;
-        UA_OpenSecureChannelResponse_init(&dummyResponse);
+        createDummyResponse(&dummyResponse);
 
         testChannel.securityMode = UA_MESSAGESECURITYMODE_SIGNANDENCRYPT;
 
@@ -257,6 +271,64 @@ START_TEST(SecureChannel_sendAsymmetricOPNMessage_SecurityModeSignAndEncrypt)
     }
 END_TEST
 
+START_TEST(SecureChannel_sendAsymmetricOPNMessage_sentDataIsValid)
+    {
+        UA_OpenSecureChannelResponse dummyResponse;
+        createDummyResponse(&dummyResponse);
+
+        testChannel.securityMode = UA_MESSAGESECURITYMODE_SIGNANDENCRYPT;
+        UA_UInt32 requestId = UA_UInt32_random();
+
+        UA_StatusCode retval = UA_SecureChannel_sendAsymmetricOPNMessage(&testChannel,
+                                                                         requestId,
+                                                                         &dummyResponse,
+                                                                         &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
+        ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Expected function to succeed");
+
+        size_t offset = 0;
+        UA_SecureConversationMessageHeader header;
+        UA_SecureConversationMessageHeader_decodeBinary(&sentData, &offset, &header);
+
+        UA_AsymmetricAlgorithmSecurityHeader asymSecurityHeader;
+        UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(&sentData, &offset, &asymSecurityHeader);
+        ck_assert_msg(UA_ByteString_equal(&dummyCertificate, &asymSecurityHeader.senderCertificate),
+                      "Expected the certificate to be equal to the one used  by the secureChannel");
+        ck_assert_msg(UA_ByteString_equal(&testChannel.securityPolicy->policyUri,
+                                          &asymSecurityHeader.securityPolicyUri),
+                      "Expected securityPolicyUri to be equal to the one used by the secureChannel");
+        UA_ByteString thumbPrint = {20, testChannel.remoteCertificateThumbprint};
+        ck_assert_msg(UA_ByteString_equal(&thumbPrint,
+                                          &asymSecurityHeader.receiverCertificateThumbprint),
+                      "Expected receiverCertificateThumbprint to be equal to the one set in the secureChannel");
+
+        for(size_t i = offset; i < header.messageHeader.messageSize; ++i) {
+            sentData.data[i] = (UA_Byte) ((sentData.data[i] - 1) % (UA_BYTE_MAX + 1));
+        }
+
+        UA_SequenceHeader sequenceHeader;
+        UA_SequenceHeader_decodeBinary(&sentData, &offset, &sequenceHeader);
+        ck_assert_msg(sequenceHeader.requestId == requestId, "Expected requestId to be %i but was %i",
+                      requestId,
+                      sequenceHeader.requestId);
+
+        UA_NodeId original = UA_NODEID_NUMERIC(0, UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE].binaryEncodingId);
+        UA_NodeId requestTypeId;
+        UA_NodeId_decodeBinary(&sentData, &offset, &requestTypeId);
+        ck_assert_msg(UA_NodeId_equal(&original, &requestTypeId), "Expected nodeIds to be equal");
+
+        UA_OpenSecureChannelResponse sentResponse;
+        UA_OpenSecureChannelResponse_decodeBinary(&sentData, &offset, &sentResponse);
+
+        ck_assert_msg(memcmp(&sentResponse, &dummyResponse, sizeof(UA_OpenSecureChannelResponse)) == 0,
+                      "Expected the sent response to be equal to the one supplied to the send function");
+
+        UA_SecureConversationMessageHeader_deleteMembers(&header);
+        UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymSecurityHeader);
+        UA_SequenceHeader_deleteMembers(&sequenceHeader);
+        UA_OpenSecureChannelResponse_deleteMembers(&sentResponse);
+    }
+END_TEST
+
 static Suite *
 testSuite_SecureChannel(void) {
     Suite *s = suite_create("SecureChannel");
@@ -288,6 +360,7 @@ testSuite_SecureChannel(void) {
     tcase_add_test(tc_sendAsymmetricOPNMessage, SecureChannel_sendAsymmetricOPNMessage_SecurityModeNone);
     tcase_add_test(tc_sendAsymmetricOPNMessage, SecureChannel_sendAsymmetricOPNMessage_SecurityModeSign);
     tcase_add_test(tc_sendAsymmetricOPNMessage, SecureChannel_sendAsymmetricOPNMessage_SecurityModeSignAndEncrypt);
+    tcase_add_test(tc_sendAsymmetricOPNMessage, SecureChannel_sendAsymmetricOPNMessage_sentDataIsValid);
     suite_add_tcase(s, tc_sendAsymmetricOPNMessage);
 
 

+ 2 - 1
tests/fuzz/fuzz_binary_message.cc

@@ -14,7 +14,8 @@
 */
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
 
-    UA_Connection c = createDummyConnection();
+    UA_ByteString sentData;
+    UA_Connection c = createDummyConnection(&sentData);
     UA_ServerConfig *config = UA_ServerConfig_new_default();
     UA_Server *server = UA_Server_new(config);
 

+ 2 - 1
tests/server/check_server_binary_messages.c

@@ -14,6 +14,7 @@
 
 size_t files;
 char **filenames;
+UA_ByteString sentData;
 
 static UA_ByteString readFile(char *filename) {
     UA_ByteString buf = UA_BYTESTRING_NULL;
@@ -39,7 +40,7 @@ static UA_ByteString readFile(char *filename) {
 }
 
 START_TEST(processMessage) {
-    UA_Connection c = createDummyConnection();
+    UA_Connection c = createDummyConnection(&sentData);
     UA_ServerConfig *config = UA_ServerConfig_new_default();
     UA_Server *server = UA_Server_new(config);
     for(size_t i = 0; i < files; i++) {

+ 14 - 2
tests/testing-plugins/testing_networklayers.c

@@ -3,12 +3,15 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdlib.h>
+#include <assert.h>
 #include "testing_networklayers.h"
 #include "ua_config_default.h"
 
+UA_ByteString *vBuffer;
+
 static UA_StatusCode
 dummyGetSendBuffer(UA_Connection *connection, size_t length, UA_ByteString *buf) {
-    buf->data = length == 0 ? NULL : (UA_Byte*)UA_malloc(length);
+    buf->data = (length == 0) ? NULL : (UA_Byte*)UA_malloc(length);
     buf->length = length;
     return UA_STATUSCODE_GOOD;
 }
@@ -20,6 +23,11 @@ dummyReleaseSendBuffer(UA_Connection *connection, UA_ByteString *buf) {
 
 static UA_StatusCode
 dummySend(UA_Connection *connection, UA_ByteString *buf) {
+    assert(connection != NULL);
+    assert(buf != NULL);
+
+    UA_ByteString_deleteMembers(vBuffer);
+    UA_ByteString_copy(buf, vBuffer);
     UA_ByteString_deleteMembers(buf);
     return UA_STATUSCODE_GOOD;
 }
@@ -30,9 +38,13 @@ dummyReleaseRecvBuffer(UA_Connection *connection, UA_ByteString *buf) {
 
 static void
 dummyClose(UA_Connection *connection) {
+    UA_ByteString_deleteMembers(vBuffer);
 }
 
-UA_Connection createDummyConnection(void) {
+UA_Connection createDummyConnection(UA_ByteString *verificationBuffer) {
+    assert(verificationBuffer != NULL);
+
+    vBuffer = verificationBuffer;
     UA_Connection c;
     c.state = UA_CONNECTION_ESTABLISHED;
     c.localConf = UA_ConnectionConfig_default;

+ 6 - 2
tests/testing-plugins/testing_networklayers.h

@@ -11,8 +11,12 @@
 extern "C" {
 #endif
 
-/** @brief Create the TCP networklayer and listen to the specified port */
-UA_Connection createDummyConnection(void);
+/** @brief Create the TCP networklayer and listen to the specified port
+ *
+ * @param verificationBuffer the send function will write the data that is sent to this buffer, so that it is
+ *                           possible to check what the send function recieved.
+ */
+UA_Connection createDummyConnection(UA_ByteString *verificationBuffer);
 
 #ifdef __cplusplus
 }

+ 38 - 3
tests/testing-plugins/testing_policy.c

@@ -6,7 +6,7 @@
  * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
 
 #include <ua_types.h>
-#include "ua_securitypolicy_none.h"
+#include <ua_plugin_securitypolicy.h>
 #include "ua_types_generated_handling.h"
 #include "testing_policy.h"
 #include "check.h"
@@ -16,6 +16,8 @@
 #define SYM_ENCRYPTION_BLOCK_SIZE 2
 #define SYM_SIGNING_KEY_LENGTH 3
 #define SYM_ENCRYPTION_KEY_LENGTH 5
+#define ASYM_REMOTE_SIGNATURE_SIZE 7
+#define ASYM_LOCAL_SIGNATURE_SIZE 11
 
 funcs_called *funcsCalled;
 
@@ -37,6 +39,11 @@ asym_sign_testing(const UA_SecurityPolicy *securityPolicy,
     ck_assert(channelContext != NULL);
     ck_assert(message != NULL);
     ck_assert(signature != NULL);
+
+    ck_assert_msg(signature->length == ASYM_LOCAL_SIGNATURE_SIZE,
+                  "Expected signature length to be %i but was %i",
+                  ASYM_LOCAL_SIGNATURE_SIZE,
+                  signature->length);
     return UA_STATUSCODE_GOOD;
 }
 
@@ -50,19 +57,29 @@ sym_sign_testing(const UA_SecurityPolicy *securityPolicy,
     ck_assert(channelContext != NULL);
     ck_assert(message != NULL);
     ck_assert(signature != NULL);
+    ck_assert(signature->length != 0);
+    ck_assert(signature->data != NULL);
+
+    memset(signature->data, 'S', signature->length);
     return UA_STATUSCODE_GOOD;
 }
 
 static size_t
 asym_getLocalSignatureSize_testing(const UA_SecurityPolicy *securityPolicy,
                                    const void *channelContext) {
-    return 0;
+    ck_assert(securityPolicy != NULL);
+    ck_assert(channelContext != NULL);
+
+    return ASYM_LOCAL_SIGNATURE_SIZE;
 }
 
 static size_t
 asym_getRemoteSignatureSize_testing(const UA_SecurityPolicy *securityPolicy,
                                     const void *channelContext) {
-    return 0;
+    ck_assert(securityPolicy != NULL);
+    ck_assert(channelContext != NULL);
+
+    return ASYM_REMOTE_SIGNATURE_SIZE;
 }
 
 static size_t
@@ -122,6 +139,16 @@ asym_encrypt_testing(const UA_SecurityPolicy *securityPolicy,
     ck_assert(securityPolicy != NULL);
     ck_assert(channelContext != NULL);
     ck_assert(data != NULL);
+
+    size_t blockSize = securityPolicy->channelModule.getRemoteAsymPlainTextBlockSize(securityPolicy);
+    ck_assert_msg(data->length % blockSize == 0,
+                  "Expected the length of the data to be encrypted to be a multiple of the plaintext block size (%i)",
+                  blockSize);
+
+    for(size_t i = 0; i < data->length; ++i) {
+        data->data[i] = (UA_Byte) ((data->data[i] + 1) % (UA_BYTE_MAX + 1));
+    }
+
     return UA_STATUSCODE_GOOD;
 }
 
@@ -137,6 +164,14 @@ makeThumbprint_testing(const UA_SecurityPolicy *securityPolicy,
                        const UA_ByteString *certificate,
                        UA_ByteString *thumbprint) {
     SET_CALLED(makeCertificateThumbprint);
+
+    ck_assert(securityPolicy != NULL);
+    ck_assert(certificate != NULL);
+    ck_assert(thumbprint != NULL);
+
+    ck_assert_msg(thumbprint->length == 20, "Thumbprints have to be 20 bytes long (current specification)");
+    memset(thumbprint->data, 42, 20);
+
     return UA_STATUSCODE_GOOD;
 }