예제 #1
0
파일: ampe.c 프로젝트: cococorp/authsae
/**
 * protect_frame - add in-place the MIC and the (encrypted) AMPE ie to a frame
 * @cand:       The candidate this frame is destined for
 * @mgmt:       The frame, populated with all the information elements  up to where the MIC information element should go
 * @mic_start:  Pointer to where the mic and AMPE ies are to be written.  Should point to the start of the IE, not the IE body.
 * @len:        On input, the total buffer size that contains this frame.  On output, the actual lenght of the frame
 *              including the two information elements added by this function.
 *
 * Returns: The zero on success, or some error.
 */
static int protect_frame(struct candidate *cand, struct ieee80211_mgmt_frame *mgmt, unsigned char *mic_start, int *len)
{
    unsigned char *clear_ampe_ie;
    unsigned char *ie;
    unsigned short cat_to_mic_len;

    assert(mic_start && cand && mgmt && len);

#define MIC_IE_BODY_SIZE     AES_BLOCK_SIZE

    if (mic_start + MIC_IE_BODY_SIZE + 2 + sizeof(struct ampe_ie) + 2 - (unsigned char *) mgmt > *len) {
		sae_debug(AMPE_DEBUG_KEYS, "protect frame: buffer too small\n");
        return -EINVAL;
    }

    clear_ampe_ie = malloc(sizeof(struct ampe_ie) + 2);
    if (!clear_ampe_ie) {
		sae_debug(AMPE_DEBUG_KEYS, "protect frame: out of memory\n");
        return -ENOMEM;
    }

    /*  IE: AMPE */
    ie = clear_ampe_ie;
    *ie++ = IEEE80211_EID_AMPE;
    *ie++ = sizeof(struct ampe_ie);
    memcpy(ie, pw_suite_selector, 4);
    ie += 4;
    memcpy(ie, cand->my_nonce, 32);
    ie += 32;
    memcpy(ie, cand->peer_nonce, 32);
    ie += 32;
    memcpy(ie, mgtk_tx, 16);
    ie += 16;
    memset(ie, 0, 8);           /*  TODO: Populate Key RSC */
    ie += 8;
    memset(ie, 0xff, 4);        /*  expire in 13 decades or so */
    ie += 4;

    /* IE: MIC */
    ie = mic_start;
    *ie++ = IEEE80211_EID_MIC;
    *ie++ = MIC_IE_BODY_SIZE;

    cat_to_mic_len = mic_start - (unsigned char *) &mgmt->action;
    siv_encrypt(&cand->sivctx, clear_ampe_ie, ie + MIC_IE_BODY_SIZE,
            sizeof(struct ampe_ie) + 2,
            ie, 3,
            cand->my_mac, ETH_ALEN,
            cand->peer_mac, ETH_ALEN,
            &mgmt->action, cat_to_mic_len);

    *len = mic_start - (unsigned char *) mgmt + sizeof(struct ampe_ie) + 2 + MIC_IE_BODY_SIZE + 2;

    sae_debug(AMPE_DEBUG_KEYS, "Protecting frame from " MACSTR " to " MACSTR "\n",
            MAC2STR(cand->my_mac), MAC2STR(cand->peer_mac));
    sae_debug(AMPE_DEBUG_KEYS, "Checking tricky lengths of protected frame %d, %d\n",
            cat_to_mic_len, sizeof(struct ampe_ie) + 2);

    sae_hexdump(AMPE_DEBUG_KEYS, "SIV- Put AAD[3]: ", (unsigned char *) &mgmt->action, cat_to_mic_len);

    free(clear_ampe_ie);

    return 0;
}
예제 #2
0
/**
 * protect_frame - add in-place the MIC and the (encrypted) AMPE ie to a frame
 * @cand:       The candidate this frame is destined for
 * @mgmt:       The frame, populated with all the information elements  up to where the MIC information element should go
 * @mic_start:  Pointer to where the mic and AMPE ies are to be written.  Should point to the start of the IE, not the IE body.
 * @len:        On input, the total buffer size that contains this frame.  On output, the actual lenght of the frame
 *              including the two information elements added by this function.
 *
 * Returns: The zero on success, or some error.
 */
static int protect_frame(struct candidate *cand, struct ieee80211_mgmt_frame *mgmt, unsigned char *mic_start, int *len)
{
    unsigned char *clear_ampe_ie;
    unsigned char *ie;
    unsigned short cat_to_mic_len;
    struct mesh_node *mesh = cand->conf->mesh;
    size_t ampe_ie_len;
    u8 ftype = mgmt->action.action_code;
    le16 igtk_keyid;

    assert(mic_start && cand && mgmt && len);

#define MIC_IE_BODY_SIZE     AES_BLOCK_SIZE

    ampe_ie_len = sizeof(struct ampe_ie);

    if (ftype != PLINK_CLOSE) {
        /* MGTK + RSC + Exp */
        ampe_ie_len += 16 + 8 + 4;

        if (mesh->conf->pmf) {
            /* IGTK KeyId + IPN + IGTK */
            ampe_ie_len += 2 + 6 + 16;
        }
    }

    if (mic_start + MIC_IE_BODY_SIZE + 2 +
        2 + ampe_ie_len - (unsigned char *) mgmt > *len) {
		sae_debug(AMPE_DEBUG_KEYS, "protect frame: buffer too small\n");
        return -EINVAL;
    }

    clear_ampe_ie = malloc(ampe_ie_len + 2);
    if (!clear_ampe_ie) {
		sae_debug(AMPE_DEBUG_KEYS, "protect frame: out of memory\n");
        return -ENOMEM;
    }

    /*  IE: AMPE */
    ie = clear_ampe_ie;
    *ie++ = IEEE80211_EID_AMPE;
    *ie++ = ampe_ie_len;
    memcpy(ie, pw_suite_selector, 4);
    ie += 4;
    memcpy(ie, cand->my_nonce, 32);
    ie += 32;
    memcpy(ie, cand->peer_nonce, 32);
    ie += 32;

    if (ftype != PLINK_CLOSE) {
        memcpy(ie, mgtk_tx, 16);
        ie += 16;
        memset(ie, 0, 8);           /*  TODO: Populate Key RSC */
        ie += 8;
        memset(ie, 0xff, 4);        /*  expire in 13 decades or so */
        ie += 4;

        if (mesh->conf->pmf) {
            igtk_keyid = htole16(mesh->igtk_keyid);
            memcpy(ie, &igtk_keyid, 2);
            ie += 2;
            memcpy(ie, mesh->igtk_ipn, 6);
            ie += 6;
            memcpy(ie, mesh->igtk_tx, 16);
            ie += 16;
        }
    }

    /* IE: MIC */
    ie = mic_start;
    *ie++ = IEEE80211_EID_MIC;
    *ie++ = MIC_IE_BODY_SIZE;

    cat_to_mic_len = mic_start - (unsigned char *) &mgmt->action;
    siv_encrypt(&cand->sivctx, clear_ampe_ie, ie + MIC_IE_BODY_SIZE,
            ampe_ie_len + 2,
            ie, 3,
            cand->my_mac, ETH_ALEN,
            cand->peer_mac, ETH_ALEN,
            &mgmt->action, cat_to_mic_len);

    *len = mic_start - (unsigned char *) mgmt + ampe_ie_len + 2 + MIC_IE_BODY_SIZE + 2;

    sae_debug(AMPE_DEBUG_KEYS, "Protecting frame from " MACSTR " to " MACSTR "\n",
            MAC2STR(cand->my_mac), MAC2STR(cand->peer_mac));
    sae_debug(AMPE_DEBUG_KEYS, "Checking tricky lengths of protected frame %d, %d\n",
            cat_to_mic_len, ampe_ie_len + 2);

    sae_hexdump(AMPE_DEBUG_KEYS, "SIV- Put AAD[3]: ", (unsigned char *) &mgmt->action, cat_to_mic_len);

    free(clear_ampe_ie);

    return 0;
}