1/* Copyright (c) (2010,2011,2015,2016,2018,2019,2021,2022) Apple Inc. All rights reserved.
2 *
3 * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which
4 * is contained in the License.txt file distributed with corecrypto) and only to
5 * people who accept that license. IMPORTANT: Any license rights granted to you by
6 * Apple Inc. (if any) are limited to internal use within your organization only on
7 * devices and computers you own or control, for the sole purpose of verifying the
8 * security characteristics and correct functioning of the Apple Software. You may
9 * not, directly or indirectly, redistribute the Apple Software or any portions thereof.
10 *
11 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
12 *
13 * This file contains Original Code and/or Modifications of Original Code
14 * as defined in and that are subject to the Apple Public Source License
15 * Version 2.0 (the 'License'). You may not use this file except in
16 * compliance with the License. The rights granted to you under the License
17 * may not be used to create, or enable the creation or redistribution of,
18 * unlawful or unlicensed copies of an Apple operating system, or to
19 * circumvent, violate, or enable the circumvention or violation of, any
20 * terms of an Apple operating system software license agreement.
21 *
22 * Please obtain a copy of the License at
23 * http://www.opensource.apple.com/apsl/ and read it before using this file.
24 *
25 * The Original Code and all software distributed under the License are
26 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
27 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
28 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
30 * Please see the License for the specific language governing rights and
31 * limitations under the License.
32 *
33 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
34 */
35
36#include "cc_internal.h"
37#include <corecrypto/ccdigest_priv.h>
38#include <corecrypto/cchmac.h>
39#include <corecrypto/ccn.h>
40#include <corecrypto/cc_priv.h>
41
42/* The HMAC_<DIG> transform looks like:
43 * <DIG> (K XOR opad || <DIG> (K XOR ipad || text))
44 * Where K is a n byte key
45 * ipad is the byte 0x36 repeated 64 times.
46 * opad is the byte 0x5c repeated 64 times.
47 * text is the data being protected.
48 */
49void
50cchmac_init(const struct ccdigest_info *di, cchmac_ctx_t hc,
51 size_t key_len, const void *key_data)
52{
53 CC_ENSURE_DIT_ENABLED
54
55 const unsigned char *key = key_data;
56
57 /* Set cchmac_data(di, hc) to key ^ opad. */
58 size_t byte = 0;
59 if (key_len <= di->block_size) {
60 for (; byte < key_len; ++byte) {
61 cchmac_data(di, hc)[byte] = key[byte] ^ 0x5c;
62 }
63 } else {
64 /* Key is longer than di->block size, reset it to key=digest(key) */
65 ccdigest_init(di, cchmac_digest_ctx(di, hc));
66 ccdigest_update(di, cchmac_digest_ctx(di, hc), len: key_len, data: key);
67 ccdigest_final(di, cchmac_digest_ctx(di, hc), cchmac_data(di, hc));
68 key_len = di->output_size;
69 for (; byte < key_len; ++byte) {
70 cchmac_data(di, hc)[byte] ^= 0x5c;
71 }
72 }
73 /* Fill remainder of cchmac_data(di, hc) with opad. */
74 if (key_len < di->block_size) {
75 cc_memset(cchmac_data(di, hc) + key_len, 0x5c, di->block_size - key_len);
76 }
77
78 /* Set cchmac_ostate32(di, hc) to the state of the first round of the
79 * outer digest. */
80 ccdigest_copy_state(di, cchmac_ostate32(di, hc), di->initial_state);
81 di->compress(cchmac_ostate(di, hc), 1, cchmac_data(di, hc));
82
83 /* Set cchmac_data(di, hc) to key ^ ipad. */
84 for (byte = 0; byte < di->block_size; ++byte) {
85 cchmac_data(di, hc)[byte] ^= (0x5c ^ 0x36);
86 }
87 ccdigest_copy_state(di, cchmac_istate32(di, hc), di->initial_state);
88 di->compress(cchmac_istate(di, hc), 1, cchmac_data(di, hc));
89 cchmac_num(di, hc) = 0;
90 cchmac_nbits(di, hc) = di->block_size * 8;
91}
92