Hi,
linux since 2.6.38 have userspace interface to cryptographic api. What do
you think about using this in busybox as alternative to internal hash
algorithms implementation? There is a sample code from my experimentation
in attachment.
#define _GNU_SOURCE
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <poll.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <linux/if_alg.h>
#define AF_ALG 38
enum hash_alg
{
HASH_MD5 = 0,
HASH_SHA1,
HASH_SHA224,
HASH_SHA256,
HASH_SHA384,
HASH_SHA512
};
const char *alg[] = {
"md5",
"sha1",
"sha224",
"sha256",
"sha384",
"sha512"
};
struct hash_ctx
{
int psocket;
int socket;
};
static const char HASH_STR[] = "hash";
int hash_init_ctx(struct hash_ctx *ctx, const char *alg)
{
struct sockaddr_alg sa;
int ret;
ctx->psocket = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (ctx->psocket < 0) {
perror("socket");
return -1;
}
memset(&sa, 0, sizeof(sa));
memcpy(sa.salg_type, HASH_STR, sizeof(HASH_STR));
strncpy(sa.salg_name, alg, sizeof(sa.salg_name));
ret = bind(ctx->psocket, (struct sockaddr *)&sa, sizeof(sa));
if (ret < 0) {
perror("bind");
return -1;
}
ctx->socket = accept(ctx->psocket, NULL, NULL);
if (ctx->socket < 0) {
perror("accept");
return -1;
}
return 0;
}
int hash_update(struct hash_ctx *ctx, uint8_t *buf, size_t bufsize)
{
ssize_t nsend;
do {
nsend = send(ctx->socket, buf, bufsize, MSG_MORE);
if (nsend < 0) {
if (errno == EINTR || errno == EAGAIN) {
continue;
}
perror("send");
return -1;
}
bufsize -= nsend;
} while (bufsize > 0);
return 0;
}
int hash_finish(struct hash_ctx *ctx, uint8_t *buf, size_t *bufsize)
{
struct msghdr msg;
struct iovec iov[1];
ssize_t nrecv;
iov[0].iov_base = buf;
iov[0].iov_len = *bufsize;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = iov;
msg.msg_iovlen = 1;
nrecv = recvmsg(ctx->socket, &msg, 0);
if (nrecv < 0) {
perror("recvmsg");
return -1;
}
if (msg.msg_flags & MSG_TRUNC) {
fprintf(stderr, "hash truncated\n");
return -1;
}
*bufsize = nrecv;
return 0;
}
int hash_file(struct hash_ctx *ctx, const char *file)
{
int fd, ret, pair[2];
loff_t offset;
ssize_t nbytes;
fd = open(file, O_RDONLY);
if (fd < 0) {
perror("open");
return -1;
}
ret = pipe(pair);
if (ret < 0) {
perror("pipe");
return -1;
}
offset = 0;
do {
ssize_t nread, nwrite;
nread = splice(fd, &offset, pair[1], NULL, 4096,
SPLICE_F_MORE | SPLICE_F_MOVE);
if (nread < 0) {
perror("splice");
return -1;
}
nbytes = nread;
while (nread > 0) {
nwrite = splice(pair[0], NULL, ctx->socket, NULL, nread,
SPLICE_F_MORE | SPLICE_F_MOVE);
if (nwrite < 0) {
perror("splice");
return -1;
}
nread -= nwrite;
}
} while (nbytes > 0);
return 0;
}
int main(int argc, char *argv[])
{
int i, ret;
uint8_t buf[512];
size_t bufsize = sizeof(buf);
struct hash_ctx ctx;
if (argc != 3) {
fprintf(stderr, "Usage: %s hash_alg file", argv[0]);
exit(EXIT_FAILURE);
}
ret = hash_init_ctx(&ctx, argv[1]);
if (ret != 0) {
exit(EXIT_FAILURE);
}
ret = hash_file(&ctx, argv[2]);
if (ret != 0) {
exit(EXIT_FAILURE);
}
ret = hash_finish(&ctx, buf, &bufsize);
if (ret != 0) {
exit(EXIT_FAILURE);
}
for (i = 0; i < bufsize; i++) {
printf("%.2x", buf[i]);
}
puts("");
return EXIT_SUCCESS;
}
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox