1/*
2 * Copyright (c) 2010 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 *  randomTest
26 *  CommonCrypto
27 */
28#include "testmore.h"
29#include "capabilities.h"
30#include "testbyteBuffer.h"
31
32
33#if (CCRANDOM == 0)
34entryPoint(CommonRandom,"Random Number Generation")
35#else
36#include <CommonCrypto/CommonRandomSPI.h>
37#include <sys/resource.h>
38
39static const int kTestTestCount = 1000;
40static const int bufmax = kTestTestCount + 16;
41
42// Number of file which can be open by CCRegression application
43// This value need to be acceptable for all CCRegression since default value can only be restored by Super User.
44#define CCREGRESSION_MAX_FILE_OPEN_LIMIT 10
45
46int CommonRandom(int argc, char *const *argv)
47{
48    int i;
49    uint8_t buf1[bufmax], buf2[bufmax], buf3[bufmax], buf4[bufmax], buf5[bufmax], buf6[bufmax], buf7[bufmax];
50    CCRandomRef rngref;
51
52	plan_tests(kTestTestCount * 14 + 11);
53
54
55    struct ccrng_state *devRandom = NULL;
56    struct ccrng_state *drbg = NULL;
57
58    // ============================================
59    //          Negative testing first
60    // ============================================
61    struct ccrng_system_state rng_array[CCREGRESSION_MAX_FILE_OPEN_LIMIT];
62    int rng_array_valid_cnt=0;
63    int rng_status=0;
64
65    // Reduce number to CCREGRESSION_MAX_FILE_OPEN_LIMIT
66    // Only SU can increase this value so we just don't restore it to default.
67    const struct rlimit rlp= { CCREGRESSION_MAX_FILE_OPEN_LIMIT, CCREGRESSION_MAX_FILE_OPEN_LIMIT };
68    is(setrlimit(RLIMIT_NOFILE, &rlp),0, "Set max number of open files");
69
70    // Exhaust opening of /dev/random
71    for(i=0; ((i < CCREGRESSION_MAX_FILE_OPEN_LIMIT) && (rng_status>=0)); i++) {
72        rng_status=ccrng_system_init(&rng_array[i]);
73        rng_array_valid_cnt++;
74    }
75    cmp_ok(rng_array_valid_cnt,<,CCREGRESSION_MAX_FILE_OPEN_LIMIT, "/dev/random exhaustion");
76
77    // Any random initialization will cause abort below.
78    // Since we can't recover, this can't be permanently in the test
79#if 0
80    isnt(CCRNGCreate(0, &rngref),kCCSuccess, "CCRNGCreate with /dev/random exhaustion");
81    devRandom = ccDevRandomGetRngState();
82    is(devRandom,NULL, "ccDevRandomGetRngState /dev/random exhaustion");
83    drbg = ccDRBGGetRngState();
84    is(drbg,NULL, "ccDRBGGetRngState /dev/random exhaustion");
85
86    // Get random under exhausted /dev/random
87    isnt(CCRandomCopyBytes(kCCRandomDefault, buf1, 1),0, "Exhausted /dev/random failure");
88    isnt(CCRandomCopyBytes(kCCRandomDevRandom, buf2, 1),0, "Exhausted /dev/random failure");
89    isnt(CCRandomCopyBytes(rngref, buf3, 1),0, "Exhausted /dev/random failure");
90    isnt(CCRandomCopyBytes(NULL, buf4, 1),0, "Exhausted /dev/random failure");
91    isnt(CCRandomGenerateBytes(buf7, 1),0, "Exhausted /dev/random failure");
92#endif
93    // Close to allow again the use of /dev/random
94    for(i=0; (i < rng_array_valid_cnt); i++) {
95        ccrng_system_done(&rng_array[i]);
96    }
97
98    // ============================================
99    //          Positive testing
100    // ============================================
101
102    is(CCRNGCreate(0, &rngref),kCCSuccess, "CCRNGCreate success");
103    devRandom = ccDevRandomGetRngState();
104    isnt(devRandom,NULL, "Dev random first state ok");
105    drbg = ccDRBGGetRngState();
106    isnt(drbg,NULL, "DRBG first state ok");
107
108    for(i=0; i < kTestTestCount; i++) {
109        size_t len = i+16;
110        is(CCRandomCopyBytes(kCCRandomDefault, buf1, len),0, "Random success");
111        is(CCRandomCopyBytes(kCCRandomDevRandom, buf2, len),0, "Random success");
112        is(CCRandomCopyBytes(rngref, buf3, len),0, "Random success");
113        is(CCRandomCopyBytes(NULL, buf4, len),0, "Random success");
114        is(ccrng_generate(devRandom, len, buf5),0, "Random success");
115        is(ccrng_generate(drbg, len, buf6),0, "Random success");
116        is(CCRandomGenerateBytes(buf7, len),0, "Random success");
117
118        ok(memcmp(buf1, buf2, len), "Buffers aren't the same");
119        ok(memcmp(buf3, buf4, len), "Buffers aren't the same");
120        ok(memcmp(buf2, buf3, len), "Buffers aren't the same");
121        ok(memcmp(buf5, buf6, len), "Buffers aren't the same");
122        ok(memcmp(buf5, buf2, len), "Buffers aren't the same");
123        ok(memcmp(buf6, buf1, len), "Buffers aren't the same");
124        ok(memcmp(buf7, buf1, len), "Buffers aren't the same");
125    }
126
127
128    // Bad inputs
129    is(CCRandomCopyBytes(kCCRandomDefault, buf1, 0),0, "Zero Length");
130    is(CCRandomCopyBytes(kCCRandomDevRandom, buf2, 0),0, "Zero Length");
131    is(CCRandomGenerateBytes(buf7, 0),0, "Zero Length");
132
133    isnt(CCRandomCopyBytes(kCCRandomDefault, NULL, 1),0, "NULL pointer");
134    isnt(CCRandomCopyBytes(kCCRandomDevRandom, NULL, 1),0, "NULL pointer");
135    isnt(CCRandomGenerateBytes(NULL, 1),0, "NULL pointer");
136
137    CCRNGRelease(rngref);
138
139    return 0;
140}
141#endif
142
143