diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2014-11-13 20:29:56 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2014-11-13 20:29:56 +0000 |
commit | 0c91d12c143c2f5d42e30144bf144fd14fb1c431 (patch) | |
tree | de43c363d84b0b3184a9686eccdeecf15834447b /lib | |
parent | cccf2634a1c24a14b95441c04ec5425c245a3ae4 (diff) |
Add many missing error checks (probably not exhaustive, but a good start):
- make VKO_compute_key() no longer void so that it can return failure.
- fix unchecked allocations in too many routines to mention /-:
- fix unchecked BN operations in gost2001_do_sign(), gost2001_do_verify(),
VKO_compute_key().
- fix the gost2001_do_sign() interface violation by having its sole caller
free the BIGNUM it passes to that function by itself, instead of having
the callee do this.
Reviewed (except for the last item) by Dmitry Eremin-Solenikov.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libcrypto/gost/gost89imit_pmeth.c | 12 | ||||
-rw-r--r-- | lib/libcrypto/gost/gost_locl.h | 4 | ||||
-rw-r--r-- | lib/libcrypto/gost/gostr341001.c | 256 | ||||
-rw-r--r-- | lib/libcrypto/gost/gostr341001_ameth.c | 222 | ||||
-rw-r--r-- | lib/libcrypto/gost/gostr341001_key.c | 28 | ||||
-rw-r--r-- | lib/libcrypto/gost/gostr341001_pmeth.c | 253 |
6 files changed, 488 insertions, 287 deletions
diff --git a/lib/libcrypto/gost/gost89imit_pmeth.c b/lib/libcrypto/gost/gost89imit_pmeth.c index fa79abf0afc..00eaf1decc4 100644 --- a/lib/libcrypto/gost/gost89imit_pmeth.c +++ b/lib/libcrypto/gost/gost89imit_pmeth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gost89imit_pmeth.c,v 1.2 2014/11/09 23:06:52 miod Exp $ */ +/* $OpenBSD: gost89imit_pmeth.c,v 1.3 2014/11/13 20:29:55 miod Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> * Copyright (c) 2005-2006 Cryptocom LTD @@ -115,20 +115,26 @@ pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) } keydata = malloc(32); + if (keydata == NULL) { + GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN, ERR_R_MALLOC_FAILURE); + return 0; + } memcpy(keydata, data->key, 32); EVP_PKEY_assign(pkey, NID_id_Gost28147_89_MAC, keydata); return 1; } -static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +static int +pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); switch (type) { case EVP_PKEY_CTRL_MD: if (EVP_MD_type(p2) != NID_id_Gost28147_89_MAC) { - GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_DIGEST_TYPE); + GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, + GOST_R_INVALID_DIGEST_TYPE); return 0; } data->md = p2; diff --git a/lib/libcrypto/gost/gost_locl.h b/lib/libcrypto/gost/gost_locl.h index 202ba39688c..9036f59771d 100644 --- a/lib/libcrypto/gost/gost_locl.h +++ b/lib/libcrypto/gost/gost_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: gost_locl.h,v 1.2 2014/11/09 19:27:29 miod Exp $ */ +/* $OpenBSD: gost_locl.h,v 1.3 2014/11/13 20:29:55 miod Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> * Copyright (c) 2005-2006 Cryptocom LTD @@ -99,7 +99,7 @@ extern int gost2001_compute_public(GOST_KEY *ec); extern ECDSA_SIG *gost2001_do_sign(BIGNUM *md, GOST_KEY *eckey); extern int gost2001_do_verify(BIGNUM *md, ECDSA_SIG *sig, GOST_KEY *ec); extern int gost2001_keygen(GOST_KEY *ec); -extern void VKO_compute_key(BIGNUM *X, BIGNUM *Y, const GOST_KEY *pkey, +extern int VKO_compute_key(BIGNUM *X, BIGNUM *Y, const GOST_KEY *pkey, GOST_KEY *priv_key, const BIGNUM *ukm); extern BIGNUM *GOST_le2bn(const unsigned char *buf, size_t len, BIGNUM *bn); extern int GOST_bn2le(BIGNUM *bn, unsigned char *buf, int len); diff --git a/lib/libcrypto/gost/gostr341001.c b/lib/libcrypto/gost/gostr341001.c index 3c314765f7e..171cf1b80a0 100644 --- a/lib/libcrypto/gost/gostr341001.c +++ b/lib/libcrypto/gost/gostr341001.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gostr341001.c,v 1.1 2014/11/09 19:17:13 miod Exp $ */ +/* $OpenBSD: gostr341001.c,v 1.2 2014/11/13 20:29:55 miod Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> * Copyright (c) 2005-2006 Cryptocom LTD @@ -59,10 +59,12 @@ #include "gost_locl.h" /* Convert little-endian byte array into bignum */ -BIGNUM *GOST_le2bn(const unsigned char * buf, size_t len, BIGNUM * bn) +BIGNUM * +GOST_le2bn(const unsigned char *buf, size_t len, BIGNUM *bn) { unsigned char temp[64]; int i; + if (len > 64) return NULL; @@ -73,7 +75,8 @@ BIGNUM *GOST_le2bn(const unsigned char * buf, size_t len, BIGNUM * bn) return BN_bin2bn(temp, len, bn); } -int GOST_bn2le(BIGNUM * bn, unsigned char * buf, int len) +int +GOST_bn2le(BIGNUM *bn, unsigned char *buf, int len) { unsigned char temp[64]; int i, bytes; @@ -93,8 +96,8 @@ int GOST_bn2le(BIGNUM * bn, unsigned char * buf, int len) return 1; } - -int gost2001_compute_public(GOST_KEY * ec) +int +gost2001_compute_public(GOST_KEY *ec) { const EC_GROUP *group = GOST_KEY_get0_group(ec); EC_POINT *pub_key = NULL; @@ -102,36 +105,44 @@ int gost2001_compute_public(GOST_KEY * ec) BN_CTX *ctx = NULL; int ok = 0; - if (!group) { + if (group == NULL) { GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, - GOST_R_KEY_IS_NOT_INITIALIZED); + GOST_R_KEY_IS_NOT_INITIALIZED); return 0; } ctx = BN_CTX_new(); + if (ctx == NULL) { + GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, + ERR_R_MALLOC_FAILURE); + return 0; + } BN_CTX_start(ctx); - if (!(priv_key = GOST_KEY_get0_private_key(ec))) { - GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); + if ((priv_key = GOST_KEY_get0_private_key(ec)) == NULL) goto err; - } pub_key = EC_POINT_new(group); - if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) { - GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); + if (pub_key == NULL) goto err; - } - if (!GOST_KEY_set_public_key(ec, pub_key)) { - GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); + if (EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx) == 0) goto err; - } - ok = 256; + if (GOST_KEY_set_public_key(ec, pub_key) == 0) + goto err; + ok = 1; + + if (ok == 0) { err: - BN_CTX_end(ctx); + GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); + } EC_POINT_free(pub_key); - BN_CTX_free(ctx); + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } return ok; } -ECDSA_SIG *gost2001_do_sign(BIGNUM * md, GOST_KEY * eckey) +ECDSA_SIG * +gost2001_do_sign(BIGNUM *md, GOST_KEY *eckey) { ECDSA_SIG *newsig = NULL; BIGNUM *order = NULL; @@ -141,9 +152,15 @@ ECDSA_SIG *gost2001_do_sign(BIGNUM * md, GOST_KEY * eckey) NULL, *e = NULL; EC_POINT *C = NULL; BN_CTX *ctx = BN_CTX_new(); + int ok = 0; + + if (ctx == NULL) { + GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); + return NULL; + } BN_CTX_start(ctx); newsig = ECDSA_SIG_new(); - if (!newsig) { + if (newsig == NULL) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } @@ -151,70 +168,88 @@ ECDSA_SIG *gost2001_do_sign(BIGNUM * md, GOST_KEY * eckey) r = newsig->r; group = GOST_KEY_get0_group(eckey); order = BN_CTX_get(ctx); - EC_GROUP_get_order(group, order, ctx); + if (order == NULL) + goto err; + if (EC_GROUP_get_order(group, order, ctx) == 0) + goto err; priv_key = GOST_KEY_get0_private_key(eckey); e = BN_CTX_get(ctx); - BN_mod(e, md, order, ctx); - if (BN_is_zero(e)) { + if (e == NULL) + goto err; + if (BN_mod(e, md, order, ctx) == 0) + goto err; + if (BN_is_zero(e)) BN_one(e); - } k = BN_CTX_get(ctx); X = BN_CTX_get(ctx); C = EC_POINT_new(group); + if (C == NULL) + goto err; do { do { if (!BN_rand_range(k, order)) { GOSTerr(GOST_F_GOST2001_DO_SIGN, GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); - ECDSA_SIG_free(newsig); - newsig = NULL; goto err; } - /* We do not want timing information to leak the length of k, - * so we compute G*k using an equivalent scalar of fixed - * bit-length. */ - if (!BN_add(k, k, order)) + /* + * We do not want timing information to leak the length + * of k, so we compute G*k using an equivalent scalar + * of fixed bit-length. + */ + if (BN_add(k, k, order) == 0) goto err; if (BN_num_bits(k) <= BN_num_bits(order)) - if (!BN_add(k, k, order)) + if (BN_add(k, k, order) == 0) goto err; - if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) { + if (EC_POINT_mul(group, C, k, NULL, NULL, ctx) == 0) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); - ECDSA_SIG_free(newsig); - newsig = NULL; goto err; } - if (!EC_POINT_get_affine_coordinates_GFp - (group, C, X, NULL, ctx)) { + if (EC_POINT_get_affine_coordinates_GFp(group, C, X, + NULL, ctx) == 0) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); - ECDSA_SIG_free(newsig); - newsig = NULL; goto err; } - BN_nnmod(r, X, order, ctx); - } - while (BN_is_zero(r)); - /* s = (r*priv_key+k*e) mod order */ - if (!tmp) + if (BN_nnmod(r, X, order, ctx) == 0) + goto err; + } while (BN_is_zero(r)); + /* s = (r*priv_key+k*e) mod order */ + if (tmp == NULL) { tmp = BN_CTX_get(ctx); - BN_mod_mul(tmp, priv_key, r, order, ctx); - if (!tmp2) + if (tmp == NULL) + goto err; + } + if (BN_mod_mul(tmp, priv_key, r, order, ctx) == 0) + goto err; + if (tmp2 == NULL) { tmp2 = BN_CTX_get(ctx); - BN_mod_mul(tmp2, k, e, order, ctx); - BN_mod_add(s, tmp, tmp2, order, ctx); - } - while (BN_is_zero(s)); + if (tmp2 == NULL) + goto err; + } + if (BN_mod_mul(tmp2, k, e, order, ctx) == 0) + goto err; + if (BN_mod_add(s, tmp, tmp2, order, ctx) == 0) + goto err; + } while (BN_is_zero(s)); + ok = 1; err: - BN_CTX_end(ctx); - BN_CTX_free(ctx); EC_POINT_free(C); - BN_free(md); + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + if (ok == 0) { + ECDSA_SIG_free(newsig); + newsig = NULL; + } return newsig; } -int gost2001_do_verify(BIGNUM * md, ECDSA_SIG * sig, GOST_KEY * ec) +int +gost2001_do_verify(BIGNUM *md, ECDSA_SIG *sig, GOST_KEY *ec) { BN_CTX *ctx = BN_CTX_new(); const EC_GROUP *group = GOST_KEY_get0_group(ec); @@ -225,6 +260,8 @@ int gost2001_do_verify(BIGNUM * md, ECDSA_SIG * sig, GOST_KEY * ec) const EC_POINT *pub_key = NULL; int ok = 0; + if (ctx == NULL) + goto err; BN_CTX_start(ctx); order = BN_CTX_get(ctx); e = BN_CTX_get(ctx); @@ -234,88 +271,129 @@ int gost2001_do_verify(BIGNUM * md, ECDSA_SIG * sig, GOST_KEY * ec) X = BN_CTX_get(ctx); R = BN_CTX_get(ctx); v = BN_CTX_get(ctx); + if (v == NULL) + goto err; - EC_GROUP_get_order(group, order, ctx); + if (EC_GROUP_get_order(group, order, ctx) == 0) + goto err; pub_key = GOST_KEY_get0_public_key(ec); 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, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); + BN_cmp(sig->s, order) >= 1 || BN_cmp(sig->r, order) >= 1) { + GOSTerr(GOST_F_GOST2001_DO_VERIFY, + GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); goto err; - } - BN_mod(e, md, order, ctx); + if (BN_mod(e, md, order, ctx) == 0) + goto err; if (BN_is_zero(e)) BN_one(e); 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 == NULL) + goto err; + if (BN_mod_mul(z1, sig->s, v, order, ctx) == 0) + goto err; + if (BN_sub(tmp, order, sig->r) == 0) + goto err; + if (BN_mod_mul(z2, tmp, v, order, ctx) == 0) + goto err; C = EC_POINT_new(group); - if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) { + if (C == NULL) + goto err; + if (EC_POINT_mul(group, C, z1, pub_key, z2, ctx) == 0) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); goto err; } - if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { + if (EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx) == 0) { 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) == 0) + goto err; if (BN_cmp(R, sig->r) != 0) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); } else { ok = 1; } - err: +err: EC_POINT_free(C); - BN_CTX_end(ctx); - BN_CTX_free(ctx); + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } return ok; } - /* Implementation of CryptoPro VKO 34.10-2001 algorithm */ -void VKO_compute_key(BIGNUM * X, BIGNUM * Y, - const GOST_KEY * pkey, GOST_KEY * priv_key, - const BIGNUM * ukm) +int +VKO_compute_key(BIGNUM *X, BIGNUM *Y, const GOST_KEY *pkey, GOST_KEY *priv_key, + const BIGNUM *ukm) { BIGNUM *p = NULL, *order = NULL; const BIGNUM *key = GOST_KEY_get0_private_key(priv_key); + const EC_GROUP *group = GOST_KEY_get0_group(priv_key); const EC_POINT *pub_key = GOST_KEY_get0_public_key(pkey); - EC_POINT *pnt = EC_POINT_new(GOST_KEY_get0_group(priv_key)); - BN_CTX *ctx = BN_CTX_new(); + EC_POINT *pnt; + BN_CTX *ctx = NULL; + int ok = 0; + pnt = EC_POINT_new(group); + if (pnt == NULL) + goto err; + ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; BN_CTX_start(ctx); p = BN_CTX_get(ctx); order = BN_CTX_get(ctx); - EC_GROUP_get_order(GOST_KEY_get0_group(priv_key), order, ctx); - BN_mod_mul(p, key, ukm, order, ctx); - EC_POINT_mul(GOST_KEY_get0_group(priv_key), pnt, NULL, pub_key, p, ctx); - EC_POINT_get_affine_coordinates_GFp(GOST_KEY_get0_group(priv_key), - pnt, X, Y, ctx); - BN_CTX_end(ctx); - BN_CTX_free(ctx); + if (order == NULL) + goto err; + if (EC_GROUP_get_order(group, order, ctx) == 0) + goto err; + if (BN_mod_mul(p, key, ukm, order, ctx) == 0) + goto err; + if (EC_POINT_mul(group, pnt, NULL, pub_key, p, ctx) == 0) + goto err; + if (EC_POINT_get_affine_coordinates_GFp(group, pnt, X, Y, ctx) == 0) + goto err; + ok = 1; + +err: + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } EC_POINT_free(pnt); + return ok; } -int gost2001_keygen(GOST_KEY * ec) +int +gost2001_keygen(GOST_KEY *ec) { BIGNUM *order = BN_new(), *d = BN_new(); const EC_GROUP *group = GOST_KEY_get0_group(ec); - EC_GROUP_get_order(group, order, NULL); + int rc = 0; + + if (order == NULL || d == NULL) + goto err; + if (EC_GROUP_get_order(group, order, NULL) == 0) + goto err; do { - if (!BN_rand_range(d, order)) { + if (BN_rand_range(d, order) == 0) { GOSTerr(GOST_F_GOST2001_KEYGEN, GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); - BN_free(d); - BN_free(order); - return 0; + goto err; } } while (BN_is_zero(d)); - GOST_KEY_set_private_key(ec, d); + + if (GOST_KEY_set_private_key(ec, d) == 0) + goto err; + rc = gost2001_compute_public(ec); + +err: BN_free(d); BN_free(order); - return gost2001_compute_public(ec); + return rc; } #endif diff --git a/lib/libcrypto/gost/gostr341001_ameth.c b/lib/libcrypto/gost/gostr341001_ameth.c index 710f2aa58c6..243a7490fab 100644 --- a/lib/libcrypto/gost/gostr341001_ameth.c +++ b/lib/libcrypto/gost/gostr341001_ameth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gostr341001_ameth.c,v 1.2 2014/11/09 23:06:52 miod Exp $ */ +/* $OpenBSD: gostr341001_ameth.c,v 1.3 2014/11/13 20:29:55 miod Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> * Copyright (c) 2005-2006 Cryptocom LTD @@ -229,31 +229,34 @@ pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub) ASN1_OCTET_STRING_free(octet); ret = GOST_KEY_set_public_key_affine_coordinates(pk->pkey.gost, X, Y); - if (!ret) + if (ret == 0) GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_EC_LIB); BN_free(X); BN_free(Y); return ret; - } -static int pub_encode_gost01(X509_PUBKEY * pub, const EVP_PKEY * pk) +static int +pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk) { ASN1_OBJECT *algobj = NULL; ASN1_OCTET_STRING *octet = NULL; + ASN1_STRING *params = NULL; void *pval = NULL; unsigned char *buf = NULL, *sptr; int key_size, ret = 0; const EC_POINT *pub_key; - BIGNUM *X, *Y; + BIGNUM *X = NULL, *Y = NULL; const GOST_KEY *ec = pk->pkey.gost; int ptype = V_ASN1_UNDEF; algobj = OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(ec))); if (pk->save_parameters) { - ASN1_STRING *params = encode_gost01_algor_params(pk); + params = encode_gost01_algor_params(pk); + if (params == NULL) + return 0; pval = params; ptype = V_ASN1_SEQUENCE; } @@ -261,44 +264,43 @@ static int pub_encode_gost01(X509_PUBKEY * pub, const EVP_PKEY * pk) key_size = GOST_KEY_get_size(ec); pub_key = GOST_KEY_get0_public_key(ec); - if (!pub_key) { + if (pub_key == NULL) { GOSTerr(GOST_F_PUB_ENCODE_GOST01, GOST_R_PUBLIC_KEY_UNDEFINED); - return 0; + goto err; } octet = ASN1_OCTET_STRING_new(); - if (!octet) { + if (octet == NULL) { GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE); - return 0; + goto err; } ret = ASN1_STRING_set(octet, NULL, 2 * key_size); - if (!ret) { + if (ret == 0) { GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_INTERNAL_ERROR); - ASN1_BIT_STRING_free(octet); - return 0; + goto err; } sptr = ASN1_STRING_data(octet); X = BN_new(); Y = BN_new(); - if (!X || !Y) { + if (X == NULL || Y == NULL) { GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE); - ASN1_BIT_STRING_free(octet); - BN_free(X); - BN_free(Y); - return 0; + goto err; } - EC_POINT_get_affine_coordinates_GFp(GOST_KEY_get0_group(ec), - pub_key, X, Y, NULL); + if (EC_POINT_get_affine_coordinates_GFp(GOST_KEY_get0_group(ec), + pub_key, X, Y, NULL) == 0) { + GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_EC_LIB); + goto err; + } GOST_bn2le(X, sptr, key_size); GOST_bn2le(Y, sptr + key_size, key_size); - BN_free(X); BN_free(Y); + BN_free(X); ret = i2d_ASN1_OCTET_STRING(octet, &buf); ASN1_BIT_STRING_free(octet); @@ -306,48 +308,60 @@ static int pub_encode_gost01(X509_PUBKEY * pub, const EVP_PKEY * pk) return 0; return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret); + +err: + BN_free(Y); + BN_free(X); + ASN1_BIT_STRING_free(octet); + ASN1_STRING_free(params); + return 0; } -static int param_print_gost01(BIO * out, const EVP_PKEY * pkey, int indent, - ASN1_PCTX * pctx) +static int +param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) { - int param_nid = EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost)); - if (!BIO_indent(out, indent, 128)) + int param_nid = + EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost)); + + if (BIO_indent(out, indent, 128) == 0) return 0; BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid)); - if (!BIO_indent(out, indent, 128)) + if (BIO_indent(out, indent, 128) == 0) return 0; - BIO_printf(out, "Digest Algorithm: %s\n", OBJ_nid2ln(GOST_KEY_get_digest(pkey->pkey.gost))); + BIO_printf(out, "Digest Algorithm: %s\n", + OBJ_nid2ln(GOST_KEY_get_digest(pkey->pkey.gost))); return 1; } -static int pub_print_gost01(BIO * out, const EVP_PKEY * pkey, int indent, - ASN1_PCTX * pctx) +static int +pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) { BN_CTX *ctx = BN_CTX_new(); BIGNUM *X, *Y; const EC_POINT *pubkey; const EC_GROUP *group; - if (!ctx) { + if (ctx == NULL) { GOSTerr(GOST_F_PUB_PRINT_GOST01, ERR_R_MALLOC_FAILURE); return 0; } BN_CTX_start(ctx); X = BN_CTX_get(ctx); Y = BN_CTX_get(ctx); + if (X == NULL || Y == NULL) + goto err; pubkey = GOST_KEY_get0_public_key(pkey->pkey.gost); group = GOST_KEY_get0_group(pkey->pkey.gost); - if (!EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, ctx)) { + if (EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, + ctx) == 0) { GOSTerr(GOST_F_PUB_PRINT_GOST01, ERR_R_EC_LIB); - BN_CTX_free(ctx); - return 0; + goto err; } - if (!BIO_indent(out, indent, 128)) - return 0; + if (BIO_indent(out, indent, 128) == 0) + goto err; BIO_printf(out, "Public key:\n"); - if (!BIO_indent(out, indent + 3, 128)) - return 0; + if (BIO_indent(out, indent + 3, 128) == 0) + goto err; BIO_printf(out, "X:"); BN_print(out, X); BIO_printf(out, "\n"); @@ -355,22 +369,28 @@ static int pub_print_gost01(BIO * out, const EVP_PKEY * pkey, int indent, BIO_printf(out, "Y:"); BN_print(out, Y); BIO_printf(out, "\n"); + BN_CTX_end(ctx); BN_CTX_free(ctx); return param_print_gost01(out, pkey, indent, pctx); + +err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return 0; } -static int priv_print_gost01(BIO * out, const EVP_PKEY * pkey, int indent, - ASN1_PCTX * pctx) +static int +priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) { const BIGNUM *key; - if (!BIO_indent(out, indent, 128)) + if (BIO_indent(out, indent, 128) == 0) return 0; BIO_printf(out, "Private key: "); key = GOST_KEY_get0_private_key(pkey->pkey.gost); - if (!key) + if (key == NULL) BIO_printf(out, "<undefined)"); else BN_print(out, key); @@ -415,6 +435,7 @@ priv_decode_gost01(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf) if (s == NULL || s->length != 32) { GOSTerr(GOST_F_PRIV_DECODE_GOST01, EVP_R_DECODE_ERROR); + ASN1_STRING_free(s); return 0; } for (i = 0; i < 32; i++) { @@ -424,70 +445,89 @@ priv_decode_gost01(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf) pk_num = BN_bin2bn(rev_buf, 32, NULL); } else { priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len); - if (!priv_key) + if (priv_key == NULL) return 0; ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL); ASN1_INTEGER_free(priv_key); - if (!ret) { + if (ret == 0) { GOSTerr(GOST_F_PRIV_DECODE_GOST01, EVP_R_DECODE_ERROR); return 0; } } ec = pk->pkey.gost; - if (!ec) { + if (ec == NULL) { ec = GOST_KEY_new(); - EVP_PKEY_assign_GOST(pk, ec); + if (ec == NULL) { + BN_free(pk_num); + return 0; + } + if (EVP_PKEY_assign_GOST(pk, ec) == 0) { + BN_free(pk_num); + GOST_KEY_free(ec); + return 0; + } } - if (!GOST_KEY_set_private_key(ec, pk_num)) { + if (GOST_KEY_set_private_key(ec, pk_num) == 0) { BN_free(pk_num); return 0; } - if (!EVP_PKEY_missing_parameters(pk)) - gost2001_compute_public(ec); + ret = 0; + if (EVP_PKEY_missing_parameters(pk) == 0) + ret = gost2001_compute_public(ec) != 0; BN_free(pk_num); - return 1; + return ret; } -static int priv_encode_gost01(PKCS8_PRIV_KEY_INFO * p8, const EVP_PKEY * pk) +static int +priv_encode_gost01(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk) { - ASN1_OBJECT *algobj = OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(pk->pkey.gost))); + ASN1_OBJECT *algobj = + OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(pk->pkey.gost))); ASN1_STRING *params = encode_gost01_algor_params(pk); unsigned char *priv_buf = NULL; int priv_len; - ASN1_INTEGER *asn1key = NULL; - if (!params) { + + if (params == NULL) + return 0; + + asn1key = BN_to_ASN1_INTEGER(GOST_KEY_get0_private_key(pk->pkey.gost), + NULL); + if (asn1key == NULL) { + ASN1_STRING_free(params); return 0; } - asn1key = BN_to_ASN1_INTEGER(GOST_KEY_get0_private_key(pk->pkey.gost), NULL); priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf); ASN1_INTEGER_free(asn1key); - return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params, - priv_buf, priv_len); + return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params, priv_buf, + priv_len); } -static int param_encode_gost01(const EVP_PKEY * pkey, unsigned char **pder) +static int +param_encode_gost01(const EVP_PKEY *pkey, unsigned char **pder) { ASN1_STRING *params = encode_gost01_algor_params(pkey); int len; - if (!params) + + if (params == NULL) return 0; len = params->length; - if (pder) + if (pder != NULL) memcpy(*pder, params->data, params->length); ASN1_STRING_free(params); return len; } -static int param_decode_gost01(EVP_PKEY * pkey, const unsigned char **pder, - int derlen) +static int +param_decode_gost01(EVP_PKEY *pkey, const unsigned char **pder, int derlen) { ASN1_OBJECT *obj = NULL; int nid; GOST_KEY *ec; EC_GROUP *group; + int ret; /* New format */ if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == **pder) @@ -522,67 +562,85 @@ static int param_decode_gost01(EVP_PKEY * pkey, const unsigned char **pder, return 0; } EC_GROUP_free(group); - if (GOST_KEY_set_digest(ec, NID_id_GostR3411_94_CryptoProParamSet) == 0) { + if (GOST_KEY_set_digest(ec, + NID_id_GostR3411_94_CryptoProParamSet) == 0) { GOSTerr(GOST_F_PARAM_DECODE_GOST01, GOST_R_INVALID_DIGEST_TYPE); GOST_KEY_free(ec); return 0; } - EVP_PKEY_assign_GOST(pkey, ec); - return 1; + ret = EVP_PKEY_assign_GOST(pkey, ec); + if (ret == 0) + GOST_KEY_free(ec); + return ret; } -static int param_missing_gost01(const EVP_PKEY * pk) +static int +param_missing_gost01(const EVP_PKEY *pk) { const GOST_KEY *ec = pk->pkey.gost; - if (!ec) + + if (ec == NULL) return 1; - if (!GOST_KEY_get0_group(ec)) + if (GOST_KEY_get0_group(ec) == NULL) return 1; if (GOST_KEY_get_digest(ec) == NID_undef) return 1; return 0; } -static int param_copy_gost01(EVP_PKEY * to, const EVP_PKEY * from) +static int +param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from) { GOST_KEY *eto = to->pkey.gost; const GOST_KEY *efrom = from->pkey.gost; + int ret = 0; + if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) { GOSTerr(GOST_F_PARAM_COPY_GOST01, - GOST_R_INCOMPATIBLE_ALGORITHMS); + GOST_R_INCOMPATIBLE_ALGORITHMS); return 0; } - if (!efrom) { + if (efrom == NULL) { GOSTerr(GOST_F_PARAM_COPY_GOST01, - GOST_R_KEY_PARAMETERS_MISSING); + GOST_R_KEY_PARAMETERS_MISSING); return 0; } - if (!eto) { + if (eto) { eto = GOST_KEY_new(); - EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto); + if (eto == NULL) { + GOSTerr(GOST_F_PARAM_COPY_GOST01, + ERR_R_MALLOC_FAILURE); + return 0; + } + if (EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto) == 0) { + GOST_KEY_free(eto); + return 0; + } } GOST_KEY_set_group(eto, GOST_KEY_get0_group(efrom)); GOST_KEY_set_digest(eto, GOST_KEY_get_digest(efrom)); - if (GOST_KEY_get0_private_key(eto)) { - gost2001_compute_public(eto); - } - return 1; + if (GOST_KEY_get0_private_key(eto) != NULL) + ret = gost2001_compute_public(eto); + + return ret; } -static int param_cmp_gost01(const EVP_PKEY * a, const EVP_PKEY * b) +static int +param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b) { if (EC_GROUP_get_curve_name(GOST_KEY_get0_group(a->pkey.gost)) != - EC_GROUP_get_curve_name(GOST_KEY_get0_group(b->pkey.gost))) { + EC_GROUP_get_curve_name(GOST_KEY_get0_group(b->pkey.gost))) return 0; - } + if (GOST_KEY_get_digest(a->pkey.gost) != GOST_KEY_get_digest(b->pkey.gost)) return 0; - return 1; + return 1; } -static int pkey_ctrl_gost01(EVP_PKEY * pkey, int op, long arg1, void *arg2) +static int +pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2) { X509_ALGOR *alg1 = NULL, *alg2 = NULL, *alg3 = NULL; int digest = GOST_KEY_get_digest(pkey->pkey.gost); diff --git a/lib/libcrypto/gost/gostr341001_key.c b/lib/libcrypto/gost/gostr341001_key.c index b236dde28a9..2405722ddd9 100644 --- a/lib/libcrypto/gost/gostr341001_key.c +++ b/lib/libcrypto/gost/gostr341001_key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gostr341001_key.c,v 1.2 2014/11/09 23:06:52 miod Exp $ */ +/* $OpenBSD: gostr341001_key.c,v 1.3 2014/11/13 20:29:55 miod Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> * Copyright (c) 2005-2006 Cryptocom LTD @@ -176,45 +176,47 @@ err: return (ok); } -int GOST_KEY_set_public_key_affine_coordinates(GOST_KEY * key, BIGNUM * x, BIGNUM * y) +int +GOST_KEY_set_public_key_affine_coordinates(GOST_KEY *key, BIGNUM *x, BIGNUM *y) { BN_CTX *ctx = NULL; BIGNUM *tx, *ty; EC_POINT *point = NULL; int ok = 0; - if (!key || !key->group || !x || !y) { + if (key == NULL || key->group == NULL || x == NULL || y == NULL) { GOSTerr(GOST_F_GOST_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER); return 0; } ctx = BN_CTX_new(); - if (!ctx) + if (ctx == NULL) goto err; point = EC_POINT_new(key->group); - - if (!point) + if (point == NULL) goto err; tx = BN_CTX_get(ctx); ty = BN_CTX_get(ctx); - if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, - x, y, ctx)) + if (ty == NULL) + goto err; + if (EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, + ctx) == 0) goto err; - if (!EC_POINT_get_affine_coordinates_GFp(key->group, point, - tx, ty, ctx)) + if (EC_POINT_get_affine_coordinates_GFp(key->group, point, tx, ty, + ctx) == 0) goto err; /* - * Check if retrieved coordinates match originals: if not values are + * Check if retrieved coordinates match originals: if not, values are * out of range. */ - if (BN_cmp(x, tx) || BN_cmp(y, ty)) { + if (BN_cmp(x, tx) != 0 || BN_cmp(y, ty) != 0) { GOSTerr(GOST_F_GOST_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, EC_R_COORDINATES_OUT_OF_RANGE); goto err; } - if (!GOST_KEY_set_public_key(key, point)) + if (GOST_KEY_set_public_key(key, point) == 0) goto err; if (GOST_KEY_check_key(key) == 0) diff --git a/lib/libcrypto/gost/gostr341001_pmeth.c b/lib/libcrypto/gost/gostr341001_pmeth.c index afcf8f973a5..859c0884d68 100644 --- a/lib/libcrypto/gost/gostr341001_pmeth.c +++ b/lib/libcrypto/gost/gostr341001_pmeth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gostr341001_pmeth.c,v 1.5 2014/11/09 23:06:52 miod Exp $ */ +/* $OpenBSD: gostr341001_pmeth.c,v 1.6 2014/11/13 20:29:55 miod Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> * Copyright (c) 2005-2006 Cryptocom LTD @@ -133,17 +133,19 @@ struct gost_pmeth_data { int sig_format; }; -static int pkey_gost01_init(EVP_PKEY_CTX * ctx) +static int +pkey_gost01_init(EVP_PKEY_CTX *ctx) { struct gost_pmeth_data *data; EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); - data = malloc(sizeof(struct gost_pmeth_data)); - if (!data) + + data = calloc(1, sizeof(struct gost_pmeth_data)); + if (data == NULL) return 0; - memset(data, 0, sizeof(struct gost_pmeth_data)); - if (pkey && pkey->pkey.gost) { - data->sign_param_nid = EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost)); + if (pkey != NULL && pkey->pkey.gost != NULL) { + data->sign_param_nid = + EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost)); data->digest_nid = GOST_KEY_get_digest(pkey->pkey.gost); } EVP_PKEY_CTX_set_data(ctx, data); @@ -151,85 +153,95 @@ static int pkey_gost01_init(EVP_PKEY_CTX * ctx) } /* Copies contents of gost_pmeth_data structure */ -static int pkey_gost01_copy(EVP_PKEY_CTX * dst, EVP_PKEY_CTX * src) +static int +pkey_gost01_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { struct gost_pmeth_data *dst_data, *src_data; - if (!pkey_gost01_init(dst)) { + + if (pkey_gost01_init(dst) == 0) return 0; - } + src_data = EVP_PKEY_CTX_get_data(src); dst_data = EVP_PKEY_CTX_get_data(dst); *dst_data = *src_data; - if (src_data->shared_ukm) { + if (src_data->shared_ukm != NULL) dst_data->shared_ukm = NULL; - } return 1; } /* Frees up gost_pmeth_data structure */ -static void pkey_gost01_cleanup(EVP_PKEY_CTX * ctx) +static void +pkey_gost01_cleanup(EVP_PKEY_CTX *ctx) { struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); + free(data->shared_ukm); free(data); } -static int pkey_gost01_paramgen(EVP_PKEY_CTX * ctx, EVP_PKEY * pkey) +static int +pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); EC_GROUP *group; GOST_KEY *gost; int ret; - if (data->sign_param_nid == NID_undef || data->digest_nid == NID_undef) { + if (data->sign_param_nid == NID_undef || + data->digest_nid == NID_undef) { GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN, GOST_R_NO_PARAMETERS_SET); return 0; } group = EC_GROUP_new_by_curve_name(data->sign_param_nid); - if (!group) + if (group == NULL) return 0; EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); gost = GOST_KEY_new(); - if (!gost) + if (gost == NULL) return 0; - if (!GOST_KEY_set_digest(gost, data->digest_nid)) + if (GOST_KEY_set_digest(gost, data->digest_nid) == 0) return 0; ret = GOST_KEY_set_group(gost, group); - if (ret) - EVP_PKEY_assign_GOST(pkey, gost); - else + if (ret != 0) + ret = EVP_PKEY_assign_GOST(pkey, gost); + if (ret == 0) GOST_KEY_free(gost); EC_GROUP_free(group); return ret; } -static int pkey_gost01_keygen(EVP_PKEY_CTX * ctx, EVP_PKEY * pkey) +static int +pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { - if (!pkey_gost01_paramgen(ctx, pkey)) + if (pkey_gost01_paramgen(ctx, pkey) == 0) return 0; - gost2001_keygen(pkey->pkey.gost); - return 1; + return gost2001_keygen(pkey->pkey.gost) != 0; } -static int pkey_gost01_sign(EVP_PKEY_CTX * ctx, unsigned char *sig, - size_t * siglen, const unsigned char *tbs, - size_t tbs_len) +static int +pkey_gost01_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbs_len) { ECDSA_SIG *unpacked_sig = NULL; EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx); BIGNUM *md; - size_t size = GOST_KEY_get_size(pkey->pkey.gost); + size_t size; + int ret; + + if (pkey == NULL || pkey->pkey.gost == NULL) + return 0; + size = GOST_KEY_get_size(pkey->pkey.gost); - if (!siglen) + if (siglen == NULL) return 0; - if (!sig) { + if (sig == NULL) { *siglen = 2 * size; return 1; } else if (*siglen < 2 * size) { @@ -238,24 +250,32 @@ static int pkey_gost01_sign(EVP_PKEY_CTX * ctx, unsigned char *sig, } OPENSSL_assert(tbs_len == 32 || tbs_len == 64); md = GOST_le2bn(tbs, tbs_len, NULL); + if (md == NULL) + return 0; unpacked_sig = gost2001_do_sign(md, pkey->pkey.gost); - if (!unpacked_sig) { + BN_free(md); + if (unpacked_sig == NULL) { return 0; } switch (pctx->sig_format) { case GOST_SIG_FORMAT_SR_BE: - return pack_signature_cp(unpacked_sig, size, sig, siglen); + ret = pack_signature_cp(unpacked_sig, size, sig, siglen); + break; case GOST_SIG_FORMAT_RS_LE: - return pack_signature_le(unpacked_sig, size, sig, siglen); + ret = pack_signature_le(unpacked_sig, size, sig, siglen); + break; default: - ECDSA_SIG_free(unpacked_sig); - return -1; + ret = -1; + break; } + if (ret <= 0) + ECDSA_SIG_free(unpacked_sig); + return ret; } -static int pkey_gost01_verify(EVP_PKEY_CTX * ctx, const unsigned char *sig, - size_t siglen, const unsigned char *tbs, - size_t tbs_len) +static int +pkey_gost01_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbs_len) { int ok = 0; EVP_PKEY *pub_key = EVP_PKEY_CTX_get0_pkey(ctx); @@ -286,24 +306,33 @@ err: return ok; } -static int gost01_VKO_key(EVP_PKEY * pub_key, EVP_PKEY * priv_key, - const unsigned char *ukm, unsigned char *key) +static int +gost01_VKO_key(EVP_PKEY *pub_key, EVP_PKEY *priv_key, const unsigned char *ukm, + unsigned char *key) { unsigned char hashbuf[128]; int digest_nid; - int ret; + int ret = 0; BN_CTX *ctx = BN_CTX_new(); BIGNUM *UKM, *X, *Y; + if (ctx == NULL) + return 0; + BN_CTX_start(ctx); UKM = BN_CTX_get(ctx); X = BN_CTX_get(ctx); Y = BN_CTX_get(ctx); + if (Y == NULL) + goto err; GOST_le2bn(ukm, 8, UKM); digest_nid = GOST_KEY_get_digest(priv_key->pkey.gost); - VKO_compute_key(X, Y, pub_key->pkey.gost, priv_key->pkey.gost, UKM); + if (VKO_compute_key(X, Y, pub_key->pkey.gost, priv_key->pkey.gost, + UKM) == 0) + goto err; + switch (digest_nid) { case NID_id_GostR3411_94_CryptoProParamSet: GOST_bn2le(X, hashbuf, 32); @@ -327,14 +356,15 @@ static int gost01_VKO_key(EVP_PKEY * pub_key, EVP_PKEY * priv_key, ret = -2; break; } +err: BN_CTX_end(ctx); BN_CTX_free(ctx); return ret; } -int pkey_gost01_decrypt(EVP_PKEY_CTX * pctx, unsigned char *key, - size_t * key_len, const unsigned char *in, - size_t in_len) +int +pkey_gost01_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_len, + const unsigned char *in, size_t in_len) { const unsigned char *p = in; EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx); @@ -387,26 +417,26 @@ int pkey_gost01_decrypt(EVP_PKEY_CTX * pctx, unsigned char *key, memcpy(wrappedKey + 8, gkt->key_info->encrypted_key->data, 32); OPENSSL_assert(gkt->key_info->imit->length == 4); memcpy(wrappedKey + 40, gkt->key_info->imit->data, 4); - gost01_VKO_key(peerkey, priv, wrappedKey, sharedKey); - if (!gost_key_unwrap_crypto_pro(nid, sharedKey, wrappedKey, key)) { + if (gost01_VKO_key(peerkey, priv, wrappedKey, sharedKey) <= 0) + goto err; + if (gost_key_unwrap_crypto_pro(nid, sharedKey, wrappedKey, key) == 0) { GOSTerr(GOST_F_PKEY_GOST01_DECRYPT, - GOST_R_ERROR_COMPUTING_SHARED_KEY); + GOST_R_ERROR_COMPUTING_SHARED_KEY); goto err; } ret = 1; - err: - if (eph_key) - EVP_PKEY_free(eph_key); - if (gkt) - GOST_KEY_TRANSPORT_free(gkt); +err: + EVP_PKEY_free(eph_key); + GOST_KEY_TRANSPORT_free(gkt); return ret; } -int pkey_gost01_derive(EVP_PKEY_CTX * ctx, unsigned char *key, - size_t * keylen) +int +pkey_gost01_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) { - /* Public key of peer in the ctx field peerkey + /* + * Public key of peer in the ctx field peerkey * Our private key in the ctx pkey * ukm is in the algorithm specific context data */ @@ -424,86 +454,98 @@ int pkey_gost01_derive(EVP_PKEY_CTX * ctx, unsigned char *key, return 32; } - gost01_VKO_key(peer_key, my_key, data->shared_ukm, key); + if (gost01_VKO_key(peer_key, my_key, data->shared_ukm, key) <= 0) + return 0; + *keylen = 32; return 1; } -int pkey_gost01_encrypt(EVP_PKEY_CTX * pctx, unsigned char *out, - size_t * out_len, const unsigned char *key, - size_t key_len) +int +pkey_gost01_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len, + const unsigned char *key, size_t key_len) { GOST_KEY_TRANSPORT *gkt = NULL; EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx); unsigned char ukm[8], shared_key[32], crypted_key[44]; int ret = 0; - int key_is_ephemeral = 1; + int key_is_ephemeral; EVP_PKEY *sec_key = EVP_PKEY_CTX_get0_peerkey(pctx); int nid = NID_id_Gost28147_89_CryptoPro_A_ParamSet; - if (data->shared_ukm) { + if (data->shared_ukm != NULL) { memcpy(ukm, data->shared_ukm, 8); - } else if (out) { + } else /* if (out != NULL) */ { arc4random_buf(ukm, 8); } /* Check for private key in the peer_key of context */ if (sec_key) { key_is_ephemeral = 0; - if (!GOST_KEY_get0_private_key(sec_key->pkey.gost)) { + if (GOST_KEY_get0_private_key(sec_key->pkey.gost) == 0) { GOSTerr(GOST_F_PKEY_GOST01_ENCRYPT, - GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR); + GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR); goto err; } } else { key_is_ephemeral = 1; - if (out) { + if (out != NULL) { + GOST_KEY *tmp_key; + sec_key = EVP_PKEY_new(); - EVP_PKEY_assign(sec_key, EVP_PKEY_base_id(pubk), - GOST_KEY_new()); - EVP_PKEY_copy_parameters(sec_key, pubk); - if (!gost2001_keygen(sec_key->pkey.gost)) { + if (sec_key == NULL) + goto err; + tmp_key = GOST_KEY_new(); + if (tmp_key == NULL) + goto err; + if (EVP_PKEY_assign(sec_key, EVP_PKEY_base_id(pubk), + tmp_key) == 0) { + GOST_KEY_free(tmp_key); + goto err; + } + if (EVP_PKEY_copy_parameters(sec_key, pubk) == 0) + goto err; + if (gost2001_keygen(sec_key->pkey.gost) == 0) { goto err; } } } - if (out) { - gost01_VKO_key(pubk, sec_key, ukm, shared_key); - gost_key_wrap_crypto_pro(nid, shared_key, ukm, key, crypted_key); + if (out != NULL) { + if (gost01_VKO_key(pubk, sec_key, ukm, shared_key) <= 0) + goto err; + gost_key_wrap_crypto_pro(nid, shared_key, ukm, key, + crypted_key); } gkt = GOST_KEY_TRANSPORT_new(); - if (!gkt) { + if (gkt == NULL) goto err; - } - if (!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm, 8)) { + if (ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm, 8) == 0) goto err; - } - if (!ASN1_OCTET_STRING_set(gkt->key_info->imit, crypted_key + 40, 4)) { + if (ASN1_OCTET_STRING_set(gkt->key_info->imit, crypted_key + 40, + 4) == 0) goto err; - } - if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key, crypted_key + 8, 32)) { + if (ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key, crypted_key + 8, + 32) == 0) goto err; - } if (key_is_ephemeral) { - if (!X509_PUBKEY_set - (&gkt->key_agreement_info->ephem_key, - out ? sec_key : pubk)) { + if (X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key, + out != NULL ? sec_key : pubk) == 0) { GOSTerr(GOST_F_PKEY_GOST01_ENCRYPT, - GOST_R_CANNOT_PACK_EPHEMERAL_KEY); + GOST_R_CANNOT_PACK_EPHEMERAL_KEY); goto err; } } ASN1_OBJECT_free(gkt->key_agreement_info->cipher); gkt->key_agreement_info->cipher = OBJ_nid2obj(nid); - if (key_is_ephemeral && sec_key) + if (key_is_ephemeral) EVP_PKEY_free(sec_key); - if (!key_is_ephemeral) { + else { /* Set control "public key from client certificate used" */ - if (EVP_PKEY_CTX_ctrl - (pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0) { + if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, + NULL) <= 0) { GOSTerr(GOST_F_PKEY_GOST01_ENCRYPT, - GOST_R_CTRL_CALL_FAILED); + GOST_R_CTRL_CALL_FAILED); goto err; } } @@ -511,21 +553,26 @@ int pkey_gost01_encrypt(EVP_PKEY_CTX * pctx, unsigned char *out, ret = 1; GOST_KEY_TRANSPORT_free(gkt); return ret; - err: - if (key_is_ephemeral && sec_key) + +err: + if (key_is_ephemeral) EVP_PKEY_free(sec_key); GOST_KEY_TRANSPORT_free(gkt); return -1; } -static int pkey_gost01_ctrl(EVP_PKEY_CTX * ctx, int type, int p1, void *p2) +static int +pkey_gost01_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx); + switch (type) { case EVP_PKEY_CTRL_MD: - if (EVP_MD_type(p2) != GostR3410_get_md_digest(pctx->digest_nid)) { - GOSTerr(GOST_F_PKEY_GOST01_CTRL, GOST_R_INVALID_DIGEST_TYPE); + if (EVP_MD_type(p2) != + GostR3410_get_md_digest(pctx->digest_nid)) { + GOSTerr(GOST_F_PKEY_GOST01_CTRL, + GOST_R_INVALID_DIGEST_TYPE); return 0; } pctx->md = p2; @@ -546,9 +593,19 @@ static int pkey_gost01_ctrl(EVP_PKEY_CTX * ctx, int type, int p1, void *p2) return 1; case EVP_PKEY_CTRL_SET_IV: - pctx->shared_ukm = malloc((int)p1); - memcpy(pctx->shared_ukm, p2, (int)p1); + { + char *ukm = malloc(p1); + + if (ukm == NULL) { + GOSTerr(GOST_F_PKEY_GOST01_CTRL, + ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(ukm, p2, p1); + free(pctx->shared_ukm); + pctx->shared_ukm = ukm; return 1; + } case EVP_PKEY_CTRL_PEER_KEY: if (p1 == 0 || p1 == 1) /* call from EVP_PKEY_derive_set_peer */ |