<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
<!-- lifted from troff+mdoc by doclifter -->
<refentry id="crypto9">
   

  <refmeta>
    <refentrytitle>CRYPTO</refentrytitle>

    <manvolnum>9</manvolnum>
  </refmeta>

   

  <refnamediv id="purpose">
    <refname>crypto</refname>

    <refpurpose>API for cryptographic services in the kernel</refpurpose>
  </refnamediv>

   

  <literallayout remap="Bd"><funcsynopsis><funcsynopsisinfo>
#define CRYPTO_SYMQ  0x1
#define CRYPTO_ASYMQ 0x2

#define EALG_MAX_BLOCK_LEN      16

struct cryptoini { int cri_alg; 
                   int cri_klen; 
                   int cri_rnd; 
                   caddr_t cri_key; 
                   u_int8_t cri_iv[EALG_MAX_BLOCK_LEN]; 
                   struct cryptoini  *cri_next; 
}; </funcsynopsisinfo><funcsynopsisinfo>struct cryptodesc { int crd_skip; 
                    int crd_len; 
                    int crd_inject; 
                    int crd_flags; 
                    struct cryptoini   CRD_INI; 
                    struct cryptodesc *crd_next; 
}; </funcsynopsisinfo><funcsynopsisinfo>struct cryptop { TAILQ_ENTRY(cryptop) crp_next; 
                 u_int64_t crp_sid; 
                 int       crp_ilen; 
                 int       crp_olen; 
                 int       crp_etype; 
                 int       crp_flags; 
                 caddr_t   crp_buf; 
                 caddr_t   crp_opaque; 
                 struct cryptodesc *crp_desc; 
                 int              (*crp_callback) (struct cryptop *); 
                 caddr_t            crp_mac; 
}; </funcsynopsisinfo><funcsynopsisinfo>struct crparam { caddr_t         crp_p; 
                 u_int           crp_nbits; 
}; </funcsynopsisinfo><funcsynopsisinfo>
#define CRK_MAXPARAM    8

struct cryptkop { TAILQ_ENTRY(cryptkop) krp_next; 
                  u_int              krp_op;         /* ie. CRK_MOD_EXP or other */ 
                  u_int              krp_status;     /* return status */ 
                  u_short            krp_iparams;    /* # of input parameters */ 
                  u_short            krp_oparams;    /* # of output parameters */ 
                  u_int32_t          krp_hid; 
                  struct crparam     krp_param[CRK_MAXPARAM]; 
                  int               (*krp_callback)(struct cryptkop *); 
}; </funcsynopsisinfo></funcsynopsis></literallayout>

   

  <!---->

   

  <para><command remap="Nm">crypto </command> is a framework for drivers of
  cryptographic hardware to register with the kernel so “consumers” (other
  kernel subsystems, and users through the
  <replaceable>/dev/crypto</replaceable> device) are able to make use of it.
  Drivers register with the framework the algorithms they support, and provide
  entry points (functions) the framework may call to establish, use, and tear
  down sessions. Sessions are used to cache cryptographic information in a
  particular driver (or associated hardware), so initialization is not needed
  with every request. Consumers of cryptographic services pass a set of
  descriptors that instruct the framework (and the drivers registered with it)
  of the operations that should be applied on the data (more than one
  cryptographic operation can be requested).</para>

   

  <sbr />

   Keying operations are supported as well. Unlike the symmetric operators described above, these sessionless commands perform mathematical operations using input and output parameters. 

  <sbr />

   Since the consumers may not be associated with a process, drivers may not 

  <citerefentry>
    <refentrytitle>sleep</refentrytitle>

    <manvolnum>9</manvolnum>
  </citerefentry>

   . The same holds for the framework. Thus, a callback mechanism is used to notify a consumer that a request has been completed (the callback is specified by the consumer on an per-request basis). The callback is invoked by the framework whether the request was successfully completed or not. An error indication is provided in the latter case. A specific error code, 

  <errorcode>EAGAIN</errorcode>

   , is used to indicate that a session number has changed and that the request may be re-submitted immediately with the new session number. Errors are only returned to the invoking function if not enough information to call the callback is available (meaning, there was a fatal error in verifying the arguments). For session initialization and teardown there is no callback mechanism used. 

  <sbr />

   The crypto_newsession(); routine is called by consumers of cryptographic services (such as the 

  <citerefentry>
    <refentrytitle>ipsec</refentrytitle>

    <manvolnum>4</manvolnum>
  </citerefentry>

   stack) that wish to establish a new session with the framework. On success, the first argument will contain the Session Identifier (SID). The second argument contains all the necessary information for the driver to establish the session. The third argument indicates whether a hardware driver (1) should be used or not (0). The various fields in the 

  <vartype>cryptoini</vartype>

   structure are: 

  <variablelist remap="Bl -tag -width .Va cri_next">
    <varlistentry>
      <term>
        <varname>cri_alg</varname>
      </term>

      <listitem>
        <para>Contains an algorithm identifier. Currently supported algorithms
        are:</para>

        <sbr />

        <table remap="Bl -tag -width .Dv CRYPTO_RIPEMD160_HMAC -compact">
          <title />

          <tgroup cols="1">
            <tbody>
              <row>
                <entry>
                  <constant>CRYPTO_DES_CBC</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_3DES_CBC</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_BLF_CBC</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_CAST_CBC</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_SKIPJACK_CBC</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_MD5_HMAC</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_SHA1_HMAC</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_RIPEMD160_HMAC</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_MD5_KPDK</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_SHA1_KPDK</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_AES_CBC</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_ARC4</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_MD5</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_SHA1</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_SHA2_HMAC</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_NULL_HMAC</constant>
                </entry>
              </row>

              <row>
                <entry>
                  <constant>CRYPTO_NULL_CBC</constant>
                </entry>
              </row>
            </tbody>
          </tgroup>
        </table>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>cri_klen</varname>
      </term>

      <listitem>
        <para>Specifies the length of the key in bits, for variable-size key
        algorithms.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>cri_rnd</varname>
      </term>

      <listitem>
        <para>Specifies the number of rounds to be used with the algorithm,
        for variable-round algorithms.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>cri_key</varname>
      </term>

      <listitem>
        <para>Contains the key to be used with the algorithm.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>cri_iv</varname>
      </term>

      <listitem>
        <para>Contains an explicit initialization vector (IV), if it does not
        prefix the data. This field is ignored during initialization. If no IV
        is explicitly passed (see below on details), a random IV is used by
        the device driver processing the request.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>cri_next</varname>
      </term>

      <listitem><para>Contains a pointer to another</para>
      <vartype>cryptoini</vartype> structure. Multiple such structures may be
      linked to establish multi-algorithm sessions (<citerefentry>
          <refentrytitle>ipsec</refentrytitle>

          <manvolnum>4</manvolnum>
        </citerefentry> is an example consumer of such a feature).</listitem>
    </varlistentry>
  </variablelist>

   

  <sbr />

   

  <para>The</para>

   

  <vartype>cryptoini</vartype>

   structure and its contents will not be modified by the framework (or the drivers used). Subsequent requests for processing that use the SID returned will avoid the cost of re-initializing the hardware (in essence, SID acts as an index in the session cache of the driver). 

  <sbr />

   crypto_freesession(); is called with the SID returned by crypto_newsession(); to disestablish the session. 

  <sbr />

   crypto_dispatch(); is called to process a request. The various fields in the 

  <vartype>cryptop</vartype>

   structure are: 

  <variablelist remap="Bl -tag -width .Va crp_callback">
    <varlistentry>
      <term>
        <varname>crp_sid</varname>
      </term>

      <listitem>
        <para>Contains the SID.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>crp_ilen</varname>
      </term>

      <listitem>
        <para>Indicates the total length in bytes of the buffer to be
        processed.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>crp_olen</varname>
      </term>

      <listitem>
        <para>On return, contains the total length of the result. For
        symmetric crypto operations, this will be the same as the input
        length. This will be used if the framework needs to allocate a new
        buffer for the result (or for re-formatting the input).</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>crp_callback</varname>
      </term>

      <listitem>
        <para>This routine is invoked upon completion of the request, whether
        successful or not. It is invoked through the crypto_done(); routine.
        If the request was not successful, an error code is set in the
        <varname>crp_etype</varname> field. It is the responsibility of the
        callback routine to set the appropriate <citerefentry>
            <refentrytitle>spl</refentrytitle>

            <manvolnum>9</manvolnum>
          </citerefentry> level.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>crp_etype</varname>
      </term>

      <listitem><para>Contains the error type, if any errors were encountered,
      or zero if the request was successfully processed. If the
      <errorcode>EAGAIN</errorcode> error code is returned, the SID has
      changed (and has been recorded in the <varname>crp_sid</varname> field).
      The consumer should record the new SID and use it in all subsequent
      requests. In this case, the request may be re-submitted immediately.
      This mechanism is used by the framework to perform session migration
      (move a session from one driver to another, because of availability,
      performance, or other considerations).</para> <sbr /> Note that this
      field only makes sense when examined by the callback routine specified
      in <varname>crp_callback</varname>. Errors are returned to the invoker
      of crypto_process(); only when enough information is not present to call
      the callback routine (i.e., if the pointer passed is
      <constant>NULL</constant> or if no callback routine was
      specified).</listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>crp_flags</varname>
      </term>

      <listitem>
        <para>Is a bitmask of flags associated with this request. Currently
        defined flags are:</para>

        <variablelist remap="Bl -tag -width .Dv CRYPTO_F_IMBUF">
          <varlistentry>
            <term>
              <constant>CRYPTO_F_IMBUF</constant>
            </term>

            <listitem>
              <para>The buffer pointed to by <varname>crp_buf</varname> is an
              mbuf chain.</para>
            </listitem>
          </varlistentry>
        </variablelist>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>crp_buf</varname>
      </term>

      <listitem>
        <para>Points to the input buffer. On return (when the callback is
        invoked), it contains the result of the request. The input buffer may
        be an mbuf chain or a contiguous buffer, depending on
        <varname>crp_flags</varname>.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>crp_opaque</varname>
      </term>

      <listitem>
        <para>This is passed through the crypto framework untouched and is
        intended for the invoking application's use.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>crp_desc</varname>
      </term>

      <listitem>
        <para>This is a linked list of descriptors. Each descriptor provides
        information about what type of cryptographic operation should be done
        on the input buffer. The various fields are:</para>

        <variablelist remap="Bl -tag -width .Va crd_inject">
          <varlistentry>
            <term>
              <varname>crd_skip</varname>
            </term>

            <listitem>
              <para>The offset in the input buffer where processing should
              start.</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>
              <varname>crd_len</varname>
            </term>

            <listitem>
              <para>How many bytes, after <varname>crd_skip</varname>, should
              be processed.</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>
              <varname>crd_inject</varname>
            </term>

            <listitem>
              <para>Offset from the beginning of the buffer to insert any
              results. For encryption algorithms, this is where the
              initialization vector (IV) will be inserted when encrypting or
              where it can be found when decrypting (subject to
              <varname>crd_flags</varname>). For MAC algorithms, this is where
              the result of the keyed hash will be inserted.</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>
              <varname>crd_flags</varname>
            </term>

            <listitem>
              <para>The following flags are defined:</para>

              <variablelist remap="Bl -tag -width .Dv CRD_F_IV_EXPLICIT">
                <varlistentry>
                  <term>
                    <constant>CRD_F_ENCRYPT</constant>
                  </term>

                  <listitem>
                    <para>For encryption algorithms, this bit is set when
                    encryption is required (when not set, decryption is
                    performed).</para>
                  </listitem>
                </varlistentry>

                <varlistentry>
                  <term>
                    <constant>CRD_F_IV_PRESENT</constant>
                  </term>

                  <listitem>
                    <para>For encryption algorithms, this bit is set when the
                    IV already precedes the data, so the
                    <varname>crd_inject</varname> value will be ignored and no
                    IV will be written in the buffer. Otherwise, the IV used
                    to encrypt the packet will be written at the location
                    pointed to by <varname>crd_inject</varname>. The IV length
                    is assumed to be equal to the blocksize of the encryption
                    algorithm. Some applications that do special “IV cooking”,
                    such as the half-IV mode in <citerefentry>
                        <refentrytitle>ipsec</refentrytitle>

                        <manvolnum>4</manvolnum>
                      </citerefentry>, can use this flag to indicate that the
                    IV should not be written on the packet. This flag is
                    typically used in conjunction with the
                    <constant>CRD_F_IV_EXPLICIT</constant> flag.</para>
                  </listitem>
                </varlistentry>

                <varlistentry>
                  <term>
                    <constant>CRD_F_IV_EXPLICIT</constant>
                  </term>

                  <listitem>
                    <para>For encryption algorithms, this bit is set when the
                    IV is explicitly provided by the consumer in the
                    <varname>cri_iv</varname> fields. Otherwise, for
                    encryption operations the IV is provided for by the driver
                    used to perform the operation, whereas for decryption
                    operations it is pointed to by the
                    <varname>crd_inject</varname> field. This flag is
                    typically used when the IV is calculated “on the fly” by
                    the consumer, and does not precede the data (some
                    <citerefentry>
                        <refentrytitle>ipsec</refentrytitle>

                        <manvolnum>4</manvolnum>
                      </citerefentry> configurations, and the encrypted swap
                    are two such examples).</para>
                  </listitem>
                </varlistentry>

                <varlistentry>
                  <term>
                    <constant>CRD_F_COMP</constant>
                  </term>

                  <listitem>
                    <para>For compression algorithms, this bit is set when
                    compression is required (when not set, decompression is
                    performed).</para>
                  </listitem>
                </varlistentry>
              </variablelist>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>
              <varname>CRD_INI</varname>
            </term>

            <listitem><para>This</para> <vartype>cryptoini</vartype> structure
            will not be modified by the framework or the device drivers. Since
            this information accompanies every cryptographic operation
            request, drivers may re-initialize state on-demand (typically an
            expensive operation). Furthermore, the cryptographic framework may
            re-route requests as a result of full queues or hardware failure,
            as described above.</listitem>
          </varlistentry>

          <varlistentry>
            <term>
              <varname>crd_next</varname>
            </term>

            <listitem>
              <para>Point to the next descriptor. Linked operations are useful
              in protocols such as <citerefentry>
                  <refentrytitle>ipsec</refentrytitle>

                  <manvolnum>4</manvolnum>
                </citerefentry>, where multiple cryptographic transforms may
              be applied on the same block of data.</para>
            </listitem>
          </varlistentry>
        </variablelist>
      </listitem>
    </varlistentry>
  </variablelist>

   

  <sbr />

   

  <para>crypto_getreq(); allocates a</para>

   

  <vartype>cryptop</vartype>

   structure with a linked list of as many 

  <vartype>cryptodesc</vartype>

   structures as were specified in the argument passed to it. 

  <sbr />

   crypto_freereq(); deallocates a structure 

  <vartype>cryptop</vartype>

   and any 

  <vartype>cryptodesc</vartype>

   structures linked to it. Note that it is the responsibility of the callback routine to do the necessary cleanups associated with the opaque field in the 

  <vartype>cryptop</vartype>

   structure. 

  <sbr />

   crypto_kdispatch(); is called to perform a keying operation. The various fields in the 

  <vartype>cryptkop</vartype>

   structure are: 

  <variablelist remap="Bl -tag -width .Va krp_callback">
    <varlistentry>
      <term>
        <varname>krp_op</varname>
      </term>

      <listitem>
        <para>Operation code, such as <constant>CRK_MOD_EXP</constant>.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>krp_status</varname>
      </term>

      <listitem>
        <para>Return code. This <varname>errno</varname>-style variable
        indicates whether lower level reasons for operation failure.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>krp_iparams</varname>
      </term>

      <listitem>
        <para>Number if input parameters to the specified operation. Note that
        each operation has a (typically hardwired) number of such
        parameters.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>krp_oparams</varname>
      </term>

      <listitem>
        <para>Number if output parameters from the specified operation. Note
        that each operation has a (typically hardwired) number of such
        parameters.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>krp_kvp</varname>
      </term>

      <listitem>
        <para>An array of kernel memory blocks containing the
        parameters.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>krp_hid</varname>
      </term>

      <listitem>
        <para>Identifier specifying which low-level driver is being
        used.</para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>
        <varname>krp_callback</varname>
      </term>

      <listitem>
        <para>Callback called on completion of a keying operation.</para>
      </listitem>
    </varlistentry>
  </variablelist>

   

  <!-- body begins here -->

   

  <refsynopsisdiv id="synopsis">
    <funcsynopsis>
      <funcsynopsisinfo>
#include &lt;opencrypto/cryptodev.h&gt;
</funcsynopsisinfo>

      <funcprototype>
        <funcdef><function>int32_t</function> crypto_get_driverid</funcdef>

        <paramdef>
          <parameter>u_int8_t</parameter>
        </paramdef>
      </funcprototype>

      <funcprototype>
        <funcdef>int <function>crypto_register</function></funcdef>

        <paramdef>
          <parameter>u_int32_t</parameter>
        </paramdef>

        <paramdef>
          <parameter>int</parameter>
        </paramdef>

        <paramdef>
          <parameter>u_int16_t</parameter>
        </paramdef>

        <paramdef>
          <parameter>u_int32_t</parameter>
        </paramdef>

        <paramdef>int (*)(<parameter>void</parameter>*</paramdef>

        <paramdef>u_int32_t * <parameter /></paramdef>

        <paramdef>struct cryptoini *)<parameter /></paramdef>

        <paramdef>int (*)(<parameter>void</parameter>*</paramdef>

        <paramdef>u_int64_t )</paramdef>

        <paramdef>int (*)(<parameter>void</parameter>*</paramdef>

        <paramdef>struct cryptop *)</paramdef>

        <paramdef>void * <parameter /></paramdef>
      </funcprototype>

      <funcprototype>
        <funcdef>int <function>crypto_kregister</function></funcdef>

        <paramdef>
          <parameter>u_int32_t</parameter>
        </paramdef>

        <paramdef>
          <parameter>int</parameter>
        </paramdef>

        <paramdef>
          <parameter>u_int32_t</parameter>
        </paramdef>

        <paramdef>int (*)(<parameter>void</parameter>*</paramdef>

        <paramdef>struct cryptkop *)</paramdef>

        <paramdef>void * <parameter /></paramdef>
      </funcprototype>

      <funcprototype>
        <funcdef>int <function>crypto_unregister</function></funcdef>

        <paramdef>
          <parameter>u_int32_t</parameter>
        </paramdef>

        <paramdef>
          <parameter>int</parameter>
        </paramdef>
      </funcprototype>

      <funcprototype>
        <funcdef>int <function>crypto_unregister_all</function></funcdef>

        <paramdef>
          <parameter>u_int32_t</parameter>
        </paramdef>
      </funcprototype>

      <funcprototype>
        <funcdef>void <function>crypto_done</function></funcdef>

        <paramdef>struct <parameter>cryptop</parameter>*</paramdef>
      </funcprototype>

      <funcprototype>
        <funcdef>void <function>crypto_kdone</function></funcdef>

        <paramdef>struct <parameter>cryptkop</parameter>*</paramdef>
      </funcprototype>

      <funcprototype>
        <funcdef>int <function>crypto_newsession</function></funcdef>

        <paramdef>u_int64_t * <parameter /></paramdef>

        <paramdef>struct <parameter>cryptoini</parameter>*</paramdef>

        <paramdef>
          <parameter>int</parameter>
        </paramdef>
      </funcprototype>

      <funcprototype>
        <funcdef>int <function>crypto_freesession</function></funcdef>

        <paramdef>
          <parameter>u_int64_t</parameter>
        </paramdef>
      </funcprototype>

      <funcprototype>
        <funcdef>int <function>crypto_dispatch</function></funcdef>

        <paramdef>struct <parameter>cryptop</parameter>*</paramdef>
      </funcprototype>

      <funcprototype>
        <funcdef>int <function>crypto_kdispatch</function></funcdef>

        <paramdef>struct <parameter>cryptkop</parameter>*</paramdef>
      </funcprototype>

      <funcprototype>
        <funcdef>int <function>crypto_unblock</function></funcdef>

        <paramdef>
          <parameter>u_int32_t</parameter>
        </paramdef>

        <paramdef>
          <parameter>int</parameter>
        </paramdef>
      </funcprototype>

      <funcprototype>
        <funcdef>struct <function>cryptop</function> *crypto_getreq</funcdef>

        <paramdef>
          <parameter>int</parameter>
        </paramdef>
      </funcprototype>

      <funcprototype>
        <funcdef>void <function>crypto_freereq</function></funcdef>

        <paramdef>
          <parameter>void</parameter>
        </paramdef>
      </funcprototype>
    </funcsynopsis>
  </refsynopsisdiv>

   

  <refsect1 id="driverside_api"><title>DRIVER-SIDE API</title> <para>The
  crypto_get_driverid(,); crypto_register(,); crypto_kregister(,);
  crypto_unregister(,); crypto_unblock(,); and crypto_done(); routines are
  used by drivers that provide support for cryptographic primitives to
  register and unregister with the kernel crypto services framework. Drivers
  must first use the crypto_get_driverid(); function to acquire a driver
  identifier, specifying the <emphasis remap="Fa">cc_flags</emphasis> as an
  argument (normally 0, but software-only drivers should specify
  <constant>CRYPTOCAP_F_SOFTWARE</constant>). For each algorithm the driver
  supports, it must then call crypto_register(.); The first two arguments are
  the driver and algorithm identifiers. The next two arguments specify the
  largest possible operator length (in bits, important for public key
  operations) and flags for this algorithm. The last four arguments must be
  provided in the first call to crypto_register(); and are ignored in all
  subsequent calls. They are pointers to three driver-provided functions that
  the framework may call to establish new cryptographic context with the
  driver, free already established context, and ask for a request to be
  processed (encrypt, decrypt, etc.); and an opaque parameter to pass when
  calling each of these routines. crypto_unregister(); is called by drivers
  that wish to withdraw support for an algorithm. The two arguments are the
  driver and algorithm identifiers, respectively. Typically, drivers for
  PCMCIA crypto cards that are being ejected will invoke this routine for all
  algorithms supported by the card. crypto_unregister_all(); will unregister
  all algorithms registered by a driver and the driver will be disabled (no
  new sessions will be allocated on that driver, and any existing sessions
  will be migrated to other drivers). The same will be done if all algorithms
  associated with a driver are unregistered one by one.</para> <para>The
  calling convention for the three driver-supplied routines is:</para>
  <itemizedlist remap="Bl -item -compact">
      <listitem>
        <para><type remap="Ft"> int </type> (*newsession)(void *, u_int32_t *,
        struct cryptoini *);</para>
      </listitem>

      <listitem>
        <para><type remap="Ft"> int </type> (*freesession)(void *,
        u_int64_t);</para>
      </listitem>

      <listitem>
        <para><type remap="Ft"> int </type> (*process)(void *, struct cryptop
        *);</para>
      </listitem>

      <listitem>
        <para><type remap="Ft"> int </type> (*kprocess)(void *, struct
        cryptkop *);</para>
      </listitem>
    </itemizedlist> <para>On invocation, the first argument to all routines is
  an opaque data value supplied when the algorithm is registered with
  crypto_register(.); The second argument to newsession(); contains the driver
  identifier obtained via crypto_get_driverid(.); On successful return, it
  should contain a driver-specific session identifier. The third argument is
  identical to that of crypto_newsession(.);</para> <para>The freesession();
  routine takes as arguments the opaque data value and the SID (which is the
  concatenation of the driver identifier and the driver-specific session
  identifier). It should clear any context associated with the session (clear
  hardware registers, memory, etc.).</para> <para>The process(); routine is
  invoked with a request to perform crypto processing. This routine must not
  block, but should queue the request and return immediately. Upon processing
  the request, the callback routine should be invoked. In case of an
  unrecoverable error, the error indication must be placed in the
  <varname>crp_etype</varname> field of the</para> <vartype>cryptop</vartype>
  structure. When the request is completed, or an error is detected, the
  process(); routine should invoke crypto_done(.); Session migration may be
  performed, as mentioned previously. <para>In case of a temporary resource
  exhaustion, the process(); routine may return
  <errorcode>ERESTART</errorcode> in which case the crypto services will
  requeue the request, mark the driver as “blocked”, and stop submitting
  requests for processing. The driver is then responsible for notifying the
  crypto services when it is again able to process requests through the
  crypto_unblock(); routine. This simple flow control mechanism should only be
  used for short-lived resource exhaustion as it causes operations to be
  queued in the crypto layer. Doing so is preferable to returning an error in
  such cases as it can cause network protocols to degrade performance by
  treating the failure much like a lost packet.</para> <para>The kprocess();
  routine is invoked with a request to perform crypto key processing. This
  routine must not block, but should queue the request and return immediately.
  Upon processing the request, the callback routine should be invoked. In case
  of an unrecoverable error, the error indication must be placed in the
  <varname>krp_status</varname> field of the</para>
  <vartype>cryptkop</vartype> structure. When the request is completed, or an
  error is detected, the kprocess(); routine should invoked
  crypto_kdone(.);</refsect1>

   

  <refsect1 id="return_values"><title>RETURN VALUES</title>
  <para>crypto_register(); crypto_kregister(); crypto_unregister();
  crypto_newsession(); crypto_freesession(,); and crypto_unblock(); return 0
  on success, or an error code on failure. crypto_get_driverid(); returns a
  non-negative value on error, and -1 on failure. crypto_getreq(); returns a
  pointer to a</para> <vartype>cryptop</vartype> structure and
  <constant>NULL</constant> on failure. crypto_dispatch(); returns
  <errorcode>EINVAL</errorcode> if its argument or the callback function was
  <constant>NULL</constant>, and 0 otherwise. The callback is provided with an
  error code in case of failure, in the <varname>crp_etype</varname>
  field.</refsect1>

   

  <refsect1 id="files">
    <title>FILES</title>

    <variablelist remap="Bl -tag -width .Pa sys/opencrypto/crypto.c">
      <varlistentry>
        <term>
          <filename>sys/opencrypto/crypto.c</filename>
        </term>

        <listitem>
          <para>most of the framework code</para>
        </listitem>
      </varlistentry>
    </variablelist>
  </refsect1>

   

  <refsect1 id="see_also">
    <title>SEE ALSO</title>

    <para><citerefentry>
        <refentrytitle>ipsec</refentrytitle>

        <manvolnum>4</manvolnum>
      </citerefentry>, <citerefentry>
        <refentrytitle>malloc</refentrytitle>

        <manvolnum>9</manvolnum>
      </citerefentry>, <citerefentry>
        <refentrytitle>sleep</refentrytitle>

        <manvolnum>9</manvolnum>
      </citerefentry></para>
  </refsect1>

   

  <refsect1 id="history">
    <title>HISTORY</title>

    <para>The cryptographic framework first appeared in <productname>OpenBSD
    2.7</productname> and was written by <phrase role="author ">Angelos D.
    Keromytis &lt;angelos@openbsd.org&gt;</phrase>. It was ported to FreeBSD
    by Sam Leffler. It was ported to Openswan by David McCullough.</para>
  </refsect1>

   

  <refsect1 id="bugs">
    <title>BUGS</title>

    <para>The framework currently assumes that all the algorithms in a
    crypto_newsession(); operation must be available by the same driver. If
    that is not the case, session initialization will fail.</para>

    <para>The framework also needs a mechanism for determining which driver is
    best for a specific set of algorithms associated with a session. Some type
    of benchmarking is in order here.</para>

    <para>Multiple instances of the same algorithm in the same session are not
    supported. Note that 3DES is considered one algorithm (and not three
    instances of DES). Thus, 3DES and DES could be mixed in the same
    request.</para>
  </refsect1>

   
</refentry>