| 1 | /* Copyright (c) (2021,2022) Apple Inc. All rights reserved. |
| 2 | * |
| 3 | * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which |
| 4 | * is contained in the License.txt file distributed with corecrypto) and only to |
| 5 | * people who accept that license. IMPORTANT: Any license rights granted to you by |
| 6 | * Apple Inc. (if any) are limited to internal use within your organization only on |
| 7 | * devices and computers you own or control, for the sole purpose of verifying the |
| 8 | * security characteristics and correct functioning of the Apple Software. You may |
| 9 | * not, directly or indirectly, redistribute the Apple Software or any portions thereof. |
| 10 | */ |
| 11 | |
| 12 | #ifndef _CORECRYPTO_CCRNG_SCHEDULE_H_ |
| 13 | #define _CORECRYPTO_CCRNG_SCHEDULE_H_ |
| 14 | |
| 15 | #include <corecrypto/cc.h> |
| 16 | #include <corecrypto/ccdrbg.h> |
| 17 | #include <stdatomic.h> |
| 18 | |
| 19 | // Depending on the environment and platform APIs available, different |
| 20 | // RNGs will use different reseed strategies. For example, an RNG that |
| 21 | // can communicate with its entropy source might check a flag set by |
| 22 | // the latter when entropy is available. In another case, the RNG |
| 23 | // might poll its entropy source on a time interval. In some cases, |
| 24 | // the RNG might always (or never) want to try to reseed. |
| 25 | // |
| 26 | // This module provides a common interface for such reseed |
| 27 | // schedules. It is intended for use as a component by RNG |
| 28 | // implementations. |
| 29 | |
| 30 | typedef enum { |
| 31 | CCRNG_SCHEDULE_CONTINUE = 1, |
| 32 | CCRNG_SCHEDULE_TRY_RESEED = 2, |
| 33 | CCRNG_SCHEDULE_MUST_RESEED = 3, |
| 34 | } ccrng_schedule_action_t; |
| 35 | |
| 36 | typedef struct ccrng_schedule_ctx ccrng_schedule_ctx_t; |
| 37 | |
| 38 | // The schedule interface provides two function pointers: one to check |
| 39 | // the schedule and one to notify the schedule of a successful reseed. |
| 40 | typedef struct ccrng_schedule_info { |
| 41 | ccrng_schedule_action_t (*read)(ccrng_schedule_ctx_t *ctx); |
| 42 | void (*notify_reseed)(ccrng_schedule_ctx_t *ctx); |
| 43 | } ccrng_schedule_info_t; |
| 44 | |
| 45 | struct ccrng_schedule_ctx { |
| 46 | const ccrng_schedule_info_t *info; |
| 47 | bool must_reseed; |
| 48 | }; |
| 49 | |
| 50 | ccrng_schedule_action_t ccrng_schedule_read(ccrng_schedule_ctx_t *ctx); |
| 51 | |
| 52 | void ccrng_schedule_notify_reseed(ccrng_schedule_ctx_t *ctx); |
| 53 | |
| 54 | // This is a concrete schedule implementation where the state of the |
| 55 | // entropy source is communicated via a flag. The entropy source can |
| 56 | // set the flag with ccrng_schedule_atomic_flag_set to indicate |
| 57 | // entropy is available. The flag is cleared automatically on read and |
| 58 | // reset if the reseed fails. |
| 59 | typedef struct ccrng_schedule_atomic_flag_ctx { |
| 60 | ccrng_schedule_ctx_t schedule_ctx; |
| 61 | _Atomic ccrng_schedule_action_t flag; |
| 62 | } ccrng_schedule_atomic_flag_ctx_t; |
| 63 | |
| 64 | void ccrng_schedule_atomic_flag_init(ccrng_schedule_atomic_flag_ctx_t *ctx); |
| 65 | |
| 66 | void ccrng_schedule_atomic_flag_set(ccrng_schedule_atomic_flag_ctx_t *ctx); |
| 67 | |
| 68 | // This is a concrete schedule implementation that simply always |
| 69 | // returns a constant action. |
| 70 | typedef struct ccrng_schedule_constant_ctx { |
| 71 | ccrng_schedule_ctx_t schedule_ctx; |
| 72 | ccrng_schedule_action_t action; |
| 73 | } ccrng_schedule_constant_ctx_t; |
| 74 | |
| 75 | void ccrng_schedule_constant_init(ccrng_schedule_constant_ctx_t *ctx, |
| 76 | ccrng_schedule_action_t action); |
| 77 | |
| 78 | // This is a concrete schedule implementation that returns "must |
| 79 | // reseed" over a given interval of time. |
| 80 | typedef struct ccrng_schedule_timer_ctx { |
| 81 | ccrng_schedule_ctx_t schedule_ctx; |
| 82 | uint64_t (*get_time)(void); |
| 83 | uint64_t reseed_interval; |
| 84 | uint64_t last_reseed_time; |
| 85 | } ccrng_schedule_timer_ctx_t; |
| 86 | |
| 87 | void ccrng_schedule_timer_init(ccrng_schedule_timer_ctx_t *ctx, |
| 88 | uint64_t (*get_time)(void), |
| 89 | uint64_t reseed_interval); |
| 90 | |
| 91 | // This is a concrete schedule implementation that combines the |
| 92 | // results of two constituent sub-schedules. Specifically, it returns |
| 93 | // the more "urgent" recommendation between the two. |
| 94 | typedef struct ccrng_schedule_tree_ctx { |
| 95 | ccrng_schedule_ctx_t schedule_ctx; |
| 96 | ccrng_schedule_ctx_t *left; |
| 97 | ccrng_schedule_ctx_t *right; |
| 98 | } ccrng_schedule_tree_ctx_t; |
| 99 | |
| 100 | void ccrng_schedule_tree_init(ccrng_schedule_tree_ctx_t *ctx, |
| 101 | ccrng_schedule_ctx_t *left, |
| 102 | ccrng_schedule_ctx_t *right); |
| 103 | |
| 104 | typedef struct ccrng_schedule_drbg_ctx { |
| 105 | ccrng_schedule_ctx_t schedule_ctx; |
| 106 | const struct ccdrbg_info *drbg_info; |
| 107 | struct ccdrbg_state *drbg_ctx; |
| 108 | } ccrng_schedule_drbg_ctx_t; |
| 109 | |
| 110 | void ccrng_schedule_drbg_init(ccrng_schedule_drbg_ctx_t *ctx, |
| 111 | const struct ccdrbg_info *drbg_info, |
| 112 | struct ccdrbg_state *drbg_ctx); |
| 113 | |
| 114 | #endif /* _CORECRYPTO_CCRNG_SCHEDULE_H_ */ |
| 115 | |