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