16ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
26ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * crypto_kernel.c
36ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
46ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * header for the cryptographic kernel
56ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
66ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * David A. McGrew
76ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * Cisco Systems, Inc.
86ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
96ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * Copyright(c) 2001-2006 Cisco Systems, Inc.
126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * All rights reserved.
136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * Redistribution and use in source and binary forms, with or without
156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * modification, are permitted provided that the following conditions
166ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * are met:
176ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
186ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   Redistributions of source code must retain the above copyright
196ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   notice, this list of conditions and the following disclaimer.
206ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
216ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   Redistributions in binary form must reproduce the above
226ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   copyright notice, this list of conditions and the following
236ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   disclaimer in the documentation and/or other materials provided
246ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   with the distribution.
256ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
266ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   Neither the name of the Cisco Systems, Inc. nor the names of its
276ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   contributors may be used to endorse or promote products derived
286ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   from this software without specific prior written permission.
296ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
306ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
316ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
326ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
336ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
346ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
356ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
366ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
376ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
386ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
396ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
406ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
416ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * OF THE POSSIBILITY OF SUCH DAMAGE.
426ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
436ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
446ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
456ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
466ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include "alloc.h"
476ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
486ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include "crypto_kernel.h"
496ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
506ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/* the debug module for the crypto_kernel */
516ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
526ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgdebug_module_t mod_crypto_kernel = {
536ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  0,                  /* debugging is off by default */
546ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  "crypto kernel"     /* printable name for module   */
556ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org};
566ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
576ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
586ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * other debug modules that can be included in the kernel
596ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
606ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
616ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgextern debug_module_t mod_auth;
626ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgextern debug_module_t mod_cipher;
636ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgextern debug_module_t mod_stat;
646ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgextern debug_module_t mod_alloc;
656ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
666ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
676ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * cipher types that can be included in the kernel
686ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
696ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
706ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgextern cipher_type_t null_cipher;
716ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgextern cipher_type_t aes_icm;
726ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgextern cipher_type_t aes_cbc;
736ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
746ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
756ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
766ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * auth func types that can be included in the kernel
776ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
786ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
796ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgextern auth_type_t null_auth;
806ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgextern auth_type_t hmac;
816ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
826ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/* crypto_kernel is a global variable, the only one of its datatype */
836ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
846ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_t
856ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel = {
866ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  crypto_kernel_state_insecure,    /* start off in insecure state */
876ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  NULL,                            /* no cipher types yet         */
886ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  NULL,                            /* no auth types yet           */
896ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  NULL                             /* no debug modules yet        */
906ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org};
916ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
926ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#define MAX_RNG_TRIALS 25
936ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
946ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
956ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_init() {
966ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  err_status_t status;
976ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
986ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* check the security state */
996ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (crypto_kernel.state == crypto_kernel_state_secure) {
1006ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1016ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /*
1026ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * we're already in the secure state, but we've been asked to
1036ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * re-initialize, so we just re-run the self-tests and then return
1046ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     */
1056ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return crypto_kernel_status();
1066ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
1076ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1086ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* initialize error reporting system */
1096ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = err_reporting_init("crypto");
1106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* load debug modules */
1146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = crypto_kernel_load_debug_module(&mod_crypto_kernel);
1156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1166ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1176ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = crypto_kernel_load_debug_module(&mod_auth);
1186ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1196ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1206ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = crypto_kernel_load_debug_module(&mod_cipher);
1216ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1226ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1236ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = crypto_kernel_load_debug_module(&mod_stat);
1246ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1256ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1266ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = crypto_kernel_load_debug_module(&mod_alloc);
1276ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1286ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1296ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1306ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* initialize random number generator */
1316ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = rand_source_init();
1326ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1336ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1346ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1356ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* run FIPS-140 statistical tests on rand_source */
1366ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = stat_test_rand_source_with_repetition(rand_source_get_octet_string, MAX_RNG_TRIALS);
1376ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1386ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1396ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1406ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* initialize pseudorandom number generator */
1416ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = ctr_prng_init(rand_source_get_octet_string);
1426ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1436ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1446ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1456ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* run FIPS-140 statistical tests on ctr_prng */
1466ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = stat_test_rand_source_with_repetition(ctr_prng_get_octet_string, MAX_RNG_TRIALS);
1476ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1486ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1496ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1506ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* load cipher types */
1516ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = crypto_kernel_load_cipher_type(&null_cipher, NULL_CIPHER);
1526ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1536ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1546ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = crypto_kernel_load_cipher_type(&aes_icm, AES_ICM);
1556ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1566ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1576ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = crypto_kernel_load_cipher_type(&aes_cbc, AES_CBC);
1586ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1596ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1606ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1616ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* load auth func types */
1626ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = crypto_kernel_load_auth_type(&null_auth, NULL_AUTH);
1636ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1646ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1656ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = crypto_kernel_load_auth_type(&hmac, HMAC_SHA1);
1666ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
1676ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1686ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1696ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* change state to secure */
1706ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  crypto_kernel.state = crypto_kernel_state_secure;
1716ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1726ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return err_status_ok;
1736ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
1746ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1756ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
1766ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_status() {
1776ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  err_status_t status;
1786ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  kernel_cipher_type_t  *ctype = crypto_kernel.cipher_type_list;
1796ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  kernel_auth_type_t    *atype = crypto_kernel.auth_type_list;
1806ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  kernel_debug_module_t *dm    = crypto_kernel.debug_module_list;
1816ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1826ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* run FIPS-140 statistical tests on rand_source */
1836ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  printf("testing rand_source...");
1846ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = stat_test_rand_source_with_repetition(rand_source_get_octet_string, MAX_RNG_TRIALS);
1856ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status) {
1866ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("failed\n");
1876ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    crypto_kernel.state = crypto_kernel_state_insecure;
1886ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
1896ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
1906ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  printf("passed\n");
1916ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1926ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* for each cipher type, describe and test */
1936ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while(ctype != NULL) {
1946ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("cipher: %s\n", ctype->cipher_type->description);
1956ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("  instance count: %d\n", ctype->cipher_type->ref_count);
1966ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("  self-test: ");
1976ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    status = cipher_type_self_test(ctype->cipher_type);
1986ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (status) {
1996ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      printf("failed with error code %d\n", status);
2006ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      exit(status);
2016ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
2026ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("passed\n");
2036ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    ctype = ctype->next;
2046ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2056ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2066ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* for each auth type, describe and test */
2076ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while(atype != NULL) {
2086ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("auth func: %s\n", atype->auth_type->description);
2096ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("  instance count: %d\n", atype->auth_type->ref_count);
2106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("  self-test: ");
2116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    status = auth_type_self_test(atype->auth_type);
2126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (status) {
2136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      printf("failed with error code %d\n", status);
2146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      exit(status);
2156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
2166ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("passed\n");
2176ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    atype = atype->next;
2186ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2196ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2206ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* describe each debug module */
2216ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  printf("debug modules loaded:\n");
2226ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while (dm != NULL) {
2236ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("  %s ", dm->mod->name);
2246ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (dm->mod->on)
2256ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      printf("(on)\n");
2266ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    else
2276ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      printf("(off)\n");
2286ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    dm = dm->next;
2296ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2306ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2316ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return err_status_ok;
2326ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
2336ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2346ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
2356ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_list_debug_modules() {
2366ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  kernel_debug_module_t *dm = crypto_kernel.debug_module_list;
2376ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2386ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* describe each debug module */
2396ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  printf("debug modules loaded:\n");
2406ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while (dm != NULL) {
2416ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("  %s ", dm->mod->name);
2426ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (dm->mod->on)
2436ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      printf("(on)\n");
2446ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    else
2456ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      printf("(off)\n");
2466ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    dm = dm->next;
2476ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2486ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2496ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return err_status_ok;
2506ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
2516ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2526ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
2536ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_shutdown() {
2546ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  err_status_t status;
2556ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2566ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /*
2576ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org   * free dynamic memory used in crypto_kernel at present
2586ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org   */
2596ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2606ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* walk down cipher type list, freeing memory */
2616ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while (crypto_kernel.cipher_type_list != NULL) {
2626ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list;
2636ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    crypto_kernel.cipher_type_list = ctype->next;
2646ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    debug_print(mod_crypto_kernel,
2656ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org		"freeing memory for cipher %s",
2666ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org		ctype->cipher_type->description);
2676ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    crypto_free(ctype);
2686ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2696ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2706ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* walk down authetication module list, freeing memory */
2716ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while (crypto_kernel.auth_type_list != NULL) {
2726ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     kernel_auth_type_t *atype = crypto_kernel.auth_type_list;
2736ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     crypto_kernel.auth_type_list = atype->next;
2746ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     debug_print(mod_crypto_kernel,
2756ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org		"freeing memory for authentication %s",
2766ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org		atype->auth_type->description);
2776ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     crypto_free(atype);
2786ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2796ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2806ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* walk down debug module list, freeing memory */
2816ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while (crypto_kernel.debug_module_list != NULL) {
2826ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    kernel_debug_module_t *kdm = crypto_kernel.debug_module_list;
2836ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    crypto_kernel.debug_module_list = kdm->next;
2846ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    debug_print(mod_crypto_kernel,
2856ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org		"freeing memory for debug module %s",
2866ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org		kdm->mod->name);
2876ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    crypto_free(kdm);
2886ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2896ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2906ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* de-initialize random number generator */  status = rand_source_deinit();
2916ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status)
2926ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
2936ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2946ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* return to insecure state */
2956ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  crypto_kernel.state = crypto_kernel_state_insecure;
2966ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2976ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return err_status_ok;
2986ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
2996ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3007bcb8db4f328fefa2056e025e1d1b657ef98adcfscottmg@chromium.orgstatic INLINE err_status_t
3016ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_do_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id,
3026ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org				  int replace) {
3036ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  kernel_cipher_type_t *ctype, *new_ctype;
3046ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  err_status_t status;
3056ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3066ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* defensive coding */
3076ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (new_ct == NULL)
3086ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_bad_param;
3096ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (new_ct->id != id)
3116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_bad_param;
3126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* check cipher type by running self-test */
3146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = cipher_type_self_test(new_ct);
3156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status) {
3166ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
3176ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
3186ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3196ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* walk down list, checking if this type is in the list already  */
3206ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  ctype = crypto_kernel.cipher_type_list;
3216ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while (ctype != NULL) {
3226ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (id == ctype->id) {
3236ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      if (!replace)
3246ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	return err_status_bad_param;
3256ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      status = cipher_type_test(new_ct, ctype->cipher_type->test_data);
3266ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      if (status)
3276ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	return status;
3286ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      new_ctype = ctype;
3296ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      break;
3306ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
3316ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    else if (new_ct == ctype->cipher_type)
3326ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      return err_status_bad_param;
3336ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    ctype = ctype->next;
3346ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
3356ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3366ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* if not found, put new_ct at the head of the list */
3376ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (ctype == NULL) {
3386ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* allocate memory */
3396ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    new_ctype = (kernel_cipher_type_t *) crypto_alloc(sizeof(kernel_cipher_type_t));
3406ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (new_ctype == NULL)
3416ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      return err_status_alloc_fail;
3426ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    new_ctype->next = crypto_kernel.cipher_type_list;
3436ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3446ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /* set head of list to new cipher type */
3456ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    crypto_kernel.cipher_type_list = new_ctype;
3466ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
3476ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3486ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* set fields */
3496ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  new_ctype->cipher_type = new_ct;
3506ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  new_ctype->id = id;
3516ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3526ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* load debug module, if there is one present */
3536ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (new_ct->debug != NULL)
3546ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    crypto_kernel_load_debug_module(new_ct->debug);
3556ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* we could check for errors here */
3566ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3576ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return err_status_ok;
3586ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
3596ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3606ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
3616ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) {
3626ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return crypto_kernel_do_load_cipher_type(new_ct, id, 0);
3636ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
3646ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3656ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
3666ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_replace_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) {
3676ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return crypto_kernel_do_load_cipher_type(new_ct, id, 1);
3686ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
3696ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3706ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
3716ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_do_load_auth_type(auth_type_t *new_at, auth_type_id_t id,
3726ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org				int replace) {
3736ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  kernel_auth_type_t *atype, *new_atype;
3746ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  err_status_t status;
3756ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3766ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* defensive coding */
3776ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (new_at == NULL)
3786ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_bad_param;
3796ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3806ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (new_at->id != id)
3816ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_bad_param;
3826ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3836ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* check auth type by running self-test */
3846ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = auth_type_self_test(new_at);
3856ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status) {
3866ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return status;
3876ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
3886ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3896ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* walk down list, checking if this type is in the list already  */
3906ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  atype = crypto_kernel.auth_type_list;
3916ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while (atype != NULL) {
3926ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (id == atype->id) {
3936ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      if (!replace)
3946ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	return err_status_bad_param;
3956ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      status = auth_type_test(new_at, atype->auth_type->test_data);
3966ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      if (status)
3976ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	return status;
3986ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      new_atype = atype;
3996ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      break;
4006ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
4016ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    else if (new_at == atype->auth_type)
4026ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      return err_status_bad_param;
4036ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    atype = atype->next;
4046ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
4056ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4066ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* if not found, put new_at at the head of the list */
4076ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (atype == NULL) {
4086ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /* allocate memory */
4096ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    new_atype = (kernel_auth_type_t *)crypto_alloc(sizeof(kernel_auth_type_t));
4106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (new_atype == NULL)
4116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      return err_status_alloc_fail;
4126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    new_atype->next = crypto_kernel.auth_type_list;
4146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /* set head of list to new auth type */
4156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    crypto_kernel.auth_type_list = new_atype;
4166ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
4176ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4186ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* set fields */
4196ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  new_atype->auth_type = new_at;
4206ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  new_atype->id = id;
4216ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4226ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* load debug module, if there is one present */
4236ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (new_at->debug != NULL)
4246ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    crypto_kernel_load_debug_module(new_at->debug);
4256ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* we could check for errors here */
4266ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4276ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return err_status_ok;
4286ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4296ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
4306ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4316ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
4326ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) {
4336ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return crypto_kernel_do_load_auth_type(new_at, id, 0);
4346ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
4356ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4366ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
4376ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_replace_auth_type(auth_type_t *new_at, auth_type_id_t id) {
4386ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return crypto_kernel_do_load_auth_type(new_at, id, 1);
4396ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
4406ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4416ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4426ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcipher_type_t *
4436ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_get_cipher_type(cipher_type_id_t id) {
4446ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  kernel_cipher_type_t *ctype;
4456ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4466ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* walk down list, looking for id  */
4476ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  ctype = crypto_kernel.cipher_type_list;
4486ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while (ctype != NULL) {
4496ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (id == ctype->id)
4506ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      return ctype->cipher_type;
4516ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    ctype = ctype->next;
4526ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
4536ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4546ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* haven't found the right one, indicate failure by returning NULL */
4556ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return NULL;
4566ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
4576ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4586ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4596ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
4606ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_alloc_cipher(cipher_type_id_t id,
4616ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org			      cipher_pointer_t *cp,
4626ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org			      int key_len) {
4636ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  cipher_type_t *ct;
4646ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4656ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /*
4666ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org   * if the crypto_kernel is not yet initialized, we refuse to allocate
4676ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org   * any ciphers - this is a bit extra-paranoid
4686ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org   */
4696ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (crypto_kernel.state != crypto_kernel_state_secure)
4706ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_init_fail;
4716ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4726ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  ct = crypto_kernel_get_cipher_type(id);
4736ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (!ct)
4746ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_fail;
4756ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4766ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return ((ct)->alloc(cp, key_len));
4776ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
4786ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4796ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4806ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4816ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgauth_type_t *
4826ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_get_auth_type(auth_type_id_t id) {
4836ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  kernel_auth_type_t *atype;
4846ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4856ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* walk down list, looking for id  */
4866ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  atype = crypto_kernel.auth_type_list;
4876ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while (atype != NULL) {
4886ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (id == atype->id)
4896ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      return atype->auth_type;
4906ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    atype = atype->next;
4916ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
4926ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4936ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* haven't found the right one, indicate failure by returning NULL */
4946ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return NULL;
4956ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
4966ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4976ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
4986ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_alloc_auth(auth_type_id_t id,
4996ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org			 auth_pointer_t *ap,
5006ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org			 int key_len,
5016ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org			 int tag_len) {
5026ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  auth_type_t *at;
5036ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5046ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /*
5056ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org   * if the crypto_kernel is not yet initialized, we refuse to allocate
5066ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org   * any auth functions - this is a bit extra-paranoid
5076ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org   */
5086ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (crypto_kernel.state != crypto_kernel_state_secure)
5096ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_init_fail;
5106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  at = crypto_kernel_get_auth_type(id);
5126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (!at)
5136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_fail;
5146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return ((at)->alloc(ap, key_len, tag_len));
5166ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
5176ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5186ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
5196ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_load_debug_module(debug_module_t *new_dm) {
5206ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  kernel_debug_module_t *kdm, *new;
5216ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5226ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* defensive coding */
5236ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (new_dm == NULL)
5246ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_bad_param;
5256ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5266ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* walk down list, checking if this type is in the list already  */
5276ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  kdm = crypto_kernel.debug_module_list;
5286ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while (kdm != NULL) {
5296ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (strncmp(new_dm->name, kdm->mod->name, 64) == 0)
5306ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      return err_status_bad_param;
5316ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    kdm = kdm->next;
5326ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
5336ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5346ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* put new_dm at the head of the list */
5356ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* allocate memory */
5366ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  new = (kernel_debug_module_t *)crypto_alloc(sizeof(kernel_debug_module_t));
5376ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (new == NULL)
5386ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_alloc_fail;
5396ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5406ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* set fields */
5416ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  new->mod = new_dm;
5426ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  new->next = crypto_kernel.debug_module_list;
5436ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5446ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* set head of list to new cipher type */
5456ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  crypto_kernel.debug_module_list = new;
5466ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5476ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return err_status_ok;
5486ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
5496ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5506ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
5516ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_kernel_set_debug_module(char *name, int on) {
5526ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  kernel_debug_module_t *kdm;
5536ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5546ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* walk down list, checking if this type is in the list already  */
5556ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  kdm = crypto_kernel.debug_module_list;
5566ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while (kdm != NULL) {
5576ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (strncmp(name, kdm->mod->name, 64) == 0) {
5586ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      kdm->mod->on = on;
5596ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      return err_status_ok;
5606ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
5616ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    kdm = kdm->next;
5626ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
5636ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5646ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return err_status_fail;
5656ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
5666ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5676ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
5686ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgcrypto_get_random(unsigned char *buffer, unsigned int length) {
5696ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (crypto_kernel.state == crypto_kernel_state_secure)
5706ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return ctr_prng_get_octet_string(buffer, length);
5716ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  else
5726ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_fail;
5736ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
574