// Copyright 2024 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package cryptotestimport ()// MakeBlockMode returns a cipher.BlockMode instance.// It expects len(iv) == b.BlockSize().typeMakeBlockModefunc(b cipher.Block, iv []byte) cipher.BlockMode// TestBlockMode performs a set of tests on cipher.BlockMode implementations,// checking the documented requirements of CryptBlocks.func ( *testing.T, cipher.Block, , MakeBlockMode) { := newRandReader() := make([]byte, .BlockSize()) .Read()testBlockModePair(, , , , )}func testBlockModePair( *testing.T, cipher.Block, , MakeBlockMode, []byte) { .Run("Encryption", func( *testing.T) {testBlockMode(, , , ) }) .Run("Decryption", func( *testing.T) {testBlockMode(, , , ) }) .Run("Roundtrip", func( *testing.T) { := newRandReader() := (, ).BlockSize()if := (, ).BlockSize(); != { .Errorf("decryption blocksize different than encryption's; got %d, want %d", , ) } , , := make([]byte, *2), make([]byte, *2), make([]byte, *2) .Read() (, ).CryptBlocks(, ) (, ).CryptBlocks(, )if !bytes.Equal(, ) { .Errorf("plaintext is different after an encrypt/decrypt cycle; got %x, want %x", , ) } })}func testBlockMode( *testing.T, MakeBlockMode, cipher.Block, []byte) { := (, ).BlockSize() .Run("WrongIVLen", func( *testing.T) { := make([]byte, .BlockSize()+1)mustPanic(, "IV length must equal block size", func() { (, ) }) }) .Run("EmptyInput", func( *testing.T) { := newRandReader() , := make([]byte, ), make([]byte, ) .Read() := bytes.Clone() (, ).CryptBlocks(, [:0])if !bytes.Equal(, ) { .Errorf("CryptBlocks modified dst on empty input; got %x, want %x", , ) } }) .Run("AlterInput", func( *testing.T) { := newRandReader() , , := make([]byte, *2), make([]byte, *2), make([]byte, *2)for , := range []int{0, , * 2} { .Read()copy(, ) (, ).CryptBlocks([:], [:])if !bytes.Equal(, ) { .Errorf("CryptBlocks modified src; got %x, want %x", , ) } } }) .Run("Aliasing", func( *testing.T) { := newRandReader() , := make([]byte, *2), make([]byte, *2)for , := range []int{0, , * 2} {// Record what output is when src and dst are different .Read() (, ).CryptBlocks([:], [:])// Check that the same output is generated when src=dst alias to the same // memory (, ).CryptBlocks([:], [:])if !bytes.Equal([:], [:]) { .Errorf("block cipher produced different output when dst = src; got %x, want %x", [:], [:]) } } }) .Run("OutOfBoundsWrite", func( *testing.T) { // Issue 21104 := newRandReader() := make([]byte, ) .Read()// Make a buffer with dst in the middle and data on either end := make([]byte, *3) , := , *2 .Read([:]) .Read([:]) := [:]// Record the prefix and suffix data to make sure they aren't written to , := make([]byte, ), make([]byte, )copy(, [:])copy(, [:])// Write to dst (the middle of the buffer) and make sure it doesn't write // beyond the dst slice on a valid CryptBlocks call (, ).CryptBlocks(, )if !bytes.Equal([:], ) { .Errorf("block cipher did out of bounds write after end of dst slice; got %x, want %x", [:], ) }if !bytes.Equal([:], ) { .Errorf("block cipher did out of bounds write before beginning of dst slice; got %x, want %x", [:], ) }// Check that dst isn't written to beyond len(src) even if there is room in // the slice = [:] // Extend dst to include suffix (, ).CryptBlocks(, )if !bytes.Equal([:], ) { .Errorf("CryptBlocks modified dst past len(src); got %x, want %x", [:], ) }// Issue 21104: Shouldn't write to anything outside of dst even if src is bigger = make([]byte, *3) .Read()mustPanic(, "output smaller than input", func() { (, ).CryptBlocks(, ) })if !bytes.Equal([:], ) { .Errorf("block cipher did out of bounds write after end of dst slice; got %x, want %x", [:], ) }if !bytes.Equal([:], ) { .Errorf("block cipher did out of bounds write before beginning of dst slice; got %x, want %x", [:], ) } })// Check that output of cipher isn't affected by adjacent data beyond input // slice scope .Run("OutOfBoundsRead", func( *testing.T) { := newRandReader() := make([]byte, ) .Read() := make([]byte, ) (, ).CryptBlocks(, )// Make a buffer with src in the middle and data on either end := make([]byte, *3) , := , *2copy([:], ) .Read([:]) .Read([:]) := make([]byte, ) (, ).CryptBlocks(, [:])if !bytes.Equal(, ) { .Errorf("CryptBlocks affected by data outside of src slice bounds; got %x, want %x", , ) } }) .Run("BufferOverlap", func( *testing.T) { := newRandReader() := make([]byte, *2) .Read()// Make src and dst slices point to same array with inexact overlap := [:] := [1 : +1]mustPanic(, "invalid buffer overlap", func() { (, ).CryptBlocks(, ) })// Only overlap on one byte = [:] = [-1 : 2*-1]mustPanic(, "invalid buffer overlap", func() { (, ).CryptBlocks(, ) })// src comes after dst with one byte overlap = [-1 : 2*-1] = [:]mustPanic(, "invalid buffer overlap", func() { (, ).CryptBlocks(, ) }) })// Input to CryptBlocks should be a multiple of BlockSize .Run("PartialBlocks", func( *testing.T) {// Check a few cases of not being a multiple of BlockSizefor , := range []int{ - 1, + 1, 2* - 1, 2* + 1} { := make([]byte, ) := make([]byte, 3*) // Make a dst large enough for all srcmustPanic(, "input not full blocks", func() { (, ).CryptBlocks(, ) }) } }) .Run("KeepState", func( *testing.T) { := newRandReader() , , := make([]byte, *4), make([]byte, *4), make([]byte, *4) .Read() , := 2*, (, ) .CryptBlocks(, [:]) .CryptBlocks([:], [:]) (, ).CryptBlocks(, )if !bytes.Equal(, ) { .Errorf("two successive CryptBlocks calls returned a different result than a single one; got %x, want %x", , ) } })}
The pages are generated with Goldsv0.7.3. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.