[toolchain] Update grpc_ratls toolchain with patching way
Signed-off-by: Qi Zheng <huaiqing.zq@antgroup.com>
This commit is contained in:
parent
a82cfb87f0
commit
cb1ee85605
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,26 @@
|
||||
From 34ac52eb5d694f0ef0cec30c66c8c417cba9789c Mon Sep 17 00:00:00 2001
|
||||
From: Qi Zheng <huaiqing.zq@antgroup.com>
|
||||
Date: Tue, 14 Nov 2023 07:43:41 +0000
|
||||
Subject: [PATCH] Fixes build with glibc 2.34
|
||||
|
||||
---
|
||||
absl/debugging/failure_signal_handler.cc | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/absl/debugging/failure_signal_handler.cc b/absl/debugging/failure_signal_handler.cc
|
||||
index a9ed6ef9..3ddebd74 100644
|
||||
--- a/absl/debugging/failure_signal_handler.cc
|
||||
+++ b/absl/debugging/failure_signal_handler.cc
|
||||
@@ -136,7 +136,8 @@ static bool SetupAlternateStackOnce() {
|
||||
#else
|
||||
const size_t page_mask = sysconf(_SC_PAGESIZE) - 1;
|
||||
#endif
|
||||
- size_t stack_size = (std::max(SIGSTKSZ, 65536) + page_mask) & ~page_mask;
|
||||
+ size_t stack_size =
|
||||
+ (std::max<size_t>(SIGSTKSZ, 65536) + page_mask) & ~page_mask;
|
||||
#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
|
||||
defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
|
||||
// Account for sanitizer instrumentation requiring additional stack space.
|
||||
--
|
||||
2.34.1
|
||||
|
@ -36,9 +36,6 @@ function build_grpc_ratls() {
|
||||
# Copy occlum dcap lib first to ease linking
|
||||
cp ${DCAP_LIB_PATH}/libocclum_dcap.so* ${INSTALL_PREFIX}/lib
|
||||
|
||||
# Copy ratls added/updated files to grpc source
|
||||
cp -rf grpc/${GRPC_VERSION}/* ${GRPC_PATH}/
|
||||
|
||||
ABSEIL_PATH=${GRPC_PATH}/third_party/abseil-cpp
|
||||
|
||||
# build and install abseil library
|
||||
|
@ -5,10 +5,10 @@ source ./env.sh
|
||||
|
||||
# Download and update cmake
|
||||
function dl_and_build_cmake() {
|
||||
# Ubuntu 20.04 has newer enough cmake version
|
||||
# Ubuntu 20.04/22.04 has newer enough cmake version
|
||||
if [ -f "/etc/os-release" ]; then
|
||||
local os_name=$(cat /etc/os-release)
|
||||
if [[ $os_name =~ "Ubuntu" && $os_name =~ "20.04" ]]; then
|
||||
if [[ $os_name =~ "Ubuntu" ]]; then
|
||||
return
|
||||
fi
|
||||
fi
|
||||
@ -27,9 +27,16 @@ function dl_grpc() {
|
||||
# GRPC source code
|
||||
rm -rf ${GRPC_PATH}
|
||||
git clone https://github.com/grpc/grpc -b ${GRPC_VERSION} ${GRPC_PATH}
|
||||
pushd ${GRPC_PATH} \
|
||||
&& git checkout ${GRPC_VERSION} \
|
||||
&& git submodule update --init
|
||||
pushd ${GRPC_PATH}
|
||||
git submodule update --init
|
||||
# Apply occlum patch
|
||||
git apply ../0001-Add-Occlum-SGX-tls-function.patch
|
||||
popd
|
||||
|
||||
ABSEIL_PATH=${GRPC_PATH}/third_party/abseil-cpp
|
||||
pushd $ABSEIL_PATH
|
||||
# Apply patch
|
||||
git apply ../../../0001-Fixes-build-with-glibc-2.34.patch
|
||||
popd
|
||||
}
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
grpc-*
|
File diff suppressed because it is too large
Load Diff
@ -1,64 +0,0 @@
|
||||
# Copyright (c) 2022 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
project(RA-TLS C CXX)
|
||||
|
||||
include(../cmake/common.cmake)
|
||||
|
||||
# Proto file
|
||||
get_filename_component(hw_proto "../../protos/ratls.proto" ABSOLUTE)
|
||||
get_filename_component(hw_proto_path "${hw_proto}" PATH)
|
||||
|
||||
# Generated sources
|
||||
set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/ratls.pb.cc")
|
||||
set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/ratls.pb.h")
|
||||
set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/ratls.grpc.pb.cc")
|
||||
set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/ratls.grpc.pb.h")
|
||||
add_custom_command(
|
||||
OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}"
|
||||
COMMAND ${_PROTOBUF_PROTOC}
|
||||
ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
--cpp_out "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
-I "${hw_proto_path}"
|
||||
--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
|
||||
"${hw_proto}"
|
||||
DEPENDS "${hw_proto}")
|
||||
|
||||
# Include generated *.pb.h files
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
# hw_grpc_proto
|
||||
add_library(hw_grpc_proto SHARED
|
||||
${hw_grpc_srcs}
|
||||
${hw_grpc_hdrs}
|
||||
${hw_proto_srcs}
|
||||
${hw_proto_hdrs})
|
||||
target_link_libraries(hw_grpc_proto
|
||||
${_REFLECTION}
|
||||
${_GRPC_GRPCPP}
|
||||
${_PROTOBUF_LIBPROTOBUF})
|
||||
|
||||
foreach(_target grpc_ratls_client grpc_ratls_server)
|
||||
add_library(${_target} SHARED "${_target}.cc")
|
||||
target_link_libraries(${_target}
|
||||
hw_grpc_proto)
|
||||
endforeach()
|
||||
|
||||
foreach(_target client server)
|
||||
add_executable(${_target} "${_target}.cc")
|
||||
target_link_libraries(${_target}
|
||||
grpc_ratls_${_target})
|
||||
endforeach()
|
@ -1,15 +0,0 @@
|
||||
# gRPC
|
||||
|
||||
This directory contains the Makefile and the template manifest for the most
|
||||
recent version of gRPC (as of this writing, version 3.18.0). This was tested
|
||||
on a machine with SGX v1 and Ubuntu 18.04.
|
||||
|
||||
The Makefile and the template manifest contain extensive comments and are made
|
||||
self-explanatory. Please review them to gain understanding of Gramine-SGX
|
||||
and requirements for applications running under Gramine-SGX.
|
||||
|
||||
# Quick Start
|
||||
|
||||
```
|
||||
./build.sh
|
||||
```
|
@ -1,27 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2022 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set -ex
|
||||
|
||||
export BUILD_TYPE=Release
|
||||
export EXP_PATH=`dirname $0`
|
||||
|
||||
# build c++ example
|
||||
cd ${EXP_PATH}
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake -D CMAKE_PREFIX_PATH=${INSTALL_PREFIX} -D CMAKE_BUILD_TYPE=${BUILD_TYPE} ..
|
||||
make -j `nproc`
|
||||
cd -
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../grpc_ratls_client.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// Parse arguments
|
||||
if (argc < 4) {
|
||||
printf("[ERROR] Three arguments must be provided\n\n");
|
||||
printf("Usage: client <grpc-server addr> <request_name> <secret_file_to_be_saved>\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
grpc_ratls_get_secret(
|
||||
argv[1],
|
||||
"dynamic_config.json",
|
||||
argv[2],
|
||||
argv[3]
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,212 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include <grpcpp/security/sgx/sgx_ra_tls.h>
|
||||
|
||||
#ifdef BAZEL_BUILD
|
||||
#include "examples/protos/ratls.grpc.pb.h"
|
||||
#else
|
||||
#include "ratls.grpc.pb.h"
|
||||
#endif
|
||||
|
||||
#include "../grpc_ratls_client.h"
|
||||
|
||||
using ratls::GrSecret;
|
||||
using ratls::SecretRequest;
|
||||
using ratls::SecretReply;
|
||||
|
||||
typedef enum {
|
||||
GRPC_RATLS_SUCCESS = 0, /// Success
|
||||
GRPC_RATLS_ERR = -1, /// General error
|
||||
GRPC_RATLS_INVALID_PARAM = -2, /// Invalid parameter
|
||||
GRPC_RATLS_BUF_ERR = -3, /// Invalid buffer or buffer allocation failure
|
||||
GRPC_RATLS_NO_SECRET = -4, /// No valid secret
|
||||
GRPC_RATLS_BUF_TOO_SMALL = -5 /// Buffer is too small
|
||||
} grpc_ratls_result_t;
|
||||
|
||||
// Client
|
||||
class GrSecretClient {
|
||||
public:
|
||||
GrSecretClient(std::shared_ptr<grpc::Channel> channel) : stub_(GrSecret::NewStub(channel)) {}
|
||||
|
||||
std::string GetSecret(const std::string& name) {
|
||||
SecretRequest request;
|
||||
request.set_name(name);
|
||||
|
||||
SecretReply reply;
|
||||
|
||||
grpc::ClientContext context;
|
||||
|
||||
grpc::Status status = stub_->GetSecret(&context, request, &reply);
|
||||
|
||||
if (status.ok()) {
|
||||
return reply.secret();
|
||||
} else {
|
||||
std::cout << status.error_code() << ": " << status.error_message() << std::endl;
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<GrSecret::Stub> stub_;
|
||||
};
|
||||
|
||||
static const unsigned char base64_table[65] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static size_t base64_decode_len(const char *b64input) {
|
||||
size_t len = strlen(b64input), padding = 0;
|
||||
|
||||
if (b64input[len - 1] == '=' && b64input[len - 2] == '=') { //last two chars are =
|
||||
padding = 2;
|
||||
} else if (b64input[len - 1] == '=') { //last char is =
|
||||
padding = 1;
|
||||
}
|
||||
|
||||
return (len * 3) / 4 - padding;
|
||||
}
|
||||
|
||||
/**
|
||||
* base64_decode - Base64 decode
|
||||
*/
|
||||
void base64_decode(const char *b64input, unsigned char *dest, size_t dest_len) {
|
||||
unsigned char dtable[256], *pos, block[4], tmp;
|
||||
size_t i, count, olen;
|
||||
size_t len = strlen(b64input);
|
||||
|
||||
memset(dtable, 0x80, 256);
|
||||
for (i = 0; i < sizeof(base64_table) - 1; i++) {
|
||||
dtable[base64_table[i]] = (unsigned char) i;
|
||||
}
|
||||
dtable['='] = 0;
|
||||
|
||||
olen = base64_decode_len(b64input);
|
||||
if (olen > dest_len) {
|
||||
printf("Base64 encoded length %ld is biggeer than %ld\n", olen, dest_len);
|
||||
return;
|
||||
}
|
||||
|
||||
pos = dest;
|
||||
count = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
tmp = dtable[(unsigned char)b64input[i]];
|
||||
if (tmp == 0x80) {
|
||||
continue;
|
||||
}
|
||||
block[count] = tmp;
|
||||
count++;
|
||||
if (count == 4) {
|
||||
*pos++ = (block[0] << 2) | (block[1] >> 4);
|
||||
*pos++ = (block[1] << 4) | (block[2] >> 2);
|
||||
*pos++ = (block[2] << 6) | block[3];
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static grpc_ratls_result_t grpc_ratls_get_secret_string(
|
||||
const char *server_addr,
|
||||
const char *config_json,
|
||||
const char *name,
|
||||
std::string* secret_string
|
||||
)
|
||||
{
|
||||
auto cred = grpc::sgx::TlsCredentials(config_json);
|
||||
auto channel = grpc::CreateChannel(server_addr, cred);
|
||||
|
||||
GrSecretClient gr_secret(channel);
|
||||
|
||||
std::string secret = gr_secret.GetSecret(name);
|
||||
// std::cout << "secret received: " << secret << "len: " << secret.length() << std::endl;
|
||||
|
||||
if (secret.empty()) {
|
||||
return GRPC_RATLS_NO_SECRET;
|
||||
} else {
|
||||
//Decode From Base64
|
||||
size_t len = base64_decode_len(secret.c_str());
|
||||
if (len) {
|
||||
char *secret_orig = (char *)malloc(len);
|
||||
if (!secret_orig) {
|
||||
return GRPC_RATLS_BUF_ERR;
|
||||
}
|
||||
base64_decode(secret.c_str(), (unsigned char *)secret_orig, len);
|
||||
secret_string->assign(secret_orig, secret_orig + len - 1);
|
||||
free(secret_orig);
|
||||
|
||||
return GRPC_RATLS_SUCCESS;
|
||||
}
|
||||
|
||||
return GRPC_RATLS_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
// Get secret to file
|
||||
int grpc_ratls_get_secret(
|
||||
const char *server_addr,
|
||||
const char *config_json,
|
||||
const char *name,
|
||||
const char *secret_file
|
||||
)
|
||||
{
|
||||
std::string secret_string;
|
||||
grpc_ratls_result_t ret = grpc_ratls_get_secret_string(
|
||||
server_addr, config_json, name, &secret_string
|
||||
);
|
||||
|
||||
if (ret == GRPC_RATLS_SUCCESS) {
|
||||
//write to file
|
||||
std::ofstream myfile;
|
||||
myfile.open(secret_file);
|
||||
myfile << secret_string;
|
||||
myfile.close();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Get secret to buffer
|
||||
int grpc_ratls_get_secret_to_buf(
|
||||
const char *server_addr,
|
||||
const char *config_json,
|
||||
const char *name,
|
||||
char *secret_buf,
|
||||
unsigned int *buf_len
|
||||
)
|
||||
{
|
||||
std::string secret_string;
|
||||
grpc_ratls_result_t ret = grpc_ratls_get_secret_string(
|
||||
server_addr, config_json, name, &secret_string
|
||||
);
|
||||
|
||||
if (ret == GRPC_RATLS_SUCCESS) {
|
||||
if (*buf_len < secret_string.size()) {
|
||||
std::cout << "buffer size is smaller than the secret string length " << secret_string.size() << std::endl;;
|
||||
return GRPC_RATLS_BUF_TOO_SMALL;
|
||||
}
|
||||
//write to buffer
|
||||
memcpy(secret_buf, secret_string.data(), secret_string.size());
|
||||
*buf_len = secret_string.size();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#ifndef _GRPC_RATLS_CLIENT_H_
|
||||
#define _GRPC_RATLS_CLIENT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// client get secret
|
||||
extern int grpc_ratls_get_secret(
|
||||
const char *server_addr, // grpc server address+port, such as "localhost:50051"
|
||||
const char *config_json, // ratls handshake config json file
|
||||
const char *name, // secret name to be requested
|
||||
const char *secret_file // secret file to be saved
|
||||
);
|
||||
|
||||
extern int grpc_ratls_get_secret_to_buf(
|
||||
const char *server_addr, // grpc server address+port, such as "localhost:50051"
|
||||
const char *config_json, // ratls handshake config json file
|
||||
const char *name, // secret name to be requested
|
||||
char *secret_buf, // buffer to save secret
|
||||
unsigned int *buf_len // buffer size
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _GRPC_RATLS_CLIENT_H_
|
@ -1,96 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include <grpcpp/security/sgx/sgx_ra_tls.h>
|
||||
#include <grpcpp/ext/proto_server_reflection_plugin.h>
|
||||
|
||||
#ifdef BAZEL_BUILD
|
||||
#include "examples/protos/ratls.grpc.pb.h"
|
||||
#else
|
||||
#include "ratls.grpc.pb.h"
|
||||
#endif
|
||||
|
||||
#include "../grpc_ratls_server.h"
|
||||
|
||||
using ratls::GrSecret;
|
||||
using ratls::SecretRequest;
|
||||
using ratls::SecretReply;
|
||||
|
||||
|
||||
// Logic and data behind the server's behavior.
|
||||
class GrSecretServiceImpl final: public GrSecret::Service {
|
||||
public:
|
||||
grpc::Status GetSecret(
|
||||
grpc::ServerContext* context, const SecretRequest* request, SecretReply* reply) override {
|
||||
//std::cout << "Request: " << request->name() << std::endl;
|
||||
auto secret = this->get_secret_string(request->name().c_str());
|
||||
if (!secret.empty()) {
|
||||
reply->set_secret(secret);
|
||||
return grpc::Status::OK;
|
||||
} else {
|
||||
return grpc::Status::CANCELLED;
|
||||
}
|
||||
}
|
||||
|
||||
GrSecretServiceImpl(const char* file) : secret_file(nullptr) {
|
||||
this->secret_file = file;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string get_secret_string(const char *name) {
|
||||
std::string secret = "";
|
||||
class grpc::sgx::json_engine secret_config(this->secret_file);
|
||||
auto item = secret_config.get_item(secret_config.get_handle(), name);
|
||||
if (item) {
|
||||
secret = secret_config.print_item(item);
|
||||
}
|
||||
|
||||
return secret;
|
||||
}
|
||||
|
||||
const char *secret_file;
|
||||
};
|
||||
|
||||
|
||||
int grpc_ratls_start_server(
|
||||
const char *server_addr,
|
||||
const char *config_json,
|
||||
const char *secret_json
|
||||
)
|
||||
{
|
||||
GrSecretServiceImpl service(secret_json);
|
||||
|
||||
grpc::EnableDefaultHealthCheckService(true);
|
||||
grpc::reflection::InitProtoReflectionServerBuilderPlugin();
|
||||
grpc::ServerBuilder builder;
|
||||
|
||||
auto creds = grpc::sgx::TlsServerCredentials(config_json);
|
||||
GPR_ASSERT(creds.get() != nullptr);
|
||||
|
||||
builder.AddListeningPort(server_addr, creds);
|
||||
builder.RegisterService(&service);
|
||||
|
||||
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
|
||||
std::cout << "Server listening on " << server_addr << std::endl;
|
||||
|
||||
server->Wait();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
#ifndef _GRPC_RATLS_SERVER_H_
|
||||
#define _GRPC_RATLS_SERVER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// start server
|
||||
extern int grpc_ratls_start_server(
|
||||
const char *server_addr, // grpc server address+port, such as "localhost:50051"
|
||||
const char *config_json, // ratls handshake config json file
|
||||
const char *secret_json // secret config json file
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _GRPC_RATLS_SERVER_H_
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "../grpc_ratls_server.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
printf("[ERROR] One argument must be provided\n\n");
|
||||
printf("Usage: server <grpc-server addr>\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
grpc_ratls_start_server(
|
||||
argv[1],
|
||||
"dynamic_config.json",
|
||||
"secret_config.json"
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// Copyright (c) 2022 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
option java_multiple_files = true;
|
||||
option java_package = "io.grpc.examples.ratls";
|
||||
option java_outer_classname = "RATLSProto";
|
||||
option objc_class_prefix = "HLW";
|
||||
|
||||
package ratls;
|
||||
|
||||
// The GRPC_RATLS secret service definition.
|
||||
service GrSecret {
|
||||
// Sends a greeting
|
||||
rpc GetSecret (SecretRequest) returns (SecretReply) {}
|
||||
}
|
||||
|
||||
// The request message containing the request's name.
|
||||
message SecretRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
// The response message containing the secret (base64 encoded string)
|
||||
message SecretReply {
|
||||
string secret = 1;
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SGX_RA_TLS_H
|
||||
#define SGX_RA_TLS_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <grpcpp/security/credentials.h>
|
||||
#include <grpcpp/security/server_credentials.h>
|
||||
|
||||
#include <cjson/cJSON.h>
|
||||
|
||||
namespace grpc {
|
||||
namespace sgx {
|
||||
|
||||
struct sgx_config;
|
||||
|
||||
std::vector<std::string> ra_tls_get_key_cert();
|
||||
|
||||
void ra_tls_parse_sgx_config(sgx_config sgx_cfg);
|
||||
|
||||
void ra_tls_parse_sgx_config(const char* file);
|
||||
|
||||
void ra_tls_verify_init();
|
||||
|
||||
int ra_tls_auth_check_schedule(void* /* config_user_data */,
|
||||
grpc_tls_server_authorization_check_arg* arg);
|
||||
|
||||
std::shared_ptr<grpc::ChannelCredentials> TlsCredentials(sgx_config sgx_cfg);
|
||||
|
||||
std::shared_ptr<grpc::ChannelCredentials> TlsCredentials(const char* sgx_cfg_json);
|
||||
|
||||
std::shared_ptr<grpc::ServerCredentials> TlsServerCredentials(sgx_config sgx_cfg);
|
||||
|
||||
std::shared_ptr<grpc::ServerCredentials> TlsServerCredentials(const char* sgx_cfg_json);
|
||||
|
||||
std::shared_ptr<grpc::Channel> CreateSecureChannel(
|
||||
string target_str, std::shared_ptr<grpc::ChannelCredentials> channel_creds);
|
||||
|
||||
class json_engine {
|
||||
public:
|
||||
json_engine();
|
||||
|
||||
json_engine(const char*);
|
||||
|
||||
~json_engine();
|
||||
|
||||
bool open(const char*);
|
||||
|
||||
void close();
|
||||
|
||||
cJSON* get_handle();
|
||||
|
||||
cJSON* get_item(cJSON* obj, const char* item);
|
||||
|
||||
char* print_item(cJSON* obj);
|
||||
|
||||
bool compare_item(cJSON* obj, const char* item);
|
||||
|
||||
private:
|
||||
cJSON* handle;
|
||||
};
|
||||
|
||||
} // namespace sgx
|
||||
} // namespace grpc
|
||||
|
||||
#endif // SGX_RA_TLS_H
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SGX_RA_TLS_OPTIONS_H
|
||||
#define SGX_RA_TLS_OPTIONS_H
|
||||
|
||||
#include <grpc/grpc_security_constants.h>
|
||||
#include <grpc/status.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpcpp/security/tls_certificate_provider.h>
|
||||
#include <grpcpp/security/tls_credentials_options.h>
|
||||
#include <grpcpp/support/config.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace grpc {
|
||||
namespace sgx {
|
||||
|
||||
// Contains configurable options on the client side.
|
||||
// Client side doesn't need to always use certificate provider. When the
|
||||
// certificate provider is not set, we will use the root certificates stored
|
||||
// in the system default locations, and assume client won't provide any
|
||||
// identity certificates(single side TLS).
|
||||
// It is used for experimental purposes for now and it is subject to change.
|
||||
class CredentialsOptions final : public grpc::experimental::TlsCredentialsOptions {
|
||||
public:
|
||||
|
||||
explicit CredentialsOptions() : TlsCredentialsOptions() {}
|
||||
|
||||
// Sets option to request the certificates from the client.
|
||||
// The default is GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE.
|
||||
void set_cert_request_type(
|
||||
grpc_ssl_client_certificate_request_type cert_request_type);
|
||||
|
||||
// Sets the option to verify the server.
|
||||
// The default is GRPC_TLS_SERVER_VERIFICATION.
|
||||
void set_verification_option(
|
||||
grpc_tls_server_verification_option server_verification_option);
|
||||
|
||||
// Sets the custom authorization config.
|
||||
void set_authorization_check_config(
|
||||
std::shared_ptr<grpc::experimental::TlsServerAuthorizationCheckConfig>
|
||||
authorization_check_config);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace sgx
|
||||
} // namespace grpc
|
||||
|
||||
#endif // SGX_RA_TLS_OPTIONS_H
|
@ -1,133 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include "src/core/lib/security/credentials/tls/tls_credentials.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <grpc/grpc.h>
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/string_util.h>
|
||||
|
||||
#include "src/core/lib/channel/channel_args.h"
|
||||
#include "src/core/lib/security/security_connector/tls/tls_security_connector.h"
|
||||
|
||||
#define GRPC_CREDENTIALS_TYPE_TLS "Tls"
|
||||
|
||||
namespace {
|
||||
|
||||
bool CredentialOptionSanityCheck(const grpc_tls_credentials_options* options,
|
||||
bool is_client) {
|
||||
if (options == nullptr) {
|
||||
gpr_log(GPR_ERROR, "TLS credentials options is nullptr.");
|
||||
return false;
|
||||
}
|
||||
// TODO(ZhenLian): remove this when it is also supported on server side.
|
||||
// if (!is_client && options->server_authorization_check_config() != nullptr) {
|
||||
// gpr_log(GPR_INFO,
|
||||
// "Server's credentials options should not contain server "
|
||||
// "authorization check config.");
|
||||
// }
|
||||
if (options->server_verification_option() != GRPC_TLS_SERVER_VERIFICATION &&
|
||||
options->server_authorization_check_config() == nullptr) {
|
||||
gpr_log(GPR_ERROR,
|
||||
"Should provider custom verifications if bypassing default ones.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TlsCredentials::TlsCredentials(
|
||||
grpc_core::RefCountedPtr<grpc_tls_credentials_options> options)
|
||||
: grpc_channel_credentials(GRPC_CREDENTIALS_TYPE_TLS),
|
||||
options_(std::move(options)) {}
|
||||
|
||||
TlsCredentials::~TlsCredentials() {}
|
||||
|
||||
grpc_core::RefCountedPtr<grpc_channel_security_connector>
|
||||
TlsCredentials::create_security_connector(
|
||||
grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,
|
||||
const char* target_name, const grpc_channel_args* args,
|
||||
grpc_channel_args** new_args) {
|
||||
const char* overridden_target_name = nullptr;
|
||||
tsi_ssl_session_cache* ssl_session_cache = nullptr;
|
||||
for (size_t i = 0; args != nullptr && i < args->num_args; i++) {
|
||||
grpc_arg* arg = &args->args[i];
|
||||
if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 &&
|
||||
arg->type == GRPC_ARG_STRING) {
|
||||
overridden_target_name = arg->value.string;
|
||||
}
|
||||
if (strcmp(arg->key, GRPC_SSL_SESSION_CACHE_ARG) == 0 &&
|
||||
arg->type == GRPC_ARG_POINTER) {
|
||||
ssl_session_cache =
|
||||
static_cast<tsi_ssl_session_cache*>(arg->value.pointer.p);
|
||||
}
|
||||
}
|
||||
grpc_core::RefCountedPtr<grpc_channel_security_connector> sc =
|
||||
grpc_core::TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector(
|
||||
this->Ref(), options_, std::move(call_creds), target_name,
|
||||
overridden_target_name, ssl_session_cache);
|
||||
if (sc == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (args != nullptr) {
|
||||
grpc_arg new_arg = grpc_channel_arg_string_create(
|
||||
const_cast<char*>(GRPC_ARG_HTTP2_SCHEME), const_cast<char*>("https"));
|
||||
*new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1);
|
||||
}
|
||||
return sc;
|
||||
}
|
||||
|
||||
TlsServerCredentials::TlsServerCredentials(
|
||||
grpc_core::RefCountedPtr<grpc_tls_credentials_options> options)
|
||||
: grpc_server_credentials(GRPC_CREDENTIALS_TYPE_TLS),
|
||||
options_(std::move(options)) {}
|
||||
|
||||
TlsServerCredentials::~TlsServerCredentials() {}
|
||||
|
||||
grpc_core::RefCountedPtr<grpc_server_security_connector>
|
||||
TlsServerCredentials::create_security_connector(
|
||||
const grpc_channel_args* /* args */) {
|
||||
return grpc_core::TlsServerSecurityConnector::
|
||||
CreateTlsServerSecurityConnector(this->Ref(), options_);
|
||||
}
|
||||
|
||||
/** -- Wrapper APIs declared in grpc_security.h -- **/
|
||||
|
||||
grpc_channel_credentials* grpc_tls_credentials_create(
|
||||
grpc_tls_credentials_options* options) {
|
||||
if (!CredentialOptionSanityCheck(options, true /* is_client */)) {
|
||||
return nullptr;
|
||||
}
|
||||
return new TlsCredentials(
|
||||
grpc_core::RefCountedPtr<grpc_tls_credentials_options>(options));
|
||||
}
|
||||
|
||||
grpc_server_credentials* grpc_tls_server_credentials_create(
|
||||
grpc_tls_credentials_options* options) {
|
||||
if (!CredentialOptionSanityCheck(options, false /* is_client */)) {
|
||||
return nullptr;
|
||||
}
|
||||
return new TlsServerCredentials(
|
||||
grpc_core::RefCountedPtr<grpc_tls_credentials_options>(options));
|
||||
}
|
@ -1,863 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include "src/core/lib/security/security_connector/tls/tls_security_connector.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
#include <grpc/grpc.h>
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/string_util.h>
|
||||
|
||||
#include "src/core/lib/gprpp/host_port.h"
|
||||
#include "src/core/lib/security/credentials/ssl/ssl_credentials.h"
|
||||
#include "src/core/lib/security/credentials/tls/tls_credentials.h"
|
||||
#include "src/core/lib/security/security_connector/ssl_utils.h"
|
||||
#include "src/core/lib/security/transport/security_handshaker.h"
|
||||
#include "src/core/lib/slice/slice_internal.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/tsi/ssl_transport_security.h"
|
||||
#include "src/core/tsi/transport_security.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
namespace {
|
||||
|
||||
tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair(
|
||||
const PemKeyCertPairList& cert_pair_list) {
|
||||
tsi_ssl_pem_key_cert_pair* tsi_pairs = nullptr;
|
||||
size_t num_key_cert_pairs = cert_pair_list.size();
|
||||
if (num_key_cert_pairs > 0) {
|
||||
GPR_ASSERT(cert_pair_list.data() != nullptr);
|
||||
tsi_pairs = static_cast<tsi_ssl_pem_key_cert_pair*>(
|
||||
gpr_zalloc(num_key_cert_pairs * sizeof(tsi_ssl_pem_key_cert_pair)));
|
||||
}
|
||||
for (size_t i = 0; i < num_key_cert_pairs; i++) {
|
||||
GPR_ASSERT(!cert_pair_list[i].private_key().empty());
|
||||
GPR_ASSERT(!cert_pair_list[i].cert_chain().empty());
|
||||
tsi_pairs[i].cert_chain =
|
||||
gpr_strdup(cert_pair_list[i].cert_chain().c_str());
|
||||
tsi_pairs[i].private_key =
|
||||
gpr_strdup(cert_pair_list[i].private_key().c_str());
|
||||
}
|
||||
return tsi_pairs;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void gpr_check_free(void* p) {
|
||||
if (p) {
|
||||
gpr_free(p);
|
||||
p = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------channel security connector-------------------
|
||||
RefCountedPtr<grpc_channel_security_connector>
|
||||
TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector(
|
||||
RefCountedPtr<grpc_channel_credentials> channel_creds,
|
||||
RefCountedPtr<grpc_tls_credentials_options> options,
|
||||
RefCountedPtr<grpc_call_credentials> request_metadata_creds,
|
||||
const char* target_name, const char* overridden_target_name,
|
||||
tsi_ssl_session_cache* ssl_session_cache) {
|
||||
if (channel_creds == nullptr) {
|
||||
gpr_log(GPR_ERROR,
|
||||
"channel_creds is nullptr in "
|
||||
"TlsChannelSecurityConnectorCreate()");
|
||||
return nullptr;
|
||||
}
|
||||
if (options == nullptr) {
|
||||
gpr_log(GPR_ERROR,
|
||||
"options is nullptr in "
|
||||
"TlsChannelSecurityConnectorCreate()");
|
||||
return nullptr;
|
||||
}
|
||||
if (target_name == nullptr) {
|
||||
gpr_log(GPR_ERROR,
|
||||
"target_name is nullptr in "
|
||||
"TlsChannelSecurityConnectorCreate()");
|
||||
return nullptr;
|
||||
}
|
||||
return MakeRefCounted<TlsChannelSecurityConnector>(
|
||||
std::move(channel_creds), std::move(options),
|
||||
std::move(request_metadata_creds), target_name, overridden_target_name,
|
||||
ssl_session_cache);
|
||||
}
|
||||
|
||||
TlsChannelSecurityConnector::TlsChannelSecurityConnector(
|
||||
RefCountedPtr<grpc_channel_credentials> channel_creds,
|
||||
RefCountedPtr<grpc_tls_credentials_options> options,
|
||||
RefCountedPtr<grpc_call_credentials> request_metadata_creds,
|
||||
const char* target_name, const char* overridden_target_name,
|
||||
tsi_ssl_session_cache* ssl_session_cache)
|
||||
: grpc_channel_security_connector(GRPC_SSL_URL_SCHEME,
|
||||
std::move(channel_creds),
|
||||
std::move(request_metadata_creds)),
|
||||
options_(std::move(options)),
|
||||
overridden_target_name_(
|
||||
overridden_target_name == nullptr ? "" : overridden_target_name),
|
||||
ssl_session_cache_(ssl_session_cache) {
|
||||
if (ssl_session_cache_ != nullptr) {
|
||||
tsi_ssl_session_cache_ref(ssl_session_cache_);
|
||||
}
|
||||
check_arg_ = ServerAuthorizationCheckArgCreate(this);
|
||||
absl::string_view host;
|
||||
absl::string_view port;
|
||||
SplitHostPort(target_name, &host, &port);
|
||||
target_name_ = std::string(host);
|
||||
// Create a watcher.
|
||||
auto watcher_ptr = absl::make_unique<TlsChannelCertificateWatcher>(this);
|
||||
certificate_watcher_ = watcher_ptr.get();
|
||||
// Register the watcher with the distributor.
|
||||
grpc_tls_certificate_distributor* distributor =
|
||||
options_->certificate_distributor();
|
||||
absl::optional<std::string> watched_root_cert_name;
|
||||
if (options_->watch_root_cert()) {
|
||||
watched_root_cert_name = options_->root_cert_name();
|
||||
}
|
||||
absl::optional<std::string> watched_identity_cert_name;
|
||||
if (options_->watch_identity_pair()) {
|
||||
watched_identity_cert_name = options_->identity_cert_name();
|
||||
}
|
||||
// We will use the root certs stored in system default locations if not
|
||||
// watching root certs on the client side. We will handle this case
|
||||
// differently here, because "watching a default roots without the identity
|
||||
// certs" is a valid case(and hence we will need to call
|
||||
// OnCertificatesChanged), but it requires nothing from the provider, and
|
||||
// hence no need to register the watcher.
|
||||
bool use_default_roots = !options_->watch_root_cert();
|
||||
if (use_default_roots && !options_->watch_identity_pair()) {
|
||||
watcher_ptr->OnCertificatesChanged(absl::nullopt, absl::nullopt);
|
||||
} else {
|
||||
distributor->WatchTlsCertificates(std::move(watcher_ptr),
|
||||
watched_root_cert_name,
|
||||
watched_identity_cert_name);
|
||||
}
|
||||
}
|
||||
|
||||
TlsChannelSecurityConnector::~TlsChannelSecurityConnector() {
|
||||
if (ssl_session_cache_ != nullptr) {
|
||||
tsi_ssl_session_cache_unref(ssl_session_cache_);
|
||||
}
|
||||
// Cancel all the watchers.
|
||||
grpc_tls_certificate_distributor* distributor =
|
||||
options_->certificate_distributor();
|
||||
if (distributor != nullptr) {
|
||||
distributor->CancelTlsCertificatesWatch(certificate_watcher_);
|
||||
}
|
||||
if (client_handshaker_factory_ != nullptr) {
|
||||
tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
|
||||
}
|
||||
if (check_arg_ != nullptr) {
|
||||
ServerAuthorizationCheckArgDestroy(check_arg_);
|
||||
}
|
||||
}
|
||||
|
||||
void TlsChannelSecurityConnector::add_handshakers(
|
||||
const grpc_channel_args* args, grpc_pollset_set* /*interested_parties*/,
|
||||
HandshakeManager* handshake_mgr) {
|
||||
MutexLock lock(&mu_);
|
||||
if (client_handshaker_factory_ != nullptr) {
|
||||
// Instantiate TSI handshaker.
|
||||
tsi_handshaker* tsi_hs = nullptr;
|
||||
tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker(
|
||||
client_handshaker_factory_,
|
||||
overridden_target_name_.empty() ? target_name_.c_str()
|
||||
: overridden_target_name_.c_str(),
|
||||
&tsi_hs);
|
||||
if (result != TSI_OK) {
|
||||
gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
|
||||
tsi_result_to_string(result));
|
||||
return;
|
||||
}
|
||||
// Create handshakers.
|
||||
handshake_mgr->Add(SecurityHandshakerCreate(tsi_hs, this, args));
|
||||
return;
|
||||
}
|
||||
// TODO(ZhenLian): Implement the logic(delegation to
|
||||
// BlockOnInitialCredentialHandshaker) when certificates are not ready.
|
||||
gpr_log(GPR_ERROR, "%s not supported yet.",
|
||||
"Client BlockOnInitialCredentialHandshaker");
|
||||
}
|
||||
|
||||
void TlsChannelSecurityConnector::check_peer(
|
||||
tsi_peer peer, grpc_endpoint* /*ep*/,
|
||||
RefCountedPtr<grpc_auth_context>* auth_context,
|
||||
grpc_closure* on_peer_checked) {
|
||||
const char* target_name = overridden_target_name_.empty()
|
||||
? target_name_.c_str()
|
||||
: overridden_target_name_.c_str();
|
||||
grpc_error_handle error = grpc_ssl_check_alpn(&peer);
|
||||
if (error != GRPC_ERROR_NONE) {
|
||||
ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
|
||||
tsi_peer_destruct(&peer);
|
||||
return;
|
||||
}
|
||||
*auth_context =
|
||||
grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE);
|
||||
if (options_->server_verification_option() == GRPC_TLS_SERVER_VERIFICATION) {
|
||||
/* Do the default host name check if specifying the target name. */
|
||||
error = internal::TlsCheckHostName(target_name, &peer);
|
||||
if (error != GRPC_ERROR_NONE) {
|
||||
ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
|
||||
tsi_peer_destruct(&peer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Do the custom server authorization check, if specified by the user. */
|
||||
const grpc_tls_server_authorization_check_config* config =
|
||||
options_->server_authorization_check_config();
|
||||
/* If server authorization config is not null, use it to perform
|
||||
* server authorization check. */
|
||||
if (config != nullptr) {
|
||||
const tsi_peer_property* p =
|
||||
tsi_peer_get_property_by_name(&peer, TSI_X509_PEM_CERT_PROPERTY);
|
||||
if (p == nullptr) {
|
||||
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
||||
"Cannot check peer: missing pem cert property.");
|
||||
} else {
|
||||
char* peer_pem = static_cast<char*>(gpr_zalloc(p->value.length + 1));
|
||||
memcpy(peer_pem, p->value.data, p->value.length);
|
||||
GPR_ASSERT(check_arg_ != nullptr);
|
||||
check_arg_->peer_cert = check_arg_->peer_cert == nullptr
|
||||
? gpr_strdup(peer_pem)
|
||||
: check_arg_->peer_cert;
|
||||
check_arg_->target_name = check_arg_->target_name == nullptr
|
||||
? gpr_strdup(target_name)
|
||||
: check_arg_->target_name;
|
||||
on_peer_checked_ = on_peer_checked;
|
||||
gpr_check_free(peer_pem);
|
||||
const tsi_peer_property* chain = tsi_peer_get_property_by_name(
|
||||
&peer, TSI_X509_PEM_CERT_CHAIN_PROPERTY);
|
||||
if (chain != nullptr) {
|
||||
char* peer_pem_chain =
|
||||
static_cast<char*>(gpr_zalloc(chain->value.length + 1));
|
||||
memcpy(peer_pem_chain, chain->value.data, chain->value.length);
|
||||
check_arg_->peer_cert_full_chain =
|
||||
check_arg_->peer_cert_full_chain == nullptr
|
||||
? gpr_strdup(peer_pem_chain)
|
||||
: check_arg_->peer_cert_full_chain;
|
||||
gpr_check_free(peer_pem_chain);
|
||||
}
|
||||
// TODO(zhenlian) - This should be cleaned up as part of the custom
|
||||
// verification changes. Fill in the subject alternative names
|
||||
std::vector<char*> subject_alternative_names;
|
||||
for (size_t i = 0; i < peer.property_count; i++) {
|
||||
const tsi_peer_property* prop = &peer.properties[i];
|
||||
if (strcmp(prop->name,
|
||||
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
|
||||
char* san = new char[prop->value.length + 1];
|
||||
memcpy(san, prop->value.data, prop->value.length);
|
||||
san[prop->value.length] = '\0';
|
||||
subject_alternative_names.emplace_back(san);
|
||||
}
|
||||
}
|
||||
if (check_arg_->subject_alternative_names != nullptr) {
|
||||
for (size_t i = 0; i < check_arg_->subject_alternative_names_size;
|
||||
++i) {
|
||||
delete[] check_arg_->subject_alternative_names[i];
|
||||
}
|
||||
delete[] check_arg_->subject_alternative_names;
|
||||
}
|
||||
check_arg_->subject_alternative_names_size =
|
||||
subject_alternative_names.size();
|
||||
if (subject_alternative_names.empty()) {
|
||||
check_arg_->subject_alternative_names = nullptr;
|
||||
} else {
|
||||
check_arg_->subject_alternative_names =
|
||||
new char*[check_arg_->subject_alternative_names_size];
|
||||
for (size_t i = 0; i < check_arg_->subject_alternative_names_size;
|
||||
++i) {
|
||||
check_arg_->subject_alternative_names[i] =
|
||||
subject_alternative_names[i];
|
||||
}
|
||||
}
|
||||
int callback_status = config->Schedule(check_arg_);
|
||||
/* Server authorization check is handled asynchronously. */
|
||||
if (callback_status) {
|
||||
tsi_peer_destruct(&peer);
|
||||
return;
|
||||
}
|
||||
/* Server authorization check is handled synchronously. */
|
||||
error = ProcessServerAuthorizationCheckResult(check_arg_);
|
||||
}
|
||||
}
|
||||
ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
|
||||
tsi_peer_destruct(&peer);
|
||||
}
|
||||
|
||||
int TlsChannelSecurityConnector::cmp(
|
||||
const grpc_security_connector* other_sc) const {
|
||||
auto* other = reinterpret_cast<const TlsChannelSecurityConnector*>(other_sc);
|
||||
int c = channel_security_connector_cmp(other);
|
||||
if (c != 0) {
|
||||
return c;
|
||||
}
|
||||
return grpc_ssl_cmp_target_name(
|
||||
target_name_.c_str(), other->target_name_.c_str(),
|
||||
overridden_target_name_.c_str(), other->overridden_target_name_.c_str());
|
||||
}
|
||||
|
||||
bool TlsChannelSecurityConnector::check_call_host(
|
||||
absl::string_view host, grpc_auth_context* auth_context,
|
||||
grpc_closure* /*on_call_host_checked*/, grpc_error_handle* error) {
|
||||
if (options_->server_verification_option() ==
|
||||
GRPC_TLS_SKIP_HOSTNAME_VERIFICATION ||
|
||||
options_->server_verification_option() ==
|
||||
GRPC_TLS_SKIP_ALL_SERVER_VERIFICATION) {
|
||||
return true;
|
||||
}
|
||||
return grpc_ssl_check_call_host(host, target_name_.c_str(),
|
||||
overridden_target_name_.c_str(), auth_context,
|
||||
error);
|
||||
}
|
||||
|
||||
void TlsChannelSecurityConnector::cancel_check_call_host(
|
||||
grpc_closure* /*on_call_host_checked*/, grpc_error_handle error) {
|
||||
GRPC_ERROR_UNREF(error);
|
||||
}
|
||||
|
||||
void TlsChannelSecurityConnector::TlsChannelCertificateWatcher::
|
||||
OnCertificatesChanged(absl::optional<absl::string_view> root_certs,
|
||||
absl::optional<PemKeyCertPairList> key_cert_pairs) {
|
||||
GPR_ASSERT(security_connector_ != nullptr);
|
||||
MutexLock lock(&security_connector_->mu_);
|
||||
if (root_certs.has_value()) {
|
||||
security_connector_->pem_root_certs_ = root_certs;
|
||||
}
|
||||
if (key_cert_pairs.has_value()) {
|
||||
security_connector_->pem_key_cert_pair_list_ = std::move(key_cert_pairs);
|
||||
}
|
||||
const bool root_ready = !security_connector_->options_->watch_root_cert() ||
|
||||
security_connector_->pem_root_certs_.has_value();
|
||||
const bool identity_ready =
|
||||
!security_connector_->options_->watch_identity_pair() ||
|
||||
security_connector_->pem_key_cert_pair_list_.has_value();
|
||||
if (root_ready && identity_ready) {
|
||||
if (security_connector_->UpdateHandshakerFactoryLocked() !=
|
||||
GRPC_SECURITY_OK) {
|
||||
gpr_log(GPR_ERROR, "Update handshaker factory failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(ZhenLian): implement the logic to signal waiting handshakers once
|
||||
// BlockOnInitialCredentialHandshaker is implemented.
|
||||
void TlsChannelSecurityConnector::TlsChannelCertificateWatcher::OnError(
|
||||
grpc_error_handle root_cert_error, grpc_error_handle identity_cert_error) {
|
||||
if (root_cert_error != GRPC_ERROR_NONE) {
|
||||
gpr_log(GPR_ERROR,
|
||||
"TlsChannelCertificateWatcher getting root_cert_error: %s",
|
||||
grpc_error_std_string(root_cert_error).c_str());
|
||||
}
|
||||
if (identity_cert_error != GRPC_ERROR_NONE) {
|
||||
gpr_log(GPR_ERROR,
|
||||
"TlsChannelCertificateWatcher getting identity_cert_error: %s",
|
||||
grpc_error_std_string(identity_cert_error).c_str());
|
||||
}
|
||||
GRPC_ERROR_UNREF(root_cert_error);
|
||||
GRPC_ERROR_UNREF(identity_cert_error);
|
||||
}
|
||||
|
||||
// TODO(ZhenLian): implement the logic to signal waiting handshakers once
|
||||
// BlockOnInitialCredentialHandshaker is implemented.
|
||||
grpc_security_status
|
||||
TlsChannelSecurityConnector::UpdateHandshakerFactoryLocked() {
|
||||
bool skip_server_certificate_verification =
|
||||
options_->server_verification_option() ==
|
||||
GRPC_TLS_SKIP_ALL_SERVER_VERIFICATION;
|
||||
/* Free the client handshaker factory if exists. */
|
||||
if (client_handshaker_factory_ != nullptr) {
|
||||
tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
|
||||
}
|
||||
std::string pem_root_certs;
|
||||
if (pem_root_certs_.has_value()) {
|
||||
// TODO(ZhenLian): update the underlying TSI layer to use C++ types like
|
||||
// std::string and absl::string_view to avoid making another copy here.
|
||||
pem_root_certs = std::string(*pem_root_certs_);
|
||||
}
|
||||
tsi_ssl_pem_key_cert_pair* pem_key_cert_pair = nullptr;
|
||||
if (pem_key_cert_pair_list_.has_value()) {
|
||||
pem_key_cert_pair = ConvertToTsiPemKeyCertPair(*pem_key_cert_pair_list_);
|
||||
}
|
||||
bool use_default_roots = !options_->watch_root_cert();
|
||||
grpc_security_status status = grpc_ssl_tsi_client_handshaker_factory_init(
|
||||
pem_key_cert_pair,
|
||||
pem_root_certs.empty() || use_default_roots ? nullptr
|
||||
: pem_root_certs.c_str(),
|
||||
skip_server_certificate_verification,
|
||||
grpc_get_tsi_tls_version(options_->min_tls_version()),
|
||||
grpc_get_tsi_tls_version(options_->max_tls_version()), ssl_session_cache_,
|
||||
&client_handshaker_factory_);
|
||||
/* Free memory. */
|
||||
if (pem_key_cert_pair != nullptr) {
|
||||
grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pair, 1);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void TlsChannelSecurityConnector::ServerAuthorizationCheckDone(
|
||||
grpc_tls_server_authorization_check_arg* arg) {
|
||||
GPR_ASSERT(arg != nullptr);
|
||||
ExecCtx exec_ctx;
|
||||
grpc_error_handle error = ProcessServerAuthorizationCheckResult(arg);
|
||||
TlsChannelSecurityConnector* connector =
|
||||
static_cast<TlsChannelSecurityConnector*>(arg->cb_user_data);
|
||||
ExecCtx::Run(DEBUG_LOCATION, connector->on_peer_checked_, error);
|
||||
}
|
||||
|
||||
grpc_error_handle
|
||||
TlsChannelSecurityConnector::ProcessServerAuthorizationCheckResult(
|
||||
grpc_tls_server_authorization_check_arg* arg) {
|
||||
grpc_error_handle error = GRPC_ERROR_NONE;
|
||||
/* Server authorization check is cancelled by caller. */
|
||||
if (arg->status == GRPC_STATUS_CANCELLED) {
|
||||
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
|
||||
absl::StrCat("Server authorization check is cancelled by the caller "
|
||||
"with error: ",
|
||||
arg->error_details->error_details())
|
||||
.c_str());
|
||||
} else if (arg->status == GRPC_STATUS_OK) {
|
||||
/* Server authorization check completed successfully but returned check
|
||||
* failure. */
|
||||
if (!arg->success) {
|
||||
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
|
||||
absl::StrCat("Server authorization check failed with error: ",
|
||||
arg->error_details->error_details())
|
||||
.c_str());
|
||||
}
|
||||
/* Server authorization check did not complete correctly. */
|
||||
} else {
|
||||
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
|
||||
absl::StrCat(
|
||||
"Server authorization check did not finish correctly with error: ",
|
||||
arg->error_details->error_details())
|
||||
.c_str());
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
grpc_tls_server_authorization_check_arg*
|
||||
TlsChannelSecurityConnector::ServerAuthorizationCheckArgCreate(
|
||||
void* user_data) {
|
||||
grpc_tls_server_authorization_check_arg* arg =
|
||||
new grpc_tls_server_authorization_check_arg();
|
||||
arg->target_name = nullptr;
|
||||
arg->peer_cert = nullptr;
|
||||
arg->peer_cert_full_chain = nullptr;
|
||||
arg->subject_alternative_names = nullptr;
|
||||
arg->subject_alternative_names_size = 0;
|
||||
arg->error_details = new grpc_tls_error_details();
|
||||
arg->cb = ServerAuthorizationCheckDone;
|
||||
arg->cb_user_data = user_data;
|
||||
arg->status = GRPC_STATUS_OK;
|
||||
return arg;
|
||||
}
|
||||
|
||||
void TlsChannelSecurityConnector::ServerAuthorizationCheckArgDestroy(
|
||||
grpc_tls_server_authorization_check_arg* arg) {
|
||||
if (arg == nullptr) {
|
||||
return;
|
||||
}
|
||||
gpr_check_free(const_cast<char*>(arg->target_name));
|
||||
gpr_check_free(const_cast<char*>(arg->peer_cert));
|
||||
gpr_check_free(const_cast<char*>(arg->peer_cert_full_chain));
|
||||
for (size_t i = 0; i < arg->subject_alternative_names_size; ++i) {
|
||||
delete[] arg->subject_alternative_names[i];
|
||||
}
|
||||
delete[] arg->subject_alternative_names;
|
||||
delete arg->error_details;
|
||||
if (arg->destroy_context != nullptr) {
|
||||
arg->destroy_context(arg->context);
|
||||
}
|
||||
delete arg;
|
||||
arg = nullptr;
|
||||
}
|
||||
|
||||
// -------------------server security connector-------------------
|
||||
RefCountedPtr<grpc_server_security_connector>
|
||||
TlsServerSecurityConnector::CreateTlsServerSecurityConnector(
|
||||
RefCountedPtr<grpc_server_credentials> server_creds,
|
||||
RefCountedPtr<grpc_tls_credentials_options> options) {
|
||||
if (server_creds == nullptr) {
|
||||
gpr_log(GPR_ERROR,
|
||||
"server_creds is nullptr in "
|
||||
"TlsServerSecurityConnectorCreate()");
|
||||
return nullptr;
|
||||
}
|
||||
if (options == nullptr) {
|
||||
gpr_log(GPR_ERROR,
|
||||
"options is nullptr in "
|
||||
"TlsServerSecurityConnectorCreate()");
|
||||
return nullptr;
|
||||
}
|
||||
return MakeRefCounted<TlsServerSecurityConnector>(std::move(server_creds),
|
||||
std::move(options));
|
||||
}
|
||||
|
||||
void TlsServerSecurityConnector::ClientAuthorizationCheckDone(
|
||||
grpc_tls_server_authorization_check_arg* arg) {
|
||||
GPR_ASSERT(arg != nullptr);
|
||||
ExecCtx exec_ctx;
|
||||
grpc_error_handle error = ProcessClientAuthorizationCheckResult(arg);
|
||||
TlsServerSecurityConnector* connector =
|
||||
static_cast<TlsServerSecurityConnector*>(arg->cb_user_data);
|
||||
ExecCtx::Run(DEBUG_LOCATION, connector->on_peer_checked_, error);
|
||||
}
|
||||
|
||||
grpc_error_handle
|
||||
TlsServerSecurityConnector::ProcessClientAuthorizationCheckResult(
|
||||
grpc_tls_server_authorization_check_arg* arg) {
|
||||
grpc_error_handle error = GRPC_ERROR_NONE;
|
||||
/* Client authorization check is cancelled by caller. */
|
||||
if (arg->status == GRPC_STATUS_CANCELLED) {
|
||||
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
|
||||
absl::StrCat("Client authorization check is cancelled by the caller "
|
||||
"with error: ",
|
||||
arg->error_details->error_details())
|
||||
.c_str());
|
||||
} else if (arg->status == GRPC_STATUS_OK) {
|
||||
/* Client authorization check completed successfully but returned check
|
||||
* failure. */
|
||||
if (!arg->success) {
|
||||
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
|
||||
absl::StrCat("Client authorization check failed with error: ",
|
||||
arg->error_details->error_details())
|
||||
.c_str());
|
||||
}
|
||||
/* Client authorization check did not complete correctly. */
|
||||
} else {
|
||||
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
|
||||
absl::StrCat(
|
||||
"Client authorization check did not finish correctly with error: ",
|
||||
arg->error_details->error_details())
|
||||
.c_str());
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
grpc_tls_server_authorization_check_arg*
|
||||
TlsServerSecurityConnector::ClientAuthorizationCheckArgCreate(
|
||||
void* user_data) {
|
||||
grpc_tls_server_authorization_check_arg* arg =
|
||||
new grpc_tls_server_authorization_check_arg();
|
||||
arg->target_name = nullptr;
|
||||
arg->peer_cert = nullptr;
|
||||
arg->peer_cert_full_chain = nullptr;
|
||||
arg->subject_alternative_names = nullptr;
|
||||
arg->subject_alternative_names_size = 0;
|
||||
arg->error_details = new grpc_tls_error_details();
|
||||
arg->cb = ClientAuthorizationCheckDone;
|
||||
arg->cb_user_data = user_data;
|
||||
arg->status = GRPC_STATUS_OK;
|
||||
return arg;
|
||||
}
|
||||
|
||||
void TlsServerSecurityConnector::ClientAuthorizationCheckArgDestroy(
|
||||
grpc_tls_server_authorization_check_arg* arg) {
|
||||
if (arg == nullptr) {
|
||||
return;
|
||||
}
|
||||
gpr_check_free(const_cast<char*>(arg->target_name));
|
||||
gpr_check_free(const_cast<char*>(arg->peer_cert));
|
||||
gpr_check_free(const_cast<char*>(arg->peer_cert_full_chain));
|
||||
for (size_t i = 0; i < arg->subject_alternative_names_size; ++i) {
|
||||
delete[] arg->subject_alternative_names[i];
|
||||
}
|
||||
delete[] arg->subject_alternative_names;
|
||||
delete arg->error_details;
|
||||
if (arg->destroy_context != nullptr) {
|
||||
arg->destroy_context(arg->context);
|
||||
}
|
||||
delete arg;
|
||||
arg = nullptr;
|
||||
}
|
||||
|
||||
TlsServerSecurityConnector::TlsServerSecurityConnector(
|
||||
RefCountedPtr<grpc_server_credentials> server_creds,
|
||||
RefCountedPtr<grpc_tls_credentials_options> options)
|
||||
: grpc_server_security_connector(GRPC_SSL_URL_SCHEME,
|
||||
std::move(server_creds)),
|
||||
options_(std::move(options)) {
|
||||
check_arg_ = ClientAuthorizationCheckArgCreate(this);
|
||||
// Create a watcher.
|
||||
auto watcher_ptr = absl::make_unique<TlsServerCertificateWatcher>(this);
|
||||
certificate_watcher_ = watcher_ptr.get();
|
||||
// Register the watcher with the distributor.
|
||||
grpc_tls_certificate_distributor* distributor =
|
||||
options_->certificate_distributor();
|
||||
absl::optional<std::string> watched_root_cert_name;
|
||||
if (options_->watch_root_cert()) {
|
||||
watched_root_cert_name = options_->root_cert_name();
|
||||
}
|
||||
absl::optional<std::string> watched_identity_cert_name;
|
||||
if (options_->watch_identity_pair()) {
|
||||
watched_identity_cert_name = options_->identity_cert_name();
|
||||
}
|
||||
// Server side won't use default system roots at any time.
|
||||
distributor->WatchTlsCertificates(std::move(watcher_ptr),
|
||||
watched_root_cert_name,
|
||||
watched_identity_cert_name);
|
||||
}
|
||||
|
||||
TlsServerSecurityConnector::~TlsServerSecurityConnector() {
|
||||
// Cancel all the watchers.
|
||||
grpc_tls_certificate_distributor* distributor =
|
||||
options_->certificate_distributor();
|
||||
if (distributor != nullptr) {
|
||||
distributor->CancelTlsCertificatesWatch(certificate_watcher_);
|
||||
}
|
||||
if (server_handshaker_factory_ != nullptr) {
|
||||
tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
|
||||
}
|
||||
if (check_arg_ != nullptr) {
|
||||
ClientAuthorizationCheckArgDestroy(check_arg_);
|
||||
}
|
||||
}
|
||||
|
||||
void TlsServerSecurityConnector::add_handshakers(
|
||||
const grpc_channel_args* args, grpc_pollset_set* /*interested_parties*/,
|
||||
HandshakeManager* handshake_mgr) {
|
||||
MutexLock lock(&mu_);
|
||||
if (server_handshaker_factory_ != nullptr) {
|
||||
// Instantiate TSI handshaker.
|
||||
tsi_handshaker* tsi_hs = nullptr;
|
||||
tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker(
|
||||
server_handshaker_factory_, &tsi_hs);
|
||||
if (result != TSI_OK) {
|
||||
gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
|
||||
tsi_result_to_string(result));
|
||||
return;
|
||||
}
|
||||
// Create handshakers.
|
||||
handshake_mgr->Add(SecurityHandshakerCreate(tsi_hs, this, args));
|
||||
return;
|
||||
}
|
||||
// TODO(ZhenLian): Implement the logic(delegation to
|
||||
// BlockOnInitialCredentialHandshaker) when certificates are not ready.
|
||||
gpr_log(GPR_ERROR, "%s not supported yet.",
|
||||
"Server BlockOnInitialCredentialHandshaker");
|
||||
}
|
||||
|
||||
void TlsServerSecurityConnector::check_peer(
|
||||
tsi_peer peer, grpc_endpoint* /*ep*/,
|
||||
RefCountedPtr<grpc_auth_context>* auth_context,
|
||||
grpc_closure* on_peer_checked) {
|
||||
grpc_error_handle error = grpc_ssl_check_alpn(&peer);
|
||||
if (error != GRPC_ERROR_NONE) {
|
||||
ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
|
||||
tsi_peer_destruct(&peer);
|
||||
return;
|
||||
}
|
||||
*auth_context =
|
||||
grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE);
|
||||
if (options_->server_verification_option() == GRPC_TLS_SERVER_VERIFICATION) {
|
||||
/* Do the default host name check if specifying the target name. */
|
||||
error = internal::TlsCheckHostName("", &peer);
|
||||
if (error != GRPC_ERROR_NONE) {
|
||||
ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
|
||||
tsi_peer_destruct(&peer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Do the custom client authorization check, if specified by the user. */
|
||||
const grpc_tls_server_authorization_check_config* config =
|
||||
options_->server_authorization_check_config();
|
||||
/* If client authorization config is not null, use it to perform
|
||||
* client authorization check. */
|
||||
if (config != nullptr) {
|
||||
const tsi_peer_property* p =
|
||||
tsi_peer_get_property_by_name(&peer, TSI_X509_PEM_CERT_PROPERTY);
|
||||
if (p == nullptr) {
|
||||
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
||||
"Cannot check peer: missing pem cert property.");
|
||||
} else {
|
||||
char* peer_pem = static_cast<char*>(gpr_zalloc(p->value.length + 1));
|
||||
memcpy(peer_pem, p->value.data, p->value.length);
|
||||
GPR_ASSERT(check_arg_ != nullptr);
|
||||
check_arg_->peer_cert = gpr_strdup(peer_pem);
|
||||
check_arg_->target_name = gpr_strdup("");
|
||||
on_peer_checked_ = on_peer_checked;
|
||||
gpr_check_free(peer_pem);
|
||||
const tsi_peer_property* chain = tsi_peer_get_property_by_name(
|
||||
&peer, TSI_X509_PEM_CERT_CHAIN_PROPERTY);
|
||||
if (chain != nullptr) {
|
||||
char* peer_pem_chain =
|
||||
static_cast<char*>(gpr_zalloc(chain->value.length + 1));
|
||||
memcpy(peer_pem_chain, chain->value.data, chain->value.length);
|
||||
check_arg_->peer_cert_full_chain =
|
||||
check_arg_->peer_cert_full_chain == nullptr
|
||||
? gpr_strdup(peer_pem_chain)
|
||||
: check_arg_->peer_cert_full_chain;
|
||||
gpr_check_free(peer_pem_chain);
|
||||
}
|
||||
// TODO(zhenlian) - This should be cleaned up as part of the custom
|
||||
// verification changes. Fill in the subject alternative names
|
||||
std::vector<char*> subject_alternative_names;
|
||||
for (size_t i = 0; i < peer.property_count; i++) {
|
||||
const tsi_peer_property* prop = &peer.properties[i];
|
||||
if (strcmp(prop->name,
|
||||
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
|
||||
char* san = new char[prop->value.length + 1];
|
||||
memcpy(san, prop->value.data, prop->value.length);
|
||||
san[prop->value.length] = '\0';
|
||||
subject_alternative_names.emplace_back(san);
|
||||
}
|
||||
}
|
||||
if (check_arg_->subject_alternative_names != nullptr) {
|
||||
for (size_t i = 0; i < check_arg_->subject_alternative_names_size;
|
||||
++i) {
|
||||
delete[] check_arg_->subject_alternative_names[i];
|
||||
}
|
||||
delete[] check_arg_->subject_alternative_names;
|
||||
}
|
||||
check_arg_->subject_alternative_names_size =
|
||||
subject_alternative_names.size();
|
||||
if (subject_alternative_names.empty()) {
|
||||
check_arg_->subject_alternative_names = nullptr;
|
||||
} else {
|
||||
check_arg_->subject_alternative_names =
|
||||
new char*[check_arg_->subject_alternative_names_size];
|
||||
for (size_t i = 0; i < check_arg_->subject_alternative_names_size;
|
||||
++i) {
|
||||
check_arg_->subject_alternative_names[i] =
|
||||
subject_alternative_names[i];
|
||||
}
|
||||
}
|
||||
int callback_status = config->Schedule(check_arg_);
|
||||
/* Client authorization check is handled asynchronously. */
|
||||
if (callback_status) {
|
||||
tsi_peer_destruct(&peer);
|
||||
return;
|
||||
}
|
||||
/* Client authorization check is handled synchronously. */
|
||||
error = ProcessClientAuthorizationCheckResult(check_arg_);
|
||||
}
|
||||
}
|
||||
ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
|
||||
tsi_peer_destruct(&peer);
|
||||
}
|
||||
|
||||
int TlsServerSecurityConnector::cmp(
|
||||
const grpc_security_connector* other) const {
|
||||
return server_security_connector_cmp(
|
||||
static_cast<const grpc_server_security_connector*>(other));
|
||||
}
|
||||
|
||||
void TlsServerSecurityConnector::TlsServerCertificateWatcher::
|
||||
OnCertificatesChanged(absl::optional<absl::string_view> root_certs,
|
||||
absl::optional<PemKeyCertPairList> key_cert_pairs) {
|
||||
GPR_ASSERT(security_connector_ != nullptr);
|
||||
MutexLock lock(&security_connector_->mu_);
|
||||
if (root_certs.has_value()) {
|
||||
security_connector_->pem_root_certs_ = root_certs;
|
||||
}
|
||||
if (key_cert_pairs.has_value()) {
|
||||
security_connector_->pem_key_cert_pair_list_ = std::move(key_cert_pairs);
|
||||
}
|
||||
bool root_being_watched = security_connector_->options_->watch_root_cert();
|
||||
bool root_has_value = security_connector_->pem_root_certs_.has_value();
|
||||
bool identity_being_watched =
|
||||
security_connector_->options_->watch_identity_pair();
|
||||
bool identity_has_value =
|
||||
security_connector_->pem_key_cert_pair_list_.has_value();
|
||||
if ((root_being_watched && root_has_value && identity_being_watched &&
|
||||
identity_has_value) ||
|
||||
(root_being_watched && root_has_value && !identity_being_watched) ||
|
||||
(!root_being_watched && identity_being_watched && identity_has_value)) {
|
||||
if (security_connector_->UpdateHandshakerFactoryLocked() !=
|
||||
GRPC_SECURITY_OK) {
|
||||
gpr_log(GPR_ERROR, "Update handshaker factory failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(ZhenLian): implement the logic to signal waiting handshakers once
|
||||
// BlockOnInitialCredentialHandshaker is implemented.
|
||||
void TlsServerSecurityConnector::TlsServerCertificateWatcher::OnError(
|
||||
grpc_error_handle root_cert_error, grpc_error_handle identity_cert_error) {
|
||||
if (root_cert_error != GRPC_ERROR_NONE) {
|
||||
gpr_log(GPR_ERROR,
|
||||
"TlsServerCertificateWatcher getting root_cert_error: %s",
|
||||
grpc_error_std_string(root_cert_error).c_str());
|
||||
}
|
||||
if (identity_cert_error != GRPC_ERROR_NONE) {
|
||||
gpr_log(GPR_ERROR,
|
||||
"TlsServerCertificateWatcher getting identity_cert_error: %s",
|
||||
grpc_error_std_string(identity_cert_error).c_str());
|
||||
}
|
||||
GRPC_ERROR_UNREF(root_cert_error);
|
||||
GRPC_ERROR_UNREF(identity_cert_error);
|
||||
}
|
||||
|
||||
// TODO(ZhenLian): implement the logic to signal waiting handshakers once
|
||||
// BlockOnInitialCredentialHandshaker is implemented.
|
||||
grpc_security_status
|
||||
TlsServerSecurityConnector::UpdateHandshakerFactoryLocked() {
|
||||
/* Free the server handshaker factory if exists. */
|
||||
if (server_handshaker_factory_ != nullptr) {
|
||||
tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
|
||||
}
|
||||
// The identity certs on the server side shouldn't be empty.
|
||||
GPR_ASSERT(pem_key_cert_pair_list_.has_value());
|
||||
GPR_ASSERT(!(*pem_key_cert_pair_list_).empty());
|
||||
std::string pem_root_certs;
|
||||
if (pem_root_certs_.has_value()) {
|
||||
// TODO(ZhenLian): update the underlying TSI layer to use C++ types like
|
||||
// std::string and absl::string_view to avoid making another copy here.
|
||||
pem_root_certs = std::string(*pem_root_certs_);
|
||||
}
|
||||
tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs = nullptr;
|
||||
pem_key_cert_pairs = ConvertToTsiPemKeyCertPair(*pem_key_cert_pair_list_);
|
||||
size_t num_key_cert_pairs = (*pem_key_cert_pair_list_).size();
|
||||
grpc_security_status status = grpc_ssl_tsi_server_handshaker_factory_init(
|
||||
pem_key_cert_pairs, num_key_cert_pairs,
|
||||
pem_root_certs.empty() ? nullptr : pem_root_certs.c_str(),
|
||||
options_->cert_request_type(),
|
||||
grpc_get_tsi_tls_version(options_->min_tls_version()),
|
||||
grpc_get_tsi_tls_version(options_->max_tls_version()),
|
||||
&server_handshaker_factory_);
|
||||
/* Free memory. */
|
||||
grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pairs,
|
||||
num_key_cert_pairs);
|
||||
return status;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
grpc_error_handle TlsCheckHostName(const char* peer_name,
|
||||
const tsi_peer* peer) {
|
||||
/* Check the peer name if specified. */
|
||||
if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) {
|
||||
return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
|
||||
absl::StrCat("Peer name ", peer_name, " is not in peer certificate")
|
||||
.c_str());
|
||||
}
|
||||
return GRPC_ERROR_NONE;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace grpc_core
|
@ -1,267 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_TLS_TLS_SECURITY_CONNECTOR_H
|
||||
#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_TLS_TLS_SECURITY_CONNECTOR_H
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include "src/core/lib/gprpp/sync.h"
|
||||
#include "src/core/lib/security/context/security_context.h"
|
||||
#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h"
|
||||
#include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h"
|
||||
|
||||
#define GRPC_TLS_TRANSPORT_SECURITY_TYPE "tls"
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
// Channel security connector using TLS as transport security protocol.
|
||||
class TlsChannelSecurityConnector final
|
||||
: public grpc_channel_security_connector {
|
||||
public:
|
||||
// static factory method to create a TLS channel security connector.
|
||||
static RefCountedPtr<grpc_channel_security_connector>
|
||||
CreateTlsChannelSecurityConnector(
|
||||
RefCountedPtr<grpc_channel_credentials> channel_creds,
|
||||
RefCountedPtr<grpc_tls_credentials_options> options,
|
||||
RefCountedPtr<grpc_call_credentials> request_metadata_creds,
|
||||
const char* target_name, const char* overridden_target_name,
|
||||
tsi_ssl_session_cache* ssl_session_cache);
|
||||
|
||||
TlsChannelSecurityConnector(
|
||||
RefCountedPtr<grpc_channel_credentials> channel_creds,
|
||||
RefCountedPtr<grpc_tls_credentials_options> options,
|
||||
RefCountedPtr<grpc_call_credentials> request_metadata_creds,
|
||||
const char* target_name, const char* overridden_target_name,
|
||||
tsi_ssl_session_cache* ssl_session_cache);
|
||||
|
||||
~TlsChannelSecurityConnector() override;
|
||||
|
||||
void add_handshakers(const grpc_channel_args* args,
|
||||
grpc_pollset_set* interested_parties,
|
||||
HandshakeManager* handshake_mgr) override;
|
||||
|
||||
void check_peer(tsi_peer peer, grpc_endpoint* ep,
|
||||
RefCountedPtr<grpc_auth_context>* auth_context,
|
||||
grpc_closure* on_peer_checked) override;
|
||||
|
||||
void cancel_check_peer(grpc_closure* /*on_peer_checked*/,
|
||||
grpc_error_handle error) override {
|
||||
// TODO(ZhenLian): call verifier->cancel() once the verifier is ready.
|
||||
GRPC_ERROR_UNREF(error);
|
||||
}
|
||||
|
||||
int cmp(const grpc_security_connector* other_sc) const override;
|
||||
|
||||
bool check_call_host(absl::string_view host, grpc_auth_context* auth_context,
|
||||
grpc_closure* on_call_host_checked,
|
||||
grpc_error_handle* error) override;
|
||||
|
||||
void cancel_check_call_host(grpc_closure* on_call_host_checked,
|
||||
grpc_error_handle error) override;
|
||||
|
||||
tsi_ssl_client_handshaker_factory* ClientHandshakerFactoryForTesting() {
|
||||
MutexLock lock(&mu_);
|
||||
return client_handshaker_factory_;
|
||||
};
|
||||
|
||||
absl::optional<absl::string_view> RootCertsForTesting() {
|
||||
MutexLock lock(&mu_);
|
||||
return pem_root_certs_;
|
||||
}
|
||||
|
||||
absl::optional<PemKeyCertPairList> KeyCertPairListForTesting() {
|
||||
MutexLock lock(&mu_);
|
||||
return pem_key_cert_pair_list_;
|
||||
}
|
||||
|
||||
private:
|
||||
// A watcher that watches certificate updates from
|
||||
// grpc_tls_certificate_distributor. It will never outlive
|
||||
// |security_connector_|.
|
||||
class TlsChannelCertificateWatcher : public grpc_tls_certificate_distributor::
|
||||
TlsCertificatesWatcherInterface {
|
||||
public:
|
||||
explicit TlsChannelCertificateWatcher(
|
||||
TlsChannelSecurityConnector* security_connector)
|
||||
: security_connector_(security_connector) {}
|
||||
void OnCertificatesChanged(
|
||||
absl::optional<absl::string_view> root_certs,
|
||||
absl::optional<PemKeyCertPairList> key_cert_pairs) override;
|
||||
void OnError(grpc_error_handle root_cert_error,
|
||||
grpc_error_handle identity_cert_error) override;
|
||||
|
||||
private:
|
||||
TlsChannelSecurityConnector* security_connector_ = nullptr;
|
||||
};
|
||||
|
||||
// Updates |client_handshaker_factory_| when the certificates that
|
||||
// |certificate_watcher_| is watching get updated.
|
||||
grpc_security_status UpdateHandshakerFactoryLocked()
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
|
||||
|
||||
// gRPC-provided callback executed by application, which servers to bring the
|
||||
// control back to gRPC core.
|
||||
static void ServerAuthorizationCheckDone(
|
||||
grpc_tls_server_authorization_check_arg* arg);
|
||||
|
||||
// A util function to process server authorization check result.
|
||||
static grpc_error_handle ProcessServerAuthorizationCheckResult(
|
||||
grpc_tls_server_authorization_check_arg* arg);
|
||||
|
||||
// A util function to create a server authorization check arg instance.
|
||||
static grpc_tls_server_authorization_check_arg*
|
||||
ServerAuthorizationCheckArgCreate(void* user_data);
|
||||
|
||||
// A util function to destroy a server authorization check arg instance.
|
||||
static void ServerAuthorizationCheckArgDestroy(
|
||||
grpc_tls_server_authorization_check_arg* arg);
|
||||
|
||||
RefCountedPtr<grpc_tls_credentials_options> options_;
|
||||
grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface*
|
||||
certificate_watcher_ = nullptr;
|
||||
grpc_closure* on_peer_checked_ = nullptr;
|
||||
std::string target_name_;
|
||||
std::string overridden_target_name_;
|
||||
grpc_tls_server_authorization_check_arg* check_arg_ = nullptr;
|
||||
|
||||
Mutex mu_;
|
||||
tsi_ssl_client_handshaker_factory* client_handshaker_factory_
|
||||
ABSL_GUARDED_BY(mu_) = nullptr;
|
||||
tsi_ssl_session_cache* ssl_session_cache_ ABSL_GUARDED_BY(mu_) = nullptr;
|
||||
absl::optional<absl::string_view> pem_root_certs_ ABSL_GUARDED_BY(mu_);
|
||||
absl::optional<PemKeyCertPairList> pem_key_cert_pair_list_
|
||||
ABSL_GUARDED_BY(mu_);
|
||||
};
|
||||
|
||||
// Server security connector using TLS as transport security protocol.
|
||||
class TlsServerSecurityConnector final : public grpc_server_security_connector {
|
||||
public:
|
||||
// static factory method to create a TLS server security connector.
|
||||
static RefCountedPtr<grpc_server_security_connector>
|
||||
CreateTlsServerSecurityConnector(
|
||||
RefCountedPtr<grpc_server_credentials> server_creds,
|
||||
RefCountedPtr<grpc_tls_credentials_options> options);
|
||||
|
||||
TlsServerSecurityConnector(
|
||||
RefCountedPtr<grpc_server_credentials> server_creds,
|
||||
RefCountedPtr<grpc_tls_credentials_options> options);
|
||||
~TlsServerSecurityConnector() override;
|
||||
|
||||
void add_handshakers(const grpc_channel_args* args,
|
||||
grpc_pollset_set* interested_parties,
|
||||
HandshakeManager* handshake_mgr) override;
|
||||
|
||||
void check_peer(tsi_peer peer, grpc_endpoint* ep,
|
||||
RefCountedPtr<grpc_auth_context>* auth_context,
|
||||
grpc_closure* on_peer_checked) override;
|
||||
|
||||
void cancel_check_peer(grpc_closure* /*on_peer_checked*/,
|
||||
grpc_error_handle error) override {
|
||||
// TODO(ZhenLian): call verifier->cancel() once the verifier is ready.
|
||||
GRPC_ERROR_UNREF(error);
|
||||
}
|
||||
|
||||
int cmp(const grpc_security_connector* other) const override;
|
||||
|
||||
tsi_ssl_server_handshaker_factory* ServerHandshakerFactoryForTesting() {
|
||||
MutexLock lock(&mu_);
|
||||
return server_handshaker_factory_;
|
||||
};
|
||||
|
||||
const absl::optional<absl::string_view>& RootCertsForTesting() {
|
||||
MutexLock lock(&mu_);
|
||||
return pem_root_certs_;
|
||||
}
|
||||
|
||||
const absl::optional<PemKeyCertPairList>& KeyCertPairListForTesting() {
|
||||
MutexLock lock(&mu_);
|
||||
return pem_key_cert_pair_list_;
|
||||
}
|
||||
|
||||
private:
|
||||
// A watcher that watches certificate updates from
|
||||
// grpc_tls_certificate_distributor. It will never outlive
|
||||
// |security_connector_|.
|
||||
class TlsServerCertificateWatcher : public grpc_tls_certificate_distributor::
|
||||
TlsCertificatesWatcherInterface {
|
||||
public:
|
||||
explicit TlsServerCertificateWatcher(
|
||||
TlsServerSecurityConnector* security_connector)
|
||||
: security_connector_(security_connector) {}
|
||||
void OnCertificatesChanged(
|
||||
absl::optional<absl::string_view> root_certs,
|
||||
absl::optional<PemKeyCertPairList> key_cert_pairs) override;
|
||||
void OnError(grpc_error_handle root_cert_error,
|
||||
grpc_error_handle identity_cert_error) override;
|
||||
|
||||
private:
|
||||
TlsServerSecurityConnector* security_connector_ = nullptr;
|
||||
};
|
||||
|
||||
// Updates |server_handshaker_factory_| when the certificates that
|
||||
// |certificate_watcher_| is watching get updated.
|
||||
grpc_security_status UpdateHandshakerFactoryLocked()
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
|
||||
|
||||
// gRPC-provided callback executed by application, which servers to bring the
|
||||
// control back to gRPC core.
|
||||
static void ClientAuthorizationCheckDone(
|
||||
grpc_tls_server_authorization_check_arg* arg);
|
||||
|
||||
// A util function to process server authorization check result.
|
||||
static grpc_error_handle ProcessClientAuthorizationCheckResult(
|
||||
grpc_tls_server_authorization_check_arg* arg);
|
||||
|
||||
// A util function to create a server authorization check arg instance.
|
||||
static grpc_tls_server_authorization_check_arg*
|
||||
ClientAuthorizationCheckArgCreate(void* user_data);
|
||||
|
||||
// A util function to destroy a server authorization check arg instance.
|
||||
static void ClientAuthorizationCheckArgDestroy(
|
||||
grpc_tls_server_authorization_check_arg* arg);
|
||||
|
||||
RefCountedPtr<grpc_tls_credentials_options> options_;
|
||||
|
||||
grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface*
|
||||
certificate_watcher_ = nullptr;
|
||||
grpc_closure* on_peer_checked_ = nullptr;
|
||||
std::string target_name_ = "localhost";
|
||||
std::string overridden_target_name_= "localhost";
|
||||
grpc_tls_server_authorization_check_arg* check_arg_ = nullptr;
|
||||
|
||||
Mutex mu_;
|
||||
tsi_ssl_server_handshaker_factory* server_handshaker_factory_
|
||||
ABSL_GUARDED_BY(mu_) = nullptr;
|
||||
absl::optional<absl::string_view> pem_root_certs_ ABSL_GUARDED_BY(mu_);
|
||||
absl::optional<PemKeyCertPairList> pem_key_cert_pair_list_
|
||||
ABSL_GUARDED_BY(mu_);
|
||||
};
|
||||
|
||||
// ---- Functions below are exposed for testing only -----------------------
|
||||
namespace internal {
|
||||
|
||||
// TlsCheckHostName checks if |peer_name| matches the identity information
|
||||
// contained in |peer|. This is AKA hostname check.
|
||||
grpc_error_handle TlsCheckHostName(const char* peer_name, const tsi_peer* peer);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_TLS_TLS_SECURITY_CONNECTOR_H
|
@ -1,260 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sgx_ra_tls_backends.h"
|
||||
|
||||
namespace grpc {
|
||||
namespace sgx {
|
||||
|
||||
struct ra_tls_context _ctx_;
|
||||
|
||||
std::vector<std::string> ra_tls_get_key_cert() {
|
||||
#ifdef SGX_RA_TLS_OCCLUM_BACKEND
|
||||
return occlum_get_key_cert();
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::vector<grpc::experimental::IdentityKeyCertPair> get_identity_key_cert_pairs(
|
||||
std::vector<std::string> key_cert) {
|
||||
grpc::experimental::IdentityKeyCertPair key_cert_pair;
|
||||
key_cert_pair.private_key = key_cert[0];
|
||||
key_cert_pair.certificate_chain = key_cert[1];
|
||||
std::vector<grpc::experimental::IdentityKeyCertPair> identity_key_cert_pairs;
|
||||
identity_key_cert_pairs.emplace_back(key_cert_pair);
|
||||
return identity_key_cert_pairs;
|
||||
}
|
||||
|
||||
void credential_option_set_certificate_provider(grpc::sgx::CredentialsOptions& options) {
|
||||
std::lock_guard<std::mutex> lock(_ctx_.mtx);
|
||||
|
||||
_ctx_.cache.id++;
|
||||
|
||||
auto certificate_provider = _ctx_.cache.certificate_provider.insert({
|
||||
_ctx_.cache.id,
|
||||
std::make_shared<grpc::experimental::StaticDataCertificateProvider>(
|
||||
get_identity_key_cert_pairs(ra_tls_get_key_cert()))
|
||||
}).first;
|
||||
|
||||
options.set_certificate_provider(certificate_provider->second);
|
||||
options.watch_identity_key_cert_pairs();
|
||||
options.set_cert_request_type(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY);
|
||||
options.set_root_cert_name("");
|
||||
options.set_identity_cert_name("");
|
||||
}
|
||||
|
||||
static sgx_config parse_sgx_config_json(const char* file) {
|
||||
class json_engine sgx_json(file);
|
||||
struct sgx_config sgx_cfg;
|
||||
|
||||
sgx_cfg.verify_mr_enclave = sgx_json.compare_item(sgx_json.get_item(sgx_json.get_handle(), "verify_mr_enclave"), "on");
|
||||
sgx_cfg.verify_mr_signer = sgx_json.compare_item(sgx_json.get_item(sgx_json.get_handle(), "verify_mr_signer"), "on");
|
||||
sgx_cfg.verify_isv_prod_id = sgx_json.compare_item(sgx_json.get_item(sgx_json.get_handle(), "verify_isv_prod_id"), "on");
|
||||
sgx_cfg.verify_isv_svn = sgx_json.compare_item(sgx_json.get_item(sgx_json.get_handle(), "verify_isv_svn"), "on");
|
||||
sgx_cfg.verify_config_svn = sgx_json.compare_item(sgx_json.get_item(sgx_json.get_handle(), "verify_config_svn"), "on");
|
||||
sgx_cfg.verify_enclave_debuggable =
|
||||
sgx_json.compare_item(sgx_json.get_item(sgx_json.get_handle(), "verify_enclave_debuggable"), "on");
|
||||
|
||||
auto objs = sgx_json.get_item(sgx_json.get_handle(), "sgx_mrs");
|
||||
auto obj_num = std::min(cJSON_GetArraySize(objs), SGX_MESUREMENTS_MAX_SIZE);
|
||||
|
||||
sgx_cfg.sgx_mrs = std::vector<sgx_measurement>(obj_num, sgx_measurement());
|
||||
for (auto i = 0; i < obj_num; i++) {
|
||||
auto obj = cJSON_GetArrayItem(objs, i);
|
||||
|
||||
auto mr_enclave = sgx_json.print_item(sgx_json.get_item(obj, "mr_enclave"));
|
||||
memset(sgx_cfg.sgx_mrs[i].mr_enclave, 0, sizeof(sgx_cfg.sgx_mrs[i].mr_enclave));
|
||||
hex_to_byte(mr_enclave+1, sgx_cfg.sgx_mrs[i].mr_enclave, sizeof(sgx_cfg.sgx_mrs[i].mr_enclave));
|
||||
|
||||
auto mr_signer = sgx_json.print_item(sgx_json.get_item(obj, "mr_signer"));
|
||||
memset(sgx_cfg.sgx_mrs[i].mr_signer, 0, sizeof(sgx_cfg.sgx_mrs[i].mr_signer));
|
||||
hex_to_byte(mr_signer+1, sgx_cfg.sgx_mrs[i].mr_signer, sizeof(sgx_cfg.sgx_mrs[i].mr_signer));
|
||||
|
||||
auto isv_prod_id = sgx_json.print_item(sgx_json.get_item(obj, "isv_prod_id"));
|
||||
sgx_cfg.sgx_mrs[i].isv_prod_id = strtoul(isv_prod_id, nullptr, 10);
|
||||
|
||||
auto isv_svn = sgx_json.print_item(sgx_json.get_item(obj, "isv_svn"));
|
||||
sgx_cfg.sgx_mrs[i].isv_svn = strtoul(isv_svn, nullptr, 10);
|
||||
|
||||
auto config_svn = sgx_json.print_item(sgx_json.get_item(obj, "config_svn"));
|
||||
sgx_cfg.sgx_mrs[i].config_svn = strtoul(config_svn, nullptr, 10);
|
||||
|
||||
if (cJSON_IsTrue(sgx_json.get_item(obj, "debuggable")) == 0)
|
||||
sgx_cfg.sgx_mrs[i].debuggable = false;
|
||||
else
|
||||
sgx_cfg.sgx_mrs[i].debuggable = true;
|
||||
};
|
||||
return sgx_cfg;
|
||||
}
|
||||
|
||||
void ra_tls_parse_sgx_config(sgx_config sgx_cfg) {
|
||||
std::lock_guard<std::mutex> lock(_ctx_.mtx);
|
||||
_ctx_.sgx_cfg = sgx_cfg;
|
||||
}
|
||||
|
||||
void ra_tls_parse_sgx_config(const char* file) {
|
||||
ra_tls_parse_sgx_config(parse_sgx_config_json(file));
|
||||
}
|
||||
|
||||
void ra_tls_verify_init() {
|
||||
std::lock_guard<std::mutex> lock(_ctx_.mtx);
|
||||
}
|
||||
|
||||
static bool verify_measurement_internal(const char* mr_enclave, const char* mr_signer,
|
||||
const char* isv_prod_id, const char* isv_svn,
|
||||
const char* config_svn, bool debuggable) {
|
||||
bool status = false;
|
||||
auto & sgx_cfg = _ctx_.sgx_cfg;
|
||||
for (auto & obj : sgx_cfg.sgx_mrs) {
|
||||
status = true;
|
||||
|
||||
if (status && sgx_cfg.verify_mr_enclave && \
|
||||
memcmp(obj.mr_enclave, mr_enclave, 32)) {
|
||||
status = false;
|
||||
}
|
||||
|
||||
if (status && sgx_cfg.verify_mr_signer && \
|
||||
memcmp(obj.mr_signer, mr_signer, 32)) {
|
||||
status = false;
|
||||
}
|
||||
|
||||
if (status && sgx_cfg.verify_isv_prod_id && \
|
||||
(obj.isv_prod_id != *(uint16_t*)isv_prod_id)) {
|
||||
status = false;
|
||||
}
|
||||
|
||||
if (status && sgx_cfg.verify_isv_svn && \
|
||||
(obj.isv_svn != *(uint16_t*)isv_svn)) {
|
||||
status = false;
|
||||
}
|
||||
|
||||
if (status && sgx_cfg.verify_config_svn && \
|
||||
(obj.config_svn != *(uint16_t*)config_svn)) {
|
||||
status = false;
|
||||
}
|
||||
|
||||
if (status && sgx_cfg.verify_enclave_debuggable && \
|
||||
(obj.debuggable != debuggable)) {
|
||||
status = false;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int verify_measurement(const char* mr_enclave, const char* mr_signer,
|
||||
const char* isv_prod_id, const char* isv_svn,
|
||||
const char* config_svn, bool debuggable) {
|
||||
std::lock_guard<std::mutex> lock(_ctx_.mtx);
|
||||
bool status = false;
|
||||
try {
|
||||
assert(mr_enclave && mr_signer && isv_prod_id && isv_svn && config_svn);
|
||||
status = verify_measurement_internal(
|
||||
mr_enclave, mr_signer, isv_prod_id, isv_svn, config_svn, debuggable
|
||||
);
|
||||
if (status) {
|
||||
grpc_printf(" |- verify result : success\n");
|
||||
} else {
|
||||
grpc_printf("Below remote sgx measurements is not in the allowable list.\n");
|
||||
grpc_printf(" |- mr_enclave : %s\n", byte_to_hex(mr_enclave, 32).c_str());
|
||||
grpc_printf(" |- mr_signer : %s\n", byte_to_hex(mr_signer, 32).c_str());
|
||||
grpc_printf(" |- isv_prod_id : %hu\n", *((uint16_t*)isv_prod_id));
|
||||
grpc_printf(" |- isv_svn : %hu\n", *((uint16_t*)isv_svn));
|
||||
grpc_printf(" |- config_svn : %hu\n", *((uint16_t*)config_svn));
|
||||
grpc_printf(" |- debuggable : %s\n", debuggable?"true":"false");
|
||||
grpc_printf(" |- verify result : failed\n");
|
||||
}
|
||||
} catch (...) {
|
||||
grpc_printf("unable to verify measurement!");
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
return status ? 0 : -1;
|
||||
}
|
||||
|
||||
int TlsAuthorizationCheck::Schedule(grpc::experimental::TlsServerAuthorizationCheckArg* arg) {
|
||||
GPR_ASSERT(arg != nullptr);
|
||||
|
||||
char der_crt[16000] = "";
|
||||
auto peer_cert_buf = arg->peer_cert();
|
||||
peer_cert_buf.copy(der_crt, peer_cert_buf.length(), 0);
|
||||
|
||||
#ifdef SGX_RA_TLS_OCCLUM_BACKEND
|
||||
int ret = occlum_verify_cert((const unsigned char *)der_crt, 16000);
|
||||
#endif
|
||||
|
||||
if (ret != 0) {
|
||||
grpc_printf("something went wrong while verifying quote\n");
|
||||
arg->set_success(0);
|
||||
arg->set_status(GRPC_STATUS_UNAUTHENTICATED);
|
||||
} else {
|
||||
arg->set_success(1);
|
||||
arg->set_status(GRPC_STATUS_OK);
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
void TlsAuthorizationCheck::Cancel(grpc::experimental::TlsServerAuthorizationCheckArg* arg) {
|
||||
GPR_ASSERT(arg != nullptr);
|
||||
arg->set_status(GRPC_STATUS_PERMISSION_DENIED);
|
||||
arg->set_error_details("cancelled");
|
||||
};
|
||||
|
||||
int ra_tls_auth_check_schedule(void* /* confiuser_data */,
|
||||
grpc_tls_server_authorization_check_arg* arg) {
|
||||
char der_crt[16000] = "";
|
||||
memcpy(der_crt, arg->peer_cert, strlen(arg->peer_cert));
|
||||
|
||||
#ifdef SGX_RA_TLS_OCCLUM_BACKEND
|
||||
int ret = occlum_verify_cert((const unsigned char *)der_crt, 16000);
|
||||
#endif
|
||||
|
||||
if (ret != 0) {
|
||||
grpc_printf("something went wrong while verifying quote\n");
|
||||
arg->success = 0;
|
||||
arg->status = GRPC_STATUS_UNAUTHENTICATED;
|
||||
} else {
|
||||
arg->success = 1;
|
||||
arg->status = GRPC_STATUS_OK;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void credential_option_set_authorization_check(grpc::sgx::CredentialsOptions& options) {
|
||||
std::lock_guard<std::mutex> lock(_ctx_.mtx);
|
||||
|
||||
_ctx_.cache.id++;
|
||||
|
||||
auto authorization_check = _ctx_.cache.authorization_check.insert({
|
||||
_ctx_.cache.id, std::make_shared<grpc::sgx::TlsAuthorizationCheck>()
|
||||
}).first;
|
||||
|
||||
auto authorization_check_config = _ctx_.cache.authorization_check_config.insert({
|
||||
_ctx_.cache.id,
|
||||
std::make_shared<grpc::experimental::TlsServerAuthorizationCheckConfig>(
|
||||
authorization_check->second)
|
||||
}).first;
|
||||
|
||||
options.set_authorization_check_config(authorization_check_config->second);
|
||||
options.set_verification_option(GRPC_TLS_SKIP_ALL_SERVER_VERIFICATION);
|
||||
}
|
||||
|
||||
} // namespace sgx
|
||||
} // namespace grpc
|
@ -1,114 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SGX_RA_TLS_BACKENDS_H
|
||||
#define SGX_RA_TLS_BACKENDS_H
|
||||
|
||||
#include "sgx_ra_tls_utils.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include <grpc/grpc_security.h>
|
||||
#include <grpc/grpc_security_constants.h>
|
||||
#include <grpcpp/security/credentials.h>
|
||||
#include <grpcpp/security/tls_certificate_provider.h>
|
||||
#include <grpcpp/security/tls_credentials_options.h>
|
||||
#include <grpcpp/security/server_credentials.h>
|
||||
#include <grpcpp/security/sgx/sgx_ra_tls_options.h>
|
||||
|
||||
// Set 1 for strict safety checks
|
||||
#define SGX_MESUREMENTS_MAX_SIZE 16
|
||||
|
||||
namespace grpc {
|
||||
namespace sgx {
|
||||
|
||||
class TlsAuthorizationCheck
|
||||
: public grpc::experimental::TlsServerAuthorizationCheckInterface {
|
||||
int Schedule(grpc::experimental::TlsServerAuthorizationCheckArg* arg) override;
|
||||
void Cancel(grpc::experimental::TlsServerAuthorizationCheckArg* arg) override;
|
||||
};
|
||||
|
||||
struct sgx_measurement {
|
||||
char mr_enclave[32];
|
||||
char mr_signer[32];
|
||||
uint16_t isv_prod_id;
|
||||
uint16_t isv_svn;
|
||||
uint16_t config_svn;
|
||||
bool debuggable;
|
||||
};
|
||||
|
||||
struct sgx_config {
|
||||
bool verify_mr_enclave = true;
|
||||
bool verify_mr_signer = true;
|
||||
bool verify_isv_prod_id = true;
|
||||
bool verify_isv_svn = true;
|
||||
bool verify_config_svn = true;
|
||||
bool verify_enclave_debuggable = true;
|
||||
std::vector<sgx_measurement> sgx_mrs;
|
||||
};
|
||||
|
||||
struct ra_tls_cache {
|
||||
int id = 0;
|
||||
std::unordered_map<
|
||||
int, std::shared_ptr<grpc::experimental::StaticDataCertificateProvider>
|
||||
> certificate_provider;
|
||||
std::unordered_map<
|
||||
int, std::shared_ptr<grpc::sgx::TlsAuthorizationCheck>
|
||||
> authorization_check;
|
||||
std::unordered_map<
|
||||
int, std::shared_ptr<grpc::experimental::TlsServerAuthorizationCheckConfig>
|
||||
> authorization_check_config;
|
||||
};
|
||||
|
||||
struct ra_tls_context {
|
||||
std::mutex mtx;
|
||||
struct sgx_config sgx_cfg;
|
||||
struct ra_tls_cache cache;
|
||||
};
|
||||
|
||||
extern struct ra_tls_context _ctx_;
|
||||
|
||||
|
||||
#ifdef SGX_RA_TLS_OCCLUM_BACKEND
|
||||
|
||||
std::vector<std::string> occlum_get_key_cert();
|
||||
|
||||
int occlum_verify_cert(const unsigned char * der_crt, size_t len);
|
||||
|
||||
#endif // SGX_RA_TLS_OCCLUM_BACKEND
|
||||
|
||||
void ra_tls_parse_sgx_config(sgx_config sgx_cfg);
|
||||
|
||||
void ra_tls_parse_sgx_config(const char* file);
|
||||
|
||||
void ra_tls_verify_init();
|
||||
|
||||
int verify_measurement(const char* mr_enclave, const char* mr_signer,
|
||||
const char* isv_prod_id, const char* isv_svn,
|
||||
const char* config_svn, bool debuggable);
|
||||
|
||||
void credential_option_set_certificate_provider(grpc::sgx::CredentialsOptions& options);
|
||||
|
||||
void credential_option_set_authorization_check(grpc::sgx::CredentialsOptions& options);
|
||||
|
||||
} // namespace sgx
|
||||
} // namespace grpc
|
||||
|
||||
#endif // SGX_RA_TLS_BACKENDS_H
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sgx_ra_tls_backends.h"
|
||||
|
||||
namespace grpc {
|
||||
namespace sgx {
|
||||
|
||||
/*
|
||||
RA-TLS: on client, only need to register ra_tls_verify_callback() for cert verification
|
||||
1. extract SGX quote from "quote" OID extension from crt
|
||||
2. compare public key's hash from cert against quote's report_data
|
||||
3. prepare user-supplied verification parameter "allow outdated TCB"
|
||||
4. call into libsgx_dcap_quoteverify to verify ECDSA/based SGX quote
|
||||
5. verify all measurements from the SGX quote
|
||||
*/
|
||||
|
||||
std::shared_ptr<grpc::ChannelCredentials> TlsCredentials(sgx_config sgx_cfg) {
|
||||
grpc::sgx::CredentialsOptions options;
|
||||
|
||||
ra_tls_parse_sgx_config(sgx_cfg);
|
||||
|
||||
credential_option_set_certificate_provider(options);
|
||||
|
||||
ra_tls_verify_init();
|
||||
credential_option_set_authorization_check(options);
|
||||
|
||||
return grpc::experimental::TlsCredentials(
|
||||
reinterpret_cast<const grpc::experimental::TlsChannelCredentialsOptions&>(options));
|
||||
};
|
||||
|
||||
std::shared_ptr<grpc::ChannelCredentials> TlsCredentials(const char* sgx_cfg_json) {
|
||||
grpc::sgx::CredentialsOptions options;
|
||||
|
||||
ra_tls_parse_sgx_config(sgx_cfg_json);
|
||||
|
||||
credential_option_set_certificate_provider(options);
|
||||
|
||||
ra_tls_verify_init();
|
||||
credential_option_set_authorization_check(options);
|
||||
|
||||
return grpc::experimental::TlsCredentials(
|
||||
reinterpret_cast<const grpc::experimental::TlsChannelCredentialsOptions&>(options));
|
||||
};
|
||||
|
||||
std::shared_ptr<grpc::ServerCredentials> TlsServerCredentials(sgx_config sgx_cfg) {
|
||||
grpc::sgx::CredentialsOptions options;
|
||||
|
||||
ra_tls_parse_sgx_config(sgx_cfg);
|
||||
|
||||
credential_option_set_certificate_provider(options);
|
||||
|
||||
ra_tls_verify_init();
|
||||
credential_option_set_authorization_check(options);
|
||||
|
||||
return grpc::experimental::TlsServerCredentials(
|
||||
reinterpret_cast<const grpc::experimental::TlsServerCredentialsOptions&>(options));
|
||||
};
|
||||
|
||||
std::shared_ptr<grpc::ServerCredentials> TlsServerCredentials(const char* sgx_cfg_json) {
|
||||
grpc::sgx::CredentialsOptions options;
|
||||
|
||||
ra_tls_parse_sgx_config(sgx_cfg_json);
|
||||
|
||||
credential_option_set_certificate_provider(options);
|
||||
|
||||
ra_tls_verify_init();
|
||||
credential_option_set_authorization_check(options);
|
||||
|
||||
return grpc::experimental::TlsServerCredentials(
|
||||
reinterpret_cast<const grpc::experimental::TlsServerCredentialsOptions&>(options));
|
||||
};
|
||||
|
||||
std::shared_ptr<grpc::Channel> CreateSecureChannel(
|
||||
string target_str, std::shared_ptr<grpc::ChannelCredentials> channel_creds) {
|
||||
GPR_ASSERT(channel_creds.get() != nullptr);
|
||||
auto channel_args = grpc::ChannelArguments();
|
||||
channel_args.SetSslTargetNameOverride("RATLS");
|
||||
return grpc::CreateCustomChannel(target_str, std::move(channel_creds), channel_args);
|
||||
};
|
||||
|
||||
} // namespace sgx
|
||||
} // namespace grpc
|
@ -1,325 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sgx_ra_tls_backends.h"
|
||||
|
||||
namespace grpc {
|
||||
namespace sgx {
|
||||
|
||||
#ifdef SGX_RA_TLS_OCCLUM_BACKEND
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include "sgx_quote_3.h"
|
||||
#include "occlum_dcap.h"
|
||||
|
||||
const char * RA_TLS_LONG_NAME = "RA-TLS Extension";
|
||||
const char * RA_TLS_SHORT_NAME = "RA-TLS";
|
||||
|
||||
std::vector<std::string> occlum_get_key_cert() {
|
||||
unsigned char private_key_pem[16000], cert_pem[16000];
|
||||
|
||||
BIGNUM * e = BN_new();
|
||||
BN_set_word(e, RSA_F4);
|
||||
RSA * rsa = RSA_new();
|
||||
RSA_generate_key_ex(rsa, 2048, e, nullptr);
|
||||
|
||||
EVP_PKEY * pkey = EVP_PKEY_new();
|
||||
EVP_PKEY_assign_RSA(pkey, rsa);
|
||||
|
||||
X509 * x509 = X509_new();
|
||||
|
||||
ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
|
||||
X509_gmtime_adj(X509_get_notBefore(x509), 0);
|
||||
X509_gmtime_adj(X509_get_notAfter(x509), 630720000L);
|
||||
X509_set_pubkey(x509, pkey);
|
||||
|
||||
X509_NAME * name = X509_NAME_new();
|
||||
// X509_NAME * name = X509_get_subject_name(x509);
|
||||
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC,
|
||||
(unsigned char *)"CN", -1, -1, 0);
|
||||
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
|
||||
(unsigned char *)"Intel Inc.", -1, -1, 0);
|
||||
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
|
||||
(unsigned char *)"localhost", -1, -1, 0);
|
||||
X509_set_subject_name(x509, name);
|
||||
X509_set_issuer_name(x509, name);
|
||||
|
||||
int32_t ret;
|
||||
size_t key_len = i2d_PUBKEY(pkey, 0);
|
||||
unsigned char *public_key = NULL;
|
||||
// size_t pubkey_len = i2d_PUBKEY(pkey, &public_key);
|
||||
size_t pubkey_len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509), &public_key);
|
||||
|
||||
if (pubkey_len != key_len) {
|
||||
grpc_printf("get public key failed!\n");
|
||||
}
|
||||
|
||||
BIO *bio = BIO_new(BIO_s_mem());
|
||||
if (nullptr == bio) {
|
||||
grpc_printf("create bio failed!\n");
|
||||
}
|
||||
|
||||
ret = PEM_write_bio_RSAPrivateKey(bio, rsa, nullptr, nullptr, 0, nullptr, nullptr);
|
||||
if (ret == 0) {
|
||||
grpc_printf("write private key failed!\n");
|
||||
}
|
||||
|
||||
ret = BIO_read(bio, private_key_pem, bio->num_write);
|
||||
if (ret == 0) {
|
||||
grpc_printf("read private key failed!\n");
|
||||
}
|
||||
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
SHA256_CTX sha256;
|
||||
SHA256_Init(&sha256);
|
||||
SHA256_Update(&sha256, public_key, key_len);
|
||||
SHA256_Final(hash, &sha256);
|
||||
|
||||
void *handle;
|
||||
uint32_t quote_size;
|
||||
uint8_t *p_quote_buffer;
|
||||
|
||||
handle = dcap_quote_open();
|
||||
quote_size = dcap_get_quote_size(handle);
|
||||
|
||||
p_quote_buffer = (uint8_t*)malloc(quote_size);
|
||||
if (nullptr == p_quote_buffer) {
|
||||
grpc_printf("Couldn't allocate quote_buffer\n");
|
||||
}
|
||||
memset(p_quote_buffer, 0, quote_size);
|
||||
|
||||
sgx_report_data_t report_data = { 0 };
|
||||
memcpy(report_data.d, hash, SHA256_DIGEST_LENGTH);
|
||||
|
||||
ret = dcap_generate_quote(handle, p_quote_buffer, &report_data);
|
||||
if (0 != ret) {
|
||||
grpc_printf( "Error in dcap_generate_quote.\n");
|
||||
}
|
||||
|
||||
int nid = OBJ_create("1.2.840.113741.1", RA_TLS_SHORT_NAME, RA_TLS_LONG_NAME);
|
||||
ASN1_OBJECT* obj = OBJ_nid2obj(nid);
|
||||
ASN1_OCTET_STRING* data = ASN1_OCTET_STRING_new();
|
||||
ASN1_OCTET_STRING_set(data, p_quote_buffer, quote_size);
|
||||
|
||||
X509_EXTENSION* ext = X509_EXTENSION_create_by_OBJ(nullptr, obj, 0, data);
|
||||
X509_add_ext(x509, ext, -1);
|
||||
|
||||
X509_sign(x509, pkey, EVP_sha1());
|
||||
|
||||
BIO *cert_bio = BIO_new(BIO_s_mem());
|
||||
if (nullptr == cert_bio) {
|
||||
grpc_printf("create crt bio failed!\n");
|
||||
}
|
||||
|
||||
if (0 == PEM_write_bio_X509(cert_bio, x509)) {
|
||||
BIO_free(cert_bio);
|
||||
grpc_printf("read crt bio failed!\n");
|
||||
}
|
||||
|
||||
ret = BIO_read(cert_bio, cert_pem, cert_bio->num_write);
|
||||
if (ret == 0) {
|
||||
grpc_printf("read pem cert failed!\n");
|
||||
}
|
||||
|
||||
BIO_free(bio);
|
||||
BIO_free(cert_bio);
|
||||
EVP_PKEY_free(pkey);
|
||||
check_free(p_quote_buffer);
|
||||
dcap_quote_close(handle);
|
||||
|
||||
std::vector<std::string> key_cert;
|
||||
key_cert.emplace_back(std::string((char*) private_key_pem));
|
||||
key_cert.emplace_back(std::string((char*) cert_pem));
|
||||
return key_cert;
|
||||
}
|
||||
|
||||
static int occlum_get_quote(X509 *x509, uint8_t **quote, size_t *len) {
|
||||
STACK_OF(X509_EXTENSION) *exts = x509->cert_info->extensions;
|
||||
int ext_num;
|
||||
int ret = -1;
|
||||
if (exts) {
|
||||
ext_num = sk_X509_EXTENSION_num(exts);
|
||||
|
||||
for (int i = 0; i < ext_num; i++) {
|
||||
X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
|
||||
ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext);
|
||||
|
||||
unsigned nid = OBJ_obj2nid(obj);
|
||||
if (nid != NID_undef) {
|
||||
const char *ln = OBJ_nid2ln(nid);
|
||||
if (memcmp(RA_TLS_LONG_NAME, ln, sizeof(RA_TLS_LONG_NAME)) == 0) {
|
||||
BIO *ext_bio = BIO_new(BIO_s_mem());
|
||||
|
||||
*len = i2d_ASN1_OCTET_STRING(ext->value, quote);
|
||||
*quote = *quote + 4;
|
||||
*len = *len - 4;
|
||||
ret = 0;
|
||||
BIO_free(ext_bio);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int occlum_verify_pubkey_hash(X509 *x509, uint8_t *pubkey_hash, size_t len) {
|
||||
EVP_PKEY *pkey = X509_get_pubkey(x509);
|
||||
|
||||
int32_t ret;
|
||||
size_t key_len = EVP_PKEY_bits(pkey)/8;
|
||||
unsigned char *public_key = NULL;
|
||||
|
||||
key_len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509), &public_key);
|
||||
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
SHA256_CTX sha256;
|
||||
SHA256_Init(&sha256);
|
||||
SHA256_Update(&sha256, public_key, key_len);
|
||||
SHA256_Final(hash, &sha256);
|
||||
|
||||
ret = memcmp(hash, pubkey_hash, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int occlum_verify_quote(uint8_t * quote_buffer, size_t quote_size) {
|
||||
void *handle;
|
||||
handle = dcap_quote_open();
|
||||
|
||||
uint32_t supplemental_size, ret;
|
||||
uint8_t *p_supplemental_buffer;
|
||||
sgx_ql_qv_result_t quote_verification_result = SGX_QL_QV_RESULT_UNSPECIFIED;
|
||||
uint32_t collateral_expiration_status = 1;
|
||||
|
||||
supplemental_size = dcap_get_supplemental_data_size(handle);
|
||||
p_supplemental_buffer = (uint8_t *)malloc(supplemental_size);
|
||||
if (NULL == p_supplemental_buffer) {
|
||||
grpc_printf("Couldn't allocate supplemental buffer\n");
|
||||
}
|
||||
memset(p_supplemental_buffer, 0, supplemental_size);
|
||||
|
||||
ret = dcap_verify_quote(
|
||||
handle,
|
||||
quote_buffer,
|
||||
quote_size,
|
||||
&collateral_expiration_status,
|
||||
"e_verification_result,
|
||||
supplemental_size,
|
||||
p_supplemental_buffer
|
||||
);
|
||||
|
||||
if (0 != ret) {
|
||||
grpc_printf( "Error in dcap_verify_quote.\n");
|
||||
}
|
||||
|
||||
if (collateral_expiration_status != 0) {
|
||||
grpc_printf("the verification collateral has expired\n");
|
||||
}
|
||||
|
||||
switch (quote_verification_result) {
|
||||
case SGX_QL_QV_RESULT_OK:
|
||||
grpc_printf("Succeed to verify the quote!\n");
|
||||
break;
|
||||
case SGX_QL_QV_RESULT_CONFIG_NEEDED:
|
||||
case SGX_QL_QV_RESULT_OUT_OF_DATE:
|
||||
case SGX_QL_QV_RESULT_OUT_OF_DATE_CONFIG_NEEDED:
|
||||
case SGX_QL_QV_RESULT_SW_HARDENING_NEEDED:
|
||||
case SGX_QL_QV_RESULT_CONFIG_AND_SW_HARDENING_NEEDED:
|
||||
grpc_printf("WARN: App: Verification completed with Non-terminal result: %x\n",
|
||||
quote_verification_result);
|
||||
break;
|
||||
case SGX_QL_QV_RESULT_INVALID_SIGNATURE:
|
||||
case SGX_QL_QV_RESULT_REVOKED:
|
||||
case SGX_QL_QV_RESULT_UNSPECIFIED:
|
||||
default:
|
||||
grpc_printf("\tError: App: Verification completed with Terminal result: %x\n",
|
||||
quote_verification_result);
|
||||
}
|
||||
check_free(p_supplemental_buffer);
|
||||
dcap_quote_close(handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int occlum_verify_cert(const unsigned char * der_crt, size_t len) {
|
||||
BIO* bio = BIO_new(BIO_s_mem());
|
||||
BIO_write(bio, der_crt, strlen((const char *)der_crt));
|
||||
X509 *x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
||||
|
||||
if (x509 == nullptr) {
|
||||
grpc_printf("parse the crt failed! \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t * quote_buf = nullptr;
|
||||
size_t quote_len = 0;
|
||||
int ret = occlum_get_quote(x509, "e_buf, "e_len);
|
||||
if (ret != 0) {
|
||||
grpc_printf("parse quote failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = occlum_verify_quote(quote_buf, quote_len);
|
||||
if (ret != 0) {
|
||||
grpc_printf("verify quote failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sgx_quote3_t *p_quote = (sgx_quote3_t *)quote_buf;
|
||||
sgx_report_body_t *p_rep_body = (sgx_report_body_t *)(&p_quote->report_body);
|
||||
sgx_report_data_t *p_rep_data =(sgx_report_data_t *)(&p_rep_body->report_data);
|
||||
uint8_t *pubkey_hash = p_rep_data->d;
|
||||
|
||||
|
||||
ret = occlum_verify_pubkey_hash(x509, pubkey_hash, SHA256_DIGEST_LENGTH);
|
||||
if (ret != 0) {
|
||||
grpc_printf("verify the public key hash failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check if enclave is debuggable
|
||||
bool debuggable = false;
|
||||
if (p_rep_body->attributes.flags & SGX_FLAGS_DEBUG)
|
||||
debuggable = true;
|
||||
|
||||
ret = verify_measurement((const char *)&p_rep_body->mr_enclave,
|
||||
(const char *)&p_rep_body->mr_signer,
|
||||
(const char *)&p_rep_body->isv_prod_id,
|
||||
(const char *)&p_rep_body->isv_svn,
|
||||
(const char *)&p_rep_body->config_svn,
|
||||
debuggable);
|
||||
if (ret != 0) {
|
||||
grpc_printf("verify the measurement failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
BIO_free(bio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // SGX_RA_TLS_OCCLUM_BACKEND
|
||||
|
||||
} // namespace sgx
|
||||
} // namespace grpc
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <grpc/grpc_security.h>
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpcpp/security/sgx/sgx_ra_tls_options.h>
|
||||
|
||||
#include "absl/container/inlined_vector.h"
|
||||
#include "src/cpp/common/tls_credentials_options_util.h"
|
||||
|
||||
namespace grpc {
|
||||
namespace sgx {
|
||||
|
||||
void CredentialsOptions::set_verification_option(
|
||||
grpc_tls_server_verification_option server_verification_option) {
|
||||
grpc_tls_credentials_options* options = c_credentials_options();
|
||||
GPR_ASSERT(options != nullptr);
|
||||
grpc_tls_credentials_options_set_server_verification_option(
|
||||
options, server_verification_option);
|
||||
}
|
||||
|
||||
void CredentialsOptions::set_authorization_check_config(
|
||||
std::shared_ptr<grpc::experimental::TlsServerAuthorizationCheckConfig> config) {
|
||||
grpc_tls_credentials_options* options = c_credentials_options();
|
||||
GPR_ASSERT(options != nullptr);
|
||||
if (config != nullptr) {
|
||||
grpc_tls_credentials_options_set_server_authorization_check_config(
|
||||
options, config->c_config());
|
||||
}
|
||||
}
|
||||
|
||||
void CredentialsOptions::set_cert_request_type(
|
||||
grpc_ssl_client_certificate_request_type cert_request_type) {
|
||||
grpc_tls_credentials_options* options = c_credentials_options();
|
||||
GPR_ASSERT(options != nullptr);
|
||||
grpc_tls_credentials_options_set_cert_request_type(options, cert_request_type);
|
||||
}
|
||||
|
||||
} // namespace sgx
|
||||
} // namespace grpc
|
@ -1,169 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sgx_ra_tls_utils.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
namespace grpc {
|
||||
namespace sgx {
|
||||
|
||||
void check_free(void* ptr) {
|
||||
if (ptr) {
|
||||
free(ptr);
|
||||
ptr = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
bool hex_to_byte(const char *src, char *dst, size_t dst_size) {
|
||||
if (std::strlen(src) < dst_size*2) {
|
||||
return false;
|
||||
} else {
|
||||
for (auto i = 0; i < dst_size; i++) {
|
||||
if (!isxdigit(src[i*2]) || !isxdigit(src[i*2+1])) {
|
||||
return false;
|
||||
} else {
|
||||
sscanf(src+i*2, "%02hhx", dst+i);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void byte_to_hex(const char *src, char *dst, size_t src_size) {
|
||||
for (auto i = 0; i < src_size; i++) {
|
||||
sprintf(dst+i*2, "%02hhx", src[i]);
|
||||
}
|
||||
};
|
||||
|
||||
std::string byte_to_hex(const char *src, size_t src_size) {
|
||||
char dst[src_size*2];
|
||||
memset(dst, 0, sizeof(dst));
|
||||
byte_to_hex(src, dst, src_size);
|
||||
return std::string(dst);
|
||||
};
|
||||
|
||||
library_engine::library_engine() : handle(nullptr), error(nullptr) {};
|
||||
|
||||
library_engine::library_engine(const char* file, int mode) : handle(nullptr), error(nullptr) {
|
||||
this->open(file, mode);
|
||||
}
|
||||
|
||||
library_engine::~library_engine() {
|
||||
this->close();
|
||||
}
|
||||
|
||||
void library_engine::open(const char* file, int mode) {
|
||||
this->close();
|
||||
handle = dlopen(file, mode);
|
||||
error = dlerror();
|
||||
if (error != nullptr || handle == nullptr) {
|
||||
throw std::runtime_error("dlopen " + std::string(file) + " error, " + std::string(error));
|
||||
}
|
||||
}
|
||||
|
||||
void library_engine::close() {
|
||||
if (handle) {
|
||||
dlclose(handle);
|
||||
}
|
||||
handle = nullptr;
|
||||
error = nullptr;
|
||||
}
|
||||
|
||||
void* library_engine::get_func(const char* name) {
|
||||
auto func = dlsym(handle, name);
|
||||
error = dlerror();
|
||||
if (error != nullptr || func == nullptr) {
|
||||
throw std::runtime_error("dlsym " + std::string(name) + " error, " + std::string(error));
|
||||
return nullptr;
|
||||
} else {
|
||||
return func;
|
||||
}
|
||||
}
|
||||
|
||||
void* library_engine::get_handle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
json_engine::json_engine() : handle(nullptr) {};
|
||||
|
||||
json_engine::json_engine(const char* file) : handle(nullptr){
|
||||
this->open(file);
|
||||
}
|
||||
|
||||
json_engine::~json_engine() {
|
||||
this->close();
|
||||
}
|
||||
|
||||
bool json_engine::open(const char* file) {
|
||||
if (!file) {
|
||||
grpc_printf("wrong json file path\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
this->close();
|
||||
|
||||
auto file_ptr = fopen(file, "r");
|
||||
fseek(file_ptr, 0, SEEK_END);
|
||||
auto length = ftell(file_ptr);
|
||||
fseek(file_ptr, 0, SEEK_SET);
|
||||
auto buffer = malloc(length);
|
||||
fread(buffer, 1, length, file_ptr);
|
||||
fclose(file_ptr);
|
||||
|
||||
this->handle = cJSON_Parse((const char *)buffer);
|
||||
|
||||
check_free(buffer);
|
||||
|
||||
if (this->handle) {
|
||||
return true;
|
||||
} else {
|
||||
grpc_printf("cjson open %s error: %s", file, cJSON_GetErrorPtr());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void json_engine::close() {
|
||||
if (this->handle) {
|
||||
cJSON_Delete(this->handle);
|
||||
this->handle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
cJSON* json_engine::get_handle() {
|
||||
return this->handle;
|
||||
}
|
||||
|
||||
cJSON* json_engine::get_item(cJSON* obj, const char* item) {
|
||||
return cJSON_GetObjectItem(obj, item);
|
||||
};
|
||||
|
||||
char* json_engine::print_item(cJSON* obj) {
|
||||
return cJSON_Print(obj);
|
||||
};
|
||||
|
||||
bool json_engine::compare_item(cJSON* obj, const char* item) {
|
||||
auto obj_item = this->print_item(obj);
|
||||
return strncmp(obj_item+1, item, std::min(strlen(item), strlen(obj_item)-2)) == 0;
|
||||
};
|
||||
|
||||
} // namespace sgx
|
||||
} // namespace grpc
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2022 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SGX_RA_TLS_UTILS_H
|
||||
#define SGX_RA_TLS_UTILS_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define grpc_printf printf
|
||||
#define grpc_fprintf fprintf
|
||||
|
||||
#include <grpcpp/security/sgx/sgx_ra_tls.h>
|
||||
|
||||
namespace grpc {
|
||||
namespace sgx {
|
||||
|
||||
|
||||
class library_engine {
|
||||
public:
|
||||
library_engine();
|
||||
|
||||
library_engine(const char*, int);
|
||||
|
||||
~library_engine();
|
||||
|
||||
void open(const char*, int);
|
||||
|
||||
void close();
|
||||
|
||||
void* get_func(const char*);
|
||||
|
||||
void* get_handle();
|
||||
|
||||
private:
|
||||
void* handle;
|
||||
char* error;
|
||||
};
|
||||
|
||||
void check_free(void* ptr);
|
||||
|
||||
bool hex_to_byte(const char* src, char* dst, size_t dst_size);
|
||||
|
||||
void byte_to_hex(const char* src, char* dst, size_t src_size);
|
||||
|
||||
std::string byte_to_hex(const char* src, size_t src_size);
|
||||
|
||||
} // namespace sgx
|
||||
} // namespace grpc
|
||||
|
||||
#endif // SGX_RA_TLS_UTILS_H
|
Loading…
Reference in New Issue
Block a user