diff --git a/.gitignore b/.gitignore index 894211e..9fa3b1b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,3 @@ -# Products -Encrypt -Decrypt - # Object files *.o *.ko diff --git a/Buffer.c b/Buffer.c deleted file mode 100644 index 51e8dd9..0000000 --- a/Buffer.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "Buffer.h" - -#include -#include -#include -#include - -void Read( struct buffer *buf, size_t length, void *destination ) -{ - assert( buf->next + length < buf->start + buf->length ); - memcpy( destination, buf->next, length ); - buf->next += length; -} - -uint32_t Read32( struct buffer *buf ) -{ - uint32_t result; - Read( buf, sizeof result, &result ); - return CFSwapInt32BigToHost( result ); -} - -uint16_t Read16( struct buffer *buf ) -{ - uint16_t result; - Read( buf, sizeof result, &result ); - return CFSwapInt16BigToHost( result ); -} - -bool OpenFile( struct buffer *buf, const char *fn ) -{ - buf->fd = open( fn, O_RDONLY ); - if (buf->fd < 0) return false; - - struct stat stat; - if (fstat( buf->fd, &stat ) < 0) { - close( buf->fd ); - return false; - } - - buf->length = stat.st_size; - - buf->start = mmap( NULL, buf->length, PROT_READ, MAP_FILE | MAP_PRIVATE, buf->fd, 0 ); - if (!buf->start) { - close( buf->fd ); - return false; - } - - buf->next = buf->start; - - return true; -} - -void OpenBuffer( struct buffer *buf, void *data, size_t length ) -{ - buf->start = buf->next = data; - buf->length = length; - buf->fd = -1; -} - -void Write( struct buffer *buf, const void *data, size_t length ) -{ - memcpy(buf->next, data, length); - buf->next += length; -} - -void Write32( struct buffer *buf, uint32_t value ) -{ - uint32_t write = CFSwapInt32HostToBig(value); - Write(buf, &write, sizeof write); -} - -void Write16( struct buffer *buf, uint16_t value ) -{ - uint16_t write = CFSwapInt16HostToBig(value); - Write(buf, &write, sizeof write); -} diff --git a/Buffer.h b/Buffer.h deleted file mode 100644 index 84cde40..0000000 --- a/Buffer.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _Buffer_h_included_ -#define _Buffer_h_included_ - -#include -#include -#include - -struct buffer { - uint8_t *start; - size_t length; - uint8_t *next; - int fd; -}; - -void Read( struct buffer *buf, size_t length, void *destination ); -uint32_t Read32( struct buffer *buf ); -uint16_t Read16( struct buffer *buf ); - -void Write( struct buffer *buf, const void *data, size_t length ); -void Write32( struct buffer *buf, uint32_t value ); -void Write16( struct buffer *buf, uint16_t value ); - -void OpenBuffer( struct buffer *buf, void *data, size_t length ); - -bool OpenFile( struct buffer *buf, const char *fn ); - -#endif diff --git a/Common.h b/Common.h deleted file mode 100644 index 39156b1..0000000 --- a/Common.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _Common_h_included_ -#define _Common_h_included_ - -#include - -struct header -{ - char magic[4]; // magic bytes \x43 \x46 \x47 \x31 (CFG1) - uint32_t payload_size; // length of ciphertext = length of padded plaintext (big endian) - uint8_t header_md5[8]; // first 8 bytes of MD5 computed over header (assuming the 8 bytes of "header_md5" are \x00) - char etl[7]; // blank electronic label (etl), always "000000" (null-terminated char array) - uint8_t unused1; // not used at the moment - uint16_t password_len; // length of the password used in AES encryption (big endian) - uint16_t padding_len; // number of padding bytes added to plaintext (big endian) - uint8_t unused2[4]; // not used at the moment - uint8_t plaintext_md5[16]; // MD5 hash of the plaintext -}; - -static const char aes_key[32] = { - 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -enum { - HeaderSize = 48 -}; - -#endif diff --git a/Decrypt.c b/Decrypt.c index d88b3af..38578f1 100644 --- a/Decrypt.c +++ b/Decrypt.c @@ -2,12 +2,59 @@ * Code is under the MIT license, see the LICENSE file. */ -#include "Common.h" -#include "Buffer.h" - #include #include +#include +#include +struct header +{ + char magic[4]; // magic bytes \x43 \x46 \x47 \x31 (CFG1) + uint32_t payload_size; // length of ciphertext = length of padded plaintext (big endian) + char header_md5[8]; // first 8 bytes of MD5 computed over header (assuming the 8 bytes of "header_md5" are \x00) + char etl[7]; // blank electronic label (etl), always "000000" (null-terminated char array) + char unused1; // not used at the moment + uint16_t password_len; // length of the password used in AES encryption (big endian) + uint16_t padding_len; // number of padding bytes added to plaintext (big endian) + char unused2[4]; // not used at the moment + char plaintext_md5[16]; // MD5 hash of the plaintext +}; + +static const char aes_key[32] = { + 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + + +struct buffer { + uint8_t *start; + size_t length; + uint8_t *next; + int fd; +}; + +void Read( struct buffer *buf, size_t length, void *destination ) +{ + assert( buf->next + length < buf->start + buf->length ); + memcpy( destination, buf->next, length ); + buf->next += length; +} + +uint32_t Read32( struct buffer *buf ) +{ + uint32_t result; + Read( buf, sizeof result, &result ); + return CFSwapInt32BigToHost( result ); +} + +uint16_t Read16( struct buffer *buf ) +{ + uint16_t result; + Read( buf, sizeof result, &result ); + return CFSwapInt16BigToHost( result ); +} void ReadHeader( struct buffer *buf, struct header *header ) { @@ -22,6 +69,30 @@ void ReadHeader( struct buffer *buf, struct header *header ) Read( buf, 16, header->plaintext_md5 ); } +bool OpenFile( struct buffer *buf, const char *fn ) +{ + buf->fd = open( fn, O_RDONLY ); + if (buf->fd < 0) return false; + + struct stat stat; + if (fstat( buf->fd, &stat ) < 0) { + close( buf->fd ); + return false; + } + + buf->length = stat.st_size; + + buf->start = mmap( NULL, buf->length, PROT_READ, MAP_FILE | MAP_PRIVATE, buf->fd, 0 ); + if (!buf->start) { + close( buf->fd ); + return false; + } + + buf->next = buf->start; + + return true; +} + int main( int argc, const char *argv[] ) { if (argc != 3) { @@ -46,7 +117,7 @@ int main( int argc, const char *argv[] ) return 1; } - char header_data[HeaderSize]; + char header_data[48]; memcpy( header_data, buf.start, sizeof header_data ); memset( &header_data[8], 0, 8 ); @@ -61,7 +132,7 @@ int main( int argc, const char *argv[] ) printf( "Password len: %d\n", header.password_len ); printf( "ETL: %s\n", header.etl ); - if (buf.length - header.payload_size != HeaderSize) { + if (buf.length - header.payload_size != 48) { fprintf( stderr, "Error: Invalid file size\n" ); return 1; } diff --git a/Encrypt.c b/Encrypt.c deleted file mode 100644 index 2498346..0000000 --- a/Encrypt.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "Buffer.h" -#include "Common.h" - -#include -#include -#include - -int main( int argc, const char *argv[] ) -{ - if (argc != 3) { - fprintf( stderr, "Call %s \n", argv[0] ); - return 1; - } - - struct buffer inputFile = { 0 }; - if (!OpenFile(&inputFile, argv[1])) { - fprintf(stderr, "Cannot open input file %s\n", argv[1]); - return 1; - } - - struct header header = { 0 }; - - memcpy(header.magic, "CFG1", sizeof header.magic); - strcpy(header.etl, "000000"); - - CC_MD5_CTX context; - CC_MD5_Init(&context); - - // Hash input data. - CC_MD5_Update(&context,inputFile.start, inputFile.length); - - // Add PKCS7 padding data to hash. Decoder calculates hash over padded data. - uint8_t pad = kCCBlockSizeAES128 - (inputFile.length % kCCBlockSizeAES128); - for (uint8_t i = 0; i < pad; i++) { - CC_MD5_Update(&context,&pad, sizeof pad); - } - - // Finalize hash and store in header. - CC_MD5_Final(header.plaintext_md5, &context); - - size_t encryptedBufferSize = inputFile.length + kCCBlockSizeAES128; - void *encryptedBuffer = malloc(encryptedBufferSize); - if (!encryptedBuffer) { - fprintf(stderr, "Not enough memory to encrypt file\n"); - return 1; - } - size_t encryptedDataLength = 0; - - CCCryptorStatus status = CCCrypt(kCCEncrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding|kCCOptionECBMode, - aes_key, sizeof aes_key, - NULL, - inputFile.start, inputFile.length, - encryptedBuffer, encryptedBufferSize, &encryptedDataLength); - - if (status != kCCSuccess) { - fprintf(stderr, "Error encrypting (%d)\n", status); - return 1; - } - - header.payload_size = encryptedDataLength; - header.padding_len = encryptedDataLength - inputFile.length; - - uint8_t headerData[HeaderSize] = {0}; - struct buffer headerBuf = {0}; - OpenBuffer(&headerBuf, headerData, sizeof headerData); - - Write(&headerBuf, header.magic, sizeof header.magic); - Write32(&headerBuf, header.payload_size); - headerBuf.next += sizeof header.header_md5; // Skip header_md5 - Write(&headerBuf, header.etl, sizeof header.etl); - Write(&headerBuf, &header.unused1, sizeof header.unused1); - Write16(&headerBuf, header.password_len); - Write16(&headerBuf, header.padding_len); - Write(&headerBuf, header.unused2, sizeof header.unused2); - Write(&headerBuf, header.plaintext_md5, sizeof header.plaintext_md5); - - uint8_t header_md5[CC_MD5_DIGEST_LENGTH]; - CC_MD5(headerData, sizeof headerData, header_md5); - memcpy(&headerData[8], header_md5, sizeof header.header_md5); - - int fdout = open( argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0600 ); - if (fdout < 0) { - fprintf( stderr, "Error: cannot write output file\n" ); - return 1; - } - - bool written = write(fdout, headerData, sizeof headerData) == sizeof headerData; - written = written && write(fdout, encryptedBuffer, encryptedDataLength) == encryptedDataLength; - - if (!written) { - fprintf(stderr, "Cannot write output file\n"); - return 1; - } - - close(fdout); - - return 0; -} diff --git a/Makefile b/Makefile deleted file mode 100644 index 738a411..0000000 --- a/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -all: Decrypt Encrypt - -Decrypt: Decrypt.o Buffer.o - clang -o $@ $^ - -Encrypt: Encrypt.o Buffer.o - clang -o $@ $^ - -Decrypt.o: Decrypt.c Buffer.h Common.h -Buffer.o: Buffer.c Buffer.h -Encrypt.o: Encrypt.c Buffer.h Common.h - -.c.o: - clang -c -o $@ $< - diff --git a/README.md b/README.md index 55036d5..762c852 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,10 @@ Thanks to [hph][1] for reverse engineering the details of that config format. ## Compile: - make + clang Decrypt.c -o Decrypt ## Run: Decrypt path/to/config.bin path/to/output.tgz - Encrypt path/to/output.tgz path/to/new/config.bin [1]: http://hph.name/207