1 /* $OpenBSD: gost89imit_pmeth.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 52 #include <string.h> 53 54 #include <openssl/opensslconf.h> 55 56 #ifndef OPENSSL_NO_GOST 57 #include <openssl/evp.h> 58 #include <openssl/err.h> 59 #include <openssl/gost.h> 60 #include <openssl/x509v3.h> /* For string_to_hex */ 61 62 #include "evp_locl.h" 63 #include "gost_locl.h" 64 65 struct gost_mac_pmeth_data { 66 EVP_MD *md; 67 unsigned char key[32]; 68 unsigned key_set :1; 69 }; 70 71 static int 72 pkey_gost_mac_init(EVP_PKEY_CTX *ctx) 73 { 74 struct gost_mac_pmeth_data *data; 75 76 data = calloc(1, sizeof(struct gost_mac_pmeth_data)); 77 if (data == NULL) 78 return 0; 79 EVP_PKEY_CTX_set_data(ctx, data); 80 return 1; 81 } 82 83 static void 84 pkey_gost_mac_cleanup(EVP_PKEY_CTX *ctx) 85 { 86 struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); 87 free(data); 88 } 89 90 static int 91 pkey_gost_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 92 { 93 struct gost_mac_pmeth_data *dst_data, *src_data; 94 95 if (pkey_gost_mac_init(dst) == 0) 96 return 0; 97 98 src_data = EVP_PKEY_CTX_get_data(src); 99 dst_data = EVP_PKEY_CTX_get_data(dst); 100 101 *dst_data = *src_data; 102 103 return 1; 104 } 105 106 static int 107 pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 108 { 109 struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); 110 unsigned char *keydata; 111 112 if (!data->key_set) { 113 GOSTerror(GOST_R_MAC_KEY_NOT_SET); 114 return 0; 115 } 116 117 keydata = malloc(32); 118 if (keydata == NULL) { 119 GOSTerror(ERR_R_MALLOC_FAILURE); 120 return 0; 121 } 122 memcpy(keydata, data->key, 32); 123 EVP_PKEY_assign(pkey, NID_id_Gost28147_89_MAC, keydata); 124 125 return 1; 126 } 127 128 static int 129 pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 130 { 131 struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); 132 133 switch (type) { 134 case EVP_PKEY_CTRL_MD: 135 if (EVP_MD_type(p2) != NID_id_Gost28147_89_MAC) { 136 GOSTerror(GOST_R_INVALID_DIGEST_TYPE); 137 return 0; 138 } 139 data->md = p2; 140 return 1; 141 142 case EVP_PKEY_CTRL_SET_MAC_KEY: 143 if (p1 != 32) { 144 GOSTerror(GOST_R_INVALID_MAC_KEY_LENGTH); 145 return 0; 146 } 147 148 memcpy(data->key, p2, 32); 149 data->key_set = 1; 150 return 1; 151 152 case EVP_PKEY_CTRL_DIGESTINIT: 153 { 154 EVP_MD_CTX *mctx = p2; 155 void *key; 156 157 if (!data->key_set) { 158 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); 159 if (pkey == NULL) { 160 GOSTerror(GOST_R_MAC_KEY_NOT_SET); 161 return 0; 162 } 163 key = EVP_PKEY_get0(pkey); 164 if (key == NULL) { 165 GOSTerror(GOST_R_MAC_KEY_NOT_SET); 166 return 0; 167 } 168 } else { 169 key = &(data->key); 170 } 171 if (mctx->digest->md_ctrl == NULL) 172 return 0; 173 return mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_SET_KEY, 32 * 8, 174 key); 175 } 176 177 } 178 179 return -2; 180 } 181 182 static int 183 pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) 184 { 185 if (value == NULL) 186 return 0; 187 if (strcmp(type, "key") == 0) { 188 void *p = (void *)value; 189 return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, 190 strlen(value), p); 191 } 192 if (strcmp(type, "hexkey") == 0) { 193 unsigned char *key; 194 int r; 195 long keylen; 196 197 key = string_to_hex(value, &keylen); 198 if (key == NULL) 199 return 0; 200 r = pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, keylen, 201 key); 202 free(key); 203 return r; 204 } 205 return -2; 206 } 207 208 static int 209 pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) 210 { 211 return 1; 212 } 213 214 static int 215 pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, 216 EVP_MD_CTX *mctx) 217 { 218 /* for platforms where sizeof(int) != sizeof(size_t)*/ 219 unsigned int tmpsiglen = *siglen; 220 int ret; 221 222 if (sig == NULL) { 223 *siglen = 4; 224 return 1; 225 } 226 227 ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen); 228 *siglen = tmpsiglen; 229 return ret; 230 } 231 232 const EVP_PKEY_METHOD gostimit_pkey_meth = { 233 .pkey_id = EVP_PKEY_GOSTIMIT, 234 235 .init = pkey_gost_mac_init, 236 .cleanup = pkey_gost_mac_cleanup, 237 .copy = pkey_gost_mac_copy, 238 239 .keygen = pkey_gost_mac_keygen, 240 241 .signctx_init = pkey_gost_mac_signctx_init, 242 .signctx = pkey_gost_mac_signctx, 243 244 .ctrl = pkey_gost_mac_ctrl, 245 .ctrl_str = pkey_gost_mac_ctrl_str, 246 }; 247 248 #endif 249