xref: /xnu-12377.81.4/tests/codesigntests.c (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796)
1*043036a2SApple OSS Distributions #include <darwintest.h>
2*043036a2SApple OSS Distributions #include <stdint.h>
3*043036a2SApple OSS Distributions #include <bsm/libbsm.h>
4*043036a2SApple OSS Distributions #include <System/sys/codesign.h>
5*043036a2SApple OSS Distributions #include <kern/cs_blobs.h>
6*043036a2SApple OSS Distributions #include <sys/errno.h>
7*043036a2SApple OSS Distributions #include <stdio.h>
8*043036a2SApple OSS Distributions #include <unistd.h>
9*043036a2SApple OSS Distributions #include <TargetConditionals.h>
10*043036a2SApple OSS Distributions 
11*043036a2SApple OSS Distributions #define MAXBUFLEN 1024 * 1024
12*043036a2SApple OSS Distributions 
13*043036a2SApple OSS Distributions T_GLOBAL_META(
14*043036a2SApple OSS Distributions 	T_META_NAMESPACE("xnu.codesigning"),
15*043036a2SApple OSS Distributions 	T_META_RADAR_COMPONENT_NAME("xnu"),
16*043036a2SApple OSS Distributions 	T_META_RADAR_COMPONENT_VERSION("codesigning"),
17*043036a2SApple OSS Distributions 	T_META_OWNER("rkendallkuppe"));
18*043036a2SApple OSS Distributions 
19*043036a2SApple OSS Distributions int
get_blob(pid_t pid,int op)20*043036a2SApple OSS Distributions get_blob(pid_t pid, int op)
21*043036a2SApple OSS Distributions {
22*043036a2SApple OSS Distributions 	uint8_t header[8];
23*043036a2SApple OSS Distributions 	unsigned int cnt;
24*043036a2SApple OSS Distributions 	int rcent;
25*043036a2SApple OSS Distributions 
26*043036a2SApple OSS Distributions 	for (cnt = 0; cnt < sizeof(header); cnt++) {
27*043036a2SApple OSS Distributions 		rcent = csops(pid, op, header, cnt);
28*043036a2SApple OSS Distributions 		if (rcent != -1 && errno != ERANGE) {
29*043036a2SApple OSS Distributions 			T_ASSERT_FAIL("errno != ERANGE for short header");
30*043036a2SApple OSS Distributions 		}
31*043036a2SApple OSS Distributions 	}
32*043036a2SApple OSS Distributions 
33*043036a2SApple OSS Distributions 	rcent = csops(pid, op, header, sizeof(header));
34*043036a2SApple OSS Distributions 	if (rcent == -1 && errno == ERANGE) {
35*043036a2SApple OSS Distributions 		uint32_t len, bufferlen, bufferlen2;
36*043036a2SApple OSS Distributions 
37*043036a2SApple OSS Distributions 		memcpy(&len, &header[4], 4);
38*043036a2SApple OSS Distributions 		bufferlen = ntohl(len);
39*043036a2SApple OSS Distributions 
40*043036a2SApple OSS Distributions 		T_LOG("Checking bufferlen on blob from kernel for csop %d", op);
41*043036a2SApple OSS Distributions 		T_ASSERT_LE_INT(bufferlen, MAXBUFLEN, "Buffer length %zu on blob from kernel can't exceed %zu",
42*043036a2SApple OSS Distributions 		    (size_t)bufferlen, MAXBUFLEN);
43*043036a2SApple OSS Distributions 		T_ASSERT_NE_INT(bufferlen, 0, "Buffer length %zu on blob from kernel can't be zero",
44*043036a2SApple OSS Distributions 		    (size_t)bufferlen);
45*043036a2SApple OSS Distributions 		T_ASSERT_GE_INT(bufferlen, 8, "Buffer length %zu on blob from kernel can't be less than a byte",
46*043036a2SApple OSS Distributions 		    (size_t)bufferlen);
47*043036a2SApple OSS Distributions 
48*043036a2SApple OSS Distributions 		uint8_t buffer[bufferlen + 1];
49*043036a2SApple OSS Distributions 
50*043036a2SApple OSS Distributions 		rcent = csops(pid, op, buffer, bufferlen - 1);
51*043036a2SApple OSS Distributions 		T_ASSERT_POSIX_ERROR(errno, ERANGE, "Performing CS OPS csops with a full buffer - 1");
52*043036a2SApple OSS Distributions 
53*043036a2SApple OSS Distributions 		rcent = csops(pid, op, buffer, bufferlen);
54*043036a2SApple OSS Distributions 		T_ASSERT_EQ_INT(rcent, 0, "Performing CS OPS with full buffer.");
55*043036a2SApple OSS Distributions 
56*043036a2SApple OSS Distributions 		memcpy(&len, &buffer[4], 4);
57*043036a2SApple OSS Distributions 		bufferlen2 = ntohl(len);
58*043036a2SApple OSS Distributions 
59*043036a2SApple OSS Distributions 		if (op == CS_OPS_BLOB) {
60*043036a2SApple OSS Distributions 			T_ASSERT_LE_INT(bufferlen2, bufferlen, "Checking %zu is %zu larger on second try",
61*043036a2SApple OSS Distributions 			    (size_t)bufferlen2, (size_t)bufferlen);
62*043036a2SApple OSS Distributions 
63*043036a2SApple OSS Distributions 			/*
64*043036a2SApple OSS Distributions 			 * CS_OPS_BLOB may want a bigger buffer than the size
65*043036a2SApple OSS Distributions 			 * of the actual blob. If the blob came in through a
66*043036a2SApple OSS Distributions 			 * load command for example, then CS_OPS_BLOB will
67*043036a2SApple OSS Distributions 			 * want to copy out the whole buffer that the load
68*043036a2SApple OSS Distributions 			 * command points to, which is usually an estimated
69*043036a2SApple OSS Distributions 			 * size. The actual blob, and therefore the size in
70*043036a2SApple OSS Distributions 			 * the blob's header, may be smaller.
71*043036a2SApple OSS Distributions 			 */
72*043036a2SApple OSS Distributions 			T_LOG("Blob is smaller (%zu) than expected (%zu). This is fine.",
73*043036a2SApple OSS Distributions 			    (size_t)bufferlen2, (size_t)bufferlen);
74*043036a2SApple OSS Distributions 		} else {
75*043036a2SApple OSS Distributions 			T_ASSERT_EQ_INT(bufferlen2, bufferlen, "Checking bufferlen sizes are different");
76*043036a2SApple OSS Distributions 		}
77*043036a2SApple OSS Distributions 
78*043036a2SApple OSS Distributions 		rcent = csops(pid, op, buffer, bufferlen + 1);
79*043036a2SApple OSS Distributions 		T_ASSERT_EQ_INT(rcent, 0, "Performing CS OPS with a full buffer + 1");
80*043036a2SApple OSS Distributions 
81*043036a2SApple OSS Distributions 		return 0;
82*043036a2SApple OSS Distributions 	} else if (rcent == 0) {
83*043036a2SApple OSS Distributions 		return 0;
84*043036a2SApple OSS Distributions 	} else {
85*043036a2SApple OSS Distributions 		return 1;
86*043036a2SApple OSS Distributions 	}
87*043036a2SApple OSS Distributions }
88*043036a2SApple OSS Distributions 
89*043036a2SApple OSS Distributions /*
90*043036a2SApple OSS Distributions  *  This source is compiled with different names and build flags.
91*043036a2SApple OSS Distributions  *  Makefile has the detail of the TESTNAME.
92*043036a2SApple OSS Distributions  */
93*043036a2SApple OSS Distributions 
94*043036a2SApple OSS Distributions T_DECL(TESTNAME, "CS OP, code sign operations test")
95*043036a2SApple OSS Distributions {
96*043036a2SApple OSS Distributions 	uint32_t status;
97*043036a2SApple OSS Distributions 	int rcent;
98*043036a2SApple OSS Distributions 	pid_t pid;
99*043036a2SApple OSS Distributions 	csops_cdhash_t cdhash_info = {0};
100*043036a2SApple OSS Distributions 	uint8_t cdhash[CS_CDHASH_LEN] = {0};
101*043036a2SApple OSS Distributions 
102*043036a2SApple OSS Distributions 	pid = getpid();
103*043036a2SApple OSS Distributions 
104*043036a2SApple OSS Distributions 	rcent = get_blob(pid, CS_OPS_ENTITLEMENTS_BLOB);
105*043036a2SApple OSS Distributions 	T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPS entitlements blob");
106*043036a2SApple OSS Distributions 
107*043036a2SApple OSS Distributions 	rcent = get_blob(0, CS_OPS_ENTITLEMENTS_BLOB);
108*043036a2SApple OSS Distributions 	T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPS entitlements blob");
109*043036a2SApple OSS Distributions 
110*043036a2SApple OSS Distributions 	rcent = get_blob(pid, CS_OPS_BLOB);
111*043036a2SApple OSS Distributions 
112*043036a2SApple OSS Distributions 	T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPS blob");
113*043036a2SApple OSS Distributions 
114*043036a2SApple OSS Distributions 	rcent = get_blob(0, CS_OPS_BLOB);
115*043036a2SApple OSS Distributions 	T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPS blob");
116*043036a2SApple OSS Distributions 
117*043036a2SApple OSS Distributions 	rcent = get_blob(pid, CS_OPS_IDENTITY);
118*043036a2SApple OSS Distributions 	T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPs identity");
119*043036a2SApple OSS Distributions 
120*043036a2SApple OSS Distributions 	rcent = get_blob(0, CS_OPS_IDENTITY);
121*043036a2SApple OSS Distributions 	T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPs identity");
122*043036a2SApple OSS Distributions 
123*043036a2SApple OSS Distributions 	rcent = csops(pid, CS_OPS_SET_STATUS, &status, sizeof(status) - 1);
124*043036a2SApple OSS Distributions 	T_ASSERT_NE_INT(rcent, 0, "Checking CS OPs set status by setting buffer to (status - 1)");
125*043036a2SApple OSS Distributions 
126*043036a2SApple OSS Distributions 	status = CS_RESTRICT;
127*043036a2SApple OSS Distributions 	rcent = csops(pid, CS_OPS_SET_STATUS, &status, sizeof(status));
128*043036a2SApple OSS Distributions 	T_ASSERT_EQ_INT(rcent, 0, "Checking CS OPs set status by setting proc RESTRICTED");
129*043036a2SApple OSS Distributions 
130*043036a2SApple OSS Distributions 	rcent = csops(pid, CS_OPS_STATUS, &status, sizeof(status));
131*043036a2SApple OSS Distributions 	T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPs status of process");
132*043036a2SApple OSS Distributions 
133*043036a2SApple OSS Distributions 	rcent = csops(pid, CS_OPS_CDHASH, cdhash, sizeof(cdhash));
134*043036a2SApple OSS Distributions 	T_ASSERT_EQ_INT(rcent, 0, "Getting CS_OPS_CDHASH");
135*043036a2SApple OSS Distributions 
136*043036a2SApple OSS Distributions 	rcent = csops(pid, CS_OPS_CDHASH_WITH_INFO, &cdhash_info, sizeof(cdhash_info));
137*043036a2SApple OSS Distributions 	T_ASSERT_EQ_INT(rcent, 0, "Getting CS_OPS_CDHASH_WITH_INFO");
138*043036a2SApple OSS Distributions 
139*043036a2SApple OSS Distributions 	/* Verify the returned CDHashes match and are the correct type */
140*043036a2SApple OSS Distributions 	T_ASSERT_EQ_INT(memcmp(cdhash_info.hash, cdhash, sizeof(cdhash)), 0, "Comparing CDHashes");
141*043036a2SApple OSS Distributions 	T_ASSERT_EQ_INT(cdhash_info.type, CS_HASHTYPE_SHA256, "Checking returned CDHash type [SHA256]");
142*043036a2SApple OSS Distributions 
143*043036a2SApple OSS Distributions 	/*
144*043036a2SApple OSS Distributions 	 * Only run the following tests if not HARD since otherwise
145*043036a2SApple OSS Distributions 	 * we'll just die when marking ourself invalid.
146*043036a2SApple OSS Distributions 	 */
147*043036a2SApple OSS Distributions 
148*043036a2SApple OSS Distributions 	if ((status & CS_KILL) == 0) {
149*043036a2SApple OSS Distributions 		rcent = csops(pid, CS_OPS_MARKINVALID, NULL, 0);
150*043036a2SApple OSS Distributions 		T_ASSERT_POSIX_ZERO(rcent, 0, "Setting CS OPs mark proc invalid");
151*043036a2SApple OSS Distributions 
152*043036a2SApple OSS Distributions 		status = CS_ENFORCEMENT;
153*043036a2SApple OSS Distributions 		rcent = csops(pid, CS_OPS_SET_STATUS, &status, sizeof(status));
154*043036a2SApple OSS Distributions 		T_ASSERT_POSIX_ERROR(rcent, -1, "Managed to set flags on an INVALID proc");
155*043036a2SApple OSS Distributions 
156*043036a2SApple OSS Distributions 		rcent = get_blob(pid, CS_OPS_ENTITLEMENTS_BLOB);
157*043036a2SApple OSS Distributions 		T_ASSERT_POSIX_ERROR(rcent, 1, "Got entitlements while invalid");
158*043036a2SApple OSS Distributions 
159*043036a2SApple OSS Distributions 		rcent = get_blob(pid, CS_OPS_IDENTITY);
160*043036a2SApple OSS Distributions 		T_ASSERT_POSIX_ERROR(rcent, 1, "Getting CS OPS identity");
161*043036a2SApple OSS Distributions 
162*043036a2SApple OSS Distributions 		rcent = get_blob(0, CS_OPS_IDENTITY);
163*043036a2SApple OSS Distributions 		T_ASSERT_POSIX_ERROR(rcent, 1, "Getting CS OPS identity");
164*043036a2SApple OSS Distributions 
165*043036a2SApple OSS Distributions 		rcent = get_blob(0, CS_OPS_BLOB);
166*043036a2SApple OSS Distributions 		T_ASSERT_POSIX_ERROR(rcent, 1, "Geting CS OPS blob");
167*043036a2SApple OSS Distributions 	}
168*043036a2SApple OSS Distributions }
169