Skip to content

Commit

Permalink
Fix for bug in git issue 260 & addressing some revie comments
Browse files Browse the repository at this point in the history
Signed-off-by: prakashngit <prakash.narayana.moorthy@intel.com>
  • Loading branch information
prakashngit committed Apr 18, 2020
1 parent 4ba4cc1 commit 4cac5c5
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 54 deletions.
16 changes: 8 additions & 8 deletions ccf_transaction_processor/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ only under the virtual enclave mode for both PDO and CCF. (set env variable SGX_
set cmake flag TARGET=virtual for ccf). Support for HW mode for both PDO and CCF will be added soon. Further,
the current implementation of PDO TP hasn't been tested under multi-threaded CCF enclaves.(CCF 0.7.1 offers initial support for multi-threading). It is recommended that the application is deployed with single worker thread per enclave. Please see https://microsoft.github.io/CCF/developers/threading.html for instructions.

CCF uses mutually authenticated TLS channels for transactions. Given that in PDO client authentication is implemented within the transaction processor itself, we do not utilize the client authentication feature provided by CCF. Once CCF is deployed, CCF's network certificate (networkcert.pem) and one set of user keys (userccf_cert.pem & userccf_privk.pem)
must be made available to all PDO processes that want to submit a CCF transaction. In this case, every
PDO process behaves as though it is a CCF user corresponding to the private key userccf_privk.pem.
CCF uses mutually authenticated TLS channels for transactions. Given that in PDO client authentication is implemented within the transaction processor itself, we do not utilize the client authentication feature provided by CCF. Once CCF is deployed, CCF's network certificate (networkcert.pem) and one set of user keys (userccf_cert.pem & userccf_privk.pem) must be made available to all PDO processes that want to submit a CCF transaction. In this case, every PDO process behaves as though it is a CCF user corresponding to the private key userccf_privk.pem.
These keys must be stored under $PDO_LEDGER_KEY_ROOT as part of PDO deployment.

It may be noted that PDO also supports TP based on the Hyperledger Sawtooth blockchain.
Expand All @@ -33,10 +31,12 @@ A feature of the CCF based TP that is not supported by Sawtooth based TP is the
responses to read-transactions include a payload signature, where the signature is generated by the CCF enclave
serving the read request. The (signing key, verifying key) pair is created within the TP,
and is globally persisted among all CCF enclaves. The verifying_key can be obtained from CCF using
the "get_ledger_verifying_key" transaction. In fact, the very first invocation of "get_ledger_verifying_key" rpc
after the service is started is used to create the key pair, which will then be globally committed.
This feature may be used by PDO clients to establish offline verifiable proof of transaction commits as
desired by the PDO smart contract application. Note that for trust purposes, it is recommended that
any entity that uses the above verifying_key gets it directly from the CCF service using the
the "get_ledger_verifying_key" transaction. This feature may be used by PDO clients to establish offline verifiable proof of transaction commits as desired by the PDO smart contract application. Note that for trust purposes, it is recommended that any entity that uses the above verifying_key gets it directly from the CCF service using the
"get_ledger_verifying_key" transaction.

We note that the very first invocation of "get_ledger_verifying_key" rpc
after the service is started is used to create the key pair, which will then be globally committed.
The system admin who deploys the CCF ledger is expected to invoke the "get_ledger_verifying_key"
rpc after deployment to generate these keys. Further, the admin must ensure that this key pair is globally committed
before making the ledger available for PDO usage. This can checked by issuing the rpc again & ensuring that a verifying key gets returned. See https://microsoft.github.io/CCF/users/issue_commands.html for instructions on
how an rpc can be issued via command line.
20 changes: 3 additions & 17 deletions ccf_transaction_processor/transaction_processor/pdo_tp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ namespace ccfapp

//create signature verifier for this enclave and cache it
const auto public_key_pem = tls::Pem(CBuffer(in.verifying_key));
this->enclave_pubk_verifier[in.verifying_key] = tls::make_public_key(public_key_pem, true);
this->enclave_pubk_verifier[in.verifying_key] = tls::make_public_key(public_key_pem, false);

return make_success(true);
};
Expand Down Expand Up @@ -270,21 +270,7 @@ namespace ccfapp
contract_info.contract_creator_verifying_key_PEM, in.contract_id, enclave_info_temp.provisioning_key_state_secret_pairs, \
enclave_info_temp.encrypted_state_encryption_key)){

// the following code is to aid in debugging the signature verification issue.
string message = in.contract_id;
message += contract_info.contract_creator_verifying_key_PEM;
for (auto prov :enclave_info_temp.provisioning_key_state_secret_pairs ) {
message += prov.pspk;
message += prov.encrypted_secret;
}
vector<uint8_t> contents(message.begin(), message.end());
vector<uint8_t> temp = raw_from_b64(enclave_info_temp.encrypted_state_encryption_key);
contents.insert(contents.end(), temp.begin(), temp.end());

string temp2 = b64_from_raw(contents.data(), contents.size());
return make_error(
jsonrpc::StandardErrorCodes::INVALID_PARAMS, "Invalid enclave signature (doc::sig::key) as follows::"+ \
temp2 + "::"+enclave_info_temp.signature +"::"+enclave_r.value().verifying_key);
return make_error( jsonrpc::StandardErrorCodes::INVALID_PARAMS, "Invalid enclave signature");
}

//all good, add enclave to contract
Expand Down Expand Up @@ -409,7 +395,7 @@ namespace ccfapp
}

// verify contract enclave signature. This signature also ensures (via the notion of channel ids) that
// the contraction invocation was performed by the transaction submitter.
// the contract invocation was performed by the transaction submitter.
if (!verify_enclave_signature_update_contract_state(in.contract_enclave_signature, this->enclave_pubk_verifier[enclave_r.value().verifying_key], \
in.nonce, contract_info.contract_creator_verifying_key_PEM, contract_info.contract_code_hash, \
state_update_info)) {
Expand Down
5 changes: 2 additions & 3 deletions ccf_transaction_processor/transaction_processor/pdo_tp.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,11 @@ namespace ccfapp
bool verify_pdo_transaction_signature_register_enclave(const vector<uint8_t>& signature, const string & verifying_key,
const EnclaveInfo & enclave_info);

bool verify_sig(const vector<uint8_t>& signature, const string & verifying_key, const vector<uint8_t> & contents);
bool verify_sig(vector<uint8_t> signature, const string & verifying_key, const vector<uint8_t> & contents);

bool verify_sig_static(const vector<uint8_t>& signature, const tls::PublicKeyPtr & pubk_verifier, \
bool verify_sig_static(vector<uint8_t> signature, const tls::PublicKeyPtr & pubk_verifier, \
const vector<uint8_t>& contents);


bool verify_pdo_transaction_signature_register_contract(const vector<uint8_t>& signature, const string & verifying_key, \
const vector<uint8_t>& contract_code_hash, const string & nonce, const vector<string> & provisioning_service_ids);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ namespace ccfapp
{


bool TPHandler::verify_sig_static(const vector<uint8_t>& signature, const tls::PublicKeyPtr & pubk_verifier, \
bool TPHandler::verify_sig_static(vector<uint8_t> signature, const tls::PublicKeyPtr & pubk_verifier, \
const vector<uint8_t>& contents) {

// verify & return true or false
return pubk_verifier->verify(contents, signature);

}

bool TPHandler::verify_sig(const vector<uint8_t>& signature, const string & verifying_key, \
bool TPHandler::verify_sig(vector<uint8_t> signature, const string & verifying_key, \
const vector<uint8_t>& contents) {

// format the verifying key as needed by CCF to create the verifier
Expand All @@ -42,7 +42,6 @@ namespace ccfapp

}


bool TPHandler::verify_pdo_transaction_signature_register_enclave(const vector<uint8_t>& signature, const string & verifying_key,
const EnclaveInfo & enclave_info){

Expand Down Expand Up @@ -94,10 +93,7 @@ namespace ccfapp
const string & contract_creator_key, const string & contract_id, const vector<ProvisioningKeysToSecretMap> & prov_key_maps, \
const string & encrypted_state_encryption_key){

return true;

// the following signature verification code does not work. See git issues for status
/*string message = contract_id;
string message = contract_id;
message += contract_creator_key;
for (auto prov :prov_key_maps ) {
message += prov.pspk;
Expand All @@ -108,7 +104,20 @@ namespace ccfapp
vector<uint8_t> temp = raw_from_b64(encrypted_state_encryption_key);
contents.insert(contents.end(), temp.begin(), temp.end());

return verify_sig_static(raw_from_b64(signature), pubk_verifier, contents);*/
auto signature_byte_array = raw_from_b64(signature);

//remove any trailing zeros (null characters) in the signature array
//this seems to be necessary for verifying this sign
while(true){
if (signature_byte_array.back() == 0){
signature_byte_array.pop_back();
}
else{
break;
}
}

return verify_sig_static(signature_byte_array, pubk_verifier, contents);
}


Expand Down
18 changes: 0 additions & 18 deletions python/pdo/contract/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,6 @@ def add_enclave_to_contract(
signature,
**extra_params):


enclave_secret_data_array = []
enclave_secret_data = dict()
enclave_secret_data['contract_id'] = contract_id
Expand All @@ -245,23 +244,6 @@ def add_enclave_to_contract(
enclave_secret_data['provisioning_key_state_secret_pairs'] = secret_list
enclave_secret_data_array.append(enclave_secret_data)

#verify enclave signature if enclave_keys is passed as optional input
#code is for debugging the issue where verification does not work at ccf ledger
#see git issues for status.
enclave_keys = extra_params.get('enclave_keys', None)
if enclave_keys is not None:
document = contract_id
document += creator_keys.verifying_key
for secret in secrets:
document += secret['pspk'] + secret['encrypted_secret']
document_ba = crypto.string_to_byte_array(document)
document_ba += crypto.base64_to_byte_array(encrypted_state_encryption_key)
if enclave_keys.verify(document_ba, signature, encoding = 'b64') == 1:
logger.info("Add enclave to contract sign verified. (doc::sig::key) as follows")
logger.info(crypto.byte_array_to_base64(document_ba)+"::"+signature+"::"+enclave_id)
else:
logger.error("Failed to verify add enclave to contract sign")

ss = create_submitter(ledger_config, pdo_signer = creator_keys)
txnsignature = ss.add_enclave_to_contract(
contract_id,
Expand Down

0 comments on commit 4cac5c5

Please sign in to comment.