Пример #1
0
static int aice_pipe_write_mem_unit(uint32_t coreid, uint32_t addr, uint32_t size,
		uint32_t count, const uint8_t *buffer)
{
	char line[AICE_PIPE_MAXLINE];
	char command[AICE_PIPE_MAXLINE];

	command[0] = AICE_WRITE_MEM_UNIT;
	set_u32(command + 1, addr);
	set_u32(command + 5, size);
	set_u32(command + 9, count);

	/* WRITE_MEM_UNIT|addr|size|count|data */
	memcpy(command + 13, buffer, size * count);

	if (aice_pipe_write(command, 13 + size * count) < 0)
		return ERROR_FAIL;

	if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
		return ERROR_FAIL;

	if (line[0] == AICE_OK)
		return ERROR_OK;
	else
		return ERROR_FAIL;

	return ERROR_OK;
}
Пример #2
0
void init_Self_Shdr(Self_Shdr* hdr) {
  set_u32(&(hdr->s_magic), 0x53434500);
  set_u32(&(hdr->s_hdrversion), 2);
#ifdef SPRX
  // on 3.41
  //set_u16(&(hdr->s_flags), 4);
  // on 3.55
  set_u16(&(hdr->s_flags), 7);
#else
  set_u16(&(hdr->s_flags), 1);
#endif
  set_u16(&(hdr->s_hdrtype), 1);
}
Пример #3
0
static int aice_pipe_write_mem_bulk(uint32_t coreid, uint32_t addr,
		uint32_t length, const uint8_t *buffer)
{
	char line[AICE_PIPE_MAXLINE];
	char command[AICE_PIPE_MAXLINE + 4];
	uint32_t remain_len = length;
	uint32_t written_len = 0;
	uint32_t write_len;

	command[0] = AICE_WRITE_MEM_BULK;
	set_u32(command + 1, addr);
	set_u32(command + 5, length);

	/* Send command first */
	if (aice_pipe_write(command, 9) < 0)
		return ERROR_FAIL;

	if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
		return ERROR_FAIL;

	if (line[0] == AICE_ERROR)
		return ERROR_FAIL;

	while (remain_len > 0) {
		if (remain_len > AICE_PIPE_MAXLINE)
			write_len = AICE_PIPE_MAXLINE;
		else
			write_len = remain_len;

		set_u32(command, write_len);
		memcpy(command + 4, buffer + written_len, write_len); /* data only */

		if (aice_pipe_write(command, write_len + 4) < 0)
			return ERROR_FAIL;

		if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
			return ERROR_FAIL;

		if (line[0] == AICE_ERROR)
			return ERROR_FAIL;

		remain_len -= write_len;
		written_len += write_len;
	}

	if (line[0] == AICE_OK)
		return ERROR_OK;
	else
		return ERROR_FAIL;
}
Пример #4
0
static int aice_pipe_read_mem_bulk(uint32_t coreid, uint32_t addr,
		uint32_t length, uint8_t *buffer)
{
	char line[AICE_PIPE_MAXLINE + 1];
	char command[AICE_PIPE_MAXLINE];
	uint32_t remain_len = length;
	uint32_t prepare_len;
	char *received_line;
	uint32_t received_len;
	int read_len;

	command[0] = AICE_READ_MEM_BULK;
	set_u32(command + 1, addr);
	set_u32(command + 5, length);

	if (aice_pipe_write(command, 9) < 0)
		return ERROR_FAIL;

	while (remain_len > 0) {
		if (remain_len > AICE_PIPE_MAXLINE)
			prepare_len = AICE_PIPE_MAXLINE;
		else
			prepare_len = remain_len;

		prepare_len++;
		received_len = 0;
		received_line = line;
		do {
			read_len = aice_pipe_read(received_line, prepare_len - received_len);
			if (read_len < 0)
				return ERROR_FAIL;
			received_line += read_len;
			received_len += read_len;
		} while (received_len < prepare_len);

		if (line[0] != AICE_OK)
			return ERROR_FAIL;

		prepare_len--;
		memcpy(buffer, line + 1, prepare_len);
		remain_len -= prepare_len;
		buffer += prepare_len;
	}

	return ERROR_OK;
}
Пример #5
0
static int aice_pipe_read_mem_unit(uint32_t coreid, uint32_t addr, uint32_t size,
		uint32_t count, uint8_t *buffer)
{
	char command[AICE_PIPE_MAXLINE];

	command[0] = AICE_READ_MEM_UNIT;
	set_u32(command + 1, addr);
	set_u32(command + 5, size);
	set_u32(command + 9, count);

	if (aice_pipe_write(command, 13) != 13)
		return ERROR_FAIL;

	if (aice_pipe_read(buffer, size * count) < 0)
		return ERROR_FAIL;

	return ERROR_OK;
}
Пример #6
0
static int aice_pipe_cache_ctl(uint32_t coreid, uint32_t subtype, uint32_t address)
{
	char line[AICE_PIPE_MAXLINE];
	char command[AICE_PIPE_MAXLINE];

	command[0] = AICE_CACHE_CTL;
	set_u32(command + 1, subtype);
	set_u32(command + 5, address);

	if (aice_pipe_write(command, 9) != 9)
		return ERROR_FAIL;

	if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
		return ERROR_FAIL;

	if (line[0] == AICE_OK)
		return ERROR_OK;
	else
		return ERROR_FAIL;
}
Пример #7
0
static int aice_pipe_write_debug_reg(uint32_t coreid, uint32_t addr, const uint32_t val)
{
	char line[AICE_PIPE_MAXLINE];
	char command[AICE_PIPE_MAXLINE];

	command[0] = AICE_WRITE_DEBUG_REG;
	set_u32(command + 1, addr);
	set_u32(command + 5, val);

	if (aice_pipe_write(command, 9) != 9)
		return ERROR_FAIL;

	if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
		return ERROR_FAIL;

	if (line[0] == AICE_OK)
		return ERROR_OK;
	else
		return ERROR_FAIL;
}
Пример #8
0
static int aice_pipe_write_reg_64(uint32_t coreid, uint32_t num, uint64_t val)
{
	char line[AICE_PIPE_MAXLINE];
	char command[AICE_PIPE_MAXLINE];

	command[0] = AICE_WRITE_REG_64;
	set_u32(command + 1, num);
	set_u32(command + 5, val & 0xFFFFFFFF);
	set_u32(command + 9, (val >> 32) & 0xFFFFFFFF);

	if (aice_pipe_write(command, 13) != 9)
		return ERROR_FAIL;

	if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
		return ERROR_FAIL;

	if (line[0] == AICE_OK)
		return ERROR_OK;
	else
		return ERROR_FAIL;
}
Пример #9
0
void init_Self_NPDRM(Self_NPDRM* npdrm, char* titleid, char* filename) {
  set_u32(&npdrm->block_type, 3);
  set_u32(&npdrm->block_size, sizeof(Self_NPDRM));
  set_u32(&npdrm->magic, 0x4E504400);
  set_u32(&npdrm->unknown3, 1);
  set_u32(&npdrm->unknown4, 3);
  set_u32(&npdrm->unknown5, 1);
  strncpy(npdrm->titleid, titleid, 0x30);
  //memcpy(npdrm->hash_unknown, npdrm_hash_unknown, sizeof(npdrm_hash_unknown));

  char *true_filename = strrchr(filename,'/');
  if(true_filename == NULL) {
    true_filename = strrchr(filename,'\\');
  }
  if(true_filename == NULL) {
    true_filename = filename;
  } else {
    true_filename++;
  }
  
  u8 npdrm_omac_key[0x10]; int i;
  for(i=0;i<0x10;i++) npdrm_omac_key[i] = npdrm_omac_key1[i] ^ npdrm_omac_key2[i];

  int buf_len = 0x30+strlen(true_filename);
  char *buf = (char*)malloc(buf_len);
  memcpy(buf, npdrm->titleid, 0x30);
  strcpy(buf+0x30, true_filename);
  aesOmac1Mode(npdrm->hash1, buf, buf_len, npdrm_omac_key3, sizeof(npdrm_omac_key3)*8);
  free(buf);
  aesOmac1Mode(npdrm->hash2, (u8*)&(npdrm->magic), 0x60, npdrm_omac_key, sizeof(npdrm_omac_key)*8);
}
Пример #10
0
void init_Self_Ihdr(Self_Ihdr* hdr) {
#ifdef NPDRM
  set_u64(&(hdr->i_authid), 0x1010000001000003LL);
  set_u32(&(hdr->i_apptype), 8);
#else
#ifdef SPRX
  set_u64(&(hdr->i_authid), 0x1070000052000001LL);
#else
  //set_u64(&(hdr->i_authid), 0x10700003FD000001LL);
  set_u64(&(hdr->i_authid), 0x10700003FF000001LL);
#endif
  set_u32(&(hdr->i_apptype), 4);
#endif
  //set_u64(&(hdr->i_authid), 0x1070000500000001LL);

  set_u32(&(hdr->i_magic), 0x01000002);
  set_u64(&(hdr->i_version), 0x0003005500000000LL);
  //set_u64(&(hdr->i_version), 0x0003004000000000LL);
  //set_u64(&(hdr->i_version), 0x0003000000000000LL);
  //set_u64(&(hdr->i_version), 0x0001004000001000LL);
  //set_u64(&(hdr->i_version), 0x0001000000000000LL);
}
Пример #11
0
void build_segment_crypt_data() {
  Self_Segment* segment_ptr;
  segment_ptr = &first_segment;
  while(segment_ptr != NULL) {
    if(segment_ptr->incrypt) {
      set_u32(&(segment_ptr->enc_segment.segment_sha1_index), segment_crypt_data_len/0x10);
      memcpy(&segment_crypt_data[segment_crypt_data_len], segment_ptr->crypt_segment.sha1, sizeof(segment_ptr->crypt_segment.sha1)); segment_crypt_data_len += sizeof(segment_ptr->crypt_segment.sha1);
      memcpy(&segment_crypt_data[segment_crypt_data_len], segment_ptr->crypt_segment.hmac, sizeof(segment_ptr->crypt_segment.hmac)); segment_crypt_data_len += sizeof(segment_ptr->crypt_segment.hmac);

      if(segment_ptr->encrypted) {
        set_u32(&(segment_ptr->enc_segment.segment_erk_index), segment_crypt_data_len/0x10);
        memcpy(&segment_crypt_data[segment_crypt_data_len], segment_ptr->crypt_segment.erk, sizeof(segment_ptr->crypt_segment.erk)); segment_crypt_data_len += sizeof(segment_ptr->crypt_segment.erk);
        set_u32(&(segment_ptr->enc_segment.segment_riv_index), segment_crypt_data_len/0x10);
        memcpy(&segment_crypt_data[segment_crypt_data_len], segment_ptr->crypt_segment.riv, sizeof(segment_ptr->crypt_segment.riv)); segment_crypt_data_len += sizeof(segment_ptr->crypt_segment.riv);
      } else {
        set_u32(&(segment_ptr->enc_segment.segment_erk_index), 0xFFFFFFFF);
        set_u32(&(segment_ptr->enc_segment.segment_riv_index), 0xFFFFFFFF);
      }
    }
    segment_ptr = segment_ptr->next_segment;
  }
}
Пример #12
0
static int aice_pipe_read_debug_reg(uint32_t coreid, uint32_t addr, uint32_t *val)
{
	char line[AICE_PIPE_MAXLINE];
	char command[AICE_PIPE_MAXLINE];

	command[0] = AICE_READ_DEBUG_REG;
	set_u32(command + 1, addr);

	if (aice_pipe_write(command, 5) != 5)
		return ERROR_FAIL;

	if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
		return ERROR_FAIL;

	*val = get_u32(line);

	return ERROR_OK;
}
Пример #13
0
static int aice_pipe_read_reg_64(uint32_t coreid, uint32_t num, uint64_t *val)
{
	char line[AICE_PIPE_MAXLINE];
	char command[AICE_PIPE_MAXLINE];

	command[0] = AICE_READ_REG_64;
	set_u32(command + 1, num);

	if (aice_pipe_write(command, 5) != 5)
		return ERROR_FAIL;

	if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
		return ERROR_FAIL;

	*val = (((uint64_t)get_u32(line + 4)) << 32) | get_u32(line);

	return ERROR_OK;
}
Пример #14
0
static int aice_pipe_memory_mode(uint32_t coreid, enum nds_memory_select mem_select)
{
	char line[AICE_PIPE_MAXLINE];
	char command[AICE_PIPE_MAXLINE];

	command[0] = AICE_MEMORY_MODE;
	set_u32(command + 1, mem_select);

	if (aice_pipe_write(command, 5) != 5)
		return ERROR_FAIL;

	if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
		return ERROR_FAIL;

	if (line[0] == AICE_OK)
		return ERROR_OK;
	else
		return ERROR_FAIL;
}
Пример #15
0
static int aice_pipe_memory_access(uint32_t coreid, enum nds_memory_access access_channel)
{
	char line[AICE_PIPE_MAXLINE];
	char command[AICE_PIPE_MAXLINE];

	command[0] = AICE_MEMORY_ACCESS;
	set_u32(command + 1, access_channel);

	if (aice_pipe_write(command, 5) != 5)
		return ERROR_FAIL;

	if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
		return ERROR_FAIL;

	if (line[0] == AICE_OK)
		return ERROR_OK;
	else
		return ERROR_FAIL;
}
Пример #16
0
static int aice_pipe_set_jtag_clock(uint32_t a_clock)
{
	char line[AICE_PIPE_MAXLINE];
	char command[AICE_PIPE_MAXLINE];

	command[0] = AICE_SET_JTAG_CLOCK;
	set_u32(command + 1, a_clock);

	if (aice_pipe_write(command, 5) != 5)
		return ERROR_FAIL;

	if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
		return ERROR_FAIL;

	if (line[0] == AICE_OK)
		return ERROR_OK;
	else
		return ERROR_FAIL;
}
Пример #17
0
static int aice_pipe_read_tlb(uint32_t coreid, uint32_t virtual_address,
		uint32_t *physical_address)
{
	char line[AICE_PIPE_MAXLINE];
	char command[AICE_PIPE_MAXLINE];

	command[0] = AICE_READ_TLB;
	set_u32(command + 1, virtual_address);

	if (aice_pipe_write(command, 5) != 5)
		return ERROR_FAIL;

	if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
		return ERROR_FAIL;

	if (line[0] == AICE_OK) {
		*physical_address = get_u32(line + 1);
		return ERROR_OK;
	} else
		return ERROR_FAIL;
}
Пример #18
0
int main(int argc, char* argv[]) {
  int i;
  u8 ecount_buf[0x10], iv[0x10];
  size_t countp;
  int num;

  if(argc < 4) {
    printf("usage: %s input.elf output.self keytype keysuffix\n", argv[0]);
    return -1;
  }

  Elf64_Ehdr input_elf_header;
  FILE *input_elf_file = fopen(argv[1], "rb");

  fseek(input_elf_file, 0, SEEK_END);
  int nlen = ftell(input_elf_file);
  fseek(input_elf_file, 0, SEEK_SET);
  input_elf_data = (u8*)malloc(nlen);
  fread(input_elf_data, 1, nlen, input_elf_file);
  fclose(input_elf_file);

  memcpy(&input_elf_header, input_elf_data, sizeof(input_elf_header));


  FILE *output_self_file = fopen(argv[2], "wb");


  printf("ELF header size @ %x\n", get_u16(&(input_elf_header.e_ehsize)) );
  printf("%d program headers @ %64llX\n", get_u16(&(input_elf_header.e_phnum)), get_u64(&(input_elf_header.e_phoff)));
  printf("%d section headers @ %64llX\n", get_u16(&(input_elf_header.e_shnum)), get_u64(&(input_elf_header.e_shoff)));

  Self_Shdr output_self_header; memset(&output_self_header, 0, sizeof(output_self_header));
  Self_Ehdr output_extended_self_header; memset(&output_extended_self_header, 0, sizeof(output_extended_self_header));
  Self_Ihdr output_self_info_header; memset(&output_self_info_header, 0, sizeof(output_self_info_header));

  set_u32(&(output_self_header.s_magic), 0x53434500);
  set_u32(&(output_self_header.s_hdrversion), 2);
  set_u16(&(output_self_header.s_flags), 1);
  set_u16(&(output_self_header.s_hdrtype), 1);
  // header size and file size aren't known yet

  set_u64(&(output_extended_self_header.e_magic), 3);
  set_u64(&(output_extended_self_header.e_ihoff), sizeof(Self_Shdr)+sizeof(Self_Ehdr));
  set_u64(&(output_extended_self_header.e_ehoff), sizeof(Self_Shdr)+sizeof(Self_Ehdr)+sizeof(Self_Ihdr));
  set_u64(&(output_extended_self_header.e_phoff), sizeof(Self_Shdr)+sizeof(Self_Ehdr)+sizeof(Self_Ihdr)+get_u64(&(input_elf_header.e_phoff)));
  // section header offset unknown

  set_u64(&(output_self_info_header.i_authid), 0x1070000500000001LL);
  set_u32(&(output_self_info_header.i_magic), 0x01000002);
  set_u32(&(output_self_info_header.i_apptype), 4);
  set_u64(&(output_self_info_header.i_version), 0x0003000000000000LL);

// set static data
  int phnum = get_u16(&(input_elf_header.e_phnum));
  u32 phsize = (sizeof(Elf64_Phdr)*get_u16(&(input_elf_header.e_phnum))); 

  Self_SDKversion sdkversion;
  Self_Cflags cflags;
  memcpy(&sdkversion, sdkversion_static, sizeof(Self_SDKversion));
  memcpy(&cflags, cflags_static, sizeof(Self_Cflags));

  int running_size = (sizeof(output_self_header)+sizeof(output_extended_self_header)+sizeof(output_self_info_header)+sizeof(input_elf_header)+phsize+0xF)&0xFFFFFFF0;

  set_u64(&(output_extended_self_header.e_pmoff), running_size); running_size += phnum*sizeof(Self_PMhdr);
  set_u64(&(output_extended_self_header.e_svoff), running_size); running_size += sizeof(Self_SDKversion);
  set_u64(&(output_extended_self_header.e_cfoff), running_size); running_size += sizeof(Self_Cflags);
  set_u64(&(output_extended_self_header.e_cfsize), sizeof(Self_Cflags));
  set_u32(&(output_self_header.s_esize), running_size - sizeof(output_self_header));

  printf("running size is %X\n", running_size);

  int maxsection = 6;

  running_size += sizeof(metadata_crypt_header)+sizeof(segment_certification_header)+maxsection*(sizeof(segment_certification_segment)+sizeof(segment_certification_crypt_encrypted))+sizeof(segment_certification_sign)+sizeof(nubpadding_static);

  printf("running size is %X\n", running_size);

  set_u64(&(output_self_header.s_shsize), running_size);

// init randomness
  gmp_randstate_t r_state;
  gmp_randinit_default(r_state);
  gmp_randseed_ui(r_state, time(NULL));

// loop through the sections

  segment_certification_header segment_header; memset(&segment_header, 0, sizeof(segment_header));
  Self_Section first_section;
  Self_Section* section_ptr = &first_section;

  set_u64(&(segment_header.signature_offset), running_size-sizeof(segment_certification_sign));
  set_u32(&(segment_header.unknown1), 1);
  set_u32(&(segment_header.segment_count), phnum);
  set_u32(&(segment_header.crypt_len), (phnum*sizeof(segment_certification_crypt_encrypted))/0x10);

  Elf64_Phdr* elf_segment = (Elf64_Phdr*)(&input_elf_data[get_u64(&(input_elf_header.e_phoff))]);

  for(i=0;i<phnum;i++) {
    memset(section_ptr, 0, sizeof(Self_Section));

    //set_u64(&(section_ptr->enc_segment.segment_offset), get_u64(&(elf_segment->p_vaddr)));
    set_u64(&(section_ptr->enc_segment.segment_offset), running_size);
    set_u64(&(section_ptr->enc_segment.segment_size), get_u64(&(elf_segment->p_filesz)));
    set_u32(&(section_ptr->enc_segment.segment_crypt_flag), 2);

    set_u32(&(section_ptr->enc_segment.segment_sha1_index), i*8);
    set_u32(&(section_ptr->enc_segment.segment_erk_index), i*8+6);
    set_u32(&(section_ptr->enc_segment.segment_riv_index), i*8+7);

    set_u32(&(section_ptr->enc_segment.segment_number), i);
    set_u32(&(section_ptr->enc_segment.unknown2), 2);
    set_u32(&(section_ptr->enc_segment.unknown3), 3);
    set_u32(&(section_ptr->enc_segment.unknown4), 2);

    set_u64(&(section_ptr->pmhdr.pm_offset), running_size);
    set_u64(&(section_ptr->pmhdr.pm_size), get_u64(&(elf_segment->p_filesz)));
    set_u32(&(section_ptr->pmhdr.pm_compressed), 1);
    set_u32(&(section_ptr->pmhdr.pm_encrypted), 1);

    mpz_t riv, erk, hmac;
    mpz_init(riv); mpz_init(erk); mpz_init(hmac);
    mpz_urandomb(erk, r_state, 128);
    mpz_urandomb(riv, r_state, 128);
    mpz_urandomb(hmac, r_state, 512);

    mpz_export(section_ptr->crypt_segment.erk, &countp, 1, 0x10, 1, 0, erk);
    mpz_export(section_ptr->crypt_segment.riv, &countp, 1, 0x10, 1, 0, riv);
    mpz_export(section_ptr->crypt_segment.hmac, &countp, 1, 0x40, 1, 0, hmac);

    section_ptr->rlen = get_u64(&(elf_segment->p_filesz));
    section_ptr->len = ((section_ptr->rlen)+0xF)&0xFFFFFFF0;
    section_ptr->data = (u8*)malloc(section_ptr->len);

    u32 in_data_offset = get_u64(&(elf_segment->p_offset)); // + get_u16(&(input_elf_header.e_ehsize)) + (sizeof(Elf64_Phdr)*get_u16(&(input_elf_header.e_phnum)));
    u8* in_data = &input_elf_data[in_data_offset];

    printf("processing segment %d with len %x offset %x\n", i, section_ptr->len, in_data_offset);
    //hexdump((u8*)elf_segment, sizeof(Elf64_Phdr));


    /*SHA_CTX c;
    SHA1_ghetto_init(&c, section_ptr->crypt_segment.hmac);
    SHA1_Update(&c, in_data, section_ptr->rlen);
    SHA1_ghetto_final(section_ptr->crypt_segment.sha1, &c, section_ptr->crypt_segment.hmac);*/
    sha1_hmac(section_ptr->crypt_segment.hmac, in_data, section_ptr->rlen, section_ptr->crypt_segment.sha1);

    memset(ecount_buf, 0, 16); num=0;
    AES_set_encrypt_key(section_ptr->crypt_segment.erk, 128, &aes_key);
    memcpy(iv, section_ptr->crypt_segment.riv, 16);

    #ifdef NO_CRYPT
      memcpy(section_ptr->data, in_data, section_ptr->len);   
    #else
      //AES_ctr128_encrypt(in_data, section_ptr->data, section_ptr->len, &aes_key, iv, ecount_buf, &num);
      aes128ctr((u8*)&aes_key, iv, in_data, section_ptr->len, section_ptr->data);
    #endif

    running_size += section_ptr->len;

// next
    if(i != phnum-1) {
      section_ptr->next_section = malloc(sizeof(Self_Section));
    }
    elf_segment += 1;  // 1 is sizeof(Elf64_Phdr)
    section_ptr = section_ptr->next_section;
  }

  printf("segment processing done\n");


// section table offset
  set_u64(&(output_extended_self_header.e_shoff), running_size);

// lay out the metadata
  u8 metadata[0x2000]; memset(metadata, 0, 0x2000);
  u32 metadata_len = 0;

  memcpy(&metadata[metadata_len], &output_self_header, sizeof(output_self_header)); metadata_len += sizeof(output_self_header);
  memcpy(&metadata[metadata_len], &output_extended_self_header, sizeof(output_extended_self_header)); metadata_len += sizeof(output_extended_self_header);
  memcpy(&metadata[metadata_len], &output_self_info_header, sizeof(output_self_info_header)); metadata_len += sizeof(output_self_info_header);
  memcpy(&metadata[metadata_len], &input_elf_header, sizeof(input_elf_header)); metadata_len += sizeof(input_elf_header);
  memcpy(&metadata[metadata_len], &input_elf_data[get_u64(&(input_elf_header.e_phoff))], phsize); metadata_len += phsize;
  metadata_len = (metadata_len+0xF)&0xFFFFFFF0;

  section_ptr = &first_section;
  while(section_ptr != NULL) {
    memcpy(&metadata[metadata_len], &(section_ptr->pmhdr), sizeof(section_ptr->pmhdr)); metadata_len += sizeof(section_ptr->pmhdr);
    section_ptr = section_ptr->next_section;
  }

  memcpy(&metadata[metadata_len], &sdkversion, sizeof(sdkversion)); metadata_len += sizeof(sdkversion);
  memcpy(&metadata[metadata_len], &cflags, sizeof(cflags)); metadata_len += sizeof(cflags);

  printf("top half of metadata ready\n");

// generate metadata encryption keys
  mpz_t bigriv, bigerk;
  mpz_init(bigriv); mpz_init(bigerk);
  mpz_urandomb(bigerk, r_state, 128);
  mpz_urandomb(bigriv, r_state, 128);

  metadata_crypt_header md_header;

  mpz_export(md_header.erk, &countp, 1, 0x10, 1, 0, bigerk);
  mpz_export(md_header.riv, &countp, 1, 0x10, 1, 0, bigriv);

  memcpy(&metadata[metadata_len], &md_header, sizeof(md_header)); metadata_len += sizeof(md_header);
  memcpy(&metadata[metadata_len], &segment_header, sizeof(segment_header)); metadata_len += sizeof(segment_header);

// copy section data
  int csection;

  csection = 0;
  section_ptr = &first_section;
  while(section_ptr != NULL) {
    memcpy(&metadata[metadata_len], &(section_ptr->enc_segment), sizeof(section_ptr->enc_segment)); metadata_len += sizeof(section_ptr->enc_segment);
    section_ptr = section_ptr->next_section;
    if((++csection) == maxsection) break;
  }

  csection = 0;
  section_ptr = &first_section;
  while(section_ptr != NULL) {
    memcpy(&metadata[metadata_len], &(section_ptr->crypt_segment), sizeof(section_ptr->crypt_segment)); metadata_len += sizeof(section_ptr->crypt_segment);
    section_ptr = section_ptr->next_section;
    if((++csection) == maxsection) break;
  }

// nubpadding time
  memcpy(&metadata[metadata_len], nubpadding_static, sizeof(nubpadding_static)); metadata_len += sizeof(nubpadding_static);

// sign shit
  u8 digest[0x14];
  sha1(metadata, metadata_len, digest);
  printf("metadata len is %X\n", metadata_len);
  //hexdump(metadata, metadata_len);
  //hexdump_nl(digest, 0x14);
  segment_certification_sign all_signed;
  memset(&all_signed, 0, sizeof(all_signed));

#ifdef GEOHOT_SIGN
  mpz_t n,k,da,kinv,r,cs,z;
  mpz_init(n); mpz_init(k); mpz_init(da); mpz_init(r); mpz_init(cs); mpz_init(z); mpz_init(kinv);
  mpz_import(r, 0x14, 1, 1, 0, 0, appold_R);
  mpz_import(n, 0x14, 1, 1, 0, 0, appold_n);
  mpz_import(k, 0x14, 1, 1, 0, 0, appold_K);
  mpz_import(da, 0x14, 1, 1, 0, 0, appold_Da);
  mpz_invert(kinv, k, n);

  mpz_import(z, 0x14, 1, 1, 0, 0, digest);

  mpz_mul(cs, r, da); mpz_mod(cs, cs, n);
  mpz_add(cs, cs, z); mpz_mod(cs, cs, n);
  mpz_mul(cs, cs, kinv); mpz_mod(cs, cs, n);

  mpz_export(all_signed.R, &countp, 1, 0x14, 1, 0, r);
  mpz_export(all_signed.S, &countp, 1, 0x14, 1, 0, cs);
#else
  get_keys(argv[3], argv[4]);
  //ecdsa_set_curve(appnew_ctype);
  //ecdsa_set_pub(appnew_pub);
  //ecdsa_set_priv(appnew_priv);
  //ecdsa_sign(digest, all_signed.R, all_signed.S);
#endif

  memcpy(&metadata[metadata_len], &all_signed, sizeof(all_signed)); metadata_len += sizeof(all_signed);

// encrypt metadata
  int metadata_offset = get_u32(&(output_self_header.s_esize)) + sizeof(Self_Shdr);

#ifndef NO_CRYPT
  /*memset(ecount_buf, 0, 16); num=0;
  AES_set_encrypt_key(&metadata[metadata_offset], 128, &aes_key);
  memcpy(iv, &metadata[metadata_offset+0x20], 16);
  //AES_ctr128_encrypt(&metadata[0x40+metadata_offset], &metadata[0x40+metadata_offset], metadata_len-metadata_offset-0x40, &aes_key, iv, ecount_buf, &num);
  aes128ctr(&metadata[0x20+metadata_offset], &metadata[0x40+metadata_offset], &metadata[0x60+metadata_offset], metadata_len-metadata_offset-0x60, &metadata[0x60+metadata_offset]);
  printf("encrypted metadata\n");

  //AES_set_encrypt_key(appold_erk, 256, &aes_key);
  //memcpy(iv, appold_riv, 16);
  AES_set_encrypt_key(appnew_erk, 256, &aes_key);
  memcpy(iv, appnew_riv, 16);
  //AES_cbc_encrypt(&metadata[metadata_offset], &metadata[metadata_offset], 0x40, &aes_key, iv, AES_ENCRYPT);
  aes256cbc_enc(appnew_erk, appnew_riv, &metadata[metadata_offset], 0x40, &metadata[metadata_offset]);

  printf("encrypted keys\n");*/
  //k.key = appnew_erk;
  //k.iv = appnew_riv;
  sce_encrypt_header(metadata, &ks);
#endif

// write the output self
  fwrite(metadata, 1, metadata_len, output_self_file);

  csection = 0;
  section_ptr = &first_section;
  while(section_ptr != 0) {
    printf("writing section with size %X\n", section_ptr->len);
    fwrite(section_ptr->data, 1, section_ptr->len, output_self_file);
    section_ptr = section_ptr->next_section;
    if((++csection) == maxsection) break;
  }

  fwrite(&input_elf_data[get_u64(&(input_elf_header.e_shoff))], sizeof(Elf64_Shdr), get_u16(&(input_elf_header.e_shnum)), output_self_file);

  fclose(output_self_file);
}
Пример #19
0
void enumerate_segments() {
  int i,num;
  size_t countp;
  u8 ecount_buf[0x10],iv[0x10];
  Self_Segment* segment_ptr = &first_segment;
  Elf64_Phdr* elf_segment = (Elf64_Phdr*)(&input_elf_data[get_u64(&(input_elf_header->e_phoff))]);

  mpz_t riv, erk, hmac;
  mpz_init(riv); mpz_init(erk); mpz_init(hmac);

  for(i=0;i<get_u16(&(input_elf_header->e_phnum));i++) {
    
    memset(segment_ptr, 0, sizeof(Self_Segment));

// these are choices you can make
    /*segment_ptr->compressed = (i<2);
    segment_ptr->incrypt = (i<6); // **TESTING
    segment_ptr->encrypted = (i<5);*/

#ifdef NPDRM
    segment_ptr->encrypted = (i<5);
    segment_ptr->compressed = (i<4);
    segment_ptr->incrypt = (i<7);
#else
    segment_ptr->encrypted = 1;
    segment_ptr->compressed = 1;
    segment_ptr->incrypt = 1;
#endif
    
    set_u32(&(segment_ptr->enc_segment.segment_number), i);

    set_u32(&(segment_ptr->enc_segment.unknown2), 2);
    set_u32(&(segment_ptr->enc_segment.unknown3), 3);

    mpz_urandomb(hmac, r_state, 512);
    mpz_export(segment_ptr->crypt_segment.hmac, &countp, 1, 0x40, 1, 0, hmac);

    if(segment_ptr->encrypted) {
      mpz_urandomb(erk, r_state, 128);
      mpz_urandomb(riv, r_state, 128);
      mpz_export(segment_ptr->crypt_segment.erk, &countp, 1, 0x10, 1, 0, erk);
      mpz_export(segment_ptr->crypt_segment.riv, &countp, 1, 0x10, 1, 0, riv);
    }

    segment_ptr->rlen = get_u64(&(elf_segment->p_filesz));

    u32 in_data_offset = get_u64(&(elf_segment->p_offset));
    u8* in_data = &input_elf_data[in_data_offset];

    if(segment_ptr->compressed) {
      int def_size = DEFLATION_BUFFER_SIZE;
      printf("deflated...", def(in_data, segment_ptr->rlen, def_buffer, &def_size)); fflush(stdout);
      segment_ptr->len = def_size;
      segment_ptr->data = (u8*)malloc(segment_ptr->len);
      memcpy(segment_ptr->data, def_buffer, def_size);
    } else {
      segment_ptr->len = segment_ptr->rlen;
      segment_ptr->data = (u8*)malloc(segment_ptr->len);
      memcpy(segment_ptr->data, in_data, segment_ptr->len);
    }

    /*if(i==0) {
      segment_ptr->padding = 0x26A4;
    } else if(i==1) {
      segment_ptr->padding = 0xC;
    } else {
      segment_ptr->padding = 0;
    }*/

    segment_ptr->padding = (0x10-(segment_ptr->len&0xF))&0xF;

// hacks to make it match
    /*if(segment_ptr->len == 0x14BCC8) {
      segment_ptr->padding += 0x4330;
    }*/

    printf("processing segment %d with rlen %x len %x offset %x...", i, segment_ptr->rlen, segment_ptr->len, in_data_offset); fflush(stdout);

    //hexdump((u8*)elf_segment, sizeof(Elf64_Phdr));

    set_u64(&(segment_ptr->enc_segment.segment_size), segment_ptr->len);
    set_u32(&(segment_ptr->enc_segment.segment_crypt_flag), 1+segment_ptr->encrypted);
    set_u32(&(segment_ptr->enc_segment.segment_compressed_flag), 1+segment_ptr->compressed);

    set_u64(&(segment_ptr->pmhdr.pm_size), segment_ptr->len);
    set_u32(&(segment_ptr->pmhdr.pm_compressed), 1+segment_ptr->compressed);
    set_u32(&(segment_ptr->pmhdr.pm_encrypted), segment_ptr->encrypted);

// compute sha1
    SHA_CTX c;
    SHA1_ghetto_init(&c, segment_ptr->crypt_segment.hmac);
    SHA1_Update(&c, segment_ptr->data, segment_ptr->len);
    SHA1_ghetto_final(segment_ptr->crypt_segment.sha1, &c, segment_ptr->crypt_segment.hmac);

    if(segment_ptr->encrypted) {
      printf("encrypted...");  fflush(stdout);
      memset(ecount_buf, 0, 16); num=0;
      AES_set_encrypt_key(segment_ptr->crypt_segment.erk, 128, &aes_key);
      memcpy(iv, segment_ptr->crypt_segment.riv, 16);
#ifndef NO_CRYPT
      AES_ctr128_encrypt(segment_ptr->data, segment_ptr->data, segment_ptr->len, &aes_key, iv, ecount_buf, &num);
#endif
    }

    if(i != get_u16(&(input_elf_header->e_phnum))-1) {
      segment_ptr->next_segment = malloc(sizeof(Self_Segment));
    }
    elf_segment += 1;  // 1 is sizeof(Elf64_Phdr)
    segment_ptr = segment_ptr->next_segment;
    printf("\n");
  }
}
Пример #20
0
int main(int argc, char* argv[]) {
  int i;
  u8 ecount_buf[0x10], iv[0x10];
  size_t countp;
  int num;
  Self_Segment* segment_ptr;

  memset(zero_padding, 0, sizeof(zero_padding));

#ifdef NPDRM
  if(argc < 3) {
    printf("usage: %s input.elf output.self <titleid>\n", argv[0]);
    printf("  warning NPDRM cares about the output file name, do not rename\n");
    return -1;
  }
#else
  if(argc < 2) {
    printf("usage: %s input.elf output.self\n", argv[0]);
    return -1;
  }
#endif

// init randomness
  gmp_randinit_default(r_state);
  gmp_randseed_ui(r_state, time(NULL));

// read elf file
  read_elf_file(argv[1]);
  input_elf_header = (Elf64_Ehdr*)input_elf_data;

  printf("ELF header size @ %x\n", get_u16(&(input_elf_header->e_ehsize)) );
  printf("%d program headers @ %llx\n", get_u16(&(input_elf_header->e_phnum)), get_u64(&(input_elf_header->e_phoff)));
  printf("%d section headers @ %llx\n", get_u16(&(input_elf_header->e_shnum)), get_u64(&(input_elf_header->e_shoff)));

// loop through the segments
  enumerate_segments();
  printf("segments enumerated\n");

// setup self headers
  Self_Shdr output_self_header; memset(&output_self_header, 0, sizeof(output_self_header));
  Self_Ehdr output_extended_self_header; memset(&output_extended_self_header, 0, sizeof(output_extended_self_header));
  Self_Ihdr output_self_info_header; memset(&output_self_info_header, 0, sizeof(output_self_info_header));
  
  init_Self_Shdr(&output_self_header);
  init_Self_Ehdr(&output_extended_self_header);
  init_Self_Ihdr(&output_self_info_header);

  set_u64(&output_self_header.s_exsize, input_elf_len);

// setup segment header
  segment_certification_header segment_header; memset(&segment_header, 0, sizeof(segment_header));
  set_u32(&(segment_header.version), 1);

// NPDRM
#ifdef NPDRM
  Self_NPDRM npdrm; memset(&npdrm, 0, sizeof(npdrm));
  init_Self_NPDRM(&npdrm, argv[3], argv[2]);
#endif
// useless bullshit
  Self_SDKversion sdkversion;
  Self_Cflags cflags;
  memcpy(&sdkversion, sdkversion_static, sizeof(Self_SDKversion));
  memcpy(&cflags, cflags_static, sizeof(Self_Cflags));

// generate metadata encryption keys
  metadata_crypt_header md_header; memset(&md_header, 0, sizeof(md_header));

#ifdef NPDRM
  memcpy(&md_header, npdrm_keypair_d, sizeof(md_header));
#else
  mpz_t bigriv, bigerk;
  mpz_init(bigriv); mpz_init(bigerk);
  mpz_urandomb(bigerk, r_state, 128);
  mpz_urandomb(bigriv, r_state, 128);

  mpz_export(md_header.erk, &countp, 1, 0x10, 1, 0, bigerk);
  mpz_export(md_header.riv, &countp, 1, 0x10, 1, 0, bigriv);
#endif

// init signing shit
  mpz_t n,k,da,kinv,r,cs,z;
  mpz_init(n); mpz_init(k); mpz_init(da); mpz_init(r); mpz_init(cs); mpz_init(z); mpz_init(kinv);
  mpz_import(r, 0x14, 1, 1, 0, 0, KEY(R));
  mpz_import(n, 0x14, 1, 1, 0, 0, KEY(n));
  mpz_import(k, 0x14, 1, 1, 0, 0, KEY(K));
  mpz_import(da, 0x14, 1, 1, 0, 0, KEY(Da));
  mpz_invert(kinv, k, n);
  segment_certification_sign all_signed; memset(&all_signed, 0, sizeof(all_signed));
  mpz_export(all_signed.R, &countp, 1, 0x14, 1, 0, r);

// **** everything here is still length independent ***
  build_segment_crypt_data();
  set_u32(&(segment_header.crypt_len), (segment_crypt_data_len)/0x10);
  set_u32(&(segment_header.unknown2), 0x30);    // needed??
  printf("built crypt data\n");

// start building metadata in theory, ordering is fixed now
  memset(&start_file, 0, sizeof(file_ll));
  running_size = 0;
  // 0x000 -- Self_Shdr
  add_file_section(&output_self_header, sizeof(output_self_header));
  // 0x020 -- Self_Ehdr
  add_file_section(&output_extended_self_header, sizeof(output_extended_self_header));
  // 0x070 -- Self_Ihdr
  set_u64(&(output_extended_self_header.e_ihoff), running_size);
  add_file_section(&output_self_info_header, sizeof(output_self_info_header));
  // 0x090 -- elf data
  set_u64(&(output_extended_self_header.e_ehoff), running_size);
  set_u64(&(output_extended_self_header.e_phoff), running_size+get_u64(&(input_elf_header->e_phoff)));
  add_file_section(input_elf_data, get_u64(&(input_elf_header->e_phoff)) + get_u16(&(input_elf_header->e_phnum)) * sizeof(Elf64_Phdr));
  add_file_section(zero_padding, (0x10-(running_size&0xF))&0xF);
  // 0x*** -- all Self_PMhdr(including not in crypt)
  set_u64(&(output_extended_self_header.e_pmoff), running_size);
  segment_ptr = &first_segment;
  while(segment_ptr != NULL) {
    add_file_section(&(segment_ptr->pmhdr), sizeof(segment_ptr->pmhdr));
    segment_ptr = segment_ptr->next_segment;
  }
  // 0x*** -- Self_SDKversion
  set_u64(&(output_extended_self_header.e_svoff), running_size);
  add_file_section(&sdkversion, sizeof(sdkversion));
  // 0x*** -- ???
#ifdef NPDRM
  add_file_section(zero_padding, 0x20);
#endif
  // 0x*** -- Self_Cflags
  set_u64(&(output_extended_self_header.e_cfoff), running_size);
  add_file_section(&cflags, sizeof(cflags));
#ifdef NPDRM
  // 0x*** -- npdrm data
  add_file_section(&npdrm, sizeof(npdrm));
#endif
  // 0x*** -- metadata_crypt_header
  set_u32(&(output_self_header.s_esize), running_size - sizeof(output_self_header));
  add_file_section(&md_header, sizeof(md_header));
  // 0x*** -- segment_certification_header
  add_file_section(&segment_header, sizeof(segment_header));
  // 0x*** -- all segment_certification_segment incrypt
  int incrypt_count = 0;
  segment_ptr = &first_segment;
  while(segment_ptr != NULL) {
    if(segment_ptr->incrypt) {
      add_file_section(&(segment_ptr->enc_segment), sizeof(segment_ptr->enc_segment));
      incrypt_count++;
    }
    segment_ptr = segment_ptr->next_segment;
  }
  set_u32(&(segment_header.segment_count), incrypt_count);
  // 0x*** -- segment_crypt_data
  add_file_section(segment_crypt_data, segment_crypt_data_len);
  // 0x*** -- nubpadding_static
  add_file_section(nubpadding_static, sizeof(nubpadding_static));
  // 0x*** -- segment_certification_sign
  set_u64(&(segment_header.signature_offset), running_size);
  add_file_section(&all_signed, sizeof(all_signed));
  // 0x*** -- data must be 0x80 aligned
  if((running_size%0x80) != 0) {
    add_file_section(zero_padding, 0x80-(running_size%0x80));
  }
  // 0x*** -- data
  set_u64(&(output_self_header.s_shsize), running_size);
  // ...data...
  segment_ptr = &first_segment;
  while(segment_ptr != NULL) {
    set_u64(&(segment_ptr->enc_segment.segment_offset), running_size);
    set_u64(&(segment_ptr->pmhdr.pm_offset), running_size);
    add_file_section(segment_ptr->data, segment_ptr->len);
    add_file_section(zero_padding, segment_ptr->padding);
    segment_ptr = segment_ptr->next_segment;
  }
  // 0x*** -- section table
#ifndef SPRX
  set_u64(&(output_extended_self_header.e_shoff), running_size);
  add_file_section(input_elf_data+get_u64(&(input_elf_header->e_shoff)), get_u16(&(input_elf_header->e_shnum)) * sizeof(Elf64_Shdr));
#endif
  // ***DONE***

  printf("file built\n");

// write self file in memory <-- useful comment
  write_self_file_in_memory();
  printf("self written in memory\n");

// sign shit
  u8 digest[0x14];
  SHA1(output_self_data, get_u64(&(segment_header.signature_offset)), digest);

  mpz_import(z, 0x14, 1, 1, 0, 0, digest);
  mpz_mul(cs, r, da); mpz_mod(cs, cs, n);
  mpz_add(cs, cs, z); mpz_mod(cs, cs, n);
  mpz_mul(cs, cs, kinv); mpz_mod(cs, cs, n);
 
  //mpz_export(all_signed.S, &countp, 1, 0x14, 1, 0, cs);
  mpz_export(&output_self_data[get_u64(&output_self_data[get_u32(output_self_data+0xC)+0x60])+0x16], &countp, 1, 0x14, 1, 0, cs);

// write the output self test
  FILE *test_self_file = fopen("test_out", "wb");
  fwrite(output_self_data, 1, running_size, test_self_file);
  fclose(test_self_file);

// encrypt metadata
  int metadata_offset = get_u32(&(output_self_header.s_esize)) + sizeof(Self_Shdr);

#ifndef NO_CRYPT
  memset(ecount_buf, 0, 16); num=0;
  AES_set_encrypt_key(&output_self_data[metadata_offset], 128, &aes_key);
  memcpy(iv, &output_self_data[metadata_offset+0x20], 16);
  AES_ctr128_encrypt(&output_self_data[0x40+metadata_offset], &output_self_data[0x40+metadata_offset], get_u64(&(output_self_header.s_shsize))-metadata_offset-0x40, &aes_key, iv, ecount_buf, &num);
  printf("encrypted metadata\n");

#ifdef NPDRM
  memcpy(&output_self_data[metadata_offset], npdrm_keypair_e, sizeof(md_header));
#else
  AES_set_encrypt_key(KEY(erk), 256, &aes_key);
  memcpy(iv, KEY(riv), 16);
  AES_cbc_encrypt(&output_self_data[metadata_offset], &output_self_data[metadata_offset], 0x40, &aes_key, iv, AES_ENCRYPT);
  printf("encrypted keys\n");
#endif

#else
  printf("NO_CRYPT is enabled...self is broken\n");
#endif
  
// write the output self
  FILE *output_self_file = fopen(argv[2], "wb");
  fwrite(output_self_data, 1, running_size, output_self_file);
  fclose(output_self_file);
}