📄 sslrec.c
字号:
if ((err = SSLAllocBuffer(&buf, sizeof(WaitingRecord), &ctx->sysCtx)) != 0)
return ERR(err);
out = (WaitingRecord*)buf.data;
out->next = 0;
out->sent = 0;
/* Allocate enough room for the transmitted record, which will be:
* 5 bytes of header +
* encrypted contents +
* macLength +
* padding [block ciphers only] +
* padding length field (1 byte) [block ciphers only]
*/
payloadSize = (uint16) (rec.contents.length + ctx->writeCipher.hash->digestSize);
blockSize = ctx->writeCipher.symCipher->blockSize;
if (blockSize > 0)
{ padding = blockSize - (payloadSize % blockSize) - 1;
payloadSize += padding + 1;
}
out->data.data = 0;
if ((err = SSLAllocBuffer(&out->data, 5 + payloadSize, &ctx->sysCtx)) != 0)
goto fail;
progress = out->data.data;
*(progress++) = rec.contentType;
progress = SSLEncodeInt(progress, rec.protocolVersion, 2);
progress = SSLEncodeInt(progress, payloadSize, 2);
/* Copy the contents into the output buffer */
memcpy(progress, rec.contents.data, rec.contents.length);
payload.data = progress;
payload.length = rec.contents.length;
progress += rec.contents.length;
/* MAC immediately follows data */
mac.data = progress;
mac.length = ctx->writeCipher.hash->digestSize;
progress += mac.length;
/* MAC the data */
if (mac.length > 0) /* Optimize away null case */
{ secret.data = ctx->writeCipher.macSecret;
secret.length = ctx->writeCipher.hash->digestSize;
if ((err = ComputeMAC(rec.contentType, payload, mac, ctx->writeCipher.sequenceNum, secret, ctx->writeCipher.hash, ctx)) != 0)
goto fail;
}
/* Update payload to reflect encrypted data: contents, mac & padding */
payload.length = payloadSize;
/* Fill in the padding bytes & padding length field with the padding value; the
* protocol only requires the last byte,
* but filling them all in avoids leaking data
*/
if (ctx->writeCipher.symCipher->blockSize > 0)
for (i = 1; i <= padding + 1; ++i)
payload.data[payload.length - i] = padding;
/* Encrypt the data */
DUMP_BUFFER_NAME("cleartext data", payload);
if ((err = ctx->writeCipher.symCipher->encrypt(payload, payload, ctx->writeCipher.symCipherState, ctx)) != 0)
goto fail;
DUMP_BUFFER_NAME("encrypted data", payload);
/* Enqueue the record to be written from the idle loop */
if (ctx->recordWriteQueue == 0)
ctx->recordWriteQueue = out;
else
{ queue = ctx->recordWriteQueue;
while (queue->next != 0)
queue = queue->next;
queue->next = out;
}
/* Increment the sequence number */
IncrementUInt64(&ctx->writeCipher.sequenceNum);
return SSLNoErr;
fail: /* Only for if we fail between when the WaitingRecord is allocated and when it is queued */
SSLFreeBuffer(&out->data, &ctx->sysCtx);
buf.data = (uint8*)out;
buf.length = sizeof(WaitingRecord);
SSLFreeBuffer(&buf, &ctx->sysCtx);
return ERR(err);
}
static SSLErr
DecryptSSLRecord(uint8 type, SSLBuffer *payload, SSLContext *ctx)
{ SSLErr err;
SSLBuffer content;
if ((ctx->readCipher.symCipher->blockSize > 0) &&
((payload->length % ctx->readCipher.symCipher->blockSize) != 0))
{ SSLFatalSessionAlert(alert_unexpected_message, ctx);
return ERR(SSLProtocolErr);
}
/* Decrypt in place */
DUMP_BUFFER_NAME("encrypted data", (*payload));
if ((err = ctx->readCipher.symCipher->decrypt(*payload, *payload, ctx->readCipher.symCipherState, ctx)) != 0)
{ SSLFatalSessionAlert(alert_close_notify, ctx);
return ERR(err);
}
DUMP_BUFFER_NAME("decrypted data", (*payload));
/* Locate content within decrypted payload */
content.data = payload->data;
content.length = payload->length - ctx->readCipher.hash->digestSize;
if (ctx->readCipher.symCipher->blockSize > 0)
{ /* padding can't be equal to or more than a block */
if (payload->data[payload->length - 1] >= ctx->readCipher.symCipher->blockSize)
{ SSLFatalSessionAlert(alert_unexpected_message, ctx);
return ERR(SSLProtocolErr);
}
content.length -= 1 + payload->data[payload->length - 1]; /* Remove block size padding */
}
/* Verify MAC on payload */
if (ctx->readCipher.hash->digestSize > 0) /* Optimize away MAC for null case */
if ((err = VerifyMAC(type, content, payload->data + content.length, ctx)) != 0)
{ SSLFatalSessionAlert(alert_bad_record_mac, ctx);
return ERR(err);
}
*payload = content; /* Modify payload buffer to indicate content length */
return SSLNoErr;
}
static uint8*
SSLEncodeUInt64(uint8 *p, uint64 value)
{ p = SSLEncodeInt(p, value.high, 4);
return SSLEncodeInt(p, value.low, 4);
}
static SSLErr
VerifyMAC(uint8 type, SSLBuffer data, uint8 *compareMAC, SSLContext *ctx)
{ SSLErr err;
uint8 macData[MAX_DIGEST_SIZE];
SSLBuffer secret, mac;
secret.data = ctx->readCipher.macSecret;
secret.length = ctx->readCipher.hash->digestSize;
mac.data = macData;
mac.length = ctx->readCipher.hash->digestSize;
if ((err = ComputeMAC(type, data, mac, ctx->readCipher.sequenceNum, secret, ctx->readCipher.hash, ctx)) != 0)
return ERR(err);
if ((memcmp(mac.data, compareMAC, mac.length)) != 0)
return ERR(SSLProtocolErr);
return SSLNoErr;
}
static SSLErr
ComputeMAC(uint8 type, SSLBuffer data, SSLBuffer mac, uint64 seqNo, SSLBuffer secret,
HashReference *macHash, SSLContext *ctx)
{ SSLErr err;
uint8 innerDigestData[MAX_DIGEST_SIZE];
uint8 scratchData[11], *progress;
SSLBuffer digest,digestCtx,scratch;
ASSERT(macHash->macPadSize <= MAX_MAC_PADDING);
ASSERT(macHash->digestSize <= MAX_DIGEST_SIZE);
ASSERT(SSLMACPad1[0] == 0x36 && SSLMACPad2[0] == 0x5C);
digestCtx.data = 0;
if ((err = SSLAllocBuffer(&digestCtx, macHash->contextSize, &ctx->sysCtx)) != 0)
goto exit;
/* MAC = hash( MAC_write_secret + pad_2 + hash( MAC_write_secret + pad_1 + seq_num + type + length + content ) ) */
if ((err = macHash->init(digestCtx)) != 0)
goto exit;
if ((err = macHash->update(digestCtx, secret)) != 0) /* MAC secret */
goto exit;
scratch.data = SSLMACPad1;
scratch.length = macHash->macPadSize;
if ((err = macHash->update(digestCtx, scratch)) != 0) /* pad1 */
goto exit;
progress = scratchData;
progress = SSLEncodeUInt64(progress, seqNo);
*progress++ = type;
progress = SSLEncodeInt(progress, data.length, 2);
scratch.data = scratchData;
scratch.length = 11;
ASSERT(progress = scratchData+11);
if ((err = macHash->update(digestCtx, scratch)) != 0) /* sequenceNo, type & length */
goto exit;
if ((err = macHash->update(digestCtx, data)) != 0) /* content */
goto exit;
digest.data = innerDigestData;
digest.length = macHash->digestSize;
if ((err = macHash->final(digestCtx, digest)) != 0) /* figure inner digest */
goto exit;
if ((err = macHash->init(digestCtx)) != 0)
goto exit;
if ((err = macHash->update(digestCtx, secret)) != 0) /* MAC secret */
goto exit;
scratch.data = SSLMACPad2;
scratch.length = macHash->macPadSize;
if ((err = macHash->update(digestCtx, scratch)) != 0) /* pad2 */
goto exit;
if ((err = macHash->update(digestCtx, digest)) != 0) /* inner digest */
goto exit;
if ((err = macHash->final(digestCtx, mac)) != 0) /* figure the mac */
goto exit;
err = SSLNoErr; /* redundant, I know */
exit:
SSLFreeBuffer(&digestCtx, &ctx->sysCtx);
return ERR(err);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -