Fix missing headers
[platform/upstream/cryptsetup.git] / lib / random.c
index 4a64418..25c8a2c 100644 (file)
@@ -1,11 +1,12 @@
 /*
  * cryptsetup kernel RNG access functions
  *
- * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #include <stdlib.h>
@@ -22,6 +23,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <assert.h>
+#include <sys/select.h>
 
 #include "libcryptsetup.h"
 #include "internal.h"
@@ -41,7 +43,8 @@ static int random_fd = -1;
 #define RANDOM_DEVICE_TIMEOUT  5
 
 /* URANDOM_DEVICE access */
-static int _get_urandom(struct crypt_device *ctx, char *buf, size_t len)
+static int _get_urandom(struct crypt_device *ctx __attribute__((unused)),
+                       char *buf, size_t len)
 {
        int r;
        size_t old_len = len;
@@ -53,8 +56,10 @@ static int _get_urandom(struct crypt_device *ctx, char *buf, size_t len)
                r = read(urandom_fd, buf, len);
                if (r == -1 && errno != EINTR)
                        return -EINVAL;
-               len -= r;
-               buf += r;
+               if (r > 0) {
+                       len -= r;
+                       buf += r;
+               }
        }
 
        assert(len == 0);
@@ -111,15 +116,17 @@ static int _get_random(struct crypt_device *ctx, char *buf, size_t len)
 
                        r = read(random_fd, buf, n);
 
-                       if (r == -1 && errno == EINTR)
+                       if (r == -1 && errno == EINTR) {
+                               r = 0;
                                continue;
+                       }
 
                        /* bogus read? */
                        if(r > (int)n)
                                return -EINVAL;
 
                        /* random device is opened with O_NONBLOCK, EAGAIN is expected */
-                       if (r == -1 && (errno != EAGAIN || errno != EWOULDBLOCK))
+                       if (r == -1 && (errno != EAGAIN && errno != EWOULDBLOCK))
                                return -EINVAL;
 
                        if (r > 0) {
@@ -140,6 +147,9 @@ static int _get_random(struct crypt_device *ctx, char *buf, size_t len)
 /* Initialisation of both RNG file descriptors is mandatory */
 int crypt_random_init(struct crypt_device *ctx)
 {
+       if (random_initialised)
+               return 0;
+
        /* Used for CRYPT_RND_NORMAL */
        if(urandom_fd == -1)
                urandom_fd = open(URANDOM_DEVICE, O_RDONLY);
@@ -168,7 +178,17 @@ int crypt_random_get(struct crypt_device *ctx, char *buf, size_t len, int qualit
        case CRYPT_RND_NORMAL:
                status = _get_urandom(ctx, buf, len);
                break;
+       case CRYPT_RND_SALT:
+               if (crypt_fips_mode())
+                       status = crypt_backend_rng(buf, len, quality, 1);
+               else
+                       status = _get_urandom(ctx, buf, len);
+               break;
        case CRYPT_RND_KEY:
+               if (crypt_fips_mode()) {
+                       status = crypt_backend_rng(buf, len, quality, 1);
+                       break;
+               }
                rng_type = ctx ? crypt_get_rng_type(ctx) :
                                 crypt_random_default_key_rng();
                switch (rng_type) {
@@ -194,7 +214,7 @@ int crypt_random_get(struct crypt_device *ctx, char *buf, size_t len, int qualit
        return status;
 }
 
-void crypt_random_exit()
+void crypt_random_exit(void)
 {
        random_initialised = 0;
 
@@ -209,7 +229,7 @@ void crypt_random_exit()
        }
 }
 
-int crypt_random_default_key_rng()
+int crypt_random_default_key_rng(void)
 {
        if (!strcmp(DEFAULT_RNG, RANDOM_DEVICE))
                return CRYPT_RNG_RANDOM;