1238384Sjkim/********************************************************************** 2238384Sjkim * gost_crypt.c * 3238384Sjkim * Copyright (c) 2005-2006 Cryptocom LTD * 4238384Sjkim * This file is distributed under the same license as OpenSSL * 5238384Sjkim * * 6238384Sjkim * OpenSSL interface to GOST 28147-89 cipher functions * 7238384Sjkim * Requires OpenSSL 0.9.9 for compilation * 8238384Sjkim **********************************************************************/ 9238384Sjkim#include <string.h> 10238384Sjkim#include "gost89.h" 11238384Sjkim#include <openssl/rand.h> 12238384Sjkim#include "e_gost_err.h" 13238384Sjkim#include "gost_lcl.h" 14246772Sjkim 15246772Sjkim#if !defined(CCGOST_DEBUG) && !defined(DEBUG) 16246772Sjkim# ifndef NDEBUG 17246772Sjkim# define NDEBUG 18246772Sjkim# endif 19246772Sjkim#endif 20246772Sjkim#include <assert.h> 21246772Sjkim 22280304Sjkimstatic int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 23280304Sjkim const unsigned char *iv, int enc); 24280304Sjkimstatic int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key, 25280304Sjkim const unsigned char *iv, int enc); 26280304Sjkim/* Handles block of data in CFB mode */ 27280304Sjkimstatic int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, 28280304Sjkim const unsigned char *in, size_t inl); 29280304Sjkim/* Handles block of data in CNT mode */ 30280304Sjkimstatic int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, 31280304Sjkim const unsigned char *in, size_t inl); 32280304Sjkim/* Cleanup function */ 33238384Sjkimstatic int gost_cipher_cleanup(EVP_CIPHER_CTX *); 34238384Sjkim/* set/get cipher parameters */ 35280304Sjkimstatic int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params); 36280304Sjkimstatic int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params); 37238384Sjkim/* Control function */ 38280304Sjkimstatic int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); 39238384Sjkim 40280304SjkimEVP_CIPHER cipher_gost = { 41280304Sjkim NID_id_Gost28147_89, 42280304Sjkim 1, /* block_size */ 43280304Sjkim 32, /* key_size */ 44280304Sjkim 8, /* iv_len */ 45280304Sjkim EVP_CIPH_CFB_MODE | EVP_CIPH_NO_PADDING | 46280304Sjkim EVP_CIPH_CUSTOM_IV | EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT, 47280304Sjkim gost_cipher_init, 48280304Sjkim gost_cipher_do_cfb, 49280304Sjkim gost_cipher_cleanup, 50280304Sjkim sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */ 51280304Sjkim gost89_set_asn1_parameters, 52280304Sjkim gost89_get_asn1_parameters, 53280304Sjkim gost_cipher_ctl, 54280304Sjkim NULL, 55280304Sjkim}; 56238384Sjkim 57280304SjkimEVP_CIPHER cipher_gost_cpacnt = { 58280304Sjkim NID_gost89_cnt, 59280304Sjkim 1, /* block_size */ 60280304Sjkim 32, /* key_size */ 61280304Sjkim 8, /* iv_len */ 62280304Sjkim EVP_CIPH_OFB_MODE | EVP_CIPH_NO_PADDING | 63280304Sjkim EVP_CIPH_CUSTOM_IV | EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT, 64280304Sjkim gost_cipher_init_cpa, 65280304Sjkim gost_cipher_do_cnt, 66280304Sjkim gost_cipher_cleanup, 67280304Sjkim sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */ 68280304Sjkim gost89_set_asn1_parameters, 69280304Sjkim gost89_get_asn1_parameters, 70280304Sjkim gost_cipher_ctl, 71280304Sjkim NULL, 72280304Sjkim}; 73238384Sjkim 74238384Sjkim/* Implementation of GOST 28147-89 in MAC (imitovstavka) mode */ 75238384Sjkim/* Init functions which set specific parameters */ 76238384Sjkimstatic int gost_imit_init_cpa(EVP_MD_CTX *ctx); 77238384Sjkim/* process block of data */ 78238384Sjkimstatic int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count); 79238384Sjkim/* Return computed value */ 80280304Sjkimstatic int gost_imit_final(EVP_MD_CTX *ctx, unsigned char *md); 81238384Sjkim/* Copies context */ 82280304Sjkimstatic int gost_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from); 83238384Sjkimstatic int gost_imit_cleanup(EVP_MD_CTX *ctx); 84238384Sjkim/* Control function, knows how to set MAC key.*/ 85280304Sjkimstatic int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr); 86238384Sjkim 87280304SjkimEVP_MD imit_gost_cpa = { 88280304Sjkim NID_id_Gost28147_89_MAC, 89280304Sjkim NID_undef, 90280304Sjkim 4, 91280304Sjkim 0, 92280304Sjkim gost_imit_init_cpa, 93280304Sjkim gost_imit_update, 94280304Sjkim gost_imit_final, 95280304Sjkim gost_imit_copy, 96280304Sjkim gost_imit_cleanup, 97280304Sjkim NULL, 98280304Sjkim NULL, 99280304Sjkim {0, 0, 0, 0, 0}, 100280304Sjkim 8, 101280304Sjkim sizeof(struct ossl_gost_imit_ctx), 102280304Sjkim gost_imit_ctrl 103280304Sjkim}; 104238384Sjkim 105280304Sjkim/* 106238384Sjkim * Correspondence between gost parameter OIDs and substitution blocks 107238384Sjkim * NID field is filed by register_gost_NID function in engine.c 108238384Sjkim * upon engine initialization 109238384Sjkim */ 110238384Sjkim 111280304Sjkimstruct gost_cipher_info gost_cipher_list[] = { 112280304Sjkim /*- NID *//* 113280304Sjkim * Subst block 114280304Sjkim *//* 115280304Sjkim * Key meshing 116280304Sjkim */ 117280304Sjkim /* 118280304Sjkim * {NID_id_GostR3411_94_CryptoProParamSet,&GostR3411_94_CryptoProParamSet,0}, 119280304Sjkim */ 120280304Sjkim {NID_id_Gost28147_89_cc, &GostR3411_94_CryptoProParamSet, 0}, 121280304Sjkim {NID_id_Gost28147_89_CryptoPro_A_ParamSet, &Gost28147_CryptoProParamSetA, 122280304Sjkim 1}, 123280304Sjkim {NID_id_Gost28147_89_CryptoPro_B_ParamSet, &Gost28147_CryptoProParamSetB, 124280304Sjkim 1}, 125280304Sjkim {NID_id_Gost28147_89_CryptoPro_C_ParamSet, &Gost28147_CryptoProParamSetC, 126280304Sjkim 1}, 127280304Sjkim {NID_id_Gost28147_89_CryptoPro_D_ParamSet, &Gost28147_CryptoProParamSetD, 128280304Sjkim 1}, 129280304Sjkim {NID_id_Gost28147_89_TestParamSet, &Gost28147_TestParamSet, 1}, 130280304Sjkim {NID_undef, NULL, 0} 131280304Sjkim}; 132238384Sjkim 133280304Sjkim/* 134280304Sjkim * get encryption parameters from crypto network settings FIXME For now we 135280304Sjkim * use environment var CRYPT_PARAMS as place to store these settings. 136280304Sjkim * Actually, it is better to use engine control command, read from 137280304Sjkim * configuration file to set them 138280304Sjkim */ 139238384Sjkimconst struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj) 140280304Sjkim{ 141280304Sjkim int nid; 142280304Sjkim struct gost_cipher_info *param; 143280304Sjkim if (!obj) { 144280304Sjkim const char *params = get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS); 145280304Sjkim if (!params || !strlen(params)) 146280304Sjkim return &gost_cipher_list[1]; 147238384Sjkim 148280304Sjkim nid = OBJ_txt2nid(params); 149280304Sjkim if (nid == NID_undef) { 150280304Sjkim GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS, 151280304Sjkim GOST_R_INVALID_CIPHER_PARAM_OID); 152280304Sjkim return NULL; 153280304Sjkim } 154280304Sjkim } else { 155280304Sjkim nid = OBJ_obj2nid(obj); 156280304Sjkim } 157280304Sjkim for (param = gost_cipher_list; param->sblock != NULL && param->nid != nid; 158280304Sjkim param++) ; 159280304Sjkim if (!param->sblock) { 160280304Sjkim GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS, GOST_R_INVALID_CIPHER_PARAMS); 161280304Sjkim return NULL; 162280304Sjkim } 163280304Sjkim return param; 164280304Sjkim} 165238384Sjkim 166238384Sjkim/* Sets cipher param from paramset NID. */ 167280304Sjkimstatic int gost_cipher_set_param(struct ossl_gost_cipher_ctx *c, int nid) 168280304Sjkim{ 169280304Sjkim const struct gost_cipher_info *param; 170280304Sjkim param = 171280304Sjkim get_encryption_params((nid == NID_undef ? NULL : OBJ_nid2obj(nid))); 172280304Sjkim if (!param) 173280304Sjkim return 0; 174238384Sjkim 175280304Sjkim c->paramNID = param->nid; 176280304Sjkim c->key_meshing = param->key_meshing; 177280304Sjkim c->count = 0; 178280304Sjkim gost_init(&(c->cctx), param->sblock); 179280304Sjkim return 1; 180280304Sjkim} 181280304Sjkim 182238384Sjkim/* Initializes EVP_CIPHER_CTX by paramset NID */ 183280304Sjkimstatic int gost_cipher_init_param(EVP_CIPHER_CTX *ctx, 184280304Sjkim const unsigned char *key, 185280304Sjkim const unsigned char *iv, int enc, 186280304Sjkim int paramNID, int mode) 187280304Sjkim{ 188280304Sjkim struct ossl_gost_cipher_ctx *c = ctx->cipher_data; 189280304Sjkim if (ctx->app_data == NULL) { 190280304Sjkim if (!gost_cipher_set_param(c, paramNID)) 191280304Sjkim return 0; 192280304Sjkim ctx->app_data = ctx->cipher_data; 193280304Sjkim } 194280304Sjkim if (key) 195280304Sjkim gost_key(&(c->cctx), key); 196280304Sjkim if (iv) 197280304Sjkim memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); 198280304Sjkim memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); 199280304Sjkim return 1; 200280304Sjkim} 201238384Sjkim 202238384Sjkimstatic int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key, 203280304Sjkim const unsigned char *iv, int enc) 204280304Sjkim{ 205280304Sjkim struct ossl_gost_cipher_ctx *c = ctx->cipher_data; 206280304Sjkim gost_init(&(c->cctx), &Gost28147_CryptoProParamSetA); 207280304Sjkim c->key_meshing = 1; 208280304Sjkim c->count = 0; 209280304Sjkim if (key) 210280304Sjkim gost_key(&(c->cctx), key); 211280304Sjkim if (iv) 212280304Sjkim memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); 213280304Sjkim memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); 214280304Sjkim return 1; 215280304Sjkim} 216238384Sjkim 217238384Sjkim/* Initializes EVP_CIPHER_CTX with default values */ 218238384Sjkimint gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 219280304Sjkim const unsigned char *iv, int enc) 220280304Sjkim{ 221280304Sjkim return gost_cipher_init_param(ctx, key, iv, enc, NID_undef, 222280304Sjkim EVP_CIPH_CFB_MODE); 223280304Sjkim} 224280304Sjkim 225280304Sjkim/* 226280304Sjkim * Wrapper around gostcrypt function from gost89.c which perform key meshing 227280304Sjkim * when nesseccary 228238384Sjkim */ 229280304Sjkimstatic void gost_crypt_mesh(void *ctx, unsigned char *iv, unsigned char *buf) 230280304Sjkim{ 231280304Sjkim struct ossl_gost_cipher_ctx *c = ctx; 232280304Sjkim assert(c->count % 8 == 0 && c->count <= 1024); 233280304Sjkim if (c->key_meshing && c->count == 1024) { 234280304Sjkim cryptopro_key_meshing(&(c->cctx), iv); 235280304Sjkim } 236280304Sjkim gostcrypt(&(c->cctx), iv, buf); 237280304Sjkim c->count = c->count % 1024 + 8; 238280304Sjkim} 239238384Sjkim 240280304Sjkimstatic void gost_cnt_next(void *ctx, unsigned char *iv, unsigned char *buf) 241280304Sjkim{ 242280304Sjkim struct ossl_gost_cipher_ctx *c = ctx; 243280304Sjkim word32 g, go; 244280304Sjkim unsigned char buf1[8]; 245280304Sjkim assert(c->count % 8 == 0 && c->count <= 1024); 246280304Sjkim if (c->key_meshing && c->count == 1024) { 247280304Sjkim cryptopro_key_meshing(&(c->cctx), iv); 248280304Sjkim } 249280304Sjkim if (c->count == 0) { 250280304Sjkim gostcrypt(&(c->cctx), iv, buf1); 251280304Sjkim } else { 252280304Sjkim memcpy(buf1, iv, 8); 253280304Sjkim } 254280304Sjkim g = buf1[0] | (buf1[1] << 8) | (buf1[2] << 16) | (buf1[3] << 24); 255280304Sjkim g += 0x01010101; 256280304Sjkim buf1[0] = (unsigned char)(g & 0xff); 257280304Sjkim buf1[1] = (unsigned char)((g >> 8) & 0xff); 258280304Sjkim buf1[2] = (unsigned char)((g >> 16) & 0xff); 259280304Sjkim buf1[3] = (unsigned char)((g >> 24) & 0xff); 260280304Sjkim g = buf1[4] | (buf1[5] << 8) | (buf1[6] << 16) | (buf1[7] << 24); 261280304Sjkim go = g; 262280304Sjkim g += 0x01010104; 263280304Sjkim if (go > g) /* overflow */ 264280304Sjkim g++; 265280304Sjkim buf1[4] = (unsigned char)(g & 0xff); 266280304Sjkim buf1[5] = (unsigned char)((g >> 8) & 0xff); 267280304Sjkim buf1[6] = (unsigned char)((g >> 16) & 0xff); 268280304Sjkim buf1[7] = (unsigned char)((g >> 24) & 0xff); 269280304Sjkim memcpy(iv, buf1, 8); 270280304Sjkim gostcrypt(&(c->cctx), buf1, buf); 271280304Sjkim c->count = c->count % 1024 + 8; 272280304Sjkim} 273238384Sjkim 274238384Sjkim/* GOST encryption in CFB mode */ 275280304Sjkimint gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, 276280304Sjkim const unsigned char *in, size_t inl) 277280304Sjkim{ 278280304Sjkim const unsigned char *in_ptr = in; 279280304Sjkim unsigned char *out_ptr = out; 280280304Sjkim size_t i = 0; 281280304Sjkim size_t j = 0; 282238384Sjkim/* process partial block if any */ 283280304Sjkim if (ctx->num) { 284280304Sjkim for (j = ctx->num, i = 0; j < 8 && i < inl; 285280304Sjkim j++, i++, in_ptr++, out_ptr++) { 286280304Sjkim if (!ctx->encrypt) 287280304Sjkim ctx->buf[j + 8] = *in_ptr; 288280304Sjkim *out_ptr = ctx->buf[j] ^ (*in_ptr); 289280304Sjkim if (ctx->encrypt) 290280304Sjkim ctx->buf[j + 8] = *out_ptr; 291280304Sjkim } 292280304Sjkim if (j == 8) { 293280304Sjkim memcpy(ctx->iv, ctx->buf + 8, 8); 294280304Sjkim ctx->num = 0; 295280304Sjkim } else { 296280304Sjkim ctx->num = j; 297280304Sjkim return 1; 298280304Sjkim } 299280304Sjkim } 300238384Sjkim 301280304Sjkim for (; i + 8 < inl; i += 8, in_ptr += 8, out_ptr += 8) { 302280304Sjkim /* 303280304Sjkim * block cipher current iv 304280304Sjkim */ 305280304Sjkim gost_crypt_mesh(ctx->cipher_data, ctx->iv, ctx->buf); 306280304Sjkim /* 307280304Sjkim * xor next block of input text with it and output it 308280304Sjkim */ 309280304Sjkim /* 310280304Sjkim * output this block 311280304Sjkim */ 312280304Sjkim if (!ctx->encrypt) 313280304Sjkim memcpy(ctx->iv, in_ptr, 8); 314280304Sjkim for (j = 0; j < 8; j++) { 315280304Sjkim out_ptr[j] = ctx->buf[j] ^ in_ptr[j]; 316280304Sjkim } 317280304Sjkim /* Encrypt */ 318280304Sjkim /* Next iv is next block of cipher text */ 319280304Sjkim if (ctx->encrypt) 320280304Sjkim memcpy(ctx->iv, out_ptr, 8); 321280304Sjkim } 322238384Sjkim/* Process rest of buffer */ 323280304Sjkim if (i < inl) { 324280304Sjkim gost_crypt_mesh(ctx->cipher_data, ctx->iv, ctx->buf); 325280304Sjkim if (!ctx->encrypt) 326280304Sjkim memcpy(ctx->buf + 8, in_ptr, inl - i); 327280304Sjkim for (j = 0; i < inl; j++, i++) { 328280304Sjkim out_ptr[j] = ctx->buf[j] ^ in_ptr[j]; 329280304Sjkim } 330280304Sjkim ctx->num = j; 331280304Sjkim if (ctx->encrypt) 332280304Sjkim memcpy(ctx->buf + 8, out_ptr, j); 333280304Sjkim } else { 334280304Sjkim ctx->num = 0; 335280304Sjkim } 336280304Sjkim return 1; 337280304Sjkim} 338238384Sjkim 339238384Sjkimstatic int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, 340280304Sjkim const unsigned char *in, size_t inl) 341280304Sjkim{ 342280304Sjkim const unsigned char *in_ptr = in; 343280304Sjkim unsigned char *out_ptr = out; 344280304Sjkim size_t i = 0; 345280304Sjkim size_t j; 346238384Sjkim/* process partial block if any */ 347280304Sjkim if (ctx->num) { 348280304Sjkim for (j = ctx->num, i = 0; j < 8 && i < inl; 349280304Sjkim j++, i++, in_ptr++, out_ptr++) { 350280304Sjkim *out_ptr = ctx->buf[j] ^ (*in_ptr); 351280304Sjkim } 352280304Sjkim if (j == 8) { 353280304Sjkim ctx->num = 0; 354280304Sjkim } else { 355280304Sjkim ctx->num = j; 356280304Sjkim return 1; 357280304Sjkim } 358280304Sjkim } 359238384Sjkim 360280304Sjkim for (; i + 8 < inl; i += 8, in_ptr += 8, out_ptr += 8) { 361280304Sjkim /* 362280304Sjkim * block cipher current iv 363280304Sjkim */ 364280304Sjkim /* Encrypt */ 365280304Sjkim gost_cnt_next(ctx->cipher_data, ctx->iv, ctx->buf); 366280304Sjkim /* 367280304Sjkim * xor next block of input text with it and output it 368280304Sjkim */ 369280304Sjkim /* 370280304Sjkim * output this block 371280304Sjkim */ 372280304Sjkim for (j = 0; j < 8; j++) { 373280304Sjkim out_ptr[j] = ctx->buf[j] ^ in_ptr[j]; 374280304Sjkim } 375280304Sjkim } 376238384Sjkim/* Process rest of buffer */ 377280304Sjkim if (i < inl) { 378280304Sjkim gost_cnt_next(ctx->cipher_data, ctx->iv, ctx->buf); 379280304Sjkim for (j = 0; i < inl; j++, i++) { 380280304Sjkim out_ptr[j] = ctx->buf[j] ^ in_ptr[j]; 381280304Sjkim } 382280304Sjkim ctx->num = j; 383280304Sjkim } else { 384280304Sjkim ctx->num = 0; 385280304Sjkim } 386280304Sjkim return 1; 387280304Sjkim} 388238384Sjkim 389238384Sjkim/* Cleaning up of EVP_CIPHER_CTX */ 390280304Sjkimint gost_cipher_cleanup(EVP_CIPHER_CTX *ctx) 391280304Sjkim{ 392280304Sjkim gost_destroy(&((struct ossl_gost_cipher_ctx *)ctx->cipher_data)->cctx); 393280304Sjkim ctx->app_data = NULL; 394280304Sjkim return 1; 395280304Sjkim} 396238384Sjkim 397238384Sjkim/* Control function for gost cipher */ 398280304Sjkimint gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) 399280304Sjkim{ 400280304Sjkim switch (type) { 401280304Sjkim case EVP_CTRL_RAND_KEY: 402280304Sjkim { 403280304Sjkim if (RAND_bytes((unsigned char *)ptr, ctx->key_len) <= 0) { 404280304Sjkim GOSTerr(GOST_F_GOST_CIPHER_CTL, 405280304Sjkim GOST_R_RANDOM_GENERATOR_ERROR); 406280304Sjkim return -1; 407280304Sjkim } 408280304Sjkim break; 409280304Sjkim } 410280304Sjkim case EVP_CTRL_PBE_PRF_NID: 411280304Sjkim if (ptr) { 412280304Sjkim *((int *)ptr) = NID_id_HMACGostR3411_94; 413280304Sjkim return 1; 414280304Sjkim } else { 415280304Sjkim return 0; 416280304Sjkim } 417238384Sjkim 418280304Sjkim default: 419280304Sjkim GOSTerr(GOST_F_GOST_CIPHER_CTL, 420280304Sjkim GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND); 421280304Sjkim return -1; 422280304Sjkim } 423280304Sjkim return 1; 424280304Sjkim} 425280304Sjkim 426238384Sjkim/* Set cipher parameters from ASN1 structure */ 427280304Sjkimint gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) 428280304Sjkim{ 429280304Sjkim int len = 0; 430280304Sjkim unsigned char *buf = NULL; 431280304Sjkim unsigned char *p = NULL; 432280304Sjkim struct ossl_gost_cipher_ctx *c = ctx->cipher_data; 433280304Sjkim GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new(); 434280304Sjkim ASN1_OCTET_STRING *os = NULL; 435280304Sjkim if (!gcp) { 436280304Sjkim GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); 437280304Sjkim return 0; 438280304Sjkim } 439280304Sjkim if (!ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len)) { 440280304Sjkim GOST_CIPHER_PARAMS_free(gcp); 441280304Sjkim GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); 442280304Sjkim return 0; 443280304Sjkim } 444280304Sjkim ASN1_OBJECT_free(gcp->enc_param_set); 445280304Sjkim gcp->enc_param_set = OBJ_nid2obj(c->paramNID); 446238384Sjkim 447280304Sjkim len = i2d_GOST_CIPHER_PARAMS(gcp, NULL); 448280304Sjkim p = buf = (unsigned char *)OPENSSL_malloc(len); 449280304Sjkim if (!buf) { 450280304Sjkim GOST_CIPHER_PARAMS_free(gcp); 451280304Sjkim GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); 452280304Sjkim return 0; 453280304Sjkim } 454280304Sjkim i2d_GOST_CIPHER_PARAMS(gcp, &p); 455280304Sjkim GOST_CIPHER_PARAMS_free(gcp); 456238384Sjkim 457280304Sjkim os = ASN1_OCTET_STRING_new(); 458238384Sjkim 459280304Sjkim if (!os || !ASN1_OCTET_STRING_set(os, buf, len)) { 460280304Sjkim OPENSSL_free(buf); 461280304Sjkim GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); 462280304Sjkim return 0; 463280304Sjkim } 464280304Sjkim OPENSSL_free(buf); 465238384Sjkim 466280304Sjkim ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os); 467280304Sjkim return 1; 468280304Sjkim} 469238384Sjkim 470238384Sjkim/* Store parameters into ASN1 structure */ 471280304Sjkimint gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) 472280304Sjkim{ 473280304Sjkim int ret = -1; 474280304Sjkim int len; 475280304Sjkim GOST_CIPHER_PARAMS *gcp = NULL; 476280304Sjkim unsigned char *p; 477280304Sjkim struct ossl_gost_cipher_ctx *c = ctx->cipher_data; 478280304Sjkim if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) { 479280304Sjkim return ret; 480280304Sjkim } 481238384Sjkim 482280304Sjkim p = params->value.sequence->data; 483238384Sjkim 484280304Sjkim gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p, 485280304Sjkim params->value.sequence->length); 486238384Sjkim 487280304Sjkim len = gcp->iv->length; 488280304Sjkim if (len != ctx->cipher->iv_len) { 489280304Sjkim GOST_CIPHER_PARAMS_free(gcp); 490280304Sjkim GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS, GOST_R_INVALID_IV_LENGTH); 491280304Sjkim return -1; 492280304Sjkim } 493280304Sjkim if (!gost_cipher_set_param(c, OBJ_obj2nid(gcp->enc_param_set))) { 494280304Sjkim GOST_CIPHER_PARAMS_free(gcp); 495280304Sjkim return -1; 496280304Sjkim } 497280304Sjkim memcpy(ctx->oiv, gcp->iv->data, len); 498238384Sjkim 499280304Sjkim GOST_CIPHER_PARAMS_free(gcp); 500238384Sjkim 501280304Sjkim return 1; 502280304Sjkim} 503238384Sjkim 504238384Sjkimint gost_imit_init_cpa(EVP_MD_CTX *ctx) 505280304Sjkim{ 506280304Sjkim struct ossl_gost_imit_ctx *c = ctx->md_data; 507280304Sjkim memset(c->buffer, 0, sizeof(c->buffer)); 508280304Sjkim memset(c->partial_block, 0, sizeof(c->partial_block)); 509280304Sjkim c->count = 0; 510280304Sjkim c->bytes_left = 0; 511280304Sjkim c->key_meshing = 1; 512280304Sjkim gost_init(&(c->cctx), &Gost28147_CryptoProParamSetA); 513280304Sjkim return 1; 514280304Sjkim} 515238384Sjkim 516280304Sjkimstatic void mac_block_mesh(struct ossl_gost_imit_ctx *c, 517280304Sjkim const unsigned char *data) 518280304Sjkim{ 519280304Sjkim unsigned char buffer[8]; 520280304Sjkim /* 521280304Sjkim * We are using local buffer for iv because CryptoPro doesn't interpret 522280304Sjkim * internal state of MAC algorithm as iv during keymeshing (but does 523280304Sjkim * initialize internal state from iv in key transport 524280304Sjkim */ 525280304Sjkim assert(c->count % 8 == 0 && c->count <= 1024); 526280304Sjkim if (c->key_meshing && c->count == 1024) { 527280304Sjkim cryptopro_key_meshing(&(c->cctx), buffer); 528280304Sjkim } 529280304Sjkim mac_block(&(c->cctx), c->buffer, data); 530280304Sjkim c->count = c->count % 1024 + 8; 531280304Sjkim} 532238384Sjkim 533238384Sjkimint gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count) 534280304Sjkim{ 535280304Sjkim struct ossl_gost_imit_ctx *c = ctx->md_data; 536280304Sjkim const unsigned char *p = data; 537280304Sjkim size_t bytes = count, i; 538280304Sjkim if (!(c->key_set)) { 539280304Sjkim GOSTerr(GOST_F_GOST_IMIT_UPDATE, GOST_R_MAC_KEY_NOT_SET); 540280304Sjkim return 0; 541280304Sjkim } 542280304Sjkim if (c->bytes_left) { 543280304Sjkim for (i = c->bytes_left; i < 8 && bytes > 0; bytes--, i++, p++) { 544280304Sjkim c->partial_block[i] = *p; 545280304Sjkim } 546280304Sjkim if (i == 8) { 547280304Sjkim mac_block_mesh(c, c->partial_block); 548280304Sjkim } else { 549280304Sjkim c->bytes_left = i; 550280304Sjkim return 1; 551280304Sjkim } 552280304Sjkim } 553280304Sjkim while (bytes > 8) { 554280304Sjkim mac_block_mesh(c, p); 555280304Sjkim p += 8; 556280304Sjkim bytes -= 8; 557280304Sjkim } 558280304Sjkim if (bytes > 0) { 559280304Sjkim memcpy(c->partial_block, p, bytes); 560280304Sjkim } 561280304Sjkim c->bytes_left = bytes; 562280304Sjkim return 1; 563280304Sjkim} 564238384Sjkim 565280304Sjkimint gost_imit_final(EVP_MD_CTX *ctx, unsigned char *md) 566280304Sjkim{ 567280304Sjkim struct ossl_gost_imit_ctx *c = ctx->md_data; 568280304Sjkim if (!c->key_set) { 569280304Sjkim GOSTerr(GOST_F_GOST_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET); 570280304Sjkim return 0; 571280304Sjkim } 572280304Sjkim if (c->count == 0 && c->bytes_left) { 573280304Sjkim unsigned char buffer[8]; 574280304Sjkim memset(buffer, 0, 8); 575280304Sjkim gost_imit_update(ctx, buffer, 8); 576280304Sjkim } 577280304Sjkim if (c->bytes_left) { 578280304Sjkim int i; 579280304Sjkim for (i = c->bytes_left; i < 8; i++) { 580280304Sjkim c->partial_block[i] = 0; 581280304Sjkim } 582280304Sjkim mac_block_mesh(c, c->partial_block); 583280304Sjkim } 584280304Sjkim get_mac(c->buffer, 32, md); 585280304Sjkim return 1; 586280304Sjkim} 587238384Sjkim 588280304Sjkimint gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr) 589280304Sjkim{ 590280304Sjkim switch (type) { 591280304Sjkim case EVP_MD_CTRL_KEY_LEN: 592280304Sjkim *((unsigned int *)(ptr)) = 32; 593280304Sjkim return 1; 594280304Sjkim case EVP_MD_CTRL_SET_KEY: 595280304Sjkim { 596280304Sjkim if (arg != 32) { 597280304Sjkim GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_LENGTH); 598280304Sjkim return 0; 599280304Sjkim } 600238384Sjkim 601280304Sjkim gost_key(&(((struct ossl_gost_imit_ctx *)(ctx->md_data))->cctx), 602280304Sjkim ptr); 603280304Sjkim ((struct ossl_gost_imit_ctx *)(ctx->md_data))->key_set = 1; 604280304Sjkim return 1; 605238384Sjkim 606280304Sjkim } 607280304Sjkim default: 608280304Sjkim return 0; 609280304Sjkim } 610280304Sjkim} 611238384Sjkim 612280304Sjkimint gost_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) 613280304Sjkim{ 614280304Sjkim memcpy(to->md_data, from->md_data, sizeof(struct ossl_gost_imit_ctx)); 615280304Sjkim return 1; 616280304Sjkim} 617238384Sjkim 618238384Sjkim/* Clean up imit ctx */ 619238384Sjkimint gost_imit_cleanup(EVP_MD_CTX *ctx) 620280304Sjkim{ 621280304Sjkim memset(ctx->md_data, 0, sizeof(struct ossl_gost_imit_ctx)); 622280304Sjkim return 1; 623280304Sjkim} 624