Home | History | Annotate | Line # | Download | only in seeding
      1 /*
      2  * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #include "internal/cryptlib.h"
     11 #include <openssl/opensslconf.h>
     12 #include "crypto/rand_pool.h"
     13 #include "prov/seeding.h"
     14 
     15 #ifdef OPENSSL_RAND_SEED_RDCPU
     16 #include "crypto/arm_arch.h"
     17 
     18 size_t OPENSSL_rndrrs_bytes(unsigned char *buf, size_t len);
     19 
     20 static size_t get_hardware_random_value(unsigned char *buf, size_t len);
     21 
     22 /*
     23  * Acquire entropy using Arm-specific cpu instructions
     24  *
     25  * Uses the RNDRRS instruction. RNDR is never needed since
     26  * RNDRRS will always be available if RNDR is an available
     27  * instruction.
     28  *
     29  * Returns the total entropy count, if it exceeds the requested
     30  * entropy count. Otherwise, returns an entropy count of 0.
     31  */
     32 size_t ossl_prov_acquire_entropy_from_cpu(RAND_POOL *pool)
     33 {
     34     size_t bytes_needed;
     35     unsigned char *buffer;
     36 
     37     bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
     38     if (bytes_needed > 0) {
     39         buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
     40 
     41         if (buffer != NULL) {
     42             if (get_hardware_random_value(buffer, bytes_needed) == bytes_needed)
     43                 ossl_rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
     44             else
     45                 ossl_rand_pool_add_end(pool, 0, 0);
     46         }
     47     }
     48 
     49     return ossl_rand_pool_entropy_available(pool);
     50 }
     51 
     52 static size_t get_hardware_random_value(unsigned char *buf, size_t len)
     53 {
     54     /* Always use RNDRRS or nothing */
     55     if (OPENSSL_armcap_P & ARMV8_RNG) {
     56         if (OPENSSL_rndrrs_bytes(buf, len) != len)
     57             return 0;
     58     } else {
     59         return 0;
     60     }
     61     return len;
     62 }
     63 
     64 #else
     65 NON_EMPTY_TRANSLATION_UNIT
     66 #endif /* OPENSSL_RAND_SEED_RDCPU */
     67