Skip to content

Commit 7ad5a90

Browse files
authored
Merge pull request #30 from lazor-kit/fix/signature-replay-discriminator
Fix/signature replay discriminator
2 parents c57edcc + da615cf commit 7ad5a90

7 files changed

Lines changed: 38 additions & 14 deletions

File tree

program/src/auth/ed25519.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ impl Authenticator for Ed25519Authenticator {
1212
authority_data: &mut [u8],
1313
_auth_payload: &[u8],
1414
_signed_payload: &[u8],
15+
_discriminator: &[u8],
1516
) -> Result<(), ProgramError> {
1617
if authority_data.len() < std::mem::size_of::<AuthorityAccountHeader>() + 32 {
1718
return Err(ProgramError::InvalidAccountData);

program/src/auth/secp256r1/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ impl Authenticator for Secp256r1Authenticator {
3636
auth_data: &mut [u8],
3737
auth_payload: &[u8],
3838
signed_payload: &[u8], // The message payload (e.g. compact instructions or args) that is signed
39+
discriminator: &[u8],
3940
) -> Result<(), ProgramError> {
4041
if auth_payload.len() < 12 {
4142
return Err(AuthError::InvalidAuthorityPayload.into());
@@ -94,8 +95,8 @@ impl Authenticator for Secp256r1Authenticator {
9495
#[cfg(target_os = "solana")]
9596
unsafe {
9697
let _res = pinocchio::syscalls::sol_sha256(
97-
[signed_payload, &slot.to_le_bytes()].as_ptr() as *const u8,
98-
2,
98+
[discriminator, signed_payload, &slot.to_le_bytes()].as_ptr() as *const u8,
99+
3,
99100
hasher.as_mut_ptr(),
100101
);
101102
}

program/src/auth/traits.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ pub trait Authenticator {
1616
authority_data: &mut [u8],
1717
auth_payload: &[u8],
1818
signed_payload: &[u8],
19+
discriminator: &[u8],
1920
) -> Result<(), ProgramError>;
2021
}

program/src/processor/create_session.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,20 +157,25 @@ pub fn process(
157157
// For Secp256r1, we need to distinguish args from auth payload.
158158
// The instruction format is [discriminator][args][payload].
159159
// `instruction_data` here is [args][payload].
160+
let data_payload = &instruction_data[..payload_offset];
160161

161162
match auth_header.authority_type {
162163
0 => {
163-
Ed25519Authenticator.authenticate(accounts, auth_data, &[], &[])?;
164+
Ed25519Authenticator.authenticate(accounts, auth_data, &[], &[], &[5])?;
164165
},
165166
1 => {
166-
if !authorizer_pda.is_writable() {
167-
return Err(ProgramError::InvalidAccountData);
168-
}
167+
// Secp256r1 (WebAuthn) - Must be Writable
168+
// Check removed: conditional writable check inside match
169+
// Verified above.
170+
171+
// Secp256r1: Full authentication with payload
172+
// signed_payload is CreateSessionArgs (contains session_key + expires_at)
169173
Secp256r1Authenticator.authenticate(
170174
accounts,
171175
auth_data,
172176
authority_payload,
173-
&instruction_data[..payload_offset], // Sign over args part?
177+
data_payload,
178+
&[5],
174179
)?;
175180
},
176181
_ => return Err(AuthError::InvalidAuthenticationKind.into()),

program/src/processor/execute.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,23 @@ pub fn process(
102102
}
103103
match authority_header.authority_type {
104104
0 => {
105-
// Ed25519: Verify signer
106-
Ed25519Authenticator.authenticate(accounts, authority_data, &[], &[])?;
105+
// Ed25519: Verify signer (authority_payload ignored)
106+
Ed25519Authenticator.authenticate(accounts, authority_data, &[], &[], &[4])?;
107107
},
108108
1 => {
109-
// Secp256r1: Full authentication
109+
// Secp256r1 (WebAuthn)
110+
// signed_payload is compact_instructions bytes for Execute
111+
// The instruction format is [discriminator][compact_instructions_bytes][payload]
112+
// instruction_data is [compact_instructions_bytes][payload]
113+
let data_payload = &instruction_data[..compact_len];
114+
let authority_payload = &instruction_data[compact_len..];
115+
110116
Secp256r1Authenticator.authenticate(
111117
accounts,
112118
authority_data,
113119
authority_payload,
114-
&compact_bytes,
120+
data_payload,
121+
&[4],
115122
)?;
116123
},
117124
_ => return Err(AuthError::InvalidAuthenticationKind.into()),

program/src/processor/manage_authority.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ pub fn process_add_authority(
185185
match admin_header.authority_type {
186186
0 => {
187187
// Ed25519: Verify signer (authority_payload ignored)
188-
Ed25519Authenticator.authenticate(accounts, admin_data, &[], &[])?;
188+
Ed25519Authenticator.authenticate(accounts, admin_data, &[], &[], &[1])?;
189189
},
190190
1 => {
191191
// Secp256r1 (WebAuthn) - Must be Writable
@@ -198,6 +198,7 @@ pub fn process_add_authority(
198198
admin_data,
199199
authority_payload,
200200
data_payload,
201+
&[1],
201202
)?;
202203
},
203204
_ => return Err(AuthError::InvalidAuthenticationKind.into()),
@@ -345,14 +346,15 @@ pub fn process_remove_authority(
345346
// Authentication
346347
match admin_header.authority_type {
347348
0 => {
348-
Ed25519Authenticator.authenticate(accounts, admin_data, &[], &[])?;
349+
Ed25519Authenticator.authenticate(accounts, admin_data, &[], &[], &[2])?;
349350
},
350351
1 => {
351352
Secp256r1Authenticator.authenticate(
352353
accounts,
353354
admin_data,
354355
authority_payload,
355356
data_payload,
357+
&[2],
356358
)?;
357359
},
358360
_ => return Err(AuthError::InvalidAuthenticationKind.into()),

program/src/processor/transfer_ownership.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,21 @@ pub fn process(
151151
// Authenticate Current Owner
152152
match auth.authority_type {
153153
0 => {
154-
Ed25519Authenticator.authenticate(accounts, data, &[], &[])?;
154+
// Ed25519: Verify signer (authority_payload ignored)
155+
Ed25519Authenticator.authenticate(accounts, data, &[], &[], &[3])?;
155156
},
156157
1 => {
158+
// Secp256r1 (WebAuthn) - Must be Writable
159+
if !current_owner.is_writable() {
160+
return Err(ProgramError::InvalidAccountData);
161+
}
162+
// Secp256r1: Full authentication with payload
157163
Secp256r1Authenticator.authenticate(
158164
accounts,
159165
data,
160166
authority_payload,
161167
data_payload,
168+
&[3],
162169
)?;
163170
},
164171
_ => return Err(AuthError::InvalidAuthenticationKind.into()),

0 commit comments

Comments
 (0)