dockerfiles/anylink/dtls-2.0.9/pkg/protocol/handshake/message_certificate_request.go

101 lines
2.7 KiB
Go

package handshake
import (
"encoding/binary"
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
"github.com/pion/dtls/v2/pkg/crypto/hash"
"github.com/pion/dtls/v2/pkg/crypto/signature"
"github.com/pion/dtls/v2/pkg/crypto/signaturehash"
)
/*
MessageCertificateRequest is so a non-anonymous server can optionally
request a certificate from the client, if appropriate for the selected cipher
suite. This message, if sent, will immediately follow the ServerKeyExchange
message (if it is sent; otherwise, this message follows the
server's Certificate message).
https://tools.ietf.org/html/rfc5246#section-7.4.4
*/
type MessageCertificateRequest struct {
CertificateTypes []clientcertificate.Type
SignatureHashAlgorithms []signaturehash.Algorithm
}
const (
messageCertificateRequestMinLength = 5
)
// Type returns the Handshake Type
func (m MessageCertificateRequest) Type() Type {
return TypeCertificateRequest
}
// Marshal encodes the Handshake
func (m *MessageCertificateRequest) Marshal() ([]byte, error) {
out := []byte{byte(len(m.CertificateTypes))}
for _, v := range m.CertificateTypes {
out = append(out, byte(v))
}
out = append(out, []byte{0x00, 0x00}...)
binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(m.SignatureHashAlgorithms)*2))
for _, v := range m.SignatureHashAlgorithms {
out = append(out, byte(v.Hash))
out = append(out, byte(v.Signature))
}
out = append(out, []byte{0x00, 0x00}...) // Distinguished Names Length
return out, nil
}
// Unmarshal populates the message from encoded data
func (m *MessageCertificateRequest) Unmarshal(data []byte) error {
if len(data) < messageCertificateRequestMinLength {
return errBufferTooSmall
}
offset := 0
certificateTypesLength := int(data[0])
offset++
if (offset + certificateTypesLength) > len(data) {
return errBufferTooSmall
}
for i := 0; i < certificateTypesLength; i++ {
certType := clientcertificate.Type(data[offset+i])
if _, ok := clientcertificate.Types()[certType]; ok {
m.CertificateTypes = append(m.CertificateTypes, certType)
}
}
offset += certificateTypesLength
if len(data) < offset+2 {
return errBufferTooSmall
}
signatureHashAlgorithmsLength := int(binary.BigEndian.Uint16(data[offset:]))
offset += 2
if (offset + signatureHashAlgorithmsLength) > len(data) {
return errBufferTooSmall
}
for i := 0; i < signatureHashAlgorithmsLength; i += 2 {
if len(data) < (offset + i + 2) {
return errBufferTooSmall
}
h := hash.Algorithm(data[offset+i])
s := signature.Algorithm(data[offset+i+1])
if _, ok := hash.Algorithms()[h]; !ok {
continue
} else if _, ok := signature.Algorithms()[s]; !ok {
continue
}
m.SignatureHashAlgorithms = append(m.SignatureHashAlgorithms, signaturehash.Algorithm{Signature: s, Hash: h})
}
return nil
}