-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandshake_message_certificate_request.go
91 lines (75 loc) · 2.44 KB
/
handshake_message_certificate_request.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package dtls
import (
"encoding/binary"
)
/*
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).
*/
type handshakeMessageCertificateRequest struct {
certificateTypes []clientCertificateType
signatureHashAlgorithms []signatureHashAlgorithm
}
const (
handshakeMessageCertificateRequestMinLength = 5
)
func (h handshakeMessageCertificateRequest) handshakeType() handshakeType {
return handshakeTypeCertificateRequest
}
func (h *handshakeMessageCertificateRequest) Marshal() ([]byte, error) {
out := []byte{byte(len(h.certificateTypes))}
for _, v := range h.certificateTypes {
out = append(out, byte(v))
}
out = append(out, []byte{0x00, 0x00}...)
binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(h.signatureHashAlgorithms)*2))
for _, v := range h.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
}
func (h *handshakeMessageCertificateRequest) Unmarshal(data []byte) error {
if len(data) < handshakeMessageCertificateRequestMinLength {
return errBufferTooSmall
}
offset := 0
certificateTypesLength := int(data[0])
offset++
if (offset + certificateTypesLength) > len(data) {
return errBufferTooSmall
}
for i := 0; i < certificateTypesLength; i++ {
certType := clientCertificateType(data[offset+i])
if _, ok := clientCertificateTypes[certType]; ok {
h.certificateTypes = append(h.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
}
hash := hashAlgorithm(data[offset+i])
signature := signatureAlgorithm(data[offset+i+1])
if _, ok := hashAlgorithms[hash]; !ok {
continue
} else if _, ok := signatureAlgorithms[signature]; !ok {
continue
}
h.signatureHashAlgorithms = append(h.signatureHashAlgorithms, signatureHashAlgorithm{signature: signature, hash: hash})
}
return nil
}