Source file src/crypto/hpke/aead.go

     1  // Copyright 2025 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 hpke
     6  
     7  import (
     8  	"crypto/cipher"
     9  	"errors"
    10  	"fmt"
    11  
    12  	"golang.org/x/crypto/chacha20poly1305"
    13  )
    14  
    15  // The AEAD is one of the three components of an HPKE ciphersuite, implementing
    16  // symmetric encryption.
    17  type AEAD interface {
    18  	ID() uint16
    19  	keySize() int
    20  	nonceSize() int
    21  	aead(key []byte) (cipher.AEAD, error)
    22  }
    23  
    24  // NewAEAD returns the AEAD implementation for the given AEAD ID.
    25  //
    26  // Applications are encouraged to use specific implementations like [AES128GCM]
    27  // or [ChaCha20Poly1305] instead, unless runtime agility is required.
    28  func NewAEAD(id uint16) (AEAD, error) {
    29  	switch id {
    30  	case 0x0001: // AES-128-GCM
    31  		return AES128GCM(), nil
    32  	case 0x0002: // AES-256-GCM
    33  		return AES256GCM(), nil
    34  	case 0x0003: // ChaCha20Poly1305
    35  		return ChaCha20Poly1305(), nil
    36  	case 0xFFFF: // Export-only
    37  		return ExportOnly(), nil
    38  	default:
    39  		return nil, fmt.Errorf("unsupported AEAD %04x", id)
    40  	}
    41  }
    42  
    43  // AES128GCM returns an AES-128-GCM AEAD implementation.
    44  func AES128GCM() AEAD { return aes128GCM }
    45  
    46  // AES256GCM returns an AES-256-GCM AEAD implementation.
    47  func AES256GCM() AEAD { return aes256GCM }
    48  
    49  // ChaCha20Poly1305 returns a ChaCha20Poly1305 AEAD implementation.
    50  func ChaCha20Poly1305() AEAD { return chacha20poly1305AEAD }
    51  
    52  // ExportOnly returns a placeholder AEAD implementation that cannot encrypt or
    53  // decrypt, but only export secrets with [Sender.Export] or [Recipient.Export].
    54  //
    55  // When this is used, [Sender.Seal] and [Recipient.Open] return errors.
    56  func ExportOnly() AEAD { return exportOnlyAEAD{} }
    57  
    58  type aead struct {
    59  	nK  int
    60  	nN  int
    61  	new func([]byte) (cipher.AEAD, error)
    62  	id  uint16
    63  }
    64  
    65  var aes128GCM = &aead{
    66  	nK:  128 / 8,
    67  	nN:  96 / 8,
    68  	new: newAESGCM,
    69  	id:  0x0001,
    70  }
    71  
    72  var aes256GCM = &aead{
    73  	nK:  256 / 8,
    74  	nN:  96 / 8,
    75  	new: newAESGCM,
    76  	id:  0x0002,
    77  }
    78  
    79  var chacha20poly1305AEAD = &aead{
    80  	nK:  chacha20poly1305.KeySize,
    81  	nN:  chacha20poly1305.NonceSize,
    82  	new: chacha20poly1305.New,
    83  	id:  0x0003,
    84  }
    85  
    86  func (a *aead) ID() uint16 {
    87  	return a.id
    88  }
    89  
    90  func (a *aead) aead(key []byte) (cipher.AEAD, error) {
    91  	if len(key) != a.nK {
    92  		return nil, errors.New("invalid key size")
    93  	}
    94  	return a.new(key)
    95  }
    96  
    97  func (a *aead) keySize() int {
    98  	return a.nK
    99  }
   100  
   101  func (a *aead) nonceSize() int {
   102  	return a.nN
   103  }
   104  
   105  type exportOnlyAEAD struct{}
   106  
   107  func (exportOnlyAEAD) ID() uint16 {
   108  	return 0xFFFF
   109  }
   110  
   111  func (exportOnlyAEAD) aead(key []byte) (cipher.AEAD, error) {
   112  	return nil, nil
   113  }
   114  
   115  func (exportOnlyAEAD) keySize() int {
   116  	return 0
   117  }
   118  
   119  func (exportOnlyAEAD) nonceSize() int {
   120  	return 0
   121  }
   122  

View as plain text