group_types.mx raw

   1  package mls
   2  
   3  // MLS group types (RFC 9420 §11, §12).
   4  // Data types and serialization from group.go.
   5  // Crypto operations (sign, encrypt, join) go in group_crypto.mx.
   6  
   7  // --- Commit ---
   8  
   9  type commit struct {
  10  	proposals []proposalOrRef
  11  	path      *updatePath // optional
  12  }
  13  
  14  func (c *commit) unmarshal(r *Reader) error {
  15  	*c = commit{}
  16  
  17  	err := r.readVector(func(r *Reader) error {
  18  		var por proposalOrRef
  19  		if err := por.unmarshal(r); err != nil {
  20  			return err
  21  		}
  22  		c.proposals = append(c.proposals, por)
  23  		return nil
  24  	})
  25  	if err != nil {
  26  		return err
  27  	}
  28  
  29  	present, ok := r.readOptional()
  30  	if !ok {
  31  		return errUnexpectedEOF
  32  	}
  33  	if present {
  34  		c.path = &updatePath{}
  35  		if err := c.path.unmarshal(r); err != nil {
  36  			return err
  37  		}
  38  	}
  39  	return nil
  40  }
  41  
  42  func (c *commit) marshal(w *Writer) {
  43  	w.writeVector(len(c.proposals), func(w *Writer, i int) {
  44  		c.proposals[i].marshal(w)
  45  	})
  46  	w.writeOptional(c.path != nil)
  47  	if c.path != nil {
  48  		c.path.marshal(w)
  49  	}
  50  }
  51  
  52  // --- GroupInfo ---
  53  
  54  type groupInfo struct {
  55  	groupContext    groupContext
  56  	extensions      []extension
  57  	confirmationTag []byte
  58  	signer          leafIndex
  59  	signature       []byte
  60  }
  61  
  62  func (info *groupInfo) unmarshal(r *Reader) error {
  63  	*info = groupInfo{}
  64  
  65  	if err := info.groupContext.unmarshal(r); err != nil {
  66  		return err
  67  	}
  68  
  69  	exts, err := unmarshalExtensionVec(r)
  70  	if err != nil {
  71  		return err
  72  	}
  73  	info.extensions = exts
  74  
  75  	var ok bool
  76  	info.confirmationTag, ok = r.readOpaqueVec()
  77  	if !ok {
  78  		return errUnexpectedEOF
  79  	}
  80  	v, ok := r.readUint32()
  81  	if !ok {
  82  		return errUnexpectedEOF
  83  	}
  84  	info.signer = leafIndex(v)
  85  	info.signature, ok = r.readOpaqueVec()
  86  	if !ok {
  87  		return errUnexpectedEOF
  88  	}
  89  	return nil
  90  }
  91  
  92  func (info *groupInfo) marshal(w *Writer) {
  93  	info.marshalTBS(w)
  94  	w.writeOpaqueVec(info.signature)
  95  }
  96  
  97  func (info *groupInfo) marshalTBS(w *Writer) {
  98  	info.groupContext.marshal(w)
  99  	marshalExtensionVec(w, info.extensions)
 100  	w.writeOpaqueVec(info.confirmationTag)
 101  	w.addUint32(uint32(info.signer))
 102  }
 103  
 104  // --- GroupSecrets ---
 105  
 106  type groupSecrets struct {
 107  	joinerSecret []byte
 108  	pathSecret   []byte // optional
 109  	psks         []preSharedKeyID
 110  }
 111  
 112  func (sec *groupSecrets) unmarshal(r *Reader) error {
 113  	*sec = groupSecrets{}
 114  
 115  	var ok bool
 116  	sec.joinerSecret, ok = r.readOpaqueVec()
 117  	if !ok {
 118  		return errUnexpectedEOF
 119  	}
 120  
 121  	present, ok := r.readOptional()
 122  	if !ok {
 123  		return errUnexpectedEOF
 124  	}
 125  	if present {
 126  		sec.pathSecret, ok = r.readOpaqueVec()
 127  		if !ok {
 128  			return errUnexpectedEOF
 129  		}
 130  	}
 131  
 132  	return r.readVector(func(r *Reader) error {
 133  		var psk preSharedKeyID
 134  		if err := psk.unmarshal(r); err != nil {
 135  			return err
 136  		}
 137  		sec.psks = append(sec.psks, psk)
 138  		return nil
 139  	})
 140  }
 141  
 142  func (sec *groupSecrets) marshal(w *Writer) {
 143  	w.writeOpaqueVec(sec.joinerSecret)
 144  	w.writeOptional(sec.pathSecret != nil)
 145  	if sec.pathSecret != nil {
 146  		w.writeOpaqueVec(sec.pathSecret)
 147  	}
 148  	w.writeVector(len(sec.psks), func(w *Writer, i int) {
 149  		sec.psks[i].marshal(w)
 150  	})
 151  }
 152  
 153  func (sec *groupSecrets) verifySingleReinitOrBranchPSK() bool {
 154  	n := 0
 155  	for _, pskID := range sec.psks {
 156  		if pskID.pskType != pskTypeResumption {
 157  			continue
 158  		}
 159  		switch pskID.usage {
 160  		case resumptionPSKUsageReinit, resumptionPSKUsageBranch:
 161  			n++
 162  		}
 163  	}
 164  	return n <= 1
 165  }
 166  
 167  // --- EncryptedGroupSecrets ---
 168  
 169  type encryptedGroupSecrets struct {
 170  	newMember             KeyPackageRef
 171  	encryptedGroupSecrets hpkeCiphertext
 172  }
 173  
 174  func (sec *encryptedGroupSecrets) unmarshal(r *Reader) error {
 175  	*sec = encryptedGroupSecrets{}
 176  	var ok bool
 177  	sec.newMember, ok = r.readOpaqueVec()
 178  	if !ok {
 179  		return errUnexpectedEOF
 180  	}
 181  	return sec.encryptedGroupSecrets.unmarshal(r)
 182  }
 183  
 184  func (sec *encryptedGroupSecrets) marshal(w *Writer) {
 185  	w.writeOpaqueVec([]byte(sec.newMember))
 186  	sec.encryptedGroupSecrets.marshal(w)
 187  }
 188  
 189  // --- Welcome ---
 190  
 191  // Welcome includes secret keying information to join a group.
 192  type Welcome struct {
 193  	cipherSuite        CipherSuite
 194  	secrets            []encryptedGroupSecrets
 195  	encryptedGroupInfo []byte
 196  }
 197  
 198  // UnmarshalWelcome reads a welcome from an MLS message envelope.
 199  func UnmarshalWelcome(raw []byte) (*Welcome, error) {
 200  	var msg mlsMessage
 201  	if err := unmarshalRaw(raw, &msg); err != nil {
 202  		return nil, err
 203  	}
 204  	if msg.wireFormat != wireFormatMLSWelcome {
 205  		return nil, errInvalidWireFormat
 206  	}
 207  	return msg.welcome, nil
 208  }
 209  
 210  // Bytes encodes the welcome in an MLSMessage envelope.
 211  func (w *Welcome) Bytes() []byte {
 212  	raw, err := marshalRaw(&mlsMessage{
 213  		version:    protocolVersionMLS10,
 214  		wireFormat: wireFormatMLSWelcome,
 215  		welcome:    w,
 216  	})
 217  	if err != nil {
 218  		panic("mls: failed to marshal welcome")
 219  	}
 220  	return raw
 221  }
 222  
 223  func (w *Welcome) unmarshal(r *Reader) error {
 224  	*w = Welcome{}
 225  	v, ok := r.readUint16()
 226  	if !ok {
 227  		return errUnexpectedEOF
 228  	}
 229  	w.cipherSuite = CipherSuite(v)
 230  
 231  	err := r.readVector(func(r *Reader) error {
 232  		var sec encryptedGroupSecrets
 233  		if err := sec.unmarshal(r); err != nil {
 234  			return err
 235  		}
 236  		w.secrets = append(w.secrets, sec)
 237  		return nil
 238  	})
 239  	if err != nil {
 240  		return err
 241  	}
 242  
 243  	w.encryptedGroupInfo, ok = r.readOpaqueVec()
 244  	if !ok {
 245  		return errUnexpectedEOF
 246  	}
 247  	return nil
 248  }
 249  
 250  func (w *Welcome) marshal(wr *Writer) {
 251  	wr.addUint16(uint16(w.cipherSuite))
 252  	wr.writeVector(len(w.secrets), func(wr *Writer, i int) {
 253  		w.secrets[i].marshal(wr)
 254  	})
 255  	wr.writeOpaqueVec(w.encryptedGroupInfo)
 256  }
 257  
 258  // NewMembers returns key package refs this welcome contains secrets for.
 259  func (w *Welcome) NewMembers() []KeyPackageRef {
 260  	refs := []KeyPackageRef{:len(w.secrets)}
 261  	for i, sec := range w.secrets {
 262  		refs[i] = sec.newMember
 263  	}
 264  	return refs
 265  }
 266  
 267  func (w *Welcome) findSecret(ref KeyPackageRef) *encryptedGroupSecrets {
 268  	for i, sec := range w.secrets {
 269  		if sec.newMember.equal(ref) {
 270  			return &w.secrets[i]
 271  		}
 272  	}
 273  	return nil
 274  }
 275