1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* lib/crypto/openssl/cmac.c - OpenSSL CMAC implementation */ 3 /* 4 * Copyright (C) 2021 by the Massachusetts Institute of Technology. 5 * 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 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * * 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 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 30 * OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "crypto_int.h" 34 35 #ifdef K5_OPENSSL_CMAC 36 37 #include <openssl/evp.h> 38 #include <openssl/params.h> 39 #include <openssl/core_names.h> 40 41 krb5_error_code 42 krb5int_cmac_checksum(const struct krb5_enc_provider *enc, krb5_key key, 43 const krb5_crypto_iov *data, size_t num_data, 44 krb5_data *output) 45 { 46 int ok; 47 EVP_MAC *mac = NULL; 48 EVP_MAC_CTX *ctx = NULL; 49 OSSL_PARAM params[2], *p = params; 50 size_t i = 0, md_len; 51 char *cipher; 52 53 if (enc == &krb5int_enc_camellia128) 54 cipher = "CAMELLIA-128-CBC"; 55 else if (enc == &krb5int_enc_camellia256) 56 cipher = "CAMELLIA-256-CBC"; 57 else 58 return KRB5_CRYPTO_INTERNAL; 59 60 mac = EVP_MAC_fetch(NULL, "CMAC", NULL); 61 if (mac == NULL) 62 return KRB5_CRYPTO_INTERNAL; 63 64 ctx = EVP_MAC_CTX_new(mac); 65 if (ctx == NULL) { 66 ok = 0; 67 goto cleanup; 68 } 69 70 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_CIPHER, cipher, 0); 71 *p = OSSL_PARAM_construct_end(); 72 73 ok = EVP_MAC_init(ctx, key->keyblock.contents, key->keyblock.length, 74 params); 75 for (i = 0; ok && i < num_data; i++) { 76 const krb5_crypto_iov *iov = &data[i]; 77 if (!SIGN_IOV(iov)) 78 continue; 79 ok = EVP_MAC_update(ctx, (uint8_t *)iov->data.data, iov->data.length); 80 } 81 ok = ok && EVP_MAC_final(ctx, (unsigned char *)output->data, &md_len, 82 output->length); 83 if (!ok) 84 goto cleanup; 85 output->length = md_len; 86 87 cleanup: 88 EVP_MAC_free(mac); 89 EVP_MAC_CTX_free(ctx); 90 return ok ? 0 : KRB5_CRYPTO_INTERNAL; 91 } 92 93 #endif /* K5_OPENSSL_CMAC */ 94