Home | History | Annotate | Line # | Download | only in test
      1      1.1  christos /*
      2      1.1  christos  * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
      3      1.1  christos  *
      4      1.1  christos  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5      1.1  christos  * this file except in compliance with the License.  You can obtain a copy
      6      1.1  christos  * in the file LICENSE in the source distribution or at
      7      1.1  christos  * https://www.openssl.org/source/license.html
      8      1.1  christos  */
      9      1.1  christos 
     10      1.1  christos #include <stdio.h>
     11      1.1  christos #include <stdlib.h>
     12      1.1  christos #include <string.h>
     13      1.1  christos #include "testutil.h"
     14      1.1  christos #include "internal/cryptlib.h"
     15      1.1  christos 
     16  1.1.1.2  christos #if (defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) && defined(OPENSSL_CPUID_OBJ)
     17  1.1.1.2  christos #define IS_X_86 1
     18      1.1  christos size_t OPENSSL_ia32_rdrand_bytes(unsigned char *buf, size_t len);
     19      1.1  christos size_t OPENSSL_ia32_rdseed_bytes(unsigned char *buf, size_t len);
     20      1.1  christos #else
     21  1.1.1.2  christos #define IS_X_86 0
     22      1.1  christos #endif
     23      1.1  christos 
     24      1.1  christos #if defined(__aarch64__) && defined(OPENSSL_CPUID_OBJ)
     25  1.1.1.2  christos #define IS_AARCH_64 1
     26  1.1.1.2  christos #include "arm_arch.h"
     27      1.1  christos 
     28      1.1  christos size_t OPENSSL_rndr_bytes(unsigned char *buf, size_t len);
     29      1.1  christos size_t OPENSSL_rndrrs_bytes(unsigned char *buf, size_t len);
     30      1.1  christos #else
     31  1.1.1.2  christos #define IS_AARCH_64 0
     32      1.1  christos #endif
     33      1.1  christos 
     34      1.1  christos #if (IS_X_86 || IS_AARCH_64)
     35      1.1  christos static int sanity_check_bytes(size_t (*rng)(unsigned char *, size_t),
     36      1.1  christos     int rounds, int min_failures, int max_retries, int max_zero_words)
     37      1.1  christos {
     38      1.1  christos     int testresult = 0;
     39  1.1.1.2  christos     unsigned char prior[31] = { 0 }, buf[31] = { 0 }, check[7];
     40      1.1  christos     int failures = 0, zero_words = 0;
     41      1.1  christos 
     42      1.1  christos     int i;
     43      1.1  christos     for (i = 0; i < rounds; i++) {
     44      1.1  christos         size_t generated = 0;
     45      1.1  christos 
     46      1.1  christos         int retry;
     47      1.1  christos         for (retry = 0; retry < max_retries; retry++) {
     48      1.1  christos             generated = rng(buf, sizeof(buf));
     49      1.1  christos             if (generated == sizeof(buf))
     50      1.1  christos                 break;
     51      1.1  christos             failures++;
     52      1.1  christos         }
     53      1.1  christos 
     54      1.1  christos         /*-
     55      1.1  christos          * Verify that we don't have too many unexpected runs of zeroes,
     56      1.1  christos          * implying that we might be accidentally using the 32-bit RDRAND
     57      1.1  christos          * instead of the 64-bit one on 64-bit systems.
     58      1.1  christos          */
     59      1.1  christos         size_t j;
     60      1.1  christos         for (j = 0; j < sizeof(buf) - 1; j++) {
     61  1.1.1.2  christos             if (buf[j] == 0 && buf[j + 1] == 0) {
     62      1.1  christos                 zero_words++;
     63      1.1  christos             }
     64      1.1  christos         }
     65      1.1  christos 
     66      1.1  christos         if (!TEST_int_eq(generated, sizeof(buf)))
     67      1.1  christos             goto end;
     68      1.1  christos         if (!TEST_false(!memcmp(prior, buf, sizeof(buf))))
     69      1.1  christos             goto end;
     70      1.1  christos 
     71      1.1  christos         /* Verify that the last 7 bytes of buf aren't all the same value */
     72      1.1  christos         unsigned char *tail = &buf[sizeof(buf) - sizeof(check)];
     73      1.1  christos         memset(check, tail[0], 7);
     74      1.1  christos         if (!TEST_false(!memcmp(check, tail, sizeof(check))))
     75      1.1  christos             goto end;
     76      1.1  christos 
     77      1.1  christos         /* Save the result and make sure it's different next time */
     78      1.1  christos         memcpy(prior, buf, sizeof(buf));
     79      1.1  christos     }
     80      1.1  christos 
     81      1.1  christos     if (!TEST_int_le(zero_words, max_zero_words))
     82      1.1  christos         goto end;
     83      1.1  christos 
     84      1.1  christos     if (!TEST_int_ge(failures, min_failures))
     85      1.1  christos         goto end;
     86      1.1  christos 
     87      1.1  christos     testresult = 1;
     88      1.1  christos end:
     89      1.1  christos     return testresult;
     90      1.1  christos }
     91      1.1  christos #endif
     92      1.1  christos 
     93      1.1  christos #if IS_X_86
     94      1.1  christos static int sanity_check_rdrand_bytes(void)
     95      1.1  christos {
     96      1.1  christos     return sanity_check_bytes(OPENSSL_ia32_rdrand_bytes, 1000, 0, 10, 10);
     97      1.1  christos }
     98      1.1  christos 
     99      1.1  christos static int sanity_check_rdseed_bytes(void)
    100      1.1  christos {
    101      1.1  christos     /*-
    102      1.1  christos      * RDSEED may take many retries to succeed; note that this is effectively
    103      1.1  christos      * multiplied by the 8x retry loop in asm, and failure probabilities are
    104      1.1  christos      * increased by the fact that we need either 4 or 8 samples depending on
    105      1.1  christos      * the platform.
    106      1.1  christos      */
    107      1.1  christos     return sanity_check_bytes(OPENSSL_ia32_rdseed_bytes, 1000, 1, 10000, 10);
    108      1.1  christos }
    109      1.1  christos #elif IS_AARCH_64
    110      1.1  christos static int sanity_check_rndr_bytes(void)
    111      1.1  christos {
    112      1.1  christos     return sanity_check_bytes(OPENSSL_rndr_bytes, 1000, 0, 10, 10);
    113      1.1  christos }
    114      1.1  christos 
    115      1.1  christos static int sanity_check_rndrrs_bytes(void)
    116      1.1  christos {
    117      1.1  christos     return sanity_check_bytes(OPENSSL_rndrrs_bytes, 1000, 0, 10000, 10);
    118      1.1  christos }
    119      1.1  christos #endif
    120      1.1  christos 
    121      1.1  christos int setup_tests(void)
    122      1.1  christos {
    123      1.1  christos #if (IS_X_86 || IS_AARCH_64)
    124      1.1  christos     OPENSSL_cpuid_setup();
    125      1.1  christos 
    126  1.1.1.2  christos #if IS_X_86
    127      1.1  christos     int have_rdseed = (OPENSSL_ia32cap_P[2] & (1 << 18)) != 0;
    128      1.1  christos     int have_rdrand = (OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) != 0;
    129      1.1  christos 
    130      1.1  christos     if (have_rdrand) {
    131      1.1  christos         ADD_TEST(sanity_check_rdrand_bytes);
    132      1.1  christos     }
    133      1.1  christos 
    134      1.1  christos     if (have_rdseed) {
    135      1.1  christos         ADD_TEST(sanity_check_rdseed_bytes);
    136      1.1  christos     }
    137  1.1.1.2  christos #elif IS_AARCH_64
    138      1.1  christos     int have_rndr_rndrrs = (OPENSSL_armcap_P & (1 << 8)) != 0;
    139      1.1  christos 
    140      1.1  christos     if (have_rndr_rndrrs) {
    141      1.1  christos         ADD_TEST(sanity_check_rndr_bytes);
    142      1.1  christos         ADD_TEST(sanity_check_rndrrs_bytes);
    143      1.1  christos     }
    144  1.1.1.2  christos #endif
    145      1.1  christos #endif
    146      1.1  christos 
    147      1.1  christos     return 1;
    148      1.1  christos }
    149