-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbackup_encrypt.c
156 lines (134 loc) · 3.57 KB
/
backup_encrypt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// compile with -lcrypto -lssl
// THIS PROGRAM DOES NOT SEEM TO WORK CORRECTLY
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/md5.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/ssl.h>
static void callback(int a, int b, void *c)
{
putchar('.');
}
static bool myrand_seeded = false;
static uint32_t myrand_state;
static void myrand_seed(const void *buf, int num)
{
myrand_seeded = true;
myrand_state = *(uint32_t *)buf & 0x7fffffff;
}
static unsigned char myrand_get_byte()
{
if (!myrand_seeded) {
myrand_seeded = true;
myrand_state = 1;
}
myrand_state = ((uint64_t)myrand_state * 0x3aa8 + 0xf4627) % 0x78f0e079;
return myrand_state >> 4;
}
static int myrand_nopseudo_bytes(unsigned char *buf, int num)
{
for (int i = 0; i < num; i++) {
buf[i] = myrand_get_byte();
}
return 1;
}
static RAND_METHOD myrand = {
myrand_seed,
myrand_nopseudo_bytes,
NULL,
NULL,
NULL,
NULL,
};
struct header {
char magic1[8];
uint64_t size;
unsigned char content_md5[16];
char magic2[16];
char version[32];
char type[32];
unsigned char password_md5[16];
char zeros[16];
};
static const char magic1[8] = {0x49, 0x4c, 0xfa, 0x42, 0x01, 0x01, 0x00, 0x00};
int main(int argc, char **argv)
{
SSL_library_init();
RAND_cleanup();
RAND_set_rand_method(&myrand);
if (argc != 4) {
fprintf(stderr, "usage: %s <chip id> <input file> <output file>\n", argv[0]);
fprintf(stderr, "chip id must be 16 lower case hex digits\n");
return 1;
}
FILE *in_file = fopen(argv[2], "r");
FILE *out_file = fopen(argv[3], "w+");
// high security crypto happens here
char key_length[4] = {0, 0, 1, 0};
char key[0x100];
char iv[0x10];
memset(iv, 0, 0x10);
char salt[0x40];
memset(salt, 0, 0x40);
// seed rng
char pbkdf2_result[0x80];
PKCS5_PBKDF2_HMAC(argv[1], 16, salt, 0x40, 0x2f59, EVP_sha384(), 0x80, pbkdf2_result);
RAND_seed(pbkdf2_result, 4);
// generate key
RSA *rsakey = RSA_generate_key(0x800, 0x10001, callback, NULL);
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_PKEY_set1_RSA(pkey, rsakey);
EVP_CIPHER_CTX *cipher_ctx = EVP_CIPHER_CTX_new();
unsigned char *key_ptr = key;
int ekl;
EVP_SealInit(cipher_ctx, EVP_aes_256_cbc(), &key_ptr, &ekl, iv, &pkey, 1);
// write key info
fseek(out_file, sizeof(struct header), SEEK_SET);
// just write the same key 5 times
for (int i = 0; i < 5; i++) {
fwrite(salt, 0x40, 1, out_file);
fwrite(key_length, 4, 1, out_file);
fwrite(key, 0x100, 1, out_file);
fwrite(iv, 0x10, 1, out_file);
}
char buf[0x2000];
char out[0x2000];
size_t read_len;
int out_len;
while (read_len = fread(buf, 1, 0x1000, in_file)) {
EVP_SealUpdate(cipher_ctx, out, &out_len, buf, read_len);
fwrite(out, out_len, 1, out_file);
}
EVP_SealFinal(cipher_ctx, out, &out_len);
fwrite(out, out_len, 1, out_file);
struct header header;
memset(&header, 0, sizeof(struct header));
memcpy(&header.magic1, &magic1, 8);
header.size = ftell(out_file);
header.magic2[0] = 1;
memcpy(&header.version, "1.40", 4);
memcpy(&header.type, "iLO 5 Backup file", 17);
char md5buf[0x200];
for (int i = 0; i < 0x200; i++) {
md5buf[i] = i % 0x4d;
}
MD5_CTX md5_ctx;
MD5_Init(&md5_ctx);
MD5_Update(&md5_ctx, md5buf, 0x200);
fseek(out_file, 0x90, SEEK_SET);
while (fread(md5buf, 1, 0x200, out_file) != 0) {
MD5_Update(&md5_ctx, md5buf, 0x200);
}
/* write content hash */
MD5_Final(&header.content_md5, &md5_ctx);
/* write empty password hash */
MD5_Init(&md5_ctx);
MD5_Final(&header.password_md5, &md5_ctx);
rewind(out_file);
fwrite(&header, sizeof(struct header), 1, out_file);
return 0;
}