#ifndef TOMCRYPT_H_ #define TOMCRYPT_H_ #include #include #include #include #include #include #include #include /* max size of either a cipher/hash block or symmetric key [largest of the two] */ #define MAXBLOCKSIZE 128 /* descriptor table size */ #define TAB_SIZE 32 /* error codes [will be expanded in future releases] */ enum { CRYPT_OK=0, /* Result OK */ CRYPT_ERROR, /* Generic Error */ CRYPT_NOP, /* Not a failure but no operation was performed */ CRYPT_INVALID_KEYSIZE, /* Invalid key size given */ CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */ CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */ CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */ CRYPT_INVALID_PACKET, /* Invalid input packet given */ CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */ CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */ CRYPT_INVALID_CIPHER, /* Invalid cipher specified */ CRYPT_INVALID_HASH, /* Invalid hash specified */ CRYPT_INVALID_PRNG, /* Invalid PRNG specified */ CRYPT_MEM, /* Out of memory */ CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */ CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */ CRYPT_INVALID_ARG, /* Generic invalid argument */ CRYPT_FILE_NOTFOUND, /* File Not Found */ CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */ CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */ CRYPT_PK_DUP, /* Duplicate key already in key ring */ CRYPT_PK_NOT_FOUND, /* Key not found in keyring */ CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */ CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */ CRYPT_PK_INVALID_PADDING /* Invalid padding on input */ }; #define LTC_MUTEX_GLOBAL(x) #define LTC_MUTEX_PROTO(x) #define LTC_MUTEX_TYPE(x) #define LTC_MUTEX_INIT(x) #define LTC_MUTEX_LOCK(x) #define LTC_MUTEX_UNLOCK(x) #define STORE32H(x, y) \ { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } #define LOAD32H(x, y) \ { x = ((unsigned long)((y)[0] & 255)<<24) | \ ((unsigned long)((y)[1] & 255)<<16) | \ ((unsigned long)((y)[2] & 255)<<8) | \ ((unsigned long)((y)[3] & 255)); } #define STORE64H(x, y) \ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } /* rotates the hard way */ #define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) #define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) #define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) #define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) #ifndef MIN #define MIN(x, y) ( ((x)<(y))?(x):(y) ) #endif struct sha256_state { uint64_t length; uint32_t state[8], curlen; unsigned char buf[64]; }; typedef union Hash_state { char dummy[1]; struct sha256_state sha256; void *data; } hash_state; /** hash descriptor */ extern struct ltc_hash_descriptor { /** name of hash */ char *name; /** internal ID */ unsigned char ID; /** Size of digest in octets */ unsigned long hashsize; /** Input block size in octets */ unsigned long blocksize; /** ASN.1 OID */ unsigned long OID[16]; /** Length of DER encoding */ unsigned long OIDlen; /** Init a hash state @param hash The hash to initialize @return CRYPT_OK if successful */ int (*init)(hash_state *hash); /** Process a block of data @param hash The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ int (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen); /** Produce the digest and store it @param hash The hash state @param out [out] The destination of the digest @return CRYPT_OK if successful */ int (*done)(hash_state *hash, unsigned char *out); /** Self-test @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int (*test)(void); /* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */ int (*hmac_block)(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); } hash_descriptor[]; int sha256_init(hash_state * md); int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen); int sha256_done(hash_state * md, unsigned char *hash); int sha256_test(void); extern const struct ltc_hash_descriptor sha256_desc; int find_hash(const char *name); int find_hash_id(unsigned char ID); int find_hash_oid(const unsigned long *ID, unsigned long IDlen); int find_hash_any(const char *name, int digestlen); int register_hash(const struct ltc_hash_descriptor *hash); int unregister_hash(const struct ltc_hash_descriptor *hash); int hash_is_valid(int idx); LTC_MUTEX_PROTO(ltc_hash_mutex) int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...); #ifndef LTC_NO_FILE int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen); int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen); #endif /* a simple macro for making hash "process" functions */ #define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \ { \ unsigned long n; \ int err; \ LTC_ARGCHK(md != NULL); \ LTC_ARGCHK(in != NULL); \ if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \ return CRYPT_INVALID_ARG; \ } \ while (inlen > 0) { \ if (md-> state_var .curlen == 0 && inlen >= block_size) { \ if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) { \ return err; \ } \ md-> state_var .length += block_size * 8; \ in += block_size; \ inlen -= block_size; \ } else { \ n = MIN(inlen, (block_size - md-> state_var .curlen)); \ memcpy(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \ md-> state_var .curlen += n; \ in += n; \ inlen -= n; \ if (md-> state_var .curlen == block_size) { \ if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) { \ return err; \ } \ md-> state_var .length += 8*block_size; \ md-> state_var .curlen = 0; \ } \ } \ } \ return CRYPT_OK; \ } #endif /* TOMCRYPT_H_ */