gost_crypt.c revision 246772
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 22238384Sjkimstatic int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 23238384Sjkim const unsigned char *iv, int enc); 24238384Sjkimstatic int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key, 25238384Sjkim const unsigned char *iv, int enc); 26238384Sjkim/* Handles block of data in CFB mode */ 27238384Sjkimstatic int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, 28238384Sjkim const unsigned char *in, size_t inl); 29238384Sjkim/* Handles block of data in CNT mode */ 30238384Sjkimstatic int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, 31238384Sjkim const unsigned char *in, size_t inl); 32238384Sjkim/* Cleanup function */ 33238384Sjkimstatic int gost_cipher_cleanup(EVP_CIPHER_CTX *); 34238384Sjkim/* set/get cipher parameters */ 35238384Sjkimstatic int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params); 36238384Sjkimstatic int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params); 37238384Sjkim/* Control function */ 38238384Sjkimstatic int gost_cipher_ctl(EVP_CIPHER_CTX *ctx,int type,int arg,void *ptr); 39238384Sjkim 40238384SjkimEVP_CIPHER cipher_gost = 41238384Sjkim { 42238384Sjkim NID_id_Gost28147_89, 43238384Sjkim 1,/*block_size*/ 44238384Sjkim 32,/*key_size*/ 45238384Sjkim 8,/*iv_len */ 46238384Sjkim EVP_CIPH_CFB_MODE| EVP_CIPH_NO_PADDING | 47238384Sjkim EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT, 48238384Sjkim gost_cipher_init, 49238384Sjkim gost_cipher_do_cfb, 50238384Sjkim gost_cipher_cleanup, 51238384Sjkim sizeof(struct ossl_gost_cipher_ctx),/* ctx_size */ 52238384Sjkim gost89_set_asn1_parameters, 53238384Sjkim gost89_get_asn1_parameters, 54238384Sjkim gost_cipher_ctl, 55238384Sjkim NULL, 56238384Sjkim }; 57238384Sjkim 58238384SjkimEVP_CIPHER cipher_gost_cpacnt = 59238384Sjkim { 60238384Sjkim NID_gost89_cnt, 61238384Sjkim 1,/*block_size*/ 62238384Sjkim 32,/*key_size*/ 63238384Sjkim 8,/*iv_len */ 64238384Sjkim EVP_CIPH_OFB_MODE| EVP_CIPH_NO_PADDING | 65238384Sjkim EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT, 66238384Sjkim gost_cipher_init_cpa, 67238384Sjkim gost_cipher_do_cnt, 68238384Sjkim gost_cipher_cleanup, 69238384Sjkim sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */ 70238384Sjkim gost89_set_asn1_parameters, 71238384Sjkim gost89_get_asn1_parameters, 72238384Sjkim gost_cipher_ctl, 73238384Sjkim NULL, 74238384Sjkim }; 75238384Sjkim 76238384Sjkim/* Implementation of GOST 28147-89 in MAC (imitovstavka) mode */ 77238384Sjkim/* Init functions which set specific parameters */ 78238384Sjkimstatic int gost_imit_init_cpa(EVP_MD_CTX *ctx); 79238384Sjkim/* process block of data */ 80238384Sjkimstatic int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count); 81238384Sjkim/* Return computed value */ 82238384Sjkimstatic int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md); 83238384Sjkim/* Copies context */ 84238384Sjkimstatic int gost_imit_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from); 85238384Sjkimstatic int gost_imit_cleanup(EVP_MD_CTX *ctx); 86238384Sjkim/* Control function, knows how to set MAC key.*/ 87238384Sjkimstatic int gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr); 88238384Sjkim 89238384SjkimEVP_MD imit_gost_cpa = 90238384Sjkim { 91238384Sjkim NID_id_Gost28147_89_MAC, 92238384Sjkim NID_undef, 93238384Sjkim 4, 94238384Sjkim 0, 95238384Sjkim gost_imit_init_cpa, 96238384Sjkim gost_imit_update, 97238384Sjkim gost_imit_final, 98238384Sjkim gost_imit_copy, 99238384Sjkim gost_imit_cleanup, 100238384Sjkim NULL, 101238384Sjkim NULL, 102238384Sjkim {0,0,0,0,0}, 103238384Sjkim 8, 104238384Sjkim sizeof(struct ossl_gost_imit_ctx), 105238384Sjkim gost_imit_ctrl 106238384Sjkim }; 107238384Sjkim 108238384Sjkim/* 109238384Sjkim * Correspondence between gost parameter OIDs and substitution blocks 110238384Sjkim * NID field is filed by register_gost_NID function in engine.c 111238384Sjkim * upon engine initialization 112238384Sjkim */ 113238384Sjkim 114238384Sjkimstruct gost_cipher_info gost_cipher_list[]= 115238384Sjkim { 116238384Sjkim/* NID */ /* Subst block */ /* Key meshing*/ 117238384Sjkim/*{NID_id_GostR3411_94_CryptoProParamSet,&GostR3411_94_CryptoProParamSet,0},*/ 118238384Sjkim {NID_id_Gost28147_89_cc,&GostR3411_94_CryptoProParamSet,0}, 119238384Sjkim {NID_id_Gost28147_89_CryptoPro_A_ParamSet,&Gost28147_CryptoProParamSetA,1}, 120238384Sjkim {NID_id_Gost28147_89_CryptoPro_B_ParamSet,&Gost28147_CryptoProParamSetB,1}, 121238384Sjkim {NID_id_Gost28147_89_CryptoPro_C_ParamSet,&Gost28147_CryptoProParamSetC,1}, 122238384Sjkim {NID_id_Gost28147_89_CryptoPro_D_ParamSet,&Gost28147_CryptoProParamSetD,1}, 123238384Sjkim {NID_id_Gost28147_89_TestParamSet,&Gost28147_TestParamSet,1}, 124238384Sjkim {NID_undef,NULL,0} 125238384Sjkim }; 126238384Sjkim 127238384Sjkim/* get encryption parameters from crypto network settings 128238384Sjkim FIXME For now we use environment var CRYPT_PARAMS as place to 129238384Sjkim store these settings. Actually, it is better to use engine control command, read from configuration file to set them */ 130238384Sjkimconst struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj) 131238384Sjkim { 132238384Sjkim int nid; 133238384Sjkim struct gost_cipher_info *param; 134238384Sjkim if (!obj) 135238384Sjkim { 136238384Sjkim const char * params = get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS); 137238384Sjkim if (!params || !strlen(params)) 138238384Sjkim return &gost_cipher_list[1]; 139238384Sjkim 140238384Sjkim nid = OBJ_txt2nid(params); 141238384Sjkim if (nid == NID_undef) 142238384Sjkim { 143238384Sjkim GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS, 144238384Sjkim GOST_R_INVALID_CIPHER_PARAM_OID); 145238384Sjkim return NULL; 146238384Sjkim } 147238384Sjkim } 148238384Sjkim else 149238384Sjkim { 150238384Sjkim nid= OBJ_obj2nid(obj); 151238384Sjkim } 152238384Sjkim for (param=gost_cipher_list;param->sblock!=NULL && param->nid!=nid; 153238384Sjkim param++); 154238384Sjkim if (!param->sblock) 155238384Sjkim { 156238384Sjkim GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,GOST_R_INVALID_CIPHER_PARAMS); 157238384Sjkim return NULL; 158238384Sjkim } 159238384Sjkim return param; 160238384Sjkim } 161238384Sjkim 162238384Sjkim/* Sets cipher param from paramset NID. */ 163238384Sjkimstatic int gost_cipher_set_param(struct ossl_gost_cipher_ctx *c,int nid) 164238384Sjkim { 165238384Sjkim const struct gost_cipher_info *param; 166238384Sjkim param=get_encryption_params((nid==NID_undef?NULL:OBJ_nid2obj(nid))); 167238384Sjkim if (!param) return 0; 168238384Sjkim 169238384Sjkim c->paramNID = param->nid; 170238384Sjkim c->key_meshing=param->key_meshing; 171238384Sjkim c->count=0; 172238384Sjkim gost_init(&(c->cctx), param->sblock); 173238384Sjkim return 1; 174238384Sjkim } 175238384Sjkim 176238384Sjkim/* Initializes EVP_CIPHER_CTX by paramset NID */ 177238384Sjkimstatic int gost_cipher_init_param(EVP_CIPHER_CTX *ctx, const unsigned char *key, 178238384Sjkim const unsigned char *iv, int enc, int paramNID,int mode) 179238384Sjkim { 180238384Sjkim struct ossl_gost_cipher_ctx *c=ctx->cipher_data; 181238384Sjkim if (ctx->app_data == NULL) 182238384Sjkim { 183238384Sjkim if (!gost_cipher_set_param(c,paramNID)) return 0; 184238384Sjkim ctx->app_data = ctx->cipher_data; 185238384Sjkim } 186238384Sjkim if (key) gost_key(&(c->cctx),key); 187238384Sjkim if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); 188238384Sjkim memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); 189238384Sjkim return 1; 190238384Sjkim } 191238384Sjkim 192238384Sjkimstatic int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key, 193238384Sjkim const unsigned char *iv, int enc) 194238384Sjkim { 195238384Sjkim struct ossl_gost_cipher_ctx *c=ctx->cipher_data; 196238384Sjkim gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA); 197238384Sjkim c->key_meshing=1; 198238384Sjkim c->count=0; 199238384Sjkim if(key) gost_key(&(c->cctx),key); 200238384Sjkim if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); 201238384Sjkim memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); 202238384Sjkim return 1; 203238384Sjkim } 204238384Sjkim 205238384Sjkim/* Initializes EVP_CIPHER_CTX with default values */ 206238384Sjkimint gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 207238384Sjkim const unsigned char *iv, int enc) 208238384Sjkim { 209238384Sjkim return gost_cipher_init_param(ctx,key,iv,enc,NID_undef,EVP_CIPH_CFB_MODE); 210238384Sjkim } 211238384Sjkim/* Wrapper around gostcrypt function from gost89.c which perform 212238384Sjkim * key meshing when nesseccary 213238384Sjkim */ 214238384Sjkimstatic void gost_crypt_mesh (void *ctx,unsigned char *iv,unsigned char *buf) 215238384Sjkim { 216238384Sjkim struct ossl_gost_cipher_ctx *c = ctx; 217246772Sjkim assert(c->count%8 == 0 && c->count <= 1024); 218246772Sjkim if (c->key_meshing && c->count==1024) 219238384Sjkim { 220238384Sjkim cryptopro_key_meshing(&(c->cctx),iv); 221238384Sjkim } 222238384Sjkim gostcrypt(&(c->cctx),iv,buf); 223246772Sjkim c->count = c->count%1024 + 8; 224238384Sjkim } 225238384Sjkim 226238384Sjkimstatic void gost_cnt_next (void *ctx, unsigned char *iv, unsigned char *buf) 227238384Sjkim { 228238384Sjkim struct ossl_gost_cipher_ctx *c = ctx; 229238384Sjkim word32 g,go; 230238384Sjkim unsigned char buf1[8]; 231246772Sjkim assert(c->count%8 == 0 && c->count <= 1024); 232246772Sjkim if (c->key_meshing && c->count==1024) 233238384Sjkim { 234238384Sjkim cryptopro_key_meshing(&(c->cctx),iv); 235238384Sjkim } 236238384Sjkim if (c->count==0) 237238384Sjkim { 238238384Sjkim gostcrypt(&(c->cctx),iv,buf1); 239238384Sjkim } 240238384Sjkim else 241238384Sjkim { 242238384Sjkim memcpy(buf1,iv,8); 243238384Sjkim } 244238384Sjkim g = buf1[0]|(buf1[1]<<8)|(buf1[2]<<16)|(buf1[3]<<24); 245238384Sjkim g += 0x01010101; 246238384Sjkim buf1[0]=(unsigned char)(g&0xff); 247238384Sjkim buf1[1]=(unsigned char)((g>>8)&0xff); 248238384Sjkim buf1[2]=(unsigned char)((g>>16)&0xff); 249238384Sjkim buf1[3]=(unsigned char)((g>>24)&0xff); 250238384Sjkim g = buf1[4]|(buf1[5]<<8)|(buf1[6]<<16)|(buf1[7]<<24); 251238384Sjkim go = g; 252238384Sjkim g += 0x01010104; 253238384Sjkim if (go > g) /* overflow*/ 254238384Sjkim g++; 255238384Sjkim buf1[4]=(unsigned char)(g&0xff); 256238384Sjkim buf1[5]=(unsigned char)((g>>8)&0xff); 257238384Sjkim buf1[6]=(unsigned char)((g>>16)&0xff); 258238384Sjkim buf1[7]=(unsigned char)((g>>24)&0xff); 259238384Sjkim memcpy(iv,buf1,8); 260238384Sjkim gostcrypt(&(c->cctx),buf1,buf); 261246772Sjkim c->count = c->count%1024 + 8; 262238384Sjkim } 263238384Sjkim 264238384Sjkim/* GOST encryption in CFB mode */ 265238384Sjkimint gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, 266238384Sjkim const unsigned char *in, size_t inl) 267238384Sjkim { 268238384Sjkim const unsigned char *in_ptr=in; 269238384Sjkim unsigned char *out_ptr=out; 270238384Sjkim size_t i=0; 271238384Sjkim size_t j=0; 272238384Sjkim/* process partial block if any */ 273238384Sjkim if (ctx->num) 274238384Sjkim { 275238384Sjkim for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++) 276238384Sjkim { 277238384Sjkim if (!ctx->encrypt) ctx->buf[j+8]=*in_ptr; 278238384Sjkim *out_ptr=ctx->buf[j]^(*in_ptr); 279238384Sjkim if (ctx->encrypt) ctx->buf[j+8]=*out_ptr; 280238384Sjkim } 281238384Sjkim if (j==8) 282238384Sjkim { 283238384Sjkim memcpy(ctx->iv,ctx->buf+8,8); 284238384Sjkim ctx->num=0; 285238384Sjkim } 286238384Sjkim else 287238384Sjkim { 288238384Sjkim ctx->num=j; 289238384Sjkim return 1; 290238384Sjkim } 291238384Sjkim } 292238384Sjkim 293238384Sjkim for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8) 294238384Sjkim { 295238384Sjkim /*block cipher current iv */ 296238384Sjkim gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf); 297238384Sjkim /*xor next block of input text with it and output it*/ 298238384Sjkim /*output this block */ 299238384Sjkim if (!ctx->encrypt) memcpy(ctx->iv,in_ptr,8); 300238384Sjkim for (j=0;j<8;j++) 301238384Sjkim { 302238384Sjkim out_ptr[j]=ctx->buf[j]^in_ptr[j]; 303238384Sjkim } 304238384Sjkim /* Encrypt */ 305238384Sjkim /* Next iv is next block of cipher text*/ 306238384Sjkim if (ctx->encrypt) memcpy(ctx->iv,out_ptr,8); 307238384Sjkim } 308238384Sjkim/* Process rest of buffer */ 309238384Sjkim if (i<inl) 310238384Sjkim { 311238384Sjkim gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf); 312238384Sjkim if (!ctx->encrypt) memcpy(ctx->buf+8,in_ptr,inl-i); 313238384Sjkim for (j=0;i<inl;j++,i++) 314238384Sjkim { 315238384Sjkim out_ptr[j]=ctx->buf[j]^in_ptr[j]; 316238384Sjkim } 317238384Sjkim ctx->num = j; 318238384Sjkim if (ctx->encrypt) memcpy(ctx->buf+8,out_ptr,j); 319238384Sjkim } 320238384Sjkim else 321238384Sjkim { 322238384Sjkim ctx->num = 0; 323238384Sjkim } 324238384Sjkim return 1; 325238384Sjkim } 326238384Sjkim 327238384Sjkimstatic int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, 328238384Sjkim const unsigned char *in, size_t inl) 329238384Sjkim { 330238384Sjkim const unsigned char *in_ptr=in; 331238384Sjkim unsigned char *out_ptr=out; 332238384Sjkim size_t i=0; 333238384Sjkim size_t j; 334238384Sjkim/* process partial block if any */ 335238384Sjkim if (ctx->num) 336238384Sjkim { 337238384Sjkim for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++) 338238384Sjkim { 339238384Sjkim *out_ptr=ctx->buf[j]^(*in_ptr); 340238384Sjkim } 341238384Sjkim if (j==8) 342238384Sjkim { 343238384Sjkim ctx->num=0; 344238384Sjkim } 345238384Sjkim else 346238384Sjkim { 347238384Sjkim ctx->num=j; 348238384Sjkim return 1; 349238384Sjkim } 350238384Sjkim } 351238384Sjkim 352238384Sjkim for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8) 353238384Sjkim { 354238384Sjkim /*block cipher current iv */ 355238384Sjkim /* Encrypt */ 356238384Sjkim gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf); 357238384Sjkim /*xor next block of input text with it and output it*/ 358238384Sjkim /*output this block */ 359238384Sjkim for (j=0;j<8;j++) 360238384Sjkim { 361238384Sjkim out_ptr[j]=ctx->buf[j]^in_ptr[j]; 362238384Sjkim } 363238384Sjkim } 364238384Sjkim/* Process rest of buffer */ 365238384Sjkim if (i<inl) 366238384Sjkim { 367238384Sjkim gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf); 368238384Sjkim for (j=0;i<inl;j++,i++) 369238384Sjkim { 370238384Sjkim out_ptr[j]=ctx->buf[j]^in_ptr[j]; 371238384Sjkim } 372238384Sjkim ctx->num = j; 373238384Sjkim } 374238384Sjkim else 375238384Sjkim { 376238384Sjkim ctx->num = 0; 377238384Sjkim } 378238384Sjkim return 1; 379238384Sjkim } 380238384Sjkim 381238384Sjkim/* Cleaning up of EVP_CIPHER_CTX */ 382238384Sjkimint gost_cipher_cleanup(EVP_CIPHER_CTX *ctx) 383238384Sjkim { 384238384Sjkim gost_destroy(&((struct ossl_gost_cipher_ctx *)ctx->cipher_data)->cctx); 385238384Sjkim ctx->app_data = NULL; 386238384Sjkim return 1; 387238384Sjkim } 388238384Sjkim 389238384Sjkim/* Control function for gost cipher */ 390238384Sjkimint gost_cipher_ctl(EVP_CIPHER_CTX *ctx,int type,int arg,void *ptr) 391238384Sjkim { 392238384Sjkim switch (type) 393238384Sjkim { 394238384Sjkim case EVP_CTRL_RAND_KEY: 395238384Sjkim { 396238384Sjkim if (RAND_bytes((unsigned char *)ptr,ctx->key_len)<=0) 397238384Sjkim { 398238384Sjkim GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_RANDOM_GENERATOR_ERROR); 399238384Sjkim return -1; 400238384Sjkim } 401238384Sjkim break; 402238384Sjkim } 403238384Sjkim case EVP_CTRL_PBE_PRF_NID: 404238384Sjkim if (ptr) { 405238384Sjkim *((int *)ptr)= NID_id_HMACGostR3411_94; 406238384Sjkim return 1; 407238384Sjkim } else { 408238384Sjkim return 0; 409238384Sjkim } 410238384Sjkim 411238384Sjkim default: 412238384Sjkim GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND); 413238384Sjkim return -1; 414238384Sjkim } 415238384Sjkim return 1; 416238384Sjkim } 417238384Sjkim 418238384Sjkim/* Set cipher parameters from ASN1 structure */ 419238384Sjkimint gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params) 420238384Sjkim { 421238384Sjkim int len=0; 422238384Sjkim unsigned char *buf=NULL; 423238384Sjkim unsigned char *p=NULL; 424238384Sjkim struct ossl_gost_cipher_ctx *c = ctx->cipher_data; 425238384Sjkim GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new(); 426238384Sjkim ASN1_OCTET_STRING *os = NULL; 427238384Sjkim if (!gcp) 428238384Sjkim { 429238384Sjkim GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); 430238384Sjkim return 0; 431238384Sjkim } 432238384Sjkim if (!ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len)) 433238384Sjkim { 434238384Sjkim GOST_CIPHER_PARAMS_free(gcp); 435238384Sjkim GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); 436238384Sjkim return 0; 437238384Sjkim } 438238384Sjkim ASN1_OBJECT_free(gcp->enc_param_set); 439238384Sjkim gcp->enc_param_set = OBJ_nid2obj(c->paramNID); 440238384Sjkim 441238384Sjkim len = i2d_GOST_CIPHER_PARAMS(gcp, NULL); 442238384Sjkim p = buf = (unsigned char*)OPENSSL_malloc(len); 443238384Sjkim if (!buf) 444238384Sjkim { 445238384Sjkim GOST_CIPHER_PARAMS_free(gcp); 446238384Sjkim GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); 447238384Sjkim return 0; 448238384Sjkim } 449238384Sjkim i2d_GOST_CIPHER_PARAMS(gcp, &p); 450238384Sjkim GOST_CIPHER_PARAMS_free(gcp); 451238384Sjkim 452238384Sjkim os = ASN1_OCTET_STRING_new(); 453238384Sjkim 454238384Sjkim if(!os || !ASN1_OCTET_STRING_set(os, buf, len)) 455238384Sjkim { 456238384Sjkim OPENSSL_free(buf); 457238384Sjkim GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); 458238384Sjkim return 0; 459238384Sjkim } 460238384Sjkim OPENSSL_free(buf); 461238384Sjkim 462238384Sjkim ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os); 463238384Sjkim return 1; 464238384Sjkim } 465238384Sjkim 466238384Sjkim/* Store parameters into ASN1 structure */ 467238384Sjkimint gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params) 468238384Sjkim { 469238384Sjkim int ret = -1; 470238384Sjkim int len; 471238384Sjkim GOST_CIPHER_PARAMS *gcp = NULL; 472238384Sjkim unsigned char *p; 473238384Sjkim struct ossl_gost_cipher_ctx *c=ctx->cipher_data; 474238384Sjkim if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) 475238384Sjkim { 476238384Sjkim return ret; 477238384Sjkim } 478238384Sjkim 479238384Sjkim p = params->value.sequence->data; 480238384Sjkim 481238384Sjkim gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p, 482238384Sjkim params->value.sequence->length); 483238384Sjkim 484238384Sjkim len = gcp->iv->length; 485238384Sjkim if (len != ctx->cipher->iv_len) 486238384Sjkim { 487238384Sjkim GOST_CIPHER_PARAMS_free(gcp); 488238384Sjkim GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS, 489238384Sjkim GOST_R_INVALID_IV_LENGTH); 490238384Sjkim return -1; 491238384Sjkim } 492238384Sjkim if (!gost_cipher_set_param(c,OBJ_obj2nid(gcp->enc_param_set))) 493238384Sjkim { 494238384Sjkim GOST_CIPHER_PARAMS_free(gcp); 495238384Sjkim return -1; 496238384Sjkim } 497238384Sjkim memcpy(ctx->oiv, gcp->iv->data, len); 498238384Sjkim 499238384Sjkim GOST_CIPHER_PARAMS_free(gcp); 500238384Sjkim 501238384Sjkim return 1; 502238384Sjkim } 503238384Sjkim 504238384Sjkim 505238384Sjkimint gost_imit_init_cpa(EVP_MD_CTX *ctx) 506238384Sjkim { 507238384Sjkim struct ossl_gost_imit_ctx *c = ctx->md_data; 508238384Sjkim memset(c->buffer,0,sizeof(c->buffer)); 509238384Sjkim memset(c->partial_block,0,sizeof(c->partial_block)); 510238384Sjkim c->count = 0; 511238384Sjkim c->bytes_left=0; 512238384Sjkim c->key_meshing=1; 513238384Sjkim gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA); 514238384Sjkim return 1; 515238384Sjkim } 516238384Sjkim 517238384Sjkimstatic void mac_block_mesh(struct ossl_gost_imit_ctx *c,const unsigned char *data) 518238384Sjkim { 519238384Sjkim unsigned char buffer[8]; 520238384Sjkim /* We are using local buffer for iv because CryptoPro doesn't 521238384Sjkim * interpret internal state of MAC algorithm as iv during keymeshing 522238384Sjkim * (but does initialize internal state from iv in key transport 523238384Sjkim */ 524246772Sjkim assert(c->count%8 == 0 && c->count <= 1024); 525246772Sjkim if (c->key_meshing && c->count==1024) 526238384Sjkim { 527238384Sjkim cryptopro_key_meshing(&(c->cctx),buffer); 528238384Sjkim } 529238384Sjkim mac_block(&(c->cctx),c->buffer,data); 530246772Sjkim c->count = c->count%1024 + 8; 531238384Sjkim } 532238384Sjkim 533238384Sjkimint gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count) 534238384Sjkim { 535238384Sjkim struct ossl_gost_imit_ctx *c = ctx->md_data; 536238384Sjkim const unsigned char *p = data; 537238384Sjkim size_t bytes = count,i; 538238384Sjkim if (!(c->key_set)) { 539238384Sjkim GOSTerr(GOST_F_GOST_IMIT_UPDATE, GOST_R_MAC_KEY_NOT_SET); 540238384Sjkim return 0; 541238384Sjkim } 542238384Sjkim if (c->bytes_left) 543238384Sjkim { 544238384Sjkim for (i=c->bytes_left;i<8&&bytes>0;bytes--,i++,p++) 545238384Sjkim { 546238384Sjkim c->partial_block[i]=*p; 547238384Sjkim } 548238384Sjkim if (i==8) 549238384Sjkim { 550238384Sjkim mac_block_mesh(c,c->partial_block); 551238384Sjkim } 552238384Sjkim else 553238384Sjkim { 554238384Sjkim c->bytes_left = i; 555238384Sjkim return 1; 556238384Sjkim } 557238384Sjkim } 558238384Sjkim while (bytes>8) 559238384Sjkim { 560238384Sjkim mac_block_mesh(c,p); 561238384Sjkim p+=8; 562238384Sjkim bytes-=8; 563238384Sjkim } 564238384Sjkim if (bytes>0) 565238384Sjkim { 566238384Sjkim memcpy(c->partial_block,p,bytes); 567238384Sjkim } 568238384Sjkim c->bytes_left=bytes; 569238384Sjkim return 1; 570238384Sjkim } 571238384Sjkim 572238384Sjkimint gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md) 573238384Sjkim { 574238384Sjkim struct ossl_gost_imit_ctx *c = ctx->md_data; 575238384Sjkim if (!c->key_set) { 576238384Sjkim GOSTerr(GOST_F_GOST_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET); 577238384Sjkim return 0; 578238384Sjkim } 579246772Sjkim if (c->count==0 && c->bytes_left) 580246772Sjkim { 581246772Sjkim unsigned char buffer[8]; 582246772Sjkim memset(buffer, 0, 8); 583246772Sjkim gost_imit_update(ctx, buffer, 8); 584246772Sjkim } 585238384Sjkim if (c->bytes_left) 586238384Sjkim { 587238384Sjkim int i; 588238384Sjkim for (i=c->bytes_left;i<8;i++) 589238384Sjkim { 590238384Sjkim c->partial_block[i]=0; 591238384Sjkim } 592238384Sjkim mac_block_mesh(c,c->partial_block); 593238384Sjkim } 594238384Sjkim get_mac(c->buffer,32,md); 595238384Sjkim return 1; 596238384Sjkim } 597238384Sjkim 598238384Sjkimint gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr) 599238384Sjkim { 600238384Sjkim switch (type) 601238384Sjkim { 602238384Sjkim case EVP_MD_CTRL_KEY_LEN: 603238384Sjkim *((unsigned int*)(ptr)) = 32; 604238384Sjkim return 1; 605238384Sjkim case EVP_MD_CTRL_SET_KEY: 606238384Sjkim { 607238384Sjkim if (arg!=32) { 608238384Sjkim GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_LENGTH); 609238384Sjkim return 0; 610238384Sjkim } 611238384Sjkim 612238384Sjkim gost_key(&(((struct ossl_gost_imit_ctx*)(ctx->md_data))->cctx),ptr) ; 613238384Sjkim ((struct ossl_gost_imit_ctx*)(ctx->md_data))->key_set = 1; 614238384Sjkim return 1; 615238384Sjkim 616238384Sjkim } 617238384Sjkim default: 618238384Sjkim return 0; 619238384Sjkim } 620238384Sjkim } 621238384Sjkim 622238384Sjkimint gost_imit_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) 623238384Sjkim { 624238384Sjkim memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_imit_ctx)); 625238384Sjkim return 1; 626238384Sjkim } 627238384Sjkim 628238384Sjkim/* Clean up imit ctx */ 629238384Sjkimint gost_imit_cleanup(EVP_MD_CTX *ctx) 630238384Sjkim { 631238384Sjkim memset(ctx->md_data,0,sizeof(struct ossl_gost_imit_ctx)); 632238384Sjkim return 1; 633238384Sjkim } 634238384Sjkim 635