From dfcc11fa52622680fe427c19dfe0528563a0691e Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Sat, 6 Jun 2020 15:42:46 +0200 Subject: [PATCH] Implement sign and verify in crypto. --- core/crypto/crypto.cpp | 2 ++ core/crypto/crypto.h | 4 +++ modules/mbedtls/crypto_mbedtls.cpp | 45 ++++++++++++++++++++++++++++++ modules/mbedtls/crypto_mbedtls.h | 3 ++ 4 files changed, 54 insertions(+) diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp index a6b1fa9f034..f1d13b06337 100644 --- a/core/crypto/crypto.cpp +++ b/core/crypto/crypto.cpp @@ -86,6 +86,8 @@ void Crypto::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_random_bytes", "size"), &Crypto::generate_random_bytes); ClassDB::bind_method(D_METHOD("generate_rsa", "size"), &Crypto::generate_rsa); ClassDB::bind_method(D_METHOD("generate_self_signed_certificate", "key", "issuer_name", "not_before", "not_after"), &Crypto::generate_self_signed_certificate, DEFVAL("CN=myserver,O=myorganisation,C=IT"), DEFVAL("20140101000000"), DEFVAL("20340101000000")); + ClassDB::bind_method(D_METHOD("sign", "hash_type", "hash", "key"), &Crypto::sign); + ClassDB::bind_method(D_METHOD("verify", "hash_type", "hash", "signature", "key"), &Crypto::verify); } /// Resource loader/saver diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h index c1bc2024bbf..472ad8ab9d6 100644 --- a/core/crypto/crypto.h +++ b/core/crypto/crypto.h @@ -31,6 +31,7 @@ #ifndef CRYPTO_H #define CRYPTO_H +#include "core/crypto/hashing_context.h" #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" #include "core/reference.h" @@ -82,6 +83,9 @@ public: virtual Ref generate_rsa(int p_bytes) = 0; virtual Ref generate_self_signed_certificate(Ref p_key, String p_issuer_name, String p_not_before, String p_not_after) = 0; + virtual Vector sign(HashingContext::HashType p_hash_type, Vector p_hash, Ref p_key) = 0; + virtual bool verify(HashingContext::HashType p_hash_type, Vector p_hash, Vector p_signature, Ref p_key) = 0; + Crypto() {} }; diff --git a/modules/mbedtls/crypto_mbedtls.cpp b/modules/mbedtls/crypto_mbedtls.cpp index 0d1a1f0138a..a432a88fd10 100644 --- a/modules/mbedtls/crypto_mbedtls.cpp +++ b/modules/mbedtls/crypto_mbedtls.cpp @@ -317,3 +317,48 @@ PackedByteArray CryptoMbedTLS::generate_random_bytes(int p_bytes) { mbedtls_ctr_drbg_random(&ctr_drbg, out.ptrw(), p_bytes); return out; } + +mbedtls_md_type_t CryptoMbedTLS::_md_type_from_hashtype(HashingContext::HashType p_hash_type, int &r_size) { + switch (p_hash_type) { + case HashingContext::HASH_MD5: + r_size = 16; + return MBEDTLS_MD_MD5; + case HashingContext::HASH_SHA1: + r_size = 20; + return MBEDTLS_MD_SHA1; + case HashingContext::HASH_SHA256: + r_size = 32; + return MBEDTLS_MD_SHA256; + default: + r_size = 0; + ERR_FAIL_V_MSG(MBEDTLS_MD_NONE, "Invalid hash type."); + } +} + +Vector CryptoMbedTLS::sign(HashingContext::HashType p_hash_type, Vector p_hash, Ref p_key) { + int size; + mbedtls_md_type_t type = _md_type_from_hashtype(p_hash_type, size); + ERR_FAIL_COND_V_MSG(type == MBEDTLS_MD_NONE, Vector(), "Invalid hash type."); + ERR_FAIL_COND_V_MSG(p_hash.size() != size, Vector(), "Invalid hash provided. Size must be " + itos(size)); + Ref key = static_cast>(p_key); + ERR_FAIL_COND_V_MSG(!key.is_valid(), Vector(), "Invalid key provided."); + ERR_FAIL_COND_V_MSG(key->is_public_only(), Vector(), "Invalid key provided. Cannot sign with public_only keys."); + size_t sig_size = 0; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + Vector out; + int ret = mbedtls_pk_sign(&(key->pkey), type, p_hash.ptr(), size, buf, &sig_size, mbedtls_ctr_drbg_random, &ctr_drbg); + ERR_FAIL_COND_V_MSG(ret, out, "Error while signing: " + itos(ret)); + out.resize(sig_size); + copymem(out.ptrw(), buf, sig_size); + return out; +} + +bool CryptoMbedTLS::verify(HashingContext::HashType p_hash_type, Vector p_hash, Vector p_signature, Ref p_key) { + int size; + mbedtls_md_type_t type = _md_type_from_hashtype(p_hash_type, size); + ERR_FAIL_COND_V_MSG(type == MBEDTLS_MD_NONE, false, "Invalid hash type."); + ERR_FAIL_COND_V_MSG(p_hash.size() != size, false, "Invalid hash provided. Size must be " + itos(size)); + Ref key = static_cast>(p_key); + ERR_FAIL_COND_V_MSG(!key.is_valid(), false, "Invalid key provided."); + return mbedtls_pk_verify(&(key->pkey), type, p_hash.ptr(), size, p_signature.ptr(), p_signature.size()) == 0; +} diff --git a/modules/mbedtls/crypto_mbedtls.h b/modules/mbedtls/crypto_mbedtls.h index b3dd0e2a392..c22ddcdb422 100644 --- a/modules/mbedtls/crypto_mbedtls.h +++ b/modules/mbedtls/crypto_mbedtls.h @@ -106,6 +106,7 @@ private: mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; static X509CertificateMbedTLS *default_certs; + mbedtls_md_type_t _md_type_from_hashtype(HashingContext::HashType p_hash_type, int &r_size); public: static Crypto *create(); @@ -117,6 +118,8 @@ public: virtual PackedByteArray generate_random_bytes(int p_bytes); virtual Ref generate_rsa(int p_bytes); virtual Ref generate_self_signed_certificate(Ref p_key, String p_issuer_name, String p_not_before, String p_not_after); + virtual Vector sign(HashingContext::HashType p_hash_type, Vector p_hash, Ref p_key); + virtual bool verify(HashingContext::HashType p_hash_type, Vector p_hash, Vector p_signature, Ref p_key); CryptoMbedTLS(); ~CryptoMbedTLS();