⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg3css.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 3 页
字号:

/*
 * We use two LFSR's (seeded from some of the input data bytes) to
 * generate two streams of pseudo-random bits.  These two bit streams
 * are then combined by simply adding with carry to generate a final
 * sequence of pseudo-random bits which is stored in the buffer that
 * 'output' points to the end of - len is the size of this buffer.
 *
 * The first LFSR is of degree 25,  and has a polynomial of:
 * x^13 + x^5 + x^4 + x^1 + 1
 *
 * The second LSFR is of degree 17,  and has a (primitive) polynomial of:
 * x^15 + x^1 + 1
 *
 * I don't know if these polynomials are primitive modulo 2,  and thus
 * represent maximal-period LFSR's.
 *
 *
 * Note that we take the output of each LFSR from the new shifted in
 * bit,  not the old shifted out bit.  Thus for ease of use the LFSR's
 * are implemented in bit reversed order.
 *
 */

#define  BIT0(x) ((x) & 1)
#define  BIT1(x) (((x) >> 1) & 1)

static void generate_bits(unsigned char *output, int len, struct mpeg3_block const *s)
{
	unsigned long lfsr0, lfsr1;
	unsigned char carry;

	/* In order to ensure that the LFSR works we need to ensure that the
	 * initial values are non-zero.  Thus when we initialise them from
	 * the seed,  we ensure that a bit is set.
	 */
	lfsr0 = (s->b[0] << 17) | (s->b[1] << 9) | ((s->b[2] & ~7) << 1) | 8 | (s->b[2] & 7);
	lfsr1 = (s->b[3] << 9) | 0x100 | s->b[4];

	++output;

	carry = 0;
	do{
		int bit;
		unsigned char val;

		for (bit = 0, val = 0; bit < 8; ++bit) 
		{
			unsigned char o_lfsr0, o_lfsr1;	/* Actually only 1 bit each */
			unsigned char combined;

			o_lfsr0 = ((lfsr0 >> 24) ^ (lfsr0 >> 21) ^ (lfsr0 >> 20) ^ (lfsr0 >> 12)) & 1;
			  lfsr0 = (lfsr0 << 1) | o_lfsr0;

			o_lfsr1 = ((lfsr1 >> 16) ^ (lfsr1 >> 2)) & 1;
			  lfsr1 = (lfsr1 << 1) | o_lfsr1;

			combined = !o_lfsr1 + carry + !o_lfsr0;
			carry = BIT1(combined);
			val |= BIT0(combined) << bit;
		}
	
		*--output = val;
	}while (--len > 0);
}


/*
 * This encryption engine implements one of 32 variations
 * one the same theme depending upon the choice in the
 * varient parameter (0 - 31).
 *
 * The algorithm itself manipulates a 40 bit input into
 * a 40 bit output.
 * The parameter 'input' is 80 bits.  It consists of
 * the 40 bit input value that is to be encrypted followed
 * by a 40 bit seed value for the pseudo random number
 * generators.
 */
static void css_engine(int varient, unsigned char const *input, struct mpeg3_block *output)
{
	unsigned char cse, term, index;
	struct mpeg3_block temp1;
	struct mpeg3_block temp2;
	unsigned char bits[30];

	int i;

/* Feed the secret into the input values such that
 * we alter the seed to the LFSR's used above,  then
 * generate the bits to play with.
 */
	for(i = 5; --i >= 0; )
		temp1.b[i] = input[5 + i] ^ mpeg3css_secret[i] ^ mpeg3css_table2[i];

	generate_bits(&bits[29], sizeof bits, &temp1);

	/* This term is used throughout the following to
	 * select one of 32 different variations on the
	 * algorithm.
	 */
	cse = mpeg3css_varients[varient] ^ mpeg3css_table2[varient];

	/* Now the actual blocks doing the encryption.  Each
	 * of these works on 40 bits at a time and are quite
	 * similar.
	 */
	for(i = 5, term = 0; --i >= 0; term = input[i]) 
	{
		index = bits[25 + i] ^ input[i];
		index = mpeg3css_table1[index] ^ ~mpeg3css_table2[index] ^ cse;

		temp1.b[i] = mpeg3css_table2[index] ^ mpeg3css_table3[index] ^ term;
	}
	temp1.b[4] ^= temp1.b[0];

	for(i = 5, term = 0; --i >= 0; term = temp1.b[i]) 
	{
		index = bits[20 + i] ^ temp1.b[i];
		index = mpeg3css_table1[index] ^ ~mpeg3css_table2[index] ^ cse;

		temp2.b[i] = mpeg3css_table2[index] ^ mpeg3css_table3[index] ^ term;
	}
	temp2.b[4] ^= temp2.b[0];

	for (i = 5, term = 0; --i >= 0; term = temp2.b[i]) 
	{
		index = bits[15 + i] ^ temp2.b[i];
		index = mpeg3css_table1[index] ^ ~mpeg3css_table2[index] ^ cse;
		index = mpeg3css_table2[index] ^ mpeg3css_table3[index] ^ term;

		temp1.b[i] = mpeg3css_table0[index] ^ mpeg3css_table2[index];
	}
	temp1.b[4] ^= temp1.b[0];

	for (i = 5, term = 0; --i >= 0; term = temp1.b[i]) 
	{
		index = bits[10 + i] ^ temp1.b[i];
		index = mpeg3css_table1[index] ^ ~mpeg3css_table2[index] ^ cse;

		index = mpeg3css_table2[index] ^ mpeg3css_table3[index] ^ term;

		temp2.b[i] = mpeg3css_table0[index] ^ mpeg3css_table2[index];
	}
	temp2.b[4] ^= temp2.b[0];

	for (i = 5, term = 0; --i >= 0; term = temp2.b[i]) 
	{
		index = bits[5 + i] ^ temp2.b[i];
		index = mpeg3css_table1[index] ^ ~mpeg3css_table2[index] ^ cse;

		temp1.b[i] = mpeg3css_table2[index] ^ mpeg3css_table3[index] ^ term;
	}
	temp1.b[4] ^= temp1.b[0];

	for (i = 5, term = 0; --i >= 0; term = temp1.b[i]) 
	{
		index = bits[i] ^ temp1.b[i];
		index = mpeg3css_table1[index] ^ ~mpeg3css_table2[index] ^ cse;

		output->b[i] = mpeg3css_table2[index] ^ mpeg3css_table3[index] ^ term;
	}
}

static void crypt_key1(mpeg3_css_t *css, int varient, unsigned char const *challenge, struct mpeg3_block *key)
{
	static unsigned char perm_challenge[] = {1, 3, 0, 7, 5, 2, 9, 6, 4, 8};

	unsigned char scratch[10];
	int i;

	for (i = 9; i >= 0; i--)
		scratch[i] = challenge[perm_challenge[i]];

	css_engine(varient, scratch, key);
}

/* This shuffles the bits in varient to make perm_varient such that
 *                4 -> !3
 *                3 ->  4
 * varient bits:  2 ->  0  perm_varient bits
 *                1 ->  2
 *                0 -> !1
 */
static void crypt_key2(mpeg3_css_t *css, int varient, unsigned char const *challenge, struct mpeg3_block *key)
{
	static unsigned char perm_challenge[] = {6, 1, 9, 3, 8, 5, 7, 4, 0, 2};

	static unsigned char perm_varient[] = 
	{
		0x0a, 0x08, 0x0e, 0x0c, 0x0b, 0x09, 0x0f, 0x0d,
		0x1a, 0x18, 0x1e, 0x1c, 0x1b, 0x19, 0x1f, 0x1d,
		0x02, 0x00, 0x06, 0x04, 0x03, 0x01, 0x07, 0x05,
		0x12, 0x10, 0x16, 0x14, 0x13, 0x11, 0x17, 0x15
	};

	unsigned char scratch[10];
	int i;

	for(i = 9; i >= 0; i--)
		scratch[i] = css->challenge[perm_challenge[i]];

	css_engine(perm_varient[varient], scratch, key);
}

/* This shuffles the bits in varient to make perm_varient such that
 *                4 ->  0
 *                3 -> !1
 * varient bits:  2 -> !4  perm_varient bits
 *                1 ->  2
 *                0 ->  3
 */
static void crypt_bus_key(mpeg3_css_t *css, int varient, unsigned char const *challenge, struct mpeg3_block *key)
{
	static unsigned char perm_challenge[] = {4,0,3,5,7, 2,8,6,1,9};
	static unsigned char perm_varient[] = {
		0x12, 0x1a, 0x16, 0x1e, 0x02, 0x0a, 0x06, 0x0e,
		0x10, 0x18, 0x14, 0x1c, 0x00, 0x08, 0x04, 0x0c,
		0x13, 0x1b, 0x17, 0x1f, 0x03, 0x0b, 0x07, 0x0f,
		0x11, 0x19, 0x15, 0x1d, 0x01, 0x09, 0x05, 0x0d};

	unsigned char scratch[10];
	int i;

	for(i = 9; i >= 0; i--)
		scratch[i] = css->challenge[perm_challenge[i]];

	css_engine(perm_varient[varient], scratch, key);
}

static int get_asf(mpeg3_css_t *css)
{
	dvd_authinfo ai;

	ai.type = DVD_LU_SEND_ASF;
	ai.lsasf.agid = 0;
	ai.lsasf.asf = 0;

	if(ioctl(css->fd, DVD_AUTH, &ai))
	{
/* Exit here for a hard drive or unencrypted CD-ROM. */
		return 1;
	}

	return 0;
}

static int authenticate_drive(mpeg3_css_t *css, const unsigned char *key)
{
	int i;

	for(i = 0; i < 5; i++)
		css->key1.b[i] = key[4 - i];

	for(i = 0; i < 32; ++i)
	{
		crypt_key1(css, i, css->challenge, &(css->keycheck));
		if(memcmp(css->keycheck.b, css->key1.b, 5) == 0)
		{
			css->varient = i;
			return 0;
		}
	}

	if (css->varient == -1) return 1;

	return 0;
}

/* Simulation of a non-CSS compliant host (i.e. the authentication fails,
 * but idea is here for a real CSS compliant authentication scheme). */
static int hostauth(mpeg3_css_t *css, dvd_authinfo *ai)
{
	int i;

	switch(ai->type) 
	{
/* Host data receive (host changes state) */
		case DVD_LU_SEND_AGID:
			ai->type = DVD_HOST_SEND_CHALLENGE;
			break;

		case DVD_LU_SEND_KEY1:
/* printf("Key 1: %02x %02x %02x %02x %02x\n",  */
/* 			ai->lsk.key[4], ai->lsk.key[3], ai->lsk.key[2], ai->lsk.key[1], ai->lsk.key[0]); */
			if(authenticate_drive(css, ai->lsk.key)) 
			{
				ai->type = DVD_AUTH_FAILURE;
				return 1;
			}
			ai->type = DVD_LU_SEND_CHALLENGE;
			break;

		case DVD_LU_SEND_CHALLENGE:
			for(i = 0; i < 10; i++)
				css->challenge[i] = ai->hsc.chal[9-i];
			crypt_key2(css, css->varient, css->challenge, &(css->key2));
			ai->type = DVD_HOST_SEND_KEY2;
			break;

/* Host data send */
		case DVD_HOST_SEND_CHALLENGE:
			for(i = 0; i < 10; i++)
				ai->hsc.chal[9 - i] = css->challenge[i];
/* Returning data, let LU change state */
			break;

		case DVD_HOST_SEND_KEY2:
			for(i = 0; i < 5; i++)
			{
				ai->hsk.key[4 - i] = css->key2.b[i];
			}
/* printf("Key 2: %02x %02x %02x %02x %02x\n",  */
/* 			ai->hsk.key[4], ai->hsk.key[3], ai->hsk.key[2], ai->hsk.key[1], ai->hsk.key[0]); */
/* Returning data, let LU change state */
			break;

		default:
			fprintf(stderr, "Got invalid state %d\n", ai->type);
			return 1;
	}

	return 0;
}

static int get_title_key(mpeg3_css_t *css, int agid, int lba, unsigned char *key)
{
	dvd_authinfo ai;
	int i;

	ai.type = DVD_LU_SEND_TITLE_KEY;

	ai.lstk.agid = agid;
	ai.lstk.lba = lba;

	if(ioctl(css->fd, DVD_AUTH, &ai))
	{
		//perror("GetTitleKey");
		return 1;
	}

	for (i = 0; i < 5; i++)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -