提交 5473b855 编写于 作者: Y YiLin.Li 提交者: jia zhang

stub_enclave: Add ra and tls librarys from sgx-ra-tls.

Choose wolfSSL as sgx-ra-tls librarys.
Signed-off-by: NYilin Li <YiLin.Li@linux.alibaba.com>
Signed-off-by: jia zhang's avatarJia Zhang <zhang.jia@linux.alibaba.com>
上级 5710157d
#ifndef _RA_ATTESTER_H_
#define _RA_ATTESTER_H_
#include <sgx_quote.h>
struct ra_tls_options {
sgx_spid_t spid;
sgx_quote_sign_type_t quote_type;
/* NULL-terminated string of domain name/IP, port and path prefix,
e.g., api.trustedservices.intel.com/sgx/dev for development and
api.trustedservices.intel.com/sgx for production. */
const char ias_server[512];
const char subscription_key[32];
};
struct ecdsa_ra_tls_options {
char subscription_key[32];
};
void create_key_and_x509_pem
(
uint8_t* pem_key,
int* pem_key_len,
uint8_t* pem_cert,
int* pem_cert_len,
const struct ra_tls_options* opts
);
#ifdef RATLS_ECDSA
void ecdsa_create_key_and_x509
(
uint8_t* der_key,
int* der_key_len,
uint8_t* der_cert,
int* der_cert_len,
const struct ecdsa_ra_tls_options* opts
);
#endif
void ra_tls_create_report(
sgx_report_t* report
);
#endif
#ifndef __RA_ATTESTER_PRIVATE_H__
#define __RA_ATTESTER_PRIVATE_H__
void create_report
(
sgx_target_info_t* target_info,
const sgx_report_data_t* report_data,
sgx_report_t* report
);
#endif
/**
* Code common to all challenger implementations (i.e., independent of
* the TLS library).
*/
#define _GNU_SOURCE
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sgx_quote.h>
#include "ra.h"
#include "ra_private.h"
#if SGX_SDK
/* SGX SDK does not have this. */
void *memmem(const void *h0, size_t k, const void *n0, size_t l);
#endif
#include "ra-challenger_private.h"
#include "ra-challenger.h"
void get_quote_from_extension
(
uint8_t* exts,
size_t exts_len,
sgx_quote_t* q
)
{
uint8_t report[2048];
uint32_t report_len;
int rc = extract_x509_extension(exts, exts_len,
ias_response_body_oid, ias_oid_len,
report, &report_len, sizeof(report));
if (rc == 1) {
get_quote_from_report(report, report_len, q);
return;
}
rc = extract_x509_extension(exts, exts_len,
quote_oid, ias_oid_len,
report, &report_len, sizeof(report));
assert(rc == 1);
memcpy(q, report, sizeof(*q));
}
/**
* @return Returns -1 if OID not found. Otherwise, returns 1;
*/
int find_oid
(
const unsigned char* ext, size_t ext_len,
const unsigned char* oid, size_t oid_len,
unsigned char** val, size_t* len
)
{
uint8_t* p = memmem(ext, ext_len, oid, oid_len);
if (p == NULL) {
return -1;
}
p += oid_len;
int i = 0;
// Some TLS libraries generate a BOOLEAN for the criticality of the extension.
if (p[i] == 0x01) {
assert(p[i++] == 0x01); // tag, 0x01 is ASN1 Boolean
assert(p[i++] == 0x01); // length
assert(p[i++] == 0x00); // value (0 is non-critical, non-zero is critical)
}
// Now comes the octet string
assert(p[i++] == 0x04); // tag for octet string
assert(p[i++] == 0x82); // length encoded in two bytes
*len = p[i++] << 8;
*len += p[i++];
*val = &p[i++];
return 1;
}
/**
* @return Returns -1 if OID was not found. Otherwise, returns 1;
*/
int extract_x509_extension
(
uint8_t* ext,
int ext_len,
const uint8_t* oid,
size_t oid_len,
uint8_t* data,
uint32_t* data_len,
uint32_t data_max_len
)
{
uint8_t* ext_data;
size_t ext_data_len;
int rc = find_oid(ext, ext_len, oid, oid_len, &ext_data, &ext_data_len);
if (rc == -1) return -1;
assert(ext_data != NULL);
assert(ext_data_len <= data_max_len);
memcpy(data, ext_data, ext_data_len);
*data_len = ext_data_len;
return 1;
}
/**
* Extract all extensions.
*/
void extract_x509_extensions
(
uint8_t* ext,
int ext_len,
attestation_verification_report_t* attn_report
)
{
extract_x509_extension(ext, ext_len,
ias_response_body_oid, ias_oid_len,
attn_report->ias_report,
&attn_report->ias_report_len,
sizeof(attn_report->ias_report));
extract_x509_extension(ext, ext_len,
ias_root_cert_oid, ias_oid_len,
attn_report->ias_sign_ca_cert,
&attn_report->ias_sign_ca_cert_len,
sizeof(attn_report->ias_sign_ca_cert));
extract_x509_extension(ext, ext_len,
ias_leaf_cert_oid, ias_oid_len,
attn_report->ias_sign_cert,
&attn_report->ias_sign_cert_len,
sizeof(attn_report->ias_sign_cert));
extract_x509_extension(ext, ext_len,
ias_report_signature_oid, ias_oid_len,
attn_report->ias_report_signature,
&attn_report->ias_report_signature_len,
sizeof(attn_report->ias_report_signature));
}
/**
* Extract ECDSA related extensions from X509.
*/
void ecdsa_extract_x509_extensions
(
uint8_t* ext,
int ext_len,
ecdsa_attestation_evidence_t* evidence
)
{
extract_x509_extension(ext, ext_len, quote_oid, ias_oid_len,
evidence->quote, &evidence->quote_len,
sizeof(evidence->quote));
extract_x509_extension(ext, ext_len, pck_crt_oid, ias_oid_len,
evidence->pck_crt, &evidence->pck_crt_len,
sizeof(evidence->pck_crt));
extract_x509_extension(ext, ext_len, pck_sign_chain_oid, ias_oid_len,
evidence->pck_sign_chain, &evidence->pck_sign_chain_len,
sizeof(evidence->pck_sign_chain));
extract_x509_extension(ext, ext_len, tcb_info_oid, ias_oid_len,
evidence->tcb_info, &evidence->tcb_info_len,
sizeof(evidence->tcb_info));
extract_x509_extension(ext, ext_len, tcb_sign_chain_oid, ias_oid_len,
evidence->tcb_sign_chain, &evidence->tcb_sign_chain_len,
sizeof(evidence->tcb_sign_chain));
extract_x509_extension(ext, ext_len, qe_identity_oid, ias_oid_len,
evidence->qe_identity, &evidence->qe_identity_len,
sizeof(evidence->qe_identity));
extract_x509_extension(ext, ext_len, root_ca_crl_oid, ias_oid_len,
evidence->root_ca_crl, &evidence->root_ca_crl_len,
sizeof(evidence->root_ca_crl));
extract_x509_extension(ext, ext_len, pck_crl_oid, ias_oid_len,
evidence->pck_crl, &evidence->pck_crl_len,
sizeof(evidence->pck_crl));
}
/**
* @return 1 if it is an EPID-based attestation RA-TLS
* certificate. Otherwise, 0.
*/
int is_epid_ratls_cert
(
const uint8_t* der_crt,
uint32_t der_crt_len
)
{
uint8_t* ext_data;
size_t ext_data_len;
int rc;
rc = find_oid(der_crt, der_crt_len,
ias_response_body_oid, ias_oid_len,
&ext_data, &ext_data_len);
if (1 == rc) return 1;
rc = find_oid(der_crt, der_crt_len,
quote_oid, ias_oid_len,
&ext_data, &ext_data_len);
if (1 == rc) return 0;
/* Something is fishy. Neither EPID nor ECDSA RA-TLC cert?! */
assert(0);
// Avoid compiler error: control reaches end of non-void function
// [-Werror=return-type]
return -1;
}
/**
* Pretty-print information of EPID-based RA-TLS certificate to file descriptor.
*/
static
void dprintf_epid_ratls_cert
(
int fd,
uint8_t* der_crt,
uint32_t der_crt_len
)
{
attestation_verification_report_t report;
extract_x509_extensions(der_crt, der_crt_len, &report);
dprintf(fd, "\nIntel Attestation Service Report\n");
dprintf(fd, "%.*s\n", report.ias_report_len, report.ias_report);
}
/**
* Pretty-print information of ECDSA-based RA-TLS certificate to file descriptor.
*/
static
void dprintf_ecdsa_ratls_cert
(
int fd,
uint8_t* der_crt,
uint32_t der_crt_len
)
{
ecdsa_attestation_evidence_t evidence;
ecdsa_extract_x509_extensions(der_crt, der_crt_len, &evidence);
dprintf(fd, "\nTCB info: ");
dprintf(fd, "%.*s\n", evidence.tcb_info_len, evidence.tcb_info);
dprintf(fd, "\nPCK Certificate:\n");
dprintf(fd, "%.*s\n", evidence.pck_crt_len, evidence.pck_crt);
}
void dprintf_ratls_cert
(
int fd,
uint8_t* der_crt,
uint32_t der_crt_len
)
{
if (is_epid_ratls_cert(der_crt, der_crt_len)) {
dprintf_epid_ratls_cert(fd, der_crt, der_crt_len);
} else {
dprintf_ecdsa_ratls_cert(fd, der_crt, der_crt_len);
}
sgx_quote_t quote;
get_quote_from_cert(der_crt, der_crt_len, &quote);
sgx_report_body_t* body = &quote.report_body;
dprintf(fd, "MRENCLAVE = ");
for (int i=0; i < SGX_HASH_SIZE; ++i) dprintf(fd, "%02x", body->mr_enclave.m[i]);
dprintf(fd, "\n");
dprintf(fd, "MRSIGNER = ");
for (int i=0; i < SGX_HASH_SIZE; ++i) dprintf(fd, "%02x", body->mr_signer.m[i]);
dprintf(fd, "\n");
}
#ifndef _RA_CHALLENGER_H_
#define _RA_CHALLENGER_H_
#include <sgx_quote.h>
/**
* Extract an Intel SGX quote from an Intel Attestation Service (IAS) report.
*/
void get_quote_from_report
(
const uint8_t* report /* in */,
const int report_len /* in */,
sgx_quote_t* quote
);
/**
* Extract an Intel SGX quote from a DER-encoded X.509 certificate.
*/
void get_quote_from_cert
(
const uint8_t* der_crt,
uint32_t der_crt_len,
sgx_quote_t* q
);
/**
* Verify SGX-related X.509 extensions.
* @return 0 if verification succeeds, 1 otherwise.
*/
int verify_sgx_cert_extensions
(
uint8_t* der_crt,
uint32_t der_crt_len
);
/**
* Pretty-print information of RA-TLS certificate to file descriptor.
*/
void dprintf_ratls_cert
(
int fd,
uint8_t* der_crt,
uint32_t der_crt_len
);
#endif
#include <stdint.h>
#include <stddef.h>
#include <sgx_quote.h>
extern const uint8_t ias_response_body_oid[];
extern const uint8_t ias_root_cert_oid[];
extern const uint8_t ias_leaf_cert_oid[];
extern const uint8_t ias_report_signature_oid[];
extern const uint8_t quote_oid[];
extern const uint8_t pck_crt_oid[];
extern const uint8_t pck_sign_chain_oid[];
extern const uint8_t tcb_info_oid[];
extern const uint8_t tcb_sign_chain_oid[];
extern const size_t ias_oid_len;
void get_quote_from_extension
(
uint8_t* ext,
size_t ext_len,
sgx_quote_t* q
);
int find_oid
(
const unsigned char* ext, size_t ext_len,
const unsigned char* oid, size_t oid_len,
unsigned char** val, size_t* len
);
void extract_x509_extensions
(
uint8_t* ext,
int ext_len,
attestation_verification_report_t* attn_report
);
int extract_x509_extension
(
uint8_t* ext,
int ext_len,
const uint8_t* oid,
size_t oid_len,
uint8_t* data,
uint32_t* data_len,
uint32_t data_max_len
);
void ecdsa_extract_x509_extensions
(
uint8_t* ext,
int ext_len,
ecdsa_attestation_evidence_t* evidence
);
/**
* @return 1 if it is an EPID-based attestation RA-TLS
* certificate. Otherwise, 0.
*/
int is_epid_ratls_cert
(
const uint8_t* der_crt,
uint32_t der_crt_len
);
/* Definitions common to attester and verifier. */
#include <stdint.h>
#include <stdlib.h>
#define OID(N) {0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF8, 0x4D, 0x8A, 0x39, (N)}
const uint8_t ias_response_body_oid[] = OID(0x02);
const uint8_t ias_root_cert_oid[] = OID(0x03);
const uint8_t ias_leaf_cert_oid[] = OID(0x04);
const uint8_t ias_report_signature_oid[] = OID(0x05);
const uint8_t quote_oid[] = OID(0x06);
const uint8_t pck_crt_oid[] = OID(0x07);
const uint8_t pck_sign_chain_oid[] = OID(0x08);
const uint8_t tcb_info_oid[] = OID(0x09);
const uint8_t tcb_sign_chain_oid[] = OID(0x0a);
const uint8_t qe_identity_oid[] = OID(0x0b);
const uint8_t root_ca_crl_oid[] = OID(0x0c);
const uint8_t pck_crl_oid[] = OID(0x0d);
const size_t ias_oid_len = sizeof(ias_response_body_oid);
#ifndef _RA_H_
#define _RA_H_
typedef struct {
uint8_t ias_report[2*1024];
uint32_t ias_report_len;
uint8_t ias_sign_ca_cert[2*1024];
uint32_t ias_sign_ca_cert_len;
uint8_t ias_sign_cert[2*1024];
uint32_t ias_sign_cert_len;
uint8_t ias_report_signature[2*1024];
uint32_t ias_report_signature_len;
} attestation_verification_report_t;
static const int rsa_3072_der_len = 1766;
static const int rsa_pub_3072_pcks_der_len = 422;
static const int rsa_pub_3072_pcks_header_len = 24;
static const int rsa_pub_3072_raw_der_len = 398; /* rsa_pub_3072_pcks_der_len - pcks_nr_1_header_len */
typedef struct {
uint8_t quote[2048];
uint32_t quote_len;
/* Certificiate in PEM format. */
uint8_t pck_crt[2048];
uint32_t pck_crt_len;
/* Certificate chain in PEM format. */
uint8_t pck_sign_chain[4096];
uint32_t pck_sign_chain_len;
/* JSON data as published by
https://api.portal.trustedservices.intel.com/documentation#pcs-tcb-info */
uint8_t tcb_info[4096];
uint32_t tcb_info_len;
/* Certificate chain in PEM format. */
uint8_t tcb_sign_chain[4096];
uint32_t tcb_sign_chain_len;
/* JSON data, e.g., as obtained from
https://api.portal.trustedservices.intel.com/documentation#pcs-qe-identity */
uint8_t qe_identity[1024];
uint32_t qe_identity_len;
/* PEM-encoded CRL as published by
https://certificates.trustedservices.intel.com/IntelSGXRootCA.crl */
uint8_t root_ca_crl[1024];
uint32_t root_ca_crl_len;
/* PEM-encoded certificate revocation list as published by
https://api.portal.trustedservices.intel.com/documentation#pcs-revocation */
uint8_t pck_crl[1024];
uint32_t pck_crl_len;
} ecdsa_attestation_evidence_t;
#endif
/* Interface to do remote attestation against Intel Attestation
Service. Two implementations exist: (1) sgxsdk-ra-attester_* to be
used with the SGX SDK. (2) nonsdk-ra-attester.c to be used with
Graphene-SGX. */
#ifndef _RA_PRIVATE_H
#define _RA_PRIVATE_H
struct ra_tls_options;
void do_remote_attestation(sgx_report_data_t* report_data,
const struct ra_tls_options* opts,
attestation_verification_report_t* r);
extern const uint8_t ias_response_body_oid[];
extern const uint8_t ias_root_cert_oid[];
extern const uint8_t ias_leaf_cert_oid[];
extern const uint8_t ias_report_signature_oid[];
extern const uint8_t quote_oid[];
extern const uint8_t pck_crt_oid[];
extern const uint8_t pck_sign_chain_oid[];
extern const uint8_t tcb_info_oid[];
extern const uint8_t tcb_sign_chain_oid[];
extern const uint8_t qe_identity_oid[];
extern const uint8_t root_ca_crl_oid[];
extern const uint8_t pck_crl_oid[];
extern const size_t ias_oid_len;
#endif
enclave {
include "ra.h"
include "ra-attester.h"
include "sgx_report.h"
trusted {
public void dummy(void);
};
untrusted {
/* define OCALLs here. */
void ocall_sgx_init_quote([out] sgx_target_info_t* target_info);
void ocall_remote_attestation([in] sgx_report_t* report,
[in] const struct ra_tls_options* opts,
[out] attestation_verification_report_t* attn_report
);
};
};
#!/bin/bash
# set -x
if [[ -z "$ECDSA_SUBSCRIPTION_KEY" ]] && ( [[ -z "$SPID" ]] || [[ -z "$EPID_SUBSCRIPTION_KEY" ]] ); then
echo "//Either SPID and EPID_SUBSCRIPTION_KEY or ECDSA_SUBSCRIPTION_KEY is required!"
fi
if ( [[ ! -z "$SPID" ]] && [[ -z "$EPID_SUBSCRIPTION_KEY" ]] ) || \
( [[ -z "$SPID" ]] && [[ ! -z "$EPID_SUBSCRIPTION_KEY" ]] ); then
echo "//For EPID, Both SPID and EPID_SUBSCRIPTION_KEY must be set!"
fi
if ( [[ "$QUOTE_TYPE" != "SGX_LINKABLE_SIGNATURE" ]] ) && \
( [[ "$QUOTE_TYPE" != "SGX_UNLINKABLE_SIGNATURE" ]] ); then
echo "//QUOTE_TYPE must be one of SGX_UNLINKABLE_SIGNATURE or SGX_LINKABLE_SIGNATURE"
fi
SPID_BYTE_ARRAY=$(echo $SPID | python -c 'import sys ; s = sys.stdin.readline().strip(); print("".join(["0x"+s[2*i:2*i+2]+"," for i in range(len(s)/2)]))')
cat <<HEREDOC
#include "ra-attester.h"
struct ra_tls_options my_ra_tls_options = {
// SPID format is 32 hex-character string, e.g., 0123456789abcdef0123456789abcdef
.spid = {{$SPID_BYTE_ARRAY}},
.quote_type = SGX_UNLINKABLE_SIGNATURE,
.ias_server = "api.trustedservices.intel.com/sgx/dev",
// EPID_SUBSCRIPTION_KEY format is "012345679abcdef012345679abcdef"
.subscription_key = "$EPID_SUBSCRIPTION_KEY"
};
struct ecdsa_ra_tls_options my_ecdsa_ra_tls_options = {
// ECDSA_SUBSCRIPTION_KEY format is "012345679abcdef012345679abcdef"
.subscription_key = "$ECDSA_SUBSCRIPTION_KEY"
};
HEREDOC
# Makefile to build the wolfSSL-based remote attestation TLS library.
######## Intel(R) SGX SDK Settings ########
SGX_SDK ?= /opt/intel/sgxsdk
SGX_MODE ?= HW
SGX_ARCH ?= x64
PROJECT_ROOT ?= $(shell readlink -f .)
WOLFSSL_ROOT := $(shell readlink -f deps/wolfssl)
SGX_COMMON_CFLAGS := -m64
SGX_LIBRARY_PATH := $(SGX_SDK)/lib64
SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign
SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r
ifeq ($(SGX_DEBUG), 1)
ifeq ($(SGX_PRERELEASE), 1)
$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!)
endif
endif
ifeq ($(SGX_DEBUG), 1)
SGX_COMMON_CFLAGS += -O0 -g
else
SGX_COMMON_CFLAGS += -O2
endif
ifneq ($(SGX_MODE), HW)
Trts_Library_Name := sgx_trts_sim
Service_Library_Name := sgx_tservice_sim
else
Trts_Library_Name := sgx_trts
Service_Library_Name := sgx_tservice
endif
Library_Name := sgx_ra_tls_wolfssl
# -DFP_MAX_BITS=8192 required for RSA keys > 2048 bits to work
Wolfssl_C_Extra_Flags := -DSGX_SDK -DWOLFSSL_SGX -DWOLFSSL_SGX_ATTESTATION -DUSER_TIME -DWOLFSSL_CERT_EXT -DFP_MAX_BITS=8192
Wolfssl_C_Files := $(PROJECT_ROOT)/wolfssl-ra-attester.c \
$(PROJECT_ROOT)/wolfssl-ra-challenger.c \
$(PROJECT_ROOT)/sgxsdk-ra-attester_t.c \
$(PROJECT_ROOT)/ra-challenger.c \
$(PROJECT_ROOT)/wolfssl-ra.c \
$(PROJECT_ROOT)/ra_tls_t.c \
$(PROJECT_ROOT)/ra_tls_options.c
Wolfssl_Include_Paths := -I$(WOLFSSL_ROOT)/ \
-I$(WOLFSSL_ROOT)/wolfcrypt/ \
-I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc \
-I$(SGX_SDK)/include/stlport \
-I/usr/include/linux
Compiler_Warnings := -Wall -Wextra -Wwrite-strings -Wlogical-op -Wshadow
Flags_Just_For_C := -Wno-implicit-function-declaration -std=c11
Common_C_Cpp_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $(Wolfssl_Include_Paths) -fno-builtin-printf -I.
Wolfssl_C_Flags := $(Compiler_Warnings) $(Flags_Just_For_C) $(Common_C_Cpp_Flags) $(Wolfssl_C_Extra_Flags)
Wolfssl_C_Objects := $(Wolfssl_C_Files:.c=.o)
override CFLAGS += $(Wolfssl_C_Flags)
.PHONY: all run clean mrproper
all: libsgx_ra_tls_wolfssl.a
######## Library Objects ########
ra_tls_t.c ra_tls_u.c ra_tls_t.h ra_tls_u.h : ra_tls.edl
$(SGX_EDGER8R) $^ --search-path $(SGX_SDK)/include
libsgx_ra_tls_wolfssl.a: ra_tls_t.o ra_tls_u.o $(Wolfssl_C_Objects)
ar rcs $@ $(Wolfssl_C_Objects)
@echo "LINK => $@"
clean:
@rm -f $(Wolfssl_C_Objects)
@rm -f ra_tls_t.c ra_tls_t.h ra_tls_u.h ra_tls_u.c libsgx_ra_tls_wolfssl.a
mrproper: clean
@rm -f ra_tls_t.c ra_tls_t.h ra_tls_u.h ra_tls_u.c libsgx_ra_tls_wolfssl.a
#include <assert.h>
#include <string.h>
#include <sgx_uae_service.h>
#include "ra.h"
#include "ra-attester.h"
#include "ra_private.h"
#include "ra_tls_t.h" // OCALLs
/* Trusted portion (called from within the enclave) to do remote
attestation with the SGX SDK. */
void do_remote_attestation
(
sgx_report_data_t* report_data,
const struct ra_tls_options* opts,
attestation_verification_report_t* attn_report
)
{
sgx_target_info_t target_info = {0, };
ocall_sgx_init_quote(&target_info);
sgx_report_t report = {0, };
sgx_status_t status = sgx_create_report(&target_info, report_data, &report);
assert(status == SGX_SUCCESS);
ocall_remote_attestation(&report, opts, attn_report);
}
void ra_tls_create_report(
sgx_report_t* report
)
{
sgx_target_info_t target_info = {0, };
sgx_report_data_t report_data = {0, };
memset(report, 0, sizeof(*report));
sgx_create_report(&target_info, &report_data, report);
}
/* Code to create an RA-TLS certificate with wolfSSL. */
#define _GNU_SOURCE // for memmem()
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sgx_uae_service.h>
#ifdef RATLS_ECDSA
#include <curl/curl.h>
#include <sgx_quote_3.h>
#endif
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#include <wolfssl/wolfcrypt/coding.h>
#include <wolfssl/wolfcrypt/rsa.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include "ra.h"
#include "wolfssl-ra.h"
#include "ra-attester.h"
#include "ra-attester_private.h"
#ifdef RATLS_ECDSA
#include "ecdsa-ra-attester.h"
#include "ecdsa-sample-data/real/sample_data.h"
#include "ecdsa-attestation-collateral.h"
#include "curl_helper.h"
static const int FMSPC_SIZE_BYTES = 6;
#endif
#include "ra_private.h"
/**
* Caller must allocate memory for certificate.
*
* @param der_crt_len On entry contains the size of der_crt buffer. On return holds actual size of certificate in bytes.
*/
static
void generate_x509
(
RsaKey* key,
uint8_t* der_crt, /* out */
int* der_crt_len, /* in/out */
const attestation_verification_report_t* attn_report
)
{
Cert crt;
wc_InitCert(&crt);
strncpy(crt.subject.country, "US", CTC_NAME_SIZE);
strncpy(crt.subject.state, "OR", CTC_NAME_SIZE);
strncpy(crt.subject.locality, "Hillsboro", CTC_NAME_SIZE);
strncpy(crt.subject.org, "Intel Inc.", CTC_NAME_SIZE);
strncpy(crt.subject.unit, "Intel Labs", CTC_NAME_SIZE);
strncpy(crt.subject.commonName, "SGX rocks!", CTC_NAME_SIZE);
strncpy(crt.subject.email, "webmaster@intel.com", CTC_NAME_SIZE);
memcpy(crt.iasAttestationReport, attn_report->ias_report,
attn_report->ias_report_len);
crt.iasAttestationReportSz = attn_report->ias_report_len;
memcpy(crt.iasSigCACert, attn_report->ias_sign_ca_cert,
attn_report->ias_sign_ca_cert_len);
crt.iasSigCACertSz = attn_report->ias_sign_ca_cert_len;
memcpy(crt.iasSigCert, attn_report->ias_sign_cert,
attn_report->ias_sign_cert_len);
crt.iasSigCertSz = attn_report->ias_sign_cert_len;
memcpy(crt.iasSig, attn_report->ias_report_signature,
attn_report->ias_report_signature_len);
crt.iasSigSz = attn_report->ias_report_signature_len;
RNG rng;
wc_InitRng(&rng);
int certSz = wc_MakeSelfCert(&crt, der_crt, *der_crt_len, key, &rng);
assert(certSz > 0);
*der_crt_len = certSz;
}
#ifdef RATLS_ECDSA
/**
* Generate RA-TLS certificate containing ECDSA-based attestation evidence.
*
* @param der_crt Caller must allocate memory for certificate.
* @param der_crt_len On entry contains the size of der_crt buffer. On return holds actual size of certificate in bytes.
*/
static
void ecdsa_generate_x509
(
RsaKey* key,
uint8_t* der_crt, /* out */
int* der_crt_len, /* in/out */
const ecdsa_attestation_evidence_t* evidence
)
{
Cert crt;
wc_InitCert(&crt);
strncpy(crt.subject.country, "US", CTC_NAME_SIZE);
strncpy(crt.subject.state, "OR", CTC_NAME_SIZE);
strncpy(crt.subject.locality, "Hillsboro", CTC_NAME_SIZE);
strncpy(crt.subject.org, "Intel Inc.", CTC_NAME_SIZE);
strncpy(crt.subject.unit, "Intel Labs", CTC_NAME_SIZE);
strncpy(crt.subject.commonName, "SGX rocks!", CTC_NAME_SIZE);
strncpy(crt.subject.email, "webmaster@intel.com", CTC_NAME_SIZE);
memcpy(crt.quote, evidence->quote, evidence->quote_len);
crt.quoteSz = evidence->quote_len;
memcpy(crt.pckCrt, evidence->pck_crt, evidence->pck_crt_len);
crt.pckCrtSz = evidence->pck_crt_len;
memcpy(crt.pckSignChain, evidence->pck_sign_chain,
evidence->pck_sign_chain_len);
crt.pckSignChainSz = evidence->pck_sign_chain_len;
memcpy(crt.tcbInfo, evidence->tcb_info,
evidence->tcb_info_len);
crt.tcbInfoSz = evidence->tcb_info_len;
memcpy(crt.tcbSignChain, evidence->tcb_sign_chain,
evidence->tcb_sign_chain_len);
crt.tcbSignChainSz = evidence->tcb_sign_chain_len;
memcpy(crt.qeIdentity, evidence->qe_identity,
evidence->qe_identity_len);
crt.qeIdentitySz = evidence->qe_identity_len;
memcpy(crt.rootCaCrl, evidence->root_ca_crl,
evidence->root_ca_crl_len);
crt.rootCaCrlSz = evidence->root_ca_crl_len;
memcpy(crt.pckCrl, evidence->pck_crl,
evidence->pck_crl_len);
crt.pckCrlSz = evidence->pck_crl_len;
RNG rng;
wc_InitRng(&rng);
int certSz = wc_MakeSelfCert(&crt, der_crt, *der_crt_len, key, &rng);
assert(certSz > 0);
*der_crt_len = certSz;
}
#endif
static void
wolfssl_create_key_and_x509
(
uint8_t* der_key,
int* der_key_len,
uint8_t* der_cert,
int* der_cert_len,
const struct ra_tls_options* opts
)
{
/* Generate key. */
RsaKey genKey;
RNG rng;
int ret;
wc_InitRng(&rng);
wc_InitRsaKey(&genKey, 0);
ret = wc_MakeRsaKey(&genKey, 3072, 65537, &rng);
assert(ret == 0);
uint8_t der[4096];
int derSz = wc_RsaKeyToDer(&genKey, der, sizeof(der));
assert(derSz >= 0);
assert(derSz <= (int) *der_key_len);
*der_key_len = derSz;
memcpy(der_key, der, derSz);
/* Generate certificate */
sgx_report_data_t report_data = {0, };
sha256_rsa_pubkey(report_data.d, &genKey);
attestation_verification_report_t attestation_report;
do_remote_attestation(&report_data, opts, &attestation_report);
// generate_x509(&genKey, der_cert, der_cert_len,
// &attestation_report);
}
#ifdef RATLS_ECDSA
static void binary_to_base16
(
const uint8_t* binary,
uint32_t binary_len,
char* base16,
uint32_t base16_len
)
{
/* + 1 for terminating null byte. */
assert(base16_len >= binary_len * 2 + 1);
for (uint32_t i = 0; i < binary_len; ++i) {
sprintf(&base16[i * 2], "%02X", binary[i]);
}
}
static
void ecdsa_get_quote_from_quote_service
(
const sgx_report_data_t* report_data,
uint8_t* quote,
uint32_t* quote_len
)
{
#ifndef SGX_SIMULATION
uint32_t quote_size = 0;
sgx_target_info_t qe_target_info = {0, };
int sockfd = connect_to_quote_service();
get_target_info_from_quote_service(sockfd, &qe_target_info, &quote_size);
assert(quote_size <= *quote_len);
sgx_report_t report;
create_report(&qe_target_info, report_data, &report);
get_quote_from_quote_service(sockfd, &report, quote, quote_size);
*quote_len = quote_size;
close(sockfd);
#else
(void) report_data;
assert(ecdsa_sample_data_quote_ppid_rsa3072_dat_len <= *quote_len);
memcpy(quote, ecdsa_sample_data_quote_ppid_rsa3072_dat, ecdsa_sample_data_quote_ppid_rsa3072_dat_len);
*quote_len = ecdsa_sample_data_quote_ppid_rsa3072_dat_len;
#endif
}
/* static void print_byte_array(FILE* f, uint8_t* data, int size) { */
/* for (int i = 0; i < size; ++i) { */
/* fprintf(f, "%02X", data[i]); */
/* } */
/* } */
/**
* Pulls PCK certificate's signing chain information out of HTTP
* response header. Also url-decodes it.
*/
static
void parse_response_header_get_pck_cert
(
CURL* curl,
const char* headers,
size_t headers_len,
char* pck_cert_chain,
uint32_t* pck_cert_chain_len
)
{
const char header_tag[] = "SGX-PCK-Certificate-Issuer-Chain: ";
char* header_begin = memmem((const char*) headers,
headers_len,
header_tag,
strlen(header_tag));
if (header_begin == NULL) {
fprintf(stderr, "HTTP headers: %.*s\n", (int) headers_len, headers);
}
assert(header_begin != NULL);
header_begin += strlen(header_tag);
char* header_end = memmem(header_begin,
headers_len - (header_begin - headers),
"\r\n",
strlen("\r\n"));
assert(header_end);
int unescaped_len;
char* unescaped = curl_easy_unescape(curl, header_begin, header_end - header_begin, &unescaped_len);
assert(unescaped);
assert(unescaped_len <= (int) *pck_cert_chain_len);
memcpy(pck_cert_chain, unescaped, unescaped_len);
*pck_cert_chain_len = unescaped_len;
curl_free(unescaped);
}
/**
* Today, this grabs the PCK certificate from Intel's backend service
* and stores it in evidence.pck_crt.
*
* Tomorrow, this may grab the PCK certificate from somewhere else,
* e.g., some local PCK certificate caching service.
*/
static
void obtain_pck_cert
(
ecdsa_attestation_evidence_t* evidence,
const struct ecdsa_ra_tls_options* opts,
sgx_ql_ppid_rsa3072_encrypted_cert_info_t* cert_data
)
{
char encrypted_ppid[786 + 1];
binary_to_base16(cert_data->enc_ppid, sizeof(cert_data->enc_ppid),
encrypted_ppid, sizeof(encrypted_ppid));
char pceid[4 + 1];
binary_to_base16((uint8_t*)&cert_data->pce_info.pce_id,
sizeof(cert_data->pce_info.pce_id),
pceid, sizeof(pceid));
char pcesvn[4 + 1];
binary_to_base16((uint8_t*)&cert_data->pce_info.pce_isv_svn,
sizeof(cert_data->pce_info.pce_isv_svn),
pcesvn, sizeof(pcesvn));
char cpusvn[32 + 1];
binary_to_base16((uint8_t*)&cert_data->cpu_svn,
sizeof(cert_data->cpu_svn),
cpusvn, sizeof(cpusvn));
#ifdef DEBUG
printf("%s:%s: PPID=%s\nPCE ID= %s\nPCE SVN= %s\nCPU SVN= %s\n",
__FILE__, __FUNCTION__, encrypted_ppid, pceid, pcesvn, cpusvn);
#endif
char url[2048];
const char base_url[] = "https://api.trustedservices.intel.com/sgx/certification/v1/pckcert";
snprintf(url, sizeof(url), "%s?encrypted_ppid=%s&cpusvn=%s&pcesvn=%s&pceid=%s",
base_url, encrypted_ppid, cpusvn, pcesvn, pceid);
/* printf("URL= %s\n", url); */
/* printf("subscription_key= %.32s\n", opts->subscription_key); */
CURL* curl = curl_easy_init();
assert(curl != NULL);
struct buffer_and_size header = {(char*) malloc(1), 0};
struct buffer_and_size body = {(char*) malloc(1), 0};
char buf[128];
int rc = snprintf(buf, sizeof(buf), "Ocp-Apim-Subscription-Key: %.32s",
opts->subscription_key);
assert(rc < (int) sizeof(buf));
struct curl_slist* request_headers = NULL;
request_headers = curl_slist_append(request_headers, buf);
http_get(curl, url, &header, &body, request_headers, NULL);
evidence->pck_sign_chain_len = sizeof(evidence->pck_sign_chain);
parse_response_header_get_pck_cert(curl, header.data, header.len,
(char*) evidence->pck_sign_chain,
&evidence->pck_sign_chain_len);
assert(sizeof(evidence->pck_crt) >= body.len);
memcpy(evidence->pck_crt, body.data, body.len);
evidence->pck_crt_len = body.len;
curl_easy_cleanup(curl);
free(header.data);
free(body.data);
curl_slist_free_all(request_headers);
}
/**
* Pulls TCB info's signing chain from HTTP response header. Also url-decodes it.
*/
static
void parse_response_header_tcb_info_cert_chain
(
CURL* curl,
const char* headers,
size_t headers_len,
char* cert_chain,
uint32_t* cert_chain_len
)
{
const char header_tag[] = "SGX-TCB-Info-Issuer-Chain: ";
char* header_begin = memmem((const char*) headers,
headers_len,
header_tag,
strlen(header_tag));
assert(header_begin != NULL);
header_begin += strlen(header_tag);
char* header_end = memmem(header_begin,
headers_len - (header_begin - headers),
"\r\n",
strlen("\r\n"));
assert(header_end);
int unescaped_len;
char* unescaped = curl_easy_unescape(curl, header_begin, header_end - header_begin, &unescaped_len);
assert(unescaped);
assert((int) *cert_chain_len >= unescaped_len);
memcpy(cert_chain, unescaped, unescaped_len);
*cert_chain_len = unescaped_len;
}
static void init(void) __attribute__((constructor));
static void init(void) {
/* Apparently this function is not thread-safe
(cf. https://curl.haxx.se/libcurl/c/curl_global_init.html
). Calling it from within the library initializer hopefully
solves this. */
curl_global_init(CURL_GLOBAL_DEFAULT);
}
static void deinit(void) __attribute__((destructor));
static void deinit(void) {
curl_global_cleanup();
}
/**
* Today, obtains the TCB information from Intel's backend service and
* stores it in evidence.tcb_info along with the signing chain in
* evidence.tcb_sign_chain.
*
* Tomorrow, this may obtain the TCB info from some local caching
* service, from an on-disk file, etc.
*/
static
void obtain_tcb_info
(
char fmspc[6],
ecdsa_attestation_evidence_t* evidence
)
{
/* Need 2 * 6 bytes when encoded into
hexadecimal. +1 byte for terminating NUL. */
char fmspc_base16[FMSPC_SIZE_BYTES * 2 + 1];
binary_to_base16((unsigned char*) fmspc, FMSPC_SIZE_BYTES, fmspc_base16,
sizeof(fmspc_base16));
char url[256];
int rc = snprintf(url, sizeof(url),
"https://api.trustedservices.intel.com/sgx/certification/v1/tcb?fmspc=%s",
fmspc_base16);
assert(rc < (int) sizeof(url));
CURL *curl = curl_easy_init();
struct buffer_and_size header = {(char*) malloc(1), 0};
struct buffer_and_size body = {(char*) malloc(1), 0};
http_get(curl, url, &header, &body, NULL, NULL);
evidence->tcb_sign_chain_len = sizeof(evidence->tcb_sign_chain);
parse_response_header_tcb_info_cert_chain(curl, header.data, header.len,
(char*) evidence->tcb_sign_chain,
&evidence->tcb_sign_chain_len);
assert(sizeof(evidence->tcb_info) >= body.len);
evidence->tcb_info_len = sizeof(evidence->tcb_info);
memcpy(evidence->tcb_info, body.data, body.len);
evidence->tcb_info_len = body.len;
curl_easy_cleanup(curl);
free(header.data);
free(body.data);
}
/**
* The FMSPC field is contained in the PCK certificate. Find the FMSPC
* OID and extract it.
*/
static
void extract_fmspc_from_pck_cert
(
char fmspc[6],
ecdsa_attestation_evidence_t* evidence
)
{
assert(NULL != evidence->pck_crt);
assert(evidence->pck_crt_len > 0);
uint8_t pck_crt_der[2048];
uint32_t pck_crt_der_len = sizeof(pck_crt_der);
int bytes = wolfSSL_CertPemToDer(evidence->pck_crt, evidence->pck_crt_len,
pck_crt_der, pck_crt_der_len, CERT_TYPE);
assert(bytes > 0);
pck_crt_der_len = (uint32_t) bytes;
DecodedCert crt;
InitDecodedCert(&crt, (byte*) pck_crt_der, pck_crt_der_len, NULL);
InitSignatureCtx(&crt.sigCtx, NULL, INVALID_DEVID);
int ret = ParseCertRelative(&crt, CERT_TYPE, NO_VERIFY, 0);
assert(ret == 0);
/* fmspc_oid[0] = 0x06 ... ASN.1 type (0x06 is OID)
fmspc_oid[1] = 0x0a ... length of OID in bytes, i.e., 10 bytes.
fmspc_oid[2 .. ] ... the OID 1.2.840.113741.1.13.1.4 */
const uint8_t fmspc_oid[] = { 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86,
0xf8, 0x4d, 0x01, 0x0d, 0x01, 0x04 };
uint8_t* p = memmem(crt.extensions, crt.extensionsSz,
fmspc_oid, sizeof(fmspc_oid));
assert(NULL != p);
p += sizeof(fmspc_oid);
/* p[0] ... ASN.1 type, i.e., octet string (0x04) */
assert(p[0] == 0x04);
/* p[1] ... length in bytes, i.e., 6 bytes (0x06) */
assert(p[1] == FMSPC_SIZE_BYTES);
p += 2;
FreeDecodedCert(&crt);
memcpy(fmspc, p, FMSPC_SIZE_BYTES);
}
/**
* Given a quote, gets corresponding PCK certificate.
*
* First, inspects the quote for all the values required to obtain the
* PCK certificate. Second, request PCK certificate from backend
* service.
*/
static
void ecdsa_get_pck_cert
(
ecdsa_attestation_evidence_t* evidence,
const struct ecdsa_ra_tls_options* opts
)
{
sgx_quote3_t* q = (sgx_quote3_t*) evidence->quote;
assert(evidence->quote_len == sizeof(sgx_quote3_t) + q->signature_data_len);
sgx_quote_header_t quote_header = q->header;
assert(quote_header.version == 3);
assert(quote_header.att_key_type == 2);
sgx_ql_ecdsa_sig_data_t* sig_data =
(sgx_ql_ecdsa_sig_data_t*) (q->signature_data);
sgx_ql_auth_data_t* auth_data =
(sgx_ql_auth_data_t*) (sig_data->auth_certification_data);
sgx_ql_certification_data_t* cert_data_generic =
(sgx_ql_certification_data_t*) (sig_data->auth_certification_data +
sizeof(*auth_data) + auth_data->size);
assert(cert_data_generic->cert_key_type == PPID_RSA3072_ENCRYPTED);
/* printf("ppid enc type= %d\n", cert_data_generic->cert_key_type); */
/* if (cert_data_generic->cert_key_type == PPID_CLEARTEXT) { */
/* sgx_ql_ppid_cleartext_cert_info_t* cert_info = */
/* (sgx_ql_ppid_cleartext_cert_info_t*) (cert_data_generic->certification_data); */
/* char ppid_base16[16*2]; */
/* binary_to_base16(cert_info->ppid, sizeof(cert_info->ppid), */
/* ppid_base16, sizeof(ppid_base16)); */
/* printf("PPID= %.32s\n", ppid_base16); */
/* assert(0); */
/* } */
assert(cert_data_generic->size == sizeof(sgx_ql_ppid_rsa3072_encrypted_cert_info_t));
sgx_ql_ppid_rsa3072_encrypted_cert_info_t* cert_data =
(sgx_ql_ppid_rsa3072_encrypted_cert_info_t*) (cert_data_generic->certification_data);
obtain_pck_cert(evidence, opts, cert_data);
}
/**
* Obtains quote, PCK certificate, TCB information, Quoting Enclave
* identity and certificate revocation lists.
*/
static
void collect_attestation_evidence
(
const sgx_report_data_t* report_data,
const struct ecdsa_ra_tls_options* opts,
ecdsa_attestation_evidence_t* evidence
)
{
evidence->quote_len = sizeof(evidence->quote);
ecdsa_get_quote_from_quote_service(report_data, evidence->quote, &evidence->quote_len);
ecdsa_get_pck_cert(evidence, opts);
char fmspc[6];
extract_fmspc_from_pck_cert(fmspc, evidence);
obtain_tcb_info(fmspc, evidence);
/* For now, these values are hard-coded in the executable. In the
future, they may be fetched dynamically. */
memcpy(evidence->qe_identity, qe_identity_json, qe_identity_json_len);
evidence->qe_identity_len = qe_identity_json_len;
memcpy(evidence->root_ca_crl, root_ca_crl_pem, root_ca_crl_pem_len);
evidence->root_ca_crl_len = root_ca_crl_pem_len;
memcpy(evidence->pck_crl, pck_crl_pem, pck_crl_pem_len);
evidence->pck_crl_len = pck_crl_pem_len;
}
static void
ecdsa_wolfssl_create_key_and_x509
(
uint8_t* der_key,
int* der_key_len,
uint8_t* der_cert,
int* der_cert_len,
const struct ecdsa_ra_tls_options* opts
)
{
/* Generate key. */
RsaKey genKey;
RNG rng;
int ret;
wc_InitRng(&rng);
wc_InitRsaKey(&genKey, 0);
ret = wc_MakeRsaKey(&genKey, 3072, 65537, &rng);
assert(ret == 0);
uint8_t der[4096];
int derSz = wc_RsaKeyToDer(&genKey, der, sizeof(der));
assert(derSz >= 0);
assert(derSz <= (int) *der_key_len);
*der_key_len = derSz;
memcpy(der_key, der, derSz);
/* Generate certificate */
sgx_report_data_t report_data = {0, };
sha256_rsa_pubkey(report_data.d, &genKey);
ecdsa_attestation_evidence_t evidence;
collect_attestation_evidence(&report_data, opts, &evidence);
ecdsa_generate_x509(&genKey, der_cert, der_cert_len, &evidence);
}
/**
* @param der_key_len On the way in, this is the max size for the der_key parameter. On the way out, this is the actual size for der_key.
* @param der_cert_len On the way in, this is the max size for the der_cert parameter. On the way out, this is the actual size for der_cert.
*/
void ecdsa_create_key_and_x509
(
uint8_t* der_key, /* out */
int* der_key_len, /* in/out */
uint8_t* der_cert, /* out */
int* der_cert_len, /* in/out */
const struct ecdsa_ra_tls_options* opts /* in */
)
{
ecdsa_wolfssl_create_key_and_x509(der_key, der_key_len,
der_cert, der_cert_len,
opts);
}
#endif
#ifdef WOLFSSL_SGX
time_t XTIME(time_t* tloc) {
time_t x = 1512498557; /* Dec 5, 2017, 10:29 PDT */
if (tloc) *tloc = x;
return x;
}
time_t mktime(struct tm* tm) {
(void) tm;
assert(0);
return (time_t) 0;
}
#endif
/**
* @param der_key_len On the way in, this is the max size for the der_key parameter. On the way out, this is the actual size for der_key.
* @param der_cert_len On the way in, this is the max size for the der_cert parameter. On the way out, this is the actual size for der_cert.
*/
void create_key_and_x509
(
uint8_t* der_key, /* out */
int* der_key_len, /* in/out */
uint8_t* der_cert, /* out */
int* der_cert_len, /* in/out */
const struct ra_tls_options* opts, /* in */
void* targetinfo, void* data, void* report
)
{
wolfssl_create_key_and_x509(der_key, der_key_len,
der_cert, der_cert_len,
opts);
}
static void create_key_111
(
uint8_t* der_key, /* out */
int* der_key_len, /* in/out */
uint8_t* der_cert, /* out */
int* der_cert_len, /* in/out */
const struct ra_tls_options* opts, /* in */
void* targetinfo, void* data, void* report
)
{
wolfssl_create_key_and_x509(der_key, der_key_len,
der_cert, der_cert_len,
opts);
}
static void
wolfssl_create_key
(
uint8_t* der_key,
int* der_key_len,
uint8_t* der_cert,
int* der_cert_len,
const struct ra_tls_options* opts,
void* targetinfo, void* data, void* report
)
{
/* Generate key. */
RsaKey genKey;
RNG rng;
int ret;
wc_InitRng(&rng);
wc_InitRsaKey(&genKey, 0);
ret = wc_MakeRsaKey(&genKey, 3072, 65537, &rng);
assert(ret == 0);
uint8_t der[4096];
int derSz = wc_RsaKeyToDer(&genKey, der, sizeof(der));
assert(derSz >= 0);
assert(derSz <= (int) *der_key_len);
*der_key_len = derSz;
memcpy(der_key, der, derSz);
/* Generate certificate */
sgx_report_data_t report_data = {0, };
sha256_rsa_pubkey(report_data.d, &genKey);
attestation_verification_report_t attestation_report;
do_remote_attestation(&report_data, opts, &attestation_report);
}
void create_key_and_x509_pem
(
uint8_t* pem_key, /* out */
int* pem_key_len, /* in/out */
uint8_t* pem_cert, /* out */
int* pem_cert_len, /* in/out */
const struct ra_tls_options* opts
)
{
unsigned char der_key[16 * 1024] = {0, };
int der_key_len = sizeof(der_key);
unsigned char der_cert[16 * 1024] = {0, };
int der_cert_len = sizeof(der_cert_len);
int len;
wolfssl_create_key_and_x509(der_key, &der_key_len,
der_cert, &der_cert_len,
opts);
len = wc_DerToPem(der_key, der_key_len, pem_key, *pem_key_len, PRIVATEKEY_TYPE);
assert(len > 0);
*pem_key_len = len;
len = wc_DerToPem(der_cert, der_cert_len, pem_cert, *pem_cert_len, CERT_TYPE);
assert(len > 0);
*pem_cert_len = len;
}
/**
* wolfSSL-based implementation of the RA-TLS challenger API
* (cf. ra-challenger.h).
*/
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#include <wolfssl/wolfcrypt/coding.h>
#include <wolfssl/wolfcrypt/rsa.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/signature.h>
#ifdef RATLS_ECDSA
#include <SgxEcdsaAttestation/QuoteVerification.h>
#endif
#include "ra.h"
#include "wolfssl-ra.h"
#include "ra-challenger.h"
#include "ra-challenger_private.h"
#ifdef RATLS_ECDSA
#include "ecdsa-sample-data/real/sample_data.h"
#endif
extern unsigned char ias_sign_ca_cert_der[];
extern unsigned int ias_sign_ca_cert_der_len;
void get_quote_from_cert
(
const uint8_t* der_crt,
uint32_t der_crt_len,
sgx_quote_t* q
)
{
DecodedCert crt;
int ret;
InitDecodedCert(&crt, (byte*) der_crt, der_crt_len, NULL);
InitSignatureCtx(&crt.sigCtx, NULL, INVALID_DEVID);
ret = ParseCertRelative(&crt, CERT_TYPE, NO_VERIFY, 0);
assert(ret == 0);
get_quote_from_extension(crt.extensions, crt.extensionsSz, q);
FreeDecodedCert(&crt);
}
void get_quote_from_report
(
const uint8_t* report /* in */,
const int report_len /* in */,
sgx_quote_t* quote
)
{
// Move report into \0 terminated buffer such that we can work
// with str* functions.
char buf[report_len + 1];
memcpy(buf, report, report_len);
buf[report_len] = '\0';
const char* json_string = "\"isvEnclaveQuoteBody\":\"";
char* p_begin = strstr(buf, json_string);
assert(p_begin != NULL);
p_begin += strlen(json_string);
const char* p_end = strchr(p_begin, '"');
assert(p_end != NULL);
const int quote_base64_len = p_end - p_begin;
uint8_t* quote_bin = malloc(quote_base64_len);
uint32_t quote_bin_len = quote_base64_len;
Base64_Decode((const byte*) p_begin, quote_base64_len,
quote_bin, &quote_bin_len);
assert(quote_bin_len <= sizeof(sgx_quote_t));
memset(quote, 0, sizeof(sgx_quote_t));
memcpy(quote, quote_bin, quote_bin_len);
free(quote_bin);
}
static
int verify_report_data_against_server_cert
(
DecodedCert* crt,
sgx_quote_t* quote
)
{
/* crt->publicKey seems to be the DER encoded public key. The
OpenSSL DER formatted version of the public key obtained with
openssl rsa -in ./server-key.pem -pubout -outform DER -out
server-pubkey.der has an additional 24 bytes
prefix/header. d->pubKeySize is 270 and the server-pubkey.der
file has 294 bytes. That's to be expected according to [1] */
/* [1] https://crypto.stackexchange.com/questions/14491/why-is-a-2048-bit-public-rsa-key-represented-by-540-hexadecimal-characters-in */
/* 2017-12-06, Thomas Knauth, A hard-coded offset into the
DER-encoded public key only works for specific key sizes. The
24 byte offset is specific to 2048 bit RSA keys. For example, a
1024 bit RSA key only has an offset of 22.
*/
RsaKey rsaKey;
unsigned int idx = 0;
int ret;
wc_InitRsaKey(&rsaKey, NULL);
ret = wc_RsaPublicKeyDecode(crt->publicKey, &idx, &rsaKey, crt->pubKeySize);
assert(ret == 0);
byte shaSum[SHA256_DIGEST_SIZE] = {0, };
sha256_rsa_pubkey(shaSum, &rsaKey);
wc_FreeRsaKey(&rsaKey);
#ifdef DEBUG
fprintf(stderr, "SHA256 of server's public key:\n");
for (int i=0; i < SHA256_DIGEST_SIZE; ++i) fprintf(stderr, "%02x", shaSum[i]);
fprintf(stderr, "\n");
fprintf(stderr, "Quote's report data:\n");
for (int i=0; i < SGX_REPORT_DATA_SIZE; ++i) fprintf(stderr, "%02x", quote->report_body.report_data.d[i]);
fprintf(stderr, "\n");
#endif
assert(SHA256_DIGEST_SIZE <= SGX_REPORT_DATA_SIZE);
ret = memcmp(quote->report_body.report_data.d, shaSum, SHA256_DIGEST_SIZE);
assert(ret == 0);
return ret;
}
static
int verify_ias_report_signature
(
attestation_verification_report_t* attn_report
)
{
DecodedCert crt;
int ret;
uint8_t der[4096];
int der_len;
der_len = wolfSSL_CertPemToDer(attn_report->ias_sign_cert, attn_report->ias_sign_cert_len,
der, sizeof(der),
CERT_TYPE);
assert(der_len > 0);
InitDecodedCert(&crt, der, der_len, NULL);
InitSignatureCtx(&crt.sigCtx, NULL, INVALID_DEVID);
ret = ParseCertRelative(&crt, CERT_TYPE, NO_VERIFY, 0);
assert(ret == 0);
RsaKey rsaKey;
unsigned int idx = 0;
ret = wc_InitRsaKey(&rsaKey, NULL);
assert(ret == 0);
ret = wc_RsaPublicKeyDecode(crt.publicKey, &idx, &rsaKey, crt.pubKeySize);
assert(ret == 0);
ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256,
/* This is required such that signature
matches what OpenSSL produces. OpenSSL
embeds the hash in an ASN.1 structure
before signing it. */
WC_SIGNATURE_TYPE_RSA_W_ENC,
attn_report->ias_report, attn_report->ias_report_len,
attn_report->ias_report_signature, attn_report->ias_report_signature_len,
&rsaKey, sizeof(rsaKey));
FreeDecodedCert(&crt);
wc_FreeRsaKey(&rsaKey);
return ret;
}
static
int verify_ias_certificate_chain(attestation_verification_report_t* attn_report) {
WOLFSSL_CERT_MANAGER* cm;
cm = wolfSSL_CertManagerNew();
assert(cm != NULL);
/* like load verify locations, 1 for success, < 0 for error */
int ret = wolfSSL_CertManagerLoadCABuffer(cm, ias_sign_ca_cert_der,
ias_sign_ca_cert_der_len,
SSL_FILETYPE_ASN1);
assert(ret == 1);
ret = wolfSSL_CertManagerVerifyBuffer(cm, attn_report->ias_sign_cert,
attn_report->ias_sign_cert_len,
SSL_FILETYPE_PEM);
assert(ret == SSL_SUCCESS);
wolfSSL_CertManagerFree(cm);
cm = NULL;
return 0;
}
/**
* Check if isvEnclaveQuoteStatus is "OK"
* (cf. https://software.intel.com/sites/default/files/managed/7e/3b/ias-api-spec.pdf,
* pg. 24).
*
* @return 0 if verified successfully, 1 otherwise.
*/
static
int verify_enclave_quote_status
(
const char* ias_report,
int ias_report_len
)
{
// Move ias_report into \0 terminated buffer such that we can work
// with str* functions.
char buf[ias_report_len + 1];
memcpy(buf, ias_report, ias_report_len);
buf[ias_report_len] = '\0';
const char* json_string = "\"isvEnclaveQuoteStatus\":\"";
char* p_begin = strstr(buf, json_string);
assert(p_begin != NULL);
p_begin += strlen(json_string);
const char* status_OK = "OK\"";
if (0 == strncmp(p_begin, status_OK, strlen(status_OK))) return 0;
#ifdef SGX_GROUP_OUT_OF_DATE
const char* status_outdated = "GROUP_OUT_OF_DATE\"";
if (0 == strncmp(p_begin, status_outdated, strlen(status_outdated))) {
printf("WARNING: isvEnclaveQuoteStatus is GROUP_OUT_OF_DATE\n");
return 0;
}
#endif
return 1;
}
static
int epid_verify_sgx_cert_extensions
(
uint8_t* der_crt,
uint32_t der_crt_len
)
{
attestation_verification_report_t attn_report;
DecodedCert crt;
int ret;
InitDecodedCert(&crt, der_crt, der_crt_len, NULL);
InitSignatureCtx(&crt.sigCtx, NULL, INVALID_DEVID);
ret = ParseCertRelative(&crt, CERT_TYPE, NO_VERIFY, 0);
assert(ret == 0);
extract_x509_extensions(crt.extensions, crt.extensionsSz, &attn_report);
/* Base64 decode attestation report signature. */
uint8_t sig_base64[sizeof(attn_report.ias_report_signature)];
memcpy(sig_base64, attn_report.ias_report_signature, attn_report.ias_report_signature_len);
int rc = Base64_Decode(sig_base64, attn_report.ias_report_signature_len,
attn_report.ias_report_signature, &attn_report.ias_report_signature_len);
assert(0 == rc);
ret = verify_ias_certificate_chain(&attn_report);
assert(ret == 0);
ret = verify_ias_report_signature(&attn_report);
assert(ret == 0);
ret = verify_enclave_quote_status((const char*) attn_report.ias_report,
attn_report.ias_report_len);
assert(ret == 0);
sgx_quote_t quote = {0, };
get_quote_from_report(attn_report.ias_report,
attn_report.ias_report_len,
&quote);
ret = verify_report_data_against_server_cert(&crt, &quote);
assert(ret == 0);
FreeDecodedCert(&crt);
return 0;
}
#ifdef RATLS_ECDSA
static
int ecdsa_verify_sgx_cert_extensions
(
uint8_t* der_crt,
uint32_t der_crt_len
)
{
DecodedCert crt;
int ret;
InitDecodedCert(&crt, der_crt, der_crt_len, NULL);
InitSignatureCtx(&crt.sigCtx, NULL, INVALID_DEVID);
ret = ParseCertRelative(&crt, CERT_TYPE, NO_VERIFY, 0);
assert(ret == 0);
ecdsa_attestation_evidence_t evidence;
ecdsa_extract_x509_extensions(crt.extensions,
crt.extensionsSz,
&evidence);
FreeDecodedCert(&crt);
/* pem_cert_chain := pck cert + pck CA cert + root CA cert */
/* crls := root ca crl + pck crl */
/* pem_trusted_root_ca_cert */
size_t pck_cert_chain_len = evidence.pck_sign_chain_len + evidence.pck_crt_len + 1;
char pck_cert_chain[pck_cert_chain_len];
memcpy(pck_cert_chain, evidence.pck_crt, evidence.pck_crt_len);
memcpy(pck_cert_chain + evidence.pck_crt_len, evidence.pck_sign_chain, evidence.pck_sign_chain_len);
pck_cert_chain[sizeof(pck_cert_chain) - 1] = '\0';
assert(evidence.root_ca_crl_len < sizeof(evidence.root_ca_crl));
evidence.root_ca_crl[evidence.root_ca_crl_len] = '\0';
assert(evidence.pck_crl_len < sizeof(evidence.pck_crl));
evidence.pck_crl[evidence.pck_crl_len] = '\0';
const char* const crls[] = {(char*) evidence.root_ca_crl,
(char*) evidence.pck_crl};
/* SGXDataCenterAttestationPrimitives/QuoteVerification/Src/ThirdParty/CMakeLists.txt depends on openssl-1.1.0i.tar.gz" */
/* libQuoteVerification.so seems to link in OpenSSL dependencies statically?! */
/* QVL expects zero terminated strings as input! */
int pck_crt_status = sgxAttestationVerifyPCKCertificate(pck_cert_chain, crls,
(char*) ecdsa_sample_data_real_trustedRootCaCert_pem);
assert(evidence.tcb_info_len < sizeof(evidence.tcb_info));
evidence.tcb_info[evidence.tcb_info_len] = '\0';
assert(evidence.tcb_sign_chain_len < sizeof(evidence.tcb_sign_chain));
evidence.tcb_sign_chain[evidence.tcb_sign_chain_len] = '\0';
int tcb_info_status = sgxAttestationVerifyTCBInfo((char*) evidence.tcb_info,
(char*) evidence.tcb_sign_chain,
(char*) evidence.root_ca_crl,
(char*) ecdsa_sample_data_real_trustedRootCaCert_pem);
assert(evidence.qe_identity_len < sizeof(evidence.qe_identity));
evidence.qe_identity[evidence.qe_identity_len] = '\0';
int qe_identity_status = sgxAttestationVerifyQEIdentity((char*) evidence.qe_identity,
(char*) evidence.tcb_sign_chain,
(char*) evidence.root_ca_crl,
(char*) ecdsa_sample_data_real_trustedRootCaCert_pem);
int quote_status = sgxAttestationVerifyQuote(evidence.quote, evidence.quote_len,
(char*) evidence.pck_crt,
(char*) evidence.pck_crl,
(char*) evidence.tcb_info,
(char*) evidence.qe_identity);
// TODO Update DCAP SDK to newest version.
if (quote_status == STATUS_TCB_OUT_OF_DATE) {
printf("!!! WARNING: quote verification resulted in STATUS_TCB_OUT_OF_DATE\n");
quote_status = 0;
}
int report_user_data_status = verify_report_data_against_server_cert(&crt, (sgx_quote_t*) evidence.quote);
return pck_crt_status || tcb_info_status || qe_identity_status || quote_status || report_user_data_status;
}
#endif
int verify_sgx_cert_extensions
(
uint8_t* der_crt,
uint32_t der_crt_len
)
{
if (is_epid_ratls_cert(der_crt, der_crt_len)) {
return epid_verify_sgx_cert_extensions(der_crt, der_crt_len);
} else {
#ifdef RATLS_ECDSA
return ecdsa_verify_sgx_cert_extensions(der_crt, der_crt_len);
#endif
}
assert(0);
// Avoid compiler error: control reaches end of non-void function
// [-Werror=return-type]
return -1;
}
#include <assert.h>
#include <stdint.h>
#include <wolfssl/options.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#include <wolfssl/wolfcrypt/rsa.h>
#include "ra.h"
#include "wolfssl-ra.h"
void sha256_rsa_pubkey
(
unsigned char hash[SHA256_DIGEST_SIZE],
RsaKey* key
)
{
// Expect a 3072 bit RSA key.
assert(key->n.used == 48 /* == 3072 / 8 / 8 */);
uint8_t buf[1024];
/* SetRsaPublicKey() only exports n and e without wrapping them in
additional ASN.1 (PKCS#1). */
int pub_rsa_key_der_len = SetRsaPublicKey(buf, key, sizeof(buf), 0);
assert(pub_rsa_key_der_len == rsa_pub_3072_raw_der_len);
Sha256 sha;
wc_InitSha256(&sha);
wc_Sha256Update(&sha, buf, pub_rsa_key_der_len);
wc_Sha256Final(&sha, hash);
}
/* This function only exists to make edger8r happy. There must be at
least one trusted (ECALL) function. */
void dummy(void) {
}
#include <wolfssl/wolfcrypt/sha256.h>
void sha256_rsa_pubkey
(
unsigned char hash[SHA256_DIGEST_SIZE],
RsaKey* key
);
diff --git a/pre-commit.sh b/pre-commit.sh
index cbac1b5..71c7976 100755
--- a/pre-commit.sh
+++ b/pre-commit.sh
@@ -3,6 +3,8 @@
#
# Our "pre-commit" hook.
+exit 0
+
# save current config
echo "\n\nSaving current config\n\n"
cp config.status tmp.status
diff --git a/src/internal.c b/src/internal.c
index a6989c4..9036910 100644
--- a/src/internal.c
+++ b/src/internal.c
@@ -9777,11 +9777,14 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
}
else {
- if (inputLength + ssl->arrays->pendingMsgOffset
- > ssl->arrays->pendingMsgSz) {
+ word32 pendSz =
+ ssl->arrays->pendingMsgSz - ssl->arrays->pendingMsgOffset;
- return BUFFER_ERROR;
- }
+ /* Catch the case where there may be the remainder of a fragmented
+ * handshake message and the next handshake message in the same
+ * record. */
+ if (inputLength > pendSz)
+ inputLength = pendSz;
XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset,
input + *inOutIdx, inputLength);
@@ -9790,13 +9793,11 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz)
{
- word32 idx = 0;
+ word32 idx = HANDSHAKE_HEADER_SZ;
ret = DoHandShakeMsgType(ssl,
- ssl->arrays->pendingMsg
- + HANDSHAKE_HEADER_SZ,
+ ssl->arrays->pendingMsg,
&idx, ssl->arrays->pendingMsgType,
- ssl->arrays->pendingMsgSz
- - HANDSHAKE_HEADER_SZ,
+ ssl->arrays->pendingMsgSz - idx,
ssl->arrays->pendingMsgSz);
#ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_PENDING_E) {
diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c
index e234253..5cdeae5 100644
--- a/wolfcrypt/src/asn.c
+++ b/wolfcrypt/src/asn.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
+#include <assert.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -61,6 +62,7 @@ ASN Options:
#include <wolfssl/wolfcrypt/pwdbased.h>
#include <wolfssl/wolfcrypt/des3.h>
#include <wolfssl/wolfcrypt/logging.h>
+#include <wolfssl/wolfcrypt/wc_port.h>
#include <wolfssl/wolfcrypt/random.h>
#include <wolfssl/wolfcrypt/hash.h>
@@ -6346,7 +6348,10 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz,
/* USER RSA ifdef portions used instead of refactor in consideration for
possible fips build */
/* Write a public RSA key to output */
-static int SetRsaPublicKey(byte* output, RsaKey* key,
+#if !defined(WOLFSSL_SGX_ATTESTATION)
+static
+#endif
+int SetRsaPublicKey(byte* output, RsaKey* key,
int outLen, int with_header)
{
#ifdef WOLFSSL_SMALL_STACK
@@ -6710,6 +6715,20 @@ typedef struct DerCert {
byte extKeyUsage[MAX_EXTKEYUSAGE_SZ]; /* Extended Key Usage extension */
byte certPolicies[MAX_CERTPOL_NB*MAX_CERTPOL_SZ]; /* Certificate Policies */
#endif
+#ifdef WOLFSSL_SGX_ATTESTATION
+ byte iasSigCACert[2048];
+ byte iasSigCert[2048];
+ byte iasSig[2048];
+ byte iasAttestationReport[2048];
+ byte quote[2048];
+ byte pckCrt[2048];
+ byte pckSignChain[4096];
+ byte tcbInfo[4096];
+ byte tcbSignChain[4096];
+ byte qeIdentity[1024];
+ byte rootCaCrl[1024];
+ byte pckCrl[1024];
+#endif
#ifdef WOLFSSL_CERT_REQ
byte attrib[MAX_ATTRIB_SZ]; /* Cert req attributes encoded */
#endif
@@ -6732,6 +6751,20 @@ typedef struct DerCert {
int extKeyUsageSz; /* encoded ExtendedKeyUsage extension length */
int certPoliciesSz; /* encoded CertPolicies extension length*/
#endif
+#ifdef WOLFSSL_SGX_ATTESTATION
+ int iasSigCACertSz;
+ int iasSigCertSz;
+ int iasSigSz;
+ int iasAttestationReportSz;
+ int quoteSz;
+ int pckCrtSz;
+ int pckSignChainSz;
+ int tcbInfoSz;
+ int tcbSignChainSz;
+ int qeIdentitySz;
+ int rootCaCrlSz;
+ int pckCrlSz;
+#endif
#ifdef WOLFSSL_ALT_NAMES
int altNamesSz; /* encoded AltNames extension length */
#endif
@@ -7104,13 +7137,26 @@ static int SetValidity(byte* output, int daysValid)
/* subtract 1 day for more compliance */
local.tm_mday -= 1;
+#if !defined(WOLFSSL_SGX_ATTESTATION)
normalTime = mktime(&local);
+#endif
RebuildTime(&normalTime, &local);
/* adjust */
local.tm_year += 1900;
local.tm_mon += 1;
+#ifdef WOLFSSL_SGX_ATTESTATION
+ /* To work around the abscence of a trusted time source in SGX, we
+ hard-code the certificate validity period. */
+ bzero(&local, sizeof(local));
+ local.tm_year = 2020;
+ local.tm_mday = 14;
+ local.tm_wday = 6; /* 6 is Friday */
+ local.tm_mon = 1; /* 1 is February */
+ local.tm_hour = 9;
+#endif
+
SetTime(&local, before + beforeSz);
beforeSz += ASN_GEN_TIME_SZ;
@@ -7121,13 +7167,24 @@ static int SetValidity(byte* output, int daysValid)
/* add daysValid */
local.tm_mday += daysValid;
+#if !defined(WOLFSSL_SGX_ATTESTATION)
normalTime = mktime(&local);
+#endif
RebuildTime(&normalTime, &local);
/* adjust */
local.tm_year += 1900;
local.tm_mon += 1;
+#ifdef WOLFSSL_SGX_ATTESTATION
+ bzero(&local, sizeof(local));
+ local.tm_year = 2030;
+ local.tm_mday = 14;
+ local.tm_wday = 5; /* 5 is Thursday */
+ local.tm_mon = 1; /* 1 is February */
+ local.tm_hour = 9;
+#endif
+
SetTime(&local, after + afterSz);
afterSz += ASN_GEN_TIME_SZ;
@@ -7445,7 +7502,16 @@ static int SetKeyUsage(byte* output, word32 outSz, word16 input)
ku, idx);
}
-static int SetOjectIdValue(byte* output, word32 outSz, int* idx,
+#if !defined(WOLFSSL_SGX_ATTESTATION)
+static
+#endif
+int SetOjectIdValue(byte* output, word32 outSz, int* idx,
+ const byte* oid, word32 oidSz);
+
+#if !defined(WOLFSSL_SGX_ATTESTATION)
+static
+#endif
+int SetOjectIdValue(byte* output, word32 outSz, int* idx,
const byte* oid, word32 oidSz)
{
/* verify room */
@@ -7459,6 +7525,53 @@ static int SetOjectIdValue(byte* output, word32 outSz, int* idx,
return 0;
}
+#ifdef WOLFSSL_SGX_ATTESTATION
+static int SetSGXExt(byte* output, word32 outSz, const byte* oid, int oidSz, const byte *input, word32 length)
+{
+ byte ext_len[1 + MAX_LENGTH_SZ];
+ byte ext_enc_len[MAX_LENGTH_SZ];
+ byte oid_enc[16];
+ int idx = 0, ext_lenSz;
+ int oid_enc_lenSz = 0;
+
+ if (output == NULL || input == NULL || oid == NULL)
+ return BAD_FUNC_ARG;
+
+ ext_lenSz = SetOctetString(length, ext_len);
+
+ SetLength(length + ext_lenSz, ext_enc_len);
+
+ SetOjectIdValue(oid_enc, sizeof(oid_enc), &oid_enc_lenSz, oid, oidSz);
+
+ if (outSz < 3)
+ return BUFFER_E;
+
+ idx = SetSequence(length + oid_enc_lenSz + ext_lenSz,
+ output);
+
+ if ((idx + length + oid_enc_lenSz + ext_lenSz) > outSz)
+ return BUFFER_E;
+
+ /* put oid */
+ XMEMCPY(output+idx, oid_enc, oid_enc_lenSz);
+ idx += oid_enc_lenSz;
+
+ /* put encoded len */
+ /* XMEMCPY(output+idx, ext_enc_len, ext_enc_lenSz); */
+ /* idx += ext_enc_lenSz; */
+
+ /* put octet header */
+ XMEMCPY(output+idx, ext_len, ext_lenSz);
+ idx += ext_lenSz;
+
+ /* put value */
+ XMEMCPY(output+idx, input, length);
+ idx += length;
+
+ return idx;
+}
+#endif
+
/* encode Extended Key Usage (RFC 5280 4.2.1.12), return total bytes written */
static int SetExtKeyUsage(byte* output, word32 outSz, byte input)
{
@@ -8055,6 +8168,103 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
der->certPoliciesSz = 0;
#endif /* WOLFSSL_CERT_EXT */
+#ifdef WOLFSSL_SGX_ATTESTATION
+ if (cert->iasSigCACertSz > 0 &&
+ cert->iasSigCertSz > 0 &&
+ cert->iasSigSz > 0 &&
+ cert->iasAttestationReportSz > 0) {
+
+// 1.2.840.113741.1337.*
+#define OID(N) {0x2A, 0x86, 0x48, 0x86, 0xF8, 0x4D, 0x8A, 0x39, (N)}
+
+ unsigned char iasAttestationReportOid[] = OID(0x02);
+ unsigned char iasSigCACertOid[] = OID(0x03);
+ unsigned char iasSigCertOid[] = OID(0x04);
+ unsigned char iasSigOid[] = OID(0x05);
+
+ der->iasSigCACertSz = SetSGXExt(der->iasSigCACert, sizeof(der->iasSigCACert),
+ iasSigCACertOid, sizeof(iasSigCACertOid),
+ cert->iasSigCACert, cert->iasSigCACertSz);
+
+ der->iasSigCertSz = SetSGXExt(der->iasSigCert, sizeof(der->iasSigCert),
+ iasSigCertOid, sizeof(iasSigCertOid),
+ cert->iasSigCert, cert->iasSigCertSz);
+
+ der->iasSigSz = SetSGXExt(der->iasSig, sizeof(der->iasSig),
+ iasSigOid, sizeof(iasSigOid),
+ cert->iasSig, cert->iasSigSz);
+
+ der->iasAttestationReportSz = SetSGXExt(der->iasAttestationReport,
+ sizeof(der->iasAttestationReport),
+ iasAttestationReportOid,
+ sizeof(iasAttestationReportOid),
+ cert->iasAttestationReport,
+ cert->iasAttestationReportSz);
+
+ der->extensionsSz += der->iasAttestationReportSz +
+ der->iasSigCACertSz +
+ der->iasSigCertSz +
+ der->iasSigSz;
+ }
+
+ if (cert->quoteSz > 0 && cert->pckCrtSz > 0 && cert->pckSignChainSz > 0 &&
+ cert->tcbInfoSz > 0 && cert->tcbSignChainSz > 0 && cert->qeIdentitySz > 0 &&
+ cert->rootCaCrlSz > 0 && cert->pckCrlSz > 0) {
+
+ const unsigned char quoteOid[] = OID(0x06);
+ der->quoteSz = SetSGXExt(der->quote, sizeof(der->quote),
+ quoteOid, sizeof(quoteOid),
+ cert->quote, cert->quoteSz);
+ assert(der->quoteSz > 0);
+
+ const unsigned char pckCrtOid[] = OID(0x07);
+ der->pckCrtSz = SetSGXExt(der->pckCrt, sizeof(der->pckCrt),
+ pckCrtOid, sizeof(pckCrtOid),
+ cert->pckCrt, cert->pckCrtSz);
+ assert(der->pckCrtSz > 0);
+
+ const unsigned char pckSignChainOid[] = OID(0x08);
+ der->pckSignChainSz = SetSGXExt(der->pckSignChain, sizeof(der->pckSignChain),
+ pckSignChainOid, sizeof(pckSignChainOid),
+ cert->pckSignChain, cert->pckSignChainSz);
+ assert(der->pckSignChainSz > 0);
+
+ const unsigned char tcbInfoOid[] = OID(0x09);
+ der->tcbInfoSz = SetSGXExt(der->tcbInfo, sizeof(der->tcbInfo),
+ tcbInfoOid, sizeof(tcbInfoOid),
+ cert->tcbInfo, cert->tcbInfoSz);
+ assert(der->tcbInfoSz > 0);
+
+ const unsigned char tcbSignChainOid[] = OID(0x0a);
+ der->tcbSignChainSz = SetSGXExt(der->tcbSignChain, sizeof(der->tcbSignChain),
+ tcbSignChainOid, sizeof(tcbSignChainOid),
+ cert->tcbSignChain, cert->tcbSignChainSz);
+ assert(der->tcbSignChainSz > 0);
+
+ const unsigned char qeIdentityOid[] = OID(0x0b);
+ der->qeIdentitySz = SetSGXExt(der->qeIdentity, sizeof(der->qeIdentity),
+ qeIdentityOid, sizeof(qeIdentityOid),
+ cert->qeIdentity, cert->qeIdentitySz);
+ assert(der->qeIdentitySz > 0);
+
+ const unsigned char rootCaCrlOid[] = OID(0x0c);
+ der->rootCaCrlSz = SetSGXExt(der->rootCaCrl, sizeof(der->rootCaCrl),
+ rootCaCrlOid, sizeof(rootCaCrlOid),
+ cert->rootCaCrl, cert->rootCaCrlSz);
+ assert(der->rootCaCrlSz > 0);
+
+ const unsigned char pckCrlOid[] = OID(0x0d);
+ der->pckCrlSz = SetSGXExt(der->pckCrl, sizeof(der->pckCrl),
+ pckCrlOid, sizeof(pckCrlOid),
+ cert->pckCrl, cert->pckCrlSz);
+ assert(der->pckCrlSz > 0);
+
+ der->extensionsSz += der->quoteSz + der->pckCrtSz + der->pckSignChainSz +
+ der->tcbInfoSz + der->tcbSignChainSz + der->qeIdentitySz + der->rootCaCrlSz +
+ der->pckCrlSz;
+}
+#endif
+
/* put extensions */
if (der->extensionsSz > 0) {
@@ -8131,6 +8341,88 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
return EXTENSIONS_E;
}
#endif /* WOLFSSL_CERT_EXT */
+#ifdef WOLFSSL_SGX_ATTESTATION
+ if (der->iasSigCACertSz && der->iasSigCertSz &&
+ der->iasSigSz && der->iasAttestationReportSz) {
+
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->iasAttestationReport, der->iasAttestationReportSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->iasSigCACert, der->iasSigCACertSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->iasSigCert, der->iasSigCertSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->iasSig, der->iasSigSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ if (der->quoteSz > 0 && der->pckCrtSz > 0 && der->pckSignChainSz > 0 &&
+ der->tcbInfoSz > 0 && der->tcbSignChainSz > 0 && der->qeIdentitySz > 0 &&
+ der->rootCaCrlSz > 0 && der->pckCrlSz > 0) {
+
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->quote, der->quoteSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->pckCrt, der->pckCrtSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->pckSignChain, der->pckSignChainSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->tcbInfo, der->tcbInfoSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->tcbSignChain, der->tcbSignChainSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->qeIdentity, der->qeIdentitySz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->rootCaCrl, der->rootCaCrlSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->pckCrl, der->pckCrlSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+}
+#endif
}
der->total = der->versionSz + der->serialSz + der->sigAlgoSz +
diff --git a/wolfssl/internal.h b/wolfssl/internal.h
index 9c77120..3c922dd 100644
--- a/wolfssl/internal.h
+++ b/wolfssl/internal.h
@@ -1272,7 +1272,7 @@ enum Misc {
/* max size of a handshake message, currently set to the certificate */
#ifndef MAX_HANDSHAKE_SZ
- #define MAX_HANDSHAKE_SZ MAX_CERTIFICATE_SZ
+ #define MAX_HANDSHAKE_SZ ((MAX_CERTIFICATE_SZ) * 4)
#endif
#ifndef SESSION_TICKET_LEN
diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h
index b730846..870ffdb 100644
--- a/wolfssl/wolfcrypt/asn_public.h
+++ b/wolfssl/wolfcrypt/asn_public.h
@@ -164,6 +164,32 @@ typedef struct Cert {
char certPolicies[CTC_MAX_CERTPOL_NB][CTC_MAX_CERTPOL_SZ];
word16 certPoliciesNb; /* Number of Cert Policy */
#endif
+#ifdef WOLFSSL_SGX_ATTESTATION
+ byte iasSigCACert[2048];
+ int iasSigCACertSz;
+ byte iasSigCert[2048];
+ int iasSigCertSz;
+ byte iasSig[2048];
+ int iasSigSz;
+ byte iasAttestationReport[2048];
+ int iasAttestationReportSz;
+ byte quote[2048];
+ int quoteSz;
+ byte pckCrt[2048];
+ int pckCrtSz;
+ byte pckSignChain[4096];
+ int pckSignChainSz;
+ byte tcbInfo[4096];
+ int tcbInfoSz;
+ byte tcbSignChain[4096];
+ int tcbSignChainSz;
+ byte qeIdentity[1024];
+ int qeIdentitySz;
+ byte rootCaCrl[1024];
+ int rootCaCrlSz;
+ byte pckCrl[1024];
+ int pckCrlSz;
+#endif
#ifdef WOLFSSL_CERT_REQ
char challengePw[CTC_NAME_SIZE];
#endif
@@ -330,6 +356,10 @@ WOLFSSL_API int wc_CreatePKCS8Key(byte* out, word32* outSz,
*/
WOLFSSL_API int wc_GetTime(void* timePtr, word32 timeSize);
+#ifdef WOLFSSL_SGX_ATTESTATION
+WOLFSSL_API int SetRsaPublicKey(byte* output, RsaKey* key, int outLen, int with_header);
+#endif
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h
index 6254b72..9a20413 100644
--- a/wolfssl/wolfcrypt/settings.h
+++ b/wolfssl/wolfcrypt/settings.h
@@ -1228,7 +1228,9 @@ extern void uITRON4_free(void *p) ;
#define WC_RSA_BLINDING
#endif
#define SINGLE_THREADED
+#if !defined(WOLFSSL_SGX_ATTESTATION)
#define NO_ASN_TIME /* can not use headers such as windows.h */
+#endif
#define HAVE_AESGCM
#define USE_CERT_BUFFERS_2048
#define USE_FAST_MATH
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册