This source file includes following definitions.
- _strlwr
- read32_be
- store32_be
- align128
- get_hexstring
- fi2rec_size
- fi2enc
- main
1
2
3 #include <stdio.h>
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <memory.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include "zlib.h"
10
11 #include "aes128.h"
12
13 static const char *g_str_err_malloc = "memory allocation error (requested %d bytes)\n";
14 static const char *g_str_shorthelp = "Usage: fi2encdec [-p PID] [-key KEY -iv IV] [-x FLAGS] in.file out.file\n"
15 " FLAGS: one or more of the following letters\n"
16 " W: checksum is word based (on new models)\n"
17 "\n";
18
19 char *_strlwr(char *moep) {
20 char *tmp = moep;
21 while((*tmp = tolower(*tmp))) tmp++;
22 return moep;
23 }
24
25
26 struct fi2_rec_s {
27 uint32_t offset;
28 uint32_t upklen;
29 uint32_t len;
30 uint32_t addr;
31 uint32_t uf1;
32 uint32_t fmain;
33 uint32_t fboot;
34 uint32_t uf2;
35 uint32_t uf3;
36 uint32_t uf4;
37 } fi2_rec_s;
38
39
40 typedef struct fi2_header_s {
41 uint32_t hlen_be;
42 uint32_t hwid;
43 uint32_t unk1;
44 uint32_t id;
45 uint32_t ch;
46 uint32_t unk2;
47 uint32_t nblk;
48 uint32_t datacs;
49 } fi2_hdr_t, *pfi2_hdr_t;
50
51 static uint32_t read32_be( const void *src_buffer )
52 {
53 unsigned char *b = (unsigned char *)src_buffer;
54 return (b[0]<<24) | (b[1] << 16) | (b[2] << 8) | b[3];
55 }
56
57 static void store32_be( void *dst_buffer, uint32_t value )
58 {
59 unsigned char *b = (unsigned char *)dst_buffer;
60 b[0] = ( value >> 24 ) & 0xFF;
61 b[1] = ( value >> 16 ) & 0xFF;
62 b[2] = ( value >> 8 ) & 0xFF;
63 b[3] = ( value >> 0 ) & 0xFF;
64 }
65
66 static uint32_t align128( uint32_t value )
67 {
68 return ( (value + 16 - 1) & 0xFFFFFFF0ul );
69 }
70
71 static int get_hexstring( void *dst, const char *str, int len )
72 {
73 int i;
74 unsigned char c;
75 unsigned char *p = (unsigned char *)dst;
76
77 if( !str ){
78 printf( "No hex string supplied!\n" );
79 return -1;
80 }
81 if( !p ) return -1;
82 if( strlen( str ) != (size_t)len*2 ){
83 printf( "Hex length mismatch in \"%s\"!\n", str );
84 return -1;
85 }
86 for( i = 0; i < len*2; i++ ){
87 c = str[i];
88 if( c < ('9'+1) && c >= '0' ) c-= 0x30;
89 else if( c < 'G' && c >= 'A' ) c -= ('A' - 0x0A);
90 else if( c < 'g' && c >= 'a' ) c -= ('a' - 0x0A);
91 else {
92 printf("Non-hex character \'%c\' at %d in string %s\n", c, i+1, str );
93 return -1;
94 }
95 p[i/2] = i & 1 ? p[i/2] | c : c << 4;
96 }
97 return 0;
98 }
99
100 static int fi2rec_size(uint32_t dryos_ver)
101 {
102
103 if (dryos_ver >= 55)
104 {
105 return sizeof (fi2_rec_s);
106 }
107 else if (dryos_ver >= 50)
108 {
109 return sizeof (fi2_rec_s) - 4;
110 }
111 else
112 {
113 return sizeof (fi2_rec_s) - 8;
114 }
115 }
116
117 static int fi2enc( char *infname, char *outfname, uint32_t *key, uint32_t *iv , uint32_t pid, uint32_t dryos_ver,
118 int32_t cs_words)
119 {
120 uLongf i;
121 size_t flen;
122 uint32_t cs;
123 FILE *fi, *fo;
124 fi2_hdr_t hdr;
125 struct fi2_rec_s fi2rec;
126 unsigned char *buf = NULL;
127 unsigned char *upkbuf = NULL;
128 unsigned char exkey[176];
129 unsigned char *pblk;
130
131 if( !infname ){
132 printf("Please supply input file name.\n");
133 return -1;
134 }
135 if( !outfname ){
136 printf("Please supply target file name.\n");
137 return -1;
138 }
139 aes128_expandkey( exkey, key );
140 cs = 0;
141 memset(&hdr, 0, sizeof (hdr));
142 memset(&fi2rec, 0, sizeof (fi2rec));
143 hdr.hwid=pid;
144 hdr.unk1=0x02230000;
145 hdr.id=0x01010000;
146 hdr.ch=0;
147 hdr.unk2=1;
148 fi2rec.addr=0;
149 fi2rec.fboot = 1;
150 if ( !(fi = fopen(infname, "rb")) ){
151 printf( "Can't open data file %s\n", infname );
152 return -1;
153 }
154 fseek( fi, 0, SEEK_END );
155 flen = ftell( fi );
156 fseek( fi, 0, SEEK_SET );
157
158 if( flen <= 0 || flen > (256 << 20) ){
159 printf( "Data file %s have unacceptable file size (%ld)\n", infname, (unsigned long) flen );
160 return -1;
161 }
162 upkbuf = (unsigned char*)malloc( flen );
163 if( !upkbuf ){
164 printf( g_str_err_malloc, flen );
165 return -1;
166 }
167 if( flen > fread( upkbuf, 1, flen, fi ) ){
168 printf( "Error reading data file\n" );
169 return -1;
170 }
171 fclose( fi );
172 i = align128( 4 + compressBound( flen ) );
173 buf = (unsigned char*)malloc( i );
174 if( !buf ){
175 printf( g_str_err_malloc, i );
176 return -1;
177 }
178 memset( buf, 0xFF, i );
179 i -= 4;
180 if( Z_OK != compress( buf + 4, &i, upkbuf, flen ) ){
181 printf( "Data compression error\n" );
182 return -1;
183 }
184 store32_be( buf, i );
185 fi2rec.upklen = flen;
186 fi2rec.offset = 0;
187 fi2rec.len = align128( i + 4 );
188
189 aes128_cbc_encrypt( buf, exkey, iv, fi2rec.len );
190 pblk = buf;
191 if (cs_words) {
192 uint32_t *wbuf = (uint32_t*)buf;
193 for( i = 0; i < fi2rec.len/4; i++) cs += wbuf[i];
194 }
195 else {
196 for( i = 0; i < fi2rec.len; i++) cs += buf[i];
197 }
198
199 free( upkbuf ); upkbuf = NULL;
200
201
202 i = 32 + fi2rec_size(dryos_ver);
203 i = align128(i);
204 store32_be( &hdr.hlen_be, i - 4 );
205 hdr.nblk = 1;
206 hdr.datacs = cs;
207 buf = (unsigned char*)malloc( i );
208 if( !buf ){
209 printf( g_str_err_malloc, i );
210 return -1;
211 }
212 memset( buf, 0, i );
213 memcpy( buf, &hdr, 32 );
214 memcpy( buf+32, &fi2rec, fi2rec_size(dryos_ver));
215 aes128_cbc_encrypt( buf, exkey, iv, i );
216
217
218
219 printf( "Saving %s\n", outfname );
220 fo = fopen(outfname,"wb");
221 if(!fo){
222 printf("Can't open file %s for writing\n", outfname);
223 return(-1);
224 }
225
226 if ( i != fwrite(buf, 1, i, fo ) ){
227 printf("\nError writing header to %s (%ld bytes)\n", outfname, i);
228 return(-1);
229 }
230 free( buf );
231
232 if (fi2rec.len != fwrite( pblk, 1, fi2rec.len, fo ) ){
233 printf("\nError writing data block to %s (%d bytes)\n", outfname, fi2rec.len);
234 return(-1);
235 }
236 free( pblk );
237 fclose( fo );
238 return 0;
239 }
240
241 int main( int argc, char **argv )
242 {
243 int i;
244 uint32_t key_buf[4];
245 uint32_t iv_buf[4];
246 uint32_t *key = NULL;
247 uint32_t *iv = NULL;
248 char *fni = NULL, *fno = NULL;
249 uint32_t pid=0;
250 uint32_t dryos_ver=0;
251 char *flags = NULL;
252 int32_t cs_words = 0;
253
254
255 for( i = 1; i < argc; i++){
256 if( argv[i][0] == '/' || argv[i][0] == '-' ){
257
258 if( !strcmp( "key", _strlwr(argv[i]+1) ) ){
259 if ( get_hexstring( key_buf, argv[++i], sizeof key_buf ) ) return -1;
260 else key = key_buf;
261 }
262 else if( !strcmp( "iv", _strlwr(argv[i]+1) ) ){
263 if ( get_hexstring( iv_buf, argv[++i], sizeof iv_buf ) ) return -1;
264 else iv = iv_buf;
265 }
266 else if( !strcmp( "p", _strlwr(argv[i]+1) ) ){
267 char *err=NULL;
268 pid = strtoul(argv[++i], &err, 0);
269 if (*err) return -1;
270 }
271 else if( !strcmp( "pv", _strlwr(argv[i]+1) ) ){
272 char *err=NULL;
273 dryos_ver = strtoul(argv[++i], &err, 0);
274 if (*err) return -1;
275 }
276 else if( !strcmp( "x", _strlwr(argv[i]+1) ) ){
277 flags = argv[++i];
278 }
279 else {
280 printf("Unexpected option: %s\n", argv[i]);
281 return -1;
282 }
283 } else {
284 if( !fni ) fni = argv[i];
285 else if( !fno ) fno = argv[i];
286 else {
287 printf("Unexpected parameter: %s\n", argv[i]);
288 return -1;
289 }
290 }
291 }
292 if( !key || !iv || !pid){
293 fputs( g_str_shorthelp, stdout );
294 return -1;
295 }
296 if (flags) {
297 if ( strstr(flags, "W") ) {
298 cs_words = 1;
299 }
300 }
301 for( i = 0; i < 4; i ++ ) key[i] = read32_be( key+i );
302 i = fi2enc( fni, fno, key, iv , pid, dryos_ver, cs_words);
303 if ( !i ) printf( "Done\n" ); else printf( "Failed!\n" );
304 return i;
305 }