1 1.3 christos /* $NetBSD: sp800-108-kdf.c,v 1.4 2023/06/19 21:41:44 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (c) 2015, Secure Endpoints Inc. 5 1.1 christos * All rights reserved. 6 1.1 christos * 7 1.1 christos * Redistribution and use in source and binary forms, with or without 8 1.1 christos * modification, are permitted provided that the following conditions 9 1.1 christos * are met: 10 1.1 christos * 11 1.1 christos * - Redistributions of source code must retain the above copyright 12 1.1 christos * notice, this list of conditions and the following disclaimer. 13 1.1 christos * 14 1.1 christos * - Redistributions in binary form must reproduce the above copyright 15 1.1 christos * notice, this list of conditions and the following disclaimer in 16 1.1 christos * the documentation and/or other materials provided with the 17 1.1 christos * distribution. 18 1.1 christos * 19 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 1.1 christos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 1.1 christos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 1.1 christos * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 1.1 christos * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 1.1 christos * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 1.1 christos * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 1.1 christos * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 1.1 christos * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 christos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 30 1.1 christos * OF THE POSSIBILITY OF SUCH DAMAGE. 31 1.1 christos * 32 1.1 christos */ 33 1.1 christos 34 1.1 christos #include "krb5_locl.h" 35 1.1 christos 36 1.1 christos /* 37 1.1 christos * SP800-108 KDF 38 1.1 christos */ 39 1.1 christos 40 1.1 christos /** 41 1.1 christos * As described in SP800-108 5.1 (for HMAC) 42 1.1 christos * 43 1.1 christos * @param context Kerberos 5 context 44 1.1 christos * @param kdf_K1 Base key material. 45 1.1 christos * @param kdf_label A string that identifies the purpose for the derived key. 46 1.1 christos * @param kdf_context A binary string containing parties, nonce, etc. 47 1.1 christos * @param md Message digest function to use for PRF. 48 1.1 christos * @param kdf_K0 Derived key data. 49 1.1 christos * 50 1.1 christos * @return Return an error code for an failure or 0 on success. 51 1.1 christos * @ingroup krb5_crypto 52 1.1 christos */ 53 1.1 christos krb5_error_code 54 1.1 christos _krb5_SP800_108_HMAC_KDF(krb5_context context, 55 1.1 christos const krb5_data *kdf_K1, 56 1.1 christos const krb5_data *kdf_label, 57 1.1 christos const krb5_data *kdf_context, 58 1.1 christos const EVP_MD *md, 59 1.1 christos krb5_data *kdf_K0) 60 1.1 christos { 61 1.3 christos HMAC_CTX *c; 62 1.1 christos unsigned char *p = kdf_K0->data; 63 1.1 christos size_t i, n, left = kdf_K0->length; 64 1.1 christos unsigned char hmac[EVP_MAX_MD_SIZE]; 65 1.1 christos unsigned int h = EVP_MD_size(md); 66 1.1 christos const size_t L = kdf_K0->length; 67 1.1 christos 68 1.1 christos heim_assert(md != NULL, "SP800-108 KDF internal error"); 69 1.1 christos 70 1.3 christos #if OPENSSL_VERSION_NUMBER < 0x10100000UL 71 1.3 christos HMAC_CTX cs; 72 1.3 christos c = &cs; 73 1.3 christos HMAC_CTX_init(c); 74 1.3 christos #else 75 1.3 christos c = HMAC_CTX_new(); 76 1.3 christos #endif 77 1.1 christos 78 1.1 christos n = L / h; 79 1.1 christos 80 1.1 christos for (i = 0; i <= n; i++) { 81 1.1 christos unsigned char tmp[4]; 82 1.1 christos size_t len; 83 1.1 christos 84 1.3 christos HMAC_Init_ex(c, kdf_K1->data, kdf_K1->length, md, NULL); 85 1.1 christos 86 1.1 christos _krb5_put_int(tmp, i + 1, 4); 87 1.3 christos HMAC_Update(c, tmp, 4); 88 1.3 christos HMAC_Update(c, kdf_label->data, kdf_label->length); 89 1.3 christos HMAC_Update(c, (unsigned char *)"", 1); 90 1.1 christos if (kdf_context) 91 1.3 christos HMAC_Update(c, kdf_context->data, kdf_context->length); 92 1.1 christos _krb5_put_int(tmp, L * 8, 4); 93 1.3 christos HMAC_Update(c, tmp, 4); 94 1.1 christos 95 1.3 christos HMAC_Final(c, hmac, &h); 96 1.1 christos len = h > left ? left : h; 97 1.1 christos memcpy(p, hmac, len); 98 1.1 christos p += len; 99 1.1 christos left -= len; 100 1.1 christos } 101 1.1 christos 102 1.3 christos #if OPENSSL_VERSION_NUMBER < 0x10100000UL 103 1.3 christos HMAC_CTX_cleanup(c); 104 1.3 christos #else 105 1.3 christos HMAC_CTX_free(c); 106 1.3 christos #endif 107 1.1 christos 108 1.1 christos return 0; 109 1.1 christos } 110