std::streamsize CryptoStreamBuf::xsgetn()

in sdk/src/encryption/CryptoStreamBuf.cc [57:126]


std::streamsize CryptoStreamBuf::xsgetn(char * _Ptr, std::streamsize _Count)
{
    const std::streamsize startCount = _Count;
    std::streamsize readCnt;
    unsigned char block[BLK_SIZE];

    //update iv base the pos
    if (!initEncrypt) {
        auto currPos = StreamBufProxy::seekoff(std::streamoff(0), std::ios_base::cur, std::ios_base::in);
        currPos -= StartPosForIV_;
        auto blkOff = currPos / BLK_SIZE;
        auto blkIdx = currPos % BLK_SIZE;
        auto iv = SymmetricCipher::IncCTRCounter(iv_, blkOff);
        cipher_->EncryptInit(key_, iv);
        encBufferCnt_ = 0;
        encBufferOff_ = 0;
        if (blkIdx > 0) {
            StreamBufProxy::seekpos(blkOff * BLK_SIZE, std::ios_base::in);
            readCnt = StreamBufProxy::xsgetn(reinterpret_cast<char *>(block), BLK_SIZE);
            auto ret = cipher_->Encrypt(encBuffer_, static_cast<int>(readCnt), block, static_cast<int>(readCnt));
            if (ret < 0) {
                return -1;
            }
            encBufferCnt_ = ret - blkIdx;
            encBufferOff_ = blkIdx;
        }
        initEncrypt = true;
    }

    //read from inner encBuffer_ first
    readCnt = read_from_encrypted_buffer(_Ptr, _Count);
    if (readCnt > 0) {
        _Count -= readCnt;
        _Ptr += readCnt;
    }

    //read from streambuf by BLK_SIZE
    while (_Count > 0) {
        readCnt = StreamBufProxy::xsgetn(reinterpret_cast<char *>(block), BLK_SIZE);
        if (readCnt <= 0)
            break;

        if (_Count < readCnt) {
            auto ret = cipher_->Encrypt(encBuffer_, static_cast<int>(readCnt), block, static_cast<int>(readCnt));
            if (ret < 0) {
                return -1;
            }
            encBufferCnt_ = ret;
            encBufferOff_ = 0;
            break;
        }
        else {
            auto ret = cipher_->Encrypt(reinterpret_cast<unsigned char *>(_Ptr), static_cast<int>(readCnt), block, static_cast<int>(readCnt));
            if (ret < 0) {
                return -1;
            }
            _Count -= ret;
            _Ptr += ret;
        }
    }

    //read from inner encBuffer_ again
    readCnt = read_from_encrypted_buffer(_Ptr, _Count);
    if (readCnt > 0) {
        _Count -= readCnt;
        _Ptr += readCnt;
    }

    return startCount - _Count;
}