Example #1
0
static int ctr_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
		       struct scatterlist *src, unsigned int nbytes)
{
	struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
	int err, first, rounds = 6 + ctx->key_length / 4;
	struct blkcipher_walk walk;
	int blocks;

	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
	blkcipher_walk_init(&walk, dst, src, nbytes);
	err = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);

	first = 1;
	kernel_neon_begin();
	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
		aes_ctr_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
				(u8 *)ctx->key_enc, rounds, blocks, walk.iv,
				first);
		first = 0;
		nbytes -= blocks * AES_BLOCK_SIZE;
		if (nbytes && nbytes == walk.nbytes % AES_BLOCK_SIZE)
			break;
		err = blkcipher_walk_done(desc, &walk,
					  walk.nbytes % AES_BLOCK_SIZE);
	}
	if (nbytes) {
		u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE;
		u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE;
		u8 __aligned(8) tail[AES_BLOCK_SIZE];

		/*
		 * Minimum alignment is 8 bytes, so if nbytes is <= 8, we need
		 * to tell aes_ctr_encrypt() to only read half a block.
		 */
		blocks = (nbytes <= 8) ? -1 : 1;

		aes_ctr_encrypt(tail, tsrc, (u8 *)ctx->key_enc, rounds,
				blocks, walk.iv, first);
		memcpy(tdst, tail, nbytes);
		err = blkcipher_walk_done(desc, &walk, 0);
	}
	kernel_neon_end();

	return err;
}
Example #2
0
int fixup_pkg(char *pkg_name, char *new_name)
{
	FILE *fp;
	u8 header[256], file_key[16], sha1_key[0x40];
	u8 *pkg_buf, *pkg_aeskey, *file_table;
	int i, base, data_size, pkg_size, total_file;

	fp = fopen(pkg_name, "rb");

	/* header check */
	fread(header, 256, 1, fp);
	if(*(u32*)(header)!=0x474b507f){
		printf("Selected file isn't a PKG file!\n");
		return -1;
	}
	if(header[4]==0x80){
		printf("Selected file isn't a debug PKG.\n");
		return -1;
	}

	pkg_aeskey = psp_pkg_key;

	/* read all file */
	fseek(fp, 0, SEEK_END);
	pkg_size = ftell(fp);
	fseek(fp, 0, SEEK_SET);

	pkg_buf = malloc(pkg_size);
	fread(pkg_buf, pkg_size, 1, fp);
	fclose(fp);

	/* make sha1 key */
	memset(sha1_key, 0, 0x40);
	memcpy(sha1_key+0x00, pkg_buf+0x60, 8);
	memcpy(sha1_key+0x08, pkg_buf+0x60, 8);
	memcpy(sha1_key+0x10, pkg_buf+0x68, 8);
	memcpy(sha1_key+0x18, pkg_buf+0x68, 8);

	base = get_be32(pkg_buf+0x24);
	data_size = get_be32(pkg_buf+0x2c);
	total_file = get_be32(pkg_buf+0x14);

	// decrypt debug pkg
	sha1_ctr_encrypt(pkg_buf+base, data_size, 0, sha1_key);



	memcpy(file_key, header+0x70, 0x10);

	// read file table
	file_table = malloc(total_file*0x20);
	memcpy(file_table, pkg_buf+base, total_file*0x20);

	// encrypt file table
	aes_ctr_encrypt(pkg_buf+base, total_file*0x20, 0, file_key, pkg_aeskey);

	// process all file
	for(i=0; i<total_file; i++){
		u8 *desc = file_table+i*0x20;
		int name_offset = get_be32(desc+0x00);
		int name_length = get_be32(desc+0x04);
		int file_offset = get_be32(desc+0x0c);
		int file_length = get_be32(desc+0x14);
		int content_type= desc[0x18];
		int file_type   = desc[0x1b];
		u8 content_name[64];

		// read name
		memcpy(content_name, pkg_buf+base+name_offset, name_length);
		content_name[name_length] = 0;

		// encrypt name
		if(content_type==0x90){
			pkg_aeskey = psp_pkg_key;
		}else{
			pkg_aeskey = ps3_pkg_key;
		}
		aes_ctr_encrypt(pkg_buf+base+name_offset, name_length, name_offset, file_key, pkg_aeskey);

		printf("file %2d: offset=%08x length=%08x type=(%2x %2x)  %s\n", i, file_offset, file_length, content_type, file_type, content_name);
		if(file_type==0x04 || file_length==0){
			// is DIR
			continue;
		}

		// encrypt data
		aes_ctr_encrypt(pkg_buf+base+file_offset, file_length, file_offset, file_key, pkg_aeskey);
	}

	// make sha1 hash
	pkg_buf[4] = 0x80;
	pkg_buf[7] = 0x02;
	memset(pkg_buf+base+data_size, 0, 0x60);
	SHA1(pkg_buf, pkg_size-0x20, pkg_buf+pkg_size-0x20);

	// write back
	fp = fopen(new_name, "wb");
	fwrite(pkg_buf, pkg_size, 1, fp);
	fclose(fp);

	free(file_table);
	free(pkg_buf);
	return 0;
}