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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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