我在openwrt应用程序中使用ocf-linux,并且在CRYPTO_AES_CBC模式下遇到OCF CRYPTO_MAX_DATA_LEN(64K-1)和E2BIG错误。
因此,我需要将输入缓冲区拆分为块< MAX_DATA_LEN并单独处理块并将生成的明文/密文块组合成一个大输出缓冲区。
Google的搜索结果很少,而且没有关于此问题的代码。维基百科表明,通过将之前的iv提供给下一个块操作,可以实现这一点:
https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher-block_chaining_.28CBC.29
问题/ POINT:
这可以使用ocf-linux吗?
有没有人遇到/解决了这个问题并且有(伪)代码=(最佳实践)要分享以保存我重新发明=轮子? 3 - 任何人都可以在下面看到我的代码有任何问题吗?
我当前的解密函数(适用于大小< MAX_DATA_LEN)如下:
我观察到的是除了第一个具有初始iv的块以外的所有解密数据。尽管使用维基百科的算法,我怀疑前一个块的后续iv在某种程度上是不正确的。
#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;
}
答案 0 :(得分:1)
解决:问题是密文和明文缓冲区是相同的,并且明文块n覆盖了密文n,包括解密块n + 1所需的IV。工作代码如下:
我很感激如何消除第二份IV副本的反馈。
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;
}
的问候; 比尔罗斯
答案 1 :(得分:0)
在ECB以外的任何模式下,对于每次不同的加密调用,IV应始终保持新鲜。否则,IV可以从密文中猜出,并且加密的安全性受到损害。
如果在加密时,当前块的IV与另一个块的IV一致,则安全性将减弱,因此长度限制。