mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-06 01:30:40 +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 SOURCES_MAYAQUA "*.c" "Crypto/*.c")
|
||||||
file(GLOB HEADERS_MAYAQUA "*.h")
|
file(GLOB HEADERS_MAYAQUA "*.h" "Crypto/*.h")
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_library(mayaqua STATIC ${SOURCES_MAYAQUA} ${HEADERS_MAYAQUA})
|
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 DNS_RESOLVER;
|
||||||
typedef struct DNS_RESOLVER_REVERSE DNS_RESOLVER_REVERSE;
|
typedef struct DNS_RESOLVER_REVERSE DNS_RESOLVER_REVERSE;
|
||||||
|
|
||||||
|
#include "Crypto/Types.h"
|
||||||
|
|
||||||
#endif // MAYATYPE_H
|
#endif // MAYATYPE_H
|
||||||
|
Loading…
Reference in New Issue
Block a user