1 /**********************************************************************
3 * Copyright (c) 2005-2006 Cryptocom LTD *
4 * This file is distributed under the same license as OpenSSL *
6 * Implements generation and parsing of GOST_KEY_TRANSPORT for *
7 * GOST R 34.10-94 algorithms *
9 * Requires OpenSSL 0.9.9 for compilation *
10 **********************************************************************/
12 #include <openssl/dh.h>
13 #include <openssl/rand.h>
14 #include <openssl/evp.h>
15 #include <openssl/objects.h>
19 #include "e_gost_err.h"
20 #include "gost_keywrap.h"
22 /* Common functions for both 94 and 2001 key exchange schemes */
23 /* Implementation of the Diffi-Hellman key agreement scheme based on
26 /* Computes Diffie-Hellman key and stores it into buffer in
27 * little-endian byte order as expected by both versions of GOST 94
30 static int compute_pair_key_le(unsigned char *pair_key
,BIGNUM
*pub_key
,DH
*dh
)
32 unsigned char be_key
[128];
34 key_size
=DH_compute_key(be_key
,pub_key
,dh
);
35 if (!key_size
) return 0;
36 memset(pair_key
,0,128);
37 for (i
=0;i
<key_size
;i
++)
39 pair_key
[i
]=be_key
[key_size
-1-i
];
45 * Computes 256 bit Key exchange key as specified in RFC 4357
47 static int make_cp_exchange_key(BIGNUM
*priv_key
,EVP_PKEY
*pubk
, unsigned char *shared_key
)
49 unsigned char dh_key
[128];
51 gost_hash_ctx hash_ctx
;
57 dh
->g
= BN_dup(pubk
->pkey
.dsa
->g
);
58 dh
->p
= BN_dup(pubk
->pkey
.dsa
->p
);
59 dh
->priv_key
= BN_dup(priv_key
);
60 ret
=compute_pair_key_le(dh_key
,((DSA
*)(EVP_PKEY_get0(pubk
)))->pub_key
,dh
) ;
63 init_gost_hash_ctx(&hash_ctx
,&GostR3411_94_CryptoProParamSet
);
64 start_hash(&hash_ctx
);
65 hash_block(&hash_ctx
,dh_key
,128);
66 finish_hash(&hash_ctx
,shared_key
);
67 done_gost_hash_ctx(&hash_ctx
);
71 /* EVP_PKEY_METHOD callback derive. Implements VKO R 34.10-94 */
73 int pkey_gost94_derive(EVP_PKEY_CTX
*ctx
,unsigned char *key
,size_t *keylen
)
75 EVP_PKEY
*pubk
= EVP_PKEY_CTX_get0_peerkey(ctx
);
76 EVP_PKEY
*mykey
= EVP_PKEY_CTX_get0_pkey(ctx
);
78 if (key
== NULL
) return 1;
80 return make_cp_exchange_key(gost_get0_priv_key(mykey
), pubk
, key
);
83 /* EVP_PKEY_METHOD callback encrypt for
84 * GOST R 34.10-94 cryptopro modification
88 int pkey_GOST94cp_encrypt(EVP_PKEY_CTX
*ctx
, unsigned char *out
, size_t *outlen
, const unsigned char* key
, size_t key_len
)
90 GOST_KEY_TRANSPORT
*gkt
=NULL
;
91 unsigned char shared_key
[32], ukm
[8],crypted_key
[44];
92 const struct gost_cipher_info
*param
=get_encryption_params(NULL
);
93 EVP_PKEY
*pubk
= EVP_PKEY_CTX_get0_pkey(ctx
);
94 struct gost_pmeth_data
*data
= EVP_PKEY_CTX_get_data(ctx
);
97 int key_is_ephemeral
=1;
98 EVP_PKEY
*mykey
= EVP_PKEY_CTX_get0_peerkey(ctx
);
100 /* Do not use vizir cipher parameters with cryptopro */
101 if (!get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS
) && param
== gost_cipher_list
)
103 param
= gost_cipher_list
+1;
108 /* If key already set, it is not ephemeral */
110 if (!gost_get0_priv_key(mykey
))
112 GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT
,
113 GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR
);
119 /* Otherwise generate ephemeral key */
120 key_is_ephemeral
= 1;
123 mykey
= EVP_PKEY_new();
124 EVP_PKEY_assign(mykey
, EVP_PKEY_base_id(pubk
),DSA_new());
125 EVP_PKEY_copy_parameters(mykey
,pubk
);
126 if (!gost_sign_keygen(EVP_PKEY_get0(mykey
)))
133 make_cp_exchange_key(gost_get0_priv_key(mykey
),pubk
,shared_key
);
134 if (data
->shared_ukm
)
136 memcpy(ukm
,data
->shared_ukm
,8);
140 if (RAND_bytes(ukm
,8)<=0)
142 GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT
,
143 GOST_R_RANDOM_GENERATOR_FAILURE
);
149 gost_init(&cctx
,param
->sblock
);
150 keyWrapCryptoPro(&cctx
,shared_key
,ukm
,key
,crypted_key
);
152 gkt
= GOST_KEY_TRANSPORT_new();
157 if(!ASN1_OCTET_STRING_set(gkt
->key_agreement_info
->eph_iv
,
162 if (!ASN1_OCTET_STRING_set(gkt
->key_info
->imit
,crypted_key
+40,4))
166 if (!ASN1_OCTET_STRING_set(gkt
->key_info
->encrypted_key
,crypted_key
+8,32))
170 if (key_is_ephemeral
) {
171 if (!X509_PUBKEY_set(&gkt
->key_agreement_info
->ephem_key
,out
?mykey
:pubk
))
173 GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT
,GOST_R_CANNOT_PACK_EPHEMERAL_KEY
);
176 if (out
) EVP_PKEY_free(mykey
);
178 ASN1_OBJECT_free(gkt
->key_agreement_info
->cipher
);
179 gkt
->key_agreement_info
->cipher
= OBJ_nid2obj(param
->nid
);
180 *outlen
= i2d_GOST_KEY_TRANSPORT(gkt
,out
?&out
:NULL
);
183 GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT
,GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO
);
186 GOST_KEY_TRANSPORT_free(gkt
);
189 if (key_is_ephemeral
) {
190 EVP_PKEY_free(mykey
);
192 GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT
,
193 GOST_R_MALLOC_FAILURE
);
195 GOST_KEY_TRANSPORT_free(gkt
);
200 /* EVP_PLEY_METHOD callback decrypt for
201 * GOST R 34.10-94 cryptopro modification
203 int pkey_GOST94cp_decrypt(EVP_PKEY_CTX
*ctx
, unsigned char *key
, size_t *key_len
,const unsigned char *in
, size_t in_len
) {
204 const unsigned char *p
= in
;
205 GOST_KEY_TRANSPORT
*gkt
= NULL
;
206 unsigned char wrappedKey
[44];
207 unsigned char sharedKey
[32];
209 const struct gost_cipher_info
*param
=NULL
;
210 EVP_PKEY
*eph_key
=NULL
;
211 EVP_PKEY
*priv
= EVP_PKEY_CTX_get0_pkey(ctx
);
219 gkt
= d2i_GOST_KEY_TRANSPORT(NULL
,(const unsigned char **)&p
,
223 GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT
,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO
);
226 eph_key
= X509_PUBKEY_get(gkt
->key_agreement_info
->ephem_key
);
227 /* No ephemeral key in the structure. Check peer key in the context
230 eph_key
= EVP_PKEY_CTX_get0_peerkey(ctx
);
232 GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT
,
236 /* Increment reference count of peer key */
237 CRYPTO_add(&(eph_key
->references
),1 ,CRYPTO_LOCK_EVP_PKEY
);
241 param
= get_encryption_params(gkt
->key_agreement_info
->cipher
);
242 gost_init(&cctx
,param
->sblock
);
243 OPENSSL_assert(gkt
->key_agreement_info
->eph_iv
->length
==8);
244 memcpy(wrappedKey
,gkt
->key_agreement_info
->eph_iv
->data
,8);
245 OPENSSL_assert(gkt
->key_info
->encrypted_key
->length
==32);
246 memcpy(wrappedKey
+8,gkt
->key_info
->encrypted_key
->data
,32);
247 OPENSSL_assert(gkt
->key_info
->imit
->length
==4);
248 memcpy(wrappedKey
+40,gkt
->key_info
->imit
->data
,4);
249 make_cp_exchange_key(gost_get0_priv_key(priv
),eph_key
,sharedKey
);
250 if (!keyUnwrapCryptoPro(&cctx
,sharedKey
,wrappedKey
,key
))
252 GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT
,
253 GOST_R_ERROR_COMPUTING_SHARED_KEY
);
257 EVP_PKEY_free(eph_key
);
258 GOST_KEY_TRANSPORT_free(gkt
);
261 EVP_PKEY_free(eph_key
);
262 GOST_KEY_TRANSPORT_free(gkt
);