X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/b27841d687ec9e84983340b5581376dfb24010ea..b2b89723a2427bba8290bd6967a1ab39cbb630be:/libs/smux/asn_random_fill.c diff --git a/libs/smux/asn_random_fill.c b/libs/smux/asn_random_fill.c new file mode 100644 index 00000000..819cf700 --- /dev/null +++ b/libs/smux/asn_random_fill.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +int +asn_random_fill(const struct asn_TYPE_descriptor_s *td, void **struct_ptr, + size_t length) { + + if(td && td->op->random_fill) { + asn_random_fill_result_t res = + td->op->random_fill(td, struct_ptr, 0, length); + return (res.code == ARFILL_OK) ? 0 : -1; + } else { + return -1; + } +} + +static uintmax_t +asn__intmax_range(intmax_t lb, intmax_t ub) { + assert(lb <= ub); + if((ub < 0) == (lb < 0)) { + return ub - lb; + } else if(lb < 0) { + return 1 + ((uintmax_t)ub + (uintmax_t)-(lb + 1)); + } else { + assert(!"Unreachable"); + return 0; + } +} + +intmax_t +asn_random_between(intmax_t lb, intmax_t rb) { + if(lb == rb) { + return lb; + } else { + const uintmax_t intmax_max = ((~(uintmax_t)0) >> 1); + uintmax_t range = asn__intmax_range(lb, rb); + uintmax_t value = 0; + uintmax_t got_entropy = 0; + + assert(RAND_MAX > 0xffffff); /* Seen 7ffffffd! */ + assert(range < intmax_max); + + for(; got_entropy < range;) { + got_entropy = (got_entropy << 24) | 0xffffff; + value = (value << 24) | (random() % 0xffffff); + } + + return lb + (intmax_t)(value % (range + 1)); + } +}