github.com/mad-day/Yawning-crypto@v0.0.0-20190711051033-5a5f8cca32ec/bsaes/internal/modes/ctr.go (about) 1 // Copyright (c) 2017 Yawning Angel <yawning at schwanenlied dot me> 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining 4 // a copy of this software and associated documentation files (the 5 // "Software"), to deal in the Software without restriction, including 6 // without limitation the rights to use, copy, modify, merge, publish, 7 // distribute, sublicense, and/or sell copies of the Software, and to 8 // permit persons to whom the Software is furnished to do so, subject to 9 // the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be 12 // included in all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 18 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 // SOFTWARE. 22 23 package modes 24 25 import ( 26 "crypto/cipher" 27 "runtime" 28 ) 29 30 func (m *BlockModesImpl) NewCTR(iv []byte) cipher.Stream { 31 ecb := m.b.(bulkECBAble) 32 if len(iv) != ecb.BlockSize() { 33 panic("bsaes/NewCTR: iv size does not match block size") 34 } 35 36 return newCTRImpl(ecb, iv) 37 } 38 39 type ctrImpl struct { 40 ecb bulkECBAble 41 ctr [blockSize]byte 42 buf []byte 43 idx int 44 45 stride int 46 } 47 48 func (c *ctrImpl) Reset() { 49 for i := range c.buf { 50 c.buf[i] = 0 51 } 52 } 53 54 func (c *ctrImpl) XORKeyStream(dst, src []byte) { 55 for len(src) > 0 { 56 if c.idx >= len(c.buf) { 57 c.generateKeyStream() 58 c.idx = 0 59 } 60 61 n := len(c.buf) - c.idx 62 if sLen := len(src); sLen < n { 63 n = sLen 64 } 65 for i, v := range src[:n] { 66 dst[i] = v ^ c.buf[c.idx+i] 67 } 68 69 dst, src = dst[n:], src[n:] 70 c.idx += n 71 } 72 } 73 74 func (c *ctrImpl) generateKeyStream() { 75 for i := 0; i < c.stride; i++ { 76 copy(c.buf[i*blockSize:], c.ctr[:]) 77 78 // Increment counter. 79 for j := blockSize; j > 0; j-- { 80 c.ctr[j-1]++ 81 if c.ctr[j-1] != 0 { 82 break 83 } 84 } 85 } 86 c.ecb.BulkEncrypt(c.buf, c.buf) 87 } 88 89 func newCTRImpl(ecb bulkECBAble, iv []byte) cipher.Stream { 90 c := new(ctrImpl) 91 c.ecb = ecb 92 c.stride = ecb.Stride() 93 copy(c.ctr[:], iv) 94 c.buf = make([]byte, c.stride*blockSize) 95 c.idx = len(c.buf) 96 97 runtime.SetFinalizer(c, (*ctrImpl).Reset) 98 99 return c 100 }