Commit 5fa7c10b authored by Matt Caswell's avatar Matt Caswell
Browse files

Fix return checks in GOST engine



Filled in lots of return value checks that were missing the GOST engine, and
added appropriate error handling.

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
(cherry picked from commit 8817e2e0)
parent 96d96746
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
/* e_gost_err.c */
/* ====================================================================
 * Copyright (c) 1999-2009 The OpenSSL Project.  All rights reserved.
 * Copyright (c) 1999-2015 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
@@ -90,6 +90,7 @@ static ERR_STRING_DATA GOST_str_functs[] = {
    {ERR_FUNC(GOST_F_GOST_IMIT_CTRL), "GOST_IMIT_CTRL"},
    {ERR_FUNC(GOST_F_GOST_IMIT_FINAL), "GOST_IMIT_FINAL"},
    {ERR_FUNC(GOST_F_GOST_IMIT_UPDATE), "GOST_IMIT_UPDATE"},
    {ERR_FUNC(GOST_F_GOST_SIGN_KEYGEN), "GOST_SIGN_KEYGEN"},
    {ERR_FUNC(GOST_F_PARAM_COPY_GOST01), "PARAM_COPY_GOST01"},
    {ERR_FUNC(GOST_F_PARAM_COPY_GOST94), "PARAM_COPY_GOST94"},
    {ERR_FUNC(GOST_F_PKEY_GOST01CP_DECRYPT), "PKEY_GOST01CP_DECRYPT"},
+1 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ void ERR_GOST_error(int function, int reason, char *file, int line);
# define GOST_F_GOST_IMIT_CTRL                            114
# define GOST_F_GOST_IMIT_FINAL                           140
# define GOST_F_GOST_IMIT_UPDATE                          115
# define GOST_F_GOST_SIGN_KEYGEN                          142
# define GOST_F_PARAM_COPY_GOST01                         116
# define GOST_F_PARAM_COPY_GOST94                         117
# define GOST_F_PKEY_GOST01CP_DECRYPT                     118
+178 −51
Original line number Diff line number Diff line
@@ -41,6 +41,11 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
    BN_CTX *ctx = BN_CTX_new();
    int ok = 0;

    if(!ctx) {
        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    BN_CTX_start(ctx);
    p = BN_CTX_get(ctx);
    a = BN_CTX_get(ctx);
@@ -48,6 +53,10 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
    x = BN_CTX_get(ctx);
    y = BN_CTX_get(ctx);
    q = BN_CTX_get(ctx);
    if(!p || !a || !b || !x || !y || !q) {
        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    while (params->nid != NID_undef && params->nid != nid)
        params++;
    if (params->nid == NID_undef) {
@@ -55,18 +64,33 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
                GOST_R_UNSUPPORTED_PARAMETER_SET);
        goto err;
    }
    BN_hex2bn(&p, params->p);
    BN_hex2bn(&a, params->a);
    BN_hex2bn(&b, params->b);
    if(!BN_hex2bn(&p, params->p)
        || !BN_hex2bn(&a, params->a)
        || !BN_hex2bn(&b, params->b)) {
        GOSTerr(GOST_F_FILL_GOST2001_PARAMS,
                ERR_R_INTERNAL_ERROR);
        goto err;
    }

    grp = EC_GROUP_new_curve_GFp(p, a, b, ctx);
    if(!grp)  {
        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    P = EC_POINT_new(grp);
    if(!P)  {
        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    BN_hex2bn(&x, params->x);
    BN_hex2bn(&y, params->y);
    EC_POINT_set_affine_coordinates_GFp(grp, P, x, y, ctx);
    BN_hex2bn(&q, params->q);
    if(!BN_hex2bn(&x, params->x)
        || !BN_hex2bn(&y, params->y)
        || !EC_POINT_set_affine_coordinates_GFp(grp, P, x, y, ctx)
        || !BN_hex2bn(&q, params->q))  {
        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR);
        goto err;
    }
#ifdef DEBUG_KEYS
    fprintf(stderr, "Set params index %d oid %s\nq=",
            (params - R3410_2001_paramset), OBJ_nid2sn(params->nid));
@@ -74,16 +98,23 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
    fprintf(stderr, "\n");
#endif

    EC_GROUP_set_generator(grp, P, q, NULL);
    if(!EC_GROUP_set_generator(grp, P, q, NULL)) {
        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    EC_GROUP_set_curve_name(grp, params->nid);

    EC_KEY_set_group(eckey, grp);
    if(!EC_KEY_set_group(eckey, grp)) {
        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    ok = 1;
 err:
    EC_POINT_free(P);
    EC_GROUP_free(grp);
    if (P) EC_POINT_free(P);
    if (grp) EC_GROUP_free(grp);
    if (ctx) {
        BN_CTX_end(ctx);
        BN_CTX_free(ctx);
    }
    return ok;
}

@@ -94,7 +125,7 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
 */
DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey)
{
    DSA_SIG *newsig = NULL;
    DSA_SIG *newsig = NULL, *ret = NULL;
    BIGNUM *md = hashsum2bn(dgst);
    BIGNUM *order = NULL;
    const EC_GROUP *group;
@@ -103,6 +134,10 @@ DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey)
        NULL, *e = NULL;
    EC_POINT *C = NULL;
    BN_CTX *ctx = BN_CTX_new();
    if(!ctx || !md) {
        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    BN_CTX_start(ctx);
    OPENSSL_assert(dlen == 32);
    newsig = DSA_SIG_new();
@@ -111,11 +146,25 @@ DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey)
        goto err;
    }
    group = EC_KEY_get0_group(eckey);
    if(!group) {
        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    order = BN_CTX_get(ctx);
    EC_GROUP_get_order(group, order, ctx);
    if(!order || !EC_GROUP_get_order(group, order, ctx)) {
        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    priv_key = EC_KEY_get0_private_key(eckey);
    if(!priv_key) {
        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    e = BN_CTX_get(ctx);
    BN_mod(e, md, order, ctx);
    if(!e || !BN_mod(e, md, order, ctx)) {
        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
        goto err;
    }
#ifdef DEBUG_SIGN
    fprintf(stderr, "digest as bignum=");
    BN_print_fp(stderr, md);
@@ -128,55 +177,80 @@ DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey)
    }
    k = BN_CTX_get(ctx);
    C = EC_POINT_new(group);
    if(!k || !C) {
        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    do {
        do {
            if (!BN_rand_range(k, order)) {
                GOSTerr(GOST_F_GOST2001_DO_SIGN,
                        GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
                DSA_SIG_free(newsig);
                newsig = NULL;
                goto err;
            }
            if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) {
                GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB);
                DSA_SIG_free(newsig);
                newsig = NULL;
                goto err;
            }
            if (!X)
                X = BN_CTX_get(ctx);
            if (!r)
                r = BN_CTX_get(ctx);
            if (!X || !r) {
                GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) {
                GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB);
                DSA_SIG_free(newsig);
                newsig = NULL;
                goto err;
            }
            if (!r)
                r = BN_CTX_get(ctx);
            BN_nnmod(r, X, order, ctx);

            if(!BN_nnmod(r, X, order, ctx)) {
                GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
                goto err;
            }
        }
        while (BN_is_zero(r));
        /* s =  (r*priv_key+k*e) mod order */
        if (!tmp)
            tmp = BN_CTX_get(ctx);
        BN_mod_mul(tmp, priv_key, r, order, ctx);
        if (!tmp2)
            tmp2 = BN_CTX_get(ctx);
        BN_mod_mul(tmp2, k, e, order, ctx);
        if (!s)
            s = BN_CTX_get(ctx);
        BN_mod_add(s, tmp, tmp2, order, ctx);
        if (!tmp || !tmp2 || !s) {
            GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
            goto err;
        }

        if(!BN_mod_mul(tmp, priv_key, r, order, ctx)
            || !BN_mod_mul(tmp2, k, e, order, ctx)
            || !BN_mod_add(s, tmp, tmp2, order, ctx)) {
            GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
            goto err;
        }
    }
    while (BN_is_zero(s));

    newsig->s = BN_dup(s);
    newsig->r = BN_dup(r);
    if(!newsig->s || !newsig->r) {
        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    ret = newsig;
 err:
    if(ctx) {
        BN_CTX_end(ctx);
        BN_CTX_free(ctx);
    EC_POINT_free(C);
    BN_free(md);
    return newsig;
    }
    if (C) EC_POINT_free(C);
    if (md) BN_free(md);
    if (!ret && newsig) {
        DSA_SIG_free(newsig);
    }
    return ret;
}

/*
@@ -196,6 +270,11 @@ int gost2001_do_verify(const unsigned char *dgst, int dgst_len,
    const EC_POINT *pub_key = NULL;
    int ok = 0;

    if(!ctx || !group) {
        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }

    BN_CTX_start(ctx);
    order = BN_CTX_get(ctx);
    e = BN_CTX_get(ctx);
@@ -205,9 +284,17 @@ int gost2001_do_verify(const unsigned char *dgst, int dgst_len,
    X = BN_CTX_get(ctx);
    R = BN_CTX_get(ctx);
    v = BN_CTX_get(ctx);
    if(!order || !e || !z1 || !z2 || !tmp || !X || !R || !v) {
        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    EC_GROUP_get_order(group, order, ctx);
    pub_key = EC_KEY_get0_public_key(ec);
    if(!pub_key || !EC_GROUP_get_order(group, order, ctx)) {
        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }

    if (BN_is_zero(sig->s) || BN_is_zero(sig->r) ||
        (BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) {
        GOSTerr(GOST_F_GOST2001_DO_VERIFY,
@@ -217,19 +304,28 @@ int gost2001_do_verify(const unsigned char *dgst, int dgst_len,
    }
    md = hashsum2bn(dgst);

    BN_mod(e, md, order, ctx);
    if(!md || !BN_mod(e, md, order, ctx)) {
        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }
#ifdef DEBUG_SIGN
    fprintf(stderr, "digest as bignum: ");
    BN_print_fp(stderr, md);
    fprintf(stderr, "\ndigest mod q: ");
    BN_print_fp(stderr, e);
#endif
    if (BN_is_zero(e))
        BN_one(e);
    if (BN_is_zero(e) && !BN_one(e)) {
        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    v = BN_mod_inverse(v, e, order, ctx);
    BN_mod_mul(z1, sig->s, v, order, ctx);
    BN_sub(tmp, order, sig->r);
    BN_mod_mul(z2, tmp, v, order, ctx);
    if(!v
        || !BN_mod_mul(z1, sig->s, v, order, ctx)
        || !BN_sub(tmp, order, sig->r)
        || !BN_mod_mul(z2, tmp, v, order, ctx)) {
        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }
#ifdef DEBUG_SIGN
    fprintf(stderr, "\nInverted digest value: ");
    BN_print_fp(stderr, v);
@@ -239,6 +335,10 @@ int gost2001_do_verify(const unsigned char *dgst, int dgst_len,
    BN_print_fp(stderr, z2);
#endif
    C = EC_POINT_new(group);
    if (!C) {
        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) {
        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB);
        goto err;
@@ -247,7 +347,10 @@ int gost2001_do_verify(const unsigned char *dgst, int dgst_len,
        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB);
        goto err;
    }
    BN_mod(R, X, order, ctx);
    if(!BN_mod(R, X, order, ctx)) {
        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }
#ifdef DEBUG_SIGN
    fprintf(stderr, "\nX=");
    BN_print_fp(stderr, X);
@@ -261,10 +364,12 @@ int gost2001_do_verify(const unsigned char *dgst, int dgst_len,
        ok = 1;
    }
 err:
    EC_POINT_free(C);
    if (C) EC_POINT_free(C);
    if (ctx) {
        BN_CTX_end(ctx);
        BN_CTX_free(ctx);
    BN_free(md);
    }
    if (md) BN_free(md);
    return ok;
}

@@ -287,6 +392,10 @@ int gost2001_compute_public(EC_KEY *ec)
        return 0;
    }
    ctx = BN_CTX_new();
    if(!ctx) {
        GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    BN_CTX_start(ctx);
    if (!(priv_key = EC_KEY_get0_private_key(ec))) {
        GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB);
@@ -294,6 +403,10 @@ int gost2001_compute_public(EC_KEY *ec)
    }

    pub_key = EC_POINT_new(group);
    if(!pub_key) {
        GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) {
        GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB);
        goto err;
@@ -304,9 +417,11 @@ int gost2001_compute_public(EC_KEY *ec)
    }
    ok = 256;
 err:
    if (pub_key) EC_POINT_free(pub_key);
    if (ctx) {
        BN_CTX_end(ctx);
    EC_POINT_free(pub_key);
        BN_CTX_free(ctx);
    }
    return ok;
}

@@ -320,7 +435,13 @@ int gost2001_keygen(EC_KEY *ec)
{
    BIGNUM *order = BN_new(), *d = BN_new();
    const EC_GROUP *group = EC_KEY_get0_group(ec);
    EC_GROUP_get_order(group, order, NULL);

    if(!group || !EC_GROUP_get_order(group, order, NULL)) {
        GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR);
        BN_free(d);
        BN_free(order);
        return 0;
    }

    do {
        if (!BN_rand_range(d, order)) {
@@ -332,7 +453,13 @@ int gost2001_keygen(EC_KEY *ec)
        }
    }
    while (BN_is_zero(d));
    EC_KEY_set_private_key(ec, d);

    if(!EC_KEY_set_private_key(ec, d)) {
        GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR);
        BN_free(d);
        BN_free(order);
        return 0;
    }
    BN_free(d);
    BN_free(order);
    return gost2001_compute_public(ec);
+31 −5
Original line number Diff line number Diff line
@@ -115,7 +115,10 @@ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
    }
    param_nid = OBJ_obj2nid(gkp->key_params);
    GOST_KEY_PARAMS_free(gkp);
    EVP_PKEY_set_type(pkey, pkey_nid);
    if(!EVP_PKEY_set_type(pkey, pkey_nid)) {
        GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, ERR_R_INTERNAL_ERROR);
        return 0;
    }
    switch (pkey_nid) {
    case NID_id_GostR3410_94:
        {
@@ -552,9 +555,19 @@ static int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
    }
    if (!eto) {
        eto = EC_KEY_new();
        EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto);
        if(!eto) {
            GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_MALLOC_FAILURE);
            return 0;
        }
        if(!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) {
            GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_INTERNAL_ERROR);
            return 0;
        }
    }
    if(!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) {
        GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_INTERNAL_ERROR);
        return 0;
    }
    EC_KEY_set_group(eto, EC_KEY_get0_group(efrom));
    if (EC_KEY_get0_private_key(eto)) {
        gost2001_compute_public(eto);
    }
@@ -729,8 +742,21 @@ static int pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk)
    }
    X = BN_new();
    Y = BN_new();
    EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
                                        pub_key, X, Y, NULL);
    if(!X || !Y) {
        GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE);
        if(X) BN_free(X);
        if(Y) BN_free(Y);
        BN_free(order);
        return 0;
    }
    if(!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
                                        pub_key, X, Y, NULL)) {
        GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_INTERNAL_ERROR);
        BN_free(X);
        BN_free(Y);
        BN_free(order);
        return 0;
    }
    data_len = 2 * BN_num_bytes(order);
    BN_free(order);
    databuf = OPENSSL_malloc(data_len);
+1 −1
Original line number Diff line number Diff line
@@ -502,7 +502,7 @@ static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx,
        long keylen;
        int ret;
        unsigned char *keybuf = string_to_hex(value, &keylen);
        if (keylen != 32) {
        if (!keybuf || keylen != 32) {
            GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR,
                    GOST_R_INVALID_MAC_KEY_LENGTH);
            OPENSSL_free(keybuf);
Loading