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