Source file src/crypto/cipher/modes_test.go

     1  // Copyright 2024 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package cipher_test
     6  
     7  import (
     8  	. "crypto/cipher"
     9  	"reflect"
    10  	"testing"
    11  )
    12  
    13  // Historically, crypto/aes's Block would implement some undocumented
    14  // methods for crypto/cipher to use from NewCTR, NewCBCEncrypter, etc.
    15  // This is no longer the case, but for now test that the mechanism is
    16  // still working until we explicitly decide to remove it.
    17  
    18  type block struct {
    19  	Block
    20  }
    21  
    22  func (block) BlockSize() int {
    23  	return 16
    24  }
    25  
    26  type specialCTR struct {
    27  	Stream
    28  }
    29  
    30  func (block) NewCTR(iv []byte) Stream {
    31  	return specialCTR{}
    32  }
    33  
    34  func TestCTRAble(t *testing.T) {
    35  	b := block{}
    36  	s := NewCTR(b, make([]byte, 16))
    37  	if _, ok := s.(specialCTR); !ok {
    38  		t.Errorf("NewCTR did not return specialCTR")
    39  	}
    40  }
    41  
    42  type specialCBC struct {
    43  	BlockMode
    44  }
    45  
    46  func (block) NewCBCEncrypter(iv []byte) BlockMode {
    47  	return specialCBC{}
    48  }
    49  
    50  func (block) NewCBCDecrypter(iv []byte) BlockMode {
    51  	return specialCBC{}
    52  }
    53  
    54  func TestCBCAble(t *testing.T) {
    55  	b := block{}
    56  	s := NewCBCEncrypter(b, make([]byte, 16))
    57  	if _, ok := s.(specialCBC); !ok {
    58  		t.Errorf("NewCBCEncrypter did not return specialCBC")
    59  	}
    60  	s = NewCBCDecrypter(b, make([]byte, 16))
    61  	if _, ok := s.(specialCBC); !ok {
    62  		t.Errorf("NewCBCDecrypter did not return specialCBC")
    63  	}
    64  }
    65  
    66  type specialGCM struct {
    67  	AEAD
    68  }
    69  
    70  func (block) NewGCM(nonceSize, tagSize int) (AEAD, error) {
    71  	return specialGCM{}, nil
    72  }
    73  
    74  func TestGCM(t *testing.T) {
    75  	b := block{}
    76  	s, err := NewGCM(b)
    77  	if err != nil {
    78  		t.Errorf("NewGCM failed: %v", err)
    79  	}
    80  	if _, ok := s.(specialGCM); !ok {
    81  		t.Errorf("NewGCM did not return specialGCM")
    82  	}
    83  }
    84  
    85  // TestNoExtraMethods makes sure we don't accidentally expose methods on the
    86  // underlying implementations of modes.
    87  func TestNoExtraMethods(t *testing.T) {
    88  	testAllImplementations(t, testNoExtraMethods)
    89  }
    90  
    91  func testNoExtraMethods(t *testing.T, newBlock func([]byte) Block) {
    92  	b := newBlock(make([]byte, 16))
    93  
    94  	ctr := NewCTR(b, make([]byte, 16))
    95  	ctrExpected := []string{"XORKeyStream"}
    96  	if got := exportedMethods(ctr); !reflect.DeepEqual(got, ctrExpected) {
    97  		t.Errorf("CTR: got %v, want %v", got, ctrExpected)
    98  	}
    99  
   100  	cbc := NewCBCEncrypter(b, make([]byte, 16))
   101  	cbcExpected := []string{"BlockSize", "CryptBlocks", "SetIV"}
   102  	if got := exportedMethods(cbc); !reflect.DeepEqual(got, cbcExpected) {
   103  		t.Errorf("CBC: got %v, want %v", got, cbcExpected)
   104  	}
   105  	cbc = NewCBCDecrypter(b, make([]byte, 16))
   106  	if got := exportedMethods(cbc); !reflect.DeepEqual(got, cbcExpected) {
   107  		t.Errorf("CBC: got %v, want %v", got, cbcExpected)
   108  	}
   109  
   110  	gcm, _ := NewGCM(b)
   111  	gcmExpected := []string{"NonceSize", "Open", "Overhead", "Seal"}
   112  	if got := exportedMethods(gcm); !reflect.DeepEqual(got, gcmExpected) {
   113  		t.Errorf("GCM: got %v, want %v", got, gcmExpected)
   114  	}
   115  }
   116  
   117  func exportedMethods(x any) []string {
   118  	var methods []string
   119  	v := reflect.ValueOf(x)
   120  	for i := 0; i < v.NumMethod(); i++ {
   121  		if v.Type().Method(i).IsExported() {
   122  			methods = append(methods, v.Type().Method(i).Name)
   123  		}
   124  	}
   125  	return methods
   126  }
   127  

View as plain text