/* * hal_internal.h * -------------- * Internal API declarations for libhal. * * Authors: Rob Austein, Paul Selkirk * Copyright (c) 2015, NORDUnet A/S All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the NORDUnet nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _HAL_INTERNAL_H_ #define _HAL_INTERNAL_H_ #include #include "hal.h" #include "verilog_constants.h" /* * Everything in this file is part of the internal API, that is, * subject to change without notice. Nothing outside of libhal itself * should be looking at this file. */ /* * htonl and htons are not available in arm-none-eabi headers or libc. */ #ifndef STM32F4XX #include #else #ifdef __ARMEL__ /* little endian */ inline uint32_t htonl(uint32_t w) { return ((w & 0x000000ff) << 24) + ((w & 0x0000ff00) << 8) + ((w & 0x00ff0000) >> 8) + ((w & 0xff000000) >> 24); } inline uint16_t htons(uint16_t w) { return ((w & 0x00ff) << 8) + ((w & 0xff00) >> 8); } #else /* big endian */ #define htonl(x) (x) #define htons(x) (x) #endif #define ntohl htonl #define ntohs htons #endif /* * Low-level I/O convenience functions, moved here from hal.h * because they use symbols defined in verilog_constants.h. */ static inline hal_error_t hal_io_zero(const hal_core_t *core) { const uint8_t buf[4] = { 0, 0, 0, 0 }; return hal_io_write(core, ADDR_CTRL, buf, sizeof(buf)); } static inline hal_error_t hal_io_init(const hal_core_t *core) { const uint8_t buf[4] = { 0, 0, 0, CTRL_INIT }; return hal_io_write(core, ADDR_CTRL, buf, sizeof(buf)); } static inline hal_error_t hal_io_next(const hal_core_t *core) { const uint8_t buf[4] = { 0, 0, 0, CTRL_NEXT }; return hal_io_write(core, ADDR_CTRL, buf, sizeof(buf)); } static inline hal_error_t hal_io_wait_ready(const hal_core_t *core) { int limit = -1; return hal_io_wait(core, STATUS_READY, &limit); } static inline hal_error_t hal_io_wait_valid(const hal_core_t *core) { int limit = -1; return hal_io_wait(core, STATUS_VALID, &limit); } static inline hal_error_t hal_io_wait_ready2(const hal_core_t *core1, const hal_core_t *core2) { int limit = -1; return hal_io_wait2(core1, core2, STATUS_READY, &limit); } static inline hal_error_t hal_io_wait_valid2(const hal_core_t *core1, const hal_core_t *core2) { int limit = -1; return hal_io_wait2(core1, core2, STATUS_VALID, &limit); } /* * Static memory allocation on start-up. Don't use this except where * really necessary. By design, there's no way to free this, we don't * want to have to manage a heap. Intent is just to allow allocation * things like the large-ish ks_index arrays used by ks_flash.c from a * memory source external to the executable image file (eg, from the * secondary SDRAM chip on the Cryptech Alpha board). * * We shouldn't need this except on the HSM, so for now we don't bother * with implementing a version of this based on malloc() or sbrk(). */ extern void *hal_allocate_static_memory(const size_t size); /* * Longest hash block and digest we support at the moment. */ #define HAL_MAX_HASH_BLOCK_LENGTH SHA512_BLOCK_LEN #define HAL_MAX_HASH_DIGEST_LENGTH SHA512_DIGEST_LEN /* * Locks and critical sections. */ extern void hal_critical_section_start(void); extern void hal_critical_section_end(void); extern void hal_ks_lock(void); extern void hal_ks_unlock(void); extern void hal_task_yield(void); /* * Thread sleep. Currently used only for bad-PIN delays. */ extern void hal_sleep(const unsigned seconds); /* * Logging. */ typedef enum { HAL_LOG_DEBUG, HAL_LOG_INFO, HAL_LOG_WARN, HAL_LOG_ERROR, HAL_LOG_SILENT } hal_log_level_t; extern void hal_log_set_level(const hal_log_level_t level); extern void hal_log(const hal_log_level_t level, const char *format, ...); /* * Dispatch structures for RPC implementation. * * The breakdown of which functions go into which dispatch vectors is * based entirely on pesky details like making sure that the right * functions get linked in the right cases, and should not be * construed as making any particular sense in any larger context. * * In theory eventually we might want a fully general mechanism to * allow us to dispatch arbitrary groups of functions either locally * or remotely on a per-user basis. In practice, we probably want to * run everything on the HSM except for hashing and digesting, so just * code for that case initially while leaving the design open for a * more general mechanism later if warranted. * * So we have three cases: * * - We're the HSM, so we do everything locally (ie, we run the RPC * server functions. * * - We're the host, so we do everything remotely (ie, we do * everything using the client-side RPC calls. * * - We're the host but are doing hashing locally, so we do a mix. * This is slightly more complicated than it might at first appear, * because we must handle the case of one of the pkey functions * taking a hash context instead of a literal hash value, in which * case we have to extract the hash value from the context and * supply it to the pkey RPC client code as a literal value. * * ...Except that for PKCS #11 we also have to handle the case of * "session keys", ie, keys which are not stored on the HSM. * Apparently people really do use these, mostly for public keys, in * order to conserve expensive memory on the HSM. So this is another * feature of mixed mode: keys with HAL_KEY_FLAG_PROXIMATE set live on * the host, not in the HSM, and the mixed-mode pkey handlers deal * with the routing. In the other two modes we ignore the flag and * send everything where we were going to send it anyway. Restricting * the fancy key handling to mixed mode lets us drop this complexity * out entirely for applications which have no use for it. */ typedef struct { hal_error_t (*set_pin)(const hal_client_handle_t client, const hal_user_t user, const char * const newpin, const size_t newpin_len); hal_error_t (*login)(const hal_client_handle_t client, const hal_user_t user, const char * const newpin, const size_t newpin_len); hal_error_t (*logout)(const hal_client_handle_t client); hal_error_t (*logout_all)(void); hal_error_t (*is_logged_in)(const hal_client_handle_t client, const hal_user_t user); hal_error_t (*get_random)(void *buffer, const size_t length); hal_error_t (*get_version)(uint32_t *version); } hal_rpc_misc_dispatch_t; typedef struct { hal_error_t (*get_digest_length)(const hal_digest_algorithm_t alg, size_t *length); hal_error_t (*get_digest_algorithm_id)(const hal_digest_algorithm_t alg, uint8_t *id, size_t *len, const size_t len_max); hal_error
//======================================================================
//
// keywrap_mem.v
// -------------
// Memory for AES KEY WRAP processing.
//
//
// Author: Joachim Strombergson
// Copyright (c) 2018, NORDUnet A/S
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// - Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
//
// - Neither the name of the NORDUnet nor the names of its contributors may
//   be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================

module keywrap_mem (
                    input wire           clk,

                    input wire           api_we,
                    input wire [13 : 0]  api_addr,
                    input wire [31 : 0]  api_wr_data,
                    output wire [31 : 0] api_rd_data,

                    input wire           core_we,
                    input wire [12 : 0]  core_addr,
                    input wire [63 : 0]  core_wr_data,
                    output wire [63 : 0] core_rd_data
                   );


  //----------------------------------------------------------------
  // Registers and memories including control signals.
  //----------------------------------------------------------------
  reg [31 : 0] mem0 [0 : 8191];
  reg [31 : 0] mem0_data;
  reg [12 : 0] mem0_addr;
  reg          mem0_we;

  reg [31 : 0] mem1 [0 : 8191];
  reg [31 : 0] mem1_data;
  reg [12 : 0] mem1_addr;
  reg          mem1_we;


  //----------------------------------------------------------------
  // Wires.
  //----------------------------------------------------------------
  reg [31 : 0] api_rd_data0;
  reg [31 : 0] api_rd_data1;
  reg [31 : 0] muxed_api_rd_data;

  reg [31 : 0] core_rd_data0;
  reg [31 : 0] core_rd_data1;


  //----------------------------------------------------------------
  // Assignments for ports.
  //----------------------------------------------------------------
  assign api_rd_data    = muxed_api_rd_data;
  assign core_rd_data   = {core_rd_data0, core_rd_data1};


  //----------------------------------------------------------------
  // mem0_access
  //----------------------------------------------------------------
  always @(posedge clk)
    begin : mem0_access
      core_rd_data0   <= mem0[core_addr];
      api_rd_data0    <= mem0[api_addr[13 : 1]];

      if (mem0_we)
        mem0[mem0_addr] <= mem0_data;
    end


  //----------------------------------------------------------------
  // mem1_access
  //----------------------------------------------------------------
  always @(posedge clk)
    begin : mem1_access
      core_rd_data1   <= mem1[core_addr];
      api_rd_data1    <= mem1[api_addr[13 : 1]];

      if (mem1_we)
        mem1[mem1_addr] <= mem1_data;
    end


  //----------------------------------------------------------------
  // api_rd_data_mux
  //----------------------------------------------------------------
  always @*
    begin : api_rd_data_mux
      if (api_addr[0])
        muxed_api_rd_data = api_rd_data1;
      else
        muxed_api_rd_data = api_rd_data0;
    end


  //----------------------------------------------------------------
  // write_mux
  // Mux that handles priority of writes and selection
  // of memory bank to write api data to.
  //----------------------------------------------------------------
  always @*
    begin : write_mux
      mem0_data = 32'h0;
      mem0_addr = 13'h0;
      mem0_we   = 1'h0;
      mem1_data = 32'h0;
      mem1_addr = 13'h0;
      mem1_we   = 1'h0;

      if (core_we)
        begin
          mem0_data = core_wr_data[63 : 32];
          mem0_addr = core_addr;
          mem0_we   = 1'h1;
          mem1_data = core_wr_data[31 : 0];
          mem1_addr = core_addr;
          mem1_we   = 1'h1;
        end

      else if (api_we)
        begin
          mem0_addr = api_addr[13 : 1];
          mem0_data = api_wr_data;
          mem1_addr = api_addr[13 : 1];
          mem1_data = api_wr_data;

          if (api_addr[0])
            mem1_we   = 1'h1;
          else
            mem0_we   = 1'h1;
        end
    end
endmodule // keywrap_mem

//======================================================================
// EOF keywrap_mem.v
//======================================================================