int crypt_backend_init(struct crypt_device *ctx) { struct utsname uts; struct sockaddr_alg sa = { .salg_family = AF_ALG, .salg_type = "hash", .salg_name = "sha256", }; int tfmfd = -1, opfd = -1; if (crypto_backend_initialised) return 0; if (uname(&uts) == -1 || strcmp(uts.sysname, "Linux")) return -EINVAL; if (crypt_kernel_socket_init(&sa, &tfmfd, &opfd, NULL, 0) < 0) return -EINVAL; close(tfmfd); close(opfd); snprintf(version, sizeof(version), "%s %s kernel cryptoAPI", uts.sysname, uts.release); crypto_backend_initialised = 1; return 0; } void crypt_backend_destroy(void) { crypto_backend_initialised = 0; } uint32_t crypt_backend_flags(void) { return CRYPT_BACKEND_KERNEL; } const char *crypt_backend_version(void) { return crypto_backend_initialised ? version : ""; } static struct hash_alg *_get_alg(const char *name) { int i = 0; while (name && hash_algs[i].name) { if (!strcmp(name, hash_algs[i].name)) return &hash_algs[i]; i++; } return NULL; }
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, const void *buffer, size_t length) { struct crypt_hmac *h; struct hash_alg *ha; struct sockaddr_alg sa = { .salg_family = AF_ALG, .salg_type = "hash", }; h = malloc(sizeof(*h)); if (!h) return -ENOMEM; ha = _get_alg(name); if (!ha) { free(h); return -EINVAL; } h->hash_len = ha->length; snprintf((char *)sa.salg_name, sizeof(sa.salg_name), "hmac(%s)", ha->kernel_name); if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd) < 0) { free(h); return -EINVAL; } if (setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) { crypt_hmac_destroy(h); return -EINVAL; } *ctx = h; return 0; } int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length) { ssize_t r; r = send(ctx->opfd, buffer, length, MSG_MORE); if (r < 0 || (size_t)r < length) return -EIO; return 0; }
int crypt_hash_init(struct crypt_hash **ctx, const char *name) { struct crypt_hash *h; struct hash_alg *ha; struct sockaddr_alg sa = { .salg_family = AF_ALG, .salg_type = "hash", }; h = malloc(sizeof(*h)); if (!h) return -ENOMEM; ha = _get_alg(name); if (!ha) { free(h); return -EINVAL; } h->hash_len = ha->length; strncpy((char *)sa.salg_name, ha->kernel_name, sizeof(sa.salg_name)); if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd, NULL, 0) < 0) { free(h); return -EINVAL; } *ctx = h; return 0; } int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length) { ssize_t r; r = send(ctx->opfd, buffer, length, MSG_MORE); if (r < 0 || (size_t)r < length) return -EIO; return 0; }