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