crypto.go raw

   1  package mls
   2  
   3  import (
   4  	"fmt"
   5  	"io"
   6  
   7  	"golang.org/x/crypto/cryptobyte"
   8  )
   9  
  10  type (
  11  	hpkePublicKey       []byte
  12  	hpkePrivateKey      []byte
  13  	signaturePublicKey  []byte
  14  	signaturePrivateKey []byte
  15  )
  16  
  17  type credentialType uint16
  18  
  19  // https://www.iana.org/assignments/mls/mls.xhtml#mls-credential-types
  20  const (
  21  	credentialTypeBasic credentialType = 0x0001
  22  	credentialTypeX509  credentialType = 0x0002
  23  )
  24  
  25  // A Credential holds information about a group member's identity.
  26  type Credential struct {
  27  	credentialType credentialType
  28  	identity       []byte   // for credentialTypeBasic
  29  	certificates   [][]byte // for credentialTypeX509
  30  }
  31  
  32  // NewBasicCredential creates a new basic credential. identity uses an
  33  // application-specific format.
  34  func NewBasicCredential(identity []byte) *Credential {
  35  	return &Credential{
  36  		credentialType: credentialTypeBasic,
  37  		identity:       identity,
  38  	}
  39  }
  40  
  41  func (cred *Credential) unmarshal(s *cryptobyte.String) error {
  42  	*cred = Credential{}
  43  
  44  	if !s.ReadUint16((*uint16)(&cred.credentialType)) {
  45  		return io.ErrUnexpectedEOF
  46  	}
  47  
  48  	switch cred.credentialType {
  49  	case credentialTypeBasic:
  50  		if !readOpaqueVec(s, &cred.identity) {
  51  			return io.ErrUnexpectedEOF
  52  		}
  53  		return nil
  54  	case credentialTypeX509:
  55  		return readVector(s, func(s *cryptobyte.String) error {
  56  			var cert []byte
  57  			if !readOpaqueVec(s, &cert) {
  58  				return io.ErrUnexpectedEOF
  59  			}
  60  			cred.certificates = append(cred.certificates, cert)
  61  			return nil
  62  		})
  63  	default:
  64  		return fmt.Errorf("mls: invalid credential type %d", cred.credentialType)
  65  	}
  66  }
  67  
  68  func (cred *Credential) marshal(b *cryptobyte.Builder) {
  69  	b.AddUint16(uint16(cred.credentialType))
  70  	switch cred.credentialType {
  71  	case credentialTypeBasic:
  72  		writeOpaqueVec(b, cred.identity)
  73  	case credentialTypeX509:
  74  		writeVector(b, len(cred.certificates), func(b *cryptobyte.Builder, i int) {
  75  			writeOpaqueVec(b, cred.certificates[i])
  76  		})
  77  	default:
  78  		panic("unreachable")
  79  	}
  80  }
  81  
  82  type hpkeCiphertext struct {
  83  	kemOutput  []byte
  84  	ciphertext []byte
  85  }
  86  
  87  func (hpke *hpkeCiphertext) unmarshal(s *cryptobyte.String) error {
  88  	*hpke = hpkeCiphertext{}
  89  	if !readOpaqueVec(s, &hpke.kemOutput) || !readOpaqueVec(s, &hpke.ciphertext) {
  90  		return io.ErrUnexpectedEOF
  91  	}
  92  	return nil
  93  }
  94  
  95  func (hpke *hpkeCiphertext) marshal(b *cryptobyte.Builder) {
  96  	writeOpaqueVec(b, hpke.kemOutput)
  97  	writeOpaqueVec(b, hpke.ciphertext)
  98  }
  99