func (s *state) DecryptPacket(pkt *lob.Packet) (*lob.Packet, error) { s.mtx.RLock() defer s.mtx.RUnlock() if !s.CanDecryptPacket() { return nil, cipherset.ErrInvalidState } if pkt == nil { return nil, nil } if !pkt.Header().IsZero() || pkt.BodyLen() < 16+4+4 { return nil, cipherset.ErrInvalidPacket } var ( nonce [16]byte bodyRaw []byte innerRaw []byte innerLen = pkt.BodyLen() - (16 + 4 + 4) body = bufpool.New() inner = bufpool.New().SetLen(innerLen) ) pkt.Body(body.SetLen(pkt.BodyLen()).RawBytes()[:0]) bodyRaw = body.RawBytes() innerRaw = inner.RawBytes() // compare token if !bytes.Equal(bodyRaw[:16], (*s.localToken)[:]) { inner.Free() body.Free() return nil, cipherset.ErrInvalidPacket } // copy nonce copy(nonce[:], bodyRaw[16:16+4]) { // verify hmac mac := bodyRaw[16+4+innerLen:] macKey := append(s.lineDecryptionKey, nonce[:4]...) h := hmac.New(sha256.New, macKey) h.Write(bodyRaw[16+4 : 16+4+innerLen]) if subtle.ConstantTimeCompare(mac, fold(h.Sum(nil), 4)) != 1 { inner.Free() body.Free() return nil, cipherset.ErrInvalidPacket } } { // decrypt inner aesBlock, err := aes.NewCipher(s.lineDecryptionKey) if err != nil { inner.Free() body.Free() return nil, err } aes := Cipher.NewCTR(aesBlock, nonce[:]) if aes == nil { inner.Free() body.Free() return nil, cipherset.ErrInvalidPacket } aes.XORKeyStream(innerRaw, bodyRaw[16+4:16+4+innerLen]) } innerPkt, err := lob.Decode(inner) if err != nil { inner.Free() body.Free() return nil, err } inner.Free() body.Free() return innerPkt, nil }
func (s *state) DecryptPacket(pkt *lob.Packet) (*lob.Packet, error) { s.mtx.RLock() defer s.mtx.RUnlock() if !s.CanDecryptPacket() { return nil, cipherset.ErrInvalidState } if pkt == nil { return nil, nil } if !pkt.Header().IsZero() || pkt.BodyLen() < lenToken+lenNonce { return nil, cipherset.ErrInvalidPacket } var ( nonce [lenNonce]byte bodyRaw []byte innerRaw []byte innerPkt *lob.Packet body = bufpool.New() inner = bufpool.New() ok bool ) pkt.Body(body.SetLen(pkt.BodyLen()).RawBytes()[:0]) bodyRaw = body.RawBytes() innerRaw = inner.RawBytes() // compare token if !bytes.Equal(bodyRaw[:lenToken], (*s.localToken)[:]) { inner.Free() body.Free() return nil, cipherset.ErrInvalidPacket } // copy nonce copy(nonce[:], bodyRaw[lenToken:lenToken+lenNonce]) // decrypt inner packet innerRaw, ok = box.OpenAfterPrecomputation( innerRaw[:0], bodyRaw[lenToken+lenNonce:], &nonce, s.lineDecryptionKey) if !ok { inner.Free() body.Free() return nil, cipherset.ErrInvalidPacket } inner.SetLen(len(innerRaw)) innerPkt, err := lob.Decode(inner) if err != nil { inner.Free() body.Free() return nil, err } inner.Free() body.Free() return innerPkt, nil }