xtool/contrib/fundamentals/TLS/flcTLSKeyExchangeParams.pas

886 lines
32 KiB
ObjectPascal

{******************************************************************************}
{ }
{ Library: Fundamentals TLS }
{ File name: flcTLSKeyExchangeParams.pas }
{ File version: 5.04 }
{ Description: TLS Key Exchange Parameters }
{ }
{ Copyright: Copyright (c) 2008-2020, David J Butler }
{ All rights reserved. }
{ Redistribution and use in source and binary forms, with }
{ or without modification, are permitted provided that }
{ the following conditions are met: }
{ Redistributions of source code must retain the above }
{ copyright notice, this list of conditions and the }
{ following disclaimer. }
{ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND }
{ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED }
{ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED }
{ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A }
{ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL }
{ THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, }
{ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR }
{ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, }
{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF }
{ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) }
{ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER }
{ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING }
{ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE }
{ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE }
{ POSSIBILITY OF SUCH DAMAGE. }
{ }
{ Github: https://github.com/fundamentalslib }
{ E-mail: fundamentals.library at gmail.com }
{ }
{ References: }
{ }
{ RFC 4492 - Elliptic Curve Cryptography (ECC) Cipher Suites for }
{ Transport Layer Security (TLS) }
{ https://tools.ietf.org/html/rfc4492 }
{ }
{ RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites for }
{ Transport Layer Security (TLS) Versions 1.2 and Earlier }
{ https://tools.ietf.org/html/rfc8422 }
{ }
{ https://ldapwiki.com/wiki/Key-Exchange }
{ https://crypto.stackexchange.com/questions/26354/whats-the-structure-of-server-key-exchange-message-during-tls-handshake }
{ https://security.stackexchange.com/questions/8343/what-key-exchange-mechanism-should-be-used-in-tls }
{ }
{ Revision history: }
{ }
{ 2008/01/18 0.01 Initial development. }
{ 2020/05/09 5.02 Create flcTLSKeyExchangeParams unit from }
{ flcTLSUtils unit. }
{ 2020/05/11 5.03 TLSDigitallySigned, SignTLSServerKeyExchangeDH_RSA. }
{ 2020/05/19 5.04 Sign/Verify RSA authentication signature for DHE_RSA. }
{ }
{******************************************************************************}
{$INCLUDE flcTLS.inc}
unit flcTLSKeyExchangeParams;
interface
uses
{ System }
SysUtils,
{ Utils }
flcStdTypes,
{ Cipher }
flcCipherRSA,
{ TLS }
flcTLSAlgorithmTypes;
{ }
{ ServerDHParams }
{ Ephemeral DH parameters }
{ }
type
TTLSServerDHParams = record
dh_p : RawByteString;
dh_g : RawByteString;
dh_Ys : RawByteString;
end;
procedure AssignTLSServerDHParams(var ServerDHParams: TTLSServerDHParams;
const p, g, Ys: RawByteString);
function EncodeTLSServerDHParams(
var Buffer; const Size: Integer;
const ServerDHParams: TTLSServerDHParams): Integer;
function DecodeTLSServerDHParams(
const Buffer; const Size: Integer;
var ServerDHParams: TTLSServerDHParams): Integer;
{ }
{ ServerRSAParams }
{ }
type
TTLSServerRSAParams = record
rsa_modulus : RawByteString;
rsa_exponent : RawByteString;
end;
procedure AssignTLSServerRSAParams(var ServerRSAParams: TTLSServerRSAParams;
const modulus, exponent: RawByteString);
function EncodeTLSServerRSAParams(
var Buffer; const Size: Integer;
const ServerRSAParams: TTLSServerRSAParams): Integer;
function DecodeTLSServerRSAParams(
const Buffer; const Size: Integer;
var ServerRSAParams: TTLSServerRSAParams): Integer;
{ }
{ ServerECDHParams }
{ }
{ }
{ ServerParamsHashBuf }
{ }
type
TTLSClientServerRandom = array[0..31] of Byte;
PTLSClientServerRandom = ^TTLSClientServerRandom;
function EncodeTLSServerDHParamsHashBuf(
var Buffer; const Size: Integer;
const client_random: TTLSClientServerRandom;
const server_random: TTLSClientServerRandom;
const Params: TTLSServerDHParams): Integer;
{ }
{ SignedStruct }
{ }
type
TTLSRSASignedStruct = packed record
md5_hash : array[0..15] of Byte;
sha_hash : array[0..19] of Byte;
end;
TTLSDSASignedStruct = packed record
sha_hash : array[0..19] of Byte;
end;
{ }
{ DigitallySigned }
{ }
{ SignatureAndHashAlgorithm algorithm; }
{ opaque signature<0..2^16-1>; }
{ }
type
TTLSDigitallySigned = record
Algorithm : TTLSSignatureAndHashAlgorithm;
Signature : RawByteString;
end;
function EncodeTLSDigitallySigned(
var Buffer; const Size: Integer;
const Signed: TTLSDigitallySigned): Integer;
function DecodeTLSDigitallySigned(
const Buffer; const Size: Integer;
var Signed: TTLSDigitallySigned): Integer;
{ }
{ ServerKeyExchange }
{ }
type
TTLSServerKeyExchange = record
DHParams : TTLSServerDHParams;
RSAParams : TTLSServerRSAParams;
SignedParams : TTLSDigitallySigned;
end;
procedure InitTLSServerKeyExchange(var ServerKeyExchange: TTLSServerKeyExchange);
procedure AssignTLSServerKeyExchangeDHParams(
var ServerKeyExchange: TTLSServerKeyExchange;
const p, g, Ys: RawByteString);
function EncodeTLSServerKeyExchange(
var Buffer; const Size: Integer;
const KeyExchangeAlgorithm: TTLSKeyExchangeAlgorithm;
const ServerKeyExchange: TTLSServerKeyExchange): Integer;
function DecodeTLSServerKeyExchange(
const Buffer; const Size: Integer;
const KeyExchangeAlgorithm: TTLSKeyExchangeAlgorithm;
var ServerKeyExchange: TTLSServerKeyExchange): Integer;
procedure SignTLSServerKeyExchangeDH_RSA(
var ServerKeyExchange: TTLSServerKeyExchange;
const client_random : TTLSClientServerRandom;
const server_random : TTLSClientServerRandom;
const RSAPrivateKey: TRSAPrivateKey);
function VerifyTLSServerKeyExchangeDH_RSA(
const ServerKeyExchange: TTLSServerKeyExchange;
const client_random : TTLSClientServerRandom;
const server_random : TTLSClientServerRandom;
const RSAPublicKey: TRSAPublicKey): Boolean;
{ }
{ ClientDiffieHellmanPublic }
{ }
type
TTLSClientDiffieHellmanPublic = record
PublicValueEncodingExplicit : Boolean;
dh_Yc : RawByteString;
end;
function EncodeTLSClientDiffieHellmanPublic(
var Buffer; const Size: Integer;
const ClientDiffieHellmanPublic: TTLSClientDiffieHellmanPublic): Integer;
function DecodeTLSClientDiffieHellmanPublic(
const Buffer; const Size: Integer;
const PublicValueEncodingExplicit: Boolean;
var ClientDiffieHellmanPublic: TTLSClientDiffieHellmanPublic): Integer;
{ }
{ ClientKeyExchange }
{ }
type
TTLSClientKeyExchange = record
EncryptedPreMasterSecret : RawByteString;
ClientDiffieHellmanPublic : TTLSClientDiffieHellmanPublic;
end;
function EncodeTLSClientKeyExchange(
var Buffer; const Size: Integer;
const KeyExchangeAlgorithm: TTLSKeyExchangeAlgorithm;
const ClientKeyExchange: TTLSClientKeyExchange): Integer;
function DecodeTLSClientKeyExchange(
const Buffer; const Size: Integer;
const KeyExchangeAlgorithm: TTLSKeyExchangeAlgorithm;
const PublicValueEncodingExplicit: Boolean;
var ClientKeyExchange: TTLSClientKeyExchange): Integer;
implementation
uses
{ Utils }
flcHash,
flcHugeInt,
{ TLS }
flcTLSAlert,
flcTLSErrors,
flcTLSOpaqueEncoding;
{ }
{ ServerDHParams }
{ Ephemeral DH parameters }
{ }
{ struct }
{ dh_p : opaque <1..2^16-1>; }
{ dh_g : opaque <1..2^16-1>; }
{ dh_Ys : opaque <1..2^16-1>; }
{ }
procedure AssignTLSServerDHParams(var ServerDHParams: TTLSServerDHParams;
const p, g, Ys: RawByteString);
begin
ServerDHParams.dh_p := p;
ServerDHParams.dh_g := g;
ServerDHParams.dh_Ys := Ys;
end;
function EncodeTLSServerDHParams(
var Buffer; const Size: Integer;
const ServerDHParams: TTLSServerDHParams): Integer;
var P : PByte;
N, L : Integer;
begin
Assert(Size >= 0);
if (ServerDHParams.dh_p = '') or
(ServerDHParams.dh_g = '') or
(ServerDHParams.dh_Ys = '') then
raise ETLSError.Create(TLSError_InvalidParameter);
N := Size;
P := @Buffer;
// dh_p
L := EncodeTLSOpaque16(P^, N, ServerDHParams.dh_p);
Dec(N, L);
Inc(P, L);
// dh_g
L := EncodeTLSOpaque16(P^, N, ServerDHParams.dh_g);
Dec(N, L);
Inc(P, L);
// dh_Ys
L := EncodeTLSOpaque16(P^, N, ServerDHParams.dh_Ys);
Dec(N, L);
Result := Size - N;
end;
function DecodeTLSServerDHParams(
const Buffer; const Size: Integer;
var ServerDHParams: TTLSServerDHParams): Integer;
var P : PByte;
N, L : Integer;
begin
Assert(Size >= 0);
N := Size;
P := @Buffer;
// dh_p
L := DecodeTLSOpaque16(P^, N, ServerDHParams.dh_p);
Dec(N, L);
Inc(P, L);
// dh_g
L := DecodeTLSOpaque16(P^, N, ServerDHParams.dh_g);
Dec(N, L);
Inc(P, L);
// dh_Ys
L := DecodeTLSOpaque16(P^, N, ServerDHParams.dh_Ys);
Dec(N, L);
Result := Size - N;
end;
{ }
{ ServerRSAParams }
{ }
{ struct }
{ rsa_modulus : opaque <1..2^16-1>; }
{ rsa_exponent : opaque <1..2^16-1>; }
{ }
procedure AssignTLSServerRSAParams(var ServerRSAParams: TTLSServerRSAParams;
const modulus, exponent: RawByteString);
begin
ServerRSAParams.rsa_modulus := modulus;
ServerRSAParams.rsa_exponent := exponent;
end;
function EncodeTLSServerRSAParams(
var Buffer; const Size: Integer;
const ServerRSAParams: TTLSServerRSAParams): Integer;
var P : PByte;
N, L : Integer;
begin
Assert(Size >= 0);
if (ServerRSAParams.rsa_modulus = '') or
(ServerRSAParams.rsa_exponent = '') then
raise ETLSError.Create(TLSError_InvalidParameter);
N := Size;
P := @Buffer;
// rsa_modulus
L := EncodeTLSOpaque16(P^, N, ServerRSAParams.rsa_modulus);
Dec(N, L);
Inc(P, L);
// rsa_exponent
L := EncodeTLSOpaque16(P^, N, ServerRSAParams.rsa_exponent);
Dec(N, L);
Result := Size - N;
end;
function DecodeTLSServerRSAParams(
const Buffer; const Size: Integer;
var ServerRSAParams: TTLSServerRSAParams): Integer;
var P : PByte;
N, L : Integer;
begin
Assert(Size >= 0);
N := Size;
P := @Buffer;
// rsa_modulus
L := DecodeTLSOpaque16(P^, N, ServerRSAParams.rsa_modulus);
Dec(N, L);
Inc(P, L);
// rsa_exponent
L := DecodeTLSOpaque16(P^, N, ServerRSAParams.rsa_exponent);
Dec(N, L);
Result := Size - N;
end;
{ }
{ ECParameters }
{ }
type
TTLSECParameters = record
CurveType : TTLSECCurveType;
NamedCurve : TTLSNamedCurve;
end;
(*
ECCurveType curve_type;
select (curve_type) {
case explicit_prime:
opaque prime_p <1..2^8-1>;
ECCurve curve;
ECPoint base;
opaque order <1..2^8-1>;
opaque cofactor <1..2^8-1>;
case explicit_char2:
uint16 m;
ECBasisType basis;
select (basis) {
case ec_trinomial:
opaque k <1..2^8-1>;
case ec_pentanomial:
opaque k1 <1..2^8-1>;
opaque k2 <1..2^8-1>;
opaque k3 <1..2^8-1>;
};
ECCurve curve;
ECPoint base;
opaque order <1..2^8-1>;
opaque cofactor <1..2^8-1>;
case named_curve:
NamedCurve namedcurve;
};
}
*)
{ }
{ ECPoint }
{ }
{ opaque point <1..2^8-1>; }
{ }
type
TTLSECPoint = array of Byte;
{ }
{ ServerECDHParams }
{ }
{ ECParameters curve_params; }
{ ECPoint public; }
{ }
type
TTLSServerECDHParams = record
CurveParams : TTLSECParameters;
PublicKey : TTLSECPoint;
end;
{ }
{ ServerParamsHashBuf }
{ }
function EncodeTLSServerDHParamsHashBuf(
var Buffer; const Size: Integer;
const client_random: TTLSClientServerRandom;
const server_random: TTLSClientServerRandom;
const Params: TTLSServerDHParams): Integer;
var P : PByte;
N, L : Integer;
begin
N := Size;
P := @Buffer;
Dec(N, 64);
if N < 0 then
raise ETLSError.Create(TLSError_InvalidBuffer);
Move(client_random, P^, 32);
Inc(P, 32);
Move(server_random, P^, 32);
Inc(P, 32);
L := EncodeTLSServerDHParams(P^, N, Params);
Dec(N, L);
Result := Size - N;
end;
{ }
{ DigitallySigned }
{ }
(* struct { *)
(* SignatureAndHashAlgorithm algorithm; *)
(* opaque signature<0..2^16-1>; *)
(* } DigitallySigned; *)
{ }
function EncodeTLSDigitallySigned(
var Buffer; const Size: Integer;
const Signed: TTLSDigitallySigned): Integer;
var P : PByte;
N, L : Integer;
begin
Assert(Signed.Algorithm.Hash <> tlshaNone);
Assert(Signed.Algorithm.Signature <> tlssaAnonymous);
Assert(Length(Signed.Signature) > 0);
N := Size;
P := @Buffer;
Dec(N, 2);
if N < 0 then
raise ETLSError.CreateAlertBufferEncode;
P^ := Ord(Signed.Algorithm.Hash);
Inc(P);
P^ := Ord(Signed.Algorithm.Signature);
Inc(P);
L := EncodeTLSOpaque16(P^, N, Signed.Signature);
Dec(N, L);
Result := Size - N;
end;
function DecodeTLSDigitallySigned(
const Buffer; const Size: Integer;
var Signed: TTLSDigitallySigned): Integer;
var P : PByte;
N, L : Integer;
begin
N := Size;
P := @Buffer;
Dec(N, 2);
if N < 0 then
raise ETLSError.CreateAlertBufferDecode;
Signed.Algorithm.Hash := TTLSHashAlgorithm(P^);
Inc(P);
Signed.Algorithm.Signature := TTLSSignatureAlgorithm(P^);
Inc(P);
L := DecodeTLSOpaque16(P^, N, Signed.Signature);
Dec(N, L);
Result := Size - N;
end;
{ }
{ Server Key Exchange }
{ }
{ select (KeyExchangeAlgorithm) }
{ case dh_anon: params : ServerDHParams; }
{ case dhe_dss: }
{ case dhe_rsa: params : ServerDHParams; }
{ signed_params : digitally-signed struct ( }
{ client_random : opaque [32]; }
{ server_random : opaque [32]; }
{ params : ServerDHParams ; }
{ ); }
{ case rsa: }
{ case dh_dss: }
{ case dh_rsa: struct (); }
{ case ec_diffie_hellman: }
{ ServerECDHParams params; }
{ Signature signed_params; }
{ }
procedure InitTLSServerKeyExchange(var ServerKeyExchange: TTLSServerKeyExchange);
begin
FillChar(ServerKeyExchange, SizeOf(ServerKeyExchange), 0);
end;
procedure AssignTLSServerKeyExchangeDHParams(
var ServerKeyExchange: TTLSServerKeyExchange;
const p, g, Ys: RawByteString);
begin
AssignTLSServerDHParams(ServerKeyExchange.DHParams, p, g, Ys);
end;
function EncodeTLSServerKeyExchange(
var Buffer; const Size: Integer;
const KeyExchangeAlgorithm: TTLSKeyExchangeAlgorithm;
const ServerKeyExchange: TTLSServerKeyExchange): Integer;
var P : PByte;
N, L : Integer;
begin
Assert(KeyExchangeAlgorithm <> tlskeaNone);
N := Size;
P := @Buffer;
case KeyExchangeAlgorithm of
tlskeaDH_Anon :
begin
L := EncodeTLSServerDHParams(P^, N, ServerKeyExchange.DHParams);
Dec(N, L);
end;
tlskeaDHE_DSS,
tlskeaDHE_RSA :
begin
L := EncodeTLSServerDHParams(P^, N, ServerKeyExchange.DHParams);
Dec(N, L);
Inc(P, L);
L := EncodeTLSDigitallySigned(P^, N, ServerKeyExchange.SignedParams);
Dec(N, L);
end;
tlskeaECDHE_ECDSA,
tlskeaECDHE_RSA : ;
tlskeaRSA,
tlskeaDH_DSS,
tlskeaDH_RSA : ;
end;
Result := Size - N;
end;
function DecodeTLSServerKeyExchange(
const Buffer; const Size: Integer;
const KeyExchangeAlgorithm: TTLSKeyExchangeAlgorithm;
var ServerKeyExchange: TTLSServerKeyExchange): Integer;
var P : PByte;
N, L : Integer;
begin
N := Size;
P := @Buffer;
case KeyExchangeAlgorithm of
tlskeaDH_Anon :
begin
L := DecodeTLSServerDHParams(P^, N, ServerKeyExchange.DHParams);
Dec(N, L);
end;
tlskeaDHE_DSS,
tlskeaDHE_RSA :
begin
L := DecodeTLSServerDHParams(P^, N, ServerKeyExchange.DHParams);
Dec(N, L);
Inc(P, L);
L := DecodeTLSDigitallySigned(P^, N, ServerKeyExchange.SignedParams);
Dec(N, L);
end;
tlskeaRSA,
tlskeaDH_DSS,
tlskeaDH_RSA : ;
end;
Result := Size - N;
end;
procedure SignTLSServerKeyExchangeDH_RSA(
var ServerKeyExchange: TTLSServerKeyExchange;
const client_random : TTLSClientServerRandom;
const server_random : TTLSClientServerRandom;
const RSAPrivateKey: TRSAPrivateKey);
const
MaxHashBufSize = 32768;
var
HashBuf : array[0..MaxHashBufSize - 1] of Byte;
L : Integer;
//HashMd5 : T128BitDigest;
//HashSha : T160BitDigest;
//SignedStruct : TTLSRSASignedStruct;
//SignHash : T256BitDigest;
SignatureBuf : RawByteString;
begin
Writeln('Sign:');
Assert(Length(ServerKeyExchange.DHParams.dh_p) > 0);
Assert(Length(ServerKeyExchange.DHParams.dh_g) > 0);
Assert(Length(ServerKeyExchange.DHParams.dh_Ys) > 0);
Assert(RSAPrivateKey.KeyBits > 0);
L := EncodeTLSServerDHParamsHashBuf(
HashBuf, SizeOf(HashBuf),
client_random,
server_random,
ServerKeyExchange.DHParams);
{
HashMd5 := CalcMD5(HashBuf, L);
HashSha := CalcSHA1(HashBuf, L);
Move(HashMd5, SignedStruct.md5_hash, SizeOf(SignedStruct.md5_hash));
Move(HashSha, SignedStruct.sha_hash, SizeOf(SignedStruct.sha_hash));
SignHash := CalcSHA256(SignedStruct, SizeOf(SignedStruct));
Writeln('SignHash:', DigestToHexU(SignHash, Sizeof(SignHash)));
Writeln('PrivateKey:', HugeWordToHex(RSAPrivateKey.Exponent), ' ', HugeWordToHex(RSAPrivateKey.Modulus));
}
SetLength(SignatureBuf, RSAPrivateKey.KeyBits div 8);
RSASignMessage(rsastEMSA_PKCS1, rsahfSHA256, RSAPrivateKey,
HashBuf, L,
Pointer(SignatureBuf)^, Length(SignatureBuf));
ServerKeyExchange.SignedParams.Algorithm.Hash := tlshaSHA256;
ServerKeyExchange.SignedParams.Algorithm.Signature := tlssaRSA;
ServerKeyExchange.SignedParams.Signature := SignatureBuf;
end;
function VerifyTLSServerKeyExchangeDH_RSA(
const ServerKeyExchange: TTLSServerKeyExchange;
const client_random : TTLSClientServerRandom;
const server_random : TTLSClientServerRandom;
const RSAPublicKey: TRSAPublicKey): Boolean;
const
MaxHashBufSize = 32768;
var
HashBuf : array[0..MaxHashBufSize - 1] of Byte;
L : Integer;
// HashMd5 : T128BitDigest;
// HashSha : T160BitDigest;
// SignedStruct : TTLSRSASignedStruct;
// SignHash : T256BitDigest;
SignatureBuf : RawByteString;
begin
Assert(Length(ServerKeyExchange.DHParams.dh_p) > 0);
Assert(Length(ServerKeyExchange.DHParams.dh_g) > 0);
Assert(Length(ServerKeyExchange.DHParams.dh_Ys) > 0);
Assert(RSAPublicKey.KeyBits > 0);
//// After validated, encode hash buf using received Params buf, it might
//// have params in a different order.
L := EncodeTLSServerDHParamsHashBuf(HashBuf, SizeOf(HashBuf),
client_random,
server_random,
ServerKeyExchange.DHParams);
SignatureBuf := ServerKeyExchange.SignedParams.Signature;
(*
HashMd5 := CalcMD5(HashBuf, L);
HashSha := CalcSHA1(HashBuf, L);
Move(HashMd5, SignedStruct.md5_hash, SizeOf(SignedStruct.md5_hash));
Move(HashSha, SignedStruct.sha_hash, SizeOf(SignedStruct.sha_hash));
SignHash := CalcSHA256(SignedStruct, SizeOf(SignedStruct));
Writeln('SignHash:', DigestToHexU(SignHash, Sizeof(SignHash)));
Writeln('Signature:', DigestToHexU(Pointer(SignatureBuf)^, Length(SignatureBuf)));
Writeln('PublicKey:', HugeWordToHex(RSAPublicKey.Exponent), ' ', HugeWordToHex(RSAPublicKey.Modulus));
*)
Result :=
RSACheckSignature(rsastEMSA_PKCS1, RSAPublicKey,
HashBuf, L,
Pointer(SignatureBuf)^, Length(SignatureBuf));
end;
{ }
{ ClientDiffieHellmanPublic }
{ select (PublicValueEncoding) }
{ case implicit: struct (); }
{ case explicit: opaque dh_Yc<1..2^16-1>; }
{ }
function EncodeTLSClientDiffieHellmanPublic(
var Buffer; const Size: Integer;
const ClientDiffieHellmanPublic: TTLSClientDiffieHellmanPublic): Integer;
var P : PByte;
N, L : Integer;
begin
N := Size;
P := @Buffer;
if ClientDiffieHellmanPublic.PublicValueEncodingExplicit then
begin
if ClientDiffieHellmanPublic.dh_Yc = '' then
raise ETLSError.Create(TLSError_InvalidParameter);
L := EncodeTLSOpaque16(P^, N, ClientDiffieHellmanPublic.dh_Yc);
Dec(N, L);
end;
Result := Size - N;
end;
function DecodeTLSClientDiffieHellmanPublic(
const Buffer; const Size: Integer;
const PublicValueEncodingExplicit: Boolean;
var ClientDiffieHellmanPublic: TTLSClientDiffieHellmanPublic): Integer;
var P : PByte;
N, L : Integer;
begin
N := Size;
P := @Buffer;
if PublicValueEncodingExplicit then
begin
L := DecodeTLSOpaque16(P^, N, ClientDiffieHellmanPublic.dh_Yc);
Dec(N, L);
end;
Result := Size - N;
end;
(*
struct {
ECPoint ecdh_Yc;
} ClientECDiffieHellmanPublic;
*)
{ }
{ ClientKeyExchange }
{ }
{ select (KeyExchangeAlgorithm) }
{ case rsa : EncryptedPreMasterSecret; }
{ case dhe_dss : }
{ case dhe_rsa : }
{ case dh_dss : }
{ case dh_rsa : }
{ case dh_anon : ClientDiffieHellmanPublic; }
{ }
function EncodeTLSClientKeyExchange(
var Buffer; const Size: Integer;
const KeyExchangeAlgorithm: TTLSKeyExchangeAlgorithm;
const ClientKeyExchange: TTLSClientKeyExchange): Integer;
var P : PByte;
N, L : Integer;
begin
N := Size;
P := @Buffer;
case KeyExchangeAlgorithm of
tlskeaRSA :
begin
L := Length(ClientKeyExchange.EncryptedPreMasterSecret);
if L = 0 then
raise ETLSError.Create(TLSError_InvalidParameter);
Move(ClientKeyExchange.EncryptedPreMasterSecret[1], P^, L);
Dec(N, L);
end;
tlskeaDHE_DSS,
tlskeaDHE_RSA,
tlskeaDH_DSS,
tlskeaDH_RSA,
tlskeaDH_Anon :
begin
L := EncodeTLSClientDiffieHellmanPublic(P^, N, ClientKeyExchange.ClientDiffieHellmanPublic);
Dec(N, L);
end;
end;
Result := Size - N;
end;
function DecodeTLSClientKeyExchange(
const Buffer; const Size: Integer;
const KeyExchangeAlgorithm: TTLSKeyExchangeAlgorithm;
const PublicValueEncodingExplicit: Boolean;
var ClientKeyExchange: TTLSClientKeyExchange): Integer;
var P : PByte;
N, L, C : Integer;
begin
N := Size;
P := @Buffer;
case KeyExchangeAlgorithm of
tlskeaRSA :
begin
L := DecodeTLSLen16(P^, N, C);
Dec(N, L);
Inc(P, L);
Assert(N = C);
SetLength(ClientKeyExchange.EncryptedPreMasterSecret, C);
Move(P^, ClientKeyExchange.EncryptedPreMasterSecret[1], C);
Dec(N, C);
end;
tlskeaDHE_DSS,
tlskeaDHE_RSA,
tlskeaDH_DSS,
tlskeaDH_RSA,
tlskeaDH_Anon :
begin
L := DecodeTLSClientDiffieHellmanPublic(P^, N, PublicValueEncodingExplicit, ClientKeyExchange.ClientDiffieHellmanPublic);
Dec(N, L);
end;
end;
Result := Size - N;
end;
end.