I am puting up a C code for the Multiplication of block (Alogrithm 1) in the GCM SP-800-38D document here. Page 11-12.
Having completed the code, I want to see if there are any way I can test the code. You can find attached below the code I have put up. Note that instead of the 128 bit block, I used a 24 bit block just for testing purposed. I will appreciate any suggestions where necessary.
void BLK_MUL (u8 *val_1,u8 *val_2, u8 *out_val)
{
u8 xdata R_val = 0xE1;
u8 xdata Z_val[3],V_val[3];
u8 mask_b = 0x80;
u16 i; u8 j;
bit rnd;
for(j=0;j<3;j++,++val_2)
{
Z_val[j]=0x00;
V_val[j]=*val_2;
}
for(i=0;i<24;i++)
{
if (*val_1 & mask_b)
{
for(j=0;j<3;j++)
Z_val[j]^=V_val[j];
}
if (!(V_val[2] & 0x01))
{//if LSB of V_val is 0
for(j=0;j<3;j++)
{ //V_val = rightshift(V_val)
if (j!=0)
if (V_val[2-j] & 0x01)
V_val[3-j] |= 0x80;
V_val[2-j]>>=1;
}
}
else
{//if LSB of V_val is 1
for(j=0;j<3;j++)
{//V_val = rightshift(V_val)
if (j!=0)
if (V_val[2-j] & 0x01)
V_val[3-j] |= 0x80;
V_val[2-j]>>=1;
}
V_val[0]^=R_val; //V_val = rightshift(V_val) ^ R
}
if(mask_b & 0x01) { val_1++; rnd=1;}
mask_b >>= 1;
if (rnd) { mask_b=0x80; rnd=0; }
}
STR_CPY(out_val,Z_val,3);
return ;
}
void main()
{
code unsigned char val_1[3] ={ 0x2b,0x7e,0x15 };
code unsigned char val_2[3] ={ 0x39,0x25,0x84 };
unsigned char out[3];
BLK_MUL (val_1,val_2,out);
return;
}
GCM mode requires that the IV is a nonce, i.e., the IV must be unique for each execution of the mode under the given key. The steps for GCM encryption are: The hash subkey for the GHASH function is generated by applying the block cipher to the “zero" block. The pre-counter block (J0) is generated from the IV.
In simple terms, Galois Counter Mode (GCM) block clipper is a combination of Counter mode (CTR) and Authentication it's faster and more secure with a better implementation for table-driven field operations. GCM has two operations, authenticated encryption and authenticated decryption.
The GCM mode uses an initialization vector (IV) in its processing. This mode is used for authenticated encryption with associated data. GCM provides confidentiality and authenticity for the encrypted data and authenticity for the additional authenticated data (AAD). The AAD is not encrypted.
Galois/Counter Mode (GCM) is a block cipher mode of operation that uses universal hashing over a binary Galois field to provide authenticated encryption. It can be implemented in hardware to achieve high speeds with low cost and low latency.
At some point you will of course have to check your code against test vectors. But there are quite a few tests that you can perform without having to know or compute any test vectors at all.
First the multiplication in GF(2^128) is commutative. Hence you can just compute BLK_MUL(val_1, val_2, out1) and BLK_MUL(val_2, val_1, out2) with any input and you should get the same result. Since your code uses val_1 and val_2 differently this is already quite a good test.
Then you can use that multiplication is distributive, I.e. you can test that (x+y)*z = (x*z)+(y*z), (where the addition in GF(2^128) is computed by xoring corresponding bytes of the two values together).
Finally, once you have implemented the whole field GF(2^128) you can also exploit that its order is 2^128-1. I.e. if you start with a value x then square it 128 times, then you should get x back.
A few additional comments:
The advantage of using equations for testing (over only using test vectors) is that you can easily run a large number of tests. Because it is rather easy to add tests this way I frequently do some simple tests with sparse inputs (e.g. just single bits set in the input) first. If something is wrong then this helps to identify the bugs fast.
Your current code uses temporary variables for the result. This is indeed a good idea, since it ensures copy safety. I think a good unit test should also cover this case. I.e. you might want to compute the same result twice: once with input and output pointing to different memory location, and once with the output being the same memory as the input.
Furthermore, at least one of the other answers talks about optimizations. I think if you refactor the code then you should look for meaningful components to reuse, rather than blindly looking for look-a-like code snippets. Since GF(2^128) is a field, of course addition and multiplication in the field are meaningful components. Another meaningful component is the multiplication by the polynomial x (which is something that is quite frequently used in crypto).
Test vectors for GCM mode can be found here and there's a bunch of NIST test vectors here.
A test example for GF(2^128) can be found at: PCLMULQDQ CPU instruction, page 78
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With