mirror of https://github.com/ericonr/purr-c.git
Split encrypt.c and fix use-after-free.
UAF from genalloc and stralloc frees. Also remove randomization of IV, not used in bsd.ac.
This commit is contained in:
parent
f3069bb932
commit
dd30aa72a8
|
@ -0,0 +1,97 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "purr.h"
|
||||
|
||||
int encrypt_FILE(FILE **filep, uint8_t **keyp, uint8_t **ivp, char **tempp)
|
||||
{
|
||||
FILE *input = *filep;
|
||||
uint8_t *key = *keyp;
|
||||
uint8_t *iv = *ivp;
|
||||
char *temp = *tempp;
|
||||
|
||||
if (input == stdin) {
|
||||
fputs("currently can't encrypt stdin!\n", stderr);
|
||||
return -1;
|
||||
}
|
||||
struct stat s;
|
||||
int errs = fstat(fileno(input), &s);
|
||||
if (errs != 0) {
|
||||
perror("couldn't stat output!");
|
||||
return -1;
|
||||
}
|
||||
off_t file_size = s.st_size;
|
||||
ssize_t blocks = file_size / br_aes_big_BLOCK_SIZE;
|
||||
if (blocks * br_aes_big_BLOCK_SIZE < file_size) blocks++;
|
||||
file_size = blocks * br_aes_big_BLOCK_SIZE;
|
||||
|
||||
key = calloc(KEY_LEN, 1);
|
||||
iv = calloc(IV_LEN, 1);
|
||||
if (key == NULL || iv == NULL) {
|
||||
perror("allocation failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t err = getrandom(key, KEY_LEN, 0);
|
||||
if (err != KEY_LEN) {
|
||||
fputs("getrandom() error!\n", stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef NO_RANDOMIZE_IV
|
||||
err = getrandom(iv, IV_LEN, 0);
|
||||
if (err != IV_LEN) {
|
||||
fputs("getrandom() error!\n", stderr);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
temp = strdup("/tmp/purrito.XXXXXX");
|
||||
int tfd = mkstemp(temp);
|
||||
if (tfd < 0) {
|
||||
perror("couldn't create temp file");
|
||||
return -1;
|
||||
}
|
||||
int errfa = posix_fallocate(tfd, 0, file_size);
|
||||
if (errfa) {
|
||||
perror("error while fallocating");
|
||||
return -1;
|
||||
}
|
||||
uint8_t *temp_map =
|
||||
mmap(NULL, file_size, PROT_WRITE, MAP_SHARED, tfd, 0);
|
||||
if (temp_map == NULL) {
|
||||
perror("mmap failure");
|
||||
return -1;
|
||||
}
|
||||
close(tfd);
|
||||
|
||||
for (ssize_t i = 0; i < blocks; i++) {
|
||||
// zero padding for the last round
|
||||
uint8_t tmp[br_aes_big_BLOCK_SIZE] = { 0 };
|
||||
fread(tmp, 1, br_aes_big_BLOCK_SIZE, input);
|
||||
memcpy(temp_map + i * br_aes_big_BLOCK_SIZE, tmp, br_aes_big_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
br_aes_big_cbcenc_keys br = { 0 };
|
||||
br_aes_big_cbcenc_init(&br, key, KEY_LEN);
|
||||
br_aes_big_cbcenc_run(&br, iv, temp_map, file_size);
|
||||
|
||||
fclose(input);
|
||||
munmap(temp_map, file_size);
|
||||
|
||||
input = fopen(temp, "r");
|
||||
if (input == NULL) {
|
||||
perror("couldn't read temp file");
|
||||
return -1;
|
||||
}
|
||||
fstat(fileno(input), &s);
|
||||
fprintf(stderr, "output file size: %lu\n", s.st_size);
|
||||
|
||||
return 0;
|
||||
}
|
2
makefile
2
makefile
|
@ -2,7 +2,7 @@ CFLAGS = -O2 -g -pipe -Wall -Wextra
|
|||
LDLIBS = -lbearssl -lsbearssl -lskarnet
|
||||
|
||||
FINAL = purr
|
||||
OBJS = purr.o socket.o urls.o files.o comm.o formats.o
|
||||
OBJS = purr.o socket.o urls.o files.o comm.o formats.o encrypt.o
|
||||
|
||||
all: $(FINAL)
|
||||
|
||||
|
|
83
purr.c
83
purr.c
|
@ -1,15 +1,9 @@
|
|||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <bearssl.h>
|
||||
#include <s6-networking/sbearssl.h>
|
||||
|
@ -218,8 +212,6 @@ int main (int argc, char **argv)
|
|||
{
|
||||
size_t i = num_ta;
|
||||
while(i--) sbearssl_ta_to(genalloc_s(sbearssl_ta, &ta_list) + i, btas + i, ta_content.s);
|
||||
genalloc_free(sbearssl_ta, &ta_list);
|
||||
stralloc_free(&ta_content);
|
||||
}
|
||||
|
||||
br_ssl_client_init_full(&sc, &xc, btas, num_ta);
|
||||
|
@ -231,79 +223,8 @@ int main (int argc, char **argv)
|
|||
uint8_t *iv = NULL;
|
||||
char *temp = NULL;
|
||||
if (send && encrypt) {
|
||||
if (input == stdin) {
|
||||
fputs("currently can't encrypt stdin!\n", stderr);
|
||||
goto early_out;
|
||||
}
|
||||
struct stat s;
|
||||
int errs = fstat(fileno(input), &s);
|
||||
if (errs != 0) {
|
||||
perror("couldn't stat output!");
|
||||
goto early_out;
|
||||
}
|
||||
off_t file_size = s.st_size;
|
||||
ssize_t blocks = file_size / br_aes_big_BLOCK_SIZE;
|
||||
if (blocks * br_aes_big_BLOCK_SIZE < file_size) blocks++;
|
||||
file_size = blocks * br_aes_big_BLOCK_SIZE;
|
||||
|
||||
key = calloc(KEY_LEN, 1);
|
||||
iv = calloc(IV_LEN, 1);
|
||||
if (key == NULL || iv == NULL) {
|
||||
perror("allocation failure");
|
||||
goto early_out;
|
||||
}
|
||||
|
||||
ssize_t err = getrandom(key, KEY_LEN, 0);
|
||||
if (err != KEY_LEN) {
|
||||
fputs("getrandom() error!\n", stderr);
|
||||
goto early_out;
|
||||
}
|
||||
err = getrandom(iv, IV_LEN, 0);
|
||||
if (err != IV_LEN) {
|
||||
fputs("getrandom() error!\n", stderr);
|
||||
goto early_out;
|
||||
}
|
||||
|
||||
temp = strdup("/tmp/purrito.XXXXXX");
|
||||
int tfd = mkstemp(temp);
|
||||
if (tfd < 0) {
|
||||
perror("couldn't create temp file");
|
||||
goto early_out;
|
||||
}
|
||||
int errfa = posix_fallocate(tfd, 0, file_size);
|
||||
if (errfa) {
|
||||
perror("error while fallocating");
|
||||
goto early_out;
|
||||
}
|
||||
uint8_t *temp_map =
|
||||
mmap(NULL, file_size, PROT_WRITE, MAP_SHARED, tfd, 0);
|
||||
if (temp_map == NULL) {
|
||||
perror("mmap failure");
|
||||
goto early_out;
|
||||
}
|
||||
close(tfd);
|
||||
|
||||
for (ssize_t i = 0; i < blocks; i++) {
|
||||
// zero padding for the last round
|
||||
uint8_t tmp[br_aes_big_BLOCK_SIZE] = { 0 };
|
||||
fread(tmp, 1, br_aes_big_BLOCK_SIZE, output);
|
||||
memcpy(temp_map + i * br_aes_big_BLOCK_SIZE, tmp, br_aes_big_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
br_aes_big_cbcenc_keys br = { 0 };
|
||||
br_aes_big_cbcenc_init(&br, key, KEY_LEN);
|
||||
br_aes_big_cbcenc_run(&br, iv, temp_map, file_size);
|
||||
|
||||
fclose(output);
|
||||
munmap(temp_map, file_size);
|
||||
|
||||
output = fopen(temp, "r");
|
||||
if (output == NULL) {
|
||||
perror("couldn't read temp file");
|
||||
goto early_out;
|
||||
}
|
||||
fstat(fileno(output), &s);
|
||||
fprintf(stderr, "output file size: %lu\n", s.st_size);
|
||||
// requires error checking
|
||||
encrypt_FILE(&input, &key, &iv, &temp);
|
||||
}
|
||||
|
||||
int socket = host_connect(link, port, debug);
|
||||
|
|
5
purr.h
5
purr.h
|
@ -15,6 +15,8 @@
|
|||
#define KEY_LEN 32
|
||||
#define IV_LEN br_aes_big_BLOCK_SIZE
|
||||
|
||||
#define NO_RANDOMIZE_IV
|
||||
|
||||
struct strip_header_info {
|
||||
FILE *output;
|
||||
char *header;
|
||||
|
@ -59,4 +61,7 @@ int send_and_receive(struct connection_information *);
|
|||
/* formats.c */
|
||||
void print_hex(uint8_t *, int);
|
||||
|
||||
/* encrypt.c */
|
||||
int encrypt_FILE(FILE **, uint8_t **, uint8_t **, char **);
|
||||
|
||||
#endif // __PURR_H_
|
||||
|
|
Loading…
Reference in New Issue