| 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) != 4| TRUE | 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)) != 0| TRUE | 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)) != 4| TRUE | 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 * 1024| TRUE | 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 > 0| TRUE | 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) != l| TRUE | 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)) != 0| TRUE | 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)) != 0| TRUE | 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 >= 0| TRUE | 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 | 1| TRUE | 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)) != 0| TRUE | 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)) != 0| TRUE | never evaluated | | FALSE | never evaluated |
|| | 0 |
| 99 | (| TRUE | never evaluated | | FALSE | never evaluated |
r = sshbuf_put_string(msg, blob, blen)) != 0| TRUE | never evaluated | | FALSE | never evaluated |
|| | 0 |
| 100 | (| TRUE | never evaluated | | FALSE | never evaluated |
r = sshbuf_put_string(msg, from, flen)) != 0| TRUE | never evaluated | | FALSE | never evaluated |
|| | 0 |
| 101 | (| TRUE | never evaluated | | FALSE | never evaluated |
r = sshbuf_put_u32(msg, 0)) != 0| TRUE | 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) == 14| TRUE | never evaluated | | FALSE | never evaluated |
) { | 0 |
| 108 | if ((| TRUE | never evaluated | | FALSE | never evaluated |
r = sshbuf_get_string(msg, &signature, &slen)) != 0| TRUE | 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 | 1| TRUE | never evaluated | | FALSE | never evaluated |
| 0 |
| 144 | , | TRUE | never evaluated | | FALSE | never evaluated |
| 0 |
| 145 | SOCK_STREAM| TRUE | never evaluated | | FALSE | never evaluated |
| 0 |
| 146 | , 0, pair) == -1| TRUE | 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()) == -1| TRUE | 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 == 0| TRUE | 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 | 0| TRUE | 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 | 1| TRUE | 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 < 0| TRUE | never evaluated | | FALSE | never evaluated |
&& pkcs11_start_helper() < 0| TRUE | 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)) != 0| TRUE | never evaluated | | FALSE | never evaluated |
|| | 0 |
| 208 | (| TRUE | never evaluated | | FALSE | never evaluated |
r = sshbuf_put_cstring(msg, name)) != 0| TRUE | never evaluated | | FALSE | never evaluated |
|| | 0 |
| 209 | (| TRUE | never evaluated | | FALSE | never evaluated |
r = sshbuf_put_cstring(msg, pin)) != 0| TRUE | 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) == 12| TRUE | never evaluated | | FALSE | never evaluated |
) { | 0 |
| 215 | if ((| TRUE | never evaluated | | FALSE | never evaluated |
r = sshbuf_get_u32(msg, &nkeys)) != 0| TRUE | 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 < nkeys| TRUE | never evaluated | | FALSE | never evaluated |
; i++) { | 0 |
| 219 | | - |
| 220 | if ((| TRUE | never evaluated | | FALSE | never evaluated |
r = sshbuf_get_string(msg, &blob, &blen)) != 0| TRUE | 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 | )) != 0| TRUE | 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)) != 0| TRUE | 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)) != 0| TRUE | never evaluated | | FALSE | never evaluated |
|| | 0 |
| 252 | (| TRUE | never evaluated | | FALSE | never evaluated |
r = sshbuf_put_cstring(msg, name)) != 0| TRUE | never evaluated | | FALSE | never evaluated |
|| | 0 |
| 253 | (| TRUE | never evaluated | | FALSE | never evaluated |
r = sshbuf_put_cstring(msg, "")) != 0| TRUE | 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) == 6| TRUE | 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 | } | - |
| | |