The structure of the Message depends on whether the SecurityPolicy requires an algorithm that combines encryption and authentication (e.g. Authenticated Encryption algorithms) used or if it requires separate algorithms for each operation (Unauthenticated Encryption algorithms).
Figure 11 shows the structure of a MessageChunk and how security is applied to the Message when using Unauthenticated Encryption algorithms. For these SecurityPolicies any padding is appended to the message before appending the Signature.
Figure 11 – MessageChunk for Unauthenticated Encryption Algorithms
Figure 12 shows the structure of a MessageChunk and how security is applied to the Message when using Authenticated Encryption algorithms. For these SecurityPolicies the Signature is calculated during encryption and appended after the encrypted data. Padding is not needed.
Figure 12 – MessageChunk for Authenticated Encryption Algorithms
Every MessageChunk has a Message header with the fields defined in Table 50.
Table 50 – OPC UA Secure Conversation Message Header
|MessageType||Byte ||A three byte ASCII code that identifies the Message type. The following values are defined at this time: MSG A Message secured with the keys associated with a channel. OPN OpenSecureChannel Message. CLO CloseSecureChannel Message.|
|IsFinal||Byte||A one byte ASCII code that indicates whether the MessageChunk is the final chunk in a Message. The following values are defined at this time: C An intermediate chunk. F The final chunk. A The final chunk (used when an error occurred and the Message is aborted). This field is only meaningful for MessageType of ‘MSG’This field is always ‘F’ for other MessageTypes.|
|MessageSize||UInt32||The length of the MessageChunk, in bytes. The length starts from the beginning of the MessageType field.|
|SecureChannelId||UInt32||A unique identifier for the SecureChannel assigned by the Server. If a Server receives a SecureChannelId which it does not recognize it shall return an appropriate transport layer error.When a Server starts the first SecureChannelId used should be a value that is likely to be unique after each restart. This ensures that a Server restart does not cause previously connected Clients to accidently ‘reuse’ SecureChannels that did not belong to them.|
The Message header is followed by a security header which specifies what cryptography operations have been applied to the Message. There are two versions of the security header which depend on the type of security applied to the Message. The security header used for asymmetric algorithms is defined in Table 51. Asymmetric algorithms are used to secure the OpenSecureChannel Messages. PKCS #1 defines a set of asymmetric algorithms that may be used by UASC implementations. The AsymmetricKeyWrapAlgorithm element of the SecurityPolicy structure defined in Table 42 is not used by UASC implementations.
Table 51 – Asymmetric algorithm Security header
|SecurityPolicyUriLength||Int32||The length of the SecurityPolicyUri in bytes. This value shall not exceed 255 bytes. If a URI is not specified this value may be 0 or -1.Other negative values are invalid.|
|SecurityPolicyUri||Byte ||The URI of the Security Policy used to secure the Message.This field is encoded as a UTF-8 string without a null terminator.|
|SenderCertificateLength||Int32||The length of the SenderCertificate in bytes. This value shall not exceed MaxSenderCertificateSize bytes. If a certificate is not specified this value may be 0 or -1. Other negative values are invalid.|
|SenderCertificate||Byte ||The X.509 v3 Certificate assigned to the sending application Instance. This is a DER encoded blob. The structure of an X.509 v3 Certificate is defined in X.509 v3. The DER format for a Certificate is defined in X690 This indicates what Private Key was used to sign the MessageChunk. The Stack shall close the channel and report an error to the application if the SenderCertificate is too large for the buffer size supported by the transport layer. This field shall be null if the Message is not signed. If the Certificate is signed by a CA, the DER encoded CA Certificate may be appended after the Certificate in the byte array. If the CA Certificate is also signed by another CA this process is repeated until the entire Certificate chain is in the buffer or if MaxSenderCertificateSize limit is reached (the process stops after the last whole Certificate that can be added without exceeding the MaxSenderCertificateSize limit). Receivers can extract the Certificates from the byte array by using the Certificate size contained in DER header (see X.509 v3).Receivers that do not handle Certificate chains shall ignore the extra bytes.|
|ReceiverCertificateThumbprintLength||Int32||The length of the ReceiverCertificateThumbprint in bytes. If encrypted, the value of this field is 20 bytes. If not encrypted the value may be 0 or -1. Other negative values are invalid.|
|ReceiverCertificateThumbprint||Byte ||The thumbprint of the X.509 v3 Certificate assigned to the receiving application Instance. The thumbprint is the CertificateDigest of the DER encoded form of the Certificate. This indicates what public key was used to encrypt the MessageChunk.This field shall be null if the Message is not encrypted.|
The receiver shall close the communication channel if any of the fields in the security header have invalid lengths.
The SenderCertificate, including any chains, shall be small enough to fit into a single MessageChunk and leave room for at least one byte of body information. The maximum size for the SenderCertificate can be calculated with this formula:
MaxSenderCertificateSize = MessageChunkSize – 12 - // Header size 4 - // SecurityPolicyUriLength SecurityPolicyUri - // UTF-8 encoded string 4 - // SenderCertificateLength 4 - // ReceiverCertificateThumbprintLength 20 - // ReceiverCertificateThumbprint 8 - // SequenceHeader size 1 - // Minimum body size 1 - // PaddingSize if present Padding - // Padding if present ExtraPadding - // ExtraPadding if present AsymmetricSignatureSize // If present
The MessageChunkSize depends on the transport protocol but shall be at least 8 192 bytes. The AsymmetricSignatureSize depends on the number of bits in the public key for the SenderCertificate. The Int32FieldLength is the length of an encoded Int32 value and it is always 4 bytes.
The security header used for symmetric algorithms defined in Table 52. Symmetric algorithms are used to secure all Messages other than the OpenSecureChannel Messages. FIPS 197 define symmetric encryption algorithms that UASC implementations may use. FIPS 180- and HMAC define some symmetric signature algorithms.
Table 52 – Symmetric algorithm Security header
|TokenId||UInt32||A unique identifier for the SecureChannel SecurityToken used to secure the Message.This identifier is returned by the Server in an OpenSecureChannel response Message. If a Server receives a TokenId which it does not recognize it shall return an appropriate transport layer error.|
The security header is always followed by the sequence header which is defined in Table 53. The sequence header ensures that the first encrypted block of every Message sent over a channel will start with different data.
Table 53 – Sequence header
|SequenceNumber||UInt32||A monotonically increasing sequence number assigned by the sender to each MessageChunk sent over the SecureChannel.|
|RequestId||UInt32||An identifier assigned by the Client to OPC UA request Message. All MessageChunks for the request and the associated response use the same identifier.|
A SequenceNumber may not be reused for any TokenId. The SecurityToken lifetime shall be short enough to ensure that this never happens; however, if it does the receiver shall treat it as a transport error and force a reconnect. The SequenceNumber does not reset when a new TokenId is issued and it shall be incremented by exactly one for each MessageChunk sent.
SecurityPolicies with LegacySequenceNumbers set to TRUE, the SequenceNumber shall monotonically increase for all Messages and shall not wrap around until it is greater than 4 294 966 271 (UInt32.MaxValue – 1 024). The first number after the wrap around shall be less than 1 024.
SecurityPolicies with LegacySequenceNumbers set to FALSE, the SequenceNumber shall start at 0 and monotonically increase for all Messages and shall not wrap around until it is equal to 4 294 967 295 (UInt32.MaxValue). The first number after the wrap around shall be 0.
Some applications will find it takes time to validate the OpenSecureChannel Requests and Responses used to renew a TokenId. In these situations, the receiver may assume the SequenceNumber is correct which allows it to process subsequent messages secured with the existing TokenId before the OpenSecureChannel Message is validated. When processing of the OpenSecureChannel Message completes, the receiver checks the SequenceNumber and closes the SecureChannel if it is incorrect.
The sequence header is followed by the Message body which is encoded with the OPC UA Binary encoding as described in 5.2.9. The body may be split across multiple MessageChunks.
Each MessageChunk when using SecurityPolicies with an Unauthenticated Encryption algorithms have a footer with the fields defined in Table 54.
Table 54 – Message Footer for Unauthenticated Encryption Algorithms
|PaddingSize||Byte||The number of padding bytes (not including the byte for the PaddingSize).|
|Padding||OctetString||Padding added to the end of the Message to ensure length of the data to encrypt is an integer multiple of the encryption block size.The value of each byte of the padding is equal to PaddingSize.|
|ExtraPaddingSize||Byte||The most significant byte of a two-byte integer used to specify the padding size when the key used to encrypt the message chunk is larger than 2 048 bits. This field is omitted if the key length is less than or equal to 2 048 bits.|
|Signature||OctetString||The signature for the MessageChunk. The signature includes the headers, all Message data, the PaddingSize and the Padding.The signature is encoded as sequence of Bytes with a length specified by the SecurityPolicy.|
The formula to calculate the amount of padding depends on the amount of data that needs to be sent (called BytesToWrite). The sender shall first calculate the maximum amount of space available in the MessageChunk (called MaxBodySize) using the following formula:
MaxBodySize = PlainTextBlockSize * Floor ((MessageChunkSize – MessageHeaderSize - SecurityHeaderSize – SignatureSize - 1)/CipherTextBlockSize) – SequenceHeaderSize;
The MessageHeaderSize is 12 bytes and the SecurityHeader size depends on whether symmetric or asymmetric cryptography is used. The SequenceHeaderSize is always 8 bytes.
During encryption a block with a size equal to PlainTextBlockSize is processed to produce a block with size equal to CipherTextBlockSize. These values depend on the encryption algorithm and may be the same.
The OPC UA Message can fit into a single chunk if BytesToWrite is less than or equal to the MaxBodySize. In this case the PaddingSize is calculated with this formula:
PaddingSize = PlainTextBlockSize – ((BytesToWrite + SignatureSize + 1) % PlainTextBlockSize);
If the BytesToWrite is greater than MaxBodySize the sender shall write MaxBodySize bytes with a PaddingSize of 0. The remaining BytesToWrite – MaxBodySize bytes shall be sent in subsequent MessageChunks.
The PaddingSize and Padding fields are not present if the MessageChunk is not encrypted.
The Signature field is not present if the MessageChunk is not signed.
Each MessageChunk when using SecurityPolicies with an Authenticated Encryption algorithms have a footer with the fields defined in Table 55.
Table 55 – Message Footer for Authenticated Encryption Algorithms
|Signature||OctetString||The signature for the MessageChunk. The signature includes the headers and all Message data.The signature is encoded as sequence of Bytes with a length specified by the SecurityPolicy.|