1 /* $OpenBSD: e_gost2814789.c,v 1.4 2017/01/29 17:49:23 beck Exp $ */ 2 /* 3 * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> 4 * Copyright (c) 2005-2006 Cryptocom LTD 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * 3. All advertising materials mentioning features or use of this 19 * software must display the following acknowledgment: 20 * "This product includes software developed by the OpenSSL Project 21 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 22 * 23 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 24 * endorse or promote products derived from this software without 25 * prior written permission. For written permission, please contact 26 * openssl-core@openssl.org. 27 * 28 * 5. Products derived from this software may not be called "OpenSSL" 29 * nor may "OpenSSL" appear in their names without prior written 30 * permission of the OpenSSL Project. 31 * 32 * 6. Redistributions of any form whatsoever must retain the following 33 * acknowledgment: 34 * "This product includes software developed by the OpenSSL Project 35 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 36 * 37 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 38 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 40 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 43 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 46 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 48 * OF THE POSSIBILITY OF SUCH DAMAGE. 49 * ==================================================================== 50 */ 51 #include <string.h> 52 53 #include <openssl/opensslconf.h> 54 55 #ifndef OPENSSL_NO_GOST 56 #include <openssl/evp.h> 57 #include <openssl/err.h> 58 #include <openssl/gost.h> 59 #include "evp_locl.h" 60 61 typedef struct { 62 GOST2814789_KEY ks; 63 int param_nid; 64 } EVP_GOST2814789_CTX; 65 66 static int 67 gost2814789_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) 68 { 69 EVP_GOST2814789_CTX *c = ctx->cipher_data; 70 71 switch (type) { 72 case EVP_CTRL_PBE_PRF_NID: 73 if (ptr != NULL) { 74 *((int *)ptr) = NID_id_HMACGostR3411_94; 75 return 1; 76 } else { 77 return 0; 78 } 79 case EVP_CTRL_INIT: 80 /* Default value to have any s-box set at all */ 81 c->param_nid = NID_id_Gost28147_89_CryptoPro_A_ParamSet; 82 return Gost2814789_set_sbox(&c->ks, c->param_nid); 83 case EVP_CTRL_GOST_SET_SBOX: 84 return Gost2814789_set_sbox(&c->ks, arg); 85 default: 86 return -1; 87 } 88 } 89 90 static int 91 gost2814789_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 92 const unsigned char *iv, int enc) 93 { 94 EVP_GOST2814789_CTX *c = ctx->cipher_data; 95 96 return Gost2814789_set_key(&c->ks, key, ctx->key_len * 8); 97 } 98 99 int 100 gost2814789_set_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) 101 { 102 int len = 0; 103 unsigned char *buf = NULL; 104 unsigned char *p = NULL; 105 EVP_GOST2814789_CTX *c = ctx->cipher_data; 106 ASN1_OCTET_STRING *os = NULL; 107 GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new(); 108 109 if (gcp == NULL) { 110 GOSTerror(ERR_R_MALLOC_FAILURE); 111 return 0; 112 } 113 if (ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len) == 0) { 114 GOST_CIPHER_PARAMS_free(gcp); 115 GOSTerror(ERR_R_ASN1_LIB); 116 return 0; 117 } 118 ASN1_OBJECT_free(gcp->enc_param_set); 119 gcp->enc_param_set = OBJ_nid2obj(c->param_nid); 120 121 len = i2d_GOST_CIPHER_PARAMS(gcp, NULL); 122 p = buf = malloc(len); 123 if (buf == NULL) { 124 GOST_CIPHER_PARAMS_free(gcp); 125 GOSTerror(ERR_R_MALLOC_FAILURE); 126 return 0; 127 } 128 i2d_GOST_CIPHER_PARAMS(gcp, &p); 129 GOST_CIPHER_PARAMS_free(gcp); 130 131 os = ASN1_OCTET_STRING_new(); 132 if (os == NULL) { 133 free(buf); 134 GOSTerror(ERR_R_MALLOC_FAILURE); 135 return 0; 136 } 137 if (ASN1_OCTET_STRING_set(os, buf, len) == 0) { 138 ASN1_OCTET_STRING_free(os); 139 free(buf); 140 GOSTerror(ERR_R_ASN1_LIB); 141 return 0; 142 } 143 free(buf); 144 145 ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os); 146 return 1; 147 } 148 149 int 150 gost2814789_get_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) 151 { 152 int ret = -1; 153 int len; 154 GOST_CIPHER_PARAMS *gcp = NULL; 155 EVP_GOST2814789_CTX *c = ctx->cipher_data; 156 unsigned char *p; 157 158 if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) 159 return ret; 160 161 p = params->value.sequence->data; 162 163 gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p, 164 params->value.sequence->length); 165 166 len = gcp->iv->length; 167 if (len != ctx->cipher->iv_len) { 168 GOST_CIPHER_PARAMS_free(gcp); 169 GOSTerror(GOST_R_INVALID_IV_LENGTH); 170 return -1; 171 } 172 173 if (!Gost2814789_set_sbox(&c->ks, OBJ_obj2nid(gcp->enc_param_set))) { 174 GOST_CIPHER_PARAMS_free(gcp); 175 return -1; 176 } 177 c->param_nid = OBJ_obj2nid(gcp->enc_param_set); 178 179 memcpy(ctx->oiv, gcp->iv->data, len); 180 memcpy(ctx->iv, gcp->iv->data, len); 181 182 GOST_CIPHER_PARAMS_free(gcp); 183 184 return 1; 185 } 186 187 BLOCK_CIPHER_func_ecb(gost2814789, Gost2814789, EVP_GOST2814789_CTX, ks) 188 BLOCK_CIPHER_func_cfb(gost2814789, Gost2814789, 64, EVP_GOST2814789_CTX, ks) 189 190 static int 191 gost2814789_cnt_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 192 const unsigned char *in, size_t inl) 193 { 194 EVP_GOST2814789_CTX *c = ctx->cipher_data; 195 196 while (inl >= EVP_MAXCHUNK) { 197 Gost2814789_cnt_encrypt(in, out, (long)EVP_MAXCHUNK, &c->ks, 198 ctx->iv, ctx->buf, &ctx->num); 199 inl -= EVP_MAXCHUNK; 200 in += EVP_MAXCHUNK; 201 out += EVP_MAXCHUNK; 202 } 203 204 if (inl) 205 Gost2814789_cnt_encrypt(in, out, inl, &c->ks, ctx->iv, ctx->buf, 206 &ctx->num); 207 return 1; 208 } 209 210 /* gost89 is CFB-64 */ 211 #define NID_gost89_cfb64 NID_id_Gost28147_89 212 213 BLOCK_CIPHER_def_ecb(gost2814789, EVP_GOST2814789_CTX, NID_gost89, 8, 32, 214 EVP_CIPH_NO_PADDING | EVP_CIPH_CTRL_INIT, 215 gost2814789_init_key, NULL, gost2814789_set_asn1_params, 216 gost2814789_get_asn1_params, gost2814789_ctl) 217 BLOCK_CIPHER_def_cfb(gost2814789, EVP_GOST2814789_CTX, NID_gost89, 32, 8, 64, 218 EVP_CIPH_NO_PADDING | EVP_CIPH_CTRL_INIT, 219 gost2814789_init_key, NULL, gost2814789_set_asn1_params, 220 gost2814789_get_asn1_params, gost2814789_ctl) 221 BLOCK_CIPHER_def1(gost2814789, cnt, cnt, OFB, EVP_GOST2814789_CTX, NID_gost89, 222 1, 32, 8, EVP_CIPH_NO_PADDING | EVP_CIPH_CTRL_INIT, 223 gost2814789_init_key, NULL, gost2814789_set_asn1_params, 224 gost2814789_get_asn1_params, gost2814789_ctl) 225 #endif 226