mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-22 01:19:52 +03:00
Mayaqua: Add new cryptographic functions for X25519/X448 keys management
The files are created in a new folder to keep the source tree tidier. Please note that only X25519/X448 keys are supported due to an OpenSSL limitation: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_new.html We have functions that handle AES keys in Encrypt.c/.h. Ideally we should move them into the new files.
This commit is contained in:
parent
4328e6e5ab
commit
9dbbfcd388
@ -1,5 +1,5 @@
|
||||
file(GLOB SOURCES_MAYAQUA "*.c")
|
||||
file(GLOB HEADERS_MAYAQUA "*.h")
|
||||
file(GLOB SOURCES_MAYAQUA "*.c" "Crypto/*.c")
|
||||
file(GLOB HEADERS_MAYAQUA "*.h" "Crypto/*.h")
|
||||
|
||||
if(WIN32)
|
||||
add_library(mayaqua STATIC ${SOURCES_MAYAQUA} ${HEADERS_MAYAQUA})
|
||||
|
221
src/Mayaqua/Crypto/Key.c
Normal file
221
src/Mayaqua/Crypto/Key.c
Normal file
@ -0,0 +1,221 @@
|
||||
#include "Key.h"
|
||||
|
||||
#include "Encrypt.h"
|
||||
#include "Memory.h"
|
||||
#include "Str.h"
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
static int CryptoKeyTypeToID(const CRYPTO_KEY_TYPE type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case KEY_UNKNOWN:
|
||||
break;
|
||||
case KEY_X25519:
|
||||
return EVP_PKEY_X25519;
|
||||
case KEY_X448:
|
||||
return EVP_PKEY_X448;
|
||||
default:
|
||||
Debug("CryptoKeyTypeToID(): Unhandled type %u!\n", type);
|
||||
}
|
||||
|
||||
return EVP_PKEY_NONE;
|
||||
}
|
||||
|
||||
UINT CryptoKeyTypeSize(const CRYPTO_KEY_TYPE type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case KEY_UNKNOWN:
|
||||
break;
|
||||
case KEY_X25519:
|
||||
return KEY_X25519_SIZE;
|
||||
case KEY_X448:
|
||||
return KEY_X448_SIZE;
|
||||
default:
|
||||
Debug("CryptoKeyTypeSize(): Unhandled type %u!\n", type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CRYPTO_KEY_RAW *CryptoKeyRawNew(const void *data, const UINT size, const CRYPTO_KEY_TYPE type)
|
||||
{
|
||||
if (size == 0 || size != CryptoKeyTypeSize(type))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CRYPTO_KEY_RAW *key = Malloc(sizeof(CRYPTO_KEY_RAW));
|
||||
key->Data = MallocEx(size, true);
|
||||
key->Size = size;
|
||||
key->Type = type;
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
Rand(key->Data, key->Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
Copy(key->Data, data, key->Size);
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
void CryptoKeyRawFree(CRYPTO_KEY_RAW *key)
|
||||
{
|
||||
if (key == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Free(key->Data);
|
||||
Free(key);
|
||||
}
|
||||
|
||||
CRYPTO_KEY_RAW *CryptoKeyRawPublic(const CRYPTO_KEY_RAW *private)
|
||||
{
|
||||
if (private == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *opaque = CryptoKeyRawToOpaque(private, false);
|
||||
if (opaque == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CRYPTO_KEY_RAW *public = NULL;
|
||||
CryptoKeyOpaqueToRaw(opaque, NULL, &public);
|
||||
CryptoKeyOpaqueFree(opaque);
|
||||
|
||||
return public;
|
||||
}
|
||||
|
||||
void *CryptoKeyRawToOpaque(const CRYPTO_KEY_RAW *key, const bool public)
|
||||
{
|
||||
if (key == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const int id = CryptoKeyTypeToID(key->Type);
|
||||
|
||||
if (public)
|
||||
{
|
||||
return EVP_PKEY_new_raw_public_key(id, NULL, key->Data, key->Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return EVP_PKEY_new_raw_private_key(id, NULL, key->Data, key->Size);
|
||||
}
|
||||
}
|
||||
|
||||
void *CryptoKeyOpaqueNew(const CRYPTO_KEY_TYPE type)
|
||||
{
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(CryptoKeyTypeToID(type), NULL);
|
||||
if (ctx == NULL)
|
||||
{
|
||||
Debug("CryptoKeyOpaqueNew(): EVP_PKEY_CTX_new_id() returned NULL!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
EVP_PKEY *key = NULL;
|
||||
|
||||
int ret = EVP_PKEY_keygen_init(ctx);
|
||||
if (ret != 1)
|
||||
{
|
||||
Debug("CryptoKeyOpaqueNew(): EVP_PKEY_keygen_init() returned %d!\n", ret);
|
||||
goto FINAL;
|
||||
}
|
||||
|
||||
ret = EVP_PKEY_keygen(ctx, &key);
|
||||
if (ret != 1)
|
||||
{
|
||||
Debug("CryptoKeyOpaqueNew(): EVP_PKEY_keygen() returned %d!\n", ret);
|
||||
}
|
||||
FINAL:
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
return key;
|
||||
}
|
||||
|
||||
void CryptoKeyOpaqueFree(void *key)
|
||||
{
|
||||
if (key != NULL)
|
||||
{
|
||||
EVP_PKEY_free(key);
|
||||
}
|
||||
}
|
||||
|
||||
bool CryptoKeyOpaqueToRaw(const void *opaque, CRYPTO_KEY_RAW **private, CRYPTO_KEY_RAW **public)
|
||||
{
|
||||
if (opaque == NULL || (private == NULL && public == NULL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CRYPTO_KEY_TYPE type;
|
||||
|
||||
switch (EVP_PKEY_id(opaque))
|
||||
{
|
||||
case EVP_PKEY_X25519:
|
||||
type = KEY_X25519;
|
||||
break;
|
||||
case EVP_PKEY_X448:
|
||||
type = KEY_X448;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (private != NULL)
|
||||
{
|
||||
size_t size;
|
||||
int ret = EVP_PKEY_get_raw_private_key(opaque, NULL, &size);
|
||||
if (ret != 1)
|
||||
{
|
||||
Debug("CryptoKeyOpaqueToRaw(): #1 EVP_PKEY_get_raw_private_key() returned %d!\n", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
CRYPTO_KEY_RAW *key = CryptoKeyRawNew(NULL, size, type);
|
||||
|
||||
ret = EVP_PKEY_get_raw_private_key(opaque, key->Data, &size);
|
||||
if (ret != 1)
|
||||
{
|
||||
Debug("CryptoKeyOpaqueToRaw(): #2 EVP_PKEY_get_raw_private_key() returned %d!\n", ret);
|
||||
CryptoKeyRawFree(key);
|
||||
return false;
|
||||
}
|
||||
|
||||
*private = key;
|
||||
}
|
||||
|
||||
if (public != NULL)
|
||||
{
|
||||
size_t size;
|
||||
int ret = EVP_PKEY_get_raw_public_key(opaque, NULL, &size);
|
||||
if (ret != 1)
|
||||
{
|
||||
Debug("CryptoKeyOpaqueToRaw(): #1 EVP_PKEY_get_raw_public_key() returned %d!\n", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
CRYPTO_KEY_RAW *key = CryptoKeyRawNew(NULL, size, type);
|
||||
|
||||
ret = EVP_PKEY_get_raw_public_key(opaque, key->Data, &size);
|
||||
if (ret != 1)
|
||||
{
|
||||
Debug("CryptoKeyOpaqueToRaw(): #2 EVP_PKEY_get_raw_public_key() returned %d!\n", ret);
|
||||
CryptoKeyRawFree(key);
|
||||
return false;
|
||||
}
|
||||
|
||||
*public = key;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
36
src/Mayaqua/Crypto/Key.h
Normal file
36
src/Mayaqua/Crypto/Key.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef CRYPTO_KEY_H
|
||||
#define CRYPTO_KEY_H
|
||||
|
||||
#include "MayaType.h"
|
||||
|
||||
#define KEY_X25519_SIZE 32
|
||||
#define KEY_X448_SIZE 56
|
||||
|
||||
enum CRYPTO_KEY_TYPE
|
||||
{
|
||||
KEY_UNKNOWN,
|
||||
KEY_X25519,
|
||||
KEY_X448
|
||||
};
|
||||
|
||||
struct CRYPTO_KEY_RAW
|
||||
{
|
||||
BYTE *Data;
|
||||
UINT Size;
|
||||
CRYPTO_KEY_TYPE Type;
|
||||
};
|
||||
|
||||
UINT CryptoKeyTypeSize(const CRYPTO_KEY_TYPE type);
|
||||
|
||||
CRYPTO_KEY_RAW *CryptoKeyRawNew(const void *data, const UINT size, const CRYPTO_KEY_TYPE type);
|
||||
void CryptoKeyRawFree(CRYPTO_KEY_RAW *key);
|
||||
|
||||
CRYPTO_KEY_RAW *CryptoKeyRawPublic(const CRYPTO_KEY_RAW *private);
|
||||
void *CryptoKeyRawToOpaque(const CRYPTO_KEY_RAW *key, const bool public);
|
||||
|
||||
void *CryptoKeyOpaqueNew(const CRYPTO_KEY_TYPE type);
|
||||
void CryptoKeyOpaqueFree(void *key);
|
||||
|
||||
bool CryptoKeyOpaqueToRaw(const void *opaque, CRYPTO_KEY_RAW **private, CRYPTO_KEY_RAW **public);
|
||||
|
||||
#endif
|
8
src/Mayaqua/Crypto/Types.h
Normal file
8
src/Mayaqua/Crypto/Types.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef CRYPTO_TYPES_H
|
||||
#define CRYPTO_TYPES_H
|
||||
|
||||
typedef enum CRYPTO_KEY_TYPE CRYPTO_KEY_TYPE;
|
||||
|
||||
typedef struct CRYPTO_KEY_RAW CRYPTO_KEY_RAW;
|
||||
|
||||
#endif
|
@ -466,4 +466,6 @@ typedef struct DNS_CACHE_REVERSE DNS_CACHE_REVERSE;
|
||||
typedef struct DNS_RESOLVER DNS_RESOLVER;
|
||||
typedef struct DNS_RESOLVER_REVERSE DNS_RESOLVER_REVERSE;
|
||||
|
||||
#include "Crypto/Types.h"
|
||||
|
||||
#endif // MAYATYPE_H
|
||||
|
Loading…
Reference in New Issue
Block a user