- Apache 2.0 section 4(b): the patches modify files that are the work of Hyperledger Besu and now say so, with the notice inside the modified files, which is what the licence asks for and what applying the patch produces. - patches/ and precompiles/ now carry the staged versions rather than an older export. The two had drifted in both directions; the only thing the published copy had that the staged one lacked was the word "audited" in front of Bouncy Castle, which we cannot evidence and which the staged version had dropped. - the brand was spelled two ways in the same repository, 62 times one way and 23 the other. It is Aere Network; AERE is the ticker. The 96 AERE_* code identifiers are untouched.
95 lines
3.8 KiB
Java
95 lines
3.8 KiB
Java
/*
|
|
* Copyright contributors to the Aere Network.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations under the License.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
package org.hyperledger.besu.evm.precompile;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import org.apache.tuweni.bytes.Bytes;
|
|
import org.apache.tuweni.bytes.Bytes32;
|
|
import org.bouncycastle.pqc.crypto.falcon.FalconParameters;
|
|
import org.bouncycastle.pqc.crypto.falcon.FalconPublicKeyParameters;
|
|
import org.bouncycastle.pqc.crypto.falcon.FalconSigner;
|
|
|
|
/**
|
|
* Shared logic for the AERE Falcon-512 / Falcon-1024 verification precompiles.
|
|
*
|
|
* <p>Transcodes the NIST round-3 reference "signed message" (sm) blob into the encoding Bouncy
|
|
* Castle's {@link FalconSigner#verifySignature(byte[], byte[])} expects and drives the audited
|
|
* verifier. No cryptography is reimplemented here.
|
|
*
|
|
* <p>NIST sm layout: {@code sigLen(2, big-endian) || nonce(40) || message || esig} where
|
|
* {@code esig = (0x20+logn) || compressedSig} and {@code sigLen == esig.length}. The Falcon public
|
|
* key is {@code (0x00+logn) || packed_h}; Bouncy Castle wants only {@code packed_h} (header
|
|
* stripped), and the signature it wants is {@code (0x30+logn) || nonce(40) || compressedSig}.
|
|
*/
|
|
final class AereFalconSupport {
|
|
|
|
static final int NONCE_LEN = 40;
|
|
|
|
private AereFalconSupport() {}
|
|
|
|
static Bytes resultWord(final boolean valid) {
|
|
return valid ? Bytes32.leftPad(Bytes.of((byte) 1)) : Bytes32.ZERO;
|
|
}
|
|
|
|
/**
|
|
* Verify a NIST signed-message blob against a Falcon public key.
|
|
*
|
|
* @param params Bouncy Castle Falcon parameter set (falcon_512 / falcon_1024)
|
|
* @param logn 9 for Falcon-512, 10 for Falcon-1024
|
|
* @param pkFull the 897- (512) or 1793-byte (1024) public key including the leading header byte
|
|
* @param sm the NIST signed-message blob
|
|
* @return true iff the signature is valid for the embedded message under pkFull
|
|
*/
|
|
static boolean verify(
|
|
final FalconParameters params, final int logn, final byte[] pkFull, final byte[] sm) {
|
|
try {
|
|
if (pkFull.length < 2 || sm.length < 2 + NONCE_LEN + 2) {
|
|
return false;
|
|
}
|
|
if ((pkFull[0] & 0xff) != logn) {
|
|
return false;
|
|
}
|
|
final int sigLen = ((sm[0] & 0xff) << 8) | (sm[1] & 0xff);
|
|
if (sigLen < 2 || 2 + NONCE_LEN + sigLen > sm.length) {
|
|
return false;
|
|
}
|
|
final int msgLen = sm.length - 2 - NONCE_LEN - sigLen;
|
|
if (msgLen < 0) {
|
|
return false;
|
|
}
|
|
final byte[] esig = Arrays.copyOfRange(sm, sm.length - sigLen, sm.length);
|
|
if ((esig[0] & 0xff) != (0x20 + logn)) {
|
|
return false;
|
|
}
|
|
final byte[] H = Arrays.copyOfRange(pkFull, 1, pkFull.length);
|
|
final byte[] nonce = Arrays.copyOfRange(sm, 2, 2 + NONCE_LEN);
|
|
final byte[] message = Arrays.copyOfRange(sm, 2 + NONCE_LEN, 2 + NONCE_LEN + msgLen);
|
|
|
|
final byte[] bcSig = new byte[1 + NONCE_LEN + (esig.length - 1)];
|
|
bcSig[0] = (byte) (0x30 + logn);
|
|
System.arraycopy(nonce, 0, bcSig, 1, NONCE_LEN);
|
|
System.arraycopy(esig, 1, bcSig, 1 + NONCE_LEN, esig.length - 1);
|
|
|
|
final FalconPublicKeyParameters pub = new FalconPublicKeyParameters(params, H);
|
|
final FalconSigner signer = new FalconSigner();
|
|
signer.init(false, pub);
|
|
return signer.verifySignature(message, bcSig);
|
|
} catch (final Throwable t) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|