// Generated by tool/gen/fn/generate.py; do not edit.
// schema_sha256=787c413dea5e27098bec8d4778942ded65ed94c4cfffda39e20fac88581b05f1
// ML-DSA-87 batch external pure verification with a shared context.
// Experimental public-only route; physical-device qualification remains separate.
// FIPS 204 Algorithms 3/8. New implementation; OA historical shader was a stub.
import attributes;
import mldsa_verification;
import shake;
struct PushConstants {
uint input_index;
uint offsets_index;
uint lengths_index;
uint sigs_index;
uint pks_index;
uint results_index;
uint batch_size;
uint message_bytes;
uint context_offset;
uint context_length;
};
[[vk::push_constant]] PushConstants push;
[[vk::binding(0, 0)]] RWByteAddressBuffer storage_buffers[];
[kernel_name("ml_dsa_87_verify")]
[domain("cryptography")]
[variant("generic")]
[dtype("u8")]
[status("experimental")]
[shader("compute")]
[numthreads(1, 1, 1)]
void main(uint3 dispatch_thread_id : SV_DispatchThreadID) {
uint idx = dispatch_thread_id.x;
if (idx >= push.batch_size || idx > 0xffffffffu / 4u) return;
uint output_base = idx * 4u;
if (!pqc_buffer_range(storage_buffers[push.results_index], output_base, 4u)) return;
storage_buffers[push.results_index].Store(output_base, 0u);
if (!pqc_buffer_range(storage_buffers[push.offsets_index], output_base, 4u)
|| !pqc_buffer_range(storage_buffers[push.lengths_index], output_base, 4u)
|| idx > 0xffffffffu / 2592u
|| idx > 0xffffffffu / 4627u) return;
uint offset = storage_buffers[push.offsets_index].Load(output_base);
uint length = storage_buffers[push.lengths_index].Load(output_base);
// Allocation padding is not part of the semantic message buffer.
if (offset > push.message_bytes || length > push.message_bytes - offset
|| push.context_length > 255u
|| push.context_offset > push.message_bytes
|| push.context_length > push.message_bytes - push.context_offset) return;
bool valid = mldsa_verify_external(
87u,
storage_buffers[push.pks_index], idx * 2592u, 2592u,
storage_buffers[push.sigs_index], idx * 4627u, 4627u,
storage_buffers[push.input_index], offset, length,
storage_buffers[push.input_index], push.context_offset, push.context_length);
storage_buffers[push.results_index].Store(output_base, valid ? 1u : 0u);
}