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