aboutsummaryrefslogtreecommitdiff
path: root/src/crypto.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto.cc')
-rw-r--r--src/crypto.cc102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/crypto.cc b/src/crypto.cc
new file mode 100644
index 0000000..8be90fd
--- /dev/null
+++ b/src/crypto.cc
@@ -0,0 +1,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;
+ }
+}