1. Changes for s_client.c to make it return non-zero exit code in case
authorDr. Stephen Henson <steve@openssl.org>
Fri, 26 Oct 2007 12:06:36 +0000 (12:06 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 26 Oct 2007 12:06:36 +0000 (12:06 +0000)
of handshake failure

2. Changes to x509_certificate_type function (crypto/x509/x509type.c) to
make it recognize GOST certificates as EVP_PKT_SIGN|EVP_PKT_EXCH
(required for s3_srvr to accept GOST client certificates).

3. Changes to EVP
- adding of function EVP_PKEY_CTX_get0_peerkey
- Make function EVP_PKEY_derive_set_peerkey work for context with
  ENCRYPT operation, because we use peerkey field in the context to
  pass non-ephemeral secret key to GOST encrypt operation.
- added EVP_PKEY_CTRL_SET_IV control command. It is really
  GOST-specific, but it is used in SSL code, so it has to go
  in some header file, available during libssl compilation

4. Fix to HMAC to avoid call of OPENSSL_cleanse on undefined data

5. Include des.h if KSSL_DEBUG is defined into some libssl files, to
  make debugging output which depends on constants defined there, work
  and other KSSL_DEBUG output fixes

6. Declaration of real GOST ciphersuites, two authentication methods
   SSL_aGOST94 and SSL_aGOST2001 and one key exchange method SSL_kGOST

7. Implementation  of these methods.

8. Support for sending unsolicited serverhello extension if GOST
  ciphersuite is selected. It is require for interoperability with
  CryptoPro CSP 3.0 and 3.6 and controlled by
  SSL_OP_CRYPTOPRO_TLSEXT_BUG constant.
  This constant is added to SSL_OP_ALL, because it does nothing, if
  non-GOST ciphersuite is selected, and all implementation of GOST
  include compatibility with CryptoPro.

9. Support for CertificateVerify message without length field. It is
   another CryptoPro bug, but support is made unconditional, because it
   does no harm for draft-conforming implementation.

10. In tls1_mac extra copy of stream mac context is no more done.
  When I've written currently commited code I haven't read
  EVP_DigestSignFinal manual carefully enough and haven't noticed that
  it does an internal digest ctx copying.

This implementation was tested against
1. CryptoPro CSP 3.6 client and server
2. Cryptopro CSP 3.0 server

31 files changed:
CHANGES
apps/s_client.c
crypto/dsa/dsa_pmeth.c
crypto/evp/evp.h
crypto/evp/pmeth_fn.c
crypto/evp/pmeth_lib.c
crypto/hmac/hm_pmeth.c
crypto/rsa/rsa_pmeth.c
crypto/x509/x509type.c
engines/ccgost/e_gost_err.c
engines/ccgost/e_gost_err.h
engines/ccgost/gost2001_keyx.c
engines/ccgost/gost94_keyx.c
engines/ccgost/gost_ameth.c
engines/ccgost/gost_crypt.c
engines/ccgost/gost_ctl.c
engines/ccgost/gost_eng.c
engines/ccgost/gost_lcl.h
engines/ccgost/gost_md.c
engines/ccgost/gost_pmeth.c
ssl/d1_enc.c
ssl/s3_clnt.c
ssl/s3_lib.c
ssl/s3_srvr.c
ssl/ssl.h
ssl/ssl_ciph.c
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/t1_enc.c
ssl/t1_lib.c
util/libeay.num

diff --git a/CHANGES b/CHANGES
index eccf5e23df8e79bc27475e0ef09c6dcd242292d7..ab2ea4d6f3a2299078c4a1794c282bcc58734187 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,10 @@
 
  Changes between 0.9.8g and 0.9.9  [xx XXX xxxx]
 
+  *) Implement remaining functionality needed to support GOST ciphersuites.
+     Interop testing has been performed using CryptoPro implementations.
+     [Victor B. Wagner <vitus@cryptocom.ru>]
+
   *) s390x assembler pack.
      [Andy Polyakov]
 
index 3ccaca333041920e2df067bd8e076707ea025994..0c3545a4ca61a569a66b0aa6e4e2b808974fde45 100644 (file)
@@ -1278,6 +1278,7 @@ SSL_set_tlsext_status_ids(con, ids);
                                if (cbuf_len != 0)
                                        {
                                        BIO_printf(bio_c_out,"shutdown\n");
+                                       ret = 0;
                                        goto shut;
                                        }
                                else
@@ -1320,6 +1321,7 @@ SSL_set_tlsext_status_ids(con, ids);
                        if (i <= 0)
                                {
                                BIO_printf(bio_c_out,"DONE\n");
+                               ret = 0;
                                goto shut;
                                /* goto end; */
                                }
@@ -1374,10 +1376,12 @@ printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240
                                BIO_printf(bio_c_out,"read X BLOCK\n");
                                break;
                        case SSL_ERROR_SYSCALL:
-                               BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error());
+                               ret=get_last_socket_error();
+                               BIO_printf(bio_err,"read:errno=%d\n",ret);
                                goto shut;
                        case SSL_ERROR_ZERO_RETURN:
                                BIO_printf(bio_c_out,"closed\n");
+                               ret=0;
                                goto shut;
                        case SSL_ERROR_SSL:
                                ERR_print_errors(bio_err);
@@ -1428,6 +1432,7 @@ printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240
                        if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q')))
                                {
                                BIO_printf(bio_err,"DONE\n");
+                               ret=0;
                                goto shut;
                                }
 
@@ -1450,12 +1455,13 @@ printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240
                        read_tty=0;
                        }
                }
+
+       ret=0;
 shut:
        if (in_init)
                print_stuff(bio_c_out,con,full_log);
        SSL_shutdown(con);
        SHUTDOWN(SSL_get_fd(con));
-       ret=0;
 end:
        if (con != NULL)
                {
index 935258b24d1d88a7205176a95cc54f9e7042b9c9..646ef3f0939d6afc76c609f37d1311da5f2a8729 100644 (file)
@@ -196,7 +196,11 @@ static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
 
                case EVP_PKEY_CTRL_PKCS7_SIGN:
                return 1;
-
+               
+               case EVP_PKEY_CTRL_PEER_KEY:
+                       DSAerr(DSA_F_PKEY_DSA_CTRL,
+                       EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+                       return -2;      
                default:
                return -2;
 
index 65538d4eac4710837290673c5ecc2779a5dbf40d..acb55fafe898ec41b766c06f2cc947adce4e942f 100644 (file)
@@ -1016,8 +1016,12 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
 
 #define EVP_PKEY_CTRL_DIGESTINIT       7
 
+/* Used by GOST key encryption in TLS */
+#define EVP_PKEY_CTRL_SET_IV           8
+
 #define EVP_PKEY_ALG_CTRL              0x1000
 
+
 #define EVP_PKEY_FLAG_AUTOARGLEN       2
 
 const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type);
@@ -1045,6 +1049,8 @@ void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data);
 void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx);
 EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx);
 
+EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx);
+
 void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data);
 void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
 
index d52dc43f077e14e30d764a317f15f704180e2e7a..7dd0f2083a171e40129197861578a7dad1d7fb8d 100644 (file)
@@ -285,13 +285,13 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
 int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
        {
        int ret;
-       if (!ctx || !ctx->pmeth || !ctx->pmeth->derive || !ctx->pmeth->ctrl)
+       if (!ctx || !ctx->pmeth || !(ctx->pmeth->derive||ctx->pmeth->encrypt) || !ctx->pmeth->ctrl)
                {
                EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
                        EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
                return -2;
                }
-       if (ctx->operation != EVP_PKEY_OP_DERIVE)
+       if (ctx->operation != EVP_PKEY_OP_DERIVE && ctx->operation != EVP_PKEY_OP_ENCRYPT)
                {
                EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
                                        EVP_R_OPERATON_NOT_INITIALIZED);
index 6abb951d0ca96a7b59dffca1107fd52781f3d45e..764271a36dd31dd9f2048fcde4334ff8b6f49dd7 100644 (file)
@@ -390,6 +390,11 @@ EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx)
        return ctx->pkey;
        }
 
+EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx)
+       {
+       return ctx->peerkey;
+       }
+       
 void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data)
        {
        ctx->app_data = data;
index 27a5c8ea572ce87b8752d34448a9e43595373c1c..6355a44413e6eaf9c23bc6777631e622f1de352c 100644 (file)
@@ -116,7 +116,8 @@ static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx)
        HMAC_CTX_cleanup(&hctx->ctx);
        if (hctx->ktmp.data)
                {
-               OPENSSL_cleanse(hctx->ktmp.data, hctx->ktmp.length);
+               if (hctx->ktmp.length)
+                       OPENSSL_cleanse(hctx->ktmp.data, hctx->ktmp.length);
                OPENSSL_free(hctx->ktmp.data);
                hctx->ktmp.data = NULL;
                }
index 98a8ce44c3ea5c0e58704b91ffcddeebfc73fd5a..de917c637ab8095d410da743188cac1637e41b31 100644 (file)
@@ -436,6 +436,10 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                case EVP_PKEY_CTRL_PKCS7_DECRYPT:
                case EVP_PKEY_CTRL_PKCS7_SIGN:
                return 1;
+               case EVP_PKEY_CTRL_PEER_KEY:
+                       RSAerr(RSA_F_PKEY_RSA_CTRL,
+                       EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+                       return -2;      
 
                default:
                return -2;
index 2cd994c5b0f57e36770730c480eed6ee377897e3..3385ad3f67cbe405f18692235b1bb086d63a4633 100644 (file)
@@ -91,6 +91,10 @@ int X509_certificate_type(X509 *x, EVP_PKEY *pkey)
                break;
        case EVP_PKEY_DH:
                ret=EVP_PK_DH|EVP_PKT_EXCH;
+               break;  
+       case NID_id_GostR3410_94:
+       case NID_id_GostR3410_2001:
+               ret=EVP_PKT_EXCH|EVP_PKT_SIGN;
                break;
        default:
                break;
index 648a2d71e5c4bfe25be7292b4bbaaef1378bb076..d483411fc2c3862fc52fa3355996fd5f1a5d6197 100644 (file)
@@ -97,6 +97,7 @@ static ERR_STRING_DATA GOST_str_functs[]=
 {ERR_FUNC(GOST_F_PKEY_GOST01CC_ENCRYPT),       "pkey_GOST01cc_encrypt"},
 {ERR_FUNC(GOST_F_PKEY_GOST01CP_ENCRYPT),       "pkey_GOST01cp_encrypt"},
 {ERR_FUNC(GOST_F_PKEY_GOST01_KEYGEN),  "PKEY_GOST01_KEYGEN"},
+{ERR_FUNC(GOST_F_PKEY_GOST2001_DERIVE),        "PKEY_GOST2001_DERIVE"},
 {ERR_FUNC(GOST_F_PKEY_GOST94CC_DECRYPT),       "pkey_GOST94cc_decrypt"},
 {ERR_FUNC(GOST_F_PKEY_GOST94CC_ENCRYPT),       "pkey_GOST94cc_encrypt"},
 {ERR_FUNC(GOST_F_PKEY_GOST94CP_DECRYPT),       "pkey_GOST94cp_decrypt"},
@@ -148,6 +149,8 @@ static ERR_STRING_DATA GOST_str_reasons[]=
 {ERR_REASON(GOST_R_NOT_ENOUGH_SPACE_FOR_KEY),"not enough space for key"},
 {ERR_REASON(GOST_R_NO_MEMORY)            ,"no memory"},
 {ERR_REASON(GOST_R_NO_PARAMETERS_SET)    ,"no parameters set"},
+{ERR_REASON(GOST_R_NO_PEER_KEY)          ,"no peer key"},
+{ERR_REASON(GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR),"no private part of non ephemeral keypair"},
 {ERR_REASON(GOST_R_PUBLIC_KEY_UNDEFINED) ,"public key undefined"},
 {ERR_REASON(GOST_R_RANDOM_GENERATOR_ERROR),"random generator error"},
 {ERR_REASON(GOST_R_RANDOM_GENERATOR_FAILURE),"random generator failure"},
@@ -155,6 +158,7 @@ static ERR_STRING_DATA GOST_str_reasons[]=
 {ERR_REASON(GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH),"session key mac does not match"},
 {ERR_REASON(GOST_R_SIGNATURE_MISMATCH)   ,"signature mismatch"},
 {ERR_REASON(GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q),"signature parts greater than q"},
+{ERR_REASON(GOST_R_UKM_NOT_SET)          ,"ukm not set"},
 {ERR_REASON(GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND),"unsupported cipher ctl command"},
 {ERR_REASON(GOST_R_UNSUPPORTED_PARAMETER_SET),"unsupported parameter set"},
 {0,NULL}
index 4fb5a985a3c41f4aab64c1ca2ed4bc20e7a5601e..a672ed9d8d4fcdddf12fe869e2c85ca696093fdf 100644 (file)
@@ -94,6 +94,7 @@ void ERR_GOST_error(int function, int reason, char *file, int line);
 #define GOST_F_PKEY_GOST01CC_ENCRYPT                    129
 #define GOST_F_PKEY_GOST01CP_ENCRYPT                    137
 #define GOST_F_PKEY_GOST01_KEYGEN                       112
+#define GOST_F_PKEY_GOST2001_DERIVE                     145
 #define GOST_F_PKEY_GOST94CC_DECRYPT                    125
 #define GOST_F_PKEY_GOST94CC_ENCRYPT                    123
 #define GOST_F_PKEY_GOST94CP_DECRYPT                    126
@@ -142,6 +143,8 @@ void ERR_GOST_error(int function, int reason, char *file, int line);
 #define GOST_R_NOT_ENOUGH_SPACE_FOR_KEY                         125
 #define GOST_R_NO_MEMORY                                106
 #define GOST_R_NO_PARAMETERS_SET                        107
+#define GOST_R_NO_PEER_KEY                              137
+#define GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR         139
 #define GOST_R_PUBLIC_KEY_UNDEFINED                     132
 #define GOST_R_RANDOM_GENERATOR_ERROR                   108
 #define GOST_R_RANDOM_GENERATOR_FAILURE                         133
@@ -149,6 +152,7 @@ void ERR_GOST_error(int function, int reason, char *file, int line);
 #define GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH           126
 #define GOST_R_SIGNATURE_MISMATCH                       110
 #define GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q           111
+#define GOST_R_UKM_NOT_SET                              138
 #define GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND           112
 #define GOST_R_UNSUPPORTED_PARAMETER_SET                113
 
index 3cef5f2e38b09b76527a999907a7a07d22e9963c..013659aa2377a3f62e8cace4081c7d54e2d1302b 100644 (file)
 #include "gost_lcl.h"
 #include "gost2001_keyx.h"
 
-/* Transform ECDH shared key into little endian as required by Cryptocom
- * key exchange */
-static void *make_key_le(const void *in, size_t inlen, void *out, size_t *outlen)
-       {
-       const char* inbuf= in;
-       char* outbuf= out;
-       int i;
-       if (*outlen < inlen)
-               {
-               return NULL;
-               }
-       for (i=0;i<inlen;i++)
-               {
-               outbuf[inlen-1-i]=inbuf[i];
-               }
-       *outlen = inlen;
-       return out;
-       }       
 
-/* Create gost 2001 ephemeral key with same parameters as peer key */
-static EC_KEY *make_ec_ephemeral_key(EC_KEY *peer_key,BIGNUM *seckey)
-       {
-       EC_KEY *out = EC_KEY_new();
-       EC_KEY_copy(out,peer_key);
-       EC_KEY_set_private_key(out,seckey);
-       gost2001_compute_public(out);
-       return out;
-       }
-/* Packs GOST elliptic curve key into EVP_PKEY setting same parameters
- * as in passed pubkey
- */
-static EVP_PKEY *ec_ephemeral_key_to_EVP(EVP_PKEY *pubk,int type,EC_KEY *ephemeral) 
-       {
-       EVP_PKEY *newkey;
-       newkey = EVP_PKEY_new();
-       EVP_PKEY_assign(newkey,type,ephemeral);
-       return newkey;
-       }       
-
-/*  
- * EVP_PKEY_METHOD callback encrypt  
- * Implementation of GOST2001 key transport, cryptocom variation 
- */
-
-int pkey_GOST01cc_encrypt (EVP_PKEY_CTX *pctx,unsigned char *out, 
-       size_t *out_len, const unsigned char *key,size_t key_len)
-       {
-       EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx);
-       struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx);     
-       GOST_KEY_TRANSPORT *gkt = NULL;
-       int ret=0;
-       const struct gost_cipher_info *cipher_info;
-       gost_ctx ctx;
-       EC_KEY *ephemeral=NULL;
-       const EC_POINT *pub_key_point=NULL;
-       unsigned char shared_key[32],encrypted_key[32],hmac[4],
-               iv[8]={0,0,0,0,0,0,0,0};
-       ephemeral = make_ec_ephemeral_key(EVP_PKEY_get0(pubk), gost_get_priv_key(data->eph_seckey));
-       if (!ephemeral) goto err;
-       /* compute shared key */
-       pub_key_point=EC_KEY_get0_public_key(EVP_PKEY_get0(pubk));
-       if (!ECDH_compute_key(shared_key,32,pub_key_point,ephemeral,make_key_le)) 
-               {
-               GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_COMPUTING_SHARED_KEY);
-               goto err;
-               }       
-       /* encrypt session key */
-       cipher_info = get_encryption_params(NULL);
-       gost_init(&ctx, cipher_info->sblock);
-       gost_key(&ctx,shared_key);
-       encrypt_cryptocom_key(key,key_len,encrypted_key,&ctx);
-       /* compute hmac of session key */
-       if (!gost_mac(&ctx,32,key,32,hmac)) 
-               {
-               GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_COMPUTING_MAC);
-               return -1;
-               }
-       gkt = GOST_KEY_TRANSPORT_new();
-       if (!gkt) 
-               {
-               GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_NO_MEMORY);
-               return -1;
-               }       
-       /* Store IV which is always zero in our case */
-       if (!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv,iv,8))
-               {
-               GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_STORING_IV);
-               goto err;
-               }       
-       if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,hmac,4)) 
-               {
-               GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_STORING_MAC);
-               goto err;
-               }       
-       if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,encrypted_key,32))
-               {       
-               GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_STORING_ENCRYPTED_KEY);
-               goto err;
-               }
-       
-       if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,data->eph_seckey))
-               {
-               GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
-               goto err;
-               }       
-       ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
-       gkt->key_agreement_info->cipher = OBJ_nid2obj(cipher_info->nid);
-       if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,&out))>0) ret = 1;
-       ;
-       err:
-       if (gkt) GOST_KEY_TRANSPORT_free(gkt);
-       return ret;
-       }
-/*  
- * EVP_PKEY_METHOD callback decrypt  
- * Implementation of GOST2001 key transport, cryptocom variation 
- */
-int pkey_GOST01cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_len, const unsigned char *in, size_t in_len)
-       {
-       /* Form DH params from compute shared key */
-       EVP_PKEY *priv=EVP_PKEY_CTX_get0_pkey(pctx);
-       GOST_KEY_TRANSPORT *gkt = NULL;
-       const unsigned char *p=in;
-       unsigned char shared_key[32];
-       unsigned char hmac[4],hmac_comp[4];
-       unsigned char iv[8];
-       int i;
-       const struct gost_cipher_info *cipher_info;
-       gost_ctx ctx;
-       const EC_POINT *pub_key_point;
-       EVP_PKEY *eph_key;
-
-       if (!key)
-               {
-               *key_len = 32;
-               return 1;
-               }       
-       /* Parse passed octet string and find out public key, iv and HMAC*/
-       gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p,
-               in_len);
-       if (!gkt)
-               {
-               GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
-               return 0;
-               }       
-       eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
-       /* Initialization vector is really ignored here */
-       OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8);
-       memcpy(iv,gkt->key_agreement_info->eph_iv->data,8);
-       /* HMAC should be computed and checked */
-       OPENSSL_assert(gkt->key_info->imit->length==4);
-       memcpy(hmac,gkt->key_info->imit->data,4);       
-       /* Compute shared key */
-       pub_key_point=EC_KEY_get0_public_key(EVP_PKEY_get0(eph_key));
-       i=ECDH_compute_key(shared_key,32,pub_key_point,EVP_PKEY_get0(priv),make_key_le);
-       EVP_PKEY_free(eph_key);
-       if (!i) 
-               {
-               GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_ERROR_COMPUTING_SHARED_KEY);
-               GOST_KEY_TRANSPORT_free(gkt);
-               return 0;
-               }
-       /* Decrypt session key */
-       cipher_info = get_encryption_params(gkt->key_agreement_info->cipher);
-       gost_init(&ctx, cipher_info->sblock);
-       gost_key(&ctx,shared_key);
-       
-       if (!decrypt_cryptocom_key(key,*key_len,gkt->key_info->encrypted_key->data, 
-                       gkt->key_info->encrypted_key->length, &ctx)) 
-               {
-               GOST_KEY_TRANSPORT_free(gkt);
-               return 0;
-               }
-       GOST_KEY_TRANSPORT_free(gkt);
-       /* check HMAC of session key*/
-       if (!gost_mac(&ctx,32,key,32,hmac_comp))
-               {
-               GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_ERROR_COMPUTING_MAC);
-               return 0;
-               }
-       /* HMAC of session key is not correct */
-    if (memcmp(hmac,hmac_comp,4)!=0)
-               {
-               GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH);
-               return 0;
-               }       
-       return 1; 
-       }
 
 /* Implementation of CryptoPro VKO 34.10-2001 algorithm */
 static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,const EC_POINT *pub_key,EC_KEY *priv_key,const unsigned char *ukm)
@@ -254,110 +67,191 @@ static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,cons
        return 32;
        }
 
+
+/*
+ * EVP_PKEY_METHOD callback derive. Implements VKO R 34.10-2001
+ * algorithm
+ */
+int pkey_gost2001_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
+{
+       /* Public key of peer in the ctx field peerkey
+        * Our private key in the ctx pkey
+        * ukm is in the algorithm specific context data
+        */
+       EVP_PKEY *my_key = EVP_PKEY_CTX_get0_pkey(ctx);
+       EVP_PKEY *peer_key = EVP_PKEY_CTX_get0_peerkey(ctx);
+       struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+       
+       if (!data->shared_ukm) {
+               GOSTerr(GOST_F_PKEY_GOST2001_DERIVE, GOST_R_UKM_NOT_SET);
+               return 0;
+       }       
+
+       if (key == NULL) {
+               *keylen = 32;
+               return 32;
+       }       
+       
+       *keylen=VKO_compute_key(key, 32, EC_KEY_get0_public_key(EVP_PKEY_get0(peer_key)),
+               (EC_KEY *)EVP_PKEY_get0(my_key),data->shared_ukm);
+       return 1;       
+}
+
+
+
+
+/*  
+ * EVP_PKEY_METHOD callback encrypt  
+ * Implementation of GOST2001 key transport, cryptocom variation 
+ */
 /* Generates ephemeral key based on pubk algorithm
  * computes shared key using VKO and returns filled up
  * GOST_KEY_TRANSPORT structure
  */
-/* Public, because it would be needed in SSL implementation */
-GOST_KEY_TRANSPORT *make_rfc4490_keytransport_2001(EVP_PKEY *pubk,BIGNUM *eph_key,
-       const unsigned char *key,size_t keylen, unsigned char *ukm,
-       size_t ukm_len)
-       {
 
+/*  
+ * EVP_PKEY_METHOD callback encrypt  
+ * Implementation of GOST2001 key transport, cryptopo variation 
+ */
+
+int pkey_GOST01cp_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);
        const struct gost_cipher_info *param=get_encryption_params(NULL);
-       EC_KEY *ephemeral = NULL;
-       GOST_KEY_TRANSPORT *gkt=NULL;
-       const EC_POINT *pub_key_point = EC_KEY_get0_public_key(EVP_PKEY_get0(pubk));
-       unsigned char shared_key[32],crypted_key[44];
-       gost_ctx ctx;
-       EVP_PKEY *newkey=NULL;
-       
-       /* Do not use vizir cipher parameters with cryptopro */
+       unsigned char ukm[8], shared_key[32], crypted_key[44];
+       int ret=0;
+       int key_is_ephemeral=1;
+       gost_ctx cctx;
+       EVP_PKEY *sec_key=EVP_PKEY_CTX_get0_peerkey(pctx);
+       if (data->shared_ukm) 
+               {
+               memcpy(ukm, data->shared_ukm,8);
+               } 
+       else if (out) 
+               {
+               
+               if (RAND_bytes(ukm,8)<=0)
+                       {
+                       GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT,
+                               GOST_R_RANDOM_GENERATOR_FAILURE);
+                       return 0;
+                       }       
+               }       
+       /* Check for private key in the peer_key of context */  
+       if (sec_key) 
+               {
+               key_is_ephemeral=0;
+               if (!gost_get0_priv_key(sec_key)) 
+                       {
+                       GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT,
+                       GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR);
+                       goto err;
+                       }       
+               } 
+       else 
+               {
+               key_is_ephemeral=1;
+               if (out) 
+                       {
+                       sec_key = EVP_PKEY_new();
+                       EVP_PKEY_assign(sec_key,EVP_PKEY_base_id(pubk),EC_KEY_new());
+                       EVP_PKEY_copy_parameters(sec_key,pubk);
+                       if (!gost2001_keygen(EVP_PKEY_get0(sec_key))) 
+                               {
+                               goto err;
+                               }       
+                       }
+               }
        if (!get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS) && param ==  gost_cipher_list)
                {
                param= gost_cipher_list+1;
                }       
-       ephemeral = make_ec_ephemeral_key(EVP_PKEY_get0(pubk),eph_key);
-    VKO_compute_key(shared_key,32,pub_key_point,ephemeral,ukm);
-       gost_init(&ctx,param->sblock);  
-       keyWrapCryptoPro(&ctx,shared_key,ukm,key,crypted_key);
+    if (out) 
+               {
+               VKO_compute_key(shared_key,32,EC_KEY_get0_public_key(EVP_PKEY_get0(pubk)),EVP_PKEY_get0(sec_key),ukm);
+               gost_init(&cctx,param->sblock); 
+               keyWrapCryptoPro(&cctx,shared_key,ukm,key,crypted_key);
+               }
        gkt = GOST_KEY_TRANSPORT_new();
        if (!gkt)
                {
-               goto memerr;
+               goto err;
                }       
        if(!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv,
                        ukm,8))
                {
-               goto memerr;
+               goto err;
                }       
        if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,crypted_key+40,4))
                {
-               goto memerr;
+               goto err;
                }
        if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,crypted_key+8,32))
                {
-               goto memerr;
-               }
-       newkey = ec_ephemeral_key_to_EVP(pubk,NID_id_GostR3410_2001,ephemeral);
-       if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,newkey))
-               {
-               GOSTerr(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001,GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
                goto err;
-               }       
+               }
+       if (key_is_ephemeral) { 
+               if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,out?sec_key:pubk))
+                       {
+                       GOSTerr(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001,
+                                       GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
+                       goto err;
+                       }       
+       }               
        ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
        gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid);
-       EVP_PKEY_free(newkey);
-       return gkt;
-       memerr:
-       GOSTerr(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001,
-               GOST_R_MALLOC_FAILURE);
-       err:            
-       GOST_KEY_TRANSPORT_free(gkt);
-       return NULL;
-       }
-
-/*  
- * EVP_PKEY_METHOD callback encrypt  
- * Implementation of GOST2001 key transport, cryptopo variation 
- */
-
-int pkey_GOST01cp_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];
-       int ret=0;
-       if (RAND_bytes(ukm,8)<=0)
-               {
-               GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT,
-                       GOST_R_RANDOM_GENERATOR_FAILURE);
-               return 0;
-               }       
-               
-       if (!(gkt=make_rfc4490_keytransport_2001(pubk,gost_get_priv_key(data->eph_seckey),key, key_len,ukm,8)))
-               {
-               goto err;
-               }       
-       if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,&out))>0) ret =1;
+       if (key_is_ephemeral && sec_key) EVP_PKEY_free(sec_key);
+       if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL))>0) ret =1;
        GOST_KEY_TRANSPORT_free(gkt);
        return ret;     
        err:            
+       if (key_is_ephemeral && sec_key) EVP_PKEY_free(sec_key);
        GOST_KEY_TRANSPORT_free(gkt);
        return -1;
        }
-/* Public, because it would be needed in SSL implementation */
-int decrypt_rfc4490_shared_key_2001(EVP_PKEY *priv,GOST_KEY_TRANSPORT *gkt,
-       unsigned char *key_buf,int key_buf_len) 
+/*  
+ * EVP_PKEY_METHOD callback decrypt  
+ * Implementation of GOST2001 key transport, cryptopo variation 
+ */
+int pkey_GOST01cp_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);
+       GOST_KEY_TRANSPORT *gkt = NULL;
+       int ret=0;      
        unsigned char wrappedKey[44];
        unsigned char sharedKey[32];
        gost_ctx ctx;
        const struct gost_cipher_info *param=NULL;
        EVP_PKEY *eph_key=NULL;
-       
+
+       if (!key)
+               {
+               *key_len = 32;
+               return 1;
+               }       
+       gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p,
+               in_len);
+       if (!gkt)
+               {
+               GOSTerr(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
+               return -1;
+               }       
+    
        eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
+       if (!eph_key) {
+               eph_key = EVP_PKEY_CTX_get0_peerkey(pctx);
+               if (! eph_key) {
+                       GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,
+                               GOST_R_NO_PEER_KEY);
+                       goto err;
+               }
+               /* Increment reference count of peer key */
+               CRYPTO_add(&(eph_key->references),1 ,CRYPTO_LOCK_EVP_PKEY);
+       }       
+               
        param = get_encryption_params(gkt->key_agreement_info->cipher);
        gost_init(&ctx,param->sblock);  
        OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8);
@@ -368,7 +262,7 @@ int decrypt_rfc4490_shared_key_2001(EVP_PKEY *priv,GOST_KEY_TRANSPORT *gkt,
        memcpy(wrappedKey+40,gkt->key_info->imit->data,4);      
        VKO_compute_key(sharedKey,32,EC_KEY_get0_public_key(EVP_PKEY_get0(eph_key)),
                EVP_PKEY_get0(priv),wrappedKey);
-       if (!keyUnwrapCryptoPro(&ctx,sharedKey,wrappedKey,key_buf))
+       if (!keyUnwrapCryptoPro(&ctx,sharedKey,wrappedKey,key))
                {
                GOSTerr(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT,
                        GOST_R_ERROR_COMPUTING_SHARED_KEY);
@@ -376,35 +270,8 @@ int decrypt_rfc4490_shared_key_2001(EVP_PKEY *priv,GOST_KEY_TRANSPORT *gkt,
                }       
                                
        EVP_PKEY_free(eph_key);
-       return 32;
-       err:
-       EVP_PKEY_free(eph_key);
-       return -1;
-       }
-/*  
- * EVP_PKEY_METHOD callback decrypt  
- * Implementation of GOST2001 key transport, cryptopo variation 
- */
-int pkey_GOST01cp_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);
-       GOST_KEY_TRANSPORT *gkt = NULL;
-       int ret=0;      
-
-       if (!key)
-               {
-               *key_len = 32;
-               return 1;
-               }       
-       gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p,
-               in_len);
-       if (!gkt)
-               {
-               GOSTerr(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
-               return -1;
-               }       
-       ret =   decrypt_rfc4490_shared_key_2001(priv,gkt,key,*key_len);
        GOST_KEY_TRANSPORT_free(gkt);
+       ret=1;
+err:   
        return ret;
        }
index a7cdb2a26d230c2031119e648eb35fda3a3c1972..69c4a2271e327b436896c4c1371ba9e1096ca698 100644 (file)
 #include "gost_keywrap.h"
 #include "gost_lcl.h"
 /* Common functions for both 94 and 2001 key exchange schemes */
-int decrypt_cryptocom_key(unsigned char *sess_key,int max_key_len,
-       const unsigned char *crypted_key,int crypted_key_len, gost_ctx *ctx)
-       {
-       int i;
-       int j;
-       int blocks = crypted_key_len >>3;
-       unsigned char gamma[8];
-       if (max_key_len <crypted_key_len)
-               {
-               GOSTerr(GOST_F_DECRYPT_CRYPTOCOM_KEY,GOST_R_NOT_ENOUGH_SPACE_FOR_KEY);
-               return 0;
-               }       
-       if ((crypted_key_len & 7) !=0) 
-               {
-               GOSTerr(GOST_F_DECRYPT_CRYPTOCOM_KEY,GOST_R_INVALID_ENCRYPTED_KEY_SIZE);
-               return 0;
-               }       
-       for (i=blocks-1;i>0;i--) 
-               {
-               gostcrypt(ctx,crypted_key+(i-1)*8,gamma);
-               for(j=0;j<8;j++) 
-                       {
-                       sess_key[i*8+j]=gamma[j]^crypted_key[i*8+j];
-                       }
-               }       
-       gostcrypt(ctx,sess_key+crypted_key_len-8,gamma);        
-       for(j=0;j<8;j++) 
-               {
-               sess_key[j]=gamma[j]^crypted_key[j];
-               }
-       return 1;
-       }
-int encrypt_cryptocom_key(const unsigned char *sess_key,int key_len,
-       unsigned char *crypted_key, gost_ctx *ctx)
-       {
-       int i;
-       int j;
-       unsigned char gamma[8];
-       memcpy(gamma,sess_key+key_len-8,8);
-       for (i=0;i<key_len;i+=8)
-               {
-               gostcrypt(ctx,gamma,gamma);
-               for (j=0;j<8;j++)
-                       gamma[j]=crypted_key[i+j]=sess_key[i+j]^gamma[j];
-               }
-       return 1;
-       }
 /* Implementation of the Diffi-Hellman key agreement scheme based on
  * GOST-94 keys */
 
@@ -87,59 +40,24 @@ static int compute_pair_key_le(unsigned char *pair_key,BIGNUM *pub_key,DH *dh)
                }
        return key_size;        
        }       
-/*
- * Computes 256 bit key exchange key for CryptoCom variation of GOST 94
- * algorithm
- */
-static int make_gost_shared_key(DH *dh,EVP_PKEY *pubk,unsigned char *shared_key) 
-       {
-       unsigned char dh_key [128];
-       int i;
-       /* Compute key */
-       memset(dh_key,0,128);
-       if (!compute_pair_key_le(dh_key,((DSA *)EVP_PKEY_get0(pubk))->pub_key,dh)) return 0;    
-       /* Fold it down to 256 bit */
-       /* According to GOST  either 2^1020<p<2^1024 or 
-        * 2^509<p<2^512, so DH_size can be exactly 128 or exactly 64 only
-        */
-       
-       if (DH_size(dh)==128)
-               {
-               for (i=0;i<64;i++)
-                       {
-                       dh_key[i]^=dh_key[64+i];
-                       }
-               }
-       for (i=0;i<32;i++)
-               {
-               shared_key[i]=dh_key[i]^dh_key[32+i];
-               }
-       return 1;
-       }
 
-static DH *make_ephemeral_key(EVP_PKEY *pubk,BIGNUM *ephemeral_key)
-       {
-       DH *dh = DH_new();
-       dh->g = BN_dup(pubk->pkey.dsa->g);
-       dh->p = BN_dup(pubk->pkey.dsa->p);
-       dh->priv_key = BN_dup(ephemeral_key);
-       /* Generate ephemeral key pair */
-       if (!DH_generate_key(dh))
-               {
-               DH_free(dh);
-               return NULL;
-               }       
-       return dh;
-       }       
 /*
  * Computes 256 bit Key exchange key as specified in RFC 4357 
  */
-static int make_cp_exchange_key(DH *dh,EVP_PKEY *pubk, unsigned char *shared_key)
+static int make_cp_exchange_key(BIGNUM *priv_key,EVP_PKEY *pubk, unsigned char *shared_key)
        {
        unsigned char dh_key [128];
+       int ret;
        gost_hash_ctx hash_ctx;
+       DH *dh = DH_new();
+       
        memset(dh_key,0,128);
-       if (!compute_pair_key_le(dh_key,((DSA *)(EVP_PKEY_get0(pubk)))->pub_key,dh)) return 0;
+       dh->g = BN_dup(pubk->pkey.dsa->g);
+       dh->p = BN_dup(pubk->pkey.dsa->p);
+       dh->priv_key = BN_dup(priv_key);
+       ret=compute_pair_key_le(dh_key,((DSA *)(EVP_PKEY_get0(pubk)))->pub_key,dh) ;
+       DH_free(dh);
+       if (!ret)       return 0;
        init_gost_hash_ctx(&hash_ctx,&GostR3411_94_CryptoProParamSet);
        start_hash(&hash_ctx);
        hash_block(&hash_ctx,dh_key,128);
@@ -148,38 +66,87 @@ static int make_cp_exchange_key(DH *dh,EVP_PKEY *pubk, unsigned char *shared_key
        return 1;
        }
 
+/* EVP_PKEY_METHOD callback derive. Implements VKO R 34.10-94 */
+
+int pkey_gost94_derive(EVP_PKEY_CTX *ctx,unsigned char *key,size_t *keylen)
+       {
+               EVP_PKEY *pubk = EVP_PKEY_CTX_get0_peerkey(ctx);
+               EVP_PKEY *mykey = EVP_PKEY_CTX_get0_pkey(ctx);
+               *keylen = 32;
+               if (key == NULL) return 1;
+
+               return make_cp_exchange_key(gost_get0_priv_key(mykey), pubk, key);
+       }
+
 /* EVP_PKEY_METHOD callback encrypt for
  * GOST R 34.10-94 cryptopro modification
  */
 
+
 int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len ) 
        {
        GOST_KEY_TRANSPORT *gkt=NULL;
-       DH *dh = NULL;
        unsigned char shared_key[32], ukm[8],crypted_key[44];
        const struct gost_cipher_info *param=get_encryption_params(NULL);
        EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx);
        struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
        int size=-1;
        gost_ctx cctx;
+       int key_is_ephemeral=1;
+       EVP_PKEY *mykey = EVP_PKEY_CTX_get0_peerkey(ctx);
 
-       if (!(data->eph_seckey))
+       /* Do not use vizir cipher parameters with cryptopro */
+       if (!get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS) && param ==  gost_cipher_list)
                {
-               GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
-                       GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT);
-               return -1;
+               param= gost_cipher_list+1;
                }       
 
-       dh = make_ephemeral_key(pubk,gost_get_priv_key(data->eph_seckey));
-       gost_init(&cctx,param->sblock); 
-       make_cp_exchange_key(dh,pubk,shared_key);
-       if (RAND_bytes(ukm,8)<=0)
+       if (mykey) 
                {
-               GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
-                       GOST_R_RANDOM_GENERATOR_FAILURE);
-               return -1;
+               /* If key already set, it is not ephemeral */
+               key_is_ephemeral=0;
+               if (!gost_get0_priv_key(mykey)) 
+                       {
+                       GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
+                       GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR);
+                       goto err;
+                       }       
+               } 
+       else 
+               {
+               /* Otherwise generate ephemeral key */
+               key_is_ephemeral = 1;
+               if (out) 
+                       {
+                       mykey = EVP_PKEY_new();
+                       EVP_PKEY_assign(mykey, EVP_PKEY_base_id(pubk),DSA_new());
+                       EVP_PKEY_copy_parameters(mykey,pubk);
+                       if (!gost_sign_keygen(EVP_PKEY_get0(mykey))) 
+                               {
+                               goto err;
+                               }       
+                       }
                }       
-       keyWrapCryptoPro(&cctx,shared_key,ukm,key,crypted_key);
+       if (out)
+               make_cp_exchange_key(gost_get0_priv_key(mykey),pubk,shared_key);
+       if (data->shared_ukm) 
+               {
+               memcpy(ukm,data->shared_ukm,8);
+               }
+       else if (out) 
+               {       
+               if (RAND_bytes(ukm,8)<=0)
+                       {
+                       GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
+                                       GOST_R_RANDOM_GENERATOR_FAILURE);
+                       goto err;
+                       }       
+               }
+               
+       if (out) {
+               gost_init(&cctx,param->sblock);
+               keyWrapCryptoPro(&cctx,shared_key,ukm,key,crypted_key);
+       }       
        gkt = GOST_KEY_TRANSPORT_new();
        if (!gkt)
                {
@@ -198,117 +165,40 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
                {
                goto memerr;
                }
-       if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,data->eph_seckey))
+       if (key_is_ephemeral) { 
+       if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,out?mykey:pubk))
                {
                GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
                goto err;
-               }       
+               }
+               if (out) EVP_PKEY_free(mykey);
+       }       
        ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
        gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid);
-       *outlen = i2d_GOST_KEY_TRANSPORT(gkt,&out);
+       *outlen = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL);
        if (!size)
                {
                GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO);
                size=-1;
                }
        GOST_KEY_TRANSPORT_free(gkt);
-       DH_free(dh);
        return 1;       
        memerr:
+               if (key_is_ephemeral) {
+                       EVP_PKEY_free(mykey);
+               }       
        GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
                GOST_R_MALLOC_FAILURE);
        err:            
        GOST_KEY_TRANSPORT_free(gkt);
-       DH_free(dh);
        return -1;
        }
 
-/* EVP_PKEY_METHOD callback encrypt for
- * GOST R 34.10-94 cryptocom modification
- */
-
-int pkey_GOST94cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,  const unsigned char *   key,size_t key_len) 
-       {
-       EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx);
-       struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
-       /* create DH structure filling parameters from passed pub_key */
-       DH *dh = NULL;
-       GOST_KEY_TRANSPORT *gkt = NULL;
-       const struct gost_cipher_info *cipher_info;
-       gost_ctx cctx;
-       EVP_PKEY *newkey=NULL;
-       unsigned char shared_key[32],encrypted_key[32],hmac[4],
-               iv[8]={0,0,0,0,0,0,0,0};
-
-       if (! data->eph_seckey)
-               {
-               GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
-                       GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT);
-               return -1;
-               }       
-       dh = make_ephemeral_key(pubk,gost_get_priv_key(data->eph_seckey));
-       if (!dh) goto err;
-       /* compute shared key */
-       if (!make_gost_shared_key(dh,pubk,shared_key)) 
-               {
-               GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_COMPUTING_SHARED_KEY);
-               goto err;
-               }       
-       /* encrypt session key */
-       cipher_info = get_encryption_params(NULL);
-       gost_init(&cctx, cipher_info->sblock);
-       gost_key(&cctx,shared_key);
-       encrypt_cryptocom_key(key,key_len,encrypted_key,&cctx);
-       /* compute hmac of session key */
-       if (!gost_mac(&cctx,32,key,32,hmac)) 
-               {
-               DH_free(dh);
-               GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_COMPUTING_MAC);
-               return -1;
-               }
-       gkt = GOST_KEY_TRANSPORT_new();
-       if (!gkt) 
-               {
-               DH_free(dh);
-               GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_NO_MEMORY);
-               return -1;
-               }       
-       /* Store IV which is always zero in our case */
-       if (!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv,iv,8))
-               {
-               GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_STORING_IV);
-               goto err;
-               }       
-       if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,hmac,4)) 
-               {
-               GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_STORING_MAC);
-               goto err;
-               }       
-       if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,encrypted_key,32))
-               {       
-               GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_STORING_ENCRYPTED_KEY);
-               goto err;
-               }
-       if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,data->eph_seckey))
-               {
-               GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
-               goto err;
-               }       
-       ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
-       gkt->key_agreement_info->cipher = OBJ_nid2obj(cipher_info->nid);
-       *outlen = i2d_GOST_KEY_TRANSPORT(gkt,&out);
-       err:
-       if (gkt) GOST_KEY_TRANSPORT_free(gkt);
-       if (dh) DH_free(dh);
-       if (newkey) EVP_PKEY_free(newkey);
-       return 1;
-       }       
        
 /* EVP_PLEY_METHOD callback decrypt for
  * GOST R 34.10-94 cryptopro modification
  */
 int pkey_GOST94cp_decrypt (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len,const unsigned char *in, size_t in_len) {
-       DH *dh = DH_new();
        const unsigned char *p = in;
        GOST_KEY_TRANSPORT *gkt = NULL;
        unsigned char wrappedKey[44];
@@ -324,18 +214,28 @@ int pkey_GOST94cp_decrypt (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_le
                return 1;
                }       
        
-       dh->g = BN_dup(priv->pkey.dsa->g);
-       dh->p = BN_dup(priv->pkey.dsa->p);
-       dh->priv_key = BN_dup(priv->pkey.dsa->priv_key);
        gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p,
                in_len);
        if (!gkt)
                {
                GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
-               DH_free(dh);
                return 0;
                }       
        eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
+       /* No ephemeral key in the structure. Check peer key in the context
+        */
+       if (!eph_key) {
+               eph_key = EVP_PKEY_CTX_get0_peerkey(ctx);
+               if (! eph_key) {
+                       GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,
+                               GOST_R_NO_PEER_KEY);
+                       goto err;
+               }
+               /* Increment reference count of peer key */
+               CRYPTO_add(&(eph_key->references),1 ,CRYPTO_LOCK_EVP_PKEY);
+       }       
+
+
        param = get_encryption_params(gkt->key_agreement_info->cipher);
        gost_init(&cctx,param->sblock); 
        OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8);
@@ -344,7 +244,7 @@ int pkey_GOST94cp_decrypt (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_le
        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);      
-       make_cp_exchange_key(dh,eph_key,sharedKey);
+       make_cp_exchange_key(gost_get0_priv_key(priv),eph_key,sharedKey);
        if (!keyUnwrapCryptoPro(&cctx,sharedKey,wrappedKey,key))
                {
                GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,
@@ -354,92 +254,10 @@ int pkey_GOST94cp_decrypt (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_le
                                
        EVP_PKEY_free(eph_key);
        GOST_KEY_TRANSPORT_free(gkt);
-       DH_free(dh);
        return 1;
 err:
        EVP_PKEY_free(eph_key);
        GOST_KEY_TRANSPORT_free(gkt);
-       DH_free(dh);
        return -1;
        }       
 
-/* EVP_PKEY_METHOD callback decrypt for
- * GOST R 34.10-94 cryptocom modification
- */
-
-int pkey_GOST94cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_len, const unsigned char *in, size_t in_len)
-       {
-       /* Form DH params from compute shared key */
-       GOST_KEY_TRANSPORT *gkt = NULL;
-       const unsigned char *p=in;
-       unsigned char shared_key[32];
-       unsigned char hmac[4],hmac_comp[4];
-       unsigned char iv[8];
-       int i;
-       const struct gost_cipher_info *cipher_info;
-       gost_ctx ctx;
-       DH *dh = DH_new();
-       EVP_PKEY *eph_key;
-       EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx);
-       
-       if (!key)
-               {
-               *key_len = 32;
-               return 1;
-               }
-       /* Construct DH structure from the our GOST private key */
-       dh->g = BN_dup(priv->pkey.dsa->g);
-       dh->p = BN_dup(priv->pkey.dsa->p);
-       dh->priv_key = BN_dup(priv->pkey.dsa->priv_key);
-       /* Parse passed octet string and find out public key, iv and HMAC*/
-       gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p,
-               in_len);
-       if (!gkt)
-               {
-               GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
-               DH_free(dh);
-               return 0;
-               }       
-       eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
-       /* Initialization vector is really ignored here */
-       OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8);
-       memcpy(iv,gkt->key_agreement_info->eph_iv->data,8);
-       /* HMAC should be computed and checked */
-       OPENSSL_assert(gkt->key_info->imit->length==4);
-       memcpy(hmac,gkt->key_info->imit->data,4);       
-       /* Compute shared key */
-       i=make_gost_shared_key(dh,eph_key,shared_key);
-       EVP_PKEY_free(eph_key);
-       DH_free(dh);
-       if (!i) 
-               {
-               GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_ERROR_COMPUTING_SHARED_KEY);
-               GOST_KEY_TRANSPORT_free(gkt);
-               return 0;
-               }
-       /* Decrypt session key */
-       cipher_info = get_encryption_params(gkt->key_agreement_info->cipher);
-       gost_init(&ctx, cipher_info->sblock);
-       gost_key(&ctx,shared_key);
-       
-       if (!decrypt_cryptocom_key(key,*key_len,gkt->key_info->encrypted_key->data, 
-                       gkt->key_info->encrypted_key->length, &ctx)) 
-               {
-               GOST_KEY_TRANSPORT_free(gkt);
-               return 0;
-               }
-       GOST_KEY_TRANSPORT_free(gkt);
-       /* check HMAC of session key*/
-       if (!gost_mac(&ctx,32,key,32,hmac_comp))
-               {
-               GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_ERROR_COMPUTING_MAC);
-               return 0;
-               }
-       /* HMAC of session key is not correct */
-    if (memcmp(hmac,hmac_comp,4)!=0)
-               {
-               GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH);
-               return 0;
-               }       
-       return 1; 
-       }       
index 39a175f52cf057bd1f2debed2b2d863443520266..617b03e70af536c0bc6c8fe5a40815d5a0339d9c 100644 (file)
@@ -48,14 +48,6 @@ static ASN1_STRING  *encode_gost_algor_params(const EVP_PKEY *key)
                }       
        switch (EVP_PKEY_base_id(key)) 
                {
-               case NID_id_GostR3410_2001_cc:
-                       pkey_param_nid = NID_id_GostR3410_2001_ParamSet_cc;
-                       cipher_param_nid = NID_id_Gost28147_89_cc;
-                       break;
-               case NID_id_GostR3410_94_cc:
-                       pkey_param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
-                       cipher_param_nid = NID_id_Gost28147_89_cc;
-                       break;
                case NID_id_GostR3410_2001:
                        pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
                        cipher_param_nid = get_encryption_params(NULL)->nid;
@@ -128,7 +120,6 @@ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
        switch (pkey_nid) 
                {
                case NID_id_GostR3410_94:
-               case NID_id_GostR3410_94_cc:
                {
                DSA *dsa= EVP_PKEY_get0(pkey);
                if (!dsa) 
@@ -140,7 +131,6 @@ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
                break;
                }
                case NID_id_GostR3410_2001:
-               case NID_id_GostR3410_2001_cc:
                {
                EC_KEY *ec = EVP_PKEY_get0(pkey);
                if (!ec) 
@@ -160,7 +150,6 @@ static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv)
        switch (EVP_PKEY_base_id(pkey)) 
                {
                case NID_id_GostR3410_94:
-               case NID_id_GostR3410_94_cc:
                {
                DSA *dsa = EVP_PKEY_get0(pkey);
                if (!dsa) 
@@ -174,7 +163,6 @@ static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv)
                break;
                }       
                case NID_id_GostR3410_2001:
-               case NID_id_GostR3410_2001_cc:
                {
                EC_KEY *ec = EVP_PKEY_get0(pkey);
                if (!ec) 
@@ -190,12 +178,11 @@ static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv)
                }
        return 1;               
        }
-BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey) 
+BIGNUM* gost_get0_priv_key(const EVP_PKEY *pkey) 
        {
        switch (EVP_PKEY_base_id(pkey)) 
                {
                case NID_id_GostR3410_94:
-               case NID_id_GostR3410_94_cc:
                {
                DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey);
                if (!dsa) 
@@ -203,11 +190,10 @@ BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey)
                        return NULL;
                        }       
                if (!dsa->priv_key) return NULL;
-               return BN_dup(dsa->priv_key);
+               return dsa->priv_key;
                break;
                }       
                case NID_id_GostR3410_2001:
-               case NID_id_GostR3410_2001_cc:
                {
                EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
                const BIGNUM* priv;
@@ -216,7 +202,7 @@ BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey)
                        return NULL;
                        }       
                if (!(priv=EC_KEY_get0_private_key(ec))) return NULL;
-               return BN_dup(priv);
+               return (BIGNUM *)priv;
                break;
                }
                }
@@ -322,7 +308,10 @@ static int priv_decode_gost( EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf)
        else
                {
                priv_key=d2i_ASN1_INTEGER(NULL,&p,priv_len);
-               if (!priv_key || !(pk_num =  ASN1_INTEGER_to_BN(priv_key, NULL))) 
+               if (!priv_key) return 0;
+               ret= ((pk_num =  ASN1_INTEGER_to_BN(priv_key, NULL))!=NULL) ;
+               ASN1_INTEGER_free(priv_key);
+               if (!ret)
                        {
                        GOSTerr(GOST_F_PRIV_DECODE_GOST_94,
                                EVP_R_DECODE_ERROR);
@@ -342,16 +331,13 @@ static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
        ASN1_STRING *params = encode_gost_algor_params(pk);
        unsigned char *priv_buf = NULL;
        int priv_len;
-       BIGNUM *key;
 
        ASN1_INTEGER *asn1key=NULL;
        if (!params) 
                {
                return 0;
                }
-       key = gost_get_priv_key(pk);
-       asn1key = BN_to_ASN1_INTEGER(key,NULL);
-       BN_free(key);
+       asn1key = BN_to_ASN1_INTEGER(gost_get0_priv_key(pk),NULL);
        priv_len = i2d_ASN1_INTEGER(asn1key,&priv_buf);
        ASN1_INTEGER_free(asn1key);
        return PKCS8_pkey_set0(p8,algobj,0,V_ASN1_SEQUENCE,params,
@@ -363,10 +349,9 @@ static int priv_print_gost (BIO *out,const EVP_PKEY *pkey, int indent,
        {
        BIGNUM *key;
        if (!BIO_indent(out,indent,128)) return 0;
-       key = gost_get_priv_key(pkey);
+       key = gost_get0_priv_key(pkey);
        if (!key) return 0;
        BN_print(out,key);
-       BN_free(key);
        return 1;
        }
 
@@ -438,7 +423,7 @@ static int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
                eto = EC_KEY_new();
                EVP_PKEY_assign(to,EVP_PKEY_base_id(from),eto);
                }       
-       EC_KEY_set_group(eto,EC_GROUP_dup(EC_KEY_get0_group(efrom)));
+       EC_KEY_set_group(eto,EC_KEY_get0_group(efrom));
        if (EC_KEY_get0_private_key(eto)) 
                {
                gost2001_compute_public(eto);
@@ -543,6 +528,7 @@ static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub)
        EC_POINT *pub_key;
        BIGNUM *X,*Y;
        ASN1_OCTET_STRING *octet= NULL;
+       int len;
        const EC_GROUP *group;
 
        if (!X509_PUBKEY_get0_param(&palgobj,&pubkey_buf,&pub_len,
@@ -561,16 +547,11 @@ static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub)
                {
                databuf[j]=octet->data[i];
                }
-       if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc) 
-               {
-               X= getbnfrombuf(databuf,octet->length/2);
-               Y= getbnfrombuf(databuf+(octet->length/2),octet->length/2);
-               }
-       else 
-               {
-               Y= getbnfrombuf(databuf,octet->length/2);
-               X= getbnfrombuf(databuf+(octet->length/2),octet->length/2);
-               }
+       len=octet->length/2;
+       ASN1_OCTET_STRING_free(octet);  
+       
+       Y= getbnfrombuf(databuf,len);
+       X= getbnfrombuf(databuf+len,len);
        OPENSSL_free(databuf);
        pub_key = EC_POINT_new(group);
        if (!EC_POINT_set_affine_coordinates_GFp(group
@@ -578,6 +559,9 @@ static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub)
                {
                GOSTerr(GOST_F_PUB_DECODE_GOST01,
                        ERR_R_EC_LIB);
+               EC_POINT_free(pub_key);
+               BN_free(X);
+               BN_free(Y);
                return 0;
                }       
        BN_free(X);
@@ -586,9 +570,10 @@ static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub)
                {
                GOSTerr(GOST_F_PUB_DECODE_GOST01,
                        ERR_R_EC_LIB);
+               EC_POINT_free(pub_key);
                return 0;
                }       
-       /*EC_POINT_free(pub_key);*/
+       EC_POINT_free(pub_key);
        return 1;
 
        }
@@ -629,16 +614,10 @@ static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
        BN_free(order);
        databuf = OPENSSL_malloc(data_len);
        memset(databuf,0,data_len);
-       if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc) 
-               {
-               store_bignum(X,databuf,data_len/2);
-               store_bignum(Y,databuf+data_len/2,data_len/2);
-               }
-       else 
-               {
-               store_bignum(X,databuf+data_len/2,data_len/2);
-               store_bignum(Y,databuf,data_len/2);
-               }
+       
+       store_bignum(X,databuf+data_len/2,data_len/2);
+       store_bignum(Y,databuf,data_len/2);
+
        BN_free(X);
        BN_free(Y);
        octet = ASN1_OCTET_STRING_new();
@@ -732,7 +711,6 @@ int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pems
        if (!*ameth) return 0;
        switch (nid) 
                {
-               case NID_id_GostR3410_94_cc:
                case NID_id_GostR3410_94:
                        EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost94);
                        EVP_PKEY_asn1_set_private (*ameth, 
@@ -749,7 +727,6 @@ int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pems
        
                        EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
                        break;
-               case NID_id_GostR3410_2001_cc:
                case NID_id_GostR3410_2001:
                        EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost01);
                        EVP_PKEY_asn1_set_private (*ameth, 
index 9f1bf9adbe9743014161f12b99aa4aa369e647d9..a6736836c435f43380c8fc954ba0d7c6e8c42c91 100644 (file)
@@ -15,11 +15,6 @@ static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
        const unsigned char *iv, int enc);
 static int     gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
        const unsigned char *iv, int enc);
-#ifdef USE_SSL
-/* Specialized init functions which set specific parameters */                 
-static int     gost_cipher_init_vizir(EVP_CIPHER_CTX *ctx, const unsigned char *key,
-       const unsigned char *iv, int enc);
-#endif
 /* Handles block of data in CFB mode */                        
 static int     gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
        const unsigned char *in, unsigned int inl);
@@ -70,30 +65,8 @@ EVP_CIPHER cipher_gost_cpacnt =
        NULL,
        };
 
-#ifdef USE_SSL
-static EVP_CIPHER cipher_gost_vizircfb = 
-       {
-       NID_undef,
-       1,/*block_size*/
-       32,/*key_size*/
-       8,/*iv_len - Ã±Ã¨Ã­ÃµÃ°Ã®Ã¯Ã®Ã±Ã»Ã«ÃªÃ */
-       EVP_CIPH_CFB_MODE| EVP_CIPH_NO_PADDING |
-       EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
-       gost_cipher_init_vizir,
-       gost_cipher_do_cfb,
-       gost_cipher_cleanup,
-       sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */
-       gost89_set_asn1_parameters,
-       gost89_get_asn1_parameters,
-       gost_cipher_ctl,
-       NULL,
-       };
-#endif
 /* Implementation of GOST 28147-89 in MAC (imitovstavka) mode */
 /* Init functions which set specific parameters */
-#ifdef USE_SSL
-static int gost_imit_init_vizir(EVP_MD_CTX *ctx);
-#endif
 static int gost_imit_init_cpa(EVP_MD_CTX *ctx);
 /* process block of data */
 static int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count);
@@ -105,27 +78,6 @@ static int gost_imit_cleanup(EVP_MD_CTX *ctx);
 /* Control function, knows how to set MAC key.*/
 static int gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr);
 
-#ifdef USE_SSL
-
-EVP_MD imit_gost_vizir =
-       {
-       NID_undef,
-       NID_undef,
-       4,
-       EVP_MD_FLAG_NEEDS_KEY,
-       gost_imit_init_vizir,
-       gost_imit_update,
-       gost_imit_final,
-       gost_imit_copy,
-       gost_imit_cleanup,
-       gost_imit_ctrl,
-       NULL,
-       NULL,
-       {0,0,0,0,0},
-       8,
-       sizeof(struct ossl_gost_imit_ctx) 
-       };
-#endif
 EVP_MD imit_gost_cpa =
        {
        NID_id_Gost28147_89_MAC,
@@ -241,24 +193,6 @@ static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
        memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
        return 1;
        }
-#ifdef USE_SSL
-/* Initializes EVP_CIPHER_CTX with fixed cryptopro A paramset */
-
-/* Initializes EVP_CIPHER_CTX with fixed vizir paramset */
-static int gost_cipher_init_vizir(EVP_CIPHER_CTX *ctx, const unsigned char *key,
-       const unsigned char *iv, int enc)
-       {
-       struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
-       gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet);
-       c->key_meshing=0;
-       c->count=0;
-       gost_key(&(c->cctx),key);
-
-       if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
-       memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
-       return 1;
-       }       
-#endif  /* def USE_SSL */
 
 /* Initializes EVP_CIPHER_CTX with default values */
 int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
@@ -541,16 +475,6 @@ int  gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params)
        return 1;
        }
 
-#ifdef USE_SSL
-
-int gost_imit_init_vizir(EVP_MD_CTX *ctx)
-       {
-       struct ossl_gost_imit_ctx *c = ctx->md_data;
-       memset(c,0,sizeof(struct ossl_gost_imit_ctx));
-       gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet);
-       return 1;
-       }
-#endif
 
 int gost_imit_init_cpa(EVP_MD_CTX *ctx)
        {
@@ -612,14 +536,15 @@ int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count)
        if (bytes>0)
                {
                memcpy(c->partial_block,p,bytes);
-               c->bytes_left=bytes;
                }       
+       c->bytes_left=bytes;
        return 1;
        }
 
 int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md)
        {
        struct ossl_gost_imit_ctx *c = ctx->md_data;
+       if (!c->key_set) return 0;
        if (c->bytes_left)
                {
                int i;
@@ -630,7 +555,6 @@ int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md)
                mac_block_mesh(c,c->partial_block);
                }
        get_mac(c->buffer,32,md);
-       if (!c->key_set) return 0;
        return 1;
        }
 
index d94089b9cbaf9b07b4ade54705bcb85429c044d5..85c2a0f2a4409490a1f58862376cc3b91713caeb 100644 (file)
@@ -34,6 +34,17 @@ const ENGINE_CMD_DEFN gost_cmds[]=
 {0,NULL,NULL,0}
        };
 
+void gost_param_free() 
+{
+       int i;
+       for (i=0;i<=GOST_PARAM_MAX;i++) 
+               if (gost_params[i]!=NULL) 
+                       {
+                       OPENSSL_free(gost_params[i]);
+                       gost_params[i]=NULL;
+                       }
+               
+}
 
 int gost_control_func(ENGINE *e,int cmd,long i, void *p, void (*f)(void))
        {
@@ -55,6 +66,7 @@ const char *get_gost_engine_param(int param)
        tmp = getenv(gost_envnames[param]);
        if (tmp) 
                {
+               if (gost_params[param]) OPENSSL_free(gost_params[param]);
                gost_params[param] = BUF_strdup(tmp);
                return gost_params[param];
                }       
@@ -68,7 +80,7 @@ int gost_set_default_param(int param, const char *value)
        tmp = getenv(gost_envnames[param]);
        /* if there is value in the environment, use it, else -passed string * */
        if (!tmp) tmp=value;
-       if (gost_params[param]) free(gost_params[param]);
+       if (gost_params[param]) OPENSSL_free(gost_params[param]);
        gost_params[param] = BUF_strdup(tmp);
 
        return 1;
index daa397f6cc1e9d9426b50eed6eeecba34993e7c4..6acc5088327f5f607d1d92017bdccadd86c7aa92 100644 (file)
@@ -37,15 +37,15 @@ static int gost_digest_nids[] =
        {NID_id_GostR3411_94,NID_id_Gost28147_89_MAC, 0};
 
 static int gost_pkey_meth_nids[] = 
-       {NID_id_GostR3410_94_cc, NID_id_GostR3410_94, NID_id_GostR3410_2001_cc,
+       {NID_id_GostR3410_94,
         NID_id_GostR3410_2001, NID_id_Gost28147_89_MAC, 0};
 
-static EVP_PKEY_METHOD *pmeth_GostR3410_94_cc = NULL, *pmeth_GostR3410_94 = NULL,
-       *pmeth_GostR3410_2001_cc = NULL, *pmeth_GostR3410_2001 = NULL,
+static EVP_PKEY_METHOD *pmeth_GostR3410_94 = NULL,
+        *pmeth_GostR3410_2001 = NULL,
        *pmeth_Gost28147_MAC = NULL;
 
-static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94_cc = NULL, *ameth_GostR3410_94 = NULL,
-       *ameth_GostR3410_2001_cc = NULL, *ameth_GostR3410_2001 = NULL,
+static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94 = NULL,
+       *ameth_GostR3410_2001 = NULL,
        *ameth_Gost28147_MAC = NULL;
 
 
@@ -61,6 +61,7 @@ static int gost_engine_finish(ENGINE *e)
 
 static int gost_engine_destroy(ENGINE *e)
        { 
+       gost_param_free();
        return 1;
        }
 
@@ -117,16 +118,12 @@ static int bind_gost (ENGINE *e,const char *id)
                goto end;
                }
 
-       if (!register_ameth_gost(NID_id_GostR3410_94_cc, &ameth_GostR3410_94_cc, "GOST94CC", "GOST R 34.10-94, Cryptocom LTD implementation")) goto end;
        if (!register_ameth_gost(NID_id_GostR3410_94, &ameth_GostR3410_94, "GOST94", "GOST R 34.10-94")) goto end;
-       if (!register_ameth_gost(NID_id_GostR3410_2001_cc, &ameth_GostR3410_2001_cc, "GOST2001CC", "GOST R 34.10-2001, Cryptocom LTD implementation")) goto end;
        if (!register_ameth_gost(NID_id_GostR3410_2001, &ameth_GostR3410_2001, "GOST2001", "GOST R 34.10-2001")) goto end;
        if (!register_ameth_gost(NID_id_Gost28147_89_MAC, &ameth_Gost28147_MAC,
                "GOST-MAC", "GOST 28147-89 MAC")) goto end;
 
-       if (!register_pmeth_gost(NID_id_GostR3410_94_cc, &pmeth_GostR3410_94_cc, 0)) goto end;
        if (!register_pmeth_gost(NID_id_GostR3410_94, &pmeth_GostR3410_94, 0)) goto end;
-       if (!register_pmeth_gost(NID_id_GostR3410_2001_cc, &pmeth_GostR3410_2001_cc, 0)) goto end;
        if (!register_pmeth_gost(NID_id_GostR3410_2001, &pmeth_GostR3410_2001, 0)) goto end;
        if (!register_pmeth_gost(NID_id_Gost28147_89_MAC, &pmeth_Gost28147_MAC, 0))
                goto end;
@@ -212,14 +209,12 @@ static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
        if (!pmeth) 
                {
                *nids = gost_pkey_meth_nids;
-               return 5;
+               return 3;
                }
 
        switch (nid) 
                {
-               case NID_id_GostR3410_94_cc: *pmeth = pmeth_GostR3410_94_cc; return 1;
                case NID_id_GostR3410_94: *pmeth = pmeth_GostR3410_94; return 1;
-               case NID_id_GostR3410_2001_cc: *pmeth = pmeth_GostR3410_2001_cc; return 1;
                case NID_id_GostR3410_2001: *pmeth = pmeth_GostR3410_2001; return 1;
                case NID_id_Gost28147_89_MAC: *pmeth = pmeth_Gost28147_MAC; return 1;
                default:;
@@ -235,13 +230,11 @@ static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
        if (!ameth) 
                {
                *nids = gost_pkey_meth_nids;
-               return 5;
+               return 3;
                }
        switch (nid) 
                {
-               case NID_id_GostR3410_94_cc: *ameth = ameth_GostR3410_94_cc; return 1;
                case NID_id_GostR3410_94: *ameth = ameth_GostR3410_94; return 1;
-               case NID_id_GostR3410_2001_cc: *ameth = ameth_GostR3410_2001_cc; return 1;
                case NID_id_GostR3410_2001: *ameth = ameth_GostR3410_2001; return 1;
                case NID_id_Gost28147_89_MAC: *ameth = ameth_Gost28147_MAC; return 1;
        
index 8026a2de9ef3b10b3083b33648cd13ead1e598dc..6a67f05123fc56e5cd344ff28af5f79fbbb84f11 100644 (file)
@@ -28,6 +28,7 @@
        int gost_control_func(ENGINE *e,int cmd, long i, void *p, void (*f)(void));
        const char *get_gost_engine_param(int param);   
        int gost_set_default_param(int param, const char *value); 
+       void gost_param_free(void);
 
 /* method registration */
 
@@ -45,8 +46,8 @@
 /* Pmeth internal representation */
        struct gost_pmeth_data {
            int sign_param_nid; /* Should be set whenever parameters are filled */
-               EVP_PKEY *eph_seckey;
                EVP_MD *md;
+               unsigned char *shared_ukm;
        };
 
        struct gost_mac_pmeth_data {
@@ -146,37 +147,22 @@ const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj);
 /* Implementation of GOST 28147-89 cipher in CFB and CNT modes */
 extern EVP_CIPHER cipher_gost;
 extern EVP_CIPHER cipher_gost_cpacnt;
-#ifdef USE_SSL
-#define EVP_MD_FLAG_NEEDS_KEY 0x20
-#define EVP_MD_CTRL_GET_TLS_MAC_KEY_LENGTH (EVP_MD_CTRL_ALG_CTRL+1)
-#define EVP_MD_CTRL_SET_KEY (EVP_MD_CTRL_ALG_CTRL+2)
-/* Ciphers and MACs specific for GOST TLS draft */
-extern EVP_CIPHER cipher_gost_vizircfb;
-extern EVP_CIPHER cipher_gost_cpacnt;
-extern EVP_MD imit_gost_vizir;
-extern EVP_MD imit_gost_cpa;
-#endif
 #define EVP_MD_CTRL_KEY_LEN (EVP_MD_CTRL_ALG_CTRL+3)
 #define EVP_MD_CTRL_SET_KEY (EVP_MD_CTRL_ALG_CTRL+4)
 /* EVP_PKEY_METHOD key encryption callbacks */
 /* From gost94_keyx.c */
 int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len );
-int pkey_GOST94cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,  const unsigned char *   key,size_t key_len);
 
 int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* in, size_t in_len );
-int pkey_GOST94cc_decrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,  const unsigned char *   in,size_t in_len);
 /* From gost2001_keyx.c */
 int pkey_GOST01cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len );
-int pkey_GOST01cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,  const unsigned char *   key,size_t key_len);
 
 int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* in, size_t in_len );
-int pkey_GOST01cc_decrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *   in,size_t in_len);
-
-/* Internal functions to make error processing happy */
-int decrypt_cryptocom_key(unsigned char *sess_key,int max_key_len,
-               const unsigned char *crypted_key,int crypted_key_len, gost_ctx *ctx);
-int encrypt_cryptocom_key(const unsigned char *sess_key,int key_len,
-               unsigned char *crypted_key, gost_ctx *ctx);
+/* derive functions */
+/* From gost2001_keyx.c */
+int pkey_gost2001_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
+/* From gost94_keyx.c */
+int pkey_gost94_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
 /* Internal functions for signature algorithms */
 int fill_GOST94_params(DSA *dsa,int nid);
 int fill_GOST2001_params(EC_KEY *eckey, int nid);
@@ -201,17 +187,14 @@ BIGNUM *hashsum2bn(const unsigned char *dgst) ;
 int store_bignum(BIGNUM *bn, unsigned char *buf,int len);
 /* Read bignum, which can have few MSB all-zeros    from buffer*/ 
 BIGNUM *getbnfrombuf(const unsigned char *buf,size_t len);
-/* Pack GOST R 34.10 signature according to CryptoCom rules */
-int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen);
 /* Pack GOST R 34.10 signature according to CryptoPro rules */
 int pack_sign_cp(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen); 
-/* Unpack GOST R 34.10 signature according to CryptoCom rules */
-DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen) ;
 /* Unpack GOST R 34.10 signature according to CryptoPro rules */
 DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen) ;
 /* from ameth.c */
 /* Get private key as BIGNUM from both R 34.10-94 and R 34.10-2001  keys*/
-BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey) ;
+/* Returns pointer into EVP_PKEY structure */
+BIGNUM* gost_get0_priv_key(const EVP_PKEY *pkey) ;
 /* Find NID by GOST 94 parameters */
 int gost94_nid_by_params(DSA *p) ;
 
index 294a624d7d5dc67bbe73119df52a51d221f2d85a..417e10887bc29c8a5fdc7c1501fb350c1372c1d3 100644 (file)
@@ -59,9 +59,11 @@ int gost_digest_final(EVP_MD_CTX *ctx,unsigned char *md)
 
 int gost_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) 
        {
-       if (to->md_data && from->md_data) 
-       memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_digest_ctx));
-
+       struct ossl_gost_digest_ctx *md_ctx=to->md_data;
+       if (to->md_data && from->md_data) {
+               memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_digest_ctx));
+               md_ctx->dctx.cipher_ctx=&(md_ctx->cctx);
+       }
        return 1;
        }               
 
index 621c209b428bbd5727e7692f1a392c5e8454bb38..4f96a7508b424dd7c797781bbc178e82f65b0e15 100644 (file)
@@ -40,10 +40,9 @@ static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
        src_data = EVP_PKEY_CTX_get_data(src);
        dst_data = EVP_PKEY_CTX_get_data(dst);
        *dst_data = *src_data;
-       if (src_data -> eph_seckey)
-               {
-               dst_data ->eph_seckey = NULL;
-               }       
+       if (src_data -> shared_ukm) {
+               dst_data->shared_ukm=NULL;
+       }       
        return 1;
        }
 
@@ -51,7 +50,7 @@ static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
 static void pkey_gost_cleanup (EVP_PKEY_CTX *ctx)
        {
        struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
-       if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey);
+       if (data->shared_ukm) OPENSSL_free(data->shared_ukm);
        OPENSSL_free(data);
        }       
 
@@ -81,33 +80,15 @@ static int pkey_gost_ctrl (EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                case EVP_PKEY_CTRL_GOST_PARAMSET:
                        pctx->sign_param_nid = (int)p1;
                        return 1;
+               case EVP_PKEY_CTRL_SET_IV:
+                       pctx->shared_ukm=OPENSSL_malloc((int)p1);
+                       memcpy(pctx->shared_ukm,p2,(int) p1);
+                       return 1;
                        
                }
        return -2;
        }
 
-static int pkey_gost_ctrl94cc_str(EVP_PKEY_CTX *ctx,
-       const char *type, const char *value)
-       {
-       if(!strcmp(type, param_ctrl_string))
-               {
-               return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
-                       NID_id_GostR3410_94_CryptoPro_A_ParamSet,
-                       NULL);
-               }
-       return -2;
-       }
-
-static int pkey_gost_ctrl01cc_str(EVP_PKEY_CTX *ctx,
-       const char *type, const char *value)
-       {
-       if(!strcmp(type, param_ctrl_string))
-               {
-               return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
-                       NID_id_GostR3410_2001_ParamSet_cc,NULL);
-               }
-       return -2;
-       }
 
 static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx,
        const char *type, const char *value)
@@ -257,23 +238,18 @@ static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
        }
 
 /* --------------------- key generation  --------------------------------*/
-/* Generates GOST 94 key and assigns it setting specified type */
-static int pkey_gost94_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type)
+
+
+/* Generates Gost_R3410_94_cp key */
+static int pkey_gost94cp_keygen (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)
                {
-               if (type== NID_id_GostR3410_94_cc)
-                       {
-                       data->sign_param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
-                       }
-               else
-                       {
                        GOSTerr(GOST_F_PKEY_GOST94_KEYGEN,
                                GOST_R_NO_PARAMETERS_SET);
                        return 0;
-                       }       
                }
        dsa = DSA_new();
        if (!fill_GOST94_params(dsa,data->sign_param_nid))
@@ -282,38 +258,20 @@ static int pkey_gost94_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type)
                return 0;
                }
        gost_sign_keygen(dsa);
-       EVP_PKEY_assign(pkey,type,dsa);
+       EVP_PKEY_assign(pkey,NID_id_GostR3410_94,dsa);
        return 1;
        }
 
-/* Generates Gost_R3410_94_cc key */
-static int pkey_gost94cc_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
-       {
-       return pkey_gost94_keygen(ctx,pkey,NID_id_GostR3410_94_cc);
-       }
-
-/* Generates Gost_R3410_94_cp key */
-static int pkey_gost94cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
-       {
-       return pkey_gost94_keygen(ctx,pkey,NID_id_GostR3410_94);
-       }
-
 /* Generates GOST_R3410 2001 key and assigns it using specified type */
-static int pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type)
+static int pkey_gost01cp_keygen (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)
                {
-               if (type == NID_id_GostR3410_2001_cc)
-                       {
-                       data->sign_param_nid = NID_id_GostR3410_2001_ParamSet_cc;
-                       }
-               else {  
                        GOSTerr(GOST_F_PKEY_GOST01_KEYGEN,
                                GOST_R_NO_PARAMETERS_SET);
                        return 0;
-                       }
                }
        ec = EC_KEY_new();
        if (!fill_GOST2001_params(ec,data->sign_param_nid))
@@ -323,41 +281,13 @@ static int pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type)
                }
        gost2001_keygen(ec);
 
-       EVP_PKEY_assign(pkey,type,ec);
+       EVP_PKEY_assign(pkey,NID_id_GostR3410_2001,ec);
        return 1;
        }
 
-/* Generates GOST R3410 2001_cc key */
-static int pkey_gost01cc_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
-       {
-       return pkey_gost01_keygen(ctx,pkey,NID_id_GostR3410_2001_cc);
-       }
 
-/* Generates GOST R3410 2001_cp key */
-static int pkey_gost01cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
-       {
-       return pkey_gost01_keygen(ctx,pkey,NID_id_GostR3410_2001);
-       }
 
 /* ----------- sign callbacks --------------------------------------*/
-static int pkey_gost94_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
-       const unsigned char *tbs, size_t tbs_len)
-       {
-       DSA_SIG *unpacked_sig=NULL;
-       EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
-       if (!siglen) return 0;
-       if (!sig)
-               {
-               *siglen= 64; /* better to check size of pkey->pkey.dsa-q */
-               return 1;
-               }       
-       unpacked_sig = gost_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
-       if (!unpacked_sig)
-               {
-               return 0;
-               }
-       return pack_sign_cc(unpacked_sig,32,sig,siglen);
-       }
 
 static int pkey_gost94_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
        const unsigned char *tbs, size_t tbs_len)
@@ -378,25 +308,6 @@ static int pkey_gost94_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *si
        return pack_sign_cp(unpacked_sig,32,sig,siglen);
        }
 
-static int pkey_gost01_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
-       const unsigned char *tbs, size_t tbs_len)
-       {
-       DSA_SIG *unpacked_sig=NULL;
-       EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
-       if (!siglen) return 0;
-       if (!sig)
-               {
-               *siglen= 64; /* better to check size of curve order*/
-               return 1;
-               }       
-       unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
-       if (!unpacked_sig)
-               {
-               return 0;
-               }
-       return pack_sign_cc(unpacked_sig,32,sig,siglen);
-       }
-
 static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
        const unsigned char *tbs, size_t tbs_len)
        {
@@ -417,17 +328,6 @@ static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *si
        }
 
 /* ------------------- verify callbacks ---------------------------*/
-static int pkey_gost94_cc_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);
-       DSA_SIG *s=unpack_cc_signature(sig,siglen);
-       if (!s) return 0;
-       if (pub_key) ok = gost_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
-       DSA_SIG_free(s);
-       return ok;
-       }
 
 static int pkey_gost94_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
        size_t siglen, const unsigned char *tbs, size_t tbs_len)
@@ -441,24 +341,6 @@ static int pkey_gost94_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
        return ok;
        }
 
-static int pkey_gost01_cc_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);
-       DSA_SIG *s=unpack_cc_signature(sig,siglen);
-#ifdef DEBUG_SIGN      
-       fprintf(stderr,"R=");
-       BN_print_fp(stderr,s->r);
-       fprintf(stderr,"\nS=");
-       BN_print_fp(stderr,s->s);
-       fprintf(stderr,"\n");
-#endif 
-       if (!s) return 0;
-       if (pub_key) ok = gost2001_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
-       DSA_SIG_free(s);
-       return ok;
-       }
 
 static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
        size_t siglen, const unsigned char *tbs, size_t tbs_len)
@@ -483,31 +365,13 @@ static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
 /* Generates ephermeral key */
 static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx)
        {
-       struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
-       EVP_PKEY *eph_key = EVP_PKEY_new();
-       EVP_PKEY *old_key =EVP_PKEY_CTX_get0_pkey(ctx);
-
-       if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey);
-       EVP_PKEY_assign(eph_key,EVP_PKEY_base_id(old_key),NULL);
-       if (!EVP_PKEY_copy_parameters(eph_key,old_key)) return 0;
-       switch (EVP_PKEY_base_id(old_key))
-               {
-               case NID_id_GostR3410_2001:
-               case NID_id_GostR3410_2001_cc:
-                       gost2001_keygen(EVP_PKEY_get0(eph_key));
-                       break;
-               case NID_id_GostR3410_94:
-               case NID_id_GostR3410_94_cc:
-                       gost_sign_keygen(EVP_PKEY_get0(eph_key));
-                       break;
-       
-                       
-               }
-
-       
-       data->eph_seckey=eph_key;
        return 1;
        }
+/* --------------- Derive init ------------------------------------*/
+int pkey_gost_derive_init(EVP_PKEY_CTX *ctx)
+{
+       return 1;
+}
 /* -------- PKEY_METHOD for GOST MAC algorithm --------------------*/
 static int pkey_gost_mac_init(EVP_PKEY_CTX *ctx)
        {
@@ -670,15 +534,6 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
 
        switch (id)
                {
-               case NID_id_GostR3410_94_cc:
-                       EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl94cc_str);
-                       EVP_PKEY_meth_set_keygen(*pmeth,NULL,pkey_gost94cc_keygen);
-                       EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost94_cc_sign);
-                       EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost94_cc_verify);
-                       EVP_PKEY_meth_set_encrypt(*pmeth,
-                               pkey_gost_encrypt_init, pkey_GOST94cc_encrypt);
-                       EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cc_decrypt);
-                       break;
                case NID_id_GostR3410_94:
                        EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl94_str);
                        EVP_PKEY_meth_set_keygen(*pmeth,NULL,pkey_gost94cp_keygen);
@@ -687,21 +542,9 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
                        EVP_PKEY_meth_set_encrypt(*pmeth,
                                pkey_gost_encrypt_init, pkey_GOST94cp_encrypt);
                        EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cp_decrypt);
-
-       
-                       break;
-               case NID_id_GostR3410_2001_cc:
-                       EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl01cc_str);
-                       EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cc_sign);
-                       EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cc_verify);
-
-                       EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost01cc_keygen);
-
-                       EVP_PKEY_meth_set_encrypt(*pmeth,
-                               pkey_gost_encrypt_init, pkey_GOST01cc_encrypt);
-                       EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cc_decrypt);
+                       EVP_PKEY_meth_set_derive(*pmeth,
+                               pkey_gost_derive_init, pkey_gost94_derive);
                        break;
-                       /* There is intentionally no break here */
                case NID_id_GostR3410_2001:
                        EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl01_str);
                        EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
@@ -712,6 +555,8 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
                        EVP_PKEY_meth_set_encrypt(*pmeth,
                                pkey_gost_encrypt_init, pkey_GOST01cp_encrypt);
                        EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt);
+                       EVP_PKEY_meth_set_derive(*pmeth,
+                               pkey_gost_derive_init, pkey_gost2001_derive);
                        break;
                case NID_id_Gost28147_89_MAC:
                        EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_mac_ctrl, pkey_gost_mac_ctrl_str);
index ef4d880551514c3d7160a3ec416133c2406b1e37..ea5e12ee070e666c125add33a9dd780fbe464740 100644 (file)
 #include <openssl/hmac.h>
 #include <openssl/md5.h>
 #include <openssl/rand.h>
-
+#ifdef KSSL_DEBUG
+#include <openssl/des.h>
+#endif
 
 int dtls1_enc(SSL *s, int send)
        {
index b2c5fee17b2f18dac25f3505ca1bca7b86c3e1a7..8141a5c6a14bf6e2ba4ace8402ecb2dafe4b7538 100644 (file)
@@ -2378,6 +2378,84 @@ int ssl3_send_client_key_exchange(SSL *s)
                        EVP_PKEY_free(srvr_pub_pkey);
                        }
 #endif /* !OPENSSL_NO_ECDH */
+               else if (alg_k & SSL_kGOST) 
+                       {
+                       /* GOST key exchange message creation */
+                       EVP_PKEY_CTX *pkey_ctx;
+                       X509 *peer_cert; 
+                       size_t msglen;
+                       unsigned int md_len;
+                       int keytype;
+                       unsigned char premaster_secret[32],shared_ukm[32];
+                       EVP_MD_CTX *ukm_hash;
+                       EVP_PKEY *pub_key;
+
+                       /* Get server sertificate PKEY and create ctx from it */
+                       peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST01)].x509;
+                       if (!peer_cert) 
+                               peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST94)].x509;
+                       if (!peer_cert)         {
+                                       SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
+                                       goto err;
+                               }       
+                               
+                       pkey_ctx=EVP_PKEY_CTX_new(pub_key=X509_get_pubkey(peer_cert),NULL);
+                       /* If we have send a certificate, and certificate key
+
+                        * parameters match those of server certificate, use
+                        * certificate key for key exchange
+                        */
+
+                        /* Otherwise, generate ephemeral key pair */
+                                       
+                       EVP_PKEY_encrypt_init(pkey_ctx);
+                         /* Generate session key */    
+                   RAND_bytes(premaster_secret,32);
+                       /* If we have client certificate, use its secret as peer key */
+                       if (s->cert->key->privatekey) {
+                               if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <0) {
+                                       /* If there was an error - just ignore it. Ephemeral key
+                                       * would be used
+                                       */
+                                       ERR_clear_error();
+                               } else {
+                                       /* Set flag "client cert key is used for key
+                                        * exchange"*/
+                               }       
+                       }                       
+                       /* Compute shared IV and store it in algorithm-specific
+                        * context data */
+                       ukm_hash = EVP_MD_CTX_create();
+                       EVP_DigestInit(ukm_hash,EVP_get_digestbynid(NID_id_GostR3411_94));
+                       EVP_DigestUpdate(ukm_hash,s->s3->client_random,SSL3_RANDOM_SIZE);
+                       EVP_DigestUpdate(ukm_hash,s->s3->server_random,SSL3_RANDOM_SIZE);
+                       EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len);
+                       EVP_MD_CTX_destroy(ukm_hash);
+                       if (EVP_PKEY_CTX_ctrl(pkey_ctx,-1,EVP_PKEY_OP_ENCRYPT,EVP_PKEY_CTRL_SET_IV,
+                               8,shared_ukm)<0) {
+                                       SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                                               SSL_R_LIBRARY_BUG);
+                                       goto err;
+                               }       
+                       /* Make GOST keytransport blob message */
+                       /*Encapsulate it into sequence */
+                       *(p++)=V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
+                       *(p++)=0x81;
+                       msglen=256;
+                       if (EVP_PKEY_encrypt(pkey_ctx,(unsigned char *)p+1,&msglen,premaster_secret,32)<0) {
+                       SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                                       SSL_R_LIBRARY_BUG);
+                               goto err;
+                       }       
+                       *(p++)= msglen & 0xff;
+                       n=msglen+3;
+                       EVP_PKEY_CTX_free(pkey_ctx);
+                       s->session->master_key_length=
+                               s->method->ssl3_enc->generate_master_secret(s,
+                                       s->session->master_key,premaster_secret,32);
+                       EVP_PKEY_free(pub_key);
+
+                       }
 #ifndef OPENSSL_NO_PSK
                else if (alg_k & SSL_kPSK)
                        {
@@ -2496,6 +2574,7 @@ int ssl3_send_client_verify(SSL *s)
        unsigned char *p,*d;
        unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
        EVP_PKEY *pkey;
+       EVP_PKEY_CTX *pctx=NULL;
 #ifndef OPENSSL_NO_RSA
        unsigned u=0;
 #endif
@@ -2509,11 +2588,19 @@ int ssl3_send_client_verify(SSL *s)
                d=(unsigned char *)s->init_buf->data;
                p= &(d[4]);
                pkey=s->cert->key->privatekey;
-
-               s->method->ssl3_enc->cert_verify_mac(s,
-                       NID_sha1,
-                       &(data[MD5_DIGEST_LENGTH]));
-
+/* Create context from key and test if sha1 is allowed as digest */
+               pctx = EVP_PKEY_CTX_new(pkey,NULL);
+               EVP_PKEY_sign_init(pctx);
+               if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1())>0)
+                       {
+                       s->method->ssl3_enc->cert_verify_mac(s,
+                                               NID_sha1,
+                                               &(data[MD5_DIGEST_LENGTH]));
+                       }
+               else
+                       {
+                       ERR_clear_error();
+                       }
 #ifndef OPENSSL_NO_RSA
                if (pkey->type == EVP_PKEY_RSA)
                        {
@@ -2565,10 +2652,30 @@ int ssl3_send_client_verify(SSL *s)
                        }
                else
 #endif
-                       {
+               if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001) 
+               {
+               unsigned char signbuf[64];
+               int i;
+               size_t sigsize;
+               s->method->ssl3_enc->cert_verify_mac(s,
+                       NID_id_GostR3411_94,
+                       data);
+               if (!EVP_PKEY_sign(pctx,signbuf,&sigsize,data,32)) {
+                       SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
+                       ERR_R_INTERNAL_ERROR);
+                       goto err;
+               }
+               for (i=63,j=0; i>=0; j++, i--) {
+                       p[2+j]=signbuf[i];
+               }       
+               s2n(j,p);
+               n=j+2;
+               }
+               else
+               {
                        SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR);
                        goto err;
-                       }
+               }
                *(d++)=SSL3_MT_CERTIFICATE_VERIFY;
                l2n3(n,d);
 
@@ -2576,8 +2683,10 @@ int ssl3_send_client_verify(SSL *s)
                s->init_num=(int)n+4;
                s->init_off=0;
                }
+       EVP_PKEY_CTX_free(pctx);
        return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 err:
+       EVP_PKEY_CTX_free(pctx);
        return(-1);
        }
 
index 9910a132e81df31ef47ebd65aeff5ed00788ebe7..00bc1b3ea924f2da3df2ef0f52c1f54c0ca77954 100644 (file)
@@ -1287,6 +1287,62 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
        128,
        },
 #endif
+       {
+       1,
+       "GOST94-GOST89-GOST89",
+       0x3000080,
+       SSL_kGOST,
+       SSL_aGOST94,
+       SSL_eGOST2814789CNT,
+       SSL_GOST89MAC,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH,
+       SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94|TLS1_STREAM_MAC,
+       256,
+       256
+       },
+       {
+       1,
+       "GOST2001-GOST89-GOST89",
+       0x3000081,
+       SSL_kGOST,
+       SSL_aGOST01,
+       SSL_eGOST2814789CNT,
+       SSL_GOST89MAC,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH,
+       SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94|TLS1_STREAM_MAC,
+       256,
+       256
+       },
+       {
+       1,
+       "GOST94-NULL-GOST94",
+       0x3000082,
+       SSL_kGOST,
+       SSL_aGOST94,
+       SSL_eNULL,
+       SSL_GOST94,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_STRONG_NONE,
+       SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94,
+       0,
+       0
+       },
+       {
+       1,
+       "GOST2001-NULL-GOST94",
+       0x3000083,
+       SSL_kGOST,
+       SSL_aGOST01,
+       SSL_eNULL,
+       SSL_GOST94,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_STRONG_NONE,
+       SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94,
+       0,
+       0
+       },
 
 #ifndef OPENSSL_NO_CAMELLIA
        /* Camellia ciphersuites from RFC4132 (256-bit portion) */
@@ -2820,7 +2876,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
                emask_a = cert->export_mask_a;
                        
 #ifdef KSSL_DEBUG
-               printf("ssl3_choose_cipher %d alg= %lx\n", i,c->algorithms);
+/*             printf("ssl3_choose_cipher %d alg= %lx\n", i,c->algorithms);*/
 #endif    /* KSSL_DEBUG */
 
                alg_k=c->algorithm_mkey;
index 2e077d4bf95fc15d37d90bf275ebce857c08a38a..3d63e2e89db8b5e5973f4b8773fdcf4f2b6d04df 100644 (file)
@@ -511,6 +511,8 @@ int ssl3_accept(SSL *s)
                                }
                        else
                                {
+                               int offset=0;
+                               int dgst_num;
                                s->state=SSL3_ST_SR_CERT_VRFY_A;
                                s->init_num=0;
 
@@ -519,13 +521,14 @@ int ssl3_accept(SSL *s)
                                 * FIXME - digest processing for CertificateVerify
                                 * should be generalized. But it is next step
                                 */
-                                                               
-                               s->method->ssl3_enc->cert_verify_mac(s,
-                                       NID_md5,
-                                   &(s->s3->tmp.cert_verify_md[0]));
-                               s->method->ssl3_enc->cert_verify_mac(s,
-                                       NID_sha1,
-                                   &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]));
+                               if (s->s3->handshake_buffer)
+                                       ssl3_digest_cached_records(s);
+                               for (dgst_num=0; dgst_num<SSL_MAX_DIGEST;dgst_num++)    
+                                       if (s->s3->handshake_dgst[dgst_num]) 
+                                               {
+                                               s->method->ssl3_enc->cert_verify_mac(s,EVP_MD_CTX_type(s->s3->handshake_dgst[dgst_num]),&(s->s3->tmp.cert_verify_md[offset]));
+                                               offset+=EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]);
+                                               }               
                                }
                        break;
 
@@ -1181,7 +1184,6 @@ int ssl3_send_server_hello(SSL *s)
                        return -1;
                        }
 #endif
-
                /* do the header */
                l=(p-d);
                d=buf;
@@ -2398,6 +2400,35 @@ int ssl3_get_client_key_exchange(SSL *s)
                        }
                else
 #endif
+               if (alg_k & SSL_kGOST) 
+               {
+                       EVP_PKEY_CTX *pkey_ctx;
+                       unsigned char premaster_secret[32];
+                       size_t outlen;                  
+
+                       /* Get our certificate privatec key*/
+                       pkey_ctx = EVP_PKEY_CTX_new(s->cert->key->privatekey,NULL);     
+                       EVP_PKEY_decrypt_init(pkey_ctx);
+                       /* Decrypt session key */
+                       if ((*p!=( V_ASN1_SEQUENCE| V_ASN1_CONSTRUCTED)) || p[1]!=0x81 ) 
+                               {
+                               SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
+                               goto err;
+                               }       
+                       if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,p+3,p[2]) <0) 
+
+                               {
+                               SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
+                               goto err;
+                               }
+                       /* Generate master secret */
+                       EVP_PKEY_CTX_free(pkey_ctx);
+                       s->session->master_key_length=
+                               s->method->ssl3_enc->generate_master_secret(s,
+                                       s->session->master_key,premaster_secret,32);
+
+               }
+               else
                {
                al=SSL_AD_HANDSHAKE_FAILURE;
                SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
@@ -2487,15 +2518,25 @@ int ssl3_get_cert_verify(SSL *s)
 
        /* we now have a signature that we need to verify */
        p=(unsigned char *)s->init_msg;
-       n2s(p,i);
-       n-=2;
-       if (i > n)
+       /* Check for broken implementations of GOST ciphersuites */
+       /* If key is GOST and n is exactly 64, it is bare
+        * signature without length field */
+       if (n==64 && (pkey->type==NID_id_GostR3410_94 ||
+               pkey->type == NID_id_GostR3410_2001) )
                {
-               SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
-               al=SSL_AD_DECODE_ERROR;
-               goto f_err;
-               }
-
+               i=64;
+               } 
+       else 
+               {       
+               n2s(p,i);
+               n-=2;
+               if (i > n)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
+                       al=SSL_AD_DECODE_ERROR;
+                       goto f_err;
+                       }
+       }
        j=EVP_PKEY_size(pkey);
        if ((i > j) || (n > j) || (n <= 0))
                {
@@ -2558,6 +2599,28 @@ int ssl3_get_cert_verify(SSL *s)
                }
        else
 #endif
+       if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001)
+               {   unsigned char signature[64];
+                       int idx;
+                       EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey,NULL);
+                       EVP_PKEY_verify_init(pctx);
+                       if (i!=64) {
+                               fprintf(stderr,"GOST signature length is %d",i);
+                       }       
+                       for (idx=0;idx<64;idx++) {
+                               signature[63-idx]=p[idx];
+                       }       
+                       j=EVP_PKEY_verify(pctx,signature,64,s->s3->tmp.cert_verify_md,32);
+                       EVP_PKEY_CTX_free(pctx);
+                       if (j<=0) 
+                               {
+                               al=SSL_AD_DECRYPT_ERROR;
+                               SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
+                                       SSL_R_BAD_ECDSA_SIGNATURE);
+                               goto f_err;
+                               }       
+               }
+       else    
                {
                SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
                al=SSL_AD_UNSUPPORTED_CERTIFICATE;
index 5781072dc1117ab7a4da785e5c0c05df3c81f312..a1e464e89f8df529c199671c944ca28b0e6e5697 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -249,6 +249,7 @@ extern "C" {
 #define SSL_TXT_kECDH          "kECDH"
 #define SSL_TXT_kEECDH         "kEECDH"
 #define SSL_TXT_kPSK            "kPSK"
+#define SSL_TXT_kGOST          "kGOST"
 
 #define        SSL_TXT_aRSA            "aRSA"
 #define        SSL_TXT_aDSS            "aDSS"
@@ -257,6 +258,9 @@ extern "C" {
 #define SSL_TXT_aKRB5          "aKRB5"
 #define SSL_TXT_aECDSA         "aECDSA"
 #define SSL_TXT_aPSK            "aPSK"
+#define SSL_TXT_aGOST94        "aGOST94"
+#define SSL_TXT_aGOST01 "aGOST01"
+#define SSL_TXT_aGOST  "aGOST"
 
 #define        SSL_TXT_DSS             "DSS"
 #define SSL_TXT_DH             "DH"
@@ -527,7 +531,7 @@ typedef struct ssl_session_st
 
 /* SSL_OP_ALL: various bug workarounds that should be rather harmless.
  *             This used to be 0x000FFFFFL before 0.9.7. */
-#define SSL_OP_ALL                                     0x00000FFFL
+#define SSL_OP_ALL                                     0x80000FFFL
 
 /* DTLS options */
 #define SSL_OP_NO_QUERY_MTU                 0x00001000L
@@ -566,7 +570,11 @@ typedef struct ssl_session_st
 #define SSL_OP_PKCS1_CHECK_2                           0x10000000L
 #define SSL_OP_NETSCAPE_CA_DN_BUG                      0x20000000L
 #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG         0x40000000L
-
+/* Make server add server-hello extension from early version of
+ * cryptopro draft, when GOST ciphersuite is negotiated. 
+ * Required for interoperability with CryptoPro CSP 3.x 
+ */
+#define SSL_OP_CRYPTOPRO_TLSEXT_BUG                    0x80000000L
 
 /* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
  * when just a single record has been written): */
@@ -1912,7 +1920,10 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_TLS1_PRF                                  284
 #define SSL_F_TLS1_SETUP_KEY_BLOCK                      211
 #define SSL_F_WRITE_PENDING                             212
-
+#define SSL_F_TLS1_FINAL_FINISH_MAC            283
+#define SSL_F_TLS1_PRF                         284
+#define SSL_F_SSL3_HANDSHAKE_MAC    285
+#define SSL_F_TLS1_CERT_VERIFY_MAC  286
 /* Reason codes. */
 #define SSL_R_APP_DATA_IN_HANDSHAKE                     100
 #define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
@@ -2172,7 +2183,8 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_WRONG_VERSION_NUMBER                      267
 #define SSL_R_X509_LIB                                  268
 #define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS          269
-
+#define SSL_R_NO_REQUIRED_DIGEST 324
+#define SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER 330
 #ifdef  __cplusplus
 }
 #endif
index 5ba5b32a073a31678c72b9018c80532cf0a8c47f..f62f37deb15e389a2373fbd50e5185e3b290ce7d 100644 (file)
@@ -243,7 +243,7 @@ static const SSL_CIPHER cipher_aliases[]={
        {0,SSL_TXT_ECDH,0,    SSL_kECDHr|SSL_kECDHe|SSL_kEECDH,0,0,0,0,0,0,0,0},
 
         {0,SSL_TXT_kPSK,0,    SSL_kPSK,  0,0,0,0,0,0,0,0},
-
+       {0,SSL_TXT_kGOST,0, SSL_kGOST,0,0,0,0,0,0,0,0},
 
        /* server authentication aliases */
        {0,SSL_TXT_aRSA,0,    0,SSL_aRSA,  0,0,0,0,0,0,0},
@@ -256,7 +256,9 @@ static const SSL_CIPHER cipher_aliases[]={
        {0,SSL_TXT_aECDSA,0,  0,SSL_aECDSA,0,0,0,0,0,0,0},
        {0,SSL_TXT_ECDSA,0,   0,SSL_aECDSA, 0,0,0,0,0,0,0},
         {0,SSL_TXT_aPSK,0,    0,SSL_aPSK,  0,0,0,0,0,0,0},
-
+       {0,SSL_TXT_aGOST94,0,0,SSL_aGOST94,0,0,0,0,0,0,0},
+       {0,SSL_TXT_aGOST01,0,0,SSL_aGOST01,0,0,0,0,0,0,0},
+       {0,SSL_TXT_aGOST,0,0,SSL_aGOST94|SSL_aGOST01,0,0,0,0,0,0,0},
 
        /* aliases combining key exchange and server authentication */
        {0,SSL_TXT_EDH,0,     SSL_kEDH,~SSL_aNULL,0,0,0,0,0,0,0},
index 6439625d4fdfbeed20d043fd776a4adbad6a0e6a..8062481faaaa51030d28aa21030d7fcf482dd03c 100644 (file)
@@ -260,6 +260,10 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_TLS1_PRF),     "TLS1_PRF"},
 {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
 {ERR_FUNC(SSL_F_WRITE_PENDING),        "WRITE_PENDING"},
+{ERR_FUNC(SSL_F_TLS1_FINAL_FINISH_MAC),"tls1_final_finish_mac"},
+{ERR_FUNC(SSL_F_TLS1_PRF),"tls1_prf"},
+{ERR_FUNC(SSL_F_SSL3_HANDSHAKE_MAC),"ssl3_handshake_mac"},
+{ERR_FUNC(SSL_F_TLS1_CERT_VERIFY_MAC),"tls1_cert_verify_mac"},
 {0,NULL}
        };
 
@@ -523,6 +527,9 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_WRONG_VERSION_NUMBER)  ,"wrong version number"},
 {ERR_REASON(SSL_R_X509_LIB)              ,"x509 lib"},
 {ERR_REASON(SSL_R_X509_VERIFICATION_SETUP_PROBLEMS),"x509 verification setup problems"},
+{ERR_REASON(SSL_R_UNSUPPORTED_DIGEST_TYPE),"unsupported digest type"},
+{ERR_REASON(SSL_R_NO_REQUIRED_DIGEST),"digest requred for handshake isn't computed"},
+{ERR_REASON(SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER),"Peer haven't sent GOST certificate, required for selected ciphersuite"},
 {0,NULL}
        };
 
index 9ed5ff2988de581ee550c76d2972ecb19260426c..ccfe399bbe879e4a81580de85e9c1b9a63c99424 100644 (file)
@@ -1742,11 +1742,24 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher)
        emask_k=0;
        emask_a=0;
 
+       
+
 #ifdef CIPHER_DEBUG
        printf("rt=%d rte=%d dht=%d ecdht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n",
                rsa_tmp,rsa_tmp_export,dh_tmp,have_ecdh_tmp,
                rsa_enc,rsa_enc_export,rsa_sign,dsa_sign,dh_rsa,dh_dsa);
 #endif
+       
+       cpk = &(c->pkeys[SSL_PKEY_GOST01]);
+       if (cpk->x509 != NULL && cpk->privatekey !=NULL) {
+               mask_k |= SSL_kGOST;
+               mask_a |= SSL_aGOST01;
+       }
+       cpk = &(c->pkeys[SSL_PKEY_GOST94]);
+       if (cpk->x509 != NULL && cpk->privatekey !=NULL) {
+               mask_k |= SSL_kGOST;
+               mask_a |= SSL_aGOST94;
+       }
 
        if (rsa_enc || (rsa_tmp && rsa_sign))
                mask_k|=SSL_kRSA;
@@ -2015,6 +2028,10 @@ X509 *ssl_get_server_send_cert(SSL *s)
                /* VRS something else here? */
                return(NULL);
                }
+       else if (alg_a & SSL_aGOST94) 
+               i=SSL_PKEY_GOST94;
+       else if (alg_a & SSL_aGOST01)
+               i=SSL_PKEY_GOST01;
        else /* if (alg_a & SSL_aNULL) */
                {
                SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,ERR_R_INTERNAL_ERROR);
index 011ef3aacaa97dc68c1ef17da10c303cab7db2ba..ee511a6512169857d527403b8365927e761e2abe 100644 (file)
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
 #include <openssl/md5.h>
+#ifdef KSSL_DEBUG
+#include <openssl/des.h>
+#endif
 
 /* seed1 through seed5 are virtually concatenated */
 static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
@@ -878,9 +881,8 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
 
        EVP_DigestSignUpdate(mac_ctx,buf,5);
        EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length);
-       if (stream_mac) EVP_MD_CTX_copy(&hmac,hash);
-       EVP_DigestSignFinal(&hmac,md,&md_size);
-       EVP_MD_CTX_cleanup(&hmac);
+       EVP_DigestSignFinal(mac_ctx,md,&md_size);
+       if (!stream_mac) EVP_MD_CTX_cleanup(&hmac);
 #ifdef TLS_DEBUG
 printf("sec=");
 {unsigned int z; for (z=0; z<md_size; z++) printf("%02X ",mac_sec[z]); printf("\n"); }
index 2c0eb3a6d005b9aa08989291ae2bc3849bff127e..615a1c4f54d244da6efc92bd07d78b89d59cbb22 100644 (file)
@@ -514,6 +514,20 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
                ret += sol;
                }
 #endif
+       if (((s->s3->tmp.new_cipher->id & 0xFFFF)==0x80 || (s->s3->tmp.new_cipher->id & 0xFFFF)==0x81) 
+               && (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG))
+               { const unsigned char cryptopro_ext[36] = {
+                       0xfd, 0xe8, /*65000*/
+                       0x00, 0x20, /*32 bytes length*/
+                       0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, 
+                       0x03,   0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06, 
+                       0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08, 
+                       0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17};
+                       if (limit-ret<36) return NULL;
+                       memcpy(ret,cryptopro_ext,36);
+                       ret+=36;
+
+               }
 
        if ((extdatalen = ret-p-2)== 0) 
                return p;
@@ -545,7 +559,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
 
                if (data+size > (d+n))
                        return 1;
-
+               fprintf(stderr,"Received extension type %d size %d\n",type,size);
                if (s->tlsext_debug_cb)
                        s->tlsext_debug_cb(s, 0, type, data, size,
                                                s->tlsext_debug_arg);
index 6e88bf6ea353c3b16c3bc0601d5dbd6a73c56d7e..afee57e1f00b615fdf60b09facdfaec019b90ee9 100755 (executable)
@@ -3933,3 +3933,4 @@ TS_TST_INFO_get_ext_by_critical         4314      EXIST::FUNCTION:
 EVP_PKEY_CTX_new_id                     4315   EXIST::FUNCTION:
 TS_REQ_get_ext_by_OBJ                   4316   EXIST::FUNCTION:
 TS_CONF_set_signer_cert                 4317   EXIST::FUNCTION:
+EVP_PKEY_CTX_get0_peerkey               4318   EXIST::FUNCTION: