diff options
Diffstat (limited to 'engines/ccgost')
-rw-r--r-- | engines/ccgost/e_gost_err.c | 4 | ||||
-rw-r--r-- | engines/ccgost/e_gost_err.h | 2 | ||||
-rw-r--r-- | engines/ccgost/gost2001_keyx.c | 51 | ||||
-rw-r--r-- | engines/ccgost/gost94_keyx.c | 52 | ||||
-rw-r--r-- | engines/ccgost/gost_asn1.c | 2 | ||||
-rw-r--r-- | engines/ccgost/gost_lcl.h | 1 | ||||
-rw-r--r-- | engines/ccgost/gost_pmeth.c | 9 |
7 files changed, 91 insertions, 30 deletions
diff --git a/engines/ccgost/e_gost_err.c b/engines/ccgost/e_gost_err.c index 469027051a..9a79a374e2 100644 --- a/engines/ccgost/e_gost_err.c +++ b/engines/ccgost/e_gost_err.c @@ -1,6 +1,6 @@ /* e_gost_err.c */ /* ==================================================================== - * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2009 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -120,10 +120,12 @@ static ERR_STRING_DATA GOST_str_reasons[]= {ERR_REASON(GOST_R_BAD_KEY_PARAMETERS_FORMAT),"bad key parameters format"}, {ERR_REASON(GOST_R_BAD_PKEY_PARAMETERS_FORMAT),"bad pkey parameters format"}, {ERR_REASON(GOST_R_CANNOT_PACK_EPHEMERAL_KEY),"cannot pack ephemeral key"}, +{ERR_REASON(GOST_R_CTRL_CALL_FAILED) ,"ctrl call failed"}, {ERR_REASON(GOST_R_ERROR_COMPUTING_SHARED_KEY),"error computing shared key"}, {ERR_REASON(GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO),"error packing key transport info"}, {ERR_REASON(GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO),"error parsing key transport info"}, {ERR_REASON(GOST_R_INCOMPATIBLE_ALGORITHMS),"incompatible algorithms"}, +{ERR_REASON(GOST_R_INCOMPATIBLE_PEER_KEY),"incompatible peer key"}, {ERR_REASON(GOST_R_INVALID_CIPHER_PARAMS),"invalid cipher params"}, {ERR_REASON(GOST_R_INVALID_CIPHER_PARAM_OID),"invalid cipher param oid"}, {ERR_REASON(GOST_R_INVALID_DIGEST_TYPE) ,"invalid digest type"}, diff --git a/engines/ccgost/e_gost_err.h b/engines/ccgost/e_gost_err.h index 652d1bb392..6dc500079d 100644 --- a/engines/ccgost/e_gost_err.h +++ b/engines/ccgost/e_gost_err.h @@ -118,10 +118,12 @@ void ERR_GOST_error(int function, int reason, char *file, int line); #define GOST_R_BAD_KEY_PARAMETERS_FORMAT 99 #define GOST_R_BAD_PKEY_PARAMETERS_FORMAT 100 #define GOST_R_CANNOT_PACK_EPHEMERAL_KEY 101 +#define GOST_R_CTRL_CALL_FAILED 132 #define GOST_R_ERROR_COMPUTING_SHARED_KEY 102 #define GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO 103 #define GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO 104 #define GOST_R_INCOMPATIBLE_ALGORITHMS 105 +#define GOST_R_INCOMPATIBLE_PEER_KEY 131 #define GOST_R_INVALID_CIPHER_PARAMS 106 #define GOST_R_INVALID_CIPHER_PARAM_OID 107 #define GOST_R_INVALID_DIGEST_TYPE 108 diff --git a/engines/ccgost/gost2001_keyx.c b/engines/ccgost/gost2001_keyx.c index 3b5a78ac3d..00759bcab0 100644 --- a/engines/ccgost/gost2001_keyx.c +++ b/engines/ccgost/gost2001_keyx.c @@ -203,6 +203,16 @@ int pkey_GOST01cp_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_le ASN1_OBJECT_free(gkt->key_agreement_info->cipher); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); if (key_is_ephemeral && sec_key) EVP_PKEY_free(sec_key); + if (!key_is_ephemeral) + { + /* Set control "public key from client certificate used" */ + if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0) + { + GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, + GOST_R_CTRL_CALL_FAILED); + goto err; + } + } if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL))>0) ret =1; GOST_KEY_TRANSPORT_free(gkt); return ret; @@ -225,7 +235,7 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l unsigned char sharedKey[32]; gost_ctx ctx; const struct gost_cipher_info *param=NULL; - EVP_PKEY *eph_key=NULL; + EVP_PKEY *eph_key=NULL, *peerkey=NULL; if (!key) { @@ -239,18 +249,35 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO); return -1; } - + + /* If key transport structure contains public key, use it */ 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) { + if (eph_key) + { + if (EVP_PKEY_derive_set_peer(pctx, eph_key) <= 0) + { GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT, - GOST_R_NO_PEER_KEY); + GOST_R_INCOMPATIBLE_PEER_KEY); goto err; + } + } + else + { + /* Set control "public key from client certificate used" */ + if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0) + { + GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT, + GOST_R_CTRL_CALL_FAILED); + goto err; + } + } + peerkey = EVP_PKEY_CTX_get0_peerkey(pctx); + if (!peerkey) + { + GOSTerr(GOST_F_PKEY_GOST01CP_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); @@ -260,7 +287,7 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l 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); - VKO_compute_key(sharedKey,32,EC_KEY_get0_public_key(EVP_PKEY_get0(eph_key)), + VKO_compute_key(sharedKey,32,EC_KEY_get0_public_key(EVP_PKEY_get0(peerkey)), EVP_PKEY_get0(priv),wrappedKey); if (!keyUnwrapCryptoPro(&ctx,sharedKey,wrappedKey,key)) { @@ -269,9 +296,9 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l goto err; } - EVP_PKEY_free(eph_key); - GOST_KEY_TRANSPORT_free(gkt); ret=1; err: + if (eph_key) EVP_PKEY_free(eph_key); + if (gkt) GOST_KEY_TRANSPORT_free(gkt); return ret; } diff --git a/engines/ccgost/gost94_keyx.c b/engines/ccgost/gost94_keyx.c index 5d04a17821..624be586a5 100644 --- a/engines/ccgost/gost94_keyx.c +++ b/engines/ccgost/gost94_keyx.c @@ -92,7 +92,6 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, 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); @@ -178,10 +177,20 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, ASN1_OBJECT_free(gkt->key_agreement_info->cipher); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); *outlen = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL); - if (!size) + if (*outlen <= 0) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO); - size=-1; + goto err; + } + if (!key_is_ephemeral) + { + /* Set control "public key from client certificate used" */ + if (EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0) + { + GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, + GOST_R_CTRL_CALL_FAILED); + goto err; + } } GOST_KEY_TRANSPORT_free(gkt); return 1; @@ -207,7 +216,7 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len unsigned char sharedKey[32]; gost_ctx cctx; const struct gost_cipher_info *param=NULL; - EVP_PKEY *eph_key=NULL; + EVP_PKEY *eph_key=NULL, *peerkey=NULL; EVP_PKEY *priv= EVP_PKEY_CTX_get0_pkey(ctx); if (!key) @@ -224,19 +233,32 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len 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) { + if (eph_key) + { + if (EVP_PKEY_derive_set_peer(ctx, eph_key) <= 0) + { GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT, - GOST_R_NO_PEER_KEY); + GOST_R_INCOMPATIBLE_PEER_KEY); goto err; + } + } + else + { + /* Set control "public key from client certificate used" */ + if (EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0) + { + GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT, + GOST_R_CTRL_CALL_FAILED); + goto err; + } + } + peerkey = EVP_PKEY_CTX_get0_peerkey(ctx); + if (!peerkey) + { + 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); @@ -246,7 +268,7 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len 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(gost_get0_priv_key(priv),eph_key,sharedKey); + make_cp_exchange_key(gost_get0_priv_key(priv),peerkey,sharedKey); if (!keyUnwrapCryptoPro(&cctx,sharedKey,wrappedKey,key)) { GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT, diff --git a/engines/ccgost/gost_asn1.c b/engines/ccgost/gost_asn1.c index 76c18c1c66..318ecfce57 100644 --- a/engines/ccgost/gost_asn1.c +++ b/engines/ccgost/gost_asn1.c @@ -27,7 +27,7 @@ IMPLEMENT_ASN1_FUNCTIONS(GOST_KEY_INFO) ASN1_NDEF_SEQUENCE(GOST_KEY_AGREEMENT_INFO) = { ASN1_SIMPLE(GOST_KEY_AGREEMENT_INFO, cipher, ASN1_OBJECT), - ASN1_IMP(GOST_KEY_AGREEMENT_INFO, ephem_key, X509_PUBKEY, 0), + ASN1_IMP_OPT(GOST_KEY_AGREEMENT_INFO, ephem_key, X509_PUBKEY, 0), ASN1_SIMPLE(GOST_KEY_AGREEMENT_INFO, eph_iv, ASN1_OCTET_STRING) } ASN1_NDEF_SEQUENCE_END(GOST_KEY_AGREEMENT_INFO) diff --git a/engines/ccgost/gost_lcl.h b/engines/ccgost/gost_lcl.h index 81fecd38a2..437a48cc86 100644 --- a/engines/ccgost/gost_lcl.h +++ b/engines/ccgost/gost_lcl.h @@ -47,6 +47,7 @@ int sign_param_nid; /* Should be set whenever parameters are filled */ EVP_MD *md; unsigned char *shared_ukm; + int peer_key_used; }; struct gost_mac_pmeth_data { diff --git a/engines/ccgost/gost_pmeth.c b/engines/ccgost/gost_pmeth.c index 2861d38327..caaea99d36 100644 --- a/engines/ccgost/gost_pmeth.c +++ b/engines/ccgost/gost_pmeth.c @@ -98,7 +98,14 @@ static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) pctx->shared_ukm=OPENSSL_malloc((int)p1); memcpy(pctx->shared_ukm,p2,(int) p1); return 1; - + case EVP_PKEY_CTRL_PEER_KEY: + if (p1 == 0 || p1 == 1) /* call from EVP_PKEY_derive_set_peer */ + return 1; + if (p1 == 2) /* TLS: peer key used? */ + return pctx->peer_key_used; + if (p1 == 3) /* TLS: peer key used! */ + return (pctx->peer_key_used = 1); + return -2; } return -2; } |