Пример #1
0
        private static uint chacha_next32([NativeTypeName("mi_random_ctx_t*")] ref mi_random_ctx_t ctx)
        {
            if (ctx.output_available <= 0)
            {
                chacha_block(ref ctx);
                ctx.output_available = 16; // (assign again to suppress static analysis warning)
            }

            uint x = ctx.output[16 - ctx.output_available];

            ctx.output[16 - ctx.output_available] = 0; // reset once the data is handed out
            ctx.output_available--;

            return(x);
        }
Пример #2
0
        private static void chacha_block([NativeTypeName("mi_random_ctx_t*")] ref mi_random_ctx_t ctx)
        {
            // scramble into `x`
            uint *x = stackalloc uint[16];

            for (nuint i = 0; i < 16; i++)
            {
                x[i] = ctx.input[i];
            }
            for (nuint i = 0; i < MI_CHACHA_ROUNDS; i += 2)
            {
                qround(x, 0, 4, 8, 12);
                qround(x, 1, 5, 9, 13);
                qround(x, 2, 6, 10, 14);
                qround(x, 3, 7, 11, 15);
                qround(x, 0, 5, 10, 15);
                qround(x, 1, 6, 11, 12);
                qround(x, 2, 7, 8, 13);
                qround(x, 3, 4, 9, 14);
            }

            // add scrambled data to the initial state
            for (nuint i = 0; i < 16; i++)
            {
                ctx.output[i] = unchecked (x[i] + ctx.input[i]);
            }

            ctx.output_available = 16;

            // increment the counter for the next round
            ctx.input[12] += 1;

            if (ctx.input[12] == 0)
            {
                ctx.input[13] += 1;

                if (ctx.input[13] == 0)
                {
                    // and keep increasing into the nonce
                    ctx.input[14] += 1;
                }
            }
        }
Пример #3
0
        private static void chacha_init([NativeTypeName("mi_random_ctx_t*")] out mi_random_ctx_t ctx, [NativeTypeName("const uint8_t*")] ReadOnlySpan <byte> key, [NativeTypeName("uint64_t")] ulong nonce)
        {
            // since we only use chacha for randomness (and not encryption) we
            // do not _need_ to read 32-bit values as little endian but we do anyways
            // just for being compatible :-)

            ctx = default;

            for (nuint i = 0; i < 4; i++)
            {
                ctx.input[i] = read32(sigma, i);
            }

            for (nuint i = 0; i < 8; i++)
            {
                ctx.input[i + 4] = read32(key, i);
            }

            ctx.input[12] = 0;
            ctx.input[13] = 0;
            ctx.input[14] = unchecked ((uint)nonce);
            ctx.input[15] = (uint)(nonce >> 32);
        }
Пример #4
0
        // random.c

        private static partial void _mi_random_init([NativeTypeName("mi_random_ctx_t*")] out mi_random_ctx_t ctx);