Merged,
Maxim.
On 12/19/16 13:36, Savolainen, Petri (Nokia - FI/Espoo) wrote:
> 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
>