/** Find a registered cipher by name @param name The name of the cipher to look for @return >= 0 if found, -1 if not present */ int find_cipher(const char *name) { int x; LTC_ARGCHK(name != NULL); LTC_MUTEX_LOCK(<c_cipher_mutex); for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x].name != NULL && !XSTRCMP(cipher_descriptor[x].name, name)) { LTC_MUTEX_UNLOCK(<c_cipher_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_cipher_mutex); return -1; }
/** Find a registered PRNG by name @param name The name of the PRNG to look for @return >= 0 if found, -1 if not present */ int find_prng(const char *name) { int x; LTC_ARGCHK(name != NULL); LTC_MUTEX_LOCK(<c_prng_mutex); for (x = 0; x < TAB_SIZE; x++) { if ((prng_descriptor[x].name != NULL) && XSTRCMP(prng_descriptor[x].name, name) == 0) { LTC_MUTEX_UNLOCK(<c_prng_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_prng_mutex); return -1; }
/** Find a cipher by ID number @param ID The ID (not same as index) of the cipher to find @return >= 0 if found, -1 if not present */ int find_cipher_id(unsigned char ID) { int x; LTC_MUTEX_LOCK(<c_cipher_mutex); for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x].ID == ID) { x = (cipher_descriptor[x].name == NULL) ? -1 : x; LTC_MUTEX_UNLOCK(<c_cipher_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_cipher_mutex); return -1; }
/** Find a registered hash by name @param name The name of the hash to look for @return >= 0 if found, -1 if not present */ int find_hash(const char *name) { int x; LTC_ARGCHK(name != NULL); LTC_MUTEX_LOCK(<c_hash_mutex); for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x].name != NULL && strcmp(hash_descriptor[x].name, name) == 0) { LTC_MUTEX_UNLOCK(<c_hash_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_hash_mutex); return -1; }
INT find_hash_oid(const ULONG *ID, ULONG IDlen) { INT x; LTC_ARGCHK(ID != NULL); LTC_MUTEX_LOCK(<c_hash_mutex); for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x].name != NULL && hash_descriptor[x].OIDlen == IDlen && !XMEMCMP(hash_descriptor[x].OID, ID, sizeof(ULONG) * IDlen)) { LTC_MUTEX_UNLOCK(<c_hash_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_hash_mutex); return -1; }
/** Find a hash by ID number @param ID The ID (not same as index) of the hash to find @return >= 0 if found, -1 if not present */ INT find_hash_id(UCHAR ID) { INT x; LTC_MUTEX_LOCK(<c_hash_mutex); for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x].ID == ID) { x = (hash_descriptor[x].name == NULL) ? -1 : x; LTC_MUTEX_UNLOCK(<c_hash_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_hash_mutex); return -1; }
int find_hash_oid(const unsigned long *ID, unsigned long IDlen) { int x; LTC_ARGCHK(ID != NULL); LTC_MUTEX_LOCK(<c_hash_mutex); for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x].name != NULL && hash_descriptor[x].OIDlen == IDlen && !XMEMCMP(hash_descriptor[x].OID, ID, sizeof(unsigned long) * IDlen)) { LTC_MUTEX_UNLOCK(<c_hash_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_hash_mutex); return -1; }
/** Terminate the PRNG @param prng The PRNG to terminate @return CRYPT_OK if successful */ int yarrow_done(prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); /* call cipher done when we invent one ;-) */ /* we invented one */ err = ctr_done(&prng->yarrow.ctr); LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return err; }
/** Read from the PRNG @param out Destination @param outlen Length of output @param prng The active PRNG to read from @return Number of octets read */ unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng) { LTC_ARGCHK(out != NULL); LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); /* put out in predictable state first */ zeromem(out, outlen); /* now randomize it */ if (ctr_encrypt(out, out, outlen, &prng->yarrow.ctr) != CRYPT_OK) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return 0; } LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return outlen; }
/** Unregister a hash from the descriptor table @param hash The hash descriptor to remove @return CRYPT_OK on success */ int unregister_hash(const struct ltc_hash_descriptor *hash) { int x; LTC_ARGCHK(hash != NULL); /* is it already registered? */ LTC_MUTEX_LOCK(<c_hash_mutex); for (x = 0; x < TAB_SIZE; x++) { if (memcmp(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) { hash_descriptor[x].name = NULL; LTC_MUTEX_UNLOCK(<c_hash_mutex); return CRYPT_OK; } } LTC_MUTEX_UNLOCK(<c_hash_mutex); return CRYPT_ERROR; }
/** Unregister a PRNG from the descriptor table @param prng The PRNG descriptor to remove @return CRYPT_OK on success */ int unregister_prng(const struct ltc_prng_descriptor *prng) { int x; LTC_ARGCHK(prng != NULL); /* is it already registered? */ LTC_MUTEX_LOCK(<c_prng_mutex); for (x = 0; x < TAB_SIZE; x++) { if (memcmp(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) != 0) { prng_descriptor[x].name = NULL; LTC_MUTEX_UNLOCK(<c_prng_mutex); return CRYPT_OK; } } LTC_MUTEX_UNLOCK(<c_prng_mutex); return CRYPT_ERROR; }
/** Unregister a cipher from the descriptor table @param cipher The cipher descriptor to remove @return CRYPT_OK on success */ int unregister_cipher(const struct ltc_cipher_descriptor *cipher) { int x; LTC_ARGCHK(cipher != NULL); /* is it already registered? */ LTC_MUTEX_LOCK(<c_cipher_mutex); for (x = 0; x < TAB_SIZE; x++) { if (XMEMCMP(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor)) == 0) { cipher_descriptor[x].name = NULL; cipher_descriptor[x].ID = 255; LTC_MUTEX_UNLOCK(<c_cipher_mutex); return CRYPT_OK; } } LTC_MUTEX_UNLOCK(<c_cipher_mutex); return CRYPT_ERROR; }
/** Make the PRNG ready to read from @param prng The PRNG to make active @return CRYPT_OK if successful */ int chacha20_prng_ready(prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->lock); if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } /* key 32 bytes, 20 rounds */ if ((err = chacha_setup(&prng->chacha.s, prng->chacha.ent, 32, 20)) != CRYPT_OK) goto LBL_UNLOCK; /* iv 8 bytes */ if ((err = chacha_ivctr64(&prng->chacha.s, prng->chacha.ent + 32, 8, 0)) != CRYPT_OK) goto LBL_UNLOCK; XMEMSET(&prng->chacha.ent, 0, sizeof(prng->chacha.ent)); prng->chacha.idx = 0; prng->ready = 1; LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); return err; }
/** Add entropy to the PRNG state @param in The data to add @param inlen Length of the data to add @param prng PRNG state to update @return CRYPT_OK if successful */ int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) { hash_state md; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return err; } /* start the hash */ if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return err; } /* hash the current pool */ if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool, hash_descriptor[prng->yarrow.hash].hashsize)) != CRYPT_OK) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return err; } /* add the new entropy */ if ((err = hash_descriptor[prng->yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return err; } /* store result */ if ((err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool)) != CRYPT_OK) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return err; } LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return CRYPT_OK; }
/** Find a cipher flexibly. First by name then if not present by block and key size @param name The name of the cipher desired @param blocklen The minimum length of the block cipher desired (octets) @param keylen The minimum length of the key size desired (octets) @return >= 0 if found, -1 if not present */ int find_cipher_any(const char *name, int blocklen, int keylen) { int x; LTC_ARGCHK(name != NULL); x = find_cipher(name); if (x != -1) return x; LTC_MUTEX_LOCK(<c_cipher_mutex); for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x].name == NULL) { continue; } if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) { LTC_MUTEX_UNLOCK(<c_cipher_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_cipher_mutex); return -1; }
/** Import a PRNG state @param in The PRNG state @param inlen Size of the state @param prng The PRNG to import @return CRYPT_OK if successful */ int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng) { int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); if (inlen != 64) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return CRYPT_INVALID_ARG; } if ((err = yarrow_start(prng)) != CRYPT_OK) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return err; } err = yarrow_add_entropy(in, 64, prng); LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return err; }
*/int find_hash_any(const char *name, int digestlen) { int x, y, z; LTC_ARGCHK(name != NULL); x = find_hash(name); if (x != -1) return x; LTC_MUTEX_LOCK(<c_hash_mutex); y = MAXBLOCKSIZE+1; z = -1; for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x].name == NULL) { continue; } if ((int)hash_descriptor[x].hashsize >= digestlen && (int)hash_descriptor[x].hashsize < y) { z = x; y = hash_descriptor[x].hashsize; } } LTC_MUTEX_UNLOCK(<c_hash_mutex); return z; }
/** Export the PRNG state @param out [out] Destination @param outlen [in/out] Max size and resulting size of the state @param prng The PRNG to export @return CRYPT_OK if successful */ int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng) { LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); /* we'll write 64 bytes for s&g's */ if (*outlen < 64) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); *outlen = 64; return CRYPT_BUFFER_OVERFLOW; } if (yarrow_read(out, 64, prng) != 64) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return CRYPT_ERROR_READPRNG; } *outlen = 64; return CRYPT_OK; }
/** Make the PRNG ready to read from @param prng The PRNG to make active @return CRYPT_OK if successful */ int yarrow_ready(prng_state *prng) { int ks, err; LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return err; } if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return err; } /* setup CTR mode using the "pool" as the key */ ks = (int)hash_descriptor[prng->yarrow.hash].hashsize; if ((err = cipher_descriptor[prng->yarrow.cipher].keysize(&ks)) != CRYPT_OK) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return err; } if ((err = ctr_start(prng->yarrow.cipher, /* what cipher to use */ prng->yarrow.pool, /* IV */ prng->yarrow.pool, ks, /* KEY and key size */ 0, /* number of rounds */ CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */ &prng->yarrow.ctr)) != CRYPT_OK) { LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return err; } LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); return CRYPT_OK; }