Crypt-MatrixSSL
view release on metacpan or search on metacpan
matrixssl-1-8-6-open/src/sslDecode.c view on Meta::CPAN
of whether or not we've already set macError to stop timing attacks.
Clear the mac in the callers buffer if we're successful
*/
if (ssl->verifyMac(ssl, ssl->rec.type, out->end,
(int32)(mac - out->end), mac) < 0 || macError) {
ssl->err = SSL_ALERT_BAD_RECORD_MAC;
matrixStrDebugMsg("Couldn't verify MAC or pad of record data\n",
NULL);
goto encodeResponse;
}
memset(mac, 0x0, ssl->deMacSize);
/*
Record data starts at out->end and ends at mac
*/
p = out->end;
pend = mac;
} else {
/*
The record data is the entire record as there is no MAC or padding
*/
p = out->end;
pend = mac = out->end + ssl->rec.len;
}
/*
Check now for maximum plaintext length of 16kb. No appropriate
SSL alert for this
*/
if ((int32)(pend - p) > SSL_MAX_PLAINTEXT_LEN) {
ssl->err = SSL_ALERT_BAD_RECORD_MAC;
matrixStrDebugMsg("Record overflow\n", NULL);
goto encodeResponse;
}
/*
Take action based on the actual record type we're dealing with
'p' points to the start of the data, and 'pend' points to the end
*/
switch (ssl->rec.type) {
case SSL_RECORD_TYPE_CHANGE_CIPHER_SPEC:
/*
Body is single byte with value 1 to indicate that the next message
will be encrypted using the negotiated cipher suite
*/
if (pend - p < 1) {
ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
matrixStrDebugMsg("Invalid length for CipherSpec\n", NULL);
goto encodeResponse;
}
if (*p == 1) {
p++;
} else {
ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
matrixStrDebugMsg("Invalid value for CipherSpec\n", NULL);
goto encodeResponse;
}
/*
If we're expecting finished, then this is the right place to get
this record. It is really part of the handshake but it has its
own record type.
Activate the read cipher callbacks, so we will decrypt incoming
data from now on.
*/
if (ssl->hsState == SSL_HS_FINISHED) {
sslActivateReadCipher(ssl);
} else {
ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE;
matrixIntDebugMsg("Invalid CipherSpec order: %d\n", ssl->hsState);
goto encodeResponse;
}
in->start = c;
goto decodeMore;
case SSL_RECORD_TYPE_ALERT:
/*
1 byte alert level (warning or fatal)
1 byte alert description corresponding to SSL_ALERT_*
*/
if (pend - p < 2) {
ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
matrixStrDebugMsg("Error in length of alert record\n", NULL);
goto encodeResponse;
}
*alertLevel = *p; p++;
*alertDescription = *p; p++;
/*
If the alert is fatal, or is a close message (usually a warning),
flag the session with ERROR so it cannot be used anymore.
Caller can decide whether or not to close on other warnings.
*/
if (*alertLevel == SSL_ALERT_LEVEL_FATAL) {
ssl->flags |= SSL_FLAGS_ERROR;
}
if (*alertDescription == SSL_ALERT_CLOSE_NOTIFY) {
ssl->flags |= SSL_FLAGS_CLOSED;
}
return SSL_ALERT;
case SSL_RECORD_TYPE_HANDSHAKE:
/*
We've got one or more handshake messages in the record data.
The handshake parsing function will take care of all messages
and return an error if there is any problem.
If there is a response to be sent (either a return handshake
or an error alert, send it). If the message was parsed, but no
response is needed, loop up and try to parse another message
*/
rc = parseSSLHandshake(ssl, (char*)p, (int32)(pend - p));
switch (rc) {
case SSL_SUCCESS:
in->start = c;
return SSL_SUCCESS;
case SSL_PROCESS_DATA:
in->start = c;
goto encodeResponse;
case SSL_ERROR:
if (ssl->err == SSL_ALERT_NONE) {
ssl->err = SSL_ALERT_HANDSHAKE_FAILURE;
}
goto encodeResponse;
}
( run in 1.009 second using v1.01-cache-2.11-cpan-39bf76dae61 )