]> git.proxmox.com Git - swtpm.git/blame - src/swtpm/key.c
swtpm: Extend en- and decryption functions for 256 bit keys
[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>
51#include <sys/stat.h>
52
53#include "key.h"
cba81569 54#include "logging.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
80 *
81 * Returns an encryption mode identifier
82 */
f163b202
SB
83enum encryption_mode
84encryption_mode_from_string(const char *mode)
85{
86 if (!strcmp(mode, "aes-cbc")) {
87 return ENCRYPTION_MODE_AES_CBC;
88 }
89
90 return ENCRYPTION_MODE_UNKNOWN;
91}
92
a39f098f
SB
93/*
94 * kdf_identifier_from_string:
95 * Convert the string in a kdf identifier
96 * @mode: string describing the kdf
97 *
98 * Return a kdf identifier
99 */
100enum kdf_identifier
101kdf_identifier_from_string(const char *kdf)
102{
103 if (!strcmp(kdf, "sha512")) {
104 return KDF_IDENTIFIER_SHA512;
105 } else if (!strcmp(kdf, "pbkdf2")) {
106 return KDF_IDENTIFIER_PBKDF2;
107 }
108
109 return KDF_IDENTIFIER_UNKNOWN;
110}
111
58548ac6
SB
112/*
113 * key_stream_to_bin
114 * Convert a stream of ASCII hex digits into a key; convert a maximum of
115 * bin_size bytes;
116 *
117 * @input: input data holding hex digits
118 * @bin: output field of bin_size
119 * @bin_size: max. number of bytes to convert
120 *
121 * Returns the number of digits that were converted.
122 */
f163b202
SB
123static ssize_t
124key_stream_to_bin(const char *input, unsigned char *bin, size_t bin_size)
125{
126 ssize_t digits = 0;
127 int n, num;
128
129 while (input[digits] &&
130 !isspace(input[digits]) &&
131 bin_size > (size_t)digits / 2) {
132 num = sscanf(&input[digits], "%2hhx%n", &bin[digits/2], &n);
133 if (num != 1 || n != 2)
134 return -1;
135 digits += 2;
136 }
137
138 if (input[digits] && !isspace(input[digits]))
139 return -1;
140
141 return (digits != 0) ? digits : -1;
142}
143
58548ac6
SB
144/*
145 * key_parse_as_hexkey:
146 * Parse the raw key data as a key in ASCII hex format; they key may
147 * have a leading '0x'.
148 * @rawkey: ASCII data for a hex key with possible leading '0x'
149 * @key: buffer for key
150 * @keylen: actual key len returned by this function
151 * @maxkeylen: the max. size of the key; this is equivalent to the size of
152 * the key buffer
153 * Returns 0 on success, -1 on failure
154 */
f163b202
SB
155static int
156key_parse_as_hexkey(const char *rawkey,
157 unsigned char *key, size_t *keylen, size_t maxkeylen)
158{
159 ssize_t digits;
160 off_t offset = 0;
161
162 if (!strncmp(rawkey, "0x", 2))
163 offset = 2;
164
165 digits = key_stream_to_bin(&rawkey[offset], key, maxkeylen);
166 if (digits < 0) {
cba81569
SB
167 logprintf(STDERR_FILENO,
168 "Could not parse key hex string into %zu byte buffer.\n",
169 maxkeylen);
f163b202
SB
170 return -1;
171 } else if (digits == 128/4) {
172 *keylen = 128/8;
748df6ee
SB
173 } else if (digits == 256/4) {
174 *keylen = 256/8;
f163b202 175 } else {
cba81569
SB
176 logprintf(STDERR_FILENO,
177 "Unsupported key length with %zu digits.\n",
178 digits);
f163b202
SB
179 return -1;
180 }
748df6ee
SB
181 if (*keylen < maxkeylen) {
182 logprintf(STDERR_FILENO,
183 "The provided key is too short. Got %zu bytes, need %zu.\n",
184 *keylen, maxkeylen);
185 return -1;
186 }
f163b202
SB
187
188 return 0;
189}
190
58548ac6
SB
191/*
192 * key_load_key:
193 * Load the raw key data from a file and convert it to a key.
194 * @filename: file holding the raw key data
195 * @keyformat: the format the raw key data are in; may either indicate
196 * binary data or hex string
197 * @key: the buffer for holding the converted key
198 * @keylen: the actual key len of the converted key returned by this
199 * function
200 * @maxkeylen: the max. size of the key; corresponds to the size of the
201 * key buffer
202 */
f163b202
SB
203int
204key_load_key(const char *filename, enum key_format keyformat,
205 unsigned char *key, size_t *keylen, size_t maxkeylen)
206{
207 int ret = -1;
208 int fd;
748df6ee 209 char filebuffer[2 + 256/4 + 1 + 1];
da521f04 210 ssize_t len;
f163b202
SB
211
212 fd = open(filename, O_RDONLY);
213 if (fd < 0) {
cba81569
SB
214 logprintf(STDERR_FILENO, "Unable to open file %s: %s\n",
215 filename, strerror(errno));
f163b202
SB
216 return -1;
217 }
218 len = read(fd, filebuffer, sizeof(filebuffer) - 1);
219 close(fd);
220 if (len < 0) {
cba81569
SB
221 logprintf(STDERR_FILENO, "Unable to read key: %s\n",
222 strerror(errno));
f163b202
SB
223 return -1;
224 }
225 filebuffer[len] = 0;
226
227 switch (keyformat) {
228 case KEY_FORMAT_BINARY:
229 *keylen = len;
da521f04 230 if (maxkeylen < (size_t)len) {
cba81569
SB
231 logprintf(STDERR_FILENO,
232 "Key is larger than buffer (%zu > %zu).\n",
233 len, maxkeylen);
f163b202
SB
234 return -1;
235 }
236 memcpy(key, filebuffer, len);
237 ret = 0;
238 break;
239 case KEY_FORMAT_HEX:
240 if (key_parse_as_hexkey(filebuffer, key, keylen, maxkeylen) < 0)
241 return -1;
242 ret = 0;
243 break;
244 case KEY_FORMAT_UNKNOWN:
245 break;
246 }
247
248 return ret;
249}
250
58548ac6
SB
251/*
252 * key_from_pwdfile:
253 * Read the key from the given password file, convert the password into
254 * a key by applying a SHA512 on the password and use the first bytes
255 * of the hash as the key.
256 * @filename: name of the file holding the password
257 * @key: the buffer for holding the key
58548ac6
SB
258 * @keylen: the actual key len of the converted key returned by this
259 * function
260 * @maxkeylen: the max. size of the key; corresponds to the size of the
261 * key buffer
a39f098f 262 * @kdfid: the kdf to invoke to create the key
58548ac6 263 */
f163b202
SB
264int
265key_from_pwdfile(const char *filename, unsigned char *key, size_t *keylen,
a39f098f 266 size_t maxkeylen, enum kdf_identifier kdfid)
f163b202 267{
a39f098f
SB
268 unsigned char *filebuffer = NULL;
269 size_t filelen;
270 int fd = -1;
0268ef45 271 ssize_t len;
3bbdd7bc 272 unsigned char hashbuf[SHA512_DIGEST_LENGTH];
a39f098f
SB
273 struct stat statbuf;
274 int ret = -1;
275 const unsigned char salt[] = {'s','w','t','p','m'};
f163b202
SB
276
277 if (maxkeylen > sizeof(hashbuf)) {
cba81569
SB
278 logprintf(STDERR_FILENO,
279 "Request keylength is too big (%zu > %zu)\n",
280 maxkeylen, sizeof(hashbuf));
f163b202
SB
281 return -1;
282 }
283
284 fd = open(filename, O_RDONLY);
285 if (fd < 0) {
cba81569
SB
286 logprintf(STDERR_FILENO,
287 "Unable to open file %s : %s\n",
288 filename, strerror(errno));
f163b202
SB
289 return -1;
290 }
a39f098f
SB
291 if (fstat(fd, &statbuf) < 0) {
292 logprintf(STDERR_FILENO,
293 "Unable to stat file %s : %s\n",
294 filename, strerror(errno));
295 goto exit_close;
296 }
297 filelen = statbuf.st_size;
f163b202 298
a39f098f
SB
299 filebuffer = malloc(filelen);
300 if (!filebuffer) {
301 logprintf(STDERR_FILENO,
302 "Could not allocate %zu bytes for filebuffer\n",
303 filebuffer);
304 goto exit_close;
305 }
306
307 len = read(fd, filebuffer, filelen);
f163b202 308 if (len < 0) {
cba81569
SB
309 logprintf(STDERR_FILENO,
310 "Unable to read passphrase: %s\n",
311 strerror(errno));
a39f098f 312 goto exit_close;
f163b202
SB
313 }
314
f163b202 315 *keylen = maxkeylen;
f163b202 316
a39f098f
SB
317 switch (kdfid) {
318 case KDF_IDENTIFIER_SHA512:
748df6ee
SB
319 if (sizeof(hashbuf) < *keylen) {
320 logprintf(STDERR_FILENO,
321 "Requested %zu bytes for key, only got %zu.\n",
322 *keylen, sizeof(hashbuf));
323 goto exit_close;
324 }
a39f098f
SB
325 SHA512(filebuffer, filelen, hashbuf);
326 memcpy(key, hashbuf, *keylen);
327 break;
328 case KDF_IDENTIFIER_PBKDF2:
329 if (PKCS5_PBKDF2_HMAC((const char *)filebuffer, len,
330 salt, sizeof(salt), 1000,
331 EVP_sha512(), *keylen, key) != 1) {
332 logprintf(STDERR_FILENO,
333 "PKCS5_PBKDF2_HMAC with SHA512 failed\n");
334 goto exit_close;
335 }
336 break;
337 case KDF_IDENTIFIER_UNKNOWN:
338 logprintf(STDERR_FILENO,
339 "Unknown KDF\n");
340 goto exit_close;
341 }
342
343 ret = 0;
344
345exit_close:
346 if (fd >= 0)
347 close(fd);
348
349 free(filebuffer);
350
351 return ret;
f163b202 352}