Skip to content

Commit 99536fd

Browse files
JoTurkJulia-RomanJuliapixeltreejadey
committed
Parse server cert messages
Co-authored-by: Julia <supa@juliaelena.ro> Co-authored-by: Julia <git@juliapixel.com> Co-authored-by: Jade <jadey@tutanota.com>
1 parent 7c45cb4 commit 99536fd

2 files changed

Lines changed: 131 additions & 10 deletions

File tree

internal/flight/flight13/flighthandlers_client.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,9 @@ func flight3PullProtectedFlight(
384384
) (int, []*dtlsflight.HandshakeCacheItem, bool, *flightParseFailure) {
385385
rules := []dtlsflight.HandshakeCachePullRule{
386386
{Typ: handshake.TypeEncryptedExtensions, Epoch: EpochHandshake, IsClient: false, Optional: false},
387+
{Typ: handshake.TypeCertificateRequest, Epoch: EpochHandshake, IsClient: false, Optional: true},
388+
{Typ: handshake.TypeCertificate, Epoch: EpochHandshake, IsClient: false, Optional: true},
389+
{Typ: handshake.TypeCertificateVerify, Epoch: EpochHandshake, IsClient: false, Optional: true},
387390
{Typ: handshake.TypeFinished, Epoch: EpochHandshake, IsClient: false, Optional: false},
388391
}
389392
pulled := flightCtx.cache.Pull(rules...)
@@ -452,6 +455,12 @@ func unmarshalFlight3ProtectedHandshakeMessage(typ handshake.Type, body []byte)
452455
switch typ {
453456
case handshake.TypeEncryptedExtensions:
454457
msg = &handshake.MessageEncryptedExtensions{}
458+
case handshake.TypeCertificateRequest:
459+
msg = &handshake.MessageCertificateRequest13{}
460+
case handshake.TypeCertificate:
461+
msg = &handshake.MessageCertificate13{}
462+
case handshake.TypeCertificateVerify:
463+
msg = &handshake.MessageCertificateVerify{}
455464
case handshake.TypeFinished:
456465
msg = &handshake.MessageFinished{}
457466
default:
@@ -476,11 +485,23 @@ func handleFlight3ProtectedHandshake(
476485
}
477486

478487
func protectedFlightParseFailure(err error) *flightParseFailure {
479-
if errors.Is(err, dtlserrors.ErrVerifyDataMismatch) {
488+
switch {
489+
case errors.Is(err, dtlserrors.ErrVerifyDataMismatch):
480490
return newFlightParseFailure(alert.HandshakeFailure, err)
491+
case errors.Is(err, dtlserrors.ErrCertificateVerifyNoCertificate):
492+
return newFlightParseFailure(alert.NoCertificate, err)
493+
case errors.Is(err, dtlserrors.ErrKeySignatureMismatch),
494+
errors.Is(err, dtlserrors.ErrInvalidCertificate),
495+
errors.Is(err, dtlserrors.ErrClientCertificateNotVerified),
496+
errors.Is(err, dtlserrors.ErrInvalidCertificateOID),
497+
errors.Is(err, dtlserrors.ErrInvalidCertificateSignatureAlgorithm),
498+
errors.Is(err, dtlserrors.ErrNotAcceptableCertificateChain):
499+
return newFlightParseFailure(alert.BadCertificate, err)
500+
case errors.Is(err, dtlserrors.ErrNoAvailableSignatureSchemes):
501+
return newFlightParseFailure(alert.InsufficientSecurity, err)
502+
default:
503+
return newFlightParseFailure(alert.InternalError, err)
481504
}
482-
483-
return newFlightParseFailure(alert.InternalError, err)
484505
}
485506

486507
func handleFlight3InboundHandshake(

internal/handshake/protected_flight13.go

Lines changed: 107 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
dtlsconfig "github.com/pion/dtls/v3/internal/config"
88
dtlserrors "github.com/pion/dtls/v3/internal/errors"
99
dtlsflight "github.com/pion/dtls/v3/internal/flight"
10+
dtlscrypto "github.com/pion/dtls/v3/internal/handshakecrypto"
1011
dtlsstate "github.com/pion/dtls/v3/internal/state"
1112
"github.com/pion/dtls/v3/pkg/protocol/handshake"
1213
)
@@ -16,7 +17,7 @@ import (
1617
func VerifyAndAppendProtectedHandshakeCacheItems13(
1718
transcript *Transcript,
1819
state *dtlsstate.State13,
19-
_ *dtlsconfig.HandshakeConfig,
20+
cfg *dtlsconfig.HandshakeConfig,
2021
cipherSuite dtlsconfig.CipherSuite,
2122
items []*dtlsflight.HandshakeCacheItem,
2223
) error {
@@ -32,6 +33,7 @@ func VerifyAndAppendProtectedHandshakeCacheItems13(
3233
flight := protectedHandshakeFlight13{
3334
transcript: working,
3435
state: state,
36+
cfg: cfg,
3537
cipherSuite: cipherSuite,
3638
}
3739
for _, item := range items {
@@ -43,15 +45,26 @@ func VerifyAndAppendProtectedHandshakeCacheItems13(
4345
return dtlserrors.ErrVerifyDataMismatch
4446
}
4547

46-
return transcript.replaceWith(working)
48+
if err := transcript.replaceWith(working); err != nil {
49+
return err
50+
}
51+
if flight.hasCertificate {
52+
state.PeerCertificates = flight.peerCertificates
53+
}
54+
55+
return nil
4756
}
4857

4958
type protectedHandshakeFlight13 struct {
5059
transcript *Transcript
5160
state *dtlsstate.State13
61+
cfg *dtlsconfig.HandshakeConfig
5262
cipherSuite dtlsconfig.CipherSuite
5363

54-
hasFinished bool
64+
peerCertificates [][]byte
65+
hasCertificate bool
66+
hasCertificateVerify bool
67+
hasFinished bool
5568
}
5669

5770
func (f *protectedHandshakeFlight13) process(item *dtlsflight.HandshakeCacheItem) error {
@@ -60,19 +73,56 @@ func (f *protectedHandshakeFlight13) process(item *dtlsflight.HandshakeCacheItem
6073
return err
6174
}
6275

63-
finished, ok := hs.Message.(*handshake.MessageFinished)
64-
if ok {
65-
return f.processFinished(item, hs, finished)
76+
switch msg := hs.Message.(type) {
77+
case *handshake.MessageCertificate13:
78+
return f.processCertificate(item, hs, msg)
79+
case *handshake.MessageCertificateVerify:
80+
return f.processCertificateVerify(item, hs, msg)
81+
case *handshake.MessageFinished:
82+
return f.processFinished(item, hs, msg)
83+
default:
84+
return f.append(item, hs)
85+
}
86+
}
87+
88+
func (f *protectedHandshakeFlight13) processCertificate(
89+
item *dtlsflight.HandshakeCacheItem,
90+
h *handshake.Handshake,
91+
certificate *handshake.MessageCertificate13,
92+
) error {
93+
f.hasCertificate = true
94+
f.peerCertificates = rawCertificatesFromCertificate13(certificate)
95+
if len(f.peerCertificates) == 0 {
96+
return dtlserrors.ErrInvalidCertificate
97+
}
98+
99+
return f.append(item, h)
100+
}
101+
102+
func (f *protectedHandshakeFlight13) processCertificateVerify(
103+
item *dtlsflight.HandshakeCacheItem,
104+
h *handshake.Handshake,
105+
verify *handshake.MessageCertificateVerify,
106+
) error {
107+
if !f.hasCertificate {
108+
return dtlserrors.ErrCertificateVerifyNoCertificate
109+
}
110+
if err := verifyServerCertificateVerify13(f.transcript, f.cfg, verify, f.peerCertificates); err != nil {
111+
return err
66112
}
113+
f.hasCertificateVerify = true
67114

68-
return f.append(item, hs)
115+
return f.append(item, h)
69116
}
70117

71118
func (f *protectedHandshakeFlight13) processFinished(
72119
item *dtlsflight.HandshakeCacheItem,
73120
h *handshake.Handshake,
74121
finished *handshake.MessageFinished,
75122
) error {
123+
if f.hasCertificate && !f.hasCertificateVerify {
124+
return dtlserrors.ErrClientCertificateNotVerified
125+
}
76126
if err := verifyServerFinished13(f.transcript, f.state, f.cipherSuite, finished); err != nil {
77127
return err
78128
}
@@ -127,6 +177,12 @@ func protectedHandshakeMessage13(typ handshake.Type, body []byte) (handshake.Mes
127177
switch typ {
128178
case handshake.TypeEncryptedExtensions:
129179
msg = &handshake.MessageEncryptedExtensions{}
180+
case handshake.TypeCertificateRequest:
181+
msg = &handshake.MessageCertificateRequest13{}
182+
case handshake.TypeCertificate:
183+
msg = &handshake.MessageCertificate13{}
184+
case handshake.TypeCertificateVerify:
185+
msg = &handshake.MessageCertificateVerify{}
130186
case handshake.TypeFinished:
131187
msg = &handshake.MessageFinished{}
132188
default:
@@ -139,6 +195,50 @@ func protectedHandshakeMessage13(typ handshake.Type, body []byte) (handshake.Mes
139195
return msg, nil
140196
}
141197

198+
func rawCertificatesFromCertificate13(certificate *handshake.MessageCertificate13) [][]byte {
199+
out := make([][]byte, 0, len(certificate.CertificateList))
200+
for _, entry := range certificate.CertificateList {
201+
out = append(out, append([]byte(nil), entry.CertificateData...))
202+
}
203+
204+
return out
205+
}
206+
207+
func verifyServerCertificateVerify13(
208+
transcript *Transcript,
209+
cfg *dtlsconfig.HandshakeConfig,
210+
verify *handshake.MessageCertificateVerify,
211+
peerCertificates [][]byte,
212+
) error {
213+
if cfg == nil {
214+
return dtlserrors.ErrNoAvailableSignatureSchemes
215+
}
216+
var validSignatureScheme bool
217+
for _, alg := range cfg.LocalSignatureSchemes {
218+
if alg.Hash == verify.HashAlgorithm && alg.Signature == verify.SignatureAlgorithm {
219+
validSignatureScheme = true
220+
221+
break
222+
}
223+
}
224+
if !validSignatureScheme {
225+
return dtlserrors.ErrNoAvailableSignatureSchemes
226+
}
227+
228+
input, err := CertificateVerifyInputFromTranscript(false, transcript)
229+
if err != nil {
230+
return err
231+
}
232+
233+
return dtlscrypto.VerifyCertificateVerify(
234+
input,
235+
verify.HashAlgorithm,
236+
verify.SignatureAlgorithm,
237+
verify.Signature,
238+
peerCertificates,
239+
)
240+
}
241+
142242
func verifyServerFinished13(
143243
transcript *Transcript,
144244
state *dtlsstate.State13,

0 commit comments

Comments
 (0)