Line | Source | Count |
1 | | - |
2 | | - |
3 | | - |
4 | | - |
5 | | - |
6 | | - |
7 | int fd = -1; | - |
8 | pid_t pid = -1; | - |
9 | | - |
10 | static void | - |
11 | send_msg(struct sshbuf *m) | - |
12 | { | - |
13 | u_char buf[4]; | - |
14 | size_t mlen = sshbuf_len(m); | - |
15 | int r; | - |
16 | | - |
17 | do { const u_int32_t __v = (mlen); ((u_char *)(buf))[0] = (__v >> 24) & 0xff; ((u_char *)(buf))[1] = (__v >> 16) & 0xff; ((u_char *)(buf))[2] = (__v >> 8) & 0xff; ((u_char *)(buf))[3] = __v & 0xff; } while (0); | - |
18 | if (atomicio((ssize_t (*)(int, void *, size_t))write, fd, buf, 4) != 4TRUE | never evaluated | FALSE | never evaluated |
|| | 0 |
19 | atomicio((ssize_t (*)(int, void *, size_t))write, fd, sshbuf_mutable_ptr(m),TRUE | never evaluated | FALSE | never evaluated |
| 0 |
20 | sshbuf_len(m)) != sshbuf_len(m)TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
21 | error("write to helper failed"); never executed: error("write to helper failed"); | 0 |
22 | if ((TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_consume(m, mlen)) != 0TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
23 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); never executed: fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 0 |
24 | } never executed: end of block | 0 |
25 | | - |
26 | static int | - |
27 | recv_msg(struct sshbuf *m) | - |
28 | { | - |
29 | u_int l, len; | - |
30 | u_char c, buf[1024]; | - |
31 | int r; | - |
32 | | - |
33 | if ((TRUE | never evaluated | FALSE | never evaluated |
len = atomicio(read, fd, buf, 4)) != 4TRUE | never evaluated | FALSE | never evaluated |
) { | 0 |
34 | error("read from helper failed: %u", len); | - |
35 | return never executed: return (0); (0);never executed: return (0); | 0 |
36 | } | - |
37 | len = (((u_int32_t)(((const u_char *)(buf))[0]) << 24) | ((u_int32_t)(((const u_char *)(buf))[1]) << 16) | ((u_int32_t)(((const u_char *)(buf))[2]) << 8) | (u_int32_t)(((const u_char *)(buf))[3])); | - |
38 | if (len > 256 * 1024TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
39 | fatal("response too long: %u", len); never executed: fatal("response too long: %u", len); | 0 |
40 | | - |
41 | sshbuf_reset(m); | - |
42 | while (len > 0TRUE | never evaluated | FALSE | never evaluated |
) { | 0 |
43 | l = len; | - |
44 | if (l > sizeof(buf)TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
45 | l = sizeof(buf); never executed: l = sizeof(buf); | 0 |
46 | if (atomicio(read, fd, buf, l) != lTRUE | never evaluated | FALSE | never evaluated |
) { | 0 |
47 | error("response from helper failed."); | - |
48 | return never executed: return (0); (0);never executed: return (0); | 0 |
49 | } | - |
50 | if ((TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_put(m, buf, l)) != 0TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
51 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); never executed: fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 0 |
52 | len -= l; | - |
53 | } never executed: end of block | 0 |
54 | if ((TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_get_u8(m, &c)) != 0TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
55 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); never executed: fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 0 |
56 | return never executed: return c; c;never executed: return c; | 0 |
57 | } | - |
58 | | - |
59 | int | - |
60 | pkcs11_init(int interactive) | - |
61 | { | - |
62 | return never executed: return (0); (0);never executed: return (0); | 0 |
63 | } | - |
64 | | - |
65 | void | - |
66 | pkcs11_terminate(void) | - |
67 | { | - |
68 | if (fd >= 0TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
69 | close(fd); never executed: close(fd); | 0 |
70 | } never executed: end of block | 0 |
71 | | - |
72 | static int | - |
73 | pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, | - |
74 | int padding) | - |
75 | { | - |
76 | struct sshkey key; | - |
77 | u_char *blob, *signature = | - |
78 | ((void *)0) | - |
79 | ; | - |
80 | size_t blen, slen = 0; | - |
81 | int r, ret = -1; | - |
82 | struct sshbuf *msg; | - |
83 | | - |
84 | if (padding != TRUE | never evaluated | FALSE | never evaluated |
| 0 |
85 | 1TRUE | never evaluated | FALSE | never evaluated |
| 0 |
86 | ) | - |
87 | return never executed: return (-1); (-1);never executed: return (-1); | 0 |
88 | key.type = KEY_RSA; | - |
89 | key.rsa = rsa; | - |
90 | if ((TRUE | never evaluated | FALSE | never evaluated |
r = sshkey_to_blob(&key, &blob, &blen)) != 0TRUE | never evaluated | FALSE | never evaluated |
) { | 0 |
91 | error("%s: sshkey_to_blob: %s", __func__, ssh_err(r)); | - |
92 | return never executed: return -1; -1;never executed: return -1; | 0 |
93 | } | - |
94 | if ((TRUE | never evaluated | FALSE | never evaluated |
msg = sshbuf_new()) == TRUE | never evaluated | FALSE | never evaluated |
| 0 |
95 | ((void *)0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
96 | ) | - |
97 | fatal("%s: sshbuf_new failed", __func__); never executed: fatal("%s: sshbuf_new failed", __func__); | 0 |
98 | if ((TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_put_u8(msg, 13)) != 0TRUE | never evaluated | FALSE | never evaluated |
|| | 0 |
99 | (TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_put_string(msg, blob, blen)) != 0TRUE | never evaluated | FALSE | never evaluated |
|| | 0 |
100 | (TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_put_string(msg, from, flen)) != 0TRUE | never evaluated | FALSE | never evaluated |
|| | 0 |
101 | (TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_put_u32(msg, 0)) != 0TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
102 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); never executed: fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 0 |
103 | free(blob); | - |
104 | send_msg(msg); | - |
105 | sshbuf_reset(msg); | - |
106 | | - |
107 | if (recv_msg(msg) == 14TRUE | never evaluated | FALSE | never evaluated |
) { | 0 |
108 | if ((TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_get_string(msg, &signature, &slen)) != 0TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
109 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); never executed: fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 0 |
110 | if (slen <= (size_t)RSA_size(rsa)TRUE | never evaluated | FALSE | never evaluated |
) { | 0 |
111 | memcpy(to, signature, slen); | - |
112 | ret = slen; | - |
113 | } never executed: end of block | 0 |
114 | free(signature); | - |
115 | } never executed: end of block | 0 |
116 | sshbuf_free(msg); | - |
117 | return never executed: return (ret); (ret);never executed: return (ret); | 0 |
118 | } | - |
119 | | - |
120 | | - |
121 | static int | - |
122 | wrap_key(RSA *rsa) | - |
123 | { | - |
124 | static RSA_METHOD *helper_rsa; | - |
125 | | - |
126 | if ((TRUE | never evaluated | FALSE | never evaluated |
helper_rsa = RSA_meth_dup(RSA_get_default_method())) == TRUE | never evaluated | FALSE | never evaluated |
| 0 |
127 | ((void *)0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
128 | ) | - |
129 | fatal("%s: RSA_meth_dup failed", __func__); never executed: fatal("%s: RSA_meth_dup failed", __func__); | 0 |
130 | if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper")TRUE | never evaluated | FALSE | never evaluated |
|| | 0 |
131 | !RSA_meth_set_priv_enc(helper_rsa, pkcs11_rsa_private_encrypt)TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
132 | fatal("%s: failed to prepare method", __func__); never executed: fatal("%s: failed to prepare method", __func__); | 0 |
133 | RSA_set_method(rsa, helper_rsa); | - |
134 | return never executed: return (0); (0);never executed: return (0); | 0 |
135 | } | - |
136 | | - |
137 | static int | - |
138 | pkcs11_start_helper(void) | - |
139 | { | - |
140 | int pair[2]; | - |
141 | | - |
142 | if (socketpair(TRUE | never evaluated | FALSE | never evaluated |
| 0 |
143 | 1TRUE | never evaluated | FALSE | never evaluated |
| 0 |
144 | , TRUE | never evaluated | FALSE | never evaluated |
| 0 |
145 | SOCK_STREAMTRUE | never evaluated | FALSE | never evaluated |
| 0 |
146 | , 0, pair) == -1TRUE | never evaluated | FALSE | never evaluated |
) { | 0 |
147 | error("socketpair: %s", strerror( | - |
148 | (*__errno_location ()) | - |
149 | )); | - |
150 | return never executed: return (-1); (-1);never executed: return (-1); | 0 |
151 | } | - |
152 | if ((TRUE | never evaluated | FALSE | never evaluated |
pid = fork()) == -1TRUE | never evaluated | FALSE | never evaluated |
) { | 0 |
153 | error("fork: %s", strerror( | - |
154 | (*__errno_location ()) | - |
155 | )); | - |
156 | return never executed: return (-1); (-1);never executed: return (-1); | 0 |
157 | } else if (pid == 0TRUE | never evaluated | FALSE | never evaluated |
) { | 0 |
158 | if ((TRUE | never evaluated | FALSE | never evaluated |
dup2(pair[1], TRUE | never evaluated | FALSE | never evaluated |
| 0 |
159 | 0TRUE | never evaluated | FALSE | never evaluated |
| 0 |
160 | ) == -1)TRUE | never evaluated | FALSE | never evaluated |
|| | 0 |
161 | (TRUE | never evaluated | FALSE | never evaluated |
dup2(pair[1], TRUE | never evaluated | FALSE | never evaluated |
| 0 |
162 | 1TRUE | never evaluated | FALSE | never evaluated |
| 0 |
163 | ) == -1)TRUE | never evaluated | FALSE | never evaluated |
) { | 0 |
164 | fprintf( | - |
165 | stderr | - |
166 | , "dup2: %s\n", strerror( | - |
167 | (*__errno_location ()) | - |
168 | )); | - |
169 | _exit(1); | - |
170 | } never executed: end of block | 0 |
171 | close(pair[0]); | - |
172 | close(pair[1]); | - |
173 | execlp("/var/tmp/openssh-test/libexec/ssh-pkcs11-helper", "/var/tmp/openssh-test/libexec/ssh-pkcs11-helper", | - |
174 | (char *) | - |
175 | ((void *)0) | - |
176 | ); | - |
177 | fprintf( | - |
178 | stderr | - |
179 | , "exec: %s: %s\n", "/var/tmp/openssh-test/libexec/ssh-pkcs11-helper", | - |
180 | strerror( | - |
181 | (*__errno_location ()) | - |
182 | )); | - |
183 | _exit(1); | - |
184 | } never executed: end of block | 0 |
185 | close(pair[1]); | - |
186 | fd = pair[0]; | - |
187 | return never executed: return (0); (0);never executed: return (0); | 0 |
188 | } | - |
189 | | - |
190 | int | - |
191 | pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp) | - |
192 | { | - |
193 | struct sshkey *k; | - |
194 | int r; | - |
195 | u_char *blob; | - |
196 | size_t blen; | - |
197 | u_int nkeys, i; | - |
198 | struct sshbuf *msg; | - |
199 | | - |
200 | if (fd < 0TRUE | never evaluated | FALSE | never evaluated |
&& pkcs11_start_helper() < 0TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
201 | return never executed: return (-1); (-1);never executed: return (-1); | 0 |
202 | | - |
203 | if ((TRUE | never evaluated | FALSE | never evaluated |
msg = sshbuf_new()) == TRUE | never evaluated | FALSE | never evaluated |
| 0 |
204 | ((void *)0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
205 | ) | - |
206 | fatal("%s: sshbuf_new failed", __func__); never executed: fatal("%s: sshbuf_new failed", __func__); | 0 |
207 | if ((TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_put_u8(msg, 20)) != 0TRUE | never evaluated | FALSE | never evaluated |
|| | 0 |
208 | (TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_put_cstring(msg, name)) != 0TRUE | never evaluated | FALSE | never evaluated |
|| | 0 |
209 | (TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_put_cstring(msg, pin)) != 0TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
210 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); never executed: fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 0 |
211 | send_msg(msg); | - |
212 | sshbuf_reset(msg); | - |
213 | | - |
214 | if (recv_msg(msg) == 12TRUE | never evaluated | FALSE | never evaluated |
) { | 0 |
215 | if ((TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_get_u32(msg, &nkeys)) != 0TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
216 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); never executed: fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 0 |
217 | *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); | - |
218 | for (i = 0; i < nkeysTRUE | never evaluated | FALSE | never evaluated |
; i++) { | 0 |
219 | | - |
220 | if ((TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_get_string(msg, &blob, &blen)) != 0TRUE | never evaluated | FALSE | never evaluated |
|| | 0 |
221 | (TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_get_string_direct(msg, TRUE | never evaluated | FALSE | never evaluated |
| 0 |
222 | ((void *)0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
223 | , TRUE | never evaluated | FALSE | never evaluated |
| 0 |
224 | ((void *)0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
225 | )) != 0TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
226 | fatal("%s: buffer error: %s", never executed: fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 0 |
227 | __func__, ssh_err(r)); never executed: fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 0 |
228 | if ((TRUE | never evaluated | FALSE | never evaluated |
r = sshkey_from_blob(blob, blen, &k)) != 0TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
229 | fatal("%s: bad key: %s", __func__, ssh_err(r)); never executed: fatal("%s: bad key: %s", __func__, ssh_err(r)); | 0 |
230 | wrap_key(k->rsa); | - |
231 | (*keysp)[i] = k; | - |
232 | free(blob); | - |
233 | } never executed: end of block | 0 |
234 | } never executed: end of block else { | 0 |
235 | nkeys = -1; | - |
236 | } never executed: end of block | 0 |
237 | sshbuf_free(msg); | - |
238 | return never executed: return (nkeys); (nkeys);never executed: return (nkeys); | 0 |
239 | } | - |
240 | | - |
241 | int | - |
242 | pkcs11_del_provider(char *name) | - |
243 | { | - |
244 | int r, ret = -1; | - |
245 | struct sshbuf *msg; | - |
246 | | - |
247 | if ((TRUE | never evaluated | FALSE | never evaluated |
msg = sshbuf_new()) == TRUE | never evaluated | FALSE | never evaluated |
| 0 |
248 | ((void *)0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
249 | ) | - |
250 | fatal("%s: sshbuf_new failed", __func__); never executed: fatal("%s: sshbuf_new failed", __func__); | 0 |
251 | if ((TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_put_u8(msg, 21)) != 0TRUE | never evaluated | FALSE | never evaluated |
|| | 0 |
252 | (TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_put_cstring(msg, name)) != 0TRUE | never evaluated | FALSE | never evaluated |
|| | 0 |
253 | (TRUE | never evaluated | FALSE | never evaluated |
r = sshbuf_put_cstring(msg, "")) != 0TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
254 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); never executed: fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 0 |
255 | send_msg(msg); | - |
256 | sshbuf_reset(msg); | - |
257 | | - |
258 | if (recv_msg(msg) == 6TRUE | never evaluated | FALSE | never evaluated |
) | 0 |
259 | ret = 0; never executed: ret = 0; | 0 |
260 | sshbuf_free(msg); | - |
261 | return never executed: return (ret); (ret);never executed: return (ret); | 0 |
262 | } | - |
| | |