blob: 59320a717066cb299c20a74e2a6d31f5bf7329bd (
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
109
110
111
112
113
114
115
116
117
|
using System;
using System.IO;
using Org.BouncyCastle.Tls.Crypto;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Tls
{
public abstract class TlsEccUtilities
{
/// <exception cref="IOException"/>
public static TlsECConfig CreateNamedECConfig(TlsContext context, int namedGroup)
{
if (NamedGroup.GetCurveBits(namedGroup) < 1)
throw new TlsFatalAlert(AlertDescription.internal_error);
return new TlsECConfig(namedGroup);
}
public static int GetMinimumCurveBits(int cipherSuite)
{
/*
* NOTE: This mechanism was added to support a minimum bit-size requirement mooted in early
* drafts of RFC 8442. This requirement was removed in later drafts, so this mechanism is
* currently somewhat trivial.
*/
return IsEccCipherSuite(cipherSuite) ? 1 : 0;
}
public static bool IsEccCipherSuite(int cipherSuite)
{
switch (TlsUtilities.GetKeyExchangeAlgorithm(cipherSuite))
{
case KeyExchangeAlgorithm.ECDH_anon:
case KeyExchangeAlgorithm.ECDH_ECDSA:
case KeyExchangeAlgorithm.ECDH_RSA:
case KeyExchangeAlgorithm.ECDHE_ECDSA:
case KeyExchangeAlgorithm.ECDHE_PSK:
case KeyExchangeAlgorithm.ECDHE_RSA:
return true;
default:
return false;
}
}
/// <exception cref="IOException"/>
public static void CheckPointEncoding(int namedGroup, byte[] encoding)
{
if (TlsUtilities.IsNullOrEmpty(encoding))
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
switch (namedGroup)
{
case NamedGroup.x25519:
case NamedGroup.x448:
return;
}
switch (encoding[0])
{
case 0x04: // uncompressed
return;
case 0x00: // infinity
case 0x02: // compressed
case 0x03: // compressed
case 0x06: // hybrid
case 0x07: // hybrid
default:
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
}
/// <exception cref="IOException"/>
public static TlsECConfig ReceiveECDHConfig(TlsContext context, Stream input)
{
short curveType = TlsUtilities.ReadUint8(input);
if (curveType != ECCurveType.named_curve)
throw new TlsFatalAlert(AlertDescription.handshake_failure);
int namedGroup = TlsUtilities.ReadUint16(input);
if (NamedGroup.RefersToAnECDHCurve(namedGroup))
{
int[] clientSupportedGroups = context.SecurityParameters.ClientSupportedGroups;
if (null == clientSupportedGroups || Arrays.Contains(clientSupportedGroups, namedGroup))
return new TlsECConfig(namedGroup);
}
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
/// <exception cref="IOException"/>
public static void WriteECConfig(TlsECConfig ecConfig, Stream output)
{
WriteNamedECParameters(ecConfig.NamedGroup, output);
}
/// <exception cref="IOException"/>
public static void WriteNamedECParameters(int namedGroup, Stream output)
{
if (!NamedGroup.RefersToASpecificCurve(namedGroup))
{
/*
* RFC 4492 5.4. All those values of NamedCurve are allowed that refer to a specific
* curve. Values of NamedCurve that indicate support for a class of explicitly defined
* curves are not allowed here [...].
*/
throw new TlsFatalAlert(AlertDescription.internal_error);
}
TlsUtilities.WriteUint8(ECCurveType.named_curve, output);
TlsUtilities.CheckUint16(namedGroup);
TlsUtilities.WriteUint16(namedGroup, output);
}
}
}
|