in FourQ_ARM_NEON/schnorrq.c [134:190]
ECCRYPTO_STATUS SchnorrQ_Verify(const unsigned char* PublicKey, const unsigned char* Message, const unsigned int SizeMessage, const unsigned char* Signature, unsigned int* valid)
{ // SchnorrQ signature verification
// It verifies the signature Signature of a message Message of size SizeMessage in bytes
// Inputs: 32-byte PublicKey, 64-byte Signature, and Message of size SizeMessage in bytes
// Output: true (valid signature) or false (invalid signature)
point_t A;
unsigned char *temp, h[64];
unsigned int i;
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
*valid = false;
temp = (unsigned char*)calloc(1, SizeMessage+64);
if (temp == NULL) {
Status = ECCRYPTO_ERROR_NO_MEMORY;
goto cleanup;
}
if (((PublicKey[15] & 0x80) != 0) || ((Signature[15] & 0x80) != 0) || (Signature[63] != 0) || ((Signature[62] & 0xC0) != 0)) { // Are bit128(PublicKey) = bit128(Signature) = 0 and Signature+32 < 2^246?
Status = ECCRYPTO_ERROR_INVALID_PARAMETER;
goto cleanup;
}
Status = decode(PublicKey, A); // Also verifies that A is on the curve. If it is not, it fails
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
memmove(temp, Signature, 32);
memmove(temp+32, PublicKey, 32);
memmove(temp+64, Message, SizeMessage);
if (CryptoHashFunction(temp, SizeMessage+64, h) != 0) {
Status = ECCRYPTO_ERROR;
goto cleanup;
}
Status = ecc_mul_double((digit_t*)(Signature+32), A, (digit_t*)h, A);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
encode(A, (unsigned char*)A);
for (i = 0; i < NWORDS_ORDER; i++) {
if (((digit_t*)A)[i] != ((digit_t*)Signature)[i]) {
goto cleanup;
}
}
*valid = true;
cleanup:
if (temp != NULL)
free(temp);
return Status;
}