1 /* $OpenBSD: gost89imit_pmeth.c,v 1.2 2014/11/09 23:06:52 miod 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 GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN, GOST_R_MAC_KEY_NOT_SET); 114 return 0; 115 } 116 117 keydata = malloc(32); 118 if (keydata == NULL) { 119 GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN, 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 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, 137 GOST_R_INVALID_DIGEST_TYPE); 138 return 0; 139 } 140 data->md = p2; 141 return 1; 142 143 case EVP_PKEY_CTRL_SET_MAC_KEY: 144 if (p1 != 32) { 145 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, 146 GOST_R_INVALID_MAC_KEY_LENGTH); 147 return 0; 148 } 149 150 memcpy(data->key, p2, 32); 151 data->key_set = 1; 152 return 1; 153 154 case EVP_PKEY_CTRL_DIGESTINIT: 155 { 156 EVP_MD_CTX *mctx = p2; 157 void *key; 158 159 if (!data->key_set) { 160 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); 161 if (pkey == NULL) { 162 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, 163 GOST_R_MAC_KEY_NOT_SET); 164 return 0; 165 } 166 key = EVP_PKEY_get0(pkey); 167 if (key == NULL) { 168 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, 169 GOST_R_MAC_KEY_NOT_SET); 170 return 0; 171 } 172 } else { 173 key = &(data->key); 174 } 175 if (mctx->digest->md_ctrl == NULL) 176 return 0; 177 return mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_SET_KEY, 32 * 8, 178 key); 179 } 180 181 } 182 183 return -2; 184 } 185 186 static int 187 pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) 188 { 189 if (value == NULL) 190 return 0; 191 if (strcmp(type, "key") == 0) { 192 void *p = (void *)value; 193 return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, 194 strlen(value), p); 195 } 196 if (strcmp(type, "hexkey") == 0) { 197 unsigned char *key; 198 int r; 199 long keylen; 200 201 key = string_to_hex(value, &keylen); 202 if (key == NULL) 203 return 0; 204 r = pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, keylen, 205 key); 206 free(key); 207 return r; 208 } 209 return -2; 210 } 211 212 static int 213 pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) 214 { 215 return 1; 216 } 217 218 static int 219 pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, 220 EVP_MD_CTX *mctx) 221 { 222 /* for platforms where sizeof(int) != sizeof(size_t)*/ 223 unsigned int tmpsiglen = *siglen; 224 int ret; 225 226 if (sig == NULL) { 227 *siglen = 4; 228 return 1; 229 } 230 231 ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen); 232 *siglen = tmpsiglen; 233 return ret; 234 } 235 236 const EVP_PKEY_METHOD gostimit_pkey_meth = { 237 .pkey_id = EVP_PKEY_GOSTIMIT, 238 239 .init = pkey_gost_mac_init, 240 .cleanup = pkey_gost_mac_cleanup, 241 .copy = pkey_gost_mac_copy, 242 243 .keygen = pkey_gost_mac_keygen, 244 245 .signctx_init = pkey_gost_mac_signctx_init, 246 .signctx = pkey_gost_mac_signctx, 247 248 .ctrl = pkey_gost_mac_ctrl, 249 .ctrl_str = pkey_gost_mac_ctrl_str, 250 }; 251 252 #endif 253