4 * Expected SUCCESSes: 2 + 2 + 3 for all tests.
10 * FIX Or how about passing a usmUser name and looking up the entry as
11 * a means of getting key material? This means the userList is
12 * available from an application...
14 * ASSUMES No key management functions return non-zero success codes.
16 * Test of generate_Ku(). SUCCESSes: 2
17 * Test of generate_kul(). SUCCESSes: 2
18 * Test of {encode,decode}_keychange(). SUCCESSes: 3
21 static char *rcsid = "$Id: keymanagetest.c,v 5.0 2002/04/20 07:30:22 hardaker Exp $"; /* */
23 #include <net-snmp/net-snmp-config.h>
26 #ifdef HAVE_NETINET_IN_H
27 #include <netinet/in.h>
35 #include "transform_oids.h"
41 extern int optind, optopt, opterr;
50 #define USAGE "Usage: %s [-h][-aklu][-E <engineID>][-N <newkey>][-O <oldkey>][-P <passphrase>]"
51 #define OPTIONLIST "aqE:hklN:O:P:u"
53 int doalltests = 0, dogenKu = 0, dogenkul = 0, dokeychange = 0;
55 #define ALLOPTIONS (doalltests + dogenKu + dogenkul + dokeychange)
58 #define LOCAL_MAXBUF (1024 * 8)
61 #define OUTPUTALWAYS(o) fprintf(stdout, "\n\n%s\n\n", o);
62 #define OUTPUT(o) if (!bequiet) { OUTPUTALWAYS(o); }
66 if (!failcount && !bequiet) \
67 fprintf(stdout, "\nSUCCESS: %s\n", s); \
70 #define FAILED(e, f) \
72 if (e != SNMPERR_SUCCESS && !bequiet) { \
73 fprintf(stdout, "\nFAILED: %s\n", f); \
81 * Test specific globals.
83 #define ENGINEID_DEFAULT "1.2.3.4wild"
84 #define PASSPHRASE_DEFAULT "Clay's Conclusion: Creativity is great, " \
85 "but plagiarism is faster."
86 #define OLDKEY_DEFAULT "This is a very old key."
87 #define NEWKEY_DEFAULT "This key, on the other hand, is very new."
89 char *engineID = NULL;
90 char *passphrase = NULL;
99 void usage(FILE * ofp);
101 int test_genkul(void);
102 int test_genKu(void);
103 int test_keychange(void);
109 main(int argc, char **argv)
111 int rval = SNMPERR_SUCCESS, failcount = 0;
114 local_progname = argv[0];
120 while ((ch = getopt(argc, argv, OPTIONLIST)) != EOF) {
165 } /* endwhile getopt */
171 } else if (ALLOPTIONS != 1) {
181 FAILED(rval, "sc_init().");
183 if (dogenKu || doalltests) {
184 failcount += test_genKu();
186 if (dogenkul || doalltests) {
187 failcount += test_genkul();
189 if (dokeychange || doalltests) {
190 failcount += test_keychange();
197 rval = sc_shutdown(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SHUTDOWN,
199 FAILED(rval, "sc_shutdown().");
216 " -E [0x]<engineID> snmpEngineID string."
218 " -k Test {encode,decode}_keychange()."
220 " -l generate_kul()."
224 " -N [0x]<newkey> New key (for testing KeyChange TC)."
226 " -O [0x]<oldkey> Old key (for testing KeyChange TC)."
228 " -P <passphrase> Source string for usmUser master key."
233 NL "" NL, local_progname);
241 /*******************************************************************-o-******
247 * Number of failures.
250 test_dosomething(void)
252 int rval = SNMPERR_SUCCESS, failcount = 0;
254 EM0(1, "UNIMPLEMENTED"); /* EM(1); /* */
256 test_dosomething_quit:
259 } /* end test_dosomething() */
264 /*******************************************************************-o-******
268 * Number of failures.
271 * Test generation of usmUser master key from a passphrase.
273 * ASSUMES Passphrase is made of printable characters!
278 int rval = SNMPERR_SUCCESS,
280 properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5), kulen;
281 char *hashname = "usmHMACMD5AuthProtocol.", *s;
282 u_char Ku[LOCAL_MAXBUF];
283 oid *hashtype = usmHMACMD5AuthProtocol;
285 OUTPUT("Test of generate_Ku --");
291 passphrase = PASSPHRASE_DEFAULT;
294 fprintf(stdout, "Passphrase%s:\n\t%s\n\n",
295 (passphrase == PASSPHRASE_DEFAULT) ? " (default)" : "",
300 memset(Ku, 0, LOCAL_MAXBUF);
301 kulen = LOCAL_MAXBUF;
303 rval = generate_Ku(hashtype, USM_LENGTH_OID_TRANSFORM,
304 passphrase, strlen(passphrase), Ku, &kulen);
305 FAILED(rval, "generate_Ku().");
307 if (kulen != properlength) {
308 FAILED(SNMPERR_GENERR, "Ku length is wrong for this hashtype.");
311 binary_to_hex(Ku, kulen, &s);
313 fprintf(stdout, "Ku (len=%d): %s\n", kulen, s);
318 fprintf(stdout, "\n");
320 if (hashtype == usmHMACMD5AuthProtocol) {
321 hashtype = usmHMACSHA1AuthProtocol;
322 hashname = "usmHMACSHA1AuthProtocol.";
323 properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1);
324 goto test_genKu_again;
329 } /* end test_genKu() */
334 /*******************************************************************-o-******
338 * Number of failures.
341 * Test of generate_kul().
343 * A passphrase and engineID are hashed into a master key Ku using
344 * both known hash transforms. Localized keys, also using both hash
345 * transforms, are generated from each of these master keys.
347 * ASSUME generate_Ku is already tested.
348 * ASSUME engineID is initially a NULL terminated string.
353 int rval = SNMPERR_SUCCESS,
355 properlength, kulen, kul_len, engineID_len, isdefault = FALSE;
358 *testname = "Using HMACMD5 to create master key.",
359 *hashname_Ku = "usmHMACMD5AuthProtocol", *hashname_kul;
361 u_char Ku[LOCAL_MAXBUF], kul[LOCAL_MAXBUF];
363 oid *hashtype_Ku = usmHMACMD5AuthProtocol, *hashtype_kul;
365 OUTPUT("Test of generate_kul --");
369 * Set passphrase and engineID.
371 * If engineID begins with 0x, assume it is written in (printable)
372 * hex and convert it to binary data.
375 passphrase = PASSPHRASE_DEFAULT;
378 fprintf(stdout, "Passphrase%s:\n\t%s\n\n",
379 (passphrase == PASSPHRASE_DEFAULT) ? " (default)" : "",
383 engineID = ENGINEID_DEFAULT;
387 engineID_len = strlen(engineID);
389 if (tolower(*(engineID + 1)) == 'x') {
390 engineID_len = hex_to_binary2(engineID + 2, engineID_len - 2, &s);
391 if (engineID_len < 0) {
392 FAILED((rval = SNMPERR_GENERR),
393 "Could not resolve hex engineID.");
396 binary_to_hex(engineID, engineID_len, &s);
400 fprintf(stdout, "engineID%s (len=%d): %s\n\n",
401 (isdefault) ? " (default)" : "",
402 engineID_len, (s) ? s : engineID);
410 * Create a master key using both hash transforms; create localized
411 * keys using both hash transforms from each master key.
413 test_genkul_again_master:
414 memset(Ku, 0, LOCAL_MAXBUF);
415 kulen = LOCAL_MAXBUF;
416 hashname_kul = "usmHMACMD5AuthProtocol";
417 hashtype_kul = usmHMACMD5AuthProtocol;
418 properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5);
421 rval = generate_Ku(hashtype_Ku, USM_LENGTH_OID_TRANSFORM,
422 passphrase, strlen(passphrase), Ku, &kulen);
423 FAILED(rval, "generate_Ku().");
425 binary_to_hex(Ku, kulen, &s);
428 "\n\nMaster Ku using \"%s\":\n\t%s\n\n", hashname_Ku, s);
432 test_genkul_again_local:
433 memset(kul, 0, LOCAL_MAXBUF);
434 kul_len = LOCAL_MAXBUF;
436 rval = generate_kul(hashtype_kul, USM_LENGTH_OID_TRANSFORM,
437 engineID, engineID_len, Ku, kulen, kul, &kul_len);
439 if ((hashtype_Ku == usmHMACMD5AuthProtocol)
440 && (hashtype_kul == usmHMACSHA1AuthProtocol)) {
441 if (rval == SNMPERR_SUCCESS) {
442 FAILED(SNMPERR_GENERR,
443 "generate_kul SHOULD fail when Ku length is "
444 "less than hash transform length.");
448 FAILED(rval, "generate_kul().");
450 if (kul_len != properlength) {
451 FAILED(SNMPERR_GENERR,
452 "kul length is wrong for the given hashtype.");
455 binary_to_hex(kul, kul_len, &s);
456 fprintf(stdout, "kul (%s) (len=%d): %s\n",
457 ((hashtype_Ku == usmHMACMD5AuthProtocol) ? "MD5" : "SHA"),
459 free_zero(s, kul_len);
464 * Create localized key using the other hash transform, but from
465 * * the same master key.
467 if (hashtype_kul == usmHMACMD5AuthProtocol) {
468 hashtype_kul = usmHMACSHA1AuthProtocol;
469 hashname_kul = "usmHMACSHA1AuthProtocol";
470 properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1);
471 goto test_genkul_again_local;
478 * Re-create the master key using the other hash transform.
480 if (hashtype_Ku == usmHMACMD5AuthProtocol) {
481 hashtype_Ku = usmHMACSHA1AuthProtocol;
482 hashname_Ku = "usmHMACSHA1AuthProtocol";
483 testname = "Using HMACSHA1 to create master key.";
484 goto test_genkul_again_master;
489 } /* end test_genkul() */
494 /*******************************************************************-o-******
498 * Number of failures.
501 * Test of KeyChange TC implementation.
503 * ASSUME newkey and oldkey begin as NULL terminated strings.
508 int rval = SNMPERR_SUCCESS,
510 properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5),
514 temp_len, isdefault_new = FALSE, isdefault_old = FALSE;
516 char *hashname = "usmHMACMD5AuthProtocol.", *s;
518 u_char oldkey_buf[LOCAL_MAXBUF],
519 newkey_buf[LOCAL_MAXBUF],
520 temp_buf[LOCAL_MAXBUF], keychange_buf[LOCAL_MAXBUF];
522 oid *hashtype = usmHMACMD5AuthProtocol;
524 OUTPUT("Test of KeyChange TC --");
528 * Set newkey and oldkey.
530 if (!newkey) { /* newkey */
531 newkey = NEWKEY_DEFAULT;
532 isdefault_new = TRUE;
534 newkey_len = strlen(newkey);
536 if (tolower(*(newkey + 1)) == 'x') {
537 newkey_len = hex_to_binary2(newkey + 2, newkey_len - 2, &s);
538 if (newkey_len < 0) {
539 FAILED((rval = SNMPERR_GENERR),
540 "Could not resolve hex newkey.");
543 binary_to_hex(newkey, newkey_len, &s);
546 if (!oldkey) { /* oldkey */
547 oldkey = OLDKEY_DEFAULT;
548 isdefault_old = TRUE;
550 oldkey_len = strlen(oldkey);
552 if (tolower(*(oldkey + 1)) == 'x') {
553 oldkey_len = hex_to_binary2(oldkey + 2, oldkey_len - 2, &s);
554 if (oldkey_len < 0) {
555 FAILED((rval = SNMPERR_GENERR),
556 "Could not resolve hex oldkey.");
559 binary_to_hex(oldkey, oldkey_len, &s);
564 test_keychange_again:
565 memset(oldkey_buf, 0, LOCAL_MAXBUF);
566 memset(newkey_buf, 0, LOCAL_MAXBUF);
567 memset(keychange_buf, 0, LOCAL_MAXBUF);
568 memset(temp_buf, 0, LOCAL_MAXBUF);
570 memcpy(oldkey_buf, oldkey, SNMP_MIN(oldkey_len, properlength));
571 memcpy(newkey_buf, newkey, SNMP_MIN(newkey_len, properlength));
572 keychange_len = LOCAL_MAXBUF;
575 binary_to_hex(oldkey_buf, properlength, &s);
576 fprintf(stdout, "\noldkey%s (len=%d): %s\n",
577 (isdefault_old) ? " (default)" : "", properlength, s);
580 binary_to_hex(newkey_buf, properlength, &s);
581 fprintf(stdout, "newkey%s (len=%d): %s\n\n",
582 (isdefault_new) ? " (default)" : "", properlength, s);
586 rval = encode_keychange(hashtype, USM_LENGTH_OID_TRANSFORM,
587 oldkey_buf, properlength,
588 newkey_buf, properlength,
589 keychange_buf, &keychange_len);
590 FAILED(rval, "encode_keychange().");
592 if (keychange_len != (properlength * 2)) {
593 FAILED(SNMPERR_GENERR,
594 "KeyChange string (encoded) is not proper length "
595 "for this hash transform.");
598 binary_to_hex(keychange_buf, keychange_len, &s);
599 fprintf(stdout, "(%s) KeyChange string: %s\n\n",
600 ((hashtype == usmHMACMD5AuthProtocol) ? "MD5" : "SHA"), s);
603 temp_len = properlength;
604 rval = decode_keychange(hashtype, USM_LENGTH_OID_TRANSFORM,
605 oldkey_buf, properlength,
606 keychange_buf, properlength * 2,
607 temp_buf, &temp_len);
608 FAILED(rval, "decode_keychange().");
610 if (temp_len != properlength) {
611 FAILED(SNMPERR_GENERR,
612 "decoded newkey is not proper length for "
613 "this hash transform.");
616 binary_to_hex(temp_buf, temp_len, &s);
617 fprintf(stdout, "decoded newkey: %s\n\n", s);
621 if (memcmp(newkey_buf, temp_buf, temp_len)) {
622 FAILED(SNMPERR_GENERR, "newkey did not decode properly.");
627 fprintf(stdout, "\n");
631 * Multiplex different test combinations.
633 * First clause is for Test #2, second clause is for (last) Test #3.
635 if (hashtype == usmHMACMD5AuthProtocol) {
636 hashtype = usmHMACSHA1AuthProtocol;
637 hashname = "usmHMACSHA1AuthProtocol (w/DES length kul's).";
638 properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES)
639 + BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
640 goto test_keychange_again;
642 } else if (properlength < BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1)) {
643 hashtype = usmHMACSHA1AuthProtocol;
644 hashname = "usmHMACSHA1AuthProtocol.";
645 properlength = BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1);
646 goto test_keychange_again;
651 } /* end test_keychange() */