cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

crypto-tls-x509-helpers.c (16204B)


      1/*
      2 * Copyright (C) 2015 Red Hat, Inc.
      3 *
      4 * This library is free software; you can redistribute it and/or
      5 * modify it under the terms of the GNU Lesser General Public
      6 * License as published by the Free Software Foundation; either
      7 * version 2.1 of the License, or (at your option) any later version.
      8 *
      9 * This library is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12 * Lesser General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU Lesser General Public
     15 * License along with this library.  If not, see
     16 * <http://www.gnu.org/licenses/>.
     17 *
     18 * Author: Daniel P. Berrange <berrange@redhat.com>
     19 */
     20
     21#include "qemu/osdep.h"
     22
     23#include "crypto-tls-x509-helpers.h"
     24#include "crypto/init.h"
     25#include "qemu/sockets.h"
     26
     27/*
     28 * This stores some static data that is needed when
     29 * encoding extensions in the x509 certs
     30 */
     31asn1_node pkix_asn1;
     32
     33/*
     34 * To avoid consuming random entropy to generate keys,
     35 * here's one we prepared earlier :-)
     36 */
     37gnutls_x509_privkey_t privkey;
     38# define PRIVATE_KEY \
     39    "-----BEGIN RSA PRIVATE KEY-----\n" \
     40    "MIIG5AIBAAKCAYEAyjWyLSNm5PZvYUKUcDWGqbLX10b2ood+YaFjWSnJrqx/q3qh\n" \
     41    "rVGBJglD25AJENJsmZF3zPP1oMhfIxsXu63Hdkb6Rdlc2RUoUP34x9VC1izH25mR\n" \
     42    "6c8DPDp1d6IraZ/llDMI1HsBFz0qGWtvOHgm815XG4PAr/N8rDsuqfv/cJ01KlnO\n" \
     43    "0OdO5QRXCJf9g/dYd41MPu7wOXk9FqjQlmRoP59HgtJ+zUpE4z+Keruw9cMT9VJj\n" \
     44    "0oT+pQ9ysenqeZ3gbT224T1khrEhT5kifhtFLNyDssRchUUWH0hiqoOO1vgb+850\n" \
     45    "W6/1VdxvuPam48py4diSPi1Vip8NITCOBaX9FIpVp4Ruw4rTPVMNMjq9Cpx/DwMP\n" \
     46    "9MbfXfnaVaZaMrmq67/zPhl0eVbUrecH2hQ3ZB9oIF4GkNskzlWF5+yPy6zqk304\n" \
     47    "AKaiFR6jRyh3YfHo2XFqV8x/hxdsIEXOtEUGhSIcpynsW+ckUCartzu7xbhXjd4b\n" \
     48    "kxJT89+riPFYij09AgMBAAECggGBAKyFkaZXXROeejrmHlV6JZGlp+fhgM38gkRz\n" \
     49    "+Jp7P7rLLAY3E7gXIPQ91WqAAmwazFNdvHPd9USfkCQYmnAi/VoZhrCPmlsQZRxt\n" \
     50    "A5QjjOnEvSPMa6SrXZxGWDCg6R8uMCb4P+FhrPWR1thnRDZOtRTQ+crc50p3mHgt\n" \
     51    "6ktXWIJRbqnag8zSfQqCYGtRmhe8sfsWT+Yl4El4+jjaAVU/B364u7+PLmaiphGp\n" \
     52    "BdJfTsTwEpgtGkPj+osDmhzXcZkfq3V+fz5JLkemsCiQKmn4VJRpg8c3ZmE8NPNt\n" \
     53    "gRtGWZ4W3WKDvhotT65WpQx4+6R8Duux/blNPBmH1Upmwd7kj7GYFBArbCjgd9PT\n" \
     54    "xgfCSUZpgOZHHkcgSB+022a8XncXna7WYYij28SLtwImFyu0nNtqECFQHH5u+k6C\n" \
     55    "LRYBSN+3t3At8dQuk01NVrJBndmjmXRfxpqUtTdeaNgVpdUYRY98s30G68NYGSra\n" \
     56    "aEvhhRSghkcLNetkobpY9pUgeqW/tQKBwQDZHHK9nDMt/zk1TxtILeUSitPXcv1/\n" \
     57    "8ufXqO0miHdH23XuXhIEA6Ef26RRVGDGgpjkveDJK/1w5feJ4H/ni4Vclil/cm38\n" \
     58    "OwRqjjd7ElHJX6JQbsxEx/gNTk5/QW1iAL9TXUalgepsSXYT6AJ0/CJv0jmJSJ36\n" \
     59    "YoKMOM8uqzb2KhN6i+RlJRi5iY53kUhWTJq5ArWvNhUzQNSYODI4bNxlsKSBL2Ik\n" \
     60    "LZ5QKHuaEjQet0IlPlfIb4PzMm8CHa/urOcCgcEA7m3zW/lL5bIFoKPjWig5Lbn1\n" \
     61    "aHfrG2ngqzWtgWtfZqMH8OkZc1Mdhhmvd46titjiLjeI+UP/uHXR0068PnrNngzl\n" \
     62    "tTgwlakzu+bWzqhBm1F+3/341st/FEk07r0P/3/PhezVjwfO8c8Exj7pLxH4wrH0\n" \
     63    "ROHgDbClmlJRu6OO78wk1+Vapf5DWa8YfA+q+fdvr7KvgGyytheKMT/b/dsqOq7y\n" \
     64    "qZPjmaJKWAvV3RWG8lWHFSdHx2IAHMHfGr17Y/w7AoHBALzwZeYebeekiVucGSjq\n" \
     65    "T8SgLhT7zCIx+JMUPjVfYzaUhP/Iu7Lkma6IzWm9nW6Drpy5pUpMzwUWDCLfzU9q\n" \
     66    "eseFIl337kEn9wLn+t5OpgAyCqYmlftxbqvdrrBN9uvnrJjWvqk/8wsDrw9JxAGc\n" \
     67    "fjeD4nBXUqvYWLXApoR9mZoGKedmoH9pFig4zlO9ig8YITnKYuQ0k6SD0b8agJHc\n" \
     68    "Ir0YSUDnRGgpjvFBGbeOCe+FGbohk/EpItJc3IAh5740lwKBwAdXd2DjokSmYKn7\n" \
     69    "oeqKxofz6+yVlLW5YuOiuX78sWlVp87xPolgi84vSEnkKM/Xsc8+goc6YstpRVa+\n" \
     70    "W+mImoA9YW1dF5HkLeWhTAf9AlgoAEIhbeIfTgBv6KNZSv7RDrDPBBxtXx/vAfSg\n" \
     71    "x0ldwk0scZsVYXLKd67yzfV7KdGUdaX4N/xYgfZm/9gCG3+q8NN2KxVHQ5F71BOE\n" \
     72    "JeABOaGo9WvnU+DNMIDZjHJMUWVw4MHz/a/UArDf/2CxaPVBNQKBwASg6j4ohSTk\n" \
     73    "J7aE6RQ3OBmmDDpixcoCJt9u9SjHVYMlbs5CEJGVSczk0SG3y8P1lOWNDSRnMksZ\n" \
     74    "xWnHdP/ogcuYMuvK7UACNAF0zNddtzOhzcpNmejFj+WCHYY/UmPr2/Kf6t7Cxk2K\n" \
     75    "3cZ4tqWsiTmBT8Bknmah7L5DrhS+ZBJliDeFAA8fZHdMH0Xjr4UBp9kF90EMTdW1\n" \
     76    "Xr5uz7ZrMsYpYQI7mmyqV9SSjUg4iBXwVSoag1iDJ1K8Qg/L7Semgg==\n" \
     77    "-----END RSA PRIVATE KEY-----\n"
     78
     79/*
     80 * This loads the private key we defined earlier
     81 */
     82static gnutls_x509_privkey_t test_tls_load_key(void)
     83{
     84    gnutls_x509_privkey_t key;
     85    const gnutls_datum_t data = { (unsigned char *)PRIVATE_KEY,
     86                                  strlen(PRIVATE_KEY) };
     87    int err;
     88
     89    err = gnutls_x509_privkey_init(&key);
     90    if (err < 0) {
     91        g_critical("Failed to init key %s", gnutls_strerror(err));
     92        abort();
     93    }
     94
     95    err = gnutls_x509_privkey_import(key, &data,
     96                                     GNUTLS_X509_FMT_PEM);
     97    if (err < 0) {
     98        if (err != GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR &&
     99            err != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
    100            g_critical("Failed to import key %s", gnutls_strerror(err));
    101            abort();
    102        }
    103
    104        err = gnutls_x509_privkey_import_pkcs8(
    105            key, &data, GNUTLS_X509_FMT_PEM, NULL, 0);
    106        if (err < 0) {
    107            g_critical("Failed to import PKCS8 key %s", gnutls_strerror(err));
    108            abort();
    109        }
    110    }
    111
    112    return key;
    113}
    114
    115
    116void test_tls_init(const char *keyfile)
    117{
    118    qcrypto_init(&error_abort);
    119
    120    if (asn1_array2tree(pkix_asn1_tab, &pkix_asn1, NULL) != ASN1_SUCCESS) {
    121        abort();
    122    }
    123
    124    privkey = test_tls_load_key();
    125    if (!g_file_set_contents(keyfile, PRIVATE_KEY, -1, NULL)) {
    126        abort();
    127    }
    128}
    129
    130
    131void test_tls_cleanup(const char *keyfile)
    132{
    133    asn1_delete_structure(&pkix_asn1);
    134    unlink(keyfile);
    135}
    136
    137/*
    138 * Turns an ASN1 object into a DER encoded byte array
    139 */
    140static void test_tls_der_encode(asn1_node src,
    141                                const char *src_name,
    142                                gnutls_datum_t *res)
    143{
    144  int size;
    145  char *data = NULL;
    146
    147  size = 0;
    148  asn1_der_coding(src, src_name, NULL, &size, NULL);
    149
    150  data = g_new0(char, size);
    151
    152  asn1_der_coding(src, src_name, data, &size, NULL);
    153
    154  res->data = (unsigned char *)data;
    155  res->size = size;
    156}
    157
    158
    159static void
    160test_tls_get_ipaddr(const char *addrstr,
    161                    char **data,
    162                    int *datalen)
    163{
    164    struct addrinfo *res;
    165    struct addrinfo hints;
    166
    167    memset(&hints, 0, sizeof(hints));
    168    hints.ai_flags = AI_NUMERICHOST;
    169    g_assert(getaddrinfo(addrstr, NULL, &hints, &res) == 0);
    170
    171    *datalen = res->ai_addrlen;
    172    *data = g_new(char, *datalen);
    173    memcpy(*data, res->ai_addr, *datalen);
    174    freeaddrinfo(res);
    175}
    176
    177/*
    178 * This is a fairly lame x509 certificate generator.
    179 *
    180 * Do not copy/use this code for generating real certificates
    181 * since it leaves out many things that you would want in
    182 * certificates for real world usage.
    183 *
    184 * This is good enough only for doing tests of the QEMU
    185 * TLS certificate code
    186 */
    187void
    188test_tls_generate_cert(QCryptoTLSTestCertReq *req,
    189                       gnutls_x509_crt_t ca)
    190{
    191    gnutls_x509_crt_t crt;
    192    int err;
    193    static char buffer[1024 * 1024];
    194    size_t size = sizeof(buffer);
    195    char serial[5] = { 1, 2, 3, 4, 0 };
    196    gnutls_datum_t der;
    197    time_t start = time(NULL) + (60 * 60 * req->start_offset);
    198    time_t expire = time(NULL) + (60 * 60 * (req->expire_offset
    199                                             ? req->expire_offset : 24));
    200
    201    /*
    202     * Prepare our new certificate object
    203     */
    204    err = gnutls_x509_crt_init(&crt);
    205    if (err < 0) {
    206        g_critical("Failed to initialize certificate %s", gnutls_strerror(err));
    207        abort();
    208    }
    209    err = gnutls_x509_crt_set_key(crt, privkey);
    210    if (err < 0) {
    211        g_critical("Failed to set certificate key %s", gnutls_strerror(err));
    212        abort();
    213    }
    214
    215    /*
    216     * A v3 certificate is required in order to be able
    217     * set any of the basic constraints, key purpose and
    218     * key usage data
    219     */
    220    gnutls_x509_crt_set_version(crt, 3);
    221
    222    if (req->country) {
    223        err = gnutls_x509_crt_set_dn_by_oid(
    224            crt, GNUTLS_OID_X520_COUNTRY_NAME, 0,
    225            req->country, strlen(req->country));
    226        if (err < 0) {
    227            g_critical("Failed to set certificate country name %s",
    228                       gnutls_strerror(err));
    229            abort();
    230        }
    231    }
    232    if (req->cn) {
    233        err = gnutls_x509_crt_set_dn_by_oid(
    234            crt, GNUTLS_OID_X520_COMMON_NAME, 0,
    235            req->cn, strlen(req->cn));
    236        if (err < 0) {
    237            g_critical("Failed to set certificate common name %s",
    238                       gnutls_strerror(err));
    239            abort();
    240        }
    241    }
    242
    243    /*
    244     * Setup the subject altnames, which are used
    245     * for hostname checks in live sessions
    246     */
    247    if (req->altname1) {
    248        err = gnutls_x509_crt_set_subject_alt_name(
    249            crt, GNUTLS_SAN_DNSNAME,
    250            req->altname1,
    251            strlen(req->altname1),
    252            GNUTLS_FSAN_APPEND);
    253        if (err < 0) {
    254            g_critical("Failed to set certificate alt name %s",
    255                       gnutls_strerror(err));
    256            abort();
    257        }
    258    }
    259    if (req->altname2) {
    260        err = gnutls_x509_crt_set_subject_alt_name(
    261            crt, GNUTLS_SAN_DNSNAME,
    262            req->altname2,
    263            strlen(req->altname2),
    264            GNUTLS_FSAN_APPEND);
    265        if (err < 0) {
    266            g_critical("Failed to set certificate %s alt name",
    267                       gnutls_strerror(err));
    268            abort();
    269        }
    270    }
    271
    272    /*
    273     * IP address need to be put into the cert in their
    274     * raw byte form, not strings, hence this is a little
    275     * more complicated
    276     */
    277    if (req->ipaddr1) {
    278        char *data;
    279        int len;
    280
    281        test_tls_get_ipaddr(req->ipaddr1, &data, &len);
    282
    283        err = gnutls_x509_crt_set_subject_alt_name(
    284            crt, GNUTLS_SAN_IPADDRESS,
    285            data, len, GNUTLS_FSAN_APPEND);
    286        if (err < 0) {
    287            g_critical("Failed to set certificate alt name %s",
    288                       gnutls_strerror(err));
    289            abort();
    290        }
    291        g_free(data);
    292    }
    293    if (req->ipaddr2) {
    294        char *data;
    295        int len;
    296
    297        test_tls_get_ipaddr(req->ipaddr2, &data, &len);
    298
    299        err = gnutls_x509_crt_set_subject_alt_name(
    300            crt, GNUTLS_SAN_IPADDRESS,
    301            data, len, GNUTLS_FSAN_APPEND);
    302        if (err < 0) {
    303            g_critical("Failed to set certificate alt name %s",
    304                       gnutls_strerror(err));
    305            abort();
    306        }
    307        g_free(data);
    308    }
    309
    310
    311    /*
    312     * Basic constraints are used to decide if the cert
    313     * is for a CA or not. We can't use the convenient
    314     * gnutls API for setting this, since it hardcodes
    315     * the 'critical' field which we want control over
    316     */
    317    if (req->basicConstraintsEnable) {
    318        asn1_node ext = NULL;
    319
    320        asn1_create_element(pkix_asn1, "PKIX1.BasicConstraints", &ext);
    321        asn1_write_value(ext, "cA",
    322                         req->basicConstraintsIsCA ? "TRUE" : "FALSE", 1);
    323        asn1_write_value(ext, "pathLenConstraint", NULL, 0);
    324        test_tls_der_encode(ext, "", &der);
    325        err = gnutls_x509_crt_set_extension_by_oid(
    326            crt, "2.5.29.19",
    327            der.data, der.size,
    328            req->basicConstraintsCritical);
    329        if (err < 0) {
    330            g_critical("Failed to set certificate basic constraints %s",
    331                       gnutls_strerror(err));
    332            g_free(der.data);
    333            abort();
    334        }
    335        asn1_delete_structure(&ext);
    336        g_free(der.data);
    337    }
    338
    339    /*
    340     * Next up the key usage extension. Again we can't
    341     * use the gnutls API since it hardcodes the extension
    342     * to be 'critical'
    343     */
    344    if (req->keyUsageEnable) {
    345        asn1_node ext = NULL;
    346        char str[2];
    347
    348        str[0] = req->keyUsageValue & 0xff;
    349        str[1] = (req->keyUsageValue >> 8) & 0xff;
    350
    351        asn1_create_element(pkix_asn1, "PKIX1.KeyUsage", &ext);
    352        asn1_write_value(ext, "", str, 9);
    353        test_tls_der_encode(ext, "", &der);
    354        err = gnutls_x509_crt_set_extension_by_oid(
    355            crt, "2.5.29.15",
    356            der.data, der.size,
    357            req->keyUsageCritical);
    358        if (err < 0) {
    359            g_critical("Failed to set certificate key usage %s",
    360                       gnutls_strerror(err));
    361            g_free(der.data);
    362            abort();
    363        }
    364        asn1_delete_structure(&ext);
    365        g_free(der.data);
    366    }
    367
    368    /*
    369     * Finally the key purpose extension. This time
    370     * gnutls has the opposite problem, always hardcoding
    371     * it to be non-critical. So once again we have to
    372     * set this the hard way building up ASN1 data ourselves
    373     */
    374    if (req->keyPurposeEnable) {
    375        asn1_node ext = NULL;
    376
    377        asn1_create_element(pkix_asn1, "PKIX1.ExtKeyUsageSyntax", &ext);
    378        if (req->keyPurposeOID1) {
    379            asn1_write_value(ext, "", "NEW", 1);
    380            asn1_write_value(ext, "?LAST", req->keyPurposeOID1, 1);
    381        }
    382        if (req->keyPurposeOID2) {
    383            asn1_write_value(ext, "", "NEW", 1);
    384            asn1_write_value(ext, "?LAST", req->keyPurposeOID2, 1);
    385        }
    386        test_tls_der_encode(ext, "", &der);
    387        err = gnutls_x509_crt_set_extension_by_oid(
    388            crt, "2.5.29.37",
    389            der.data, der.size,
    390            req->keyPurposeCritical);
    391        if (err < 0) {
    392            g_critical("Failed to set certificate key purpose %s",
    393                       gnutls_strerror(err));
    394            g_free(der.data);
    395            abort();
    396        }
    397        asn1_delete_structure(&ext);
    398        g_free(der.data);
    399    }
    400
    401    /*
    402     * Any old serial number will do, so lets pick 5
    403     */
    404    err = gnutls_x509_crt_set_serial(crt, serial, 5);
    405    if (err < 0) {
    406        g_critical("Failed to set certificate serial %s",
    407                   gnutls_strerror(err));
    408        abort();
    409    }
    410
    411    err = gnutls_x509_crt_set_activation_time(crt, start);
    412    if (err < 0) {
    413        g_critical("Failed to set certificate activation %s",
    414                   gnutls_strerror(err));
    415        abort();
    416    }
    417    err = gnutls_x509_crt_set_expiration_time(crt, expire);
    418    if (err < 0) {
    419        g_critical("Failed to set certificate expiration %s",
    420                   gnutls_strerror(err));
    421        abort();
    422    }
    423
    424
    425    /*
    426     * If no 'ca' is set then we are self signing
    427     * the cert. This is done for the root CA certs
    428     */
    429    err = gnutls_x509_crt_sign2(crt, ca ? ca : crt, privkey,
    430                                GNUTLS_DIG_SHA256, 0);
    431    if (err < 0) {
    432        g_critical("Failed to sign certificate %s",
    433                   gnutls_strerror(err));
    434        abort();
    435    }
    436
    437    /*
    438     * Finally write the new cert out to disk
    439     */
    440    err = gnutls_x509_crt_export(
    441        crt, GNUTLS_X509_FMT_PEM, buffer, &size);
    442    if (err < 0) {
    443        g_critical("Failed to export certificate %s: %d",
    444                   gnutls_strerror(err), err);
    445        abort();
    446    }
    447
    448    if (!g_file_set_contents(req->filename, buffer, -1, NULL)) {
    449        g_critical("Failed to write certificate %s",
    450                   req->filename);
    451        abort();
    452    }
    453
    454    req->crt = crt;
    455}
    456
    457
    458void test_tls_write_cert_chain(const char *filename,
    459                               gnutls_x509_crt_t *certs,
    460                               size_t ncerts)
    461{
    462    size_t i;
    463    size_t capacity = 1024, offset = 0;
    464    char *buffer = g_new0(char, capacity);
    465    int err;
    466
    467    for (i = 0; i < ncerts; i++) {
    468        size_t len = capacity - offset;
    469    retry:
    470        err = gnutls_x509_crt_export(certs[i], GNUTLS_X509_FMT_PEM,
    471                                     buffer + offset, &len);
    472        if (err < 0) {
    473            if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) {
    474                buffer = g_renew(char, buffer, offset + len);
    475                capacity = offset + len;
    476                goto retry;
    477            }
    478            g_critical("Failed to export certificate chain %s: %d",
    479                       gnutls_strerror(err), err);
    480            abort();
    481        }
    482        offset += len;
    483    }
    484
    485    if (!g_file_set_contents(filename, buffer, offset, NULL)) {
    486        abort();
    487    }
    488    g_free(buffer);
    489}
    490
    491
    492void test_tls_discard_cert(QCryptoTLSTestCertReq *req)
    493{
    494    if (!req->crt) {
    495        return;
    496    }
    497
    498    gnutls_x509_crt_deinit(req->crt);
    499    req->crt = NULL;
    500
    501    if (getenv("QEMU_TEST_DEBUG_CERTS") == NULL) {
    502        unlink(req->filename);
    503    }
    504}