| Line | Source | Count |
| 1 | | - |
| 2 | | - |
| 3 | | - |
| 4 | | - |
| 5 | | - |
| 6 | | - |
| 7 | | - |
| 8 | | - |
| 9 | | - |
| 10 | | - |
| 11 | | - |
| 12 | | - |
| 13 | | - |
| 14 | | - |
| 15 | | - |
| 16 | | - |
| 17 | | - |
| 18 | | - |
| 19 | | - |
| 20 | | - |
| 21 | | - |
| 22 | | - |
| 23 | | - |
| 24 | | - |
| 25 | | - |
| 26 | | - |
| 27 | #include "includes.h" | - |
| 28 | | - |
| 29 | #ifdef WITH_OPENSSL | - |
| 30 | | - |
| 31 | | - |
| 32 | #include <stdarg.h> | - |
| 33 | #include <stdio.h> | - |
| 34 | #include <string.h> | - |
| 35 | #include <signal.h> | - |
| 36 | | - |
| 37 | #include <openssl/dh.h> | - |
| 38 | | - |
| 39 | #include "openbsd-compat/openssl-compat.h" | - |
| 40 | | - |
| 41 | #include "sshkey.h" | - |
| 42 | #include "cipher.h" | - |
| 43 | #include "digest.h" | - |
| 44 | #include "kex.h" | - |
| 45 | #include "log.h" | - |
| 46 | #include "packet.h" | - |
| 47 | #include "dh.h" | - |
| 48 | #include "ssh2.h" | - |
| 49 | #include "compat.h" | - |
| 50 | #ifdef GSSAPI | - |
| 51 | #include "ssh-gss.h" | - |
| 52 | #endif | - |
| 53 | #include "monitor_wrap.h" | - |
| 54 | #include "dispatch.h" | - |
| 55 | #include "ssherr.h" | - |
| 56 | #include "sshbuf.h" | - |
| 57 | #include "misc.h" | - |
| 58 | | - |
| 59 | static int input_kex_dh_gex_request(int, u_int32_t, struct ssh *); | - |
| 60 | static int input_kex_dh_gex_init(int, u_int32_t, struct ssh *); | - |
| 61 | | - |
| 62 | int | - |
| 63 | kexgex_server(struct ssh *ssh) | - |
| 64 | { | - |
| 65 | ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST, | - |
| 66 | &input_kex_dh_gex_request); | - |
| 67 | debug("expecting SSH2_MSG_KEX_DH_GEX_REQUEST"); | - |
| 68 | return 0;executed 40 times by 1 test: return 0; | 40 |
| 69 | } | - |
| 70 | | - |
| 71 | static int | - |
| 72 | input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh) | - |
| 73 | { | - |
| 74 | struct kex *kex = ssh->kex; | - |
| 75 | int r; | - |
| 76 | u_int min = 0, max = 0, nbits = 0; | - |
| 77 | const BIGNUM *dh_p, *dh_g; | - |
| 78 | | - |
| 79 | debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); | - |
| 80 | if ((r = sshpkt_get_u32(ssh, &min)) != 0 ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 81 | (r = sshpkt_get_u32(ssh, &nbits)) != 0 ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 82 | (r = sshpkt_get_u32(ssh, &max)) != 0 ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 83 | (r = sshpkt_get_end(ssh)) != 0)| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 84 | goto out; never executed: goto out; | 0 |
| 85 | kex->nbits = nbits; | - |
| 86 | kex->min = min; | - |
| 87 | kex->max = max; | - |
| 88 | min = MAXIMUM(DH_GRP_MIN, min);| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 89 | max = MINIMUM(DH_GRP_MAX, max);| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 90 | nbits = MAXIMUM(DH_GRP_MIN, nbits);| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 91 | nbits = MINIMUM(DH_GRP_MAX, nbits);| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 92 | | - |
| 93 | if (kex->max < kex->min || kex->nbits < kex->min ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 94 | kex->max < kex->nbits || kex->max < DH_GRP_MIN) {| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 95 | r = SSH_ERR_DH_GEX_OUT_OF_RANGE; | - |
| 96 | goto out; never executed: goto out; | 0 |
| 97 | } | - |
| 98 | | - |
| 99 | | - |
| 100 | kex->dh = PRIVSEP(choose_dh(min, nbits, max));| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 101 | if (kex->dh == NULL) {| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 102 | sshpkt_disconnect(ssh, "no matching DH grp found"); | - |
| 103 | r = SSH_ERR_ALLOC_FAIL; | - |
| 104 | goto out; never executed: goto out; | 0 |
| 105 | } | - |
| 106 | debug("SSH2_MSG_KEX_DH_GEX_GROUP sent"); | - |
| 107 | DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); | - |
| 108 | if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_GROUP)) != 0 ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 109 | (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 110 | (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 111 | (r = sshpkt_send(ssh)) != 0)| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 112 | goto out; never executed: goto out; | 0 |
| 113 | | - |
| 114 | | - |
| 115 | if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 116 | goto out; never executed: goto out; | 0 |
| 117 | | - |
| 118 | debug("expecting SSH2_MSG_KEX_DH_GEX_INIT"); | - |
| 119 | ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &input_kex_dh_gex_init); | - |
| 120 | r = 0; | - |
| 121 | out:code before this statement executed 40 times by 1 test: out: | 40 |
| 122 | return r;executed 40 times by 1 test: return r; | 40 |
| 123 | } | - |
| 124 | | - |
| 125 | static int | - |
| 126 | input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) | - |
| 127 | { | - |
| 128 | struct kex *kex = ssh->kex; | - |
| 129 | BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; | - |
| 130 | const BIGNUM *pub_key, *dh_p, *dh_g; | - |
| 131 | struct sshkey *server_host_public, *server_host_private; | - |
| 132 | u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; | - |
| 133 | u_char hash[SSH_DIGEST_MAX_LENGTH]; | - |
| 134 | size_t sbloblen, slen; | - |
| 135 | size_t klen = 0, hashlen; | - |
| 136 | int kout, r; | - |
| 137 | | - |
| 138 | if (kex->load_host_public_key == NULL ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 139 | kex->load_host_private_key == NULL) {| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 140 | r = SSH_ERR_INVALID_ARGUMENT; | - |
| 141 | goto out; never executed: goto out; | 0 |
| 142 | } | - |
| 143 | server_host_public = kex->load_host_public_key(kex->hostkey_type, | - |
| 144 | kex->hostkey_nid, ssh); | - |
| 145 | server_host_private = kex->load_host_private_key(kex->hostkey_type, | - |
| 146 | kex->hostkey_nid, ssh); | - |
| 147 | if (server_host_public == NULL) {| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 148 | r = SSH_ERR_NO_HOSTKEY_LOADED; | - |
| 149 | goto out; never executed: goto out; | 0 |
| 150 | } | - |
| 151 | | - |
| 152 | | - |
| 153 | if ((dh_client_pub = BN_new()) == NULL) {| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 154 | r = SSH_ERR_ALLOC_FAIL; | - |
| 155 | goto out; never executed: goto out; | 0 |
| 156 | } | - |
| 157 | if ((r = sshpkt_get_bignum2(ssh, dh_client_pub)) != 0 ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 158 | (r = sshpkt_get_end(ssh)) != 0)| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 159 | goto out; never executed: goto out; | 0 |
| 160 | | - |
| 161 | DH_get0_key(kex->dh, &pub_key, NULL); | - |
| 162 | DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); | - |
| 163 | | - |
| 164 | #ifdef DEBUG_KEXDH | - |
| 165 | fprintf(stderr, "dh_client_pub= "); | - |
| 166 | BN_print_fp(stderr, dh_client_pub); | - |
| 167 | fprintf(stderr, "\n"); | - |
| 168 | debug("bits %d", BN_num_bits(dh_client_pub)); | - |
| 169 | DHparams_print_fp(stderr, kex->dh); | - |
| 170 | fprintf(stderr, "pub= "); | - |
| 171 | BN_print_fp(stderr, pub_key); | - |
| 172 | fprintf(stderr, "\n"); | - |
| 173 | #endif | - |
| 174 | if (!dh_pub_is_valid(kex->dh, dh_client_pub)) {| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 175 | sshpkt_disconnect(ssh, "bad client public DH value"); | - |
| 176 | r = SSH_ERR_MESSAGE_INCOMPLETE; | - |
| 177 | goto out; never executed: goto out; | 0 |
| 178 | } | - |
| 179 | | - |
| 180 | klen = DH_size(kex->dh); | - |
| 181 | if ((kbuf = malloc(klen)) == NULL ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 182 | (shared_secret = BN_new()) == NULL) {| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 183 | r = SSH_ERR_ALLOC_FAIL; | - |
| 184 | goto out; never executed: goto out; | 0 |
| 185 | } | - |
| 186 | if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 187 | BN_bin2bn(kbuf, kout, shared_secret) == NULL) {| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 188 | r = SSH_ERR_LIBCRYPTO_ERROR; | - |
| 189 | goto out; never executed: goto out; | 0 |
| 190 | } | - |
| 191 | #ifdef DEBUG_KEXDH | - |
| 192 | dump_digest("shared secret", kbuf, kout); | - |
| 193 | #endif | - |
| 194 | if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 195 | &sbloblen)) != 0)| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 196 | goto out; never executed: goto out; | 0 |
| 197 | | - |
| 198 | hashlen = sizeof(hash); | - |
| 199 | if ((r = kexgex_hash(| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 200 | kex->hash_alg,| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 201 | kex->client_version_string,| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 202 | kex->server_version_string,| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 203 | sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 204 | sshbuf_ptr(kex->my), sshbuf_len(kex->my),| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 205 | server_host_key_blob, sbloblen,| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 206 | kex->min, kex->nbits, kex->max,| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 207 | dh_p, dh_g,| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 208 | dh_client_pub,| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 209 | pub_key,| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 210 | shared_secret,| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 211 | hash, &hashlen)) != 0)| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 212 | goto out; never executed: goto out; | 0 |
| 213 | | - |
| 214 | | - |
| 215 | if (kex->session_id == NULL) {| TRUE | evaluated 8 times by 1 test | | FALSE | evaluated 32 times by 1 test |
| 8-32 |
| 216 | kex->session_id_len = hashlen; | - |
| 217 | kex->session_id = malloc(kex->session_id_len); | - |
| 218 | if (kex->session_id == NULL) {| TRUE | never evaluated | | FALSE | evaluated 8 times by 1 test |
| 0-8 |
| 219 | r = SSH_ERR_ALLOC_FAIL; | - |
| 220 | goto out; never executed: goto out; | 0 |
| 221 | } | - |
| 222 | memcpy(kex->session_id, hash, kex->session_id_len); | - |
| 223 | }executed 8 times by 1 test: end of block | 8 |
| 224 | | - |
| 225 | | - |
| 226 | if ((r = kex->sign(server_host_private, server_host_public, &signature,| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 227 | &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0)| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 228 | goto out; never executed: goto out; | 0 |
| 229 | | - |
| 230 | | - |
| 231 | | - |
| 232 | | - |
| 233 | if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 234 | (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 235 | (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || | TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 236 | (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 237 | (r = sshpkt_send(ssh)) != 0)| TRUE | never evaluated | | FALSE | evaluated 40 times by 1 test |
| 0-40 |
| 238 | goto out; never executed: goto out; | 0 |
| 239 | | - |
| 240 | if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)| TRUE | evaluated 40 times by 1 test | | FALSE | never evaluated |
| 0-40 |
| 241 | r = kex_send_newkeys(ssh);executed 40 times by 1 test: r = kex_send_newkeys(ssh); | 40 |
| 242 | out:code before this statement executed 40 times by 1 test: out: | 40 |
| 243 | DH_free(kex->dh); | - |
| 244 | kex->dh = NULL; | - |
| 245 | BN_clear_free(dh_client_pub); | - |
| 246 | if (kbuf) {| TRUE | evaluated 40 times by 1 test | | FALSE | never evaluated |
| 0-40 |
| 247 | explicit_bzero(kbuf, klen); | - |
| 248 | free(kbuf); | - |
| 249 | }executed 40 times by 1 test: end of block | 40 |
| 250 | BN_clear_free(shared_secret); | - |
| 251 | free(server_host_key_blob); | - |
| 252 | free(signature); | - |
| 253 | return r;executed 40 times by 1 test: return r; | 40 |
| 254 | } | - |
| 255 | #endif /* WITH_OPENSSL */ | - |
| | |