group_crypto.mx raw

   1  package mls
   2  
   3  // MLS group crypto operations (RFC 9420 §11, §12).
   4  // GroupInfo signing, Welcome encryption/decryption.
   5  
   6  var (
   7  	errGroupSecretsNotFound error
   8  )
   9  
  10  func (info *groupInfo) verifySignature(signerPub []byte) (ok bool) {
  11  	cs := info.groupContext.cipherSuite
  12  	var w Writer
  13  	info.marshalTBS(&w)
  14  	tbs, err := w.bytes()
  15  	if err != nil {
  16  		return false
  17  	}
  18  	return cs.verifyWithLabel(signerPub, []byte("GroupInfoTBS"), tbs, info.signature)
  19  }
  20  
  21  func (info *groupInfo) sign(signerPriv []byte) (err error) {
  22  	cs := info.groupContext.cipherSuite
  23  	var w Writer
  24  	info.marshalTBS(&w)
  25  	tbs, err := w.bytes()
  26  	if err != nil {
  27  		return err
  28  	}
  29  	sig, err := cs.signWithLabel(signerPriv, []byte("GroupInfoTBS"), tbs)
  30  	if err != nil {
  31  		return err
  32  	}
  33  	info.signature = sig
  34  	return nil
  35  }
  36  
  37  func (info *groupInfo) verifyConfirmationTag(joinerSecret, pskSecret []byte) (ok bool) {
  38  	cs := info.groupContext.cipherSuite
  39  	epochSecret, err := info.groupContext.extractEpochSecret(joinerSecret, pskSecret)
  40  	if err != nil {
  41  		return false
  42  	}
  43  	confirmationKey, err := cs.deriveSecret(epochSecret, secretLabelConfirm)
  44  	if err != nil {
  45  		return false
  46  	}
  47  	return cs.verifyMAC(confirmationKey, info.groupContext.confirmedTranscriptHash, info.confirmationTag)
  48  }
  49  
  50  func (info *groupInfo) encrypt(joinerSecret, pskSecret []byte) (out []byte, err2 error) {
  51  	cs := info.groupContext.cipherSuite
  52  	welcomeSecret, err := extractWelcomeSecret(cs, joinerSecret, pskSecret)
  53  	if err != nil {
  54  		return nil, err
  55  	}
  56  
  57  	welcomeNonce, err := cs.expandWithLabel(welcomeSecret, []byte("nonce"), nil, uint16(cs.AEADNonceSize()))
  58  	if err != nil {
  59  		return nil, err
  60  	}
  61  	welcomeKey, err := cs.expandWithLabel(welcomeSecret, []byte("key"), nil, uint16(cs.AEADKeySize()))
  62  	if err != nil {
  63  		return nil, err
  64  	}
  65  
  66  	rawGroupInfo, err := marshalRaw(info)
  67  	if err != nil {
  68  		return nil, err
  69  	}
  70  
  71  	return cs.aeadSeal(welcomeKey, welcomeNonce, rawGroupInfo, nil)
  72  }
  73  
  74  func (sec *groupSecrets) encrypt(cs CipherSuite, initKey []byte, encryptedGroupInfo []byte) (p *hpkeCiphertext, err2 error) {
  75  	raw, err := marshalRaw(sec)
  76  	if err != nil {
  77  		return nil, err
  78  	}
  79  	kemOutput, ciphertext, err := cs.encryptWithLabel(initKey, []byte("Welcome"), encryptedGroupInfo, raw)
  80  	if err != nil {
  81  		return nil, err
  82  	}
  83  	return &hpkeCiphertext{kemOutput: kemOutput, ciphertext: ciphertext}, nil
  84  }
  85  
  86  func (w *Welcome) decryptGroupSecrets(ref []byte, initKeyPriv []byte) (p *groupSecrets, err2 error) {
  87  	cs := w.cipherSuite
  88  	sec := w.findSecret(ref)
  89  	if sec == nil {
  90  		return nil, errGroupSecretsNotFound
  91  	}
  92  	raw, err := cs.decryptWithLabel(initKeyPriv, []byte("Welcome"), w.encryptedGroupInfo, sec.encryptedGroupSecrets.kemOutput, sec.encryptedGroupSecrets.ciphertext)
  93  	if err != nil {
  94  		return nil, err
  95  	}
  96  	var gs groupSecrets
  97  	if e := unmarshalRaw(raw, &gs); e != nil {
  98  		return nil, e
  99  	}
 100  	return &gs, nil
 101  }
 102  
 103  func (w *Welcome) decryptGroupInfo(joinerSecret, pskSecret []byte) (p *groupInfo, err2 error) {
 104  	cs := w.cipherSuite
 105  	welcomeSecret, err := extractWelcomeSecret(cs, joinerSecret, pskSecret)
 106  	if err != nil {
 107  		return nil, err
 108  	}
 109  
 110  	welcomeNonce, err := cs.expandWithLabel(welcomeSecret, []byte("nonce"), nil, uint16(cs.AEADNonceSize()))
 111  	if err != nil {
 112  		return nil, err
 113  	}
 114  	welcomeKey, err := cs.expandWithLabel(welcomeSecret, []byte("key"), nil, uint16(cs.AEADKeySize()))
 115  	if err != nil {
 116  		return nil, err
 117  	}
 118  
 119  	rawGroupInfo, err := cs.aeadOpen(welcomeKey, welcomeNonce, w.encryptedGroupInfo, nil)
 120  	if err != nil {
 121  		return nil, err
 122  	}
 123  
 124  	var info groupInfo
 125  	if e := unmarshalRaw(rawGroupInfo, &info); e != nil {
 126  		return nil, e
 127  	}
 128  	return &info, nil
 129  }
 130