PageRenderTime 27ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/crypto/external/bsd/heimdal/dist/lib/hcrypto/rand-egd.c

http://www.minix3.org/
C | 262 lines | 174 code | 52 blank | 36 comment | 28 complexity | f57f6c5970a7b3adc5997069c3ee80c7 MD5 | raw file
Possible License(s): MIT, WTFPL, AGPL-1.0, BSD-3-Clause, GPL-3.0, LGPL-2.0, JSON, 0BSD
  1. /* $NetBSD: rand-egd.c,v 1.1.1.2 2014/04/24 12:45:30 pettai Exp $ */
  2. /*
  3. * Copyright (c) 2007 Kungliga Tekniska Hรถgskolan
  4. * (Royal Institute of Technology, Stockholm, Sweden).
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. *
  18. * 3. Neither the name of the Institute nor the names of its contributors
  19. * may be used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  26. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. * SUCH DAMAGE.
  33. */
  34. #include <config.h>
  35. #include <sys/types.h>
  36. #ifdef HAVE_SYS_UN_H
  37. #include <sys/un.h>
  38. #endif
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #ifdef HAVE_UNISTD_H
  42. #include <unistd.h>
  43. #endif
  44. #include <assert.h>
  45. #include <rand.h>
  46. #include <randi.h>
  47. #include <krb5/roken.h>
  48. static const char *egd_path = "/var/run/egd-pool";
  49. #define MAX_EGD_DATA 255
  50. static int
  51. connect_egd(const char *path)
  52. {
  53. struct sockaddr_un addr;
  54. int fd;
  55. memset(&addr, 0, sizeof(addr));
  56. if (strlen(path) > sizeof(addr.sun_path))
  57. return -1;
  58. addr.sun_family = AF_UNIX;
  59. strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
  60. fd = socket(AF_UNIX, SOCK_STREAM, 0);
  61. if (fd < 0)
  62. return -1;
  63. rk_cloexec(fd);
  64. if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
  65. close(fd);
  66. return -1;
  67. }
  68. return fd;
  69. }
  70. static int
  71. get_entropy(int fd, void *data, size_t len)
  72. {
  73. unsigned char msg[2];
  74. assert(len <= MAX_EGD_DATA);
  75. msg[0] = 0x02; /* read blocking data */
  76. msg[1] = len; /* wanted length */
  77. if (net_write(fd, msg, sizeof(msg)) != sizeof(msg))
  78. return 0;
  79. if (net_read(fd, data, len) != len)
  80. return 0;
  81. return 1;
  82. }
  83. static int
  84. put_entropy(int fd, const void *data, size_t len)
  85. {
  86. unsigned char msg[4];
  87. assert (len <= MAX_EGD_DATA);
  88. msg[0] = 0x03; /* write data */
  89. msg[1] = 0; /* dummy */
  90. msg[2] = 0; /* entropy */
  91. msg[3] = len; /* length */
  92. if (net_write(fd, msg, sizeof(msg)) != sizeof(msg))
  93. return 0;
  94. if (net_write(fd, data, len) != len)
  95. return 0;
  96. return 1;
  97. }
  98. /*
  99. *
  100. */
  101. static void
  102. egd_seed(const void *indata, int size)
  103. {
  104. size_t len;
  105. int fd, ret = 1;
  106. fd = connect_egd(egd_path);
  107. if (fd < 0)
  108. return;
  109. while(size) {
  110. len = size;
  111. if (len > MAX_EGD_DATA)
  112. len = MAX_EGD_DATA;
  113. ret = put_entropy(fd, indata, len);
  114. if (ret != 1)
  115. break;
  116. indata = ((unsigned char *)indata) + len;
  117. size -= len;
  118. }
  119. close(fd);
  120. }
  121. static int
  122. get_bytes(const char *path, unsigned char *outdata, int size)
  123. {
  124. size_t len;
  125. int fd, ret = 1;
  126. if (path == NULL)
  127. path = egd_path;
  128. fd = connect_egd(path);
  129. if (fd < 0)
  130. return 0;
  131. while(size) {
  132. len = size;
  133. if (len > MAX_EGD_DATA)
  134. len = MAX_EGD_DATA;
  135. ret = get_entropy(fd, outdata, len);
  136. if (ret != 1)
  137. break;
  138. outdata += len;
  139. size -= len;
  140. }
  141. close(fd);
  142. return ret;
  143. }
  144. static int
  145. egd_bytes(unsigned char *outdata, int size)
  146. {
  147. return get_bytes(NULL, outdata, size);
  148. }
  149. static void
  150. egd_cleanup(void)
  151. {
  152. }
  153. static void
  154. egd_add(const void *indata, int size, double entropi)
  155. {
  156. egd_seed(indata, size);
  157. }
  158. static int
  159. egd_pseudorand(unsigned char *outdata, int size)
  160. {
  161. return get_bytes(NULL, outdata, size);
  162. }
  163. static int
  164. egd_status(void)
  165. {
  166. int fd;
  167. fd = connect_egd(egd_path);
  168. if (fd < 0)
  169. return 0;
  170. close(fd);
  171. return 1;
  172. }
  173. const RAND_METHOD hc_rand_egd_method = {
  174. egd_seed,
  175. egd_bytes,
  176. egd_cleanup,
  177. egd_add,
  178. egd_pseudorand,
  179. egd_status
  180. };
  181. const RAND_METHOD *
  182. RAND_egd_method(void)
  183. {
  184. return &hc_rand_egd_method;
  185. }
  186. int
  187. RAND_egd(const char *filename)
  188. {
  189. return RAND_egd_bytes(filename, 128);
  190. }
  191. int
  192. RAND_egd_bytes(const char *filename, int size)
  193. {
  194. void *data;
  195. int ret;
  196. if (size <= 0)
  197. return 0;
  198. data = malloc(size);
  199. if (data == NULL)
  200. return 0;
  201. ret = get_bytes(filename, data, size);
  202. if (ret != 1) {
  203. free(data);
  204. return ret;
  205. }
  206. RAND_seed(data, size);
  207. memset(data, 0, size);
  208. free(data);
  209. return 1;
  210. }