1 /*
2 * Copyright (c) 2019-2022 Apple Inc.
3 * All rights reserved.
4 */
5
6 #include <sys/systm.h>
7 #include <sys/errno.h>
8 #include <corecrypto/cchmac.h>
9 #include <net/content_filter.h>
10 #include <net/content_filter_crypto.h>
11
12 extern int cfil_log_level;
13
14 #define CFIL_CRYPTO_LOG(level, fmt, ...) \
15 do { \
16 if (cfil_log_level >= level) \
17 printf("%s:%d " fmt "\n",\
18 __FUNCTION__, __LINE__, ##__VA_ARGS__); \
19 } while (0)
20
21 #define CFIL_CRYPTO_LOG_4BYTES(name) \
22 CFIL_CRYPTO_LOG(LOG_DEBUG, \
23 "%s \t%s: %hhX %hhX %hhX %hhX", \
24 prefix, name, ptr[0], ptr[1], ptr[2], ptr[3])
25
26 #define CFIL_CRYPTO_LOG_8BYTES(name) \
27 CFIL_CRYPTO_LOG(LOG_DEBUG, \
28 "%s \t%s: %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX", \
29 prefix, name, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7])
30
31 #define CFIL_CRYPTO_LOG_16BYTES(name) \
32 CFIL_CRYPTO_LOG(LOG_DEBUG, \
33 "%s \t%s: %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX", \
34 prefix, name, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15])
35
36 #define CFIL_CRYPTO_LOG_28BYTES(name) \
37 CFIL_CRYPTO_LOG(LOG_DEBUG, \
38 "%s \t%s: %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX", \
39 prefix, name, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18], ptr[19], ptr[20], ptr[21], ptr[22], ptr[23], ptr[24], ptr[25], ptr[26], ptr[27])
40
41 #define CFIL_CRYPTO_LOG_32BYTES(name, prefix) \
42 CFIL_CRYPTO_LOG(LOG_DEBUG, \
43 "%s \t%s: %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX", \
44 prefix, name, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18], ptr[19], ptr[20], ptr[21], ptr[22], ptr[23], ptr[24], ptr[25], ptr[26], ptr[27], ptr[28], ptr[29], ptr[30], ptr[31])
45
46 static void
cfil_crypto_print_data(cfil_crypto_data_t data,const char * prefix)47 cfil_crypto_print_data(cfil_crypto_data_t data, const char *prefix)
48 {
49 u_int8_t *ptr = NULL;
50 CFIL_CRYPTO_LOG(LOG_DEBUG, "%s NE Filter crypto data:", prefix);
51
52 ptr = (u_int8_t *)&data->flow_id;
53 CFIL_CRYPTO_LOG_16BYTES("flow_id");
54
55 ptr = (u_int8_t *)&data->sock_id;
56 CFIL_CRYPTO_LOG_8BYTES("sock_id");
57
58 ptr = (u_int8_t *)&data->direction;
59 CFIL_CRYPTO_LOG_4BYTES("direction");
60
61 ptr = (u_int8_t *)&data->remote;
62 CFIL_CRYPTO_LOG_28BYTES("remote");
63 ptr = (u_int8_t *)&data->local;
64 CFIL_CRYPTO_LOG_28BYTES("local");
65
66 ptr = (u_int8_t *)&data->socketProtocol;
67 CFIL_CRYPTO_LOG_4BYTES("socketProtocol");
68
69 ptr = (u_int8_t *)&data->pid;
70 CFIL_CRYPTO_LOG_4BYTES("pid");
71
72 ptr = (u_int8_t *)&data->effective_pid;
73 CFIL_CRYPTO_LOG_4BYTES("effective_pid");
74
75 ptr = (u_int8_t *)&data->responsible_pid;
76 CFIL_CRYPTO_LOG_4BYTES("responsible_pid");
77
78 ptr = (u_int8_t *)&data->uuid;
79 CFIL_CRYPTO_LOG_16BYTES("uuid");
80 ptr = (u_int8_t *)&data->effective_uuid;
81 CFIL_CRYPTO_LOG_16BYTES("effective_uuid");
82 ptr = (u_int8_t *)&data->responsible_uuid;
83 CFIL_CRYPTO_LOG_16BYTES("responsible_uuid");
84
85 ptr = (u_int8_t *)&data->byte_count_in;
86 CFIL_CRYPTO_LOG_8BYTES("byte_count_in");
87
88 ptr = (u_int8_t *)&data->byte_count_out;
89 CFIL_CRYPTO_LOG_8BYTES("byte_count_out");
90 }
91
92 cfil_crypto_state_t
cfil_crypto_init_client(cfil_crypto_key client_key)93 cfil_crypto_init_client(cfil_crypto_key client_key)
94 {
95 if (client_key == NULL) {
96 return NULL;
97 }
98
99 struct cfil_crypto_state *state;
100 state = kalloc_type(struct cfil_crypto_state,
101 Z_WAITOK | Z_ZERO | Z_NOFAIL);
102
103 memcpy(state->key, client_key, sizeof(cfil_crypto_key));
104 state->digest_info = ccsha256_di();
105
106 CFIL_CRYPTO_LOG(LOG_DEBUG, "Inited client key");
107 return state;
108 }
109
110 void
cfil_crypto_cleanup_state(cfil_crypto_state_t state)111 cfil_crypto_cleanup_state(cfil_crypto_state_t state)
112 {
113 if (state != NULL) {
114 kfree_type(struct cfil_crypto_state, state);
115 }
116 }
117
118 static void
cfil_crypto_update_context(const struct ccdigest_info * di,cchmac_ctx_t ctx,cfil_crypto_data_t data,const struct iovec * __counted_by (extra_data_count)extra_data,size_t extra_data_count)119 cfil_crypto_update_context(const struct ccdigest_info *di,
120 cchmac_ctx_t ctx, cfil_crypto_data_t data,
121 const struct iovec *__counted_by(extra_data_count)extra_data, size_t extra_data_count)
122 {
123 const uint8_t context[32] = {[0 ... 31] = 0x20}; // 0x20 repeated 32 times
124 const char context_string[] = "NEFilterCrypto";
125 uint8_t separator = 0;
126 cchmac_update(di, ctx, sizeof(context), context);
127 cchmac_update(di, ctx, sizeof(context_string) - 1, context_string);
128 cchmac_update(di, ctx, sizeof(separator), &separator);
129 cchmac_update(di, ctx, sizeof(struct cfil_crypto_data), data);
130 for (size_t extra_idx = 0; extra_idx < extra_data_count; extra_idx++) {
131 if (extra_data[extra_idx].iov_base != NULL && extra_data[extra_idx].iov_len > 0) {
132 cchmac_update(di, ctx, extra_data[extra_idx].iov_len, extra_data[extra_idx].iov_base);
133 }
134 }
135 }
136
137 int
cfil_crypto_sign_data(cfil_crypto_state_t state,cfil_crypto_data_t data,const struct iovec * __counted_by (extra_data_count)extra_data,size_t extra_data_count,cfil_crypto_signature signature,u_int32_t * signature_length)138 cfil_crypto_sign_data(cfil_crypto_state_t state, cfil_crypto_data_t data,
139 const struct iovec *__counted_by(extra_data_count)extra_data, size_t extra_data_count,
140 cfil_crypto_signature signature, u_int32_t *signature_length)
141 {
142 u_int8_t *ptr = NULL;
143
144 if (state->digest_info == NULL) {
145 return EINVAL;
146 }
147
148 if (data == NULL ||
149 signature == NULL ||
150 signature_length == NULL) {
151 return EINVAL;
152 }
153
154 size_t required_tag_length = state->digest_info->output_size;
155 if (*signature_length < required_tag_length) {
156 return ERANGE;
157 }
158
159 *signature_length = (u_int32_t)required_tag_length;
160
161 cchmac_ctx_decl(state->digest_info->state_size,
162 state->digest_info->block_size, ctx);
163 cchmac_init(state->digest_info, ctx,
164 sizeof(state->key),
165 state->key);
166 cfil_crypto_update_context(state->digest_info, ctx, data, extra_data, extra_data_count);
167 cchmac_final(state->digest_info, ctx, signature);
168
169 if (cfil_log_level >= LOG_DEBUG) {
170 cfil_crypto_print_data(data, "SIGN");
171 CFIL_CRYPTO_LOG(LOG_DEBUG, "Signed data: datalen %lu", sizeof(struct cfil_crypto_data));
172 ptr = (u_int8_t *)signature;
173 CFIL_CRYPTO_LOG_32BYTES("Signature", "SIGN");
174 }
175
176 return 0;
177 }
178