]> wagner.pp.ru Git - openssl-gost/engine.git/commitdiff
New Gost CMS support, KARI/KTRI parsing
authorDmitry Belyavskiy <beldmit@gmail.com>
Sat, 2 May 2020 15:07:15 +0000 (18:07 +0300)
committerDmitry Belyavskiy <beldmit@gmail.com>
Mon, 4 May 2020 11:57:59 +0000 (14:57 +0300)
e_gost_err.c
e_gost_err.h
gost.txt
gost_ameth.c

index b643f112adcd1e84de86f33150e981bccb65c183..b7aa855203572c3b187435e6ef6f824f3f0219b4 100644 (file)
@@ -25,6 +25,12 @@ static ERR_STRING_DATA GOST_str_functs[] = {
     {ERR_PACK(0, GOST_F_GOST89_SET_ASN1_PARAMETERS, 0),
      "gost89_set_asn1_parameters"},
     {ERR_PACK(0, GOST_F_GOST_CIPHER_CTL, 0), "gost_cipher_ctl"},
+    {ERR_PACK(0, GOST_F_GOST_CMS_SET_KARI_SHARED_INFO, 0),
+     "gost_cms_set_kari_shared_info"},
+    {ERR_PACK(0, GOST_F_GOST_CMS_SET_KTRI_SHARED_INFO, 0),
+     "gost_cms_set_ktri_shared_info"},
+    {ERR_PACK(0, GOST_F_GOST_CMS_SET_SHARED_INFO, 0),
+     "gost_cms_set_shared_info"},
     {ERR_PACK(0, GOST_F_GOST_EC_COMPUTE_PUBLIC, 0), "gost_ec_compute_public"},
     {ERR_PACK(0, GOST_F_GOST_EC_KEYGEN, 0), "gost_ec_keygen"},
     {ERR_PACK(0, GOST_F_GOST_EC_SIGN, 0), "gost_ec_sign"},
@@ -102,9 +108,12 @@ static ERR_STRING_DATA GOST_str_reasons[] = {
     "error computing export keys"},
     {ERR_PACK(0, 0, GOST_R_ERROR_COMPUTING_SHARED_KEY),
     "error computing shared key"},
+    {ERR_PACK(0, 0, GOST_R_ERROR_DECODING_PUBLIC_KEY),
+    "error decoding public key"},
     {ERR_PACK(0, 0, GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO),
     "error parsing key transport info"},
     {ERR_PACK(0, 0, GOST_R_ERROR_POINT_MUL), "error point mul"},
+    {ERR_PACK(0, 0, GOST_R_ERROR_SETTING_PEER_KEY), "error setting peer key"},
     {ERR_PACK(0, 0, GOST_R_INCOMPATIBLE_ALGORITHMS), "incompatible algorithms"},
     {ERR_PACK(0, 0, GOST_R_INCOMPATIBLE_PEER_KEY), "incompatible peer key"},
     {ERR_PACK(0, 0, GOST_R_INVALID_CIPHER), "invalid cipher"},
@@ -135,6 +144,8 @@ static ERR_STRING_DATA GOST_str_reasons[] = {
     "unsupported cipher ctl command"},
     {ERR_PACK(0, 0, GOST_R_UNSUPPORTED_PARAMETER_SET),
     "unsupported parameter set"},
+    {ERR_PACK(0, 0, GOST_R_UNSUPPORTED_RECIPIENT_INFO),
+    "unsupported recipient info"},
     {0, NULL}
 };
 
index 0d7ec94074eb0e787fe007d80f0a3a4ed84b9e9c..f656239833414ecb12968a08b7e15dbd367a0b42 100644 (file)
@@ -36,6 +36,9 @@ void ERR_GOST_error(int function, int reason, char *file, int line);
 # define GOST_F_GOST89_GET_ASN1_PARAMETERS                104
 # define GOST_F_GOST89_SET_ASN1_PARAMETERS                105
 # define GOST_F_GOST_CIPHER_CTL                           106
+# define GOST_F_GOST_CMS_SET_KARI_SHARED_INFO             156
+# define GOST_F_GOST_CMS_SET_KTRI_SHARED_INFO             157
+# define GOST_F_GOST_CMS_SET_SHARED_INFO                  155
 # define GOST_F_GOST_EC_COMPUTE_PUBLIC                    107
 # define GOST_F_GOST_EC_KEYGEN                            108
 # define GOST_F_GOST_EC_SIGN                              109
@@ -98,8 +101,10 @@ void ERR_GOST_error(int function, int reason, char *file, int line);
 # define GOST_R_CTRL_CALL_FAILED                          104
 # define GOST_R_ERROR_COMPUTING_EXPORT_KEYS               135
 # define GOST_R_ERROR_COMPUTING_SHARED_KEY                105
+# define GOST_R_ERROR_DECODING_PUBLIC_KEY                 138
 # define GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO          106
 # define GOST_R_ERROR_POINT_MUL                           107
+# define GOST_R_ERROR_SETTING_PEER_KEY                    139
 # define GOST_R_INCOMPATIBLE_ALGORITHMS                   108
 # define GOST_R_INCOMPATIBLE_PEER_KEY                     109
 # define GOST_R_INVALID_CIPHER                            134
@@ -125,5 +130,6 @@ void ERR_GOST_error(int function, int reason, char *file, int line);
 # define GOST_R_UKM_NOT_SET                               129
 # define GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND            130
 # define GOST_R_UNSUPPORTED_PARAMETER_SET                 131
+# define GOST_R_UNSUPPORTED_RECIPIENT_INFO                137
 
 #endif
index d56823e8c22806eadb6a46d65450584d6d1cfb96..959b99cc608d748934f70c5c84c2023d7d654d28 100644 (file)
--- a/gost.txt
+++ b/gost.txt
@@ -13,6 +13,9 @@ GOST_F_GET_ENCRYPTION_PARAMS:103:get_encryption_params
 GOST_F_GOST89_GET_ASN1_PARAMETERS:104:gost89_get_asn1_parameters
 GOST_F_GOST89_SET_ASN1_PARAMETERS:105:gost89_set_asn1_parameters
 GOST_F_GOST_CIPHER_CTL:106:gost_cipher_ctl
+GOST_F_GOST_CMS_SET_KARI_SHARED_INFO:156:gost_cms_set_kari_shared_info
+GOST_F_GOST_CMS_SET_KTRI_SHARED_INFO:157:gost_cms_set_ktri_shared_info
+GOST_F_GOST_CMS_SET_SHARED_INFO:155:gost_cms_set_shared_info
 GOST_F_GOST_EC_COMPUTE_PUBLIC:107:gost_ec_compute_public
 GOST_F_GOST_EC_KEYGEN:108:gost_ec_keygen
 GOST_F_GOST_EC_SIGN:109:gost_ec_sign
@@ -75,8 +78,10 @@ GOST_R_CIPHER_NOT_FOUND:103:cipher not found
 GOST_R_CTRL_CALL_FAILED:104:ctrl call failed
 GOST_R_ERROR_COMPUTING_EXPORT_KEYS:135:error computing export keys
 GOST_R_ERROR_COMPUTING_SHARED_KEY:105:error computing shared key
+GOST_R_ERROR_DECODING_PUBLIC_KEY:138:error decoding public key
 GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO:106:error parsing key transport info
 GOST_R_ERROR_POINT_MUL:107:error point mul
+GOST_R_ERROR_SETTING_PEER_KEY:139:error setting peer key
 GOST_R_INCOMPATIBLE_ALGORITHMS:108:incompatible algorithms
 GOST_R_INCOMPATIBLE_PEER_KEY:109:incompatible peer key
 GOST_R_INVALID_CIPHER:134:invalid cipher
@@ -103,3 +108,4 @@ GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q:128:signature parts greater than q
 GOST_R_UKM_NOT_SET:129:ukm not set
 GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND:130:unsupported cipher ctl command
 GOST_R_UNSUPPORTED_PARAMETER_SET:131:unsupported parameter set
+GOST_R_UNSUPPORTED_RECIPIENT_INFO:137:unsupported recipient info
index f13b4ed8a544a6ab21b4d7262fc6952d5ea53fce..92319e74c55ae3a85edde2484e30e0647d472e0e 100644 (file)
@@ -220,6 +220,153 @@ BIGNUM *gost_get0_priv_key(const EVP_PKEY *pkey)
     return NULL;
 }
 
+/*
+ * GOST CMS processing functions
+ */
+/* FIXME reaarange declarations */
+static int pub_decode_gost_ec(EVP_PKEY *pk, X509_PUBKEY *pub);
+
+static int gost_cms_set_kari_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
+{
+       int ret = 0;
+       X509_ALGOR *alg;
+       ASN1_OCTET_STRING *ukm;
+
+       /* Deal with originator */
+       X509_ALGOR *pubalg = NULL;
+       ASN1_BIT_STRING *pubkey = NULL;
+
+       EVP_PKEY *peer_key = NULL;
+       X509_PUBKEY *tmp   = NULL;
+
+       int nid;
+       unsigned char shared_key[64];
+       size_t shared_key_size = 64;
+       const EVP_CIPHER *cipher = NULL;
+
+       if (CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm) == 0)
+               goto err;
+
+       if (CMS_RecipientInfo_kari_get0_orig_id(ri, &pubalg, &pubkey, NULL, NULL, NULL) == 0)
+                 goto err;
+
+       nid = OBJ_obj2nid(alg->algorithm);
+       if (alg->parameter->type != V_ASN1_SEQUENCE)
+                 goto err;
+
+       switch (nid) {
+               case NID_kuznyechik_kexp15:
+               case NID_magma_kexp15:
+                       cipher = EVP_get_cipherbynid(nid);
+                       break;
+       }
+
+       if (cipher == NULL) {
+                       GOSTerr(GOST_F_GOST_CMS_SET_KARI_SHARED_INFO, GOST_R_CIPHER_NOT_FOUND);
+                 goto err;
+  }
+
+       if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_SET_IV,
+               ASN1_STRING_length(ukm), (void *)ASN1_STRING_get0_data(ukm)) <= 0)
+                       goto err;
+
+       if (pubkey != NULL && pubalg != NULL) {
+               const ASN1_OBJECT *paobj = NULL;
+               int ptype = 0;
+               const void *param = NULL;
+
+               peer_key = EVP_PKEY_new();
+               tmp = X509_PUBKEY_new();
+
+               if ((peer_key == NULL) || (tmp == NULL)) {
+                       GOSTerr(GOST_F_GOST_CMS_SET_KARI_SHARED_INFO, ERR_R_MALLOC_FAILURE);
+                       goto err;
+               }
+
+               X509_ALGOR_get0(&paobj, &ptype, &param, pubalg);
+
+               if (X509_PUBKEY_set0_param(tmp, (ASN1_OBJECT *)paobj,
+                       ptype, (void *)param,
+                       (unsigned char *)ASN1_STRING_get0_data(pubkey),
+                       ASN1_STRING_length(pubkey) ) == 0) {
+                               GOSTerr(GOST_F_GOST_CMS_SET_KARI_SHARED_INFO, GOST_R_PUBLIC_KEY_UNDEFINED);
+                               goto err;
+               }
+
+               if (pub_decode_gost_ec(peer_key, tmp) <= 0) {
+                               GOSTerr(GOST_F_GOST_CMS_SET_KARI_SHARED_INFO, GOST_R_ERROR_DECODING_PUBLIC_KEY);
+                               goto err;
+               }
+
+               if (EVP_PKEY_derive_set_peer(pctx, peer_key) <= 0) {
+                               GOSTerr(GOST_F_GOST_CMS_SET_KARI_SHARED_INFO, GOST_R_ERROR_SETTING_PEER_KEY);
+                               goto err;
+               }
+       }
+
+       if (EVP_PKEY_derive(pctx, shared_key, &shared_key_size) <= 0) {
+               GOSTerr(GOST_F_GOST_CMS_SET_KARI_SHARED_INFO, GOST_R_ERROR_COMPUTING_SHARED_KEY);
+               goto err;
+       }
+
+       EVP_CIPHER_CTX_set_flags(CMS_RecipientInfo_kari_get0_ctx(ri), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
+       if (EVP_DecryptInit_ex(CMS_RecipientInfo_kari_get0_ctx(ri), cipher, NULL,
+               shared_key, ukm->data+24) == 0)
+                       goto err;
+
+       ret = 1;
+err:
+       EVP_PKEY_free(peer_key);
+       if (ret == 0) {
+               X509_PUBKEY_free(tmp);
+       }
+
+       return ret;
+}
+
+static int gost_cms_set_ktri_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
+{
+       X509_ALGOR *alg;
+       struct gost_pmeth_data *gctx = EVP_PKEY_CTX_get_data(pctx);
+
+       CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg);
+
+       switch (OBJ_obj2nid(alg->algorithm)) {
+               case NID_kuznyechik_kexp15:
+                       gctx->cipher_nid = NID_kuznyechik_ctr;
+                       break;
+
+               case NID_magma_kexp15:
+                       gctx->cipher_nid = NID_magma_ctr;
+                       break;
+
+               case NID_id_GostR3410_2012_256:
+               case NID_id_GostR3410_2012_512:
+                       gctx->cipher_nid = NID_id_Gost28147_89;
+                       break;
+
+               default:
+                       GOSTerr(GOST_F_GOST_CMS_SET_KTRI_SHARED_INFO, GOST_R_UNSUPPORTED_RECIPIENT_INFO);
+                       return 0;
+       }
+
+       return 1;
+}
+
+static int gost_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
+{
+       switch(CMS_RecipientInfo_type(ri)) {
+               case CMS_RECIPINFO_AGREE:
+                       return gost_cms_set_kari_shared_info(pctx, ri);
+               break;
+               case CMS_RECIPINFO_TRANS:
+                       return gost_cms_set_ktri_shared_info(pctx, ri);
+               break;
+       }
+
+       GOSTerr(GOST_F_GOST_CMS_SET_SHARED_INFO, GOST_R_UNSUPPORTED_RECIPIENT_INFO);
+       return 0;
+}
 /*
  * Control function
  */
@@ -263,7 +410,7 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
         return 1;
 #endif
     case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
-        if (arg1 == 0) {
+        if (arg1 == 0) { /* Encryption */
             ASN1_STRING *params = encode_gost_algor_params(pkey);
             if (!params) {
                 return -1;
@@ -271,7 +418,7 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
             PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO *)arg2, &alg1);
             X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_id(pkey)),
                             V_ASN1_SEQUENCE, params);
-        }
+                               }
         return 1;
 #ifndef OPENSSL_NO_CMS
     case ASN1_PKEY_CTRL_CMS_ENVELOPE:
@@ -284,8 +431,26 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
                                              NULL, &alg1);
             X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_id(pkey)),
                             V_ASN1_SEQUENCE, params);
+        } else {
+          EVP_PKEY_CTX *pctx;
+          CMS_RecipientInfo *ri = arg2;
+          pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+          if (!pctx)
+              return 0;
+          return gost_cms_set_shared_info(pctx, ri);
         }
         return 1;
+#ifdef ASN1_PKEY_CTRL_CMS_RI_TYPE
+  case ASN1_PKEY_CTRL_CMS_RI_TYPE:
+        *(int *)arg2 = CMS_RECIPINFO_TRANS;
+        return 1;
+       case ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED:
+                       if (arg1 == CMS_RECIPINFO_AGREE || arg1 == CMS_RECIPINFO_TRANS)
+                               return 1;
+                       else
+                               return 0;
+                       break;
+#endif
 #endif
     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
         *(int *)arg2 = md_nid;