Beispiel #1
0
/*
 * Polynomial Evaluator, used to determine the Syndrome Vector. This is
 * relatively straightforward, and there are faster algorithms.
 */
static uint8_t evalpoly(uint8_t p[ECC_CAPACITY], uint8_t x)
{
	uint8_t y = 0;
	for (int i = 0; i < ECC_CAPACITY; i++)
		y = GF_ADD(y, GF_MUL(p[i], GF_EXP(x, i)));
	return y;
}
Beispiel #2
0
/*
 * Reed - Solomon Encoder. The Encoder uses a shift register algorithm,
 * as detailed in _Applied Modern Algebra_ by Dornhoff and Hohn (p.446).
 * Note that the message is reversed in the code array; this was done to
 * allow for (emergency) recovery of the message directly from the
 * data stream.
 */
extern void ecc_encode(uint8_t m[ECC_PAYLOAD], uint8_t c[ECC_CAPACITY])
{
	uint8_t r[ECC_OFFSET] = { 0x0 };

	for (int i = 0; i < ECC_PAYLOAD; i++)
	{
		c[(ECC_CAPACITY - 1) - i] = m[i];
		uint8_t rtmp = GF_ADD(m[i], r[5]);
		for (int j = ECC_OFFSET - 1; j > 0; j--)
			r[j] = GF_ADD(GF_MUL(rtmp, g[j]), r[j - 1]);
		r[0] = GF_MUL(rtmp, g[0]);
	}
	for (int i = 0; i < ECC_OFFSET; i++)
		c[i] = r[i];

	REVERSE(c, ECC_CAPACITY);
}
Beispiel #3
0
/*
 * Polynomial Solver. Simple exhaustive search, as solving polynomials is
 * generally NP - Complete anyway.
 */
static void polysolve(uint8_t polynom[4], uint8_t roots[3], int *numsol)
{
	*numsol = 0;

	for (int i = 0; i < ECC_CAPACITY; i++)
	{
		uint8_t y = 0;
		for (int j = 0; j < 4; j++)
			y = GF_ADD(y, GF_MUL(polynom[j], GF_EXP(e2v[i], j)));
		if (y == 0)
			roots[(*numsol)++] = e2v[i];
	}
}
Beispiel #4
0
/*
 * Determine the number of errors in a block. Since we have to find the
 * determinant of the S[] matrix in order to determine singularity, we
 * also return the determinant to be used by the Cramer's Rule correction
 * algorithm.
 */
static void errnum(uint8_t s[ECC_OFFSET + 1], uint8_t *det, int *errs)
{
	*det = GF_MUL(s[2], GF_MUL(s[4], s[6]));
	*det = GF_ADD(*det, GF_MUL(s[2], GF_MUL(s[5], s[5])));
	*det = GF_ADD(*det, GF_MUL(s[6], GF_MUL(s[3], s[3])));
	*det = GF_ADD(*det, GF_MUL(s[4], GF_MUL(s[4], s[4])));
	*errs = 3;

	if (*det != 0)
		return;

	*det = GF_ADD(GF_MUL(s[2], s[4]), GF_EXP(s[3], 2));
	*errs = 2;
	if (*det != 0)
		return;

	*det = s[1];
	*errs = 1;
	if (*det != 0)
		return;

	*errs = 4;
}
Beispiel #5
0
/*
 * Full implementation of the three error correcting Peterson decoder. For
 * t<6, it is faster than Massey - Berlekamp. It is also somewhat more
 * intuitive.
 */
extern void ecc_decode(uint8_t code[ECC_CAPACITY], uint8_t mesg[ECC_CAPACITY], int *errcode)
{
	REVERSE(code, ECC_CAPACITY);

	uint8_t syn[ECC_OFFSET + 1], deter, z[4], e0, e1, e2, n0, n1, n2, w0, w1, w2, x0, x[3];
	int sols;

	*errcode = 0;

	/*
	 * First, get the message out of the code, so that even if we can't correct
	 * it, we return an estimate.
	 */
	for (int i = 0; i < ECC_PAYLOAD; i++)
		mesg[i] = code[(ECC_CAPACITY - 1) - i];

	syndrome(code, syn);

	if (syn[0] == 0)
		return;

	/*
	 * We now know we have at least one error. If there are no errors detected,
	 * we assume that something funny is going on, and so return with errcode 4,
	 * else pass the number of errors back via errcode.
	 */
	errnum(syn, &deter, errcode);

	if (*errcode == 4)
		return;

	/* Having obtained the syndrome, the number of errors, and the determinant,
	 * we now proceed to correct the block.	If we do not find exactly the
	 * number of solutions equal to the number of errors, we have exceeded our
	 * error capacity, and return with the block uncorrected, and errcode 4.
	 */

	switch (*errcode)
	{
		case 1:
			x0 = GF_MUL(syn[2], GF_INV(syn[1]));
			w0 = GF_MUL(GF_EXP(syn[1], 2), GF_INV(syn[2]));
			if (v2e[x0] > 5)
				mesg[(ECC_CAPACITY - 1) - v2e[x0]] = GF_ADD(mesg[(ECC_CAPACITY - 1) - v2e[x0]], w0);
			return;

		case 2:
			z[0] = GF_MUL(GF_ADD(GF_MUL(syn[1], syn[3]), GF_EXP(syn[2], 2)), GF_INV(deter));
			z[1] = GF_MUL(GF_ADD(GF_MUL(syn[2], syn[3]), GF_MUL(syn[1], syn[4])), GF_INV(deter));
			z[2] = 1;
			z[3] = 0;
			polysolve(z, x, &sols);
			if (sols != 2)
			{
				*errcode = 4;
				return;
			}
			w0 = GF_MUL(z[0], syn[1]);
			w1 = GF_ADD(GF_MUL(z[0], syn[2]), GF_MUL(z[1], syn[1]));
			n0 = (ECC_CAPACITY - 1) - v2e[GF_INV(x[0])];
			n1 = (ECC_CAPACITY - 1) - v2e[GF_INV(x[1])];
			e0 = GF_MUL(GF_ADD(w0, GF_MUL(w1, x[0])), GF_INV(z[1]));
			e1 = GF_MUL(GF_ADD(w0, GF_MUL(w1, x[1])), GF_INV(z[1]));
			if (n0 < ECC_PAYLOAD)
				mesg[n0] = GF_ADD(mesg[n0], e0);
			if (n1 < ECC_PAYLOAD)
				mesg[n1] = GF_ADD(mesg[n1], e1);
			return;

		case 3:
			z[3] = 1;
			z[2] = GF_MUL(syn[1], GF_MUL(syn[4], syn[6]));
			z[2] = GF_ADD(z[2], GF_MUL(syn[1], GF_MUL(syn[5], syn[5])));
			z[2] = GF_ADD(z[2], GF_MUL(syn[5], GF_MUL(syn[3], syn[3])));
			z[2] = GF_ADD(z[2], GF_MUL(syn[3], GF_MUL(syn[4], syn[4])));
			z[2] = GF_ADD(z[2], GF_MUL(syn[2], GF_MUL(syn[5], syn[4])));
			z[2] = GF_ADD(z[2], GF_MUL(syn[2], GF_MUL(syn[3], syn[6])));
			z[2] = GF_MUL(z[2], GF_INV(deter));

			z[1] = GF_MUL(syn[1], GF_MUL(syn[3], syn[6]));
			z[1] = GF_ADD(z[1], GF_MUL(syn[1], GF_MUL(syn[5], syn[4])));
			z[1] = GF_ADD(z[1], GF_MUL(syn[4], GF_MUL(syn[3], syn[3])));
			z[1] = GF_ADD(z[1], GF_MUL(syn[2], GF_MUL(syn[4], syn[4])));
			z[1] = GF_ADD(z[1], GF_MUL(syn[2], GF_MUL(syn[3], syn[5])));
			z[1] = GF_ADD(z[1], GF_MUL(syn[2], GF_MUL(syn[2], syn[6])));
			z[1] = GF_MUL(z[1], GF_INV(deter));

			z[0] = GF_MUL(syn[2], GF_MUL(syn[3], syn[4]));
			z[0] = GF_ADD(z[0], GF_MUL(syn[3], GF_MUL(syn[2], syn[4])));
			z[0] = GF_ADD(z[0], GF_MUL(syn[3], GF_MUL(syn[5], syn[1])));
			z[0] = GF_ADD(z[0], GF_MUL(syn[4], GF_MUL(syn[4], syn[1])));
			z[0] = GF_ADD(z[0], GF_MUL(syn[3], GF_MUL(syn[3], syn[3])));
			z[0] = GF_ADD(z[0], GF_MUL(syn[2], GF_MUL(syn[2], syn[5])));
			z[0] = GF_MUL(z[0], GF_INV(deter));

			polysolve (z, x, &sols);
			if (sols != 3)
			{
				*errcode = 4;
				return;
			}

			w0 = GF_MUL(z[0], syn[1]);
			w1 = GF_ADD(GF_MUL(z[0], syn[2]), GF_MUL(z[1], syn[1]));
			w2 = GF_ADD(GF_MUL(z[0], syn[3]), GF_ADD(GF_MUL(z[1], syn[2]), GF_MUL(z[2], syn[1])));

			n0 = (ECC_CAPACITY - 1) - v2e[GF_INV(x[0])];
			n1 = (ECC_CAPACITY - 1) - v2e[GF_INV(x[1])];
			n2 = (ECC_CAPACITY - 1) - v2e[GF_INV(x[2])];

			e0 = GF_ADD(w0, GF_ADD(GF_MUL(w1, x[0]), GF_MUL(w2, GF_EXP(x[0], 2))));
			e0 = GF_MUL(e0, GF_INV(GF_ADD(z[1], GF_EXP(x[0], 2))));
			e1 = GF_ADD(w0, GF_ADD(GF_MUL(w1, x[1]), GF_MUL(w2, GF_EXP(x[1], 2))));
			e1 = GF_MUL(e1, GF_INV(GF_ADD(z[1], GF_EXP(x[1], 2))));
			e2 = GF_ADD(w0, GF_ADD(GF_MUL(w1, x[2]), GF_MUL(w2, GF_EXP(x[2], 2))));
			e2 = GF_MUL(e2, GF_INV(GF_ADD(z[1], GF_EXP(x[2], 2))));

			if (n0 < ECC_PAYLOAD)
				mesg[n0] = GF_ADD(mesg[n0], e0);
			if (n1 < ECC_PAYLOAD)
				mesg[n1] = GF_ADD(mesg[n1], e1);
			if (n2 < ECC_PAYLOAD)
				mesg[n2] = GF_ADD(mesg[n2], e2);
			return;
	}
}
Beispiel #6
0
int main(void) {
  gf a, b, c;

  gf_init();
  a = 1;
  b = 37;
  c = 78;
  testit("1 * ( 37 + 78 ) = 1 * 37 + 1 * 78",
         GF_MUL(a, GF_ADD(b, c)),
         GF_ADD(GF_MUL(a, b), GF_MUL(a, c)));
  testit("(1 * 37) * 78 = 1 * (37 * 78)",
         GF_MUL(GF_MUL(a, b), c),
         GF_MUL(a, GF_MUL(b, c)));
  testit("(37 * 78) * 37 = (37 * 37) * 78",
         GF_MUL(GF_MUL(b, c), b),
         GF_MUL(GF_MUL(b, b), c));
  testit("b * b^-1 = 1", GF_MUL(b, GF_INV(b)), 1);

  return 0;
}
Beispiel #7
0
/*M
  \emph{Computes addition of a row multiplied by a constant.}

  Computes $a = a + c * b$, $a, b \in \gf{2^8}^k, c \in \gf{2^8}$.
**/
void gf_add_mul(gf *a, gf *b, gf c, int k) {
  int i;
  for (i = 0; i < k; i++)
    a[i] = GF_ADD(a[i], GF_MUL(c, b[i]));
}