/* Wrapper around gostcrypt function from gost89.c which perform * key meshing when nesseccary */ static void gost_crypt_mesh (void *ctx,unsigned char *iv,unsigned char *buf) { struct ossl_gost_cipher_ctx *c = ctx; if (c->count&&c->key_meshing && c->count%1024==0) { cryptopro_key_meshing(&(c->cctx),iv); } gostcrypt(&(c->cctx),iv,buf); c->count+=8; }
/* Wrapper around gostcrypt function from gost89.c which perform * key meshing when nesseccary */ static void gost_crypt_mesh (void *ctx,unsigned char *iv,unsigned char *buf) { struct ossl_gost_cipher_ctx *c = ctx; assert(c->count%8 == 0 && c->count <= 1024); if (c->key_meshing && c->count==1024) { cryptopro_key_meshing(&(c->cctx),iv); } gostcrypt(&(c->cctx),iv,buf); c->count = c->count%1024 + 8; }
static void gost_cnt_next (void *ctx, unsigned char *iv, unsigned char *buf) { struct ossl_gost_cipher_ctx *c = ctx; word32 g,go; unsigned char buf1[8]; assert(c->count%8 == 0 && c->count <= 1024); if (c->key_meshing && c->count==1024) { cryptopro_key_meshing(&(c->cctx),iv); } if (c->count==0) { gostcrypt(&(c->cctx),iv,buf1); } else { memcpy(buf1,iv,8); } g = buf1[0]|(buf1[1]<<8)|(buf1[2]<<16)|((word32)buf1[3]<<24); g += 0x01010101; buf1[0]=(unsigned char)(g&0xff); buf1[1]=(unsigned char)((g>>8)&0xff); buf1[2]=(unsigned char)((g>>16)&0xff); buf1[3]=(unsigned char)((g>>24)&0xff); g = buf1[4]|(buf1[5]<<8)|(buf1[6]<<16)|((word32)buf1[7]<<24); go = g; g += 0x01010104; if (go > g) /* overflow*/ g++; buf1[4]=(unsigned char)(g&0xff); buf1[5]=(unsigned char)((g>>8)&0xff); buf1[6]=(unsigned char)((g>>16)&0xff); buf1[7]=(unsigned char)((g>>24)&0xff); memcpy(iv,buf1,8); gostcrypt(&(c->cctx),buf1,buf); c->count = c->count%1024 + 8; }
static int dstu_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { gost_subst_block sbox; gost_ctx *gctx = ctx->cipher_data; unpack_sbox(default_sbox, &sbox); gost_init(gctx, &sbox); if (key) gost_key(gctx, key); if (iv) { memcpy(ctx->oiv, iv, DSTU_CIPHER_BLOCK_SIZE); memcpy(ctx->iv, iv, DSTU_CIPHER_BLOCK_SIZE); gostcrypt(gctx, ctx->iv, ctx->buf); ctx->num = 0; } return 1; }
static int dstu_cipher_ctrl(EVP_CIPHER_CTX *ctx, int cmd, int p1, void *p2) { gost_subst_block sbox; gost_ctx *gctx = ctx->cipher_data; switch (cmd) { case DSTU_SET_CUSTOM_SBOX: if ((!p2) || (sizeof(default_sbox) != p1)) return 0; unpack_sbox((unsigned char *)p2, &sbox); gost_init(gctx, &sbox); memcpy(ctx->iv, ctx->oiv, DSTU_CIPHER_BLOCK_SIZE); gostcrypt(gctx, ctx->iv, ctx->buf); return 1; case EVP_CTRL_PBE_PRF_NID: if (!p2) return 0; *((int *)(p2)) = NID_hmacWithDstu34311; return 1; } return 0; }
virtual void do_block(data_type * data) override { gostcrypt(&m_ctx, data, data); }
static int dstu_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) { size_t to_use, i, blocks; gost_ctx *gctx = ctx->cipher_data; unsigned char tmpiv[DSTU_CIPHER_BLOCK_SIZE], *out_start = out; if ((!inl) && (!in)) return 0; if ((!inl) || (!in)) return -1; if (ctx->num) { to_use = ((size_t)(ctx->num) < inl) ? (size_t)(ctx->num) : inl; for (i = 0; i < to_use; i++) { if (ctx->encrypt) { *out = *in ^ ctx->buf[DSTU_CIPHER_BLOCK_SIZE - ctx->num + i]; ctx->iv[DSTU_CIPHER_BLOCK_SIZE - ctx->num + i] = *out; } else { ctx->iv[DSTU_CIPHER_BLOCK_SIZE - ctx->num + i] = *in; *out = *in ^ ctx->buf[DSTU_CIPHER_BLOCK_SIZE - ctx->num + i]; } in++; out++; } ctx->num -= to_use; inl -= to_use; if (!ctx->num) gostcrypt(gctx, ctx->iv, ctx->buf); } if (inl) { blocks = inl >> 3; if (blocks) { if (ctx->encrypt) { gost_enc_cfb(gctx, ctx->iv, in, out, blocks); memcpy(ctx->iv, out + (blocks * DSTU_CIPHER_BLOCK_SIZE) - DSTU_CIPHER_BLOCK_SIZE, DSTU_CIPHER_BLOCK_SIZE); } else { memcpy(tmpiv, ctx->iv, DSTU_CIPHER_BLOCK_SIZE); memcpy(ctx->iv, in + (blocks * DSTU_CIPHER_BLOCK_SIZE) - DSTU_CIPHER_BLOCK_SIZE, DSTU_CIPHER_BLOCK_SIZE); gost_dec_cfb(gctx, tmpiv, in, out, blocks); } gostcrypt(gctx, ctx->iv, ctx->buf); out += blocks * DSTU_CIPHER_BLOCK_SIZE; in += blocks * DSTU_CIPHER_BLOCK_SIZE; inl -= blocks * DSTU_CIPHER_BLOCK_SIZE; } } if (inl) { for (i = 0; i < inl; i++) { if (ctx->encrypt) { *out = *in ^ ctx->buf[i]; ctx->iv[i] = *out; } else { ctx->iv[i] = *in; *out = *in ^ ctx->buf[i]; } in++; out++; } ctx->num = DSTU_CIPHER_BLOCK_SIZE - inl; } return out - out_start; }