summaryrefslogtreecommitdiff
path: root/testing/keymanagetest.c
diff options
context:
space:
mode:
Diffstat (limited to 'testing/keymanagetest.c')
-rw-r--r--testing/keymanagetest.c651
1 files changed, 651 insertions, 0 deletions
diff --git a/testing/keymanagetest.c b/testing/keymanagetest.c
new file mode 100644
index 0000000..394a29c
--- /dev/null
+++ b/testing/keymanagetest.c
@@ -0,0 +1,651 @@
+/*
+ * keymanagetest.c
+ *
+ * Expected SUCCESSes: 2 + 2 + 3 for all tests.
+ *
+ * Returns:
+ * Number of FAILUREs.
+ *
+ *
+ * FIX Or how about passing a usmUser name and looking up the entry as
+ * a means of getting key material? This means the userList is
+ * available from an application...
+ *
+ * ASSUMES No key management functions return non-zero success codes.
+ *
+ * Test of generate_Ku(). SUCCESSes: 2
+ * Test of generate_kul(). SUCCESSes: 2
+ * Test of {encode,decode}_keychange(). SUCCESSes: 3
+ */
+
+static char *rcsid = "$Id: keymanagetest.c 6918 2002-04-20 07:30:29Z hardaker $"; /* */
+
+#include <net-snmp/net-snmp-config.h>
+
+#include <stdio.h>
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include "asn1.h"
+#include "snmp_api.h"
+#include "keytools.h"
+#include "tools.h"
+#include "scapi.h"
+#include "transform_oids.h"
+#include "callback.h"
+
+#include <stdlib.h>
+
+extern char *optarg;
+extern int optind, optopt, opterr;
+
+
+
+/*
+ * Globals, &c...
+ */
+char *local_progname;
+
+#define USAGE "Usage: %s [-h][-aklu][-E <engineID>][-N <newkey>][-O <oldkey>][-P <passphrase>]"
+#define OPTIONLIST "aqE:hklN:O:P:u"
+
+int doalltests = 0, dogenKu = 0, dogenkul = 0, dokeychange = 0;
+
+#define ALLOPTIONS (doalltests + dogenKu + dogenkul + dokeychange)
+
+
+#define LOCAL_MAXBUF (1024 * 8)
+#define NL "\n"
+
+#define OUTPUTALWAYS(o) fprintf(stdout, "\n\n%s\n\n", o);
+#define OUTPUT(o) if (!bequiet) { OUTPUTALWAYS(o); }
+
+#define SUCCESS(s) \
+{ \
+ if (!failcount && !bequiet) \
+ fprintf(stdout, "\nSUCCESS: %s\n", s); \
+}
+
+#define FAILED(e, f) \
+{ \
+ if (e != SNMPERR_SUCCESS && !bequiet) { \
+ fprintf(stdout, "\nFAILED: %s\n", f); \
+ failcount += 1; \
+ } \
+}
+
+
+
+/*
+ * Test specific globals.
+ */
+#define ENGINEID_DEFAULT "1.2.3.4wild"
+#define PASSPHRASE_DEFAULT "Clay's Conclusion: Creativity is great, " \
+ "but plagiarism is faster."
+#define OLDKEY_DEFAULT "This is a very old key."
+#define NEWKEY_DEFAULT "This key, on the other hand, is very new."
+
+char *engineID = NULL;
+char *passphrase = NULL;
+char *oldkey = NULL;
+char *newkey = NULL;
+int bequiet = 0;
+
+
+/*
+ * Prototypes.
+ */
+void usage(FILE * ofp);
+
+int test_genkul(void);
+int test_genKu(void);
+int test_keychange(void);
+
+
+
+
+int
+main(int argc, char **argv)
+{
+ int rval = SNMPERR_SUCCESS, failcount = 0;
+ char ch;
+
+ local_progname = argv[0];
+ optarg = NULL;
+
+ /*
+ * Parse.
+ */
+ while ((ch = getopt(argc, argv, OPTIONLIST)) != EOF) {
+ switch (ch) {
+ case 'a':
+ doalltests = 1;
+ break;
+ case 'E':
+ engineID = optarg;
+ break;
+ case 'k':
+ dokeychange = 1;
+ break;
+ case 'l':
+ dogenkul = 1;
+ break;
+ case 'N':
+ newkey = optarg;
+ break;
+ case 'O':
+ oldkey = optarg;
+ break;
+ case 'P':
+ passphrase = optarg;
+ break;
+ case 'u':
+ dogenKu = 1;
+ break;
+ case 'q':
+ bequiet = 1;
+ break;
+ case 'h':
+ rval = 0;
+ default:
+ usage(stdout);
+ exit(rval);
+ }
+
+ argc -= 1;
+ argv += 1;
+ if (optarg) {
+ argc -= 1;
+ argv += 1;
+ }
+
+ optind = 1;
+ optarg = NULL;
+ } /* endwhile getopt */
+
+ if ((argc > 1)) {
+ usage(stdout);
+ exit(1000);
+
+ } else if (ALLOPTIONS != 1) {
+ usage(stdout);
+ exit(1000);
+ }
+
+
+ /*
+ * Test stuff.
+ */
+ rval = sc_init();
+ FAILED(rval, "sc_init().");
+
+ if (dogenKu || doalltests) {
+ failcount += test_genKu();
+ }
+ if (dogenkul || doalltests) {
+ failcount += test_genkul();
+ }
+ if (dokeychange || doalltests) {
+ failcount += test_keychange();
+ }
+
+
+ /*
+ * Cleanup.
+ */
+ rval = sc_shutdown(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SHUTDOWN,
+ NULL, NULL);
+ FAILED(rval, "sc_shutdown().");
+
+ return failcount;
+
+} /* end main() */
+
+
+
+
+
+void
+usage(FILE * ofp)
+{
+ fprintf(ofp,
+ USAGE
+ "" NL
+ " -a All tests." NL
+ " -E [0x]<engineID> snmpEngineID string."
+ NL
+ " -k Test {encode,decode}_keychange()."
+ NL
+ " -l generate_kul()."
+ NL
+ " -h Help."
+ NL
+ " -N [0x]<newkey> New key (for testing KeyChange TC)."
+ NL
+ " -O [0x]<oldkey> Old key (for testing KeyChange TC)."
+ NL
+ " -P <passphrase> Source string for usmUser master key."
+ NL
+ " -u generate_Ku()."
+ NL
+ " -q be quiet."
+ NL "" NL, local_progname);
+
+} /* end usage() */
+
+
+
+
+#ifdef EXAMPLE
+/*******************************************************************-o-******
+ * test_dosomething
+ *
+ * Test template.
+ *
+ * Returns:
+ * Number of failures.
+ */
+int
+test_dosomething(void)
+{
+ int rval = SNMPERR_SUCCESS, failcount = 0;
+
+ EM0(1, "UNIMPLEMENTED"); /* EM(1); /* */
+
+ test_dosomething_quit:
+ return failcount;
+
+} /* end test_dosomething() */
+#endif /* EXAMPLE */
+
+
+
+/*******************************************************************-o-******
+ * test_genKu
+ *
+ * Returns:
+ * Number of failures.
+ *
+ *
+ * Test generation of usmUser master key from a passphrase.
+ *
+ * ASSUMES Passphrase is made of printable characters!
+ */
+int
+test_genKu(void)
+{
+ int rval = SNMPERR_SUCCESS,
+ failcount = 0,
+ properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5), kulen;
+ char *hashname = "usmHMACMD5AuthProtocol.", *s;
+ u_char Ku[LOCAL_MAXBUF];
+ oid *hashtype = usmHMACMD5AuthProtocol;
+
+ OUTPUT("Test of generate_Ku --");
+
+ /*
+ * Set passphrase.
+ */
+ if (!passphrase) {
+ passphrase = PASSPHRASE_DEFAULT;
+ }
+ if (!bequiet)
+ fprintf(stdout, "Passphrase%s:\n\t%s\n\n",
+ (passphrase == PASSPHRASE_DEFAULT) ? " (default)" : "",
+ passphrase);
+
+
+ test_genKu_again:
+ memset(Ku, 0, LOCAL_MAXBUF);
+ kulen = LOCAL_MAXBUF;
+
+ rval = generate_Ku(hashtype, USM_LENGTH_OID_TRANSFORM,
+ passphrase, strlen(passphrase), Ku, &kulen);
+ FAILED(rval, "generate_Ku().");
+
+ if (kulen != properlength) {
+ FAILED(SNMPERR_GENERR, "Ku length is wrong for this hashtype.");
+ }
+
+ binary_to_hex(Ku, kulen, &s);
+ if (!bequiet)
+ fprintf(stdout, "Ku (len=%d): %s\n", kulen, s);
+ free_zero(s, kulen);
+
+ SUCCESS(hashname);
+ if (!bequiet)
+ fprintf(stdout, "\n");
+
+ if (hashtype == usmHMACMD5AuthProtocol) {
+ hashtype = usmHMACSHA1AuthProtocol;
+ hashname = "usmHMACSHA1AuthProtocol.";
+ properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1);
+ goto test_genKu_again;
+ }
+
+ return failcount;
+
+} /* end test_genKu() */
+
+
+
+
+/*******************************************************************-o-******
+ * test_genkul
+ *
+ * Returns:
+ * Number of failures.
+ *
+ *
+ * Test of generate_kul().
+ *
+ * A passphrase and engineID are hashed into a master key Ku using
+ * both known hash transforms. Localized keys, also using both hash
+ * transforms, are generated from each of these master keys.
+ *
+ * ASSUME generate_Ku is already tested.
+ * ASSUME engineID is initially a NULL terminated string.
+ */
+int
+test_genkul(void)
+{
+ int rval = SNMPERR_SUCCESS,
+ failcount = 0,
+ properlength, kulen, kul_len, engineID_len, isdefault = FALSE;
+
+ char *s = NULL,
+ *testname = "Using HMACMD5 to create master key.",
+ *hashname_Ku = "usmHMACMD5AuthProtocol", *hashname_kul;
+
+ u_char Ku[LOCAL_MAXBUF], kul[LOCAL_MAXBUF];
+
+ oid *hashtype_Ku = usmHMACMD5AuthProtocol, *hashtype_kul;
+
+ OUTPUT("Test of generate_kul --");
+
+
+ /*
+ * Set passphrase and engineID.
+ *
+ * If engineID begins with 0x, assume it is written in (printable)
+ * hex and convert it to binary data.
+ */
+ if (!passphrase) {
+ passphrase = PASSPHRASE_DEFAULT;
+ }
+ if (!bequiet)
+ fprintf(stdout, "Passphrase%s:\n\t%s\n\n",
+ (passphrase == PASSPHRASE_DEFAULT) ? " (default)" : "",
+ passphrase);
+
+ if (!engineID) {
+ engineID = ENGINEID_DEFAULT;
+ isdefault = TRUE;
+ }
+
+ engineID_len = strlen(engineID);
+
+ if (tolower(*(engineID + 1)) == 'x') {
+ engineID_len = hex_to_binary2(engineID + 2, engineID_len - 2, &s);
+ if (engineID_len < 0) {
+ FAILED((rval = SNMPERR_GENERR),
+ "Could not resolve hex engineID.");
+ }
+ engineID = s;
+ binary_to_hex(engineID, engineID_len, &s);
+ }
+
+ if (!bequiet)
+ fprintf(stdout, "engineID%s (len=%d): %s\n\n",
+ (isdefault) ? " (default)" : "",
+ engineID_len, (s) ? s : engineID);
+ if (s) {
+ SNMP_FREE(s);
+ }
+
+
+
+ /*
+ * Create a master key using both hash transforms; create localized
+ * keys using both hash transforms from each master key.
+ */
+ test_genkul_again_master:
+ memset(Ku, 0, LOCAL_MAXBUF);
+ kulen = LOCAL_MAXBUF;
+ hashname_kul = "usmHMACMD5AuthProtocol";
+ hashtype_kul = usmHMACMD5AuthProtocol;
+ properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5);
+
+
+ rval = generate_Ku(hashtype_Ku, USM_LENGTH_OID_TRANSFORM,
+ passphrase, strlen(passphrase), Ku, &kulen);
+ FAILED(rval, "generate_Ku().");
+
+ binary_to_hex(Ku, kulen, &s);
+ if (!bequiet)
+ fprintf(stdout,
+ "\n\nMaster Ku using \"%s\":\n\t%s\n\n", hashname_Ku, s);
+ free_zero(s, kulen);
+
+
+ test_genkul_again_local:
+ memset(kul, 0, LOCAL_MAXBUF);
+ kul_len = LOCAL_MAXBUF;
+
+ rval = generate_kul(hashtype_kul, USM_LENGTH_OID_TRANSFORM,
+ engineID, engineID_len, Ku, kulen, kul, &kul_len);
+
+ if ((hashtype_Ku == usmHMACMD5AuthProtocol)
+ && (hashtype_kul == usmHMACSHA1AuthProtocol)) {
+ if (rval == SNMPERR_SUCCESS) {
+ FAILED(SNMPERR_GENERR,
+ "generate_kul SHOULD fail when Ku length is "
+ "less than hash transform length.");
+ }
+
+ } else {
+ FAILED(rval, "generate_kul().");
+
+ if (kul_len != properlength) {
+ FAILED(SNMPERR_GENERR,
+ "kul length is wrong for the given hashtype.");
+ }
+
+ binary_to_hex(kul, kul_len, &s);
+ fprintf(stdout, "kul (%s) (len=%d): %s\n",
+ ((hashtype_Ku == usmHMACMD5AuthProtocol) ? "MD5" : "SHA"),
+ kul_len, s);
+ free_zero(s, kul_len);
+ }
+
+
+ /*
+ * Create localized key using the other hash transform, but from
+ * * the same master key.
+ */
+ if (hashtype_kul == usmHMACMD5AuthProtocol) {
+ hashtype_kul = usmHMACSHA1AuthProtocol;
+ hashname_kul = "usmHMACSHA1AuthProtocol";
+ properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1);
+ goto test_genkul_again_local;
+ }
+
+ SUCCESS(testname);
+
+
+ /*
+ * Re-create the master key using the other hash transform.
+ */
+ if (hashtype_Ku == usmHMACMD5AuthProtocol) {
+ hashtype_Ku = usmHMACSHA1AuthProtocol;
+ hashname_Ku = "usmHMACSHA1AuthProtocol";
+ testname = "Using HMACSHA1 to create master key.";
+ goto test_genkul_again_master;
+ }
+
+ return failcount;
+
+} /* end test_genkul() */
+
+
+
+
+/*******************************************************************-o-******
+ * test_keychange
+ *
+ * Returns:
+ * Number of failures.
+ *
+ *
+ * Test of KeyChange TC implementation.
+ *
+ * ASSUME newkey and oldkey begin as NULL terminated strings.
+ */
+int
+test_keychange(void)
+{
+ int rval = SNMPERR_SUCCESS,
+ failcount = 0,
+ properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5),
+ oldkey_len,
+ newkey_len,
+ keychange_len,
+ temp_len, isdefault_new = FALSE, isdefault_old = FALSE;
+
+ char *hashname = "usmHMACMD5AuthProtocol.", *s;
+
+ u_char oldkey_buf[LOCAL_MAXBUF],
+ newkey_buf[LOCAL_MAXBUF],
+ temp_buf[LOCAL_MAXBUF], keychange_buf[LOCAL_MAXBUF];
+
+ oid *hashtype = usmHMACMD5AuthProtocol;
+
+ OUTPUT("Test of KeyChange TC --");
+
+
+ /*
+ * Set newkey and oldkey.
+ */
+ if (!newkey) { /* newkey */
+ newkey = NEWKEY_DEFAULT;
+ isdefault_new = TRUE;
+ }
+ newkey_len = strlen(newkey);
+
+ if (tolower(*(newkey + 1)) == 'x') {
+ newkey_len = hex_to_binary2(newkey + 2, newkey_len - 2, &s);
+ if (newkey_len < 0) {
+ FAILED((rval = SNMPERR_GENERR),
+ "Could not resolve hex newkey.");
+ }
+ newkey = s;
+ binary_to_hex(newkey, newkey_len, &s);
+ }
+
+ if (!oldkey) { /* oldkey */
+ oldkey = OLDKEY_DEFAULT;
+ isdefault_old = TRUE;
+ }
+ oldkey_len = strlen(oldkey);
+
+ if (tolower(*(oldkey + 1)) == 'x') {
+ oldkey_len = hex_to_binary2(oldkey + 2, oldkey_len - 2, &s);
+ if (oldkey_len < 0) {
+ FAILED((rval = SNMPERR_GENERR),
+ "Could not resolve hex oldkey.");
+ }
+ oldkey = s;
+ binary_to_hex(oldkey, oldkey_len, &s);
+ }
+
+
+
+ test_keychange_again:
+ memset(oldkey_buf, 0, LOCAL_MAXBUF);
+ memset(newkey_buf, 0, LOCAL_MAXBUF);
+ memset(keychange_buf, 0, LOCAL_MAXBUF);
+ memset(temp_buf, 0, LOCAL_MAXBUF);
+
+ memcpy(oldkey_buf, oldkey, SNMP_MIN(oldkey_len, properlength));
+ memcpy(newkey_buf, newkey, SNMP_MIN(newkey_len, properlength));
+ keychange_len = LOCAL_MAXBUF;
+
+
+ binary_to_hex(oldkey_buf, properlength, &s);
+ fprintf(stdout, "\noldkey%s (len=%d): %s\n",
+ (isdefault_old) ? " (default)" : "", properlength, s);
+ SNMP_FREE(s);
+
+ binary_to_hex(newkey_buf, properlength, &s);
+ fprintf(stdout, "newkey%s (len=%d): %s\n\n",
+ (isdefault_new) ? " (default)" : "", properlength, s);
+ SNMP_FREE(s);
+
+
+ rval = encode_keychange(hashtype, USM_LENGTH_OID_TRANSFORM,
+ oldkey_buf, properlength,
+ newkey_buf, properlength,
+ keychange_buf, &keychange_len);
+ FAILED(rval, "encode_keychange().");
+
+ if (keychange_len != (properlength * 2)) {
+ FAILED(SNMPERR_GENERR,
+ "KeyChange string (encoded) is not proper length "
+ "for this hash transform.");
+ }
+
+ binary_to_hex(keychange_buf, keychange_len, &s);
+ fprintf(stdout, "(%s) KeyChange string: %s\n\n",
+ ((hashtype == usmHMACMD5AuthProtocol) ? "MD5" : "SHA"), s);
+ SNMP_FREE(s);
+
+ temp_len = properlength;
+ rval = decode_keychange(hashtype, USM_LENGTH_OID_TRANSFORM,
+ oldkey_buf, properlength,
+ keychange_buf, properlength * 2,
+ temp_buf, &temp_len);
+ FAILED(rval, "decode_keychange().");
+
+ if (temp_len != properlength) {
+ FAILED(SNMPERR_GENERR,
+ "decoded newkey is not proper length for "
+ "this hash transform.");
+ }
+
+ binary_to_hex(temp_buf, temp_len, &s);
+ fprintf(stdout, "decoded newkey: %s\n\n", s);
+ SNMP_FREE(s);
+
+
+ if (memcmp(newkey_buf, temp_buf, temp_len)) {
+ FAILED(SNMPERR_GENERR, "newkey did not decode properly.");
+ }
+
+
+ SUCCESS(hashname);
+ fprintf(stdout, "\n");
+
+
+ /*
+ * Multiplex different test combinations.
+ *
+ * First clause is for Test #2, second clause is for (last) Test #3.
+ */
+ if (hashtype == usmHMACMD5AuthProtocol) {
+ hashtype = usmHMACSHA1AuthProtocol;
+ hashname = "usmHMACSHA1AuthProtocol (w/DES length kul's).";
+ properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES)
+ + BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
+ goto test_keychange_again;
+
+ } else if (properlength < BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1)) {
+ hashtype = usmHMACSHA1AuthProtocol;
+ hashname = "usmHMACSHA1AuthProtocol.";
+ properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1);
+ goto test_keychange_again;
+ }
+
+ return failcount;
+
+} /* end test_keychange() */