diff options
Diffstat (limited to 'testing/fulltests/snmpv3/T010scapitest_capp.c')
-rw-r--r-- | testing/fulltests/snmpv3/T010scapitest_capp.c | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/testing/fulltests/snmpv3/T010scapitest_capp.c b/testing/fulltests/snmpv3/T010scapitest_capp.c new file mode 100644 index 0000000..ee794a7 --- /dev/null +++ b/testing/fulltests/snmpv3/T010scapitest_capp.c @@ -0,0 +1,459 @@ +/* + * scapitest.c + * + * HEADER Testing SCAPI API + * + * Expected SUCCESSes: 2 + 10 + 1 for all tests. + * + * Returns: + * Number of FAILUREs. + * + * + * ASSUMES No key management functions return non-zero success codes. + * + * XXX Split into individual modules? + * XXX Error/fringe conditions should be tested. + * + * + * Test of sc_random. SUCCESSes: 2. + * REQUIRES a human to spot check for obvious non-randomness... + * + * Test of sc_generate_keyed_hash and sc_check_keyed_hash. SUCCESSes: 10. + * + * Test of sc_encrypt and sc_decrypt. SUCCESSes: 1. + */ + +#include <net-snmp/net-snmp-config.h> + +#include <stdio.h> +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +#include <net-snmp/library/asn1.h> +#include <net-snmp/library/snmp_api.h> +#include <net-snmp/library/keytools.h> +#include <net-snmp/library/tools.h> +#include <net-snmp/library/scapi.h> +#include <net-snmp/library/transform_oids.h> +#include <net-snmp/library/callback.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/library/snmpusm.h> + +#include <stdlib.h> + +extern char *optarg; +extern int optind, optopt, opterr; + +#define DEBUG /* */ + + + +/* + * Globals, &c... + */ +char *local_progname; +int testcount=0; +int failcount=0; + +#define USAGE "Usage: %s [-h][-acHr]" +#define OPTIONLIST "achHr" + +int doalltests = 0, docrypt = 0, dokeyedhash = 0, dorandom = 0; + +#define ALLOPTIONS (doalltests + docrypt + dokeyedhash + dorandom) + + + +#define LOCAL_MAXBUF (1024 * 8) +#define NL "\n" + +#define OUTPUT(o) printf("# %s\n", o); + +#define SUCCESS(s) \ +{ \ + printf("# Done with %s\n", s); \ +} + +#define FAILED(e, f) \ +{ \ + if (e != SNMPERR_SUCCESS) { \ + printf("not ok: %d - %s\n", ++testcount, f); \ + failcount += 1; \ + } else { \ + printf("ok: %d - %s\n", ++testcount, f); \ + } \ + fflush(stdout); \ +} + +#define BIGSTRING \ + (const u_char *) \ + " A port may be a pleasant retreat for any mind grown weary of" \ + "the struggle for existence. The vast expanse of sky, the" \ + "mobile architecture of the clouds, the chameleon coloration" \ + "of the sea, the beacons flashing on the shore, together make" \ + "a prism which is marvellously calculated to entertain but not" \ + "fatigue the eye. The lofty ships with their complex webs of" \ + "rigging, swayed to and fro by the swell in harmonious dance," \ + "all help to maintain a taste for rhythm and beauty in the" \ + "mind. And above all there is a mysterious, aristrocratic kind" \ + "of pleasure to be had, for those who have lost all curiosity" \ + "or ambition, as they strech on the belvedere or lean over the" \ + "mole to watch the arrivals and departures of other men, those" \ + "who still have sufficient strength of purpose in them, the" \ + "urge to travel or enrich themselves." \ + " -- Baudelaire" \ + " From _The_Poems_in_Prose_, \"The Port\" (XLI)." + +#define BIGSECRET \ + (const u_char *) \ + "Shhhh... Don't tell *anyone* about this. Not a soul." +#define BKWDSECRET \ + (const u_char *) \ + ".luos a toN .siht tuoba *enoyna* llet t'noD ...hhhhS" + +#define MLCOUNT_MAX 6 /* MAC Length Count Maximum. */ + + + +/* + * Prototypes. + */ +void usage(void); + +int test_docrypt(void); +int test_dokeyedhash(void); +int test_dorandom(void); + + + + +int +main(int argc, char **argv) +{ + int rval = SNMPERR_SUCCESS; + char ch; + + local_progname = argv[0]; + + /* + * Parse. + */ + while ((ch = getopt(argc, argv, OPTIONLIST)) != EOF) { + switch (ch) { + case 'a': + doalltests = 1; + break; + case 'c': + docrypt = 1; + break; + case 'H': + dokeyedhash = 1; + break; + case 'r': + dorandom = 1; + break; + case 'h': + rval = 0; + default: + usage(); + exit(rval); + } + + argc -= 1; + argv += 1; + optind = 1; + } /* endwhile getopt */ + + if ((argc > 1)) { + usage(); + exit(1000); + + } else if (ALLOPTIONS != 1) { + doalltests = 1; + } + + + /* + * Test stuff. + */ + rval = sc_init(); + FAILED(rval, "sc_init() return code"); + + + if (docrypt || doalltests) { + test_docrypt(); + } + if (dokeyedhash || doalltests) { + test_dokeyedhash(); + } + if (dorandom || doalltests) { + test_dorandom(); + } + + printf("1..%d\n", testcount); + return 0; +} /* end main() */ + + + + + +void +usage(void) +{ + printf( USAGE + "" NL + " -a All tests." NL + " -c Test of sc_encrypt()/sc_decrypt()." + NL + " -h Help." + NL + " -H Test sc_{generate,check}_keyed_hash()." + NL + " -r Test sc_random()." + NL "" NL, local_progname); + +} /* end usage() */ + + + + +/*******************************************************************-o-****** + * test_dorandom + * + * One large request, one set of short requests. + * + * Returns: + * Number of failures. + * + * XXX probably should split up into individual options. + */ +int +test_dorandom(void) +{ + int rval = SNMPERR_SUCCESS, + origrequest = (1024 * 2), + origrequest_short = 19, shortcount = 7, i; + size_t nbytes = origrequest; + u_char buf[LOCAL_MAXBUF]; + + OUTPUT("Random test -- large request:"); + + rval = sc_random(buf, &nbytes); + FAILED(rval, "sc_random() return code"); + + if (nbytes != origrequest) { + FAILED(SNMPERR_GENERR, + "sc_random() returned different than requested."); + } + + dump_chunk("scapitest", NULL, buf, nbytes); + + SUCCESS("Random test -- large request."); + + + OUTPUT("Random test -- short requests:"); + origrequest_short = 16; + + for (i = 0; i < shortcount; i++) { + nbytes = origrequest_short; + rval = sc_random(buf, &nbytes); + FAILED(rval, "sc_random() return code"); + + if (nbytes != origrequest_short) { + FAILED(SNMPERR_GENERR, + "sc_random() returned different " "than requested."); + } + + dump_chunk("scapitest", NULL, buf, nbytes); + } /* endfor */ + + SUCCESS("Random test -- short requests."); + + + return failcount; + +} /* end test_dorandom() */ + + + +/*******************************************************************-o-****** + * test_dokeyedhash + * + * Returns: + * Number of failures. + * + * + * Test keyed hashes with a variety of MAC length requests. + * + * + * NOTE Both tests intentionally use the same secret + * + * FIX Get input or output from some other package which hashes... + * XXX Could cut this in half with a little indirection... + */ +int +test_dokeyedhash(void) +{ + int rval = SNMPERR_SUCCESS, + bigstring_len = strlen((const char *) BIGSTRING), + secret_len = strlen((const char *) BIGSECRET), + properlength, + mlcount = 0; /* MAC Length count. */ + size_t hblen; /* Hash Buffer length. */ + + u_int hashbuf_len[MLCOUNT_MAX] = { + LOCAL_MAXBUF, + USM_MD5_AND_SHA_AUTH_LEN, + USM_MD5_AND_SHA_AUTH_LEN, + USM_MD5_AND_SHA_AUTH_LEN, + 7, + 0, + }; + + u_char hashbuf[LOCAL_MAXBUF]; + char *s; + + test_dokeyedhash_again: + + OUTPUT("Starting Keyed hash test using MD5 --"); + + memset(hashbuf, 0, LOCAL_MAXBUF); + hblen = hashbuf_len[mlcount]; + properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5); + + rval = + sc_generate_keyed_hash(usmHMACMD5AuthProtocol, + USM_LENGTH_OID_TRANSFORM, BIGSECRET, + secret_len, BIGSTRING, + bigstring_len, + hashbuf, &hblen); + FAILED(rval, "sc_generate_keyed_hash() return code"); + + if (hashbuf_len[mlcount] > properlength) { + if (hblen != properlength) { + FAILED(SNMPERR_GENERR, "Wrong MD5 hash length returned. (1)"); + } + + } else if (hblen != hashbuf_len[mlcount]) { + FAILED(SNMPERR_GENERR, "Wrong MD5 hash length returned. (2)"); + } + + rval = + sc_check_keyed_hash(usmHMACMD5AuthProtocol, + USM_LENGTH_OID_TRANSFORM, BIGSECRET, + secret_len, BIGSTRING, bigstring_len, hashbuf, + hblen); + FAILED(rval, "sc_check_keyed_hash() return code"); + + binary_to_hex(hashbuf, hblen, &s); + printf("# hash buffer (len=%" NETSNMP_PRIz "u, request=%d): %s\n", + hblen, hashbuf_len[mlcount], s); + SNMP_FREE(s); + + + + OUTPUT("Starting Keyed hash test using SHA1 --"); + + memset(hashbuf, 0, LOCAL_MAXBUF); + hblen = hashbuf_len[mlcount]; + properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1); + + rval = + sc_generate_keyed_hash(usmHMACSHA1AuthProtocol, + USM_LENGTH_OID_TRANSFORM, BIGSECRET, + secret_len, BIGSTRING, bigstring_len, + hashbuf, &hblen); + FAILED(rval, "sc_generate_keyed_hash() return code"); + + if (hashbuf_len[mlcount] > properlength) { + if (hblen != properlength) { + FAILED(SNMPERR_GENERR, + "Wrong SHA1 hash length returned. (1)"); + } + + } else if (hblen != hashbuf_len[mlcount]) { + FAILED(SNMPERR_GENERR, "Wrong SHA1 hash length returned. (2)"); + } + + rval = + sc_check_keyed_hash(usmHMACSHA1AuthProtocol, + USM_LENGTH_OID_TRANSFORM, BIGSECRET, + secret_len, BIGSTRING, bigstring_len, hashbuf, + hblen); + FAILED(rval, "sc_check_keyed_hash() return code"); + + binary_to_hex(hashbuf, hblen, &s); + printf("# hash buffer (len=%" NETSNMP_PRIz "u, request=%d): %s\n", + hblen, hashbuf_len[mlcount], s); + SNMP_FREE(s); + + SUCCESS("Keyed hash test using SHA1."); + + /* + * Run the basic hash tests but vary the size MAC requests. + */ + if (hashbuf_len[++mlcount] != 0) { + goto test_dokeyedhash_again; + } + + + return failcount; + +} /* end test_dokeyedhash() */ + + + + + +/*******************************************************************-o-****** + * test_docrypt + * + * Returns: + * Number of failures. + */ +int +test_docrypt(void) +{ + int rval = SNMPERR_SUCCESS, + bigstring_len = strlen((const char *) BIGSTRING), + secret_len = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES), + iv_len = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV); + + size_t buf_len = LOCAL_MAXBUF; + size_t cryptbuf_len = LOCAL_MAXBUF; + + u_char buf[LOCAL_MAXBUF], + cryptbuf[LOCAL_MAXBUF], secret[LOCAL_MAXBUF], iv[LOCAL_MAXBUF]; + + OUTPUT("Starting Test 1DES-CBC --"); + + + memset(buf, 0, LOCAL_MAXBUF); + + memcpy(secret, BIGSECRET, secret_len); + memcpy(iv, BKWDSECRET, iv_len); + + rval = sc_encrypt(usmDESPrivProtocol, USM_LENGTH_OID_TRANSFORM, + secret, secret_len, + iv, iv_len, + BIGSTRING, bigstring_len, cryptbuf, &cryptbuf_len); + FAILED(rval, "sc_encrypt() return code."); + + rval = sc_decrypt(usmDESPrivProtocol, USM_LENGTH_OID_TRANSFORM, + secret, secret_len, + iv, iv_len, cryptbuf, cryptbuf_len, buf, &buf_len); + FAILED(rval, "sc_decrypt() return code."); + + /* ignore the pad */ + buf_len -= buf[buf_len-1]; + + FAILED((buf_len != bigstring_len), "Decrypted buffer is the right length."); + printf("# original length: %d\n", bigstring_len); + printf("# output length: %" NETSNMP_PRIz "u\n", buf_len); + + FAILED((memcmp(buf, BIGSTRING, bigstring_len) != 0), + "Decrypted buffer is the same as the original plaintext."); + return failcount; +} /* end test_docrypt() */ |