#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <linux/if_alg.h>
#include "crypto_backend.h"
{
*tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (*tfmfd == -1)
- goto bad;
+ return -ENOENT;
- if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) == -1)
- goto bad;
+ if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) == -1) {
+ close(*tfmfd);
+ *tfmfd = -1;
+ return -ENOENT;
+ }
*opfd = accept(*tfmfd, NULL, 0);
- if (*opfd == -1)
- goto bad;
-
- return 0;
-bad:
- if (*tfmfd != -1) {
+ if (*opfd == -1) {
close(*tfmfd);
*tfmfd = -1;
+ return -EINVAL;
}
- if (*opfd != -1) {
- close(*opfd);
- *opfd = -1;
- }
- return -EINVAL;
+
+ 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 */
+/*
+ *ciphers
+ *
+ * ENOENT - no API available
+ * ENOTSUP - algorithm not available
+ */
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
const char *mode, const void *buffer, size_t length)
{
.salg_family = AF_ALG,
.salg_type = "skcipher",
};
+ int r;
h = malloc(sizeof(*h));
if (!h)
snprintf((char *)sa.salg_name, sizeof(sa.salg_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);
- return -ENOTSUP;
+ if (r == -ENOENT)
+ return crypt_kernel_cipher_available();
+ return r;
}
if (setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) {
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) {
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;
}
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 == -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)) {
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
- log_err(_("Cannot benchmark %s.\n"), cipher);
+ } else if (r == -ENOTSUP)
+ log_err(_("Cipher %s is not available.\n"), opt_cipher);
} else {
- log_std("%s", header);
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)
+ break;
+ if (i == 0)
+ log_std("%s", header);
+
snprintf(cipher, MAX_CIPHER_LEN, "%s-%s",
bciphers[i].cipher, bciphers[i].mode);
if (!r)
}
}
+ if (r == -ENOENT)
+ log_err( _("Required kernel crypto interface is not available.\n"
+ "Ensure you have af_skcipher kernel module loaded.\n"));
return r;
}