Compare commits
No commits in common. "master" and "0.17.0" have entirely different histories.
3
.github/workflows/Makefile
vendored
3
.github/workflows/Makefile
vendored
@ -1,3 +0,0 @@
|
|||||||
all:
|
|
||||||
cue export --out yaml > ci.yaml
|
|
||||||
|
|
37
.github/workflows/actions.cue
vendored
37
.github/workflows/actions.cue
vendored
@ -1,37 +0,0 @@
|
|||||||
package actions
|
|
||||||
|
|
||||||
#Name: string
|
|
||||||
#Branches: branches: [...string]
|
|
||||||
#Tags: tags: [...string]
|
|
||||||
|
|
||||||
#On: {
|
|
||||||
push?: #Branches
|
|
||||||
pull_request?: #Branches
|
|
||||||
page_build?: #Branches
|
|
||||||
}
|
|
||||||
|
|
||||||
#Action: "actions/checkout@v2" | "erlef/setup-beam@v1"
|
|
||||||
#Uses: {
|
|
||||||
uses: #Action
|
|
||||||
with?: {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#Run: {
|
|
||||||
name: string
|
|
||||||
run: string
|
|
||||||
}
|
|
||||||
#Steps: #Uses | #Run
|
|
||||||
|
|
||||||
#OS_Version: *"ubuntu-latest" | "macos-latest" | "windows_latest"
|
|
||||||
|
|
||||||
#Jobs: ci: {
|
|
||||||
name: string
|
|
||||||
"runs-on": string
|
|
||||||
strategy:
|
|
||||||
matrix: {
|
|
||||||
otp_vsn: [...string]
|
|
||||||
os: [...#OS_Version]
|
|
||||||
}
|
|
||||||
steps: [...#Steps]
|
|
||||||
}
|
|
34
.github/workflows/ci.yaml
vendored
34
.github/workflows/ci.yaml
vendored
@ -1,34 +0,0 @@
|
|||||||
name: build
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
jobs:
|
|
||||||
ci:
|
|
||||||
name: Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}}
|
|
||||||
runs-on: ${{matrix.os}}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
otp_vsn:
|
|
||||||
- "24.3"
|
|
||||||
- "25.3"
|
|
||||||
- "26.2"
|
|
||||||
os:
|
|
||||||
- ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: erlef/setup-beam@v1
|
|
||||||
with:
|
|
||||||
otp-version: ${{matrix.otp_vsn}}
|
|
||||||
rebar3-version: 3.16.1
|
|
||||||
- name: Update apt-get database
|
|
||||||
run: sudo apt-get update
|
|
||||||
- name: Install libsodium
|
|
||||||
run: sudo apt-get install -y libsodium-dev
|
|
||||||
- name: Compile source code
|
|
||||||
run: make compile
|
|
||||||
- name: Run the tests
|
|
||||||
run: make tests
|
|
21
.github/workflows/setup.cue
vendored
21
.github/workflows/setup.cue
vendored
@ -1,21 +0,0 @@
|
|||||||
package actions
|
|
||||||
|
|
||||||
name: #Name & "build"
|
|
||||||
on: #On & {
|
|
||||||
push: branches: [
|
|
||||||
_branch,
|
|
||||||
]
|
|
||||||
pull_request: branches: [
|
|
||||||
_branch,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
jobs: #Jobs
|
|
||||||
jobs: ci: {
|
|
||||||
name: "Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}}"
|
|
||||||
"runs-on": "${{matrix.os}}"
|
|
||||||
strategy: matrix: {
|
|
||||||
otp_vsn: _versions.otp
|
|
||||||
os: ["ubuntu-latest"]
|
|
||||||
}
|
|
||||||
}
|
|
40
.github/workflows/steps.cue
vendored
40
.github/workflows/steps.cue
vendored
@ -1,40 +0,0 @@
|
|||||||
package actions
|
|
||||||
|
|
||||||
// Versions for simplicity
|
|
||||||
_versions: {
|
|
||||||
// The versions here have an underlying Debian/Ubuntu which support enough of
|
|
||||||
// libsodium to handle what enacl provides. Older versions will fail to compile
|
|
||||||
otp: ["22.3", "23.3", "24.0"]
|
|
||||||
rebar3: "3.16.1"
|
|
||||||
}
|
|
||||||
|
|
||||||
_branch: "master"
|
|
||||||
|
|
||||||
jobs: ci: steps:
|
|
||||||
[
|
|
||||||
{
|
|
||||||
uses: "actions/checkout@v2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
uses: "erlef/setup-beam@v1"
|
|
||||||
with: {
|
|
||||||
"otp-version": "${{matrix.otp_vsn}}"
|
|
||||||
"rebar3-version": _versions.rebar3
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Update apt-get database"
|
|
||||||
run: "sudo apt-get update"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Install libsodium"
|
|
||||||
run: "sudo apt-get install -y libsodium-dev"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Compile source code"
|
|
||||||
run: "make compile"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Run the tests"
|
|
||||||
run: "make tests"
|
|
||||||
}]
|
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,6 +1,5 @@
|
|||||||
.rebar
|
.rebar
|
||||||
.rebar3
|
.rebar3
|
||||||
.envrc
|
|
||||||
ebin
|
ebin
|
||||||
*.beam
|
*.beam
|
||||||
*.o
|
*.o
|
||||||
@ -13,8 +12,3 @@ doc/*.png
|
|||||||
doc/*.css
|
doc/*.css
|
||||||
_build
|
_build
|
||||||
/.eqc-info
|
/.eqc-info
|
||||||
priv/enacl_nif.dll
|
|
||||||
priv/enacl_nif.exp
|
|
||||||
priv/enacl_nif.lib
|
|
||||||
c_src/*.d
|
|
||||||
|
|
||||||
|
16
.vscode/c_cpp_properties.json
vendored
16
.vscode/c_cpp_properties.json
vendored
@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "Linux",
|
|
||||||
"includePath": [
|
|
||||||
"${workspaceFolder}/**"
|
|
||||||
],
|
|
||||||
"defines": [],
|
|
||||||
"compilerPath": "/nix/store/fb30zc52va0g99q8qgv7kx4ngq163pii-gcc-wrapper-9.3.0/bin/gcc",
|
|
||||||
"cStandard": "c11",
|
|
||||||
"cppStandard": "c++17",
|
|
||||||
"intelliSenseMode": "clang-x64"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 4
|
|
||||||
}
|
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"C_Cpp.errorSquiggles": "Disabled"
|
|
||||||
}
|
|
188
CHANGELOG.md
188
CHANGELOG.md
@ -5,139 +5,11 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [1.2.1]
|
## [Unreleased]
|
||||||
|
|
||||||
### Fixed [1.2.1]
|
|
||||||
|
|
||||||
- Export types from the `enacl` module so it can be referenced in other parts of your system (serokell.io)
|
|
||||||
|
|
||||||
## [1.2.0]
|
|
||||||
|
|
||||||
### Fixed [1.2.0]
|
|
||||||
|
|
||||||
- `sign_verify_detached/3` The code now verifies the size of signatures in detached mode. Before
|
|
||||||
this change, you could supply a larger binary and the code would only use the first `SIGNBYTES`
|
|
||||||
of the binary, assuming the signature were in there. Now, it fails with a badarg if the signature
|
|
||||||
doesn't match expectation in size.
|
|
||||||
|
|
||||||
## [1.1.1]
|
|
||||||
|
|
||||||
### Added [1.1.1]
|
|
||||||
|
|
||||||
- Introduce the ability to reload the enacl module (Bryan Paxton, @starbelly)
|
|
||||||
|
|
||||||
## [1.1.0]
|
|
||||||
|
|
||||||
### Added [1.1.0]
|
|
||||||
|
|
||||||
- Secretstream support was added to the API (Alexander Malaev)
|
|
||||||
- Add KDF functions (Nicolas Goy, @kuon)
|
|
||||||
- Add pwhash/5 specifying what algorithm to use for older compatibility (Nicolas Goy, @kuon)
|
|
||||||
|
|
||||||
### Changed [1.1.0]
|
|
||||||
|
|
||||||
- Remove rebar3_hex as a direct dependency (Bryan Paxton, @starbelly)
|
|
||||||
|
|
||||||
## [1.0.0]
|
|
||||||
|
|
||||||
### Compatibility [1.0.0]
|
|
||||||
|
|
||||||
- Some functions have been streamlined to badarg in certain cases where it made more
|
|
||||||
sense to do so than returning back an error to the caller.
|
|
||||||
- Functions generally don't return error values for internal errors. They now raise
|
|
||||||
exceptions when this happens. If you can't allocate a binary, there is usually not
|
|
||||||
much the programmer can do with that information, sans crashing.
|
|
||||||
- If you used `aead_chacha20poly1305_*` functions, please read through the changelog
|
|
||||||
carefully as we have made changes to these functions. TL;DR: look for
|
|
||||||
`aead_chacha20poly1305_ietf_*` but note it is *not* just a simple substitution
|
|
||||||
into your code.
|
|
||||||
- The `kx` constants have been renamed to follow libsodium one-to-one.
|
|
||||||
- All calls with `verify` now returns booleans. See `sign_verify_detached`, which
|
|
||||||
were changed by this.
|
|
||||||
- Many constants were changed to their underlying libsodium names.
|
|
||||||
|
|
||||||
### Removed [1.0.0]
|
|
||||||
|
|
||||||
- The functions of the form `aead_chacha20poly1305_*` were removed. They implement
|
|
||||||
the IETF variant, and the argument order for them were wrong. Also, they used
|
|
||||||
severely limited nonce values, which is somewhat dangerous. The `..._NONCEBYTES`
|
|
||||||
name was changed to the consistent `..._NPUBBYTES`.
|
|
||||||
|
|
||||||
### Added [1.0.0]
|
|
||||||
|
|
||||||
- Added `aead_chacha20poly1305_ietf_*` variants.
|
|
||||||
- Implement multipart signature support, by Garry Hill.
|
|
||||||
- Implement enacl:crypto_sign_seed_keypair/1, by Ole Andre Birkedal.
|
|
||||||
- Implement enacl:crypto_sign_ed25519_sk_to_pk/1, by an anonymous contribution.
|
|
||||||
- Added AEAD XChaCha20-Poly1305 support, thanks to Github/ECrownofFire.
|
|
||||||
- The Password Hash Generation functions now support memory and operations limits,
|
|
||||||
thanks to Github/ECrownofFire.
|
|
||||||
- Implement enacl:randombytes_uint32/0. Returns a random 32bit unsigned
|
|
||||||
integer, by means of the underlying random source.
|
|
||||||
- Implement enacl:randombytes_uniform/1. Takes up to a 32bit unsigned
|
|
||||||
integer and produces a uniform integer in the range [0..N). Note
|
|
||||||
that the implementation avoids the typical non-uniformness which
|
|
||||||
would be present on a modulus operation on the nearest power-of-two
|
|
||||||
integer.
|
|
||||||
- Added Win32 build support (Tino Breddin)
|
|
||||||
- Added a nix shell for easier development
|
|
||||||
|
|
||||||
### Changed [1.0.0]
|
|
||||||
|
|
||||||
- Started a split the C code over multiple files for easier maintenance.
|
|
||||||
- Rewrote the generichash routines to be more consistent. We are now more-or-less
|
|
||||||
following the style of the Erlang/OTP `crypto` library. While here, make sure
|
|
||||||
we clean up correctly and that we don't accidentally mis-ref-count data. The
|
|
||||||
code is a bit more goto heavy, but this style is surprisingly common in C code.
|
|
||||||
- Use sodium's dynamic memory allocators. These guarantee 64bit alignment, and also
|
|
||||||
provide guard pages around the allocation, somewhat protecting it. It adds some
|
|
||||||
page table pressure compared to the current code, but is easier to maintain and
|
|
||||||
much cleaner code.
|
|
||||||
- The code now rejects updates to generichash states which were already finalized.
|
|
||||||
- We now track the desired outlen of a generichash operation in the opaque NIF
|
|
||||||
resource rather than on the Erlang side. This avoids some checks in the code,
|
|
||||||
and streamlines a good deal of the interface.
|
|
||||||
- Split AEAD routines off from the main enacl_nif.c file
|
|
||||||
- Renamed many routines from enif_* to enacl_*. This better reflects where they live
|
|
||||||
in the code base, and avoids pollution of the enif_* "namespace".
|
|
||||||
- Split Sign Public Key routines from the rest. Modernize the handling of contexts.
|
|
||||||
- The multi-part generic hash routines now follow the structure of the crypto
|
|
||||||
modules multi-part constructions in API and style.
|
|
||||||
- The AEAD constructions have been streamlined so they follow the rules of libsodium
|
|
||||||
closer than before. In particular, some dead code has been removed as a result.
|
|
||||||
- Constants are now named by their libsodium counterpart. This should make it easier
|
|
||||||
to find the correct names given the libsodium documentation.
|
|
||||||
- Generichash now checks if a `_final` call has already happened and rejects further
|
|
||||||
hashing on the object. The rejection is an error: if you ever do this, your code
|
|
||||||
is definitely wrong and there is no recovery possible.
|
|
||||||
|
|
||||||
### Fixed [1.0.0]
|
|
||||||
|
|
||||||
- Fix a resource leak in generichash/sign init/update/final.
|
|
||||||
- Clang static analysis warnings (Thomas Arts).
|
|
||||||
- Replace a constant 31 with a computation from libsodium (Thomas Arts, from a security review).
|
|
||||||
- Some subtle memory leaks in the error path for kx operations were plugged.
|
|
||||||
- The multi-part generichash interface is now properly process/thread safe.
|
|
||||||
- The sign interface is now properly process/thread safe.
|
|
||||||
|
|
||||||
## [0.17.2]
|
|
||||||
|
|
||||||
### Fixed [0.17.2]
|
|
||||||
|
|
||||||
- Work around `rebar3 hex` publishing .so files
|
|
||||||
|
|
||||||
## [0.17.1]
|
|
||||||
|
|
||||||
### Fixed [0.17.1]
|
|
||||||
|
|
||||||
- Provide a fix for the `pwhash_str/x` functions. The C strings were
|
|
||||||
not properly handled wrt. NULL-termination and what the libsodium
|
|
||||||
library expects.
|
|
||||||
|
|
||||||
## [0.17.0]
|
## [0.17.0]
|
||||||
|
|
||||||
### Added [0.17.0]
|
### Added
|
||||||
|
|
||||||
- Expose the AEAD ChaCha20 Poly1305 (IETF) functionality (Hans
|
- Expose the AEAD ChaCha20 Poly1305 (IETF) functionality (Hans
|
||||||
Svensson / Quviq).
|
Svensson / Quviq).
|
||||||
- Expose Curve25519 Scalar Multiplication over a base point in the
|
- Expose Curve25519 Scalar Multiplication over a base point in the
|
||||||
@ -149,13 +21,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||||||
to verify the enacl library on embedded platforms and so on.
|
to verify the enacl library on embedded platforms and so on.
|
||||||
- Support generichash functions (Venkatakumar Srinivasan / Xaptum)
|
- Support generichash functions (Venkatakumar Srinivasan / Xaptum)
|
||||||
|
|
||||||
### Fixed [0.17.0]
|
### Fixed
|
||||||
|
|
||||||
- The type specification of generichash/2 and generichash/3 was
|
- The type specification of generichash/2 and generichash/3 was
|
||||||
corrected (Technion)
|
corrected (Technion)
|
||||||
|
|
||||||
### Changed [0.17.0]
|
### Changed
|
||||||
|
|
||||||
- Removed the experimental feature flag `ERL_NIF_DIRTY_JOB_CPU_BOUND`.
|
- Removed the experimental feature flag `ERL_NIF_DIRTY_JOB_CPU_BOUND`.
|
||||||
This breaks compatibility with older Erlang releases of dirty
|
This breaks compatibility with older Erlang releases of dirty
|
||||||
schedulers, but prepares us correctly for the new releases where the
|
schedulers, but prepares us correctly for the new releases where the
|
||||||
@ -173,26 +43,24 @@ Bump libsodium requirement to version 1.0.12. This gives us access to
|
|||||||
a number of functions which are added recently and thus gives us
|
a number of functions which are added recently and thus gives us
|
||||||
access to implement these from libsodium.
|
access to implement these from libsodium.
|
||||||
|
|
||||||
### Added [0.16.0]
|
### Added
|
||||||
|
|
||||||
- Add kx_* functions (Alexander Malaev)
|
- Add kx_* functions (Alexander Malaev)
|
||||||
- chacha stream functions added, siphash-2-4 added, unsafe_memzero/1
|
- chacha stream functions added, siphash-2-4 added, unsafe_memzero/1
|
||||||
added (no attribution)
|
added (no attribution)
|
||||||
|
|
||||||
### Fixed [0.16.0]
|
### Fixed
|
||||||
|
|
||||||
- Do not use the dirty-scheduler test macro as it is gone.
|
- Do not use the dirty-scheduler test macro as it is gone.
|
||||||
|
|
||||||
## [0.15.0]
|
## [0.15.0]
|
||||||
|
|
||||||
### Fixed [0.15.0]
|
### Fixed
|
||||||
|
|
||||||
- Using `enacl:sign_verify_detacted` on large iolists would fail to do
|
- Using `enacl:sign_verify_detacted` on large iolists would fail to do
|
||||||
the correct thing due to a typo. This has been corrected. Also the
|
the correct thing due to a typo. This has been corrected. Also the
|
||||||
EQC tests have been extended to include large binary support to
|
EQC tests have been extended to include large binary support to
|
||||||
capture these kinds of errors in the future.
|
capture these kinds of errors in the future.
|
||||||
|
|
||||||
### Changed [0.15.0]
|
### Changed
|
||||||
|
|
||||||
- Many dirty-scheduler tunings have been performed to make sure we
|
- Many dirty-scheduler tunings have been performed to make sure we
|
||||||
won't block a scheduler ever.
|
won't block a scheduler ever.
|
||||||
@ -208,40 +76,33 @@ a better citizen to other libraries and other parts of the system.
|
|||||||
|
|
||||||
## [0.14.0]
|
## [0.14.0]
|
||||||
|
|
||||||
### Added [0.14.0]
|
### Added
|
||||||
|
|
||||||
- Add support for libsodiums `box_seal` functions (Amir Ghassemi Nasr)
|
- Add support for libsodiums `box_seal` functions (Amir Ghassemi Nasr)
|
||||||
- Add support for libsodiums `crypto_sign_detached` (Joel Stanley,
|
- Add support for libsodiums `crypto_sign_detached` (Joel Stanley,
|
||||||
Parnell Springmeyer)
|
Parnell Springmeyer)
|
||||||
|
### Changed
|
||||||
### Changed [0.14.0]
|
|
||||||
|
|
||||||
- Switch the tag names to the form `0.14.0` rather than `v0.14.0`. For
|
- Switch the tag names to the form `0.14.0` rather than `v0.14.0`. For
|
||||||
this release both tags are present, but from the next release on, it
|
this release both tags are present, but from the next release on, it
|
||||||
won't be the case.
|
won't be the case.
|
||||||
|
|
||||||
## [0.13.0]
|
## [0.13.0]
|
||||||
|
|
||||||
### Fixed [0.13.0]
|
### Fixed
|
||||||
|
|
||||||
- Quell warnings from the C code
|
- Quell warnings from the C code
|
||||||
|
|
||||||
### Added [0.13.0]
|
### Added
|
||||||
|
|
||||||
- Add Ed 25519 utility API (Alexander Færøy)
|
- Add Ed 25519 utility API (Alexander Færøy)
|
||||||
- Add FreeBSD support for the NIF compilation (Ricardo Lanziano)
|
- Add FreeBSD support for the NIF compilation (Ricardo Lanziano)
|
||||||
|
|
||||||
## [0.12.1]
|
## [0.12.1]
|
||||||
|
|
||||||
### Changed [0.12.1]
|
### Changed
|
||||||
|
|
||||||
- Provide the `priv` directory for being able to properly build
|
- Provide the `priv` directory for being able to properly build
|
||||||
without manual intervention.
|
without manual intervention.
|
||||||
|
|
||||||
## [0.12.0]
|
## [0.12.0]
|
||||||
|
|
||||||
### Added [0.12.0]
|
### Added
|
||||||
|
|
||||||
- Introduce an extension interface for various necessary extensions to
|
- Introduce an extension interface for various necessary extensions to
|
||||||
the eNaCl system for handling the Tor network, thanks to Alexander
|
the eNaCl system for handling the Tor network, thanks to Alexander
|
||||||
Færøy (ahf).
|
Færøy (ahf).
|
||||||
@ -251,15 +112,12 @@ a better citizen to other libraries and other parts of the system.
|
|||||||
|
|
||||||
## [0.11.0]
|
## [0.11.0]
|
||||||
|
|
||||||
### Added [0.11.0]
|
### Added
|
||||||
|
|
||||||
- Introduce NIF layer beforenm/afternm calls.
|
- Introduce NIF layer beforenm/afternm calls.
|
||||||
- Introduce the API for precomputed keys (beforenm/afternm calls).
|
- Introduce the API for precomputed keys (beforenm/afternm calls).
|
||||||
- Use test cases which tries to inject `iodata()` rather than binaries
|
- Use test cases which tries to inject `iodata()` rather than binaries
|
||||||
in all places where `iodata()` tend to be accepted.
|
in all places where `iodata()` tend to be accepted.
|
||||||
|
### Fixed
|
||||||
### Fixed [0.11.0]
|
|
||||||
|
|
||||||
- Fix type for `enacl:box_open/4`. The specification was wrong which
|
- Fix type for `enacl:box_open/4`. The specification was wrong which
|
||||||
results in errors in other applications using enacl.
|
results in errors in other applications using enacl.
|
||||||
|
|
||||||
@ -267,8 +125,7 @@ a better citizen to other libraries and other parts of the system.
|
|||||||
|
|
||||||
Maintenance release. Fix some usability problems with the library.
|
Maintenance release. Fix some usability problems with the library.
|
||||||
|
|
||||||
### Fixed [0.10.2]
|
### Fixed
|
||||||
|
|
||||||
- Do not compile the C NIF code if there are no dirty scheduler
|
- Do not compile the C NIF code if there are no dirty scheduler
|
||||||
support in the Erlang system (Thanks to David N. Welton)
|
support in the Erlang system (Thanks to David N. Welton)
|
||||||
- Fix dialyzer warnings (Thanks Anthony Ramine)
|
- Fix dialyzer warnings (Thanks Anthony Ramine)
|
||||||
@ -282,7 +139,7 @@ Maintenance release. Fix some usability problems with the library.
|
|||||||
|
|
||||||
## [0.10.1]
|
## [0.10.1]
|
||||||
|
|
||||||
### Added [0.10.1]
|
### Added
|
||||||
|
|
||||||
- This small patch-release provides tests for the `randombytes/1`
|
- This small patch-release provides tests for the `randombytes/1`
|
||||||
function call, and optimizes EQC tests to make it easier to implement
|
function call, and optimizes EQC tests to make it easier to implement
|
||||||
@ -298,15 +155,15 @@ included in this library.
|
|||||||
Ultra-late beta; tuning for the last couple of functions which could
|
Ultra-late beta; tuning for the last couple of functions which could
|
||||||
be nice to have.
|
be nice to have.
|
||||||
|
|
||||||
### Added [0.10.0]
|
### Added
|
||||||
|
|
||||||
Added the function `randombytes/1` to obtain randombytes from the
|
Added the function `randombytes/1` to obtain randombytes from the
|
||||||
operating system. The system uses the "best" applicable (P)RNG on the
|
operating system. The system uses the "best" applicable (P)RNG on the
|
||||||
target system:
|
target system:
|
||||||
|
|
||||||
- Windows: `RtlGenRandom()`
|
* Windows: `RtlGenRandom()`
|
||||||
- OpenBSD, Bitrig: `arc4random()`
|
* OpenBSD, Bitrig: `arc4random()`
|
||||||
- Unix in general: `/dev/urandom`
|
* Unix in general: `/dev/urandom`
|
||||||
|
|
||||||
Do note that on Linux and FreeBSD at the *least*, this is the best
|
Do note that on Linux and FreeBSD at the *least*, this is the best
|
||||||
thing you can do. Relying on `/dev/random` is almost always wrong and
|
thing you can do. Relying on `/dev/random` is almost always wrong and
|
||||||
@ -320,3 +177,4 @@ Ultra-late beta. Code probably works, but it requires some real-world
|
|||||||
use before it is deemed entirely stable.
|
use before it is deemed entirely stable.
|
||||||
|
|
||||||
Initial release.
|
Initial release.
|
||||||
|
|
||||||
|
@ -3,15 +3,9 @@ List of people who have contributed to the eNaCl source code:
|
|||||||
Alexander Færøy
|
Alexander Færøy
|
||||||
Alexander Malaev
|
Alexander Malaev
|
||||||
Amir Ghassemi Nasr
|
Amir Ghassemi Nasr
|
||||||
Bryan Paxton
|
|
||||||
GitHub/ECrownofFire
|
|
||||||
Geller Bedoya
|
Geller Bedoya
|
||||||
Jesper Louis Andersen
|
Jesper Louis Andersen
|
||||||
Joel Stanley
|
Joel Stanley
|
||||||
Konrad Zemek
|
Konrad Zemek
|
||||||
Nicolas Goy
|
|
||||||
Parnell Springmeyer
|
Parnell Springmeyer
|
||||||
Ricardo Lanziano
|
Ricardo Lanziano
|
||||||
Tino Breddin
|
|
||||||
Venkatakumar Srinivasan
|
|
||||||
|
|
||||||
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2014-2018 Jesper Louis Andersen
|
Copyright (c) 2014 Jesper Louis Andersen
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
4
Makefile
4
Makefile
@ -5,10 +5,6 @@ RUN_EQC=erl -pa _build/default/lib/enacl/ebin -noshell -s enacl_eqc -s init stop
|
|||||||
compile:
|
compile:
|
||||||
$(REBAR) compile
|
$(REBAR) compile
|
||||||
|
|
||||||
.PHONY: tests
|
|
||||||
tests:
|
|
||||||
$(REBAR) ct
|
|
||||||
|
|
||||||
eqc_compile: compile
|
eqc_compile: compile
|
||||||
erlc -o _build/default/lib/enacl/ebin eqc_test/enacl_eqc.erl
|
erlc -o _build/default/lib/enacl/ebin eqc_test/enacl_eqc.erl
|
||||||
|
|
||||||
|
64
README.md
64
README.md
@ -6,40 +6,42 @@ Frank Denis took the source and made it far more portable in the
|
|||||||
libsodium library. The enacl project is somewhat misnamed, as it uses
|
libsodium library. The enacl project is somewhat misnamed, as it uses
|
||||||
libsodium as the underlying driver.
|
libsodium as the underlying driver.
|
||||||
|
|
||||||
## INSTALL/Requirements
|
Several Erlang ports of NaCl/libsodium exists, but this one is a
|
||||||
|
rewrite with the following foci:
|
||||||
|
|
||||||
* New-ish Erlang installation. Tested back to version 22.3, but version 21 *may*
|
## INSTALL/Requirements:
|
||||||
work as well.
|
|
||||||
* *Requires* the libsodium library, and has been tested with version
|
|
||||||
1.0.18. Lower versions might work, or they might fail to compile,
|
|
||||||
due to missing functionality. In particular, this means your libsodium installation
|
|
||||||
must be fairly recent as well.
|
|
||||||
|
|
||||||
*Note:* If installing on systems which cuts packages into
|
* Erlang/OTP 17.3. This library *needs* the newest dirty scheduler
|
||||||
subpackages, make sure you also get the "-dev" package containing
|
implementation. The library relies on dirty scheduler support in
|
||||||
the header files necessary in order to compile software linking to
|
order to handle long-running cryptography jobs, by moving them off
|
||||||
libsodium.
|
the main Erlang scheduler and letting the dirty schedulers handle
|
||||||
|
the work. This keeps the Erlang VM responsive.
|
||||||
|
* *Requires* the libsodium library, and at least in version 1.0.12.
|
||||||
|
*Note:* If installing on systems which cuts packages into
|
||||||
|
subpackages, make sure you also get the "-dev" package containing
|
||||||
|
the header files necessary in order to compile software linking to
|
||||||
|
libsodium.
|
||||||
|
|
||||||
To build the software execute:
|
To build the software execute:
|
||||||
|
|
||||||
make
|
make
|
||||||
|
|
||||||
or
|
or
|
||||||
|
|
||||||
rebar compile
|
rebar compile
|
||||||
|
|
||||||
To build and run licensed eqc test execute:
|
To build and run licensed eqc test execute:
|
||||||
|
|
||||||
make eqc_run
|
make eqc_run
|
||||||
|
|
||||||
To build and run eqc-mini version of test execute:
|
To build and run eqc-mini version of test execute:
|
||||||
|
|
||||||
make eqc_mini_run
|
make eqc_mini_run
|
||||||
|
|
||||||
## Features
|
## Features:
|
||||||
|
|
||||||
* Complete NaCl library, implementing all default functionality.
|
* Complete NaCl library, implementing all default functionality.
|
||||||
* Implements a large set of additional functionality from libsodium.
|
* Implements a small set of additional functionality from libsodium.
|
||||||
Most notably access to a proper CSPRNG random source
|
Most notably access to a proper CSPRNG random source
|
||||||
* Tests created by aggressive use of Erlang QuickCheck.
|
* Tests created by aggressive use of Erlang QuickCheck.
|
||||||
* NaCl is a very fast cryptographic library. That is,
|
* NaCl is a very fast cryptographic library. That is,
|
||||||
@ -58,17 +60,21 @@ In addition, I would like to thank Steve Vinoski, Rickard Green, and
|
|||||||
Sverker Eriksson for providing the Dirty Scheduler API in the first
|
Sverker Eriksson for providing the Dirty Scheduler API in the first
|
||||||
place.
|
place.
|
||||||
|
|
||||||
## Usage
|
# USING:
|
||||||
|
|
||||||
In general, consult the libsodium documentation at [Libsodium documentation](https://download.libsodium.org/doc/)
|
In general, consult the libsodium documentation at
|
||||||
|
|
||||||
|
https://download.libsodium.org/doc/
|
||||||
|
|
||||||
The original NaCl documentation is nowadays largely superceded by the
|
The original NaCl documentation is nowadays largely superceded by the
|
||||||
libsodium documentation, but it is still worth a visit [NaCl website](https://nacl.cr.yp.to)
|
libsodium documentation, but it is still worth a visit
|
||||||
|
|
||||||
|
https://nacl.cr.yp.to
|
||||||
|
|
||||||
but also note that our interface has full Edoc documentation,
|
but also note that our interface has full Edoc documentation,
|
||||||
generated by executing
|
generated by executing
|
||||||
|
|
||||||
rebar3 doc
|
rebar3 doc
|
||||||
|
|
||||||
## Hints
|
## Hints
|
||||||
|
|
||||||
@ -126,11 +132,12 @@ However, their correct use is still needed in order to be secure:
|
|||||||
a foreign system as an oracle in order to learn the structure of a
|
a foreign system as an oracle in order to learn the structure of a
|
||||||
string, breaking the cryptograhic system in the process.
|
string, breaking the cryptograhic system in the process.
|
||||||
|
|
||||||
## Versions
|
# Versions
|
||||||
|
|
||||||
See CHANGELOG.md
|
See CHANGELOG.md
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
# Overview
|
||||||
|
|
||||||
The NaCl cryptographic library provides a number of different
|
The NaCl cryptographic library provides a number of different
|
||||||
cryptographic primitives. In the following, we split up the different
|
cryptographic primitives. In the following, we split up the different
|
||||||
@ -192,7 +199,7 @@ This implements cryptography where there is a shared secret key between parties.
|
|||||||
* *String comparison:* Implements guaranteed constant-time string
|
* *String comparison:* Implements guaranteed constant-time string
|
||||||
comparisons to protect against timing attacks.
|
comparisons to protect against timing attacks.
|
||||||
|
|
||||||
## Rationale
|
# Rationale
|
||||||
|
|
||||||
Doing crypto right in Erlang is not that easy. For one, the crypto
|
Doing crypto right in Erlang is not that easy. For one, the crypto
|
||||||
system has to be rather fast, which rules out Erlang as the main
|
system has to be rather fast, which rules out Erlang as the main
|
||||||
@ -244,7 +251,7 @@ perhaps being able to switch faster. There are plans to rerun these
|
|||||||
tests on OSX and Illumos as well, in order to investigate the numbers
|
tests on OSX and Illumos as well, in order to investigate the numbers
|
||||||
on more platforms.
|
on more platforms.
|
||||||
|
|
||||||
## Testing
|
# Testing
|
||||||
|
|
||||||
Every primitive has been stress-tested through the use of Erlang
|
Every primitive has been stress-tested through the use of Erlang
|
||||||
QuickCheck with both *positive* and *negative* testing. This has been
|
QuickCheck with both *positive* and *negative* testing. This has been
|
||||||
@ -271,8 +278,11 @@ sure we have no memory leaks as they will show themselves under the
|
|||||||
extensive QuickCheck test cases we run. It has been verified there are
|
extensive QuickCheck test cases we run. It has been verified there are
|
||||||
no leaks in the code.
|
no leaks in the code.
|
||||||
|
|
||||||
## Notes
|
# Notes
|
||||||
|
|
||||||
[0] Other people have worked on bits and pieces of NaCl. These are
|
[0] Other people have worked on bits and pieces of NaCl. These are
|
||||||
just the 3 main authors. Please see the page [NaCl](http://nacl.cr.yp.to)
|
just the 3 main authors. Please see the page
|
||||||
|
|
||||||
|
http://nacl.cr.yp.to
|
||||||
|
|
||||||
for the full list of authors.
|
for the full list of authors.
|
||||||
|
@ -47,7 +47,7 @@ box() ->
|
|||||||
#{ public := PK1} = enacl:box_keypair(),
|
#{ public := PK1} = enacl:box_keypair(),
|
||||||
#{ secret := SK2} = enacl:box_keypair(),
|
#{ secret := SK2} = enacl:box_keypair(),
|
||||||
B = binary:copy(<<0>>, 1),
|
B = binary:copy(<<0>>, 1),
|
||||||
Nonce = binary:copy(<<0>>, enacl:box_NONCEBYTES()()),
|
Nonce = binary:copy(<<0>>, enacl:box_nonce_size()),
|
||||||
box(B, Nonce, PK1, SK2, 10*1000).
|
box(B, Nonce, PK1, SK2, 10*1000).
|
||||||
|
|
||||||
box(_B, _Nonce, _PK1, _SK2, 0) -> ok;
|
box(_B, _Nonce, _PK1, _SK2, 0) -> ok;
|
||||||
@ -62,7 +62,7 @@ box_before_after() ->
|
|||||||
box_beforenm(PK1, SK2, 10*1000),
|
box_beforenm(PK1, SK2, 10*1000),
|
||||||
R = enacl:box_beforenm(PK1, SK2),
|
R = enacl:box_beforenm(PK1, SK2),
|
||||||
B = binary:copy(<<0>>, 8192),
|
B = binary:copy(<<0>>, 8192),
|
||||||
Nonce = binary:copy(<<0>>, enacl:box_NONCEBYTES()()),
|
Nonce = binary:copy(<<0>>, enacl:box_nonce_size()),
|
||||||
box_afternm(B, Nonce, R, 10*1000),
|
box_afternm(B, Nonce, R, 10*1000),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
@ -100,8 +100,8 @@ sign(Msg, SK, N) ->
|
|||||||
|
|
||||||
secretbox() ->
|
secretbox() ->
|
||||||
Msg = binary:copy(<<0>>, 8192),
|
Msg = binary:copy(<<0>>, 8192),
|
||||||
Nonce = binary:copy(<<0>>, enacl:secretbox_NONCEBYTES()()),
|
Nonce = binary:copy(<<0>>, enacl:secretbox_nonce_size()),
|
||||||
Key = binary:copy(<<0>>, enacl:secretbox_KEYBYTES()),
|
Key = binary:copy(<<0>>, enacl:secretbox_key_size()),
|
||||||
secretbox(Msg, Nonce, Key, 10*1000).
|
secretbox(Msg, Nonce, Key, 10*1000).
|
||||||
|
|
||||||
secretbox(_Msg, _Nonce, _Key, 0) -> ok;
|
secretbox(_Msg, _Nonce, _Key, 0) -> ok;
|
||||||
@ -111,7 +111,7 @@ secretbox(Msg, Nonce, Key, N) ->
|
|||||||
|
|
||||||
|
|
||||||
stream() ->
|
stream() ->
|
||||||
stream(16384, binary:copy(<<0>>, enacl:stream_NONCEBYTES()), binary:copy(<<0>>, enacl:stream_KEYBYTES()), 10*1000).
|
stream(16384, binary:copy(<<0>>, enacl:stream_nonce_size()), binary:copy(<<0>>, enacl:stream_key_size()), 10*1000).
|
||||||
|
|
||||||
stream(_L, _Nonce, _K, 0) -> ok;
|
stream(_L, _Nonce, _K, 0) -> ok;
|
||||||
stream(L, Nonce, K, N) ->
|
stream(L, Nonce, K, N) ->
|
||||||
@ -120,7 +120,7 @@ stream(L, Nonce, K, N) ->
|
|||||||
|
|
||||||
auth() ->
|
auth() ->
|
||||||
Msg = binary:copy(<<0>>, 4096),
|
Msg = binary:copy(<<0>>, 4096),
|
||||||
Key = binary:copy(<<0>>, enacl:auth_KEYBYTES()),
|
Key = binary:copy(<<0>>, enacl:auth_key_size()),
|
||||||
auth(Msg, Key, 10*1000).
|
auth(Msg, Key, 10*1000).
|
||||||
|
|
||||||
auth(_Msg, _Key, 0) -> ok;
|
auth(_Msg, _Key, 0) -> ok;
|
||||||
@ -130,7 +130,7 @@ auth(Msg, Key, N) ->
|
|||||||
|
|
||||||
onetime_auth() ->
|
onetime_auth() ->
|
||||||
Msg = binary:copy(<<0>>, 16384),
|
Msg = binary:copy(<<0>>, 16384),
|
||||||
Key = binary:copy(<<0>>, enacl:onetime_auth_KEYBYTES()),
|
Key = binary:copy(<<0>>, enacl:onetime_auth_key_size()),
|
||||||
onetime_auth(Msg, Key, 10*1000).
|
onetime_auth(Msg, Key, 10*1000).
|
||||||
|
|
||||||
onetime_auth(_Msg, _Key, 0) -> ok;
|
onetime_auth(_Msg, _Key, 0) -> ok;
|
||||||
|
75
c_src/Makefile
Normal file
75
c_src/Makefile
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# Based on c_src.mk from erlang.mk by Loïc Hoguin <essen@ninenines.eu>
|
||||||
|
|
||||||
|
PROJECT ?= enacl_nif
|
||||||
|
|
||||||
|
ERTS_INCLUDE_DIR ?= $(shell erl -noshell -s init stop -eval "io:format(\"~s/erts-~s/include/\", [code:root_dir(), erlang:system_info(version)]).")
|
||||||
|
ERL_INTERFACE_INCLUDE_DIR ?= $(shell erl -noshell -s init stop -eval "io:format(\"~s\", [code:lib_dir(erl_interface, include)]).")
|
||||||
|
ERL_INTERFACE_LIB_DIR ?= $(shell erl -noshell -s init stop -eval "io:format(\"~s\", [code:lib_dir(erl_interface, lib)]).")
|
||||||
|
|
||||||
|
C_SRC_DIR = $(CURDIR)
|
||||||
|
C_SRC_OUTPUT ?= $(CURDIR)/../priv/$(PROJECT).so
|
||||||
|
|
||||||
|
# System type and C compiler/flags.
|
||||||
|
MACHINE_SYS := $(shell uname -m)
|
||||||
|
UNAME_SYS := $(shell uname -s)
|
||||||
|
ifeq ($(UNAME_SYS), Darwin)
|
||||||
|
CC ?= cc
|
||||||
|
CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes
|
||||||
|
CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall
|
||||||
|
LDFLAGS ?= -arch x86_64 -flat_namespace -undefined suppress
|
||||||
|
else ifeq ($(UNAME_SYS), FreeBSD)
|
||||||
|
CC ?= cc
|
||||||
|
CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes -I /usr/local/include
|
||||||
|
CXXFLAGS ?= -O3 -finline-functions -Wall
|
||||||
|
LDFLAGS ?= -fPIC -L /usr/local/lib
|
||||||
|
else ifeq ($(UNAME_SYS), Linux)
|
||||||
|
CC ?= gcc
|
||||||
|
CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
|
||||||
|
CXXFLAGS ?= -O3 -finline-functions -Wall
|
||||||
|
else ifeq ($(UNAME_SYS), SunOS)
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS ?= -m64 -I/opt/local/include -O2 -std=c99 -finline-functions -Wall -Wmissing-prototypes
|
||||||
|
CXXFALGS ?= -O2 -finline-function -Wall
|
||||||
|
LDFLAGS ?= -m64 -fPIC -L /opt/local/lib
|
||||||
|
endif
|
||||||
|
|
||||||
|
CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
|
||||||
|
CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
|
||||||
|
|
||||||
|
LDLIBS += -L $(ERL_INTERFACE_LIB_DIR) -lerl_interface -lei -lsodium
|
||||||
|
LDFLAGS += -shared
|
||||||
|
|
||||||
|
# Verbosity.
|
||||||
|
|
||||||
|
c_verbose_0 = @echo " C " $(?F);
|
||||||
|
c_verbose = $(c_verbose_$(V))
|
||||||
|
|
||||||
|
cpp_verbose_0 = @echo " CPP " $(?F);
|
||||||
|
cpp_verbose = $(cpp_verbose_$(V))
|
||||||
|
|
||||||
|
link_verbose_0 = @echo " LD " $(@F);
|
||||||
|
link_verbose = $(link_verbose_$(V))
|
||||||
|
|
||||||
|
SOURCES := $(shell find $(C_SRC_DIR) -type f \( -name "*.c" -o -name "*.C" -o -name "*.cc" -o -name "*.cpp" \))
|
||||||
|
OBJECTS = $(addsuffix .o, $(basename $(SOURCES)))
|
||||||
|
|
||||||
|
COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c
|
||||||
|
COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c
|
||||||
|
|
||||||
|
$(C_SRC_OUTPUT): $(OBJECTS)
|
||||||
|
$(link_verbose) $(CC) $(OBJECTS) $(LDFLAGS) $(LDLIBS) -o $(C_SRC_OUTPUT)
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(COMPILE_C) $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
|
%.o: %.cc
|
||||||
|
$(COMPILE_CPP) $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
|
%.o: %.C
|
||||||
|
$(COMPILE_CPP) $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
|
%.o: %.cpp
|
||||||
|
$(COMPILE_CPP) $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -f $(C_SRC_OUTPUT) $(OBJECTS)
|
242
c_src/aead.c
242
c_src/aead.c
@ -1,242 +0,0 @@
|
|||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
#include "aead.h"
|
|
||||||
#include "enacl.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* AEAD ChaCha20 Poly1305
|
|
||||||
*/
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_chacha20poly1305_ietf_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_KEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_chacha20poly1305_ietf_NPUBBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_chacha20poly1305_ietf_ABYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_ABYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX(
|
|
||||||
ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env,
|
|
||||||
crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_chacha20poly1305_ietf_encrypt(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
ErlNifBinary key, nonce, ad, message, ciphertext;
|
|
||||||
|
|
||||||
if (argc != 4)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[0], &message))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &ad))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[2], &nonce))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[3], &key))
|
|
||||||
goto bad_arg;
|
|
||||||
if (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
if (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(message.size +
|
|
||||||
crypto_aead_chacha20poly1305_ietf_ABYTES,
|
|
||||||
&ciphertext)) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_aead_chacha20poly1305_ietf_encrypt(ciphertext.data, NULL, message.data,
|
|
||||||
message.size, ad.data, ad.size,
|
|
||||||
NULL, nonce.data, key.data);
|
|
||||||
|
|
||||||
ret = enif_make_binary(env, &ciphertext);
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
err:
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
done:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_chacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
ErlNifBinary key, nonce, ad, message, ciphertext;
|
|
||||||
|
|
||||||
if (argc != 4)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[0], &ciphertext))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &ad))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[2], &nonce))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[3], &key))
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (ciphertext.size < crypto_aead_chacha20poly1305_ietf_ABYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
if (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
if (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(ciphertext.size -
|
|
||||||
crypto_aead_chacha20poly1305_ietf_ABYTES,
|
|
||||||
&message)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crypto_aead_chacha20poly1305_ietf_decrypt(
|
|
||||||
message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data,
|
|
||||||
ad.size, nonce.data, key.data) != 0) {
|
|
||||||
ret = enacl_error_tuple(env, "failed_verification");
|
|
||||||
goto release;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = enif_make_binary(env, &message);
|
|
||||||
goto done;
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
release:
|
|
||||||
enif_release_binary(&message);
|
|
||||||
done:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* AEAD XChaCha20 Poly1305
|
|
||||||
*/
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_xchacha20poly1305_ietf_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_xchacha20poly1305_ietf_NPUBBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_xchacha20poly1305_ietf_ABYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_ABYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX(
|
|
||||||
ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env,
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_xchacha20poly1305_ietf_encrypt(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary key, nonce, ad, message, ciphertext;
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
|
|
||||||
if (argc != 4)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[0], &message))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &ad))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[2], &nonce))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[3], &key))
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (key.size != crypto_aead_xchacha20poly1305_ietf_KEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
if (nonce.size != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(message.size +
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_ABYTES,
|
|
||||||
&ciphertext)) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_encrypt(
|
|
||||||
ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, NULL,
|
|
||||||
nonce.data, key.data);
|
|
||||||
|
|
||||||
ret = enif_make_binary(env, &ciphertext);
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
err:
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
done:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_xchacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary key, nonce, ad, message, ciphertext;
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
|
|
||||||
if (argc != 4)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[0], &ciphertext))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &ad))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[2], &nonce))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[3], &key))
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (ciphertext.size < crypto_aead_xchacha20poly1305_ietf_ABYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
if (key.size != crypto_aead_xchacha20poly1305_ietf_KEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
if (nonce.size != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(ciphertext.size -
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_ABYTES,
|
|
||||||
&message)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crypto_aead_xchacha20poly1305_ietf_decrypt(
|
|
||||||
message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data,
|
|
||||||
ad.size, nonce.data, key.data) != 0) {
|
|
||||||
ret = enacl_error_tuple(env, "failed_verification");
|
|
||||||
goto release;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = enif_make_binary(env, &message);
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
release:
|
|
||||||
enif_release_binary(&message);
|
|
||||||
done:
|
|
||||||
return ret;
|
|
||||||
}
|
|
46
c_src/aead.h
46
c_src/aead.h
@ -1,46 +0,0 @@
|
|||||||
#ifndef ENACL_AEAD_H
|
|
||||||
#define ENACL_AEAD_H
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
/* AEAD ChaCha20 Poly1305 */
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_chacha20poly1305_ietf_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_chacha20poly1305_ietf_NPUBBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_chacha20poly1305_ietf_ABYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX(
|
|
||||||
ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]);
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_chacha20poly1305_ietf_encrypt(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_chacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
/* AEAD XChaCha20 Poly1305 */
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_xchacha20poly1305_ietf_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_xchacha20poly1305_ietf_NPUBBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_xchacha20poly1305_ietf_ABYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX(
|
|
||||||
ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]);
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_xchacha20poly1305_ietf_encrypt(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_aead_xchacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,16 +0,0 @@
|
|||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
#include "enacl.h"
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_error_tuple(ErlNifEnv *env, char *error_atom) {
|
|
||||||
return enif_make_tuple2(env, enif_make_atom(env, "error"),
|
|
||||||
enif_make_atom(env, error_atom));
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_internal_error(ErlNifEnv *env) {
|
|
||||||
return enif_raise_exception(env, enif_make_atom(env, "enacl_internal_error"));
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_error_finalized(ErlNifEnv *env) {
|
|
||||||
return enif_raise_exception(env, enif_make_atom(env, "enacl_finalized"));
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
#ifndef ENACL_H
|
|
||||||
#define ENACL_H
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
#define ATOM_OK "ok"
|
|
||||||
#define ATOM_ERROR "error"
|
|
||||||
#define ATOM_TRUE "true"
|
|
||||||
#define ATOM_FALSE "false"
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_error_tuple(ErlNifEnv *, char *);
|
|
||||||
ERL_NIF_TERM enacl_error_finalized(ErlNifEnv *);
|
|
||||||
ERL_NIF_TERM enacl_internal_error(ErlNifEnv *);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,86 +0,0 @@
|
|||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
#include "enacl.h"
|
|
||||||
#include "enacl_ext.h"
|
|
||||||
|
|
||||||
static void uint64_pack(unsigned char *y, ErlNifUInt64 x) {
|
|
||||||
*y++ = x;
|
|
||||||
x >>= 8;
|
|
||||||
*y++ = x;
|
|
||||||
x >>= 8;
|
|
||||||
*y++ = x;
|
|
||||||
x >>= 8;
|
|
||||||
*y++ = x;
|
|
||||||
x >>= 8;
|
|
||||||
*y++ = x;
|
|
||||||
x >>= 8;
|
|
||||||
*y++ = x;
|
|
||||||
x >>= 8;
|
|
||||||
*y++ = x;
|
|
||||||
x >>= 8;
|
|
||||||
*y++ = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ErlNifUInt64 uint64_unpack(const unsigned char *x) {
|
|
||||||
ErlNifUInt64 result;
|
|
||||||
|
|
||||||
result = x[7];
|
|
||||||
result <<= 8;
|
|
||||||
result |= x[6];
|
|
||||||
result <<= 8;
|
|
||||||
result |= x[5];
|
|
||||||
result <<= 8;
|
|
||||||
result |= x[4];
|
|
||||||
result <<= 8;
|
|
||||||
result |= x[3];
|
|
||||||
result <<= 8;
|
|
||||||
result |= x[2];
|
|
||||||
result <<= 8;
|
|
||||||
result |= x[1];
|
|
||||||
result <<= 8;
|
|
||||||
result |= x[0];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int crypto_block(unsigned char *out, const unsigned char *in,
|
|
||||||
const unsigned char *k) {
|
|
||||||
ErlNifUInt64 v0 = uint64_unpack(in + 0);
|
|
||||||
ErlNifUInt64 v1 = uint64_unpack(in + 8);
|
|
||||||
ErlNifUInt64 k0 = uint64_unpack(k + 0);
|
|
||||||
ErlNifUInt64 k1 = uint64_unpack(k + 8);
|
|
||||||
ErlNifUInt64 k2 = uint64_unpack(k + 16);
|
|
||||||
ErlNifUInt64 k3 = uint64_unpack(k + 24);
|
|
||||||
ErlNifUInt64 sum = 0;
|
|
||||||
ErlNifUInt64 delta = 0x9e3779b97f4a7c15;
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < 32; ++i) {
|
|
||||||
sum += delta;
|
|
||||||
v0 += ((v1 << 7) + k0) ^ (v1 + sum) ^ ((v1 >> 12) + k1);
|
|
||||||
v1 += ((v0 << 16) + k2) ^ (v0 + sum) ^ ((v0 >> 8) + k3);
|
|
||||||
}
|
|
||||||
uint64_pack(out + 0, v0);
|
|
||||||
uint64_pack(out + 8, v1);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary in, out, key;
|
|
||||||
|
|
||||||
if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &in)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &key)) || (in.size != 16) ||
|
|
||||||
(key.size != 32)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(in.size, &out)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_block(out.data, in.data, key.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &out);
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#ifndef ENACL_EXT_H
|
|
||||||
#define ENACL_EXT_H
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
#endif
|
|
2050
c_src/enacl_nif.c
2050
c_src/enacl_nif.c
File diff suppressed because it is too large
Load Diff
@ -1,301 +0,0 @@
|
|||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
#include "enacl.h"
|
|
||||||
#include "generichash.h"
|
|
||||||
|
|
||||||
typedef struct enacl_generichash_ctx {
|
|
||||||
ErlNifMutex *mtx;
|
|
||||||
crypto_generichash_state *ctx; // Underlying hash state from sodium
|
|
||||||
int alive; // Is the context still valid for updates/finalizes?
|
|
||||||
int outlen; // Final size of the hash
|
|
||||||
|
|
||||||
} enacl_generichash_ctx;
|
|
||||||
|
|
||||||
static ErlNifResourceType *enacl_generic_hash_ctx_rtype;
|
|
||||||
|
|
||||||
static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env,
|
|
||||||
enacl_generichash_ctx *);
|
|
||||||
|
|
||||||
int enacl_init_generic_hash_ctx(ErlNifEnv *env) {
|
|
||||||
enacl_generic_hash_ctx_rtype =
|
|
||||||
enif_open_resource_type(env, NULL, "enacl_generichash_context",
|
|
||||||
(ErlNifResourceDtor *)enacl_generic_hash_ctx_dtor,
|
|
||||||
ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL);
|
|
||||||
|
|
||||||
if (enacl_generic_hash_ctx_rtype == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env,
|
|
||||||
enacl_generichash_ctx *obj) {
|
|
||||||
if (!obj->alive) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->ctx)
|
|
||||||
sodium_free(obj->ctx);
|
|
||||||
|
|
||||||
if (obj->mtx != NULL)
|
|
||||||
enif_mutex_destroy(obj->mtx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generic hash
|
|
||||||
*/
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_BYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_generichash_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_generichash_BYTES_MIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_generichash_BYTES_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_generichash_KEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_generichash_KEYBYTES_MIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_generichash_KEYBYTES_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary hash, message, key;
|
|
||||||
unsigned hash_size;
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
|
|
||||||
// Validate the arguments
|
|
||||||
if (argc != 3)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_get_uint(env, argv[0], &hash_size))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &message))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[2], &key))
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
// Verify that hash size is
|
|
||||||
// crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
|
|
||||||
if ((hash_size < crypto_generichash_BYTES_MIN) ||
|
|
||||||
(hash_size > crypto_generichash_BYTES_MAX)) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate key size
|
|
||||||
unsigned char *k = key.data;
|
|
||||||
if (0 == key.size) {
|
|
||||||
k = NULL;
|
|
||||||
} else if (key.size < crypto_generichash_KEYBYTES_MIN ||
|
|
||||||
key.size > crypto_generichash_KEYBYTES_MAX) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate memory for hash
|
|
||||||
if (!enif_alloc_binary(hash_size, &hash)) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate hash
|
|
||||||
if (0 != crypto_generichash(hash.data, hash.size, message.data, message.size,
|
|
||||||
k, key.size)) {
|
|
||||||
goto release;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = enif_make_binary(env, &hash);
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
release:
|
|
||||||
enif_release_binary(&hash);
|
|
||||||
err:
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
done:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary key;
|
|
||||||
unsigned hash_size;
|
|
||||||
enacl_generichash_ctx *obj = NULL;
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
|
|
||||||
// Validate the arguments
|
|
||||||
if (argc != 2)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_get_uint(env, argv[0], &hash_size))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &key))
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
// Verify that hash size is valid
|
|
||||||
if ((hash_size < crypto_generichash_BYTES_MIN) ||
|
|
||||||
(hash_size > crypto_generichash_BYTES_MAX)) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate key size
|
|
||||||
unsigned char *k = key.data;
|
|
||||||
if (0 == key.size) {
|
|
||||||
k = NULL;
|
|
||||||
} else if (key.size < crypto_generichash_KEYBYTES_MIN ||
|
|
||||||
key.size > crypto_generichash_KEYBYTES_MAX) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the resource
|
|
||||||
if ((obj = enif_alloc_resource(enacl_generic_hash_ctx_rtype,
|
|
||||||
sizeof(enacl_generichash_ctx))) == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate the state context via libsodium
|
|
||||||
// Note that this ensures a 64byte alignment for the resource
|
|
||||||
// And also protects the resource via guardpages
|
|
||||||
obj->mtx = NULL;
|
|
||||||
obj->ctx = NULL;
|
|
||||||
obj->alive = 0;
|
|
||||||
obj->outlen = 0;
|
|
||||||
|
|
||||||
obj->ctx = (crypto_generichash_state *)sodium_malloc(
|
|
||||||
crypto_generichash_statebytes());
|
|
||||||
if (obj->ctx == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
obj->alive = 1;
|
|
||||||
obj->outlen = hash_size;
|
|
||||||
|
|
||||||
if ((obj->mtx = enif_mutex_create("enacl.generichash")) == NULL) {
|
|
||||||
ret = enacl_error_tuple(env, "mutex_create");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the library function
|
|
||||||
if (0 != crypto_generichash_init(obj->ctx, k, key.size, obj->outlen)) {
|
|
||||||
ret = enacl_error_tuple(env, "hash_init_error");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = enif_make_resource(env, obj);
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
err:
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
if (obj != NULL) {
|
|
||||||
if (obj->alive) {
|
|
||||||
sodium_free(obj->ctx);
|
|
||||||
obj->alive = 0; // Maintain the invariant consistently
|
|
||||||
}
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
if (obj != NULL) {
|
|
||||||
enif_release_resource(obj);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
ErlNifBinary data;
|
|
||||||
enacl_generichash_ctx *obj = NULL;
|
|
||||||
|
|
||||||
// Validate the arguments
|
|
||||||
if (argc != 2)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_get_resource(env, argv[0],
|
|
||||||
(ErlNifResourceType *)enacl_generic_hash_ctx_rtype,
|
|
||||||
(void **)&obj))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &data))
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
enif_mutex_lock(obj->mtx);
|
|
||||||
if (!obj->alive) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update hash state
|
|
||||||
if (0 != crypto_generichash_update(obj->ctx, data.data, data.size)) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = argv[0];
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
err:
|
|
||||||
ret = enacl_error_finalized(env);
|
|
||||||
done:
|
|
||||||
enif_mutex_unlock(obj->mtx);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
ErlNifBinary hash;
|
|
||||||
enacl_generichash_ctx *obj = NULL;
|
|
||||||
|
|
||||||
if (argc != 1)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_get_resource(env, argv[0], enacl_generic_hash_ctx_rtype,
|
|
||||||
(void **)&obj))
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
enif_mutex_lock(obj->mtx);
|
|
||||||
if (!obj->alive) {
|
|
||||||
ret = enacl_error_finalized(env);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(obj->outlen, &hash)) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != crypto_generichash_final(obj->ctx, hash.data, hash.size)) {
|
|
||||||
goto release;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finalize the object such that it cannot be reused by accident
|
|
||||||
if (obj->ctx)
|
|
||||||
sodium_free(obj->ctx);
|
|
||||||
obj->alive = 0;
|
|
||||||
|
|
||||||
ret = enif_make_binary(env, &hash);
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
release:
|
|
||||||
enif_release_binary(&hash);
|
|
||||||
err:
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
done:
|
|
||||||
enif_mutex_unlock(obj->mtx);
|
|
||||||
return ret;
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
#ifndef ENACL_GENERICHASH_H
|
|
||||||
#define ENACL_GENERICHASH_H
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
int enacl_init_generic_hash_ctx(ErlNifEnv *env);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_BYTES(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]);
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]);
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]);
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]);
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]);
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]);
|
|
||||||
ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]);
|
|
||||||
|
|
||||||
#endif
|
|
62
c_src/hash.c
62
c_src/hash.c
@ -1,62 +0,0 @@
|
|||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
#include "enacl.h"
|
|
||||||
#include "hash.h"
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_shorthash_BYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_shorthash_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_shorthash_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_shorthash_KEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_shorthash(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary a, m, k;
|
|
||||||
|
|
||||||
if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &k))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (k.size != crypto_shorthash_KEYBYTES) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_shorthash_BYTES, &a)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_shorthash(a.data, m.data, m.size, k.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &a);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_hash(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary input;
|
|
||||||
ErlNifBinary result;
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
|
|
||||||
if ((argc != 1) || (!enif_inspect_iolist_as_binary(env, argv[0], &input)))
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_hash_BYTES, &result))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
crypto_hash(result.data, input.data, input.size);
|
|
||||||
ret = enif_make_binary(env, &result);
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
err:
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
done:
|
|
||||||
return ret;
|
|
||||||
}
|
|
17
c_src/hash.h
17
c_src/hash.h
@ -1,17 +0,0 @@
|
|||||||
#ifndef ENACL_HASH_H
|
|
||||||
#define ENACL_HASH_H
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_shorthash_BYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_shorthash_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_shorthash(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_hash(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]);
|
|
||||||
#endif
|
|
59
c_src/kdf.c
59
c_src/kdf.c
@ -1,59 +0,0 @@
|
|||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
#include "enacl.h"
|
|
||||||
#include "kdf.h"
|
|
||||||
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kdf_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_kdf_KEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kdf_CONTEXTBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_kdf_CONTEXTBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kdf_derive_from_key(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary m, c, r;
|
|
||||||
ErlNifUInt64 id;
|
|
||||||
|
|
||||||
// Validate the arguments
|
|
||||||
if ((argc != 3) ||
|
|
||||||
(!enif_inspect_iolist_as_binary(env, argv[0], &m)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &c)) ||
|
|
||||||
(!enif_get_uint64(env, argv[2], &id))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check Master Key length
|
|
||||||
if (m.size != crypto_kdf_KEYBYTES) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check Context Key length
|
|
||||||
if (c.size != crypto_kdf_CONTEXTBYTES) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate memory for return binary
|
|
||||||
if (!enif_alloc_binary(crypto_kdf_KEYBYTES, &r)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crypto_kdf_derive_from_key(r.data, r.size,
|
|
||||||
id,
|
|
||||||
(const char *)c.data,
|
|
||||||
m.data) != 0) {
|
|
||||||
/* out of memory */
|
|
||||||
enif_release_binary(&r);
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
return enif_make_binary(env, &r);
|
|
||||||
}
|
|
||||||
|
|
15
c_src/kdf.h
15
c_src/kdf.h
@ -1,15 +0,0 @@
|
|||||||
#ifndef ENACL_KDF_H
|
|
||||||
#define ENACL_KDF_H
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kdf_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kdf_CONTEXTBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kdf_derive_from_key(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
#endif
|
|
151
c_src/kx.c
151
c_src/kx.c
@ -1,151 +0,0 @@
|
|||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
#include "enacl.h"
|
|
||||||
#include "kx.h"
|
|
||||||
|
|
||||||
/* Key exchange */
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kx_SECRETKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_kx_SECRETKEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kx_PUBLICKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_kx_PUBLICKEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kx_SESSIONKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_kx_SESSIONKEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kx_keypair(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary pk, sk;
|
|
||||||
|
|
||||||
if (argc != 0) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_kx_PUBLICKEYBYTES, &pk)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_kx_SECRETKEYBYTES, &sk)) {
|
|
||||||
enif_release_binary(&pk);
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_kx_keypair(pk.data, sk.data);
|
|
||||||
|
|
||||||
return enif_make_tuple2(env, enif_make_binary(env, &pk),
|
|
||||||
enif_make_binary(env, &sk));
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
ErlNifBinary rx, tx, server_pk, server_sk, client_pk;
|
|
||||||
|
|
||||||
if (argc != 3)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[0], &server_pk))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &server_sk))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[2], &client_pk))
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (server_pk.size != crypto_kx_PUBLICKEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
if (server_sk.size != crypto_kx_SECRETKEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
if (client_pk.size != crypto_kx_PUBLICKEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto release_rx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data,
|
|
||||||
server_sk.data, client_pk.data)) {
|
|
||||||
// suspicious client public key
|
|
||||||
ret = enacl_error_tuple(env, "invalid_client_public_key");
|
|
||||||
goto release_tx_rx;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = enif_make_tuple2(env, enif_make_binary(env, &rx),
|
|
||||||
enif_make_binary(env, &tx));
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
release_tx_rx:
|
|
||||||
enif_release_binary(&tx);
|
|
||||||
release_rx:
|
|
||||||
enif_release_binary(&rx);
|
|
||||||
done:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary rx, tx, client_pk, client_sk, server_pk;
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
|
|
||||||
if (argc != 3)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[0], &client_pk))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &client_sk))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[2], &server_pk))
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (client_pk.size != crypto_kx_PUBLICKEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
if (client_sk.size != crypto_kx_SECRETKEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
if (server_pk.size != crypto_kx_PUBLICKEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto release_rx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data,
|
|
||||||
client_sk.data, server_pk.data)) {
|
|
||||||
// suspicious server public key
|
|
||||||
ret = enacl_error_tuple(env, "invalid_server_public_key");
|
|
||||||
goto release_tx_rx;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = enif_make_tuple2(env, enif_make_binary(env, &rx),
|
|
||||||
enif_make_binary(env, &tx));
|
|
||||||
goto done;
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
release_tx_rx:
|
|
||||||
enif_release_binary(&tx);
|
|
||||||
release_rx:
|
|
||||||
enif_release_binary(&rx);
|
|
||||||
done:
|
|
||||||
return ret;
|
|
||||||
}
|
|
24
c_src/kx.h
24
c_src/kx.h
@ -1,24 +0,0 @@
|
|||||||
#ifndef ENACL_KX_H
|
|
||||||
#define ENACL_KX_H
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kx_SECRETKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kx_PUBLICKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kx_SESSIONKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kx_keypair(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
#endif
|
|
286
c_src/public.c
286
c_src/public.c
@ -1,286 +0,0 @@
|
|||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
#include "enacl.h"
|
|
||||||
#include "public.h"
|
|
||||||
|
|
||||||
/* Public-key cryptography */
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_NONCEBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_box_NONCEBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_ZEROBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_box_ZEROBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_BOXZEROBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_box_BOXZEROBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_PUBLICKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_box_PUBLICKEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_SECRETKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_box_SECRETKEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_BEFORENMBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_box_BEFORENMBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_SEALBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_box_SEALBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_keypair(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary pk, sk;
|
|
||||||
|
|
||||||
if (argc != 0) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_box_PUBLICKEYBYTES, &pk)) {
|
|
||||||
return enacl_error_tuple(env, "alloc_failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_box_SECRETKEYBYTES, &sk)) {
|
|
||||||
enif_release_binary(&pk);
|
|
||||||
return enacl_error_tuple(env, "alloc_failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_box_keypair(pk.data, sk.data);
|
|
||||||
|
|
||||||
return enif_make_tuple2(env, enif_make_binary(env, &pk),
|
|
||||||
enif_make_binary(env, &sk));
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary padded_msg, nonce, pk, sk, result;
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
|
|
||||||
if (argc != 4)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_iolist_as_binary(env, argv[0], &padded_msg))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &nonce))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[2], &pk))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[3], &sk))
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (nonce.size != crypto_box_NONCEBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
if (pk.size != crypto_box_PUBLICKEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
if (sk.size != crypto_box_SECRETKEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
if (padded_msg.size < crypto_box_ZEROBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(padded_msg.size, &result)) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data,
|
|
||||||
pk.data, sk.data)) {
|
|
||||||
goto release;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = enif_make_sub_binary(env, enif_make_binary(env, &result),
|
|
||||||
crypto_box_BOXZEROBYTES,
|
|
||||||
padded_msg.size - crypto_box_BOXZEROBYTES);
|
|
||||||
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
release:
|
|
||||||
enif_release_binary(&result);
|
|
||||||
err:
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
done:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_open(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary padded_ciphertext, nonce, pk, sk, result;
|
|
||||||
|
|
||||||
if ((argc != 4) ||
|
|
||||||
(!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &nonce)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &pk)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[3], &sk))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((nonce.size != crypto_box_NONCEBYTES) ||
|
|
||||||
(pk.size != crypto_box_PUBLICKEYBYTES) ||
|
|
||||||
(sk.size != crypto_box_SECRETKEYBYTES) ||
|
|
||||||
(padded_ciphertext.size < crypto_box_BOXZEROBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(padded_ciphertext.size, &result)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != crypto_box_open(result.data, padded_ciphertext.data,
|
|
||||||
padded_ciphertext.size, nonce.data, pk.data,
|
|
||||||
sk.data)) {
|
|
||||||
enif_release_binary(&result);
|
|
||||||
return enacl_error_tuple(env, "failed_verification");
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK);
|
|
||||||
ERL_NIF_TERM ret_bin = enif_make_sub_binary(
|
|
||||||
env, enif_make_binary(env, &result), crypto_box_ZEROBYTES,
|
|
||||||
padded_ciphertext.size - crypto_box_ZEROBYTES);
|
|
||||||
|
|
||||||
return enif_make_tuple2(env, ret_ok, ret_bin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Precomputed crypto boxes */
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_beforenm(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary k, pk, sk;
|
|
||||||
|
|
||||||
if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &pk)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &sk)) ||
|
|
||||||
(pk.size != crypto_box_PUBLICKEYBYTES) ||
|
|
||||||
(sk.size != crypto_box_SECRETKEYBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_box_BEFORENMBYTES, &k)) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != crypto_box_beforenm(k.data, pk.data, sk.data)) {
|
|
||||||
// error
|
|
||||||
enif_release_binary(&k);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return enif_make_binary(env, &k);
|
|
||||||
err:
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary result, m, nonce, k;
|
|
||||||
|
|
||||||
if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &nonce)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &k)) ||
|
|
||||||
(m.size < crypto_box_ZEROBYTES) ||
|
|
||||||
(nonce.size != crypto_box_NONCEBYTES) ||
|
|
||||||
(k.size != crypto_box_BEFORENMBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(m.size, &result)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_box_afternm(result.data, m.data, m.size, nonce.data, k.data);
|
|
||||||
|
|
||||||
return enif_make_sub_binary(env, enif_make_binary(env, &result),
|
|
||||||
crypto_box_BOXZEROBYTES,
|
|
||||||
m.size - crypto_box_BOXZEROBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary result, m, nonce, k;
|
|
||||||
|
|
||||||
if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &nonce)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &k)) ||
|
|
||||||
(m.size < crypto_box_BOXZEROBYTES) ||
|
|
||||||
(nonce.size != crypto_box_NONCEBYTES) ||
|
|
||||||
(k.size != crypto_box_BEFORENMBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(m.size, &result)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != crypto_box_open_afternm(result.data, m.data, m.size, nonce.data,
|
|
||||||
k.data)) {
|
|
||||||
enif_release_binary(&result);
|
|
||||||
return enacl_error_tuple(env, "failed_verification");
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK);
|
|
||||||
ERL_NIF_TERM ret_bin =
|
|
||||||
enif_make_sub_binary(env, enif_make_binary(env, &result),
|
|
||||||
crypto_box_ZEROBYTES, m.size - crypto_box_ZEROBYTES);
|
|
||||||
return enif_make_tuple2(env, ret_ok, ret_bin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sealed box functions */
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_seal(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary key, msg, ciphertext;
|
|
||||||
|
|
||||||
if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &msg)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &key))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(msg.size + crypto_box_SEALBYTES, &ciphertext)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_box_seal(ciphertext.data, msg.data, msg.size, key.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &ciphertext);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary pk, sk, ciphertext, msg;
|
|
||||||
|
|
||||||
if ((argc != 3) ||
|
|
||||||
(!enif_inspect_iolist_as_binary(env, argv[0], &ciphertext)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &pk)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &sk))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ciphertext.size < crypto_box_SEALBYTES) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(ciphertext.size - crypto_box_SEALBYTES, &msg)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crypto_box_seal_open(msg.data, ciphertext.data, ciphertext.size, pk.data,
|
|
||||||
sk.data) != 0) {
|
|
||||||
enif_release_binary(&msg);
|
|
||||||
return enacl_error_tuple(env, "failed_verification");
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK);
|
|
||||||
ERL_NIF_TERM ret_bin = enif_make_binary(env, &msg);
|
|
||||||
|
|
||||||
return enif_make_tuple2(env, ret_ok, ret_bin);
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
#ifndef ENACL_PUBLIC_H
|
|
||||||
#define ENACL_PUBLIC_H
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_NONCEBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_ZEROBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_BOXZEROBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_PUBLICKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_SECRETKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_BEFORENMBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_keypair(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_open(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_beforenm(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_SEALBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_seal(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
#endif
|
|
180
c_src/pwhash.c
180
c_src/pwhash.c
@ -1,180 +0,0 @@
|
|||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
#include "enacl.h"
|
|
||||||
#include "pwhash.h"
|
|
||||||
|
|
||||||
static size_t enacl_pwhash_opslimit(ErlNifEnv *env, ERL_NIF_TERM arg) {
|
|
||||||
ERL_NIF_TERM a;
|
|
||||||
size_t r;
|
|
||||||
|
|
||||||
if (enif_is_atom(env, arg)) {
|
|
||||||
a = enif_make_atom(env, "interactive");
|
|
||||||
if (enif_is_identical(a, arg)) {
|
|
||||||
return crypto_pwhash_OPSLIMIT_INTERACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = enif_make_atom(env, "moderate");
|
|
||||||
if (enif_is_identical(a, arg)) {
|
|
||||||
return crypto_pwhash_OPSLIMIT_MODERATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = enif_make_atom(env, "sensitive");
|
|
||||||
if (enif_is_identical(a, arg)) {
|
|
||||||
return crypto_pwhash_OPSLIMIT_SENSITIVE;
|
|
||||||
}
|
|
||||||
} else if (enif_get_ulong(env, arg, &r)) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t enacl_pwhash_memlimit(ErlNifEnv *env, ERL_NIF_TERM arg) {
|
|
||||||
ERL_NIF_TERM a;
|
|
||||||
size_t r;
|
|
||||||
|
|
||||||
if (enif_is_atom(env, arg)) {
|
|
||||||
a = enif_make_atom(env, "interactive");
|
|
||||||
if (enif_is_identical(a, arg)) {
|
|
||||||
return crypto_pwhash_MEMLIMIT_INTERACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = enif_make_atom(env, "moderate");
|
|
||||||
if (enif_is_identical(a, arg)) {
|
|
||||||
return crypto_pwhash_MEMLIMIT_MODERATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = enif_make_atom(env, "sensitive");
|
|
||||||
if (enif_is_identical(a, arg)) {
|
|
||||||
return crypto_pwhash_MEMLIMIT_SENSITIVE;
|
|
||||||
}
|
|
||||||
} else if (enif_get_ulong(env, arg, &r)) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_pwhash_SALTBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_pwhash_SALTBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int enacl_pwhash_alg(ErlNifEnv *env, ERL_NIF_TERM arg) {
|
|
||||||
ERL_NIF_TERM a;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (enif_is_atom(env, arg)) {
|
|
||||||
a = enif_make_atom(env, "default");
|
|
||||||
if (enif_is_identical(a, arg)) {
|
|
||||||
return crypto_pwhash_ALG_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = enif_make_atom(env, "argon2i13");
|
|
||||||
if (enif_is_identical(a, arg)) {
|
|
||||||
return crypto_pwhash_ALG_ARGON2I13;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = enif_make_atom(env, "argon2id13");
|
|
||||||
if (enif_is_identical(a, arg)) {
|
|
||||||
return crypto_pwhash_ALG_ARGON2ID13;
|
|
||||||
}
|
|
||||||
} else if (enif_get_int(env, arg, &r)) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary h, p, s;
|
|
||||||
size_t o, m;
|
|
||||||
int alg;
|
|
||||||
|
|
||||||
// Validate the arguments
|
|
||||||
if ((argc != 5) || (!enif_inspect_iolist_as_binary(env, argv[0], &p)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &s)) ||
|
|
||||||
!(o = enacl_pwhash_opslimit(env, argv[2])) ||
|
|
||||||
!(m = enacl_pwhash_memlimit(env, argv[3])) ||
|
|
||||||
!(alg = enacl_pwhash_alg(env, argv[4]))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check limits
|
|
||||||
if ((o < crypto_pwhash_OPSLIMIT_MIN) || (o > crypto_pwhash_OPSLIMIT_MAX) ||
|
|
||||||
(m < crypto_pwhash_MEMLIMIT_MIN) || (m > crypto_pwhash_MEMLIMIT_MAX)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check Salt size
|
|
||||||
if (s.size != crypto_pwhash_SALTBYTES) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate memory for return binary
|
|
||||||
if (!enif_alloc_binary(crypto_box_SEEDBYTES, &h)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crypto_pwhash(h.data, h.size, (char *)p.data, p.size, s.data, o, m,
|
|
||||||
alg) != 0) {
|
|
||||||
/* out of memory */
|
|
||||||
enif_release_binary(&h);
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
return enif_make_binary(env, &h);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_pwhash_str(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary h, p;
|
|
||||||
size_t o, m;
|
|
||||||
|
|
||||||
// Validate the arguments
|
|
||||||
if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &p)) ||
|
|
||||||
!(o = enacl_pwhash_opslimit(env, argv[1])) ||
|
|
||||||
!(m = enacl_pwhash_memlimit(env, argv[2]))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check limits
|
|
||||||
if ((o < crypto_pwhash_OPSLIMIT_MIN) || (o > crypto_pwhash_OPSLIMIT_MAX) ||
|
|
||||||
(m < crypto_pwhash_MEMLIMIT_MIN) || (m > crypto_pwhash_MEMLIMIT_MAX)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate memory for return binary
|
|
||||||
if (!enif_alloc_binary(crypto_pwhash_STRBYTES, &h)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crypto_pwhash_str((char *)h.data, (char *)p.data, p.size, o, m) != 0) {
|
|
||||||
/* out of memory */
|
|
||||||
enif_release_binary(&h);
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
return enif_make_binary(env, &h);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_pwhash_str_verify(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary h, p;
|
|
||||||
// Validate the arguments
|
|
||||||
if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &h)) ||
|
|
||||||
(!enif_inspect_iolist_as_binary(env, argv[1], &p))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM ret = enif_make_atom(env, ATOM_TRUE);
|
|
||||||
if (crypto_pwhash_str_verify((char *)h.data, (char *)p.data, p.size) != 0) {
|
|
||||||
/* wrong password */
|
|
||||||
ret = enif_make_atom(env, ATOM_FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
#ifndef ENACL_PWHASH_H
|
|
||||||
#define ENACL_PWHASH_H
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_pwhash_SALTBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_pwhash_str(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_pwhash_str_verify(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,49 +0,0 @@
|
|||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
#include "enacl.h"
|
|
||||||
#include "randombytes.h"
|
|
||||||
|
|
||||||
ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
unsigned req_size;
|
|
||||||
ErlNifBinary result;
|
|
||||||
|
|
||||||
if ((argc != 1) || (!enif_get_uint(env, argv[0], &req_size))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(req_size, &result)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
randombytes(result.data, result.size);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &result);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enif_randombytes_uint32(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifUInt64 result;
|
|
||||||
|
|
||||||
if (argc != 0) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = randombytes_random();
|
|
||||||
return enif_make_uint64(env, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enif_randombytes_uniform(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
unsigned upper_bound;
|
|
||||||
ErlNifUInt64 result;
|
|
||||||
|
|
||||||
if ((argc != 1) || (!enif_get_uint(env, argv[0], &upper_bound))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = randombytes_uniform(upper_bound);
|
|
||||||
return enif_make_uint64(env, result);
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
#ifndef ENACL_RANDOMBYTES_H
|
|
||||||
#define ENACL_RANDOMBYTES_H
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enif_randombytes_uint32(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enif_randombytes_uniform(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
#endif
|
|
382
c_src/secret.c
382
c_src/secret.c
@ -1,382 +0,0 @@
|
|||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
#include "enacl.h"
|
|
||||||
#include "secret.h"
|
|
||||||
|
|
||||||
/* Secret key cryptography */
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_secretbox_NONCEBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_secretbox_NONCEBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretbox_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_secretbox_KEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_secretbox_ZEROBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_secretbox_ZEROBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_secretbox_BOXZEROBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_secretbox_BOXZEROBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_stream_chacha20_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_stream_chacha20_KEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_stream_chacha20_NONCEBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_stream_chacha20_NONCEBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_stream_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_stream_KEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_stream_NONCEBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_stream_NONCEBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_auth_BYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_auth_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_auth_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_auth_KEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_onetimeauth_BYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_onetimeauth_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_onetimeauth_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_onetimeauth_KEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretbox(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary key, nonce, padded_msg, padded_ciphertext;
|
|
||||||
|
|
||||||
if ((argc != 3) ||
|
|
||||||
(!enif_inspect_iolist_as_binary(env, argv[0], &padded_msg)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &nonce)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &key))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((key.size != crypto_secretbox_KEYBYTES) ||
|
|
||||||
(nonce.size != crypto_secretbox_NONCEBYTES) ||
|
|
||||||
(padded_msg.size < crypto_secretbox_ZEROBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(padded_msg.size, &padded_ciphertext)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_secretbox(padded_ciphertext.data, padded_msg.data, padded_msg.size,
|
|
||||||
nonce.data, key.data);
|
|
||||||
|
|
||||||
return enif_make_sub_binary(env, enif_make_binary(env, &padded_ciphertext),
|
|
||||||
crypto_secretbox_BOXZEROBYTES,
|
|
||||||
padded_msg.size - crypto_secretbox_BOXZEROBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretbox_open(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary key, nonce, padded_ciphertext, padded_msg;
|
|
||||||
|
|
||||||
if ((argc != 3) ||
|
|
||||||
(!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &nonce)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &key))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((key.size != crypto_secretbox_KEYBYTES) ||
|
|
||||||
(nonce.size != crypto_secretbox_NONCEBYTES) ||
|
|
||||||
(padded_ciphertext.size < crypto_secretbox_BOXZEROBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(padded_ciphertext.size, &padded_msg)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crypto_secretbox_open(padded_msg.data, padded_ciphertext.data,
|
|
||||||
padded_ciphertext.size, nonce.data,
|
|
||||||
key.data) != 0) {
|
|
||||||
enif_release_binary(&padded_msg);
|
|
||||||
return enacl_error_tuple(env, "failed_verification");
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK);
|
|
||||||
ERL_NIF_TERM ret_bin = enif_make_sub_binary(
|
|
||||||
env, enif_make_binary(env, &padded_msg), crypto_secretbox_ZEROBYTES,
|
|
||||||
padded_ciphertext.size - crypto_secretbox_ZEROBYTES);
|
|
||||||
return enif_make_tuple2(env, ret_ok, ret_bin);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretbox_easy(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary key, nonce, msg, cipherbox;
|
|
||||||
|
|
||||||
if ((argc != 3) ||
|
|
||||||
(!enif_inspect_iolist_as_binary(env, argv[0], &msg)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &nonce)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &key))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((key.size != crypto_secretbox_KEYBYTES) ||
|
|
||||||
(nonce.size != crypto_secretbox_NONCEBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(msg.size + crypto_secretbox_MACBYTES, &cipherbox)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_secretbox_easy(cipherbox.data, msg.data, msg.size,
|
|
||||||
nonce.data, key.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &cipherbox);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretbox_open_easy(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary key, nonce, cipherbox, msg;
|
|
||||||
|
|
||||||
if ((argc != 3) ||
|
|
||||||
(!enif_inspect_iolist_as_binary(env, argv[0], &cipherbox)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &nonce)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &key))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((key.size != crypto_secretbox_KEYBYTES) ||
|
|
||||||
(nonce.size != crypto_secretbox_NONCEBYTES) ||
|
|
||||||
(cipherbox.size < crypto_secretbox_MACBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(cipherbox.size - crypto_secretbox_MACBYTES, &msg)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crypto_secretbox_open_easy(msg.data, cipherbox.data, cipherbox.size,
|
|
||||||
nonce.data, key.data) != 0) {
|
|
||||||
enif_release_binary(&msg);
|
|
||||||
return enacl_error_tuple(env, "failed_verification");
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK);
|
|
||||||
ERL_NIF_TERM ret_bin = enif_make_binary(env, &msg);
|
|
||||||
return enif_make_tuple2(env, ret_ok, ret_bin);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_stream_chacha20(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary c, n, k;
|
|
||||||
ErlNifUInt64 clen;
|
|
||||||
|
|
||||||
if ((argc != 3) || (!enif_get_uint64(env, argv[0], &clen)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &n)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &k))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((k.size != crypto_stream_chacha20_KEYBYTES) ||
|
|
||||||
(n.size != crypto_stream_chacha20_NONCEBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(clen, &c)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_stream_chacha20(c.data, c.size, n.data, k.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &c);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_stream_chacha20_xor(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary c, m, n, k;
|
|
||||||
|
|
||||||
if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &n)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &k))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((k.size != crypto_stream_chacha20_KEYBYTES) ||
|
|
||||||
(n.size != crypto_stream_chacha20_NONCEBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(m.size, &c)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_stream_chacha20_xor(c.data, m.data, m.size, n.data, k.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &c);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_stream(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary c, n, k;
|
|
||||||
ErlNifUInt64 clen;
|
|
||||||
|
|
||||||
if ((argc != 3) || (!enif_get_uint64(env, argv[0], &clen)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &n)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &k))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((k.size != crypto_stream_KEYBYTES) ||
|
|
||||||
(n.size != crypto_stream_NONCEBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(clen, &c)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_stream(c.data, c.size, n.data, k.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &c);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_stream_xor(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary c, m, n, k;
|
|
||||||
|
|
||||||
if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &n)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &k))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((k.size != crypto_stream_KEYBYTES) ||
|
|
||||||
(n.size != crypto_stream_NONCEBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(m.size, &c)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_stream_xor(c.data, m.data, m.size, n.data, k.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &c);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_auth(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary a, m, k;
|
|
||||||
|
|
||||||
if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &k))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (k.size != crypto_auth_KEYBYTES) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_auth_BYTES, &a)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_auth(a.data, m.data, m.size, k.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &a);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_auth_verify(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary a, m, k;
|
|
||||||
|
|
||||||
if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &a)) ||
|
|
||||||
(!enif_inspect_iolist_as_binary(env, argv[1], &m)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &k))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((k.size != crypto_auth_KEYBYTES) || (a.size != crypto_auth_BYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == crypto_auth_verify(a.data, m.data, m.size, k.data)) {
|
|
||||||
return enif_make_atom(env, "true");
|
|
||||||
} else {
|
|
||||||
return enif_make_atom(env, "false");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_onetimeauth(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary a, m, k;
|
|
||||||
|
|
||||||
if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &k))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (k.size != crypto_onetimeauth_KEYBYTES) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_onetimeauth_BYTES, &a)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_onetimeauth(a.data, m.data, m.size, k.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &a);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_onetimeauth_verify(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary a, m, k;
|
|
||||||
|
|
||||||
if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &a)) ||
|
|
||||||
(!enif_inspect_iolist_as_binary(env, argv[1], &m)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &k))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((k.size != crypto_onetimeauth_KEYBYTES) ||
|
|
||||||
(a.size != crypto_onetimeauth_BYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == crypto_onetimeauth_verify(a.data, m.data, m.size, k.data)) {
|
|
||||||
return enif_make_atom(env, "true");
|
|
||||||
} else {
|
|
||||||
return enif_make_atom(env, "false");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
#ifndef ENACL_SECRET_H
|
|
||||||
#define ENACL_SECRET_H
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretbox_NONCEBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretbox_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretbox_ZEROBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretbox_BOXZEROBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_stream_chacha20_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_stream_chacha20_NONCEBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_stream_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_stream_NONCEBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_auth_BYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_auth_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_onetimeauth_BYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_onetimeauth_KEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretbox(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretbox_open(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretbox_easy(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretbox_open_easy(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_stream_chacha20(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_stream_chacha20_xor(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_stream(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_stream_xor(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_auth(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_auth_verify(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_onetimeauth(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_onetimeauth_verify(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,462 +0,0 @@
|
|||||||
#include <erl_nif.h>
|
|
||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include "enacl.h"
|
|
||||||
#include "secretstream.h"
|
|
||||||
|
|
||||||
typedef struct enacl_secretstream_ctx {
|
|
||||||
ErlNifMutex *mtx;
|
|
||||||
crypto_secretstream_xchacha20poly1305_state
|
|
||||||
*state; // The underlying secretstream state
|
|
||||||
int alive; // Is the context still valid for updates/finalization
|
|
||||||
} enacl_secretstream_ctx;
|
|
||||||
|
|
||||||
ErlNifResourceType *enacl_secretstream_ctx_rtype = NULL;
|
|
||||||
|
|
||||||
static void enacl_secretstream_ctx_dtor(ErlNifEnv *env,
|
|
||||||
enacl_secretstream_ctx *);
|
|
||||||
|
|
||||||
int enacl_init_secretstream_ctx(ErlNifEnv *env) {
|
|
||||||
enacl_secretstream_ctx_rtype =
|
|
||||||
enif_open_resource_type(env, NULL, "enacl_secretstream_context",
|
|
||||||
(ErlNifResourceDtor *)enacl_secretstream_ctx_dtor,
|
|
||||||
ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL);
|
|
||||||
|
|
||||||
if (enacl_secretstream_ctx_rtype == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void enacl_secretstream_ctx_dtor(ErlNifEnv *env,
|
|
||||||
enacl_secretstream_ctx *obj) {
|
|
||||||
if (!obj->alive) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->state)
|
|
||||||
sodium_memzero(obj->state,
|
|
||||||
crypto_secretstream_xchacha20poly1305_statebytes());
|
|
||||||
enif_free(obj->state);
|
|
||||||
|
|
||||||
if (obj->mtx != NULL)
|
|
||||||
enif_mutex_destroy(obj->mtx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Secretstream
|
|
||||||
*/
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_secretstream_xchacha20poly1305_ABYTES(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_ABYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_HEADERBYTES(
|
|
||||||
ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
|
|
||||||
return enif_make_int64(env,
|
|
||||||
crypto_secretstream_xchacha20poly1305_HEADERBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_KEYBYTES(
|
|
||||||
ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_KEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX(
|
|
||||||
ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
|
|
||||||
return enif_make_int64(
|
|
||||||
env, crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_MESSAGE(
|
|
||||||
ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
|
|
||||||
|
|
||||||
return enif_make_int64(env,
|
|
||||||
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_PUSH(
|
|
||||||
ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
|
|
||||||
|
|
||||||
return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_PUSH);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_REKEY(
|
|
||||||
ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
|
|
||||||
|
|
||||||
return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_REKEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_FINAL(
|
|
||||||
ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
|
|
||||||
|
|
||||||
return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_FINAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_secretstream_xchacha20poly1305_keygen(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]) {
|
|
||||||
|
|
||||||
ErlNifBinary key;
|
|
||||||
|
|
||||||
if (argc != 0) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_secretstream_xchacha20poly1305_KEYBYTES,
|
|
||||||
&key)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_secretstream_xchacha20poly1305_keygen(key.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
int crypto_secretstream_xchacha20poly1305_init_push
|
|
||||||
(crypto_secretstream_xchacha20poly1305_state *state,
|
|
||||||
unsigned char out[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
|
|
||||||
const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
|
|
||||||
*/
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_push(
|
|
||||||
ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
ErlNifBinary key, header;
|
|
||||||
enacl_secretstream_ctx *obj = NULL;
|
|
||||||
|
|
||||||
if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &key))) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key.size != crypto_secretstream_xchacha20poly1305_KEYBYTES) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_secretstream_xchacha20poly1305_HEADERBYTES,
|
|
||||||
&header)) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((obj = enif_alloc_resource(enacl_secretstream_ctx_rtype,
|
|
||||||
sizeof(enacl_secretstream_ctx))) == NULL) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto release_header;
|
|
||||||
}
|
|
||||||
obj->alive = 0;
|
|
||||||
obj->state = enif_alloc(crypto_secretstream_xchacha20poly1305_statebytes());
|
|
||||||
|
|
||||||
if (obj->state == NULL) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto release;
|
|
||||||
}
|
|
||||||
obj->alive = 1;
|
|
||||||
|
|
||||||
if ((obj->mtx = enif_mutex_create("enacl.secretstream")) == NULL) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto free;
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_secretstream_xchacha20poly1305_init_push(obj->state, header.data,
|
|
||||||
key.data);
|
|
||||||
|
|
||||||
ret = enif_make_tuple2(env, enif_make_binary(env, &header),
|
|
||||||
enif_make_resource(env, obj));
|
|
||||||
|
|
||||||
goto release;
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
free:
|
|
||||||
if (obj->alive)
|
|
||||||
if (obj->state != NULL) {
|
|
||||||
sodium_memzero(obj->state,
|
|
||||||
crypto_secretstream_xchacha20poly1305_statebytes());
|
|
||||||
enif_free(obj->state);
|
|
||||||
obj->state = NULL;
|
|
||||||
}
|
|
||||||
release_header:
|
|
||||||
enif_release_binary(&header);
|
|
||||||
release:
|
|
||||||
// This also frees the mutex via the destructor
|
|
||||||
enif_release_resource(obj);
|
|
||||||
done:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
crypto_secretstream_xchacha20poly1305_init_pull
|
|
||||||
(crypto_secretstream_xchacha20poly1305_state *state,
|
|
||||||
const unsigned char in[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
|
|
||||||
const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
|
|
||||||
*/
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_pull(
|
|
||||||
ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
ErlNifBinary header, key;
|
|
||||||
enacl_secretstream_ctx *obj = NULL;
|
|
||||||
|
|
||||||
if (argc != 2) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_inspect_binary(env, argv[0], &header)) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &key)) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((key.size != crypto_secretstream_xchacha20poly1305_KEYBYTES) ||
|
|
||||||
(header.size != crypto_secretstream_xchacha20poly1305_HEADERBYTES)) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((obj = enif_alloc_resource(enacl_secretstream_ctx_rtype,
|
|
||||||
sizeof(enacl_secretstream_ctx))) == NULL) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->alive = 0;
|
|
||||||
obj->state = enif_alloc(crypto_secretstream_xchacha20poly1305_statebytes());
|
|
||||||
|
|
||||||
if (obj->state == NULL) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto release;
|
|
||||||
}
|
|
||||||
obj->alive = 1;
|
|
||||||
|
|
||||||
if ((obj->mtx = enif_mutex_create("enacl.secretstream")) == NULL) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto free;
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_secretstream_xchacha20poly1305_init_pull(obj->state, header.data,
|
|
||||||
key.data);
|
|
||||||
|
|
||||||
ret = enif_make_resource(env, obj);
|
|
||||||
|
|
||||||
goto release;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
free:
|
|
||||||
if (obj->alive)
|
|
||||||
if (obj->state != NULL) {
|
|
||||||
sodium_memzero(obj->state,
|
|
||||||
crypto_secretstream_xchacha20poly1305_statebytes());
|
|
||||||
enif_free(obj->state);
|
|
||||||
obj->state = NULL;
|
|
||||||
}
|
|
||||||
release:
|
|
||||||
// This also frees the mutex via the destructor
|
|
||||||
enif_release_resource(obj);
|
|
||||||
done:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
void
|
|
||||||
crypto_secretstream_xchacha20poly1305_rekey
|
|
||||||
(crypto_secretstream_xchacha20poly1305_state *state)
|
|
||||||
*/
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_secretstream_xchacha20poly1305_rekey(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]) {
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
enacl_secretstream_ctx *obj = NULL;
|
|
||||||
|
|
||||||
if (argc != 1) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_get_resource(env, argv[0],
|
|
||||||
(ErlNifResourceType *)enacl_secretstream_ctx_rtype,
|
|
||||||
(void **)&obj)) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
enif_mutex_lock(obj->mtx);
|
|
||||||
if (!obj->alive) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_secretstream_xchacha20poly1305_rekey(obj->state);
|
|
||||||
|
|
||||||
ret = enif_make_atom(env, ATOM_OK);
|
|
||||||
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
err:
|
|
||||||
ret = enacl_error_finalized(env);
|
|
||||||
done:
|
|
||||||
enif_mutex_unlock(obj->mtx);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
int
|
|
||||||
crypto_secretstream_xchacha20poly1305_push
|
|
||||||
(crypto_secretstream_xchacha20poly1305_state *state,
|
|
||||||
unsigned char *out, unsigned long long *outlen_p,
|
|
||||||
const unsigned char *m, unsigned long long mlen,
|
|
||||||
const unsigned char *ad, unsigned long long adlen, unsigned char tag)
|
|
||||||
*/
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_secretstream_xchacha20poly1305_push(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]) {
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
ErlNifBinary m, ad, out;
|
|
||||||
ErlNifUInt64 tag;
|
|
||||||
enacl_secretstream_ctx *obj = NULL;
|
|
||||||
|
|
||||||
if (argc != 4) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_get_resource(env, argv[0],
|
|
||||||
(ErlNifResourceType *)enacl_secretstream_ctx_rtype,
|
|
||||||
(void **)&obj)) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &m)) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_inspect_binary(env, argv[2], &ad)) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_get_uint64(env, argv[3], &tag)) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(m.size + crypto_secretstream_xchacha20poly1305_ABYTES,
|
|
||||||
&out)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
enif_mutex_lock(obj->mtx);
|
|
||||||
if (!obj->alive) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_secretstream_xchacha20poly1305_push(obj->state, out.data, NULL, m.data,
|
|
||||||
m.size, ad.data, ad.size, tag);
|
|
||||||
|
|
||||||
if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL) {
|
|
||||||
if (obj->state) {
|
|
||||||
obj->alive = 0;
|
|
||||||
sodium_memzero(obj->state,
|
|
||||||
crypto_secretstream_xchacha20poly1305_statebytes());
|
|
||||||
enif_free(obj->state);
|
|
||||||
obj->state = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = enif_make_binary(env, &out);
|
|
||||||
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
err:
|
|
||||||
ret = enacl_error_finalized(env);
|
|
||||||
enif_release_binary(&out);
|
|
||||||
done:
|
|
||||||
enif_mutex_unlock(obj->mtx);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
crypto_secretstream_xchacha20poly1305_pull
|
|
||||||
(crypto_secretstream_xchacha20poly1305_state *state,
|
|
||||||
unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p,
|
|
||||||
const unsigned char *in, unsigned long long inlen,
|
|
||||||
const unsigned char *ad, unsigned long long adlen)
|
|
||||||
*/
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_secretstream_xchacha20poly1305_pull(ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]) {
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
ErlNifBinary m, in, ad;
|
|
||||||
unsigned char tag;
|
|
||||||
enacl_secretstream_ctx *obj = NULL;
|
|
||||||
|
|
||||||
if (argc != 3) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_get_resource(env, argv[0],
|
|
||||||
(ErlNifResourceType *)enacl_secretstream_ctx_rtype,
|
|
||||||
(void **)&obj)) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &in)) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in.size < crypto_secretstream_xchacha20poly1305_ABYTES) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_inspect_binary(env, argv[2], &ad)) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in.size < crypto_secretstream_xchacha20poly1305_ABYTES) {
|
|
||||||
goto bad_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(in.size - crypto_secretstream_xchacha20poly1305_ABYTES,
|
|
||||||
&m)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
enif_mutex_lock(obj->mtx);
|
|
||||||
if (!obj->alive) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != crypto_secretstream_xchacha20poly1305_pull(obj->state, m.data, NULL,
|
|
||||||
&tag, in.data, in.size,
|
|
||||||
ad.data, ad.size)) {
|
|
||||||
ret = enacl_error_tuple(env, "failed_verification");
|
|
||||||
goto release;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL) {
|
|
||||||
if (obj->state) {
|
|
||||||
obj->alive = 0;
|
|
||||||
sodium_memzero(obj->state,
|
|
||||||
crypto_secretstream_xchacha20poly1305_statebytes());
|
|
||||||
enif_free(obj->state);
|
|
||||||
obj->state = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = enif_make_tuple2(env, enif_make_binary(env, &m),
|
|
||||||
enif_make_int64(env, tag));
|
|
||||||
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
err:
|
|
||||||
ret = enacl_error_finalized(env);
|
|
||||||
release:
|
|
||||||
enif_release_binary(&m);
|
|
||||||
done:
|
|
||||||
enif_mutex_unlock(obj->mtx);
|
|
||||||
return ret;
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
#ifndef ENACL_SECRETSTREAM_H
|
|
||||||
#define ENACL_SECRETSTREAM_H
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
int enacl_init_secretstream_ctx(ErlNifEnv *env);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_ABYTES(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_HEADERBYTES(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_KEYBYTES(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_MESSAGE(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_PUSH(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_REKEY(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_FINAL(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_keygen(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_push(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_pull(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_rekey(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_push(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_pull(
|
|
||||||
ErlNifEnv *env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[]
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif
|
|
488
c_src/sign.c
488
c_src/sign.c
@ -1,488 +0,0 @@
|
|||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
#include "enacl.h"
|
|
||||||
#include "sign.h"
|
|
||||||
|
|
||||||
typedef struct enacl_sign_ctx {
|
|
||||||
ErlNifMutex *mtx;
|
|
||||||
crypto_sign_state *state; // The underlying signature state
|
|
||||||
int alive; // Is the context still valid for updates/finalization
|
|
||||||
} enacl_sign_ctx;
|
|
||||||
|
|
||||||
ErlNifResourceType *enacl_sign_ctx_rtype = NULL;
|
|
||||||
|
|
||||||
void enacl_sign_ctx_dtor(ErlNifEnv *env, enacl_sign_ctx *);
|
|
||||||
|
|
||||||
int enacl_init_sign_ctx(ErlNifEnv *env) {
|
|
||||||
enacl_sign_ctx_rtype =
|
|
||||||
enif_open_resource_type(env, NULL, "enacl_sign_context",
|
|
||||||
(ErlNifResourceDtor *)enacl_sign_ctx_dtor,
|
|
||||||
ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL);
|
|
||||||
|
|
||||||
if (enacl_sign_ctx_rtype == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void enacl_sign_ctx_dtor(ErlNifEnv *env, enacl_sign_ctx *obj) {
|
|
||||||
if (!obj->alive)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (obj->state) {
|
|
||||||
sodium_memzero(obj->state, crypto_sign_statebytes());
|
|
||||||
enif_free(obj->state);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->mtx != NULL)
|
|
||||||
enif_mutex_destroy(obj->mtx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
int crypto_sign_init(crypto_sign_state *state)
|
|
||||||
*/
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_init(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
enacl_sign_ctx *obj = NULL;
|
|
||||||
|
|
||||||
if (argc != 0)
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
if ((obj = enif_alloc_resource(enacl_sign_ctx_rtype,
|
|
||||||
sizeof(enacl_sign_ctx))) == NULL) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
obj->alive = 0;
|
|
||||||
obj->state = enif_alloc(crypto_sign_statebytes());
|
|
||||||
if (obj->state == NULL) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto release;
|
|
||||||
}
|
|
||||||
obj->alive = 1;
|
|
||||||
|
|
||||||
if ((obj->mtx = enif_mutex_create("enacl.sign")) == NULL) {
|
|
||||||
goto free;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != crypto_sign_init(obj->state)) {
|
|
||||||
goto free;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create return values
|
|
||||||
ret = enif_make_resource(env, obj);
|
|
||||||
|
|
||||||
goto release;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
free:
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
if (obj->alive)
|
|
||||||
if (obj->state != NULL) {
|
|
||||||
sodium_memzero(obj->state, crypto_sign_statebytes());
|
|
||||||
enif_free(obj->state);
|
|
||||||
obj->state = NULL;
|
|
||||||
}
|
|
||||||
release:
|
|
||||||
// This also frees the mutex via the destructor
|
|
||||||
enif_release_resource(obj);
|
|
||||||
done:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
int crypto_sign_update(crypto_sign_state *state,
|
|
||||||
const unsigned char *m,
|
|
||||||
unsigned long long mlen);
|
|
||||||
*/
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_update(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
enacl_sign_ctx *obj = NULL;
|
|
||||||
ErlNifBinary data;
|
|
||||||
|
|
||||||
// Validate the arguments
|
|
||||||
if (argc != 2)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_get_resource(env, argv[0], enacl_sign_ctx_rtype, (void **)&obj))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &data))
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
enif_mutex_lock(obj->mtx);
|
|
||||||
if (!obj->alive) {
|
|
||||||
ret = enacl_error_finalized(env);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != crypto_sign_update(obj->state, data.data, data.size)) {
|
|
||||||
ret = enacl_internal_error(env); // This should never be hit
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = argv[0];
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
done:
|
|
||||||
enif_mutex_unlock(obj->mtx);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_final_create(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
enacl_sign_ctx *obj = NULL;
|
|
||||||
ErlNifBinary sk, sig;
|
|
||||||
unsigned long long siglen;
|
|
||||||
|
|
||||||
if (argc != 2)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_get_resource(env, argv[0], enacl_sign_ctx_rtype, (void **)&obj))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &sk))
|
|
||||||
goto bad_arg;
|
|
||||||
if (sk.size != crypto_sign_SECRETKEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
enif_mutex_lock(obj->mtx);
|
|
||||||
if (!obj->alive) {
|
|
||||||
ret = enacl_error_finalized(env);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) {
|
|
||||||
ret = enacl_internal_error(env);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_sign_final_create(obj->state, sig.data, &siglen, sk.data);
|
|
||||||
|
|
||||||
ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK);
|
|
||||||
ERL_NIF_TERM signature = enif_make_binary(env, &sig);
|
|
||||||
|
|
||||||
ret = enif_make_tuple2(env, ok, signature);
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
cleanup:
|
|
||||||
obj->alive = 0;
|
|
||||||
sodium_memzero(obj->state, crypto_sign_statebytes());
|
|
||||||
enif_free(obj->state);
|
|
||||||
obj->state = NULL;
|
|
||||||
done:
|
|
||||||
enif_mutex_unlock(obj->mtx);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_final_verify(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary pk, sig;
|
|
||||||
enacl_sign_ctx *obj = NULL;
|
|
||||||
ERL_NIF_TERM ret;
|
|
||||||
|
|
||||||
if (argc != 3)
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_get_resource(env, argv[0], enacl_sign_ctx_rtype, (void **)&obj))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[1], &sig))
|
|
||||||
goto bad_arg;
|
|
||||||
if (!enif_inspect_binary(env, argv[2], &pk))
|
|
||||||
goto bad_arg;
|
|
||||||
if (pk.size != crypto_sign_PUBLICKEYBYTES)
|
|
||||||
goto bad_arg;
|
|
||||||
|
|
||||||
enif_mutex_lock(obj->mtx);
|
|
||||||
if (!obj->alive) {
|
|
||||||
ret = enacl_error_finalized(env);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == crypto_sign_final_verify(obj->state, sig.data, pk.data)) {
|
|
||||||
ret = enif_make_atom(env, "true");
|
|
||||||
} else {
|
|
||||||
ret = enif_make_atom(env, "false");
|
|
||||||
}
|
|
||||||
// Mark as done
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
bad_arg:
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
cleanup:
|
|
||||||
// Get rid of the context and mark it as dead
|
|
||||||
obj->alive = 0;
|
|
||||||
sodium_memzero(obj->state, crypto_sign_statebytes());
|
|
||||||
enif_free(obj->state);
|
|
||||||
obj->state = NULL;
|
|
||||||
done:
|
|
||||||
enif_mutex_unlock(obj->mtx);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ed 25519 */
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_sign_ed25519_keypair(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary pk, sk;
|
|
||||||
|
|
||||||
if (argc != 0) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_sign_ed25519_SECRETKEYBYTES, &sk)) {
|
|
||||||
enif_release_binary(&pk);
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_sign_ed25519_keypair(pk.data, sk.data);
|
|
||||||
|
|
||||||
return enif_make_tuple2(env, enif_make_binary(env, &pk),
|
|
||||||
enif_make_binary(env, &sk));
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_sign_ed25519_sk_to_pk(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary pk, sk;
|
|
||||||
|
|
||||||
if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &sk)) ||
|
|
||||||
(sk.size != crypto_sign_ed25519_SECRETKEYBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_sign_ed25519_sk_to_pk(pk.data, sk.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &pk);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_sign_ed25519_public_to_curve25519(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary curve25519_pk, ed25519_pk;
|
|
||||||
|
|
||||||
if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &ed25519_pk)) ||
|
|
||||||
(ed25519_pk.size != crypto_sign_ed25519_PUBLICKEYBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_pk)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crypto_sign_ed25519_pk_to_curve25519(curve25519_pk.data, ed25519_pk.data) != 0) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
return enif_make_binary(env, &curve25519_pk);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_sign_ed25519_secret_to_curve25519(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary curve25519_sk, ed25519_sk;
|
|
||||||
|
|
||||||
if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &ed25519_sk)) ||
|
|
||||||
(ed25519_sk.size != crypto_sign_ed25519_SECRETKEYBYTES)) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_sk)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_sign_ed25519_sk_to_curve25519(curve25519_sk.data, ed25519_sk.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &curve25519_sk);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_sign_ed25519_PUBLICKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_sign_ed25519_PUBLICKEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_sign_ed25519_SECRETKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_sign_ed25519_SECRETKEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_PUBLICKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_sign_PUBLICKEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_SECRETKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_sign_SECRETKEYBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_SEEDBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
return enif_make_int64(env, crypto_sign_SEEDBYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_keypair(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary pk, sk;
|
|
||||||
|
|
||||||
if (argc != 0) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) {
|
|
||||||
enif_release_binary(&pk);
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_sign_keypair(pk.data, sk.data);
|
|
||||||
|
|
||||||
return enif_make_tuple2(env, enif_make_binary(env, &pk),
|
|
||||||
enif_make_binary(env, &sk));
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_seed_keypair(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary pk, sk, seed;
|
|
||||||
|
|
||||||
if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &seed))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) {
|
|
||||||
enif_release_binary(&pk);
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_sign_seed_keypair(pk.data, sk.data, seed.data);
|
|
||||||
|
|
||||||
return enif_make_tuple2(env, enif_make_binary(env, &pk),
|
|
||||||
enif_make_binary(env, &sk));
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary m, sk, sm;
|
|
||||||
unsigned long long smlen;
|
|
||||||
|
|
||||||
if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &sk))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sk.size != crypto_sign_SECRETKEYBYTES) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(m.size + crypto_sign_BYTES, &sm)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_sign(sm.data, &smlen, m.data, m.size, sk.data);
|
|
||||||
|
|
||||||
return enif_make_sub_binary(env, enif_make_binary(env, &sm), 0, smlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_open(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary m, sm, pk;
|
|
||||||
unsigned long long mlen;
|
|
||||||
|
|
||||||
if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &sm)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &pk))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pk.size != crypto_sign_PUBLICKEYBYTES) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(sm.size, &m)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == crypto_sign_open(m.data, &mlen, sm.data, sm.size, pk.data)) {
|
|
||||||
ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK);
|
|
||||||
ERL_NIF_TERM ret_bin =
|
|
||||||
enif_make_sub_binary(env, enif_make_binary(env, &m), 0, mlen);
|
|
||||||
return enif_make_tuple2(env, ret_ok, ret_bin);
|
|
||||||
} else {
|
|
||||||
enif_release_binary(&m);
|
|
||||||
return enacl_error_tuple(env, "failed_verification");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_detached(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary m, sk, sig;
|
|
||||||
unsigned long long siglen;
|
|
||||||
|
|
||||||
if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[1], &sk))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sk.size != crypto_sign_SECRETKEYBYTES) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) {
|
|
||||||
return enacl_internal_error(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_sign_detached(sig.data, &siglen, m.data, m.size, sk.data);
|
|
||||||
|
|
||||||
return enif_make_binary(env, &sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_sign_verify_detached(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]) {
|
|
||||||
ErlNifBinary m, sig, pk;
|
|
||||||
|
|
||||||
if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &sig)) ||
|
|
||||||
(!enif_inspect_iolist_as_binary(env, argv[1], &m)) ||
|
|
||||||
(!enif_inspect_binary(env, argv[2], &pk))) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sig.size != crypto_sign_BYTES) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pk.size != crypto_sign_PUBLICKEYBYTES) {
|
|
||||||
return enif_make_badarg(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == crypto_sign_verify_detached(sig.data, m.data, m.size, pk.data)) {
|
|
||||||
return enif_make_atom(env, ATOM_TRUE);
|
|
||||||
} else {
|
|
||||||
return enif_make_atom(env, ATOM_FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
70
c_src/sign.h
70
c_src/sign.h
@ -1,70 +0,0 @@
|
|||||||
#ifndef ENACL_SIGN_H
|
|
||||||
#define ENACL_SIGN_H
|
|
||||||
|
|
||||||
#include <erl_nif.h>
|
|
||||||
|
|
||||||
int enacl_init_sign_ctx(ErlNifEnv *env);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_init(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_update(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_final_create(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_final_verify(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_ed25519_keypair(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_ed25519_sk_to_pk(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_sign_ed25519_public_to_curve25519(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_sign_ed25519_secret_to_curve25519(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_sign_ed25519_PUBLICKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_sign_ed25519_SECRETKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_PUBLICKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_SECRETKEYBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_SEEDBYTES(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_keypair(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_seed_keypair(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_open(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM enacl_crypto_sign_detached(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
ERL_NIF_TERM
|
|
||||||
enacl_crypto_sign_verify_detached(ErlNifEnv *env, int argc,
|
|
||||||
ERL_NIF_TERM const argv[]);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||||||
-module(enacl_eqc).
|
-module(enacl_eqc).
|
||||||
-include_lib("eqc/include/eqc.hrl").
|
-include_lib("eqc/include/eqc.hrl").
|
||||||
-compile([export_all, nowarn_export_all]).
|
-compile(export_all).
|
||||||
|
|
||||||
-ifndef(mini).
|
-ifndef(mini).
|
||||||
-compile({parse_transform, eqc_parallelize}).
|
-compile({parse_transform, eqc_parallelize}).
|
||||||
@ -83,8 +83,8 @@ v_binary(_, _) -> false.
|
|||||||
|
|
||||||
|
|
||||||
%% Typical generators based on the binaries
|
%% Typical generators based on the binaries
|
||||||
nonce() -> g_binary(enacl:box_NONCEBYTES()).
|
nonce() -> g_binary(enacl:box_nonce_size()).
|
||||||
nonce_valid(N) -> v_binary(enacl:box_NONCEBYTES(), N).
|
nonce_valid(N) -> v_binary(enacl:box_nonce_size(), N).
|
||||||
|
|
||||||
%% Generator of natural numbers
|
%% Generator of natural numbers
|
||||||
g_nat() ->
|
g_nat() ->
|
||||||
@ -111,10 +111,10 @@ keypair_bad() ->
|
|||||||
#{ public := PK, secret := SK} = enacl:box_keypair(),
|
#{ public := PK, secret := SK} = enacl:box_keypair(),
|
||||||
case X of
|
case X of
|
||||||
pk ->
|
pk ->
|
||||||
PKBytes = enacl:box_PUBLICKEYBYTES(),
|
PKBytes = enacl:box_public_key_bytes(),
|
||||||
{oneof([return(a), nat(), ?SUCHTHAT(B, binary(), byte_size(B) /= PKBytes)]), SK};
|
{oneof([return(a), nat(), ?SUCHTHAT(B, binary(), byte_size(B) /= PKBytes)]), SK};
|
||||||
sk ->
|
sk ->
|
||||||
SKBytes = enacl:box_SECRETKEYBYTES(),
|
SKBytes = enacl:box_secret_key_bytes(),
|
||||||
{PK, oneof([return(a), nat(), ?SUCHTHAT(B, binary(), byte_size(B) /= SKBytes)])}
|
{PK, oneof([return(a), nat(), ?SUCHTHAT(B, binary(), byte_size(B) /= SKBytes)])}
|
||||||
end
|
end
|
||||||
end).
|
end).
|
||||||
@ -122,35 +122,6 @@ keypair_bad() ->
|
|||||||
keypair() ->
|
keypair() ->
|
||||||
?FAULT(keypair_bad(), keypair_good()).
|
?FAULT(keypair_bad(), keypair_good()).
|
||||||
|
|
||||||
kx_keypair_good() ->
|
|
||||||
#{ public := PK, secret := SK} = enacl:kx_keypair(),
|
|
||||||
{PK, SK}.
|
|
||||||
|
|
||||||
kx_keypair_bad() ->
|
|
||||||
?LET(X, elements([pk, sk]),
|
|
||||||
begin
|
|
||||||
#{ public := PK, secret := SK} = enacl:box_keypair(),
|
|
||||||
case X of
|
|
||||||
pk ->
|
|
||||||
PKBytes = enacl:kx_public_key_size(),
|
|
||||||
{oneof([return(a), nat(), ?SUCHTHAT(B, binary(), byte_size(B) /= PKBytes)]), SK};
|
|
||||||
sk ->
|
|
||||||
SKBytes = enacl:kx_secret_key_size(),
|
|
||||||
{PK, oneof([return(a), nat(), ?SUCHTHAT(B, binary(), byte_size(B) /= SKBytes)])}
|
|
||||||
end
|
|
||||||
end).
|
|
||||||
|
|
||||||
g_generichash_data() ->
|
|
||||||
binary().
|
|
||||||
|
|
||||||
g_generichash_key() ->
|
|
||||||
?LET({Min, Max}, {return(enacl_nif:crypto_generichash_KEYBYTES_MIN()), return(enacl_nif:crypto_generichash_KEYBYTES_MAX())},
|
|
||||||
largebinary({limit, Min, Max})).
|
|
||||||
|
|
||||||
g_generichash_size() ->
|
|
||||||
?LET({Min, Max}, {return(enacl_nif:crypto_generichash_BYTES_MIN()), return(enacl_nif:crypto_generichash_BYTES_MAX())},
|
|
||||||
choose(Min, Max)).
|
|
||||||
|
|
||||||
%% CRYPTO BOX
|
%% CRYPTO BOX
|
||||||
%% ---------------------------
|
%% ---------------------------
|
||||||
%% * box/4
|
%% * box/4
|
||||||
@ -159,8 +130,8 @@ g_generichash_size() ->
|
|||||||
%% * box_afternm/3
|
%% * box_afternm/3
|
||||||
%% * box_open_afternm/3
|
%% * box_open_afternm/3
|
||||||
keypair_valid(PK, SK) when is_binary(PK), is_binary(SK) ->
|
keypair_valid(PK, SK) when is_binary(PK), is_binary(SK) ->
|
||||||
PKBytes = enacl:box_PUBLICKEYBYTES(),
|
PKBytes = enacl:box_public_key_bytes(),
|
||||||
SKBytes = enacl:box_SECRETKEYBYTES(),
|
SKBytes = enacl:box_secret_key_bytes(),
|
||||||
byte_size(PK) == PKBytes andalso byte_size(SK) == SKBytes;
|
byte_size(PK) == PKBytes andalso byte_size(SK) == SKBytes;
|
||||||
keypair_valid(_PK, _SK) -> false.
|
keypair_valid(_PK, _SK) -> false.
|
||||||
|
|
||||||
@ -264,11 +235,11 @@ beforenm_key() ->
|
|||||||
oneof([
|
oneof([
|
||||||
elements([a,b,c]),
|
elements([a,b,c]),
|
||||||
real(),
|
real(),
|
||||||
?SUCHTHAT(X, binary(), byte_size(X) /= enacl:box_BEFORENMBYTES())
|
?SUCHTHAT(X, binary(), byte_size(X) /= enacl:box_beforenm_bytes())
|
||||||
])
|
])
|
||||||
end).
|
end).
|
||||||
|
|
||||||
v_key(K) when is_binary(K) -> byte_size(K) == enacl:box_BEFORENMBYTES();
|
v_key(K) when is_binary(K) -> byte_size(K) == enacl:box_beforenm_bytes();
|
||||||
v_key(_) -> false.
|
v_key(_) -> false.
|
||||||
|
|
||||||
prop_beforenm_correct() ->
|
prop_beforenm_correct() ->
|
||||||
@ -324,11 +295,11 @@ sign_keypair_bad() ->
|
|||||||
KP = enacl:sign_keypair(),
|
KP = enacl:sign_keypair(),
|
||||||
case X of
|
case X of
|
||||||
pk ->
|
pk ->
|
||||||
Sz = enacl:sign_PUBLICBYTES(),
|
Sz = enacl:sign_keypair_public_size(),
|
||||||
?LET(Wrong, oneof([a, int(), ?SUCHTHAT(B, binary(), byte_size(B) /= Sz)]),
|
?LET(Wrong, oneof([a, int(), ?SUCHTHAT(B, binary(), byte_size(B) /= Sz)]),
|
||||||
KP#{ public := Wrong });
|
KP#{ public := Wrong });
|
||||||
sk ->
|
sk ->
|
||||||
Sz = enacl:sign_SECRETBYTES(),
|
Sz = enacl:sign_keypair_secret_size(),
|
||||||
?LET(Wrong, oneof([a, int(), ?SUCHTHAT(B, binary(), byte_size(B) /= Sz)]),
|
?LET(Wrong, oneof([a, int(), ?SUCHTHAT(B, binary(), byte_size(B) /= Sz)]),
|
||||||
KP#{ secret := Wrong })
|
KP#{ secret := Wrong })
|
||||||
end
|
end
|
||||||
@ -342,12 +313,12 @@ sign_keypair() ->
|
|||||||
|
|
||||||
sign_keypair_public_valid(#{ public := Public })
|
sign_keypair_public_valid(#{ public := Public })
|
||||||
when is_binary(Public) ->
|
when is_binary(Public) ->
|
||||||
byte_size(Public) == enacl:sign_PUBLICBYTES();
|
byte_size(Public) == enacl:sign_keypair_public_size();
|
||||||
sign_keypair_public_valid(_) -> false.
|
sign_keypair_public_valid(_) -> false.
|
||||||
|
|
||||||
sign_keypair_secret_valid(#{ secret := Secret })
|
sign_keypair_secret_valid(#{ secret := Secret })
|
||||||
when is_binary(Secret) ->
|
when is_binary(Secret) ->
|
||||||
byte_size(Secret) == enacl:sign_SECRETBYTES();
|
byte_size(Secret) == enacl:sign_keypair_secret_size();
|
||||||
sign_keypair_secret_valid(_) -> false.
|
sign_keypair_secret_valid(_) -> false.
|
||||||
|
|
||||||
sign_keypair_valid(KP) ->
|
sign_keypair_valid(KP) ->
|
||||||
@ -408,18 +379,18 @@ signed_message_good_d(M) ->
|
|||||||
end)}]).
|
end)}]).
|
||||||
|
|
||||||
signed_message_bad() ->
|
signed_message_bad() ->
|
||||||
Sz = enacl:sign_PUBLICBYTES(),
|
Sz = enacl:sign_keypair_public_size(),
|
||||||
{binary(), oneof([a, int(), ?SUCHTHAT(B, binary(Sz), byte_size(B) /= Sz)])}.
|
{binary(), oneof([a, int(), ?SUCHTHAT(B, binary(Sz), byte_size(B) /= Sz)])}.
|
||||||
|
|
||||||
signed_message_bad_d() ->
|
signed_message_bad_d() ->
|
||||||
Sz = enacl:sign_PUBLICBYTES(),
|
Sz = enacl:sign_keypair_public_size(),
|
||||||
{binary(), oneof([a, int(), ?SUCHTHAT(B, binary(Sz), byte_size(B) /= Sz)])}.
|
{binary(), oneof([a, int(), ?SUCHTHAT(B, binary(Sz), byte_size(B) /= Sz)])}.
|
||||||
|
|
||||||
signed_message(M) ->
|
signed_message(M) ->
|
||||||
?FAULT(signed_message_bad(), signed_message_good(M)).
|
?FAULT(signed_message_bad(), signed_message_good(M)).
|
||||||
|
|
||||||
signed_message_d(M) ->
|
signed_message_d(M) ->
|
||||||
?FAULT(signed_message_bad_d(), signed_message_good_d(M)).
|
?FAULT(signed_message_bad(), signed_message_good(M)).
|
||||||
|
|
||||||
signed_message_valid({valid, _}, _) -> true;
|
signed_message_valid({valid, _}, _) -> true;
|
||||||
signed_message_valid({invalid, _}, _) -> true;
|
signed_message_valid({invalid, _}, _) -> true;
|
||||||
@ -432,9 +403,9 @@ prop_sign_detached_open() ->
|
|||||||
true ->
|
true ->
|
||||||
case SignMsg of
|
case SignMsg of
|
||||||
{valid, Sig} ->
|
{valid, Sig} ->
|
||||||
equals(true, enacl:sign_verify_detached(Sig, Msg, PK));
|
equals({ok, Msg}, enacl:sign_verify_detached(Sig, Msg, PK));
|
||||||
{invalid, Sig} ->
|
{invalid, Sig} ->
|
||||||
equals(false, enacl:sign_verify_detached(Sig, Msg, PK))
|
equals({error, failed_verification}, enacl:sign_verify_detached(Sig, Msg, PK))
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
badargs(fun() -> enacl:sign_verify_detached(SignMsg, Msg, PK) end)
|
badargs(fun() -> enacl:sign_verify_detached(SignMsg, Msg, PK) end)
|
||||||
@ -496,19 +467,19 @@ prop_seal_box_correct() ->
|
|||||||
%% * secretbox/3
|
%% * secretbox/3
|
||||||
%% * secretbo_open/3
|
%% * secretbo_open/3
|
||||||
secret_key_good() ->
|
secret_key_good() ->
|
||||||
Sz = enacl:secretbox_KEYBYTES(),
|
Sz = enacl:secretbox_key_size(),
|
||||||
binary(Sz).
|
binary(Sz).
|
||||||
|
|
||||||
secret_key_bad() ->
|
secret_key_bad() ->
|
||||||
oneof([return(a),
|
oneof([return(a),
|
||||||
nat(),
|
nat(),
|
||||||
?SUCHTHAT(B, binary(), byte_size(B) /= enacl:secretbox_KEYBYTES())]).
|
?SUCHTHAT(B, binary(), byte_size(B) /= enacl:secretbox_key_size())]).
|
||||||
|
|
||||||
secret_key() ->
|
secret_key() ->
|
||||||
?FAULT(secret_key_bad(), secret_key_good()).
|
?FAULT(secret_key_bad(), secret_key_good()).
|
||||||
|
|
||||||
secret_key_valid(SK) when is_binary(SK) ->
|
secret_key_valid(SK) when is_binary(SK) ->
|
||||||
Sz = enacl:secretbox_KEYBYTES(),
|
Sz = enacl:secretbox_key_size(),
|
||||||
byte_size(SK) == Sz;
|
byte_size(SK) == Sz;
|
||||||
secret_key_valid(_SK) -> false.
|
secret_key_valid(_SK) -> false.
|
||||||
|
|
||||||
@ -550,87 +521,24 @@ prop_secretbox_failure_integrity() ->
|
|||||||
equals(Err, {error, failed_verification})
|
equals(Err, {error, failed_verification})
|
||||||
end).
|
end).
|
||||||
|
|
||||||
secretbox_easy(Msg, Nonce, Key) ->
|
|
||||||
try enacl:secretbox_easy(Msg, Nonce, Key)
|
|
||||||
catch error:badarg -> badarg
|
|
||||||
end.
|
|
||||||
|
|
||||||
secretbox_open_easy(Msg, Nonce, Key) ->
|
|
||||||
try enacl:secretbox_open_easy(Msg, Nonce, Key)
|
|
||||||
catch error:badarg -> badarg
|
|
||||||
end.
|
|
||||||
|
|
||||||
prop_secretbox_easy_correct() ->
|
|
||||||
?FORALL({Msg, Nonce, Key},
|
|
||||||
{?FAULT_RATE(1, 40, g_iodata()),
|
|
||||||
?FAULT_RATE(1, 40, nonce()),
|
|
||||||
?FAULT_RATE(1, 40, secret_key())},
|
|
||||||
begin
|
|
||||||
case v_iodata(Msg) andalso nonce_valid(Nonce) andalso secret_key_valid(Key) of
|
|
||||||
true ->
|
|
||||||
CipherText = enacl:secretbox_easy(Msg, Nonce, Key),
|
|
||||||
{ok, DecodedMsg} = enacl:secretbox_open_easy(CipherText, Nonce, Key),
|
|
||||||
equals(iolist_to_binary(Msg), DecodedMsg);
|
|
||||||
false ->
|
|
||||||
case secretbox_easy(Msg, Nonce, Key) of
|
|
||||||
badarg -> true;
|
|
||||||
Res ->
|
|
||||||
failure(secretbox_open_easy(Res, Nonce, Key))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end).
|
|
||||||
|
|
||||||
prop_secretbox_easy_failure_integrity() ->
|
|
||||||
?FORALL({Msg, Nonce, Key}, {g_iodata(), nonce(), secret_key()},
|
|
||||||
begin
|
|
||||||
CipherText = enacl:secretbox_easy(Msg, Nonce, Key),
|
|
||||||
Err = enacl:secretbox_open_easy([<<"x">>, CipherText], Nonce, Key),
|
|
||||||
equals(Err, {error, failed_verification})
|
|
||||||
end).
|
|
||||||
|
|
||||||
%% AEAD ChaCha20Poly1305
|
%% AEAD ChaCha20Poly1305
|
||||||
%% ------------------------------------------------------------
|
%% ------------------------------------------------------------
|
||||||
%% * aead_chacha20poly1305_encrypt/4,
|
%% * aead_chacha20poly1305_encrypt/4,
|
||||||
%% * aead_chacha20poly1305_decrypt/4,
|
%% * aead_chacha20poly1305_decrypt/4,
|
||||||
prop_aead_chacha20poly1305_ietf() ->
|
prop_aead_chacha20poly1305() ->
|
||||||
NPubBytes = enacl:aead_chacha20poly1305_ietf_NPUBBYTES(),
|
|
||||||
?FORALL({Key, Msg, AD, Nonce},
|
?FORALL({Key, Msg, AD, Nonce},
|
||||||
{binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), binary(NPubBytes)},
|
{binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), largeint()},
|
||||||
begin
|
begin
|
||||||
EncryptMsg = enacl:aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key),
|
EncryptMsg = enacl:aead_chacha20poly1305_encrypt(Key, Nonce, AD, Msg),
|
||||||
equals(enacl:aead_chacha20poly1305_ietf_decrypt(EncryptMsg, AD, Nonce, Key), Msg)
|
equals(enacl:aead_chacha20poly1305_decrypt(Key, Nonce, AD, EncryptMsg), Msg)
|
||||||
end).
|
end).
|
||||||
|
|
||||||
prop_aead_chacha20poly1305_ietf_fail() ->
|
prop_aead_chacha20poly1305_fail() ->
|
||||||
NPubBytes = enacl:aead_chacha20poly1305_ietf_NPUBBYTES(),
|
|
||||||
?FORALL({Key, Msg, AD, Nonce},
|
?FORALL({Key, Msg, AD, Nonce},
|
||||||
{binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), binary(NPubBytes)},
|
{binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), largeint()},
|
||||||
begin
|
begin
|
||||||
EncryptMsg = enacl:aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key),
|
EncryptMsg = enacl:aead_chacha20poly1305_encrypt(Key, Nonce, AD, Msg),
|
||||||
case enacl:aead_chacha20poly1305_ietf_decrypt(<<0:8, EncryptMsg/binary>>, AD, Nonce, Key) of
|
case enacl:aead_chacha20poly1305_decrypt(Key, Nonce, AD, <<0:8, EncryptMsg/binary>>) of
|
||||||
{error, _} -> true;
|
|
||||||
_ -> false
|
|
||||||
end
|
|
||||||
end).
|
|
||||||
|
|
||||||
%% * aead_xchacha20poly1305_encrypt/4,
|
|
||||||
%% * aead_xchacha20poly1305_decrypt/4,
|
|
||||||
prop_aead_xchacha20poly1305_ietf() ->
|
|
||||||
NPubBytes = enacl:aead_xchacha20poly1305_ietf_NPUBBYTES(),
|
|
||||||
?FORALL({Key, Msg, AD, Nonce},
|
|
||||||
{binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), binary(NPubBytes)},
|
|
||||||
begin
|
|
||||||
EncryptMsg = enacl:aead_xchacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key),
|
|
||||||
equals(enacl:aead_xchacha20poly1305_ietf_decrypt(EncryptMsg, AD, Nonce, Key), Msg)
|
|
||||||
end).
|
|
||||||
|
|
||||||
prop_aead_xchacha20poly1305_ietf_fail() ->
|
|
||||||
NPubBytes = enacl:aead_xchacha20poly1305_ietf_NPUBBYTES(),
|
|
||||||
?FORALL({Key, Msg, AD, Nonce},
|
|
||||||
{binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), binary(NPubBytes)},
|
|
||||||
begin
|
|
||||||
EncryptMsg = enacl:aead_xchacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key),
|
|
||||||
case enacl:aead_xchacha20poly1305_ietf_decrypt(<<0:8, EncryptMsg/binary>>, AD, Nonce, Key) of
|
|
||||||
{error, _} -> true;
|
{error, _} -> true;
|
||||||
_ -> false
|
_ -> false
|
||||||
end
|
end
|
||||||
@ -656,26 +564,23 @@ xor_bytes(<<A, As/binary>>, <<B, Bs/binary>>) ->
|
|||||||
[A bxor B | xor_bytes(As, Bs)];
|
[A bxor B | xor_bytes(As, Bs)];
|
||||||
xor_bytes(<<>>, <<>>) -> [].
|
xor_bytes(<<>>, <<>>) -> [].
|
||||||
|
|
||||||
positive() ->
|
%% prop_stream_xor_correct() ->
|
||||||
?LET(N, nat(), N+1).
|
%% ?FORALL({Msg, Nonce, Key},
|
||||||
|
%% {?FAULT_RATE(1, 40, g_iodata()),
|
||||||
chacha20_nonce() ->
|
%% ?FAULT_RATE(1, 40, nonce()),
|
||||||
Sz = enacl:stream_chacha20_NONCEBYTES(),
|
%% ?FAULT_RATE(1, 40, secret_key())},
|
||||||
binary(Sz).
|
%% case v_iodata(Msg) andalso nonce_valid(Nonce) andalso secret_key_valid(Key) of
|
||||||
|
%% true ->
|
||||||
chacha20_key() ->
|
%% Stream = enacl:stream(iolist_size(Msg), Nonce, Key),
|
||||||
Sz = enacl:stream_chacha20_KEYBYTES(),
|
%% CipherText = enacl:stream_xor(Msg, Nonce, Key),
|
||||||
binary(Sz).
|
%% StreamXor = enacl:stream_xor(CipherText, Nonce, Key),
|
||||||
|
%% conjunction([
|
||||||
prop_stream_chacha20_correct() ->
|
%% {'xor', equals(iolist_to_binary(Msg), StreamXor)},
|
||||||
?FORALL(Len, positive(),
|
%% {stream, equals(iolist_to_binary(xor_bytes(Stream, iolist_to_binary(Msg))), CipherText)}
|
||||||
?FORALL({Msg, Nonce, Key}, {binary(Len), chacha20_nonce(), chacha20_key()},
|
%% ]);
|
||||||
begin
|
%% false ->
|
||||||
CT = enacl:stream_chacha20_xor(Msg, Nonce, Key),
|
%% badargs(fun() -> enacl:stream_xor(Msg, Nonce, Key) end)
|
||||||
Stream = enacl:stream_chacha20(Len, Nonce, Key),
|
%% end).
|
||||||
CT2 = list_to_binary(xor_bytes(Stream, Msg)),
|
|
||||||
equals(CT, CT2)
|
|
||||||
end)).
|
|
||||||
|
|
||||||
%% CRYPTO AUTH
|
%% CRYPTO AUTH
|
||||||
%% ------------------------------------------------------------
|
%% ------------------------------------------------------------
|
||||||
@ -694,19 +599,19 @@ prop_auth_correct() ->
|
|||||||
end).
|
end).
|
||||||
|
|
||||||
authenticator_bad() ->
|
authenticator_bad() ->
|
||||||
oneof([a, int(), ?SUCHTHAT(X, binary(), byte_size(X) /= enacl:auth_BYTES())]).
|
oneof([a, int(), ?SUCHTHAT(X, binary(), byte_size(X) /= enacl:auth_size())]).
|
||||||
|
|
||||||
authenticator_good(Msg, Key) when is_binary(Key) ->
|
authenticator_good(Msg, Key) when is_binary(Key) ->
|
||||||
Sz = enacl:secretbox_KEYBYTES(),
|
Sz = enacl:secretbox_key_size(),
|
||||||
case v_iodata(Msg) andalso byte_size(Key) == Sz of
|
case v_iodata(Msg) andalso byte_size(Key) == Sz of
|
||||||
true ->
|
true ->
|
||||||
frequency([{1, ?LAZY({invalid, binary(enacl:auth_BYTES())})},
|
frequency([{1, ?LAZY({invalid, binary(enacl:auth_size())})},
|
||||||
{3, return({valid, enacl:auth(Msg, Key)})}]);
|
{3, return({valid, enacl:auth(Msg, Key)})}]);
|
||||||
false ->
|
false ->
|
||||||
binary(enacl:auth_BYTES())
|
binary(enacl:auth_size())
|
||||||
end;
|
end;
|
||||||
authenticator_good(_Msg, _Key) ->
|
authenticator_good(_Msg, _Key) ->
|
||||||
binary(enacl:auth_BYTES()).
|
binary(enacl:auth_size()).
|
||||||
|
|
||||||
authenticator(Msg, Key) ->
|
authenticator(Msg, Key) ->
|
||||||
?FAULT(authenticator_bad(), authenticator_good(Msg, Key)).
|
?FAULT(authenticator_bad(), authenticator_good(Msg, Key)).
|
||||||
@ -749,19 +654,19 @@ prop_onetimeauth_correct() ->
|
|||||||
end).
|
end).
|
||||||
|
|
||||||
ot_authenticator_bad() ->
|
ot_authenticator_bad() ->
|
||||||
oneof([a, int(), ?SUCHTHAT(X, binary(), byte_size(X) /= enacl:onetime_auth_BYTES())]).
|
oneof([a, int(), ?SUCHTHAT(X, binary(), byte_size(X) /= enacl:onetime_auth_size())]).
|
||||||
|
|
||||||
ot_authenticator_good(Msg, Key) when is_binary(Key) ->
|
ot_authenticator_good(Msg, Key) when is_binary(Key) ->
|
||||||
Sz = enacl:secretbox_KEYBYTES(),
|
Sz = enacl:secretbox_key_size(),
|
||||||
case v_iodata(Msg) andalso byte_size(Key) == Sz of
|
case v_iodata(Msg) andalso byte_size(Key) == Sz of
|
||||||
true ->
|
true ->
|
||||||
frequency([{1, ?LAZY({invalid, binary(enacl:onetime_auth_BYTES())})},
|
frequency([{1, ?LAZY({invalid, binary(enacl:onetime_auth_size())})},
|
||||||
{3, return({valid, enacl:onetime_auth(Msg, Key)})}]);
|
{3, return({valid, enacl:onetime_auth(Msg, Key)})}]);
|
||||||
false ->
|
false ->
|
||||||
binary(enacl:onetime_auth_BYTES())
|
binary(enacl:onetime_auth_size())
|
||||||
end;
|
end;
|
||||||
ot_authenticator_good(_Msg, _Key) ->
|
ot_authenticator_good(_Msg, _Key) ->
|
||||||
binary(enacl:auth_BYTES()).
|
binary(enacl:auth_size()).
|
||||||
|
|
||||||
ot_authenticator(Msg, Key) ->
|
ot_authenticator(Msg, Key) ->
|
||||||
?FAULT(ot_authenticator_bad(), ot_authenticator_good(Msg, Key)).
|
?FAULT(ot_authenticator_bad(), ot_authenticator_good(Msg, Key)).
|
||||||
@ -799,13 +704,6 @@ pwhash(Passwd, Salt) ->
|
|||||||
error:badarg -> badarg
|
error:badarg -> badarg
|
||||||
end.
|
end.
|
||||||
|
|
||||||
pwhash(Password, Salt, Ops, Mem, Alg) ->
|
|
||||||
try
|
|
||||||
enacl:pwhsah(Password, Salt, Ops, Mem, Alg)
|
|
||||||
catch
|
|
||||||
error:badarg -> badarg
|
|
||||||
end.
|
|
||||||
|
|
||||||
pwhash_str(Passwd) ->
|
pwhash_str(Passwd) ->
|
||||||
try
|
try
|
||||||
enacl:pwhash_str(Passwd)
|
enacl:pwhash_str(Passwd)
|
||||||
@ -820,36 +718,20 @@ pwhash_str_verify(PasswdHash, Passwd) ->
|
|||||||
error:badarg -> badarg
|
error:badarg -> badarg
|
||||||
end.
|
end.
|
||||||
|
|
||||||
prop_pwhash() ->
|
|
||||||
?FORALL({Password, Salt, OLimit, MLimit, Alg},
|
|
||||||
{binary(16),
|
|
||||||
binary(16),
|
|
||||||
elements([interactive, moderate]), %% These could add senstitive, but are too runtime-expensive
|
|
||||||
elements([interactive, moderate]), %% And that is for a reason.
|
|
||||||
elements([default, 'argon2id13'])}, %% Argon2I13 uses different limits, so it is kept out as
|
|
||||||
%% this would otherwise fail
|
|
||||||
begin
|
|
||||||
Bin1 = enacl:pwhash(Password, Salt, OLimit, MLimit, Alg),
|
|
||||||
Bin2 = enacl:pwhash(Password, Salt, OLimit, MLimit, Alg),
|
|
||||||
equals(Bin1, Bin2)
|
|
||||||
end).
|
|
||||||
|
|
||||||
prop_pwhash_str_verify() ->
|
prop_pwhash_str_verify() ->
|
||||||
?FORALL({Passwd, OLimit, MLimit},
|
?FORALL({Passwd},
|
||||||
{?FAULT_RATE(1, 40, g_iodata()),
|
{?FAULT_RATE(1, 40, g_iodata())},
|
||||||
elements([interactive, moderate]),
|
begin
|
||||||
elements([interactive, moderate])},
|
case v_iodata(Passwd) of
|
||||||
begin
|
true ->
|
||||||
case v_iodata(Passwd) of
|
{ok, Ascii} = enacl:pwhash_str(Passwd),
|
||||||
true ->
|
S = enacl:pwhash_str_verify(Ascii, Passwd),
|
||||||
Ascii = enacl:pwhash_str(Passwd, OLimit, MLimit),
|
equals(S, true);
|
||||||
S = enacl:pwhash_str_verify(Ascii, Passwd),
|
false ->
|
||||||
equals(S, true);
|
badargs(fun() -> enacl:pwhash_str(Passwd) end),
|
||||||
false ->
|
badargs(fun() -> enacl:pwhash_str_verify("", Passwd) end)
|
||||||
badargs(fun() -> enacl:pwhash_str(Passwd) end),
|
end
|
||||||
badargs(fun() -> enacl:pwhash_str_verify("", Passwd) end)
|
end).
|
||||||
end
|
|
||||||
end).
|
|
||||||
|
|
||||||
%% SUBTLE HASHING
|
%% SUBTLE HASHING
|
||||||
%% ---------------------------
|
%% ---------------------------
|
||||||
@ -876,41 +758,6 @@ prop_crypto_hash_neq() ->
|
|||||||
enacl:hash(X) /= enacl:hash(Y)
|
enacl:hash(X) /= enacl:hash(Y)
|
||||||
).
|
).
|
||||||
|
|
||||||
prop_crypto_shorthash_eq() ->
|
|
||||||
?FORALL(X, g_iodata(),
|
|
||||||
case v_iodata(X) of
|
|
||||||
true -> equals(enacl:hash(X), enacl:hash(X));
|
|
||||||
false ->
|
|
||||||
try
|
|
||||||
enacl:hash(X),
|
|
||||||
false
|
|
||||||
catch
|
|
||||||
error:badarg -> true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
).
|
|
||||||
prop_crypto_generichash_eq() ->
|
|
||||||
?FORALL({Sz, X, Key}, {g_generichash_size(), g_generichash_data(), g_generichash_key()},
|
|
||||||
equals(enacl:generichash(Sz, X, Key), enacl:generichash(Sz, X, Key))).
|
|
||||||
|
|
||||||
generichash_loop(S, []) -> S;
|
|
||||||
generichash_loop(S, [M|Ms]) ->
|
|
||||||
S2 = enacl:generichash_update(S, M),
|
|
||||||
generichash_loop(S2, Ms).
|
|
||||||
|
|
||||||
prop_crypto_generichash_multi_part_eq() ->
|
|
||||||
?FORALL({Sz, Xs, Key}, {g_generichash_size(), list(g_generichash_data()), g_generichash_key()},
|
|
||||||
begin
|
|
||||||
S1 = generichash_loop(enacl:generichash_init(Sz, Key), Xs),
|
|
||||||
S2 = generichash_loop(enacl:generichash_init(Sz, Key), Xs),
|
|
||||||
equals(enacl:generichash_final(S1), enacl:generichash_final(S2))
|
|
||||||
end).
|
|
||||||
|
|
||||||
prop_crypto_shorthash_neq() ->
|
|
||||||
?FORALL({X, Y}, diff_pair(),
|
|
||||||
enacl:hash(X) /= enacl:hash(Y)
|
|
||||||
).
|
|
||||||
|
|
||||||
%% STRING COMPARISON
|
%% STRING COMPARISON
|
||||||
%% -------------------------
|
%% -------------------------
|
||||||
%% * verify_16/2,
|
%% * verify_16/2,
|
||||||
@ -970,8 +817,7 @@ prop_randombytes() ->
|
|||||||
?FORALL(X, g_nat(),
|
?FORALL(X, g_nat(),
|
||||||
case is_nat(X) of
|
case is_nat(X) of
|
||||||
true ->
|
true ->
|
||||||
R = enacl:randombytes(X),
|
is_binary(enacl:randombytes(X));
|
||||||
is_binary(R) andalso (byte_size(R) == X);
|
|
||||||
false ->
|
false ->
|
||||||
try
|
try
|
||||||
enacl:randombytes(X),
|
enacl:randombytes(X),
|
||||||
@ -982,84 +828,8 @@ prop_randombytes() ->
|
|||||||
end
|
end
|
||||||
end).
|
end).
|
||||||
|
|
||||||
prop_randombytes_uint32() ->
|
|
||||||
?FORALL(_, return(x),
|
|
||||||
begin
|
|
||||||
V = enacl:randombytes_uint32(),
|
|
||||||
is_integer(V)
|
|
||||||
end).
|
|
||||||
|
|
||||||
%% KX
|
|
||||||
%% ---------------------------
|
|
||||||
prop_kx() ->
|
|
||||||
?FORALL({{CPK, CSK}, {SPK, SSK}}, {kx_keypair_good(), kx_keypair_good()},
|
|
||||||
begin
|
|
||||||
#{ client_tx := CTX, client_rx := CRX} = enacl:kx_client_session_keys(CPK, CSK, SPK),
|
|
||||||
#{ server_tx := STX, server_rx := SRX} = enacl:kx_server_session_keys(SPK, SSK, CPK),
|
|
||||||
%% This keypair must be shared in both directions
|
|
||||||
conjunction([{ctx_srx, equals(CTX, SRX)}, {stx_crx, equals(STX, CRX)}])
|
|
||||||
end).
|
|
||||||
|
|
||||||
%% SCRAMBLING
|
|
||||||
prop_scramble_block() ->
|
|
||||||
?FORALL({Block, Key}, {binary(16), eqc_gen:largebinary(32)},
|
|
||||||
is_binary(enacl_ext:scramble_block_16(Block, Key))).
|
|
||||||
|
|
||||||
%% Scala multiplication
|
|
||||||
prop_scalarmult() ->
|
|
||||||
Bytes = 32,
|
|
||||||
?FORALL({S1, S2, Basepoint}, {binary(Bytes), binary(Bytes), binary(Bytes)},
|
|
||||||
equals(enacl:curve25519_scalarmult(S1,
|
|
||||||
enacl:curve25519_scalarmult(S2, Basepoint)),
|
|
||||||
enacl:curve25519_scalarmult(S2,
|
|
||||||
enacl:curve25519_scalarmult(S1, Basepoint)))
|
|
||||||
).
|
|
||||||
|
|
||||||
%% Secretstream
|
|
||||||
secretstream_key() ->
|
|
||||||
?LET(K, enacl:secretstream_xchacha20poly1305_keygen(), K).
|
|
||||||
|
|
||||||
secretstream_msg() ->
|
|
||||||
?LET({Tag, AD, Msg}, {oneof([message,rekey,push]), binary(), binary()},
|
|
||||||
{Tag, AD, Msg}).
|
|
||||||
|
|
||||||
secretstream_msgs() ->
|
|
||||||
?LET({Ms, {_, AD, Msg}}, {list(secretstream_msg()), secretstream_msg()},
|
|
||||||
Ms ++ [{final, AD, Msg}]).
|
|
||||||
|
|
||||||
push_messages(_State, []) ->
|
|
||||||
[];
|
|
||||||
push_messages(State, [{Tag, AD, Msg}|Next]) ->
|
|
||||||
Block = enacl:secretstream_xchacha20poly1305_push(State, Msg, AD, Tag),
|
|
||||||
[Block|push_messages(State, Next)].
|
|
||||||
|
|
||||||
pull_messages(_State, [], []) ->
|
|
||||||
true;
|
|
||||||
pull_messages(State, [B|Bs], [{_Tag, AD, _Msg}=Expect|Next]) ->
|
|
||||||
{Msgx, Tagx} = enacl:secretstream_xchacha20poly1305_pull(State, B, AD),
|
|
||||||
case equals(Expect, {Tagx, AD, Msgx}) of
|
|
||||||
true ->
|
|
||||||
pull_messages(State, Bs, Next);
|
|
||||||
R ->
|
|
||||||
R
|
|
||||||
end.
|
|
||||||
|
|
||||||
prop_secretstream() ->
|
|
||||||
?FORALL({Key, Msgs}, {secretstream_key(), secretstream_msgs()},
|
|
||||||
begin
|
|
||||||
%% Encrypt
|
|
||||||
{Header, State} = enacl:secretstream_xchacha20poly1305_init_push(Key),
|
|
||||||
Blocks = push_messages(State, Msgs),
|
|
||||||
%% Decrypt & Verify
|
|
||||||
DState = enacl:secretstream_xchacha20poly1305_init_pull(Header, Key),
|
|
||||||
pull_messages(DState, Blocks, Msgs)
|
|
||||||
end).
|
|
||||||
|
|
||||||
%% HELPERS
|
|
||||||
|
|
||||||
%% INTERNAL FUNCTIONS
|
%% INTERNAL FUNCTIONS
|
||||||
%% ------------------------------------------------------------
|
%% ------------------------------------------------------------
|
||||||
|
|
||||||
badargs(Thunk) ->
|
badargs(Thunk) ->
|
||||||
try
|
try
|
||||||
Thunk(),
|
Thunk(),
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
-module(enacl_ext_eqc).
|
-module(enacl_ext_eqc).
|
||||||
|
|
||||||
-include_lib("eqc/include/eqc.hrl").
|
-include_lib("eqc/include/eqc.hrl").
|
||||||
-compile({parse_transform, eqc_parallelize}).
|
-compile(export_all).
|
||||||
-compile([export_all, nowarn_export_all]).
|
|
||||||
|
|
||||||
public_keypair() ->
|
public_keypair() ->
|
||||||
?LET(#{ public := PK, secret := SK}, enacl_ext:curve25519_keypair(),
|
?LET(#{ public := PK, secret := SK}, enacl_ext:curve25519_keypair(),
|
||||||
|
42
rebar.config
42
rebar.config
@ -1,39 +1,9 @@
|
|||||||
{erl_opts, [debug_info]}.
|
{erl_opts, [debug_info]}.
|
||||||
|
|
||||||
{plugins, [pc]}.
|
{pre_hooks, [{"freebsd", compile, "gmake -C c_src"},
|
||||||
|
{"freebsd", clean, "gmake -C c_src clean"},
|
||||||
{project_plugins, [rebar3_hex]}.
|
{"netbsd", compile, "gmake -C c_src"},
|
||||||
|
{"netbsd", clean, "gmake -C c_src clean"},
|
||||||
{provider_hooks, [
|
{"(linux|darwin|solaris)", compile, "make -C c_src"},
|
||||||
{pre, [
|
{"(linux|darwin|solaris)", clean, "make -C c_src clean"}
|
||||||
{compile, {pc, compile}},
|
|
||||||
{clean, {pc, clean}}
|
|
||||||
]}
|
|
||||||
]}.
|
|
||||||
|
|
||||||
{port_specs, [
|
|
||||||
{"priv/enacl_nif.so", [
|
|
||||||
"c_src/*.c"
|
|
||||||
]}
|
|
||||||
]}.
|
|
||||||
|
|
||||||
{port_env, [
|
|
||||||
{"darwin", "CFLAGS", "$CFLAGS -fPIC -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes"},
|
|
||||||
{"darwin", "CXXFLAGS", "$CXXFLAGS -fPIC -O3 -finline-functions -Wall"},
|
|
||||||
{"darwin", "LDFLAGS", "$LDFLAGS -flat_namespace -undefined suppress -lsodium"},
|
|
||||||
|
|
||||||
{"linux", "CFLAGS", "$CFLAGS -fPIC -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes"},
|
|
||||||
{"linux", "CXXFLAGS", "$CXXFLAGS -fPIC -O3 -finline-functions -Wall"},
|
|
||||||
{"linux", "LDFLAGS", "$LDFLAGS -lsodium"},
|
|
||||||
|
|
||||||
{"freebsd", "CFLAGS", "$CFLAGS -fPIC -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes -I /usr/local/include"},
|
|
||||||
{"freebsd", "CXXFLAGS", "$CXXFLAGS -fPIC -O3 -finline-functions -Wall"},
|
|
||||||
{"freebsd", "LDFLAGS", "$LDFLAGS -fPIC -L /usr/local/lib -lsodium"},
|
|
||||||
|
|
||||||
{"solaris", "CFLAGS", "$CFLAGS -fPIC -m64 -I/opt/local/include -O2 -std=c99 -finline-functions -Wall -Wmissing-prototypes"},
|
|
||||||
{"solaris", "CXXFLAGS", "$CXXFLAGS -fPIC -O2 -finline-function -Wall"},
|
|
||||||
{"solaris", "LDFLAGS", "$LDFLAGS -m64 -fPIC -L /opt/local/lib -lsodium"},
|
|
||||||
|
|
||||||
{"win32", "CFLAGS", "$CFLAGS /LD /O2 /DNDEBUG"},
|
|
||||||
{"win32", "LDFLAGS", "$LDFLAGS libsodium.dll.a"}
|
|
||||||
]}.
|
]}.
|
||||||
|
12
shell.nix
12
shell.nix
@ -1,12 +0,0 @@
|
|||||||
{ pkgs ? import <nixpkgs> {} }:
|
|
||||||
|
|
||||||
pkgs.mkShell {
|
|
||||||
buildInputs = [
|
|
||||||
pkgs.hello
|
|
||||||
|
|
||||||
# keep this line if you use bash
|
|
||||||
pkgs.bashInteractive
|
|
||||||
pkgs.erlang
|
|
||||||
pkgs.libsodium
|
|
||||||
];
|
|
||||||
}
|
|
@ -1,9 +1,8 @@
|
|||||||
{application,enacl,
|
{application, enacl,
|
||||||
[{description,"Erlang libsodium (NaCl) bindings"},
|
[
|
||||||
{vsn,"1.2.1"},
|
{description, "Erlang NaCl bindings"},
|
||||||
{registered,[]},
|
{vsn, "0.17.0"},
|
||||||
{applications,[kernel,stdlib]},
|
{registered, []},
|
||||||
{env,[]},
|
{applications, [kernel, stdlib]},
|
||||||
{maintainers,["Jesper Louis Andersen"]},
|
{env, []}
|
||||||
{licenses,["MIT","ISC"]},
|
]}.
|
||||||
{links,[{"Github","https://github.com/jlouis/enacl"}]}]}.
|
|
||||||
|
816
src/enacl.erl
816
src/enacl.erl
File diff suppressed because it is too large
Load Diff
@ -25,10 +25,8 @@
|
|||||||
|
|
||||||
crypto_sign_PUBLICKEYBYTES/0,
|
crypto_sign_PUBLICKEYBYTES/0,
|
||||||
crypto_sign_SECRETKEYBYTES/0,
|
crypto_sign_SECRETKEYBYTES/0,
|
||||||
crypto_sign_SEEDBYTES/0,
|
|
||||||
|
|
||||||
crypto_sign_keypair/0,
|
crypto_sign_keypair/0,
|
||||||
crypto_sign_seed_keypair/1,
|
|
||||||
|
|
||||||
crypto_sign/2,
|
crypto_sign/2,
|
||||||
crypto_sign_open/2,
|
crypto_sign_open/2,
|
||||||
@ -36,11 +34,6 @@
|
|||||||
crypto_sign_detached/2,
|
crypto_sign_detached/2,
|
||||||
crypto_sign_verify_detached/3,
|
crypto_sign_verify_detached/3,
|
||||||
|
|
||||||
crypto_sign_init/0,
|
|
||||||
crypto_sign_update/2,
|
|
||||||
crypto_sign_final_create/2,
|
|
||||||
crypto_sign_final_verify/3,
|
|
||||||
|
|
||||||
crypto_box_seal/2,
|
crypto_box_seal/2,
|
||||||
crypto_box_seal_open/3,
|
crypto_box_seal_open/3,
|
||||||
crypto_box_SEALBYTES/0
|
crypto_box_SEALBYTES/0
|
||||||
@ -57,10 +50,6 @@
|
|||||||
crypto_secretbox_b/3,
|
crypto_secretbox_b/3,
|
||||||
crypto_secretbox_open/3,
|
crypto_secretbox_open/3,
|
||||||
crypto_secretbox_open_b/3,
|
crypto_secretbox_open_b/3,
|
||||||
crypto_secretbox_easy/3,
|
|
||||||
crypto_secretbox_easy_b/3,
|
|
||||||
crypto_secretbox_open_easy/3,
|
|
||||||
crypto_secretbox_open_easy_b/3,
|
|
||||||
|
|
||||||
crypto_stream_chacha20_KEYBYTES/0,
|
crypto_stream_chacha20_KEYBYTES/0,
|
||||||
crypto_stream_chacha20_NONCEBYTES/0,
|
crypto_stream_chacha20_NONCEBYTES/0,
|
||||||
@ -78,19 +67,12 @@
|
|||||||
crypto_stream_xor/3,
|
crypto_stream_xor/3,
|
||||||
crypto_stream_xor_b/3,
|
crypto_stream_xor_b/3,
|
||||||
|
|
||||||
crypto_aead_chacha20poly1305_ietf_encrypt/4,
|
crypto_aead_chacha20poly1305_encrypt/4,
|
||||||
crypto_aead_chacha20poly1305_ietf_decrypt/4,
|
crypto_aead_chacha20poly1305_decrypt/4,
|
||||||
crypto_aead_chacha20poly1305_ietf_KEYBYTES/0,
|
crypto_aead_chacha20poly1305_KEYBYTES/0,
|
||||||
crypto_aead_chacha20poly1305_ietf_NPUBBYTES/0,
|
crypto_aead_chacha20poly1305_NPUBBYTES/0,
|
||||||
crypto_aead_chacha20poly1305_ietf_ABYTES/0,
|
crypto_aead_chacha20poly1305_ABYTES/0,
|
||||||
crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX/0,
|
crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX/0,
|
||||||
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_encrypt/4,
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_decrypt/4,
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_KEYBYTES/0,
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES/0,
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_ABYTES/0,
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX/0,
|
|
||||||
|
|
||||||
crypto_auth_BYTES/0,
|
crypto_auth_BYTES/0,
|
||||||
crypto_auth_KEYBYTES/0,
|
crypto_auth_KEYBYTES/0,
|
||||||
@ -123,7 +105,6 @@
|
|||||||
%% Ed 25519
|
%% Ed 25519
|
||||||
-export([
|
-export([
|
||||||
crypto_sign_ed25519_keypair/0,
|
crypto_sign_ed25519_keypair/0,
|
||||||
crypto_sign_ed25519_sk_to_pk/1,
|
|
||||||
crypto_sign_ed25519_public_to_curve25519/1,
|
crypto_sign_ed25519_public_to_curve25519/1,
|
||||||
crypto_sign_ed25519_secret_to_curve25519/1,
|
crypto_sign_ed25519_secret_to_curve25519/1,
|
||||||
crypto_sign_ed25519_PUBLICKEYBYTES/0,
|
crypto_sign_ed25519_PUBLICKEYBYTES/0,
|
||||||
@ -151,19 +132,11 @@
|
|||||||
|
|
||||||
%% Password Hashing - Argon2 Algorithm
|
%% Password Hashing - Argon2 Algorithm
|
||||||
-export([
|
-export([
|
||||||
crypto_pwhash_SALTBYTES/0,
|
crypto_pwhash/2,
|
||||||
crypto_pwhash/5,
|
crypto_pwhash_str/1,
|
||||||
crypto_pwhash_str/3,
|
|
||||||
crypto_pwhash_str_verify/2
|
crypto_pwhash_str_verify/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
%% Key Derivation
|
|
||||||
-export([
|
|
||||||
crypto_kdf_KEYBYTES/0,
|
|
||||||
crypto_kdf_CONTEXTBYTES/0,
|
|
||||||
crypto_kdf_derive_from_key/3
|
|
||||||
]).
|
|
||||||
|
|
||||||
%% Generic hash
|
%% Generic hash
|
||||||
-export([
|
-export([
|
||||||
crypto_generichash_BYTES/0,
|
crypto_generichash_BYTES/0,
|
||||||
@ -174,33 +147,13 @@
|
|||||||
crypto_generichash_KEYBYTES_MAX/0,
|
crypto_generichash_KEYBYTES_MAX/0,
|
||||||
crypto_generichash/3,
|
crypto_generichash/3,
|
||||||
crypto_generichash_init/2,
|
crypto_generichash_init/2,
|
||||||
crypto_generichash_update/2,
|
crypto_generichash_update/3,
|
||||||
crypto_generichash_final/1
|
crypto_generichash_final/2
|
||||||
]).
|
|
||||||
|
|
||||||
%% Secretstream
|
|
||||||
-export([
|
|
||||||
crypto_secretstream_xchacha20poly1305_ABYTES/0,
|
|
||||||
crypto_secretstream_xchacha20poly1305_HEADERBYTES/0,
|
|
||||||
crypto_secretstream_xchacha20poly1305_KEYBYTES/0,
|
|
||||||
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX/0,
|
|
||||||
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE/0,
|
|
||||||
crypto_secretstream_xchacha20poly1305_TAG_PUSH/0,
|
|
||||||
crypto_secretstream_xchacha20poly1305_TAG_REKEY/0,
|
|
||||||
crypto_secretstream_xchacha20poly1305_TAG_FINAL/0,
|
|
||||||
crypto_secretstream_xchacha20poly1305_keygen/0,
|
|
||||||
crypto_secretstream_xchacha20poly1305_init_push/1,
|
|
||||||
crypto_secretstream_xchacha20poly1305_push/4,
|
|
||||||
crypto_secretstream_xchacha20poly1305_init_pull/2,
|
|
||||||
crypto_secretstream_xchacha20poly1305_pull/3,
|
|
||||||
crypto_secretstream_xchacha20poly1305_rekey/1
|
|
||||||
]).
|
]).
|
||||||
|
|
||||||
%% Access to the RNG
|
%% Access to the RNG
|
||||||
-export([
|
-export([
|
||||||
randombytes/1,
|
randombytes/1
|
||||||
randombytes_uint32/0,
|
|
||||||
randombytes_uniform/1
|
|
||||||
]).
|
]).
|
||||||
|
|
||||||
%% Undocumented features :>
|
%% Undocumented features :>
|
||||||
@ -232,33 +185,13 @@ crypto_generichash_KEYBYTES_MAX() -> erlang:nif_error(nif_not_loaded).
|
|||||||
crypto_generichash(_HashSize, _Message, _Key) -> erlang:nif_error(nif_not_loaded).
|
crypto_generichash(_HashSize, _Message, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||||
|
|
||||||
crypto_generichash_init(_HashSize, _Key) -> erlang:nif_error(nif_not_loaded).
|
crypto_generichash_init(_HashSize, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_generichash_update(_HashState, _Message) -> erlang:nif_error(nif_not_loaded).
|
crypto_generichash_update(_HashSize, _HashState, _Message) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_generichash_final(_HashState) -> erlang:nif_error(nif_not_loaded).
|
crypto_generichash_final(_HashSize, _HashState) -> erlang:nif_error(nif_not_loaded).
|
||||||
|
|
||||||
crypto_secretstream_xchacha20poly1305_ABYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_pwhash(_Password, _Salt) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_secretstream_xchacha20poly1305_HEADERBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_pwhash_str(_Password) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_secretstream_xchacha20poly1305_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretstream_xchacha20poly1305_TAG_PUSH() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretstream_xchacha20poly1305_TAG_REKEY() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretstream_xchacha20poly1305_TAG_FINAL() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretstream_xchacha20poly1305_keygen() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretstream_xchacha20poly1305_init_push(_Key) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretstream_xchacha20poly1305_push(_Ref, _Message, _AD, _Tag) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretstream_xchacha20poly1305_init_pull(_Header, _Key) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretstream_xchacha20poly1305_pull(_Ref, _CipherText, _AD) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretstream_xchacha20poly1305_rekey(_Ref) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
|
|
||||||
crypto_pwhash_SALTBYTES() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_pwhash(_Password, _Salt, _Ops, _Mem, _Alg) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_pwhash_str(_Password, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_pwhash_str_verify(_HashedPassword, _Password) -> erlang:nif_error(nif_not_loaded).
|
crypto_pwhash_str_verify(_HashedPassword, _Password) -> erlang:nif_error(nif_not_loaded).
|
||||||
|
|
||||||
crypto_kdf_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_kdf_CONTEXTBYTES() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_kdf_derive_from_key(_MasterKey, _Context, _Id) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
|
|
||||||
crypto_box_NONCEBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_box_NONCEBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_box_ZEROBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_box_ZEROBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_box_BOXZEROBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_box_BOXZEROBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
@ -278,10 +211,8 @@ crypto_box_open_afternm_b(_CipherText, _Nonce, _K) -> erlang:nif_error(nif_not_l
|
|||||||
|
|
||||||
crypto_sign_PUBLICKEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_sign_PUBLICKEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_sign_SECRETKEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_sign_SECRETKEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_sign_SEEDBYTES() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
|
|
||||||
crypto_sign_keypair() -> erlang:nif_error(nif_not_loaded).
|
crypto_sign_keypair() -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_sign_seed_keypair(_S) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_sign(_M, _SK) -> erlang:nif_error(nif_not_loaded).
|
crypto_sign(_M, _SK) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_sign_open(_SignedMessage, _PK) -> erlang:nif_error(nif_not_loaded).
|
crypto_sign_open(_SignedMessage, _PK) -> erlang:nif_error(nif_not_loaded).
|
||||||
|
|
||||||
@ -289,11 +220,6 @@ crypto_sign_detached(_M, _SK) -> erlang:nif_error(nif_not_loaded).
|
|||||||
|
|
||||||
crypto_sign_verify_detached(_Sig, _M, _PK) -> erlang:nif_error(nif_not_loaded).
|
crypto_sign_verify_detached(_Sig, _M, _PK) -> erlang:nif_error(nif_not_loaded).
|
||||||
|
|
||||||
crypto_sign_init() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_sign_update(_S, _M) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_sign_final_create(_S, _SK) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_sign_final_verify(_State, _Sig, _PK) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
|
|
||||||
crypto_box_seal(_Msg, _PK) -> erlang:nif_error(nif_not_loaded).
|
crypto_box_seal(_Msg, _PK) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_box_seal_open(_CipherText, _PK, _SK) -> erlang:nif_error(nif_not_loaded).
|
crypto_box_seal_open(_CipherText, _PK, _SK) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_box_SEALBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_box_SEALBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
@ -307,10 +233,6 @@ crypto_secretbox(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
|||||||
crypto_secretbox_b(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
crypto_secretbox_b(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_secretbox_open(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
crypto_secretbox_open(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_secretbox_open_b(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
crypto_secretbox_open_b(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_secretbox_easy(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretbox_easy_b(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretbox_open_easy(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_secretbox_open_easy_b(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
|
|
||||||
crypto_stream_chacha20_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_stream_chacha20_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_stream_chacha20_NONCEBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_stream_chacha20_NONCEBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
@ -326,19 +248,12 @@ crypto_stream_b(_Bytes, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
|||||||
crypto_stream_xor(_M, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
crypto_stream_xor(_M, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_stream_xor_b(_M, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
crypto_stream_xor_b(_M, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||||
|
|
||||||
crypto_aead_chacha20poly1305_ietf_encrypt(_Message, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
crypto_aead_chacha20poly1305_encrypt(_Key, _Nonce, _AD, _Message) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_aead_chacha20poly1305_ietf_decrypt(_CipherText, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
crypto_aead_chacha20poly1305_decrypt(_Key, _Nonce, _AD, _Message) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_aead_chacha20poly1305_ietf_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_aead_chacha20poly1305_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_aead_chacha20poly1305_ietf_NPUBBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_aead_chacha20poly1305_NPUBBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_aead_chacha20poly1305_ietf_ABYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_aead_chacha20poly1305_ABYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded).
|
crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded).
|
||||||
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_encrypt(_Message, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_decrypt(_CipherText, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_ABYTES() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
|
|
||||||
crypto_auth_BYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_auth_BYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_auth_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_auth_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
@ -362,7 +277,6 @@ crypto_curve25519_scalarmult(_Secret, _BasePoint) -> erlang:nif_error(nif_not_lo
|
|||||||
crypto_curve25519_scalarmult_base(_Secret) -> erlang:nif_error(nif_not_loaded).
|
crypto_curve25519_scalarmult_base(_Secret) -> erlang:nif_error(nif_not_loaded).
|
||||||
|
|
||||||
crypto_sign_ed25519_keypair() -> erlang:nif_error(nif_not_loaded).
|
crypto_sign_ed25519_keypair() -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_sign_ed25519_sk_to_pk(_SecretKey) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
crypto_sign_ed25519_public_to_curve25519(_PublicKey) -> erlang:nif_error(nif_not_loaded).
|
crypto_sign_ed25519_public_to_curve25519(_PublicKey) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_sign_ed25519_secret_to_curve25519(_SecretKey) -> erlang:nif_error(nif_not_loaded).
|
crypto_sign_ed25519_secret_to_curve25519(_SecretKey) -> erlang:nif_error(nif_not_loaded).
|
||||||
crypto_sign_ed25519_PUBLICKEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_sign_ed25519_PUBLICKEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
@ -382,7 +296,5 @@ crypto_kx_PUBLICKEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
|||||||
crypto_kx_SECRETKEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
crypto_kx_SECRETKEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||||
|
|
||||||
randombytes(_RequestedSize) -> erlang:nif_error(nif_not_loaded).
|
randombytes(_RequestedSize) -> erlang:nif_error(nif_not_loaded).
|
||||||
randombytes_uint32() -> erlang:nif_error(nif_not_loaded).
|
|
||||||
randombytes_uniform(_UpperBound) -> erlang:nif_error(nif_not_loaded).
|
|
||||||
|
|
||||||
scramble_block_16(_Block, _Key) -> erlang:nif_error(nif_not_loaded).
|
scramble_block_16(_Block, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||||
|
@ -1,196 +0,0 @@
|
|||||||
-module(enacl_SUITE).
|
|
||||||
-include_lib("common_test/include/ct.hrl").
|
|
||||||
|
|
||||||
-compile([export_all, nowarn_export_all]).
|
|
||||||
|
|
||||||
suite() ->
|
|
||||||
[{timetrap, {seconds, 30}}].
|
|
||||||
|
|
||||||
init_per_group(_Group, Config) ->
|
|
||||||
Config.
|
|
||||||
|
|
||||||
end_per_group(_Group, _Config) ->
|
|
||||||
ok.
|
|
||||||
|
|
||||||
init_per_suite(Config) ->
|
|
||||||
application:ensure_all_started(enacl),
|
|
||||||
Config.
|
|
||||||
|
|
||||||
end_per_suite(_Config) ->
|
|
||||||
application:stop(enacl),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
init_per_testcase(x, Config) ->
|
|
||||||
{ok, _} = dbg:tracer(),
|
|
||||||
dbg:p(all, c),
|
|
||||||
dbg:tpl(graphql_execute, lookup_field, '_', cx),
|
|
||||||
Config;
|
|
||||||
init_per_testcase(_Case, Config) ->
|
|
||||||
Config.
|
|
||||||
|
|
||||||
end_per_testcase(x, _Config) ->
|
|
||||||
dbg:stop_clear(),
|
|
||||||
ok;
|
|
||||||
end_per_testcase(_Case, _Config) ->
|
|
||||||
ok.
|
|
||||||
|
|
||||||
groups() ->
|
|
||||||
Neg = {negative, [shuffle, parallel],
|
|
||||||
[generichash_basic_neg]},
|
|
||||||
Pos = {positive, [shuffle, parallel],
|
|
||||||
[
|
|
||||||
aead_chacha20poly1305_ietf,
|
|
||||||
aead_xchacha20poly1305,
|
|
||||||
generichash_basic_pos,
|
|
||||||
generichash_chunked,
|
|
||||||
kx,
|
|
||||||
pwhash,
|
|
||||||
secretstream,
|
|
||||||
sign,
|
|
||||||
verify_detached
|
|
||||||
]},
|
|
||||||
|
|
||||||
[Neg, Pos].
|
|
||||||
|
|
||||||
all() ->
|
|
||||||
[{group, negative},
|
|
||||||
{group, positive}].
|
|
||||||
|
|
||||||
%% -- BASIC --------------------------------------
|
|
||||||
generichash_basic_neg(_Config) ->
|
|
||||||
%% Negative generichash invocations
|
|
||||||
Msg = <<"I've seen things you people wouldn't believe: attack ships on fire off the shoulder of Orion. "
|
|
||||||
"I've watched C-beams glitter in the dark near the Tannhäuser Gate. "
|
|
||||||
"All those... moments... will be lost... in time, like... tears... in rain">>,
|
|
||||||
Key = <<"Hash Key 123456789">>,
|
|
||||||
{'EXIT', {badarg, _}} = (catch enacl:generichash(9, Msg, Key)),
|
|
||||||
{'EXIT', {badarg, _}} = (catch enacl:generichash(65, Msg, Key)),
|
|
||||||
{'EXIT', {badarg, _}} = (catch enacl:generichash(32, Msg, <<"Small">>)),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
generichash_basic_pos(_Config) ->
|
|
||||||
Msg = <<"I've seen things you people wouldn't believe: attack ships on fire off the shoulder of Orion. "
|
|
||||||
"I've watched C-beams glitter in the dark near the Tannhäuser Gate. "
|
|
||||||
"All those... moments... will be lost... in time, like... tears... in rain">>,
|
|
||||||
Key = <<"Hash Key 123456789">>,
|
|
||||||
<<189,104,45,187,170,229,212,4,121,43,137,74,241,173,181,77,
|
|
||||||
67,211,133,70,196,6,128,97>> = enacl:generichash(24, Msg, Key),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
generichash_chunked(_Config) ->
|
|
||||||
Msg = <<"I've seen things you people wouldn't believe: attack ships on fire off the shoulder of Orion. "
|
|
||||||
"I've watched C-beams glitter in the dark near the Tannhäuser Gate. "
|
|
||||||
"All those... moments... will be lost... in time, like... tears... in rain">>,
|
|
||||||
Key = <<"Hash Key 123456789">>,
|
|
||||||
State = enacl:generichash_init(24, Key),
|
|
||||||
State = generichash_chunked(State, Msg, 10000),
|
|
||||||
Expected = <<46,49,32,18,13,186,182,105,106,122,253,139,89,176,169,141,
|
|
||||||
73,93,99,6,41,216,110,41>>,
|
|
||||||
Expected = enacl:generichash_final(State),
|
|
||||||
try enacl:generichash_final(State) of
|
|
||||||
_ -> ct:fail(must_finalize)
|
|
||||||
catch
|
|
||||||
error:enacl_finalized ->
|
|
||||||
ok
|
|
||||||
end,
|
|
||||||
try enacl:generichash_update(State, <<"x">>) of
|
|
||||||
_ -> ct:fail(must_finalize)
|
|
||||||
catch
|
|
||||||
error:enacl_finalized ->
|
|
||||||
ok
|
|
||||||
end,
|
|
||||||
ok.
|
|
||||||
|
|
||||||
generichash_chunked(State, _Msg, 0) -> State;
|
|
||||||
generichash_chunked(State, Msg, N) ->
|
|
||||||
State2 = enacl:generichash_update(State, Msg),
|
|
||||||
generichash_chunked(State2, Msg, N-1).
|
|
||||||
|
|
||||||
aead_xchacha20poly1305(_Config) ->
|
|
||||||
NonceLen = enacl:aead_xchacha20poly1305_ietf_NPUBBYTES(),
|
|
||||||
KLen = enacl:aead_xchacha20poly1305_ietf_KEYBYTES(),
|
|
||||||
Key = binary:copy(<<"K">>, KLen),
|
|
||||||
Msg = <<"test">>,
|
|
||||||
AD = <<1,2,3,4,5,6>>,
|
|
||||||
Nonce = binary:copy(<<"N">>, NonceLen),
|
|
||||||
|
|
||||||
CipherText = enacl:aead_xchacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key),
|
|
||||||
Msg = enacl:aead_xchacha20poly1305_ietf_decrypt(CipherText, AD, Nonce, Key),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
aead_chacha20poly1305_ietf(_Config) ->
|
|
||||||
NonceLen = enacl:aead_chacha20poly1305_ietf_NPUBBYTES(),
|
|
||||||
KLen = enacl:aead_chacha20poly1305_ietf_KEYBYTES(),
|
|
||||||
Key = binary:copy(<<"K">>, KLen),
|
|
||||||
Msg = <<"test">>,
|
|
||||||
AD = <<1,2,3,4,5,6>>,
|
|
||||||
Nonce = binary:copy(<<"N">>, NonceLen),
|
|
||||||
|
|
||||||
CipherText = enacl:aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key),
|
|
||||||
Msg = enacl:aead_chacha20poly1305_ietf_decrypt(CipherText, AD, Nonce, Key),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
pwhash(_Config) ->
|
|
||||||
PW = <<"XYZZY">>,
|
|
||||||
Salt = <<"1234567890abcdef">>,
|
|
||||||
Hash1 = <<164,75,127,151,168,101,55,77,48,77,240,204,64,20,43,23,88,
|
|
||||||
18,133,11,53,151,2,113,232,95,84,165,50,7,60,20>>,
|
|
||||||
Hash1 = enacl:pwhash(PW, Salt),
|
|
||||||
Str1 = enacl:pwhash_str(PW),
|
|
||||||
true = enacl:pwhash_str_verify(Str1, PW),
|
|
||||||
false = enacl:pwhash_str_verify(Str1, <<PW/binary, 1>>),
|
|
||||||
16 = enacl:pwhash_SALTBYTES(),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
sign(_Config) ->
|
|
||||||
#{public := PK, secret := SK} = enacl:sign_keypair(),
|
|
||||||
Msg = <<"Test">>,
|
|
||||||
State = enacl:sign_init(),
|
|
||||||
Create = sign_chunked(State, Msg, 10000),
|
|
||||||
{ok, Signature} = enacl:sign_final_create(Create, SK),
|
|
||||||
StateVerify = enacl:sign_init(),
|
|
||||||
Verify = sign_chunked(StateVerify, Msg, 10000),
|
|
||||||
true = enacl:sign_final_verify(Verify, Signature, PK),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
sign_chunked(S, _M, 0) -> S;
|
|
||||||
sign_chunked(S, M, N) ->
|
|
||||||
S2 = enacl:sign_update(S, M),
|
|
||||||
sign_chunked(S2, M, N-1).
|
|
||||||
|
|
||||||
kx(_Config) ->
|
|
||||||
#{ public := CPK, secret := CSK} = enacl:kx_keypair(),
|
|
||||||
#{ public := SPK, secret := SSK} = enacl:kx_keypair(),
|
|
||||||
#{ client_tx := CTX, client_rx := CRX} = enacl:kx_client_session_keys(CPK, CSK, SPK),
|
|
||||||
#{ server_tx := STX, server_rx := SRX} = enacl:kx_server_session_keys(SPK, SSK, CPK),
|
|
||||||
%% Verify we got a shared keypair
|
|
||||||
CTX = SRX,
|
|
||||||
STX = CRX,
|
|
||||||
ok.
|
|
||||||
|
|
||||||
secretstream(_Config) ->
|
|
||||||
Part1 = <<"Arbitrary data to encrypt">>,
|
|
||||||
Part2 = <<"split into">>,
|
|
||||||
Part3 = <<"three messages">>,
|
|
||||||
|
|
||||||
Key = enacl:secretstream_xchacha20poly1305_keygen(),
|
|
||||||
|
|
||||||
%% Encrypt
|
|
||||||
{Header, State} = enacl:secretstream_xchacha20poly1305_init_push(Key),
|
|
||||||
Block1 = enacl:secretstream_xchacha20poly1305_push(State, Part1, <<"AD1">>, message),
|
|
||||||
Block2 = enacl:secretstream_xchacha20poly1305_push(State, Part2, <<>>, message),
|
|
||||||
Block3 = enacl:secretstream_xchacha20poly1305_push(State, Part3, <<"AD3">>, final),
|
|
||||||
|
|
||||||
%% Decrypt
|
|
||||||
DState = enacl:secretstream_xchacha20poly1305_init_pull(Header, Key),
|
|
||||||
{Part1, message} = enacl:secretstream_xchacha20poly1305_pull(DState, Block1, <<"AD1">>),
|
|
||||||
{Part2, message} = enacl:secretstream_xchacha20poly1305_pull(DState, Block2, <<>>),
|
|
||||||
{Part3, final} = enacl:secretstream_xchacha20poly1305_pull(DState, Block3, <<"AD3">>),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
verify_detached(_Config) ->
|
|
||||||
#{ public := PK, secret := SK} = enacl:sign_keypair(),
|
|
||||||
M = <<"Arbitrary data to encrypt">>,
|
|
||||||
Sig = enacl:sign_detached(M, SK),
|
|
||||||
true = enacl:sign_verify_detached(Sig, M, PK),
|
|
||||||
ok.
|
|
Loading…
x
Reference in New Issue
Block a user