~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/arch/x86/intel_sdsi/intel_sdsi.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php