Skip to content

Commit

Permalink
Move ExportKeyingMaterial to State
Browse files Browse the repository at this point in the history
Move `ExportKeyingMaterial` from `Conn` to `State`.
  • Loading branch information
jdbruijn committed Mar 30, 2020
1 parent e1af363 commit 8e29cb5
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 32 deletions.
27 changes: 0 additions & 27 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,33 +355,6 @@ func (c *Conn) SelectedSRTPProtectionProfile() (SRTPProtectionProfile, bool) {
return c.state.srtpProtectionProfile, true
}

// ExportKeyingMaterial from https://tools.ietf.org/html/rfc5705
// This allows protocols to use DTLS for key establishment, but
// then use some of the keying material for their own purposes
func (c *Conn) ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error) {
c.lock.Lock()
defer c.lock.Unlock()

if c.getLocalEpoch() == 0 {
return nil, errHandshakeInProgress
} else if len(context) != 0 {
return nil, errContextUnsupported
} else if _, ok := invalidKeyingLabels[label]; ok {
return nil, errReservedExportKeyingMaterial
}

localRandom := c.state.localRandom.marshalFixed()
remoteRandom := c.state.remoteRandom.marshalFixed()

seed := []byte(label)
if c.state.isClient {
seed = append(append(seed, localRandom[:]...), remoteRandom[:]...)
} else {
seed = append(append(seed, remoteRandom[:]...), localRandom[:]...)
}
return prfPHash(c.state.masterSecret, seed, length, c.state.cipherSuite.hashFunc())
}

func (c *Conn) writePackets(ctx context.Context, pkts []*packet) error {
c.lock.Lock()
defer c.lock.Unlock()
Expand Down
10 changes: 5 additions & 5 deletions conn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,33 +364,33 @@ func TestExportKeyingMaterial(t *testing.T) {
}
c.setLocalEpoch(0)

_, err := c.ExportKeyingMaterial(exportLabel, nil, 0)
_, err := c.state.ExportKeyingMaterial(exportLabel, nil, 0)
if err != errHandshakeInProgress {
t.Errorf("ExportKeyingMaterial when epoch == 0: expected '%s' actual '%s'", errHandshakeInProgress, err)
}

c.setLocalEpoch(1)
_, err = c.ExportKeyingMaterial(exportLabel, []byte{0x00}, 0)
_, err = c.state.ExportKeyingMaterial(exportLabel, []byte{0x00}, 0)
if err != errContextUnsupported {
t.Errorf("ExportKeyingMaterial with context: expected '%s' actual '%s'", errContextUnsupported, err)
}

for k := range invalidKeyingLabels {
_, err = c.ExportKeyingMaterial(k, nil, 0)
_, err = c.state.ExportKeyingMaterial(k, nil, 0)
if err != errReservedExportKeyingMaterial {
t.Errorf("ExportKeyingMaterial reserved label: expected '%s' actual '%s'", errReservedExportKeyingMaterial, err)
}
}

keyingMaterial, err := c.ExportKeyingMaterial(exportLabel, nil, 10)
keyingMaterial, err := c.state.ExportKeyingMaterial(exportLabel, nil, 10)
if err != nil {
t.Errorf("ExportKeyingMaterial as server: unexpected error '%s'", err)
} else if !bytes.Equal(keyingMaterial, expectedServerKey) {
t.Errorf("ExportKeyingMaterial client export: expected (% 02x) actual (% 02x)", expectedServerKey, keyingMaterial)
}

c.state.isClient = true
keyingMaterial, err = c.ExportKeyingMaterial(exportLabel, nil, 10)
keyingMaterial, err = c.state.ExportKeyingMaterial(exportLabel, nil, 10)
if err != nil {
t.Errorf("ExportKeyingMaterial as server: unexpected error '%s'", err)
} else if !bytes.Equal(keyingMaterial, expectedClientKey) {
Expand Down
25 changes: 25 additions & 0 deletions state.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,28 @@ func (s *State) UnmarshalBinary(data []byte) error {
}
return nil
}

// ExportKeyingMaterial returns length bytes of exported key material in a new
// slice as defined in RFC 5705.
// This allows protocols to use DTLS for key establishment, but
// then use some of the keying material for their own purposes
func (s *State) ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error) {
if s.localEpoch.Load().(uint16) == 0 {
return nil, errHandshakeInProgress
} else if len(context) != 0 {
return nil, errContextUnsupported
} else if _, ok := invalidKeyingLabels[label]; ok {
return nil, errReservedExportKeyingMaterial
}

localRandom := s.localRandom.marshalFixed()
remoteRandom := s.remoteRandom.marshalFixed()

seed := []byte(label)
if s.isClient {
seed = append(append(seed, localRandom[:]...), remoteRandom[:]...)
} else {
seed = append(append(seed, remoteRandom[:]...), localRandom[:]...)
}
return prfPHash(s.masterSecret, seed, length, s.cipherSuite.hashFunc())
}

0 comments on commit 8e29cb5

Please sign in to comment.