-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Maxim Radugin
committed
Sep 5, 2013
1 parent
5d0c70e
commit 1ddca5c
Showing
5 changed files
with
953 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
TARGET = dmcryptfile | ||
LIBS = -lm | ||
CC = gcc | ||
CFLAGS = -g -Wall | ||
|
||
.PHONY: default all clean | ||
|
||
default: $(TARGET) | ||
all: default | ||
|
||
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c)) | ||
HEADERS = $(wildcard *.h) | ||
|
||
%.o: %.c $(HEADERS) | ||
$(CC) $(CFLAGS) -c $< -o $@ | ||
|
||
.PRECIOUS: $(TARGET) $(OBJECTS) | ||
|
||
$(TARGET): $(OBJECTS) | ||
$(CC) $(OBJECTS) -Wall $(LIBS) -o $@ | ||
|
||
clean: | ||
-rm -f *.o | ||
-rm -f $(TARGET) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* crypto backend implementation | ||
* | ||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved. | ||
* Copyright (C) 2010-2012, Milan Broz | ||
* | ||
* This file is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 2.1 of the License, or (at your option) any later version. | ||
* | ||
* This file is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public | ||
* License along with this file; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
*/ | ||
#ifndef _CRYPTO_BACKEND_H | ||
#define _CRYPTO_BACKEND_H | ||
|
||
#define ENABLE_AF_ALG | ||
|
||
#include <stdint.h> | ||
#include <string.h> | ||
|
||
struct crypt_device; | ||
struct crypt_hash; | ||
struct crypt_hmac; | ||
struct crypt_cipher; | ||
|
||
int crypt_backend_init(struct crypt_device *ctx); | ||
|
||
#define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */ | ||
|
||
uint32_t crypt_backend_flags(void); | ||
const char *crypt_backend_version(void); | ||
|
||
/* HASH */ | ||
int crypt_hash_size(const char *name); | ||
int crypt_hash_init(struct crypt_hash **ctx, const char *name); | ||
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length); | ||
int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length); | ||
int crypt_hash_destroy(struct crypt_hash *ctx); | ||
|
||
/* HMAC */ | ||
int crypt_hmac_size(const char *name); | ||
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, | ||
const void *buffer, size_t length); | ||
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length); | ||
int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length); | ||
int crypt_hmac_destroy(struct crypt_hmac *ctx); | ||
|
||
/* RNG (if fips paramater set, must provide FIPS compliance) */ | ||
enum { CRYPT_RND_NORMAL = 0, CRYPT_RND_KEY = 1, CRYPT_RND_SALT = 2 }; | ||
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips); | ||
|
||
/* PBKDF*/ | ||
int crypt_pbkdf_check(const char *kdf, const char *hash, | ||
const char *password, size_t password_size, | ||
const char *salt, size_t salt_size, | ||
uint64_t *iter_secs); | ||
int crypt_pbkdf(const char *kdf, const char *hash, | ||
const char *password, size_t password_length, | ||
const char *salt, size_t salt_length, | ||
char *key, size_t key_length, | ||
unsigned int iterations); | ||
|
||
#if 0 | ||
/* internal PBKDF2 implementation */ | ||
int pkcs5_pbkdf2(const char *hash, | ||
const char *P, size_t Plen, | ||
const char *S, size_t Slen, | ||
unsigned int c, | ||
unsigned int dkLen,char *DK); | ||
#endif | ||
|
||
/* CRC32 */ | ||
uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len); | ||
|
||
/* ciphers */ | ||
extern int crypt_cipher_init(struct crypt_cipher **ctx, const char *name, | ||
const char *mode, const void *buffer, size_t length); | ||
extern int crypt_cipher_destroy(struct crypt_cipher *ctx); | ||
extern int crypt_cipher_encrypt(struct crypt_cipher *ctx, | ||
const char *in, char *out, size_t length, | ||
const char *iv, size_t iv_length); | ||
extern int crypt_cipher_decrypt(struct crypt_cipher *ctx, | ||
const char *in, char *out, size_t length, | ||
const char *iv, size_t iv_length); | ||
|
||
#endif /* _CRYPTO_BACKEND_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
/* | ||
* Linux kernel userspace API crypto backend implementation (skcipher) | ||
* | ||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved. | ||
* Copyright (C) 2012, Milan Broz | ||
* | ||
* This file is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 2.1 of the License, or (at your option) any later version. | ||
* | ||
* This file is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public | ||
* License along with this file; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
*/ | ||
|
||
#include <string.h> | ||
#include <stdlib.h> | ||
#include <stdio.h> | ||
#include <errno.h> | ||
#include <unistd.h> | ||
#include <sys/socket.h> | ||
#include <sys/stat.h> | ||
#include "crypto_backend.h" | ||
|
||
#ifdef ENABLE_AF_ALG | ||
|
||
#include <linux/if_alg.h> | ||
|
||
#ifndef AF_ALG | ||
#define AF_ALG 38 | ||
#endif | ||
#ifndef SOL_ALG | ||
#define SOL_ALG 279 | ||
#endif | ||
|
||
struct crypt_cipher { | ||
int tfmfd; | ||
int opfd; | ||
}; | ||
|
||
/* Shared with hash kernel backend */ | ||
int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd); | ||
|
||
int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd) | ||
{ | ||
*tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0); | ||
if (*tfmfd == -1) | ||
return -ENOTSUP; | ||
|
||
if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) == -1) { | ||
close(*tfmfd); | ||
*tfmfd = -1; | ||
return -ENOENT; | ||
} | ||
|
||
*opfd = accept(*tfmfd, NULL, 0); | ||
if (*opfd == -1) { | ||
close(*tfmfd); | ||
*tfmfd = -1; | ||
return -EINVAL; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
/* | ||
*ciphers | ||
* | ||
* ENOENT - algorithm not available | ||
* ENOTSUP - AF_ALG family not available | ||
* (but cannot check specificaly for skcipher API) | ||
*/ | ||
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name, | ||
const char *mode, const void *buffer, size_t length) | ||
{ | ||
struct crypt_cipher *h; | ||
struct sockaddr_alg sa = { | ||
.salg_family = AF_ALG, | ||
.salg_type = "skcipher", | ||
}; | ||
int r; | ||
|
||
h = malloc(sizeof(*h)); | ||
if (!h) | ||
return -ENOMEM; | ||
|
||
snprintf((char *)sa.salg_name, sizeof(sa.salg_name), | ||
"%s(%s)", mode, name); | ||
|
||
r = crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd); | ||
if (r < 0) { | ||
free(h); | ||
return r; | ||
} | ||
|
||
if (setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) { | ||
crypt_cipher_destroy(h); | ||
return -EINVAL; | ||
} | ||
|
||
*ctx = h; | ||
return 0; | ||
} | ||
|
||
/* The in/out should be aligned to page boundary */ | ||
static int crypt_cipher_crypt(struct crypt_cipher *ctx, | ||
const char *in, char *out, size_t length, | ||
const char *iv, size_t iv_length, | ||
uint32_t direction) | ||
{ | ||
int r = 0; | ||
ssize_t len; | ||
struct af_alg_iv *alg_iv; | ||
struct cmsghdr *header; | ||
uint32_t *type; | ||
struct iovec iov = { | ||
.iov_base = (void*)(uintptr_t)in, | ||
.iov_len = length, | ||
}; | ||
int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + iv_length) : 0; | ||
char buffer[CMSG_SPACE(sizeof(*type)) + iv_msg_size]; | ||
struct msghdr msg = { | ||
.msg_control = buffer, | ||
.msg_controllen = sizeof(buffer), | ||
.msg_iov = &iov, | ||
.msg_iovlen = 1, | ||
}; | ||
|
||
if (!in || !out || !length) | ||
return -EINVAL; | ||
|
||
if ((!iv && iv_length) || (iv && !iv_length)) | ||
return -EINVAL; | ||
|
||
memset(buffer, 0, sizeof(buffer)); | ||
|
||
/* Set encrypt/decrypt operation */ | ||
header = CMSG_FIRSTHDR(&msg); | ||
header->cmsg_level = SOL_ALG; | ||
header->cmsg_type = ALG_SET_OP; | ||
header->cmsg_len = CMSG_LEN(sizeof(*type)); | ||
type = (void*)CMSG_DATA(header); | ||
*type = direction; | ||
|
||
/* Set IV */ | ||
if (iv) { | ||
header = CMSG_NXTHDR(&msg, header); | ||
header->cmsg_level = SOL_ALG; | ||
header->cmsg_type = ALG_SET_IV; | ||
header->cmsg_len = iv_msg_size; | ||
alg_iv = (void*)CMSG_DATA(header); | ||
alg_iv->ivlen = iv_length; | ||
memcpy(alg_iv->iv, iv, iv_length); | ||
} | ||
|
||
len = sendmsg(ctx->opfd, &msg, 0); | ||
if (len != (ssize_t)length) { | ||
r = -EIO; | ||
goto bad; | ||
} | ||
|
||
len = read(ctx->opfd, out, length); | ||
if (len != (ssize_t)length) | ||
r = -EIO; | ||
bad: | ||
memset(buffer, 0, sizeof(buffer)); | ||
return r; | ||
} | ||
|
||
int crypt_cipher_encrypt(struct crypt_cipher *ctx, | ||
const char *in, char *out, size_t length, | ||
const char *iv, size_t iv_length) | ||
{ | ||
return crypt_cipher_crypt(ctx, in, out, length, | ||
iv, iv_length, ALG_OP_ENCRYPT); | ||
} | ||
|
||
int crypt_cipher_decrypt(struct crypt_cipher *ctx, | ||
const char *in, char *out, size_t length, | ||
const char *iv, size_t iv_length) | ||
{ | ||
return crypt_cipher_crypt(ctx, in, out, length, | ||
iv, iv_length, ALG_OP_DECRYPT); | ||
} | ||
|
||
int crypt_cipher_destroy(struct crypt_cipher *ctx) | ||
{ | ||
if (ctx->tfmfd != -1) | ||
close(ctx->tfmfd); | ||
if (ctx->opfd != -1) | ||
close(ctx->opfd); | ||
memset(ctx, 0, sizeof(*ctx)); | ||
free(ctx); | ||
return 0; | ||
} | ||
|
||
#else /* ENABLE_AF_ALG */ | ||
|
||
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name, | ||
const char *mode, const void *buffer, size_t length) | ||
{ | ||
return -ENOTSUP; | ||
} | ||
|
||
int crypt_cipher_destroy(struct crypt_cipher *ctx) | ||
{ | ||
return 0; | ||
} | ||
|
||
int crypt_cipher_encrypt(struct crypt_cipher *ctx, | ||
const char *in, char *out, size_t length, | ||
const char *iv, size_t iv_length) | ||
{ | ||
return -EINVAL; | ||
} | ||
int crypt_cipher_decrypt(struct crypt_cipher *ctx, | ||
const char *in, char *out, size_t length, | ||
const char *iv, size_t iv_length) | ||
{ | ||
return -EINVAL; | ||
} | ||
#endif |
Oops, something went wrong.