Skip to content

Commit

Permalink
[WASI] Implement the common context in wasi-crypto.
Browse files Browse the repository at this point in the history
Signed-off-by: sonder-joker <[email protected]>
  • Loading branch information
sonder-joker authored and hydai committed Jul 26, 2022
1 parent ab9ebaf commit e49952d
Show file tree
Hide file tree
Showing 7 changed files with 630 additions and 0 deletions.
67 changes: 67 additions & 0 deletions include/host/wasi_crypto/common/array_output.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

//===-- wasi_crypto/common/array_output.h - ArrayOutput definition --------===//
//
// Part of the WasmEdge Project.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the class definitions of the wasi-crypto ArrayOutput.
///
//===----------------------------------------------------------------------===//
#pragma once

#include "common/span.h"
#include "host/wasi_crypto/utils/error.h"
#include "host/wasi_crypto/utils/secret_vec.h"

#include <atomic>
#include <memory>
#include <mutex>
#include <type_traits>
#include <utility>
#include <vector>

namespace WasmEdge {
namespace Host {
namespace WasiCrypto {
namespace Common {

/// Functions returning arrays whose size is not constant or too large to be
/// safely allocated on the stack return a handle to an ArrayOutput type.
///
/// More detail:
/// https://github.com/WebAssembly/wasi-crypto/blob/main/docs/wasi-crypto.md#array-outputs
class ArrayOutput {
public:
ArrayOutput(const ArrayOutput &) noexcept = delete;
ArrayOutput &operator=(const ArrayOutput &) noexcept = delete;
ArrayOutput &operator=(ArrayOutput &&) noexcept = delete;
ArrayOutput(ArrayOutput &&) noexcept = delete;

ArrayOutput(std::vector<uint8_t> &&Data) noexcept : Data(std::move(Data)) {}

ArrayOutput(SecretVec &&Data) noexcept : Data(std::move(Data)) {}

/// Copy the content to the @param Buf buffer.
/// Multiple calls are possible, the total number of bytes to be read is
/// guaranteed to always match data size
///
/// @returns the number of bytes read. If all pull, return true.
std::tuple<size_t, bool> pull(Span<uint8_t> Buf) noexcept;

/// Return ArrayOutput data size
size_t len() const noexcept { return Data.size(); }

private:
const SecretVec Data;
size_t Pos = 0;
std::mutex Mutex;
};

} // namespace Common
} // namespace WasiCrypto
} // namespace Host
} // namespace WasmEdge
112 changes: 112 additions & 0 deletions include/host/wasi_crypto/common/func.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

//===-- wasi_crypto/common/func.h - Common func ---------------------------===//
//
// Part of the WasmEdge Project.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the common func module of wasi-crypto
///
//===----------------------------------------------------------------------===//
#pragma once

#include "host/wasi_crypto/utils/hostfunction.h"

namespace WasmEdge {
namespace Host {
namespace WasiCrypto {
namespace Common {

class ArrayOutputLen : public HostFunction<ArrayOutputLen> {
public:
using HostFunction::HostFunction;

Expect<uint32_t> body(Runtime::Instance::MemoryInstance *MemInst,
int32_t ArrayOutputHandle, uint32_t /* Out */ SizePtr);
};

class ArrayOutputPull : public HostFunction<ArrayOutputPull> {
public:
using HostFunction::HostFunction;

Expect<uint32_t> body(Runtime::Instance::MemoryInstance *MemInst,
int32_t ArrayOutputHandle, uint32_t BufPtr,
uint32_t BufLen, uint32_t /* Out */ SizePtr);
};

class OptionsOpen : public HostFunction<OptionsOpen> {
public:
using HostFunction::HostFunction;

Expect<uint32_t> body(Runtime::Instance::MemoryInstance *MemInst,
uint32_t AlgType, uint32_t /* Out */ OptionsHandlePtr);
};

class OptionsClose : public HostFunction<OptionsClose> {
public:
using HostFunction::HostFunction;

Expect<uint32_t> body(Runtime::Instance::MemoryInstance *MemInst,
int32_t OptionsHandle);
};

class OptionsSet : public HostFunction<OptionsSet> {
public:
using HostFunction::HostFunction;

Expect<uint32_t> body(Runtime::Instance::MemoryInstance *MemInst,
int32_t OptionsHandle, uint32_t NamePtr,
uint32_t NameLen, uint32_t ValuePtr, uint32_t ValueLen);
};

class OptionsSetU64 : public HostFunction<OptionsSetU64> {
public:
using HostFunction::HostFunction;

Expect<uint32_t> body(Runtime::Instance::MemoryInstance *MemInst,
int32_t OptionsHandle, uint32_t NamePtr,
uint32_t NameLen, uint64_t Value);
};

class OptionsSetGuestBuffer : public HostFunction<OptionsSetGuestBuffer> {
public:
using HostFunction::HostFunction;

Expect<uint32_t> body(Runtime::Instance::MemoryInstance *MemInst,
int32_t OptionsHandle, uint32_t NamePtr,
uint32_t NameLen, uint32_t BufPtr, uint32_t BufLen);
};

class SecretsManagerOpen : public HostFunction<SecretsManagerOpen> {
public:
using HostFunction::HostFunction;

Expect<uint32_t> body(Runtime::Instance::MemoryInstance *MemInst,
uint32_t OptOptionsHandlePtr,
uint32_t /* Out */ SecretsManagerHandlePtr);
};

class SecretsManagerClose : public HostFunction<SecretsManagerClose> {
public:
using HostFunction::HostFunction;

Expect<uint32_t> body(Runtime::Instance::MemoryInstance *MemInst,
int32_t SecretsManagerHandle);
};

class SecretsManagerInvalidate : public HostFunction<SecretsManagerInvalidate> {
public:
using HostFunction::HostFunction;

Expect<uint32_t> body(Runtime::Instance::MemoryInstance *MemInst,
int32_t SecretsManagerHandle, uint32_t KeyIdPtr,
uint32_t KeyIdLen, uint64_t Version);
};

} // namespace Common
} // namespace WasiCrypto
} // namespace Host
} // namespace WasmEdge
60 changes: 60 additions & 0 deletions include/host/wasi_crypto/common/options.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

//===-- wasi_crypto/common/options.h - Options definition -----------------===//
//
// Part of the WasmEdge Project.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the Options definition of wasi-crypto
///
//===----------------------------------------------------------------------===//
#pragma once

#include "common/span.h"
#include "host/wasi_crypto/kx/options.h"
#include "host/wasi_crypto/signatures/options.h"
#include "host/wasi_crypto/symmetric/options.h"
#include "wasi_crypto/api.hpp"

#include <string_view>
#include <variant>

namespace WasmEdge {
namespace Host {
namespace WasiCrypto {
namespace Common {

/// Some functions support options. For example, options can be used to access
/// features that are only relevant to specific ciphers and hash functions.
///
/// Options are represented as a (key, value) map, keys being strings. They are
/// attached to a context, such as a cipher state. Applications can set, but
/// also read the value associated with a key in order to either get the default
/// value, or obtain runtime information.
///
/// More detail:
/// https://github.com/WebAssembly/wasi-crypto/blob/main/docs/wasi-crypto.md#options
using Options =
std::variant<Symmetric::Options, Kx::Options, Signatures::Options>;

Options optionsOpen(__wasi_algorithm_type_e_t Alg) noexcept;

/// Set byte vectors
WasiCryptoExpect<void> optionsSet(Options &Options, std::string_view Name,
Span<const uint8_t> Value) noexcept;

/// Set unsigned integers
WasiCryptoExpect<void> optionsSetU64(Options &Options, std::string_view Name,
uint64_t Value) noexcept;

/// Set memory buffers
WasiCryptoExpect<void> optionsSetGuestBuffer(Options &Options,
std::string_view Name,
Span<uint8_t> Value) noexcept;
} // namespace Common
} // namespace WasiCrypto
} // namespace Host
} // namespace WasmEdge
34 changes: 34 additions & 0 deletions lib/host/wasi_crypto/common/array_output.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

#include "host/wasi_crypto/common/array_output.h"

#include <algorithm>
#include <climits>
#include <mutex>
#include <vector>

namespace WasmEdge {
namespace Host {
namespace WasiCrypto {
namespace Common {

std::tuple<size_t, bool> ArrayOutput::pull(Span<uint8_t> Buf) noexcept {
std::scoped_lock Lock{Mutex};

using DataPosT = decltype(Data)::difference_type;

size_t OutputSize = std::min(Buf.size(), Data.size() - Pos);

std::copy(Data.begin() + static_cast<DataPosT>(Pos),
Data.begin() + static_cast<DataPosT>(Pos + OutputSize),
Buf.begin());
Pos += OutputSize;

return {OutputSize, Pos + OutputSize == Data.size()};
}

} // namespace Common
} // namespace WasiCrypto
} // namespace Host
} // namespace WasmEdge
88 changes: 88 additions & 0 deletions lib/host/wasi_crypto/common/ctx.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

#include "host/wasi_crypto/ctx.h"
#include "host/wasi_crypto/common/array_output.h"
#include "host/wasi_crypto/common/options.h"
#include "wasi_crypto/api.hpp"

namespace WasmEdge {
namespace Host {
namespace WasiCrypto {

WasiCryptoExpect<size_t>
Context::arrayOutputLen(__wasi_array_output_t ArrayOutputHandle) noexcept {
return ArrayOutputManager.get(ArrayOutputHandle)
.map(&Common::ArrayOutput::len);
}

WasiCryptoExpect<size_t>
Context::arrayOutputPull(__wasi_array_output_t ArrayOutputHandle,
Span<uint8_t> Buf) noexcept {
return ArrayOutputManager.get(ArrayOutputHandle)
.map([=](Common::ArrayOutput &ArrayOutput) noexcept {
auto [Size, AlreadyConsumed] = ArrayOutput.pull(Buf);
if (AlreadyConsumed) {
ArrayOutputManager.close(ArrayOutputHandle);
}
return Size;
});
}

WasiCryptoExpect<__wasi_options_t>
Context::optionsOpen(__wasi_algorithm_type_e_t AlgType) noexcept {
return OptionsManager.registerManager(Common::optionsOpen(AlgType));
}

WasiCryptoExpect<void>
Context::optionsClose(__wasi_options_t OptionsHandle) noexcept {
return OptionsManager.close(OptionsHandle);
}

WasiCryptoExpect<void> Context::optionsSet(__wasi_options_t OptionsHandle,
std::string_view Name,
Span<const uint8_t> Value) noexcept {
return OptionsManager.get(OptionsHandle)
.and_then([Name, Value](auto &&Options) noexcept {
return Common::optionsSet(Options, Name, Value);
});
}

WasiCryptoExpect<void> Context::optionsSetU64(__wasi_options_t OptionsHandle,
std::string_view Name,
uint64_t Value) noexcept {
return OptionsManager.get(OptionsHandle)
.and_then([Name, Value](auto &&Options) noexcept {
return Common::optionsSetU64(Options, Name, Value);
});
}

WasiCryptoExpect<void>
Context::optionsSetGuestBuffer(__wasi_options_t OptionsHandle,
std::string_view Name,
Span<uint8_t> Buf) noexcept {
return OptionsManager.get(OptionsHandle)
.and_then([Name, Buf](auto &&Options) noexcept {
return Common::optionsSetGuestBuffer(Options, Name, Buf);
});
}

WasiCryptoExpect<__wasi_secrets_manager_t>
Context::secretsManagerOpen(__wasi_opt_options_t) noexcept {
return WasiCryptoUnexpect(__WASI_CRYPTO_ERRNO_NOT_IMPLEMENTED);
}

WasiCryptoExpect<void>
Context::secretsManagerClose(__wasi_secrets_manager_t) noexcept {
return WasiCryptoUnexpect(__WASI_CRYPTO_ERRNO_NOT_IMPLEMENTED);
}

WasiCryptoExpect<void>
Context::secretsManagerInvalidate(__wasi_secrets_manager_t, Span<const uint8_t>,
__wasi_version_t) noexcept {
return WasiCryptoUnexpect(__WASI_CRYPTO_ERRNO_NOT_IMPLEMENTED);
}

} // namespace WasiCrypto
} // namespace Host
} // namespace WasmEdge
Loading

0 comments on commit e49952d

Please sign in to comment.