switch to forward-secure encryption after sending the SHLO

This commit is contained in:
Marten Seemann
2017-01-11 17:44:32 +07:00
parent 936a29ff35
commit b5c8c11c0c
3 changed files with 24 additions and 17 deletions

View File

@@ -68,6 +68,7 @@ func (c *linkedConnection) Close() error { return nil }
func setAEAD(cs handshake.CryptoSetup, aead crypto.AEAD) { func setAEAD(cs handshake.CryptoSetup, aead crypto.AEAD) {
*(*bool)(unsafe.Pointer(reflect.ValueOf(cs).Elem().FieldByName("receivedForwardSecurePacket").UnsafeAddr())) = true *(*bool)(unsafe.Pointer(reflect.ValueOf(cs).Elem().FieldByName("receivedForwardSecurePacket").UnsafeAddr())) = true
*(*bool)(unsafe.Pointer(reflect.ValueOf(cs).Elem().FieldByName("sentSHLO").UnsafeAddr())) = true
*(*crypto.AEAD)(unsafe.Pointer(reflect.ValueOf(cs).Elem().FieldByName("forwardSecureAEAD").UnsafeAddr())) = aead *(*crypto.AEAD)(unsafe.Pointer(reflect.ValueOf(cs).Elem().FieldByName("forwardSecureAEAD").UnsafeAddr())) = aead
} }

View File

@@ -31,6 +31,7 @@ type cryptoSetupServer struct {
secureAEAD crypto.AEAD secureAEAD crypto.AEAD
forwardSecureAEAD crypto.AEAD forwardSecureAEAD crypto.AEAD
receivedForwardSecurePacket bool receivedForwardSecurePacket bool
sentSHLO bool
receivedSecurePacket bool receivedSecurePacket bool
aeadChanged chan protocol.EncryptionLevel aeadChanged chan protocol.EncryptionLevel
@@ -187,9 +188,12 @@ func (h *cryptoSetupServer) Open(dst, src []byte, packetNumber protocol.PacketNu
// Seal a message, call LockForSealing() before! // Seal a message, call LockForSealing() before!
func (h *cryptoSetupServer) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel) { func (h *cryptoSetupServer) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel) {
if h.receivedForwardSecurePacket { if h.forwardSecureAEAD != nil && h.sentSHLO {
return h.forwardSecureAEAD.Seal(dst, src, packetNumber, associatedData), protocol.EncryptionForwardSecure return h.forwardSecureAEAD.Seal(dst, src, packetNumber, associatedData), protocol.EncryptionForwardSecure
} else if h.secureAEAD != nil { } else if h.secureAEAD != nil {
// secureAEAD and forwardSecureAEAD are created at the same time (when receiving the CHLO)
// make sure that the SHLO isn't sent forward-secure
h.sentSHLO = true
return h.secureAEAD.Seal(dst, src, packetNumber, associatedData), protocol.EncryptionSecure return h.secureAEAD.Seal(dst, src, packetNumber, associatedData), protocol.EncryptionSecure
} else { } else {
return (&crypto.NullAEAD{}).Seal(dst, src, packetNumber, associatedData), protocol.EncryptionUnencrypted return (&crypto.NullAEAD{}).Seal(dst, src, packetNumber, associatedData), protocol.EncryptionUnencrypted
@@ -375,6 +379,7 @@ func (h *cryptoSetupServer) handleCHLO(sni string, data []byte, cryptoData map[T
replyMap[TagSNO] = serverNonce replyMap[TagSNO] = serverNonce
replyMap[TagVER] = protocol.SupportedVersionsAsTags replyMap[TagVER] = protocol.SupportedVersionsAsTags
// note that the SHLO *has* to fit into one packet
var reply bytes.Buffer var reply bytes.Buffer
WriteHandshakeMessage(&reply, TagSHLO, replyMap) WriteHandshakeMessage(&reply, TagSHLO, replyMap)
utils.Debugf("Sending SHLO:\n%s", printHandshakeMessage(replyMap)) utils.Debugf("Sending SHLO:\n%s", printHandshakeMessage(replyMap))
@@ -386,7 +391,7 @@ func (h *cryptoSetupServer) handleCHLO(sni string, data []byte, cryptoData map[T
// DiversificationNonce returns a diversification nonce if required in the next packet to be Seal'ed. See LockForSealing()! // DiversificationNonce returns a diversification nonce if required in the next packet to be Seal'ed. See LockForSealing()!
func (h *cryptoSetupServer) DiversificationNonce() []byte { func (h *cryptoSetupServer) DiversificationNonce() []byte {
if h.receivedForwardSecurePacket || h.secureAEAD == nil { if h.secureAEAD == nil || h.sentSHLO {
return nil return nil
} }
return h.diversificationNonce return h.diversificationNonce

View File

@@ -194,8 +194,8 @@ var _ = Describe("Crypto setup", func() {
Expect(cs.DiversificationNonce()).To(HaveLen(32)) Expect(cs.DiversificationNonce()).To(HaveLen(32))
}) })
It("does not return nonce for FS packets", func() { It("does not return nonce after sending the SHLO", func() {
cs.receivedForwardSecurePacket = true cs.sentSHLO = true
Expect(cs.DiversificationNonce()).To(BeEmpty()) Expect(cs.DiversificationNonce()).To(BeEmpty())
}) })
@@ -633,15 +633,6 @@ var _ = Describe("Crypto setup", func() {
Expect(d).To(Equal([]byte("decrypted"))) Expect(d).To(Equal([]byte("decrypted")))
}) })
It("is not used after receiving forward secure packet", func() {
doCHLO()
_, _, err := cs.Open(nil, []byte("forward secure encrypted"), 0, []byte{})
Expect(err).ToNot(HaveOccurred())
d, enc := cs.Seal(nil, []byte("foobar"), 0, []byte{})
Expect(d).To(Equal([]byte("foobar forward sec")))
Expect(enc).To(Equal(protocol.EncryptionForwardSecure))
})
It("is not accepted after receiving forward secure packet", func() { It("is not accepted after receiving forward secure packet", func() {
doCHLO() doCHLO()
_, _, err := cs.Open(nil, []byte("forward secure encrypted"), 0, []byte{}) _, _, err := cs.Open(nil, []byte("forward secure encrypted"), 0, []byte{})
@@ -653,15 +644,25 @@ var _ = Describe("Crypto setup", func() {
}) })
Context("forward secure encryption", func() { Context("forward secure encryption", func() {
It("is used after receiving forward secure packet", func() { It("is used after sending out one packet with initial encryption", func() {
doCHLO() doCHLO()
_, enc, err := cs.Open(nil, []byte("forward secure encrypted"), 0, []byte{}) _, enc := cs.Seal(nil, []byte("SHLO"), 0, []byte{})
Expect(enc).To(Equal(protocol.EncryptionForwardSecure)) Expect(enc).To(Equal(protocol.EncryptionSecure))
Expect(err).ToNot(HaveOccurred())
d, enc := cs.Seal(nil, []byte("foobar"), 0, []byte{}) d, enc := cs.Seal(nil, []byte("foobar"), 0, []byte{})
Expect(d).To(Equal([]byte("foobar forward sec"))) Expect(d).To(Equal([]byte("foobar forward sec")))
Expect(enc).To(Equal(protocol.EncryptionForwardSecure)) Expect(enc).To(Equal(protocol.EncryptionForwardSecure))
}) })
It("regards the handshake as complete once it receives a forward encrypted packet", func() {
doCHLO()
_, enc := cs.Seal(nil, []byte("SHLO"), 0, []byte{})
Expect(enc).To(Equal(protocol.EncryptionSecure))
_, enc = cs.Seal(nil, []byte("foobar"), 0, []byte{})
Expect(enc).To(Equal(protocol.EncryptionForwardSecure))
Expect(cs.HandshakeComplete()).To(BeFalse())
cs.receivedForwardSecurePacket = true
Expect(cs.HandshakeComplete()).To(BeTrue())
})
}) })
Context("forcing encryption levels", func() { Context("forcing encryption levels", func() {