forked from cloud-security-research/sgx-ra-tls
-
Notifications
You must be signed in to change notification settings - Fork 1
/
mbedtls-ra-challenger.c
240 lines (196 loc) · 7.41 KB
/
mbedtls-ra-challenger.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#define _GNU_SOURCE
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mbedtls/base64.h>
#include "mbedtls/ctr_drbg.h"
#include <mbedtls/sha256.h>
#include <mbedtls/x509_crt.h>
#include <mbedtls/pk.h>
#include <mbedtls/pk_internal.h>
#include <sgx_quote.h>
#include "ra.h"
#include "ra-challenger.h"
#include "ra-challenger_private.h"
extern unsigned char ias_sign_ca_cert_der[];
extern unsigned int ias_sign_ca_cert_der_len;
void get_quote_from_report(const uint8_t* report /* in */,
const int report_len /* in */,
sgx_quote_t* quote)
{
(void) report_len;
const char* json_string = "\"isvEnclaveQuoteBody\":\"";
char* p_begin = strstr((const char*) report, 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);
size_t quote_bin_len = quote_base64_len;
mbedtls_base64_decode(quote_bin, quote_base64_len,
"e_bin_len,
(unsigned char*) p_begin, quote_base64_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);
}
void get_quote_from_cert
(
const uint8_t* der_crt,
uint32_t der_crt_len,
sgx_quote_t* q
)
{
mbedtls_x509_crt crt;
mbedtls_x509_crt_init(&crt);
mbedtls_x509_crt_parse(&crt, der_crt, der_crt_len);
get_quote_from_extension(crt.v3_ext.p, crt.v3_ext.len, q);
mbedtls_x509_crt_free(&crt);
}
static
int verify_report_data_against_server_cert
(
mbedtls_x509_crt* crt,
sgx_quote_t* quote
)
{
static const int pk_der_size_max = 512;
uint8_t pk_der[pk_der_size_max];
memset(pk_der, 0, pk_der_size_max);
/* From the mbedtls documentation: Write a public key to a
SubjectPublicKeyInfo DER structure Note: data is written at the
end of the buffer! Use the return value to determine where you
should start using the buffer. */
int pk_der_size_byte = mbedtls_pk_write_pubkey_der(&crt->pk, pk_der, pk_der_size_max);
// Can only handle 2048 bit RSA keys for now. Other key sizes will
// have a different pk_der_offset.
assert(pk_der_size_byte == 294);
/* Move the data to the beginning of the buffer, to avoid pointer
arithmetic from this point forward. */
memmove(pk_der, pk_der + pk_der_size_max - pk_der_size_byte, pk_der_size_byte);
/* 24 since we skip the DER structure header. */
static const uint64_t pk_der_offset = 24;
static const size_t SHA256_DIGEST_SIZE = 32;
uint8_t shaSum[SHA256_DIGEST_SIZE];
memset(shaSum, 0, SHA256_DIGEST_SIZE);
mbedtls_sha256(pk_der + pk_der_offset, pk_der_size_byte - pk_der_offset,
shaSum, 0 /* is224 */);
#if 0
printf_sgx("sha256 of server's public key:\n");
for (unsigned int i=0; i < SHA256_DIGEST_SIZE; ++i) mbedtls_printf("%02x", shaSum[i]);
mbedtls_printf("\n");
mbedtls_printf("quote report data:\n");
for (int i=0; i < SGX_REPORT_DATA_SIZE; ++i) mbedtls_printf("%02x", quote->report_body.report_data.d[i]);
mbedtls_printf("\n");
#endif
int ret;
ret = memcmp(quote->report_body.report_data.d,
shaSum, SHA256_DIGEST_SIZE);
assert(ret == 0);
#if 0
if (ret == 0) mbedtls_printf("hash of server's public key matches matches report data\n");
#endif
return ret;
}
static
int verify_ias_report_signature
(
attestation_verification_report_t* attn_report
)
{
// Create certificate structure
mbedtls_x509_crt cert;
mbedtls_x509_crt_init(&cert);
int ret;
/* mbedtls_x509_crt_parse requires PEM-encoded certificates to be
zero terminated (How braindead is this?). */
assert(attn_report->ias_sign_cert_len < sizeof(attn_report->ias_sign_cert));
attn_report->ias_sign_cert[attn_report->ias_sign_cert_len] = '\0';
ret = mbedtls_x509_crt_parse(&cert,
attn_report->ias_sign_cert,
attn_report->ias_sign_cert_len + 1); /* +1 for the zero byte */
assert(ret == 0);
// Extract RSA public key
assert(cert.pk.pk_info->type == MBEDTLS_PK_RSA);
mbedtls_rsa_context* rsa = (mbedtls_rsa_context*) cert.pk.pk_ctx;
// Compute signature
uint8_t sha256[32];
ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
attn_report->ias_report,
attn_report->ias_report_len,
sha256);
assert(ret == 0);
// Verify signature
ret = mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC,
MBEDTLS_MD_SHA256, 0,
sha256,
attn_report->ias_report_signature);
return ret;
}
static
int verify_ias_certificate_chain(attestation_verification_report_t* attn_report) {
mbedtls_x509_crt cacert;
mbedtls_x509_crt_init(&cacert);
int ret;
ret = mbedtls_x509_crt_parse(&cacert,
ias_sign_ca_cert_der,
ias_sign_ca_cert_der_len);
assert(ret == 0);
mbedtls_x509_crt cert;
mbedtls_x509_crt_init(&cert);
/* mbedtls_x509_crt_parse requires PEM-encoded certificates to be
zero terminated (How brainded is this?). */
assert(attn_report->ias_sign_cert_len < sizeof(attn_report->ias_sign_cert));
attn_report->ias_sign_cert[attn_report->ias_sign_cert_len] = '\0';
ret = mbedtls_x509_crt_parse(&cert,
attn_report->ias_sign_cert,
attn_report->ias_sign_cert_len + 1); /* +1 for the zero byte. */
assert(ret == 0);
uint32_t flags;
ret = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &flags, NULL, NULL);
assert(ret == 0);
return ret;
}
/**
* @return 0 if verified successfully, 1 otherwise.
*/
int verify_sgx_cert_extensions
(
uint8_t* der_crt,
uint32_t der_crt_len
)
{
attestation_verification_report_t attn_report;
mbedtls_x509_crt crt;
mbedtls_x509_crt_init(&crt);
int ret;
ret = mbedtls_x509_crt_parse(&crt, der_crt, der_crt_len);
extract_x509_extensions(crt.v3_ext.p,
crt.v3_ext.len,
&attn_report);
uint8_t base64[sizeof(attn_report.ias_report_signature)];
memcpy(base64, attn_report.ias_report_signature, attn_report.ias_report_signature_len);
size_t decoded_len;
ret = mbedtls_base64_decode(attn_report.ias_report_signature,
sizeof(attn_report.ias_report_signature),
&decoded_len, base64, attn_report.ias_report_signature_len);
assert(0 == ret);
assert(decoded_len <= UINT32_MAX);
attn_report.ias_report_signature_len = (uint32_t) decoded_len;
ret = verify_ias_certificate_chain(&attn_report);
assert(ret == 0);
ret = verify_ias_report_signature(&attn_report);
assert(ret == 0);
sgx_quote_t quote = {0, };
get_quote_from_report(attn_report.ias_report,
attn_report.ias_report_len,
"e);
ret = verify_report_data_against_server_cert(&crt, "e);
assert(ret == 0);
mbedtls_x509_crt_free(&crt);
return 0;
}