/* * update pools */ static void add_entropy(FState *st, const uint8 *data, unsigned len) { unsigned pos; uint8 hash[BLOCK]; MD_CTX md; /* hash given data */ md_init(&md); md_update(&md, data, len); md_result(&md, hash); /* * Make sure the pool 0 is initialized, then update randomly. */ if (st->reseed_count == 0) pos = 0; else pos = get_rand_pool(st); md_update(&st->pool[pos], hash, BLOCK); if (pos == 0) st->pool0_bytes += len; px_memset(hash, 0, BLOCK); px_memset(&md, 0, sizeof(md)); }
static void hmac_free(PX_HMAC *h) { unsigned bs; bs = px_md_block_size(h->md); px_md_free(h->md); px_memset(h->p.ipad, 0, bs); px_memset(h->p.opad, 0, bs); px_free(h->p.ipad); px_free(h->p.opad); px_free(h); }
static void hmac_init(PX_HMAC *h, const uint8 *key, unsigned klen) { unsigned bs, i; uint8 *keybuf; PX_MD *md = h->md; bs = px_md_block_size(md); keybuf = px_alloc(bs); memset(keybuf, 0, bs); if (klen > bs) { px_md_update(md, key, klen); px_md_finish(md, keybuf); px_md_reset(md); } else memcpy(keybuf, key, klen); for (i = 0; i < bs; i++) { h->p.ipad[i] = keybuf[i] ^ HMAC_IPAD; h->p.opad[i] = keybuf[i] ^ HMAC_OPAD; } px_memset(keybuf, 0, bs); px_free(keybuf); px_md_update(md, h->p.ipad, bs); }
/* * The time between reseed must be at least RESEED_INTERVAL * microseconds. */ static int enough_time_passed(FState *st) { int ok; struct timeval tv; struct timeval *last = &st->last_reseed_time; gettimeofday(&tv, NULL); /* check how much time has passed */ ok = 0; if (tv.tv_sec > last->tv_sec + 1) ok = 1; else if (tv.tv_sec == last->tv_sec + 1) { if (1000000 + tv.tv_usec - last->tv_usec >= RESEED_INTERVAL) ok = 1; } else if (tv.tv_usec - last->tv_usec >= RESEED_INTERVAL) ok = 1; /* reseed will happen, update last_reseed_time */ if (ok) memcpy(last, &tv, sizeof(tv)); px_memset(&tv, 0, sizeof(tv)); return ok; }
void pgp_cfb_free(PGP_CFB *ctx) { px_cipher_free(ctx->ciph); px_memset(ctx, 0, sizeof(*ctx)); px_free(ctx); }
static void combo_free(PX_Combo *cx) { if (cx->cipher) px_cipher_free(cx->cipher); px_memset(cx, 0, sizeof(*cx)); px_free(cx); }
static void int_md5_free(PX_MD *h) { MD5_CTX *ctx = (MD5_CTX *) h->p.ptr; px_memset(ctx, 0, sizeof(*ctx)); px_free(ctx); px_free(h); }
int pgp_free(PGP_Context *ctx) { if (ctx->pub_key) pgp_key_free(ctx->pub_key); px_memset(ctx, 0, sizeof *ctx); px_free(ctx); return 0; }
static void md_result(MD_CTX * ctx, uint8 *dst) { SHA256_CTX tmp; memcpy(&tmp, ctx, sizeof(*ctx)); SHA256_Final(dst, &tmp); px_memset(&tmp, 0, sizeof(tmp)); }
static void int_sha224_free(PX_MD *h) { SHA224_CTX *ctx = (SHA224_CTX *) h->p.ptr; px_memset(ctx, 0, sizeof(*ctx)); px_free(ctx); px_free(h); }
static void gen_ossl_free(PX_Cipher *c) { ossldata *od = (ossldata *) c->ptr; EVP_CIPHER_CTX_cleanup(&od->evp_ctx); px_memset(od, 0, sizeof(*od)); px_free(od); px_free(c); }
/* * generate new key from all the pools */ static void reseed(FState *st) { unsigned k; unsigned n; MD_CTX key_md; uint8 buf[BLOCK]; /* set pool as empty */ st->pool0_bytes = 0; /* * Both #0 and #1 reseed would use only pool 0. Just skip #0 then. */ n = ++st->reseed_count; /* * The goal: use k-th pool only 1/(2^k) of the time. */ md_init(&key_md); for (k = 0; k < NUM_POOLS; k++) { md_result(&st->pool[k], buf); md_update(&key_md, buf, BLOCK); if (n & 1 || !n) break; n >>= 1; } /* add old key into mix too */ md_update(&key_md, st->key, BLOCK); /* now we have new key */ md_result(&key_md, st->key); /* use new key */ ciph_init(&st->ciph, st->key, BLOCK); px_memset(&key_md, 0, sizeof(key_md)); px_memset(buf, 0, BLOCK); }
static void intctx_free(PX_Cipher *c) { struct int_ctx *cx = (struct int_ctx *) c->ptr; if (cx) { px_memset(cx, 0, sizeof *cx); px_free(cx); } px_free(c); }
/* * Mix a block of data into RNG. */ static void add_block_entropy(PX_MD *md, text *data) { uint8 sha1[20]; px_md_reset(md); px_md_update(md, (uint8 *) VARDATA(data), VARSIZE(data) - VARHDRSZ); px_md_finish(md, sha1); px_add_entropy(sha1, 20); px_memset(sha1, 0, 20); }
static void system_reseed(void) { uint8 buf[1024]; int n; time_t t; int skip = 1; t = time(NULL); if (seed_time == 0) skip = 0; else if ((t - seed_time) < SYSTEM_RESEED_MIN) skip = 1; else if ((t - seed_time) > SYSTEM_RESEED_MAX) skip = 0; else if (check_time == 0 || (t - check_time) > SYSTEM_RESEED_CHECK_TIME) { check_time = t; /* roll dice */ px_get_random_bytes(buf, 1); skip = buf[0] >= SYSTEM_RESEED_CHANCE; } /* clear 1 byte */ px_memset(buf, 0, sizeof(buf)); if (skip) return; n = px_acquire_system_randomness(buf); if (n > 0) fortuna_add_entropy(buf, n); seed_time = t; px_memset(buf, 0, sizeof(buf)); }
static int calc_s2k_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key, unsigned key_len) { unsigned md_rlen; uint8 buf[PGP_MAX_DIGEST]; unsigned preload = 0; uint8 *dst; unsigned remain; md_rlen = px_md_result_size(md); dst = s2k->key; remain = s2k->key_len; while (remain > 0) { px_md_reset(md); if (preload > 0) { memset(buf, 0, preload); px_md_update(md, buf, preload); } preload++; px_md_update(md, s2k->salt, PGP_S2K_SALT); px_md_update(md, key, key_len); px_md_finish(md, buf); if (remain > md_rlen) { memcpy(dst, buf, md_rlen); remain -= md_rlen; dst += md_rlen; } else { memcpy(dst, buf, remain); remain = 0; } } px_memset(buf, 0, sizeof(buf)); return 0; }
static void hmac_finish(PX_HMAC *h, uint8 *dst) { PX_MD *md = h->md; unsigned bs, hlen; uint8 *buf; bs = px_md_block_size(md); hlen = px_md_result_size(md); buf = px_alloc(hlen); px_md_finish(md, buf); px_md_reset(md); px_md_update(md, h->p.opad, bs); px_md_update(md, buf, hlen); px_md_finish(md, dst); px_memset(buf, 0, hlen); px_free(buf); }
/* * Mix user data into RNG. It is for user own interests to have * RNG state shuffled. */ static void add_entropy(text *data1, text *data2, text *data3) { PX_MD *md; uint8 rnd[3]; if (!data1 && !data2 && !data3) return; if (px_get_random_bytes(rnd, 3) < 0) return; if (px_find_digest("sha1", &md) < 0) return; /* * Try to make the feeding unpredictable. * * Prefer data over keys, as it's rather likely that key is same in * several calls. */ /* chance: 7/8 */ if (data1 && rnd[0] >= 32) add_block_entropy(md, data1); /* chance: 5/8 */ if (data2 && rnd[1] >= 160) add_block_entropy(md, data2); /* chance: 5/8 */ if (data3 && rnd[2] >= 160) add_block_entropy(md, data3); px_md_free(md); px_memset(rnd, 0, sizeof(rnd)); }
/* * Hide public constants. (counter, pools > 0) * * This can also be viewed as spreading the startup * entropy over all of the components. */ static void startup_tricks(FState *st) { int i; uint8 buf[BLOCK]; /* Use next block as counter. */ encrypt_counter(st, st->counter); /* Now shuffle pools, excluding #0 */ for (i = 1; i < NUM_POOLS; i++) { encrypt_counter(st, buf); encrypt_counter(st, buf + CIPH_BLOCK); md_update(&st->pool[i], buf, BLOCK); } px_memset(buf, 0, BLOCK); /* Hide the key. */ rekey(st); /* This can be done only once. */ st->tricks_done = 1; }
int px_gen_salt(const char *salt_type, char *buf, int rounds) { int res; struct generator *g; char *p; char rbuf[16]; for (g = gen_list; g->name; g++) if (pg_strcasecmp(g->name, salt_type) == 0) break; if (g->name == NULL) return PXE_UNKNOWN_SALT_ALGO; if (g->def_rounds) { if (rounds == 0) rounds = g->def_rounds; if (rounds < g->min_rounds || rounds > g->max_rounds) return PXE_BAD_SALT_ROUNDS; } res = px_get_pseudo_random_bytes((uint8 *) rbuf, g->input_len); if (res < 0) return res; p = g->gen(rounds, rbuf, g->input_len, buf, PX_MAX_SALT_LEN); px_memset(rbuf, 0, sizeof(rbuf)); if (p == NULL) return PXE_BAD_SALT_ROUNDS; return strlen(p); }
static void clear_and_pfree(text *p) { px_memset(p, 0, VARSIZE(p)); pfree(p); }
static int calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key, unsigned key_len) { unsigned md_rlen; uint8 buf[PGP_MAX_DIGEST]; uint8 *dst; unsigned preload = 0; unsigned remain, c, curcnt, count; count = s2k_decode_count(s2k->iter); md_rlen = px_md_result_size(md); remain = s2k->key_len; dst = s2k->key; while (remain > 0) { px_md_reset(md); if (preload) { memset(buf, 0, preload); px_md_update(md, buf, preload); } preload++; px_md_update(md, s2k->salt, PGP_S2K_SALT); px_md_update(md, key, key_len); curcnt = PGP_S2K_SALT + key_len; while (curcnt < count) { if (curcnt + PGP_S2K_SALT < count) c = PGP_S2K_SALT; else c = count - curcnt; px_md_update(md, s2k->salt, c); curcnt += c; if (curcnt + key_len < count) c = key_len; else if (curcnt < count) c = count - curcnt; else break; px_md_update(md, key, c); curcnt += c; } px_md_finish(md, buf); if (remain > md_rlen) { memcpy(dst, buf, md_rlen); remain -= md_rlen; dst += md_rlen; } else { memcpy(dst, buf, remain); remain = 0; } } px_memset(buf, 0, sizeof(buf)); return 0; }