1#include "mbedtls_wrapper.hpp"
2// otherwise we have different definitions for mbedtls_pk_context / mbedtls_sha256_context
3#define MBEDTLS_ALLOW_PRIVATE_ACCESS
4
5#include "mbedtls/sha256.h"
6#include "mbedtls/pk.h"
7
8#include <stdexcept>
9
10using namespace std;
11using namespace duckdb_mbedtls;
12
13/*
14# Command line tricks to help here
15# Create a new key
16openssl genrsa -out private.pem 2048
17
18# Export public key
19openssl rsa -in private.pem -outform PEM -pubout -out public.pem
20
21# Calculate digest and write to 'hash' file on command line
22openssl dgst -binary -sha256 dummy > hash
23
24# Calculate signature from hash
25openssl pkeyutl -sign -in hash -inkey private.pem -pkeyopt digest:sha256 -out dummy.sign
26*/
27
28
29void MbedTlsWrapper::ComputeSha256Hash(const char* in, size_t in_len, char* out) {
30
31 mbedtls_sha256_context sha_context;
32 mbedtls_sha256_init(ctx: &sha_context);
33 if(mbedtls_sha256_starts(ctx: &sha_context, is224: false) || mbedtls_sha256_update(ctx: &sha_context, input: (const unsigned char*) in, ilen: in_len) || mbedtls_sha256_finish(ctx: &sha_context, output: (unsigned char*)out)) {
34 throw runtime_error("SHA256 Error");
35 }
36 mbedtls_sha256_free(ctx: &sha_context);
37}
38
39string MbedTlsWrapper::ComputeSha256Hash(const string& file_content) {
40 string hash;
41 hash.resize(n: MbedTlsWrapper::SHA256_HASH_BYTES);
42 ComputeSha256Hash(in: file_content.data(), in_len: file_content.size(), out: (char*)hash.data());
43 return hash;
44}
45
46bool MbedTlsWrapper::IsValidSha256Signature(const std::string &pubkey, const std::string &signature, const std::string &sha256_hash) {
47
48 if (signature.size() != 256 || sha256_hash.size() != 32) {
49 throw std::runtime_error("Invalid input lengths, expected signature length 256, got " + to_string(val: signature.size()) + ", hash length 32, got " + to_string(val: sha256_hash.size()));
50 }
51
52 mbedtls_pk_context pk_context;
53 mbedtls_pk_init(ctx: &pk_context);
54
55 if (mbedtls_pk_parse_public_key( ctx: &pk_context,
56 key: (const unsigned char*) pubkey.c_str(),keylen: pubkey.size() + 1 )) {
57 throw runtime_error("RSA public key import error");
58 }
59
60 // actually verify
61 bool valid = mbedtls_pk_verify(ctx: &pk_context, md_alg: MBEDTLS_MD_SHA256,
62 hash: (const unsigned char*) sha256_hash.data(), hash_len: sha256_hash.size(),
63 sig: (const unsigned char*)signature.data(), sig_len: signature.length()) == 0;
64
65 mbedtls_pk_free(ctx: &pk_context);
66 return valid;
67}
68
69// used in s3fs
70void MbedTlsWrapper::Hmac256(const char* key, size_t key_len, const char* message, size_t message_len, char* out) {
71 mbedtls_md_context_t hmac_ctx;
72 const mbedtls_md_info_t *md_type = mbedtls_md_info_from_type(md_type: MBEDTLS_MD_SHA256);
73 if (!md_type) {
74 throw runtime_error("failed to init hmac");
75 }
76
77 if (mbedtls_md_setup(ctx: &hmac_ctx, md_info: md_type, hmac: 1) ||
78 mbedtls_md_hmac_starts(ctx: &hmac_ctx, key: (const unsigned char *) key, keylen: key_len) ||
79 mbedtls_md_hmac_update(ctx: &hmac_ctx, input: (const unsigned char *)message, ilen: message_len) ||
80 mbedtls_md_hmac_finish(ctx: &hmac_ctx, output: (unsigned char *) out)) {
81 throw runtime_error("HMAC256 Error");
82 }
83 mbedtls_md_free(ctx: &hmac_ctx);
84}