Reviewed-by: Petri Savolainen <petri.savolai...@nokia.com>

> -----Original Message-----
> From: lng-odp [mailto:lng-odp-boun...@lists.linaro.org] On Behalf Of Bill
> Fischofer
> Sent: Monday, December 12, 2016 5:06 PM
> To: lng-odp@lists.linaro.org
> Subject: [lng-odp] [API-NEXT PATCHv9 1/3] api: random: add explicit
> controls over random data
> 
> Rework the odp_random_data() API to replace the use_entropy with an
> explicit odp_random_kind parameter that controls the type of random
> desired. Two new APIs are also introduced:
> 
> - odp_random_max_kind() returns the maximum kind of random data available
> 
> - odp_random_test_data() permits applications to generate repeatable
>   random sequences for testing purposes
> 
> Signed-off-by: Bill Fischofer <bill.fischo...@linaro.org>
> ---
> Changes in v9:
> - Remove kind parameter and expand seed to uint64_t in
> odp_random_test_data()
> - Clarify that seed variables must be thread-local
> 
> Changes in v8:
> - Clarify random kind hierarchy more explicitly
> - Rename odp_random_repeatable_data() to odp_random_test_data()
> 
> Changes in v7:
> - Clarify hierarchy of random kinds
> - Expand on intended use of odp_random_repeatable_data()
> 
> Changes in v6:
> - Add odp_random_max_kind() API instead of adding this to the
>   odp_crypto_capability() API.
> - Rename odp_random_seeded_data() to odp_random_repeatable_data()
> - Merge API defs, implementation, and validation to preserve bisectability
> 
> Changes in v5:
> - Change return type from int to int32_t for random APIs
> 
> Changes in v4:
> - Normalize random API signatures with other ODP APIs
> - Add new odp_random_seeded_data() API for repeatable random data
> generation
> - Add additional tests for new odp_random_seeded_data() API
> - Break out crypto section of User Guide to its own sub-document
> - Add User Guide docuemntation for ODP random data API.
> 
> Changes in v3:
> - Address commments by Petri
> - Rename ODP_RAND_NORMAL to ODP_RANDOM_BASIC to avoid confusion with the
> mathematical term "normal"
> 
>  include/odp/api/spec/random.h                   | 72
> +++++++++++++++++++++++--
>  platform/linux-generic/odp_crypto.c             | 48 +++++++++++++++--
>  test/common_plat/validation/api/random/random.c | 48 ++++++++++++++++-
>  test/common_plat/validation/api/random/random.h |  2 +
>  4 files changed, 160 insertions(+), 10 deletions(-)
> 
> diff --git a/include/odp/api/spec/random.h b/include/odp/api/spec/random.h
> index 00fa15b..4765475 100644
> --- a/include/odp/api/spec/random.h
> +++ b/include/odp/api/spec/random.h
> @@ -24,18 +24,82 @@ extern "C" {
>   */
> 
>  /**
> + * Random kind selector
> + *
> + * The kind of random denotes the statistical quality of the random data
> + * returned. Basic random simply appears uniformly distributed,
> Cryptographic
> + * random is statistically random and suitable for use by cryptographic
> + * functions. True random is generated from a hardware entropy source
> rather
> + * than an algorithm and is thus completely unpredictable. These form a
> + * hierarchy where higher quality data is presumably more costly to
> generate
> + * than lower quality data.
> + */
> +typedef enum {
> +     /** Basic random, presumably pseudo-random generated by SW. This
> +      *  is the lowest kind of random */
> +     ODP_RANDOM_BASIC,
> +     /** Cryptographic quality random */
> +     ODP_RANDOM_CRYPTO,
> +     /** True random, generated from a HW entropy source. This is the
> +      *  highest kind of random */
> +     ODP_RANDOM_TRUE,
> +} odp_random_kind_t;
> +
> +/**
> + * Query random max kind
> + *
> + * Implementations support the returned max kind and all kinds weaker
> than it.
> + *
> + * @return kind The maximum odp_random_kind_t supported by this
> implementation
> + */
> +odp_random_kind_t odp_random_max_kind(void);
> +
> +/**
>   * Generate random byte data
>   *
> + * The intent in supporting different kinds of random data is to allow
> + * tradeoffs between performance and the quality of random data needed.
> The
> + * assumption is that basic random is cheap while true random is
> relatively
> + * expensive in terms of time to generate, with cryptographic random
> being
> + * something in between. Implementations that support highly efficient
> true
> + * random are free to use this for all requested kinds. So it is always
> + * permissible to "upgrade" a random data request, but never to
> "downgrade"
> + * such requests.
> + *
>   * @param[out]    buf   Output buffer
> - * @param         size  Size of output buffer
> - * @param use_entropy   Use entropy
> + * @param         len   Length of output buffer in bytes
> + * @param         kind  Specifies the type of random data required.
> Request
> + *                      is expected to fail if the implementation is
> unable to
> + *                      provide the requested type.
> + *
> + * @return Number of bytes written
> + * @retval <0 on failure
> + */
> +int32_t odp_random_data(uint8_t *buf, uint32_t len, odp_random_kind_t
> kind);
> +
> +/**
> + * Generate repeatable random data for testing purposes
> + *
> + * For testing purposes it is often useful to generate "random" sequences
> that
> + * are repeatable. This is accomplished by supplying a seed value that is
> used
> + * for pseudo-random data generation. The caller-provided seed value is
> + * updated for each call to continue the sequence. Restarting a series of
> + * calls with the same initial seed value will generate the same sequence
> of
> + * random test data.
> + *
> + * This function returns data of ODP_RANDOM_BASIC quality and should be
> used
> + * only for testing purposes. Use odp_random_data() for production.
>   *
> - * @todo Define the implication of the use_entropy parameter
> + * @param[out]    buf  Output buffer
> + * @param         len  Length of output buffer in bytes
> + * @param[in,out] seed Seed value to use. This must be a thread-local
> + *                     variable. Results are undefined if multiple
> threads
> + *                     call this routine with the same seed variable.
>   *
>   * @return Number of bytes written
>   * @retval <0 on failure
>   */
> -int32_t odp_random_data(uint8_t *buf, int32_t size, odp_bool_t
> use_entropy);
> +int32_t odp_random_test_data(uint8_t *buf, uint32_t len, uint64_t *seed);
> 
>  /**
>   * @}
> diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-
> generic/odp_crypto.c
> index 7e686ff..c2d0c45 100644
> --- a/platform/linux-generic/odp_crypto.c
> +++ b/platform/linux-generic/odp_crypto.c
> @@ -4,6 +4,7 @@
>   * SPDX-License-Identifier:     BSD-3-Clause
>   */
> 
> +#include <odp_posix_extensions.h>
>  #include <odp/api/crypto.h>
>  #include <odp_internal.h>
>  #include <odp/api/atomic.h>
> @@ -19,6 +20,7 @@
>  #include <odp_packet_internal.h>
> 
>  #include <string.h>
> +#include <stdlib.h>
> 
>  #include <openssl/des.h>
>  #include <openssl/rand.h>
> @@ -877,12 +879,48 @@ int odp_crypto_term_global(void)
>       return rc;
>  }
> 
> -int32_t
> -odp_random_data(uint8_t *buf, int32_t len, odp_bool_t use_entropy
> ODP_UNUSED)
> +odp_random_kind_t odp_random_max_kind(void)
>  {
> -     int32_t rc;
> -     rc = RAND_bytes(buf, len);
> -     return (1 == rc) ? len /*success*/: -1 /*failure*/;
> +     return ODP_RANDOM_CRYPTO;
> +}
> +
> +int32_t odp_random_data(uint8_t *buf, uint32_t len, odp_random_kind_t
> kind)
> +{
> +     int rc;
> +
> +     switch (kind) {
> +     case ODP_RANDOM_BASIC:
> +             RAND_pseudo_bytes(buf, len);
> +             return len;
> +
> +     case ODP_RANDOM_CRYPTO:
> +             rc = RAND_bytes(buf, len);
> +             return (1 == rc) ? (int)len /*success*/: -1 /*failure*/;
> +
> +     case ODP_RANDOM_TRUE:
> +     default:
> +             return -1;
> +     }
> +}
> +
> +int32_t odp_random_test_data(uint8_t *buf, uint32_t len, uint64_t *seed)
> +{
> +     union {
> +             uint32_t rand_word;
> +             uint8_t rand_byte[4];
> +     } u;
> +     uint32_t i = 0, j;
> +     uint32_t seed32 = (*seed) & 0xffffffff;
> +
> +     while (i < len) {
> +             u.rand_word = rand_r(&seed32);
> +
> +             for (j = 0; j < 4 && i < len; j++, i++)
> +                     *buf++ = u.rand_byte[j];
> +     }
> +
> +     *seed = seed32;
> +     return len;
>  }
> 
>  odp_crypto_compl_t odp_crypto_compl_from_event(odp_event_t ev)
> diff --git a/test/common_plat/validation/api/random/random.c
> b/test/common_plat/validation/api/random/random.c
> index 7572366..a0e2ef7 100644
> --- a/test/common_plat/validation/api/random/random.c
> +++ b/test/common_plat/validation/api/random/random.c
> @@ -13,12 +13,58 @@ void random_test_get_size(void)
>       int32_t ret;
>       uint8_t buf[32];
> 
> -     ret = odp_random_data(buf, sizeof(buf), false);
> +     ret = odp_random_data(buf, sizeof(buf), ODP_RANDOM_BASIC);
>       CU_ASSERT(ret == sizeof(buf));
>  }
> 
> +void random_test_kind(void)
> +{
> +     int32_t rc;
> +     uint8_t buf[4096];
> +     uint32_t buf_size = sizeof(buf);
> +     odp_random_kind_t max_kind = odp_random_max_kind();
> +
> +     rc = odp_random_data(buf, buf_size, max_kind);
> +     CU_ASSERT(rc > 0);
> +
> +     switch (max_kind) {
> +     case ODP_RANDOM_BASIC:
> +             rc = odp_random_data(buf, 4, ODP_RANDOM_CRYPTO);
> +             CU_ASSERT(rc < 0);
> +             /* Fall through */
> +
> +     case ODP_RANDOM_CRYPTO:
> +             rc = odp_random_data(buf, 4, ODP_RANDOM_TRUE);
> +             CU_ASSERT(rc < 0);
> +             break;
> +
> +     default:
> +             break;
> +     }
> +}
> +
> +void random_test_repeat(void)
> +{
> +     uint8_t buf1[1024];
> +     uint8_t buf2[1024];
> +     int32_t rc;
> +     uint64_t seed1 = 12345897;
> +     uint64_t seed2 = seed1;
> +
> +     rc = odp_random_test_data(buf1, sizeof(buf1), &seed1);
> +     CU_ASSERT(rc == sizeof(buf1));
> +
> +     rc = odp_random_test_data(buf2, sizeof(buf2), &seed2);
> +     CU_ASSERT(rc == sizeof(buf2));
> +
> +     CU_ASSERT(seed1 == seed2);
> +     CU_ASSERT(memcmp(buf1, buf2, sizeof(buf1)) == 0);
> +}
> +
>  odp_testinfo_t random_suite[] = {
>       ODP_TEST_INFO(random_test_get_size),
> +     ODP_TEST_INFO(random_test_kind),
> +     ODP_TEST_INFO(random_test_repeat),
>       ODP_TEST_INFO_NULL,
>  };
> 
> diff --git a/test/common_plat/validation/api/random/random.h
> b/test/common_plat/validation/api/random/random.h
> index 26202cc..c4bca78 100644
> --- a/test/common_plat/validation/api/random/random.h
> +++ b/test/common_plat/validation/api/random/random.h
> @@ -11,6 +11,8 @@
> 
>  /* test functions: */
>  void random_test_get_size(void);
> +void random_test_kind(void);
> +void random_test_repeat(void);
> 
>  /* test arrays: */
>  extern odp_testinfo_t random_suite[];
> --
> 2.7.4

Reply via email to