我正在为Karl Malbrain的AES implementation编写一个包装器来处理大于16字节的输入文件。
因此,我编写了一个函数aes_encrypt_block
,它将输入缓冲区(message
)拆分为16个字节的块(chunk
/ chunk_cipher
),调用加密/解密函数和将加密/解密的16个字节放回结果缓冲区。
这很有效。但是,我需要在加密之前填充消息。因此,我加密的最后16个字节(在for循环之外)是填充字节。将这些字节复制到输出缓冲区(cipher
)时,我得到一个段错误。我真的不知道出了什么问题。
你看到了错误吗?
此致
#include "aes.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#define DEBUG 1
void aes_encrypt_block(uint8_t **message, uint8_t **cipher, uint8_t blocks, uint8_t pad_bytes);
void aes_decrypt_block(uint8_t **msg_decrypted, uint8_t **cipher, uint8_t blocks, uint8_t pad_bytes);
unsigned long readFile(char *fileName, uint8_t **buffer);
//unsigned long readFile1(char *fileName, uint8_t *buffer);
uint8_t secret[16] = {0x44, 0x43, 0x45, 0x33, 0x44, 0x03, 0x34, 0x44, 0x43, 0x45, 0x33, 0x44, 0x03, 0x34, 0x03, 0x34};
uint8_t *chunk = NULL;
uint8_t *chunk_cipher = NULL;
uint8_t expanded[176] = {0x00};
uint8_t *buffer = NULL;
uint8_t *cipher = NULL;
uint8_t *msg_decrypted = NULL;
uint8_t mode = -1;
int main(int argc, char *argv[]) {
uint32_t i = 0;
uint8_t blocks = -1, pad_bytes = -1;
unsigned long fileLen;
char* ch = NULL;
if(argc<3) {
printf("Wrong arguments supplied.\n\n%s {0/1} OUT\n\n\t0 - encrypt\n\t1 - decrypt\n\tOUT - file to read from / to write to.\n\n", argv[0]);
return 0;
} else {
mode = atoi(argv[1]);
if(mode<0 || mode>1) {
printf("Wrong arguments supplied.\n\n%s {0/1} OUT\n\n\t0 - encrypt\n\t1 - decrypt\n\tOUT - file to read from / to write to.\n\n", argv[0]);
return 0;
}
}
puts("");
// Read file
fileLen = readFile(argv[2], &buffer);
// Setting up parameters and memory
if(fileLen%16!=0) {
printf("- ");
blocks = fileLen/16+1;
pad_bytes = (blocks*16)-fileLen;
} else {
printf("+ ");
blocks = fileLen/16+1;
pad_bytes = 16;
}
cipher = malloc((blocks*16)*sizeof(int));
if(cipher==NULL) printf("malloc() error!\n");
aes_expand_key(secret, expanded);
if(DEBUG) printf("size: %u, size/16: %d, blocks: %d, padding: %d\n\n", fileLen, fileLen/16, blocks, pad_bytes);
if(!mode) { // We will encrypt
aes_encrypt_block(&buffer, &cipher, blocks, pad_bytes);
free(buffer);
FILE *file_enc;
file_enc = fopen("bla.enc", "wb");
fileLen = fwrite(&cipher, sizeof(uint8_t), 32, file_enc);
printf("\nWrote %ld bytes to %s\n", fileLen, argv[2]);
fclose(file_enc);
} else { // We will decrypt
msg_decrypted = malloc((16*blocks)*sizeof(uint8_t));
// Decrypting blocks
aes_decrypt_block(msg_decrypted, cipher, blocks, pad_bytes);
puts("\nDecrypted message:");
printf("%s\n", msg_decrypted);
puts("");
free(msg_decrypted);
}
return 0;
}
unsigned long readFile(char *fileName, uint8_t **buffer) {
unsigned long fileLen = 0;
uint8_t i;
char* ch = NULL;
FILE *file;
file = fopen (fileName, "rb"); /* open the file for reading */
if(file==NULL) {
perror(fileName);
return 0;
}
fseek(file, 0, SEEK_END);
fileLen=ftell(file);
fseek(file, 0, SEEK_SET);
*buffer=malloc(fileLen+1);
if (!buffer) {
fprintf(stderr, "Memory error!");
fclose(file);
return;
}
fread(*buffer, 1, fileLen, file);
printf( "Source message in hex(%s, %ld bytes):\n", fileName, fileLen );
for (ch = *buffer ; ch < *buffer + fileLen; ++ch) {
printf( "%02X", *ch );
}
puts("\nASCII:\n---------");
for (ch = *buffer ; ch < *buffer + fileLen; ++ch) {
printf( "%c", *ch );
}
puts("");
fclose(file);
return fileLen;
}
void aes_encrypt_block(uint8_t **message, uint8_t **cipher, uint8_t blocks, uint8_t pad_bytes) {
uint8_t i;
chunk = malloc(16*sizeof(uint8_t));
if(chunk==NULL) printf("malloc() error!\n");
chunk_cipher = malloc(16*sizeof(uint8_t));
if(chunk_cipher == NULL) printf("malloc() error!\n");
for(i=0; i<(blocks-1); i++) {
memcpy(chunk, message[i*16], 16*sizeof(uint8_t));
aes_encrypt(chunk, expanded, chunk_cipher);
memcpy(cipher[i*16], chunk_cipher, 16*sizeof(uint8_t));
}
// Padding
memcpy(chunk, message[(blocks-1)*16], (16-pad_bytes)*sizeof(uint8_t));
uint8_t j;
for(j=0; j<=pad_bytes; j++) {
chunk[15-j] = pad_bytes;
}
aes_encrypt(chunk, expanded, chunk_cipher);
memcpy(cipher[i*16], chunk, 16*sizeof(uint8_t));
}
修改
Valgrind输出(test.c中的第149行对应于:memcpy(cipher[i*16], chunk, 16*sizeof(uint8_t));
)
Valgrind outputs:
InvalidWrite: Invalid write of size 4
Call stack:
/usr/lib/valgrind/vgpreload_memcheck-x86-linux.so 0x402E08A: memcpy
/home/dev/aes/test.c|149|0x804A604: aes_encrypt_block
/home/dev/aes/test.c|59|0x8049AFE: main
Address 0x0 is not stack'd, malloc'd or (recently) free'd
Valgrind found 1 errors!
答案 0 :(得分:2)
如果pad_bytes == 16
那么这个循环:
for(j=0; j<=pad_bytes; j++) {
chunk[15-j] = pad_bytes;
}
将在chunk
开始之前写入无效位置,可能会损坏您的堆。
应该是:
for(j=0; j<pad_bytes; j++) {
chunk[15-j] = pad_bytes;
}
另请注意,您似乎还有一些memory leaks,其中通过malloc
分配的内存不在free
d,例如chunk
中的chunk_cipher
和aes_encrypt_block()
。
答案 1 :(得分:0)
我会说这行
memcpy(cipher[i*16], chunk_cipher, 16*sizeof(uint8_t));
应该是
memcpy((*cipher) + i*16, chunk_cipher, 16*sizeof(uint8_t));
(memcpy()
的第二次调用适用于第一个参数)
甚至可以更好地更改aes_encrypt_block()
的签名
void aes_encrypt_block(uint8_t **message, uint8_t **cipher, uint8_t blocks, uint8_t pad_bytes)
到
void aes_encrypt_block(uint8_t **message, uint8_t (*cipher)[16], uint8_t blocks, uint8_t pad_bytes)
并做
memcpy(cipher + i, chunk_cipher, sizeof(*cipher));
(memcpy()
的第二次调用适用于第一个参数)