Submitted by: "Victor B. Wagner" <vitus@cryptocom.ru>
authorDr. Stephen Henson <steve@openssl.org>
Tue, 17 Mar 2009 15:38:34 +0000 (15:38 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 17 Mar 2009 15:38:34 +0000 (15:38 +0000)
Reviewed by: steve@openssl.org

Update ccgost engine to support parameter files.

CHANGES
engines/ccgost/README.gost
engines/ccgost/e_gost_err.c
engines/ccgost/e_gost_err.h
engines/ccgost/gost_ameth.c
engines/ccgost/gost_pmeth.c

diff --git a/CHANGES b/CHANGES
index df5967cf72af3a99a183df9a6d45d6fa30376f63..565645aab0f3a1478bd0addd7f20bf7a38251edd 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,9 @@
 
  Changes between 0.9.8j and 0.9.9  [xx XXX xxxx]
 
+  *) Update Gost ENGINE to support parameter files.
+     [Victor B. Wagner <vitus@cryptocom.ru>]
+
   *) Support GeneralizedTime in ca utility. 
      [Oliver Martin <oliver@volatilevoid.net>, Steve Henson]
 
index 89da172e1c277622f419add92c62026664572810..3acc5d09ce01c47f2a7805a14eb44a2b3684e1ad 100644 (file)
@@ -80,9 +80,7 @@ And section which describes configuration of the engine should contain
 Where engine_id parameter specifies name of engine (should be "gost").
 dynamic_path is a location of the loadable shared library implementing the
 engine. If the engine is compiled statically or is located in the OpenSSL
-engines directory, this line can be omitted. But as of October 2007 there is
-some bug in OpenSSL engine initialization code which prevents engine from
-correct initialization if it is loaded without explicit dynamic_path.
+engines directory, this line can be omitted. 
 default_algorithms parameter specifies that all algorithms, provided by
 engine, should be used.
 
@@ -119,7 +117,21 @@ USAGE WITH COMMAND LINE openssl UTILITY
 There are no algorithm-specific things with generation of certificate
 request once you have a private key.
 
-2. S/MIME operations
+2. Generation of certificate request along with private/public keypar
+
+   openssl req -newkey gost2001 -pkeyopt paramset:A
+
+   Syntax of -pkeyopt parameter is identical with genpkey command.
+
+   You can also use oldstyle syntax -newkey gost2001:paramfile, but in
+   this case you should create parameter file first. 
+
+   It can be created with
+
+   openssl genpkey -genparam -algorithm gost2001 -pkeyopt paramset:A\
+      -out paramfile.
+
+3. S/MIME operations
 
 If you want to send encrypted mail using GOST algorithms, don't forget
 to specify -gost89 as encryption algorithm for OpenSSL smime command.
@@ -127,7 +139,7 @@ While OpenSSL is clever enough to find out that GOST R 34.11-94 digest
 must be used for digital signing with GOST private key, it have no way
 to derive symmetric encryption algorithm from key exchange keys.
 
-3. TLS operations
+4. TLS operations
 
 OpenSSL supports all four ciphersuites defined in the IETF draft.
 Once you've loaded GOST key and certificate into your TLS server,
@@ -154,7 +166,7 @@ keys would be supported and clients can negotiate ones they wish.
 This allows creation of TLS servers which use GOST ciphersuites for
 Russian clients and RSA/DSA ciphersuites for foreign clients.
 
-4. Calculation of digests and symmetric encryption
+5. Calculation of digests and symmetric encryption
  OpenSSL provides specific commands (like sha1, aes etc) for calculation
  of digests and symmetric encryption. Since such commands cannot be
  added dynamically, no such commands are provided for GOST algorithms.
@@ -192,7 +204,7 @@ Russian clients and RSA/DSA ciphersuites for foreign clients.
  openssl enc -gost89-cnt -out encrypted-file -in plain-text-file -k <passphrase>
 
 
-5. Encrypting private keys and PKCS12
+6. Encrypting private keys and PKCS12
 
 To produce PKCS12 files compatible with MagPro CSP, you need to use
 GOST algorithm for encryption of PKCS12 file and also GOST R 34.11-94
@@ -201,7 +213,15 @@ hash to derive key from password.
 openssl pksc12 -export -inkey gost.pem -in gost_cert.pem -keypbe gost89\
    -certpbe gost89 -macalg md_gost94
  
+7. Testing speed of symmetric ciphers.
+   
+To test performance of GOST symmetric ciphers you should use -evp switch
+of the openssl speed command. Engine-provided ciphers couldn't be
+accessed by cipher-specific functions, only via generic evp interface
+
+ openssl speed -evp gost89
+ openssl speed -evp gost89-cnt
+
 
 PROGRAMMING INTERFACES DETAILS
 
index 006a8969c26bbea79c80cda7a126292713e3fbc9..4d2b09169ad24f0f98c8a1cbb2e63e47f9795dad 100644 (file)
@@ -1,6 +1,6 @@
 /* e_gost_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2008 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
@@ -92,10 +92,12 @@ static ERR_STRING_DATA GOST_str_functs[]=
 {ERR_FUNC(GOST_F_PKEY_GOST01CP_DECRYPT),       "PKEY_GOST01CP_DECRYPT"},
 {ERR_FUNC(GOST_F_PKEY_GOST01CP_ENCRYPT),       "PKEY_GOST01CP_ENCRYPT"},
 {ERR_FUNC(GOST_F_PKEY_GOST01CP_KEYGEN),        "PKEY_GOST01CP_KEYGEN"},
+{ERR_FUNC(GOST_F_PKEY_GOST01_PARAMGEN),        "PKEY_GOST01_PARAMGEN"},
 {ERR_FUNC(GOST_F_PKEY_GOST2001_DERIVE),        "PKEY_GOST2001_DERIVE"},
 {ERR_FUNC(GOST_F_PKEY_GOST94CP_DECRYPT),       "PKEY_GOST94CP_DECRYPT"},
 {ERR_FUNC(GOST_F_PKEY_GOST94CP_ENCRYPT),       "PKEY_GOST94CP_ENCRYPT"},
 {ERR_FUNC(GOST_F_PKEY_GOST94CP_KEYGEN),        "PKEY_GOST94CP_KEYGEN"},
+{ERR_FUNC(GOST_F_PKEY_GOST94_PARAMGEN),        "PKEY_GOST94_PARAMGEN"},
 {ERR_FUNC(GOST_F_PKEY_GOST_CTRL),      "PKEY_GOST_CTRL"},
 {ERR_FUNC(GOST_F_PKEY_GOST_CTRL01_STR),        "PKEY_GOST_CTRL01_STR"},
 {ERR_FUNC(GOST_F_PKEY_GOST_CTRL94_STR),        "PKEY_GOST_CTRL94_STR"},
index a8e6841f22d497c6edf819ad03e722988a7550bb..14326e01e7b8812071b3088aa3dfcea9f201a7a6 100644 (file)
@@ -93,10 +93,12 @@ void ERR_GOST_error(int function, int reason, char *file, int line);
 #define GOST_F_PKEY_GOST01CP_DECRYPT                    118
 #define GOST_F_PKEY_GOST01CP_ENCRYPT                    119
 #define GOST_F_PKEY_GOST01CP_KEYGEN                     120
+#define GOST_F_PKEY_GOST01_PARAMGEN                     138
 #define GOST_F_PKEY_GOST2001_DERIVE                     121
 #define GOST_F_PKEY_GOST94CP_DECRYPT                    122
 #define GOST_F_PKEY_GOST94CP_ENCRYPT                    123
 #define GOST_F_PKEY_GOST94CP_KEYGEN                     124
+#define GOST_F_PKEY_GOST94_PARAMGEN                     139
 #define GOST_F_PKEY_GOST_CTRL                           125
 #define GOST_F_PKEY_GOST_CTRL01_STR                     126
 #define GOST_F_PKEY_GOST_CTRL94_STR                     127
index b9d9ba734b64f79a96da4c0fb87074b4038b7a89..7b3ba5048b4b2667374c5044eb481d79e2244556 100644 (file)
@@ -806,6 +806,59 @@ static int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
                }
        return -2;
 }      
+
+int gost94_param_encode(const EVP_PKEY *pkey, unsigned char **pder) 
+{
+   int nid=gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
+   return i2d_ASN1_OBJECT(OBJ_nid2obj(nid),pder);
+}
+int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder) 
+{
+   int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey)));
+   return i2d_ASN1_OBJECT(OBJ_nid2obj(nid),pder);
+}
+
+int gost94_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
+{
+       ASN1_OBJECT *obj=NULL;
+       DSA *dsa = EVP_PKEY_get0(pkey);
+       int nid;
+       if (d2i_ASN1_OBJECT(&obj,pder,derlen)==NULL) {
+               return 0;
+       }
+       nid = OBJ_obj2nid(obj);
+       ASN1_OBJECT_free(obj);
+       if (!dsa) 
+               {
+               dsa=DSA_new();
+               if (!EVP_PKEY_assign(pkey,NID_id_GostR3410_94,dsa)) return 0;
+               }
+       if (!fill_GOST94_params(dsa,nid)) return 0;
+       return 1;
+}      
+
+int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+       ASN1_OBJECT *obj=NULL;
+       int nid;
+       EC_KEY *ec = EVP_PKEY_get0(pkey);
+       if (d2i_ASN1_OBJECT(&obj,pder,derlen)==NULL) {
+               return 0;
+       }
+       nid = OBJ_obj2nid(obj);
+       ASN1_OBJECT_free(obj);
+       if (!ec) 
+               {
+               ec = EC_KEY_new();
+               if (!EVP_PKEY_assign(pkey,NID_id_GostR3410_2001,ec)) return 0;
+               }       
+       if (!fill_GOST2001_params(ec, nid)) return 0;
+       return 1;
+}      
+
+
+
+
+
 /* ----------------------------------------------------------------------*/
 int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info) 
        {
@@ -820,7 +873,8 @@ int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pems
                                priv_decode_gost, priv_encode_gost, 
                                priv_print_gost94);
 
-                       EVP_PKEY_asn1_set_param (*ameth, 0, 0,
+                       EVP_PKEY_asn1_set_param (*ameth, 
+                               gost94_param_decode, gost94_param_encode,
                                param_missing_gost94, param_copy_gost94, 
                                param_cmp_gost94,param_print_gost94 );
                        EVP_PKEY_asn1_set_public (*ameth,
@@ -836,7 +890,8 @@ int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pems
                                priv_decode_gost, priv_encode_gost, 
                                priv_print_gost01);
 
-                       EVP_PKEY_asn1_set_param (*ameth, 0, 0,
+                       EVP_PKEY_asn1_set_param (*ameth, 
+                               gost2001_param_decode, gost2001_param_encode,
                                param_missing_gost01, param_copy_gost01, 
                                param_cmp_gost01, param_print_gost01);
                        EVP_PKEY_asn1_set_public (*ameth,
index 996beaf4b640ceb6c75a23bad488c51cb45220b2..2861d383272d227598ea3e52ac8e88e8b5f2acb1 100644 (file)
 static int pkey_gost_init(EVP_PKEY_CTX *ctx)
        {
        struct gost_pmeth_data *data;
+       EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
        data = OPENSSL_malloc(sizeof(struct gost_pmeth_data));
        if (!data) return 0;
        memset(data,0,sizeof(struct gost_pmeth_data));
+       if (pkey && EVP_PKEY_get0(pkey)) 
+               {
+               switch (EVP_PKEY_base_id(pkey)) {
+               case NID_id_GostR3410_94:
+                 data->sign_param_nid = gost94_nid_by_params(EVP_PKEY_get0(pkey));
+                 break;
+               case NID_id_GostR3410_2001:
+                  data->sign_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey)));
+               break;
+               default:
+                       return 0;
+               }         
+               }
        EVP_PKEY_CTX_set_data(ctx,data);
        return 1;
        }
@@ -239,15 +253,16 @@ static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
 
 /* --------------------- key generation  --------------------------------*/
 
-
-/* Generates Gost_R3410_94_cp key */
-static int pkey_gost94cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+static int pkey_gost_paramgen_init(EVP_PKEY_CTX *ctx) {
+       return 1;
+}      
+static int pkey_gost94_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 
        {
        struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
        DSA *dsa=NULL;
        if (data->sign_param_nid == NID_undef)
                {
-                       GOSTerr(GOST_F_PKEY_GOST94CP_KEYGEN,
+                       GOSTerr(GOST_F_PKEY_GOST94_PARAMGEN,
                                GOST_R_NO_PARAMETERS_SET);
                        return 0;
                }
@@ -257,34 +272,51 @@ static int pkey_gost94cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
                DSA_free(dsa);
                return 0;
                }
-       gost_sign_keygen(dsa);
        EVP_PKEY_assign(pkey,NID_id_GostR3410_94,dsa);
        return 1;
        }
-
-/* Generates GOST_R3410 2001 key and assigns it using specified type */
-static int pkey_gost01cp_keygen(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_KEY *ec=NULL;
+
        if (data->sign_param_nid == NID_undef)
                {
-                       GOSTerr(GOST_F_PKEY_GOST01CP_KEYGEN,
+                       GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN,
                                GOST_R_NO_PARAMETERS_SET);
                        return 0;
                }
-       ec = EC_KEY_new();
+       if (!ec)        
+               ec = EC_KEY_new();
        if (!fill_GOST2001_params(ec,data->sign_param_nid))
                {
                EC_KEY_free(ec);
                return 0;
                }
-       gost2001_keygen(ec);
-
        EVP_PKEY_assign(pkey,NID_id_GostR3410_2001,ec);
        return 1;
        }
 
+/* Generates Gost_R3410_94_cp key */
+static int pkey_gost94cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+       {
+       DSA *dsa;
+       if (!pkey_gost94_paramgen(ctx,pkey)) return 0;
+       dsa = EVP_PKEY_get0(pkey);
+       gost_sign_keygen(dsa);
+       return 1;
+       }
+
+/* Generates GOST_R3410 2001 key and assigns it using specified type */
+static int pkey_gost01cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+       {
+       EC_KEY *ec;
+    if (!pkey_gost01_paramgen(ctx,pkey)) return 0;
+       ec = EVP_PKEY_get0(pkey);
+       gost2001_keygen(ec);
+       return 1;
+       }
+
 
 
 /* ----------- sign callbacks --------------------------------------*/
@@ -544,6 +576,7 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
                        EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cp_decrypt);
                        EVP_PKEY_meth_set_derive(*pmeth,
                                pkey_gost_derive_init, pkey_gost94_derive);
+                       EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost94_paramgen);       
                        break;
                case NID_id_GostR3410_2001:
                        EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl01_str);
@@ -557,6 +590,7 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
                        EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt);
                        EVP_PKEY_meth_set_derive(*pmeth,
                                pkey_gost_derive_init, pkey_gost2001_derive);
+                       EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost01_paramgen);       
                        break;
                case NID_id_Gost28147_89_MAC:
                        EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_mac_ctrl, pkey_gost_mac_ctrl_str);