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