Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
355 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* | ||
* ISC License | ||
* | ||
* Copyright (c) 2017 | ||
* Hendrik Beskow | ||
* | ||
* Permission to use, copy, modify, and/or distribute this software for any | ||
* purpose with or without fee is hereby granted, provided that the above | ||
* copyright notice and this permission notice appear in all copies. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
*/ |
Submodule libhydrogen
added at
df9dd3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
MRuby::Gem::Specification.new('mruby-libhydrogen') do |spec| | ||
spec.license = 'ISC' | ||
spec.author = 'Hendrik Beskow' | ||
spec.summary = 'libhydrogen for mruby' | ||
spec.add_conflict 'mruby-libsodium' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,283 @@ | ||
#include "mrb_libhydrogen.h" | ||
|
||
static mrb_value | ||
mrb_randombytes_random(mrb_state *mrb, mrb_value randombytes_module) | ||
{ | ||
#if (MRB_INT_BIT >= 64) | ||
return mrb_fixnum_value(randombytes_random()); | ||
#else | ||
return mrb_float_value(mrb, randombytes_random()); | ||
#endif | ||
} | ||
|
||
static mrb_value | ||
mrb_randombytes_uniform(mrb_state *mrb, mrb_value randombytes_module) | ||
{ | ||
mrb_int upper_bound; | ||
mrb_get_args(mrb, "i", &upper_bound); | ||
mrb_assert_int_fit(mrb_int, upper_bound, uint32_t, UINT32_MAX); | ||
|
||
return mrb_fixnum_value((mrb_int) randombytes_uniform((uint32_t) upper_bound)); | ||
} | ||
|
||
static mrb_value | ||
mrb_randombytes_buf(mrb_state *mrb, mrb_value randombytes_module) | ||
{ | ||
mrb_int len; | ||
mrb_get_args(mrb, "i", &len); | ||
mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); | ||
mrb_value buf = mrb_str_new(mrb, NULL, len); | ||
|
||
randombytes_buf(RSTRING_PTR(buf), len); | ||
|
||
return buf; | ||
} | ||
|
||
static mrb_value | ||
mrb_randombytes_buf_deterministic(mrb_state *mrb, mrb_value randombytes_module) | ||
{ | ||
mrb_int len; | ||
mrb_value seed; | ||
mrb_get_args(mrb, "iS", &len, &seed); | ||
mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); | ||
mrb_hydro_check_length(mrb, RSTRING_LEN(seed), randombytes_SEEDBYTES, "seed"); | ||
mrb_value buf = mrb_str_new(mrb, NULL, len); | ||
|
||
randombytes_buf_deterministic(RSTRING_PTR(buf), len, (uint8_t *) RSTRING_PTR(seed)); | ||
|
||
return buf; | ||
} | ||
|
||
static mrb_value | ||
mrb_hydro_hash_keygen(mrb_state *mrb, mrb_value hydro_hash_class) | ||
{ | ||
mrb_int key_len = hydro_hash_KEYBYTES; | ||
mrb_get_args(mrb, "|i", &key_len); | ||
mrb_hydro_check_length_between(mrb, key_len, hydro_hash_KEYBYTES_MIN, hydro_hash_KEYBYTES_MAX, "key_len"); | ||
mrb_value key = mrb_str_new(mrb, NULL, key_len); | ||
|
||
hydro_hash_keygen((uint8_t *) RSTRING_PTR(key), key_len); | ||
|
||
return key; | ||
} | ||
|
||
static mrb_value | ||
mrb_hydro_hash_init(mrb_state *mrb, mrb_value self) | ||
{ | ||
const char *ctx; | ||
mrb_value key; | ||
mrb_get_args(mrb, "zS", &ctx, &key); | ||
mrb_hydro_check_length(mrb, strlen(ctx), hydro_hash_CONTEXTBYTES, "ctx"); | ||
size_t key_len = mrb_hydro_check_length_between(mrb, RSTRING_LEN(key), hydro_hash_KEYBYTES_MIN, hydro_hash_KEYBYTES_MAX, "key"); | ||
|
||
hydro_hash_state *state = mrb_realloc(mrb, DATA_PTR(self), sizeof(*state)); | ||
mrb_data_init(self, state, &mrb_hydro_hash_type); | ||
|
||
int rc = hydro_hash_init(state, ctx, (uint8_t *) RSTRING_PTR(key), key_len); | ||
assert(rc == 0); | ||
|
||
return self; | ||
} | ||
|
||
static mrb_value | ||
mrb_hydro_hash_update(mrb_state *mrb, mrb_value self) | ||
{ | ||
char *in; | ||
mrb_int in_len; | ||
mrb_get_args(mrb, "s", &in, &in_len); | ||
|
||
int rc = hydro_hash_update((hydro_hash_state *) DATA_PTR(self), (uint8_t *) in, in_len); | ||
assert(rc == 0); | ||
|
||
return self; | ||
} | ||
|
||
static mrb_value | ||
mrb_hydro_hash_final(mrb_state *mrb, mrb_value self) | ||
{ | ||
mrb_int out_len = hydro_hash_BYTES; | ||
mrb_get_args(mrb, "|i", &out_len); | ||
mrb_hydro_check_length_between(mrb, out_len, hydro_hash_BYTES_MIN, hydro_hash_BYTES_MAX, "out_len"); | ||
mrb_value out = mrb_str_new(mrb, NULL, out_len); | ||
|
||
int rc = hydro_hash_final((hydro_hash_state *) DATA_PTR(self), (uint8_t *) RSTRING_PTR(out), out_len); | ||
assert(rc == 0); | ||
|
||
return out; | ||
} | ||
|
||
static mrb_value | ||
mrb_hydro_hash_hash(mrb_state *mrb, mrb_value hydro_hash_class) | ||
{ | ||
char *in; | ||
mrb_int in_len; | ||
const char *ctx; | ||
mrb_value key; | ||
mrb_int out_len = hydro_hash_BYTES; | ||
mrb_get_args(mrb, "szS|i", &in, &in_len, &ctx, &key, &out_len); | ||
mrb_hydro_check_length(mrb, strlen(ctx), hydro_hash_CONTEXTBYTES, "ctx"); | ||
size_t key_len = mrb_hydro_check_length_between(mrb, RSTRING_LEN(key), hydro_hash_KEYBYTES_MIN, hydro_hash_KEYBYTES_MAX, "key"); | ||
mrb_hydro_check_length_between(mrb, out_len, hydro_hash_BYTES_MIN, hydro_hash_BYTES_MAX, "out"); | ||
mrb_value out = mrb_str_new(mrb, NULL, out_len); | ||
|
||
int rc = hydro_hash_hash((uint8_t *) RSTRING_PTR(out), out_len, in, in_len, ctx, (uint8_t *) RSTRING_PTR(key), key_len); | ||
assert(rc == 0); | ||
|
||
return out; | ||
} | ||
|
||
static mrb_value | ||
mrb_hydro_secretbox_keygen(mrb_state *mrb, mrb_value hydro_secretbox_class) | ||
{ | ||
mrb_value key = mrb_str_new(mrb, NULL, hydro_secretbox_KEYBYTES); | ||
hydro_secretbox_keygen((uint8_t *) RSTRING_PTR(key)); | ||
return key; | ||
} | ||
|
||
static mrb_value | ||
mrb_hydro_secretbox_encrypt(mrb_state *mrb, mrb_value hydro_secretbox_module) | ||
{ | ||
char *m; | ||
mrb_int mlen; | ||
const char *ctx; | ||
mrb_value key; | ||
mrb_int msg_id = 0; | ||
mrb_get_args(mrb, "szS|i", &m, &mlen, &ctx, &key, &msg_id); | ||
mrb_hydro_check_length(mrb, strlen(ctx), hydro_secretbox_CONTEXTBYTES, "ctx"); | ||
mrb_hydro_check_length(mrb, RSTRING_LEN(key), hydro_secretbox_KEYBYTES, "key"); | ||
mrb_assert_int_fit(mrb_int, msg_id, uint64_t, UINT64_MAX); | ||
mrb_int ciphertext_len; | ||
if(unlikely(mrb_int_add_overflow(mlen, hydro_secretbox_HEADERBYTES, &ciphertext_len))) { | ||
mrb_raise(mrb, E_RANGE_ERROR, "mlen is too large"); | ||
} | ||
mrb_value ciphertext = mrb_str_new(mrb, NULL, ciphertext_len); | ||
|
||
int rc = hydro_secretbox_encrypt((uint8_t *) RSTRING_PTR(ciphertext), m, mlen, msg_id, ctx, (uint8_t *) RSTRING_PTR(key)); | ||
assert(rc == 0); | ||
|
||
return ciphertext; | ||
} | ||
|
||
static mrb_value | ||
mrb_hydro_secretbox_decrypt(mrb_state *mrb, mrb_value hydro_secretbox_module) | ||
{ | ||
char *c; | ||
mrb_int clen; | ||
const char *ctx; | ||
mrb_value key; | ||
mrb_int msg_id = 0; | ||
mrb_get_args(mrb, "szS|i", &c, &clen, &ctx, &key, &msg_id); | ||
if (clen < hydro_secretbox_HEADERBYTES) { | ||
mrb_raise(mrb, E_RANGE_ERROR, "ciphertext is too short"); | ||
} | ||
mrb_hydro_check_length(mrb, strlen(ctx), hydro_secretbox_CONTEXTBYTES, "ctx"); | ||
mrb_hydro_check_length(mrb, RSTRING_LEN(key), hydro_secretbox_KEYBYTES, "key"); | ||
mrb_assert_int_fit(mrb_int, msg_id, uint64_t, UINT64_MAX); | ||
mrb_value m = mrb_str_new(mrb, NULL, clen - hydro_secretbox_HEADERBYTES); | ||
|
||
int rc = hydro_secretbox_decrypt(RSTRING_PTR(m), (uint8_t *) c, clen, msg_id, ctx, (uint8_t *) RSTRING_PTR(key)); | ||
assert(rc == 0); | ||
|
||
return m; | ||
} | ||
|
||
static mrb_value | ||
mrb_hydro_kdf_keygen(mrb_state *mrb, mrb_value hydro_kdf_module) | ||
{ | ||
mrb_value key = mrb_str_new(mrb, NULL, hydro_kdf_KEYBYTES); | ||
hydro_kdf_keygen((uint8_t *) RSTRING_PTR(key)); | ||
return key; | ||
} | ||
|
||
static mrb_value | ||
mrb_hydro_kdf_derive_from_key(mrb_state *mrb, mrb_value hydro_kdf_module) | ||
{ | ||
mrb_int subkey_id; | ||
const char *ctx; | ||
mrb_value key; | ||
mrb_int subkey_len = 32; | ||
mrb_get_args(mrb, "izS|i", &subkey_id, &ctx, &key, &subkey_len); | ||
mrb_assert_int_fit(mrb_int, subkey_id, uint64_t, UINT64_MAX); | ||
mrb_hydro_check_length(mrb, strlen(ctx), hydro_kdf_CONTEXTBYTES, "ctx"); | ||
mrb_hydro_check_length(mrb, RSTRING_LEN(key), hydro_kdf_KEYBYTES, "key"); | ||
mrb_hydro_check_length_between(mrb, subkey_len, hydro_kdf_BYTES_MIN, hydro_kdf_BYTES_MAX, "subkey_len"); | ||
mrb_value subkey = mrb_str_new(mrb, NULL, subkey_len); | ||
|
||
int rc = hydro_kdf_derive_from_key((uint8_t *) RSTRING_PTR(subkey), subkey_len, subkey_id, ctx, (uint8_t *) RSTRING_PTR(key)); | ||
assert(rc == 0); | ||
|
||
return subkey; | ||
} | ||
|
||
void | ||
mrb_mruby_libhydrogen_gem_init(mrb_state* mrb) | ||
{ | ||
errno = 0; | ||
if (hydro_init() != 0) { | ||
mrb_sys_fail(mrb, "hydro_init"); | ||
} | ||
|
||
struct RClass *randombytes_mod, *hydro_mod, *hydro_hash_cl, *hydro_secretbox_mod, *hydro_kdf_mod, *hydro_sign_cl, *hydro_kx_cl; | ||
|
||
randombytes_mod = mrb_define_module(mrb, "RandomBytes"); | ||
mrb_define_const(mrb, randombytes_mod, "SEEDBYTES", mrb_fixnum_value(randombytes_SEEDBYTES)); | ||
mrb_define_module_function(mrb, randombytes_mod, "random", mrb_randombytes_random, MRB_ARGS_NONE()); | ||
mrb_define_module_function(mrb, randombytes_mod, "uniform", mrb_randombytes_uniform, MRB_ARGS_REQ(1)); | ||
mrb_define_module_function(mrb, randombytes_mod, "buf", mrb_randombytes_buf, MRB_ARGS_ARG(1, 1)); | ||
mrb_define_module_function(mrb, randombytes_mod, "buf_deterministic", mrb_randombytes_buf_deterministic, MRB_ARGS_ARG(2, 1)); | ||
|
||
hydro_mod = mrb_define_module(mrb, "Hydro"); | ||
|
||
hydro_hash_cl = mrb_define_class_under(mrb, hydro_mod, "Hash", mrb->object_class); | ||
MRB_SET_INSTANCE_TT(hydro_hash_cl, MRB_TT_DATA); | ||
mrb_define_const(mrb, hydro_hash_cl, "BYTES", mrb_fixnum_value(hydro_hash_BYTES)); | ||
mrb_define_const(mrb, hydro_hash_cl, "BYTES_MAX", mrb_fixnum_value(hydro_hash_BYTES_MAX)); | ||
mrb_define_const(mrb, hydro_hash_cl, "BYTES_MIN", mrb_fixnum_value(hydro_hash_BYTES_MIN)); | ||
mrb_define_const(mrb, hydro_hash_cl, "CONTEXTBYTES", mrb_fixnum_value(hydro_hash_CONTEXTBYTES)); | ||
mrb_define_const(mrb, hydro_hash_cl, "KEYBYTES", mrb_fixnum_value(hydro_hash_KEYBYTES)); | ||
mrb_define_const(mrb, hydro_hash_cl, "KEYBYTES_MAX", mrb_fixnum_value(hydro_hash_KEYBYTES_MAX)); | ||
mrb_define_const(mrb, hydro_hash_cl, "KEYBYTES_MIN", mrb_fixnum_value(hydro_hash_KEYBYTES_MIN)); | ||
mrb_define_class_method(mrb, hydro_hash_cl, "keygen", mrb_hydro_hash_keygen, MRB_ARGS_OPT(1)); | ||
mrb_define_method(mrb, hydro_hash_cl, "initialize", mrb_hydro_hash_init, MRB_ARGS_REQ(2)); | ||
mrb_define_method(mrb, hydro_hash_cl, "update", mrb_hydro_hash_update, MRB_ARGS_REQ(1)); | ||
mrb_define_alias(mrb, hydro_hash_cl, "<<", "update"); | ||
mrb_define_method(mrb, hydro_hash_cl, "final", mrb_hydro_hash_final, MRB_ARGS_REQ(1)); | ||
mrb_define_class_method(mrb, hydro_hash_cl, "hash", mrb_hydro_hash_hash, MRB_ARGS_ARG(3, 1)); | ||
|
||
hydro_secretbox_mod = mrb_define_module_under(mrb, hydro_mod, "SecretBox"); | ||
mrb_define_const(mrb, hydro_secretbox_mod, "CONTEXTBYTES", mrb_fixnum_value(hydro_secretbox_CONTEXTBYTES)); | ||
mrb_define_const(mrb, hydro_secretbox_mod, "HEADERBYTES", mrb_fixnum_value(hydro_secretbox_HEADERBYTES)); | ||
mrb_define_const(mrb, hydro_secretbox_mod, "KEYBYTES", mrb_fixnum_value(hydro_secretbox_KEYBYTES)); | ||
mrb_define_const(mrb, hydro_secretbox_mod, "PROBEBYTES", mrb_fixnum_value(hydro_secretbox_PROBEBYTES)); | ||
mrb_define_module_function(mrb, hydro_secretbox_mod, "keygen", mrb_hydro_secretbox_keygen, MRB_ARGS_NONE()); | ||
mrb_define_module_function(mrb, hydro_secretbox_mod, "encrypt", mrb_hydro_secretbox_encrypt, MRB_ARGS_ARG(3, 1)); | ||
mrb_define_module_function(mrb, hydro_secretbox_mod, "decrypt", mrb_hydro_secretbox_decrypt, MRB_ARGS_ARG(3, 1)); | ||
|
||
hydro_kdf_mod = mrb_define_class_under(mrb, hydro_mod, "Kdf", mrb->object_class); | ||
mrb_define_const(mrb, hydro_kdf_mod, "CONTEXTBYTES", mrb_fixnum_value(hydro_kdf_CONTEXTBYTES)); | ||
mrb_define_const(mrb, hydro_kdf_mod, "KEYBYTES", mrb_fixnum_value(hydro_kdf_KEYBYTES)); | ||
mrb_define_const(mrb, hydro_kdf_mod, "BYTES_MAX", mrb_fixnum_value(hydro_kdf_BYTES_MAX)); | ||
mrb_define_const(mrb, hydro_kdf_mod, "BYTES_MAX", mrb_fixnum_value(hydro_kdf_BYTES_MIN)); | ||
mrb_define_module_function(mrb, hydro_kdf_mod, "keygen", mrb_hydro_kdf_keygen, MRB_ARGS_NONE()); | ||
mrb_define_module_function(mrb, hydro_kdf_mod, "derive_from_key", mrb_hydro_kdf_derive_from_key, MRB_ARGS_ARG(3, 1)); | ||
|
||
hydro_sign_cl = mrb_define_class_under(mrb, hydro_mod, "Sign", mrb->object_class); | ||
MRB_SET_INSTANCE_TT(hydro_sign_cl, MRB_TT_DATA); | ||
mrb_define_const(mrb, hydro_sign_cl, "BYTES", mrb_fixnum_value(hydro_sign_BYTES)); | ||
mrb_define_const(mrb, hydro_sign_cl, "CONTEXTBYTES", mrb_fixnum_value(hydro_sign_CONTEXTBYTES)); | ||
mrb_define_const(mrb, hydro_sign_cl, "PUBLICKEYBYTES", mrb_fixnum_value(hydro_sign_PUBLICKEYBYTES)); | ||
mrb_define_const(mrb, hydro_sign_cl, "SECRETKEYBYTES", mrb_fixnum_value(hydro_sign_SECRETKEYBYTES)); | ||
mrb_define_const(mrb, hydro_sign_cl, "SEEDBYTES", mrb_fixnum_value(hydro_sign_SEEDBYTES)); | ||
|
||
hydro_kx_cl = mrb_define_class_under(mrb, hydro_mod, "Kx", mrb->object_class); | ||
MRB_SET_INSTANCE_TT(hydro_kx_cl, MRB_TT_DATA); | ||
mrb_define_const(mrb, hydro_kx_cl, "SESSIONKEYBYTES", mrb_fixnum_value(hydro_kx_SESSIONKEYBYTES)); | ||
mrb_define_const(mrb, hydro_kx_cl, "PUBLICKEYBYTES", mrb_fixnum_value(hydro_kx_PUBLICKEYBYTES)); | ||
mrb_define_const(mrb, hydro_kx_cl, "SECRETKEYBYTES", mrb_fixnum_value(hydro_kx_SECRETKEYBYTES)); | ||
mrb_define_const(mrb, hydro_kx_cl, "PSKBYTES", mrb_fixnum_value(hydro_kx_PSKBYTES)); | ||
mrb_define_const(mrb, hydro_kx_cl, "RESPONSE1BYTES", mrb_fixnum_value(hydro_kx_RESPONSE1BYTES)); | ||
mrb_define_const(mrb, hydro_kx_cl, "RESPONSE2BYTES", mrb_fixnum_value(hydro_kx_RESPONSE2BYTES)); | ||
mrb_define_const(mrb, hydro_kx_cl, "RESPONSE3BYTES", mrb_fixnum_value(hydro_kx_RESPONSE3BYTES)); | ||
} | ||
|
||
void mrb_mruby_libhydrogen_gem_final(mrb_state* mrb) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#include <mruby.h> | ||
#include <errno.h> | ||
#include "libhydrogen/hydrogen.c" | ||
#include <mruby/error.h> | ||
#include <mruby/value.h> | ||
#include <mruby/class.h> | ||
#include <mruby/string.h> | ||
#include <mruby/data.h> | ||
#include <mruby/numeric.h> | ||
#include <assert.h> | ||
|
||
#if (__GNUC__ >= 3) || (__INTEL_COMPILER >= 800) || defined(__clang__) | ||
# define likely(x) __builtin_expect(!!(x), 1) | ||
# define unlikely(x) __builtin_expect(!!(x), 0) | ||
#else | ||
# define likely(x) (x) | ||
# define unlikely(x) (x) | ||
#endif | ||
|
||
MRB_INLINE void | ||
mrb_hydro_check_length(mrb_state *mrb, size_t obj_size, size_t hydro_const, const char *type) | ||
{ | ||
if (unlikely(obj_size != hydro_const)) { | ||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "expected a length == %S bytes %S, got %S bytes", | ||
mrb_fixnum_value(hydro_const), | ||
mrb_str_new_static(mrb, type, strlen(type)), | ||
mrb_fixnum_value(obj_size)); | ||
} | ||
} | ||
|
||
MRB_INLINE size_t | ||
mrb_hydro_check_length_between(mrb_state *mrb, size_t obj_size, size_t min, size_t max, const char *type) | ||
{ | ||
if (unlikely(obj_size < min||obj_size > max)) { | ||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "expected a length between %S and %S (inclusive) bytes %S, got %S bytes", | ||
mrb_fixnum_value(min), | ||
mrb_fixnum_value(max), | ||
mrb_str_new_static(mrb, type, strlen(type)), | ||
mrb_fixnum_value(obj_size)); | ||
} | ||
|
||
return obj_size; | ||
} | ||
|
||
static const struct mrb_data_type mrb_hydro_hash_type = { | ||
"$mrb_i_hydro_hash_type", mrb_free, | ||
}; |