Kaynağa Gözat

Adds structure for certificate_request in TLS 1.3

* TLS 1.3 requries specific marshalling/unmarshalling of data
* This code should probably be rewritten in order ot use
  a bit cleaner approach for dealing with bytes
tls13
Henry D. Case 6 yıl önce
committed by Henry Dorsett Case
ebeveyn
işleme
e62ddc004c
2 değiştirilmiş dosya ile 223 ekleme ve 0 silme
  1. +210
    -0
      handshake_messages.go
  2. +13
    -0
      handshake_messages_test.go

+ 210
- 0
handshake_messages.go Dosyayı Görüntüle

@@ -36,6 +36,53 @@ type clientHelloMsg struct {
earlyData bool
}

// Helpers

// Marshalling of signature_algorithms extension see https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
// for more details. Extension is serialized in data buffer
// Function advances data slice and returns it, so that it can be used for further processing
func marshallExtensionSignatureAlgorithms(data []byte, sigSchemes []SignatureScheme) ([]byte) {
data[0] = byte(extensionSignatureAlgorithms >> 8)
data[1] = byte(extensionSignatureAlgorithms)
l := 2 + 2*len(sigSchemes)
data[2] = byte(l >> 8)
data[3] = byte(l)
data = data[4:]

l -= 2
data[0] = byte(l >> 8)
data[1] = byte(l)
data = data[2:]
for _, sigAlgo := range sigSchemes {
data[0] = byte(sigAlgo >> 8)
data[1] = byte(sigAlgo)
data = data[2:]
}
return data
}

// Unmrshalling of signature_algorithms extension see https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
// for more details.
// In case of error function returns alertDecoderError otherwise filled SignatureScheme slice and alertSuccess
func unmarshallExtensionSignatureAlgorithms(data []byte, length int) ([]SignatureScheme, alert) {
if length < 2 || length&1 != 0 {
return nil, alertDecodeError
}

l := int(data[0])<<8 | int(data[1])
if l != length-2 {
return nil, alertDecodeError
}
n := l / 2
d := data[2:]
sigSchemes := make([]SignatureScheme, n)
for i := range sigSchemes {
sigSchemes[i] = SignatureScheme(d[0])<<8 | SignatureScheme(d[1])
d = d[2:]
}
return sigSchemes, alertSuccess
}

func (m *clientHelloMsg) equal(i interface{}) bool {
m1, ok := i.(*clientHelloMsg)
if !ok {
@@ -2030,6 +2077,169 @@ func (m *certificateRequestMsg) unmarshal(data []byte) alert {
return alertSuccess
}

type certificateRequestMsg13 struct {
raw []byte

requestContext []byte
supportedSignatureAlgorithms []SignatureScheme
certificateAuthorities [][]byte
}

func (m *certificateRequestMsg13) equal(i interface{}) bool {
m1, ok := i.(*certificateRequestMsg13)
return ok &&
bytes.Equal(m.raw, m1.raw) &&
bytes.Equal(m.requestContext, m1.requestContext) &&
eqByteSlices(m.certificateAuthorities, m1.certificateAuthorities) &&
eqSignatureAlgorithms(m.supportedSignatureAlgorithms, m1.supportedSignatureAlgorithms)
}

func (m *certificateRequestMsg13) marshal() (x []byte) {
if m.raw != nil {
return m.raw
}

// See https://tools.ietf.org/html/draft-ietf-tls-tls13-21#section-4.3.2
length := 1 + len(m.requestContext)
numExtensions := 1
extensionsLength := 2 + 2*len(m.supportedSignatureAlgorithms)

casLength := 0
if len(m.certificateAuthorities) > 0 {
for _, ca := range m.certificateAuthorities {
casLength += 2 + len(ca)
}
extensionsLength += 2 + casLength
numExtensions++
}

extensionsLength += 4 * numExtensions
length += 2 + extensionsLength

x = make([]byte, 4+length)
x[0] = typeCertificateRequest
x[1] = uint8(length >> 16)
x[2] = uint8(length >> 8)
x[3] = uint8(length)

x[4] = uint8(len(m.requestContext))
copy(x[5:], m.requestContext)
z := x[5+len(m.requestContext):]

z[0] = byte(extensionsLength >> 8)
z[1] = byte(extensionsLength)
z = z[2:]

// TODO: this function should be reused by CH
z = marshallExtensionSignatureAlgorithms(z, m.supportedSignatureAlgorithms)
// certificate_authorities
if casLength > 0 {
z[0] = byte(extensionCAs >> 8)
z[1] = byte(extensionCAs)
l := 2 + casLength
z[2] = byte(l >> 8)
z[3] = byte(l)
z = z[4:]

z[0] = uint8(casLength >> 8)
z[1] = uint8(casLength)
z = z[2:]
for _, ca := range m.certificateAuthorities {
z[0] = uint8(len(ca) >> 8)
z[1] = uint8(len(ca))
z = z[2:]
copy(z, ca)
z = z[len(ca):]
}
}

m.raw = x
return
}

func (m *certificateRequestMsg13) unmarshal(data []byte) alert {
m.raw = data
m.supportedSignatureAlgorithms = nil
m.certificateAuthorities = nil

if len(data) < 5 {
return alertDecodeError
}

length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
if uint32(len(data))-4 != length {
return alertDecodeError
}

ctxLen := data[4]
if len(data) < 5+int(ctxLen)+2 {
return alertDecodeError
}
m.requestContext = data[5 : 5+ctxLen]
data = data[5+ctxLen:]

extensionsLength := int(data[0])<<8 | int(data[1])
data = data[2:]
if len(data) != extensionsLength {
return alertDecodeError
}

for len(data) != 0 {
if len(data) < 4 {
return alertDecodeError
}
extension := uint16(data[0])<<8 | uint16(data[1])
length := int(data[2])<<8 | int(data[3])
data = data[4:]
if len(data) < length {
return alertDecodeError
}

switch extension {
case extensionSignatureAlgorithms:
// TODO: unmarshallExtensionSignatureAlgorithms should be shared with CH and pre-1.3 CV
// https://tools.ietf.org/html/draft-ietf-tls-tls13-21#section-4.2.3
var err alert
m.supportedSignatureAlgorithms, err = unmarshallExtensionSignatureAlgorithms(data, length)
if err != alertSuccess {
return err
}
case extensionCAs:
// TODO DRY: share code with CH
if length < 2 {
return alertDecodeError
}
l := int(data[0])<<8 | int(data[1])
if l != length-2 || l < 3 {
return alertDecodeError
}
cas := make([]byte, l)
copy(cas, data[2:])
m.certificateAuthorities = nil
for len(cas) > 0 {
if len(cas) < 2 {
return alertDecodeError
}
caLen := uint16(cas[0])<<8 | uint16(cas[1])
cas = cas[2:]

if len(cas) < int(caLen) {
return alertDecodeError
}

m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
cas = cas[caLen:]
}
}
data = data[length:]
}

if len(m.supportedSignatureAlgorithms) == 0 {
return alertDecodeError
}
return alertSuccess
}

type certificateVerifyMsg struct {
raw []byte
hasSignatureAndHash bool


+ 13
- 0
handshake_messages_test.go Dosyayı Görüntüle

@@ -20,6 +20,7 @@ var tests = []interface{}{

&certificateMsg{},
&certificateRequestMsg{},
&certificateRequestMsg13{},
&certificateVerifyMsg{},
&certificateStatusMsg{},
&clientKeyExchangeMsg{},
@@ -272,6 +273,18 @@ func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value
return reflect.ValueOf(m)
}

func (*certificateRequestMsg13) Generate(rand *rand.Rand, size int) reflect.Value {
m := &certificateRequestMsg13{}
m.requestContext = randomBytes(rand.Intn(5), rand)
m.supportedSignatureAlgorithms = supportedSignatureAlgorithms
numCAs := rand.Intn(100)
m.certificateAuthorities = make([][]byte, numCAs)
for i := 0; i < numCAs; i++ {
m.certificateAuthorities[i] = randomBytes(rand.Intn(15)+1, rand)
}
return reflect.ValueOf(m)
}

func (*certificateVerifyMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &certificateVerifyMsg{}
m.signature = randomBytes(rand.Intn(15)+1, rand)


Yükleniyor…
İptal
Kaydet