2 * Linux kernel userspace API crypto backend implementation (skcipher)
4 * Copyright (C) 2012, Red Hat, Inc. All rights reserved.
5 * Copyright (C) 2012-2014, Milan Broz
7 * This file is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This file is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this file; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <sys/socket.h>
29 #include "crypto_backend.h"
33 #include <linux/if_alg.h>
52 /* FIXME: Getting block size should be dynamic from cipher backend. */
53 static struct cipher_alg cipher_algs[] = {
54 { "cipher_null", 16 },
72 static struct cipher_alg *_get_alg(const char *name)
76 while (name && cipher_algs[i].name) {
77 if (!strcasecmp(name, cipher_algs[i].name))
78 return &cipher_algs[i];
84 int crypt_cipher_blocksize(const char *name)
86 struct cipher_alg *ca = _get_alg(name);
88 return ca ? ca->blocksize : -EINVAL;
91 /* Shared with hash kernel backend */
92 int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd);
94 int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd)
96 *tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
100 if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) == -1) {
106 *opfd = accept(*tfmfd, NULL, 0);
119 * ENOENT - algorithm not available
120 * ENOTSUP - AF_ALG family not available
121 * (but cannot check specificaly for skcipher API)
123 int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
124 const char *mode, const void *buffer, size_t length)
126 struct crypt_cipher *h;
127 struct sockaddr_alg sa = {
128 .salg_family = AF_ALG,
129 .salg_type = "skcipher",
133 h = malloc(sizeof(*h));
137 snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
138 "%s(%s)", mode, name);
140 r = crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd);
146 if (length && strcmp(name, "cipher_null") &&
147 setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) {
148 crypt_cipher_destroy(h);
156 /* The in/out should be aligned to page boundary */
157 static int crypt_cipher_crypt(struct crypt_cipher *ctx,
158 const char *in, char *out, size_t length,
159 const char *iv, size_t iv_length,
164 struct af_alg_iv *alg_iv;
165 struct cmsghdr *header;
168 .iov_base = (void*)(uintptr_t)in,
171 int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + iv_length) : 0;
172 char buffer[CMSG_SPACE(sizeof(*type)) + iv_msg_size];
173 struct msghdr msg = {
174 .msg_control = buffer,
175 .msg_controllen = sizeof(buffer),
180 if (!in || !out || !length)
183 if ((!iv && iv_length) || (iv && !iv_length))
186 memset(buffer, 0, sizeof(buffer));
188 /* Set encrypt/decrypt operation */
189 header = CMSG_FIRSTHDR(&msg);
193 header->cmsg_level = SOL_ALG;
194 header->cmsg_type = ALG_SET_OP;
195 header->cmsg_len = CMSG_LEN(sizeof(*type));
196 type = (void*)CMSG_DATA(header);
201 header = CMSG_NXTHDR(&msg, header);
202 header->cmsg_level = SOL_ALG;
203 header->cmsg_type = ALG_SET_IV;
204 header->cmsg_len = iv_msg_size;
205 alg_iv = (void*)CMSG_DATA(header);
206 alg_iv->ivlen = iv_length;
207 memcpy(alg_iv->iv, iv, iv_length);
210 len = sendmsg(ctx->opfd, &msg, 0);
211 if (len != (ssize_t)length) {
216 len = read(ctx->opfd, out, length);
217 if (len != (ssize_t)length)
220 crypt_backend_memzero(buffer, sizeof(buffer));
224 int crypt_cipher_encrypt(struct crypt_cipher *ctx,
225 const char *in, char *out, size_t length,
226 const char *iv, size_t iv_length)
228 return crypt_cipher_crypt(ctx, in, out, length,
229 iv, iv_length, ALG_OP_ENCRYPT);
232 int crypt_cipher_decrypt(struct crypt_cipher *ctx,
233 const char *in, char *out, size_t length,
234 const char *iv, size_t iv_length)
236 return crypt_cipher_crypt(ctx, in, out, length,
237 iv, iv_length, ALG_OP_DECRYPT);
240 int crypt_cipher_destroy(struct crypt_cipher *ctx)
242 if (ctx->tfmfd != -1)
246 memset(ctx, 0, sizeof(*ctx));
251 #else /* ENABLE_AF_ALG */
253 int crypt_cipher_blocksize(const char *name)
258 int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
259 const char *mode, const void *buffer, size_t length)
264 int crypt_cipher_destroy(struct crypt_cipher *ctx)
269 int crypt_cipher_encrypt(struct crypt_cipher *ctx,
270 const char *in, char *out, size_t length,
271 const char *iv, size_t iv_length)
275 int crypt_cipher_decrypt(struct crypt_cipher *ctx,
276 const char *in, char *out, size_t length,
277 const char *iv, size_t iv_length)