add a method to force the encryption level when sealing a packet

This commit is contained in:
Marten Seemann
2017-02-25 14:18:55 +07:00
parent 178c14f1d4
commit 599926e3cb
6 changed files with 127 additions and 0 deletions

View File

@@ -312,6 +312,25 @@ func (h *cryptoSetupClient) Seal(dst, src []byte, packetNumber protocol.PacketNu
return (&crypto.NullAEAD{}).Seal(dst, src, packetNumber, associatedData), protocol.EncryptionUnencrypted
}
func (h *cryptoSetupClient) SealWith(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte, forceEncryptionLevel protocol.EncryptionLevel) ([]byte, protocol.EncryptionLevel, error) {
switch forceEncryptionLevel {
case protocol.EncryptionUnencrypted:
return (&crypto.NullAEAD{}).Seal(dst, src, packetNumber, associatedData), protocol.EncryptionUnencrypted, nil
case protocol.EncryptionSecure:
if h.secureAEAD == nil {
return nil, protocol.EncryptionUnspecified, errors.New("CryptoSetupClient: no secureAEAD")
}
return h.secureAEAD.Seal(dst, src, packetNumber, associatedData), protocol.EncryptionSecure, nil
case protocol.EncryptionForwardSecure:
if h.forwardSecureAEAD == nil {
return nil, protocol.EncryptionUnspecified, errors.New("CryptoSetupClient: no forwardSecureAEAD")
}
return h.forwardSecureAEAD.Seal(dst, src, packetNumber, associatedData), protocol.EncryptionForwardSecure, nil
}
return nil, protocol.EncryptionUnspecified, errors.New("no encryption level specified")
}
func (h *cryptoSetupClient) DiversificationNonce() []byte {
panic("not needed for cryptoSetupClient")
}

View File

@@ -744,6 +744,48 @@ var _ = Describe("Crypto setup", func() {
Expect(enc).To(Equal(protocol.EncryptionForwardSecure))
})
})
Context("forcing encryption levels", func() {
It("forces null encryption", func() {
d, enc, err := cs.SealWith(nil, []byte("foobar"), 0, []byte{}, protocol.EncryptionUnencrypted)
Expect(err).ToNot(HaveOccurred())
Expect(d).To(Equal(foobarFNVSigned))
Expect(enc).To(Equal(protocol.EncryptionUnencrypted))
})
It("forces initial encryption", func() {
doCompleteREJ()
d, enc, err := cs.SealWith(nil, []byte("foobar"), 0, []byte{}, protocol.EncryptionSecure)
Expect(err).ToNot(HaveOccurred())
Expect(d).To(Equal([]byte("foobar normal sec")))
Expect(enc).To(Equal(protocol.EncryptionSecure))
})
It("errors of no AEAD for initial encryption is available", func() {
_, enc, err := cs.SealWith(nil, []byte("foobar"), 0, []byte{}, protocol.EncryptionSecure)
Expect(err).To(MatchError("CryptoSetupClient: no secureAEAD"))
Expect(enc).To(Equal(protocol.EncryptionUnspecified))
})
It("forces forward-secure encryption", func() {
doSHLO()
d, enc, err := cs.SealWith(nil, []byte("foobar"), 0, []byte{}, protocol.EncryptionForwardSecure)
Expect(err).ToNot(HaveOccurred())
Expect(d).To(Equal([]byte("foobar forward sec")))
Expect(enc).To(Equal(protocol.EncryptionForwardSecure))
})
It("errors of no AEAD for forward-secure encryption is available", func() {
_, enc, err := cs.SealWith(nil, []byte("foobar"), 0, []byte{}, protocol.EncryptionForwardSecure)
Expect(err).To(MatchError("CryptoSetupClient: no forwardSecureAEAD"))
Expect(enc).To(Equal(protocol.EncryptionUnspecified))
})
It("errors if no encryption level is specified", func() {
_, _, err := cs.SealWith(nil, []byte("foobar"), 0, []byte{}, protocol.EncryptionUnspecified)
Expect(err).To(MatchError("no encryption level specified"))
})
})
})
Context("Diversification Nonces", func() {

View File

@@ -7,6 +7,7 @@ type CryptoSetup interface {
HandleCryptoStream() error
Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error)
Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel)
SealWith(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte, forceEncryptionLevel protocol.EncryptionLevel) ([]byte, protocol.EncryptionLevel, error)
LockForSealing()
UnlockForSealing()
HandshakeComplete() bool

View File

@@ -4,6 +4,7 @@ import (
"bytes"
"crypto/rand"
"encoding/binary"
"errors"
"io"
"sync"
@@ -195,6 +196,25 @@ func (h *cryptoSetupServer) Seal(dst, src []byte, packetNumber protocol.PacketNu
}
}
func (h *cryptoSetupServer) SealWith(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte, forceEncryptionLevel protocol.EncryptionLevel) ([]byte, protocol.EncryptionLevel, error) {
switch forceEncryptionLevel {
case protocol.EncryptionUnencrypted:
return (&crypto.NullAEAD{}).Seal(dst, src, packetNumber, associatedData), protocol.EncryptionUnencrypted, nil
case protocol.EncryptionSecure:
if h.secureAEAD == nil {
return nil, protocol.EncryptionUnspecified, errors.New("CryptoSetupServer: no secureAEAD")
}
return h.secureAEAD.Seal(dst, src, packetNumber, associatedData), protocol.EncryptionSecure, nil
case protocol.EncryptionForwardSecure:
if h.forwardSecureAEAD == nil {
return nil, protocol.EncryptionUnspecified, errors.New("CryptoSetupServer: no forwardSecureAEAD")
}
return h.forwardSecureAEAD.Seal(dst, src, packetNumber, associatedData), protocol.EncryptionForwardSecure, nil
}
return nil, protocol.EncryptionUnspecified, errors.New("no encryption level specified")
}
func (h *cryptoSetupServer) isInchoateCHLO(cryptoData map[Tag][]byte, cert []byte) bool {
if _, ok := cryptoData[TagPUBS]; !ok {
return true

View File

@@ -659,6 +659,48 @@ var _ = Describe("Crypto setup", func() {
Expect(enc).To(Equal(protocol.EncryptionForwardSecure))
})
})
Context("forcing encryption levels", func() {
It("forces null encryption", func() {
d, enc, err := cs.SealWith(nil, []byte("foobar"), 0, []byte{}, protocol.EncryptionUnencrypted)
Expect(err).ToNot(HaveOccurred())
Expect(d).To(Equal(foobarFNVSigned))
Expect(enc).To(Equal(protocol.EncryptionUnencrypted))
})
It("forces initial encryption", func() {
doCHLO()
d, enc, err := cs.SealWith(nil, []byte("foobar"), 0, []byte{}, protocol.EncryptionSecure)
Expect(err).ToNot(HaveOccurred())
Expect(d).To(Equal([]byte("foobar normal sec")))
Expect(enc).To(Equal(protocol.EncryptionSecure))
})
It("errors of no AEAD for initial encryption is available", func() {
_, enc, err := cs.SealWith(nil, []byte("foobar"), 0, []byte{}, protocol.EncryptionSecure)
Expect(err).To(MatchError("CryptoSetupServer: no secureAEAD"))
Expect(enc).To(Equal(protocol.EncryptionUnspecified))
})
It("forces forward-secure encryption", func() {
doCHLO()
d, enc, err := cs.SealWith(nil, []byte("foobar"), 0, []byte{}, protocol.EncryptionForwardSecure)
Expect(err).ToNot(HaveOccurred())
Expect(d).To(Equal([]byte("foobar forward sec")))
Expect(enc).To(Equal(protocol.EncryptionForwardSecure))
})
It("errors of no AEAD for forward-secure encryption is available", func() {
_, enc, err := cs.SealWith(nil, []byte("foobar"), 0, []byte{}, protocol.EncryptionForwardSecure)
Expect(err).To(MatchError("CryptoSetupServer: no forwardSecureAEAD"))
Expect(enc).To(Equal(protocol.EncryptionUnspecified))
})
It("errors if no encryption level is specified", func() {
_, _, err := cs.SealWith(nil, []byte("foobar"), 0, []byte{}, protocol.EncryptionUnspecified)
Expect(err).To(MatchError("no encryption level specified"))
})
})
})
Context("STK verification and creation", func() {

View File

@@ -24,6 +24,9 @@ func (m *mockCryptoSetup) Open(dst, src []byte, packetNumber protocol.PacketNumb
func (m *mockCryptoSetup) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel) {
return append(src, bytes.Repeat([]byte{0}, 12)...), m.encLevelSeal
}
func (m *mockCryptoSetup) SealWith(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte, encLevel protocol.EncryptionLevel) ([]byte, protocol.EncryptionLevel, error) {
panic("not implemented")
}
func (m *mockCryptoSetup) LockForSealing() {}
func (m *mockCryptoSetup) UnlockForSealing() {}
func (m *mockCryptoSetup) HandshakeComplete() bool { return m.handshakeComplete }