This source file includes following definitions.
- alg_socket
- afalg_buffer
- afalg_stream
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21 #include "af_alg.h"
22
23 #if USE_LINUX_CRYPTO_API
24
25 #include <unistd.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <linux/if_alg.h>
30 #include <sys/stat.h>
31 #include <sys/sendfile.h>
32 #include <sys/socket.h>
33
34 #include "sys-limits.h"
35
36 #define BLOCKSIZE 32768
37
38
39
40 static int
41 alg_socket (char const *alg)
42 {
43 struct sockaddr_alg salg = {
44 .salg_family = AF_ALG,
45 .salg_type = "hash",
46 };
47
48 for (size_t i = 0; (salg.salg_name[i] = alg[i]) != '\0'; i++)
49 if (i == sizeof salg.salg_name - 1)
50
51 return -EINVAL;
52
53 int cfd = socket (AF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
54 if (cfd < 0)
55 return -EAFNOSUPPORT;
56 int ofd = (bind (cfd, (struct sockaddr *) &salg, sizeof salg) == 0
57 ? accept4 (cfd, NULL, 0, SOCK_CLOEXEC)
58 : -1);
59 close (cfd);
60 return ofd < 0 ? -EAFNOSUPPORT : ofd;
61 }
62
63 int
64 afalg_buffer (const char *buffer, size_t len, const char *alg,
65 void *resblock, ssize_t hashlen)
66 {
67
68
69
70
71 if (len == 0)
72 return -EAFNOSUPPORT;
73
74 int ofd = alg_socket (alg);
75 if (ofd < 0)
76 return ofd;
77
78 int result;
79
80 for (;;)
81 {
82 ssize_t size = (len > BLOCKSIZE ? BLOCKSIZE : len);
83 if (send (ofd, buffer, size, MSG_MORE) != size)
84 {
85 result = -EAFNOSUPPORT;
86 break;
87 }
88 buffer += size;
89 len -= size;
90 if (len == 0)
91 {
92 result = read (ofd, resblock, hashlen) == hashlen ? 0 : -EAFNOSUPPORT;
93 break;
94 }
95 }
96
97 close (ofd);
98 return result;
99 }
100
101 int
102 afalg_stream (FILE *stream, const char *alg,
103 void *resblock, ssize_t hashlen)
104 {
105 int ofd = alg_socket (alg);
106 if (ofd < 0)
107 return ofd;
108
109
110
111
112
113 int fd = fileno (stream);
114 int result;
115 struct stat st;
116 off_t off = ftello (stream);
117 if (0 <= off && fstat (fd, &st) == 0
118 && (S_ISREG (st.st_mode) || S_TYPEISSHM (&st) || S_TYPEISTMO (&st))
119 && off < st.st_size && st.st_size - off < SYS_BUFSIZE_MAX)
120 {
121
122
123
124
125 if (fflush (stream))
126 result = -EIO;
127 else
128 {
129 off_t nbytes = st.st_size - off;
130 if (sendfile (ofd, fd, &off, nbytes) == nbytes)
131 {
132 if (read (ofd, resblock, hashlen) == hashlen)
133 {
134
135 if (lseek (fd, off, SEEK_SET) != (off_t)-1)
136 result = 0;
137 else
138
139 result = -EAFNOSUPPORT;
140 }
141 else
142
143 result = -EAFNOSUPPORT;
144 }
145 else
146
147 result = -EAFNOSUPPORT;
148 }
149 }
150 else
151 {
152
153
154
155 off_t nseek = 0;
156
157 for (;;)
158 {
159 char buf[BLOCKSIZE];
160
161
162 size_t blocksize = (nseek == 0 && off < 0 ? 1 : BLOCKSIZE);
163 ssize_t size = fread (buf, 1, blocksize, stream);
164 if (size == 0)
165 {
166
167
168
169
170 result = ferror (stream) ? -EIO : nseek == 0 ? -EAFNOSUPPORT : 0;
171 break;
172 }
173 nseek -= size;
174 if (send (ofd, buf, size, MSG_MORE) != size)
175 {
176 if (nseek == -1)
177 {
178
179
180 ungetc ((unsigned char) buf[0], stream);
181 result = -EAFNOSUPPORT;
182 }
183 else if (fseeko (stream, nseek, SEEK_CUR) == 0)
184
185 result = -EAFNOSUPPORT;
186 else
187 result = -EIO;
188 break;
189 }
190
191
192
193 if (feof (stream))
194 {
195 result = 0;
196 break;
197 }
198 }
199
200 if (result == 0 && read (ofd, resblock, hashlen) != hashlen)
201 {
202 if (nseek == 0 || fseeko (stream, nseek, SEEK_CUR) == 0)
203
204 result = -EAFNOSUPPORT;
205 else
206 result = -EIO;
207 }
208 }
209 close (ofd);
210 return result;
211 }
212
213 #endif