示例#1
0
/**
 * Processes encryption key information received in a REGISTER message
 */
int handle_register_keys(const struct register_h *reg,
                         const unsigned char *enckey,
                         struct pr_group_list_t *group, int hostidx,
                         uint32_t src)
{
    unsigned char premaster[PUBKEY_LEN];
    unsigned int len;
    struct pr_destinfo_t *dest;

    dest = &group->destinfo[hostidx];
    memcpy(dest->rand2, reg->rand2, sizeof(dest->rand2));
    if (group->keyextype == KEYEX_RSA) {
        if (!RSA_decrypt(group->proxy_privkey.rsa, enckey,
                         ntohs(reg->keyinfo_len), premaster, &len)) {
            glog1(group, "Rejecting REGISTER from %s: "
                         "failed to decrypt premaster secret", dest->name);
            return 0;
        }
        if (len != MASTER_LEN) {
            glog1(group, "Rejecting REGISTER from %s: "
                         "premaster secret wrong length", dest->name);
            return 0;
        }
    } else {
        if (!import_EC_key(&dest->dhkey.ec, enckey,
                           ntohs(reg->keyinfo_len), 1)) {
            glog1(group, "Rejecting REGISTER from %s: "
                         "failed to import ECDH key", dest->name);
            return 0;
        }
        if (get_EC_curve(dest->dhkey.ec) !=
                get_EC_curve(group->proxy_dhkey.ec)) {
            glog1(group, "Rejecting REGISTER from %s: "
                         "invalid curve for ECDH", dest->name);
            return 0;
        }
        if (!get_ECDH_key(dest->dhkey.ec, group->proxy_dhkey.ec,
                          premaster, &len)) {
            glog1(group, "Rejecting REGISTER from %s: "
                         "failed to calculate premaster secret", dest->name);
            return 0;
        }

    }
    memcpy(dest->premaster, premaster, len);
    dest->premaster_len = len;
    calculate_client_keys(group, hostidx);

    if (dest->pubkey.key) {
        if (!verify_client_key(group, hostidx)) {
            return 0;
        }
    }

    return 1;
}
示例#2
0
/**
 * Read encryption related fields from an ANNOUNCE
 */
int read_announce_encryption(struct group_list_t *group,
                             struct enc_info_he *encinfo,
                             const unsigned char *packet, int packetlen)
{
    int keyextype, sigtype, keytype, i;
    unsigned char *keys;

    keys = (unsigned char *)encinfo + sizeof(struct enc_info_he);
    // Sanity check the selected encryption parameters
    if (!cipher_supported(encinfo->keytype)) {
        glog1(group, "Keytype invalid or not supported here");
        send_abort(group, "Keytype invalid or not supported here");
        return 0;
    }
    if (!hash_supported(encinfo->hashtype)) {
        glog1(group, "Hashtype invalid or not supported here");
        send_abort(group, "Hashtype invalid or not supported here");
        return 0;
    }
    keyextype = (encinfo->keyextype_sigtype & 0xF0) >> 4;
    sigtype = encinfo->keyextype_sigtype & 0x0F;
    if (((sigtype != SIG_HMAC) && (sigtype != SIG_KEYEX) &&
                (sigtype != SIG_AUTHENC)) ||
            ((sigtype == SIG_AUTHENC) && (!is_auth_enc(encinfo->keytype)))) {
        glog1(group, "Invalid sigtype specified");
        send_abort(group, "Invalid sigtype specified");
        return 0;
    } 
    if ((keyextype != KEYEX_RSA) && (keyextype != KEYEX_ECDH_RSA) &&
            (keyextype != KEYEX_ECDH_ECDSA)) {
        glog1(group, "Invalid keyextype specified");
        send_abort(group, "Invalid keyextype specified");
        return 0;
    }
    group->keyextype = keyextype;
    group->keytype = encinfo->keytype;
    group->hashtype = encinfo->hashtype;
    group->sigtype = sigtype;
    group->client_auth = ((encinfo->flags & FLAG_CLIENT_AUTH) != 0);

    if (!verify_server_fingerprint(keys, ntohs(encinfo->keylen), group)) {
        glog1(group, "Failed to verify server key fingerprint");
        send_abort(group, "Failed to verify server key fingerprint");
        return 0;
    }

    if ((group->keyextype == KEYEX_RSA) ||
            (group->keyextype == KEYEX_ECDH_RSA)) {
        keytype = KEYBLOB_RSA;
    } else {
        keytype = KEYBLOB_EC;
    }
    // Load server key and select a matching client key
    if (keytype == KEYBLOB_RSA) {
        if (!import_RSA_key(&group->server_pubkey.rsa, keys,
                            ntohs(encinfo->keylen))) {
            glog0(group, "Failed to load server public key");
            send_abort(group, "Failed to load server public key");
            return 0;
        }
        group->server_pubkeylen = RSA_keylen(group->server_pubkey.rsa);
        for (i = 0; i < key_count; i++) {
            if ((privkey_type[i] == KEYBLOB_RSA) &&
                    (group->server_pubkeylen == RSA_keylen(privkey[i].rsa))) {
                group->client_privkey = privkey[i];
                group->client_privkeylen = RSA_keylen(privkey[i].rsa);
                break;
            }
        }
    } else {
        if (!import_EC_key(&group->server_pubkey.ec, keys,
                           ntohs(encinfo->keylen), 0)) {
            glog0(group, "Failed to load server public key");
            send_abort(group, "Failed to load server public key");
            return 0;
        }
        group->server_pubkeylen = ECDSA_siglen(group->server_pubkey.ec);
        for (i = 0; i < key_count; i++) {
            if ((privkey_type[i] == KEYBLOB_EC) &&
                    (get_EC_curve(group->server_pubkey.ec) ==
                        get_EC_curve(privkey[i].ec))) {
                group->client_privkey = privkey[i];
                group->client_privkeylen = ECDSA_siglen(privkey[i].ec);
                break;
            }
        }
    }
    if (!group->client_privkey.key) {
        glog1(group, "No client key compatible with server key");
        send_abort(group, "No client key compatible with server key");
        return 0;
    }
    if (has_proxy) {
        if (!proxy_pubkey.key) {
            glog1(group, "Response proxy set but haven't gotten key yet");
            send_abort(group,"Response proxy set but haven't gotten key yet");
            return 0;
        }
        if (!(((keytype == KEYBLOB_RSA) && (proxy_pubkeytype == KEYBLOB_RSA)) &&
                    (RSA_keylen(group->server_pubkey.rsa) ==
                        RSA_keylen(proxy_pubkey.rsa))) &&
                !(((keytype == KEYBLOB_EC) && (proxy_pubkeytype==KEYBLOB_EC)) &&
                    (get_EC_curve(group->server_pubkey.ec) ==
                        get_EC_curve(proxy_pubkey.ec)))) {
            glog1(group, "Response proxy key not compatible with server key");
            send_abort(group,
                    "Response proxy key not compatible with server key");
            return 0;
        }
    }
    if ((group->keyextype == KEYEX_ECDH_ECDSA) ||
            (group->keyextype == KEYEX_ECDH_RSA)) {
        unsigned char *sigcopy;
        int siglen;
        unsigned char *dhblob = keys + ntohs(encinfo->keylen);
        unsigned char *sig = dhblob + ntohs(encinfo->dhlen);

        if (!import_EC_key(&group->server_dhkey.ec, dhblob,
                           ntohs(encinfo->dhlen), 1)) {
            glog0(group, "Failed to load server public ECDH key");
            send_abort(group, "Failed to load server public ECDH key");
            return 0;
        }

        group->client_dhkey.ec =
                gen_EC_key(get_EC_curve(group->server_dhkey.ec), 1, NULL);
        if (!group->client_dhkey.key) {
            glog0(group, "Failed to generate client ECDH key");
            send_abort(group, "Failed to generate client ECDH key");
            return 0;
        }
        if (has_proxy) {
            // We already checked if the proxy key exists, so no need to repeat
            if (get_EC_curve(group->server_dhkey.ec) !=
                    get_EC_curve(proxy_dhkey.ec)) {
                glog1(group, "Response proxy ECDH key "
                             "not compatible with server ECDH key");
                send_abort(group, "Response proxy ECDH key "
                        "not compatible with server ECDH key");
                return 0;
            }
        }

        siglen = ntohs(encinfo->siglen);
        sigcopy = safe_calloc(siglen, 1);
        memcpy(sigcopy, sig, siglen);
        memset(sig, 0, siglen);
        if (keytype == KEYBLOB_RSA) {
            if (!verify_RSA_sig(group->server_pubkey.rsa, group->hashtype,
                                packet, packetlen, sigcopy, siglen)) {
                glog1(group, "Signature verification failed");
                send_abort(group, "Signature verification failed");
                free(sigcopy);
                return 0;
            }
        } else {
            if (!verify_ECDSA_sig(group->server_pubkey.ec, group->hashtype,
                                  packet, packetlen, sigcopy, siglen)) {
                glog1(group, "Signature verification failed");
                send_abort(group, "Signature verification failed");
                free(sigcopy);
                return 0;
            }
        }
        free(sigcopy);
    }

    // Calculate keys
    if (!calculate_server_keys(group, encinfo)) {
        return 0;
    }

    return 1;
}
示例#3
0
文件: client_common.c 项目: No9/uftp
/**
 * Process a PROXY_KEY message
 */
void handle_proxy_key(const union sockaddr_u *src,
                      unsigned char *message, unsigned meslen)
{
    struct proxy_key_h *proxykey;
    unsigned char *keyblob, *dhblob, *sig;
    unsigned char fingerprint[HMAC_LEN];
    unsigned int fplen, keylen, dhlen, siglen;
    char addrname[INET6_ADDRSTRLEN];
    int rval;

    proxykey = (struct proxy_key_h *)message;

    if (meslen < (proxykey->hlen * 4U) ||
            ((proxykey->hlen * 4U) < sizeof(struct proxy_key_h) +
                ntohs(proxykey->bloblen) + ntohs(proxykey->dhlen) +
                ntohs(proxykey->siglen))) {
        log2(0, 0, 0, "Rejecting PROXY_KEY: invalid message size");
        return;
    }

    if ((rval = getnameinfo((const struct sockaddr *)src,
            family_len(*src), addrname, sizeof(addrname),
            NULL, 0, NI_NUMERICHOST)) != 0) {
        log1(0, 0, 0, "getnameinfo failed: %s", gai_strerror(rval));
    }
    log2(0, 0, 0, "Received PROXY_KEY from %s", addrname);

    if (!has_proxy) {
        log2(0, 0, 0, "No reply proxy specified");
        return;
    }
    if (!addr_equal(&proxy_info.addr, src)) {
        log2(0, 0, 0, "PROXY_KEY not from specified reply proxy");
        return;
    }

    keyblob = (unsigned char *)proxykey + sizeof(struct proxy_key_h);
    keylen = ntohs(proxykey->bloblen);
    dhblob = keyblob + keylen;
    dhlen = ntohs(proxykey->dhlen);
    sig = dhblob + dhlen;
    siglen = ntohs(proxykey->siglen);

    if (keyblob[0] == KEYBLOB_RSA) {
        if (!import_RSA_key(&proxy_pubkey.rsa, keyblob, keylen)) {
            log0(0, 0, 0, "Failed to import public key from PROXY_KEY");
            return;
        } 
        if (proxy_info.has_fingerprint) {
            hash(HASH_SHA1, keyblob, keylen, fingerprint, &fplen);
            if (memcmp(proxy_info.fingerprint, fingerprint, fplen)) {
                log1(0, 0, 0, "Failed to verify PROXY_KEY fingerprint");
                free_RSA_key(proxy_pubkey.rsa);
                return;
            }
        }
        if (!verify_RSA_sig(proxy_pubkey.rsa, HASH_SHA1,
                            (unsigned char *)&proxykey->nonce,
                            sizeof(proxykey->nonce), sig, siglen)) {
            log1(0, 0, 0, "Failed to verify PROXY_KEY signature");
            free_RSA_key(proxy_pubkey.rsa);
            return;
        }
    } else {
        if (!import_EC_key(&proxy_pubkey.ec, keyblob, keylen, 0)) {
            log0(0, 0, 0, "Failed to import public key from PROXY_KEY");
            return;
        } 
        if (proxy_info.has_fingerprint) {
            hash(HASH_SHA1, keyblob, keylen, fingerprint, &fplen);
            if (memcmp(proxy_info.fingerprint, fingerprint, fplen)) {
                log1(0, 0, 0, "Failed to verify PROXY_KEY fingerprint");
                free_RSA_key(proxy_pubkey.rsa);
                return;
            }
        }
        if (!verify_ECDSA_sig(proxy_pubkey.ec, HASH_SHA1,
                              (unsigned char *)&proxykey->nonce,
                              sizeof(proxykey->nonce), sig, siglen)) {
            log1(0, 0, 0, "Failed to verify PROXY_KEY signature");
            free_RSA_key(proxy_pubkey.rsa);
            return;
        }
    }
    if (dhlen) {
        if (!import_EC_key(&proxy_dhkey.ec, dhblob, dhlen, 1)) {
            log0(0, 0, 0, "Failed to import ECDH public key from PROXY_KEY");
            return;
        } 
    }
}
示例#4
0
/**
 * Process an HB_REQ message
 */
void handle_hb_request(const union sockaddr_u *src,
                       unsigned char *packet, unsigned packetlen)
{
    struct hb_req_h *hbreq;
    unsigned char *keyblob, *sig;
    union key_t key;
    unsigned char fingerprint[HMAC_LEN];
    unsigned int fplen, bloblen, siglen;
    char destname[INET6_ADDRSTRLEN], destport[PORTNAME_LEN];
    int resp, rval;

    hbreq = (struct hb_req_h *)(packet + sizeof(struct uftp_h));

    if ((rval = getnameinfo((const struct sockaddr *)src, family_len(*src),
            destname, sizeof(destname), destport, sizeof(destport),
            NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
        log1(0, 0, 0, "getnameinfo failed: %s", gai_strerror(rval));
    }
    if ((packetlen < sizeof(struct uftp_h) + (hbreq->hlen * 4)) ||
            ((hbreq->hlen * 4) < sizeof(struct hb_req_h))) {
        log1(0,0,0, "Rejecting HB_REQ from %s: invalid message size", destname);
        return;
    }
    log2(0, 0, 0, "Received HB_REQ from %s", destname);
    if ((proxy_type == SERVER_PROXY) && have_down_fingerprint) {
        if (addr_equal(&down_addr, src)) {
            resp = HB_AUTH_OK;
        } else if (down_nonce != ntohl(hbreq->nonce)) {
            resp = HB_AUTH_CHALLENGE;
        } else {
            keyblob = (unsigned char *)hbreq + sizeof(struct hb_req_h);
            bloblen = ntohs(hbreq->bloblen);
            sig = keyblob + bloblen;
            siglen = ntohs(hbreq->siglen);

            // First check key fingerprint, then check signature
            if (keyblob[0] == KEYBLOB_RSA) {
                if (!import_RSA_key(&key.rsa, keyblob, bloblen)) {
                    log1(0, 0, 0, "Failed to import public key from HB_REQ");
                    resp = HB_AUTH_FAILED;
                    goto end;
                } 

                hash(HASH_SHA1, keyblob, bloblen, fingerprint, &fplen);
                if (memcmp(down_fingerprint, fingerprint, fplen)) {
                    log1(0, 0, 0, "Failed to verify HB_REQ fingerprint");
                    resp = HB_AUTH_FAILED;
                    goto end;
                }

                if (!verify_RSA_sig(key.rsa, HASH_SHA1,
                        (unsigned char *)&hbreq->nonce,
                        sizeof(hbreq->nonce), sig, siglen)) {
                    log1(0, 0, 0, "Failed to verify HB_REQ signature");
                    resp = HB_AUTH_FAILED;
                    goto end;
                }
            } else {
                if (!import_EC_key(&key.ec, keyblob, bloblen, 0)) {
                    log1(0, 0, 0, "Failed to import public key from HB_REQ");
                    resp = HB_AUTH_FAILED;
                    goto end;
                } 

                hash(HASH_SHA1, keyblob, bloblen, fingerprint, &fplen);
                if (memcmp(down_fingerprint, fingerprint, fplen)) {
                    log1(0, 0, 0, "Failed to verify HB_REQ fingerprint");
                    resp = HB_AUTH_FAILED;
                    goto end;
                }

                if (!verify_ECDSA_sig(key.ec, HASH_SHA1,
                        (unsigned char *)&hbreq->nonce,
                        sizeof(hbreq->nonce), sig, siglen)) {
                    log1(0, 0, 0, "Failed to verify HB_REQ signature");
                    resp = HB_AUTH_FAILED;
                    goto end;
                }
            }

            down_addr = *src;
            log2(0, 0, 0, "Using %s:%s as downstream address:port",
                       destname, destport);
            down_nonce = rand32();
            resp = HB_AUTH_OK;
        }
    } else {
        resp = HB_AUTH_OK;
    }

end:
    send_hb_response(src, resp);
}
示例#5
0
/**
 * Handles an incoming CLIENT_KEY message from a client.
 */
void handle_clientkey(struct pr_group_list_t *group, int hostidx,
                      const unsigned char *message, unsigned meslen,
                      uint32_t src)
{
    const struct client_key_h *clientkey;
    const unsigned char *keyblob, *verify;
    struct pr_destinfo_t *dest;
    int dupmsg;

    clientkey = (const struct client_key_h *)message;
    keyblob = (const unsigned char *)clientkey + sizeof(struct client_key_h);
    verify = keyblob + ntohs(clientkey->bloblen);

    if (group->destcount == MAXPROXYDEST) {
        glog1(group, "Rejecting CLIENT_KEY from %08X: "
                     "max destinations exceeded", ntohl(src));
        send_downstream_abort(group, src, "Max destinations exceeded", 0);
        return;
    }
    if ((meslen < (clientkey->hlen * 4U)) ||
            ((clientkey->hlen * 4U) < sizeof(struct client_key_h) +
                ntohs(clientkey->bloblen) + ntohs(clientkey->siglen))) {
        glog1(group, "Rejecting CLIENT_KEY from %08X: invalid message size",
                     ntohl(src));
        send_downstream_abort(group, src, "Invalid message size", 0);
        return;
    }
    if ((((group->keyextype == KEYEX_RSA) ||
                    (group->keyextype == KEYEX_ECDH_RSA)) &&
                (keyblob[0] != KEYBLOB_RSA)) ||
            ((group->keyextype == KEYEX_ECDH_ECDSA) &&
             (keyblob[0] != KEYBLOB_EC))) {
        glog1(group, "Rejecting CLIENT_KEY from %08X: invalid keyblob type",
                     ntohl(src));
        send_downstream_abort(group, src, "Invalid keyblob type", 0);
        return;
    }


    if (hostidx == -1) {
        hostidx = add_client(src, group);
    }
    dest = &group->destinfo[hostidx];
    dupmsg = (dest->pubkey.key != 0);

    if (!dest->verified) {
        if (keyblob[0] == KEYBLOB_RSA) {
            if (!import_RSA_key(&dest->pubkey.rsa, keyblob,
                                ntohs(clientkey->bloblen))) {
                glog1(group, "Failed to load client public key");
                send_downstream_abort(group, src,
                                      "Failed to load client public key", 0);
                return;
            }
            dest->pubkeylen = RSA_keylen(dest->pubkey.rsa);
        } else {
            if (!import_EC_key(&dest->pubkey.ec, keyblob,
                               ntohs(clientkey->bloblen), 0)) {
                glog1(group, "Failed to load client public key");
                send_downstream_abort(group, src,
                                      "Failed to load client public key", 0);
                return;
            }
            dest->pubkeylen = ECDSA_siglen(dest->pubkey.ec);
        }
        if (!verify_fingerprint(client_fp, client_fp_count, keyblob,
                                ntohs(clientkey->bloblen), group, src)) {
            glog1(group, "Failed to verify client key fingerprint");
            send_downstream_abort(group, src, 
                                  "Failed to verify client key fingerprint", 0);
            return;
        }
        dest->verified = 1;
    }

    memcpy(dest->verifydata, verify, ntohs(clientkey->siglen));
    dest->verifylen = ntohs(clientkey->siglen);
    if (dest->registered) {
        if (!verify_client_key(group, hostidx)) {
            return;
        }
        dest->state = PR_CLIENT_REGISTERED;
    }

    glog2(group,"Received CLIENT_KEY%s from %s", dupmsg ? "+" : "", dest->name);

    if (dest->state == PR_CLIENT_REGISTERED) {
        // Pass in a dummy REGISTER message to check_pending, since
        // CLIENT_KEY is basically an extension of REGISTER.
        struct register_h reg;
        reg.func = REGISTER;
        check_pending(group, hostidx, (unsigned char *)&reg);
    }
}