Browse Source

SecureChannel: Conditionally compile methods that are only for encryption

Julius Pfrommer 5 years ago
parent
commit
a496cd4caf
1 changed files with 168 additions and 150 deletions
  1. 168 150
      src/ua_securechannel.c

+ 168 - 150
src/ua_securechannel.c

@@ -331,19 +331,68 @@ calculateAsymAlgSecurityHeaderLength(const UA_SecureChannel *channel) {
     return asymHeaderLength;
 }
 
+static UA_StatusCode
+prependHeadersAsym(UA_SecureChannel *const channel, UA_Byte *header_pos,
+                   const UA_Byte *buf_end, size_t totalLength,
+                   size_t securityHeaderLength, UA_UInt32 requestId,
+                   size_t *const finalLength) {
+    UA_StatusCode retval;
+    size_t dataToEncryptLength =
+        totalLength - (UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH + securityHeaderLength);
+    UA_SecureConversationMessageHeader respHeader;
+    respHeader.messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL;
+    respHeader.messageHeader.messageSize = (UA_UInt32)
+        (totalLength +
+         UA_SecurityPolicy_getRemoteAsymEncryptionBufferLengthOverhead(channel->securityPolicy,
+                                                                       channel->channelContext,
+                                                                       dataToEncryptLength));
+    respHeader.secureChannelId = channel->securityToken.channelId;
+    retval = UA_encodeBinary(&respHeader,
+                             &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER],
+                             &header_pos, &buf_end, NULL, NULL);
+    if(retval != UA_STATUSCODE_GOOD)
+        return retval;
+
+    UA_AsymmetricAlgorithmSecurityHeader asymHeader;
+    UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
+    asymHeader.securityPolicyUri = channel->securityPolicy->policyUri;
+    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
+       channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
+        asymHeader.senderCertificate = channel->securityPolicy->localCertificate;
+        asymHeader.receiverCertificateThumbprint.length = 20;
+        asymHeader.receiverCertificateThumbprint.data = channel->remoteCertificateThumbprint;
+    }
+    retval = UA_encodeBinary(&asymHeader,
+                             &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER],
+                             &header_pos, &buf_end, NULL, NULL);
+    if(retval != UA_STATUSCODE_GOOD)
+        return retval;
+
+    UA_SequenceHeader seqHeader;
+    seqHeader.requestId = requestId;
+    seqHeader.sequenceNumber = UA_atomic_addUInt32(&channel->sendSequenceNumber, 1);
+    retval = UA_encodeBinary(&seqHeader, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
+                             &header_pos, &buf_end, NULL, NULL);
+
+    *finalLength = respHeader.messageHeader.messageSize;
+
+    return retval;
+}
+
 static void
 hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start,
               const UA_Byte **buf_end) {
-    const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
-    *buf_start += UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH + UA_SEQUENCE_HEADER_LENGTH;
-
-    /* Add the SecurityHeaderLength */
+    *buf_start += UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH;
+    *buf_start += UA_SEQUENCE_HEADER_LENGTH;
     *buf_start += calculateAsymAlgSecurityHeaderLength(channel);
 
+#ifdef UA_ENABLE_ENCRYPTION
     if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
        channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
         return;
 
+    const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
+
     /* Hide bytes for signature and padding */
     size_t potentialEncryptMaxSize = (size_t)(*buf_end - *buf_start) + UA_SEQUENCE_HEADER_LENGTH;
     *buf_end -= securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm.
@@ -354,8 +403,11 @@ hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start,
     *buf_end -= UA_SecurityPolicy_getRemoteAsymEncryptionBufferLengthOverhead(securityPolicy,
                                                                               channel->channelContext,
                                                                               potentialEncryptMaxSize);
+#endif
 }
 
+#ifdef UA_ENABLE_ENCRYPTION
+
 static void
 padChunkAsym(UA_SecureChannel *channel, const UA_ByteString *const buf,
              size_t securityHeaderLength, UA_Byte **buf_pos) {
@@ -401,89 +453,39 @@ padChunkAsym(UA_SecureChannel *channel, const UA_ByteString *const buf,
     }
 }
 
-static UA_StatusCode
-prependHeadersAsym(UA_SecureChannel *const channel, UA_Byte *header_pos,
-                   const UA_Byte *buf_end, size_t totalLength,
-                   size_t securityHeaderLength, UA_UInt32 requestId,
-                   size_t *const finalLength) {
-    UA_StatusCode retval;
-    size_t dataToEncryptLength =
-        totalLength - (UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH + securityHeaderLength);
-    UA_SecureConversationMessageHeader respHeader;
-    respHeader.messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL;
-    respHeader.messageHeader.messageSize = (UA_UInt32)
-        (totalLength +
-         UA_SecurityPolicy_getRemoteAsymEncryptionBufferLengthOverhead(channel->securityPolicy,
-                                                                       channel->channelContext,
-                                                                       dataToEncryptLength));
-    respHeader.secureChannelId = channel->securityToken.channelId;
-    retval = UA_encodeBinary(&respHeader,
-                             &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER],
-                             &header_pos, &buf_end, NULL, NULL);
-    if(retval != UA_STATUSCODE_GOOD)
-        return retval;
-
-    UA_AsymmetricAlgorithmSecurityHeader asymHeader;
-    UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
-    asymHeader.securityPolicyUri = channel->securityPolicy->policyUri;
-    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
-       channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
-        asymHeader.senderCertificate = channel->securityPolicy->localCertificate;
-        asymHeader.receiverCertificateThumbprint.length = 20;
-        asymHeader.receiverCertificateThumbprint.data = channel->remoteCertificateThumbprint;
-    }
-    retval = UA_encodeBinary(&asymHeader,
-                             &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER],
-                             &header_pos, &buf_end, NULL, NULL);
-    if(retval != UA_STATUSCODE_GOOD)
-        return retval;
-
-    UA_SequenceHeader seqHeader;
-    seqHeader.requestId = requestId;
-    seqHeader.sequenceNumber = UA_atomic_addUInt32(&channel->sendSequenceNumber, 1);
-    retval = UA_encodeBinary(&seqHeader, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
-                             &header_pos, &buf_end, NULL, NULL);
-
-    *finalLength = respHeader.messageHeader.messageSize;
-
-    return retval;
-}
-
 static UA_StatusCode
 signAndEncryptAsym(UA_SecureChannel *const channel, size_t preSignLength,
                    UA_ByteString *buf, size_t securityHeaderLength,
                    size_t totalLength) {
-    const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
-
-    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
-       channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
-        /* Sign message */
-        const UA_ByteString dataToSign = {preSignLength, buf->data};
-        size_t sigsize = securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm.
-            getLocalSignatureSize(securityPolicy, channel->channelContext);
-        UA_ByteString signature = {sigsize, buf->data + preSignLength};
-        retval = securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm.
-            sign(securityPolicy, channel->channelContext, &dataToSign, &signature);
-        if(retval != UA_STATUSCODE_GOOD)
-            return retval;
+    if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
+       channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
+        return UA_STATUSCODE_GOOD;
 
-        /* Specification part 6, 6.7.4: The OpenSecureChannel Messages are
-         * signed and encrypted if the SecurityMode is not None (even if the
-         * SecurityMode is SignOnly). */
-        size_t unencrypted_length =
-            UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH + securityHeaderLength;
-        UA_ByteString dataToEncrypt = {totalLength - unencrypted_length,
-                                       &buf->data[unencrypted_length]};
-        retval = securityPolicy->asymmetricModule.cryptoModule.encryptionAlgorithm.
-            encrypt(securityPolicy, channel->channelContext, &dataToEncrypt);
-        if(retval != UA_STATUSCODE_GOOD)
-            return retval;
-    }
+    const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
+    
+    /* Sign message */
+    const UA_ByteString dataToSign = {preSignLength, buf->data};
+    size_t sigsize = securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm.
+        getLocalSignatureSize(securityPolicy, channel->channelContext);
+    UA_ByteString signature = {sigsize, buf->data + preSignLength};
+    UA_StatusCode retval = securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm.
+        sign(securityPolicy, channel->channelContext, &dataToSign, &signature);
+    if(retval != UA_STATUSCODE_GOOD)
+        return retval;
 
-    return retval;
+    /* Specification part 6, 6.7.4: The OpenSecureChannel Messages are
+     * signed and encrypted if the SecurityMode is not None (even if the
+     * SecurityMode is SignOnly). */
+    size_t unencrypted_length =
+        UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH + securityHeaderLength;
+    UA_ByteString dataToEncrypt = {totalLength - unencrypted_length,
+                                   &buf->data[unencrypted_length]};
+    return securityPolicy->asymmetricModule.cryptoModule.encryptionAlgorithm.
+        encrypt(securityPolicy, channel->channelContext, &dataToEncrypt);
 }
 
+#endif /* UA_ENABLE_ENCRYPTION */
+
 /* Sends an OPN message using asymmetric encryption if defined */
 UA_StatusCode
 UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel,
@@ -524,7 +526,9 @@ UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel,
     const size_t securityHeaderLength = calculateAsymAlgSecurityHeaderLength(channel);
 
     /* Add padding to the chunk */
+#ifdef UA_ENABLE_ENCRYPTION
     padChunkAsym(channel, &buf, securityHeaderLength, &buf_pos);
+#endif
 
     /* The total message length */
     size_t pre_sig_length = (uintptr_t)buf_pos - (uintptr_t)buf.data;
@@ -542,9 +546,11 @@ UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel,
     if(retval != UA_STATUSCODE_GOOD)
         goto error;
 
+#ifdef UA_ENABLE_ENCRYPTION
     retval = signAndEncryptAsym(channel, pre_sig_length, &buf, securityHeaderLength, total_length);
     if(retval != UA_STATUSCODE_GOOD)
         goto error;
+#endif
 
     /* Send the message, the buffer is freed in the network layer */
     buf.length = finalLength;
@@ -563,6 +569,8 @@ error:
 /* Send Symmetric Message */
 /**************************/
 
+#ifdef UA_ENABLE_ENCRYPTION
+
 static UA_UInt16
 calculatePaddingSym(const UA_SecurityPolicy *securityPolicy, const void *channelContext,
                     size_t bytesToWrite, UA_Byte *paddingSize, UA_Byte *extraPaddingSize) {
@@ -571,23 +579,88 @@ calculatePaddingSym(const UA_SecurityPolicy *securityPolicy, const void *channel
     size_t signatureSize = securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm.
         getLocalSignatureSize(securityPolicy, channelContext);
 
-    UA_UInt16 padding = (UA_UInt16)
-        (encryptionBlockSize - ((bytesToWrite + signatureSize + 1) % encryptionBlockSize));
+    size_t padding = (encryptionBlockSize -
+                      ((bytesToWrite + signatureSize + 1) % encryptionBlockSize));
     *paddingSize = (UA_Byte)padding;
     *extraPaddingSize = (UA_Byte)(padding >> 8);
-    return padding;
+    return (UA_UInt16)padding;
 }
 
 static void
-setBufPos(UA_MessageContext *mc) {
-    const UA_SecureChannel *channel = mc->channel;
+padChunkSym(UA_MessageContext *messageContext, size_t bodyLength) {
+    if(messageContext->channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
+        return;
+
+    /* The bytes for the padding and signature were removed from buf_end before
+     * encoding the payload. So we don't have to check if there is enough
+     * space. */
+
+    size_t bytesToWrite = bodyLength + UA_SEQUENCE_HEADER_LENGTH;
+    UA_Byte paddingSize = 0;
+    UA_Byte extraPaddingSize = 0;
+    UA_UInt16 totalPaddingSize =
+        calculatePaddingSym(messageContext->channel->securityPolicy,
+                            messageContext->channel->channelContext,
+                            bytesToWrite, &paddingSize, &extraPaddingSize);
+
+    /* This is <= because the paddingSize byte also has to be written. */
+    for(UA_UInt16 i = 0; i <= totalPaddingSize; ++i) {
+        *messageContext->buf_pos = paddingSize;
+        ++(messageContext->buf_pos);
+    }
+    if(extraPaddingSize > 0) {
+        *messageContext->buf_pos = extraPaddingSize;
+        ++(messageContext->buf_pos);
+    }
+}
+
+static UA_StatusCode
+signChunkSym(UA_MessageContext *const messageContext, size_t preSigLength) {
+    const UA_SecureChannel *channel = messageContext->channel;
+    if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
+       channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
+        return UA_STATUSCODE_GOOD;
+
     const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
+    UA_ByteString dataToSign = messageContext->messageBuffer;
+    dataToSign.length = preSigLength;
+    UA_ByteString signature;
+    signature.length = securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm.
+        getLocalSignatureSize(securityPolicy, channel->channelContext);
+    signature.data = messageContext->buf_pos;
 
+    return securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm.
+        sign(securityPolicy, channel->channelContext, &dataToSign, &signature);
+}
+
+static UA_StatusCode
+encryptChunkSym(UA_MessageContext *const messageContext, size_t totalLength) {
+    const UA_SecureChannel *channel = messageContext->channel;
+    if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
+        return UA_STATUSCODE_GOOD;
+        
+    UA_ByteString dataToEncrypt;
+    dataToEncrypt.data = messageContext->messageBuffer.data + UA_SECUREMH_AND_SYMALGH_LENGTH;
+    dataToEncrypt.length = totalLength - UA_SECUREMH_AND_SYMALGH_LENGTH;
+
+    const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
+    return securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.
+        encrypt(securityPolicy, channel->channelContext, &dataToEncrypt);
+}
+
+#endif /* UA_ENABLE_ENCRYPTION */
+
+static void
+setBufPos(UA_MessageContext *mc) {
     /* Forward the data pointer so that the payload is encoded after the
      * message header */
     mc->buf_pos = &mc->messageBuffer.data[UA_SECURE_MESSAGE_HEADER_LENGTH];
     mc->buf_end = &mc->messageBuffer.data[mc->messageBuffer.length];
 
+#ifdef UA_ENABLE_ENCRYPTION
+    const UA_SecureChannel *channel = mc->channel;
+    const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
+
     /* Reserve space for the message footer at the end of the chunk if the chunk
      * is signed and/or encrypted. The footer includes the fields PaddingSize,
      * Padding, ExtraPadding and Signature. The padding fields are only present
@@ -619,6 +692,7 @@ setBufPos(UA_MessageContext *mc) {
             UA_SYMMETRIC_ALG_SECURITY_HEADER_LENGTH;
         mc->buf_end -= (maxEncryptDataSize % encryptionBlockSize) + 1;
     }
+#endif
 }
 
 static UA_StatusCode
@@ -645,39 +719,11 @@ checkLimitsSym(UA_MessageContext *const messageContext, size_t *const bodyLength
     return UA_STATUSCODE_GOOD;
 }
 
-static void
-padChunkSym(UA_MessageContext *messageContext, size_t bodyLength) {
-    if(messageContext->channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
-        return;
-
-    /* The bytes for the padding and signature were removed from buf_end before
-     * encoding the payload. So we don't have to check if there is enough
-     * space. */
-
-    size_t bytesToWrite = bodyLength + UA_SEQUENCE_HEADER_LENGTH;
-    UA_Byte paddingSize = 0;
-    UA_Byte extraPaddingSize = 0;
-    UA_UInt16 totalPaddingSize =
-        calculatePaddingSym(messageContext->channel->securityPolicy,
-                            messageContext->channel->channelContext,
-                            bytesToWrite, &paddingSize, &extraPaddingSize);
-
-    /* This is <= because the paddingSize byte also has to be written. */
-    for(UA_UInt16 i = 0; i <= totalPaddingSize; ++i) {
-        *messageContext->buf_pos = paddingSize;
-        ++(messageContext->buf_pos);
-    }
-    if(extraPaddingSize > 0) {
-        *messageContext->buf_pos = extraPaddingSize;
-        ++(messageContext->buf_pos);
-    }
-}
-
 static UA_StatusCode
 encodeHeadersSym(UA_MessageContext *const messageContext, size_t totalLength) {
-    UA_StatusCode res = UA_STATUSCODE_GOOD;
-    UA_SecureChannel *const channel = messageContext->channel;
+    UA_SecureChannel *channel = messageContext->channel;
     UA_Byte *header_pos = messageContext->messageBuffer.data;
+
     UA_SecureConversationMessageHeader respHeader;
     respHeader.secureChannelId = channel->securityToken.channelId;
     respHeader.messageHeader.messageTypeAndChunkType = messageContext->messageType;
@@ -686,8 +732,10 @@ encodeHeadersSym(UA_MessageContext *const messageContext, size_t totalLength) {
         respHeader.messageHeader.messageTypeAndChunkType += UA_CHUNKTYPE_FINAL;
     else
         respHeader.messageHeader.messageTypeAndChunkType += UA_CHUNKTYPE_INTERMEDIATE;
-    res = UA_encodeBinary(&respHeader, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER],
-                          &header_pos, &messageContext->buf_end, NULL, NULL);
+
+    UA_StatusCode res =
+        UA_encodeBinary(&respHeader, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER],
+                        &header_pos, &messageContext->buf_end, NULL, NULL);
 
     UA_SymmetricAlgorithmSecurityHeader symSecHeader;
     symSecHeader.tokenId = channel->securityToken.tokenId;
@@ -704,40 +752,6 @@ encodeHeadersSym(UA_MessageContext *const messageContext, size_t totalLength) {
     return res;
 }
 
-static UA_StatusCode
-signChunkSym(UA_MessageContext *const messageContext, size_t preSigLength) {
-    UA_SecureChannel *const channel = messageContext->channel;
-    const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
-    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
-       channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
-        UA_ByteString dataToSign = messageContext->messageBuffer;
-        dataToSign.length = preSigLength;
-        UA_ByteString signature;
-        signature.length = securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm.
-            getLocalSignatureSize(securityPolicy, channel->channelContext);
-        signature.data = messageContext->buf_pos;
-        return securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm
-                             .sign(securityPolicy, channel->channelContext, &dataToSign, &signature);
-    }
-
-    return UA_STATUSCODE_GOOD;
-}
-
-static UA_StatusCode
-encryptChunkSym(UA_MessageContext *const messageContext, size_t totalLength) {
-    UA_SecureChannel *const channel = messageContext->channel;
-    const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
-    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
-        UA_ByteString dataToEncrypt;
-        dataToEncrypt.data = messageContext->messageBuffer.data + UA_SECUREMH_AND_SYMALGH_LENGTH;
-        dataToEncrypt.length = totalLength - UA_SECUREMH_AND_SYMALGH_LENGTH;
-        return securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.
-            encrypt(securityPolicy, channel->channelContext, &dataToEncrypt);
-    }
-
-    return UA_STATUSCODE_GOOD;
-}
-
 static UA_StatusCode
 sendSymmetricChunk(UA_MessageContext *messageContext) {
     UA_StatusCode res = UA_STATUSCODE_GOOD;
@@ -753,7 +767,9 @@ sendSymmetricChunk(UA_MessageContext *messageContext) {
         goto error;
 
     /* Add padding */
+#ifdef UA_ENABLE_ENCRYPTION
     padChunkSym(messageContext, bodyLength);
+#endif
 
     /* The total message length */
     size_t pre_sig_length = (uintptr_t)(messageContext->buf_pos) -
@@ -774,6 +790,7 @@ sendSymmetricChunk(UA_MessageContext *messageContext) {
     if(res != UA_STATUSCODE_GOOD)
         goto error;
 
+#ifdef UA_ENABLE_ENCRYPTION
     res = signChunkSym(messageContext, pre_sig_length);
     if(res != UA_STATUSCODE_GOOD)
         goto error;
@@ -781,6 +798,7 @@ sendSymmetricChunk(UA_MessageContext *messageContext) {
     res = encryptChunkSym(messageContext, total_length);
     if(res != UA_STATUSCODE_GOOD)
         goto error;
+#endif
 
     /* Send the chunk, the buffer is freed in the network layer */
     return connection->send(channel->connection, &messageContext->messageBuffer);