fips_rand.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  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. #define OPENSSL_FIPSAPI
  50. /*
  51. * This is a FIPS approved AES PRNG based on ANSI X9.31 A.2.4.
  52. */
  53. #include <openssl/crypto.h>
  54. #include "e_os.h"
  55. /* If we don't define _XOPEN_SOURCE_EXTENDED, struct timeval won't
  56. be defined and gettimeofday() won't be declared with strict compilers
  57. like DEC C in ANSI C mode. */
  58. #ifndef _XOPEN_SOURCE_EXTENDED
  59. #define _XOPEN_SOURCE_EXTENDED 1
  60. #endif
  61. #include <openssl/rand.h>
  62. #include <openssl/aes.h>
  63. #include <openssl/err.h>
  64. #include <openssl/fips_rand.h>
  65. #ifndef OPENSSL_SYS_WIN32
  66. #include <sys/time.h>
  67. #endif
  68. #include <assert.h>
  69. #ifndef OPENSSL_SYS_WIN32
  70. # ifdef OPENSSL_UNISTD
  71. # include OPENSSL_UNISTD
  72. # else
  73. # include <unistd.h>
  74. # endif
  75. #endif
  76. #include <string.h>
  77. #include <openssl/fips.h>
  78. #include "fips_locl.h"
  79. #ifdef OPENSSL_FIPS
  80. void *OPENSSL_stderr(void);
  81. #define AES_BLOCK_LENGTH 16
  82. /* AES FIPS PRNG implementation */
  83. typedef struct
  84. {
  85. int seeded;
  86. int keyed;
  87. int test_mode;
  88. int second;
  89. int error;
  90. unsigned long counter;
  91. AES_KEY ks;
  92. int vpos;
  93. /* Temporary storage for key if it equals seed length */
  94. unsigned char tmp_key[AES_BLOCK_LENGTH];
  95. unsigned char V[AES_BLOCK_LENGTH];
  96. unsigned char DT[AES_BLOCK_LENGTH];
  97. unsigned char last[AES_BLOCK_LENGTH];
  98. } FIPS_PRNG_CTX;
  99. static FIPS_PRNG_CTX sctx;
  100. static int fips_prng_fail = 0;
  101. void FIPS_x931_stick(void)
  102. {
  103. fips_prng_fail = 1;
  104. }
  105. static void fips_rand_prng_reset(FIPS_PRNG_CTX *ctx)
  106. {
  107. ctx->seeded = 0;
  108. ctx->keyed = 0;
  109. ctx->test_mode = 0;
  110. ctx->counter = 0;
  111. ctx->second = 0;
  112. ctx->error = 0;
  113. ctx->vpos = 0;
  114. OPENSSL_cleanse(ctx->V, AES_BLOCK_LENGTH);
  115. OPENSSL_cleanse(&ctx->ks, sizeof(AES_KEY));
  116. }
  117. static int fips_set_prng_key(FIPS_PRNG_CTX *ctx,
  118. const unsigned char *key, unsigned int keylen)
  119. {
  120. FIPS_selftest_check();
  121. if (keylen != 16 && keylen != 24 && keylen != 32)
  122. {
  123. /* error: invalid key size */
  124. return 0;
  125. }
  126. AES_set_encrypt_key(key, keylen << 3, &ctx->ks);
  127. if (keylen == 16)
  128. {
  129. memcpy(ctx->tmp_key, key, 16);
  130. ctx->keyed = 2;
  131. }
  132. else
  133. ctx->keyed = 1;
  134. ctx->seeded = 0;
  135. ctx->second = 0;
  136. return 1;
  137. }
  138. static int fips_set_prng_seed(FIPS_PRNG_CTX *ctx,
  139. const unsigned char *seed, unsigned int seedlen)
  140. {
  141. unsigned int i;
  142. if (!ctx->keyed)
  143. return 0;
  144. /* In test mode seed is just supplied data */
  145. if (ctx->test_mode)
  146. {
  147. if (seedlen != AES_BLOCK_LENGTH)
  148. return 0;
  149. memcpy(ctx->V, seed, AES_BLOCK_LENGTH);
  150. ctx->seeded = 1;
  151. return 1;
  152. }
  153. /* Outside test mode XOR supplied data with existing seed */
  154. for (i = 0; i < seedlen; i++)
  155. {
  156. ctx->V[ctx->vpos++] ^= seed[i];
  157. if (ctx->vpos == AES_BLOCK_LENGTH)
  158. {
  159. ctx->vpos = 0;
  160. /* Special case if first seed and key length equals
  161. * block size check key and seed do not match.
  162. */
  163. if (ctx->keyed == 2)
  164. {
  165. if (!memcmp(ctx->tmp_key, ctx->V, 16))
  166. {
  167. RANDerr(RAND_F_FIPS_SET_PRNG_SEED,
  168. RAND_R_PRNG_SEED_MUST_NOT_MATCH_KEY);
  169. return 0;
  170. }
  171. OPENSSL_cleanse(ctx->tmp_key, 16);
  172. ctx->keyed = 1;
  173. }
  174. ctx->seeded = 1;
  175. }
  176. }
  177. return 1;
  178. }
  179. static int fips_set_test_mode(FIPS_PRNG_CTX *ctx)
  180. {
  181. if (ctx->keyed)
  182. {
  183. RANDerr(RAND_F_FIPS_SET_TEST_MODE,RAND_R_PRNG_KEYED);
  184. return 0;
  185. }
  186. ctx->test_mode = 1;
  187. return 1;
  188. }
  189. int FIPS_x931_test_mode(void)
  190. {
  191. return fips_set_test_mode(&sctx);
  192. }
  193. int FIPS_x931_set_dt(unsigned char *dt)
  194. {
  195. if (!sctx.test_mode)
  196. {
  197. RANDerr(RAND_F_FIPS_X931_SET_DT,RAND_R_NOT_IN_TEST_MODE);
  198. return 0;
  199. }
  200. memcpy(sctx.DT, dt, AES_BLOCK_LENGTH);
  201. return 1;
  202. }
  203. void FIPS_get_timevec(unsigned char *buf, unsigned long *pctr)
  204. {
  205. #ifdef OPENSSL_SYS_WIN32
  206. FILETIME ft;
  207. #else
  208. struct timeval tv;
  209. #endif
  210. #ifndef GETPID_IS_MEANINGLESS
  211. unsigned long pid;
  212. #endif
  213. #ifdef OPENSSL_SYS_WIN32
  214. GetSystemTimeAsFileTime(&ft);
  215. buf[0] = (unsigned char) (ft.dwHighDateTime & 0xff);
  216. buf[1] = (unsigned char) ((ft.dwHighDateTime >> 8) & 0xff);
  217. buf[2] = (unsigned char) ((ft.dwHighDateTime >> 16) & 0xff);
  218. buf[3] = (unsigned char) ((ft.dwHighDateTime >> 24) & 0xff);
  219. buf[4] = (unsigned char) (ft.dwLowDateTime & 0xff);
  220. buf[5] = (unsigned char) ((ft.dwLowDateTime >> 8) & 0xff);
  221. buf[6] = (unsigned char) ((ft.dwLowDateTime >> 16) & 0xff);
  222. buf[7] = (unsigned char) ((ft.dwLowDateTime >> 24) & 0xff);
  223. #else
  224. gettimeofday(&tv,NULL);
  225. buf[0] = (unsigned char) (tv.tv_sec & 0xff);
  226. buf[1] = (unsigned char) ((tv.tv_sec >> 8) & 0xff);
  227. buf[2] = (unsigned char) ((tv.tv_sec >> 16) & 0xff);
  228. buf[3] = (unsigned char) ((tv.tv_sec >> 24) & 0xff);
  229. buf[4] = (unsigned char) (tv.tv_usec & 0xff);
  230. buf[5] = (unsigned char) ((tv.tv_usec >> 8) & 0xff);
  231. buf[6] = (unsigned char) ((tv.tv_usec >> 16) & 0xff);
  232. buf[7] = (unsigned char) ((tv.tv_usec >> 24) & 0xff);
  233. #endif
  234. buf[8] = (unsigned char) (*pctr & 0xff);
  235. buf[9] = (unsigned char) ((*pctr >> 8) & 0xff);
  236. buf[10] = (unsigned char) ((*pctr >> 16) & 0xff);
  237. buf[11] = (unsigned char) ((*pctr >> 24) & 0xff);
  238. (*pctr)++;
  239. #ifndef GETPID_IS_MEANINGLESS
  240. pid=(unsigned long)getpid();
  241. buf[12] = (unsigned char) (pid & 0xff);
  242. buf[13] = (unsigned char) ((pid >> 8) & 0xff);
  243. buf[14] = (unsigned char) ((pid >> 16) & 0xff);
  244. buf[15] = (unsigned char) ((pid >> 24) & 0xff);
  245. #endif
  246. }
  247. static int fips_rand(FIPS_PRNG_CTX *ctx,
  248. unsigned char *out, unsigned int outlen)
  249. {
  250. unsigned char R[AES_BLOCK_LENGTH], I[AES_BLOCK_LENGTH];
  251. unsigned char tmp[AES_BLOCK_LENGTH];
  252. int i;
  253. if (ctx->error)
  254. {
  255. RANDerr(RAND_F_FIPS_RAND,RAND_R_PRNG_ERROR);
  256. return 0;
  257. }
  258. if (!ctx->keyed)
  259. {
  260. RANDerr(RAND_F_FIPS_RAND,RAND_R_NO_KEY_SET);
  261. return 0;
  262. }
  263. if (!ctx->seeded)
  264. {
  265. RANDerr(RAND_F_FIPS_RAND,RAND_R_PRNG_NOT_SEEDED);
  266. return 0;
  267. }
  268. for (;;)
  269. {
  270. if (!ctx->test_mode)
  271. FIPS_get_timevec(ctx->DT, &ctx->counter);
  272. AES_encrypt(ctx->DT, I, &ctx->ks);
  273. for (i = 0; i < AES_BLOCK_LENGTH; i++)
  274. tmp[i] = I[i] ^ ctx->V[i];
  275. AES_encrypt(tmp, R, &ctx->ks);
  276. for (i = 0; i < AES_BLOCK_LENGTH; i++)
  277. tmp[i] = R[i] ^ I[i];
  278. AES_encrypt(tmp, ctx->V, &ctx->ks);
  279. /* Continuous PRNG test */
  280. if (ctx->second)
  281. {
  282. if (fips_prng_fail)
  283. memcpy(ctx->last, R, AES_BLOCK_LENGTH);
  284. if (!memcmp(R, ctx->last, AES_BLOCK_LENGTH))
  285. {
  286. RANDerr(RAND_F_FIPS_RAND,RAND_R_PRNG_STUCK);
  287. ctx->error = 1;
  288. fips_set_selftest_fail();
  289. return 0;
  290. }
  291. }
  292. memcpy(ctx->last, R, AES_BLOCK_LENGTH);
  293. if (!ctx->second)
  294. {
  295. ctx->second = 1;
  296. if (!ctx->test_mode)
  297. continue;
  298. }
  299. if (outlen <= AES_BLOCK_LENGTH)
  300. {
  301. memcpy(out, R, outlen);
  302. break;
  303. }
  304. memcpy(out, R, AES_BLOCK_LENGTH);
  305. out += AES_BLOCK_LENGTH;
  306. outlen -= AES_BLOCK_LENGTH;
  307. }
  308. return 1;
  309. }
  310. int FIPS_x931_set_key(const unsigned char *key, int keylen)
  311. {
  312. int ret;
  313. CRYPTO_w_lock(CRYPTO_LOCK_RAND);
  314. ret = fips_set_prng_key(&sctx, key, keylen);
  315. CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
  316. return ret;
  317. }
  318. int FIPS_x931_seed(const void *seed, int seedlen)
  319. {
  320. int ret;
  321. CRYPTO_w_lock(CRYPTO_LOCK_RAND);
  322. ret = fips_set_prng_seed(&sctx, seed, seedlen);
  323. CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
  324. return ret;
  325. }
  326. int FIPS_x931_bytes(unsigned char *out, int count)
  327. {
  328. int ret;
  329. CRYPTO_w_lock(CRYPTO_LOCK_RAND);
  330. ret = fips_rand(&sctx, out, count);
  331. CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
  332. return ret;
  333. }
  334. int FIPS_x931_status(void)
  335. {
  336. int ret;
  337. CRYPTO_r_lock(CRYPTO_LOCK_RAND);
  338. ret = sctx.seeded;
  339. CRYPTO_r_unlock(CRYPTO_LOCK_RAND);
  340. return ret;
  341. }
  342. void FIPS_x931_reset(void)
  343. {
  344. CRYPTO_w_lock(CRYPTO_LOCK_RAND);
  345. fips_rand_prng_reset(&sctx);
  346. CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
  347. }
  348. static int fips_do_rand_seed(const void *seed, int seedlen)
  349. {
  350. FIPS_x931_seed(seed, seedlen);
  351. return 1;
  352. }
  353. static int fips_do_rand_add(const void *seed, int seedlen,
  354. double add_entropy)
  355. {
  356. FIPS_x931_seed(seed, seedlen);
  357. return 1;
  358. }
  359. static const RAND_METHOD rand_x931_meth=
  360. {
  361. fips_do_rand_seed,
  362. FIPS_x931_bytes,
  363. FIPS_x931_reset,
  364. fips_do_rand_add,
  365. FIPS_x931_bytes,
  366. FIPS_x931_status
  367. };
  368. const RAND_METHOD *FIPS_x931_method(void)
  369. {
  370. return &rand_x931_meth;
  371. }
  372. #endif