In the Finished Message FOR TLS, verify data is 12 byte long unless it is stated otherwise in the ciphersuite, so in your case it is 12 byte long. It is in the following handshake message form:
struct {
HandshakeType msg_type; /* handshake type */
uint24 length; /* bytes in message */
select (HandshakeType) {
...
case finished: Finished;
} body;
} Handshake;
However, since the question turned out to be DTLS NOT TLS this is modified to
struct {
HandshakeType msg_type;
uint24 length;
uint16 message_seq; // New field
uint24 fragment_offset; // New field
uint24 fragment_length; // New field
select (HandshakeType) {
...
case finished: Finished;
} body;
} Handshake;
Finished message is created using the PRF of the agreed cipher suite. After creating Handshake message you need to convert it to a TLSCipherText structure, in the form of
struct {
ContentType type;
ProtocolVersion version;
uint16 length;
select (SecurityParameters.cipher_type) {
case stream: GenericStreamCipher;
case block: GenericBlockCipher;
case aead: GenericAEADCipher;
} fragment;
} TLSCiphertext;
but again DTLS is different
struct {
ContentType type;
ProtocolVersion version;
uint16 epoch; // New field
uint48 sequence_number; // New field
uint16 length;
select (CipherSpec.cipher_type) {
case block: GenericBlockCipher;
case aead: GenericAEADCipher; // New field [sic]
} fragment;
} DTLSCiphertext;
Here you are using ECDHE_RSA_AES_128_GCM_SHA256 which is an AEAD Cipher, so it is in the form of GenericAEADCipher:
struct {
opaque nonce_explicit[SecurityParameters.record_iv_length];
aead-ciphered struct {
opaque content[TLSCompressed.length];
};
} GenericAEADCipher;
Here, the nonce_explicit contains 8 byte nonce, and you combine this with the 'fixed IV' from key derivation (4 bytes) then you get 12 byte IV for AES-GCM mode encryption. (Note that you only sent the last 8 bytes of the IV).
In this structure, the aead-ciphered
result includes encryption output || authentication tag
.
So you have sent the authentication tag by concatenating it to encrypted message.
In the case for finished message, encryption output and authentication tag are outputs of the encryption of Finished message.
At the end, expected finished message from server side for cipher suite ECDHE_RSA_AES_128_GCM_SHA256 should look like this for TLS:
16 --ContentType(hanshake)
03 03 --protocolVersion(tls 1.2)
00 28 -- message length(40)
--finished message--
00 00 00 00 00 00 00 00 --nonce_explicit. (8 byte) (this is write sequence number, for initial handshake this should be all zero)
xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx -- encrypted finished message. (16 byte) (Note that finished message is of length 16(1 byte finished message type + 3 byte handshake message length + 12 byte verify_data) )
yy yy yy yy yy yy yy yy yy yy yy yy yy yy yy yy -- authentication tag. (16 byte) (this is also output of the encrption of finished message using AES-GCM)
but this for DTLS
16 -- type=handshake
fe fd -- version=DTLS1.2
nn nn -- epoch, 1 for the initial negotiation, more if renegotiation
00 00 00 00 00 00 -- seqnum, always zero because Finished is first after CCS
00 30 -- length=48
(8 bytes) -- explicit nonce
(24 bytes) -- encryption of Finished handshake message
(16 bytes) -- authentication tag
The nonce_explicit MAY be the 64-bit sequence number
. So, i guess it is not forced to use the sequence number as nonce-explicit. So you do not need to worry about the iv part of your message above. Also note that,Each value of the nonce_explicit MUST be distinct for each distinct invocation of the GCM encrypt function for any fixed key. Failure to meet this uniqueness requirement can significantly degrade security.
$\endgroup$HandshakeMessage
is 8 bytes longer; see tools.ietf.org/html/rfc6347#section-4.2.2 . @Makif: even for resumption sequence number starts at zero, which as you note may be used for record-nonce. (But resumption has new working keys due to new hello-nonces used in KDF.) $\endgroup$