Topic: Fragmentation of CertificateVerify messages
Hi everyone,
I am using custom signature algorithms for TLS 1.3 authentication.
The sizes of the signatures are huge, so the CertificateVerify message is bigger than the max. size allowed by standard (i.e. MAX_RECORD_SIZE = 16384 and MAX_PLAINTEXT_SZ = (1 << 14)), so the extra fragmentation of CertificateVerify message has to be added.
I am trying to implement the fragmentation, but my code does not work correctly and I am not sure how to fix it. I tried to reuse the fragmentation code from the SendTls13Certificate() function as much as possible. For now, the first fragment seems to be correct, but the second fragment contains some garbage value (partially from the previous fragment of the Server Certificate message).
static int SendTls13CertificateVerify(WOLFSSL* ssl)
{
/*
...
*/
switch(ssl->options.asyncState)
{
/*
...
*/
case TLS_ASYNC_FINALIZE:
{
/* Put the record and handshake headers on. */
word32 length = args->length + HASH_SIG_SIZE + VERIFY_HEADER;
word32 payloadSz = length;
word32 maxFragment = wolfSSL_GetMaxRecordSize(ssl, MAX_RECORD_SIZE);
while (length > 0 && ret == 0) {
word32 fragSz = 0;
args->sendSz = RECORD_HEADER_SZ;
if (ssl->fragOffset == 0) {
if (length <= maxFragment - HANDSHAKE_HEADER_SZ) {
fragSz = length;
}
else
fragSz = maxFragment - HANDSHAKE_HEADER_SZ;
args->sendSz += fragSz + HANDSHAKE_HEADER_SZ;
}
else {
fragSz = min(length, maxFragment);
args->sendSz += fragSz;
}
args->sendSz += MAX_MSG_EXTRA;
/* Check buffers are big enough and grow if needed. */
if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0)
return ret;
/* Get position in output buffer to write new message to. */
args->output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
if (ssl->fragOffset == 0) {
AddTls13RecordHeader(args->output, fragSz + HANDSHAKE_HEADER_SZ, handshake, ssl);
AddTls13HandShakeHeader(args->output + RECORD_HEADER_SZ, payloadSz, 0, fragSz, certificate_verify, ssl);
args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ +
fragSz;
}
else
AddTls13RecordHeader(args->output, fragSz, handshake, ssl);
ssl->fragOffset += fragSz;
length -= fragSz;
/* This message is always encrypted. */
args->sendSz = BuildTls13Message(ssl, args->output,
MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA,
args->output + RECORD_HEADER_SZ,
args->sendSz - RECORD_HEADER_SZ, handshake, 1, 0, 0);
if (args->sendSz < 0)
return args->sendSz;
ssl->buffers.outputBuffer.length += args->sendSz;
if (!ssl->options.groupMessages)
ret = SendBuffered(ssl);
}
/* Advance state and proceed */
ssl->options.asyncState = TLS_ASYNC_END;
} /* case TLS_ASYNC_FINALIZE */
FALL_THROUGH;
case TLS_ASYNC_END:
{
/* Clean up the fragment offset */
ssl->fragOffset = 0;
if (ret < 0) {
goto exit_scv;
}
else {
args->sendSz = ret;
ret = 0;
}
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn)
AddPacketName(ssl, "CertificateVerify");
if (ssl->toInfoOn) {
AddPacketInfo(ssl, "CertificateVerify", handshake,
args->output, args->sendSz, WRITE_PROTO, ssl->heap);
}
#endif
ssl->buffers.outputBuffer.length += args->sendSz;
if (!ssl->options.groupMessages)
ret = SendBuffered(ssl);
break;
}
default:
ret = INPUT_CASE_ERROR;
} /* switch(ssl->options.asyncState) */
exit_scv:
WOLFSSL_LEAVE("SendTls13CertificateVerify", ret);
WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND);
#ifdef WOLFSSL_ASYNC_CRYPT
/* Handle async operation */
if (ret == WC_PENDING_E) {
return ret;
}
#endif /* WOLFSSL_ASYNC_CRYPT */
/* Final cleanup */
FreeScv13Args(ssl, args);
FreeKeyExchange(ssl);
return ret;
}
Please give me some clues how to fix this. Thanks in advance!
Regards,
Yulia