| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| |
|
| | #include <config.h> |
| |
|
| | #include "af_alg.h" |
| |
|
| | #if USE_LINUX_CRYPTO_API |
| |
|
| | #include <unistd.h> |
| | #include <string.h> |
| | #include <stdio.h> |
| | #include <errno.h> |
| | #include <linux/if_alg.h> |
| | #include <sys/stat.h> |
| | #include <sys/sendfile.h> |
| | #include <sys/socket.h> |
| |
|
| | #include "sys-limits.h" |
| |
|
| | #define BLOCKSIZE 32768 |
| |
|
| | |
| | |
| | static int |
| | alg_socket (char const *alg) |
| | { |
| | struct sockaddr_alg salg = { |
| | .salg_family = AF_ALG, |
| | .salg_type = "hash", |
| | }; |
| | |
| | for (size_t i = 0; (salg.salg_name[i] = alg[i]) != '\0'; i++) |
| | if (i == sizeof salg.salg_name - 1) |
| | |
| | return -EINVAL; |
| |
|
| | int cfd = socket (AF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0); |
| | if (cfd < 0) |
| | return -EAFNOSUPPORT; |
| | int ofd = (bind (cfd, (struct sockaddr *) &salg, sizeof salg) == 0 |
| | ? accept4 (cfd, NULL, 0, SOCK_CLOEXEC) |
| | : -1); |
| | close (cfd); |
| | return ofd < 0 ? -EAFNOSUPPORT : ofd; |
| | } |
| |
|
| | int |
| | afalg_buffer (const char *buffer, size_t len, const char *alg, |
| | void *resblock, ssize_t hashlen) |
| | { |
| | |
| | |
| | |
| | |
| | if (len == 0) |
| | return -EAFNOSUPPORT; |
| |
|
| | int ofd = alg_socket (alg); |
| | if (ofd < 0) |
| | return ofd; |
| |
|
| | int result; |
| |
|
| | for (;;) |
| | { |
| | ssize_t size = (len > BLOCKSIZE ? BLOCKSIZE : len); |
| | if (send (ofd, buffer, size, MSG_MORE) != size) |
| | { |
| | result = -EAFNOSUPPORT; |
| | break; |
| | } |
| | buffer += size; |
| | len -= size; |
| | if (len == 0) |
| | { |
| | result = read (ofd, resblock, hashlen) == hashlen ? 0 : -EAFNOSUPPORT; |
| | break; |
| | } |
| | } |
| |
|
| | close (ofd); |
| | return result; |
| | } |
| |
|
| | int |
| | afalg_stream (FILE *stream, const char *alg, |
| | void *resblock, ssize_t hashlen) |
| | { |
| | int ofd = alg_socket (alg); |
| | if (ofd < 0) |
| | return ofd; |
| |
|
| | |
| | |
| | |
| | |
| | int fd = fileno (stream); |
| | int result; |
| | struct stat st; |
| | off_t off = ftello (stream); |
| | if (0 <= off && fstat (fd, &st) == 0 |
| | && (S_ISREG (st.st_mode) || S_TYPEISSHM (&st) || S_TYPEISTMO (&st)) |
| | && off < st.st_size && st.st_size - off < SYS_BUFSIZE_MAX) |
| | { |
| | |
| | |
| | |
| | |
| | if (fflush (stream)) |
| | result = -EIO; |
| | else |
| | { |
| | off_t nbytes = st.st_size - off; |
| | if (sendfile (ofd, fd, &off, nbytes) == nbytes) |
| | { |
| | if (read (ofd, resblock, hashlen) == hashlen) |
| | { |
| | |
| | if (lseek (fd, off, SEEK_SET) != (off_t)-1) |
| | result = 0; |
| | else |
| | |
| | result = -EAFNOSUPPORT; |
| | } |
| | else |
| | |
| | result = -EAFNOSUPPORT; |
| | } |
| | else |
| | |
| | result = -EAFNOSUPPORT; |
| | } |
| | } |
| | else |
| | { |
| | |
| |
|
| | |
| | off_t nseek = 0; |
| |
|
| | for (;;) |
| | { |
| | char buf[BLOCKSIZE]; |
| | |
| | |
| | size_t blocksize = (nseek == 0 && off < 0 ? 1 : BLOCKSIZE); |
| | ssize_t size = fread (buf, 1, blocksize, stream); |
| | if (size == 0) |
| | { |
| | |
| | |
| | |
| | |
| | result = ferror (stream) ? -EIO : nseek == 0 ? -EAFNOSUPPORT : 0; |
| | break; |
| | } |
| | nseek -= size; |
| | if (send (ofd, buf, size, MSG_MORE) != size) |
| | { |
| | if (nseek == -1) |
| | { |
| | |
| | |
| | ungetc ((unsigned char) buf[0], stream); |
| | result = -EAFNOSUPPORT; |
| | } |
| | else if (fseeko (stream, nseek, SEEK_CUR) == 0) |
| | |
| | result = -EAFNOSUPPORT; |
| | else |
| | result = -EIO; |
| | break; |
| | } |
| |
|
| | |
| | |
| | if (feof (stream)) |
| | { |
| | result = 0; |
| | break; |
| | } |
| | } |
| |
|
| | if (result == 0 && read (ofd, resblock, hashlen) != hashlen) |
| | { |
| | if (nseek == 0 || fseeko (stream, nseek, SEEK_CUR) == 0) |
| | |
| | result = -EAFNOSUPPORT; |
| | else |
| | result = -EIO; |
| | } |
| | } |
| | close (ofd); |
| | return result; |
| | } |
| |
|
| | #endif |
| |
|