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