Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*  Copyright(c) 2016-20 Intel Corporation. */
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  * FIXME: OpenSSL 3.0 has deprecated some functions. For now just ignore
0022  * the warnings.
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; /* SECINFO 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     /* sanity check */
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     /* BE -> LE */
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 }