Skip to content

Commit

Permalink
Switch to using COSE_Sign for the QueryRequest
Browse files Browse the repository at this point in the history
Fixes #104

Signed-off-by: Dave Thaler <dthaler@microsoft.com>
  • Loading branch information
dthaler committed Jul 23, 2023
1 parent 1ea0f50 commit 0b94f70
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 28 deletions.
4 changes: 2 additions & 2 deletions TeepUnitTest/ProtocolTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ static void TestConfigureKeys(teep_signature_kind_t signatureKind)
char agent_public_key_filename[256];
REQUIRE(StartAgentBroker(TEEP_AGENT_DATA_DIRECTORY, TRUE, signatureKind, agent_public_key_filename) == 0);

// Copy Agent keys to TAM
// Copy Agent keys to TAM.
CopyFile(agent_public_key_filename, TAM_DATA_DIRECTORY "/trusted");

// Copy TAM keys to Agent
// Copy TAM keys to Agent.
char tam_public_key_filename[256];
TamGetPublicKey(signatureKind, tam_public_key_filename);
CopyFile(tam_public_key_filename, TEEP_AGENT_DATA_DIRECTORY "/trusted");
Expand Down
7 changes: 4 additions & 3 deletions protocol/TeepAgentLib/AgentKeys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ void TeepAgentGetSigningKeyPair(_Out_ struct t_cose_key* keyPair, _Out_ teep_sig
*kind = g_teep_agent_signing_key_kind;
}

vector<struct t_cose_key> g_tam_key_pairs;
map<teep_signature_kind_t,struct t_cose_key> g_tam_key_pairs;

/* TODO: This is just a placeholder for a real implementation.
* Currently we provide untrusted keys into the TAM.
Expand Down Expand Up @@ -64,14 +64,15 @@ teep_error_code_t TeepAgentConfigureTamKeys(_In_z_ const char* directory_name)
if (result != TEEP_ERR_SUCCESS) {
break;
}
g_tam_key_pairs.emplace_back(key_pair);
teep_signature_kind_t kind = (strstr(filename, "es256") != nullptr) ? TEEP_SIGNATURE_ES256 : TEEP_SIGNATURE_EDDSA;
g_tam_key_pairs[kind] = key_pair;
}
closedir(dir);
return result;
}

/* Get the TEEP Agents' public keys to verify an incoming message against. */
vector<struct t_cose_key> TeepAgentGetTamKeys()
map<teep_signature_kind_t, struct t_cose_key> TeepAgentGetTamKeys()
{
return g_tam_key_pairs;
}
Expand Down
4 changes: 2 additions & 2 deletions protocol/TeepAgentLib/AgentKeys.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (c) TEEP contributors
// SPDX-License-Identifier: MIT
#pragma once
#include <vector>
#include <map>

teep_error_code_t TeepAgentConfigureTamKeys(_In_z_ const char* directory_name);

std::vector<struct t_cose_key> TeepAgentGetTamKeys();
std::map<teep_signature_kind_t, struct t_cose_key> TeepAgentGetTamKeys();

void TeepAgentGetSigningKeyPair(_Out_ struct t_cose_key* keyPair, _Out_ teep_signature_kind_t* kind);
4 changes: 2 additions & 2 deletions protocol/TeepAgentLib/TeepAgent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -754,8 +754,8 @@ static teep_error_code_t TeepAgentVerifyMessageSignature(
UsefulBufC signed_cose;
signed_cose.ptr = message;
signed_cose.len = messageLength;
for (auto key_pair : TeepAgentGetTamKeys()) {
teep_error_code_t teeperr = teep_verify_cbor_message(&key_pair, &signed_cose, pencoded);
for (auto [kind, key_pair] : TeepAgentGetTamKeys()) {
teep_error_code_t teeperr = teep_verify_cbor_message(kind, &key_pair, &signed_cose, pencoded);
if (teeperr == TEEP_ERR_SUCCESS) {
// TODO(#114): save key_pair in session
return TEEP_ERR_SUCCESS;
Expand Down
1 change: 1 addition & 0 deletions protocol/TeepCommonLib/TeepCommonLib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
<WarningLevel>Level3</WarningLevel>
<AdditionalIncludeDirectories>$(ProgramW6432)\openssl\include;$(SolutionDir)external\openssl\include;$(SolutionDir)external\openssl\_build\include;$(SolutionDir)external/t_cose/inc;$(SolutionDir)external/qcbor/inc</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
Expand Down
208 changes: 198 additions & 10 deletions protocol/TeepCommonLib/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,34 @@ teep_error_code_t TeepInitialize(_In_z_ const char* signing_private_key_pair_fil
return teep_load_signing_key_pair(&key_pair, signing_private_key_pair_filename, signing_public_key_filename, signature_kind);
}

teep_error_code_t
teep_compute_key_id(teep_signature_kind_t signature_kind, _In_ const struct t_cose_key* key_pair, _Out_ UsefulBuf* key_id)
{
#if 1
// TODO: this is not correct or secure, switch to the other code path once we
// can get the public key from a t_cose_key key pair.
*(teep_signature_kind_t*)key_id->ptr = signature_kind;
key_id->len = sizeof(signature_kind);
return TEEP_ERR_SUCCESS;
#else
// Get the public key.
if (signature_kind == TEEP_SIGNATURE_ES256) {
}
else {
}
// Compute SHA-256 hash.
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, public_key.key.buffer.ptr, public_key.key.buffer.len);
SHA256_Final(hash, &sha256);
*key_id = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(hash);
return TEEP_ERR_PERMANENT_ERROR;
#endif
}

teep_error_code_t
teep_sign1_cbor_message(
_In_ const struct t_cose_key* key_pair,
Expand All @@ -234,7 +262,12 @@ teep_sign1_cbor_message(
// Initialize for signing.
struct t_cose_sign1_sign_ctx sign_ctx;
t_cose_sign1_sign_init(&sign_ctx, 0, get_cose_algorithm(signature_kind));
t_cose_sign1_set_signing_key(&sign_ctx, *key_pair, NULL_Q_USEFUL_BUF_C);
UsefulBuf_MAKE_STACK_UB(key_id, SHA256_DIGEST_LENGTH);
teep_error_code_t result = teep_compute_key_id(signature_kind, key_pair, &key_id);
if (result != TEEP_ERR_SUCCESS) {
return result;
}
t_cose_sign1_set_signing_key(&sign_ctx, *key_pair, UsefulBuf_Const(key_id));

// Compute the size of the output and auxiliary buffers.
struct q_useful_buf null_buff { NULL, SIZE_MAX };
Expand Down Expand Up @@ -292,19 +325,90 @@ teep_sign_cbor_message(
teep_signature_kind_t signature_kind,
_Out_ UsefulBufC* signed_message)
{
// TODO(#104): t_cose 2.0 should support Sign.
// Switch to it once it's ready and supports EdDSA.
// In the meantime, we just use Sign1 ES256.
// Initialize for signing.
struct t_cose_sign_sign_ctx sign_ctx;
t_cose_sign_sign_init(&sign_ctx, T_COSE_OPT_MESSAGE_TYPE_SIGN);

struct t_cose_signature_sign_eddsa eddsa_signer;
struct t_cose_signature_sign_main es256_signer;
UsefulBuf_MAKE_STACK_UB(eddsa_key_id, SHA256_DIGEST_LENGTH);
UsefulBuf_MAKE_STACK_UB(es256_key_id, SHA256_DIGEST_LENGTH);
for (const auto& [kind, key_pair] : key_pairs) {
int32_t algorithm_id = (kind == TEEP_SIGNATURE_ES256) ? T_COSE_ALGORITHM_ES256 : T_COSE_ALGORITHM_EDDSA;
if (kind == TEEP_SIGNATURE_ES256) {
t_cose_signature_sign_main_init(&es256_signer, algorithm_id);
teep_error_code_t result = teep_compute_key_id(kind, &key_pair, &es256_key_id);
if (result != TEEP_ERR_SUCCESS) {
return result;
}
t_cose_signature_sign_main_set_signing_key(&es256_signer, key_pair, UsefulBuf_Const(es256_key_id));
t_cose_sign_add_signer(&sign_ctx, t_cose_signature_sign_from_main(&es256_signer));
} else {
t_cose_signature_sign_eddsa_init(&eddsa_signer);
teep_error_code_t result = teep_compute_key_id(kind, &key_pair, &eddsa_key_id);
if (result != TEEP_ERR_SUCCESS) {
return result;
}
t_cose_signature_sign_eddsa_set_signing_key(&eddsa_signer, key_pair, UsefulBuf_Const(eddsa_key_id));
t_cose_sign_add_signer(&sign_ctx, t_cose_signature_sign_from_eddsa(&eddsa_signer));

// Compute the size of the output and auxiliary buffers.
struct q_useful_buf null_buff { NULL, SIZE_MAX };
struct q_useful_buf_c signed_cose;
enum t_cose_err_t return_value = t_cose_sign_sign(&sign_ctx,
NULL_Q_USEFUL_BUF_C, // No externally supplied AAD.
*unsigned_message,
null_buff,
&signed_cose);

// Allocate buffers of the right size.
if (signed_cose.len > signed_message_buffer.len) {
return TEEP_ERR_TEMPORARY_ERROR;
}
struct q_useful_buf auxiliary_buffer = {};
auxiliary_buffer.len = t_cose_signature_sign_eddsa_auxiliary_buffer_size(&eddsa_signer);
if (auxiliary_buffer.len > 0) {
// TODO: remove workaround for https://github.com/laurencelundblade/t_cose/issues/251
// once it is fixed.
auxiliary_buffer.len += 50;

auxiliary_buffer.ptr = malloc(auxiliary_buffer.len);
if (auxiliary_buffer.ptr == NULL) {
return TEEP_ERR_TEMPORARY_ERROR;
}
}

t_cose_signature_sign_eddsa_set_auxiliary_buffer(&eddsa_signer, auxiliary_buffer);
}
}

return teep_sign1_cbor_message(&key_pairs[TEEP_SIGNATURE_ES256],
unsigned_message,
// Sign.
enum t_cose_err_t return_value = t_cose_sign_sign(&sign_ctx,
NULL_Q_USEFUL_BUF_C, // No externally supplied AAD.
*unsigned_message,
/* Non-const pointer and length of the
* buffer where the completed output is
* written to. The length here is that
* of the whole buffer.
*/
signed_message_buffer,
TEEP_SIGNATURE_ES256,
/* Const pointer and actual length of
* the completed, signed and encoded
* COSE_Sign1 message. This points
* into the output buffer and has the
* lifetime of the output buffer.
*/
signed_message);
if (return_value != T_COSE_SUCCESS) {
TeepLogMessage("COSE Sign failed with error %d\n", return_value);
return TEEP_ERR_PERMANENT_ERROR;
}

return TEEP_ERR_SUCCESS;
}

teep_error_code_t
teep_verify_cbor_message(
teep_verify_cbor_message_sign1(
_In_ const struct t_cose_key* key_pair,
_In_ const UsefulBufC* signed_cose,
_Out_ UsefulBufC* encoded)
Expand All @@ -313,7 +417,7 @@ teep_verify_cbor_message(

t_cose_sign1_verify_init(&verify_ctx, T_COSE_OPT_DECODE_ONLY);
UsefulBufC payload = {};
int return_value = t_cose_sign1_verify(&verify_ctx, *signed_cose, &payload, nullptr);
t_cose_err_t return_value = t_cose_sign1_verify(&verify_ctx, *signed_cose, &payload, nullptr);
if (return_value != T_COSE_SUCCESS) {
TeepLogMessage("First t_cose_sign1_verify failed with error %d\n", return_value);
return TEEP_ERR_PERMANENT_ERROR;
Expand All @@ -338,7 +442,7 @@ teep_verify_cbor_message(
return_value = t_cose_sign1_verify(&verify_ctx,
*signed_cose, /* COSE to verify */
encoded, /* Payload from signed_cose */
NULL); /* Don't return parameters */
nullptr); /* Don't return parameters */
free(auxiliary_buffer.ptr);
if (return_value != T_COSE_SUCCESS) {
TeepLogMessage("Second t_cose_sign1_verify failed with error %d\n", return_value);
Expand All @@ -348,6 +452,90 @@ teep_verify_cbor_message(
return TEEP_ERR_SUCCESS;
}

teep_error_code_t
teep_verify_cbor_message_sign(
teep_signature_kind_t signature_kind,
_In_ const struct t_cose_key* key_pair,
_In_ const UsefulBufC* signed_cose,
_Out_ UsefulBufC* encoded)
{
struct t_cose_sign_verify_ctx verify_ctx;

UsefulBuf_MAKE_STACK_UB(key_id, SHA256_DIGEST_LENGTH);
teep_error_code_t result = teep_compute_key_id(signature_kind, key_pair, &key_id);
if (result != TEEP_ERR_SUCCESS) {
return result;
}

// Initialize verifiers.
t_cose_sign_verify_init(&verify_ctx, T_COSE_OPT_DECODE_ONLY);
struct t_cose_signature_verify_main es256_verifier;
struct t_cose_signature_verify_eddsa eddsa_verifier;
if (signature_kind == TEEP_SIGNATURE_ES256) {
// ES256 verifier.
t_cose_signature_verify_main_init(&es256_verifier);
t_cose_signature_verify_main_set_key(&es256_verifier, *key_pair, UsefulBuf_Const(key_id));
t_cose_sign_add_verifier(&verify_ctx, t_cose_signature_verify_from_main(&es256_verifier));
} else {
// EdDSA verifier.
t_cose_signature_verify_eddsa_init(&eddsa_verifier, 0);
t_cose_signature_verify_eddsa_set_key(&eddsa_verifier, *key_pair, UsefulBuf_Const(key_id));
t_cose_sign_add_verifier(&verify_ctx, t_cose_signature_verify_from_eddsa(&eddsa_verifier));
}

// Compute the auxiliary buffer size needed.
// TODO: this code path is blocked on https://github.com/laurencelundblade/t_cose/issues/252
// which causes t_cose_sign_verify to fail when it shouldn't.
UsefulBufC payload = {};
t_cose_err_t return_value = t_cose_sign_verify(&verify_ctx, *signed_cose, NULL_Q_USEFUL_BUF_C, &payload, nullptr);
if (return_value != T_COSE_SUCCESS) {
TeepLogMessage("First t_cose_sign1_verify failed with error %d\n", return_value);
return TEEP_ERR_PERMANENT_ERROR;
}

// Allocate an auxiliary buffer of the right size.
struct q_useful_buf auxiliary_buffer = {};
auxiliary_buffer.len = t_cose_signature_verify_eddsa_auxiliary_buffer_size(&eddsa_verifier);
if (auxiliary_buffer.len > 0) {
auxiliary_buffer.ptr = malloc(auxiliary_buffer.len);
if (auxiliary_buffer.ptr == NULL) {
TeepLogMessage("teep_verify_cbor_message could not allocate %d bytes\n", auxiliary_buffer.len);
return TEEP_ERR_TEMPORARY_ERROR;
}
}
t_cose_signature_verify_eddsa_set_auxiliary_buffer(&eddsa_verifier, auxiliary_buffer);

// Do the actual verification.
t_cose_sign_verify_init(&verify_ctx, 0);
return_value = t_cose_sign_verify(&verify_ctx,
*signed_cose, /* COSE to verify */
NULL_Q_USEFUL_BUF_C, /* No AAD */
encoded, /* Payload from signed_cose */
nullptr); /* Don't return parameters */
if (return_value != T_COSE_SUCCESS) {
TeepLogMessage("Second t_cose_sign_verify failed with error %d\n", return_value);
return TEEP_ERR_PERMANENT_ERROR;
}

return TEEP_ERR_SUCCESS;
}

teep_error_code_t
teep_verify_cbor_message(
teep_signature_kind_t signature_kind,
_In_ const struct t_cose_key* key_pair,
_In_ const UsefulBufC* signed_cose,
_Out_ UsefulBufC* encoded)
{
#if 0
teep_error_code_t result = teep_verify_cbor_message_sign1(key_pair, signed_cose, encoded);
if (result == TEEP_ERR_SUCCESS) {
return TEEP_ERR_SUCCESS;
}
#endif
return teep_verify_cbor_message_sign(signature_kind, key_pair, signed_cose, encoded);
}

#ifdef TEEP_USE_CERTIFICATES // Currently unused.
_Ret_writes_bytes_maybenull_(*pCertificateSize)
const unsigned char* GetDerCertificate(
Expand Down
1 change: 1 addition & 0 deletions protocol/TeepCommonLib/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ teep_sign_cbor_message(

teep_error_code_t
teep_verify_cbor_message(
teep_signature_kind_t signature_kind,
_In_ const struct t_cose_key* key_pair,
_In_ const UsefulBufC* signed_cose,
_Out_ UsefulBufC* encoded);
Expand Down
7 changes: 4 additions & 3 deletions protocol/TeepTamLib/TamKeys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ teep_error_code_t TamGetSigningKeyPairs(_Out_ std::map<teep_signature_kind_t, st
return TEEP_ERR_SUCCESS;
}

vector<struct t_cose_key> g_agent_key_pairs;
map<teep_signature_kind_t, struct t_cose_key> g_agent_key_pairs;

/* TODO: This is just a placeholder for a real implementation.
* Currently we provide untrusted keys into the TAM.
Expand Down Expand Up @@ -63,7 +63,8 @@ teep_error_code_t TamConfigureAgentKeys(_In_z_ const char* directory_name)
if (result != TEEP_ERR_SUCCESS) {
break;
}
g_agent_key_pairs.emplace_back(key_pair);
teep_signature_kind_t kind = (strstr(filename, "es256") != nullptr) ? TEEP_SIGNATURE_ES256 : TEEP_SIGNATURE_EDDSA;
g_agent_key_pairs[kind] = key_pair;

TeepLogMessage("TAM loaded TEEP agent key from %s\n", keyfile.c_str());
}
Expand All @@ -72,7 +73,7 @@ teep_error_code_t TamConfigureAgentKeys(_In_z_ const char* directory_name)
}

/* Get the TEEP Agents' public keys to verify an incoming message against. */
vector<struct t_cose_key> TamGetTeepAgentKeys()
map<teep_signature_kind_t, struct t_cose_key> TamGetTeepAgentKeys()
{
return g_agent_key_pairs;
}
Expand Down
3 changes: 1 addition & 2 deletions protocol/TeepTamLib/TamKeys.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
// SPDX-License-Identifier: MIT
#pragma once
#include <map>
#include <vector>

teep_error_code_t TamConfigureAgentKeys(_In_z_ const char* directory_name);

std::vector<struct t_cose_key> TamGetTeepAgentKeys();
std::map<teep_signature_kind_t, struct t_cose_key> TamGetTeepAgentKeys();

teep_error_code_t TamGetSigningKeyPairs(_Out_ std::map<teep_signature_kind_t, struct t_cose_key>& key_pairs);

Expand Down
Loading

0 comments on commit 0b94f70

Please sign in to comment.