text: #if !defined(HSS_H_)
  #define HSS_H_
  
  #include <stdlib.h>
  #include <stddef.h>
  #include "common_defs.h"
  
  /*
   * This is intended to be a usable (nontoy) implementation of the LMS
   * signature scheme.  The public data (public keys, signatures) are
   * precisely the same as the standard LMS implmentation; however it
   * strives to be more usable, in the following ways:
   *
   * - During signature generation time, it incrementally computes the next
   *   trees; that means that it doesn't need to generate the next Merkle tree
   *   from scratch on the 1025th signature.
   * - It doesn't try to hold the entire Merkle tree in memory; hence a level
   *   25 Merkle tree doesn't need to save 2**25 internal node values.  This
   *   does increase the time to generate the next siganture (as we will need
   *   to recompute some internal nodes); however by only a small constant factor
   * - It divides the private key into three parts, only one of which needs to
   *   be kept secret, and updated dynamically; the other parts are a working
   *   copy (that can be kept in RAM, and can be dynamically regenerated as
   *   needed), and some optional static (nonprivate) data (which can speed up
   *   the regeneration process)
   * - API to explicitly reserve the next N signatures (so that we don't need
   *   to update the secure storage copy quite as often)
   *
   *
   * We use a nonflat memory structure for the working_key.  Part of the reason
   * we use a flat representation elsewhere is so that they can be written (and
   * later read) to/from disk as required; we specifically assume that the
   * working_key is never written to disk. And, being able to use C structures
   * makes this rather nontrivial structure a bit more transparent
   *
   * Here is the intended order of usage:
   * Step 1: generate the private/public keypair:
   *   The API to do this is hss_generate_private_key; this is done once per
   *   private key; and you should write the private key to secure storage
   *   (which the passed update_private_key function could do)
   *
   * Step 2: (which you can do per restart):
   *   Load the private keypair into memory: hss_load_private_key
   *
   * Step 3: generate signatures (which you can do lots of time after you've
   *      loaded the key into memory):
   *   The API to do this is hss_generate_signature.  Note that this needs
   *   to update the private key state; the update_private_key function pointer
   *   can be useful here
   *
   * Step 4: (when you're done with the loaded private key; optional)
   *   Free the ephemeral copy (hss_free_working_key).  Note that this is not
   *   required for correctness; this just does a free()
   *
   *
   * One can also verify signatures at any time; all that needs is a public
   * key, a signature and a message; it's not a part of the intended order
   * of usage
   */
  
  struct hss_extra_info;
  
  /*
   * This will generate a fresh (unadorned) private key, with the selected
   * parameter set, the corresponding public key, and (optionally) the aux_data
   * that is associated with the private key.
   *
   * The generate_random function will be called when this function needs
   * random values; it is assumed to generate cryptographically secure ones.
   * We ask you to pass a function, rather than an array of random values,
   * to emphasize that we really do need fresh random data here; the security
   * of this entire system depends on it.
   *
   * levels, lm_type, lm_ots_type is the parameter set for the new key.
   * levels is the number of levels in the HSS hierarchy (1-8), while
   * lm_type[], lm_ots_type[] are arrays giving the parameter set of each
   * individual level; level i of the hierarchy will have LMS parameter set
   * lm_type[i] and OTS parameter set lm_ots_type[i] (where i=0 is the topmost
   * Merkle tree.
   *
   * The update_private_key function will be called when the private key is
   * generated; it is expected to write the private key to secure storage (and
   * the context pointer is a value that is passed to the update_private_key
   * function; it can be used to tell the update_private_key function where
   * in the secure storage to place the key).  If the passed update_private_key
   * function pointer is NULL, the private will will be written to the context
   * pointer (which is expected to hold 48 bytes of data)
   *
   * public_key is where the freshly generated public key will be placed, and
   * len_public_key is the size of the array (and this will generate an error
   * if the public key is larger than the array).  See the hss_get_public_key_len
   * function for the expected length of the public key
   *
   * aux_data is where to place internal nodes of the Merkle tree, and
   * len_aux_data is the length of the provided buffer.  This aux_data
   * is optional (pass in a NULL if it's not being used), but does significantly
   * speed the generate_working_key process.  It's envisioned use is to write
   * this aux_data to disk, and reread it when it's time to regenerate the
   * ephemeral key; it need not be kept in secure storage; revealing it doesn't
   * help an attacker to generate forgeries, and if an attacker does manage to
   * corrupt it, the regeneration process will detect the corruption and ignore
   * it.  Also, even if writing it to disk is not possible, passing in a
   * small array here and passing that to the initial regeneration call will
   * speed that up (and later ones can omit it; those will go slow, but at
   * least you got the speed up benefit the first time).
   *
   * One slightly tricky thing about aux data is that the required length of the
   * aux data; there are several different possible time/memory trade-offs.
   * Depending on the length, we'll automatically pick the fastest option that
   * fits. If we have N bytes available total, see hss_get_aux_data_len for
   * the amount of data we'll actually use (and so the amount you need to write
   * to disk)
   */
  bool hss_generate_private_key(
      bool (*generate_random)(void *output, size_t length),
      unsigned levels,
      const param_set_t *lm_type, const param_set_t *lm_ots_type,
      bool (*update_private_key)(unsigned char *private_key,
              size_t len_private_key, void *context),
          void *context,
      unsigned char *public_key, size_t len_public_key,
      unsigned char *aux_data, size_t len_aux_data,
      struct hss_extra_info *info);
  
  /*
   * This is the routine to load a private key into memory, and
   * initialize the working data structures; these data structures
   * allow us to generate signtures quickly
   *
   * The read_private_key is a function to read the private key from secure
   * storage, with context being a value passed to that function.
   * If the read_private_key pointer is NULL, we assume that the context
   * pointer points to the private key.
   * This assumes that the key has already been generated by
   * hss_generate_private_key
   *
   * memory_target is a value which gives a goal for the amount of memory (in
   * bytes) that this structure should take up.  There are a number of
   * time/memory trade-offs possible; the function uses this parameter as a
   * guide as to what trade-offs it should take.  This structure tries to
   * allocate no more than memory_target bytes; however it is considered
   * advisatory; this function will never fail beccause memory_target was too
   * small (so passing 0 will work, and will minimize the memory used)
   *
   * aux_data points to a buffer containing the auxiliary data generated
   * during the key generation process, with len_aux_data being the length
   * of the buffer.  Passing it a NULL means that we're not providing that
   * data (which is fine; it just means this will take longer)
   *
   * On success, this malloc's the ephemeral key (struct hss_working_key*) and
   * retursn it.  Because it mallocs it, it asssumes that the caller will
   * eventually free it (via the hss_free_working_key function, don't try
   * calling free() yourself)
   */
  struct hss_working_key;
  struct hss_working_key *hss_load_private_key(
      bool (*read_private_key)(unsigned char *private_key,
              size_t len_private_key, void *context),
          void *context,
      size_t memory_target,
      const unsigned char *aux_data, size_t len_aux_data, /* Optional */
      struct hss_extra_info *info);
  
  /*
   * Corresponding function to free the working key
   */
  void hss_free_working_key( struct hss_working_key * );
  
  /*
   * This will actually generate a signature
   *
   * working_key is the key that has been allocated by allocate_working_key and
   * initialied by hss_generate_working_key
   *
   * The update_private_key function will be called when the private key is
   * updated; it is expected to write the private key to secure storage (and the
   * context pointer is a value that is passed to the update_private_key
   * function; it can be used to tell the update_private_key function where
   * in the secure storage to place the key).  And, if it is NULL, the context
   * is expected to point to a copy of the private_key in RAM.
   * One distinction is that, on an update, len_private_key will be 8;
   * the update_private_key can choose to update only the first 8 bytes
   * of the private key (the rest will be unchanged), or write all
   * 48 bytes (private_key will point to the full 48 byte value)
   *
   * message, message_len are the message being signed
   *
   * signature is where the signature will be written, with signature_len being
   * the length of the buffer.  See the hss_get_signature_len function for the
   * expected signature length for this parameter set; if signature_len is too
   * short for the signature to fit, this will fail.
   */
  bool hss_generate_signature(
      struct hss_working_key *working_key,
      bool (*update_private_key)(unsigned char *private_key,
              size_t len_private_key, void *context),
      void *context,
      const void *message, size_t message_len,
      unsigned char *signature, size_t signature_len,
      struct hss_extra_info *info);
  
  /*
   * See hss_verify.h for the signature verfication routine; it's in a
   * separate file for those programs that only need to verify a signature
   */
  #include "hss_verify.h"
  
  /*
   * Lower level routines to allocate and initialize a working key.
   *
   * hss_load_working_key will do the work of the below routines; these are
   * provided separately in case you need more control (e.g. reuse an already
   * allocated working key)
   *
   * First, the routine to allocate (but not initialize) a working key.
   *
   * The levels/lm_type/lm_ots_type are the same parameter sets as in the
   * generate public/private keypair call; the parameter set must match the
   * values for the private key.
   *
   * memory_target is a value which gives a goal for the amount of memory that
   * this structure should take up.  There are a number of time/memory trade-offs
   * possible; the function uses this parameter as a guide as to what trade-offs
   * it should take.  This structure tries to allocate no more than memory_target
   * bytes; however it is considered advisatory; this function will never fail
   * beccause memory_target was too small (so passing 0 will work, and will
   * minimize the memory used)
   */
  struct hss_working_key *allocate_working_key(
      unsigned levels,
      const param_set_t *lm_type, const param_set_t *lm_ots_type,
      size_t memory_target,
      struct hss_extra_info *info);
  
  /*
   * This is called on reload (or initial key generation), it'll take the
   * working key that's been allocated by allocate_working_key, and initialize
   * it based on the private key; this working key is what we need to actually
   * generate signatures.
   *
   * The read_private_key is a function to read the private key from secure
   * storage, with context being a value passed to that function.
   * If NULL, we assume that the context pointer points to the private key
   *
   * aux_data points to a buffer containing the auxiliary data generated
   * during the key generation process, with len_aux_data being the length
   * of the buffer.  Passing it a NULL means that we're not providing that
   * data (which is fine; it just means this will take longer)
   *
   * working_key is a pointer to the allocated working key
   */
  bool hss_generate_working_key(
      bool (*read_private_key)(unsigned char *private_key,
              size_t len_private_key, void *context),
          void *context,
      const unsigned char *aux_data, size_t len_aux_data,  /* Optional */
      struct hss_working_key *working_key,
      struct hss_extra_info *info);
  
  /*
   * This will make sure that (at least) N signatures are reserved; that is, we
   * won't need to actually call the update function for the next N signatures
   * generated
   *
   * This can be useful if the update_private_key function is expensive.
   *
   * Note that if, N (or more) signatures are already reserved, this won't do
   * anything.
   */
  bool hss_reserve_signature(
      struct hss_working_key *w,
      bool (*update_private_key)(unsigned char *private_key,
              size_t len_private_key, void *context),
      void *context,
      unsigned sigs_to_reserve,
      struct hss_extra_info *info);
  
  /*
   * This will set the autoreserve, so that when the signing process runs out,
   * it will automatically reserve N more signatures (in addition to the one
   * that is being used for the current signature)
   *
   * This can be useful if the update_private_key function is expensive,
   * setting sigs_to_autoreserve=99 means will actually update the private
   * key once every 100 signatures
   */
  bool hss_set_autoreserve(
      struct hss_working_key *w,
      unsigned sigs_to_autoreserve,
      struct hss_extra_info *info);
  
  /*
   * This returns the required lengths for the various objects we export
   *
   * This is the length of the private key (which is written to secure storage)
   */
  size_t hss_get_private_key_len(unsigned levels,
                     const param_set_t *lm_type,
                     const param_set_t *lm_ots_type);
  #define HSS_MAX_PRIVATE_KEY_LEN (8 + 8 + SEED_LEN + 16)
  
  /*
   * This include file has the functions that contains the lengths of the other
   * public objects
   */
  #include "hss_common.h"
  
  /*
   * Get the signature length.  We don't put this in hss_common because we
   * assume we have a loaded private key
   * Returns 0 on error
   */
  size_t hss_get_signature_len_from_working_key(
                                          struct hss_working_key *working_key);
  
  /*
   * This returns the amount of aux data we use
   * This is slightly different from the above routines; given the bound on the
   * amount of data the aux_data is allowed to take (max_length), this returns
   * the amount of data we'll actually use
   */
  size_t hss_get_aux_data_len(size_t max_length,
                     unsigned levels,
                     const param_set_t *lm_type,
                     const param_set_t *lm_ots_type);
  
  /*
   * This returns the parameter set for a given private key.
   * This is here to solve a chicken-and-egg problem: the hss_working_key
   * must be initialized to the same parameter set as the private key,
   * but (other than this function, or somehow remembering it) there's
   * no way to retreive the parameter set.
   *
   * read_private_key/context will read the private key (if read_private_key is
   * NULL, context is assumed to point to the private key)
   *
   * On success, *levels will be set to the number of levels, and lm_type[]
   * and lm_ots_type[] will be set to the lm/ots parameter sets
   *
   * On success, this returns true; on failure (can't read the private key, or
   * the * private key is invalid), returns false 
   */
  bool hss_get_parameter_set( unsigned *levels,
                             param_set_t lm_type[ MAX_HSS_LEVELS ],
                             param_set_t lm_ots_type[ MAX_HSS_LEVELS ],
                             bool (*read_private_key)(unsigned char *private_key,
                                         size_t len_private_key, void *context),
                             void *context);
  
  enum hss_error_code {
      hss_error_none = 0,      /* I don't know nothing about any error */
  
      hss_range_normal_failures, /* There errors happen during normal use */
                               /* of the signature scheme */
      hss_error_bad_signature, /* Invalid signature */
      hss_error_private_key_expired, /* This private key has generated all */
                               /* the signatures it is allowed */
      hss_error_not_that_many_sigs_left, /* Reservation request failed */
                               /* because the key couldn't do that many  */
                               /* signatures */
  
      hss_range_bad_parameters, /* These errors are cause by the */
                            /* application passing in a bad parameter */
      hss_error_no_randomness, /* No RNG supplied */
      hss_error_bad_param_set, /* Application asked for an illegal parmaeter */
                               /* set */
      hss_error_buffer_overflow, /* Buffer provide not big enough */
      hss_error_got_null,      /* Application passed in a NULL pointer */
      hss_error_bad_aux,       /* Error with provided aux buffer */
      hss_error_no_private_buffer, /* Application didn't provide a place */
                               /* to put the private key */
      hss_error_incompatible_param_set, /* The parameter set of the working */
                               /* set didn't agree with the private key */
      hss_error_key_uninitialized, /* The working key used had never been */
                               /* initialized with a private key */
      hss_error_key_mismatch,  /* The working set and the private key */
                               /* do not correspond */
      hss_error_ctx_uninitialized, /* The incremental ctx wasn't initialized */
                               /* properly */
      hss_error_ctx_already_used, /* The ctx has already been used */
      hss_error_bad_public_key, /* Somehow, we got an invalid public key */
  
      hss_range_processing_error, /* These errors are cause by an */
                               /* error while processing */
      hss_error_bad_randomness, /* The RNG claimed failure */
      hss_error_private_key_write_failed, /* The write of the private key */
                               /* to NVRAM failed */
      hss_error_private_key_read_failed, /* The read of the private key */
                               /* from NVRAM failed */
      hss_error_out_of_memory, /* A malloc failure caused us to fail */
  
      hss_range_my_problem,    /* These are caused by internal errors */
                               /* within the HSS implementation */
      hss_error_internal,      /* Some internal assertion failed (should */
                               /* never happen) */
  };
  
  /*
   * This is the structure that allows us to pass noncritical information
   * to and from the above routines (without requiring us to add each
   * one as an additional parameter
   */
  struct hss_extra_info {
      int num_threads;     /* Number of threads we're allowed to ues */
      bool last_signature; /* Set if we just signed the last signature */
                           /* allowed by this private key */
      enum hss_error_code error_code; /* The more recent error detected */
  };
  
  /* Accessor APIs in case someone doesn't feel comfortable about reaching */
  /* into the structure */
  void hss_init_extra_info( struct hss_extra_info * );
  void hss_extra_info_set_threads( struct hss_extra_info *, int );
  bool hss_extra_info_test_last_signature( struct hss_extra_info * );
  enum hss_error_code hss_extra_info_test_error_code( struct hss_extra_info * );
  
  #endif /* HSS_H_ */
  