mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-11 19:00:02 +01:00
Handle kernel crypto api init failure better.
This commit is contained in:
@@ -24,6 +24,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <linux/if_alg.h>
|
#include <linux/if_alg.h>
|
||||||
#include "crypto_backend.h"
|
#include "crypto_backend.h"
|
||||||
|
|
||||||
@@ -43,29 +44,40 @@ int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd)
|
|||||||
{
|
{
|
||||||
*tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
|
*tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
|
||||||
if (*tfmfd == -1)
|
if (*tfmfd == -1)
|
||||||
goto bad;
|
return -ENOENT;
|
||||||
|
|
||||||
if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) == -1)
|
if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) == -1) {
|
||||||
goto bad;
|
|
||||||
|
|
||||||
*opfd = accept(*tfmfd, NULL, 0);
|
|
||||||
if (*opfd == -1)
|
|
||||||
goto bad;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
bad:
|
|
||||||
if (*tfmfd != -1) {
|
|
||||||
close(*tfmfd);
|
close(*tfmfd);
|
||||||
*tfmfd = -1;
|
*tfmfd = -1;
|
||||||
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
if (*opfd != -1) {
|
|
||||||
close(*opfd);
|
*opfd = accept(*tfmfd, NULL, 0);
|
||||||
*opfd = -1;
|
if (*opfd == -1) {
|
||||||
|
close(*tfmfd);
|
||||||
|
*tfmfd = -1;
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
return -EINVAL;
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ciphers */
|
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
|
||||||
|
*/
|
||||||
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
||||||
const char *mode, const void *buffer, size_t length)
|
const char *mode, const void *buffer, size_t length)
|
||||||
{
|
{
|
||||||
@@ -74,6 +86,7 @@ int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
|||||||
.salg_family = AF_ALG,
|
.salg_family = AF_ALG,
|
||||||
.salg_type = "skcipher",
|
.salg_type = "skcipher",
|
||||||
};
|
};
|
||||||
|
int r;
|
||||||
|
|
||||||
h = malloc(sizeof(*h));
|
h = malloc(sizeof(*h));
|
||||||
if (!h)
|
if (!h)
|
||||||
@@ -82,9 +95,12 @@ int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
|||||||
snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
|
snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
|
||||||
"%s(%s)", mode, name);
|
"%s(%s)", mode, name);
|
||||||
|
|
||||||
if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd) < 0) {
|
r = crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd);
|
||||||
|
if (r < 0) {
|
||||||
free(h);
|
free(h);
|
||||||
return -ENOTSUP;
|
if (r == -ENOENT)
|
||||||
|
return crypt_kernel_cipher_available();
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) {
|
if (setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) {
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg,
|
|||||||
r = crypt_cipher_init(&cipher, "blowfish", "ecb",
|
r = crypt_cipher_init(&cipher, "blowfish", "ecb",
|
||||||
&key[alg->key_offset], alg->key_size);
|
&key[alg->key_offset], alg->key_size);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto out;
|
return r;
|
||||||
|
|
||||||
memcpy(iv, &key[alg->iv_offset], alg->iv_size);
|
memcpy(iv, &key[alg->iv_offset], alg->iv_size);
|
||||||
for (i = 0; i < TCRYPT_HDR_LEN; i += bs) {
|
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);
|
bs, NULL, 0);
|
||||||
blowfish_le(&buf[i]);
|
blowfish_le(&buf[i]);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto out;
|
break;
|
||||||
for (j = 0; j < bs; j++)
|
for (j = 0; j < bs; j++)
|
||||||
buf[i + j] ^= iv[j];
|
buf[i + j] ^= iv[j];
|
||||||
memcpy(iv, iv_old, bs);
|
memcpy(iv, iv_old, bs);
|
||||||
}
|
}
|
||||||
out:
|
|
||||||
crypt_cipher_destroy(cipher);
|
crypt_cipher_destroy(cipher);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -394,10 +394,18 @@ static int decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
|
|||||||
continue;
|
continue;
|
||||||
r = decrypt_hdr_one(&tcrypt_cipher[i].cipher[j],
|
r = decrypt_hdr_one(&tcrypt_cipher[i].cipher[j],
|
||||||
tcrypt_cipher[i].mode, key, &hdr2);
|
tcrypt_cipher[i].mode, key, &hdr2);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
log_dbg("Error %s.", tcrypt_cipher[i].cipher[j].name);
|
|
||||||
break;
|
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);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strncmp(hdr2.d.magic, TCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) {
|
if (!strncmp(hdr2.d.magic, TCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) {
|
||||||
|
|||||||
@@ -489,14 +489,18 @@ static int action_benchmark(int arg __attribute__((unused)))
|
|||||||
strncat(cipher, cipher_mode, MAX_CIPHER_LEN);
|
strncat(cipher, cipher_mode, MAX_CIPHER_LEN);
|
||||||
log_std("%11s %4db %5.1f MiB/s %5.1f MiB/s\n",
|
log_std("%11s %4db %5.1f MiB/s %5.1f MiB/s\n",
|
||||||
cipher, key_size, enc_mbr, dec_mbr);
|
cipher, key_size, enc_mbr, dec_mbr);
|
||||||
} else
|
} else if (r == -ENOTSUP)
|
||||||
log_err(_("Cannot benchmark %s.\n"), cipher);
|
log_err(_("Cipher %s is not available.\n"), opt_cipher);
|
||||||
} else {
|
} else {
|
||||||
log_std("%s", header);
|
|
||||||
for (i = 0; bciphers[i].cipher; i++) {
|
for (i = 0; bciphers[i].cipher; i++) {
|
||||||
r = crypt_benchmark(NULL, bciphers[i].cipher, bciphers[i].mode,
|
r = crypt_benchmark(NULL, bciphers[i].cipher, bciphers[i].mode,
|
||||||
bciphers[i].key_size, bciphers[i].iv_size,
|
bciphers[i].key_size, bciphers[i].iv_size,
|
||||||
buffer_size, &enc_mbr, &dec_mbr);
|
buffer_size, &enc_mbr, &dec_mbr);
|
||||||
|
if (r == -ENOENT)
|
||||||
|
break;
|
||||||
|
if (i == 0)
|
||||||
|
log_std("%s", header);
|
||||||
|
|
||||||
snprintf(cipher, MAX_CIPHER_LEN, "%s-%s",
|
snprintf(cipher, MAX_CIPHER_LEN, "%s-%s",
|
||||||
bciphers[i].cipher, bciphers[i].mode);
|
bciphers[i].cipher, bciphers[i].mode);
|
||||||
if (!r)
|
if (!r)
|
||||||
@@ -508,6 +512,9 @@ static int action_benchmark(int arg __attribute__((unused)))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r == -ENOENT)
|
||||||
|
log_err( _("Required kernel crypto interface is not available.\n"
|
||||||
|
"Ensure you have af_skcipher kernel module loaded.\n"));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user