RFD 301: Has anybody seen my keys? – Een sleutelhiërarchie-strategie voor beveiliging op rack-niveau

Achtergrond en doel

Binnen een Oxide-rack bevinden zich veel verschillende soorten geheimen. Aan de basis van het systeem hebben we de DeviceId- en Alias-sleutels, die zijn opgeslagen op de Root of Trust (RoT) en respectievelijk worden gebruikt voor platformidentiteit en het ondertekenen van metingen voor attestatie [RFD 36]. Deze sleutels, samen met een derde RoT-gehost sleutelpaar dat wordt gebruikt voor het authenticeren van efemere Diffie-Hellman-overeenkomsten, stellen sleds in staat om beveiligde sprockets-sessies te vormen voor berichten op de applicatielaag [RFD 238]. Deze sprockets-sessies stellen elke sled in staat om vertrouwelijk informatie uit te wisselen op point-to-point basis, waarbij de integriteit van berichten wordt beschermd en de authenticiteit van het eindpunt en de attestatie van de draaiende software worden gegarandeerd.

Om beveiligingsgaranties op rack-niveau te bieden, zodat een aanvaller niet met een subset van sleds of schijven kan weglopen en nuttige informatie kan herstellen, hebben we een Trust Quorum ontworpen [RFD 238].

Het primaire beschermingsmechanisme achter het trust quorum is Shamir's Secret Sharing. Een gedeeld geheim op rack-niveau wordt gebruikt als bron voor sleutelafleiding voor andere sleutels die worden gebruikt om opgeslagen gegevens (storage at rest) te beschermen. Het rack-geheim wordt door een dealer-proces gesplitst in N unieke sleuteldelen en via sprockets-sessies gedistribueerd naar elke bootstrap agent, samen met de unieke platformidentiteiten van de N leden van het trust quorum. Deze platformidentiteiten zijn ingebakken in de openbare sleutelcertificaten op de RoT om verificatie mogelijk te maken dat een entiteit is wie hij beweert te zijn. Na distributie van deze informatie kunnen bootstrap agents sprockets-verbindingen tot stand brengen met andere agents, het lidmaatschap van de groep verifiëren (via de uitgewisselde certificaten) en K-1 delen ophalen van andere agents, zodat ze het rack-geheim kunnen reconstrueren uit K delen. Cruciaal is dat zonder het verkrijgen van K delen geen informatie over het rack-geheim kan worden achterhaald.

Zoals beschreven in [RFD 238], worden individuele delen onversleuteld opgeslagen op de M.2-schijven van elke sled. Een aanvaller zou minstens K van deze schijven moeten stelen om het rack-geheim te reconstrueren, wat onuitvoerbaar is zonder aanzienlijke tijd en verstoring tijdens fysieke toegang. In de toekomst zijn we van plan deze geheimen te "sealen" met behulp van onze Root of Trust (RoT), zodat ze alleen worden ontsleuteld bij het opstarten van de sled. Sealing zou betekenen dat een aanvaller K volledige sleds zou moeten stelen en deze succesvol zou moeten kunnen opstarten om het rack-geheim te herstellen. Het gewicht van K sleds maakt dit prohibitief voor een incidentele aanvaller.

Met dit rack-geheim beschikken we over een gedeeld geheim dat alleen beschikbaar is wanneer voldoende (K) van de N sleds in de groep in hetzelfde rack zijn geplaatst en elkaar voldoende vertrouwen om delen met elkaar uit te wisselen. Vanuit dit gedeelde geheim kunnen we zaken doen zoals het afleiden of inkapselen (wrapping) van individuele encryptiesleutels voor elk individueel U.2-apparaat, en onafhankelijk rack-niveau root-certificaten afleiden voor interne services.

Het doel van deze RFD is het identificeren van het volgende:

  • Welke gegevens worden beschermd door het rack-geheim?
  • Wat is de temporele levenscyclus van die gegevens?
  • Wat is de ruimtelijke lokaliteit van die gegevens? (Is het lokaal voor een specifieke schijf/sled/rack/cluster?)
  • Welke fysieke of logische beperkingen voorkomen dat de versleutelde gegevens worden verplaatst?
  • Wat is de sleutelhiërarchie die wordt gebruikt om die gegevens te beschermen?
  • Welke sleutels beschermen welke gegevens?
  • Welke sleutels worden afgeleid van welke geheimen en sleutels?
  • Welke sleutels zijn ingekapseld (wrapped / versleuteld door andere sleutels)?
  • Hoe worden sleutels afgeleid of ingekapseld (Key Schedule)?
  • Wat gebeurt er in het geval van een sleutelcompromis?

Deze vragen zijn kritisch voor de beveiliging van ons rack. Onze conclusies kunnen evolueren op basis van ervaringen met de huidige oplossing en meer tijd om oplossingen te implementeren die onze beveiligingshouding versterken en uitbreiden. Voor nu moet deze RFD echter sterke antwoorden leveren om onze gegevens at rest optimaal te beschermen.

Leaf Peeping

Onze sleutelhiërarchie op rack-niveau begint bij de wortel met het Rack Secret. Elk lid van het trust quorum kan voldoende delen verkrijgen om het rack-geheim te herberekenen. Het rack-geheim zelf is geen sleutel, dus we moeten sleutels ervan afleiden via een key derivation function (KDF) die kan worden gebruikt voor diverse doeleinden in ons rack.

Om onze sleutelhiërarchie te construeren en de interne knooppunten in de boom in te vullen, beginnen we met het opsommen van de gegevens die binnen het rack moeten worden beschermd, welke unieke sleutels worden gebruikt voor die bescherming, en de beveiligingsgaranties die we van die sleutels verwachten. Nadat we de leaf-keys (bladsleutels) hebben vastgesteld, kunnen we terugwerken naar de rest van de hiërarchie.

De onderstaande tabel toont de gegevens die we voorlopig willen beschermen via de sleutelhiërarchie van het rack-geheim.

GegevensOpslagtypeOpslagapparaatLevensduur
Control Plane-gegevensCockroachDBSommige U.2-apparatenTijdelijk tot de levensduur van het rack
Control Plane-metricsClickhouseSommige U.2-apparaten?
Crucible ExtentsBestandenDe meeste U.2-apparatenLevensduur van een storage volume
Crucible volume-encryptiesleutelsCockroachDBSommige U.2-apparatenLevensduur van een storage volume
Authenticatietokens voor gebruikersCockroachDBSommige U.2-apparatenTijdelijk / user-session TTL
Interne Service Leaf CertsBestandenAlle U.2-apparaten (niet alle certs op alle apparaten)Cert TTL
Interne CA Root Cert Private KeyBestandAlle sleds?Lang genoeg om Leaf Cert CSR's te ondertekenen; daarna mogelijk herafgeleid voor rotatie
Interne CA Root Cert Public KeyBestandEén of meer U.2-apparaten op alle sledsTot Cert-rotatie

Alle opgeslagen gegevens bevinden zich op U.2-apparaten, hetzij in bestanden of in databases die uiteindelijk in bestanden belanden. We hebben besloten om geen hardware-ondersteunde volledige schijfencryptie (FDE) te gebruiken (vanwege een gebrek aan vertrouwen in de implementatie, complexiteit van sleutelbeheer en meerdere mogelijke leveranciers), en we zullen één zpool per U.2-apparaat hebben. We willen bijna de gehele zpool versleutelen via een root /crypt dataset met ZFS-encryptie, waarbij we specifieke datasets zoals Crucible uitsluiten omdat deze hun eigen encryptie bieden.

We kunnen er dus van uitgaan dat alle noodzakelijke klant- en control-plane-gegevens op elk U.2-apparaat zijn versleuteld. Om sleutelcompromissen te beperken (zodat als één schijf wordt gestolen en de sleutel wordt gecompromitteerd, niet alle andere schijven gecompromitteerd zijn), kiezen we voor een individuele sleutel per schijf. ZFS biedt flexibiliteit in hoe we deze sleutels genereren en wijzigen: sleutelrotatie wordt intern beheerd door de ZFS-kernelmodule en het wijzigen van de sleutel van de gebruiker vereist geen her-encryptie van de gehele dataset.

Omdat we alle kritieke gegevens op de U.2's versleutelen met ZFS-encryptie (inclusief Crucible-sleutels) en deze ZFS-sleutels niet op die schijven worden opgeslagen, voldoen we aan de vereisten voor data at rest bescherming.

Opbouwen van een sleutelhiërarchie vanuit een Rack Secret

Uitgaande van een statisch cluster hebben we een rack-geheim dat kan worden berekend uit K sleuteldelen en kan worden gebruikt om afgeleide sleutels (child keys) te genereren.

Het rack-geheim beschermt elke sleutel in het systeem die wordt gebruikt na de ontgrendeling van het rack. Er zijn twee mechanismen om de volgende sleutels in de hiërarchie te verkrijgen:

  1. Sleutelafleiding (Key Derivation): Dit gebruiken we om primaire afgeleide sleutels te genereren vanuit het rack-geheim. Het kan ook worden gebruikt om sleutels vanuit andere sleutels af te leiden.
  • Voordeel: Afgeleide sleutels hoeven niet op schijf te worden opgeslagen; ze kunnen worden geregenereerd.
  • Nadeel: Als een afgeleide sleutel verandert, veranderen alle downstream afgeleide sleutels mee.
  1. Sleutelomsluiting (Key Wrapping / Key Encryption): Dit is het simpelweg versleutelen van een sleutel.
  • Voordeel: Als de wrapper-sleutel wordt geroteerd, hoeven de downstream sleutels niet te veranderen. Dit is essentieel voor grote hoeveelheden data op opslag; je wilt niet alles hoeven ontsleutelen en opnieuw versleutelen omdat een parent-sleutel is geroteerd.
  • Nadeel: De ingekapselde (versleutelde) sleutel moet ergens op schijf worden opgeslagen.

Voor het trust quorum hebben we het specifieke probleem dat er nieuwe delen worden gegenereerd wanneer nodes worden toegevoegd of verwijderd. Hoewel het mogelijk is om hetzelfde rack-geheim te behouden, is dit minder veilig over tijd: een kwaadaardige node die het rack-geheim eenmaal heeft bemachtigd, kan dan alle huidige en toekomstige gegevens herstellen. We geven daarom de voorkeur aan het roteren van het rack-geheim bij elke wijziging van het trust quorum (reconfiguratie).

Doelen en Beperkingen

Onze beveiligingsdoelen:

  • Sleutels zoveel mogelijk afleiden uit het rack-geheim om de noodzaak van het opslaan van wrapped keys te beperken.
  • Rotatie van het rack-geheim mogelijk maken om een gecompromitteerd geheim te mitigeren.
  • Unieke encryptiesleutels per U.2-schijf gebruiken.
  • Garanderen dat nieuwe (lege) sleds geen toegang hebben tot at rest gegevens van oude sleds na een reconfiguratie, tenzij deze gedeeld zijn.

Onze beperkingen:

  • We moeten de ZFS wrapper-sleutels per U.2-schijf kunnen wijzigen wanneer het rack-geheim wordt geroteerd. Dit vereist dat de oude en nieuwe wrapper-sleutel gelijktijdig bekend zijn.
  • Rekening houden met het feit dat niet alle sleds tegelijkertijd weten wanneer een nieuwe reconfiguratie is voltooid (gezien de gedistribueerde aard).
  • Erkennen dat het vastleggen (commitment) van een nieuwe configuratie kan gebeuren na meerdere "valse starts".

Gezien deze punten moeten sleds die lid zijn van zowel de oude als de nieuwe groep, gelijktijdig toegang hebben tot zowel het oude als het nieuwe vastgelegde rack-geheim.

De oplossing via de Dealer

De meest directe oplossing is via de dealer tijdens een reconfiguratie. Elke configuratie wordt genummerd met een monotoon stijgend epoch.

  1. Bij Epoch 1 krijgt elke sled een deel en berekent deze het rack-geheim om de oorspronkelijke ZFS-encryptiesleutels voor de U.2-apparaten af te leiden.
  2. Bij een reconfiguratie haalt de dealer genoeg delen op om het rack-geheim voor de huidige epoch (1) te herberekenen.
  3. De dealer genereert een nieuw rack-geheim voor Epoch 2 en splitst dit in delen.
  4. De dealer leidt een old-rack-secret encryptiesleutel af uit het Epoch 2 geheim en versleutelt het Epoch 1 rack-geheim hiermee.
  5. Dit versleutelde geheim wordt naar de sleds van de nieuwe groep gestuurd als onderdeel van het prepare bericht.
  6. Zodra een sled ziet dat de configuratie voor de nieuwe epoch is vastgelegd (committed), haalt deze de delen op voor het nieuwe rack-geheim, leidt de old-rack-secret sleutel af, ontsleutelt het oude rack-geheim, en configureert de ZFS-encryptie voor elke U.2-schijf opnieuw met de nieuwe sleutels.
  7. Na de wijziging wordt het versleutelde rack-geheim van de oude epoch veilig verwijderd.

Sleutelafleiding (Key Derivation)

We focussen ons hier op opslagencryptiesleutels en rack-geheim encryptiesleutels.

Technische Specificaties

  • KDF: We gebruiken [HKDF] met SHA3-256 als hash-algoritme.
  • Encryptie rack-geheim: Chacha20poly1305.
  • ZFS Encryptie: AES-GCM-256 (de sterkste optie binnen ZFS).
  • Sleutellengte: Zowel AES-GCM-256 als Chacha20poly1305 gebruiken 32-byte (256-bit) sleutels.

De dealer kiest voor elke epoch een willekeurige 32-byte salt. Deze salt wordt gebruikt in de sleutelafleiding voor de oude versleutelde rack-geheimen, maar niet voor de schijfencryptiesleutels.

Om afgeleide sleutels te binden aan hun specifieke gebruik en context, gebruiken we een info parameter in de HKDF-Expand functie. Hiermee voorkomen we dat een sleutel per ongeluk voor een ander doel wordt gebruikt.

Definitie van Info-strings:

  • Rack Secret Info: "rack-secret" + newepoch + '-' + oldepoch

(Waarbij epoch een 4-byte big-endian integer is).

  • U.2 Drive Info: "U.2-zfs-" + pcivendorid + drivemodel + driveserial_number

(Deze tuple identificeert een U.2-schijf uniek).

In de praktijk wordt de encryptie van het oude geheim alleen uitgevoerd door de dealer. Andere bootstrap agents leiden alleen de sleutel af die nodig is om het oude rack-geheim te ontsleutelen.

Conclusies (Determinations)

  • Elk U.2-apparaat heeft een aparte encryptiesleutel voor opslag.
  • Alle opslagsleutels worden afgeleid van het huidige rack-geheim met gebruik van de serienummers van de schijven.
  • Rack-delen kunnen alleen worden opgehaald voor de huidige epoch.
  • We leiden een encryptiesleutel voor het rack-geheim af uit een nieuw voorbereid rack-geheim om het oude (huidige) rack-geheim bij commit te beschermen.
  • Bij het vernemen van de commit van een nieuwe epoch, halen leden van de nieuwe groep de delen op, berekenen het nieuwe rack-geheim, ontsleutelen het oude rack-geheim, herconfigureren de opslagencryptie en wissen vervolgens alle tijdelijke rack-geheimen veilig uit het geheugen.

Externe Referenties

  • [RFD 36] Root of Trust and Attestation
  • [RFD 238] Trust Quorum and Rack Unlock