[PATCH 1/5] gost: populate params tables with new curves

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 1/5] gost: populate params tables with new curves

Dmitry Baryshkov
Allow users to specify new curves via strings.

Sponsored by ROSA Linux

Signed-off-by: Dmitry Baryshkov <[hidden email]>
---
 src/lib/libcrypto/gost/gostr341001_params.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/lib/libcrypto/gost/gostr341001_params.c b/src/lib/libcrypto/gost/gostr341001_params.c
index 282a21041999..9764964cdc1e 100644
--- a/src/lib/libcrypto/gost/gostr341001_params.c
+++ b/src/lib/libcrypto/gost/gostr341001_params.c
@@ -94,12 +94,22 @@ static const GostR3410_params GostR3410_256_params[] = {
  { "0",  NID_id_GostR3410_2001_TestParamSet },
  { "XA", NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet },
  { "XB", NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet },
+ { "TCA", NID_id_tc26_gost_3410_12_256_paramSetA },
+ { "TCB", NID_id_tc26_gost_3410_12_256_paramSetB },
+ { "TCC", NID_id_tc26_gost_3410_12_256_paramSetC },
+ { "TCD", NID_id_tc26_gost_3410_12_256_paramSetD },
  { NULL, NID_undef },
 };
 
 static const GostR3410_params GostR3410_512_params[] = {
  { "A",  NID_id_tc26_gost_3410_12_512_paramSetA },
  { "B",  NID_id_tc26_gost_3410_12_512_paramSetB },
+ { "C",  NID_id_tc26_gost_3410_12_512_paramSetC },
+ { "0",  NID_id_tc26_gost_3410_12_512_paramSetTest},
+ /* Duplicates for compatibility with OpenSSL */
+ { "TCA", NID_id_tc26_gost_3410_12_512_paramSetA },
+ { "TCB", NID_id_tc26_gost_3410_12_512_paramSetB },
+ { "TCC", NID_id_tc26_gost_3410_12_512_paramSetC },
  { NULL, NID_undef },
 };
 
--
2.27.0

Reply | Threaded
Open this post in threaded view
|

[PATCH 2/5] gost: use ECerror to report EC errors

Dmitry Baryshkov
GOST code uses GOSTerror(EC_R_foo) to report several errors. Use
ECerror(EC_R_foo) instead to make error messages match error code.

Sponsored by ROSA Linux.

Signed-off-by: Dmitry Baryshkov <[hidden email]>
---
 src/lib/libcrypto/gost/gostr341001_ameth.c |  2 +-
 src/lib/libcrypto/gost/gostr341001_key.c   | 14 +++++++-------
 src/lib/libcrypto/gost/gostr341001_pmeth.c |  2 +-
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/lib/libcrypto/gost/gostr341001_ameth.c b/src/lib/libcrypto/gost/gostr341001_ameth.c
index 27a95f2069cd..0e9521178da5 100644
--- a/src/lib/libcrypto/gost/gostr341001_ameth.c
+++ b/src/lib/libcrypto/gost/gostr341001_ameth.c
@@ -547,7 +547,7 @@ param_decode_gost01(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
  }
  group = EC_GROUP_new_by_curve_name(nid);
  if (group == NULL) {
- GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
+ ECerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
  GOST_KEY_free(ec);
  return 0;
  }
diff --git a/src/lib/libcrypto/gost/gostr341001_key.c b/src/lib/libcrypto/gost/gostr341001_key.c
index 0af39f21bf33..74f8cab9d86c 100644
--- a/src/lib/libcrypto/gost/gostr341001_key.c
+++ b/src/lib/libcrypto/gost/gostr341001_key.c
@@ -121,7 +121,7 @@ GOST_KEY_check_key(const GOST_KEY *key)
  return 0;
  }
  if (EC_POINT_is_at_infinity(key->group, key->pub_key) != 0) {
- GOSTerror(EC_R_POINT_AT_INFINITY);
+ ECerror(EC_R_POINT_AT_INFINITY);
  goto err;
  }
  if ((ctx = BN_CTX_new()) == NULL)
@@ -131,14 +131,14 @@ GOST_KEY_check_key(const GOST_KEY *key)
 
  /* testing whether the pub_key is on the elliptic curve */
  if (EC_POINT_is_on_curve(key->group, key->pub_key, ctx) == 0) {
- GOSTerror(EC_R_POINT_IS_NOT_ON_CURVE);
+ ECerror(EC_R_POINT_IS_NOT_ON_CURVE);
  goto err;
  }
  /* testing whether pub_key * order is the point at infinity */
  if ((order = BN_new()) == NULL)
  goto err;
  if (EC_GROUP_get_order(key->group, order, ctx) == 0) {
- GOSTerror(EC_R_INVALID_GROUP_ORDER);
+ ECerror(EC_R_INVALID_GROUP_ORDER);
  goto err;
  }
  if (EC_POINT_mul(key->group, point, NULL, key->pub_key, order,
@@ -147,7 +147,7 @@ GOST_KEY_check_key(const GOST_KEY *key)
  goto err;
  }
  if (EC_POINT_is_at_infinity(key->group, point) == 0) {
- GOSTerror(EC_R_WRONG_ORDER);
+ ECerror(EC_R_WRONG_ORDER);
  goto err;
  }
  /*
@@ -156,7 +156,7 @@ GOST_KEY_check_key(const GOST_KEY *key)
  */
  if (key->priv_key != NULL) {
  if (BN_cmp(key->priv_key, order) >= 0) {
- GOSTerror(EC_R_WRONG_ORDER);
+ ECerror(EC_R_WRONG_ORDER);
  goto err;
  }
  if (EC_POINT_mul(key->group, point, key->priv_key, NULL, NULL,
@@ -165,7 +165,7 @@ GOST_KEY_check_key(const GOST_KEY *key)
  goto err;
  }
  if (EC_POINT_cmp(key->group, point, key->pub_key, ctx) != 0) {
- GOSTerror(EC_R_INVALID_PRIVATE_KEY);
+ ECerror(EC_R_INVALID_PRIVATE_KEY);
  goto err;
  }
  }
@@ -212,7 +212,7 @@ GOST_KEY_set_public_key_affine_coordinates(GOST_KEY *key, BIGNUM *x, BIGNUM *y)
  * out of range.
  */
  if (BN_cmp(x, tx) != 0 || BN_cmp(y, ty) != 0) {
- GOSTerror(EC_R_COORDINATES_OUT_OF_RANGE);
+ ECerror(EC_R_COORDINATES_OUT_OF_RANGE);
  goto err;
  }
  if (GOST_KEY_set_public_key(key, point) == 0)
diff --git a/src/lib/libcrypto/gost/gostr341001_pmeth.c b/src/lib/libcrypto/gost/gostr341001_pmeth.c
index 0eb1d873deaf..0e0cae99e3fc 100644
--- a/src/lib/libcrypto/gost/gostr341001_pmeth.c
+++ b/src/lib/libcrypto/gost/gostr341001_pmeth.c
@@ -246,7 +246,7 @@ pkey_gost01_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
  *siglen = 2 * size;
  return 1;
  } else if (*siglen < 2 * size) {
- GOSTerror(EC_R_BUFFER_TOO_SMALL);
+ ECerror(EC_R_BUFFER_TOO_SMALL);
  return 0;
  }
  if (tbs_len != 32 && tbs_len != 64) {
--
2.27.0

Reply | Threaded
Open this post in threaded view
|

[PATCH 3/5] gost: support new PublicKeyParameters format

Dmitry Baryshkov
In reply to this post by Dmitry Baryshkov
Add support for updated PublicKeyParameters format as defined by
draft-deremin-rfc4491-bis.

Signed-off-by: Dmitry Baryshkov <[hidden email]>
---
 src/lib/libcrypto/gost/gost_asn1.c         |  2 +-
 src/lib/libcrypto/gost/gostr341001_ameth.c | 42 ++++++++++++++++++++--
 2 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/src/lib/libcrypto/gost/gost_asn1.c b/src/lib/libcrypto/gost/gost_asn1.c
index 2652162777b7..703d64070449 100644
--- a/src/lib/libcrypto/gost/gost_asn1.c
+++ b/src/lib/libcrypto/gost/gost_asn1.c
@@ -190,7 +190,7 @@ static const ASN1_TEMPLATE GOST_KEY_PARAMS_seq_tt[] = {
  .item = &ASN1_OBJECT_it,
  },
  {
- .flags = 0,
+ .flags = ASN1_TFLG_OPTIONAL,
  .tag = 0,
  .offset = offsetof(GOST_KEY_PARAMS, hash_params),
  .field_name = "hash_params",
diff --git a/src/lib/libcrypto/gost/gostr341001_ameth.c b/src/lib/libcrypto/gost/gostr341001_ameth.c
index 0e9521178da5..7cb70ed420ae 100644
--- a/src/lib/libcrypto/gost/gostr341001_ameth.c
+++ b/src/lib/libcrypto/gost/gostr341001_ameth.c
@@ -90,9 +90,33 @@ decode_gost01_algor_params(EVP_PKEY *pkey, const unsigned char **p, int len)
  return 0;
  }
  param_nid = OBJ_obj2nid(gkp->key_params);
- digest_nid = OBJ_obj2nid(gkp->hash_params);
+ if (gkp->hash_params)
+ digest_nid = OBJ_obj2nid(gkp->hash_params);
+ else {
+ switch (param_nid) {
+ case NID_id_tc26_gost_3410_12_256_paramSetA:
+ case NID_id_tc26_gost_3410_12_256_paramSetB:
+ case NID_id_tc26_gost_3410_12_256_paramSetC:
+ case NID_id_tc26_gost_3410_12_256_paramSetD:
+ digest_nid = NID_id_tc26_gost3411_2012_256;
+ break;
+ case NID_id_tc26_gost_3410_12_512_paramSetTest:
+ case NID_id_tc26_gost_3410_12_512_paramSetA:
+ case NID_id_tc26_gost_3410_12_512_paramSetB:
+ case NID_id_tc26_gost_3410_12_512_paramSetC:
+ digest_nid = NID_id_tc26_gost3411_2012_512;
+ break;
+ default:
+ digest_nid = NID_undef;
+ }
+ }
  GOST_KEY_PARAMS_free(gkp);
 
+ if (digest_nid == NID_undef) {
+ GOSTerror(GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
+ return 0;
+ }
+
  ec = pkey->pkey.gost;
  if (ec == NULL) {
  ec = GOST_KEY_new();
@@ -137,7 +161,21 @@ encode_gost01_algor_params(const EVP_PKEY *key)
  pkey_param_nid =
     EC_GROUP_get_curve_name(GOST_KEY_get0_group(key->pkey.gost));
  gkp->key_params = OBJ_nid2obj(pkey_param_nid);
- gkp->hash_params = OBJ_nid2obj(GOST_KEY_get_digest(key->pkey.gost));
+ switch (pkey_param_nid) {
+ case NID_id_GostR3410_2001_TestParamSet:
+ case NID_id_GostR3410_2001_CryptoPro_A_ParamSet:
+ case NID_id_GostR3410_2001_CryptoPro_B_ParamSet:
+ case NID_id_GostR3410_2001_CryptoPro_C_ParamSet:
+ case NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet:
+ case NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet:
+ case NID_id_tc26_gost_3410_12_512_paramSetA:
+ case NID_id_tc26_gost_3410_12_512_paramSetB:
+ gkp->hash_params = OBJ_nid2obj(GOST_KEY_get_digest(key->pkey.gost));
+ break;
+ default:
+ gkp->hash_params = NULL;
+ break;
+ }
  /*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid); */
  params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
  if (params->length <= 0) {
--
2.27.0

Reply | Threaded
Open this post in threaded view
|

[PATCH 4/5] gostr341001: support unwrapped private keys support

Dmitry Baryshkov
In reply to this post by Dmitry Baryshkov
GOST private keys can be wrapped in OCTET STRING, INTEGER or come
unwrapped. Support the latter format.

Sponsored by ROSA Linux

Signed-off-by: Dmitry Baryshkov <[hidden email]>
---
 src/lib/libcrypto/gost/gost_asn1.c         |  52 ++++++++++
 src/lib/libcrypto/gost/gost_asn1.h         |  11 ++
 src/lib/libcrypto/gost/gostr341001_ameth.c | 115 +++++++++++++++++++--
 3 files changed, 169 insertions(+), 9 deletions(-)

diff --git a/src/lib/libcrypto/gost/gost_asn1.c b/src/lib/libcrypto/gost/gost_asn1.c
index 703d64070449..bfd81faa1ee2 100644
--- a/src/lib/libcrypto/gost/gost_asn1.c
+++ b/src/lib/libcrypto/gost/gost_asn1.c
@@ -17,6 +17,58 @@
 #include "gost_locl.h"
 #include "gost_asn1.h"
 
+static const ASN1_TEMPLATE MASKED_GOST_KEY_seq_tt[] = {
+ {
+ .flags = 0,
+ .tag = 0,
+ .offset = offsetof(MASKED_GOST_KEY, masked_priv_key),
+ .field_name = "masked_priv_key",
+ .item = &ASN1_OCTET_STRING_it,
+ },
+ {
+ .flags = 0,
+ .tag = 0,
+ .offset = offsetof(MASKED_GOST_KEY, public_key),
+ .field_name = "public_key",
+ .item = &ASN1_OCTET_STRING_it,
+ },
+};
+
+const ASN1_ITEM MASKED_GOST_KEY_it = {
+ .itype = ASN1_ITYPE_NDEF_SEQUENCE,
+ .utype = V_ASN1_SEQUENCE,
+ .templates = MASKED_GOST_KEY_seq_tt,
+ .tcount = sizeof(MASKED_GOST_KEY_seq_tt) / sizeof(ASN1_TEMPLATE),
+ .funcs = NULL,
+ .size = sizeof(MASKED_GOST_KEY),
+ .sname = "MASKED_GOST_KEY",
+};
+
+MASKED_GOST_KEY *
+d2i_MASKED_GOST_KEY(MASKED_GOST_KEY **a, const unsigned char **in, long len)
+{
+ return (MASKED_GOST_KEY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+    &MASKED_GOST_KEY_it);
+}
+
+int
+i2d_MASKED_GOST_KEY(MASKED_GOST_KEY *a, unsigned char **out)
+{
+ return ASN1_item_i2d((ASN1_VALUE *)a, out, &MASKED_GOST_KEY_it);
+}
+
+MASKED_GOST_KEY *
+MASKED_GOST_KEY_new(void)
+{
+ return (MASKED_GOST_KEY *)ASN1_item_new(&MASKED_GOST_KEY_it);
+}
+
+void
+MASKED_GOST_KEY_free(MASKED_GOST_KEY *a)
+{
+ ASN1_item_free((ASN1_VALUE *)a, &MASKED_GOST_KEY_it);
+}
+
 static const ASN1_TEMPLATE GOST_KEY_TRANSPORT_seq_tt[] = {
  {
  .flags = 0,
diff --git a/src/lib/libcrypto/gost/gost_asn1.h b/src/lib/libcrypto/gost/gost_asn1.h
index 7cabfc79c965..cdbda7b98b67 100644
--- a/src/lib/libcrypto/gost/gost_asn1.h
+++ b/src/lib/libcrypto/gost/gost_asn1.h
@@ -56,6 +56,17 @@
 
 __BEGIN_HIDDEN_DECLS
 
+typedef struct {
+ ASN1_OCTET_STRING *masked_priv_key;
+ ASN1_OCTET_STRING *public_key;
+} MASKED_GOST_KEY;
+
+MASKED_GOST_KEY *MASKED_GOST_KEY_new(void);
+void MASKED_GOST_KEY_free(MASKED_GOST_KEY *a);
+MASKED_GOST_KEY *d2i_MASKED_GOST_KEY(MASKED_GOST_KEY **a, const unsigned char **in, long len);
+int i2d_MASKED_GOST_KEY(MASKED_GOST_KEY *a, unsigned char **out);
+extern const ASN1_ITEM MASKED_GOST_KEY_it;
+
 typedef struct {
  ASN1_OCTET_STRING *encrypted_key;
  ASN1_OCTET_STRING *imit;
diff --git a/src/lib/libcrypto/gost/gostr341001_ameth.c b/src/lib/libcrypto/gost/gostr341001_ameth.c
index 7cb70ed420ae..880c17ceaab8 100644
--- a/src/lib/libcrypto/gost/gostr341001_ameth.c
+++ b/src/lib/libcrypto/gost/gostr341001_ameth.c
@@ -437,6 +437,70 @@ priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
  return pub_print_gost01(out, pkey, indent, pctx);
 }
 
+static BIGNUM *unmask_priv_key(EVP_PKEY *pk,
+ const unsigned char *buf, int len, int num_masks)
+{
+ BIGNUM *pknum_masked = NULL, *q, *mask;
+ const GOST_KEY *key_ptr = pk->pkey.gost;
+ const EC_GROUP *group = GOST_KEY_get0_group(key_ptr);
+ const unsigned char *p = buf + num_masks * len;
+ BN_CTX *ctx;
+
+ pknum_masked = GOST_le2bn(buf, len, NULL);
+ if (!pknum_masked) {
+ GOSTerror(ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (num_masks == 0)
+ return pknum_masked;
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ GOSTerror(ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ BN_CTX_start(ctx);
+
+ q = BN_CTX_get(ctx);
+ if (!q) {
+ GOSTerror(ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ mask = BN_CTX_get(ctx);
+ if (!mask) {
+ GOSTerror(ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (EC_GROUP_get_order(group, q, NULL) <= 0) {
+ GOSTerror(ERR_R_EC_LIB);
+ goto err;
+ }
+
+ for (; p != buf; p -= len) {
+ if (GOST_le2bn(p, len, mask) == NULL ||
+    !BN_mod_mul(pknum_masked, pknum_masked, mask, q, ctx)) {
+ GOSTerror(ERR_R_BN_LIB);
+ goto err;
+ }
+ }
+
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+
+ return pknum_masked;
+
+err:
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+
+ BN_free(pknum_masked);
+ return NULL;
+}
+
 static int
 priv_decode_gost01(EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf)
 {
@@ -450,6 +514,7 @@ priv_decode_gost01(EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf)
  GOST_KEY *ec;
  int ptype = V_ASN1_UNDEF;
  ASN1_STRING *pval = NULL;
+ int expected_key_len;
 
  if (PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf) == 0) {
  GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
@@ -467,29 +532,61 @@ priv_decode_gost01(EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf)
  return 0;
  }
  p = pkey_buf;
- if (V_ASN1_OCTET_STRING == *p) {
+
+ expected_key_len = (pkey_bits_gost01(pk) + 7) / 8;
+ if (expected_key_len == 0) {
+ EVPerror(EVP_R_DECODE_ERROR);
+ return 0;
+ } else if (priv_len % expected_key_len == 0) {
+ /* Key is not wrapped but masked */
+ pk_num = unmask_priv_key(pk, pkey_buf, expected_key_len,
+ priv_len / expected_key_len - 1);
+ } else if (V_ASN1_OCTET_STRING == *p) {
  /* New format - Little endian octet string */
  ASN1_OCTET_STRING *s =
     d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
 
  if (s == NULL) {
- GOSTerror(EVP_R_DECODE_ERROR);
+ EVPerror(EVP_R_DECODE_ERROR);
  ASN1_STRING_free(s);
  return 0;
  }
 
  pk_num = GOST_le2bn(s->data, s->length, NULL);
  ASN1_STRING_free(s);
- } else {
- priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
- if (priv_key == NULL)
+ } else if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == *p) {
+ /* New format - Structure with masked private and separate public key */
+ MASKED_GOST_KEY *s =
+    d2i_MASKED_GOST_KEY(NULL, &p, priv_len);
+
+ if (s == NULL ||
+    !s->masked_priv_key ||
+    s->masked_priv_key->length % expected_key_len != 0) {
+ EVPerror(EVP_R_DECODE_ERROR);
+ MASKED_GOST_KEY_free(s);
  return 0;
- ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL);
- ASN1_INTEGER_free(priv_key);
- if (ret == 0) {
- GOSTerror(EVP_R_DECODE_ERROR);
+ }
+
+ pk_num = unmask_priv_key(pk, s->masked_priv_key->data,
+ expected_key_len,
+ s->masked_priv_key->length / expected_key_len - 1);
+ MASKED_GOST_KEY_free(s);
+ } else if (V_ASN1_INTEGER == *p) {
+ priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
+ if (priv_key == NULL) {
+ EVPerror(EVP_R_DECODE_ERROR);
  return 0;
  }
+ pk_num = ASN1_INTEGER_to_BN(priv_key, NULL);
+ ASN1_INTEGER_free(priv_key);
+ } else {
+ EVPerror(EVP_R_DECODE_ERROR);
+ return 0;
+ }
+
+ if (pk_num == NULL) {
+ EVPerror(EVP_R_DECODE_ERROR);
+ return 0;
  }
 
  ec = pk->pkey.gost;
--
2.27.0

Reply | Threaded
Open this post in threaded view
|

[PATCH 5/5] pkcs12: add support for GOST PFX files

Dmitry Baryshkov
In reply to this post by Dmitry Baryshkov
Russian standard body has changed the way MAC key is calculated for
PKCS12 files. Generate proper keys depending on the digest type used for
MAC generation.

Sponsored by ROSA Linux

Signed-off-by: Dmitry Baryshkov <[hidden email]>
---
 src/lib/libcrypto/pkcs12/p12_key.c  | 18 ++++++++++++++++++
 src/lib/libcrypto/pkcs12/p12_mutl.c | 28 +++++++++++++++++++++-------
 src/lib/libcrypto/pkcs12/pkcs12.h   |  5 +++++
 3 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/src/lib/libcrypto/pkcs12/p12_key.c b/src/lib/libcrypto/pkcs12/p12_key.c
index d419a9d83598..9a5297a23131 100644
--- a/src/lib/libcrypto/pkcs12/p12_key.c
+++ b/src/lib/libcrypto/pkcs12/p12_key.c
@@ -195,3 +195,21 @@ end:
  EVP_MD_CTX_cleanup(&ctx);
  return ret;
 }
+
+int
+PKCS12_key_gen_gost(const char *pass, int passlen, unsigned char *salt,
+    int saltlen, int iter, int n, unsigned char *out,
+    const EVP_MD *md_type)
+{
+ unsigned char buf[96];
+
+ if (n != PKCS12_GOST_KEY_LEN)
+ return 0;
+
+ if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, md_type, sizeof(buf), buf))
+ return 0;
+
+ memcpy(out, buf + sizeof(buf) - PKCS12_GOST_KEY_LEN, PKCS12_GOST_KEY_LEN);
+
+ return 1;
+}
diff --git a/src/lib/libcrypto/pkcs12/p12_mutl.c b/src/lib/libcrypto/pkcs12/p12_mutl.c
index f3132ec75f68..023bbbd92db1 100644
--- a/src/lib/libcrypto/pkcs12/p12_mutl.c
+++ b/src/lib/libcrypto/pkcs12/p12_mutl.c
@@ -74,6 +74,7 @@ PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
     unsigned char *mac, unsigned int *maclen)
 {
  const EVP_MD *md_type;
+ int md_type_nid;
  HMAC_CTX hmac;
  unsigned char key[EVP_MAX_MD_SIZE], *salt;
  int saltlen, iter;
@@ -97,13 +98,26 @@ PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
  PKCS12error(PKCS12_R_UNKNOWN_DIGEST_ALGORITHM);
  return 0;
  }
- md_size = EVP_MD_size(md_type);
- if (md_size < 0)
- return 0;
- if (!PKCS12_key_gen(pass, passlen, salt, saltlen, PKCS12_MAC_ID, iter,
-    md_size, key, md_type)) {
- PKCS12error(PKCS12_R_KEY_GEN_ERROR);
- return 0;
+ md_type_nid = EVP_MD_type(md_type);
+ if ((md_type_nid == NID_id_GostR3411_94 ||
+     md_type_nid == NID_id_tc26_gost3411_2012_256 ||
+     md_type_nid == NID_id_tc26_gost3411_2012_512) &&
+    getenv("LEGACY_GOST_PKCS12") == NULL) {
+ md_size = PKCS12_GOST_KEY_LEN;
+ if (!PKCS12_key_gen_gost(pass, passlen, salt, saltlen, iter,
+    md_size, key, md_type)) {
+ PKCS12error(PKCS12_R_KEY_GEN_ERROR);
+ return 0;
+ }
+ } else {
+ md_size = EVP_MD_size(md_type);
+ if (md_size < 0)
+ return 0;
+ if (!PKCS12_key_gen(pass, passlen, salt, saltlen, PKCS12_MAC_ID, iter,
+    md_size, key, md_type)) {
+ PKCS12error(PKCS12_R_KEY_GEN_ERROR);
+ return 0;
+ }
  }
  HMAC_CTX_init(&hmac);
  if (!HMAC_Init_ex(&hmac, key, md_size, md_type, NULL) ||
diff --git a/src/lib/libcrypto/pkcs12/pkcs12.h b/src/lib/libcrypto/pkcs12/pkcs12.h
index 56635f9d7e0a..4dab109bbc3a 100644
--- a/src/lib/libcrypto/pkcs12/pkcs12.h
+++ b/src/lib/libcrypto/pkcs12/pkcs12.h
@@ -91,6 +91,11 @@ extern "C" {
 #define PKCS12_add_friendlyname PKCS12_add_friendlyname_asc
 #endif
 
+#define PKCS12_GOST_KEY_LEN 32
+int PKCS12_key_gen_gost(const char *pass, int passlen, unsigned char *salt,
+    int saltlen, int iter, int n, unsigned char *out,
+    const EVP_MD *md_type);
+
 /* MS key usage constants */
 
 #define KEY_EX 0x10
--
2.27.0

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 1/5] gost: populate params tables with new curves

Dmitry Baryshkov
In reply to this post by Dmitry Baryshkov
Gracious ping for these patches.

сб, 27 июн. 2020 г. в 20:14, Dmitry Baryshkov <[hidden email]>:

>
> Allow users to specify new curves via strings.
>
> Sponsored by ROSA Linux
>
> Signed-off-by: Dmitry Baryshkov <[hidden email]>
> ---
>  src/lib/libcrypto/gost/gostr341001_params.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/src/lib/libcrypto/gost/gostr341001_params.c b/src/lib/libcrypto/gost/gostr341001_params.c
> index 282a21041999..9764964cdc1e 100644
> --- a/src/lib/libcrypto/gost/gostr341001_params.c
> +++ b/src/lib/libcrypto/gost/gostr341001_params.c
> @@ -94,12 +94,22 @@ static const GostR3410_params GostR3410_256_params[] = {
>         { "0",  NID_id_GostR3410_2001_TestParamSet },
>         { "XA", NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet },
>         { "XB", NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet },
> +       { "TCA", NID_id_tc26_gost_3410_12_256_paramSetA },
> +       { "TCB", NID_id_tc26_gost_3410_12_256_paramSetB },
> +       { "TCC", NID_id_tc26_gost_3410_12_256_paramSetC },
> +       { "TCD", NID_id_tc26_gost_3410_12_256_paramSetD },
>         { NULL, NID_undef },
>  };
>
>  static const GostR3410_params GostR3410_512_params[] = {
>         { "A",  NID_id_tc26_gost_3410_12_512_paramSetA },
>         { "B",  NID_id_tc26_gost_3410_12_512_paramSetB },
> +       { "C",  NID_id_tc26_gost_3410_12_512_paramSetC },
> +       { "0",  NID_id_tc26_gost_3410_12_512_paramSetTest},
> +       /* Duplicates for compatibility with OpenSSL */
> +       { "TCA", NID_id_tc26_gost_3410_12_512_paramSetA },
> +       { "TCB", NID_id_tc26_gost_3410_12_512_paramSetB },
> +       { "TCC", NID_id_tc26_gost_3410_12_512_paramSetC },
>         { NULL, NID_undef },
>  };
>
> --
> 2.27.0
>


--
With best wishes
Dmitry