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
> 

Reply via email to