[Opentnl-cvs] tnl/libtomcrypt/encauth/gcm gcm_add_aad.c,NONE,1.1 gcm_add_iv.c,NONE,1.1 gcm_done.c,NO
Brought to you by:
mark_frohnmayer,
s_alanet
Update of /cvsroot/opentnl/tnl/libtomcrypt/encauth/gcm In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26694/libtomcrypt/encauth/gcm Added Files: gcm_add_aad.c gcm_add_iv.c gcm_done.c gcm_gf_mult.c gcm_init.c gcm_memory.c gcm_process.c gcm_reset.c gcm_test.c Log Message: Updated to libtomcrypt 1.0.2 Not tested on linux or OS X --- NEW FILE: gcm_process.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ /** @file gcm_process.c GCM implementation, process message data, by Tom St Denis */ #include "tomcrypt.h" #ifdef GCM_MODE /** Process plaintext/ciphertext through GCM @param gcm The GCM state @param pt The plaintext @param ptlen The plaintext length (ciphertext length is the same) @param ct The ciphertext @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) @return CRYPT_OK on success */ int gcm_process(gcm_state *gcm, unsigned char *pt, unsigned long ptlen, unsigned char *ct, int direction) { unsigned long x, y; unsigned char b; int err; LTC_ARGCHK(gcm != NULL); if (ptlen > 0) { LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); } if (gcm->buflen > 16 || gcm->buflen < 0) { return CRYPT_INVALID_ARG; } if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { return err; } /* in AAD mode? */ if (gcm->mode == GCM_MODE_AAD) { /* let's process the AAD */ if (gcm->buflen) { gcm->totlen += gcm->buflen * CONST64(8); gcm_mult_h(gcm, gcm->X); } /* increment counter */ for (y = 15; y >= 12; y--) { if (++gcm->Y[y]) { break; } } /* encrypt the counter */ cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K); gcm->buflen = 0; gcm->mode = GCM_MODE_TEXT; } if (gcm->mode != GCM_MODE_TEXT) { return CRYPT_INVALID_ARG; } x = 0; #ifdef LTC_FAST if (gcm->buflen == 0) { if (direction == GCM_ENCRYPT) { for (x = 0; x < (ptlen & ~15); x += 16) { /* ctr encrypt */ for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *((LTC_FAST_TYPE*)(&ct[x + y])) = *((LTC_FAST_TYPE*)(&pt[x+y])) ^ *((LTC_FAST_TYPE*)(&gcm->buf[y])); *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&ct[x+y])); } /* GMAC it */ gcm->pttotlen += 128; gcm_mult_h(gcm, gcm->X); /* increment counter */ for (y = 15; y >= 12; y--) { if (++gcm->Y[y]) { break; } } cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K); } } else { for (x = 0; x < (ptlen & ~15); x += 16) { /* ctr encrypt */ for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&ct[x+y])); *((LTC_FAST_TYPE*)(&pt[x + y])) = *((LTC_FAST_TYPE*)(&ct[x+y])) ^ *((LTC_FAST_TYPE*)(&gcm->buf[y])); } /* GMAC it */ gcm->pttotlen += 128; gcm_mult_h(gcm, gcm->X); /* increment counter */ for (y = 15; y >= 12; y--) { if (++gcm->Y[y]) { break; } } cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K); } } } #endif /* process text */ for (; x < ptlen; x++) { if (gcm->buflen == 16) { gcm->pttotlen += 128; gcm_mult_h(gcm, gcm->X); /* increment counter */ for (y = 15; y >= 12; y--) { if (++gcm->Y[y]) { break; } } cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K); gcm->buflen = 0; } if (direction == GCM_ENCRYPT) { b = ct[x] = pt[x] ^ gcm->buf[gcm->buflen]; } else { b = ct[x]; pt[x] = ct[x] ^ gcm->buf[gcm->buflen]; } gcm->X[gcm->buflen++] ^= b; } return CRYPT_OK; } #endif --- NEW FILE: gcm_memory.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ /** @file gcm_memory.c GCM implementation, process a packet, by Tom St Denis */ #include "tomcrypt.h" #ifdef GCM_MODE /** Process an entire GCM packet in one call. @param cipher Index of cipher to use @param key The secret key @param keylen The length of the secret key @param IV The initial vector @param IVlen The length of the initial vector @param adata The additional authentication data (header) @param adatalen The length of the adata @param pt The plaintext @param ptlen The length of the plaintext (ciphertext length is the same) @param ct The ciphertext @param tag [out] The MAC tag @param taglen [in/out] The MAC tag length @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) @return CRYPT_OK on success */ int gcm_memory( int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *IV, unsigned long IVlen, const unsigned char *adata, unsigned long adatalen, unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen, int direction) { gcm_state *gcm; int err; if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } if (cipher_descriptor[cipher].accel_gcm_memory != NULL) { cipher_descriptor[cipher].accel_gcm_memory (key, keylen, IV, IVlen, adata, adatalen, pt, ptlen, ct, tag, taglen, direction); return CRYPT_OK; } gcm = XMALLOC(sizeof(*gcm)); if (gcm == NULL) { return CRYPT_MEM; } if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) { goto LTC_ERR; } if ((err = gcm_add_iv(gcm, IV, IVlen)) != CRYPT_OK) { goto LTC_ERR; } if ((err = gcm_add_aad(gcm, adata, adatalen)) != CRYPT_OK) { goto LTC_ERR; } if ((err = gcm_process(gcm, pt, ptlen, ct, direction)) != CRYPT_OK) { goto LTC_ERR; } err = gcm_done(gcm, tag, taglen); LTC_ERR: XFREE(gcm); return err; } #endif --- NEW FILE: gcm_add_aad.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ /** @file gcm_add_aad.c GCM implementation, Add AAD data to the stream, by Tom St Denis */ #include "tomcrypt.h" #ifdef GCM_MODE /** Add AAD to the GCM state @param gcm The GCM state @param adata The additional authentication data to add to the GCM state @param adatalen The length of the AAD data. @return CRYPT_OK on success */ int gcm_add_aad(gcm_state *gcm, const unsigned char *adata, unsigned long adatalen) { unsigned long x, y; int err; LTC_ARGCHK(gcm != NULL); if (adatalen > 0) { LTC_ARGCHK(adata != NULL); } if (gcm->buflen > 16 || gcm->buflen < 0) { return CRYPT_INVALID_ARG; } if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { return err; } /* in IV mode? */ if (gcm->mode == GCM_MODE_IV) { /* let's process the IV */ if (gcm->ivmode || gcm->buflen != 12) { for (x = 0; x < (unsigned long)gcm->buflen; x++) { gcm->X[x] ^= gcm->buf[x]; } if (gcm->buflen) { gcm->totlen += gcm->buflen * CONST64(8); gcm_mult_h(gcm, gcm->X); } /* mix in the length */ zeromem(gcm->buf, 8); STORE64H(gcm->totlen, gcm->buf+8); for (x = 0; x < 16; x++) { gcm->X[x] ^= gcm->buf[x]; } gcm_mult_h(gcm, gcm->X); /* copy counter out */ XMEMCPY(gcm->Y, gcm->X, 16); zeromem(gcm->X, 16); } else { XMEMCPY(gcm->Y, gcm->buf, 12); gcm->Y[12] = 0; gcm->Y[13] = 0; gcm->Y[14] = 0; gcm->Y[15] = 1; } XMEMCPY(gcm->Y_0, gcm->Y, 16); zeromem(gcm->buf, 16); gcm->buflen = 0; gcm->totlen = 0; gcm->mode = GCM_MODE_AAD; } if (gcm->mode != GCM_MODE_AAD || gcm->buflen >= 16) { return CRYPT_INVALID_ARG; } x = 0; #ifdef LTC_FAST if (gcm->buflen == 0) { for (x = 0; x < (adatalen & ~15); x += 16) { for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&adata[x + y])); } gcm_mult_h(gcm, gcm->X); gcm->totlen += 128; } adata += x; } #endif /* start adding AAD data to the state */ for (; x < adatalen; x++) { gcm->X[gcm->buflen++] ^= *adata++; if (gcm->buflen == 16) { /* GF mult it */ gcm_mult_h(gcm, gcm->X); gcm->buflen = 0; gcm->totlen += 128; } } return CRYPT_OK; } #endif --- NEW FILE: gcm_done.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ /** @file gcm_done.c GCM implementation, Terminate the stream, by Tom St Denis */ #include "tomcrypt.h" #ifdef GCM_MODE /** Terminate a GCM stream @param gcm The GCM state @param tag [out] The destination for the MAC tag @param taglen [in/out] The length of the MAC tag @return CRYPT_OK on success */ int gcm_done(gcm_state *gcm, unsigned char *tag, unsigned long *taglen) { unsigned long x; int err; LTC_ARGCHK(gcm != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(taglen != NULL); if (gcm->buflen > 16 || gcm->buflen < 0) { return CRYPT_INVALID_ARG; } if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { return err; } if (gcm->mode != GCM_MODE_TEXT) { return CRYPT_INVALID_ARG; } /* handle remaining ciphertext */ if (gcm->buflen) { gcm->pttotlen += gcm->buflen * CONST64(8); gcm_mult_h(gcm, gcm->X); } /* length */ STORE64H(gcm->totlen, gcm->buf); STORE64H(gcm->pttotlen, gcm->buf+8); for (x = 0; x < 16; x++) { gcm->X[x] ^= gcm->buf[x]; } gcm_mult_h(gcm, gcm->X); /* encrypt original counter */ cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y_0, gcm->buf, &gcm->K); for (x = 0; x < 16 && x < *taglen; x++) { tag[x] = gcm->buf[x] ^ gcm->X[x]; } *taglen = x; cipher_descriptor[gcm->cipher].done(&gcm->K); return CRYPT_OK; } #endif --- NEW FILE: gcm_test.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ /** @file gcm_test.c GCM implementation, testing, by Tom St Denis */ #include "tomcrypt.h" #ifdef GCM_MODE /** Test the GCM code @return CRYPT_OK on success */ int gcm_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { unsigned char K[32]; int keylen; unsigned char P[64]; unsigned long ptlen; unsigned char A[64]; unsigned long alen; unsigned char IV[64]; unsigned long IVlen; unsigned char C[64]; unsigned char T[16]; } tests[] = { /* test case #1 */ { /* key */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 16, /* plaintext */ { 0 }, 0, /* AAD data */ { 0 }, 0, /* IV */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 12, /* ciphertext */ { 0 }, /* tag */ { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a } }, /* test case #2 */ { /* key */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 16, /* PT */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 16, /* ADATA */ { 0 }, 0, /* IV */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 12, /* CT */ { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, /* TAG */ { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf } }, /* test case #3 */ { /* key */ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, 16, /* PT */ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55, }, 64, /* ADATA */ { 0 }, 0, /* IV */ { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }, 12, /* CT */ { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85, }, /* TAG */ { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4, } }, /* test case #4 */ { /* key */ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, 16, /* PT */ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, }, 60, /* ADATA */ { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2, }, 20, /* IV */ { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }, 12, /* CT */ { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, }, /* TAG */ { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47, } }, /* test case #5 */ { /* key */ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, 16, /* PT */ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, }, 60, /* ADATA */ { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2, }, 20, /* IV */ { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, }, 8, /* CT */ { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, 0xc2, 0x3f, 0x45, 0x98, }, /* TAG */ { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb, } }, /* test case #6 */ { /* key */ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, 16, /* PT */ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, }, 60, /* ADATA */ { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2, }, 20, /* IV */ { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, 0xa6, 0x37, 0xb3, 0x9b, }, 60, /* CT */ { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, 0x4c, 0x34, 0xae, 0xe5, }, /* TAG */ { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50, } } /* rest of test cases are the same except AES key size changes... ignored... */ }; int idx, err; unsigned long x, y; gcm_state gcm; unsigned char out[2][64], T[2][16]; /* find aes */ idx = find_cipher("aes"); if (idx == -1) { idx = find_cipher("rijndael"); if (idx == -1) { return CRYPT_NOP; } } for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { y = sizeof(T[0]); if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen, tests[x].IV, tests[x].IVlen, tests[x].A, tests[x].alen, (unsigned char*)tests[x].P, tests[x].ptlen, out[0], T[0], &y, GCM_ENCRYPT)) != CRYPT_OK) { return err; } if (memcmp(out[0], tests[x].C, tests[x].ptlen)) { #if 0 printf("\nCiphertext wrong %lu\n", x); for (y = 0; y < tests[x].ptlen; y++) { printf("%02x", out[0][y] & 255); } printf("\n"); #endif return CRYPT_FAIL_TESTVECTOR; } if (memcmp(T[0], tests[x].T, 16)) { #if 0 printf("\nTag on plaintext wrong %lu\n", x); for (y = 0; y < 16; y++) { printf("%02x", T[0][y] & 255); } printf("\n"); #endif return CRYPT_FAIL_TESTVECTOR; } y = sizeof(T[1]); if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen, tests[x].IV, tests[x].IVlen, tests[x].A, tests[x].alen, out[1], tests[x].ptlen, out[0], T[1], &y, GCM_DECRYPT)) != CRYPT_OK) { return err; } if (memcmp(out[1], tests[x].P, tests[x].ptlen)) { #if 0 printf("\nplaintext wrong %lu\n", x); for (y = 0; y < tests[x].ptlen; y++) { printf("%02x", out[0][y] & 255); } printf("\n"); #endif return CRYPT_FAIL_TESTVECTOR; } if (memcmp(T[1], tests[x].T, 16)) { #if 0 printf("\nTag on ciphertext wrong %lu\n", x); for (y = 0; y < 16; y++) { printf("%02x", T[1][y] & 255); } printf("\n"); #endif return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif --- NEW FILE: gcm_add_iv.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ /** @file gcm_add_iv.c GCM implementation, add IV data to the state, by Tom St Denis */ #include "tomcrypt.h" #ifdef GCM_MODE /** Add IV data to the GCM state @param gcm The GCM state @param IV The initial value data to add @param IVlen The length of the IV @return CRYPT_OK on success */ int gcm_add_iv(gcm_state *gcm, const unsigned char *IV, unsigned long IVlen) { unsigned long x, y; int err; LTC_ARGCHK(gcm != NULL); if (IVlen > 0) { LTC_ARGCHK(IV != NULL); } /* must be in IV mode */ if (gcm->mode != GCM_MODE_IV) { return CRYPT_INVALID_ARG; } if (gcm->buflen >= 16 || gcm->buflen < 0) { return CRYPT_INVALID_ARG; } if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { return err; } /* trip the ivmode flag */ if (IVlen + gcm->buflen > 12) { gcm->ivmode |= 1; } x = 0; #ifdef LTC_FAST if (gcm->buflen == 0) { for (x = 0; x < (IVlen & ~15); x += 16) { for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&IV[x + y])); } gcm_mult_h(gcm, gcm->X); gcm->totlen += 128; } IV += x; } #endif /* start adding IV data to the state */ for (; x < IVlen; x++) { gcm->buf[gcm->buflen++] = *IV++; if (gcm->buflen == 16) { /* GF mult it */ for (y = 0; y < 16; y++) { gcm->X[y] ^= gcm->buf[y]; } gcm_mult_h(gcm, gcm->X); gcm->buflen = 0; gcm->totlen += 128; } } return CRYPT_OK; } #endif --- NEW FILE: gcm_reset.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ /** @file gcm_reset.c GCM implementation, reset a used state so it can accept IV data, by Tom St Denis */ #include "tomcrypt.h" #ifdef GCM_MODE /** Reset a GCM state to as if you just called gcm_init(). This saves the initialization time. @param gcm The GCM state to reset @return CRYPT_OK on success */ int gcm_reset(gcm_state *gcm) { LTC_ARGCHK(gcm != NULL); zeromem(gcm->buf, sizeof(gcm->buf)); zeromem(gcm->X, sizeof(gcm->X)); gcm->mode = GCM_MODE_IV; gcm->ivmode = 0; gcm->buflen = 0; gcm->totlen = 0; gcm->pttotlen = 0; return CRYPT_OK; } #endif --- NEW FILE: gcm_gf_mult.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ /** @file gcm_gf_mult.c GCM implementation, initialize state, by Tom St Denis */ #include "tomcrypt.h" #ifdef GCM_MODE /* right shift */ static void gcm_rightshift(unsigned char *a) { int x; for (x = 15; x > 0; x--) { a[x] = (a[x]>>1) | ((a[x-1]<<7)&0x80); } a[0] >>= 1; } /* c = b*a */ static const unsigned char mask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; static const unsigned char poly[] = { 0x00, 0xE1 }; /** GCM GF multiplier (internal use only) @param a First value @param b Second value @param c Destination for a * b */ void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c) { unsigned char Z[16], V[16]; unsigned x, y, z; zeromem(Z, 16); XMEMCPY(V, a, 16); for (x = 0; x < 128; x++) { if (b[x>>3] & mask[x&7]) { for (y = 0; y < 16; y++) { Z[y] ^= V[y]; } } z = V[15] & 0x01; gcm_rightshift(V); V[0] ^= poly[z]; } XMEMCPY(c, Z, 16); } /** GCM multiply by H @param gcm The GCM state which holds the H value @param I The value to multiply H by */ void gcm_mult_h(gcm_state *gcm, unsigned char *I) { unsigned char T[16]; #ifdef GCM_TABLES int x, y; XMEMCPY(T, &gcm->PC[0][I[0]][0], 16); for (x = 1; x < 16; x++) { #ifdef LTC_FAST for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *((LTC_FAST_TYPE *)(T + y)) ^= *((LTC_FAST_TYPE *)(&gcm->PC[x][I[x]][y])); } #else for (y = 0; y < 16; y++) { T[y] ^= gcm->PC[x][I[x]][y]; } #endif } #else gcm_gf_mult(gcm->H, I, T); #endif XMEMCPY(I, T, 16); } #endif --- NEW FILE: gcm_init.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ /** @file gcm_init.c GCM implementation, initialize state, by Tom St Denis */ #include "tomcrypt.h" #ifdef GCM_MODE /** Initialize a GCM state @param gcm The GCM state to initialize @param cipher The index of the cipher to use @param key The secret key @param keylen The length of the secret key @return CRYPT_OK on success */ int gcm_init(gcm_state *gcm, int cipher, const unsigned char *key, int keylen) { int err; unsigned char B[16]; #ifdef GCM_TABLES int x, y; #endif LTC_ARGCHK(gcm != NULL); LTC_ARGCHK(key != NULL); #ifdef LTC_FAST if (16 % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif /* is cipher valid? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } if (cipher_descriptor[cipher].block_length != 16) { return CRYPT_INVALID_CIPHER; } /* schedule key */ if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &gcm->K)) != CRYPT_OK) { return err; } /* H = E(0) */ zeromem(B, 16); cipher_descriptor[cipher].ecb_encrypt(B, gcm->H, &gcm->K); /* setup state */ zeromem(gcm->buf, sizeof(gcm->buf)); zeromem(gcm->X, sizeof(gcm->X)); gcm->cipher = cipher; gcm->mode = GCM_MODE_IV; gcm->ivmode = 0; gcm->buflen = 0; gcm->totlen = 0; gcm->pttotlen = 0; #ifdef GCM_TABLES /* setup tables */ zeromem(B, 16); for (x = 0; x < 16; x++) { for (y = 0; y < 256; y++) { B[x] = y; gcm_gf_mult(gcm->H, B, &gcm->PC[x][y][0]); } B[x] = 0; } #endif return CRYPT_OK; } #endif |