0001
0002
0003
0004 #define _GNU_SOURCE
0005 #include <assert.h>
0006 #include <getopt.h>
0007 #include <stdbool.h>
0008 #include <stdint.h>
0009 #include <stdio.h>
0010 #include <stdlib.h>
0011 #include <string.h>
0012 #include <sys/stat.h>
0013 #include <sys/types.h>
0014 #include <unistd.h>
0015 #include <openssl/err.h>
0016 #include <openssl/pem.h>
0017 #include "defines.h"
0018 #include "main.h"
0019
0020
0021
0022
0023
0024 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
0025
0026 struct q1q2_ctx {
0027 BN_CTX *bn_ctx;
0028 BIGNUM *m;
0029 BIGNUM *s;
0030 BIGNUM *q1;
0031 BIGNUM *qr;
0032 BIGNUM *q2;
0033 };
0034
0035 static void free_q1q2_ctx(struct q1q2_ctx *ctx)
0036 {
0037 BN_CTX_free(ctx->bn_ctx);
0038 BN_free(ctx->m);
0039 BN_free(ctx->s);
0040 BN_free(ctx->q1);
0041 BN_free(ctx->qr);
0042 BN_free(ctx->q2);
0043 }
0044
0045 static bool alloc_q1q2_ctx(const uint8_t *s, const uint8_t *m,
0046 struct q1q2_ctx *ctx)
0047 {
0048 ctx->bn_ctx = BN_CTX_new();
0049 ctx->s = BN_bin2bn(s, SGX_MODULUS_SIZE, NULL);
0050 ctx->m = BN_bin2bn(m, SGX_MODULUS_SIZE, NULL);
0051 ctx->q1 = BN_new();
0052 ctx->qr = BN_new();
0053 ctx->q2 = BN_new();
0054
0055 if (!ctx->bn_ctx || !ctx->s || !ctx->m || !ctx->q1 || !ctx->qr ||
0056 !ctx->q2) {
0057 free_q1q2_ctx(ctx);
0058 return false;
0059 }
0060
0061 return true;
0062 }
0063
0064 static void reverse_bytes(void *data, int length)
0065 {
0066 int i = 0;
0067 int j = length - 1;
0068 uint8_t temp;
0069 uint8_t *ptr = data;
0070
0071 while (i < j) {
0072 temp = ptr[i];
0073 ptr[i] = ptr[j];
0074 ptr[j] = temp;
0075 i++;
0076 j--;
0077 }
0078 }
0079
0080 static bool calc_q1q2(const uint8_t *s, const uint8_t *m, uint8_t *q1,
0081 uint8_t *q2)
0082 {
0083 struct q1q2_ctx ctx;
0084 int len;
0085
0086 if (!alloc_q1q2_ctx(s, m, &ctx)) {
0087 fprintf(stderr, "Not enough memory for Q1Q2 calculation\n");
0088 return false;
0089 }
0090
0091 if (!BN_mul(ctx.q1, ctx.s, ctx.s, ctx.bn_ctx))
0092 goto out;
0093
0094 if (!BN_div(ctx.q1, ctx.qr, ctx.q1, ctx.m, ctx.bn_ctx))
0095 goto out;
0096
0097 if (BN_num_bytes(ctx.q1) > SGX_MODULUS_SIZE) {
0098 fprintf(stderr, "Too large Q1 %d bytes\n",
0099 BN_num_bytes(ctx.q1));
0100 goto out;
0101 }
0102
0103 if (!BN_mul(ctx.q2, ctx.s, ctx.qr, ctx.bn_ctx))
0104 goto out;
0105
0106 if (!BN_div(ctx.q2, NULL, ctx.q2, ctx.m, ctx.bn_ctx))
0107 goto out;
0108
0109 if (BN_num_bytes(ctx.q2) > SGX_MODULUS_SIZE) {
0110 fprintf(stderr, "Too large Q2 %d bytes\n",
0111 BN_num_bytes(ctx.q2));
0112 goto out;
0113 }
0114
0115 len = BN_bn2bin(ctx.q1, q1);
0116 reverse_bytes(q1, len);
0117 len = BN_bn2bin(ctx.q2, q2);
0118 reverse_bytes(q2, len);
0119
0120 free_q1q2_ctx(&ctx);
0121 return true;
0122 out:
0123 free_q1q2_ctx(&ctx);
0124 return false;
0125 }
0126
0127 struct sgx_sigstruct_payload {
0128 struct sgx_sigstruct_header header;
0129 struct sgx_sigstruct_body body;
0130 };
0131
0132 static bool check_crypto_errors(void)
0133 {
0134 int err;
0135 bool had_errors = false;
0136 const char *filename;
0137 int line;
0138 char str[256];
0139
0140 for ( ; ; ) {
0141 if (ERR_peek_error() == 0)
0142 break;
0143
0144 had_errors = true;
0145 err = ERR_get_error_line(&filename, &line);
0146 ERR_error_string_n(err, str, sizeof(str));
0147 fprintf(stderr, "crypto: %s: %s:%d\n", str, filename, line);
0148 }
0149
0150 return had_errors;
0151 }
0152
0153 static inline const BIGNUM *get_modulus(RSA *key)
0154 {
0155 const BIGNUM *n;
0156
0157 RSA_get0_key(key, &n, NULL, NULL);
0158 return n;
0159 }
0160
0161 static RSA *gen_sign_key(void)
0162 {
0163 unsigned long sign_key_length;
0164 BIO *bio;
0165 RSA *key;
0166
0167 sign_key_length = (unsigned long)&sign_key_end -
0168 (unsigned long)&sign_key;
0169
0170 bio = BIO_new_mem_buf(&sign_key, sign_key_length);
0171 if (!bio)
0172 return NULL;
0173
0174 key = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
0175 BIO_free(bio);
0176
0177 return key;
0178 }
0179
0180 enum mrtags {
0181 MRECREATE = 0x0045544145524345,
0182 MREADD = 0x0000000044444145,
0183 MREEXTEND = 0x00444E4554584545,
0184 };
0185
0186 static bool mrenclave_update(EVP_MD_CTX *ctx, const void *data)
0187 {
0188 if (!EVP_DigestUpdate(ctx, data, 64)) {
0189 fprintf(stderr, "digest update failed\n");
0190 return false;
0191 }
0192
0193 return true;
0194 }
0195
0196 static bool mrenclave_commit(EVP_MD_CTX *ctx, uint8_t *mrenclave)
0197 {
0198 unsigned int size;
0199
0200 if (!EVP_DigestFinal_ex(ctx, (unsigned char *)mrenclave, &size)) {
0201 fprintf(stderr, "digest commit failed\n");
0202 return false;
0203 }
0204
0205 if (size != 32) {
0206 fprintf(stderr, "invalid digest size = %u\n", size);
0207 return false;
0208 }
0209
0210 return true;
0211 }
0212
0213 struct mrecreate {
0214 uint64_t tag;
0215 uint32_t ssaframesize;
0216 uint64_t size;
0217 uint8_t reserved[44];
0218 } __attribute__((__packed__));
0219
0220
0221 static bool mrenclave_ecreate(EVP_MD_CTX *ctx, uint64_t blob_size)
0222 {
0223 struct mrecreate mrecreate;
0224 uint64_t encl_size;
0225
0226 for (encl_size = 0x1000; encl_size < blob_size; )
0227 encl_size <<= 1;
0228
0229 memset(&mrecreate, 0, sizeof(mrecreate));
0230 mrecreate.tag = MRECREATE;
0231 mrecreate.ssaframesize = 1;
0232 mrecreate.size = encl_size;
0233
0234 if (!EVP_DigestInit_ex(ctx, EVP_sha256(), NULL))
0235 return false;
0236
0237 return mrenclave_update(ctx, &mrecreate);
0238 }
0239
0240 struct mreadd {
0241 uint64_t tag;
0242 uint64_t offset;
0243 uint64_t flags;
0244 uint8_t reserved[40];
0245 } __attribute__((__packed__));
0246
0247 static bool mrenclave_eadd(EVP_MD_CTX *ctx, uint64_t offset, uint64_t flags)
0248 {
0249 struct mreadd mreadd;
0250
0251 memset(&mreadd, 0, sizeof(mreadd));
0252 mreadd.tag = MREADD;
0253 mreadd.offset = offset;
0254 mreadd.flags = flags;
0255
0256 return mrenclave_update(ctx, &mreadd);
0257 }
0258
0259 struct mreextend {
0260 uint64_t tag;
0261 uint64_t offset;
0262 uint8_t reserved[48];
0263 } __attribute__((__packed__));
0264
0265 static bool mrenclave_eextend(EVP_MD_CTX *ctx, uint64_t offset,
0266 const uint8_t *data)
0267 {
0268 struct mreextend mreextend;
0269 int i;
0270
0271 for (i = 0; i < 0x1000; i += 0x100) {
0272 memset(&mreextend, 0, sizeof(mreextend));
0273 mreextend.tag = MREEXTEND;
0274 mreextend.offset = offset + i;
0275
0276 if (!mrenclave_update(ctx, &mreextend))
0277 return false;
0278
0279 if (!mrenclave_update(ctx, &data[i + 0x00]))
0280 return false;
0281
0282 if (!mrenclave_update(ctx, &data[i + 0x40]))
0283 return false;
0284
0285 if (!mrenclave_update(ctx, &data[i + 0x80]))
0286 return false;
0287
0288 if (!mrenclave_update(ctx, &data[i + 0xC0]))
0289 return false;
0290 }
0291
0292 return true;
0293 }
0294
0295 static bool mrenclave_segment(EVP_MD_CTX *ctx, struct encl *encl,
0296 struct encl_segment *seg)
0297 {
0298 uint64_t end = seg->size;
0299 uint64_t offset;
0300
0301 for (offset = 0; offset < end; offset += PAGE_SIZE) {
0302 if (!mrenclave_eadd(ctx, seg->offset + offset, seg->flags))
0303 return false;
0304
0305 if (seg->measure) {
0306 if (!mrenclave_eextend(ctx, seg->offset + offset, seg->src + offset))
0307 return false;
0308 }
0309 }
0310
0311 return true;
0312 }
0313
0314 bool encl_measure(struct encl *encl)
0315 {
0316 uint64_t header1[2] = {0x000000E100000006, 0x0000000000010000};
0317 uint64_t header2[2] = {0x0000006000000101, 0x0000000100000060};
0318 struct sgx_sigstruct *sigstruct = &encl->sigstruct;
0319 struct sgx_sigstruct_payload payload;
0320 uint8_t digest[SHA256_DIGEST_LENGTH];
0321 unsigned int siglen;
0322 RSA *key = NULL;
0323 EVP_MD_CTX *ctx;
0324 int i;
0325
0326 memset(sigstruct, 0, sizeof(*sigstruct));
0327
0328 sigstruct->header.header1[0] = header1[0];
0329 sigstruct->header.header1[1] = header1[1];
0330 sigstruct->header.header2[0] = header2[0];
0331 sigstruct->header.header2[1] = header2[1];
0332 sigstruct->exponent = 3;
0333 sigstruct->body.attributes = SGX_ATTR_MODE64BIT;
0334 sigstruct->body.xfrm = 3;
0335
0336
0337 if (check_crypto_errors())
0338 goto err;
0339
0340 key = gen_sign_key();
0341 if (!key) {
0342 ERR_print_errors_fp(stdout);
0343 goto err;
0344 }
0345
0346 BN_bn2bin(get_modulus(key), sigstruct->modulus);
0347
0348 ctx = EVP_MD_CTX_create();
0349 if (!ctx)
0350 goto err;
0351
0352 if (!mrenclave_ecreate(ctx, encl->src_size))
0353 goto err;
0354
0355 for (i = 0; i < encl->nr_segments; i++) {
0356 struct encl_segment *seg = &encl->segment_tbl[i];
0357
0358 if (!mrenclave_segment(ctx, encl, seg))
0359 goto err;
0360 }
0361
0362 if (!mrenclave_commit(ctx, sigstruct->body.mrenclave))
0363 goto err;
0364
0365 memcpy(&payload.header, &sigstruct->header, sizeof(sigstruct->header));
0366 memcpy(&payload.body, &sigstruct->body, sizeof(sigstruct->body));
0367
0368 SHA256((unsigned char *)&payload, sizeof(payload), digest);
0369
0370 if (!RSA_sign(NID_sha256, digest, SHA256_DIGEST_LENGTH,
0371 sigstruct->signature, &siglen, key))
0372 goto err;
0373
0374 if (!calc_q1q2(sigstruct->signature, sigstruct->modulus, sigstruct->q1,
0375 sigstruct->q2))
0376 goto err;
0377
0378
0379 reverse_bytes(sigstruct->signature, SGX_MODULUS_SIZE);
0380 reverse_bytes(sigstruct->modulus, SGX_MODULUS_SIZE);
0381
0382 EVP_MD_CTX_destroy(ctx);
0383 RSA_free(key);
0384 return true;
0385
0386 err:
0387 EVP_MD_CTX_destroy(ctx);
0388 RSA_free(key);
0389 return false;
0390 }