Cómo extender LUKS2

Cómo extender LUKS2

Leí una guía hace unos años sobre cómo LUKS1 se extiende hacia el espacio libre derecho y adyacente sin pérdida de datos, pero no podía salir. Hoy en día LUKS2 ha llegado con muchas características nuevas, ¿hace diferencias en la extensión izquierda sin pérdida de datos?

Respuesta1

tl; drEn realidad, todavía no es posible. El formato de metadatos sugiere que debería ser factible, pero hasta ahora no se ha implementado. Por lo tanto, debe ceñirse al viejo "reubicar todos los datos" o "crear una nueva partición y dejar que LVM se preocupe por ello". Lo mismo que haces con LUKS1 y la mayoría de los sistemas de archivos.


Elencabezado LUKS2tiene un concepto desegmentos de datos:

El objeto Segments contiene una definición de áreas cifradas en el disco que contiene datos del usuario (en LUKS1 se menciona como la carga útil de datos del usuario). Para un dispositivo LUKS normal, solo hay un segmento de datos presente.

Durante el nuevo cifrado de datos, el área de datos se divide internamente según la clave nueva y la antigua, pero solo se debe presentar al usuario un área abstraída.

Consegmentos de datos, debería ser posible mover el encabezado LUKS hacia la izquierda, seguir apuntando a los datos originales (primer segmento) y usar el espacio libre (entre el encabezado y el segmento de datos) como un nuevo segmento de datos, agregado lógicamente al final del dispositivo de cripta. Así como LVM agrega grupos arbitrarios de extensiones físicas a un volumen lógico.

Pero eso es sólo una teoría.

Hasta el momento, no existe ningún uso/herramienta práctica que implemente esta función y no tengo idea de si hay planes para hacerlo.


Intenté hacerlo funcionar de una manera poco convencional (prueba de concepto, más o menos):

# truncate -s 100M foobar.img
# cryptsetup luksFormat --type=luks2 foobar.img
# cryptsetup luksOpen foobar.img foobar
# yes > /dev/mapper/foobar
# sync
# hexdump -C /dev/mapper/foobar
00000000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*
05400000

Patrón sí cifrado LUKS2. ¿Cómo es el segmento de datos?

# cryptsetup luksDump foobar.img
Data segments:
  0: crypt
    offset: 16777216 [bytes]
    length: (whole device)
    cipher: aes-xts-plain64
    sector: 512 [bytes]
# strings -n 100 foobar.img
"segments":{"0":{"type":"crypt","offset":"16777216","iv_tweak":"0","size":"dynamic","encryption":"aes-xts-plain64","sector_size":512}}

Este último es en realidad el aspecto de los metadatos LUKS2 sin procesar: es un formato JSON. Lo editaremos más tarde...

Hagámoslo crecer - hacia la izquierda (por 100M):

# truncate -s 100M barfoo.img
# cat foobar.img >> barfoo.img
# ls -lh *.img
-rw-r--r-- 1 root root 200M Jun  9 20:57 barfoo.img
-rw-r--r-- 1 root root 100M Jun  9 20:53 foobar.img

Entonces barfoo.img tiene 100 millones de espacio vacío nuevo seguido de 100 millones de contenedores LUKS originales.

Reubique el encabezado LUKS al nuevo inicio del dispositivo:

# dd bs=1M count=16 if=foobar.img of=barfoo.img conv=notrunc
# cryptsetup luksOpen barfoo.img barfoo
# hexdump -C -n 16 /dev/mapper/barfoo
00000000  4e a6 39 e7 e0 e8 63 ae  81 72 29 81 5f 1b 08 c2  |N.9...c..r)._...|
00000010

Se puede abrir ahora, pero elsegmento de datostodavía apunta al antiguo desplazamiento (16MiB) pero, por supuesto, no está allí; agregamos 100M, por lo que el desplazamiento para estesegmento de datosdebería ser 116MiB ahora.

Edítelo (compensación 16777216 para compensar 121634816):

# strings -n 100 barfoo.img | head -n 1 > barfoo.json
# nano -w barfoo.json
# dd if=barfoo.json of=barfoo.img bs=1 seek=4096 conv=notrunc
# dd if=barfoo.json of=barfoo.img bs=1 seek=20480 conv=notrunc

Resultado:

# cryptsetup luksDump barfoo.img
Device barfoo.img is not a valid LUKS device.

Ah, pero claro. LUKS2 ahora también tiene sumas de verificación de metadatos. No quiere que edites cosas con nano y destroces el encabezado con dd. No hay magia arcana para usted, señor. Bueno, eso es hasta que parches la suma de comprobación también...

# cryptsetup luksDump barfoo.img --debug
# LUKS2 header version 2 of size 16384 bytes, checksum sha256.
# Checksum:8552bf514ab70b53e63180e9fdd3bb59db1385e3dca87f792f8197b33b851aa1 (on-disk)
# Checksum:e6f322921feae0193bcbc4cddc23b87b7f192266b4a2ef34847580fd7ca18a3e (in-memory)
# LUKS2 header checksum error (offset 0).

...básicamente reemplace la suma de comprobación en el disco con la en memoria aquí.

# echo e6f322921feae0193bcbc4cddc23b87b7f192266b4a2ef34847580fd7ca18a3e |
  xxd -r -ps - |
  dd of=barfoo.img bs=1 seek=448 conv=notrunc

Resultado (ahora realmente):

# cryptsetup luksDump barfoo.img
Data segments:
  0: crypt
    offset: 121634816 [bytes]
    length: (whole device)
    cipher: aes-xts-plain64
    sector: 512 [bytes]
# hexdump -C /dev/mapper/barfoo
00000000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*
05400000

En este punto, hemos movido con éxito el encabezado LUKS 100M hacia la izquierda. Pero el tamaño del dispositivo sigue siendo el mismo... ahora, ¿podemos agregar otro segmento de datos? Hay un segmento de 100 millones gratuito desde el desplazamiento de 16 millones a 116 millones. Agreguémoslo al JSON.

# nano -w barfoo.json
man this is unreadable
# jq < barfoo.json > barfoo.pretty
# nano -w barfoo.pretty
...
  "segments": {
    "0": {
      "type": "crypt",
      "offset": "121634816",
      "iv_tweak": "0",
      "size": "88080384",
      "encryption": "aes-xts-plain64",
      "sector_size": 512
    },
    "1": {
      "type": "crypt",
      "offset": "16777216",
      "iv_tweak": "172032",
      "size": "104857600",
      "encryption": "aes-xts-plain64",
      "sector_size": 512
    }
  },
  "digests": {
    "0": {
      "type": "pbkdf2",
      "keyslots": [
        "0"
      ],
      "segments": [
        "0",
        "1"
      ],
...and so on and so forth...

Resultado:

# cryptsetup luksDump barfoo.img
Data segments:
  0: crypt
    offset: 121634816 [bytes]
    length: 88080384 [bytes]
    cipher: aes-xts-plain64
    sector: 512 [bytes]

  1: crypt
    offset: 16777216 [bytes]
    length: 104857600 [bytes]
    cipher: aes-xts-plain65
    sector: 512 [bytes]

Desafortunadamente, en este punto, el dispositivo se abrió bien, tenía el tamaño aumentado correcto (¡YAY!), pero los datos eran incorrectos (¡NOO!). El byte lógico 0 se asignó al byte físico 16MiB en lugar de los 116MiB esperados.

Oye, ese es el segmento 1, no el segmento 0, ¡tonto! ¿Qué salió mal?

No sé. Es casi como si no se supusiera que usted debería hacer modificaciones simples de metadatos para desbloquear funciones ocultas que nadie ha probado todavía.

Tal vez se deba a mi falta de comprensión, pero incluso al colocar los segmentos al revés, seguiría abriéndolos en el orden incorrecto. ¿Algo los está clasificando por compensación física? ¿Pero por qué?

Desafortunadamente, esta pieza de magia en particular terminó en un fracaso. Ya sea porque hice algo mal o simplemente aún no está listo para usar. Aún así, la funcionalidad está ahí, por lo que todavía hay esperanza para el futuro.

Tenga en cuenta que incluso si funcionara, no sería aconsejable utilizarlo.

información relacionada