2 * Linux kernel userspace API crypto backend implementation
4 * Copyright (C) 2010-2011, Red Hat, Inc. All rights reserved.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <sys/socket.h>
26 #include <sys/utsname.h>
27 #include <linux/if_alg.h>
28 #include "crypto_backend.h"
30 /* FIXME: remove later */
36 static int crypto_backend_initialised = 0;
40 const char *kernel_name;
44 static struct hash_alg hash_algs[] = {
45 { "sha1", "sha1", 20 },
46 { "sha256", "sha256", 32 },
47 { "sha512", "sha512", 64 },
48 { "ripemd160", "rmd160", 20 },
49 { "whirlpool", "wp512", 64 },
65 static int _socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd)
67 *tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
71 if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) == -1)
74 *opfd = accept(*tfmfd, NULL, 0);
91 int crypt_backend_init(struct crypt_device *ctx)
95 struct sockaddr_alg sa = {
96 .salg_family = AF_ALG,
100 int tfmfd = -1, opfd = -1;
102 if (crypto_backend_initialised)
105 log_dbg("Initialising kernel crypto API backend.");
107 if (uname(&uts) == -1 || strcmp(uts.sysname, "Linux"))
109 log_dbg("Kernel version %s %s.", uts.sysname, uts.release);
111 if (_socket_init(&sa, &tfmfd, &opfd) < 0)
117 crypto_backend_initialised = 1;
121 uint32_t crypt_backend_flags(void)
123 return CRYPT_BACKEND_KERNEL;
126 static struct hash_alg *_get_alg(const char *name)
130 while (name && hash_algs[i].name) {
131 if (!strcmp(name, hash_algs[i].name))
132 return &hash_algs[i];
139 int crypt_hash_size(const char *name)
141 struct hash_alg *ha = _get_alg(name);
143 return ha ? ha->length : -EINVAL;
146 int crypt_hash_init(struct crypt_hash **ctx, const char *name)
148 struct crypt_hash *h;
150 struct sockaddr_alg sa = {
151 .salg_family = AF_ALG,
155 h = malloc(sizeof(*h));
164 h->hash_len = ha->length;
166 strncpy((char *)sa.salg_name, ha->kernel_name, sizeof(sa.salg_name));
168 if (_socket_init(&sa, &h->tfmfd, &h->opfd) < 0) {
177 int crypt_hash_restart(struct crypt_hash *ctx)
182 int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
186 r = send(ctx->opfd, buffer, length, MSG_MORE);
187 if (r < 0 || r < length)
193 int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
197 if (length > ctx->hash_len)
200 r = read(ctx->opfd, buffer, length);
207 int crypt_hash_destroy(struct crypt_hash *ctx)
209 if (ctx->tfmfd != -1)
213 memset(ctx, 0, sizeof(*ctx));
219 int crypt_hmac_size(const char *name)
221 return crypt_hash_size(name);
224 int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
225 const void *buffer, size_t length)
227 struct crypt_hmac *h;
229 struct sockaddr_alg sa = {
230 .salg_family = AF_ALG,
234 h = malloc(sizeof(*h));
243 h->hash_len = ha->length;
245 snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
246 "hmac(%s)", ha->kernel_name);
248 if (_socket_init(&sa, &h->tfmfd, &h->opfd) < 0) {
253 if (setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) {
254 crypt_hmac_destroy(h);
262 int crypt_hmac_restart(struct crypt_hmac *ctx)
267 int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
271 r = send(ctx->opfd, buffer, length, MSG_MORE);
272 if (r < 0 || r < length)
278 int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
282 if (length > ctx->hash_len)
285 r = read(ctx->opfd, buffer, length);
292 int crypt_hmac_destroy(struct crypt_hmac *ctx)
294 if (ctx->tfmfd != -1)
298 memset(ctx, 0, sizeof(*ctx));