github.com/cloudflare/circl@v1.5.0/hpke/aead_test.go (about)

     1  package hpke
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/rand"
     6  	"fmt"
     7  	"testing"
     8  
     9  	"github.com/cloudflare/circl/internal/test"
    10  )
    11  
    12  func TestAeadExporter(t *testing.T) {
    13  	suite := Suite{kdfID: KDF_HKDF_SHA256, aeadID: AEAD_AES128GCM}
    14  	exporter := &encdecContext{suite: suite}
    15  	maxLength := uint(255 * suite.kdfID.ExtractSize())
    16  
    17  	err := test.CheckPanic(func() {
    18  		exporter.Export([]byte("exporter"), maxLength+1)
    19  	})
    20  	test.CheckNoErr(t, err, "exporter max size")
    21  }
    22  
    23  func setupAeadTest() (*sealContext, *openContext, error) {
    24  	suite := Suite{aeadID: AEAD_AES128GCM}
    25  	key := make([]byte, suite.aeadID.KeySize())
    26  	if n, err := rand.Read(key); err != nil {
    27  		return nil, nil, err
    28  	} else if n != len(key) {
    29  		return nil, nil, fmt.Errorf("unexpected key size: got %d; want %d", n, len(key))
    30  	}
    31  
    32  	aead, err := suite.aeadID.New(key)
    33  	if err != nil {
    34  		return nil, nil, err
    35  	}
    36  
    37  	Nn := suite.aeadID.NonceSize()
    38  	baseNonce := make([]byte, Nn)
    39  	if n, err := rand.Read(baseNonce); err != nil {
    40  		return nil, nil, err
    41  	} else if n != len(baseNonce) {
    42  		return nil, nil, fmt.Errorf("unexpected base nonce size: got %d; want %d", n, len(baseNonce))
    43  	}
    44  
    45  	sealer := &sealContext{
    46  		&encdecContext{
    47  			suite, nil, nil, nil, nil, nil, baseNonce, make([]byte, Nn), aead, make([]byte, Nn),
    48  		},
    49  	}
    50  	opener := &openContext{
    51  		&encdecContext{
    52  			suite, nil, nil, nil, nil, nil, baseNonce, make([]byte, Nn), aead, make([]byte, Nn),
    53  		},
    54  	}
    55  	return sealer, opener, nil
    56  }
    57  
    58  func TestAeadNonceUpdate(t *testing.T) {
    59  	sealer, opener, err := setupAeadTest()
    60  	test.CheckNoErr(t, err, "setup failed")
    61  
    62  	pt := []byte("plaintext")
    63  	aad := []byte("aad")
    64  
    65  	numAttempts := 2
    66  	var prevCt []byte
    67  	for i := 0; i < numAttempts; i++ {
    68  		ct, err := sealer.Seal(pt, aad)
    69  		if err != nil {
    70  			t.Fatalf("encryption failed: %s", err)
    71  		}
    72  
    73  		if prevCt != nil && bytes.Equal(ct, prevCt) {
    74  			t.Error("ciphertext matches the previous (nonce not updated)")
    75  		}
    76  
    77  		_, err = opener.Open(ct, aad)
    78  		if err != nil {
    79  			t.Errorf("decryption failed: %s", err)
    80  		}
    81  
    82  		prevCt = ct
    83  	}
    84  }
    85  
    86  func TestOpenPhaseMismatch(t *testing.T) {
    87  	sealer, opener, err := setupAeadTest()
    88  	test.CheckNoErr(t, err, "setup failed")
    89  
    90  	pt := []byte("plaintext")
    91  	aad := []byte("aad")
    92  
    93  	ct, err := sealer.Seal(pt, aad)
    94  	if err != nil {
    95  		t.Fatalf("encryption failed: %s", err)
    96  	}
    97  
    98  	recovered, err := opener.Open(ct, aad)
    99  	if err != nil {
   100  		t.Fatalf("decryption failed: %s", err)
   101  	}
   102  
   103  	if !bytes.Equal(pt, recovered) {
   104  		t.Fatal("Plaintext mismatch")
   105  	}
   106  
   107  	_, err = opener.Open(ct, aad)
   108  	if err == nil {
   109  		t.Fatal("decryption succeeded when it should have failed")
   110  	}
   111  }
   112  
   113  func TestSealPhaseMismatch(t *testing.T) {
   114  	sealer, opener, err := setupAeadTest()
   115  	test.CheckNoErr(t, err, "setup failed")
   116  
   117  	pt := []byte("plaintext")
   118  	aad := []byte("aad")
   119  
   120  	_, err = sealer.Seal(pt, aad)
   121  	if err != nil {
   122  		t.Fatalf("encryption failed: %s", err)
   123  	}
   124  
   125  	ct, err := sealer.Seal(pt, aad)
   126  	if err != nil {
   127  		t.Fatalf("encryption failed: %s", err)
   128  	}
   129  
   130  	_, err = opener.Open(ct, aad)
   131  	if err == nil {
   132  		t.Fatal("decryption succeeded when it should have failed")
   133  	}
   134  }
   135  
   136  func TestAeadSeqOverflow(t *testing.T) {
   137  	sealer, opener, err := setupAeadTest()
   138  	test.CheckNoErr(t, err, "setup failed")
   139  
   140  	Nn := len(sealer.baseNonce)
   141  	pt := []byte("plaintext")
   142  	aad := []byte("aad")
   143  
   144  	// Sets sequence number to 256 before its max value = 0xFF...FF.
   145  	for i := 0; i < Nn; i++ {
   146  		sealer.sequenceNumber[i] = 0xFF
   147  		opener.sequenceNumber[i] = 0xFF
   148  	}
   149  	sealer.sequenceNumber[Nn-1] = 0x00
   150  	opener.sequenceNumber[Nn-1] = 0x00
   151  
   152  	numAttempts := 260
   153  	wantCorrect := 2 * 255
   154  	wantIncorrect := 2*numAttempts - wantCorrect
   155  	gotCorrect := 0
   156  	gotIncorrect := 0
   157  
   158  	for i := 0; i < numAttempts; i++ {
   159  		ct, err := sealer.Seal(pt, aad)
   160  		switch {
   161  		case ct != nil && err == nil:
   162  			gotCorrect++
   163  		case ct == nil && err != nil:
   164  			gotIncorrect++
   165  		default:
   166  			t.FailNow()
   167  		}
   168  
   169  		pt2, err := opener.Open(ct, aad)
   170  		switch {
   171  		case pt2 != nil && err == nil:
   172  			gotCorrect++
   173  		case pt2 == nil && err != nil:
   174  			gotIncorrect++
   175  		default:
   176  			t.FailNow()
   177  		}
   178  	}
   179  
   180  	if gotCorrect != wantCorrect {
   181  		test.ReportError(t, gotCorrect, wantCorrect)
   182  	}
   183  	if gotIncorrect != wantIncorrect {
   184  		test.ReportError(t, gotIncorrect, wantIncorrect)
   185  	}
   186  }