Native TLS

Ondersteund door

 

TsgcWebSocketClient

TsgcTCPClient

TsgcHTTP1Client

TsgcHTTP2Client

TsgcWebSocketServer

TsgcWebSocketHTTPServer

TsgcHTTPServer

TsgcWebSocketProxyServer

TsgcWebSocketLoadBalancerServer

 

*Vereist het sgcCrypto-pack, dat vanaf de Standard-editie wordt meegeleverd.

 

De native TLS-engine is een TLS 1.3- en TLS 1.2-implementatie die volledig in Object Pascal is geschreven bovenop de sgcCrypto-units. Het is geen binding: er is geen OpenSSL-DLL om te distribueren, geen SChannel-aanroep en geen platform-TLS-bibliotheek bij betrokken. Dezelfde broncode compileert van Delphi 7 tot en met RAD Studio 13 en draait op elk platform dat de componenten ondersteunen.

 

De reden om ernaar te grijpen is de sleuteluitwisseling. De engine biedt de hybride post-quantum groepen van RFC 10024, en X25519MLKEM768 is de eerste groep die ze voorstelt, zodat een client die erop overstapt een post-quantum sleuteluitwisseling onderhandelt met elke server die er een ondersteunt, zonder verdere wijziging aan de toepassing. De hybride groepen bestaan alleen in TLS 1.3, dus een verbinding die terugvalt op TLS 1.2 gebruikt een klassieke curve. Zie Post-quantumcryptografie voor wat die groepen zijn en waarom een hybride vandaag de verstandige migratie is.

 

Inschakelen

 

Stel de IOHandler in en er verandert verder niets. De eigenschappen voor certificaat, sleutel, rootcertificaat, verificatie en ALPN die u al gebruikt blijven werken, de engine leest dezelfde.

 


// client
oClient := TsgcWebSocketClient.Create(nil);
oClient.URL := 'wss://www.esegece.com:2053';
oClient.TLS := True;
oClient.TLSOptions.IOHandler := iohNativeTLS;
oClient.TLSOptions.VerifyCertificate := True;
oClient.TLSOptions.RootCertFile := 'cacert.pem';
oClient.Active := True;

// server
oServer := TsgcWebSocketServer.Create(nil);
oServer.SSL := True;
oServer.SSLOptions.IOHandler := iohNativeTLS;
oServer.SSLOptions.CertFile := 'certificate.pem';
oServer.SSLOptions.KeyFile := 'key.pem';
oServer.Active := True;

 

Op een server draait de engine ook op de event-gestuurde engines. Stel IOHandlerOptions.IOHandlerType in op iohIOCP op Windows of iohEPOLL op Linux en de handler wordt gebouwd op de bijbehorende TLS-provider, zodat dezelfde configuratie op alle drie de engines werkt.

 

Het selecteren van iohNativeTLS in een build zonder het sgcCrypto-pack geeft een uitzondering die dat meldt, in plaats van stilzwijgend terug te vallen op een andere bibliotheek.

 

TLS-versies

 

De engine spreekt TLS 1.3 en TLS 1.2, als client en als server, op de Indy-client, op de Indy-server en op de IOCP- en EPOLL-server-engines. TLS 1.3 wordt altijd gekozen wanneer beide kanten het ondersteunen. Voor de native engine is TLSOptions.Version op een client en SSLOptions.Version op een server de laagste toegestane versie.

 

Versie Onderhandelt
tlsUndefined (de standaardwaarde) TLS 1.3 of TLS 1.2
tls1_2 TLS 1.3 of TLS 1.2
tls1_3 Alleen TLS 1.3
tls1_0, tls1_1 Niets. Een client geeft een configuratiefout bij het verbinden, en een server bij het starten, omdat de engine uitsluitend TLS 1.2 en TLS 1.3 ondersteunt.

 

Dit is niet hoe de OpenSSL-handler de eigenschap leest. Met iohOpenSSL betekent tls1_2 precies TLS 1.2, terwijl het met iohNativeTLS TLS 1.2 of hoger betekent. De cipher suite-lijst bepaalt de rest. Om alleen TLS 1.2 te krijgen, laat u Version op tls1_2 staan en noemt u in NativeTLS_Options.CipherSuites alleen TLS 1.2-suites. Een lijst die alleen TLS 1.3-suites noemt, geeft alleen TLS 1.3, en een lijst die suites van beide versies noemt, staat beide toe. Version tls1_3 samen met een lijst van TLS 1.2-suites laat geen versie over om te onderhandelen, en de verbinding geeft een fout bij het starten.

 


// TLS 1.3 and TLS 1.2, tls1_2 is the lowest version allowed
oClient.TLSOptions.IOHandler := iohNativeTLS;
oClient.TLSOptions.Version := tls1_2;

// TLS 1.3 only
oClient.TLSOptions.Version := tls1_3;

// TLS 1.2 only: name TLS 1.2 suites and no TLS 1.3 suite
oClient.TLSOptions.Version := tls1_2;
oClient.TLSOptions.NativeTLS_Options.CipherSuites :=
  'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256';

 

Groepen en cipher suites

 

TLSOptions.NativeTLS_Options op een client, en SSLOptions.NativeTLS_Options op een server, dragen de twee voorkeurslijsten. Beide zijn tekenreeksen in de OpenSSL-stijl, items gescheiden door dubbele punten, de meest geprefereerde eerst, en één lijst bedient TLS 1.3 en TLS 1.2 samen. Laat er een leeg om de standaardwaarde van de engine te behouden. Een ongeldige lijst geeft een fout wanneer de verbinding start, zodat een typefout niet stilzwijgend wordt genegeerd.

 

Eigenschap Geaccepteerde namen Standaardwaarde
Groups X25519MLKEM768, SecP256r1MLKEM768, SecP384r1MLKEM1024, X25519, secp256r1, secp384r1. De aliassen P-256, prime256v1 en P-384 worden ook geaccepteerd, en namen worden vergeleken zonder te letten op hoofdletters of kleine letters. De drie hybride groepen gelden alleen voor TLS 1.3. X25519MLKEM768:X25519:secp256r1:secp384r1
CipherSuites TLS 1.3: TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256. TLS 1.2: de suites in de tabel hieronder. Zowel IANA-namen als namen in OpenSSL-stijl zoals ECDHE-RSA-AES128-GCM-SHA256 worden geaccepteerd, en de engine meldt de IANA-naam. TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256, plus de TLS 1.2-standaardwaarden hieronder

 

De eerste groep in de lijst is degene waarvoor een client een sleuteldeel verstuurt, dus X25519MLKEM768 vooraan laten staan is wat de eerste vlucht al post-quantum maakt. Een item laten voorafgaan door een vraagteken slaat het over wanneer deze build het niet heeft, en elk ander onbekend of niet-beschikbaar item laat de hele lijst mislukken.

 


// only the hybrid post-quantum groups, and only AES-256-GCM
oClient.TLSOptions.NativeTLS_Options.Groups :=
  'X25519MLKEM768:SecP256r1MLKEM768:SecP384r1MLKEM1024';
oClient.TLSOptions.NativeTLS_Options.CipherSuites := 'TLS_AES_256_GCM_SHA384';

// tolerate a build where X25519 is not compiled in
oClient.TLSOptions.NativeTLS_Options.Groups := '?X25519MLKEM768:secp256r1';

 

TLS 1.2-cipher suites

 

Standaard zijn alleen suites met forward secrecy en AEAD ingeschakeld. De AES-CBC-suites en de RSA-sleuteluitwisseling zijn er voor tegenpartijen die het niet beter kunnen, en ze worden alleen aangeboden of geaccepteerd wanneer CipherSuites ze noemt.

 

Suites Ingeschakeld
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 Standaard, in deze volgorde.
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 Alleen wanneer genoemd in CipherSuites.
TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA256 Alleen wanneer genoemd in CipherSuites. De RSA-sleuteluitwisseling biedt geen forward secrecy.

 

De ECDHE-suites van een TLS 1.2-verbinding gebruiken een klassieke groep uit de Groups-lijst, X25519, secp256r1 of secp384r1, houd dus ten minste een daarvan in de lijst wanneer er TLS 1.2-tegenpartijen verbinding moeten kunnen maken. De RSA-sleuteluitwisseling gebruikt helemaal geen groep.

 


// TLS 1.3, and TLS 1.2 with AES-GCM plus AES-CBC for older clients
oServer.SSLOptions.IOHandler := iohNativeTLS;
oServer.SSLOptions.Version := tls1_2;
oServer.SSLOptions.NativeTLS_Options.CipherSuites :=
  'TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:' +
  'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:' +
  'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA';

 

In een build die met SGC_CRYPTO_FIPS is gemaakt, worden de twee groepen die op X25519 zijn gebouwd, de ChaCha20-Poly1305-suites en de RSA-sleuteluitwisseling weggecompileerd, en veranderen de standaardwaarden in SecP256r1MLKEM768:SecP384r1MLKEM1024:secp256r1:secp384r1 en TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256, met de vier ECDHE-AES-GCM-suites voor TLS 1.2. Zie FIPS-modus.

 

TLS 1.2-gedrag

 

TLS 1.2 is geïmplementeerd met de beveiligingen die een moderne tegenpartij verwacht, en zonder de onderdelen van het protocol die verantwoordelijk waren voor de bekende aanvallen erop.

 

 

Sessiehervatting

De engine hervat sessies met stateless sessietickets, in TLS 1.3 (RFC 8446) en in TLS 1.2 (RFC 5077). Na een volledige handshake stuurt de server een ticket, verzegeld met AES-256-GCM onder een sleutel die alleen de server heeft. De client bewaart het in een sessiecache, gesleuteld op host, poort en ALPN-lijst, en biedt het aan bij de volgende verbinding, waarna de certificaatuitwisseling wordt overgeslagen. Een ticket dat de server niet kan openen, of een verlopen ticket, geeft een volledige handshake met een nieuw ticket.

Eigenschap Standaardwaarde Betekenis
NativeTLS_Options.SessionTickets True Een server geeft tickets uit en een client bewaart en biedt ze aan. False schakelt hervatting uit, elke handshake is dan volledig.
NativeTLS_Options.TicketLifetime 7200 Alleen server. Aantal seconden dat een ticket kan worden gebruikt om te hervatten, ten hoogste 604800. De ticketsleutel van de server roteert elke TicketLifetime seconden, en de vorige sleutel blijft nog één periode geldig.

De opties zijn TLSOptions.NativeTLS_Options op een client en SSLOptions.NativeTLS_Options op een server. De sessiecache hoort bij elk clientonderdeel, dus herverbindingen van dezelfde TsgcWebSocketClient, TsgcHTTP1Client, TsgcTCPClient of TsgcLDAPClient worden hervat, en dat geldt ook voor de upstream-verbinding van TsgcWebSocketProxyServer.

TLS 1.2-hervatting vereist het extended master secret van RFC 7627. Een TLS 1.2-sessie zonder dit wordt nooit hervat en krijgt geen ticket, en er wordt ook geen ticket uitgegeven wanneer de server om een clientcertificaat vraagt. Een TLS 1.3-ticket opent nooit als TLS 1.2-sessie, en omgekeerd.

Of een verbinding is hervat, wordt gemeld via de eigenschap Resumed van TsgcIdSSLIOHandlerSocketNativeTLS, de hieronder beschreven handler.

Wat er is onderhandeld

 

Zodra de handshake is voltooid, meldt de client-handler, TsgcIdSSLIOHandlerSocketNativeTLS in de unit sgcSSL_NativeTLS_Indy, het resultaat. VersionName is TLSv1.2 of TLSv1.3, CipherSuiteName is de IANA-naam van de suite, GroupName is de sleuteluitwisselingsgroep, leeg bij de RSA-sleuteluitwisseling, en PeerSignatureSchemeName is het handtekeningschema dat de server gebruikte. De handler is degene die de client doorgeeft aan OnSSLAfterCreateHandler.

 


procedure TForm1.oClientSSLAfterCreateHandler(Sender: TObject;
  aType: TwsSSLHandler; aSSLHandler: TIdSSLIOHandlerSocketBase);
begin
  FHandler := aSSLHandler;
end;

procedure TForm1.oClientConnect(Connection: TsgcWSConnection);
var
  oHandler: TsgcIdSSLIOHandlerSocketNativeTLS;
begin
  if FHandler is TsgcIdSSLIOHandlerSocketNativeTLS then
  begin
    oHandler := TsgcIdSSLIOHandlerSocketNativeTLS(FHandler);
    Memo1.Lines.Add(oHandler.VersionName + ' ' + oHandler.CipherSuiteName +
      ' ' + oHandler.GroupName + ' ' + oHandler.PeerSignatureSchemeName);
  end;
end;

 

Certificaten en verificatie

 

Een server leest CertFile, KeyFile en Password. CertFile en KeyFile kunnen PEM zijn, of CertFile kan een .pfx- of .p12-bestand zijn, herkend aan de extensie. Een PKCS#12-bestand bevat het certificaat, de keten en de private key, dus KeyFile is dan niet nodig, en het wordt geopend met Password. Het wordt gelezen door de pure Pascal PKCS#12-lezer van sgcCrypto_PKCS12, zonder OpenSSL. Een client die VerifyCertificate op True zet, controleert de serverketen tegen de hieronder beschreven vertrouwde roots en controleert dat de naam overeenkomt met de host waarmee hij verbinding heeft gemaakt. VerifyDepth wordt doorgegeven, en een waarde boven 16 wordt op 16 begrensd.

 

De vertrouwde roots zijn de certificaten in RootCertFile. Door NativeTLS_Options.UseSystemRoots op True te zetten, worden de certificeringsinstanties toegevoegd die het besturingssysteem vertrouwt. Standaard is dit False. Beide combineren: de roots uit RootCertFile worden eerst geladen, de systeemroots worden aan hetzelfde archief toegevoegd, en een keten wordt geaccepteerd wanneer deze naar een van beide leidt. Wanneer geen systeemroot wordt gevonden, wordt niets toegevoegd en geen fout gegenereerd, zodat de verificatie alleen op RootCertFile steunt. De eigenschap is TLSOptions.NativeTLS_Options.UseSystemRoots op een client en SSLOptions.NativeTLS_Options.UseSystemRoots op een server, waar de roots alleen dienen om clientcertificaten te valideren. Waar de systeemroots vandaan komen, hangt af van het platform:

Om zelf een map met certificaatbestanden te laden, leest TsgcTLS13TrustStore.AddDirectory(aDirectory, aRemovedDirectory) in de unit sgcSSL_NativeTLS_Certificates elk PEM- of DER-bestand van aDirectory, slaat elk bestand over waarvan de naam ook in aRemovedDirectory voorkomt, en geeft terug hoeveel certificaten het heeft toegevoegd. Het werkt op elk platform.

 

Om de naam vast te leggen die het certificaat moet dragen, in plaats van de host van de verbinding te gebruiken, stelt u TLSOptions.OpenSSL_Options.X509Checks.HostName of IPAddress in, met de bijbehorende vlag in X509Checks.Mode. De engine leest die twee waarden ook al is ze geen OpenSSL, zodat de eigenschap hetzelfde betekent welke IOHandler ook is geselecteerd.

 

Op een server vraagt SSLOptions.VerifyCertificate de client om een certificaat en valideert dit tegen de hierboven beschreven vertrouwde roots, en SSLOptions.VerifyCertificate_Options.FailIfNoCertificate weigert een client die er geen verstuurt. VerifyClientOnce heeft hier niets te doen. TLS 1.3 kent geen heronderhandeling, en de engine weigert die bij TLS 1.2, dus er wordt nooit een tweede keer gevraagd.

 

ALPN werkt zoals gebruikelijk via ALPNProtocols op een client en via de ALPN-selectie op de server, zodat HTTP/2 over de native engine h2 op dezelfde manier onderhandelt als over OpenSSL. Zie ALPN.

 

QUIC-modus

De engine voert ook de TLS 1.3-handshake van QUIC en HTTP/3 uit (RFC 9001). Zet SSLQUICOptions.IOHandler op TsgcQUICClient, TLSOptions.IOHandler op TsgcHTTP3Client, QUICOptions.SSLOptions.IOHandler op TsgcQUICServer en TsgcHTTP3Server, of SSLOptions.IOHandler op een server met HTTP3Options.Enabled, op iohNativeTLS.

Zie QUIC voor de vergelijking van de engines.

Wat het niet doet

 

De engine is bewust smal gehouden. Alles hieronder is een echte beperking, geen instelling om naar te zoeken.

 

 

Niets wat de tegenpartij verstuurt geeft een uitzondering. Een protocolfout beëindigt de verbinding met de juiste TLS-waarschuwing, en de reden wordt zoals gebruikelijk gemeld via de foutgebeurtenissen van de component.

De AES-GCM- en AES-CBC-recordbescherming gebruikt de AES-NI- en PCLMULQDQ-instructies op Windows-builds gemaakt met Delphi wanneer de CPU ze heeft, zie sgcAES_HardwareAvailable in Symmetrische versleuteling. Voor een build waarin geen enkel onderdeel van de bibliotheek OpenSSL laadt, zie Werken zonder OpenSSL.