aboutsummaryrefslogtreecommitdiff
path: root/src/crypto.cc
blob: 8be90fdbac6ecb64caec0a7cda91a3d623760ee6 (plain) (blame)
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include "login.hh"

#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>

static void DumpOpenSSLErrors(const char *Where, const char *What){
	LOG_ERR("OpenSSL error(s) while executing %s at %s:", What, Where);
	ERR_print_errors_cb(
		[](const char *str, usize len, void *u) -> int {
			// NOTE(fusion): These error strings already have trailing newlines,
			// for whatever reason.
			if(len > 0 && str[len - 1] == '\n'){
				len -= 1;
			}

			if(len > 0){
				LOG_ERR("> %*s", (int)len, str);
			}

			return 1;
		}, NULL);
}

RSAKey *RSALoadPEM(const char *FileName){
	FILE *File = fopen(FileName, "rb");
	if(File == NULL){
		LOG_ERR("Failed to open \"%s\"", FileName);
		return NULL;
	}

	RSA *Key = PEM_read_RSAPrivateKey(File, NULL, NULL, NULL);
	fclose(File);
	if(Key == NULL){
		LOG_ERR("Failed to read key from \"%s\"", FileName);
		DumpOpenSSLErrors("RSALoadPem", "PEM_read_PrivateKey");
	}

	return (RSAKey*)Key;
}

void RSAFree(RSAKey *Key){
	RSA_free((RSA*)Key);
}

bool RSADecrypt(RSAKey *Key, uint8 *Data, int Size){
	ASSERT(Data != NULL && Size > 0);
	if(Key == NULL){
		LOG_ERR("Key not initialized");
		return false;
	}

	if(Size != RSA_size((RSA*)Key)){
		LOG_ERR("Invalid data size %d (expected %d)", Size, RSA_size((RSA*)Key));
		return false;
	}

	if(RSA_private_decrypt(Size, Data, Data, (RSA*)Key, RSA_NO_PADDING) == -1){
		DumpOpenSSLErrors("RSADecrypt", "RSA_private_decrypt");
		return false;
	}

	return true;
}

void XTEAEncrypt(const uint32 *Key, uint8 *Data, int Size){
	ASSERT(Key != NULL);
	while(Size >= 8){
		uint32 Sum = 0x00000000UL;
		uint32 Delta = 0x9E3779B9UL;
		uint32 V0 = BufferRead32LE(&Data[0]);
		uint32 V1 = BufferRead32LE(&Data[4]);
		for(int i = 0; i < 32; i += 1){
			V0 += (((V1 << 4) ^ (V1 >> 5)) + V1) ^ (Sum + Key[Sum & 3]);
			Sum += Delta;
			V1 += (((V0 << 4) ^ (V0 >> 5)) + V0) ^ (Sum + Key[(Sum >> 11) & 3]);
		}
		BufferWrite32LE(&Data[0], V0);
		BufferWrite32LE(&Data[4], V1);
		Data += 8;
		Size -= 8;
	}
}

void XTEADecrypt(const uint32 *Key, uint8 *Data, int Size){
	ASSERT(Key != NULL);
	while(Size >= 8){
		uint32 Sum = 0xC6EF3720UL;
		uint32 Delta = 0x9E3779B9UL;
		uint32 V0 = BufferRead32LE(&Data[0]);
		uint32 V1 = BufferRead32LE(&Data[4]);
		for(int i = 0; i < 32; i += 1){
			V1 -= (((V0 << 4) ^ (V0 >> 5)) + V0) ^ (Sum + Key[(Sum >> 11) & 3]);
			Sum -= Delta;
			V0 -= (((V1 << 4) ^ (V1 >> 5)) + V1) ^ (Sum + Key[Sum & 3]);
		}
		BufferWrite32LE(&Data[0], V0);
		BufferWrite32LE(&Data[4], V1);
		Data += 8;
		Size -= 8;
	}
}