Compare commits
No commits in common. "master" and "1.0.0" have entirely different histories.
8 changed files with 77 additions and 257 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,7 +1,3 @@
|
||||||
# Products
|
|
||||||
Encrypt
|
|
||||||
Decrypt
|
|
||||||
|
|
||||||
# Object files
|
# Object files
|
||||||
*.o
|
*.o
|
||||||
*.ko
|
*.ko
|
||||||
|
|
76
Buffer.c
76
Buffer.c
|
@ -1,76 +0,0 @@
|
||||||
#include "Buffer.h"
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
27
Buffer.h
27
Buffer.h
|
@ -1,27 +0,0 @@
|
||||||
#ifndef _Buffer_h_included_
|
|
||||||
#define _Buffer_h_included_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
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
|
|
30
Common.h
30
Common.h
|
@ -1,30 +0,0 @@
|
||||||
#ifndef _Common_h_included_
|
|
||||||
#define _Common_h_included_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
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
|
|
81
Decrypt.c
81
Decrypt.c
|
@ -2,12 +2,59 @@
|
||||||
* Code is under the MIT license, see the LICENSE file.
|
* Code is under the MIT license, see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Common.h"
|
|
||||||
#include "Buffer.h"
|
|
||||||
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#include <CommonCrypto/CommonCrypto.h>
|
#include <CommonCrypto/CommonCrypto.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
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 )
|
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 );
|
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[] )
|
int main( int argc, const char *argv[] )
|
||||||
{
|
{
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
|
@ -46,7 +117,7 @@ int main( int argc, const char *argv[] )
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char header_data[HeaderSize];
|
char header_data[48];
|
||||||
memcpy( header_data, buf.start, sizeof header_data );
|
memcpy( header_data, buf.start, sizeof header_data );
|
||||||
memset( &header_data[8], 0, 8 );
|
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( "Password len: %d\n", header.password_len );
|
||||||
printf( "ETL: %s\n", header.etl );
|
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" );
|
fprintf( stderr, "Error: Invalid file size\n" );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
98
Encrypt.c
98
Encrypt.c
|
@ -1,98 +0,0 @@
|
||||||
#include "Buffer.h"
|
|
||||||
#include "Common.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <CommonCrypto/CommonCrypto.h>
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
|
||||||
|
|
||||||
int main( int argc, const char *argv[] )
|
|
||||||
{
|
|
||||||
if (argc != 3) {
|
|
||||||
fprintf( stderr, "Call %s <input> <output>\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;
|
|
||||||
}
|
|
15
Makefile
15
Makefile
|
@ -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 $@ $<
|
|
||||||
|
|
|
@ -6,11 +6,10 @@ Thanks to [hph][1] for reverse engineering the details of that config format.
|
||||||
|
|
||||||
## Compile:
|
## Compile:
|
||||||
|
|
||||||
make
|
clang Decrypt.c -o Decrypt
|
||||||
|
|
||||||
## Run:
|
## Run:
|
||||||
|
|
||||||
Decrypt path/to/config.bin path/to/output.tgz
|
Decrypt path/to/config.bin path/to/output.tgz
|
||||||
Encrypt path/to/output.tgz path/to/new/config.bin
|
|
||||||
|
|
||||||
[1]: http://hph.name/207
|
[1]: http://hph.name/207
|
||||||
|
|
Loading…
Add table
Reference in a new issue