2016-07-24 4 views
0

Ich benutze Ocf-Linux in einer Openwrt-Anwendung und habe in OCF CRYPTO_MAX_DATA_LEN (64K-1) und E2BIG Fehler im CRYPTO_AES_CBC-Modus ausgeführt.ocf-linux, Aufteilen von großen Puffern in Stücke <MAX_DATA_LEN

Als Konsequenz muss ich den Eingabepuffer in Blöcke < MAX_DATA_LEN teilen und Chunks einzeln verarbeiten und die resultierenden Klartext/chiffrierten Textblöcke in einem großen Ausgabepuffer zusammenstellen.

Google hat spärliche Ergebnisse und keinen Code zu diesem Problem. Wikipedia zeigt dies möglich ist, durch die vorherige iv zum nächsten Block Betrieb Fütterung:

https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher-block_chaining_.28CBC.29

FRAGEN/POINT:

  1. Ist das möglich ocf-linux mit?

  2. Hat jemand dieses Problem gelöst/gelöst und hat (Pseudo-) Code = (Best Practice) zu teilen, um mich zu retten das Rad neu erfinden? 3 - Kann jemand irgendwelche Probleme mit meinem Code unten sehen?

Meine aktuelle decrypt Funktion (Arbeits für Größe < MAX_DATA_LEN) folgt:

Was ich beobachte falsche entschlüsselten Daten für alle ist, aber der erste Block mit dem Anfang iv. Ich vermute, dass nachfolgende ivs aus dem vorherigen Block irgendwie falsch sind, trotz der Verwendung des Algorithmus aus Wikipedia.

#define  AES_CHUNK_SIZE 0xFFE0 
#define  IV_SIZE   128 // bits 

int aes_decrypt(struct cryptodev_ctx* ctx, const void* iv, const void* ciphertext, void* plaintext, size_t size) 
{ 
    struct crypt_op cryp; 
    void* p; 

    /* check plaintext and ciphertext alignment */ 
    if (ctx->alignmask) { 
      p = (void*)(((unsigned long)plaintext + ctx->alignmask) & ~ctx->alignmask); 
      if (plaintext != p) { 
       DebugPrintf(DEBUG_ERR, "%s: plaintext is not aligned\n", __func__); 
       return ERROR; 
      } 

      p = (void*)(((unsigned long)ciphertext + ctx->alignmask) & ~ctx->alignmask); 
      if (ciphertext != p) { 
       DebugPrintf(DEBUG_ERR, "%s: ciphertext is not aligned\n", __func__); 
       return ERROR; 
      } 
    } 

    memset(&cryp, 0, sizeof(cryp)); 

    /* Decrypt ciphertext to plaintext */ 
    cryp.ses = ctx->sess.ses; 
    cryp.len = size; 
    cryp.src = (void*)ciphertext; 
    cryp.dst = plaintext; 
    cryp.iv = (void*)iv; 
    cryp.op = COP_DECRYPT; 
    if (size <= CRYPTO_MAX_DATA_LEN) { 
      if (ioctl(ctx->cfd, CIOCCRYPT, &cryp)) { 
       DebugPrintf(DEBUG_ERR, "%s: ioctl(CIOCCRYPT)\n", __func__); 
       return ERROR; 
      } 
    } else { 
      unsigned int i, remainder; 
      cryp.len = AES_CHUNK_SIZE; 
      remainder = size % AES_CHUNK_SIZE; 
      char byte; 
      DebugPrintf(DEBUG_ERR, "%s: Decrypting large block AES_CHUNK_SIZE: %x size: %x remainder: %x\n", 
        __func__, 
        (unsigned int) AES_CHUNK_SIZE, 
        (unsigned int) size, 
        remainder); 
      for (i = 0; i < (size/AES_CHUNK_SIZE); i++) { 
        DebugPrintf(DEBUG_ERR, "%s: Decrypting chunk: %x\n", __func__, i); 
        if (ioctl(ctx->cfd, CIOCCRYPT, &cryp)) { 
         DebugPrintf(DEBUG_ERR, "%s: ioctl(CIOCCRYPT)\n", __func__); 
         return ERROR; 
        } 
        // Print first 32 bytes of decrypted chunk data 
        DebugPrintf(DEBUG_ERROR, "Decrypted data, Section offset: %x\n", (unsigned int) (AES_CHUNK_SIZE * i)); 
        for (int j = 0; j < 32 ; j++) { 
          byte = cryp.dst[AES_CHUNK_SIZE * i + j]; 
          DebugPrintf(DEBUG_ERROR, "%x ", byte); 
        } 
        DebugPrintf(DEBUG_ERROR, "\n"); 
        cryp.src += AES_CHUNK_SIZE; 
        cryp.dst += AES_CHUNK_SIZE; 
        cryp.iv = cryp.src - (IV_SIZE/8); 
      } 
      if (remainder) { 
        DebugPrintf(DEBUG_ERR, "%s: Decrypting last chunk: %x\n", __func__, i); 
        cryp.len = remainder; 
        if (ioctl(ctx->cfd, CIOCCRYPT, &cryp)) { 
         DebugPrintf(DEBUG_ERR, "%s: ioctl(CIOCCRYPT)\n", __func__); 
         return ERROR; 
        } 
        DebugPrintf(DEBUG_ERROR, "Decrypted data, Section offset: %x\n", (unsigned int) (AES_CHUNK_SIZE * i)); 
        for (int j = 0; j < 32 ; j++) { 
          byte = cryp.dst[AES_CHUNK_SIZE * i + j]; 
          DebugPrintf(DEBUG_ERROR, "%x ", byte); 
        } 
        DebugPrintf(DEBUG_ERROR, "\n"); 
      } 
      } 
    } 
return OK; 
} 

Antwort

0

In jedem anderen Modus als ECB sollte die IV für jeden unterschiedlichen Aufruf der Verschlüsselung immer frisch sein. Andernfalls wäre IV aus dem Chiffretext zu erraten und die Sicherheit der Verschlüsselung gefährdet.

Wenn während der Verschlüsselung die IV für den aktuellen Block mit einer für einen anderen Block übereinstimmt, wird die Sicherheit geschwächt, daher die Längenbeschränkung.

1

Gelöst: Das Problem bestand darin, dass die Chiffretext- und Klartextpuffer identisch waren und der Klartextblock n den Chiffretext n überschrieb, einschließlich der IV, die zum Entschlüsseln von Block n + 1 benötigt wurde. Arbeitscode folgt:

Ich würde mich über Feedback freuen, wie die zweite IV Kopie zu beseitigen.

int aes_decrypt(struct cryptodev_ctx* ctx, const void* iv, const void* ciphertext, void* plaintext, size_t size) 
{ 
    struct crypt_op cryp; 
    void* p; 

    /* check plaintext and ciphertext alignment */ 
    if (ctx->alignmask) { 
      p = (void*)(((unsigned long)plaintext + ctx->alignmask) & ~ctx->alignmask); 
      if (plaintext != p) { 
       return ERROR; 
      } 

      p = (void*)(((unsigned long)ciphertext + ctx->alignmask) & ~ctx->alignmask); 
      if (ciphertext != p) { 
       return ERROR; 
      } 
    } 

    memset(&cryp, 0, sizeof(cryp)); 

    /* Decrypt ciphertext to plaintext */ 
    cryp.ses = ctx->sess.ses; 
    cryp.len = size; 
    cryp.src = (void*)ciphertext; 
    cryp.dst = plaintext; 
    cryp.iv = (void*)iv; 
    cryp.op = COP_DECRYPT; 
    if (size <= CRYPTO_MAX_DATA_LEN) { 
      if (ioctl(ctx->cfd, CIOCCRYPT, &cryp)) { 
       return ERROR; 
      } 
    } else { 
      unsigned int i, remainder; 
      cryp.len = AES_CHUNK_SIZE; 
      remainder = size % AES_CHUNK_SIZE; 
      char this_iv[IV_SIZE/8]; 
      char next_iv[IV_SIZE/8]; 

      for (i = 0; i < (size/AES_CHUNK_SIZE); i++) { 
        // For case where ciphertext and plaintext use same buffer (ciphertext overwritten by plaintext) 
        // need to copy the last block of ciphertext from CHUNK n 
        // to use as IV for chunk n + 1 
        memcpy(next_iv, cryp.src + AES_CHUNK_SIZE - (IV_SIZE/8), IV_SIZE/8); 
        if (ioctl(ctx->cfd, CIOCCRYPT, &cryp)) { 
         return ERROR; 
        } 

        cryp.src += AES_CHUNK_SIZE; 
        cryp.dst += AES_CHUNK_SIZE; 
        memcpy(this_iv, next_iv, IV_SIZE/8); 
        cryp.iv = (void*) &this_iv; 
      } 
      if (remainder) { 
        cryp.len = remainder; 
        if (ioctl(ctx->cfd, CIOCCRYPT, &cryp)) { 
         return ERROR; 
        } 
      } 
    } 
    return OK; 
} 

Grüße; Bill Ross