OLD | NEW |
(Empty) | |
| 1 /********************************************************************** |
| 2 * gost_crypt.c * |
| 3 * Copyright (c) 2005-2006 Cryptocom LTD * |
| 4 * This file is distributed under the same license as OpenSSL * |
| 5 * * |
| 6 * OpenSSL interface to GOST 28147-89 cipher functions * |
| 7 * Requires OpenSSL 0.9.9 for compilation * |
| 8 **********************************************************************/ |
| 9 #include <string.h> |
| 10 #include "gost89.h" |
| 11 #include <openssl/rand.h> |
| 12 #include "e_gost_err.h" |
| 13 #include "gost_lcl.h" |
| 14 static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, |
| 15 const unsigned char *iv, int enc); |
| 16 static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *k
ey, |
| 17 const unsigned char *iv, int enc); |
| 18 /* Handles block of data in CFB mode */ |
| 19 static int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, |
| 20 const unsigned char *in, size_t inl); |
| 21 /* Handles block of data in CNT mode */ |
| 22 static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, |
| 23 const unsigned char *in, size_t inl); |
| 24 /* Cleanup function */ |
| 25 static int gost_cipher_cleanup(EVP_CIPHER_CTX *); |
| 26 /* set/get cipher parameters */ |
| 27 static int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params); |
| 28 static int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params); |
| 29 /* Control function */ |
| 30 static int gost_cipher_ctl(EVP_CIPHER_CTX *ctx,int type,int arg,void *ptr); |
| 31 |
| 32 EVP_CIPHER cipher_gost = |
| 33 { |
| 34 NID_id_Gost28147_89, |
| 35 1,/*block_size*/ |
| 36 32,/*key_size*/ |
| 37 8,/*iv_len */ |
| 38 EVP_CIPH_CFB_MODE| EVP_CIPH_NO_PADDING | |
| 39 EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT, |
| 40 gost_cipher_init, |
| 41 gost_cipher_do_cfb, |
| 42 gost_cipher_cleanup, |
| 43 sizeof(struct ossl_gost_cipher_ctx),/* ctx_size */ |
| 44 gost89_set_asn1_parameters, |
| 45 gost89_get_asn1_parameters, |
| 46 gost_cipher_ctl, |
| 47 NULL, |
| 48 }; |
| 49 |
| 50 EVP_CIPHER cipher_gost_cpacnt = |
| 51 { |
| 52 NID_gost89_cnt, |
| 53 1,/*block_size*/ |
| 54 32,/*key_size*/ |
| 55 8,/*iv_len */ |
| 56 EVP_CIPH_OFB_MODE| EVP_CIPH_NO_PADDING | |
| 57 EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT, |
| 58 gost_cipher_init_cpa, |
| 59 gost_cipher_do_cnt, |
| 60 gost_cipher_cleanup, |
| 61 sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */ |
| 62 gost89_set_asn1_parameters, |
| 63 gost89_get_asn1_parameters, |
| 64 gost_cipher_ctl, |
| 65 NULL, |
| 66 }; |
| 67 |
| 68 /* Implementation of GOST 28147-89 in MAC (imitovstavka) mode */ |
| 69 /* Init functions which set specific parameters */ |
| 70 static int gost_imit_init_cpa(EVP_MD_CTX *ctx); |
| 71 /* process block of data */ |
| 72 static int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count); |
| 73 /* Return computed value */ |
| 74 static int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md); |
| 75 /* Copies context */ |
| 76 static int gost_imit_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from); |
| 77 static int gost_imit_cleanup(EVP_MD_CTX *ctx); |
| 78 /* Control function, knows how to set MAC key.*/ |
| 79 static int gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr); |
| 80 |
| 81 EVP_MD imit_gost_cpa = |
| 82 { |
| 83 NID_id_Gost28147_89_MAC, |
| 84 NID_undef, |
| 85 4, |
| 86 0, |
| 87 gost_imit_init_cpa, |
| 88 gost_imit_update, |
| 89 gost_imit_final, |
| 90 gost_imit_copy, |
| 91 gost_imit_cleanup, |
| 92 NULL, |
| 93 NULL, |
| 94 {0,0,0,0,0}, |
| 95 8, |
| 96 sizeof(struct ossl_gost_imit_ctx), |
| 97 gost_imit_ctrl |
| 98 }; |
| 99 |
| 100 /* |
| 101 * Correspondence between gost parameter OIDs and substitution blocks |
| 102 * NID field is filed by register_gost_NID function in engine.c |
| 103 * upon engine initialization |
| 104 */ |
| 105 |
| 106 struct gost_cipher_info gost_cipher_list[]= |
| 107 { |
| 108 /* NID */ /* Subst block */ /* Key meshing*/ |
| 109 /*{NID_id_GostR3411_94_CryptoProParamSet,&GostR3411_94_CryptoProParamSet,0},*/ |
| 110 {NID_id_Gost28147_89_cc,&GostR3411_94_CryptoProParamSet,0}, |
| 111 {NID_id_Gost28147_89_CryptoPro_A_ParamSet,&Gost28147_CryptoProParamSetA,
1}, |
| 112 {NID_id_Gost28147_89_CryptoPro_B_ParamSet,&Gost28147_CryptoProParamSetB,
1}, |
| 113 {NID_id_Gost28147_89_CryptoPro_C_ParamSet,&Gost28147_CryptoProParamSetC,
1}, |
| 114 {NID_id_Gost28147_89_CryptoPro_D_ParamSet,&Gost28147_CryptoProParamSetD,
1}, |
| 115 {NID_id_Gost28147_89_TestParamSet,&Gost28147_TestParamSet,1}, |
| 116 {NID_undef,NULL,0} |
| 117 }; |
| 118 |
| 119 /* get encryption parameters from crypto network settings |
| 120 FIXME For now we use environment var CRYPT_PARAMS as place to |
| 121 store these settings. Actually, it is better to use engine control com
mand, read from configuration file to set them */ |
| 122 const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj) |
| 123 { |
| 124 int nid; |
| 125 struct gost_cipher_info *param; |
| 126 if (!obj) |
| 127 { |
| 128 const char * params = get_gost_engine_param(GOST_PARAM_CRYPT_PAR
AMS); |
| 129 if (!params || !strlen(params)) |
| 130 return &gost_cipher_list[1]; |
| 131 |
| 132 nid = OBJ_txt2nid(params); |
| 133 if (nid == NID_undef) |
| 134 { |
| 135 GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS, |
| 136 GOST_R_INVALID_CIPHER_PARAM_OID); |
| 137 return NULL; |
| 138 } |
| 139 } |
| 140 else |
| 141 { |
| 142 nid= OBJ_obj2nid(obj); |
| 143 } |
| 144 for (param=gost_cipher_list;param->sblock!=NULL && param->nid!=nid; |
| 145 param++); |
| 146 if (!param->sblock) |
| 147 { |
| 148 GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,GOST_R_INVALID_CIPHER_PARAM
S); |
| 149 return NULL; |
| 150 } |
| 151 return param; |
| 152 } |
| 153 |
| 154 /* Sets cipher param from paramset NID. */ |
| 155 static int gost_cipher_set_param(struct ossl_gost_cipher_ctx *c,int nid) |
| 156 { |
| 157 const struct gost_cipher_info *param; |
| 158 param=get_encryption_params((nid==NID_undef?NULL:OBJ_nid2obj(nid))); |
| 159 if (!param) return 0; |
| 160 |
| 161 c->paramNID = param->nid; |
| 162 c->key_meshing=param->key_meshing; |
| 163 c->count=0; |
| 164 gost_init(&(c->cctx), param->sblock); |
| 165 return 1; |
| 166 } |
| 167 |
| 168 /* Initializes EVP_CIPHER_CTX by paramset NID */ |
| 169 static int gost_cipher_init_param(EVP_CIPHER_CTX *ctx, const unsigned char *key, |
| 170 const unsigned char *iv, int enc, int paramNID,int mode) |
| 171 { |
| 172 struct ossl_gost_cipher_ctx *c=ctx->cipher_data; |
| 173 if (ctx->app_data == NULL) |
| 174 { |
| 175 if (!gost_cipher_set_param(c,paramNID)) return 0; |
| 176 ctx->app_data = ctx->cipher_data; |
| 177 } |
| 178 if (key) gost_key(&(c->cctx),key); |
| 179 if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); |
| 180 memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); |
| 181 return 1; |
| 182 } |
| 183 |
| 184 static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key, |
| 185 const unsigned char *iv, int enc) |
| 186 { |
| 187 struct ossl_gost_cipher_ctx *c=ctx->cipher_data; |
| 188 gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA); |
| 189 c->key_meshing=1; |
| 190 c->count=0; |
| 191 if(key) gost_key(&(c->cctx),key); |
| 192 if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); |
| 193 memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); |
| 194 return 1; |
| 195 } |
| 196 |
| 197 /* Initializes EVP_CIPHER_CTX with default values */ |
| 198 int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, |
| 199 const unsigned char *iv, int enc) |
| 200 { |
| 201 return gost_cipher_init_param(ctx,key,iv,enc,NID_undef,EVP_CIPH_CFB_MODE
); |
| 202 } |
| 203 /* Wrapper around gostcrypt function from gost89.c which perform |
| 204 * key meshing when nesseccary |
| 205 */ |
| 206 static void gost_crypt_mesh (void *ctx,unsigned char *iv,unsigned char *buf) |
| 207 { |
| 208 struct ossl_gost_cipher_ctx *c = ctx; |
| 209 if (c->count&&c->key_meshing && c->count%1024==0) |
| 210 { |
| 211 cryptopro_key_meshing(&(c->cctx),iv); |
| 212 } |
| 213 gostcrypt(&(c->cctx),iv,buf); |
| 214 c->count+=8; |
| 215 } |
| 216 |
| 217 static void gost_cnt_next (void *ctx, unsigned char *iv, unsigned char *buf) |
| 218 { |
| 219 struct ossl_gost_cipher_ctx *c = ctx; |
| 220 word32 g,go; |
| 221 unsigned char buf1[8]; |
| 222 if (c->count && c->key_meshing && c->count %1024 ==0) |
| 223 { |
| 224 cryptopro_key_meshing(&(c->cctx),iv); |
| 225 } |
| 226 if (c->count==0) |
| 227 { |
| 228 gostcrypt(&(c->cctx),iv,buf1); |
| 229 } |
| 230 else |
| 231 { |
| 232 memcpy(buf1,iv,8); |
| 233 } |
| 234 g = buf1[0]|(buf1[1]<<8)|(buf1[2]<<16)|(buf1[3]<<24); |
| 235 g += 0x01010101; |
| 236 buf1[0]=(unsigned char)(g&0xff); |
| 237 buf1[1]=(unsigned char)((g>>8)&0xff); |
| 238 buf1[2]=(unsigned char)((g>>16)&0xff); |
| 239 buf1[3]=(unsigned char)((g>>24)&0xff); |
| 240 g = buf1[4]|(buf1[5]<<8)|(buf1[6]<<16)|(buf1[7]<<24); |
| 241 go = g; |
| 242 g += 0x01010104; |
| 243 if (go > g) /* overflow*/ |
| 244 g++; |
| 245 buf1[4]=(unsigned char)(g&0xff); |
| 246 buf1[5]=(unsigned char)((g>>8)&0xff); |
| 247 buf1[6]=(unsigned char)((g>>16)&0xff); |
| 248 buf1[7]=(unsigned char)((g>>24)&0xff); |
| 249 memcpy(iv,buf1,8); |
| 250 gostcrypt(&(c->cctx),buf1,buf); |
| 251 c->count +=8; |
| 252 } |
| 253 |
| 254 /* GOST encryption in CFB mode */ |
| 255 int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, |
| 256 const unsigned char *in, size_t inl) |
| 257 { |
| 258 const unsigned char *in_ptr=in; |
| 259 unsigned char *out_ptr=out; |
| 260 size_t i=0; |
| 261 size_t j=0; |
| 262 /* process partial block if any */ |
| 263 if (ctx->num) |
| 264 { |
| 265 for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++) |
| 266 { |
| 267 if (!ctx->encrypt) ctx->buf[j+8]=*in_ptr; |
| 268 *out_ptr=ctx->buf[j]^(*in_ptr); |
| 269 if (ctx->encrypt) ctx->buf[j+8]=*out_ptr; |
| 270 } |
| 271 if (j==8) |
| 272 { |
| 273 memcpy(ctx->iv,ctx->buf+8,8); |
| 274 ctx->num=0; |
| 275 } |
| 276 else |
| 277 { |
| 278 ctx->num=j; |
| 279 return 1; |
| 280 } |
| 281 } |
| 282 |
| 283 for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8) |
| 284 { |
| 285 /*block cipher current iv */ |
| 286 gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf); |
| 287 /*xor next block of input text with it and output it*/ |
| 288 /*output this block */ |
| 289 if (!ctx->encrypt) memcpy(ctx->iv,in_ptr,8); |
| 290 for (j=0;j<8;j++) |
| 291 { |
| 292 out_ptr[j]=ctx->buf[j]^in_ptr[j]; |
| 293 } |
| 294 /* Encrypt */ |
| 295 /* Next iv is next block of cipher text*/ |
| 296 if (ctx->encrypt) memcpy(ctx->iv,out_ptr,8); |
| 297 } |
| 298 /* Process rest of buffer */ |
| 299 if (i<inl) |
| 300 { |
| 301 gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf); |
| 302 if (!ctx->encrypt) memcpy(ctx->buf+8,in_ptr,inl-i); |
| 303 for (j=0;i<inl;j++,i++) |
| 304 { |
| 305 out_ptr[j]=ctx->buf[j]^in_ptr[j]; |
| 306 } |
| 307 ctx->num = j; |
| 308 if (ctx->encrypt) memcpy(ctx->buf+8,out_ptr,j); |
| 309 } |
| 310 else |
| 311 { |
| 312 ctx->num = 0; |
| 313 } |
| 314 return 1; |
| 315 } |
| 316 |
| 317 static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, |
| 318 const unsigned char *in, size_t inl) |
| 319 { |
| 320 const unsigned char *in_ptr=in; |
| 321 unsigned char *out_ptr=out; |
| 322 size_t i=0; |
| 323 size_t j; |
| 324 /* process partial block if any */ |
| 325 if (ctx->num) |
| 326 { |
| 327 for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++) |
| 328 { |
| 329 *out_ptr=ctx->buf[j]^(*in_ptr); |
| 330 } |
| 331 if (j==8) |
| 332 { |
| 333 ctx->num=0; |
| 334 } |
| 335 else |
| 336 { |
| 337 ctx->num=j; |
| 338 return 1; |
| 339 } |
| 340 } |
| 341 |
| 342 for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8) |
| 343 { |
| 344 /*block cipher current iv */ |
| 345 /* Encrypt */ |
| 346 gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf); |
| 347 /*xor next block of input text with it and output it*/ |
| 348 /*output this block */ |
| 349 for (j=0;j<8;j++) |
| 350 { |
| 351 out_ptr[j]=ctx->buf[j]^in_ptr[j]; |
| 352 } |
| 353 } |
| 354 /* Process rest of buffer */ |
| 355 if (i<inl) |
| 356 { |
| 357 gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf); |
| 358 for (j=0;i<inl;j++,i++) |
| 359 { |
| 360 out_ptr[j]=ctx->buf[j]^in_ptr[j]; |
| 361 } |
| 362 ctx->num = j; |
| 363 } |
| 364 else |
| 365 { |
| 366 ctx->num = 0; |
| 367 } |
| 368 return 1; |
| 369 } |
| 370 |
| 371 /* Cleaning up of EVP_CIPHER_CTX */ |
| 372 int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx) |
| 373 { |
| 374 gost_destroy(&((struct ossl_gost_cipher_ctx *)ctx->cipher_data)->cctx); |
| 375 ctx->app_data = NULL; |
| 376 return 1; |
| 377 } |
| 378 |
| 379 /* Control function for gost cipher */ |
| 380 int gost_cipher_ctl(EVP_CIPHER_CTX *ctx,int type,int arg,void *ptr) |
| 381 { |
| 382 switch (type) |
| 383 { |
| 384 case EVP_CTRL_RAND_KEY: |
| 385 { |
| 386 if (RAND_bytes((unsigned char *)ptr,ctx->key_len)<=0) |
| 387 { |
| 388 GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_RANDOM_GENERATOR_E
RROR); |
| 389 return -1; |
| 390 } |
| 391 break; |
| 392 } |
| 393 case EVP_CTRL_PBE_PRF_NID: |
| 394 if (ptr) { |
| 395 *((int *)ptr)= NID_id_HMACGostR3411_94; |
| 396 return 1; |
| 397 } else { |
| 398 return 0; |
| 399 } |
| 400 |
| 401 default: |
| 402 GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_UNSUPPORTED_CIPHER
_CTL_COMMAND); |
| 403 return -1; |
| 404 } |
| 405 return 1; |
| 406 } |
| 407 |
| 408 /* Set cipher parameters from ASN1 structure */ |
| 409 int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params) |
| 410 { |
| 411 int len=0; |
| 412 unsigned char *buf=NULL; |
| 413 unsigned char *p=NULL; |
| 414 struct ossl_gost_cipher_ctx *c = ctx->cipher_data; |
| 415 GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new(); |
| 416 ASN1_OCTET_STRING *os = NULL; |
| 417 if (!gcp) |
| 418 { |
| 419 GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); |
| 420 return 0; |
| 421 } |
| 422 if (!ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len)) |
| 423 { |
| 424 GOST_CIPHER_PARAMS_free(gcp); |
| 425 GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); |
| 426 return 0; |
| 427 } |
| 428 ASN1_OBJECT_free(gcp->enc_param_set); |
| 429 gcp->enc_param_set = OBJ_nid2obj(c->paramNID); |
| 430 |
| 431 len = i2d_GOST_CIPHER_PARAMS(gcp, NULL); |
| 432 p = buf = (unsigned char*)OPENSSL_malloc(len); |
| 433 if (!buf) |
| 434 { |
| 435 GOST_CIPHER_PARAMS_free(gcp); |
| 436 GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); |
| 437 return 0; |
| 438 } |
| 439 i2d_GOST_CIPHER_PARAMS(gcp, &p); |
| 440 GOST_CIPHER_PARAMS_free(gcp); |
| 441 |
| 442 os = ASN1_OCTET_STRING_new(); |
| 443 |
| 444 if(!os || !ASN1_OCTET_STRING_set(os, buf, len)) |
| 445 { |
| 446 OPENSSL_free(buf); |
| 447 GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); |
| 448 return 0; |
| 449 } |
| 450 OPENSSL_free(buf); |
| 451 |
| 452 ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os); |
| 453 return 1; |
| 454 } |
| 455 |
| 456 /* Store parameters into ASN1 structure */ |
| 457 int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params) |
| 458 { |
| 459 int ret = -1; |
| 460 int len; |
| 461 GOST_CIPHER_PARAMS *gcp = NULL; |
| 462 unsigned char *p; |
| 463 struct ossl_gost_cipher_ctx *c=ctx->cipher_data; |
| 464 if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) |
| 465 { |
| 466 return ret; |
| 467 } |
| 468 |
| 469 p = params->value.sequence->data; |
| 470 |
| 471 gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p, |
| 472 params->value.sequence->length); |
| 473 |
| 474 len = gcp->iv->length; |
| 475 if (len != ctx->cipher->iv_len) |
| 476 { |
| 477 GOST_CIPHER_PARAMS_free(gcp); |
| 478 GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS, |
| 479 GOST_R_INVALID_IV_LENGTH); |
| 480 return -1; |
| 481 } |
| 482 if (!gost_cipher_set_param(c,OBJ_obj2nid(gcp->enc_param_set))) |
| 483 { |
| 484 GOST_CIPHER_PARAMS_free(gcp); |
| 485 return -1; |
| 486 } |
| 487 memcpy(ctx->oiv, gcp->iv->data, len); |
| 488 |
| 489 GOST_CIPHER_PARAMS_free(gcp); |
| 490 |
| 491 return 1; |
| 492 } |
| 493 |
| 494 |
| 495 int gost_imit_init_cpa(EVP_MD_CTX *ctx) |
| 496 { |
| 497 struct ossl_gost_imit_ctx *c = ctx->md_data; |
| 498 memset(c->buffer,0,sizeof(c->buffer)); |
| 499 memset(c->partial_block,0,sizeof(c->partial_block)); |
| 500 c->count = 0; |
| 501 c->bytes_left=0; |
| 502 c->key_meshing=1; |
| 503 gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA); |
| 504 return 1; |
| 505 } |
| 506 |
| 507 static void mac_block_mesh(struct ossl_gost_imit_ctx *c,const unsigned char *dat
a) |
| 508 { |
| 509 unsigned char buffer[8]; |
| 510 /* We are using local buffer for iv because CryptoPro doesn't |
| 511 * interpret internal state of MAC algorithm as iv during keymeshing |
| 512 * (but does initialize internal state from iv in key transport |
| 513 */ |
| 514 if (c->key_meshing&& c->count && c->count %1024 ==0) |
| 515 { |
| 516 cryptopro_key_meshing(&(c->cctx),buffer); |
| 517 } |
| 518 mac_block(&(c->cctx),c->buffer,data); |
| 519 c->count +=8; |
| 520 } |
| 521 |
| 522 int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count) |
| 523 { |
| 524 struct ossl_gost_imit_ctx *c = ctx->md_data; |
| 525 const unsigned char *p = data; |
| 526 size_t bytes = count,i; |
| 527 if (!(c->key_set)) { |
| 528 GOSTerr(GOST_F_GOST_IMIT_UPDATE, GOST_R_MAC_KEY_NOT_SET); |
| 529 return 0; |
| 530 } |
| 531 if (c->bytes_left) |
| 532 { |
| 533 for (i=c->bytes_left;i<8&&bytes>0;bytes--,i++,p++) |
| 534 { |
| 535 c->partial_block[i]=*p; |
| 536 } |
| 537 if (i==8) |
| 538 { |
| 539 mac_block_mesh(c,c->partial_block); |
| 540 } |
| 541 else |
| 542 { |
| 543 c->bytes_left = i; |
| 544 return 1; |
| 545 } |
| 546 } |
| 547 while (bytes>8) |
| 548 { |
| 549 mac_block_mesh(c,p); |
| 550 p+=8; |
| 551 bytes-=8; |
| 552 } |
| 553 if (bytes>0) |
| 554 { |
| 555 memcpy(c->partial_block,p,bytes); |
| 556 } |
| 557 c->bytes_left=bytes; |
| 558 return 1; |
| 559 } |
| 560 |
| 561 int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md) |
| 562 { |
| 563 struct ossl_gost_imit_ctx *c = ctx->md_data; |
| 564 if (!c->key_set) { |
| 565 GOSTerr(GOST_F_GOST_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET); |
| 566 return 0; |
| 567 } |
| 568 if (c->bytes_left) |
| 569 { |
| 570 int i; |
| 571 for (i=c->bytes_left;i<8;i++) |
| 572 { |
| 573 c->partial_block[i]=0; |
| 574 } |
| 575 mac_block_mesh(c,c->partial_block); |
| 576 } |
| 577 get_mac(c->buffer,32,md); |
| 578 return 1; |
| 579 } |
| 580 |
| 581 int gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr) |
| 582 { |
| 583 switch (type) |
| 584 { |
| 585 case EVP_MD_CTRL_KEY_LEN: |
| 586 *((unsigned int*)(ptr)) = 32; |
| 587 return 1; |
| 588 case EVP_MD_CTRL_SET_KEY: |
| 589 { |
| 590 if (arg!=32) { |
| 591 GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_LE
NGTH); |
| 592 return 0; |
| 593 } |
| 594 |
| 595 gost_key(&(((struct ossl_gost_imit_ctx*)(ctx->md_data))->cctx),p
tr) ; |
| 596 ((struct ossl_gost_imit_ctx*)(ctx->md_data))->key_set = 1; |
| 597 return 1; |
| 598 |
| 599 } |
| 600 default: |
| 601 return 0; |
| 602 } |
| 603 } |
| 604 |
| 605 int gost_imit_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) |
| 606 { |
| 607 memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_imit_ctx)); |
| 608 return 1; |
| 609 } |
| 610 |
| 611 /* Clean up imit ctx */ |
| 612 int gost_imit_cleanup(EVP_MD_CTX *ctx) |
| 613 { |
| 614 memset(ctx->md_data,0,sizeof(struct ossl_gost_imit_ctx)); |
| 615 return 1; |
| 616 } |
| 617 |
OLD | NEW |