AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 787635
Accepted
Sobrique
Sobrique
Asked: 2024-12-04 20:37:19 +0800 CST2024-12-04 20:37:19 +0800 CST 2024-12-04 20:37:19 +0800 CST

Cryptsetup relata "Não há espaço suficiente na área json do cabeçalho para o novo slot de chave"

  • 772

Estou usando o Almalinux, caso isso seja relevante aqui.

Usamos LUKS2 no disco local, com LVM no topo - então /dev/sda1 e 2 não são criptografados, mas /dev/sda3 é criptografado e usado para o sistema operacional.

Também usamos clevis/tang para fazer a descriptografia automática (e isso está funcionando bem).

Quando construímos via kickstart, definimos uma senha temporária ao criptografar e construir - e então, quando terminamos a construção inicial, usamos o ansible para definir senhas de boa qualidade, de acordo com nossas práticas de proteção/segurança.

Então isso envolve um script que faz o equivalente a:

cryptsetup luksOpen -S 0 --test-passphrase /dev/sda3 && cryptsetup luksChangeKey -S0 --force-password --batch-mode 

(E, claro, a senha de compilação 'padrão' é testada e substituída por uma do nosso sistema de gerenciamento de chaves).

Isso começou a falhar recentemente e estou um pouco perplexo sobre o que pode estar dando errado.

Definitivamente funciona em nossa 'compilação' inicial, que usa uma imagem de compilação um pouco desatualizada, mas depois mudamos dnf updatepara a revisão atual e agora não conseguimos mais usar luksChangeKey ou luksAddkey.

# Adding new keyslot 2 by passphrase, volume key provided by passphrase (-1).
# Selected keyslot 2.
# Keyslot 0 priority 1 != 2 (required), skipped.
# Keyslot 1 priority 1 != 2 (required), skipped.
# Trying to open LUKS2 keyslot 0.
# Running keyslot key derivation.
# Reading keyslot area [0x8000].
# Acquiring read lock for device /dev/sda3.
# Opening lock resource file /run/cryptsetup/L_8:3
# Verifying lock handle for /dev/sda3.
# Device /dev/sda3 READ lock taken.
# Reusing open ro fd on device /dev/sda3
# Device /dev/sda3 READ lock released.
# Verifying key from keyslot 0, digest 0.
# Keyslot 2 assigned to digest 0.
# Trying to allocate LUKS2 keyslot 2.
# Found area 548864 -> 806912
# Running argon2id() benchmark.
# PBKDF benchmark: memory cost = 65536, iterations = 4, threads = 4 (took 72 ms)
# PBKDF benchmark: memory cost = 227555, iterations = 4, threads = 4 (took 264 ms)
# PBKDF benchmark: memory cost = 1048576, iterations = 6, threads = 4 (took 1982 ms)
# Benchmark returns argon2id() 6 iterations, 1048576 memory, 4 threads (for 512-bits key).
# JSON does not fit in the designated area.
# Not enough space in header json area for new keyslot.
# Rolling back in-memory LUKS2 json metadata.
# Releasing crypt device /dev/sda3 context.
# Releasing device-mapper backend.
# Closing read only fd for /dev/sda3.
Command failed with code -1 (wrong or missing parameters).

Gostaria de saber se alguém pode me ajudar a entender o que está errado aqui e o que preciso fazer para remediar.

Existe uma opção de 'tamanho do cabeçalho inicial' que eu possa especificar em nossas compilações? Ou um parâmetro para cryptsetup? Ou estou "apenas" encontrando um bug? (Mas não estou convencido de que algo tão amplamente usado como cryptsetupvai ter um bug do tipo 'ninguém pode mudar suas senhas')

É assim que o cabeçalho LUKs aparece em um host de exemplo.

LUKS header information
Version:           2
Epoch:             5
Metadata area:     16384 [bytes]
Keyslots area:     16744448 [bytes]
UUID:              
Label:             (no label)
Subsystem:         (no subsystem)
Flags:           (no flags)

Data segments:
  0: crypt
    offset: 16777216 [bytes]
    length: (whole device)
    cipher: aes-xts-plain64
    sector: 512 [bytes]

Keyslots:
  0: luks2
    Key:        512 bits
    Priority:   normal
    Cipher:     aes-xts-plain64
    Cipher key: 512 bits
    PBKDF:      argon2id
    Time cost:  9
    Memory:     1048576
    Threads:    4
    Salt:       
    AF stripes: 4000
    AF hash:    sha256
    Area offset:32768 [bytes]
    Area length:258048 [bytes]
    Digest ID:  0
  1: luks2
    Key:        512 bits
    Priority:   normal
    Cipher:     aes-xts-plain64
    Cipher key: 512 bits
    PBKDF:      pbkdf2
    Hash:       sha256
    Iterations: 1000
    Salt:       
    AF stripes: 4000
    AF hash:    sha256
    Area offset:290816 [bytes]
    Area length:258048 [bytes]
    Digest ID:  0
Tokens:
  0: clevis
    Keyslot:    1
Digests:
  0: pbkdf2
    Hash:       sha256
    Iterations: 105025
    Salt:       
    Digest:    

Estou esquecendo de algo profundo? Como dito, tenho certeza de que isso funciona se eu não "atualizar" a caixa para um kernel mais novo, então minha solução alternativa atual é construí-la, recodificar manualmente e então continuar a atualizá-la, mas isso parece... abaixo do ideal.

cryptsetup versões 2.6.0 e 2.7.2

head -c 1M /dev/sda3 | strings -n 128 

reformatado:

{
  "keyslots": {
    "0": {
      "type": "luks2",
      "key_size": 64,
      "af": {
        "type": "luks1",
        "stripes": 4000,
        "hash": "sha256"
      },
      "area": {
        "type": "raw",
        "offset": "32768",
        "size": "258048",
        "encryption": "aes-xts-plain64",
        "key_size": 64
      },
      "kdf": {
        "type": "argon2id",
        "time": 7,
        "memory": 1048576,
        "cpus": 4,
        "salt": "(removed)"
      }
    },
    "1": {
      "type": "luks2",
      "key_size": 64,
      "af": {
        "type": "luks1",
        "stripes": 4000,
        "hash": "sha256"
      },
      "area": {
        "type": "raw",
        "offset": "290816",
        "size": "258048",
        "encryption": "aes-xts-plain64",
        "key_size": 64
      },
      "kdf": {
        "type": "pbkdf2",
        "hash": "sha256",
        "iterations": 1000,
        "salt": "(removed)"
      }
    }
  },
  "tokens": {
    "0": {
      "type": "clevis",
      "keyslots": [
        "1"
      ],
      "jwe": {
        "ciphertext": "(removed)",
        "encrypted_key": "",
        "iv": "(removed)",
        "protected": "",
        "tag": "(removed)"
      }
    }
  },
  "segments": {
    "0": {
      "type": "crypt",
      "offset": "16777216",
      "size": "dynamic",
      "iv_tweak": "0",
      "encryption": "aes-xts-plain64",
      "sector_size": 512
    }
  },
  "digests": {
    "0": {
      "type": "pbkdf2",
      "keyslots": [
        "0",
        "1"
      ],
      "segments": [
        "0"
      ],
      "hash": "sha256",
      "iterations": 88086,
      "salt": "(removed)",
      "digest": "(removed)"
    }
  },
  "config": {
    "json_size": "12288",
    "keyslots_size": "16744448"
  }
}

Edição 2: A história se complica: luksHeaderBackup e depois uma restauração falha.

Mas matar o 'slot 0' e adicionar uma chave ainda funciona. (Supondo que o 'slot 1' você pode extrair, mas nos meus casos clevis-luks-passfunciona bem o suficiente)

luks
  • 1 1 respostas
  • 51 Views

1 respostas

  • Voted
  1. Best Answer
    Sobrique
    2024-12-12T22:08:30+08:002024-12-12T22:08:30+08:00

    Resumo do meu relatório de 'problema' contra o cryptsetup que pode ser encontrado aqui: https://gitlab.com/cryptsetup/cryptsetup/-/issues/924

    A raiz desse problema está relacionada ao dimensionamento padrão do cabeçalho LUKS ao criar via Kickstart e ao tamanho da pegada que o clevis/tang ocupa.

    Especificamente, quando construí essas caixas, usei a diretiva kickstart:

    part pv.0 --fstype=lvmpv --size=1000 --grow --encrypted --passphrase=DEFAULT_PASSWORD
    

    Isso aplica os padrões para luksFormat (no almalinux, não tenho certeza se esse é sempre o padrão) de 16 MB de cabeçalho LUKS, mas 16k - 4k para a área de metadados JSON.

    Normalmente isso é bom, porque um slot de chave luks não tem muitos metadados, então é um padrão sensato no geral.

    No entanto, usamos clevis/tang para desbloquear e configurar - durante o kickstart - umclevis luks bind

    Usamos 6 servidores tang — 3 por site — por motivos de resiliência.

    Nosso script de pós-instalação do kickstart inclui:

    ## Below has been manually wrapped for ease of reading
    
    CLEVIS_CFG='{"t":2,"pins":{"tang":[{"url":"http://tang-10.sitea.domain"},
    {"url":"http://tang-11.siteb.domain"},
    {"url":"http://tang-12.sitea.domain"},
    {"url":"http://tang-13.siteb.domain"},
    {"url":"http://tang-14.sitea.domain"},
    {"url":"http://tang-15.siteb.domain"}]}}'
    
    for device in /dev/sd*[0-9] /dev/nvm*[0-9]
    do
       echo checking $device for being LUKS
       cryptsetup isLuks $device
       if [ $? -eq 0 ] 
       then
          echo "$device is LUKS doing clevis sss config"
          clevis luks list -d $device
          echo $DEFAULT_PASSWORD | clevis luks bind -k - -d $device -y -f sss $CLEVIS_CFG
          echo "Final state post clevis:"
          cryptsetup luksDump $device
       fi
    done
    

    No entanto, temos 6 servidores tang definidos para o sssdesbloqueio, o que pode ser anormalmente grande. (Mas era para resiliência de site duplo - realmente não queríamos estar em um lugar onde toda a nossa empresa não conseguisse inicializar sem múltiplas falhas)

    Os metadados da manilha são consideravelmente maiores e adicionam cerca de 10k à área de metadados, então se verificarmos a ocupação:

    [root@desktop~]# cryptsetup luksDump --dump-json-metadata /dev/sda3 | jq -c | wc -c
    12111
    

    A maior parte disso está na chave tokens.0.jwe.protected, que tem cerca de 10k. (No post acima, ela foi cortada para resumir).

    Por exemplo:

    [root@desktop ~]# cryptsetup luksDump /dev/sda3 --dump-json-metadata | jq '.tokens."0".jwe.protected' | wc -c
    10849
    

    E compare isso com a área de metadados configurada:

    "config":{
        "json_size":"12288",
        "keyslots_size":"16744448"
      }
    

    Então temos apenas 'alguns' bytes livres, e isso não é suficiente para uma nova chave.

    Isso costumava funcionar em nossas implantações 9.1, porque cryptsetupfaria a substituição no local, e essa era a raiz da minha confusão - ainda consigo reproduzir um luksChangeKey bem-sucedido imediatamente após a inicialização, compilando em um initrd 9.1 e um repositório 9.2:

    # Key change, old slot 0, new slot 0.
    # Key slot 0 is going to be overwritten.
    # Wiping keyslot 0 area only.
    

    Não estou claro por que isso é diferente, pois este é o cryptsetup 2.6.0 com as mesmas bibliotecas de criptografia, mas no meu exemplo acima o ChangeKey usa

    # Verifying key from keyslot 0, digest 0.
    # Keyslot 2 assigned to digest 0.
    # Trying to allocate LUKS2 keyslot 2.
    

    E não temos espaço para outro slot de chave, e nunca tivemos, porque clevis/tang ocupa mais do cabeçalho JSON, e é por isso que falha.

    Portanto, as soluções para este problema são:

    Reformate o disco com uma área de metadados json maior.

      --luks2-metadata-size <size>
           This option can be used to enlarge the LUKS2 metadata (JSON)
           area. The size includes 4096 bytes for binary metadata
           (usable JSON area is smaller of the binary area). According
           to LUKS2 specification, only these values are valid: 16, 32,
           64, 128, 256, 512, 1024, 2048 and 4096 kB The <size> can be
           specified with unit suffix (for example 128k).
    

    Por exemplo, o padrão de 16k significa 16k - 4k disponíveis, que é o que temos.

    Esta seria uma opção destrutiva, exigindo um backup/restauração ou reconstrução do disco.

    Inconvenientemente, a partdiretiva kickstart não suporta nenhuma das opções necessárias para o --encryptionsinalizador, então você teria que fazer algo um pouco mais complicado com sua lógica de criação de partição, provavelmente por meio de um %prescript para selecionar as unidades, o tamanho da partição e passar os parâmetros necessários para cryptsetup luksFormat diretamente.

    Despejar o cabeçalho, redimensioná-lo e restaurá-lo.

    Não tenho um processo detalhado, mas deve ser possível cryptsetup luksDump --dump-volume-keycriar um novo cabeçalho do tamanho apropriado com as mesmas configurações: parâmetros de criptografia (cifra, modo, tamanho do setor), uuid do dispositivo LUSK2 e mesmo deslocamento de dados - e, claro, chave de volume - e então substituir o cabeçalho antigo pelo novo.

    As páginas de manual cryptsetup-luksDump e cryptsetup-luksFormat serão uma referência aqui.

    Com um GRANDE aviso de que isso é um pouco... perigoso, aqui está o que parece ter funcionado com sucesso:

    cryptsetup luksDump --dump-volume-key --volume-key-file=volkey /dev/sda3 
    cryptsetup luksHeaderBackup /dev/sda3 --header-backup-file=headerbackup.img
    
    ## Copy these files to somewhere in case the rest goes wrong. Just bear in mind that someone can use those files to "recover" your system too, so ensure they're handled securely
    
    clevis luks unbind -d /dev/sda3 -s 1 ## may not be necessary
    dd if=/dev/zero of=/tmp/luks_test.img bs=1M count=32
    losetup -f --show /tmp/luks_test.img 
    ## This created /dev/loop0, so use that in the next line. 
    ## note: This NEEDS to have the same block sizes and encryption of sda3
    ## This works because they used the same defaults each time. 
    ##NB If you set a different passphrase, it's a bit easier to confirm that you're using the 'new' one not the 'old' one. 
    cryptsetup luksFormat --volume-key=volkey --uuid=<UUID OF sda3> --luks-metadata-size=32k --force-password /dev/loop0
    cryptsetup luksHeaderBackup /dev/loop0 --header-backup-file=new_luks_header.img
    cryptsetup luksHeaderRestore /dev/sda3 --header-backup-file=new_luks_header.img
    ## rerun the clevis luks bind script referenced in my OP to re-apply the clevis-tang config. 
    

    Cruze os dedos e reinicie, porque se você errou, provavelmente deixou seu sistema irrecuperável. (Quero dizer, talvez você tenha feito backup do volkey/header em outro dispositivo, mas tenha em mente que isso é um risco à segurança, então tenha cuidado).

    Verifique o sucesso usando luksChangeKey na senha temporária que você definiu no cabeçalho 'new', para alterá-la para qualquer senha que você normalmente usaria que fosse mais apropriada. (Se ele inicializou, você sabe que clevis/tang funcionaram).

    Basta conviver com dois slots de chave e usar a opção de descriptografia do Clevis para alterar a "outra" chave quando precisar.

    clevis-luks-pass -d <devicename> -s 1 
    

    Irá extrair a senha que o clevis gera e usa, para que você possa usá-la para fazer um luksKillSlotseguido por um luksAddKey.

    Isso pode não ser sempre adequado, mas no cenário acima - onde nossa frase-senha luks slot 0 é um caso de fallback para quando o mecanismo clevis/tang falha, será viável. Você ainda não poderá adicionar mais chaves.

    • 2

relate perguntas

  • Maneira mais rápida de contar zero bytes em uma partição

  • Forneça a senha para udisks para desbloquear o dispositivo criptografado com LUKS

  • Como verificar novamente uma senha LUKS

  • Como aumentar o tamanho de uma partição que fica antes de uma criptografada?

  • alterar o nome designado da raiz lvm criptografada? de sdo para sdn no crypttab?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve