xref: /xnu-8792.81.2/osfmk/corecrypto/cchmac_init.c (revision 19c3b8c28c31cb8130e034cfb5df6bf9ba342d90)
1 /* Copyright (c) (2010,2011,2015,2016,2018,2019) 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  */
49 void
cchmac_init(const struct ccdigest_info * di,cchmac_ctx_t hc,size_t key_len,const void * key_data)50 cchmac_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), key_len, 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