1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2013, 2015 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "data/encrypted-file.h"
20 #include "data/file-handle-def.h"
25 #include "data/file-name.h"
26 #include "libpspp/assertion.h"
27 #include "libpspp/cast.h"
28 #include "libpspp/cmac-aes256.h"
29 #include "libpspp/message.h"
30 #include "libpspp/str.h"
32 #include "gl/minmax.h"
33 #include "gl/rijndael-alg-fst.h"
34 #include "gl/xalloc.h"
37 #define _(msgid) gettext (msgid)
41 const struct file_handle *fh;
45 uint8_t ciphertext[256];
46 uint8_t plaintext[256];
47 unsigned int ofs, n, readable;
49 uint32_t rk[4 * (RIJNDAEL_MAXNR + 1)];
53 static bool decode_password (const char *input, char output[11]);
54 static void fill_buffer (struct encrypted_file *);
56 /* If FILENAME names an encrypted SPSS file, returns 1 and initializes *FP
57 for further use by the caller.
59 If FILENAME can be opened and read, but is not an encrypted SPSS file,
62 If FILENAME cannot be open or read, returns a negative errno value. */
64 encrypted_file_open (struct encrypted_file **fp, const struct file_handle *fh)
66 struct encrypted_file *f;
67 enum { HEADER_SIZE = 36 };
68 char data[HEADER_SIZE + sizeof f->ciphertext];
72 f = xmalloc (sizeof *f);
75 f->file = fn_open (fh, "rb");
78 msg (ME, _("An error occurred while opening `%s': %s."),
79 fh_get_file_name (fh), strerror (errno));
84 n = fread (data, 1, sizeof data, f->file);
85 if (n < HEADER_SIZE + 2 * 16)
87 int error = feof (f->file) ? 0 : errno;
89 msg (ME, _("An error occurred while reading `%s': %s."),
90 fh_get_file_name (fh), strerror (error));
95 if (memcmp (data + 8, "ENCRYPTED", 9))
101 f->n = n - HEADER_SIZE;
102 memcpy (f->ciphertext, data + HEADER_SIZE, f->n);
110 fn_close (fh, f->file);
117 /* Attempts to use PASSWORD, which may be a plaintext or "encrypted" password,
118 to unlock F. Returns true if successful, otherwise false. */
120 encrypted_file_unlock (struct encrypted_file *f, const char *password)
122 char decoded_password[11];
124 return (encrypted_file_unlock__ (f, password)
125 || (decode_password (password, decoded_password)
126 && encrypted_file_unlock__ (f, decoded_password)));
129 /* Attempts to read N bytes of plaintext from F into BUF. Returns the number
130 of bytes successfully read. A return value less than N may indicate end of
131 file or an error; use encrypted_file_close() to distinguish.
133 This function can only be used after encrypted_file_unlock() returns
136 encrypted_file_read (struct encrypted_file *f, void *buf_, size_t n)
143 unsigned int chunk = MIN (n - ofs, f->readable - f->ofs);
146 memcpy (buf + ofs, &f->plaintext[f->ofs], chunk);
161 /* Closes F. Returns 0 if no read errors occurred, otherwise a positive errno
164 encrypted_file_close (struct encrypted_file *f)
166 int error = f->error > 0 ? f->error : 0;
167 if (fclose (f->file) == EOF && !error)
174 #define b(x) (1 << (x))
176 static const uint16_t m0[4][2] = {
177 { b(2), b(2) | b(3) | b(6) | b(7) },
178 { b(3), b(0) | b(1) | b(4) | b(5) },
179 { b(4) | b(7), b(8) | b(9) | b(12) | b(14) },
180 { b(5) | b(6), b(10) | b(11) | b(14) | b(15) },
183 static const uint16_t m1[4][2] = {
184 { b(0) | b(3) | b(12) | b(15), b(0) | b(1) | b(4) | b(5) },
185 { b(1) | b(2) | b(13) | b(14), b(2) | b(3) | b(6) | b(7) },
186 { b(4) | b(7) | b(8) | b(11), b(8) | b(9) | b(12) | b(13) },
187 { b(5) | b(6) | b(9) | b(10), b(10) | b(11) | b(14) | b(15) },
190 static const uint16_t m2[4][2] = {
191 { b(2), b(1) | b(3) | b(9) | b(11) },
192 { b(3), b(0) | b(2) | b(8) | b(10) },
193 { b(4) | b(7), b(4) | b(6) | b(12) | b(14) },
194 { b(5) | b(6), b(5) | b(7) | b(13) | b(15) },
197 static const uint16_t m3[4][2] = {
198 { b(0) | b(3) | b(12) | b(15), b(0) | b(2) | b(8) | b(10) },
199 { b(1) | b(2) | b(13) | b(14), b(1) | b(3) | b(9) | b(11) },
200 { b(4) | b(7) | b(8) | b(11), b(4) | b(6) | b(12) | b(14) },
201 { b(5) | b(6) | b(9) | b(10), b(5) | b(7) | b(13) | b(15) },
205 decode_nibble (const uint16_t table[4][2], int nibble)
209 for (i = 0; i < 4; i++)
210 if (table[i][0] & (1 << nibble))
216 /* Returns true if X has exactly one 1-bit, false otherwise. */
220 return x && (x & (x - 1)) == 0;
223 /* If X has exactly one 1-bit, returns its index, where bit 0 is the LSB.
224 Otherwise, returns 0. */
226 find_1bit (uint16_t x)
233 for (i = 0; i < 16; i++)
240 /* Attempts to decode a pair of encoded password characters A and B into a
241 single byte of the plaintext password. Returns 0 if A and B are not a valid
242 encoded password pair, otherwise a byte of the plaintext password. */
244 decode_password_2bytes (uint8_t a, uint8_t b)
246 int x = find_1bit (decode_nibble (m0, a >> 4) & decode_nibble (m2, b >> 4));
247 int y = find_1bit (decode_nibble (m1, a & 15) & decode_nibble (m3, b & 15));
248 return x < 0 || y < 0 ? 0 : (x << 4) | y;
251 /* Decodes an SPSS so-called "encrypted" password INPUT into OUTPUT.
253 An encoded password is always an even number of bytes long and no longer
254 than 20 bytes. A decoded password is never longer than 10 bytes plus a null
257 Returns true if successful, otherwise false. */
259 decode_password (const char *input, char output[11])
263 len = strlen (input);
264 if (len > 20 || len % 2)
267 for (; *input; input += 2)
269 int c = decode_password_2bytes (input[0], input[1]);
279 /* Check for magic number at beginning of plaintext decrypted from F. */
281 is_good_magic (const struct encrypted_file *f)
284 rijndaelDecrypt (f->rk, f->Nr, CHAR_CAST (const char *, f->ciphertext),
287 const struct substring magic[] = {
288 ss_cstr ("$FL2@(#)"),
289 ss_cstr ("$FL3@(#)"),
290 ss_cstr ("* Encoding"),
291 ss_buffer ("PK\3\4\x14\0\x8", 7)
293 for (size_t i = 0; i < sizeof magic / sizeof *magic; i++)
294 if (ss_equals (ss_buffer (plaintext, magic[i].length), magic[i]))
299 /* Attempts to use plaintext password PASSWORD to unlock F. Returns true if
300 successful, otherwise false. */
302 encrypted_file_unlock__ (struct encrypted_file *f, const char *password)
304 /* NIST SP 800-108 fixed data. */
305 static const uint8_t fixed[] = {
307 0x00, 0x00, 0x00, 0x01,
310 0x35, 0x27, 0x13, 0xcc, 0x53, 0xa7, 0x78, 0x89,
311 0x87, 0x53, 0x22, 0x11, 0xd6, 0x5b, 0x31, 0x58,
312 0xdc, 0xfe, 0x2e, 0x7e, 0x94, 0xda, 0x2f, 0x00,
313 0xcc, 0x15, 0x71, 0x80, 0x0a, 0x6c, 0x63, 0x53,
319 0x38, 0xc3, 0x38, 0xac, 0x22, 0xf3, 0x63, 0x62,
320 0x0e, 0xce, 0x85, 0x3f, 0xb8, 0x07, 0x4c, 0x4e,
321 0x2b, 0x77, 0xc7, 0x21, 0xf5, 0x1a, 0x80, 0x1d,
322 0x67, 0xfb, 0xe1, 0xe1, 0x83, 0x07, 0xd8, 0x0d,
325 0x00, 0x00, 0x01, 0x00,
328 char padded_password[32];
333 /* Truncate password to at most 10 bytes. */
334 password_len = strlen (password);
335 if (password_len > 10)
338 /* padded_password = password padded with zeros to 32 bytes. */
339 memset (padded_password, 0, sizeof padded_password);
340 memcpy (padded_password, password, password_len);
342 /* cmac = CMAC(padded_password, fixed). */
343 cmac_aes256 (CHAR_CAST (const uint8_t *, padded_password),
344 fixed, sizeof fixed, cmac);
346 /* The key is the cmac repeated twice. */
347 memcpy(key, cmac, 16);
348 memcpy(key + 16, cmac, 16);
350 /* Use key to initialize AES. */
351 assert (sizeof key == 32);
352 f->Nr = rijndaelKeySetupDec (f->rk, CHAR_CAST (const char *, key), 256);
354 if (!is_good_magic (f))
361 /* Checks the 16 bytes of PLAINTEXT for PKCS#7 padding bytes. Returns the
362 number of padding bytes (between 1 and 16, inclusive), if well formed,
365 check_padding (const uint8_t *plaintext)
367 uint8_t pad = plaintext[15];
368 if (pad < 1 || pad > 16)
371 for (size_t i = 1; i < pad; i++)
372 if (plaintext[15 - i] != pad)
379 fill_buffer (struct encrypted_file *f)
381 /* Move bytes between f->ciphertext[f->readable] and f->ciphertext[f->n] to
382 the beginning of f->ciphertext.
384 The first time this is called for a given file, it does nothing because
385 f->readable is initially 0. After that, in steady state f->readable is 16
386 less than f->n, so the final 16 bytes of ciphertext become the first 16
387 bytes. This is necessary because we don't know until we hit end-of-file
388 whether padding in the last 16 bytes will require us to discard up to 16
390 memmove (f->ciphertext, f->ciphertext + f->readable, f->n - f->readable);
395 if (f->error) /* or assert(!f->error)? */
398 /* Read new ciphernext, extending f->n, until we've filled up f->ciphertext
399 or until we reach end-of-file or encounter an error.
401 Afterward, f->error indicates what happened. */
402 while (f->n < sizeof f->ciphertext)
404 size_t retval = fread (f->ciphertext + f->n, 1,
405 sizeof f->ciphertext - f->n, f->file);
408 f->error = ferror (f->file) ? errno : EOF;
414 /* Calculate the number of readable bytes. If we're at the end of the file,
415 then we can read everything, otherwise we hold back the last 16 bytes
416 because they might be padding or not. */
419 assert (f->n == sizeof f->ciphertext);
420 f->readable = f->n - 16;
425 /* If we have an incomplete block then trim it off and complain. */
426 unsigned int overhang = f->readable % 16;
430 msg (ME, _("%s: encrypted file corrupted (ends in incomplete %u-byte "
431 "ciphertext block)"),
432 fh_get_file_name (f->fh), overhang);
434 f->readable -= overhang;
437 /* Decrypt all the blocks we have. */
438 for (size_t ofs = 0; ofs < f->readable; ofs += 16)
439 rijndaelDecrypt (f->rk, f->Nr,
440 CHAR_CAST (const char *, f->ciphertext + ofs),
441 CHAR_CAST (char *, f->plaintext + ofs));
443 /* If we're at end of file then check the padding and trim it off. */
446 unsigned int pad = check_padding (&f->plaintext[f->n - 16]);
449 msg (ME, _("%s: encrypted file corrupted (ends with bad padding)"),
450 fh_get_file_name (f->fh));