Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(259)

Side by Side Diff: openssl/fips/rand/fips_rand.c

Issue 9254031: Upgrade chrome's OpenSSL to same version Android ships with. (Closed) Base URL: http://src.chromium.org/svn/trunk/deps/third_party/openssl/
Patch Set: '' Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « openssl/fips/rand/fips_rand.h ('k') | openssl/fips/rand/fips_rand_selftest.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* ====================================================================
2 * Copyright (c) 2007 The OpenSSL Project. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * 3. All advertising materials mentioning features or use of this
17 * software must display the following acknowledgment:
18 * "This product includes software developed by the OpenSSL Project
19 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20 *
21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22 * endorse or promote products derived from this software without
23 * prior written permission. For written permission, please contact
24 * openssl-core@openssl.org.
25 *
26 * 5. Products derived from this software may not be called "OpenSSL"
27 * nor may "OpenSSL" appear in their names without prior written
28 * permission of the OpenSSL Project.
29 *
30 * 6. Redistributions of any form whatsoever must retain the following
31 * acknowledgment:
32 * "This product includes software developed by the OpenSSL Project
33 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46 * OF THE POSSIBILITY OF SUCH DAMAGE.
47 *
48 */
49
50 /*
51 * This is a FIPS approved AES PRNG based on ANSI X9.31 A.2.4.
52 */
53
54 #include "e_os.h"
55
56 /* If we don't define _XOPEN_SOURCE_EXTENDED, struct timeval won't
57 be defined and gettimeofday() won't be declared with strict compilers
58 like DEC C in ANSI C mode. */
59 #ifndef _XOPEN_SOURCE_EXTENDED
60 #define _XOPEN_SOURCE_EXTENDED 1
61 #endif
62
63 #include <openssl/rand.h>
64 #include <openssl/aes.h>
65 #include <openssl/err.h>
66 #include <openssl/fips_rand.h>
67 #ifndef OPENSSL_SYS_WIN32
68 #include <sys/time.h>
69 #endif
70 #include <assert.h>
71 #ifndef OPENSSL_SYS_WIN32
72 # ifdef OPENSSL_UNISTD
73 # include OPENSSL_UNISTD
74 # else
75 # include <unistd.h>
76 # endif
77 #endif
78 #include <string.h>
79 #include <openssl/fips.h>
80 #include "fips_locl.h"
81
82 #ifdef OPENSSL_FIPS
83
84 void *OPENSSL_stderr(void);
85
86 #define AES_BLOCK_LENGTH 16
87
88
89 /* AES FIPS PRNG implementation */
90
91 typedef struct
92 {
93 int seeded;
94 int keyed;
95 int test_mode;
96 int second;
97 int error;
98 unsigned long counter;
99 AES_KEY ks;
100 int vpos;
101 /* Temporary storage for key if it equals seed length */
102 unsigned char tmp_key[AES_BLOCK_LENGTH];
103 unsigned char V[AES_BLOCK_LENGTH];
104 unsigned char DT[AES_BLOCK_LENGTH];
105 unsigned char last[AES_BLOCK_LENGTH];
106 } FIPS_PRNG_CTX;
107
108 static FIPS_PRNG_CTX sctx;
109
110 static int fips_prng_fail = 0;
111
112 void FIPS_rng_stick(void)
113 {
114 fips_prng_fail = 1;
115 }
116
117 static void fips_rand_prng_reset(FIPS_PRNG_CTX *ctx)
118 {
119 ctx->seeded = 0;
120 ctx->keyed = 0;
121 ctx->test_mode = 0;
122 ctx->counter = 0;
123 ctx->second = 0;
124 ctx->error = 0;
125 ctx->vpos = 0;
126 OPENSSL_cleanse(ctx->V, AES_BLOCK_LENGTH);
127 OPENSSL_cleanse(&ctx->ks, sizeof(AES_KEY));
128 }
129
130
131 static int fips_set_prng_key(FIPS_PRNG_CTX *ctx,
132 const unsigned char *key, FIPS_RAND_SIZE_T keylen)
133 {
134 FIPS_selftest_check();
135 if (keylen != 16 && keylen != 24 && keylen != 32)
136 {
137 /* error: invalid key size */
138 return 0;
139 }
140 AES_set_encrypt_key(key, keylen << 3, &ctx->ks);
141 if (keylen == 16)
142 {
143 memcpy(ctx->tmp_key, key, 16);
144 ctx->keyed = 2;
145 }
146 else
147 ctx->keyed = 1;
148 ctx->seeded = 0;
149 ctx->second = 0;
150 return 1;
151 }
152
153 static int fips_set_prng_seed(FIPS_PRNG_CTX *ctx,
154 const unsigned char *seed, FIPS_RAND_SIZE_T seedlen)
155 {
156 int i;
157 if (!ctx->keyed)
158 return 0;
159 /* In test mode seed is just supplied data */
160 if (ctx->test_mode)
161 {
162 if (seedlen != AES_BLOCK_LENGTH)
163 return 0;
164 memcpy(ctx->V, seed, AES_BLOCK_LENGTH);
165 ctx->seeded = 1;
166 return 1;
167 }
168 /* Outside test mode XOR supplied data with existing seed */
169 for (i = 0; i < seedlen; i++)
170 {
171 ctx->V[ctx->vpos++] ^= seed[i];
172 if (ctx->vpos == AES_BLOCK_LENGTH)
173 {
174 ctx->vpos = 0;
175 /* Special case if first seed and key length equals
176 * block size check key and seed do not match.
177 */
178 if (ctx->keyed == 2)
179 {
180 if (!memcmp(ctx->tmp_key, ctx->V, 16))
181 {
182 RANDerr(RAND_F_FIPS_SET_PRNG_SEED,
183 RAND_R_PRNG_SEED_MUST_NOT_MATCH_ KEY);
184 return 0;
185 }
186 OPENSSL_cleanse(ctx->tmp_key, 16);
187 ctx->keyed = 1;
188 }
189 ctx->seeded = 1;
190 }
191 }
192 return 1;
193 }
194
195 static int fips_set_test_mode(FIPS_PRNG_CTX *ctx)
196 {
197 if (ctx->keyed)
198 {
199 RANDerr(RAND_F_FIPS_SET_TEST_MODE,RAND_R_PRNG_KEYED);
200 return 0;
201 }
202 ctx->test_mode = 1;
203 return 1;
204 }
205
206 int FIPS_rand_test_mode(void)
207 {
208 return fips_set_test_mode(&sctx);
209 }
210
211 int FIPS_rand_set_dt(unsigned char *dt)
212 {
213 if (!sctx.test_mode)
214 {
215 RANDerr(RAND_F_FIPS_RAND_SET_DT,RAND_R_NOT_IN_TEST_MODE);
216 return 0;
217 }
218 memcpy(sctx.DT, dt, AES_BLOCK_LENGTH);
219 return 1;
220 }
221
222 static void fips_get_dt(FIPS_PRNG_CTX *ctx)
223 {
224 #ifdef OPENSSL_SYS_WIN32
225 FILETIME ft;
226 #else
227 struct timeval tv;
228 #endif
229 unsigned char *buf = ctx->DT;
230
231 #ifndef GETPID_IS_MEANINGLESS
232 unsigned long pid;
233 #endif
234
235 #ifdef OPENSSL_SYS_WIN32
236 GetSystemTimeAsFileTime(&ft);
237 buf[0] = (unsigned char) (ft.dwHighDateTime & 0xff);
238 buf[1] = (unsigned char) ((ft.dwHighDateTime >> 8) & 0xff);
239 buf[2] = (unsigned char) ((ft.dwHighDateTime >> 16) & 0xff);
240 buf[3] = (unsigned char) ((ft.dwHighDateTime >> 24) & 0xff);
241 buf[4] = (unsigned char) (ft.dwLowDateTime & 0xff);
242 buf[5] = (unsigned char) ((ft.dwLowDateTime >> 8) & 0xff);
243 buf[6] = (unsigned char) ((ft.dwLowDateTime >> 16) & 0xff);
244 buf[7] = (unsigned char) ((ft.dwLowDateTime >> 24) & 0xff);
245 #else
246 gettimeofday(&tv,NULL);
247 buf[0] = (unsigned char) (tv.tv_sec & 0xff);
248 buf[1] = (unsigned char) ((tv.tv_sec >> 8) & 0xff);
249 buf[2] = (unsigned char) ((tv.tv_sec >> 16) & 0xff);
250 buf[3] = (unsigned char) ((tv.tv_sec >> 24) & 0xff);
251 buf[4] = (unsigned char) (tv.tv_usec & 0xff);
252 buf[5] = (unsigned char) ((tv.tv_usec >> 8) & 0xff);
253 buf[6] = (unsigned char) ((tv.tv_usec >> 16) & 0xff);
254 buf[7] = (unsigned char) ((tv.tv_usec >> 24) & 0xff);
255 #endif
256 buf[8] = (unsigned char) (ctx->counter & 0xff);
257 buf[9] = (unsigned char) ((ctx->counter >> 8) & 0xff);
258 buf[10] = (unsigned char) ((ctx->counter >> 16) & 0xff);
259 buf[11] = (unsigned char) ((ctx->counter >> 24) & 0xff);
260
261 ctx->counter++;
262
263
264 #ifndef GETPID_IS_MEANINGLESS
265 pid=(unsigned long)getpid();
266 buf[12] = (unsigned char) (pid & 0xff);
267 buf[13] = (unsigned char) ((pid >> 8) & 0xff);
268 buf[14] = (unsigned char) ((pid >> 16) & 0xff);
269 buf[15] = (unsigned char) ((pid >> 24) & 0xff);
270 #endif
271 }
272
273 static int fips_rand(FIPS_PRNG_CTX *ctx,
274 unsigned char *out, FIPS_RAND_SIZE_T outlen)
275 {
276 unsigned char R[AES_BLOCK_LENGTH], I[AES_BLOCK_LENGTH];
277 unsigned char tmp[AES_BLOCK_LENGTH];
278 int i;
279 if (ctx->error)
280 {
281 RANDerr(RAND_F_FIPS_RAND,RAND_R_PRNG_ERROR);
282 return 0;
283 }
284 if (!ctx->keyed)
285 {
286 RANDerr(RAND_F_FIPS_RAND,RAND_R_NO_KEY_SET);
287 return 0;
288 }
289 if (!ctx->seeded)
290 {
291 RANDerr(RAND_F_FIPS_RAND,RAND_R_PRNG_NOT_SEEDED);
292 return 0;
293 }
294 for (;;)
295 {
296 if (!ctx->test_mode)
297 fips_get_dt(ctx);
298 AES_encrypt(ctx->DT, I, &ctx->ks);
299 for (i = 0; i < AES_BLOCK_LENGTH; i++)
300 tmp[i] = I[i] ^ ctx->V[i];
301 AES_encrypt(tmp, R, &ctx->ks);
302 for (i = 0; i < AES_BLOCK_LENGTH; i++)
303 tmp[i] = R[i] ^ I[i];
304 AES_encrypt(tmp, ctx->V, &ctx->ks);
305 /* Continuous PRNG test */
306 if (ctx->second)
307 {
308 if (fips_prng_fail)
309 memcpy(ctx->last, R, AES_BLOCK_LENGTH);
310 if (!memcmp(R, ctx->last, AES_BLOCK_LENGTH))
311 {
312 RANDerr(RAND_F_FIPS_RAND,RAND_R_PRNG_STUCK);
313 ctx->error = 1;
314 fips_set_selftest_fail();
315 return 0;
316 }
317 }
318 memcpy(ctx->last, R, AES_BLOCK_LENGTH);
319 if (!ctx->second)
320 {
321 ctx->second = 1;
322 if (!ctx->test_mode)
323 continue;
324 }
325
326 if (outlen <= AES_BLOCK_LENGTH)
327 {
328 memcpy(out, R, outlen);
329 break;
330 }
331
332 memcpy(out, R, AES_BLOCK_LENGTH);
333 out += AES_BLOCK_LENGTH;
334 outlen -= AES_BLOCK_LENGTH;
335 }
336 return 1;
337 }
338
339
340 int FIPS_rand_set_key(const unsigned char *key, FIPS_RAND_SIZE_T keylen)
341 {
342 int ret;
343 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
344 ret = fips_set_prng_key(&sctx, key, keylen);
345 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
346 return ret;
347 }
348
349 int FIPS_rand_seed(const void *seed, FIPS_RAND_SIZE_T seedlen)
350 {
351 int ret;
352 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
353 ret = fips_set_prng_seed(&sctx, seed, seedlen);
354 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
355 return ret;
356 }
357
358
359 int FIPS_rand_bytes(unsigned char *out, FIPS_RAND_SIZE_T count)
360 {
361 int ret;
362 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
363 ret = fips_rand(&sctx, out, count);
364 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
365 return ret;
366 }
367
368 int FIPS_rand_status(void)
369 {
370 int ret;
371 CRYPTO_r_lock(CRYPTO_LOCK_RAND);
372 ret = sctx.seeded;
373 CRYPTO_r_unlock(CRYPTO_LOCK_RAND);
374 return ret;
375 }
376
377 void FIPS_rand_reset(void)
378 {
379 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
380 fips_rand_prng_reset(&sctx);
381 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
382 }
383
384 static void fips_do_rand_seed(const void *seed, FIPS_RAND_SIZE_T seedlen)
385 {
386 FIPS_rand_seed(seed, seedlen);
387 }
388
389 static void fips_do_rand_add(const void *seed, FIPS_RAND_SIZE_T seedlen,
390 double add_entropy)
391 {
392 FIPS_rand_seed(seed, seedlen);
393 }
394
395 static const RAND_METHOD rand_fips_meth=
396 {
397 fips_do_rand_seed,
398 FIPS_rand_bytes,
399 FIPS_rand_reset,
400 fips_do_rand_add,
401 FIPS_rand_bytes,
402 FIPS_rand_status
403 };
404
405 const RAND_METHOD *FIPS_rand_method(void)
406 {
407 return &rand_fips_meth;
408 }
409
410 #endif
OLDNEW
« no previous file with comments | « openssl/fips/rand/fips_rand.h ('k') | openssl/fips/rand/fips_rand_selftest.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698