/* compute TLSv1 PRF (pseudo random function using HMAC) */ static void doPRF(byte* digest, word32 digLen, const byte* secret,word32 secLen, const byte* label, word32 labLen, const byte* seed, word32 seedLen) { word32 half = (secLen + 1) / 2; byte md5_half[MAX_PRF_HALF]; /* half is real size */ byte sha_half[MAX_PRF_HALF]; /* half is real size */ byte labelSeed[MAX_PRF_LABSEED]; /* labLen + seedLen is real size */ byte md5_result[MAX_PRF_DIG]; /* digLen is real size */ byte sha_result[MAX_PRF_DIG]; /* digLen is real size */ if (half > MAX_PRF_HALF) return; if (labLen + seedLen > MAX_PRF_LABSEED) return; if (digLen > MAX_PRF_DIG) return; XMEMSET(md5_result, 0, digLen); XMEMSET(sha_result, 0, digLen); XMEMCPY(md5_half, secret, half); XMEMCPY(sha_half, secret + half - secLen % 2, half); XMEMCPY(labelSeed, label, labLen); XMEMCPY(labelSeed + labLen, seed, seedLen); p_hash(md5_result, digLen, md5_half, half, labelSeed, labLen + seedLen, md5_mac); p_hash(sha_result, digLen, sha_half, half, labelSeed, labLen + seedLen, sha_mac); get_xor(digest, digLen, md5_result, sha_result); }
/* Wrapper to call straight thru to p_hash in TSL 1.2 cases to remove stack use */ static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, const byte* label, word32 labLen, const byte* seed, word32 seedLen, int useAtLeastSha256, int hash_type) { if (useAtLeastSha256) { byte labelSeed[MAX_PRF_LABSEED]; /* labLen + seedLen is real size */ if (labLen + seedLen > MAX_PRF_LABSEED) return; XMEMCPY(labelSeed, label, labLen); XMEMCPY(labelSeed + labLen, seed, seedLen); /* If a cipher suite wants an algorithm better than sha256, it * should use better. */ if (hash_type < sha256_mac) hash_type = sha256_mac; p_hash(digest, digLen, secret, secLen, labelSeed, labLen + seedLen, hash_type); } #ifndef NO_OLD_TLS else doPRF(digest, digLen, secret, secLen, label, labLen, seed, seedLen); #endif }
static void printrans(ACISM const*psp, STATE s, char const *charv, FILE *out, MEMREF const *pattv) { (void)pattv; TRAN x = psp->tranv[s]; if (!x) { fprintf(out, "(empty)\n"); return; } SYMBOL sym = t_sym(psp,x); char c = charv[sym]; if (sym) fprintf(out, "--"); else fprintf(out, "%02X ", c); putc("M-"[!(x & IS_MATCH)], out); putc("S-"[!(x & IS_SUFFIX)], out); STATE next = t_next(psp, x); if (t_isleaf(psp, x)) { fprintf(out, " => %d\n", t_strno(psp, x)); } else { fprintf(out, " %7"FX"d", next); if (x & IS_MATCH) { int i; for (i = p_hash(psp, s); psp->hashv[i].state != s; ++i); fprintf(out, " #> %"FX"d", psp->hashv[i].strno); } putc('\n', out); } }
//--------------|--------------------------------------------- void acism_dump(ACISM const* psp, PS_DUMP_TYPE pdt, FILE *out, MEMREF const*pattv) { int i, empty; char charv[256]; int symdist[257] = {}; for (i = 256; --i >=0;) charv[psp->symv[i]] = i; if (pdt & PS_STATS) { for (i = psp->tran_size, empty = 0; --i >= 0;) { if (psp->tranv[i]) { ++symdist[t_sym(psp, psp->tranv[i])]; } else ++empty; } fprintf(out, "strs:%zu syms:%zu chars:%zu " "trans:%d empty:%d mod:%d hash:%d size:%lu\n", psp->nstrs, psp->nsyms, psp->nchars, psp->tran_size, empty, psp->hash_mod, psp->hash_size, (long)sizeof(ACISM) + p_size(psp)); } if (pdt & PS_TRAN) { fprintf(out, "==== TRAN:\n%8s %8s Ch MS %8s\n", "Cell", "State", "Next"); for (i = 1; i < (int)psp->tran_size; ++i) { fprintf(out, "%8d %8d ", i, i - t_sym(psp, psp->tranv[i])); printrans(psp, i, charv, out, pattv); } } if (pdt & PS_HASH) { fprintf(out, "==== HASH:\n.....: state strno\n"); for (i = 0; i < (int)psp->hash_size; ++i) { STATE state = psp->hashv[i].state; if (state) fprintf(out, "%5d: %7"FX"u %3d %8"FX"u %.*s\n", i, state, i - p_hash(psp, state), PSTR(psp, psp->hashv[i].strno, pattv)); else fprintf(out, "%5d: %7"FX"d --- %8"FX"d\n", i, state, psp->hashv[i].strno); } } if (pdt & PS_TREE) { fprintf(out, "==== TREE:\n"); char str[psp->maxlen + 1]; printree(psp, 0, 0, str, charv, out, pattv); } //TODO: calculate stats: backref chain lengths ... }
// compute TLSv1 PRF (pseudo random function using HMAC) void PRF(byte* digest, uint digLen, const byte* secret, uint secLen, const byte* label, uint labLen, const byte* seed, uint seedLen) { uint half = (secLen + 1) / 2; output_buffer md5_half(half); output_buffer sha_half(half); output_buffer labelSeed(labLen + seedLen); md5_half.write(secret, half); sha_half.write(secret + half - secLen % 2, half); labelSeed.write(label, labLen); labelSeed.write(seed, seedLen); output_buffer md5_result(digLen); output_buffer sha_result(digLen); p_hash(md5_result, md5_half, labelSeed, md5); p_hash(sha_result, sha_half, labelSeed, sha); md5_result.set_current(0); sha_result.set_current(0); get_xor(digest, digLen, md5_result, sha_result); }
int acism_lookup(ac_trie_t const *psp, const char *text, size_t len, ACISM_ACTION *cb, void *context, int *statep, bool caseless) { ac_trie_t const ps = *psp; char const *cp = text, *endp = cp + len; uint8_t s; STATE state = *statep; int ret = 0; while (cp < endp) { s = caseless ? g_ascii_tolower (*cp++) : *cp++; _SYMBOL sym = ps.symv[s]; if (!sym) { // Input byte is not in any pattern string. state = ROOT; continue; } // Search for a valid transition from this (state, sym), // following the backref chain. TRAN next; while (!t_valid(&ps, next = p_tran(&ps, state, sym)) && state != ROOT) { TRAN back = p_tran(&ps, state, BACK); state = t_valid(&ps, back) ? t_next(&ps, back) : ROOT; } if (!t_valid(&ps, next)) continue; if (!(next & (IS_MATCH | IS_SUFFIX))) { // No complete match yet; keep going. state = t_next(&ps, next); continue; } // At this point, one or more patterns have matched. // Find all matches by following the backref chain. // A valid node for (sym) with no SUFFIX flag marks the // end of the suffix chain. // In the same backref traversal, find a new (state), // if the original transition is to a leaf. STATE s = state; // Initially state is ROOT. The chain search saves the // first state from which the next char has a transition. state = t_isleaf(&ps, next) ? 0 : t_next(&ps, next); while (1) { if (t_valid(&ps, next)) { if (next & IS_MATCH) { unsigned strno, ss = s + sym, i; if (t_isleaf(&ps, ps.tranv[ss])) { strno = t_strno(&ps, ps.tranv[ss]); } else { for (i = p_hash(&ps, ss); ps.hashv[i].state != ss; ++i); strno = ps.hashv[i].strno; } if ((ret = cb(strno, cp - text, context))) goto EXIT; } if (!state && !t_isleaf(&ps, next)) state = t_next(&ps, next); if ( state && !(next & IS_SUFFIX)) break; } if (s == ROOT) break; TRAN b = p_tran(&ps, s, BACK); s = t_valid(&ps, b) ? t_next(&ps, b) : ROOT; next = p_tran(&ps, s, sym); } } EXIT: *statep = state; return ret; }