⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sslrec.c

📁 Netscape公司提供的安全套接字层
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 + -