]> git.proxmox.com Git - swtpm.git/blame - src/swtpm/key.c
swtpm: Add another exit label to avoid gcc -fanalyzer false positive
[swtpm.git] / src / swtpm / key.c
CommitLineData
f163b202
SB
1/*
2 * key.c -- Common key handling code for swtpm and swtpm_cuse
3 *
ad976d1a 4 * (c) Copyright IBM Corporation 2014, 2015.
f163b202
SB
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
7849b6c6 40#include <openssl/sha.h>
a39f098f 41#include <openssl/evp.h>
f163b202
SB
42
43#include <ctype.h>
44#include <errno.h>
45#include <fcntl.h>
46#include <string.h>
47#include <stdio.h>
a39f098f 48#include <stdlib.h>
f163b202
SB
49#include <unistd.h>
50#include <sys/types.h>
f163b202
SB
51
52#include "key.h"
cba81569 53#include "logging.h"
a442092d 54#include "utils.h"
f163b202 55
58548ac6
SB
56/*
57 * key_format_from_string:
58 * Convert the string into a key format identifier
59 * @format: either 'hex' or 'binary'
60 *
61 * Returns a key format identifier
62 */
f163b202
SB
63enum key_format
64key_format_from_string(const char *format)
65{
66 if (!strcmp(format, "hex")) {
67 return KEY_FORMAT_HEX;
68 } else if (!strcmp(format, "binary")) {
69 return KEY_FORMAT_BINARY;
70 }
cba81569 71 logprintf(STDERR_FILENO, "Unknown key format '%s'.\n", format);
f163b202
SB
72
73 return KEY_FORMAT_UNKNOWN;
74}
75
58548ac6
SB
76/*
77 * encryption_mode_from_string:
78 * Convert the string into a encryption mode identifier
79 * @mode: string describing encryption mode
68a5b241 80 * @keylen: the length of the key in bytes
58548ac6
SB
81 *
82 * Returns an encryption mode identifier
83 */
f163b202 84enum encryption_mode
68a5b241 85encryption_mode_from_string(const char *mode, size_t *keylen)
f163b202 86{
68a5b241
SB
87 if (!strcmp(mode, "aes-cbc") || !strcmp(mode, "aes-128-cbc")) {
88 *keylen = 128/8;
89 return ENCRYPTION_MODE_AES_CBC;
90 } else if (!strcmp(mode, "aes-256-cbc")) {
91 *keylen = 256/8;
f163b202
SB
92 return ENCRYPTION_MODE_AES_CBC;
93 }
94
95 return ENCRYPTION_MODE_UNKNOWN;
96}
97
a39f098f
SB
98/*
99 * kdf_identifier_from_string:
100 * Convert the string in a kdf identifier
101 * @mode: string describing the kdf
102 *
103 * Return a kdf identifier
104 */
105enum kdf_identifier
106kdf_identifier_from_string(const char *kdf)
107{
108 if (!strcmp(kdf, "sha512")) {
109 return KDF_IDENTIFIER_SHA512;
110 } else if (!strcmp(kdf, "pbkdf2")) {
111 return KDF_IDENTIFIER_PBKDF2;
112 }
113
114 return KDF_IDENTIFIER_UNKNOWN;
115}
116
58548ac6
SB
117/*
118 * key_stream_to_bin
119 * Convert a stream of ASCII hex digits into a key; convert a maximum of
120 * bin_size bytes;
121 *
122 * @input: input data holding hex digits
123 * @bin: output field of bin_size
124 * @bin_size: max. number of bytes to convert
125 *
126 * Returns the number of digits that were converted.
127 */
f163b202
SB
128static ssize_t
129key_stream_to_bin(const char *input, unsigned char *bin, size_t bin_size)
130{
131 ssize_t digits = 0;
132 int n, num;
133
134 while (input[digits] &&
dd92f458 135 !isspace((int)input[digits]) &&
f163b202
SB
136 bin_size > (size_t)digits / 2) {
137 num = sscanf(&input[digits], "%2hhx%n", &bin[digits/2], &n);
138 if (num != 1 || n != 2)
139 return -1;
140 digits += 2;
141 }
142
dd92f458 143 if (input[digits] && !isspace((int)input[digits]))
f163b202
SB
144 return -1;
145
146 return (digits != 0) ? digits : -1;
147}
148
58548ac6
SB
149/*
150 * key_parse_as_hexkey:
151 * Parse the raw key data as a key in ASCII hex format; they key may
152 * have a leading '0x'.
153 * @rawkey: ASCII data for a hex key with possible leading '0x'
154 * @key: buffer for key
155 * @keylen: actual key len returned by this function
156 * @maxkeylen: the max. size of the key; this is equivalent to the size of
157 * the key buffer
158 * Returns 0 on success, -1 on failure
159 */
f163b202
SB
160static int
161key_parse_as_hexkey(const char *rawkey,
162 unsigned char *key, size_t *keylen, size_t maxkeylen)
163{
164 ssize_t digits;
165 off_t offset = 0;
166
167 if (!strncmp(rawkey, "0x", 2))
168 offset = 2;
169
170 digits = key_stream_to_bin(&rawkey[offset], key, maxkeylen);
171 if (digits < 0) {
cba81569
SB
172 logprintf(STDERR_FILENO,
173 "Could not parse key hex string into %zu byte buffer.\n",
174 maxkeylen);
f163b202
SB
175 return -1;
176 } else if (digits == 128/4) {
177 *keylen = 128/8;
748df6ee
SB
178 } else if (digits == 256/4) {
179 *keylen = 256/8;
f163b202 180 } else {
cba81569
SB
181 logprintf(STDERR_FILENO,
182 "Unsupported key length with %zu digits.\n",
183 digits);
f163b202
SB
184 return -1;
185 }
748df6ee
SB
186 if (*keylen < maxkeylen) {
187 logprintf(STDERR_FILENO,
188 "The provided key is too short. Got %zu bytes, need %zu.\n",
189 *keylen, maxkeylen);
190 return -1;
191 }
f163b202
SB
192
193 return 0;
194}
195
58548ac6 196/*
f4be1e86 197 * key_load_key_fd:
58548ac6 198 * Load the raw key data from a file and convert it to a key.
f4be1e86 199 * @fd: file descriptor to read raw key data from
58548ac6
SB
200 * @keyformat: the format the raw key data are in; may either indicate
201 * binary data or hex string
202 * @key: the buffer for holding the converted key
203 * @keylen: the actual key len of the converted key returned by this
204 * function
205 * @maxkeylen: the max. size of the key; corresponds to the size of the
206 * key buffer
207 */
f163b202 208int
f4be1e86
SB
209key_load_key_fd(int fd, enum key_format keyformat,
210 unsigned char *key, size_t *keylen, size_t maxkeylen)
f163b202
SB
211{
212 int ret = -1;
748df6ee 213 char filebuffer[2 + 256/4 + 1 + 1];
da521f04 214 ssize_t len;
f163b202 215
a442092d 216 len = read_eintr(fd, filebuffer, sizeof(filebuffer) - 1);
f163b202 217 if (len < 0) {
cba81569
SB
218 logprintf(STDERR_FILENO, "Unable to read key: %s\n",
219 strerror(errno));
f163b202
SB
220 return -1;
221 }
222 filebuffer[len] = 0;
223
224 switch (keyformat) {
225 case KEY_FORMAT_BINARY:
226 *keylen = len;
da521f04 227 if (maxkeylen < (size_t)len) {
cba81569
SB
228 logprintf(STDERR_FILENO,
229 "Key is larger than buffer (%zu > %zu).\n",
230 len, maxkeylen);
f163b202
SB
231 return -1;
232 }
233 memcpy(key, filebuffer, len);
234 ret = 0;
235 break;
236 case KEY_FORMAT_HEX:
237 if (key_parse_as_hexkey(filebuffer, key, keylen, maxkeylen) < 0)
238 return -1;
239 ret = 0;
240 break;
241 case KEY_FORMAT_UNKNOWN:
242 break;
243 }
244
245 return ret;
246}
f4be1e86
SB
247/*
248 * key_load_key:
249 * Load the raw key data from a file and convert it to a key.
250 * @filename: file holding the raw key data
251 * @keyformat: the format the raw key data are in; may either indicate
252 * binary data or hex string
253 * @key: the buffer for holding the converted key
254 * @keylen: the actual key len of the converted key returned by this
255 * function
256 * @maxkeylen: the max. size of the key; corresponds to the size of the
257 * key buffer
258 */
259int
260key_load_key(const char *filename, enum key_format keyformat,
261 unsigned char *key, size_t *keylen, size_t maxkeylen)
262{
263 int ret;
264 int fd;
265
266 fd = open(filename, O_RDONLY);
267 if (fd < 0) {
268 logprintf(STDERR_FILENO, "Unable to open file %s: %s\n",
269 filename, strerror(errno));
270 return -1;
271 }
272 ret = key_load_key_fd(fd, keyformat, key, keylen, maxkeylen);
273
274 close(fd);
275
276 return ret;
277}
f163b202 278
58548ac6
SB
279/*
280 * key_from_pwdfile:
a947bebd
SB
281 * Read the password from the given file descriptor, convert the password into
282 * a key by applying a KDF on the password and use the first bytes
58548ac6 283 * of the hash as the key.
a947bebd 284 * @fd: file descriptor to read password from
58548ac6 285 * @key: the buffer for holding the key
58548ac6
SB
286 * @keylen: the actual key len of the converted key returned by this
287 * function
288 * @maxkeylen: the max. size of the key; corresponds to the size of the
289 * key buffer
a39f098f 290 * @kdfid: the kdf to invoke to create the key
58548ac6 291 */
f163b202 292int
a947bebd
SB
293key_from_pwdfile_fd(int fd, unsigned char *key, size_t *keylen,
294 size_t maxkeylen, enum kdf_identifier kdfid)
f163b202 295{
a39f098f 296 unsigned char *filebuffer = NULL;
e7fb07e8
SB
297 size_t filelen = 1024;
298 off_t offset = 0;
0268ef45 299 ssize_t len;
3bbdd7bc 300 unsigned char hashbuf[SHA512_DIGEST_LENGTH];
a39f098f
SB
301 int ret = -1;
302 const unsigned char salt[] = {'s','w','t','p','m'};
f163b202
SB
303
304 if (maxkeylen > sizeof(hashbuf)) {
cba81569
SB
305 logprintf(STDERR_FILENO,
306 "Request keylength is too big (%zu > %zu)\n",
307 maxkeylen, sizeof(hashbuf));
f163b202
SB
308 return -1;
309 }
310
e7fb07e8 311 while (true) {
4450856d
SB
312 unsigned char *tmp = filebuffer;
313
314 filebuffer = realloc(tmp, filelen);
e7fb07e8
SB
315 if (!filebuffer) {
316 logprintf(STDERR_FILENO,
317 "Could not allocate %zu bytes for filebuffer\n",
318 filelen);
4450856d 319 free(tmp);
e7fb07e8
SB
320 goto exit;
321 }
a39f098f 322
a442092d 323 len = read_eintr(fd, &filebuffer[offset], filelen - offset);
e7fb07e8
SB
324 if (len < 0) {
325 logprintf(STDERR_FILENO,
326 "Unable to read passphrase: %s\n",
327 strerror(errno));
87ce53ff 328 goto err_free_buffer;
e7fb07e8
SB
329 }
330 /* EOF ? */
331 if ((size_t)len < filelen - offset) {
332 len += offset;
333 break;
334 }
335 /* expecting more bytes */
336 offset += len;
337 filelen += 1024;
f163b202
SB
338 }
339
f163b202 340 *keylen = maxkeylen;
f163b202 341
a39f098f
SB
342 switch (kdfid) {
343 case KDF_IDENTIFIER_SHA512:
748df6ee
SB
344 if (sizeof(hashbuf) < *keylen) {
345 logprintf(STDERR_FILENO,
346 "Requested %zu bytes for key, only got %zu.\n",
347 *keylen, sizeof(hashbuf));
87ce53ff 348 goto err_free_buffer;
748df6ee 349 }
63717f99 350 SHA512(filebuffer, len, hashbuf);
a39f098f
SB
351 memcpy(key, hashbuf, *keylen);
352 break;
353 case KDF_IDENTIFIER_PBKDF2:
354 if (PKCS5_PBKDF2_HMAC((const char *)filebuffer, len,
355 salt, sizeof(salt), 1000,
356 EVP_sha512(), *keylen, key) != 1) {
357 logprintf(STDERR_FILENO,
358 "PKCS5_PBKDF2_HMAC with SHA512 failed\n");
87ce53ff 359 goto err_free_buffer;
a39f098f
SB
360 }
361 break;
362 case KDF_IDENTIFIER_UNKNOWN:
363 logprintf(STDERR_FILENO,
364 "Unknown KDF\n");
87ce53ff 365 goto err_free_buffer;
a39f098f
SB
366 }
367
a947bebd 368 ret = 0;
a39f098f 369
87ce53ff 370err_free_buffer:
a39f098f
SB
371 free(filebuffer);
372
87ce53ff 373exit:
a39f098f 374 return ret;
f163b202 375}
a947bebd
SB
376
377/*
378 * key_from_pwdfile:
379 * Read the password from the given file, convert the password into
380 * a key by applying a KDF on the password and use the first bytes
381 * of the hash as the key.
382 * @filename: name of the file holding the password
383 * @key: the buffer for holding the key
384 * @keylen: the actual key len of the converted key returned by this
385 * function
386 * @maxkeylen: the max. size of the key; corresponds to the size of the
387 * key buffer
388 * @kdfid: the kdf to invoke to create the key
389 */
390int
391key_from_pwdfile(const char *filename, unsigned char *key, size_t *keylen,
392 size_t maxkeylen, enum kdf_identifier kdfid)
393{
394 int ret;
395 int fd;
396
397 fd = open(filename, O_RDONLY);
398 if (fd < 0) {
399 logprintf(STDERR_FILENO,
400 "Unable to open file %s : %s\n",
401 filename, strerror(errno));
402 return -1;
403 }
404
405 ret = key_from_pwdfile_fd(fd, key, keylen, maxkeylen, kdfid);
406
407 close(fd);
408
409 return ret;
410}