Commit 2eaabb71 authored by Richard Levitte's avatar Richard Levitte
Browse files

Step 3 of move of engines: copy the corresponding vendor header files.

parent 5572f482
Loading
Loading
Loading
Loading
+178 −0
Original line number Diff line number Diff line
/* This header declares the necessary definitions for using the exponentiation
 * acceleration capabilities, and rnd number generation of the AEP card. 
 *
 */

/*
 *
 * Some AEP defines
 *
 */

/*Successful return value*/
#define AEP_R_OK                                0x00000000

/*Miscelleanous unsuccessful return value*/
#define AEP_R_GENERAL_ERROR                     0x10000001

/*Insufficient host memory*/
#define AEP_R_HOST_MEMORY                       0x10000002

#define AEP_R_FUNCTION_FAILED                   0x10000006

/*Invalid arguments in function call*/
#define AEP_R_ARGUMENTS_BAD                     0x10020000

#define AEP_R_NO_TARGET_RESOURCES				0x10030000

/*Error occuring on socket operation*/
#define AEP_R_SOCKERROR							0x10000010

/*Socket has been closed from the other end*/
#define AEP_R_SOCKEOF							0x10000011

/*Invalid handles*/
#define AEP_R_CONNECTION_HANDLE_INVALID         0x100000B3

#define AEP_R_TRANSACTION_HANDLE_INVALID		0x10040000

/*Transaction has not yet returned from accelerator*/
#define AEP_R_TRANSACTION_NOT_READY				0x00010000

/*There is already a thread waiting on this transaction*/
#define AEP_R_TRANSACTION_CLAIMED				0x10050000

/*The transaction timed out*/
#define AEP_R_TIMED_OUT							0x10060000

#define AEP_R_FXN_NOT_IMPLEMENTED				0x10070000

#define AEP_R_TARGET_ERROR						0x10080000

/*Error in the AEP daemon process*/
#define AEP_R_DAEMON_ERROR						0x10090000

/*Invalid ctx id*/
#define AEP_R_INVALID_CTX_ID					0x10009000

#define AEP_R_NO_KEY_MANAGER					0x1000a000

/*Error obtaining a mutex*/
#define AEP_R_MUTEX_BAD                         0x000001A0

/*Fxn call before AEP_Initialise ot after AEP_Finialise*/
#define AEP_R_AEPAPI_NOT_INITIALIZED			0x10000190

/*AEP_Initialise has already been called*/
#define AEP_R_AEPAPI_ALREADY_INITIALIZED		0x10000191

/*Maximum number of connections to daemon reached*/
#define AEP_R_NO_MORE_CONNECTION_HNDLS			0x10000200

/*
 *
 * Some AEP Type definitions
 *
 */

/* an unsigned 8-bit value */
typedef unsigned char				AEP_U8;

/* an unsigned 8-bit character */
typedef char					AEP_CHAR;

/* a BYTE-sized Boolean flag */
typedef AEP_U8					AEP_BBOOL;

/*Unsigned value, at least 16 bits long*/
typedef unsigned short				AEP_U16;

/* an unsigned value, at least 32 bits long */
#ifdef SIXTY_FOUR_BIT_LONG
typedef unsigned int				AEP_U32;
#else
typedef unsigned long				AEP_U32;
#endif

#ifdef SIXTY_FOUR_BIT_LONG
typedef unsigned long				AEP_U64;
#else
typedef struct { unsigned long l1, l2; }	AEP_U64;
#endif

/* at least 32 bits; each bit is a Boolean flag */
typedef AEP_U32			AEP_FLAGS;

typedef AEP_U8	    	*AEP_U8_PTR;
typedef AEP_CHAR    	*AEP_CHAR_PTR;
typedef AEP_U32			*AEP_U32_PTR;
typedef AEP_U64			*AEP_U64_PTR;
typedef void        	*AEP_VOID_PTR;

/* Pointer to a AEP_VOID_PTR-- i.e., pointer to pointer to void */
typedef AEP_VOID_PTR 	*AEP_VOID_PTR_PTR;

/*Used to identify an AEP connection handle*/
typedef AEP_U32					AEP_CONNECTION_HNDL;

/*Pointer to an AEP connection handle*/
typedef AEP_CONNECTION_HNDL 	*AEP_CONNECTION_HNDL_PTR;

/*Used by an application (in conjunction with the apps process id) to 
identify an individual transaction*/
typedef AEP_U32					AEP_TRANSACTION_ID;

/*Pointer to an applications transaction identifier*/
typedef AEP_TRANSACTION_ID 		*AEP_TRANSACTION_ID_PTR;

/*Return value type*/
typedef AEP_U32					AEP_RV;

#define MAX_PROCESS_CONNECTIONS 256

#define RAND_BLK_SIZE 1024

typedef enum{
        NotConnected=   0,
        Connected=              1,
        InUse=                  2
} AEP_CONNECTION_STATE;


typedef struct AEP_CONNECTION_ENTRY{
        AEP_CONNECTION_STATE    conn_state;
        AEP_CONNECTION_HNDL     conn_hndl;
} AEP_CONNECTION_ENTRY;


typedef AEP_RV t_AEP_OpenConnection(AEP_CONNECTION_HNDL_PTR phConnection);
typedef AEP_RV t_AEP_CloseConnection(AEP_CONNECTION_HNDL hConnection);

typedef AEP_RV t_AEP_ModExp(AEP_CONNECTION_HNDL hConnection,
			    AEP_VOID_PTR pA, AEP_VOID_PTR pP,
			    AEP_VOID_PTR pN,
			    AEP_VOID_PTR pResult,
			    AEP_TRANSACTION_ID* pidTransID);

typedef AEP_RV t_AEP_ModExpCrt(AEP_CONNECTION_HNDL hConnection,
			       AEP_VOID_PTR pA, AEP_VOID_PTR pP,
			       AEP_VOID_PTR pQ,
			       AEP_VOID_PTR pDmp1, AEP_VOID_PTR pDmq1,
			       AEP_VOID_PTR pIqmp,
			       AEP_VOID_PTR pResult,
			       AEP_TRANSACTION_ID* pidTransID);

#ifdef AEPRAND
typedef AEP_RV t_AEP_GenRandom(AEP_CONNECTION_HNDL hConnection,
			       AEP_U32 Len,
			       AEP_U32 Type,
			       AEP_VOID_PTR pResult,
			       AEP_TRANSACTION_ID* pidTransID);
#endif

typedef AEP_RV t_AEP_Initialize(AEP_VOID_PTR pInitArgs);
typedef AEP_RV t_AEP_Finalize();
typedef AEP_RV t_AEP_SetBNCallBacks(AEP_RV (*GetBigNumSizeFunc)(),
				    AEP_RV (*MakeAEPBigNumFunc)(),
				    AEP_RV (*ConverAEPBigNumFunc)());
+48 −0
Original line number Diff line number Diff line
/* This header declares the necessary definitions for using the exponentiation
 * acceleration capabilities of Atalla cards. The only cryptographic operation
 * is performed by "ASI_RSAPrivateKeyOpFn" and this takes a structure that
 * defines an "RSA private key". However, it is really only performing a
 * regular mod_exp using the supplied modulus and exponent - no CRT form is
 * being used. Hence, it is a generic mod_exp function in disguise, and we use
 * it as such.
 *
 * Thanks to the people at Atalla for letting me know these definitions are
 * fine and that they can be reproduced here.
 *
 * Geoff.
 */

typedef struct ItemStr
	{
	unsigned char *data;
	int len;
	} Item;

typedef struct RSAPrivateKeyStr
	{
	void *reserved;
	Item version;
	Item modulus;
	Item publicExponent;
	Item privateExponent;
	Item prime[2];
	Item exponent[2];
	Item coefficient;
	} RSAPrivateKey;

/* Predeclare the function pointer types that we dynamically load from the DSO.
 * These use the same names and form that Ben's original support code had (in
 * crypto/bn/bn_exp.c) unless of course I've inadvertently changed the style
 * somewhere along the way!
 */

typedef int tfnASI_GetPerformanceStatistics(int reset_flag,
					unsigned int *ret_buf);

typedef int tfnASI_GetHardwareConfig(long card_num, unsigned int *ret_buf);

typedef int tfnASI_RSAPrivateKeyOpFn(RSAPrivateKey * rsaKey,
					unsigned char *output,
					unsigned char *input,
					unsigned int modulus_len);
+234 −0
Original line number Diff line number Diff line
/* Attribution notice: Rainbow have generously allowed me to reproduce
 * the necessary definitions here from their API. This means the support
 * can build independently of whether application builders have the
 * API or hardware. This will allow developers to easily produce software
 * that has latent hardware support for any users that have accelertors
 * installed, without the developers themselves needing anything extra.
 *
 * I have only clipped the parts from the CryptoSwift header files that
 * are (or seem) relevant to the CryptoSwift support code. This is
 * simply to keep the file sizes reasonable.
 * [Geoff]
 */


/* NB: These type widths do *not* seem right in general, in particular
 * they're not terribly friendly to 64-bit architectures (unsigned long)
 * will be 64-bit on IA-64 for a start. I'm leaving these alone as they
 * agree with Rainbow's API and this will only be called into question
 * on platforms with Rainbow support anyway! ;-) */

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

typedef long              SW_STATUS;              /* status           */
typedef unsigned char     SW_BYTE;                /* 8 bit byte       */
typedef unsigned short    SW_U16;                 /* 16 bit number    */
#if defined(_IRIX)
#include <sgidefs.h>
typedef __uint32_t        SW_U32;
#else
typedef unsigned long     SW_U32;                 /* 32 bit integer   */
#endif
 
#if defined(OPENSSL_SYS_WIN32)
  typedef struct _SW_U64 {
      SW_U32 low32;
      SW_U32 high32;
  } SW_U64;                                         /* 64 bit integer   */
#elif defined(OPENSSL_SYS_MACINTOSH_CLASSIC)
  typedef longlong SW_U64
#else /* Unix variants */
  typedef struct _SW_U64 {
      SW_U32 low32;
      SW_U32 high32;
  } SW_U64;                                         /* 64 bit integer   */
#endif

/* status codes */
#define SW_OK                 (0L)
#define SW_ERR_BASE           (-10000L)
#define SW_ERR_NO_CARD        (SW_ERR_BASE-1) /* The Card is not present   */
#define SW_ERR_CARD_NOT_READY (SW_ERR_BASE-2) /* The card has not powered  */
                                              /*    up yet                 */
#define SW_ERR_TIME_OUT       (SW_ERR_BASE-3) /* Execution of a command    */
                                              /*    time out               */
#define SW_ERR_NO_EXECUTE     (SW_ERR_BASE-4) /* The Card failed to        */
                                              /*    execute the command    */
#define SW_ERR_INPUT_NULL_PTR (SW_ERR_BASE-5) /* a required pointer is     */
                                              /*    NULL                   */
#define SW_ERR_INPUT_SIZE     (SW_ERR_BASE-6) /* size is invalid, too      */
                                              /*    small, too large.      */
#define SW_ERR_INVALID_HANDLE (SW_ERR_BASE-7) /* Invalid SW_ACC_CONTEXT    */
                                              /*    handle                 */
#define SW_ERR_PENDING        (SW_ERR_BASE-8) /* A request is already out- */
                                              /*    standing at this       */
                                              /*    context handle         */
#define SW_ERR_AVAILABLE      (SW_ERR_BASE-9) /* A result is available.    */
#define SW_ERR_NO_PENDING     (SW_ERR_BASE-10)/* No request is pending.    */
#define SW_ERR_NO_MEMORY      (SW_ERR_BASE-11)/* Not enough memory         */
#define SW_ERR_BAD_ALGORITHM  (SW_ERR_BASE-12)/* Invalid algorithm type    */
                                              /*    in SW_PARAM structure  */
#define SW_ERR_MISSING_KEY    (SW_ERR_BASE-13)/* No key is associated with */
                                              /*    context.               */
                                              /*    swAttachKeyParam() is  */
                                              /*    not called.            */
#define SW_ERR_KEY_CMD_MISMATCH \
                              (SW_ERR_BASE-14)/* Cannot perform requested  */
                                              /*    SW_COMMAND_CODE since  */
                                              /*    key attached via       */
                                              /*    swAttachKeyParam()     */
                                              /*    cannot be used for this*/
                                              /*    SW_COMMAND_CODE.       */
#define SW_ERR_NOT_IMPLEMENTED \
                              (SW_ERR_BASE-15)/* Not implemented           */
#define SW_ERR_BAD_COMMAND    (SW_ERR_BASE-16)/* Bad command code          */
#define SW_ERR_BAD_ITEM_SIZE  (SW_ERR_BASE-17)/* too small or too large in */
                                              /*    the "initems" or       */
                                              /*    "outitems".            */
#define SW_ERR_BAD_ACCNUM     (SW_ERR_BASE-18)/* Bad accelerator number    */
#define SW_ERR_SELFTEST_FAIL  (SW_ERR_BASE-19)/* At least one of the self  */
                                              /*    test fail, look at the */
                                              /*    selfTestBitmap in      */
                                              /*    SW_ACCELERATOR_INFO for*/
                                              /*    details.               */
#define SW_ERR_MISALIGN       (SW_ERR_BASE-20)/* Certain alogrithms require*/
                                              /*    key materials aligned  */
                                              /*    in certain order, e.g. */
                                              /*    128 bit for CRT        */
#define SW_ERR_OUTPUT_NULL_PTR \
                              (SW_ERR_BASE-21)/* a required pointer is     */
                                              /*    NULL                   */
#define SW_ERR_OUTPUT_SIZE \
                              (SW_ERR_BASE-22)/* size is invalid, too      */
                                              /*    small, too large.      */
#define SW_ERR_FIRMWARE_CHECKSUM \
                              (SW_ERR_BASE-23)/* firmware checksum mismatch*/
                                              /*    download failed.       */
#define SW_ERR_UNKNOWN_FIRMWARE \
                              (SW_ERR_BASE-24)/* unknown firmware error    */
#define SW_ERR_INTERRUPT      (SW_ERR_BASE-25)/* request is abort when     */
                                              /*    it's waiting to be     */
                                              /*    completed.             */
#define SW_ERR_NVWRITE_FAIL   (SW_ERR_BASE-26)/* error in writing to Non-  */
                                              /*    volatile memory        */
#define SW_ERR_NVWRITE_RANGE  (SW_ERR_BASE-27)/* out of range error in     */
                                              /*    writing to NV memory   */
#define SW_ERR_RNG_ERROR      (SW_ERR_BASE-28)/* Random Number Generation  */
                                              /*    failure                */
#define SW_ERR_DSS_FAILURE    (SW_ERR_BASE-29)/* DSS Sign or Verify failure*/
#define SW_ERR_MODEXP_FAILURE (SW_ERR_BASE-30)/* Failure in various math   */
                                              /*    calculations           */
#define SW_ERR_ONBOARD_MEMORY (SW_ERR_BASE-31)/* Error in accessing on -   */
                                              /*    board memory           */
#define SW_ERR_FIRMWARE_VERSION \
                              (SW_ERR_BASE-32)/* Wrong version in firmware */
                                              /*    update                 */
#define SW_ERR_ZERO_WORKING_ACCELERATOR \
                              (SW_ERR_BASE-44)/* All accelerators are bad  */


  /* algorithm type */
#define SW_ALG_CRT          1
#define SW_ALG_EXP          2
#define SW_ALG_DSA          3
#define SW_ALG_NVDATA       4

  /* command code */
#define SW_CMD_MODEXP_CRT   1 /* perform Modular Exponentiation using  */
                              /*  Chinese Remainder Theorem (CRT)      */
#define SW_CMD_MODEXP       2 /* perform Modular Exponentiation        */
#define SW_CMD_DSS_SIGN     3 /* perform DSS sign                      */
#define SW_CMD_DSS_VERIFY   4 /* perform DSS verify                    */
#define SW_CMD_RAND         5 /* perform random number generation      */
#define SW_CMD_NVREAD       6 /* perform read to nonvolatile RAM       */
#define SW_CMD_NVWRITE      7 /* perform write to nonvolatile RAM      */

typedef SW_U32            SW_ALGTYPE;             /* alogrithm type   */
typedef SW_U32            SW_STATE;               /* state            */
typedef SW_U32            SW_COMMAND_CODE;        /* command code     */
typedef SW_U32            SW_COMMAND_BITMAP[4];   /* bitmap           */

typedef struct _SW_LARGENUMBER {
    SW_U32    nbytes;       /* number of bytes in the buffer "value"  */
    SW_BYTE*  value;        /* the large integer as a string of       */
                            /*   bytes in network (big endian) order  */
} SW_LARGENUMBER;               

#if defined(OPENSSL_SYS_WIN32)
    #include <windows.h>
    typedef HANDLE          SW_OSHANDLE;          /* handle to kernel object */
    #define SW_OS_INVALID_HANDLE  INVALID_HANDLE_VALUE
    #define SW_CALLCONV _stdcall
#elif defined(OPENSSL_SYS_MACINTOSH_CLASSIC)
    /* async callback mechanisms */
    /* swiftCallbackLevel */
    #define SW_MAC_CALLBACK_LEVEL_NO         0		
    #define SW_MAC_CALLBACK_LEVEL_HARDWARE   1	/* from the hardware ISR */
    #define SW_MAC_CALLBACK_LEVEL_SECONDARY  2	/* as secondary ISR */
    typedef int             SW_MAC_CALLBACK_LEVEL;
    typedef int             SW_OSHANDLE;
    #define SW_OS_INVALID_HANDLE  (-1)
    #define SW_CALLCONV
#else /* Unix variants */
    typedef int             SW_OSHANDLE;          /* handle to driver */
    #define SW_OS_INVALID_HANDLE  (-1)
    #define SW_CALLCONV
#endif 

typedef struct _SW_CRT {
    SW_LARGENUMBER  p;      /* prime number p                         */
    SW_LARGENUMBER  q;      /* prime number q                         */
    SW_LARGENUMBER  dmp1;   /* exponent1                              */
    SW_LARGENUMBER  dmq1;   /* exponent2                              */
    SW_LARGENUMBER  iqmp;   /* CRT coefficient                        */
} SW_CRT;

typedef struct _SW_EXP {
    SW_LARGENUMBER  modulus; /* modulus                                */
    SW_LARGENUMBER  exponent;/* exponent                               */
} SW_EXP;

typedef struct _SW_DSA {
    SW_LARGENUMBER  p;      /*                                        */
    SW_LARGENUMBER  q;      /*                                        */
    SW_LARGENUMBER  g;      /*                                        */
    SW_LARGENUMBER  key;    /* private/public key                     */
} SW_DSA;

typedef struct _SW_NVDATA {
    SW_U32 accnum;          /* accelerator board number               */
    SW_U32 offset;          /* offset in byte                         */
} SW_NVDATA;

typedef struct _SW_PARAM {
    SW_ALGTYPE    type;     /* type of the alogrithm                  */
    union {
        SW_CRT    crt;
        SW_EXP    exp;
        SW_DSA    dsa;
        SW_NVDATA nvdata;
    } up;
} SW_PARAM;

typedef SW_U32 SW_CONTEXT_HANDLE; /* opaque context handle */


/* Now the OpenSSL bits, these function types are the for the function
 * pointers that will bound into the Rainbow shared libraries. */
typedef SW_STATUS SW_CALLCONV t_swAcquireAccContext(SW_CONTEXT_HANDLE *hac);
typedef SW_STATUS SW_CALLCONV t_swAttachKeyParam(SW_CONTEXT_HANDLE hac,
                                                SW_PARAM *key_params);
typedef SW_STATUS SW_CALLCONV t_swSimpleRequest(SW_CONTEXT_HANDLE hac,
                                                SW_COMMAND_CODE cmd,
                				SW_LARGENUMBER pin[],
                                		SW_U32 pin_count,
                                                SW_LARGENUMBER pout[],
                				SW_U32 pout_count);
typedef SW_STATUS SW_CALLCONV t_swReleaseAccContext(SW_CONTEXT_HANDLE hac);

#ifdef __cplusplus
}
#endif /* __cplusplus */
+149 −0
Original line number Diff line number Diff line
/**********************************************************************/
/*                                                                    */
/*  Prototypes of the CCA verbs used by the 4758 CCA openssl driver   */
/*                                                                    */
/*  Maurice Gittens <maurice@gittens.nl>                              */
/*                                                                    */
/**********************************************************************/

#ifndef __HW_4758_CCA__
#define __HW_4758_CCA__

/*
 *  Only WIN32 support for now
 */
#if defined(WIN32)

  #define CCA_LIB_NAME "CSUNSAPI"

  #define CSNDPKX   "CSNDPKX_32"
  #define CSNDKRR   "CSNDKRR_32"
  #define CSNDPKE   "CSNDPKE_32"
  #define CSNDPKD   "CSNDPKD_32"
  #define CSNDDSV   "CSNDDSV_32"
  #define CSNDDSG   "CSNDDSG_32"
  #define CSNBRNG   "CSNBRNG_32"

  #define SECURITYAPI __stdcall
#else
    /* Fixme!!         
      Find out the values of these constants for other platforms.
    */
  #define CCA_LIB_NAME "CSUNSAPI"

  #define CSNDPKX   "CSNDPKX"
  #define CSNDKRR   "CSNDKRR"
  #define CSNDPKE   "CSNDPKE"
  #define CSNDPKD   "CSNDPKD"
  #define CSNDDSV   "CSNDDSV"
  #define CSNDDSG   "CSNDDSG"
  #define CSNBRNG   "CSNBRNG"

  #define SECURITYAPI
#endif

/*
 * security API prototypes
 */

/* PKA Key Record Read */
typedef void (SECURITYAPI *F_KEYRECORDREAD)
             (long          * return_code,
              long          * reason_code,
              long          * exit_data_length,
              unsigned char * exit_data,
              long          * rule_array_count,
              unsigned char * rule_array,
              unsigned char * key_label,
              long          * key_token_length,
              unsigned char * key_token);

/* Random Number Generate */
typedef void (SECURITYAPI *F_RANDOMNUMBERGENERATE)
             (long          * return_code,
              long          * reason_code,
              long          * exit_data_length,
              unsigned char * exit_data,
              unsigned char * form,
              unsigned char * random_number);

/* Digital Signature Generate */
typedef void (SECURITYAPI *F_DIGITALSIGNATUREGENERATE)
             (long          * return_code,
              long          * reason_code,
              long          * exit_data_length,
              unsigned char * exit_data,
              long          * rule_array_count,
              unsigned char * rule_array,
              long          * PKA_private_key_id_length,
              unsigned char * PKA_private_key_id,
              long          * hash_length,
              unsigned char * hash,
              long          * signature_field_length,
              long          * signature_bit_length,
              unsigned char * signature_field);

/* Digital Signature Verify */
typedef void (SECURITYAPI *F_DIGITALSIGNATUREVERIFY)(
              long          * return_code,
              long          * reason_code,
              long          * exit_data_length,
              unsigned char * exit_data,
              long          * rule_array_count,
              unsigned char * rule_array,
              long          * PKA_public_key_id_length,
              unsigned char * PKA_public_key_id,
              long          * hash_length,
              unsigned char * hash,
              long          * signature_field_length,
              unsigned char * signature_field);

/* PKA Public Key Extract */
typedef void (SECURITYAPI *F_PUBLICKEYEXTRACT)(
              long          * return_code,
              long          * reason_code,
              long          * exit_data_length,
              unsigned char * exit_data,
              long          * rule_array_count,
              unsigned char * rule_array,
              long          * source_key_identifier_length,
              unsigned char * source_key_identifier,
              long          * target_key_token_length,
              unsigned char * target_key_token);

/* PKA Encrypt */
typedef void   (SECURITYAPI *F_PKAENCRYPT)
               (long          *  return_code,
                 long          *  reason_code,
                 long          *  exit_data_length,
                 unsigned char *  exit_data,
                 long          *  rule_array_count,
                 unsigned char *  rule_array,
                 long          *  key_value_length,
                 unsigned char *  key_value,
                 long          *  data_struct_length,
                 unsigned char *  data_struct,
                 long          *  RSA_public_key_length,
                 unsigned char *  RSA_public_key,
                 long          *  RSA_encipher_length,
                 unsigned char *  RSA_encipher );

/* PKA Decrypt */
typedef void    (SECURITYAPI *F_PKADECRYPT)
                (long          *  return_code,
                 long          *  reason_code,
                 long          *  exit_data_length,
                 unsigned char *  exit_data,
                 long          *  rule_array_count,
                 unsigned char *  rule_array,
                 long          *  enciphered_key_length,
                 unsigned char *  enciphered_key,
                 long          *  data_struct_length,
                 unsigned char *  data_struct,
                 long          *  RSA_private_key_length,
                 unsigned char *  RSA_private_key,
                 long          *  key_value_length,
                 unsigned char *  key_value    );


#endif
+100 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading