diff options
| author | Greg Hudson <ghudson@mit.edu> | 2009-10-19 20:04:21 +0000 |
|---|---|---|
| committer | Greg Hudson <ghudson@mit.edu> | 2009-10-19 20:04:21 +0000 |
| commit | e6b93b7dd43bb765900b2db71641479b597844da (patch) | |
| tree | 2b6da09e37da6ca699a8cb43c87e8a4218132254 /src/lib/crypto/crypto_tests | |
| parent | 04a5d19e61bedbb1da4db52334c00f7a54a9d5a8 (diff) | |
| download | krb5-e6b93b7dd43bb765900b2db71641479b597844da.tar.gz krb5-e6b93b7dd43bb765900b2db71641479b597844da.tar.xz krb5-e6b93b7dd43bb765900b2db71641479b597844da.zip | |
Implement new APIs to allow improved crypto performance
Merge branches/enc-perf to trunk. Adds the krb5_key opaque type, the
krb5_k_* APIs to use them, and caching of derived keys when krb5_k_*
functions are used. Updates the krb5 auth context and GSS id-rec to
use krb5_keys.
ticket: 6576
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@22944 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/crypto/crypto_tests')
| -rw-r--r-- | src/lib/crypto/crypto_tests/Makefile.in | 4 | ||||
| -rw-r--r-- | src/lib/crypto/crypto_tests/aes-test.c | 6 | ||||
| -rw-r--r-- | src/lib/crypto/crypto_tests/t_cksum.c | 9 | ||||
| -rw-r--r-- | src/lib/crypto/crypto_tests/t_cts.c | 23 | ||||
| -rw-r--r-- | src/lib/crypto/crypto_tests/t_encrypt.c | 128 | ||||
| -rw-r--r-- | src/lib/crypto/crypto_tests/t_hmac.c | 5 | ||||
| -rw-r--r-- | src/lib/crypto/crypto_tests/t_kperf.c | 119 |
7 files changed, 239 insertions, 55 deletions
diff --git a/src/lib/crypto/crypto_tests/Makefile.in b/src/lib/crypto/crypto_tests/Makefile.in index ab6ebfa4c6..7b240d5783 100644 --- a/src/lib/crypto/crypto_tests/Makefile.in +++ b/src/lib/crypto/crypto_tests/Makefile.in @@ -33,6 +33,7 @@ EXTRADEPSRCS=\ $(srcdir)/t_shs3.c \ $(srcdir)/t_shs.c \ $(srcdir)/t_verify.c \ + $(srcdir)/t_kperf.c \ $(srcdir)/ytest.c ##DOSBUILDTOP = ..\..\.. @@ -149,6 +150,9 @@ t_shs: t_shs.o $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB) t_shs3: t_shs3.o $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB) $(CC_LINK) -o t_shs3 t_shs3.o $(SUPPORT_LIB) $(CRYPTO_DEPLIB) +t_kperf: t_kperf.o $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB) + $(CC_LINK) -o t_kperf t_kperf.o $(SUPPORT_LIB) $(CRYPTO_DEPLIB) + ytest: ytest.o shs.o $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB) $(CC_LINK) -o ytest ytest.o $(SUPPORT_LIB) $(CRYPTO_DEPLIB) diff --git a/src/lib/crypto/crypto_tests/aes-test.c b/src/lib/crypto/crypto_tests/aes-test.c index c05fd26e3c..8999bd7578 100644 --- a/src/lib/crypto/crypto_tests/aes-test.c +++ b/src/lib/crypto/crypto_tests/aes-test.c @@ -50,7 +50,11 @@ static void init() } static void enc() { - krb5int_aes_encrypt(&enc_key, &ivec, &in, &out); + krb5_key key; + + krb5_k_create_key(NULL, &enc_key, &key); + krb5int_aes_encrypt(key, &ivec, &in, &out); + krb5_k_free_key(NULL, key); } static void hexdump(const char *label, const char *cp, int len) diff --git a/src/lib/crypto/crypto_tests/t_cksum.c b/src/lib/crypto/crypto_tests/t_cksum.c index 98187f7f16..2b53651197 100644 --- a/src/lib/crypto/crypto_tests/t_cksum.c +++ b/src/lib/crypto/crypto_tests/t_cksum.c @@ -75,6 +75,7 @@ main(argc, argv) krb5_boolean valid; size_t length; krb5_keyblock keyblock; + krb5_key key; krb5_error_code kret=0; krb5_data plaintext, newstyle_checksum; @@ -89,6 +90,8 @@ main(argc, argv) keyblock.length = sizeof(testkey); keyblock.contents = testkey; + krb5_k_create_key(NULL, &keyblock, &key); + length = khp.hashsize; newstyle_checksum.length = length; @@ -102,13 +105,13 @@ main(argc, argv) plaintext.length = strlen(argv[msgindex]); plaintext.data = argv[msgindex]; - if ((kret = (*(khp.hash))(&keyblock, 0, 0, &plaintext, &newstyle_checksum))) { + if ((kret = (*(khp.hash))(key, 0, 0, &plaintext, &newstyle_checksum))) { printf("krb5_calculate_checksum choked with %d\n", kret); break; } print_checksum("correct", MD, argv[msgindex], &newstyle_checksum); - if ((kret = (*(khp.verify))(&keyblock, 0, 0, &plaintext, &newstyle_checksum, + if ((kret = (*(khp.verify))(key, 0, 0, &plaintext, &newstyle_checksum, &valid))) { printf("verify on new checksum choked with %d\n", kret); break; @@ -120,7 +123,7 @@ main(argc, argv) printf("Verify succeeded for \"%s\"\n", argv[msgindex]); newstyle_checksum.data[0]++; - if ((kret = (*(khp.verify))(&keyblock, 0, 0, &plaintext, &newstyle_checksum, + if ((kret = (*(khp.verify))(key, 0, 0, &plaintext, &newstyle_checksum, &valid))) { printf("verify on new checksum choked with %d\n", kret); break; diff --git a/src/lib/crypto/crypto_tests/t_cts.c b/src/lib/crypto/crypto_tests/t_cts.c index aef813273f..fab5b27071 100644 --- a/src/lib/crypto/crypto_tests/t_cts.c +++ b/src/lib/crypto/crypto_tests/t_cts.c @@ -114,15 +114,12 @@ static void test_cts() "I would like the General Gau's Chicken, please, and wonton soup."; static const unsigned char aeskey[16] = "chicken teriyaki"; static const int lengths[] = { 17, 31, 32, 47, 48, 64 }; - extern krb5_error_code krb5int_aes_encrypt(const krb5_keyblock *, - const krb5_data *, - const krb5_data *, - krb5_data *); int i; char outbuf[64], encivbuf[16], decivbuf[16], outbuf2[64]; krb5_data in, out, enciv, deciv, out2; - krb5_keyblock key; + krb5_keyblock keyblock; + krb5_key key; krb5_error_code err; in.data = input; @@ -131,11 +128,17 @@ static void test_cts() enciv.length = deciv.length = 16; enciv.data = encivbuf; deciv.data = decivbuf; - key.contents = aeskey; - key.length = 16; + keyblock.contents = aeskey; + keyblock.length = 16; + + err = krb5_k_create_key(NULL, &keyblock, &key); + if (err) { + printf("error %ld from krb5_k_create_key\n", (long)err); + exit(1); + } memset(enciv.data, 0, 16); - printk("AES 128-bit key", &key); + printk("AES 128-bit key", &keyblock); for (i = 0; i < sizeof(lengths)/sizeof(lengths[0]); i++) { memset(enciv.data, 0, 16); memset(deciv.data, 0, 16); @@ -143,7 +146,7 @@ static void test_cts() printf("\n"); in.length = out.length = lengths[i]; printd("IV", &enciv); - err = krb5int_aes_encrypt(&key, &enciv, &in, &out); + err = krb5int_aes_encrypt(key, &enciv, &in, &out); if (err) { printf("error %ld from krb5int_aes_encrypt\n", (long)err); exit(1); @@ -152,7 +155,7 @@ static void test_cts() printd("Output", &out); printd("Next IV", &enciv); out2.length = out.length; - err = krb5int_aes_decrypt(&key, &deciv, &out, &out2); + err = krb5int_aes_decrypt(key, &deciv, &out, &out2); if (err) { printf("error %ld from krb5int_aes_decrypt\n", (long)err); exit(1); diff --git a/src/lib/crypto/crypto_tests/t_encrypt.c b/src/lib/crypto/crypto_tests/t_encrypt.c index 739c6d3e0b..aac31fb21f 100644 --- a/src/lib/crypto/crypto_tests/t_encrypt.c +++ b/src/lib/crypto/crypto_tests/t_encrypt.c @@ -78,12 +78,14 @@ int main () { krb5_context context = 0; - krb5_data in, in2, out, out2, check, check2, state; + krb5_data in, in2, out, out2, check, check2, state, signdata; krb5_crypto_iov iov[5]; - int i; + int i, j, pos; + unsigned int dummy; size_t len; krb5_enc_data enc_out, enc_out2; - krb5_keyblock *key; + krb5_keyblock *keyblock; + krb5_key key; memset(iov, 0, sizeof(iov)); @@ -94,6 +96,8 @@ main () test ("Seeding random number generator", krb5_c_random_seed (context, &in)); + + /* Set up output buffers. */ out.data = malloc(2048); out2.data = malloc(2048); check.data = malloc(2048); @@ -107,39 +111,67 @@ main () out2.length = 2048; check.length = 2048; check2.length = 2048; + for (i = 0; interesting_enctypes[i]; i++) { krb5_enctype enctype = interesting_enctypes [i]; + printf ("Testing enctype %d\n", enctype); test ("Initializing a keyblock", - krb5_init_keyblock (context, enctype, 0, &key)); - test ("Generating random key", - krb5_c_make_random_key (context, enctype, key)); + krb5_init_keyblock (context, enctype, 0, &keyblock)); + test ("Generating random keyblock", + krb5_c_make_random_key (context, enctype, keyblock)); + test ("Creating opaque key from keyblock", + krb5_k_create_key (context, keyblock, &key)); + enc_out.ciphertext = out; enc_out2.ciphertext = out2; /* We use an intermediate `len' because size_t may be different size than `int' */ - krb5_c_encrypt_length (context, key->enctype, in.length, &len); + krb5_c_encrypt_length (context, keyblock->enctype, in.length, &len); enc_out.ciphertext.length = len; - test ("Encrypting", - krb5_c_encrypt (context, key, 7, 0, &in, &enc_out)); + + /* Encrypt, decrypt, and see if we got the plaintext back again. */ + test ("Encrypting (c)", + krb5_c_encrypt (context, keyblock, 7, 0, &in, &enc_out)); test ("Decrypting", - krb5_c_decrypt (context, key, 7, 0, &enc_out, &check)); + krb5_c_decrypt (context, keyblock, 7, 0, &enc_out, &check)); test ("Comparing", compare_results (&in, &check)); - if ( krb5_c_crypto_length(context, key->enctype, KRB5_CRYPTO_TYPE_HEADER, &len) == 0 ){ - /* We support iov/aead*/ - int j, pos; - krb5_data signdata; - signdata.magic = KV5M_DATA; - signdata.data = (char *) "This should be signed"; - signdata.length = strlen(signdata.data); + + /* Try again with the opaque-key-using variants. */ + memset(out.data, 0, out.length); + test ("Encrypting (k)", + krb5_k_encrypt (context, key, 7, 0, &in, &enc_out)); + test ("Decrypting", + krb5_k_decrypt (context, key, 7, 0, &enc_out, &check)); + test ("Comparing", compare_results (&in, &check)); + + /* Check if this enctype supports IOV encryption. */ + if ( krb5_c_crypto_length(context, keyblock->enctype, + KRB5_CRYPTO_TYPE_HEADER, &dummy) == 0 ){ + /* Set up iovecs for stream decryption. */ + memcpy(out2.data, enc_out.ciphertext.data, enc_out.ciphertext.length); iov[0].flags= KRB5_CRYPTO_TYPE_STREAM; + iov[0].data.data = out2.data; + iov[0].data.length = enc_out.ciphertext.length; iov[1].flags = KRB5_CRYPTO_TYPE_DATA; - iov[0].data = enc_out.ciphertext; - iov[1].data = out; - test("IOV stream decrypting", - krb5_c_decrypt_iov( context, key, 7, 0, iov, 2)); + + /* Decrypt the encrypted data from above and check it. */ + test("IOV stream decrypting (c)", + krb5_c_decrypt_iov( context, keyblock, 7, 0, iov, 2)); test("Comparing results", compare_results(&in, &iov[1].data)); + + /* Try again with the opaque-key-using variant. */ + memcpy(out2.data, enc_out.ciphertext.data, enc_out.ciphertext.length); + test("IOV stream decrypting (k)", + krb5_k_decrypt_iov( context, key, 7, 0, iov, 2)); + test("Comparing results", + compare_results(&in, &iov[1].data)); + + /* Set up iovecs for AEAD encryption. */ + signdata.magic = KV5M_DATA; + signdata.data = (char *) "This should be signed"; + signdata.length = strlen(signdata.data); iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; iov[1].flags = KRB5_CRYPTO_TYPE_DATA; iov[1].data = in; /*We'll need to copy memory before encrypt*/ @@ -147,8 +179,10 @@ main () iov[2].data = signdata; iov[3].flags = KRB5_CRYPTO_TYPE_PADDING; iov[4].flags = KRB5_CRYPTO_TYPE_TRAILER; + + /* "Allocate" data for the iovec buffers from the "out" buffer. */ test("Setting up iov lengths", - krb5_c_crypto_length_iov(context, key->enctype, iov, 5)); + krb5_c_crypto_length_iov(context, keyblock->enctype, iov, 5)); for (j=0,pos=0; j <= 4; j++ ){ if (iov[j].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) continue; @@ -157,56 +191,70 @@ main () } assert (iov[1].data.length == in.length); memcpy(iov[1].data.data, in.data, in.length); - test("iov encrypting", - krb5_c_encrypt_iov(context, key, 7, 0, iov, 5)); + + /* Encrypt and decrypt in place, and check the result. */ + test("iov encrypting (c)", + krb5_c_encrypt_iov(context, keyblock, 7, 0, iov, 5)); assert(iov[1].data.length == in.length); test("iov decrypting", - krb5_c_decrypt_iov(context, key, 7, 0, iov, 5)); + krb5_c_decrypt_iov(context, keyblock, 7, 0, iov, 5)); test("Comparing results", compare_results(&in, &iov[1].data)); + /* Try again with opaque-key-using variants. */ + test("iov encrypting (k)", + krb5_k_encrypt_iov(context, key, 7, 0, iov, 5)); + assert(iov[1].data.length == in.length); + test("iov decrypting", + krb5_k_decrypt_iov(context, key, 7, 0, iov, 5)); + test("Comparing results", + compare_results(&in, &iov[1].data)); } + enc_out.ciphertext.length = out.length; check.length = 2048; + test ("init_state", - krb5_c_init_state (context, key, 7, &state)); + krb5_c_init_state (context, keyblock, 7, &state)); test ("Encrypting with state", - krb5_c_encrypt (context, key, 7, &state, &in, &enc_out)); + krb5_c_encrypt (context, keyblock, 7, &state, &in, &enc_out)); test ("Encrypting again with state", - krb5_c_encrypt (context, key, 7, &state, &in2, &enc_out2)); + krb5_c_encrypt (context, keyblock, 7, &state, &in2, &enc_out2)); test ("free_state", - krb5_c_free_state (context, key, &state)); + krb5_c_free_state (context, keyblock, &state)); test ("init_state", - krb5_c_init_state (context, key, 7, &state)); + krb5_c_init_state (context, keyblock, 7, &state)); test ("Decrypting with state", - krb5_c_decrypt (context, key, 7, &state, &enc_out, &check)); + krb5_c_decrypt (context, keyblock, 7, &state, &enc_out, &check)); test ("Decrypting again with state", - krb5_c_decrypt (context, key, 7, &state, &enc_out2, &check2)); + krb5_c_decrypt (context, keyblock, 7, &state, &enc_out2, &check2)); test ("free_state", - krb5_c_free_state (context, key, &state)); + krb5_c_free_state (context, keyblock, &state)); test ("Comparing", compare_results (&in, &check)); test ("Comparing", compare_results (&in2, &check2)); - krb5_free_keyblock (context, key); + + krb5_free_keyblock (context, keyblock); + krb5_k_free_key (context, key); } /* Test the RC4 decrypt fallback from key usage 9 to 8. */ test ("Initializing an RC4 keyblock", - krb5_init_keyblock (context, ENCTYPE_ARCFOUR_HMAC, 0, &key)); + krb5_init_keyblock (context, ENCTYPE_ARCFOUR_HMAC, 0, &keyblock)); test ("Generating random RC4 key", - krb5_c_make_random_key (context, ENCTYPE_ARCFOUR_HMAC, key)); + krb5_c_make_random_key (context, ENCTYPE_ARCFOUR_HMAC, keyblock)); enc_out.ciphertext = out; - krb5_c_encrypt_length (context, key->enctype, in.length, &len); + krb5_c_encrypt_length (context, keyblock->enctype, in.length, &len); enc_out.ciphertext.length = len; check.length = 2048; test ("Encrypting with RC4 key usage 8", - krb5_c_encrypt (context, key, 8, 0, &in, &enc_out)); + krb5_c_encrypt (context, keyblock, 8, 0, &in, &enc_out)); test ("Decrypting with RC4 key usage 9", - krb5_c_decrypt (context, key, 9, 0, &enc_out, &check)); + krb5_c_decrypt (context, keyblock, 9, 0, &enc_out, &check)); test ("Comparing", compare_results (&in, &check)); - krb5_free_keyblock (context, key); + krb5_free_keyblock (context, keyblock); free(out.data); free(out2.data); free(check.data); diff --git a/src/lib/crypto/crypto_tests/t_hmac.c b/src/lib/crypto/crypto_tests/t_hmac.c index bf629c359f..30830d6173 100644 --- a/src/lib/crypto/crypto_tests/t_hmac.c +++ b/src/lib/crypto/crypto_tests/t_hmac.c @@ -98,6 +98,7 @@ static krb5_error_code hmac1(const struct krb5_hash_provider *h, char tmp[40]; size_t blocksize, hashsize; krb5_error_code err; + krb5_key k; printk(" test key", key); blocksize = h->blocksize; @@ -120,7 +121,9 @@ static krb5_error_code hmac1(const struct krb5_hash_provider *h, printk(" pre-hashed key", key); } printd(" hmac input", in); - err = krb5_hmac(h, key, 1, in, out); + krb5_k_create_key(NULL, key, &k); + err = krb5_hmac(h, k, 1, in, out); + krb5_k_free_key(NULL, k); if (err == 0) printd(" hmac output", out); return err; diff --git a/src/lib/crypto/crypto_tests/t_kperf.c b/src/lib/crypto/crypto_tests/t_kperf.c new file mode 100644 index 0000000000..f56aa3cd15 --- /dev/null +++ b/src/lib/crypto/crypto_tests/t_kperf.c @@ -0,0 +1,119 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/crypto/crypto_tests/t_kperf.c + * + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This file contains a harness to measure the performance improvement + * of using the the krb5_k functions (which cache derived keys) over + * the equivalent krb5_c functions which do not. Sample usages: + * + * ./t_kperf ce aes128-cts 10 100000 + * ./t_kperf kv aes256-cts 1024 10000 + * + * The first usage encrypts ('e') a hundred thousand ten-byte blobs + * with aes128-cts, using the non-caching APIs ('c'). The second + * usage verifies ('v') ten thousand checksums over 1K blobs with the + * first available keyed checksum type for aes256-cts, using the + * caching APIs ('k'). Run commands under "time" to measure how much + * time is used by the operations. + */ + +#include "k5-int.h" + +int +main(int argc, char **argv) +{ + krb5_keyblock kblock; + krb5_key key; + krb5_enctype enctype; + krb5_cksumtype cktype, *cktypelist; + int blocksize, num_blocks, intf, op, i; + unsigned int count; + size_t outlen, cklen; + krb5_data block; + krb5_enc_data outblock; + krb5_checksum sum; + krb5_boolean val; + + if (argc != 5) { + fprintf(stderr, "Usage: t_kperf {c|k}{e|d|m|v} type size nblocks\n"); + exit(1); + } + intf = argv[1][0]; + assert(intf == 'c' || intf =='k'); + op = argv[1][1]; + assert(krb5_string_to_enctype(argv[2], &enctype) == 0); + blocksize = atoi(argv[3]); + num_blocks = atoi(argv[4]); + + /* Pick the first available keyed checksum type. */ + krb5_c_keyed_checksum_types(NULL, enctype, &count, &cktypelist); + assert(count > 0); + cktype = cktypelist[0]; + + block.data = "notrandom"; + block.length = 9; + krb5_c_random_seed(NULL, &block); + + krb5_c_make_random_key(NULL, enctype, &kblock); + krb5_k_create_key(NULL, &kblock, &key); + + block.length = blocksize; + block.data = calloc(1, blocksize); + + krb5_c_encrypt_length(NULL, enctype, blocksize, &outlen); + outblock.enctype = enctype; + outblock.ciphertext.length = outlen; + outblock.ciphertext.data = calloc(1, outlen); + + krb5_c_checksum_length(NULL, cktype, &cklen); + sum.checksum_type = cktype; + sum.length = cklen; + sum.contents = calloc(1, cklen); + + for (i = 0; i < num_blocks; i++) { + if (intf == 'c') { + if (op == 'e') + krb5_c_encrypt(NULL, &kblock, 0, NULL, &block, &outblock); + else if (op == 'd') + krb5_c_decrypt(NULL, &kblock, 0, NULL, &outblock, &block); + else if (op == 'm') + krb5_c_make_checksum(NULL, cktype, &kblock, 0, &block, &sum); + else if (op == 'v') + krb5_c_verify_checksum(NULL, &kblock, 0, &block, &sum, &val); + } else { + if (op == 'e') + krb5_k_encrypt(NULL, key, 0, NULL, &block, &outblock); + else if (op == 'd') + krb5_k_decrypt(NULL, key, 0, NULL, &outblock, &block); + else if (op == 'm') + krb5_k_make_checksum(NULL, cktype, key, 0, &block, &sum); + else if (op == 'v') + krb5_k_verify_checksum(NULL, key, 0, &block, &sum, &val); + } + } + return 0; +} |
