|
@@ -331,19 +331,68 @@ calculateAsymAlgSecurityHeaderLength(const UA_SecureChannel *channel) {
|
|
return asymHeaderLength;
|
|
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
|
|
static void
|
|
hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start,
|
|
hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start,
|
|
const UA_Byte **buf_end) {
|
|
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);
|
|
*buf_start += calculateAsymAlgSecurityHeaderLength(channel);
|
|
|
|
|
|
|
|
+#ifdef UA_ENABLE_ENCRYPTION
|
|
if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
|
|
if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
|
|
channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
|
|
channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+ const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
|
|
|
|
+
|
|
/* Hide bytes for signature and padding */
|
|
/* Hide bytes for signature and padding */
|
|
size_t potentialEncryptMaxSize = (size_t)(*buf_end - *buf_start) + UA_SEQUENCE_HEADER_LENGTH;
|
|
size_t potentialEncryptMaxSize = (size_t)(*buf_end - *buf_start) + UA_SEQUENCE_HEADER_LENGTH;
|
|
*buf_end -= securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm.
|
|
*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,
|
|
*buf_end -= UA_SecurityPolicy_getRemoteAsymEncryptionBufferLengthOverhead(securityPolicy,
|
|
channel->channelContext,
|
|
channel->channelContext,
|
|
potentialEncryptMaxSize);
|
|
potentialEncryptMaxSize);
|
|
|
|
+#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifdef UA_ENABLE_ENCRYPTION
|
|
|
|
+
|
|
static void
|
|
static void
|
|
padChunkAsym(UA_SecureChannel *channel, const UA_ByteString *const buf,
|
|
padChunkAsym(UA_SecureChannel *channel, const UA_ByteString *const buf,
|
|
size_t securityHeaderLength, UA_Byte **buf_pos) {
|
|
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
|
|
static UA_StatusCode
|
|
signAndEncryptAsym(UA_SecureChannel *const channel, size_t preSignLength,
|
|
signAndEncryptAsym(UA_SecureChannel *const channel, size_t preSignLength,
|
|
UA_ByteString *buf, size_t securityHeaderLength,
|
|
UA_ByteString *buf, size_t securityHeaderLength,
|
|
size_t totalLength) {
|
|
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 */
|
|
/* Sends an OPN message using asymmetric encryption if defined */
|
|
UA_StatusCode
|
|
UA_StatusCode
|
|
UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel,
|
|
UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel,
|
|
@@ -524,7 +526,9 @@ UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel,
|
|
const size_t securityHeaderLength = calculateAsymAlgSecurityHeaderLength(channel);
|
|
const size_t securityHeaderLength = calculateAsymAlgSecurityHeaderLength(channel);
|
|
|
|
|
|
/* Add padding to the chunk */
|
|
/* Add padding to the chunk */
|
|
|
|
+#ifdef UA_ENABLE_ENCRYPTION
|
|
padChunkAsym(channel, &buf, securityHeaderLength, &buf_pos);
|
|
padChunkAsym(channel, &buf, securityHeaderLength, &buf_pos);
|
|
|
|
+#endif
|
|
|
|
|
|
/* The total message length */
|
|
/* The total message length */
|
|
size_t pre_sig_length = (uintptr_t)buf_pos - (uintptr_t)buf.data;
|
|
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)
|
|
if(retval != UA_STATUSCODE_GOOD)
|
|
goto error;
|
|
goto error;
|
|
|
|
|
|
|
|
+#ifdef UA_ENABLE_ENCRYPTION
|
|
retval = signAndEncryptAsym(channel, pre_sig_length, &buf, securityHeaderLength, total_length);
|
|
retval = signAndEncryptAsym(channel, pre_sig_length, &buf, securityHeaderLength, total_length);
|
|
if(retval != UA_STATUSCODE_GOOD)
|
|
if(retval != UA_STATUSCODE_GOOD)
|
|
goto error;
|
|
goto error;
|
|
|
|
+#endif
|
|
|
|
|
|
/* Send the message, the buffer is freed in the network layer */
|
|
/* Send the message, the buffer is freed in the network layer */
|
|
buf.length = finalLength;
|
|
buf.length = finalLength;
|
|
@@ -563,6 +569,8 @@ error:
|
|
/* Send Symmetric Message */
|
|
/* Send Symmetric Message */
|
|
/**************************/
|
|
/**************************/
|
|
|
|
|
|
|
|
+#ifdef UA_ENABLE_ENCRYPTION
|
|
|
|
+
|
|
static UA_UInt16
|
|
static UA_UInt16
|
|
calculatePaddingSym(const UA_SecurityPolicy *securityPolicy, const void *channelContext,
|
|
calculatePaddingSym(const UA_SecurityPolicy *securityPolicy, const void *channelContext,
|
|
size_t bytesToWrite, UA_Byte *paddingSize, UA_Byte *extraPaddingSize) {
|
|
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.
|
|
size_t signatureSize = securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm.
|
|
getLocalSignatureSize(securityPolicy, channelContext);
|
|
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;
|
|
*paddingSize = (UA_Byte)padding;
|
|
*extraPaddingSize = (UA_Byte)(padding >> 8);
|
|
*extraPaddingSize = (UA_Byte)(padding >> 8);
|
|
- return padding;
|
|
|
|
|
|
+ return (UA_UInt16)padding;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
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;
|
|
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
|
|
/* Forward the data pointer so that the payload is encoded after the
|
|
* message header */
|
|
* message header */
|
|
mc->buf_pos = &mc->messageBuffer.data[UA_SECURE_MESSAGE_HEADER_LENGTH];
|
|
mc->buf_pos = &mc->messageBuffer.data[UA_SECURE_MESSAGE_HEADER_LENGTH];
|
|
mc->buf_end = &mc->messageBuffer.data[mc->messageBuffer.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
|
|
/* 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,
|
|
* is signed and/or encrypted. The footer includes the fields PaddingSize,
|
|
* Padding, ExtraPadding and Signature. The padding fields are only present
|
|
* Padding, ExtraPadding and Signature. The padding fields are only present
|
|
@@ -619,6 +692,7 @@ setBufPos(UA_MessageContext *mc) {
|
|
UA_SYMMETRIC_ALG_SECURITY_HEADER_LENGTH;
|
|
UA_SYMMETRIC_ALG_SECURITY_HEADER_LENGTH;
|
|
mc->buf_end -= (maxEncryptDataSize % encryptionBlockSize) + 1;
|
|
mc->buf_end -= (maxEncryptDataSize % encryptionBlockSize) + 1;
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
}
|
|
}
|
|
|
|
|
|
static UA_StatusCode
|
|
static UA_StatusCode
|
|
@@ -645,39 +719,11 @@ checkLimitsSym(UA_MessageContext *const messageContext, size_t *const bodyLength
|
|
return UA_STATUSCODE_GOOD;
|
|
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
|
|
static UA_StatusCode
|
|
encodeHeadersSym(UA_MessageContext *const messageContext, size_t totalLength) {
|
|
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_Byte *header_pos = messageContext->messageBuffer.data;
|
|
|
|
+
|
|
UA_SecureConversationMessageHeader respHeader;
|
|
UA_SecureConversationMessageHeader respHeader;
|
|
respHeader.secureChannelId = channel->securityToken.channelId;
|
|
respHeader.secureChannelId = channel->securityToken.channelId;
|
|
respHeader.messageHeader.messageTypeAndChunkType = messageContext->messageType;
|
|
respHeader.messageHeader.messageTypeAndChunkType = messageContext->messageType;
|
|
@@ -686,8 +732,10 @@ encodeHeadersSym(UA_MessageContext *const messageContext, size_t totalLength) {
|
|
respHeader.messageHeader.messageTypeAndChunkType += UA_CHUNKTYPE_FINAL;
|
|
respHeader.messageHeader.messageTypeAndChunkType += UA_CHUNKTYPE_FINAL;
|
|
else
|
|
else
|
|
respHeader.messageHeader.messageTypeAndChunkType += UA_CHUNKTYPE_INTERMEDIATE;
|
|
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;
|
|
UA_SymmetricAlgorithmSecurityHeader symSecHeader;
|
|
symSecHeader.tokenId = channel->securityToken.tokenId;
|
|
symSecHeader.tokenId = channel->securityToken.tokenId;
|
|
@@ -704,40 +752,6 @@ encodeHeadersSym(UA_MessageContext *const messageContext, size_t totalLength) {
|
|
return res;
|
|
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
|
|
static UA_StatusCode
|
|
sendSymmetricChunk(UA_MessageContext *messageContext) {
|
|
sendSymmetricChunk(UA_MessageContext *messageContext) {
|
|
UA_StatusCode res = UA_STATUSCODE_GOOD;
|
|
UA_StatusCode res = UA_STATUSCODE_GOOD;
|
|
@@ -753,7 +767,9 @@ sendSymmetricChunk(UA_MessageContext *messageContext) {
|
|
goto error;
|
|
goto error;
|
|
|
|
|
|
/* Add padding */
|
|
/* Add padding */
|
|
|
|
+#ifdef UA_ENABLE_ENCRYPTION
|
|
padChunkSym(messageContext, bodyLength);
|
|
padChunkSym(messageContext, bodyLength);
|
|
|
|
+#endif
|
|
|
|
|
|
/* The total message length */
|
|
/* The total message length */
|
|
size_t pre_sig_length = (uintptr_t)(messageContext->buf_pos) -
|
|
size_t pre_sig_length = (uintptr_t)(messageContext->buf_pos) -
|
|
@@ -774,6 +790,7 @@ sendSymmetricChunk(UA_MessageContext *messageContext) {
|
|
if(res != UA_STATUSCODE_GOOD)
|
|
if(res != UA_STATUSCODE_GOOD)
|
|
goto error;
|
|
goto error;
|
|
|
|
|
|
|
|
+#ifdef UA_ENABLE_ENCRYPTION
|
|
res = signChunkSym(messageContext, pre_sig_length);
|
|
res = signChunkSym(messageContext, pre_sig_length);
|
|
if(res != UA_STATUSCODE_GOOD)
|
|
if(res != UA_STATUSCODE_GOOD)
|
|
goto error;
|
|
goto error;
|
|
@@ -781,6 +798,7 @@ sendSymmetricChunk(UA_MessageContext *messageContext) {
|
|
res = encryptChunkSym(messageContext, total_length);
|
|
res = encryptChunkSym(messageContext, total_length);
|
|
if(res != UA_STATUSCODE_GOOD)
|
|
if(res != UA_STATUSCODE_GOOD)
|
|
goto error;
|
|
goto error;
|
|
|
|
+#endif
|
|
|
|
|
|
/* Send the chunk, the buffer is freed in the network layer */
|
|
/* Send the chunk, the buffer is freed in the network layer */
|
|
return connection->send(channel->connection, &messageContext->messageBuffer);
|
|
return connection->send(channel->connection, &messageContext->messageBuffer);
|