Пример #1
0
int
dh_gm_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in,
        BN_CTX *bn_ctx)
{
    int ret = 0;
    BUF_MEM * mem_h = NULL;
    BIGNUM * bn_s = NULL, *bn_h = NULL, *bn_g = NULL;
    DH *static_key = NULL, *ephemeral_key = NULL;

    check(ctx && ctx->static_key && s && ctx->ka_ctx, "Invalid arguments");

    BN_CTX_start(bn_ctx);

    static_key = EVP_PKEY_get1_DH(ctx->static_key);
    if (!static_key)
        goto err;

    /* Convert nonce to BIGNUM */
    bn_s = BN_bin2bn((unsigned char *) s->data, s->length, bn_s);
    if (!bn_s)
        goto err;

    /* complete the DH and convert the result to a BIGNUM */
    mem_h = dh_compute_key(ctx->static_key, in, bn_ctx);
    if (!mem_h)
        goto err;
    bn_h = BN_bin2bn((unsigned char *) mem_h->data, mem_h->length, bn_h);
    if (!bn_h)
        goto err;

    /* Initialize ephemeral parameters with parameters from the static key */
    ephemeral_key = DHparams_dup_with_q(static_key);
    if (!ephemeral_key)
        goto err;

    /* map to new generator */
    bn_g = BN_CTX_get(bn_ctx);
    if (!bn_g ||
        /* bn_g = g^s mod p */
        !BN_mod_exp(bn_g, static_key->g, bn_s, static_key->p, bn_ctx) ||
        /* ephemeral_key->g = bn_g * h mod p = g^s * h mod p */
        !BN_mod_mul(ephemeral_key->g, bn_g, bn_h, static_key->p, bn_ctx))
        goto err;

    /* Copy ephemeral key to context structure */
    if (!EVP_PKEY_set1_DH(ctx->ka_ctx->key, ephemeral_key))
        goto err;

    ret = 1;

err:
    if (mem_h) {
        OPENSSL_cleanse(mem_h->data, mem_h->max);
        BUF_MEM_free(mem_h);
    }
    if (bn_h)
        BN_clear_free(bn_h);
    if (bn_s)
        BN_clear_free(bn_s);
    /* Decrement reference count, keys are still available via PACE_CTX */
    if (static_key)
        DH_free(static_key);
    if (ephemeral_key)
        DH_free(ephemeral_key);
    BN_CTX_end(bn_ctx);

    return ret;
}
Пример #2
0
EVP_PKEY *
EVP_PKEY_dup(EVP_PKEY *key)
{
    EVP_PKEY *out = NULL;
    DH *dh_in = NULL, *dh_out = NULL;
    EC_KEY *ec_in = NULL, *ec_out = NULL;
    RSA *rsa_in = NULL, *rsa_out = NULL;

    check(key, "Invalid arguments");

    out = EVP_PKEY_new();

    if (!out)
        goto err;

    switch (EVP_PKEY_base_id(key)) {
        case EVP_PKEY_DH:
            dh_in = EVP_PKEY_get1_DH(key);
            if (!dh_in)
                goto err;

            dh_out = DHparams_dup_with_q(dh_in);
            if (!dh_out)
                goto err;

            EVP_PKEY_set1_DH(out, dh_out);
            DH_free(dh_out);
            DH_free(dh_in);
            break;

        case EVP_PKEY_EC:
            ec_in = EVP_PKEY_get1_EC_KEY(key);
            if (!ec_in)
                goto err;

            ec_out = EC_KEY_dup(ec_in);
            if (!ec_out)
                goto err;

            EVP_PKEY_set1_EC_KEY(out, ec_out);
            EC_KEY_free(ec_out);
            EC_KEY_free(ec_in);
            break;

        case EVP_PKEY_RSA:
            rsa_in = EVP_PKEY_get1_RSA(key);
            if (!rsa_in)
                goto err;

            rsa_out = RSAPrivateKey_dup(rsa_in);
            if (!rsa_out)
                goto err;

            EVP_PKEY_set1_RSA(out, rsa_out);
            RSA_free(rsa_out);
            RSA_free(rsa_in);
            break;

        default:
            log_err("Unknown protocol");
            goto err;
    }

    return out;

err:
    if (dh_in)
        DH_free(dh_in);
    if (ec_in)
        EC_KEY_free(ec_in);
    if (rsa_in)
        RSA_free(rsa_in);

    return NULL;
}
Пример #3
0
int
dh_im_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in,
        BN_CTX *bn_ctx)
{
    int ret = 0;
    BUF_MEM * x_mem = NULL;
    BIGNUM * x_bn = NULL, *a = NULL, *p_1 = NULL, *q = NULL;
    DH *static_key = NULL, *ephemeral_key = NULL;

    check((ctx && in && ctx->ka_ctx), "Invalid arguments");
    if (in->length < (size_t) EVP_CIPHER_key_length(ctx->ka_ctx->cipher)
            || !ctx->static_key)
        goto err;

    BN_CTX_start(bn_ctx);

    static_key = EVP_PKEY_get1_DH(ctx->static_key);
    if (!static_key)
        goto err;

    /* Initialize ephemeral parameters with parameters from the static key */
    ephemeral_key = DHparams_dup_with_q(static_key);
    if (!ephemeral_key)
        goto err;

    /* Perform the actual mapping */
    x_mem = cipher_no_pad(ctx->ka_ctx, NULL, in, s, 1);
    if (!x_mem)
        goto err;
    x_bn = BN_bin2bn((unsigned char *) x_mem->data, x_mem->length, x_bn);
    a = BN_CTX_get(bn_ctx);
    q = DH_get_q(static_key, bn_ctx);
    p_1 = BN_dup(static_key->p);
    if (!x_bn || !a || !q || !p_1 ||
            /* p_1 = p-1 */
            !BN_sub_word(p_1, 1) ||
            /* a = p-1 / q */
            !BN_div(a, NULL, p_1, q, bn_ctx) ||
            /* g~ = x^a mod p */
            !BN_mod_exp(ephemeral_key->g, x_bn, a, static_key->p, bn_ctx))
        goto err;

    /* check if g~ != 1 */
    check((!BN_is_one(ephemeral_key->g)), "Bad DH generator");

    /* Copy ephemeral key to context structure */
    if (!EVP_PKEY_set1_DH(ctx->ka_ctx->key, ephemeral_key))
        goto err;

    ret = 1;

err:
    if (q)
        BN_clear_free(q);
    if (p_1)
        BN_clear_free(p_1);
    if (x_bn)
        BN_clear_free(x_bn);
    if (x_mem)
        BUF_MEM_free(x_mem);
    /* Decrement reference count, keys are still available via PACE_CTX */
    if (static_key)
        DH_free(static_key);
    if (ephemeral_key)
        DH_free(ephemeral_key);
    BN_CTX_end(bn_ctx);

    return ret;
}