0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <dirent.h>
0013 #include <errno.h>
0014 #include <fcntl.h>
0015 #include <getopt.h>
0016 #include <stdbool.h>
0017 #include <stdio.h>
0018 #include <stdint.h>
0019 #include <stdlib.h>
0020 #include <string.h>
0021 #include <unistd.h>
0022
0023 #include <sys/types.h>
0024
0025 #define SDSI_DEV "intel_vsec.sdsi"
0026 #define AUX_DEV_PATH "/sys/bus/auxiliary/devices/"
0027 #define SDSI_PATH (AUX_DEV_DIR SDSI_DEV)
0028 #define GUID 0x6dd191
0029 #define REGISTERS_MIN_SIZE 72
0030
0031 #define __round_mask(x, y) ((__typeof__(x))((y) - 1))
0032 #define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1)
0033
0034 struct enabled_features {
0035 uint64_t reserved:3;
0036 uint64_t sdsi:1;
0037 uint64_t reserved1:60;
0038 };
0039
0040 struct auth_fail_count {
0041 uint64_t key_failure_count:3;
0042 uint64_t key_failure_threshold:3;
0043 uint64_t auth_failure_count:3;
0044 uint64_t auth_failure_threshold:3;
0045 uint64_t reserved:52;
0046 };
0047
0048 struct availability {
0049 uint64_t reserved:48;
0050 uint64_t available:3;
0051 uint64_t threshold:3;
0052 };
0053
0054 struct sdsi_regs {
0055 uint64_t ppin;
0056 uint64_t reserved;
0057 struct enabled_features en_features;
0058 uint64_t reserved1;
0059 struct auth_fail_count auth_fail_count;
0060 struct availability prov_avail;
0061 uint64_t reserved2;
0062 uint64_t reserved3;
0063 uint64_t socket_id;
0064 };
0065
0066 struct sdsi_dev {
0067 struct sdsi_regs regs;
0068 char *dev_name;
0069 char *dev_path;
0070 int guid;
0071 };
0072
0073 enum command {
0074 CMD_NONE,
0075 CMD_SOCKET_INFO,
0076 CMD_DUMP_CERT,
0077 CMD_PROV_AKC,
0078 CMD_PROV_CAP,
0079 };
0080
0081 static void sdsi_list_devices(void)
0082 {
0083 struct dirent *entry;
0084 DIR *aux_dir;
0085 bool found = false;
0086
0087 aux_dir = opendir(AUX_DEV_PATH);
0088 if (!aux_dir) {
0089 fprintf(stderr, "Cannot open directory %s\n", AUX_DEV_PATH);
0090 return;
0091 }
0092
0093 while ((entry = readdir(aux_dir))) {
0094 if (!strncmp(SDSI_DEV, entry->d_name, strlen(SDSI_DEV))) {
0095 found = true;
0096 printf("%s\n", entry->d_name);
0097 }
0098 }
0099
0100 if (!found)
0101 fprintf(stderr, "No sdsi devices found.\n");
0102 }
0103
0104 static int sdsi_update_registers(struct sdsi_dev *s)
0105 {
0106 FILE *regs_ptr;
0107 int ret;
0108
0109 memset(&s->regs, 0, sizeof(s->regs));
0110
0111
0112 ret = chdir(s->dev_path);
0113 if (ret == -1) {
0114 perror("chdir");
0115 return ret;
0116 }
0117
0118 regs_ptr = fopen("registers", "r");
0119 if (!regs_ptr) {
0120 perror("Could not open 'registers' file");
0121 return -1;
0122 }
0123
0124 if (s->guid != GUID) {
0125 fprintf(stderr, "Unrecognized guid, 0x%x\n", s->guid);
0126 fclose(regs_ptr);
0127 return -1;
0128 }
0129
0130
0131 ret = fread(&s->regs, sizeof(uint8_t), sizeof(s->regs), regs_ptr);
0132 if (ret != sizeof(s->regs)) {
0133 fprintf(stderr, "Could not read 'registers' file\n");
0134 fclose(regs_ptr);
0135 return -1;
0136 }
0137
0138 fclose(regs_ptr);
0139
0140 return 0;
0141 }
0142
0143 static int sdsi_read_reg(struct sdsi_dev *s)
0144 {
0145 int ret;
0146
0147 ret = sdsi_update_registers(s);
0148 if (ret)
0149 return ret;
0150
0151
0152 printf("\n");
0153 printf("Socket information for device %s\n", s->dev_name);
0154 printf("\n");
0155 printf("PPIN: 0x%lx\n", s->regs.ppin);
0156 printf("Enabled Features\n");
0157 printf(" SDSi: %s\n", !!s->regs.en_features.sdsi ? "Enabled" : "Disabled");
0158 printf("Authorization Failure Count\n");
0159 printf(" AKC Failure Count: %d\n", s->regs.auth_fail_count.key_failure_count);
0160 printf(" AKC Failure Threshold: %d\n", s->regs.auth_fail_count.key_failure_threshold);
0161 printf(" CAP Failure Count: %d\n", s->regs.auth_fail_count.auth_failure_count);
0162 printf(" CAP Failure Threshold: %d\n", s->regs.auth_fail_count.auth_failure_threshold);
0163 printf("Provisioning Availability\n");
0164 printf(" Updates Available: %d\n", s->regs.prov_avail.available);
0165 printf(" Updates Threshold: %d\n", s->regs.prov_avail.threshold);
0166 printf("Socket ID: %ld\n", s->regs.socket_id & 0xF);
0167
0168 return 0;
0169 }
0170
0171 static int sdsi_certificate_dump(struct sdsi_dev *s)
0172 {
0173 uint64_t state_certificate[512] = {0};
0174 bool first_instance;
0175 uint64_t previous;
0176 FILE *cert_ptr;
0177 int i, ret, size;
0178
0179 ret = sdsi_update_registers(s);
0180 if (ret)
0181 return ret;
0182
0183 if (!s->regs.en_features.sdsi) {
0184 fprintf(stderr, "SDSi feature is present but not enabled.");
0185 fprintf(stderr, " Unable to read state certificate");
0186 return -1;
0187 }
0188
0189 ret = chdir(s->dev_path);
0190 if (ret == -1) {
0191 perror("chdir");
0192 return ret;
0193 }
0194
0195 cert_ptr = fopen("state_certificate", "r");
0196 if (!cert_ptr) {
0197 perror("Could not open 'state_certificate' file");
0198 return -1;
0199 }
0200
0201 size = fread(state_certificate, 1, sizeof(state_certificate), cert_ptr);
0202 if (!size) {
0203 fprintf(stderr, "Could not read 'state_certificate' file\n");
0204 fclose(cert_ptr);
0205 return -1;
0206 }
0207
0208 printf("%3d: 0x%lx\n", 0, state_certificate[0]);
0209 previous = state_certificate[0];
0210 first_instance = true;
0211
0212 for (i = 1; i < (int)(round_up(size, sizeof(uint64_t))/sizeof(uint64_t)); i++) {
0213 if (state_certificate[i] == previous) {
0214 if (first_instance) {
0215 puts("*");
0216 first_instance = false;
0217 }
0218 continue;
0219 }
0220 printf("%3d: 0x%lx\n", i, state_certificate[i]);
0221 previous = state_certificate[i];
0222 first_instance = true;
0223 }
0224 printf("%3d\n", i);
0225
0226 fclose(cert_ptr);
0227
0228 return 0;
0229 }
0230
0231 static int sdsi_provision(struct sdsi_dev *s, char *bin_file, enum command command)
0232 {
0233 int bin_fd, prov_fd, size, ret;
0234 char buf[4096] = { 0 };
0235 char cap[] = "provision_cap";
0236 char akc[] = "provision_akc";
0237 char *prov_file;
0238
0239 if (!bin_file) {
0240 fprintf(stderr, "No binary file provided\n");
0241 return -1;
0242 }
0243
0244
0245 bin_fd = open(bin_file, O_RDONLY);
0246 if (bin_fd == -1) {
0247 fprintf(stderr, "Could not open file %s: %s\n", bin_file, strerror(errno));
0248 return bin_fd;
0249 }
0250
0251 prov_file = (command == CMD_PROV_AKC) ? akc : cap;
0252
0253 ret = chdir(s->dev_path);
0254 if (ret == -1) {
0255 perror("chdir");
0256 close(bin_fd);
0257 return ret;
0258 }
0259
0260
0261 prov_fd = open(prov_file, O_WRONLY);
0262 if (prov_fd == -1) {
0263 fprintf(stderr, "Could not open file %s: %s\n", prov_file, strerror(errno));
0264 close(bin_fd);
0265 return prov_fd;
0266 }
0267
0268
0269 size = read(bin_fd, buf, 4096);
0270 if (size == -1) {
0271 close(bin_fd);
0272 close(prov_fd);
0273 return -1;
0274 }
0275
0276 ret = write(prov_fd, buf, size);
0277 if (ret == -1) {
0278 close(bin_fd);
0279 close(prov_fd);
0280 perror("Provisioning failed");
0281 return ret;
0282 }
0283
0284 printf("Provisioned %s file %s successfully\n", prov_file, bin_file);
0285
0286 close(bin_fd);
0287 close(prov_fd);
0288
0289 return 0;
0290 }
0291
0292 static int sdsi_provision_akc(struct sdsi_dev *s, char *bin_file)
0293 {
0294 int ret;
0295
0296 ret = sdsi_update_registers(s);
0297 if (ret)
0298 return ret;
0299
0300 if (!s->regs.en_features.sdsi) {
0301 fprintf(stderr, "SDSi feature is present but not enabled. Unable to provision");
0302 return -1;
0303 }
0304
0305 if (!s->regs.prov_avail.available) {
0306 fprintf(stderr, "Maximum number of updates (%d) has been reached.\n",
0307 s->regs.prov_avail.threshold);
0308 return -1;
0309 }
0310
0311 if (s->regs.auth_fail_count.key_failure_count ==
0312 s->regs.auth_fail_count.key_failure_threshold) {
0313 fprintf(stderr, "Maximum number of AKC provision failures (%d) has been reached.\n",
0314 s->regs.auth_fail_count.key_failure_threshold);
0315 fprintf(stderr, "Power cycle the system to reset the counter\n");
0316 return -1;
0317 }
0318
0319 return sdsi_provision(s, bin_file, CMD_PROV_AKC);
0320 }
0321
0322 static int sdsi_provision_cap(struct sdsi_dev *s, char *bin_file)
0323 {
0324 int ret;
0325
0326 ret = sdsi_update_registers(s);
0327 if (ret)
0328 return ret;
0329
0330 if (!s->regs.en_features.sdsi) {
0331 fprintf(stderr, "SDSi feature is present but not enabled. Unable to provision");
0332 return -1;
0333 }
0334
0335 if (!s->regs.prov_avail.available) {
0336 fprintf(stderr, "Maximum number of updates (%d) has been reached.\n",
0337 s->regs.prov_avail.threshold);
0338 return -1;
0339 }
0340
0341 if (s->regs.auth_fail_count.auth_failure_count ==
0342 s->regs.auth_fail_count.auth_failure_threshold) {
0343 fprintf(stderr, "Maximum number of CAP provision failures (%d) has been reached.\n",
0344 s->regs.auth_fail_count.auth_failure_threshold);
0345 fprintf(stderr, "Power cycle the system to reset the counter\n");
0346 return -1;
0347 }
0348
0349 return sdsi_provision(s, bin_file, CMD_PROV_CAP);
0350 }
0351
0352 static int read_sysfs_data(const char *file, int *value)
0353 {
0354 char buff[16];
0355 FILE *fp;
0356
0357 fp = fopen(file, "r");
0358 if (!fp) {
0359 perror(file);
0360 return -1;
0361 }
0362
0363 if (!fgets(buff, 16, fp)) {
0364 fprintf(stderr, "Failed to read file '%s'", file);
0365 fclose(fp);
0366 return -1;
0367 }
0368
0369 fclose(fp);
0370 *value = strtol(buff, NULL, 0);
0371
0372 return 0;
0373 }
0374
0375 static struct sdsi_dev *sdsi_create_dev(char *dev_no)
0376 {
0377 int dev_name_len = sizeof(SDSI_DEV) + strlen(dev_no) + 1;
0378 struct sdsi_dev *s;
0379 int guid;
0380 DIR *dir;
0381
0382 s = (struct sdsi_dev *)malloc(sizeof(*s));
0383 if (!s) {
0384 perror("malloc");
0385 return NULL;
0386 }
0387
0388 s->dev_name = (char *)malloc(sizeof(SDSI_DEV) + strlen(dev_no) + 1);
0389 if (!s->dev_name) {
0390 perror("malloc");
0391 free(s);
0392 return NULL;
0393 }
0394
0395 snprintf(s->dev_name, dev_name_len, "%s.%s", SDSI_DEV, dev_no);
0396
0397 s->dev_path = (char *)malloc(sizeof(AUX_DEV_PATH) + dev_name_len);
0398 if (!s->dev_path) {
0399 perror("malloc");
0400 free(s->dev_name);
0401 free(s);
0402 return NULL;
0403 }
0404
0405 snprintf(s->dev_path, sizeof(AUX_DEV_PATH) + dev_name_len, "%s%s", AUX_DEV_PATH,
0406 s->dev_name);
0407 dir = opendir(s->dev_path);
0408 if (!dir) {
0409 fprintf(stderr, "Could not open directory '%s': %s\n", s->dev_path,
0410 strerror(errno));
0411 free(s->dev_path);
0412 free(s->dev_name);
0413 free(s);
0414 return NULL;
0415 }
0416
0417 if (chdir(s->dev_path) == -1) {
0418 perror("chdir");
0419 free(s->dev_path);
0420 free(s->dev_name);
0421 free(s);
0422 return NULL;
0423 }
0424
0425 if (read_sysfs_data("guid", &guid)) {
0426 free(s->dev_path);
0427 free(s->dev_name);
0428 free(s);
0429 return NULL;
0430 }
0431
0432 s->guid = guid;
0433
0434 return s;
0435 }
0436
0437 static void sdsi_free_dev(struct sdsi_dev *s)
0438 {
0439 free(s->dev_path);
0440 free(s->dev_name);
0441 free(s);
0442 }
0443
0444 static void usage(char *prog)
0445 {
0446 printf("Usage: %s [-l] [-d DEVNO [-iD] [-a FILE] [-c FILE]]\n", prog);
0447 }
0448
0449 static void show_help(void)
0450 {
0451 printf("Commands:\n");
0452 printf(" %-18s\t%s\n", "-l, --list", "list available sdsi devices");
0453 printf(" %-18s\t%s\n", "-d, --devno DEVNO", "sdsi device number");
0454 printf(" %-18s\t%s\n", "-i --info", "show socket information");
0455 printf(" %-18s\t%s\n", "-D --dump", "dump state certificate data");
0456 printf(" %-18s\t%s\n", "-a --akc FILE", "provision socket with AKC FILE");
0457 printf(" %-18s\t%s\n", "-c --cap FILE>", "provision socket with CAP FILE");
0458 }
0459
0460 int main(int argc, char *argv[])
0461 {
0462 char bin_file[PATH_MAX], *dev_no = NULL;
0463 char *progname;
0464 enum command command = CMD_NONE;
0465 struct sdsi_dev *s;
0466 int ret = 0, opt;
0467 int option_index = 0;
0468
0469 static struct option long_options[] = {
0470 {"akc", required_argument, 0, 'a'},
0471 {"cap", required_argument, 0, 'c'},
0472 {"devno", required_argument, 0, 'd'},
0473 {"dump", no_argument, 0, 'D'},
0474 {"help", no_argument, 0, 'h'},
0475 {"info", no_argument, 0, 'i'},
0476 {"list", no_argument, 0, 'l'},
0477 {0, 0, 0, 0 }
0478 };
0479
0480
0481 progname = argv[0];
0482
0483 while ((opt = getopt_long_only(argc, argv, "+a:c:d:Da:c:h", long_options,
0484 &option_index)) != -1) {
0485 switch (opt) {
0486 case 'd':
0487 dev_no = optarg;
0488 break;
0489 case 'l':
0490 sdsi_list_devices();
0491 return 0;
0492 case 'i':
0493 command = CMD_SOCKET_INFO;
0494 break;
0495 case 'D':
0496 command = CMD_DUMP_CERT;
0497 break;
0498 case 'a':
0499 case 'c':
0500 if (!access(optarg, F_OK) == 0) {
0501 fprintf(stderr, "Could not open file '%s': %s\n", optarg,
0502 strerror(errno));
0503 return -1;
0504 }
0505
0506 if (!realpath(optarg, bin_file)) {
0507 perror("realpath");
0508 return -1;
0509 }
0510
0511 command = (opt == 'a') ? CMD_PROV_AKC : CMD_PROV_CAP;
0512 break;
0513 case 'h':
0514 usage(progname);
0515 show_help();
0516 return 0;
0517 default:
0518 usage(progname);
0519 return -1;
0520 }
0521 }
0522
0523 if (!dev_no) {
0524 if (command != CMD_NONE)
0525 fprintf(stderr, "Missing device number, DEVNO, for this command\n");
0526 usage(progname);
0527 return -1;
0528 }
0529
0530 s = sdsi_create_dev(dev_no);
0531 if (!s)
0532 return -1;
0533
0534
0535 switch (command) {
0536 case CMD_NONE:
0537 fprintf(stderr, "Missing command for device %s\n", dev_no);
0538 usage(progname);
0539 break;
0540 case CMD_SOCKET_INFO:
0541 ret = sdsi_read_reg(s);
0542 break;
0543 case CMD_DUMP_CERT:
0544 ret = sdsi_certificate_dump(s);
0545 break;
0546 case CMD_PROV_AKC:
0547 ret = sdsi_provision_akc(s, bin_file);
0548 break;
0549 case CMD_PROV_CAP:
0550 ret = sdsi_provision_cap(s, bin_file);
0551 break;
0552 }
0553
0554
0555 sdsi_free_dev(s);
0556
0557 return ret;
0558 }