1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * sdsi: Intel On Demand (formerly Software Defined Silicon) tool for
4  * provisioning certificates and activation payloads on supported cpus.
5  *
6  * See https://github.com/intel/intel-sdsi/blob/master/os-interface.rst
7  * for register descriptions.
8  *
9  * Copyright (C) 2022 Intel Corporation. All rights reserved.
10  */
11 
12 #include <dirent.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <getopt.h>
16 #include <stdbool.h>
17 #include <stdio.h>
18 #include <stdint.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 
23 #include <sys/types.h>
24 
25 #ifndef __packed
26 #define __packed __attribute__((packed))
27 #endif
28 
29 #define min(x, y) ({                            \
30 	typeof(x) _min1 = (x);                  \
31 	typeof(y) _min2 = (y);                  \
32 	(void) (&_min1 == &_min2);              \
33 	_min1 < _min2 ? _min1 : _min2; })
34 
35 #define SDSI_DEV		"intel_vsec.sdsi"
36 #define AUX_DEV_PATH		"/sys/bus/auxiliary/devices/"
37 #define SDSI_PATH		(AUX_DEV_DIR SDSI_DEV)
38 #define GUID_V1			0x6dd191
39 #define REGS_SIZE_GUID_V1	72
40 #define GUID_V2			0xF210D9EF
41 #define REGS_SIZE_GUID_V2	80
42 #define STATE_CERT_MAX_SIZE	4096
43 #define METER_CERT_MAX_SIZE	4096
44 #define STATE_MAX_NUM_LICENSES	16
45 #define STATE_MAX_NUM_IN_BUNDLE	(uint32_t)8
46 
47 #define __round_mask(x, y) ((__typeof__(x))((y) - 1))
48 #define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1)
49 
50 struct nvram_content_auth_err_sts {
51 	uint64_t reserved:3;
52 	uint64_t sdsi_content_auth_err:1;
53 	uint64_t reserved1:1;
54 	uint64_t sdsi_metering_auth_err:1;
55 	uint64_t reserved2:58;
56 };
57 
58 struct enabled_features {
59 	uint64_t reserved:3;
60 	uint64_t sdsi:1;
61 	uint64_t reserved1:8;
62 	uint64_t attestation:1;
63 	uint64_t reserved2:13;
64 	uint64_t metering:1;
65 	uint64_t reserved3:37;
66 };
67 
68 struct key_provision_status {
69 	uint64_t reserved:1;
70 	uint64_t license_key_provisioned:1;
71 	uint64_t reserved2:62;
72 };
73 
74 struct auth_fail_count {
75 	uint64_t key_failure_count:3;
76 	uint64_t key_failure_threshold:3;
77 	uint64_t auth_failure_count:3;
78 	uint64_t auth_failure_threshold:3;
79 	uint64_t reserved:52;
80 };
81 
82 struct availability {
83 	uint64_t reserved:48;
84 	uint64_t available:3;
85 	uint64_t threshold:3;
86 	uint64_t reserved2:10;
87 };
88 
89 struct nvram_update_limit {
90 	uint64_t reserved:12;
91 	uint64_t sdsi_50_pct:1;
92 	uint64_t sdsi_75_pct:1;
93 	uint64_t sdsi_90_pct:1;
94 	uint64_t reserved2:49;
95 };
96 
97 struct sdsi_regs {
98 	uint64_t ppin;
99 	struct nvram_content_auth_err_sts auth_err_sts;
100 	struct enabled_features en_features;
101 	struct key_provision_status key_prov_sts;
102 	struct auth_fail_count auth_fail_count;
103 	struct availability prov_avail;
104 	struct nvram_update_limit limits;
105 	uint64_t pcu_cr3_capid_cfg;
106 	union {
107 		struct {
108 			uint64_t socket_id;
109 		} v1;
110 		struct {
111 			uint64_t reserved;
112 			uint64_t socket_id;
113 			uint64_t reserved2;
114 		} v2;
115 	} extra;
116 };
117 #define CONTENT_TYPE_LK_ENC		0xD
118 #define CONTENT_TYPE_LK_BLOB_ENC	0xE
119 
120 struct state_certificate {
121 	uint32_t content_type;
122 	uint32_t region_rev_id;
123 	uint32_t header_size;
124 	uint32_t total_size;
125 	uint32_t key_size;
126 	uint32_t num_licenses;
127 };
128 
129 struct license_key_info {
130 	uint32_t key_rev_id;
131 	uint64_t key_image_content[6];
132 } __packed;
133 
134 #define LICENSE_BLOB_SIZE(l)	(((l) & 0x7fffffff) * 4)
135 #define LICENSE_VALID(l)	(!!((l) & 0x80000000))
136 
137 // License Group Types
138 #define LBT_ONE_TIME_UPGRADE	1
139 #define LBT_METERED_UPGRADE	2
140 
141 struct license_blob_content {
142 	uint32_t type;
143 	uint64_t id;
144 	uint64_t ppin;
145 	uint64_t previous_ppin;
146 	uint32_t rev_id;
147 	uint32_t num_bundles;
148 } __packed;
149 
150 struct bundle_encoding {
151 	uint32_t encoding;
152 	uint32_t encoding_rsvd[7];
153 };
154 
155 struct meter_certificate {
156 	uint32_t signature;
157 	uint32_t version;
158 	uint64_t ppin;
159 	uint32_t counter_unit;
160 	uint32_t bundle_length;
161 	uint64_t reserved;
162 	uint32_t mmrc_encoding;
163 	uint32_t mmrc_counter;
164 };
165 
166 struct bundle_encoding_counter {
167 	uint32_t encoding;
168 	uint32_t counter;
169 };
170 #define METER_BUNDLE_SIZE sizeof(struct bundle_encoding_counter)
171 #define BUNDLE_COUNT(length) ((length) / METER_BUNDLE_SIZE)
172 #define METER_MAX_NUM_BUNDLES							\
173 		((METER_CERT_MAX_SIZE - sizeof(struct meter_certificate)) /	\
174 		 sizeof(struct bundle_encoding_counter))
175 
176 struct sdsi_dev {
177 	struct sdsi_regs regs;
178 	struct state_certificate sc;
179 	char *dev_name;
180 	char *dev_path;
181 	uint32_t guid;
182 };
183 
184 enum command {
185 	CMD_SOCKET_INFO,
186 	CMD_METER_CERT,
187 	CMD_STATE_CERT,
188 	CMD_PROV_AKC,
189 	CMD_PROV_CAP,
190 };
191 
sdsi_list_devices(void)192 static void sdsi_list_devices(void)
193 {
194 	struct dirent *entry;
195 	DIR *aux_dir;
196 	bool found = false;
197 
198 	aux_dir = opendir(AUX_DEV_PATH);
199 	if (!aux_dir) {
200 		fprintf(stderr, "Cannot open directory %s\n", AUX_DEV_PATH);
201 		return;
202 	}
203 
204 	while ((entry = readdir(aux_dir))) {
205 		if (!strncmp(SDSI_DEV, entry->d_name, strlen(SDSI_DEV))) {
206 			found = true;
207 			printf("%s\n", entry->d_name);
208 		}
209 	}
210 
211 	if (!found)
212 		fprintf(stderr, "No On Demand devices found.\n");
213 }
214 
sdsi_update_registers(struct sdsi_dev * s)215 static int sdsi_update_registers(struct sdsi_dev *s)
216 {
217 	FILE *regs_ptr;
218 	int ret;
219 
220 	memset(&s->regs, 0, sizeof(s->regs));
221 
222 	/* Open the registers file */
223 	ret = chdir(s->dev_path);
224 	if (ret == -1) {
225 		perror("chdir");
226 		return ret;
227 	}
228 
229 	regs_ptr = fopen("registers", "r");
230 	if (!regs_ptr) {
231 		perror("Could not open 'registers' file");
232 		return -1;
233 	}
234 
235 	if (s->guid != GUID_V1 && s->guid != GUID_V2) {
236 		fprintf(stderr, "Unrecognized guid, 0x%x\n", s->guid);
237 		fclose(regs_ptr);
238 		return -1;
239 	}
240 
241 	/* Update register info for this guid */
242 	ret = fread(&s->regs, sizeof(uint8_t), sizeof(s->regs), regs_ptr);
243 	if ((s->guid == GUID_V1 && ret != REGS_SIZE_GUID_V1) ||
244 	    (s->guid == GUID_V2 && ret != REGS_SIZE_GUID_V2)) {
245 		fprintf(stderr, "Could not read 'registers' file\n");
246 		fclose(regs_ptr);
247 		return -1;
248 	}
249 
250 	fclose(regs_ptr);
251 
252 	return 0;
253 }
254 
sdsi_read_reg(struct sdsi_dev * s)255 static int sdsi_read_reg(struct sdsi_dev *s)
256 {
257 	int ret;
258 
259 	ret = sdsi_update_registers(s);
260 	if (ret)
261 		return ret;
262 
263 	/* Print register info for this guid */
264 	printf("\n");
265 	printf("Socket information for device %s\n", s->dev_name);
266 	printf("\n");
267 	printf("PPIN:                           0x%lx\n", s->regs.ppin);
268 	printf("NVRAM Content Authorization Error Status\n");
269 	printf("    SDSi Auth Err Sts:          %s\n", !!s->regs.auth_err_sts.sdsi_content_auth_err ? "Error" : "Okay");
270 
271 	if (!!s->regs.en_features.metering)
272 		printf("    Metering Auth Err Sts:      %s\n", !!s->regs.auth_err_sts.sdsi_metering_auth_err ? "Error" : "Okay");
273 
274 	printf("Enabled Features\n");
275 	printf("    On Demand:                  %s\n", !!s->regs.en_features.sdsi ? "Enabled" : "Disabled");
276 	printf("    Attestation:                %s\n", !!s->regs.en_features.attestation ? "Enabled" : "Disabled");
277 	printf("    On Demand:                  %s\n", !!s->regs.en_features.sdsi ? "Enabled" : "Disabled");
278 	printf("    Metering:                   %s\n", !!s->regs.en_features.metering ? "Enabled" : "Disabled");
279 	printf("License Key (AKC) Provisioned:  %s\n", !!s->regs.key_prov_sts.license_key_provisioned ? "Yes" : "No");
280 	printf("Authorization Failure Count\n");
281 	printf("    AKC Failure Count:          %d\n", s->regs.auth_fail_count.key_failure_count);
282 	printf("    AKC Failure Threshold:      %d\n", s->regs.auth_fail_count.key_failure_threshold);
283 	printf("    CAP Failure Count:          %d\n", s->regs.auth_fail_count.auth_failure_count);
284 	printf("    CAP Failure Threshold:      %d\n", s->regs.auth_fail_count.auth_failure_threshold);
285 	printf("Provisioning Availability\n");
286 	printf("    Updates Available:          %d\n", s->regs.prov_avail.available);
287 	printf("    Updates Threshold:          %d\n", s->regs.prov_avail.threshold);
288 	printf("NVRAM Udate Limit\n");
289 	printf("    50%% Limit Reached:          %s\n", !!s->regs.limits.sdsi_50_pct ? "Yes" : "No");
290 	printf("    75%% Limit Reached:          %s\n", !!s->regs.limits.sdsi_75_pct ? "Yes" : "No");
291 	printf("    90%% Limit Reached:          %s\n", !!s->regs.limits.sdsi_90_pct ? "Yes" : "No");
292 	if (s->guid == GUID_V1)
293 		printf("Socket ID:                      %ld\n", s->regs.extra.v1.socket_id & 0xF);
294 	else
295 		printf("Socket ID:                      %ld\n", s->regs.extra.v2.socket_id & 0xF);
296 
297 	return 0;
298 }
299 
license_blob_type(uint32_t type)300 static char *license_blob_type(uint32_t type)
301 {
302 	switch (type) {
303 	case LBT_ONE_TIME_UPGRADE:
304 		return "One time upgrade";
305 	case LBT_METERED_UPGRADE:
306 		return "Metered upgrade";
307 	default:
308 		return "Unknown license blob type";
309 	}
310 }
311 
content_type(uint32_t type)312 static char *content_type(uint32_t type)
313 {
314 	switch (type) {
315 	case  CONTENT_TYPE_LK_ENC:
316 		return "Licencse key encoding";
317 	case CONTENT_TYPE_LK_BLOB_ENC:
318 		return "License key + Blob encoding";
319 	default:
320 		return "Unknown content type";
321 	}
322 }
323 
get_feature(uint32_t encoding,char * feature)324 static void get_feature(uint32_t encoding, char *feature)
325 {
326 	char *name = (char *)&encoding;
327 
328 	feature[3] = name[0];
329 	feature[2] = name[1];
330 	feature[1] = name[2];
331 	feature[0] = name[3];
332 }
333 
sdsi_meter_cert_show(struct sdsi_dev * s)334 static int sdsi_meter_cert_show(struct sdsi_dev *s)
335 {
336 	char buf[METER_CERT_MAX_SIZE] = {0};
337 	struct bundle_encoding_counter *bec;
338 	struct meter_certificate *mc;
339 	uint32_t count = 0;
340 	FILE *cert_ptr;
341 	int ret, size;
342 	char name[4];
343 
344 	ret = sdsi_update_registers(s);
345 	if (ret)
346 		return ret;
347 
348 	if (!s->regs.en_features.sdsi) {
349 		fprintf(stderr, "SDSi feature is present but not enabled.\n");
350 		fprintf(stderr, " Unable to read meter certificate\n");
351 		return -1;
352 	}
353 
354 	if (!s->regs.en_features.metering) {
355 		fprintf(stderr, "Metering not supporting on this socket.\n");
356 		return -1;
357 	}
358 
359 	ret = chdir(s->dev_path);
360 	if (ret == -1) {
361 		perror("chdir");
362 		return ret;
363 	}
364 
365 	cert_ptr = fopen("meter_certificate", "r");
366 	if (!cert_ptr) {
367 		perror("Could not open 'meter_certificate' file");
368 		return -1;
369 	}
370 
371 	size = fread(buf, 1, sizeof(buf), cert_ptr);
372 	if (!size) {
373 		fprintf(stderr, "Could not read 'meter_certificate' file\n");
374 		fclose(cert_ptr);
375 		return -1;
376 	}
377 	fclose(cert_ptr);
378 
379 	mc = (struct meter_certificate *)buf;
380 
381 	printf("\n");
382 	printf("Meter certificate for device %s\n", s->dev_name);
383 	printf("\n");
384 
385 	get_feature(mc->signature, name);
386 	printf("Signature:                    %.4s\n", name);
387 
388 	printf("Version:                      %d\n", mc->version);
389 	printf("Count Unit:                   %dms\n", mc->counter_unit);
390 	printf("PPIN:                         0x%lx\n", mc->ppin);
391 	printf("Feature Bundle Length:        %d\n", mc->bundle_length);
392 
393 	get_feature(mc->mmrc_encoding, name);
394 	printf("MMRC encoding:                %.4s\n", name);
395 
396 	printf("MMRC counter:                 %d\n", mc->mmrc_counter);
397 	if (mc->bundle_length % METER_BUNDLE_SIZE) {
398 		fprintf(stderr, "Invalid bundle length\n");
399 		return -1;
400 	}
401 
402 	if (mc->bundle_length > METER_MAX_NUM_BUNDLES * METER_BUNDLE_SIZE)  {
403 		fprintf(stderr, "More than %ld bundles: actual %ld\n",
404 			METER_MAX_NUM_BUNDLES, BUNDLE_COUNT(mc->bundle_length));
405 		return -1;
406 	}
407 
408 	bec = (struct bundle_encoding_counter *)(mc + 1);
409 
410 	printf("Number of Feature Counters:   %ld\n", BUNDLE_COUNT(mc->bundle_length));
411 	while (count < BUNDLE_COUNT(mc->bundle_length)) {
412 		char feature[5];
413 
414 		feature[4] = '\0';
415 		get_feature(bec[count].encoding, feature);
416 		printf("    %s:          %d\n", feature, bec[count].counter);
417 		++count;
418 	}
419 
420 	return 0;
421 }
422 
sdsi_state_cert_show(struct sdsi_dev * s)423 static int sdsi_state_cert_show(struct sdsi_dev *s)
424 {
425 	char buf[STATE_CERT_MAX_SIZE] = {0};
426 	struct state_certificate *sc;
427 	struct license_key_info *lki;
428 	uint32_t offset = 0;
429 	uint32_t count = 0;
430 	FILE *cert_ptr;
431 	int ret, size;
432 
433 	ret = sdsi_update_registers(s);
434 	if (ret)
435 		return ret;
436 
437 	if (!s->regs.en_features.sdsi) {
438 		fprintf(stderr, "On Demand feature is present but not enabled.");
439 		fprintf(stderr, " Unable to read state certificate");
440 		return -1;
441 	}
442 
443 	ret = chdir(s->dev_path);
444 	if (ret == -1) {
445 		perror("chdir");
446 		return ret;
447 	}
448 
449 	cert_ptr = fopen("state_certificate", "r");
450 	if (!cert_ptr) {
451 		perror("Could not open 'state_certificate' file");
452 		return -1;
453 	}
454 
455 	size = fread(buf, 1, sizeof(buf), cert_ptr);
456 	if (!size) {
457 		fprintf(stderr, "Could not read 'state_certificate' file\n");
458 		fclose(cert_ptr);
459 		return -1;
460 	}
461 	fclose(cert_ptr);
462 
463 	sc = (struct state_certificate *)buf;
464 
465 	/* Print register info for this guid */
466 	printf("\n");
467 	printf("State certificate for device %s\n", s->dev_name);
468 	printf("\n");
469 	printf("Content Type:          %s\n", content_type(sc->content_type));
470 	printf("Region Revision ID:    %d\n", sc->region_rev_id);
471 	printf("Header Size:           %d\n", sc->header_size * 4);
472 	printf("Total Size:            %d\n", sc->total_size);
473 	printf("OEM Key Size:          %d\n", sc->key_size * 4);
474 	printf("Number of Licenses:    %d\n", sc->num_licenses);
475 
476 	/* Skip over the license sizes 4 bytes per license) to get the license key info */
477 	lki = (void *)sc + sizeof(*sc) + (4 * sc->num_licenses);
478 
479 	printf("License blob Info:\n");
480 	printf("    License Key Revision ID:    0x%x\n", lki->key_rev_id);
481 	printf("    License Key Image Content:  0x%lx%lx%lx%lx%lx%lx\n",
482 	       lki->key_image_content[5], lki->key_image_content[4],
483 	       lki->key_image_content[3], lki->key_image_content[2],
484 	       lki->key_image_content[1], lki->key_image_content[0]);
485 
486 	while (count++ < sc->num_licenses) {
487 		uint32_t blob_size_field = *(uint32_t *)(buf + 0x14 + count * 4);
488 		uint32_t blob_size = LICENSE_BLOB_SIZE(blob_size_field);
489 		bool license_valid = LICENSE_VALID(blob_size_field);
490 		struct license_blob_content *lbc =
491 			(void *)(sc) +			// start of the state certificate
492 			sizeof(*sc) +			// size of the state certificate
493 			(4 * sc->num_licenses) +	// total size of the blob size blocks
494 			sizeof(*lki) +			// size of the license key info
495 			offset;				// offset to this blob content
496 		struct bundle_encoding *bundle = (void *)(lbc) + sizeof(*lbc);
497 		char feature[5];
498 		uint32_t i;
499 
500 		printf("     Blob %d:\n", count - 1);
501 		printf("        License blob size:          %u\n", blob_size);
502 		printf("        License is valid:           %s\n", license_valid ? "Yes" : "No");
503 		printf("        License blob type:          %s\n", license_blob_type(lbc->type));
504 		printf("        License blob ID:            0x%lx\n", lbc->id);
505 		printf("        PPIN:                       0x%lx\n", lbc->ppin);
506 		printf("        Previous PPIN:              0x%lx\n", lbc->previous_ppin);
507 		printf("        Blob revision ID:           %u\n", lbc->rev_id);
508 		printf("        Number of Features:         %u\n", lbc->num_bundles);
509 
510 		feature[4] = '\0';
511 
512 		for (i = 0; i < min(lbc->num_bundles, STATE_MAX_NUM_IN_BUNDLE); i++) {
513 			get_feature(bundle[i].encoding, feature);
514 			printf("                 Feature %d:         %s\n", i, feature);
515 		}
516 
517 		if (lbc->num_bundles > STATE_MAX_NUM_IN_BUNDLE)
518 			fprintf(stderr, "        Warning: %d > %d licenses in bundle reported.\n",
519 				lbc->num_bundles, STATE_MAX_NUM_IN_BUNDLE);
520 
521 		offset += blob_size;
522 	};
523 
524 	return 0;
525 }
526 
sdsi_provision(struct sdsi_dev * s,char * bin_file,enum command command)527 static int sdsi_provision(struct sdsi_dev *s, char *bin_file, enum command command)
528 {
529 	int bin_fd, prov_fd, size, ret;
530 	char buf[STATE_CERT_MAX_SIZE] = { 0 };
531 	char cap[] = "provision_cap";
532 	char akc[] = "provision_akc";
533 	char *prov_file;
534 
535 	if (!bin_file) {
536 		fprintf(stderr, "No binary file provided\n");
537 		return -1;
538 	}
539 
540 	/* Open the binary */
541 	bin_fd = open(bin_file, O_RDONLY);
542 	if (bin_fd == -1) {
543 		fprintf(stderr, "Could not open file %s: %s\n", bin_file, strerror(errno));
544 		return bin_fd;
545 	}
546 
547 	prov_file = (command == CMD_PROV_AKC) ? akc : cap;
548 
549 	ret = chdir(s->dev_path);
550 	if (ret == -1) {
551 		perror("chdir");
552 		close(bin_fd);
553 		return ret;
554 	}
555 
556 	/* Open the provision file */
557 	prov_fd = open(prov_file, O_WRONLY);
558 	if (prov_fd == -1) {
559 		fprintf(stderr, "Could not open file %s: %s\n", prov_file, strerror(errno));
560 		close(bin_fd);
561 		return prov_fd;
562 	}
563 
564 	/* Read the binary file into the buffer */
565 	size = read(bin_fd, buf, STATE_CERT_MAX_SIZE);
566 	if (size == -1) {
567 		close(bin_fd);
568 		close(prov_fd);
569 		return -1;
570 	}
571 
572 	ret = write(prov_fd, buf, size);
573 	if (ret == -1) {
574 		close(bin_fd);
575 		close(prov_fd);
576 		perror("Provisioning failed");
577 		return ret;
578 	}
579 
580 	printf("Provisioned %s file %s successfully\n", prov_file, bin_file);
581 
582 	close(bin_fd);
583 	close(prov_fd);
584 
585 	return 0;
586 }
587 
sdsi_provision_akc(struct sdsi_dev * s,char * bin_file)588 static int sdsi_provision_akc(struct sdsi_dev *s, char *bin_file)
589 {
590 	int ret;
591 
592 	ret = sdsi_update_registers(s);
593 	if (ret)
594 		return ret;
595 
596 	if (!s->regs.en_features.sdsi) {
597 		fprintf(stderr, "On Demand feature is present but not enabled. Unable to provision");
598 		return -1;
599 	}
600 
601 	if (!s->regs.prov_avail.available) {
602 		fprintf(stderr, "Maximum number of updates (%d) has been reached.\n",
603 			s->regs.prov_avail.threshold);
604 		return -1;
605 	}
606 
607 	if (s->regs.auth_fail_count.key_failure_count ==
608 	    s->regs.auth_fail_count.key_failure_threshold) {
609 		fprintf(stderr, "Maximum number of AKC provision failures (%d) has been reached.\n",
610 			s->regs.auth_fail_count.key_failure_threshold);
611 		fprintf(stderr, "Power cycle the system to reset the counter\n");
612 		return -1;
613 	}
614 
615 	return sdsi_provision(s, bin_file, CMD_PROV_AKC);
616 }
617 
sdsi_provision_cap(struct sdsi_dev * s,char * bin_file)618 static int sdsi_provision_cap(struct sdsi_dev *s, char *bin_file)
619 {
620 	int ret;
621 
622 	ret = sdsi_update_registers(s);
623 	if (ret)
624 		return ret;
625 
626 	if (!s->regs.en_features.sdsi) {
627 		fprintf(stderr, "On Demand feature is present but not enabled. Unable to provision");
628 		return -1;
629 	}
630 
631 	if (!s->regs.prov_avail.available) {
632 		fprintf(stderr, "Maximum number of updates (%d) has been reached.\n",
633 			s->regs.prov_avail.threshold);
634 		return -1;
635 	}
636 
637 	if (s->regs.auth_fail_count.auth_failure_count ==
638 	    s->regs.auth_fail_count.auth_failure_threshold) {
639 		fprintf(stderr, "Maximum number of CAP provision failures (%d) has been reached.\n",
640 			s->regs.auth_fail_count.auth_failure_threshold);
641 		fprintf(stderr, "Power cycle the system to reset the counter\n");
642 		return -1;
643 	}
644 
645 	return sdsi_provision(s, bin_file, CMD_PROV_CAP);
646 }
647 
read_sysfs_data(const char * file,int * value)648 static int read_sysfs_data(const char *file, int *value)
649 {
650 	char buff[16];
651 	FILE *fp;
652 
653 	fp = fopen(file, "r");
654 	if (!fp) {
655 		perror(file);
656 		return -1;
657 	}
658 
659 	if (!fgets(buff, 16, fp)) {
660 		fprintf(stderr, "Failed to read file '%s'", file);
661 		fclose(fp);
662 		return -1;
663 	}
664 
665 	fclose(fp);
666 	*value = strtol(buff, NULL, 0);
667 
668 	return 0;
669 }
670 
sdsi_create_dev(char * dev_no)671 static struct sdsi_dev *sdsi_create_dev(char *dev_no)
672 {
673 	int dev_name_len = sizeof(SDSI_DEV) + strlen(dev_no) + 1;
674 	struct sdsi_dev *s;
675 	int guid;
676 	DIR *dir;
677 
678 	s = (struct sdsi_dev *)malloc(sizeof(*s));
679 	if (!s) {
680 		perror("malloc");
681 		return NULL;
682 	}
683 
684 	s->dev_name = (char *)malloc(sizeof(SDSI_DEV) + strlen(dev_no) + 1);
685 	if (!s->dev_name) {
686 		perror("malloc");
687 		free(s);
688 		return NULL;
689 	}
690 
691 	snprintf(s->dev_name, dev_name_len, "%s.%s", SDSI_DEV, dev_no);
692 
693 	s->dev_path = (char *)malloc(sizeof(AUX_DEV_PATH) + dev_name_len);
694 	if (!s->dev_path) {
695 		perror("malloc");
696 		free(s->dev_name);
697 		free(s);
698 		return NULL;
699 	}
700 
701 	snprintf(s->dev_path, sizeof(AUX_DEV_PATH) + dev_name_len, "%s%s", AUX_DEV_PATH,
702 		 s->dev_name);
703 	dir = opendir(s->dev_path);
704 	if (!dir) {
705 		fprintf(stderr, "Could not open directory '%s': %s\n", s->dev_path,
706 			strerror(errno));
707 		free(s->dev_path);
708 		free(s->dev_name);
709 		free(s);
710 		return NULL;
711 	}
712 
713 	if (chdir(s->dev_path) == -1) {
714 		perror("chdir");
715 		free(s->dev_path);
716 		free(s->dev_name);
717 		free(s);
718 		return NULL;
719 	}
720 
721 	if (read_sysfs_data("guid", &guid)) {
722 		free(s->dev_path);
723 		free(s->dev_name);
724 		free(s);
725 		return NULL;
726 	}
727 
728 	s->guid = guid;
729 
730 	return s;
731 }
732 
sdsi_free_dev(struct sdsi_dev * s)733 static void sdsi_free_dev(struct sdsi_dev *s)
734 {
735 	free(s->dev_path);
736 	free(s->dev_name);
737 	free(s);
738 }
739 
usage(char * prog)740 static void usage(char *prog)
741 {
742 	printf("Usage: %s [-l] [-d DEVNO [-i] [-s] [-m] [-a FILE] [-c FILE]]\n", prog);
743 }
744 
show_help(void)745 static void show_help(void)
746 {
747 	printf("Commands:\n");
748 	printf("  %-18s\t%s\n", "-l, --list",           "list available On Demand devices");
749 	printf("  %-18s\t%s\n", "-d, --devno DEVNO",    "On Demand device number");
750 	printf("  %-18s\t%s\n", "-i, --info",           "show socket information");
751 	printf("  %-18s\t%s\n", "-s, --state",          "show state certificate");
752 	printf("  %-18s\t%s\n", "-m, --meter",          "show meter certificate");
753 	printf("  %-18s\t%s\n", "-a, --akc FILE",       "provision socket with AKC FILE");
754 	printf("  %-18s\t%s\n", "-c, --cap FILE>",      "provision socket with CAP FILE");
755 }
756 
main(int argc,char * argv[])757 int main(int argc, char *argv[])
758 {
759 	char bin_file[PATH_MAX], *dev_no = NULL;
760 	bool device_selected = false;
761 	char *progname;
762 	enum command command = -1;
763 	struct sdsi_dev *s;
764 	int ret = 0, opt;
765 	int option_index = 0;
766 
767 	static struct option long_options[] = {
768 		{"akc",		required_argument,	0, 'a'},
769 		{"cap",		required_argument,	0, 'c'},
770 		{"devno",	required_argument,	0, 'd'},
771 		{"help",	no_argument,		0, 'h'},
772 		{"info",	no_argument,		0, 'i'},
773 		{"list",	no_argument,		0, 'l'},
774 		{"meter",	no_argument,		0, 'm'},
775 		{"state",	no_argument,		0, 's'},
776 		{0,		0,			0, 0 }
777 	};
778 
779 
780 	progname = argv[0];
781 
782 	while ((opt = getopt_long_only(argc, argv, "+a:c:d:hilms", long_options,
783 			&option_index)) != -1) {
784 		switch (opt) {
785 		case 'd':
786 			dev_no = optarg;
787 			device_selected = true;
788 			break;
789 		case 'l':
790 			sdsi_list_devices();
791 			return 0;
792 		case 'i':
793 			command = CMD_SOCKET_INFO;
794 			break;
795 		case 'm':
796 			command = CMD_METER_CERT;
797 			break;
798 		case 's':
799 			command = CMD_STATE_CERT;
800 			break;
801 		case 'a':
802 		case 'c':
803 			if (!access(optarg, F_OK) == 0) {
804 				fprintf(stderr, "Could not open file '%s': %s\n", optarg,
805 					strerror(errno));
806 				return -1;
807 			}
808 
809 			if (!realpath(optarg, bin_file)) {
810 				perror("realpath");
811 				return -1;
812 			}
813 
814 			command = (opt == 'a') ? CMD_PROV_AKC : CMD_PROV_CAP;
815 			break;
816 		case 'h':
817 			usage(progname);
818 			show_help();
819 			return 0;
820 		default:
821 			usage(progname);
822 			return -1;
823 		}
824 	}
825 
826 	if (device_selected) {
827 		s = sdsi_create_dev(dev_no);
828 		if (!s)
829 			return -1;
830 
831 		switch (command) {
832 		case CMD_SOCKET_INFO:
833 			ret = sdsi_read_reg(s);
834 			break;
835 		case CMD_METER_CERT:
836 			ret = sdsi_meter_cert_show(s);
837 			break;
838 		case CMD_STATE_CERT:
839 			ret = sdsi_state_cert_show(s);
840 			break;
841 		case CMD_PROV_AKC:
842 			ret = sdsi_provision_akc(s, bin_file);
843 			break;
844 		case CMD_PROV_CAP:
845 			ret = sdsi_provision_cap(s, bin_file);
846 			break;
847 		default:
848 			fprintf(stderr, "No command specified\n");
849 			return -1;
850 		}
851 
852 		sdsi_free_dev(s);
853 
854 	} else {
855 		fprintf(stderr, "No device specified\n");
856 		return -1;
857 	}
858 
859 	return ret;
860 }
861