X-Git-Url: http://wagner.pp.ru/gitweb/?a=blobdiff_plain;ds=sidebyside;f=test_mgm.c;fp=test_mgm.c;h=d6b5a740484e231dc42a7dd5abd3be592908d90c;hb=41bff5cad003c9239623e556e69a281b2a8e80b1;hp=0000000000000000000000000000000000000000;hpb=140770d1dfcda28d8cf5b0e53d58b04f1fde0c6a;p=openssl-gost%2Fengine.git diff --git a/test_mgm.c b/test_mgm.c new file mode 100644 index 0000000..d6b5a74 --- /dev/null +++ b/test_mgm.c @@ -0,0 +1,268 @@ +# include +# include +# include +# include +#include +#include + +static void hexdump(FILE *f, const char *title, const unsigned char *s, int l) +{ + int n = 0; + + fprintf(f, "%s", title); + for (; n < l; ++n) { + if ((n % 16) == 0) + fprintf(f, "\n%04x", n); + fprintf(f, " %02x", s[n]); + } + fprintf(f, "\n"); +} + +void grasshopper_mgm_big() +{ + const unsigned char gh_key[] = { +0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, +0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + }; + + const unsigned char gh_nonce[] = { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88 + }; + + const unsigned char gh_adata[] = { + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0xEA, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05 + }; + + const unsigned char gh_pdata[] = { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A, 0x00, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A, 0x00, 0x11, + 0xAA, 0xBB, 0xCC + }; + + const unsigned char etalon_tag[] = { + 0xCF, 0x5D, 0x65, 0x6F, 0x40, 0xC3, 0x4F, 0x5C, 0x46, 0xE8, 0xBB, 0x0E, 0x29, 0xFC, 0xDB, 0x4C + }; + + unsigned char tag[16]; + unsigned char gh_cdata[sizeof(gh_pdata)]; + unsigned char *pcdata = gh_cdata; + + int asize = sizeof(gh_adata); + int psize = sizeof(gh_pdata); + int fsize = 0; + + const EVP_CIPHER *ciph; + EVP_CIPHER_CTX *enc = NULL; + + int i; + + ciph = EVP_get_cipherbynid(NID_kuznyechik_mgm); + if (ciph == NULL) { + fprintf(stderr, "Could not obtain cipher"); + return; + } + + enc = EVP_CIPHER_CTX_new(); + EVP_EncryptInit_ex(enc, ciph, NULL, gh_key, gh_nonce); + + EVP_EncryptUpdate(enc, NULL, &asize, gh_adata, sizeof(gh_adata)); + EVP_EncryptUpdate(enc, gh_cdata, &psize, gh_pdata, sizeof(gh_pdata)); + EVP_EncryptFinal_ex(enc, NULL, &fsize); + + EVP_CIPHER_CTX_ctrl(enc, EVP_CTRL_AEAD_GET_TAG, 16, tag); + + if (memcmp (tag, etalon_tag, 16)) { + fprintf(stderr, "Shit happens!\n"); + hexdump(stderr, "Etalon tag", etalon_tag, 16); + hexdump(stderr, "Got tag", tag, 16); + return; + } + fprintf(stderr, "OK - big chunks!\n"); + EVP_CIPHER_CTX_free(enc); + + fprintf(stderr, "================ \n"); +} + +void grasshopper_mgm_small() +{ + const unsigned char gh_key[] = { +0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, +0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + }; + + const unsigned char gh_nonce[] = { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88 + }; + + const unsigned char gh_adata[] = { + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0xEA, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05 + }; + + const unsigned char gh_pdata[] = { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A, 0x00, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A, 0x00, 0x11, + 0xAA, 0xBB, 0xCC + }; + + const unsigned char etalon_tag[] = { + 0xCF, 0x5D, 0x65, 0x6F, 0x40, 0xC3, 0x4F, 0x5C, 0x46, 0xE8, 0xBB, 0x0E, 0x29, 0xFC, 0xDB, 0x4C + }; + + unsigned char tag[16]; + unsigned char gh_cdata[sizeof(gh_pdata)]; + unsigned char *pcdata = gh_cdata; + + int asize = sizeof(gh_adata); + int psize = sizeof(gh_pdata); + int fsize = 0; + + const EVP_CIPHER *ciph; + EVP_CIPHER_CTX *enc = NULL; + + int i; + + ciph = EVP_get_cipherbynid(NID_kuznyechik_mgm); + if (ciph == NULL) { + fprintf(stderr, "Could not obtain cipher"); + return; + } + + enc = EVP_CIPHER_CTX_new(); + EVP_EncryptInit_ex(enc, ciph, NULL, gh_key, gh_nonce); + + for (i = 0; i < sizeof(gh_adata); i++) + { + asize = 1; + EVP_EncryptUpdate(enc, NULL, &asize, gh_adata+i, 1); + } + + for (i = 0; i < sizeof(gh_pdata); i++) + { + psize = 1; + EVP_EncryptUpdate(enc, pcdata, &psize, gh_pdata+i, 1); + pcdata += psize; + } + + EVP_EncryptFinal_ex(enc, NULL, &fsize); + + EVP_CIPHER_CTX_ctrl(enc, EVP_CTRL_AEAD_GET_TAG, 16, tag); + + if (memcmp (tag, etalon_tag, 16)) { + fprintf(stderr, "Shit happens!\n"); + hexdump(stderr, "Etalon tag", etalon_tag, 16); + hexdump(stderr, "Got tag", tag, 16); + return; + } + fprintf(stderr, "OK - small chunks!\n"); + EVP_CIPHER_CTX_free(enc); + +} + +#define L_ENDIAN 1 +static void gf128_mul_uint64(uint64_t *z, uint64_t *x, uint64_t *y) +{ + int i = 0, n = 0; + uint64_t t, s0, s1; + + BUF_reverse((unsigned char *)x, NULL, 16); + BUF_reverse((unsigned char *)y, NULL, 16); + +#ifdef L_ENDIAN + s0 = x[0]; + s1 = x[1]; +#else + s0 = bswap_64(x[0]); + s1 = bswap_64(x[1]); +#endif + + memset(z, 0, sizeof(uint64_t)*2); + + /* lower half */ +#ifdef L_ENDIAN + t = y[0]; +#else + t = bswap_64(y[0]); +#endif + + for( i = 0; i < 64; i++ ) { + if( t&0x1 ) { z[0] ^= s0; z[1] ^= s1; } + t >>= 1; + n = s1 >> 63; + s1 <<= 1; s1 ^= ( s0 >> 63 ); s0 <<= 1; + if(n) s0 ^= 0x87; + } + + /* upper half */ +#ifdef L_ENDIAN + t = y[1]; +#else + t = bswap_64(y[1]); +#endif + + for( i = 0; i < 63; i++ ) { + if( t&0x1 ) { z[0] ^= s0; z[1] ^= s1; } + t >>= 1; + n = s1 >> 63; + s1 <<= 1; s1 ^= ( s0 >> 63 ); s0 <<= 1; + if( n ) s0 ^= 0x87; + } + + if( t&0x1 ) { + z[0] ^= s0; + z[1] ^= s1; + } +#ifndef L_ENDIAN + z[0] = bswap_64(z[0]); + z[1] = bswap_64(z[1]); +#endif + BUF_reverse((unsigned char *)z, NULL, 16); +} + +void gf_mul(void) +{ + unsigned char H[16] = { + 0x8D, 0xB1, 0x87, 0xD6, 0x53, 0x83, 0x0E, 0xA4, 0xBC, 0x44, 0x64, 0x76, 0x95, 0x2C, 0x30, 0x0B + }; + + unsigned char A[16] = { + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 + }; + + unsigned char etalon[16] = { + 0x4C, 0xF4, 0x27, 0xF4, 0xAD, 0xB7, 0x5C, 0xF4, 0xC0, 0xDA, 0x39, 0xD5, 0xAB, 0x48, 0xCF, 0x38 + }; + + unsigned char result_bd[16]; + gf128_mul_uint64((uint64_t *)result_bd, (uint64_t *)H, (uint64_t *)A); + + + hexdump(stderr, "Etalon", etalon, 16); + + if (memcmp (etalon, result_bd, 16)) { + fprintf(stderr, "Shit happens - BD!\n"); + hexdump(stderr, "Result - BD", result_bd, 16); + } else + fprintf(stderr, "OK - BD!\n"); + + return; +} + +int main(void) +{ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL); + + gf_mul(); + grasshopper_mgm_big(); + grasshopper_mgm_small(); + ERR_print_errors_fp(stderr); + + return 0; +}