public int DoFinal(byte[] outBytes, int outOff) { if (null == outBytes) { throw new ArgumentNullException(nameof(outBytes)); } if (outOff < 0) { throw new ArgumentException("cannot be negative", nameof(outOff)); } CheckData(); Array.Clear(mMac, 0, MacSize); int resultLen; switch (mState) { case State.DecData: { if (mBufPos < MacSize) { throw new InvalidCipherTextException("data too short"); } resultLen = mBufPos - MacSize; Check.OutputLength(outBytes, outOff, resultLen, "output buffer too short"); if (resultLen > 0) { mPoly1305.BlockUpdate(mBuf, 0, resultLen); ProcessData(mBuf, 0, resultLen, outBytes, outOff); } FinishData(State.DecFinal); if (!Arrays.ConstantTimeAreEqual(MacSize, mMac, 0, mBuf, resultLen)) { throw new InvalidCipherTextException("mac check in ChaCha20Poly1305 failed"); } break; } case State.EncData: { resultLen = mBufPos + MacSize; Check.OutputLength(outBytes, outOff, resultLen, "output buffer too short"); if (mBufPos > 0) { ProcessData(mBuf, 0, mBufPos, outBytes, outOff); mPoly1305.BlockUpdate(outBytes, outOff, mBufPos); } FinishData(State.EncFinal); Array.Copy(mMac, 0, outBytes, outOff + mBufPos, MacSize); break; } default: throw new InvalidOperationException(); } Reset(false, true); return(resultLen); }
public int ProcessBytes(byte[] inBytes, int inOff, int len, byte[] outBytes, int outOff) { if (null == inBytes) { throw new ArgumentNullException(nameof(inBytes)); } if (null == outBytes) { throw new ArgumentNullException(nameof(outBytes)); } if (inOff < 0) { throw new ArgumentException("cannot be negative", nameof(inOff)); } if (len < 0) { throw new ArgumentException("cannot be negative", nameof(len)); } Check.DataLength(inBytes, inOff, len, "input buffer too short"); if (outOff < 0) { throw new ArgumentException("cannot be negative", nameof(outOff)); } CheckData(); var resultLen = 0; switch (mState) { case State.DecData: { for (var i = 0; i < len; ++i) { mBuf[mBufPos] = inBytes[inOff + i]; if (++mBufPos == mBuf.Length) { mPoly1305.BlockUpdate(mBuf, 0, BufSize); ProcessData(mBuf, 0, BufSize, outBytes, outOff + resultLen); Array.Copy(mBuf, BufSize, mBuf, 0, MacSize); mBufPos = MacSize; resultLen += BufSize; } } break; } case State.EncData: { if (mBufPos != 0) { while (len > 0) { --len; mBuf[mBufPos] = inBytes[inOff++]; if (++mBufPos == BufSize) { ProcessData(mBuf, 0, BufSize, outBytes, outOff); mPoly1305.BlockUpdate(outBytes, outOff, BufSize); mBufPos = 0; resultLen = BufSize; break; } } } while (len >= BufSize) { ProcessData(inBytes, inOff, BufSize, outBytes, outOff + resultLen); mPoly1305.BlockUpdate(outBytes, outOff + resultLen, BufSize); inOff += BufSize; len -= BufSize; resultLen += BufSize; } if (len > 0) { Array.Copy(inBytes, inOff, mBuf, 0, len); mBufPos = len; } break; } default: throw new InvalidOperationException(); } return(resultLen); }