]>
Commit | Line | Data |
---|---|---|
1d5e0797 SB |
1 | /* |
2 | * capabilities.c -- capabilities | |
3 | * | |
4 | * (c) Copyright IBM Corporation 2019. | |
5 | * | |
6 | * Author: Stefan Berger <stefanb@us.ibm.com> | |
7 | * | |
8 | * All rights reserved. | |
9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions are | |
12 | * met: | |
13 | * | |
14 | * Redistributions of source code must retain the above copyright notice, | |
15 | * this list of conditions and the following disclaimer. | |
16 | * | |
17 | * Redistributions in binary form must reproduce the above copyright | |
18 | * notice, this list of conditions and the following disclaimer in the | |
19 | * documentation and/or other materials provided with the distribution. | |
20 | * | |
21 | * Neither the names of the IBM Corporation nor the names of its | |
22 | * contributors may be used to endorse or promote products derived from | |
23 | * this software without specific prior written permission. | |
24 | * | |
25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
26 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
27 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
28 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
29 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
30 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
31 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
32 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
33 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
34 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
35 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
36 | */ | |
37 | ||
38 | #include "config.h" | |
39 | ||
40 | #define _GNU_SOURCE | |
41 | #include <stdio.h> | |
42 | #include <stdlib.h> | |
c6b52d18 SB |
43 | #include <string.h> |
44 | ||
45 | #include <libtpms/tpm_library.h> | |
da8752b1 | 46 | #include <libtpms/tpm_error.h> |
1d5e0797 SB |
47 | |
48 | #include "capabilities.h" | |
49 | #include "logging.h" | |
86931b4f | 50 | #include "swtpm_nvstore.h" |
1d5e0797 | 51 | |
c6b52d18 SB |
52 | /* Convert the RSA key size indicators supported by libtpms into capability |
53 | * strings. | |
54 | * libtpms may return us something like this here: | |
55 | * "TPMAttributes":{"manufacturer":"id:00001014",\ | |
56 | * "version":"id:20191023","model":"swtpm","RSAKeySizes":[1024,2048,3072]}} | |
57 | * | |
58 | * or an older version may not report RSA keysizes: | |
59 | * "TPMAttributes":{"manufacturer":"id:00001014",\ | |
60 | * "version":"id:20191023","model":"swtpm"}} | |
61 | */ | |
62 | static int get_rsa_keysize_caps(char **keysizecaps) | |
63 | { | |
64 | int ret = 0; | |
65 | char *start, *endptr; | |
66 | const char *needle = "\"RSAKeySizes\":["; | |
67 | char *info_data = TPMLIB_GetInfo(4 /*TPMLIB_INFO_TPMFEATURES*/); | |
68 | char buffer[128]; | |
69 | off_t offset = 0; | |
70 | int n; | |
71 | ||
72 | if (!info_data) | |
ccaf99f1 | 73 | goto cleanup; |
c6b52d18 SB |
74 | |
75 | start = strstr(info_data, needle); | |
76 | if (start) { | |
77 | start += strlen(needle); | |
78 | while (1) { | |
79 | unsigned long int keysize = strtoul(start, &endptr, 10); | |
80 | ||
81 | if (*endptr != ',' && *endptr != ']') { | |
82 | logprintf(STDERR_FILENO, "Malformed TPMLIB_GetInfo() string\n"); | |
83 | ret = -1; | |
84 | goto cleanup; | |
85 | } | |
86 | ||
87 | n = snprintf(buffer + offset, sizeof(buffer) - offset, | |
88 | ", \"rsa-keysize-%lu\"", | |
89 | keysize); | |
90 | if (n < 0 || (unsigned)n >= sizeof(buffer) - offset) { | |
91 | logprintf(STDERR_FILENO, "%s: buffer is too small\n", __func__); | |
92 | ret = -1; | |
93 | goto cleanup; | |
94 | } | |
95 | if (*endptr == ']') | |
96 | break; | |
97 | ||
98 | offset += n; | |
99 | start = endptr + 1; | |
100 | } | |
101 | ||
102 | *keysizecaps = strndup(buffer, sizeof(buffer) - 1); | |
103 | if (*keysizecaps == NULL) | |
104 | goto oom; | |
105 | } | |
106 | ||
107 | cleanup: | |
108 | free(info_data); | |
109 | return ret; | |
110 | ||
111 | oom: | |
112 | logprintf(STDERR_FILENO, "Out of memory\n"); | |
113 | ret = -1; | |
114 | goto cleanup; | |
115 | } | |
116 | ||
bf3f5175 | 117 | int capabilities_print_json(bool cusetpm, TPMLIB_TPMVersion tpmversion) |
1d5e0797 SB |
118 | { |
119 | char *string = NULL; | |
120 | int ret = -1; | |
121 | int n; | |
122 | #ifdef WITH_SECCOMP | |
374b6691 | 123 | const char *cmdarg_seccomp = "\"cmdarg-seccomp\", "; |
1d5e0797 | 124 | #else |
374b6691 | 125 | const char *cmdarg_seccomp = ""; |
1d5e0797 | 126 | #endif |
da8752b1 MAL |
127 | const char *with_tpm1 = ""; |
128 | const char *with_tpm2 = ""; | |
c6b52d18 | 129 | char *keysizecaps = NULL; |
0716f994 SR |
130 | const char *nvram_backend_dir = "\"nvram-backend-dir\", "; |
131 | const char *nvram_backend_file = "\"nvram-backend-file\""; | |
c6b52d18 | 132 | |
76001cd2 SB |
133 | /* ignore errors */ |
134 | TPMLIB_ChooseTPMVersion(tpmversion); | |
bf3f5175 | 135 | |
c6b52d18 SB |
136 | ret = get_rsa_keysize_caps(&keysizecaps); |
137 | if (ret < 0) | |
138 | goto cleanup; | |
1d5e0797 | 139 | |
da8752b1 MAL |
140 | if (TPMLIB_ChooseTPMVersion(TPMLIB_TPM_VERSION_1_2) == TPM_SUCCESS) |
141 | with_tpm1 = "\"tpm-1.2\", "; | |
142 | if (TPMLIB_ChooseTPMVersion(TPMLIB_TPM_VERSION_2) == TPM_SUCCESS) | |
143 | with_tpm2 = "\"tpm-2.0\", "; | |
144 | ||
1d5e0797 SB |
145 | n = asprintf(&string, |
146 | "{ " | |
147 | "\"type\": \"swtpm\", " | |
148 | "\"features\": [ " | |
d5296e19 | 149 | "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" |
155ccdf5 MAL |
150 | " ], " |
151 | "\"version\": \"" VERSION "\" " | |
1d5e0797 | 152 | "}", |
da8752b1 MAL |
153 | with_tpm1, |
154 | with_tpm2, | |
1d5e0797 | 155 | !cusetpm ? "\"tpm-send-command-header\", ": "", |
b3c32ed5 | 156 | true ? "\"flags-opt-startup\", " : "", |
97e910af | 157 | true ? "\"flags-opt-disable-auto-shutdown\", ": "", |
d5296e19 | 158 | true ? "\"ctrl-opt-terminate\", " : "", |
374b6691 | 159 | cmdarg_seccomp, |
1d5e0797 | 160 | true ? "\"cmdarg-key-fd\", " : "", |
86931b4f | 161 | true ? "\"cmdarg-pwd-fd\", " : "", |
e6cbc55d | 162 | true ? "\"cmdarg-print-states\", " : "", |
cdc39fd9 | 163 | true ? "\"cmdarg-chroot\", " : "", |
e821754b | 164 | true ? "\"cmdarg-migration\", " : "", |
86931b4f | 165 | nvram_backend_dir, |
0716f994 | 166 | nvram_backend_file, |
c6b52d18 | 167 | keysizecaps ? keysizecaps : "" |
1d5e0797 SB |
168 | ); |
169 | ||
170 | if (n < 0) { | |
171 | logprintf(STDERR_FILENO, "Out of memory\n"); | |
172 | goto cleanup; | |
173 | } | |
174 | ||
175 | ret = 0; | |
176 | ||
177 | fprintf(stdout, "%s\n", string); | |
178 | ||
179 | cleanup: | |
c6b52d18 | 180 | free(keysizecaps); |
1d5e0797 SB |
181 | free(string); |
182 | ||
183 | return ret; | |
184 | } |