]> www.wagner.pp.ru Git - openssl-gost/engine.git/blobdiff - gost_ameth.c
tcl_tests: ca.try: Ignore openssl crl exit status for 'corrupted CRL' test
[openssl-gost/engine.git] / gost_ameth.c
index de1cdcabff1edc6c9d0f26cf0e5900e12c7b94fe..8e02a15c27b3c663274b8a81853164716e586a54 100644 (file)
@@ -43,6 +43,7 @@ static int pkey_bits_gost(const EVP_PKEY *pk)
 
     switch (EVP_PKEY_base_id(pk)) {
     case NID_id_GostR3410_2001:
+    case NID_id_GostR3410_2001DH:
     case NID_id_GostR3410_2012_256:
         return 256;
     case NID_id_GostR3410_2012_512:
@@ -87,6 +88,7 @@ static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key)
        }
         break;
     case NID_id_GostR3410_2001:
+    case NID_id_GostR3410_2001DH:
         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr));
         gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
         break;
@@ -127,6 +129,7 @@ static int gost_decode_nid_params(EVP_PKEY *pkey, int pkey_nid, int param_nid)
     case NID_id_GostR3410_2012_256:
     case NID_id_GostR3410_2012_512:
     case NID_id_GostR3410_2001:
+    case NID_id_GostR3410_2001DH:
         if (!key_ptr) {
             key_ptr = EC_KEY_new();
             if (!EVP_PKEY_assign(pkey, pkey_nid, key_ptr)) {
@@ -186,6 +189,7 @@ static int gost_set_priv_key(EVP_PKEY *pkey, BIGNUM *priv)
     case NID_id_GostR3410_2012_512:
     case NID_id_GostR3410_2012_256:
     case NID_id_GostR3410_2001:
+    case NID_id_GostR3410_2001DH:
         {
             EC_KEY *ec = EVP_PKEY_get0(pkey);
             if (!ec) {
@@ -210,6 +214,7 @@ BIGNUM *gost_get0_priv_key(const EVP_PKEY *pkey)
     case NID_id_GostR3410_2012_512:
     case NID_id_GostR3410_2012_256:
     case NID_id_GostR3410_2001:
+    case NID_id_GostR3410_2001DH:
         {
             EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
             if (ec)
@@ -224,7 +229,7 @@ BIGNUM *gost_get0_priv_key(const EVP_PKEY *pkey)
  * GOST CMS processing functions
  */
 /* FIXME reaarange declarations */
-static int pub_decode_gost_ec(EVP_PKEY *pk, X509_PUBKEY *pub);
+static int pub_decode_gost_ec(EVP_PKEY *pk, const X509_PUBKEY *pub);
 
 static int gost_cms_set_kari_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
 {
@@ -340,6 +345,8 @@ static int gost_cms_set_ktri_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *
                        gctx->cipher_nid = NID_magma_ctr;
                        break;
 
+               case NID_id_GostR3410_2001:
+               case NID_id_GostR3410_2001DH:
                case NID_id_GostR3410_2012_256:
                case NID_id_GostR3410_2012_512:
                        gctx->cipher_nid = NID_id_Gost28147_89;
@@ -367,6 +374,42 @@ static int gost_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
        GOSTerr(GOST_F_GOST_CMS_SET_SHARED_INFO, GOST_R_UNSUPPORTED_RECIPIENT_INFO);
        return 0;
 }
+
+static ASN1_STRING *gost_encode_cms_params(int ka_nid)
+{
+       ASN1_STRING *ret = NULL;
+       ASN1_STRING *params = ASN1_STRING_new();
+
+       /* It's a hack. We have only one OID here, so we can use
+        * GOST_KEY_PARAMS which is a sequence of 3 OIDs,
+        * the 1st one is mandatory and the rest are optional */
+       GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
+
+       if (params == NULL || gkp == NULL) {
+                 GOSTerr(GOST_F_GOST_ENCODE_CMS_PARAMS, ERR_R_MALLOC_FAILURE);
+                       goto end;
+       }
+
+       gkp->key_params = OBJ_nid2obj(ka_nid);
+       params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
+
+       if (params->length < 0) {
+                 GOSTerr(GOST_F_GOST_ENCODE_CMS_PARAMS, ERR_R_MALLOC_FAILURE);
+                       goto end;
+       }
+
+       params->type = V_ASN1_SEQUENCE;
+       ret = params;
+
+end:
+       GOST_KEY_PARAMS_free(gkp);
+
+       if (ret == NULL)
+               ASN1_STRING_free(params);
+
+       return ret;
+}
+
 /*
  * Control function
  */
@@ -383,6 +426,7 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
         md_nid = NID_id_GostR3411_2012_256;
         break;
     case NID_id_GostR3410_2001:
+    case NID_id_GostR3410_2001DH:
     case NID_id_GostR3410_94:
         md_nid = NID_id_GostR3411_94;
         break;
@@ -423,14 +467,44 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
 #ifndef OPENSSL_NO_CMS
     case ASN1_PKEY_CTRL_CMS_ENVELOPE:
         if (arg1 == 0) {
-            ASN1_STRING *params = encode_gost_algor_params(pkey);
-            if (!params) {
-                return -1;
-            }
-            CMS_RecipientInfo_ktri_get0_algs((CMS_RecipientInfo *)arg2, NULL,
-                                             NULL, &alg1);
-            X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_id(pkey)),
-                            V_ASN1_SEQUENCE, params);
+          EVP_PKEY_CTX *pctx;
+          CMS_RecipientInfo *ri = arg2;
+
+          struct gost_pmeth_data *gctx = NULL;
+          ASN1_STRING *params = NULL;
+
+          pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+          if (!pctx)
+            return 0;
+
+          gctx = EVP_PKEY_CTX_get_data(pctx);
+
+          switch (gctx->cipher_nid) {
+            case NID_magma_ctr:
+            case NID_kuznyechik_ctr:
+              {
+                int ka_nid;
+
+                nid = (gctx->cipher_nid == NID_magma_ctr) ? NID_magma_kexp15 :
+                  NID_kuznyechik_kexp15;
+
+                ka_nid = (EVP_PKEY_base_id(pkey) == NID_id_GostR3410_2012_256) ?
+                  NID_id_tc26_agreement_gost_3410_2012_256 : NID_id_tc26_agreement_gost_3410_2012_512;
+
+                params = gost_encode_cms_params(ka_nid);
+              }
+              break;
+            default:
+                params = encode_gost_algor_params(pkey);
+              break;
+          }
+
+          if (params == NULL)
+              return -1;
+
+          CMS_RecipientInfo_ktri_get0_algs((CMS_RecipientInfo *)arg2, NULL,
+              NULL, &alg1);
+          X509_ALGOR_set0(alg1, OBJ_nid2obj(nid), V_ASN1_SEQUENCE, params);
         } else {
           EVP_PKEY_CTX *pctx;
           CMS_RecipientInfo *ri = arg2;
@@ -828,62 +902,63 @@ static int param_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
 }
 
 /* ---------- Public key functions * --------------------------------------*/
-static int pub_decode_gost_ec(EVP_PKEY *pk, X509_PUBKEY *pub)
+static int pub_decode_gost_ec(EVP_PKEY *pk, const X509_PUBKEY *pub)
 {
     X509_ALGOR *palg = NULL;
     const unsigned char *pubkey_buf = NULL;
-    unsigned char *databuf;
+    unsigned char *databuf = NULL;
     ASN1_OBJECT *palgobj = NULL;
     int pub_len;
-    EC_POINT *pub_key;
-    BIGNUM *X, *Y;
+    EC_POINT *pub_key = NULL;
+    BIGNUM *X = NULL, *Y = NULL;
     ASN1_OCTET_STRING *octet = NULL;
     size_t len;
     const EC_GROUP *group;
+    int retval = 0;
 
     if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
-        return 0;
+        goto ret;
     EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
     if (!decode_gost_algor_params(pk, palg))
-        return 0;
+        goto ret;
     group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
     octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
     if (!octet) {
         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
-        return 0;
+        goto ret;
     }
     databuf = OPENSSL_malloc(octet->length);
-    if (databuf == NULL) {
+    if (!databuf) {
         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
-        ASN1_OCTET_STRING_free(octet);
-        return 0;
+        goto ret;
     }
 
     BUF_reverse(databuf, octet->data, octet->length);
     len = octet->length / 2;
-    ASN1_OCTET_STRING_free(octet);
 
     Y = BN_bin2bn(databuf, len, NULL);
     X = BN_bin2bn(databuf + len, len, NULL);
-    OPENSSL_free(databuf);
+    if (!X || !Y) {
+        GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_BN_LIB);
+        goto ret;
+    }
     pub_key = EC_POINT_new(group);
     if (!EC_POINT_set_affine_coordinates(group, pub_key, X, Y, NULL)) {
         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
-        EC_POINT_free(pub_key);
-        BN_free(X);
-        BN_free(Y);
-        return 0;
+        goto ret;
     }
-    BN_free(X);
-    BN_free(Y);
-    if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk), pub_key)) {
+
+    retval = EC_KEY_set_public_key(EVP_PKEY_get0(pk), pub_key);
+    if (!retval)
         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
-        EC_POINT_free(pub_key);
-        return 0;
-    }
-    EC_POINT_free(pub_key);
-    return 1;
 
+ret:
+    EC_POINT_free(pub_key);
+    BN_free(X);
+    BN_free(Y);
+    OPENSSL_free(databuf);
+    ASN1_OCTET_STRING_free(octet);
+    return retval;
 }
 
 static int pub_encode_gost_ec(X509_PUBKEY *pub, const EVP_PKEY *pk)
@@ -905,11 +980,14 @@ static int pub_encode_gost_ec(X509_PUBKEY *pub, const EVP_PKEY *pk)
     pval = params;
 
     order = BN_new();
-    if (!order) {
+    if (order == NULL || EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL) == 0) {
         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
         goto err;
     }
-    EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL);
+    if (EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL) == 0) {
+        GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
     pub_key = EC_KEY_get0_public_key(ec);
     if (!pub_key) {
         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, GOST_R_PUBLIC_KEY_UNDEFINED);
@@ -988,6 +1066,7 @@ static int pkey_size_gost(const EVP_PKEY *pk)
     switch (EVP_PKEY_base_id(pk)) {
     case NID_id_GostR3410_94:
     case NID_id_GostR3410_2001:
+    case NID_id_GostR3410_2001DH:
     case NID_id_GostR3410_2012_256:
         return 64;
     case NID_id_GostR3410_2012_512:
@@ -1082,6 +1161,7 @@ int register_ameth_gost(int nid, EVP_PKEY_ASN1_METHOD **ameth,
         return 0;
     switch (nid) {
     case NID_id_GostR3410_2001:
+    case NID_id_GostR3410_2001DH:
         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
         EVP_PKEY_asn1_set_private(*ameth,
                                   priv_decode_gost, priv_encode_gost,