// Otherwise, we make sure the error message for decrypting arm9bin mentions this.
}
-int decrypt_cetk_key(void *key, const void *cetk)
-{
- // This function only decrypts the NATIVE_FIRM CETK.
- // I don't need it for anything else atm.
- // Either way, this is the reason for the two checks here at the top.
-
- static int common_key_y_init = 0;
- uint8_t iv[AES_BLOCK_SIZE] = {0};
-
- uint32_t sigtype = __builtin_bswap32(*(uint32_t *)cetk);
- if (sigtype != SIG_TYPE_RSA2048_SHA256) return 1;
-
- ticket_h *ticket = (ticket_h *)(cetk + sizeof(sigtype) + 0x13C);
- if (ticket->ticketCommonKeyYIndex != 1) return 1;
-
- if (!common_key_y_init) {
- uint8_t common_key_y[AES_BLOCK_SIZE] = {0};
- uint8_t *p9_base = (uint8_t *)0x08028000;
- uint8_t *i;
- for (i = p9_base + 0x70000 - AES_BLOCK_SIZE; i >= p9_base; i--) {
- if (i[0] == 0xD0 && i[4] == 0x9C && i[8] == 0x32 && i[12] == 0x23) {
- // At i, there's 7 keys with 4 bytes padding between them.
- // We only need the 2nd.
- memcpy(common_key_y, i + AES_BLOCK_SIZE + 4, sizeof(common_key_y));
- fprintf(BOTTOM_SCREEN, "Found the common key Y\n");
-
- break;
- }
- }
- if (i < p9_base) return 1;
-
- aes_setkey(0x3D, common_key_y, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
- common_key_y_init = 1;
- }
-
- aes_use_keyslot(0x3D);
-
- memcpy(iv, ticket->titleID, sizeof(ticket->titleID));
-
- fprintf(BOTTOM_SCREEN, "Decrypting key\n");
- memcpy(key, ticket->titleKey, sizeof(ticket->titleKey));
- aes(key, key, 1, iv, AES_CBC_DECRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
-
- return 0;
-}
-
int decrypt_firm_title(firm_h *dest, ncch_h *ncch, uint32_t *size, void *key)
{
uint8_t firm_iv[16] = {0};
// Firmware is likely encrypted. Decrypt.
if (!read_file(firm_key, path_firmkey, AES_BLOCK_SIZE)) {
- fprintf(BOTTOM_SCREEN, "Failed to load FIRM key,\n"
- " Attempting to generate with CETK.\n");
-
- if (!read_file(fcram_temp, path_cetk, FCRAM_SPACING)) {
- fprintf(BOTTOM_SCREEN, "Failed to load CETK\n");
- return 1;
- }
- fprintf(BOTTOM_SCREEN, "Loaded CETK\n");
-
- if (decrypt_cetk_key(firm_key, fcram_temp) != 0) {
- fprintf(BOTTOM_SCREEN, "Failed to decrypt the CETK\n");
- return 1;
- }
- fprintf(BOTTOM_SCREEN, "Saving FIRM key for future use\n");
- write_file(firm_key, path_firmkey, AES_BLOCK_SIZE);
+ fprintf(BOTTOM_SCREEN, "Failed to load FIRM key\n");
+ return 1;
} else {
fprintf(BOTTOM_SCREEN, "Loaded FIRM key\n");
}
}
}
-void putc(void* buf, unsigned char color, const int c) {
+unsigned char color_top = 0xf0;
+unsigned char color_bottom = 0xf0;
+
+void putc(void* buf, const int c) {
if ((int)buf == stdout || (int)buf == stderr) {
unsigned int width = 0;
unsigned int height = 0;
char* colorbuf;
char* strbuf;
+ unsigned char* color = NULL;
+
if ((int)buf == TOP_SCREEN) {
width = TEXT_TOP_WIDTH;
height = TEXT_TOP_HEIGHT;
strbuf = text_buffer_top;
cursor_x = top_cursor_x;
cursor_y = top_cursor_y;
+ color = &color_top;
} else if ((int)buf == BOTTOM_SCREEN) {
width = TEXT_BOTTOM_WIDTH;
height = TEXT_BOTTOM_HEIGHT;
strbuf = text_buffer_bottom;
cursor_x = bottom_cursor_x;
cursor_y = bottom_cursor_y;
+ color = &color_bottom;
}
unsigned int offset = width * cursor_y + cursor_x;
break;
default:
strbuf[offset] = c;
- colorbuf[offset] = color; // White on black.
+ colorbuf[offset] = *color; // White on black.
cursor_x++;
if (cursor_x >= width) {
cursor_y++;
}
}
-void puts(void* buf, unsigned char color, const char *string) {
+void puts(void* buf, const char *string) {
char *ref = (char*)string;
while(*ref != '\0') {
- putc(buf, color, *ref);
+ putc(buf, *ref);
ref++;
}
}
-void put_int64(void* channel, unsigned char color, int64_t n, int length) {
+void put_int64(void* channel, int64_t n, int length) {
char conv[32], out[32];
memset(conv, 0, 32);
memset(out, 0, 32);
for(int i=0; i < len; i++)
out[i] = conv[(len-1) - i];
- puts(channel, color, out);
+ puts(channel, out);
}
-void put_uint64(void* channel, unsigned char color, uint64_t n, int length) {
+void put_uint64(void* channel, uint64_t n, int length) {
char conv[32], out[32];
memset(conv, 0, 32);
memset(out, 0, 32);
for(int i=0; i < len; i++)
out[i] = conv[(len-1) - i];
- puts(channel, color, out);
+ puts(channel, out);
}
-void put_uint(void* channel, unsigned char color, unsigned int n, int length) {
- put_uint64(channel, color, n, length);
+void put_uint(void* channel, unsigned int n, int length) {
+ put_uint64(channel, n, length);
}
-void put_int(void* channel, unsigned char color, int n, int length) {
- put_int64(channel, color, n, length);
+void put_int(void* channel, int n, int length) {
+ put_int64(channel, n, length);
}
void fflush(void* channel) {
for(int y=0; y < TEXT_BOTTOM_HEIGHT; y++) {
char c = text_buffer_bottom[y*TEXT_BOTTOM_WIDTH+x];
uint32_t color_fg = colors[((color_buffer_bottom[y*TEXT_BOTTOM_WIDTH+x] >> 4) & 0x0f)];
- uint32_t color_bg = colors[(color_buffer_top[y*TEXT_TOP_WIDTH+x] & 0x0f)];
+ uint32_t color_bg = colors[(color_buffer_bottom[y*TEXT_BOTTOM_WIDTH+x] & 0x0f)];
draw_character(framebuffers->bottom, c, x, y, color_fg, color_bg);
}
}
va_start( ap, format );
char *ref = (char*)format;
- unsigned char color = 0xf0;
+
+ unsigned char* color;
+ if ((int)channel == TOP_SCREEN)
+ color = &color_top;
+ else if ((int)channel == TOP_SCREEN)
+ color = &color_bottom;
while(*ref != '\0') {
if (*ref == 0x1B && *(++ref) == '[' && ( (int)channel == stdout || (int)channel == stderr) ) {
++ref;
if(*ref >= '0' && *ref <= '7') {
// Valid FG color.
- color &= 0x0f; // Remove fg color.
- color |= (*ref - '0') << 4;
+ *color &= 0x0f; // Remove fg color.
+ *color |= (*ref - '0') << 4;
}
}
// [40-47] Set bg color
++ref;
if(*ref >= '0' && *ref <= '7') {
// Valid BG color.
- color &= 0xf0; // Remove bg color.
- color |= *ref - '0';
+ *color &= 0xf0; // Remove bg color.
+ *color |= *ref - '0';
}
- }
+ } else if (*ref == '0') {
+ // Reset.
+ *color = 0xf0;
+ }
++ref;
case 'd':
switch(type_size) {
case 2:
- put_int64(channel, color, va_arg( ap, int64_t ), length);
+ put_int64(channel, va_arg( ap, int64_t ), length);
break;
default:
- put_int(channel, color, va_arg( ap, int ), length);
+ put_int(channel, va_arg( ap, int ), length);
break;
}
break;
case 'u':
switch(type_size) {
case 2:
- put_uint64(channel, color, va_arg( ap, uint64_t ), length);
+ put_uint64(channel, va_arg( ap, uint64_t ), length);
break;
default:
- put_uint(channel, color, va_arg( ap, unsigned int ), length);
+ put_uint(channel, va_arg( ap, unsigned int ), length);
break;
}
break;
case 's':
- puts(channel, color, va_arg( ap, char* ));
+ puts(channel, va_arg( ap, char* ));
break;
case 'c':
- putc(channel, color, va_arg( ap, int ));
+ putc(channel, va_arg( ap, int ));
break;
case 'p':
- color = va_arg( ap, unsigned int );
+ puts(channel, va_arg( ap, char* ));
break;
case '%':
- putc(channel, color, '%');
+ putc(channel, '%');
break;
case 'h':
goto check_format; // Integers get promoted. No point here.
break;
}
} else {
- putc(channel, color, *ref);
+ putc(channel, *ref);
}
++ref;
}