Fix skcipher failure handling.
authorMilan Broz <gmazyland@gmail.com>
Fri, 30 Nov 2012 12:37:14 +0000 (13:37 +0100)
committerMilan Broz <gmazyland@gmail.com>
Fri, 30 Nov 2012 12:37:14 +0000 (13:37 +0100)
lib/crypto_backend/crypto_cipher_kernel.c
lib/tcrypt/tcrypt.c
src/cryptsetup.c

index ddd6678..41cdf18 100644 (file)
@@ -44,7 +44,7 @@ int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd)
 {
        *tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
        if (*tfmfd == -1)
-               return -ENOENT;
+               return -ENOTSUP;
 
        if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) == -1) {
                close(*tfmfd);
@@ -62,21 +62,12 @@ int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd)
        return 0;
 }
 
-static int crypt_kernel_cipher_available(void)
-{
-       struct stat st;
-
-       if(stat("/sys/module/algif_skcipher", &st) < 0)
-               return -ENOENT;
-
-       return -ENOTSUP;
-}
-
 /*
  *ciphers
  *
- * ENOENT - no API available
- * ENOTSUP - algorithm not available
+ * ENOENT - algorithm not available
+ * ENOTSUP - AF_ALG family not available
+ * (but cannot check specificaly for skcipher API)
  */
 int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
                    const char *mode, const void *buffer, size_t length)
@@ -98,8 +89,6 @@ int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
        r = crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd);
        if (r < 0) {
                free(h);
-               if (r == -ENOENT)
-                       return crypt_kernel_cipher_available();
                return r;
        }
 
index 373637d..69a70b4 100644 (file)
@@ -398,13 +398,11 @@ static int decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
                                break;
                }
 
-               if (r == -ENOENT) {
-                       log_err(cd, _("Required kernel crypto interface is not available.\n"
-                                     "Ensure you have af_skcipher kernel module loaded.\n"));
-                       return -ENOTSUP;
-               }
                if (r < 0) {
                        log_dbg("TCRYPT:   returned error %d, skipped.", r);
+                       if (r == -ENOTSUP)
+                               break;
+                       r = -ENOENT;
                        continue;
                }
 
@@ -468,7 +466,7 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
        unsigned char pwd[TCRYPT_KEY_POOL_LEN] = {};
        size_t passphrase_size;
        char *key;
-       int r = -EINVAL, i, legacy_modes;
+       int r = -EINVAL, i, legacy_modes, skipped = 0;
 
        if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN))
                return -ENOMEM;
@@ -506,10 +504,17 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
 
                /* Decrypt header */
                r = decrypt_hdr(cd, hdr, key, legacy_modes);
+               if (r == -ENOENT) {
+                       skipped++;
+                       continue;
+               }
                if (r != -EPERM)
                        break;
        }
 
+       if (skipped == i || r == -ENOTSUP)
+               log_err(cd, _("Required kernel crypto interface not available.\n"
+                             "Ensure you have algif_skcipher kernel module loaded.\n"));
        if (r < 0)
                goto out;
 
index 31896f2..820fdba 100644 (file)
@@ -462,7 +462,7 @@ static int action_benchmark(int arg __attribute__((unused)))
        char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
        double enc_mbr = 0, dec_mbr = 0;
        int key_size = (opt_key_size ?: DEFAULT_PLAIN_KEYBITS);
-       int iv_size = 16;
+       int iv_size = 16, skipped = 0;
        int buffer_size = 1024 * 1024;
        char *c;
        int i, r;
@@ -489,15 +489,17 @@ static int action_benchmark(int arg __attribute__((unused)))
                        strncat(cipher, cipher_mode, MAX_CIPHER_LEN);
                        log_std("%11s  %4db  %5.1f MiB/s  %5.1f MiB/s\n",
                                cipher, key_size, enc_mbr, dec_mbr);
-               } else if (r == -ENOTSUP)
+               } else if (r == -ENOENT)
                        log_err(_("Cipher %s is not available.\n"), opt_cipher);
        } else {
                for (i = 0; bciphers[i].cipher; i++) {
                        r = crypt_benchmark(NULL, bciphers[i].cipher, bciphers[i].mode,
                                            bciphers[i].key_size, bciphers[i].iv_size,
                                            buffer_size, &enc_mbr, &dec_mbr);
-                       if (r == -ENOENT)
+                       if (r == -ENOTSUP)
                                break;
+                       if (r == -ENOENT)
+                               skipped++;
                        if (i == 0)
                                log_std("%s", header);
 
@@ -510,11 +512,13 @@ static int action_benchmark(int arg __attribute__((unused)))
                                log_std("%11s  %4db %12s %12s\n", cipher,
                                        bciphers[i].key_size*8, _("N/A"), _("N/A"));
                }
+               if (skipped == i)
+                       r = -ENOTSUP;
        }
 
-       if (r == -ENOENT)
-               log_err( _("Required kernel crypto interface is not available.\n"
-                          "Ensure you have af_skcipher kernel module loaded.\n"));
+       if (r == -ENOTSUP)
+               log_err( _("Required kernel crypto interface not available.\n"
+                          "Ensure you have algif_skcipher kernel module loaded.\n"));
        return r;
 }