luksrku/util.c
Johannes Bauer 2cde43d357 Fix issue with TLSv1.3 negotiation
TLSv1.3 behaves differently in how PSK identity/PSK identity hints are
exchanged, at least in regards to OpenSSL. This caused the TLS client to
not send their TLS identity to the server, which rejected the connection
(it expected "luksrku v1"). Couldn't solve it with TLSv1.3, so we're now
simply forcing TLSv1.2.
2019-07-22 21:46:18 +02:00

162 lines
4.1 KiB
C

/*
luksrku - Tool to remotely unlock LUKS disks using TLS.
Copyright (C) 2016-2016 Johannes Bauer
This file is part of luksrku.
luksrku is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; this program is ONLY licensed under
version 3 of the License, later versions are explicitly excluded.
luksrku is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with luksrku; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Johannes Bauer <JohannesBauer@gmx.de>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include "util.h"
#include "log.h"
#include "global.h"
char* query_passphrase(const char *prompt) {
char *passphrase = calloc(1, MAX_PASSPHRASE_LENGTH);
if (!passphrase) {
log_libc(LLVL_ERROR, "malloc(3) of passphrase memory");
return NULL;
}
if (EVP_read_pw_string(passphrase, MAX_PASSPHRASE_LENGTH - 1, prompt, 0) != 0) {
log_openssl(LLVL_ERROR, "EVP_read_pw_string failed");
free(passphrase);
return NULL;
}
return passphrase;
}
void dump_hex_long(FILE *f, const void *vdata, unsigned int length) {
const uint8_t *data = (const uint8_t*)vdata;
for (unsigned int i = 0; i < length; i += 32) {
fprintf(f, "%4x ", i);
for (unsigned int j = i; j < i + 32; j++) {
fprintf(f, "%02x", data[j]);
}
fprintf(f, "\n");
}
}
void dump_hex(FILE *f, const void *vdata, unsigned int length) {
const uint8_t *data = (const uint8_t*)vdata;
for (unsigned int i = 0; i < length; i++) {
fprintf(f, "%02x", data[i]);
}
}
bool is_hex(const char *str, int length) {
for (int i = 0; i < length; i++) {
if (((str[i] >= '0') && (str[i] <= '9')) ||
((str[i] >= 'a') && (str[i] <= 'f')) ||
((str[i] >= 'A') && (str[i] <= 'F'))) {
continue;
}
return false;
}
return true;
}
static int parse_nibble(char nibble) {
if ((nibble >= '0') && (nibble <= '9')) {
return nibble - '0';
} else if ((nibble >= 'a') && (nibble <= 'f')) {
return nibble - 'a' + 10;
} else if ((nibble >= 'A') && (nibble <= 'F')) {
return nibble - 'A' + 10;
}
return -1;
}
static int parse_hexchar(const char *str) {
int high = parse_nibble(str[0]);
int low = parse_nibble(str[1]);
if ((high == -1) || (low == -1)) {
return -1;
}
return (high << 4) | low;
}
int parse_hexstr(const char *hexstr, uint8_t *data, int maxlen) {
int length = 0;
for (int i = 0; i < maxlen; i++) {
if (*hexstr == 0) {
break;
}
int next_char = parse_hexchar(hexstr);
if (next_char == -1) {
return -1;
}
data[length++] = next_char;
hexstr += 2;
}
return length;
}
bool is_valid_uuid(const char *ascii_uuid) {
// e43fff25-5a01-40e8-b437-80b9d56c19ff
// '-' at offsets 8 13 18 23
if (!ascii_uuid) {
return false;
}
if (strlen(ascii_uuid) != 36) {
return false;
}
if ((ascii_uuid[8] != '-') || (ascii_uuid[13] != '-') || (ascii_uuid[18] != '-') || (ascii_uuid[23] != '-')) {
return false;
}
if (!is_hex(ascii_uuid + 0, 8) || !is_hex(ascii_uuid + 9, 4) || !is_hex(ascii_uuid + 14, 4) || !is_hex(ascii_uuid + 19, 4) || !is_hex(ascii_uuid + 24, 12)) {
return false;
}
return true;
}
bool parse_uuid(uint8_t *uuid, const char *ascii_uuid) {
if (!is_valid_uuid(ascii_uuid)) {
return false;
}
parse_hexstr(ascii_uuid + 0, uuid + 0, 4);
parse_hexstr(ascii_uuid + 9, uuid + 4, 2);
parse_hexstr(ascii_uuid + 14, uuid + 6, 2);
parse_hexstr(ascii_uuid + 19, uuid + 8, 2);
parse_hexstr(ascii_uuid + 24, uuid + 10, 6);
return true;
}
void sprintf_uuid(char *buffer, const uint8_t *uuid) {
buffer[0] = 0;
for (int i = 0; i < 16; i++) {
if ((i == 4) || (i == 6) || (i == 8) || (i == 10)) {
buffer += sprintf(buffer, "-");
}
buffer += sprintf(buffer, "%02x", uuid[i]);
}
}
void dump_uuid(FILE *f, const uint8_t *uuid) {
char ascii_uuid[40];
sprintf_uuid(ascii_uuid, uuid);
fprintf(f, "%s", ascii_uuid);
}