michael@0: /* michael@0: * auth.c michael@0: * michael@0: * some bookkeeping functions for authentication functions michael@0: * michael@0: * David A. McGrew michael@0: * Cisco Systems, Inc. michael@0: */ michael@0: michael@0: /* michael@0: * michael@0: * Copyright (c) 2001-2006, Cisco Systems, Inc. michael@0: * All rights reserved. michael@0: * michael@0: * Redistribution and use in source and binary forms, with or without michael@0: * modification, are permitted provided that the following conditions michael@0: * are met: michael@0: * michael@0: * Redistributions of source code must retain the above copyright michael@0: * notice, this list of conditions and the following disclaimer. michael@0: * michael@0: * Redistributions in binary form must reproduce the above michael@0: * copyright notice, this list of conditions and the following michael@0: * disclaimer in the documentation and/or other materials provided michael@0: * with the distribution. michael@0: * michael@0: * Neither the name of the Cisco Systems, Inc. nor the names of its michael@0: * contributors may be used to endorse or promote products derived michael@0: * from this software without specific prior written permission. michael@0: * michael@0: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS michael@0: * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE michael@0: * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, michael@0: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES michael@0: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR michael@0: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) michael@0: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, michael@0: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) michael@0: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED michael@0: * OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: * michael@0: */ michael@0: michael@0: #include "auth.h" michael@0: michael@0: /* the debug module for authentiation */ michael@0: michael@0: debug_module_t mod_auth = { michael@0: 0, /* debugging is off by default */ michael@0: "auth func" /* printable name for module */ michael@0: }; michael@0: michael@0: michael@0: int michael@0: auth_get_key_length(const auth_t *a) { michael@0: return a->key_len; michael@0: } michael@0: michael@0: int michael@0: auth_get_tag_length(const auth_t *a) { michael@0: return a->out_len; michael@0: } michael@0: michael@0: int michael@0: auth_get_prefix_length(const auth_t *a) { michael@0: return a->prefix_len; michael@0: } michael@0: michael@0: int michael@0: auth_type_get_ref_count(const auth_type_t *at) { michael@0: return at->ref_count; michael@0: } michael@0: michael@0: /* michael@0: * auth_type_test() tests an auth function of type ct against michael@0: * test cases provided in a list test_data of values of key, data, and tag michael@0: * that is known to be good michael@0: */ michael@0: michael@0: /* should be big enough for most occasions */ michael@0: #define SELF_TEST_TAG_BUF_OCTETS 32 michael@0: michael@0: err_status_t michael@0: auth_type_test(const auth_type_t *at, const auth_test_case_t *test_data) { michael@0: const auth_test_case_t *test_case = test_data; michael@0: auth_t *a; michael@0: err_status_t status; michael@0: uint8_t tag[SELF_TEST_TAG_BUF_OCTETS]; michael@0: int i, case_num = 0; michael@0: michael@0: debug_print(mod_auth, "running self-test for auth function %s", michael@0: at->description); michael@0: michael@0: /* michael@0: * check to make sure that we have at least one test case, and michael@0: * return an error if we don't - we need to be paranoid here michael@0: */ michael@0: if (test_case == NULL) michael@0: return err_status_cant_check; michael@0: michael@0: /* loop over all test cases */ michael@0: while (test_case != NULL) { michael@0: michael@0: /* check test case parameters */ michael@0: if (test_case->tag_length_octets > SELF_TEST_TAG_BUF_OCTETS) michael@0: return err_status_bad_param; michael@0: michael@0: /* allocate auth */ michael@0: status = auth_type_alloc(at, &a, test_case->key_length_octets, michael@0: test_case->tag_length_octets); michael@0: if (status) michael@0: return status; michael@0: michael@0: /* initialize auth */ michael@0: status = auth_init(a, test_case->key); michael@0: if (status) { michael@0: auth_dealloc(a); michael@0: return status; michael@0: } michael@0: michael@0: /* zeroize tag then compute */ michael@0: octet_string_set_to_zero(tag, test_case->tag_length_octets); michael@0: status = auth_compute(a, test_case->data, michael@0: test_case->data_length_octets, tag); michael@0: if (status) { michael@0: auth_dealloc(a); michael@0: return status; michael@0: } michael@0: michael@0: debug_print(mod_auth, "key: %s", michael@0: octet_string_hex_string(test_case->key, michael@0: test_case->key_length_octets)); michael@0: debug_print(mod_auth, "data: %s", michael@0: octet_string_hex_string(test_case->data, michael@0: test_case->data_length_octets)); michael@0: debug_print(mod_auth, "tag computed: %s", michael@0: octet_string_hex_string(tag, test_case->tag_length_octets)); michael@0: debug_print(mod_auth, "tag expected: %s", michael@0: octet_string_hex_string(test_case->tag, michael@0: test_case->tag_length_octets)); michael@0: michael@0: /* check the result */ michael@0: status = err_status_ok; michael@0: for (i=0; i < test_case->tag_length_octets; i++) michael@0: if (tag[i] != test_case->tag[i]) { michael@0: status = err_status_algo_fail; michael@0: debug_print(mod_auth, "test case %d failed", case_num); michael@0: debug_print(mod_auth, " (mismatch at octet %d)", i); michael@0: } michael@0: if (status) { michael@0: auth_dealloc(a); michael@0: return err_status_algo_fail; michael@0: } michael@0: michael@0: /* deallocate the auth function */ michael@0: status = auth_dealloc(a); michael@0: if (status) michael@0: return status; michael@0: michael@0: /* michael@0: * the auth function passed the test case, so move on to the next test michael@0: * case in the list; if NULL, we'll quit and return an OK michael@0: */ michael@0: test_case = test_case->next_test_case; michael@0: ++case_num; michael@0: } michael@0: michael@0: return err_status_ok; michael@0: } michael@0: michael@0: michael@0: /* michael@0: * auth_type_self_test(at) performs auth_type_test on at's internal michael@0: * list of test data. michael@0: */ michael@0: michael@0: err_status_t michael@0: auth_type_self_test(const auth_type_t *at) { michael@0: return auth_type_test(at, at->test_data); michael@0: } michael@0: