Better tcrypt test options.
[platform/upstream/cryptsetup.git] / lib / tcrypt / tcrypt.c
index 4d2cdb3..920be02 100644 (file)
@@ -244,7 +244,7 @@ static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg,
        r = crypt_cipher_init(&cipher, "blowfish", "ecb",
                              &key[alg->key_offset], alg->key_size);
        if (r < 0)
-               goto out;
+               return r;
 
        memcpy(iv, &key[alg->iv_offset], alg->iv_size);
        for (i = 0; i < TCRYPT_HDR_LEN; i += bs) {
@@ -254,12 +254,12 @@ static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg,
                                          bs, NULL, 0);
                blowfish_le(&buf[i]);
                if (r < 0)
-                       goto out;
+                       break;
                for (j = 0; j < bs; j++)
                        buf[i + j] ^= iv[j];
                memcpy(iv, iv_old, bs);
        }
-out:
+
        crypt_cipher_destroy(cipher);
        return r;
 }
@@ -344,6 +344,8 @@ static int decrypt_hdr_cbci(struct tcrypt_algs *ciphers,
        memcpy(iv, &key[ciphers->cipher[0].iv_offset], bs);
 
        /* Initialize all ciphers in chain in ECB mode */
+       for (j = 0; j < ciphers->chain_count; j++)
+               cipher[j] = NULL;
        for (j = 0; j < ciphers->chain_count; j++) {
                r = crypt_cipher_init(&cipher[j], ciphers->cipher[j].name, "ecb",
                                      &key[ciphers->cipher[j].key_offset],
@@ -377,7 +379,7 @@ static int decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
                        const char *key, int legacy_modes)
 {
        struct tcrypt_phdr hdr2;
-       int i, j, r;
+       int i, j, r = -EINVAL;
 
        for (i = 0; tcrypt_cipher[i].chain_count; i++) {
                if (!legacy_modes && tcrypt_cipher[i].legacy)
@@ -394,10 +396,16 @@ static int decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
                                continue;
                        r = decrypt_hdr_one(&tcrypt_cipher[i].cipher[j],
                                            tcrypt_cipher[i].mode, key, &hdr2);
-                       if (r < 0) {
-                               log_dbg("Error %s.", tcrypt_cipher[i].cipher[j].name);
+                       if (r < 0)
+                               break;
+               }
+
+               if (r < 0) {
+                       log_dbg("TCRYPT:   returned error %d, skipped.", r);
+                       if (r == -ENOTSUP)
                                break;
-                       }
+                       r = -ENOENT;
+                       continue;
                }
 
                if (!strncmp(hdr2.d.magic, TCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) {
@@ -460,7 +468,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;
@@ -498,10 +506,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 && 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;