Security changes (#9923)

* Move test-only functions to test modules

* Remove sigverify disable

* Remove chacha CTR code
This commit is contained in:
sakridge 2020-05-08 10:00:23 -07:00 committed by GitHub
parent 01ab1d1369
commit f98bfda6f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 36 additions and 132 deletions

View File

@ -19,10 +19,6 @@ void chacha20_encrypt(const u32 input[16],
unsigned char output[64],
int num_rounds);
void chacha20_encrypt_ctr(const uint8_t *in, uint8_t *out, size_t in_len,
const uint8_t key[CHACHA_KEY_SIZE], const uint8_t nonce[CHACHA_NONCE_SIZE],
uint32_t counter);
void chacha20_cbc128_encrypt(const unsigned char* in, unsigned char* out,
uint32_t len, const uint8_t* key,
unsigned char* ivec);

View File

@ -22,10 +22,6 @@
x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
// sigma contains the ChaCha constants, which happen to be an ASCII string.
static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
'2', '-', 'b', 'y', 't', 'e', ' ', 'k' };
void chacha20_encrypt(const u32 input[16],
unsigned char output[64],
int num_rounds)
@ -51,52 +47,3 @@ void chacha20_encrypt(const u32 input[16],
}
}
void chacha20_encrypt_ctr(const uint8_t *in, uint8_t *out, size_t in_len,
const uint8_t key[CHACHA_KEY_SIZE],
const uint8_t nonce[CHACHA_NONCE_SIZE],
uint32_t counter)
{
uint32_t input[16];
uint8_t buf[64];
size_t todo, i;
input[0] = U8TO32_LITTLE(sigma + 0);
input[1] = U8TO32_LITTLE(sigma + 4);
input[2] = U8TO32_LITTLE(sigma + 8);
input[3] = U8TO32_LITTLE(sigma + 12);
input[4] = U8TO32_LITTLE(key + 0);
input[5] = U8TO32_LITTLE(key + 4);
input[6] = U8TO32_LITTLE(key + 8);
input[7] = U8TO32_LITTLE(key + 12);
input[8] = U8TO32_LITTLE(key + 16);
input[9] = U8TO32_LITTLE(key + 20);
input[10] = U8TO32_LITTLE(key + 24);
input[11] = U8TO32_LITTLE(key + 28);
input[12] = counter;
input[13] = U8TO32_LITTLE(nonce + 0);
input[14] = U8TO32_LITTLE(nonce + 4);
input[15] = U8TO32_LITTLE(nonce + 8);
while (in_len > 0) {
todo = sizeof(buf);
if (in_len < todo) {
todo = in_len;
}
chacha20_encrypt(input, buf, 20);
for (i = 0; i < todo; i++) {
out[i] = in[i] ^ buf[i];
}
out += todo;
in += todo;
in_len -= todo;
input[12]++;
}
}

View File

@ -198,7 +198,6 @@ impl ClusterInfoVoteListener {
pub fn new(
exit: &Arc<AtomicBool>,
cluster_info: Arc<ClusterInfo>,
sigverify_disabled: bool,
sender: CrossbeamSender<Vec<Packets>>,
poh_recorder: &Arc<Mutex<PohRecorder>>,
vote_tracker: Arc<VoteTracker>,
@ -214,7 +213,6 @@ impl ClusterInfoVoteListener {
let _ = Self::recv_loop(
exit_,
&cluster_info,
sigverify_disabled,
verified_vote_packets_sender,
verified_vote_transactions_sender,
);
@ -263,7 +261,6 @@ impl ClusterInfoVoteListener {
fn recv_loop(
exit: Arc<AtomicBool>,
cluster_info: &ClusterInfo,
sigverify_disabled: bool,
verified_vote_packets_sender: VerifiedVotePacketsSender,
verified_vote_transactions_sender: VerifiedVoteTransactionsSender,
) -> Result<()> {
@ -277,7 +274,7 @@ impl ClusterInfoVoteListener {
last_ts = new_ts;
if !votes.is_empty() {
let (vote_txs, packets) = Self::verify_votes(votes, labels, sigverify_disabled);
let (vote_txs, packets) = Self::verify_votes(votes, labels);
verified_vote_transactions_sender.send(vote_txs)?;
verified_vote_packets_sender.send(packets)?;
}
@ -289,14 +286,9 @@ impl ClusterInfoVoteListener {
fn verify_votes(
votes: Vec<Transaction>,
labels: Vec<CrdsValueLabel>,
sigverify_disabled: bool,
) -> (Vec<Transaction>, Vec<(CrdsValueLabel, Packets)>) {
let msgs = packet::to_packets_chunked(&votes, 1);
let r = if sigverify_disabled {
sigverify::ed25519_verify_disabled(&msgs)
} else {
sigverify::ed25519_verify_cpu(&msgs)
};
let r = sigverify::ed25519_verify_cpu(&msgs);
assert_eq!(
r.iter()
@ -986,7 +978,7 @@ mod tests {
solana_logger::setup();
let votes = vec![];
let labels = vec![];
let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, labels, false);
let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, labels);
assert!(vote_txs.is_empty());
assert!(packets.is_empty());
}
@ -1017,7 +1009,7 @@ mod tests {
let vote_tx = test_vote_tx();
let votes = vec![vote_tx.clone()];
let labels = vec![CrdsValueLabel::Vote(0, Pubkey::new_rand())];
let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, labels, false);
let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, labels);
assert_eq!(vote_txs.len(), 1);
verify_packets_len(&packets, 1);
}
@ -1033,7 +1025,7 @@ mod tests {
.into_iter()
.map(|_| label.clone())
.collect();
let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, labels, false);
let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, labels);
assert_eq!(vote_txs.len(), 2);
verify_packets_len(&packets, 2);
}

View File

@ -51,7 +51,7 @@ type ArchiverMap = Vec<HashMap<Pubkey, Vec<Proof>>>;
#[derive(Default)]
pub struct StorageStateInner {
storage_results: StorageResults,
pub storage_results: StorageResults,
pub storage_keys: StorageKeys,
archiver_map: ArchiverMap,
storage_blockhash: Hash,
@ -86,16 +86,6 @@ const KEY_SIZE: usize = 64;
type InstructionSender = Sender<Instruction>;
fn get_identity_index_from_signature(key: &Signature) -> usize {
let rkey = key.as_ref();
let mut res: usize = (rkey[0] as usize)
| ((rkey[1] as usize) << 8)
| ((rkey[2] as usize) << 16)
| ((rkey[3] as usize) << 24);
res &= NUM_IDENTITIES - 1;
res
}
impl StorageState {
pub fn new(hash: &Hash, slots_per_turn: u64, slots_per_segment: u64) -> Self {
let storage_keys = vec![0u8; KEY_SIZE * NUM_IDENTITIES];
@ -117,16 +107,6 @@ impl StorageState {
}
}
pub fn get_mining_key(&self, key: &Signature) -> Vec<u8> {
let idx = get_identity_index_from_signature(key);
self.state.read().unwrap().storage_keys[idx..idx + KEY_SIZE].to_vec()
}
pub fn get_mining_result(&self, key: &Signature) -> Hash {
let idx = get_identity_index_from_signature(key);
self.state.read().unwrap().storage_results[idx]
}
pub fn get_storage_blockhash(&self) -> Hash {
self.state.read().unwrap().storage_blockhash
}
@ -658,6 +638,16 @@ pub fn test_cluster_info(id: &Pubkey) -> Arc<ClusterInfo> {
Arc::new(cluster_info)
}
pub fn get_identity_index_from_signature(key: &Signature) -> usize {
let rkey = key.as_ref();
let mut res: usize = (rkey[0] as usize)
| ((rkey[1] as usize) << 8)
| ((rkey[2] as usize) << 16)
| ((rkey[3] as usize) << 24);
res &= NUM_IDENTITIES - 1;
res
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -9,7 +9,7 @@ use crate::{
fetch_stage::FetchStage,
poh_recorder::{PohRecorder, WorkingBankEntry},
sigverify::TransactionSigVerifier,
sigverify_stage::{DisabledSigVerifier, SigVerifyStage},
sigverify_stage::SigVerifyStage,
};
use crossbeam_channel::unbounded;
use solana_ledger::{
@ -43,7 +43,6 @@ impl Tpu {
transactions_sockets: Vec<UdpSocket>,
tpu_forwards_sockets: Vec<UdpSocket>,
broadcast_sockets: Vec<UdpSocket>,
sigverify_disabled: bool,
transaction_status_sender: Option<TransactionStatusSender>,
blockstore: &Arc<Blockstore>,
broadcast_type: &BroadcastStageType,
@ -62,19 +61,15 @@ impl Tpu {
);
let (verified_sender, verified_receiver) = unbounded();
let sigverify_stage = if !sigverify_disabled {
let sigverify_stage = {
let verifier = TransactionSigVerifier::default();
SigVerifyStage::new(packet_receiver, verified_sender, verifier)
} else {
let verifier = DisabledSigVerifier::default();
SigVerifyStage::new(packet_receiver, verified_sender, verifier)
};
let (verified_vote_sender, verified_vote_receiver) = unbounded();
let cluster_info_vote_listener = ClusterInfoVoteListener::new(
&exit,
cluster_info.clone(),
sigverify_disabled,
verified_vote_sender,
&poh_recorder,
vote_tracker,

View File

@ -17,7 +17,7 @@ use crate::{
rpc_subscriptions::RpcSubscriptions,
shred_fetch_stage::ShredFetchStage,
sigverify_shreds::ShredSigVerifier,
sigverify_stage::{DisabledSigVerifier, SigVerifyStage},
sigverify_stage::SigVerifyStage,
storage_stage::{StorageStage, StorageState},
};
use crossbeam_channel::unbounded;
@ -64,7 +64,6 @@ pub struct Sockets {
#[derive(Default)]
pub struct TvuConfig {
pub max_ledger_shreds: Option<u64>,
pub sigverify_disabled: bool,
pub shred_version: u16,
pub halt_on_trusted_validators_accounts_hash_mismatch: bool,
pub trusted_validators: Option<HashSet<Pubkey>>,
@ -128,19 +127,11 @@ impl Tvu {
);
let (verified_sender, verified_receiver) = unbounded();
let sigverify_stage = if !tvu_config.sigverify_disabled {
SigVerifyStage::new(
fetch_receiver,
verified_sender,
ShredSigVerifier::new(bank_forks.clone(), leader_schedule_cache.clone()),
)
} else {
SigVerifyStage::new(
fetch_receiver,
verified_sender,
DisabledSigVerifier::default(),
)
};
let sigverify_stage = SigVerifyStage::new(
fetch_receiver,
verified_sender,
ShredSigVerifier::new(bank_forks.clone(), leader_schedule_cache.clone()),
);
let cluster_slots = Arc::new(ClusterSlots::default());
let (duplicate_slots_reset_sender, duplicate_slots_reset_receiver) = unbounded();

View File

@ -59,7 +59,6 @@ use std::{
#[derive(Clone, Debug)]
pub struct ValidatorConfig {
pub dev_sigverify_disabled: bool,
pub dev_halt_at_slot: Option<Slot>,
pub expected_genesis_hash: Option<Hash>,
pub expected_shred_version: Option<u16>,
@ -87,7 +86,6 @@ pub struct ValidatorConfig {
impl Default for ValidatorConfig {
fn default() -> Self {
Self {
dev_sigverify_disabled: false,
dev_halt_at_slot: None,
expected_genesis_hash: None,
expected_shred_version: None,
@ -441,7 +439,6 @@ impl Validator {
retransmit_slots_sender,
TvuConfig {
max_ledger_shreds: config.max_ledger_shreds,
sigverify_disabled: config.dev_sigverify_disabled,
halt_on_trusted_validators_accounts_hash_mismatch: config
.halt_on_trusted_validators_accounts_hash_mismatch,
shred_version: node.info.shred_version,
@ -450,10 +447,6 @@ impl Validator {
},
);
if config.dev_sigverify_disabled {
warn!("signature verification disabled");
}
let tpu = Tpu::new(
&cluster_info,
&poh_recorder,
@ -462,7 +455,6 @@ impl Validator {
node.sockets.tpu,
node.sockets.tpu_forwards,
node.sockets.broadcast,
config.dev_sigverify_disabled,
transaction_status_sender,
&blockstore,
&config.broadcast_stage_type,

View File

@ -5,7 +5,10 @@ mod tests {
use log::*;
use solana_core::{
commitment::BlockCommitmentCache,
storage_stage::{test_cluster_info, StorageStage, StorageState, SLOTS_PER_TURN_TEST},
storage_stage::{
get_identity_index_from_signature, test_cluster_info, StorageStage, StorageState,
SLOTS_PER_TURN_TEST,
},
};
use solana_ledger::{
bank_forks::BankForks,
@ -19,7 +22,7 @@ mod tests {
hash::Hash,
message::Message,
pubkey::Pubkey,
signature::{Keypair, Signer},
signature::{Keypair, Signature, Signer},
transaction::Transaction,
};
use solana_storage_program::storage_instruction::{self, StorageAccountType};
@ -34,6 +37,11 @@ mod tests {
time::Duration,
};
fn get_mining_result(storage_state: &StorageState, key: &Signature) -> Hash {
let idx = get_identity_index_from_signature(key);
storage_state.state.read().unwrap().storage_results[idx]
}
#[test]
fn test_storage_stage_process_account_proofs() {
solana_logger::setup();
@ -205,7 +213,7 @@ mod tests {
let hash = Hash::default();
let signature = keypair.sign_message(&hash.as_ref());
let mut result = storage_state.get_mining_result(&signature);
let mut result = get_mining_result(&storage_state, &signature);
assert_eq!(result, Hash::default());
@ -228,7 +236,7 @@ mod tests {
if solana_perf::perf_libs::api().is_some() {
for _ in 0..5 {
result = storage_state.get_mining_result(&signature);
result = get_mining_result(&storage_state, &signature);
if result != Hash::default() {
info!("found result = {:?} sleeping..", result);
break;

View File

@ -572,12 +572,6 @@ pub fn main() {
.requires("entrypoint")
.help("Skip the RPC vote account sanity check")
)
.arg(
Arg::with_name("dev_no_sigverify")
.long("dev-no-sigverify")
.takes_value(false)
.help("Run without signature verification"),
)
.arg(
Arg::with_name("dev_halt_at_slot")
.long("dev-halt-at-slot")
@ -867,7 +861,6 @@ pub fn main() {
};
let mut validator_config = ValidatorConfig {
dev_sigverify_disabled: matches.is_present("dev_no_sigverify"),
dev_halt_at_slot: value_t!(matches, "dev_halt_at_slot", Slot).ok(),
expected_genesis_hash: matches
.value_of("expected_genesis_hash")