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
|
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math.EC;
namespace Org.BouncyCastle.Crypto.Tls
{
/**
* ECDHE key exchange (see RFC 4492)
*/
internal class TlsECDheKeyExchange : TlsECDHKeyExchange
{
internal TlsECDheKeyExchange(TlsClientContext context, int keyExchange)
: base(context, keyExchange)
{
}
public override void SkipServerKeyExchange()
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
public override void ProcessServerKeyExchange(Stream input)
{
SecurityParameters securityParameters = context.SecurityParameters;
ISigner signer = InitSigner(tlsSigner, securityParameters);
Stream sigIn = new SignerStream(input, signer, null);
byte curveType = TlsUtilities.ReadUint8(sigIn);
ECDomainParameters curve_params;
// Currently, we only support named curves
if (curveType == ECCurveType.named_curve)
{
int namedCurve = TlsUtilities.ReadUint16(sigIn);
// TODO Check namedCurve is one we offered?
curve_params = NamedCurveHelper.GetECParameters(namedCurve);
}
else
{
// TODO Add support for explicit curve parameters (read from sigIn)
throw new TlsFatalAlert(AlertDescription.handshake_failure);
}
byte[] publicBytes = TlsUtilities.ReadOpaque8(sigIn);
byte[] sigByte = TlsUtilities.ReadOpaque16(input);
if (!signer.VerifySignature(sigByte))
{
throw new TlsFatalAlert(AlertDescription.decrypt_error);
}
// TODO Check curve_params not null
ECPoint Q = curve_params.Curve.DecodePoint(publicBytes);
this.ecAgreeServerPublicKey = ValidateECPublicKey(new ECPublicKeyParameters(Q, curve_params));
}
public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
{
/*
* RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable
* with ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is
* prohibited because the use of a long-term ECDH client key would jeopardize the
* forward secrecy property of these algorithms.
*/
byte[] types = certificateRequest.CertificateTypes;
foreach (byte type in types)
{
switch (type)
{
case ClientCertificateType.rsa_sign:
case ClientCertificateType.dss_sign:
case ClientCertificateType.ecdsa_sign:
break;
default:
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
}
}
public override void ProcessClientCredentials(TlsCredentials clientCredentials)
{
if (clientCredentials is TlsSignerCredentials)
{
// OK
}
else
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
}
protected virtual ISigner InitSigner(TlsSigner tlsSigner, SecurityParameters securityParameters)
{
ISigner signer = tlsSigner.CreateVerifyer(this.serverPublicKey);
signer.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length);
signer.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length);
return signer;
}
}
}
|