0

The following test code should theoretically give me the result from the NIST test suite of 58e2fccefa7e3061367f1d57a4e7455a , however a hexdump of the output yields 9eeaed13b5f591104e2cda197fb99eeaed13b5f591104e2cda197fb9 instead ?

#include <iostream>
#include <cstdio>
#include <polarssl/md.h>
#include <polarssl/entropy.h>
#include <polarssl/ctr_drbg.h>
#include <polarssl/cipher.h>
#include <cstdlib>
#include <fstream>


int main(int argc, char** argv) {
const cipher_info_t *cipher_info;
        cipher_info = cipher_info_from_string( "AES-128-GCM" );
        cipher_context_t cipher_ctx;
    cipher_init_ctx (&cipher_ctx,cipher_info);
        std::cout<<"KEYLEN"<<std::endl;
        std::cout<<cipher_info->key_length<<std::endl;
    std::cout<<"IVLEN"<<std::endl;
    std::cout<<cipher_info->iv_size<<std::endl;
unsigned char key[cipher_info->key_length/8];
    unsigned char iv[cipher_info->iv_size];
    memset(key,0x00,cipher_info->key_length/8);
    memset(iv,0x00,cipher_info->iv_size);
    unsigned char iBuffer[10];
    unsigned char oBuffer[1024];
    size_t ilen, olen;


std::ofstream oFile2;
    oFile2.open("testOut",std::ofstream::out | std::ofstream::trunc | std::ofstream::binary);

        cipher_setkey( &cipher_ctx,key,cipher_info->key_length,POLARSSL_ENCRYPT);
        cipher_set_iv( &cipher_ctx, iv, 16 );
        cipher_reset( &cipher_ctx );
    cipher_update( &cipher_ctx, iBuffer, sizeof(iBuffer), oBuffer, &olen );
    oFile2 << oBuffer;
    cipher_finish( &cipher_ctx, oBuffer, &olen );
    oFile2 << oBuffer;
    oFile2.close();
}

This is the nIST test :

Variable 
Value 
K  00000000000000000000000000000000
P
IV 000000000000000000000000
H 66e94bd4ef8a2c3b884cfa59ca342b2e
Yo 00000000000000000000000000000001
E ( K,Yo) 58e2fccefa7e3061367f1d57a4e7455a
len(A)||len(C)  00000000000000000000000000000000
GHASH (H,A,C) 00000000000000000000000000000000    
C
T 58e2fccefa7e3061367f1d57a4e7455a

(test case No. 1 http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf)

Little Code
  • 1,315
  • 2
  • 16
  • 37

1 Answers1

2

I can see two immediate mistakes:

  1. the plain text size is set to 10 bytes instead of no bytes at all - this makes the ciphertext too large and the authentication tag incorrect;
  2. the IV is 12 bytes set to 0 instead of 16 bytes set to 0 - 12 is the default for GCM mode - this makes the ciphertext if any and authentication tag incorrect.

These issues are in the following lines:

unsigned char iBuffer[10];
...
cipher_update( &cipher_ctx, iBuffer, sizeof(iBuffer), oBuffer, &olen );

and

cipher_set_iv( &cipher_ctx, iv, 16 );

Furthermore, it seems like the API requires you to retrieve the tag separately using the ...write_tag... method. Currently you are only seeing the CTR ciphertext, not the authentication tag.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Thank you for your feedback. I am a little confused by point (1). Surely I need to give the unsigned char a length, no ? – Little Code May 13 '15 at 09:49
  • Indeed, no: the variable P in the NIST test is empty. You could give it `iBuffer[0]` I suppose. – Maarten Bodewes May 13 '15 at 09:57
  • I replaced sizeof(iBuffer) with 0 and that seemed to yield the empty result. But now if I try to use Test Case 2 from the NIST document where K&P is 00000000000000000000000000000000, IV 000000000000000000000000 and result 0388dace60b6a392f328c2b971b2fe78, I get a different result even though I tweaked my code to : unsigned char iBuffer[16]; memset(iBuffer,0x00,cipher_info->key_length/8); cipher_update( &cipher_ctx, iBuffer, 16, oBuffer, &olen );. I'm getting all confused ;-( – Little Code May 13 '15 at 10:19
  • Did test case 1 run ok now? – Maarten Bodewes May 13 '15 at 10:34
  • Actually, I thought it did because I got 0 bytes of Ciphertext back, but If I try to output the Tag to the file by calling cipher_write_tag(&cipher_ctx,tag,16); and then oFile2 << tag; I still end up with a zero byte file instead of one containing the expected tag of 58e2fccefa7e3061367f1d57a4e7455a – Little Code May 13 '15 at 10:46
  • Did you feed it null or a char []? – Maarten Bodewes May 13 '15 at 10:50
  • Just explicitly told it 0 length via cipher_update( &cipher_ctx, iBuffer, 0, oBuffer, &olen ); I also tried with defining unsigned char iBuffer[0]; – Little Code May 13 '15 at 11:02
  • Check the [`...write_tag...` method](https://tls.mbed.org/api/cipher_8h.html#a54a922d31e506aa36dd8ed7798ed2a41)? It seems like this API requires you to write the tag separately. I'll amend my answer (later today). Writing and verifying the tag separately is - in my opinion - a solid API design choice by the way. – Maarten Bodewes May 13 '15 at 11:16
  • yeah, that's wha I was trying with the call to cipher_write_tag, I tried changing 16 to 128 and I still get the wrong tag ( 7cb223efcb0ff020311a f5780004) – Little Code May 13 '15 at 11:20
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/77704/discussion-between-maarten-bodewes-and-little-code). – Maarten Bodewes May 13 '15 at 11:21