"gost_grasshopper_cipher_ctl"},
{ERR_PACK(0, GOST_F_GOST_GRASSHOPPER_CIPHER_DO_CTRACPKM_OMAC, 0),
"gost_grasshopper_cipher_do_ctracpkm_omac"},
+ {ERR_PACK(0, GOST_F_GOST_GRASSHOPPER_CIPHER_INIT_CTRACPKM_OMAC, 0),
+ "gost_grasshopper_cipher_init_ctracpkm_omac"},
{ERR_PACK(0, GOST_F_GOST_GRASSHOPPER_SET_ASN1_PARAMETERS, 0),
"gost_grasshopper_set_asn1_parameters"},
{ERR_PACK(0, GOST_F_GOST_IMIT_CTRL, 0), "gost_imit_ctrl"},
{ERR_PACK(0, GOST_F_MAGMA_CIPHER_CTL, 0), "magma_cipher_ctl"},
{ERR_PACK(0, GOST_F_MAGMA_CIPHER_CTL_ACPKM_OMAC, 0),
"magma_cipher_ctl_acpkm_omac"},
+ {ERR_PACK(0, GOST_F_MAGMA_CIPHER_INIT_CTR_ACPKM_OMAC, 0),
+ "magma_cipher_init_ctr_acpkm_omac"},
{ERR_PACK(0, GOST_F_OMAC_ACPKM_IMIT_CTRL, 0), "omac_acpkm_imit_ctrl"},
{ERR_PACK(0, GOST_F_OMAC_ACPKM_IMIT_FINAL, 0), "omac_acpkm_imit_final"},
{ERR_PACK(0, GOST_F_OMAC_ACPKM_IMIT_UPDATE, 0), "omac_acpkm_imit_update"},
# define GOST_F_GOST_ENCODE_CMS_PARAMS 161
# define GOST_F_GOST_GRASSHOPPER_CIPHER_CTL 111
# define GOST_F_GOST_GRASSHOPPER_CIPHER_DO_CTRACPKM_OMAC 160
+# define GOST_F_GOST_GRASSHOPPER_CIPHER_INIT_CTRACPKM_OMAC 162
# define GOST_F_GOST_GRASSHOPPER_SET_ASN1_PARAMETERS 112
# define GOST_F_GOST_IMIT_CTRL 113
# define GOST_F_GOST_IMIT_FINAL 114
# define GOST_F_GOST_KDFTREE2012_256 149
# define GOST_F_GOST_KEXP15 143
# define GOST_F_GOST_KIMP15 148
-# define GOST_F_MAGMA_CIPHER_CTL 162
-# define GOST_F_MAGMA_CIPHER_CTL_ACPKM_OMAC 163
+# define GOST_F_MAGMA_CIPHER_CTL 163
+# define GOST_F_MAGMA_CIPHER_CTL_ACPKM_OMAC 164
+# define GOST_F_MAGMA_CIPHER_INIT_CTR_ACPKM_OMAC 165
# define GOST_F_OMAC_ACPKM_IMIT_CTRL 144
# define GOST_F_OMAC_ACPKM_IMIT_FINAL 145
# define GOST_F_OMAC_ACPKM_IMIT_UPDATE 146
GOSTerr(GOST_F_GOST_CMS_SET_SHARED_INFO, GOST_R_UNSUPPORTED_RECIPIENT_INFO);
return 0;
}
+
+static ASN1_STRING *gost_encode_cms_params(int ka_nid)
+{
+ ASN1_STRING *ret = NULL;
+ ASN1_STRING *params = ASN1_STRING_new();
+
+ /* It's a hack. We have only one OID here, so we can use
+ * GOST_KEY_PARAMS which is a sequence of 3 OIDs,
+ * the 1st one is mandatory and the rest are optional */
+ GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
+
+ if (params == NULL || gkp == NULL) {
+ GOSTerr(GOST_F_GOST_ENCODE_CMS_PARAMS, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+
+ gkp->key_params = OBJ_nid2obj(ka_nid);
+ params->length = i2d_GOST_KEY_PARAMS(gkp, ¶ms->data);
+
+ if (params->length < 0) {
+ GOSTerr(GOST_F_GOST_ENCODE_CMS_PARAMS, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+
+ params->type = V_ASN1_SEQUENCE;
+ ret = params;
+
+end:
+ GOST_KEY_PARAMS_free(gkp);
+
+ if (ret == NULL)
+ ASN1_STRING_free(params);
+
+ return ret;
+}
+
/*
* Control function
*/
#ifndef OPENSSL_NO_CMS
case ASN1_PKEY_CTRL_CMS_ENVELOPE:
if (arg1 == 0) {
- ASN1_STRING *params = encode_gost_algor_params(pkey);
- if (!params) {
- return -1;
- }
- CMS_RecipientInfo_ktri_get0_algs((CMS_RecipientInfo *)arg2, NULL,
- NULL, &alg1);
- X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_id(pkey)),
- V_ASN1_SEQUENCE, params);
+ EVP_PKEY_CTX *pctx;
+ CMS_RecipientInfo *ri = arg2;
+
+ struct gost_pmeth_data *gctx = NULL;
+ ASN1_STRING *params = NULL;
+
+ pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+ if (!pctx)
+ return 0;
+
+ gctx = EVP_PKEY_CTX_get_data(pctx);
+
+ switch (gctx->cipher_nid) {
+ case NID_magma_ctr:
+ case NID_kuznyechik_ctr:
+ {
+ int ka_nid;
+
+ nid = (gctx->cipher_nid == NID_magma_ctr) ? NID_magma_kexp15 :
+ NID_kuznyechik_kexp15;
+
+ ka_nid = (EVP_PKEY_base_id(pkey) == NID_id_GostR3410_2012_256) ?
+ NID_id_tc26_agreement_gost_3410_2012_256 : NID_id_tc26_agreement_gost_3410_2012_512;
+
+ params = gost_encode_cms_params(ka_nid);
+ }
+ break;
+ default:
+ params = encode_gost_algor_params(pkey);
+ break;
+ }
+
+ if (params == NULL)
+ return -1;
+
+ CMS_RecipientInfo_ktri_get0_algs((CMS_RecipientInfo *)arg2, NULL,
+ NULL, &alg1);
+ X509_ALGOR_set0(alg1, OBJ_nid2obj(nid), V_ASN1_SEQUENCE, params);
} else {
EVP_PKEY_CTX *pctx;
CMS_RecipientInfo *ri = arg2;
if (!gost_cipher_set_param(c, NID_id_tc26_gost_28147_param_Z))
return 0;
EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx));
+
+ if (enc) {
+ if (init_zero_kdf_seed(c->kdf_seed) == 0)
+ return -1;
+ }
}
+
if (key)
magma_key(&(c->cctx), key);
if (iv) {
{
if (key) {
struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
- unsigned char keys[64];
- const EVP_MD *md = EVP_get_digestbynid(NID_magma_mac);
- EVP_PKEY *mac_key;
-
- if (md == NULL)
- return 0;
-
- if (enc) {
- if (RAND_bytes(c->kdf_seed, 8) != 1)
- return 0;
- }
-
- if (gost_kdftree2012_256(keys, 64, key, 32, (const unsigned char *)"kdf tree", 8, c->kdf_seed, 8, 1) <= 0)
- return 0;
-
+ unsigned char cipher_key[32];
c->omac_ctx = EVP_MD_CTX_new();
- mac_key = EVP_PKEY_new_mac_key(NID_magma_mac, NULL, keys+32, 32);
- if (mac_key == NULL || c->omac_ctx == NULL) {
- EVP_PKEY_free(mac_key);
- OPENSSL_cleanse(keys, sizeof(keys));
- return 0;
+ if (c->omac_ctx == NULL) {
+ GOSTerr(GOST_F_MAGMA_CIPHER_INIT_CTR_ACPKM_OMAC, ERR_R_MALLOC_FAILURE);
+ return 0;
}
- if (EVP_DigestInit_ex(c->omac_ctx, md, NULL) <= 0 ||
- EVP_DigestSignInit(c->omac_ctx, NULL, md, NULL, mac_key) <= 0) {
- EVP_PKEY_free(mac_key);
- OPENSSL_cleanse(keys, sizeof(keys));
- return 0;
+ if (gost2015_acpkm_omac_init(NID_magma_mac, enc, key,
+ c->omac_ctx, cipher_key, c->kdf_seed) != 1) {
+ EVP_MD_CTX_free(c->omac_ctx);
+ c->omac_ctx = NULL;
+ return 0;
}
- EVP_PKEY_free(mac_key);
- OPENSSL_cleanse(keys + 32, sizeof(keys) - 32);
- return magma_cipher_init(ctx, keys, iv, enc);
+ return magma_cipher_init(ctx, cipher_key, iv, enc);
}
+
return magma_cipher_init(ctx, key, iv, enc);
}
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
int dgst_nid = NID_undef;
- if (!data || !data->shared_ukm) {
+ if (!data || data->shared_ukm_size == 0) {
GOSTerr(GOST_F_PKEY_GOST_EC_DERIVE, GOST_R_UKM_NOT_SET);
return 0;
}
int key_is_ephemeral = 1;
gost_ctx cctx;
EVP_PKEY *sec_key = EVP_PKEY_CTX_get0_peerkey(pctx);
- if (data->shared_ukm) {
+ if (data->shared_ukm_size) {
memcpy(ukm, data->shared_ukm, 8);
} else {
if (RAND_bytes(ukm, 8) <= 0) {
key_is_ephemeral = 1;
}
+ if (data->shared_ukm_size == 0) {
+ if (RAND_bytes(data->shared_ukm, 32) <= 0) {
+ GOSTerr(GOST_F_PKEY_GOST2018_ENCRYPT, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ data->shared_ukm_size = 32;
+ }
+
if (gost_keg(data->shared_ukm, pkey_nid,
EC_KEY_get0_public_key(EVP_PKEY_get0(pubk)),
EVP_PKEY_get0(sec_key), expkeys) <= 0) {
goto err;
}
+ pst->ukm = ASN1_OCTET_STRING_new();
+ if (pst->ukm == NULL) {
+ GOSTerr(GOST_F_PKEY_GOST2018_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!ASN1_OCTET_STRING_set(pst->ukm, data->shared_ukm, data->shared_ukm_size)) {
+ GOSTerr(GOST_F_PKEY_GOST2018_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
if (!ASN1_OCTET_STRING_set(pst->psexp, exp_buf, exp_len)) {
GOSTerr(GOST_F_PKEY_GOST2018_ENCRYPT, ERR_R_MALLOC_FAILURE);
goto err;
int pkey_gost_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out,
size_t *out_len, const unsigned char *key, size_t key_len)
{
- struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx);
- if (data->shared_ukm == NULL || data->shared_ukm_size == 8)
- return pkey_GOST_ECcp_encrypt(pctx, out, out_len, key, key_len);
- else if (data->shared_ukm_size == 32)
- return pkey_gost2018_encrypt(pctx, out, out_len, key, key_len);
- else {
- GOSTerr(GOST_F_PKEY_GOST_ENCRYPT, ERR_R_INTERNAL_ERROR);
- return -1;
- }
+ struct gost_pmeth_data *gctx = EVP_PKEY_CTX_get_data(pctx);
+ switch (gctx->cipher_nid)
+ {
+ case NID_id_Gost28147_89:
+ case NID_undef: /* FIXME */
+ return pkey_GOST_ECcp_encrypt(pctx, out, out_len, key, key_len);
+ break;
+ case NID_kuznyechik_ctr:
+ case NID_magma_ctr:
+ return pkey_gost2018_encrypt(pctx, out, out_len, key, key_len);
+ break;
+ default:
+ GOSTerr(GOST_F_PKEY_GOST_ENCRYPT, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
}
/*
o q * Q_eph is not equal to zero point.
*/
- if (data->shared_ukm == NULL && pst->ukm != NULL) {
+ if (data->shared_ukm_size == 0 && pst->ukm != NULL) {
if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_SET_IV,
ASN1_STRING_length(pst->ukm), (void *)ASN1_STRING_get0_data(pst->ukm)) < 0) {
GOSTerr(GOST_F_PKEY_GOST2018_DECRYPT, GOST_R_UKM_NOT_SET);
}
}
- if (data->shared_ukm == NULL) {
- GOSTerr(GOST_F_PKEY_GOST2018_DECRYPT, GOST_R_UKM_NOT_SET);
- goto err;
- }
-
if (gost_keg(data->shared_ukm, pkey_nid,
EC_KEY_get0_public_key(EVP_PKEY_get0(eph_key)),
EVP_PKEY_get0(priv), expkeys) <= 0) {
size_t *key_len, const unsigned char *in, size_t in_len)
{
struct gost_pmeth_data *gctx = EVP_PKEY_CTX_get_data(pctx);
-#if 0
- if (data->shared_ukm == NULL || data->shared_ukm_size == 8)
- return pkey_GOST_ECcp_decrypt(pctx, key, key_len, in, in_len);
- else if (data->shared_ukm_size == 32)
- return pkey_gost2018_decrypt(pctx, key, key_len, in, in_len);
- else {
- GOSTerr(GOST_F_PKEY_GOST_DECRYPT, ERR_R_INTERNAL_ERROR);
- return -1;
- }
-#else
switch (gctx->cipher_nid)
{
case NID_id_Gost28147_89:
GOSTerr(GOST_F_PKEY_GOST_DECRYPT, ERR_R_INTERNAL_ERROR);
return -1;
}
-#endif
}
#include "gost_gost2015.h"
#include "e_gost_err.h"
#include <string.h>
+#include <openssl/rand.h>
int gost2015_final_call(EVP_CIPHER_CTX *ctx, EVP_MD_CTX *omac_ctx, size_t mac_size,
unsigned char *encrypted_mac,
}
return 1;
}
+
+int gost2015_acpkm_omac_init(int nid, int enc, const unsigned char *inkey,
+ EVP_MD_CTX *omac_ctx,
+ unsigned char *outkey, unsigned char *kdf_seed)
+{
+ int ret = 0;
+ unsigned char keys[64];
+ const EVP_MD *md = EVP_get_digestbynid(nid);
+ EVP_PKEY *mac_key;
+
+ if (md == NULL)
+ return 0;
+
+ if (enc) {
+ if (RAND_bytes(kdf_seed, 8) != 1)
+ return 0;
+ }
+
+ if (gost_kdftree2012_256(keys, 64, inkey, 32, (const unsigned char *)"kdf tree", 8, kdf_seed, 8, 1) <= 0)
+ return 0;
+
+ mac_key = EVP_PKEY_new_mac_key(nid, NULL, keys+32, 32);
+
+ if (mac_key == NULL)
+ goto end;
+
+ if (EVP_DigestInit_ex(omac_ctx, md, NULL) <= 0 ||
+ EVP_DigestSignInit(omac_ctx, NULL, md, NULL, mac_key) <= 0)
+ goto end;
+
+ memcpy(outkey, keys, 32);
+
+ ret = 1;
+end:
+ EVP_PKEY_free(mac_key);
+ OPENSSL_cleanse(keys, sizeof(keys));
+
+ return ret;
+}
+
+int init_zero_kdf_seed(unsigned char *kdf_seed)
+{
+ int is_zero_kdfseed = 1, i;
+ for (i = 0; i < 8; i++) {
+ if (kdf_seed[i] != 0)
+ is_zero_kdfseed = 0;
+ }
+
+ return is_zero_kdfseed ? RAND_bytes(kdf_seed, 8) : 1;
+}
int gost2015_process_unprotected_attributes(STACK_OF(X509_ATTRIBUTE) *attrs,
int encryption, size_t mac_len, unsigned char *final_tag);
+
+int gost2015_acpkm_omac_init(int nid, int enc, const unsigned char *inkey,
+ EVP_MD_CTX *omac_ctx,
+ unsigned char *outkey, unsigned char *kdf_seed);
+int init_zero_kdf_seed(unsigned char *kdf_seed);
+
#endif
if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) {
EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx));
+ if (enc && c->type == GRASSHOPPER_CIPHER_CTRACPKM) {
+ gost_grasshopper_cipher_ctx_ctr *ctr = EVP_CIPHER_CTX_get_cipher_data(ctx);
+ if (init_zero_kdf_seed(ctr->kdf_seed) == 0)
+ return -1;
+ }
}
if (key != NULL) {
c->section_size = 4096;
if (key) {
- unsigned char keys[64];
- const EVP_MD *md = EVP_get_digestbynid(NID_kuznyechik_mac);
- EVP_PKEY *mac_key;
-
- if (md == NULL)
- return 0;
-
- if (enc) {
- if (RAND_bytes(c->kdf_seed, 8) != 1)
- return 0;
- }
-
- if (gost_kdftree2012_256(keys, 64, key, 32, (const unsigned char *)"kdf tree", 8, c->kdf_seed, 8, 1) <= 0)
- return 0;
-
+ unsigned char cipher_key[32];
c->omac_ctx = EVP_MD_CTX_new();
- mac_key = EVP_PKEY_new_mac_key(NID_kuznyechik_mac, NULL, keys+32, 32);
- if (mac_key == NULL || c->omac_ctx == NULL) {
- EVP_PKEY_free(mac_key);
- return 0;
+ if (c->omac_ctx == NULL) {
+ GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_INIT_CTRACPKM_OMAC, ERR_R_MALLOC_FAILURE);
+ return 0;
}
- if (EVP_DigestInit_ex(c->omac_ctx, md, NULL) <= 0 ||
- EVP_DigestSignInit(c->omac_ctx, NULL, md, NULL, mac_key) <= 0) {
- EVP_PKEY_free(mac_key);
- return 0;
+ if (gost2015_acpkm_omac_init(NID_kuznyechik_mac, enc, key,
+ c->omac_ctx, cipher_key, c->kdf_seed) != 1) {
+ EVP_MD_CTX_free(c->omac_ctx);
+ c->omac_ctx = NULL;
+ return 0;
}
- EVP_PKEY_free(mac_key);
- return gost_grasshopper_cipher_init(ctx, keys, iv, enc);
+ return gost_grasshopper_cipher_init(ctx, cipher_key, iv, enc);
}
+
return gost_grasshopper_cipher_init(ctx, key, iv, enc);
}
int sign_param_nid; /* Should be set whenever parameters are
* filled */
EVP_MD *md;
- unsigned char *shared_ukm;
- size_t shared_ukm_size; /* XXX temporary use shared_ukm and hash for 2018 CKE */
+ unsigned char shared_ukm[32];
+ size_t shared_ukm_size;
int peer_key_used;
int cipher_nid; /* KExp15/KImp15 algs */
};
return 0;
*dst_data = *src_data;
- if (src_data->shared_ukm) {
- dst_data->shared_ukm = NULL;
- }
+
return 1;
}
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
if (!data)
return;
- OPENSSL_free(data->shared_ukm);
OPENSSL_free(data);
}
return 1;
case EVP_PKEY_CTRL_SET_IV:
OPENSSL_assert(p2 != NULL);
- pctx->shared_ukm = OPENSSL_malloc((int)p1);
- if (pctx->shared_ukm == NULL) {
- GOSTerr(GOST_F_PKEY_GOST_CTRL, ERR_R_MALLOC_FAILURE);
- return 0;
- }
memcpy(pctx->shared_ukm, p2, (int)p1);
pctx->shared_ukm_size = p1;
return 1;
- case EVP_PKEY_CTRL_CIPHER:
- pctx->cipher_nid = p1;
+ case EVP_PKEY_CTRL_CIPHER:
+ switch (p1) {
+ case NID_magma_ctr_acpkm:
+ case NID_magma_ctr_acpkm_omac:
+ case NID_magma_ctr:
+ pctx->cipher_nid = NID_magma_ctr;
+ return 1;
+ case NID_kuznyechik_ctr_acpkm:
+ case NID_kuznyechik_ctr_acpkm_omac:
+ case NID_kuznyechik_ctr:
+ pctx->cipher_nid = NID_kuznyechik_ctr;
+ return 1;
+ default:
+ pctx->cipher_nid = p1;
+ return 1;
+ }
return 1;
case EVP_PKEY_CTRL_PEER_KEY:
if (p1 == 0 || p1 == 1) /* call from EVP_PKEY_derive_set_peer */