1 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2 * project 2010. 3 */ 4 /* ==================================================================== 5 * Copyright (c) 2010 The OpenSSL Project. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * 3. All advertising materials mentioning features or use of this 20 * software must display the following acknowledgment: 21 * "This product includes software developed by the OpenSSL Project 22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 23 * 24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 25 * endorse or promote products derived from this software without 26 * prior written permission. For written permission, please contact 27 * licensing@OpenSSL.org. 28 * 29 * 5. Products derived from this software may not be called "OpenSSL" 30 * nor may "OpenSSL" appear in their names without prior written 31 * permission of the OpenSSL Project. 32 * 33 * 6. Redistributions of any form whatsoever must retain the following 34 * acknowledgment: 35 * "This product includes software developed by the OpenSSL Project 36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 37 * 38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 49 * OF THE POSSIBILITY OF SUCH DAMAGE. 50 * ==================================================================== 51 */ 52 53 #include <stdio.h> 54 #include "cryptlib.h" 55 #include <openssl/x509.h> 56 #include <openssl/x509v3.h> 57 #include <openssl/evp.h> 58 #include <openssl/cmac.h> 59 #include "evp_locl.h" 60 61 /* The context structure and "key" is simply a CMAC_CTX */ 62 63 static int pkey_cmac_init(EVP_PKEY_CTX *ctx) 64 { 65 ctx->data = CMAC_CTX_new(); 66 if (!ctx->data) 67 return 0; 68 ctx->keygen_info_count = 0; 69 return 1; 70 } 71 72 static int pkey_cmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 73 { 74 if (!pkey_cmac_init(dst)) 75 return 0; 76 if (!CMAC_CTX_copy(dst->data, src->data)) 77 return 0; 78 return 1; 79 } 80 81 static void pkey_cmac_cleanup(EVP_PKEY_CTX *ctx) 82 { 83 CMAC_CTX_free(ctx->data); 84 } 85 86 static int pkey_cmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 87 { 88 CMAC_CTX *cmkey = CMAC_CTX_new(); 89 CMAC_CTX *cmctx = ctx->data; 90 if (!cmkey) 91 return 0; 92 if (!CMAC_CTX_copy(cmkey, cmctx)) 93 { 94 CMAC_CTX_free(cmkey); 95 return 0; 96 } 97 EVP_PKEY_assign(pkey, EVP_PKEY_CMAC, cmkey); 98 99 return 1; 100 } 101 102 static int int_update(EVP_MD_CTX *ctx,const void *data,size_t count) 103 { 104 if (!CMAC_Update(ctx->pctx->data, data, count)) 105 return 0; 106 return 1; 107 } 108 109 static int cmac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) 110 { 111 EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT); 112 mctx->update = int_update; 113 return 1; 114 } 115 116 static int cmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, 117 EVP_MD_CTX *mctx) 118 { 119 return CMAC_Final(ctx->data, sig, siglen); 120 } 121 122 static int pkey_cmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 123 { 124 CMAC_CTX *cmctx = ctx->data; 125 switch (type) 126 { 127 128 case EVP_PKEY_CTRL_SET_MAC_KEY: 129 if (!p2 || p1 < 0) 130 return 0; 131 if (!CMAC_Init(cmctx, p2, p1, NULL, NULL)) 132 return 0; 133 break; 134 135 case EVP_PKEY_CTRL_CIPHER: 136 if (!CMAC_Init(cmctx, NULL, 0, p2, ctx->engine)) 137 return 0; 138 break; 139 140 case EVP_PKEY_CTRL_MD: 141 if (ctx->pkey && !CMAC_CTX_copy(ctx->data, 142 (CMAC_CTX *)ctx->pkey->pkey.ptr)) 143 return 0; 144 if (!CMAC_Init(cmctx, NULL, 0, NULL, NULL)) 145 return 0; 146 break; 147 148 default: 149 return -2; 150 151 } 152 return 1; 153 } 154 155 static int pkey_cmac_ctrl_str(EVP_PKEY_CTX *ctx, 156 const char *type, const char *value) 157 { 158 if (!value) 159 { 160 return 0; 161 } 162 if (!strcmp(type, "key")) 163 { 164 void *p = (void *)value; 165 return pkey_cmac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, 166 strlen(p), p); 167 } 168 if (!strcmp(type, "cipher")) 169 { 170 const EVP_CIPHER *c; 171 c = EVP_get_cipherbyname(value); 172 if (!c) 173 return 0; 174 return pkey_cmac_ctrl(ctx, EVP_PKEY_CTRL_CIPHER, -1, (void *)c); 175 } 176 if (!strcmp(type, "hexkey")) 177 { 178 unsigned char *key; 179 int r; 180 long keylen; 181 key = string_to_hex(value, &keylen); 182 if (!key) 183 return 0; 184 r = pkey_cmac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, keylen, key); 185 OPENSSL_free(key); 186 return r; 187 } 188 return -2; 189 } 190 191 const EVP_PKEY_METHOD cmac_pkey_meth = 192 { 193 EVP_PKEY_CMAC, 194 EVP_PKEY_FLAG_SIGCTX_CUSTOM, 195 pkey_cmac_init, 196 pkey_cmac_copy, 197 pkey_cmac_cleanup, 198 199 0, 0, 200 201 0, 202 pkey_cmac_keygen, 203 204 0, 0, 205 206 0, 0, 207 208 0,0, 209 210 cmac_signctx_init, 211 cmac_signctx, 212 213 0,0, 214 215 0,0, 216 217 0,0, 218 219 0,0, 220 221 pkey_cmac_ctrl, 222 pkey_cmac_ctrl_str 223 224 };