]> git.proxmox.com Git - swtpm.git/blob - src/swtpm/capabilities.c
swtpm*: report 'version' in --print-capabilities
[swtpm.git] / src / swtpm / capabilities.c
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>
43 #include <string.h>
44
45 #include <libtpms/tpm_library.h>
46 #include <libtpms/tpm_error.h>
47
48 #include "capabilities.h"
49 #include "logging.h"
50
51 /* Convert the RSA key size indicators supported by libtpms into capability
52 * strings.
53 * libtpms may return us something like this here:
54 * "TPMAttributes":{"manufacturer":"id:00001014",\
55 * "version":"id:20191023","model":"swtpm","RSAKeySizes":[1024,2048,3072]}}
56 *
57 * or an older version may not report RSA keysizes:
58 * "TPMAttributes":{"manufacturer":"id:00001014",\
59 * "version":"id:20191023","model":"swtpm"}}
60 */
61 static int get_rsa_keysize_caps(char **keysizecaps)
62 {
63 int ret = 0;
64 char *start, *endptr;
65 const char *needle = "\"RSAKeySizes\":[";
66 char *info_data = TPMLIB_GetInfo(4 /*TPMLIB_INFO_TPMFEATURES*/);
67 char buffer[128];
68 off_t offset = 0;
69 int n;
70
71 if (!info_data)
72 goto cleanup;
73
74 start = strstr(info_data, needle);
75 if (start) {
76 start += strlen(needle);
77 while (1) {
78 unsigned long int keysize = strtoul(start, &endptr, 10);
79
80 if (*endptr != ',' && *endptr != ']') {
81 logprintf(STDERR_FILENO, "Malformed TPMLIB_GetInfo() string\n");
82 ret = -1;
83 goto cleanup;
84 }
85
86 n = snprintf(buffer + offset, sizeof(buffer) - offset,
87 ", \"rsa-keysize-%lu\"",
88 keysize);
89 if (n < 0 || (unsigned)n >= sizeof(buffer) - offset) {
90 logprintf(STDERR_FILENO, "%s: buffer is too small\n", __func__);
91 ret = -1;
92 goto cleanup;
93 }
94 if (*endptr == ']')
95 break;
96
97 offset += n;
98 start = endptr + 1;
99 }
100
101 *keysizecaps = strndup(buffer, sizeof(buffer) - 1);
102 if (*keysizecaps == NULL)
103 goto oom;
104 }
105
106 cleanup:
107 free(info_data);
108 return ret;
109
110 oom:
111 logprintf(STDERR_FILENO, "Out of memory\n");
112 ret = -1;
113 goto cleanup;
114 }
115
116 int capabilities_print_json(bool cusetpm)
117 {
118 char *string = NULL;
119 int ret = -1;
120 int n;
121 #ifdef WITH_SECCOMP
122 const char *cmdarg_seccomp = "\"cmdarg-seccomp\", ";
123 #else
124 const char *cmdarg_seccomp = "";
125 #endif
126 const char *with_tpm1 = "";
127 const char *with_tpm2 = "";
128 char *keysizecaps = NULL;
129
130 ret = get_rsa_keysize_caps(&keysizecaps);
131 if (ret < 0)
132 goto cleanup;
133
134 if (TPMLIB_ChooseTPMVersion(TPMLIB_TPM_VERSION_1_2) == TPM_SUCCESS)
135 with_tpm1 = "\"tpm-1.2\", ";
136 if (TPMLIB_ChooseTPMVersion(TPMLIB_TPM_VERSION_2) == TPM_SUCCESS)
137 with_tpm2 = "\"tpm-2.0\", ";
138
139 n = asprintf(&string,
140 "{ "
141 "\"type\": \"swtpm\", "
142 "\"features\": [ "
143 "%s%s%s%s%s%s%s%s"
144 " ], "
145 "\"version\": \"" VERSION "\" "
146 "}",
147 with_tpm1,
148 with_tpm2,
149 !cusetpm ? "\"tpm-send-command-header\", ": "",
150 !cusetpm ? "\"flags-opt-startup\", " : "",
151 cmdarg_seccomp,
152 true ? "\"cmdarg-key-fd\", " : "",
153 true ? "\"cmdarg-pwd-fd\"" : "",
154 keysizecaps ? keysizecaps : ""
155 );
156
157 if (n < 0) {
158 logprintf(STDERR_FILENO, "Out of memory\n");
159 goto cleanup;
160 }
161
162 ret = 0;
163
164 fprintf(stdout, "%s\n", string);
165
166 cleanup:
167 free(keysizecaps);
168 free(string);
169
170 return ret;
171 }