Skip to content

Commit 928144e

Browse files
authored
Merge pull request #960 from CosmWasm/move-limits
Move ED25519 msg limits from `crypto` to `vm`
2 parents ff0fab5 + f03b8fe commit 928144e

File tree

8 files changed

+30
-88
lines changed

8 files changed

+30
-88
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ and this project adheres to
1616
- cosmwasm-std: Remove `Context` - deprecated in previous release
1717
- cosmwasm-std: Remove `HandleResponse`, `InitResponse`, and `MigrateResponse` -
1818
deprecated in previous release
19+
- cosmwasm-crypto: Remove `ed25519::MESSAGE_MAX_LEN`, `ed25519::BATCH_MAX_LEN`
20+
and message length verification as this should not be a concern of
21+
`cosmwasm-crypto`.
1922

2023
[#905]: https://github.com/CosmWasm/cosmwasm/issues/905
2124

@@ -33,6 +36,8 @@ and this project adheres to
3336
- cosmwasm-vm: More accurate error messages for op codes related to bulk memory
3437
operations, reference types, SIMD and the Threads extension.
3538
- cosmwasm-vm: Update `wasmer` to `2.0.0-rc2`
39+
- cosmwasm-vm: ED25519 message length and batch length limits are now hardcoded
40+
in `cosmwasm-vm` itself instead of being imported from `cosmwasm-crypto`.
3641

3742
### Fixed
3843

packages/crypto/src/ed25519.rs

-34
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,6 @@ use std::convert::TryInto;
55

66
use crate::errors::{CryptoError, CryptoResult};
77

8-
/// Max length of a message for ed25519 verification in bytes.
9-
/// This is an arbitrary value, for performance / memory contraints. If you need to verify larger
10-
/// messages, let us know.
11-
pub const MESSAGE_MAX_LEN: usize = 128 * 1024;
12-
13-
/// Max number of batch messages / signatures / public_keys.
14-
/// This is an arbitrary value, for performance / memory contraints. If you need to batch-verify a
15-
/// larger number of signatures, let us know.
16-
pub const BATCH_MAX_LEN: usize = 256;
17-
188
/// Length of a serialized public key
199
pub const EDDSA_PUBKEY_LEN: usize = 32;
2010

@@ -30,7 +20,6 @@ pub const EDDSA_PUBKEY_LEN: usize = 32;
3020
/// - public key: raw ED25519 public key (32 bytes).
3121
pub fn ed25519_verify(message: &[u8], signature: &[u8], public_key: &[u8]) -> CryptoResult<bool> {
3222
// Validation
33-
check_message_length(message)?;
3423
let signature = read_signature(signature)?;
3524
let pubkey = read_pubkey(public_key)?;
3625

@@ -108,7 +97,6 @@ pub fn ed25519_batch_verify(
10897
.zip(public_keys.iter())
10998
{
11099
// Validation
111-
check_message_length(message)?;
112100
let signature = read_signature(signature)?;
113101
let pubkey = read_pubkey(public_key)?;
114102

@@ -149,28 +137,6 @@ fn read_pubkey(data: &[u8]) -> Result<[u8; 32], InvalidEd25519PubkeyFormat> {
149137
data.try_into().map_err(|_| InvalidEd25519PubkeyFormat)
150138
}
151139

152-
struct MessageTooLong {
153-
limit: usize,
154-
actual: usize,
155-
}
156-
157-
impl From<MessageTooLong> for CryptoError {
158-
fn from(original: MessageTooLong) -> Self {
159-
CryptoError::message_too_long(original.limit, original.actual)
160-
}
161-
}
162-
163-
fn check_message_length(message: &[u8]) -> Result<(), MessageTooLong> {
164-
if message.len() > MESSAGE_MAX_LEN {
165-
Err(MessageTooLong {
166-
limit: MESSAGE_MAX_LEN,
167-
actual: message.len(),
168-
})
169-
} else {
170-
Ok(())
171-
}
172-
}
173-
174140
#[cfg(test)]
175141
mod tests {
176142
use super::*;

packages/crypto/src/errors.rs

-29
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,6 @@ pub enum CryptoError {
3434
#[cfg(feature = "backtraces")]
3535
backtrace: Backtrace,
3636
},
37-
#[error("Message is longer than supported by this implementation (Limit: {limit}, actual length: {actual})")]
38-
MessageTooLong {
39-
limit: usize,
40-
actual: usize,
41-
#[cfg(feature = "backtraces")]
42-
backtrace: Backtrace,
43-
},
4437
#[error("Invalid recovery parameter. Supported values: 0 and 1.")]
4538
InvalidRecoveryParam {
4639
#[cfg(feature = "backtraces")]
@@ -86,15 +79,6 @@ impl CryptoError {
8679
}
8780
}
8881

89-
pub fn message_too_long(limit: usize, actual: usize) -> Self {
90-
CryptoError::MessageTooLong {
91-
limit,
92-
actual,
93-
#[cfg(feature = "backtraces")]
94-
backtrace: Backtrace::capture(),
95-
}
96-
}
97-
9882
pub fn invalid_recovery_param() -> Self {
9983
CryptoError::InvalidRecoveryParam {
10084
#[cfg(feature = "backtraces")]
@@ -106,7 +90,6 @@ impl CryptoError {
10690
/// contract VM boundary.
10791
pub fn code(&self) -> u32 {
10892
match self {
109-
CryptoError::MessageTooLong { .. } => 2,
11093
CryptoError::InvalidHashFormat { .. } => 3,
11194
CryptoError::InvalidSignatureFormat { .. } => 4,
11295
CryptoError::InvalidPubkeyFormat { .. } => 5,
@@ -162,18 +145,6 @@ mod tests {
162145
}
163146
}
164147

165-
#[test]
166-
fn message_too_long_works() {
167-
let error = CryptoError::message_too_long(5, 7);
168-
match error {
169-
CryptoError::MessageTooLong { limit, actual, .. } => {
170-
assert_eq!(limit, 5);
171-
assert_eq!(actual, 7);
172-
}
173-
_ => panic!("wrong error type!"),
174-
}
175-
}
176-
177148
#[test]
178149
fn invalid_pubkey_format_works() {
179150
let error = CryptoError::invalid_pubkey_format();

packages/crypto/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ mod identity_digest;
1010
mod secp256k1;
1111

1212
#[doc(hidden)]
13-
pub use crate::ed25519::{ed25519_batch_verify, ed25519_verify};
13+
pub use crate::ed25519::EDDSA_PUBKEY_LEN;
1414
#[doc(hidden)]
15-
pub use crate::ed25519::{BATCH_MAX_LEN, EDDSA_PUBKEY_LEN, MESSAGE_MAX_LEN};
15+
pub use crate::ed25519::{ed25519_batch_verify, ed25519_verify};
1616
#[doc(hidden)]
1717
pub use crate::errors::{CryptoError, CryptoResult};
1818
#[doc(hidden)]

packages/std/src/errors/recover_pubkey_error.rs

-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ impl PartialEq<RecoverPubkeyError> for RecoverPubkeyError {
6262
impl From<CryptoError> for RecoverPubkeyError {
6363
fn from(original: CryptoError) -> Self {
6464
match original {
65-
CryptoError::MessageTooLong { .. } => panic!("Conversion not supported"),
6665
CryptoError::InvalidHashFormat { .. } => RecoverPubkeyError::InvalidHashFormat,
6766
CryptoError::InvalidPubkeyFormat { .. } => panic!("Conversion not supported"),
6867
CryptoError::InvalidSignatureFormat { .. } => {

packages/std/src/errors/verification_error.rs

-4
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ pub enum VerificationError {
1212
BatchErr,
1313
#[error("Generic error")]
1414
GenericErr,
15-
#[error("Message is longer than supported")]
16-
MessageTooLong,
1715
#[error("Invalid hash format")]
1816
InvalidHashFormat,
1917
#[error("Invalid signature format")]
@@ -45,7 +43,6 @@ impl PartialEq<VerificationError> for VerificationError {
4543
match self {
4644
VerificationError::BatchErr => matches!(rhs, VerificationError::BatchErr),
4745
VerificationError::GenericErr => matches!(rhs, VerificationError::GenericErr),
48-
VerificationError::MessageTooLong => matches!(rhs, VerificationError::MessageTooLong),
4946
VerificationError::InvalidHashFormat => {
5047
matches!(rhs, VerificationError::InvalidHashFormat)
5148
}
@@ -77,7 +74,6 @@ impl PartialEq<VerificationError> for VerificationError {
7774
impl From<CryptoError> for VerificationError {
7875
fn from(original: CryptoError) -> Self {
7976
match original {
80-
CryptoError::MessageTooLong { .. } => VerificationError::MessageTooLong,
8177
CryptoError::InvalidHashFormat { .. } => VerificationError::InvalidHashFormat,
8278
CryptoError::InvalidPubkeyFormat { .. } => VerificationError::InvalidPubkeyFormat,
8379
CryptoError::InvalidSignatureFormat { .. } => VerificationError::InvalidSignatureFormat,

packages/std/src/imports.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ impl Api for ExternalApi {
279279
match result {
280280
0 => Ok(true),
281281
1 => Ok(false),
282-
2 => Err(VerificationError::MessageTooLong),
282+
2 => panic!("Error code 2 unused since CosmWasm 0.15. This is a bug in the VM."),
283283
3 => panic!("InvalidHashFormat must not happen. This is a bug in the VM."),
284284
4 => Err(VerificationError::InvalidSignatureFormat),
285285
5 => Err(VerificationError::InvalidPubkeyFormat),
@@ -311,7 +311,7 @@ impl Api for ExternalApi {
311311
match result {
312312
0 => Ok(true),
313313
1 => Ok(false),
314-
2 => Err(VerificationError::MessageTooLong),
314+
2 => panic!("Error code 2 unused since CosmWasm 0.15. This is a bug in the VM."),
315315
3 => panic!("InvalidHashFormat must not happen. This is a bug in the VM."),
316316
4 => Err(VerificationError::InvalidSignatureFormat),
317317
5 => Err(VerificationError::InvalidPubkeyFormat),

packages/vm/src/imports.rs

+21-16
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ use cosmwasm_crypto::{
77
ed25519_batch_verify, ed25519_verify, secp256k1_recover_pubkey, secp256k1_verify, CryptoError,
88
};
99
use cosmwasm_crypto::{
10-
BATCH_MAX_LEN, ECDSA_PUBKEY_MAX_LEN, ECDSA_SIGNATURE_LEN, EDDSA_PUBKEY_LEN,
11-
MESSAGE_HASH_MAX_LEN, MESSAGE_MAX_LEN,
10+
ECDSA_PUBKEY_MAX_LEN, ECDSA_SIGNATURE_LEN, EDDSA_PUBKEY_LEN, MESSAGE_HASH_MAX_LEN,
1211
};
1312

1413
#[cfg(feature = "iterator")]
@@ -42,6 +41,14 @@ const MAX_LENGTH_HUMAN_ADDRESS: usize = 90;
4241
const MAX_LENGTH_QUERY_CHAIN_REQUEST: usize = 64 * KI;
4342
/// Length of a serialized Ed25519 signature
4443
const MAX_LENGTH_ED25519_SIGNATURE: usize = 64;
44+
/// Max length of a Ed25519 message in bytes.
45+
/// This is an arbitrary value, for performance / memory contraints. If you need to verify larger
46+
/// messages, let us know.
47+
const MAX_LENGTH_ED25519_MESSAGE: usize = 128 * 1024;
48+
/// Max number of batch Ed25519 messages / signatures / public_keys.
49+
/// This is an arbitrary value, for performance / memory contraints. If you need to batch-verify a
50+
/// larger number of signatures, let us know.
51+
const MAX_COUNT_ED25519_BATCH: usize = 256;
4552

4653
/// Max length for a debug message
4754
const MAX_LENGTH_DEBUG: usize = 2 * MI;
@@ -326,9 +333,9 @@ fn do_secp256k1_verify<A: BackendApi, S: Storage, Q: Querier>(
326333
| CryptoError::InvalidPubkeyFormat { .. }
327334
| CryptoError::InvalidSignatureFormat { .. }
328335
| CryptoError::GenericErr { .. } => err.code(),
329-
CryptoError::BatchErr { .. }
330-
| CryptoError::InvalidRecoveryParam { .. }
331-
| CryptoError::MessageTooLong { .. } => panic!("Error must not happen for this call"),
336+
CryptoError::BatchErr { .. } | CryptoError::InvalidRecoveryParam { .. } => {
337+
panic!("Error must not happen for this call")
338+
}
332339
},
333340
|valid| if valid { 0 } else { 1 },
334341
))
@@ -360,9 +367,9 @@ fn do_secp256k1_recover_pubkey<A: BackendApi, S: Storage, Q: Querier>(
360367
| CryptoError::InvalidSignatureFormat { .. }
361368
| CryptoError::InvalidRecoveryParam { .. }
362369
| CryptoError::GenericErr { .. } => Ok(to_high_half(err.code())),
363-
CryptoError::BatchErr { .. }
364-
| CryptoError::InvalidPubkeyFormat { .. }
365-
| CryptoError::MessageTooLong { .. } => panic!("Error must not happen for this call"),
370+
CryptoError::BatchErr { .. } | CryptoError::InvalidPubkeyFormat { .. } => {
371+
panic!("Error must not happen for this call")
372+
}
366373
},
367374
}
368375
}
@@ -373,7 +380,7 @@ fn do_ed25519_verify<A: BackendApi, S: Storage, Q: Querier>(
373380
signature_ptr: u32,
374381
pubkey_ptr: u32,
375382
) -> VmResult<u32> {
376-
let message = read_region(&env.memory(), message_ptr, MESSAGE_MAX_LEN)?;
383+
let message = read_region(&env.memory(), message_ptr, MAX_LENGTH_ED25519_MESSAGE)?;
377384
let signature = read_region(&env.memory(), signature_ptr, MAX_LENGTH_ED25519_SIGNATURE)?;
378385
let pubkey = read_region(&env.memory(), pubkey_ptr, EDDSA_PUBKEY_LEN)?;
379386

@@ -382,8 +389,7 @@ fn do_ed25519_verify<A: BackendApi, S: Storage, Q: Querier>(
382389
process_gas_info::<A, S, Q>(env, gas_info)?;
383390
Ok(result.map_or_else(
384391
|err| match err {
385-
CryptoError::MessageTooLong { .. }
386-
| CryptoError::InvalidPubkeyFormat { .. }
392+
CryptoError::InvalidPubkeyFormat { .. }
387393
| CryptoError::InvalidSignatureFormat { .. }
388394
| CryptoError::GenericErr { .. } => err.code(),
389395
CryptoError::BatchErr { .. }
@@ -405,17 +411,17 @@ fn do_ed25519_batch_verify<A: BackendApi, S: Storage, Q: Querier>(
405411
let messages = read_region(
406412
&env.memory(),
407413
messages_ptr,
408-
(MESSAGE_MAX_LEN + 4) * BATCH_MAX_LEN,
414+
(MAX_LENGTH_ED25519_MESSAGE + 4) * MAX_COUNT_ED25519_BATCH,
409415
)?;
410416
let signatures = read_region(
411417
&env.memory(),
412418
signatures_ptr,
413-
(MAX_LENGTH_ED25519_SIGNATURE + 4) * BATCH_MAX_LEN,
419+
(MAX_LENGTH_ED25519_SIGNATURE + 4) * MAX_COUNT_ED25519_BATCH,
414420
)?;
415421
let public_keys = read_region(
416422
&env.memory(),
417423
public_keys_ptr,
418-
(EDDSA_PUBKEY_LEN + 4) * BATCH_MAX_LEN,
424+
(EDDSA_PUBKEY_LEN + 4) * MAX_COUNT_ED25519_BATCH,
419425
)?;
420426

421427
let messages = decode_sections(&messages);
@@ -433,7 +439,6 @@ fn do_ed25519_batch_verify<A: BackendApi, S: Storage, Q: Querier>(
433439
Ok(result.map_or_else(
434440
|err| match err {
435441
CryptoError::BatchErr { .. }
436-
| CryptoError::MessageTooLong { .. }
437442
| CryptoError::InvalidPubkeyFormat { .. }
438443
| CryptoError::InvalidSignatureFormat { .. }
439444
| CryptoError::GenericErr { .. } => err.code(),
@@ -1561,7 +1566,7 @@ mod tests {
15611566

15621567
let mut msg = hex::decode(EDDSA_MSG_HEX).unwrap();
15631568
// extend / break msg
1564-
msg.extend_from_slice(&[0x00; MESSAGE_MAX_LEN + 1]);
1569+
msg.extend_from_slice(&[0x00; MAX_LENGTH_ED25519_MESSAGE + 1]);
15651570
let msg_ptr = write_data(&env, &msg);
15661571
let sig = hex::decode(EDDSA_SIG_HEX).unwrap();
15671572
let sig_ptr = write_data(&env, &sig);

0 commit comments

Comments
 (0)