From ce11795cf3e1816597f296e91e0753963494ca32 Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Thu, 19 Dec 2024 15:21:36 +0000 Subject: [PATCH] Remove unused code (#255) --- app/src/main.cpp | 1 - app/src/receipt.h | 237 ------------------------------------ app/src/service_endpoints.h | 2 +- app/src/verifier.h | 137 --------------------- 4 files changed, 1 insertion(+), 376 deletions(-) delete mode 100644 app/src/receipt.h diff --git a/app/src/main.cpp b/app/src/main.cpp index 5ae981fa..a2a56121 100644 --- a/app/src/main.cpp +++ b/app/src/main.cpp @@ -13,7 +13,6 @@ #include "kv_types.h" #include "operations_endpoints.h" #include "policy_engine.h" -#include "receipt.h" #include "service_endpoints.h" #include "tracing.h" #include "util.h" diff --git a/app/src/receipt.h b/app/src/receipt.h deleted file mode 100644 index 45e5258b..00000000 --- a/app/src/receipt.h +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#include "cbor.h" -#include "cose.h" - -#include -#include -#include -#include - -namespace scitt -{ - // Receipt header parameter to specify the type of tree. For now CCF is the - // only defined algorithm. - static constexpr const char* COSE_HEADER_PARAM_TREE_ALGORITHM = "tree_alg"; - static constexpr std::string_view TREE_ALGORITHM_CCF = "CCF"; - - static constexpr const char* COSE_HEADER_PARAM_REGISTRATION_TIME = - "registration_time"; - - static constexpr const char* COSE_HEADER_PARAM_MEASUREMENT = - "enclave_measurement"; - // TODO: At some point, this will probably be replaced by an iss + kid - static constexpr const char* COSE_HEADER_PARAM_SERVICE_ID = "service_id"; - - struct ReceiptProcessingError : public std::runtime_error - { - ReceiptProcessingError(const std::string& msg) : std::runtime_error(msg) {} - }; - - /** - * Create the protected header for the countersignature - * receipt. - */ - static std::vector create_countersign_protected_header( - ::timespec registration_time, - std::optional issuer, - std::optional> kid, - std::string_view service_id, - std::string_view measurement) - { - cbor::encoder encoder; - - QCBOREncode_OpenMap(encoder); - QCBOREncode_AddTextToMap( - encoder, - COSE_HEADER_PARAM_TREE_ALGORITHM, - cbor::from_string(TREE_ALGORITHM_CCF)); - - if (issuer.has_value()) - { - QCBOREncode_AddTextToMapN( - encoder, cose::COSE_HEADER_PARAM_ISSUER, cbor::from_string(*issuer)); - } - if (kid.has_value()) - { - QCBOREncode_AddBytesToMapN( - encoder, cose::COSE_HEADER_PARAM_KID, cbor::from_bytes(*kid)); - } - - // This is the legacy header parameter, currently specified by - // draft-birkholz-scitt-receipts. Eventually this will be phased out in - // favour of the iss/kid headers above. - QCBOREncode_AddTextToMap( - encoder, COSE_HEADER_PARAM_SERVICE_ID, cbor::from_string(service_id)); - - // Adds measurement to the receipt to be able to determine the source - // code version of the enclave that generated the receipt. - QCBOREncode_AddTextToMap( - encoder, COSE_HEADER_PARAM_MEASUREMENT, cbor::from_string(measurement)); - - QCBOREncode_AddUInt64ToMap( - encoder, COSE_HEADER_PARAM_REGISTRATION_TIME, registration_time.tv_sec); - QCBOREncode_CloseMap(encoder); - - return encoder.finish(); - } - - /** - * Get the curve size, in bytes, associated with the public key of the given - * DER-encoded certificate. - * - * If the curve size is not a whole number of bytes, it will be rounded up to - * the nearest value. For example, given a certificate's key using the P521 - * curve, this function returns 66. - */ - static size_t get_certificate_ecdsa_curve_size(std::span der) - { - ccf::crypto::OpenSSL::Unique_X509 cert( - ccf::crypto::OpenSSL::Unique_BIO(der.data(), der.size()), false, true); - ccf::crypto::OpenSSL::Unique_PKEY pk(X509_get_pubkey(cert), EVP_PKEY_free); - - size_t bits = EVP_PKEY_bits(pk); - return (bits + 7) / 8; - } - - /** - * Convert an ECDSA signature from ASN1/DER encoding to IEEE P1363 (ie. r and - * s concatenated). - * - * The format is what CCF returns in its receipts, whereas the latter is - * preferred in the COSE/JOSE ecosystem. - * - * The curve size must be specified, in bytes, as the signature size is - * dependent of it. The encoded signature is written to the given output - * buffer. The written size is returned. - */ - static size_t convert_ecdsa_signature( - std::span signature, size_t curve_size, UsefulBuf out) - { - if (out.len < 2 * curve_size) - { - throw ReceiptProcessingError("Not enough space to encode signature"); - } - - const uint8_t* p = signature.data(); - ccf::crypto::OpenSSL::Unique_ECDSA_SIG sig( - d2i_ECDSA_SIG(NULL, &p, signature.size())); - - const BIGNUM* r = ECDSA_SIG_get0_r(sig); - const BIGNUM* s = ECDSA_SIG_get0_s(sig); - - uint8_t* dst = static_cast(out.ptr); - if (BN_bn2binpad(r, dst, curve_size) < 0) - { - throw std::logic_error("ecdsa signature is larger than curve size"); - } - if (BN_bn2binpad(s, dst + curve_size, curve_size) < 0) - { - throw std::logic_error("ecdsa signature is larger than curve size"); - } - return 2 * curve_size; - } - - /** - * Serialize a CCF receipt into a CBOR encoder. - * - * The receipt has the following format: - * ``` - * ReceiptContents = [ - * signature: bstr - * node_certificate: bstr - * inclusion_proof: [+ ProofElement] - * leaf_info: [ - * internal_hash: bstr - * internal_data: bstr - * ] - * ] - * ProofElement = [ - * left: bool - * hash: bstr - * ] - * ``` - */ - static void encode_receipt_contents( - QCBOREncodeContext* ctx, const ccf::ReceiptPtr& receipt) - { - if (receipt->is_signature_transaction()) - { - throw ReceiptProcessingError("Signature transactions are not supported"); - } - - auto proof_receipt = std::dynamic_pointer_cast(receipt); - - auto& write_set_digest = proof_receipt->leaf_components.write_set_digest; - auto& commit_evidence = proof_receipt->leaf_components.commit_evidence; - auto node_cert_der = ccf::crypto::cert_pem_to_der(proof_receipt->cert); - - // Contents array: [signature, node_certificate, inclusion_proof, leaf_info] - QCBOREncode_OpenArray(ctx); - - UsefulBuf signature; - QCBOREncode_OpenBytes(ctx, &signature); - size_t curve_size = get_certificate_ecdsa_curve_size(node_cert_der); - size_t signature_size = - convert_ecdsa_signature(proof_receipt->signature, curve_size, signature); - QCBOREncode_CloseBytes(ctx, signature_size); - - QCBOREncode_AddBytes(ctx, cbor::from_bytes(node_cert_der)); - - // Inclusion proof array: [left, hash]* - QCBOREncode_OpenArray(ctx); - - for (auto& step : proof_receipt->proof) - { - auto left = step.direction == ccf::ProofReceipt::ProofStep::Left; - QCBOREncode_OpenArray(ctx); - QCBOREncode_AddBool(ctx, left); - QCBOREncode_AddBytes(ctx, cbor::from_sha256_hash(step.hash)); - QCBOREncode_CloseArray(ctx); - } - - // End of inclusion proof array - QCBOREncode_CloseArray(ctx); - - // Leaf info array: [write_set_digest, commit_evidence] - QCBOREncode_OpenArray(ctx); - QCBOREncode_AddBytes(ctx, cbor::from_sha256_hash(write_set_digest)); - QCBOREncode_AddBytes(ctx, cbor::from_string(commit_evidence)); - QCBOREncode_CloseArray(ctx); - - // End of contents array - QCBOREncode_CloseArray(ctx); - } - - /** - * Serialize an EntryInfo and its associated CCF receipt into a - * Receipt structure. - * - * ``` - * Receipt = [ - * protected: empty_or_serialized_map, - * contents: ReceiptContents - * ] - * ``` - */ - static std::vector serialize_receipt( - const EntryInfo& entry_info, const ccf::ReceiptPtr& ccf_receipt_ptr) - { - auto sign_protected = entry_info.sign_protected; - - cbor::encoder encoder; - - // [ protected, contents ] - QCBOREncode_OpenArray(encoder); - QCBOREncode_AddBytes(encoder, cbor::from_bytes(sign_protected)); - - encode_receipt_contents(encoder, ccf_receipt_ptr); - - QCBOREncode_CloseArray(encoder); - - return encoder.finish(); - } -} // namespace scitt diff --git a/app/src/service_endpoints.h b/app/src/service_endpoints.h index dd99c603..d3d54b43 100644 --- a/app/src/service_endpoints.h +++ b/app/src/service_endpoints.h @@ -24,7 +24,7 @@ namespace scitt GetServiceParameters::Out out; out.service_id = service_id; - out.tree_algorithm = TREE_ALGORITHM_CCF; + out.tree_algorithm = "CCF"; out.signature_algorithm = JOSE_ALGORITHM_ES256; out.service_certificate = ccf::crypto::b64_from_raw(certificate_der); return out; diff --git a/app/src/verifier.h b/app/src/verifier.h index 6e78814b..1c56df8b 100644 --- a/app/src/verifier.h +++ b/app/src/verifier.h @@ -559,143 +559,6 @@ namespace scitt::verifier return ccf::crypto::split_x509_cert_bundle(*ca_certs); } - /** - * Get a PublicKey out of a JSON Web Key. - */ - static PublicKey get_jwk_public_key(const scitt::did::Jwk& jwk) - { - if (jwk.kty != "EC" && jwk.kty != "RSA" && jwk.kty != "OKP") - { - throw VerificationError("JWK has an unsupported key type"); - } - - // TODO: check the `use` and `key_ops` fields of the JWK - // to ensure the key usage is correct. - std::optional cose_alg; - if (jwk.alg.has_value()) - { - try - { - cose_alg = get_cose_alg_from_jose_alg(jwk.alg.value()); - } - catch (const InvalidSignatureAlgorithm& e) - { - throw VerificationError(e.what()); - } - } - - if (jwk.kty == "RSA" && jwk.n.has_value() && jwk.e.has_value()) - { - auto n = ccf::crypto::raw_from_b64url(jwk.n.value()); - auto e = ccf::crypto::raw_from_b64url(jwk.e.value()); - ccf::crypto::OpenSSL::Unique_BIGNUM n_bn; - ccf::crypto::OpenSSL::Unique_BIGNUM e_bn; - if (BN_bin2bn(n.data(), n.size(), n_bn) == nullptr) - { - throw VerificationError("JWK n could not be parsed"); - } - if (BN_bin2bn(e.data(), e.size(), e_bn) == nullptr) - { - throw VerificationError("JWK e could not be parsed"); - } - -#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 - std::pair, std::vector> r( - BN_num_bytes(n_bn), BN_num_bytes(e_bn)); - - ccf::crypto::OpenSSL::CHECKPOSITIVE( - BN_bn2nativepad(n_bn, r.first.data(), r.first.size())); - ccf::crypto::OpenSSL::CHECKPOSITIVE( - BN_bn2nativepad(e_bn, r.second.data(), r.second.size())); - - return PublicKey(r.first, r.second, cose_alg); -#else - ccf::crypto::OpenSSL::Unique_RSA rsa; - if (!RSA_set0_key(rsa, n_bn, e_bn, nullptr)) - { - throw std::runtime_error("RSA key could not be set"); - } - // Ignore previous pointers, as they're now managed by RSA*. - (void)n_bn.release(); - (void)e_bn.release(); - - return PublicKey(rsa, cose_alg); -#endif - } - - if (jwk.kty == "OKP" && jwk.crv == "Ed25519" && jwk.x.has_value()) - { - auto x = ccf::crypto::raw_from_b64url(jwk.x.value()); - return PublicKey(EVP_PKEY_ED25519, x, cose_alg); - } - - if ( - jwk.kty == "EC" && jwk.crv.has_value() && jwk.x.has_value() && - jwk.y.has_value()) - { - auto crv = jwk.crv.value(); - auto x = ccf::crypto::raw_from_b64url(jwk.x.value()); - auto y = ccf::crypto::raw_from_b64url(jwk.y.value()); - ccf::crypto::OpenSSL::Unique_BIGNUM x_bn; - ccf::crypto::OpenSSL::Unique_BIGNUM y_bn; - if (BN_bin2bn(x.data(), x.size(), x_bn) == nullptr) - { - throw VerificationError("JWK x could not be parsed"); - } - if (BN_bin2bn(y.data(), y.size(), y_bn) == nullptr) - { - throw VerificationError("JWK y could not be parsed"); - } - int nid; - if (crv == "P-256") - { - nid = NID_X9_62_prime256v1; - } - else if (crv == "P-384") - { - nid = NID_secp384r1; - } - else if (crv == "P-521") - { - nid = NID_secp521r1; - } - else - { - throw VerificationError("JWK EC Key has no valid supported curve"); - } - -#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 - ccf::crypto::OpenSSL::Unique_BN_CTX bn_ctx; - ccf::crypto::OpenSSL::Unique_EC_GROUP group(nid); - ccf::crypto::OpenSSL::Unique_EC_POINT p(group); - ccf::crypto::OpenSSL::CHECK1( - EC_POINT_set_affine_coordinates(group, p, x_bn, y_bn, bn_ctx)); - size_t buf_size = EC_POINT_point2oct( - group, p, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, bn_ctx); - std::vector buf(buf_size); - ccf::crypto::OpenSSL::CHECKPOSITIVE(EC_POINT_point2oct( - group, - p, - POINT_CONVERSION_UNCOMPRESSED, - buf.data(), - buf.size(), - bn_ctx)); - - return PublicKey(buf, nid, cose_alg); -#else - auto ec_key = ccf::crypto::OpenSSL::Unique_EC_KEY(nid); - if (!EC_KEY_set_public_key_affine_coordinates(ec_key, x_bn, y_bn)) - { - throw std::runtime_error("EC key could not be set"); - } - - return PublicKey(ec_key, cose_alg); -#endif - } - - throw VerificationError("JWK has no valid supported key"); - } - /** * Assuming a verified chain and leaf certificate, enforce additional * policies.