mirror of
https://github.com/bjdgyc/anylink.git
synced 2025-08-08 19:22:42 +08:00
添加 github.com/pion/dtls 代码
This commit is contained in:
104
dtls-2.0.9/pkg/crypto/ciphersuite/ccm.go
Normal file
104
dtls-2.0.9/pkg/crypto/ciphersuite/ccm.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package ciphersuite
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/ccm"
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
// CCMTagLen is the length of Authentication Tag
|
||||
type CCMTagLen int
|
||||
|
||||
// CCM Enums
|
||||
const (
|
||||
CCMTagLength8 CCMTagLen = 8
|
||||
CCMTagLength CCMTagLen = 16
|
||||
ccmNonceLength = 12
|
||||
)
|
||||
|
||||
// CCM Provides an API to Encrypt/Decrypt DTLS 1.2 Packets
|
||||
type CCM struct {
|
||||
localCCM, remoteCCM ccm.CCM
|
||||
localWriteIV, remoteWriteIV []byte
|
||||
tagLen CCMTagLen
|
||||
}
|
||||
|
||||
// NewCCM creates a DTLS GCM Cipher
|
||||
func NewCCM(tagLen CCMTagLen, localKey, localWriteIV, remoteKey, remoteWriteIV []byte) (*CCM, error) {
|
||||
localBlock, err := aes.NewCipher(localKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
localCCM, err := ccm.NewCCM(localBlock, int(tagLen), ccmNonceLength)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
remoteBlock, err := aes.NewCipher(remoteKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
remoteCCM, err := ccm.NewCCM(remoteBlock, int(tagLen), ccmNonceLength)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &CCM{
|
||||
localCCM: localCCM,
|
||||
localWriteIV: localWriteIV,
|
||||
remoteCCM: remoteCCM,
|
||||
remoteWriteIV: remoteWriteIV,
|
||||
tagLen: tagLen,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Encrypt encrypt a DTLS RecordLayer message
|
||||
func (c *CCM) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) {
|
||||
payload := raw[recordlayer.HeaderSize:]
|
||||
raw = raw[:recordlayer.HeaderSize]
|
||||
|
||||
nonce := append(append([]byte{}, c.localWriteIV[:4]...), make([]byte, 8)...)
|
||||
if _, err := rand.Read(nonce[4:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
additionalData := generateAEADAdditionalData(&pkt.Header, len(payload))
|
||||
encryptedPayload := c.localCCM.Seal(nil, nonce, payload, additionalData)
|
||||
|
||||
encryptedPayload = append(nonce[4:], encryptedPayload...)
|
||||
raw = append(raw, encryptedPayload...)
|
||||
|
||||
// Update recordLayer size to include explicit nonce
|
||||
binary.BigEndian.PutUint16(raw[recordlayer.HeaderSize-2:], uint16(len(raw)-recordlayer.HeaderSize))
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
// Decrypt decrypts a DTLS RecordLayer message
|
||||
func (c *CCM) Decrypt(in []byte) ([]byte, error) {
|
||||
var h recordlayer.Header
|
||||
err := h.Unmarshal(in)
|
||||
switch {
|
||||
case err != nil:
|
||||
return nil, err
|
||||
case h.ContentType == protocol.ContentTypeChangeCipherSpec:
|
||||
// Nothing to encrypt with ChangeCipherSpec
|
||||
return in, nil
|
||||
case len(in) <= (8 + recordlayer.HeaderSize):
|
||||
return nil, errNotEnoughRoomForNonce
|
||||
}
|
||||
|
||||
nonce := append(append([]byte{}, c.remoteWriteIV[:4]...), in[recordlayer.HeaderSize:recordlayer.HeaderSize+8]...)
|
||||
out := in[recordlayer.HeaderSize+8:]
|
||||
|
||||
additionalData := generateAEADAdditionalData(&h, len(out)-int(c.tagLen))
|
||||
out, err = c.remoteCCM.Open(out[:0], nonce, out, additionalData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errDecryptPacket, err)
|
||||
}
|
||||
return append(in[:recordlayer.HeaderSize], out...), nil
|
||||
}
|
Reference in New Issue
Block a user