summary refs log tree commit diff
path: root/crypto/src/tls/DtlsProtocol.cs
blob: 3d72bca9f63f856ee8d9f974fe3f83b215a1bc1f (plain) (blame)
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using System;
using System.Collections.Generic;
using System.IO;

using Org.BouncyCastle.Utilities;

namespace Org.BouncyCastle.Tls
{
    public abstract class DtlsProtocol
    {
        internal DtlsProtocol()
        {
        }

        /// <exception cref="IOException"/>
        internal virtual void ProcessFinished(byte[] body, byte[] expected_verify_data)
        {
            MemoryStream buf = new MemoryStream(body, false);

            byte[] verify_data = TlsUtilities.ReadFully(expected_verify_data.Length, buf);

            TlsProtocol.AssertEmpty(buf);

            if (!Arrays.ConstantTimeAreEqual(expected_verify_data, verify_data))
                throw new TlsFatalAlert(AlertDescription.handshake_failure);
        }

        /// <exception cref="IOException"/>
        internal static void ApplyMaxFragmentLengthExtension(DtlsRecordLayer recordLayer, short maxFragmentLength)
        {
            if (maxFragmentLength >= 0)
            {
                if (!MaxFragmentLength.IsValid(maxFragmentLength))
                    throw new TlsFatalAlert(AlertDescription.internal_error); 

                int plainTextLimit = 1 << (8 + maxFragmentLength);
                recordLayer.SetPlaintextLimit(plainTextLimit);
            }
        }

        /// <exception cref="IOException"/>
        internal static short EvaluateMaxFragmentLengthExtension(bool resumedSession,
            IDictionary<int, byte[]> clientExtensions, IDictionary<int, byte[]> serverExtensions,
            short alertDescription)
        {
            short maxFragmentLength = TlsExtensionsUtilities.GetMaxFragmentLengthExtension(serverExtensions);
            if (maxFragmentLength >= 0)
            {
                if (!MaxFragmentLength.IsValid(maxFragmentLength)
                    || (!resumedSession && maxFragmentLength != TlsExtensionsUtilities
                        .GetMaxFragmentLengthExtension(clientExtensions)))
                {
                    throw new TlsFatalAlert(alertDescription);
                }
            }
            return maxFragmentLength;
        }

        /// <exception cref="IOException"/>
        internal static byte[] GenerateCertificate(TlsContext context, Certificate certificate, Stream endPointHash)
        {
            MemoryStream buf = new MemoryStream();
            certificate.Encode(context, buf, endPointHash);
            return buf.ToArray();
        }

        /// <exception cref="IOException"/>
        internal static byte[] GenerateSupplementalData(IList<SupplementalDataEntry> supplementalData)
        {
            MemoryStream buf = new MemoryStream();
            TlsProtocol.WriteSupplementalData(buf, supplementalData);
            return buf.ToArray();
        }

        /// <exception cref="IOException"/>
        internal static void SendCertificateMessage(TlsContext context, DtlsReliableHandshake handshake,
            Certificate certificate, Stream endPointHash)
        {
            SecurityParameters securityParameters = context.SecurityParameters;
            if (null != securityParameters.LocalCertificate)
                throw new TlsFatalAlert(AlertDescription.internal_error);

            if (null == certificate)
            {
                certificate = Certificate.EmptyChain;
            }

            byte[] certificateBody = GenerateCertificate(context, certificate, endPointHash);
            handshake.SendMessage(HandshakeType.certificate, certificateBody);

            securityParameters.m_localCertificate = certificate;
        }

        /// <exception cref="IOException"/>
        internal static int ValidateSelectedCipherSuite(int selectedCipherSuite, short alertDescription)
        {
            switch (TlsUtilities.GetEncryptionAlgorithm(selectedCipherSuite))
            {
            case EncryptionAlgorithm.RC4_40:
            case EncryptionAlgorithm.RC4_128:
            case -1:
                throw new TlsFatalAlert(alertDescription);
            default:
                return selectedCipherSuite;
            }
        }
    }
}